pax_global_header00006660000000000000000000000064141762153360014522gustar00rootroot0000000000000052 comment=aa2d16575cbffd5b85d07b8b9f4254bd880ceaf2 postcss-8.4.6/000077500000000000000000000000001417621533600132375ustar00rootroot00000000000000postcss-8.4.6/.editorconfig000066400000000000000000000002231417621533600157110ustar00rootroot00000000000000root = true [*] indent_style = space indent_size = 2 end_of_line = lf charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true postcss-8.4.6/.github/000077500000000000000000000000001417621533600145775ustar00rootroot00000000000000postcss-8.4.6/.github/CONTRIBUTING.md000066400000000000000000000045631417621533600170400ustar00rootroot00000000000000# Contributing Guide to PostCSS If you want to contribute to PostCSS, there are a few things that you should be familiar with. ## In Case You Have Questions About Using PostCSS * **Ask for help in [the chat]** If you're stuck, chances are someone had a similar problem before. [the chat]: https://gitter.im/postcss/postcss ## Adding Your Plugin to the List If you created or found a plugin and want to add it to the PostCSS plugins list follow these simple steps: PR should not change plugins defined in README — it only contains favorite plugins moderated by the PostCSS author. Plugins submitted by the community are located in [`docs/plugins`]. * **Keep plugins ordered** Be sure that a plugin is not already present and find a suitable position for it in alphabetical order. However plugins with `postcss-` prefix should come first. * **Check spelling** Before submitting a PR make sure the spelling check is passing. To run the check use `npm test`. If it fails with an unknown word error, add it as a word to `.yaspellerrc` dictionary. * **Check PostCSS plugin guidelines** The suggested plugin should match plugin [guidelines]. - **Provide link to suggested plugin** Make sure your pull request description contains a link to the plugin you want to add. [`docs/plugins`]: https://github.com/postcss/postcss/blob/main/docs/plugins.md [guidelines]: https://github.com/postcss/postcss/blob/main/docs/guidelines/plugin.md ## TypeScript Declaration Improvements If you found a bug or want to add certain improvements to types declaration file: * **Check current TypeScript styling** Be sure that your changes match TypeScript styling rules defined in typings file. * We use classes for existing JS classes like `Stringifier`. * Namespaces used for separating functions related to the same subject. * Interfaces used for defining custom types. Make sure you read through declaration file writing [best practices] by the TypeScript team. [best practices]: https://www.typescriptlang.org/docs/handbook/declaration-files/do-s-and-don-ts.html ## Core Development If you want to add new features or fix existing issues - **Become familiar with PostCSS architecture** For a gentle intro to PostCSS architecture look through our [guide]. [guide]: https://github.com/postcss/postcss/blob/main/docs/architecture.md postcss-8.4.6/.github/FUNDING.yml000066400000000000000000000000571417621533600164160ustar00rootroot00000000000000open_collective: postcss tidelift: npm/postcss postcss-8.4.6/.github/workflows/000077500000000000000000000000001417621533600166345ustar00rootroot00000000000000postcss-8.4.6/.github/workflows/deno.yml000066400000000000000000000022671417621533600203130ustar00rootroot00000000000000name: Deno on: push: tags: - "8.*" jobs: build: runs-on: ubuntu-latest steps: - name: Setup Deno environment uses: denolib/setup-deno@v2.3.0 with: deno-version: v1.x - name: Checkout postcss-deno uses: actions/checkout@v2 with: repository: postcss/postcss-deno token: ${{ secrets.PAT }} - name: Checkout sources uses: actions/checkout@v2 with: ref: main path: postcss - name: Convert the code run: | rm -rf deno deno run --unstable --allow-write --allow-read to_deno.js deno fmt deno deno test --unstable --allow-read --allow-env deno/test/* - name: Get the tag name id: get_version run: echo ::set-output name=VERSION::${GITHUB_REF/refs\/tags\//} - name: Commit the changes and create the tag run: | git config user.name deno-conversion git config user.email github-actions@github.com git add deno git commit -m "update code" git push git tag ${{ steps.get_version.outputs.VERSION }} git push --tags postcss-8.4.6/.github/workflows/test.yml000066400000000000000000000047031417621533600203420ustar00rootroot00000000000000name: Test on: push: pull_request: jobs: full: name: Node.js 17 Full runs-on: ubuntu-latest steps: - name: Checkout the repository uses: actions/checkout@v2 - name: Install pnpm uses: pnpm/action-setup@v2 with: version: latest - name: Install Node.js uses: actions/setup-node@v2 with: node-version: 17 cache: pnpm - name: Install dependencies run: pnpm install --frozen-lockfile --ignore-scripts - name: Run tests run: pnpm test env: FORCE_COLOR: 2 short: runs-on: ubuntu-latest strategy: matrix: node-version: - 16 - 14 - 12 name: Node.js ${{ matrix.node-version }} Quick steps: - name: Checkout the repository uses: actions/checkout@v2 - name: Install pnpm uses: pnpm/action-setup@v2 with: version: latest - name: Install Node.js ${{ matrix.node-version }} uses: actions/setup-node@v2 with: node-version: ${{ matrix.node-version }} cache: pnpm - name: Install dependencies run: pnpm install --frozen-lockfile --ignore-scripts - name: Run unit tests run: pnpm unit env: FORCE_COLOR: 2 old: runs-on: ubuntu-latest name: Node.js 10 Quick steps: - name: Checkout the repository uses: actions/checkout@v2 - name: Install pnpm uses: pnpm/action-setup@v1 with: version: 3 env: ACTIONS_ALLOW_UNSECURE_COMMANDS: true - name: Install Node.js 10 uses: actions/setup-node@v2 with: node-version: 10 - name: Install dependencies run: pnpm install --frozen-lockfile --ignore-scripts - name: Run unit tests run: pnpm unit env: FORCE_COLOR: 2 windows: runs-on: windows-latest name: Windows Quick steps: - name: Checkout the repository uses: actions/checkout@v2 - name: Install pnpm uses: pnpm/action-setup@v2 with: version: latest - name: Install Node.js LTS uses: actions/setup-node@v2 with: node-version: 16 cache: pnpm - name: Install dependencies run: pnpm install --frozen-lockfile --ignore-scripts - name: Run unit tests run: pnpm unit env: FORCE_COLOR: 2 postcss-8.4.6/.gitignore000066400000000000000000000000771417621533600152330ustar00rootroot00000000000000node_modules/ coverage/ docs/api/index.html docs/api/assets/ postcss-8.4.6/.npmignore000066400000000000000000000000451417621533600152350ustar00rootroot00000000000000coverage/ test/ docs/ tsconfig.json postcss-8.4.6/CHANGELOG.md000066400000000000000000000656301417621533600150620ustar00rootroot00000000000000# Change Log This project adheres to [Semantic Versioning](https://semver.org/). ## 8.4.6 * Prevented comment removing when it change meaning of CSS. * Fixed parsing space in last semicolon-less CSS Custom Properties. * Fixed comment cleaning in CSS Custom Properties with space. * Fixed throwing an error on `.root` access for plugin-less case. ## 8.4.5 * Fixed `raws` types to make object extendable (by James Garbutt). * Moved from Yarn 1 to pnpm. ## 8.4.4 * Fixed absolute path in source map on zero plugins mode. ## 8.4.3 * Fixed `this.css.replace is not a function` error. ## 8.4.2 * Fixed previous source map support in zero plugins mode. ## 8.4.1 * Fixed `Stringifier` types (by James Garbutt). ## 8.4 “President Camio” * Added ranges for errors and warnings (by Adaline Valentina Simonian). * Added `Stringifier` types (by James Garbutt). * Added `Processor` types. * Removed `PostCSS does nothing` warning by lazy parser (Bogdan Dolin). * Fixed `Node#walkRules()` types (by Aleks Hudochenkov). * Fixed types `Root` and `Document` in result values (by James Garbutt). * Reduced npm install size by 0.5 MB. * Moved tests from Jest to `uvu` (by Andrey Kim). * Fixed docs (by Paul Shryock). ## 8.3.11 * Remove debugging code. ## 8.3.10 * Fixed `Maximum call stack` issue of some source maps (by Yeting Li). ## 8.3.9 * Replaced `nanocolors` to `picocolors`. * Reduced package size. ## 8.3.8 * Update `nanocolors`. ## 8.3.7 * Replaced `colorette` to `nanocolors`. * Added bug field to `package.json` (by Christian Oliff). * Improved docs (by Andrew Bruce and Paul Shryock). ## 8.3.6 * Fixed column in `missed semicolon` error (by @Gusted). ## 8.3.5 * Fixed broken AST detection. ## 8.3.4 * Fixed broken AST detection. ## 8.3.3 * Fixed broken AST on `postcss` dependency duplication in custom parsers. ## 8.3.2 * Update changelog. ## 8.3.1 * Fixed false positives `PostCSS does nothing` warning on `syntax` option. ## 8.3 “Duke Murmur” * Added `Node#assign()` shortcut (by Jonathan Neal). * Added experimental `Document` node to AST (by Aleks Hudochenkov). * Moved to faster fork of `source-map` (by Valentin Semirulnik). ## 8.2.15 * Fixed `list` type definitions (by @n19htz). ## 8.2.14 * Removed `source-map` from client-side bundle (by Barak Igal). ## 8.2.13 * Fixed ReDoS vulnerabilities in source map parsing (by Yeting Li). ## 8.2.12 * Fixed `package.json` exports. ## 8.2.11 * Fixed `DEP0148` warning in Node.js 16. * Fixed docs (by @semiromid). ## 8.2.10 * Fixed ReDoS vulnerabilities in source map parsing. * Fixed webpack 5 support (by Barak Igal). * Fixed docs (by Roeland Moors). ## 8.2.9 * Exported `NodeErrorOptions` type (by Rouven Weßling). ## 8.2.8 * Fixed browser builds in webpack 4 (by Matt Jones). ## 8.2.7 * Fixed browser builds in webpack 5 (by Matt Jones). ## 8.2.6 * Fixed `Maximum call stack size exceeded` in `Node#toJSON`. * Fixed docs (by inokawa). ## 8.2.5 * Fixed escaped characters handling in `list.split` (by Natalie Weizenbaum). ## 8.2.4 * Added plugin name to `postcss.plugin()` warning (by Tom Williams). * Fixed docs (by Bill Columbia). ## 8.2.3 * Fixed `JSON.stringify(Node[])` support (by Niklas Mischkulnig). ## 8.2.2 * Fixed CSS-in-JS support (by James Garbutt). * Fixed plugin types (by Ludovico Fischer). * Fixed `Result#warn()` types. ## 8.2.1 * Fixed `Node#toJSON()` and `postcss.fromJSON()` (by Niklas Mischkulnig). ## 8.2 “Prince Orobas” * Added `Node#toJSON()` and `postcss.fromJSON()` (by Niklas Mischkulnig). ## 8.1.14 * Fixed parser performance regression. ## 8.1.13 * Fixed broken AST after moving nodes in visitor API. ## 8.1.12 * Fixed Autoprefixer regression. ## 8.1.11 * Added PostCSS update suggestion on unknown event in plugin. ## 8.1.10 * Fixed `LazyResult` type export (by Evan You). * Fixed `LazyResult` type compatibility with `Promise` (by Anton Kastritskiy). ## 8.1.9 * Reduced dependencies number (by Bogdan Chadkin). ## 8.1.8 * Fixed `LazyResult` type compatibility with `Promise` (by Ludovico Fischer). * Fixed HTTPS links in documentation. ## 8.1.7 * Fixed `import` support in TypeScript (by Remco Haszing). ## 8.1.6 * Reverted `package.exports` Node.js 15 fix. ## 8.1.5 * Fixed Node.js 15 warning (by 沈鸿飞). ## 8.1.4 * Fixed TypeScript definition (by Arthur Petrie). ## 8.1.3 * Added `package.types`. ## 8.1.2 * Fixed API docs (by Arthur Petrie). * Improved plugin guide (by Yunus Gaziev). * Prepared code base for Deno support (by Oscar Otero). ## 8.1.1 * Updated funding link. ## 8.1 “Duke Gemory” * Added `Once` and `OnceExit` events. * Fixed `Root` and `RootExit` events re-visiting. * Fixed node re-visiting on deep children changes. * Added docs for visitor API events. ## 8.0.9 * Replace prototype in PostCSS 7 nodes instead of recreating them. * Added missed `Transformer` to exported types (by Pierre-Marie Dartus). ## 8.0.8 * Fix `8.0.7` regression on PostCSS 7 nodes converting (by Adam Wathan). ## 8.0.7 * Fixed compatibility issue with mixin AST with PostCSS 7 and 8 nodes. * Added migration guide translation to Chinese to the warning. ## 8.0.6 * Fixed child adding methods in `Container`. ## 8.0.5 * Update changelog. ## 8.0.4 * Fixed `Cannot read property 'line' of null` error. * Fixed source map support for declarations. ## 8.0.3 * Fixed client-side bundling support. ## 8.0.2 * Fixed plugin packs support. ## 8.0.1 * Updated `Processor#version`. ## 8.0 “President Ose” * Removed support for Node.js 6.x, 8.x, 11.x, and 13.x versions. * Removed `postcss.vendor` helpers. * Deprecated `postcss.plugin()` API. * Treats `sourceMap.sources` as URL instead of file path. * Plugins and runners must have `postcss` in `peerDependencies`. * Prohibited to extend PostCSS AST classes. * Moved from JSDoc to TypeDoc. * Moved unknown source from counter to random IDs. * Added visitor API for plugins (by Alexey Bondarenko). * Added ES modules support. * Added named exports for public classes `const { Rule } = require('postcss)`. * Added `position.url` to `Node#origin()` result. * Added `opts.maps.absolute = true` option. * Added `opts.maps.annotation = (file, root) => url` option support. * Added `Node#source.offset` (by Ayaz Zaynutdinov). * Added `Declaration#variable`. * Added JSON source map support. * Added index source map support. * Added `Declaration#value` auto-converting to string. * Fixed parsing `{}` in at-rule parameters. * Fixed parsing empty Custom Properties. `--foo: ;` will have ` ` value. * Fixed building PostCSS with Rollup (by MapGrid). * Fixed TypeScript types. * Fixed source map relative paths. * Fixed calling `replaceWith` with input replaced node (by Joseph Kaptur). * Improved “Writing a PostCSS Plugin” docs (by Alexey Bondarenko). * Removed Babel from the project’s release process. * Removed docs from npm package. * Replaced `chalk` to `colorette`. ## 7.0.38 * Update `Processor#version`. ## 7.0.37 * Backport `chalk` to `nanocolors` migration. ## 7.0.36 * Backport ReDoS vulnerabilities from PostCSS 8. ## 7.0.35 * Add migration guide link to PostCSS 8 error text. ## 7.0.34 * Fix compatibility with `postcss-scss` 2. ## 7.0.33 * Add error message for PostCSS 8 plugins. ## 7.0.32 * Fix error message (by @admosity). ## 7.0.31 * Use only the latest source map annotation (by Emmanouil Zoumpoulakis). ## 7.0.30 * Fix TypeScript definition (by Natalie Weizenbaum). ## 7.0.29 * Update `Processor#version`. ## 7.0.28 * Fix TypeScript definition (by Natalie Weizenbaum). ## 7.0.27 * Fix TypeScript definition (by Natalie Weizenbaum). ## 7.0.26 * Fix TypeScript definition (by Natalie Weizenbaum). ## 7.0.25 * Fix absolute path support for Windows (by Tom Raviv). ## 7.0.24 * Fix TypeScript definition (by Keith Cirkel). ## 7.0.23 * Update `Processor#version`. ## 7.0.22 * Add funding link for `npm fund`. ## 7.0.21 * Revert passing `nodes` property to node constructor. ## 7.0.20 * Allow to pass PostCSS’s nodes in `nodes` property to node constructor. ## 7.0.19 * Fix passing `nodes` property to node constructor. ## 7.0.18 * Fix TypeScript type definitions (by Jan Buschtöns). ## 7.0.17 * Fix TypeScript type definitions (by Bob Matcuk and Jan Buschtöns). ## 7.0.16 * Revert Custom Properties fix until PostCSS 8.0. ## 7.0.15 * Fix Custom Properties support (by Ivan Solovev). ## 7.0.14 * Fix tokenizer for `postcss-less` (by Matt Lyons). ## 7.0.13 * Fix parsing regression in 7.0.12 for comments between property and value. ## 7.0.12 * Fix parsing broken CSS with two words in declaration property. ## 7.0.11 * Fix source maps on declaration semicolon (by Niklas Mischkulnig). ## 7.0.10 * Fix source maps (by Niklas Mischkulnig). ## 7.0.9 * Increase stringifing performance for non-raws AST. ## 7.0.8 * Fix TypeScript definitions (by Ankur Oberoi). * Use `support-colors` 6.0. ## 7.0.7 * Extend `Error` in `CssSyntaxError`. ## 7.0.6 * Fix parsing files with BOM (by Veniamin Krol). ## 7.0.5 * Reduce npm package size (by Gilad Peleg). ## 7.0.4 * Fix safe parser regression. ## 7.0.3 * Fix tokenizer extendability (by Andrew Powell). * Reduce npm package size. ## 7.0.2 * Fix warning text (by Rui Pedro M Lima). ## 7.0.1 * Fix JSDoc (by Steven Lambert). ## 7.0 “President Amy” * Remove Node.js 9 and Node.js 4 support. * Remove IE and “dead” browsers support for client-side Babel transpiling. * Add CSS position on error happened inside `walk()` (by Nikhil Gaba). * Add `LazyResult#finally` (by Igor Kamyshev). * Add warning on calling PostCSS without plugins and syntax options. * Reduce client-side size. ## 6.0.23 * Fix parsing nested at-rules without semicolon, params, and spaces. * Fix docs (by Kevin Schiffer and Pat Cavit). ## 6.0.22 * Fix `Node#prev` and `Node#next` on missed parent. ## 6.0.21 * Rename Chinese docs to fix `yarnpkg.com` issue. ## 6.0.20 * Better error message on `null` as input CSS. ## 6.0.19 * Fix TypeScript definitions for source maps (by Oleh Kuchuk). * Fix `source` field in TypeScript definitions (by Sylvain Pollet-Villard). ## 6.0.18 * Use primitive object in TypeScript definitions (by Sylvain Pollet-Villard). ## 6.0.17 * Fix parsing comment in selector between word tokens (by Oleh Kuchuk). ## 6.0.16 * Fix warning text (by Michael Keller). ## 6.0.15 * Add warning about missed `from` option on `process().then()` call. * Add IE 10 support. ## 6.0.14 * Fix TypeScript definitions (by Jed Mao). ## 6.0.13 * Fix TypeScript definitions for case of multiple PostCSS versions in `node_modules` (by Chris Eppstein). * Use `source-map` 0.6. ## 6.0.12 * Don’t copy `*` hack to declaration indent. ## 6.0.11 * Add upper case `!IMPORTANT` support. ## 6.0.10 * Reduce PostCSS size in webpack bundle. ## 6.0.9 * Improve error message for plugin with old PostCSS (by Igor Adamenko). ## 6.0.8 * Fix Node.js 4.2.2 support. ## 6.0.7 * Fix base64 decoding for old Node.js and browser. ## 6.0.6 * Fix `end` position in at-rule without semicolon (by Oleh Kuchuk). ## 6.0.5 * Move Babel config from `package.json` for `node_modules` compiling cases. ## 6.0.4 * Fix parsing `;;` after rules. * Use Chalk 2.0. ## 6.0.3 * Fix escape sequences parsing (by Oleh Kuchuk). * Added ability to force disable colors with an environment variable. * Improved color detection of some terminal apps. ## 6.0.2 * Keep `raws.before` on moving `Root` children to new `Root`. ## 6.0.1 * Fix parser extensibility to use it in Safe Parser. ## 6.0 “Marquis Orias” * Remove node.js 0.12 support. * Remove deprecated method from PostCSS 4. * Insert methods remove child from previous parent, instead of closing. * Insert methods and cloning doesn’t clean `raws` anymore. * Methods `moveTo`, `moveAfter`, `moveBefore` were deprecated. * Options was changed in `Plugin#process(css, processOptions, pluginOptions)`. * Add stream parser to reduce memory usage (by Oleh Kuchuk). * Add `before()`/`after()` shortcuts for `node.parent.insertBefore(node, x)`. * Add `Rule#raws.ownSemicolon` for semicolon after templates for `@apply`. * Use `babel-preset-env` to compile npm package. * Remove `js-base64` from dependencies (by Roman Dvornov). * Fix error message on single `:` in CSS. * Move tests to Jest. * Clean up test (by Gabriel Kalani). ## 5.2.18 * Fix TypeScript definitions for case of multiple PostCSS versions in `node_modules` (by Chris Eppstein). ## 5.2.17 * Add `postcss-sass` suggestion to syntax error on `.sass` input. ## 5.2.16 * Better error on wrong argument in node constructor. ## 5.2.15 * Fix TypeScript definitions (by bumbleblym). ## 5.2.14 * Fix browser bundle building in webpack (by janschoenherr). ## 5.2.13 * Do not add comment to important raws. * Fix JSDoc (by Dmitry Semigradsky). ## 5.2.12 * Fix typo in deprecation message (by Garet McKinley). ## 5.2.11 * Fix TypeScript definitions (by Jed Mao). ## 5.2.10 * Fix TypeScript definitions (by Jed Mao). ## 5.2.9 * Update TypeScript definitions (by Jed Mao). ## 5.2.8 * Fix error message (by Ben Briggs). ## 5.2.7 * Better error message on syntax object in plugins list. ## 5.2.6 * Fix `postcss.vendor` for values with spaces (by 刘祺). ## 5.2.5 * Better error message on unclosed string (by Ben Briggs). ## 5.2.4 * Improve terminal CSS syntax highlight (by Simon Lydell). ## 5.2.3 * Better color highlight in syntax error code frame. * Fix color highlight support in old systems. ## 5.2.2 * Update `Processor#version`. ## 5.2.1 * Fix source map path for CSS without `from` option (by Michele Locati). ## 5.2 “Duke Vapula” * Add syntax highlight to code frame in syntax error (by Andrey Popp). * Use Babel code frame style and size in syntax error. * Add `[` and `]` tokens to parse `[attr=;] {}` correctly. * Add `ignoreErrors` options to tokenizer (by Andrey Popp). * Fix error position on tab indent (by Simon Lydell). ## 5.1.2 * Suggests SCSS/Less parsers on parse errors depends on file extension. ## 5.1.1 * Fix TypeScript definitions (by Efremov Alexey). ## 5.1 “King and President Zagan” * Add URI in source map support (by Mark Finger). * Add `map.from` option (by Mark Finger). * Add `` mappings for nodes without source (by Bogdan Chadkin). * Add function value support to `map.prev` option (by Chris Montoro). * Add declaration value type check in shortcut creating (by 刘祺). * `Result#warn` now returns new created warning. * Don’t call plugin creator in `postcss.plugin` call. * Add source maps to PostCSS ES5 build. * Add JSDoc to PostCSS classes. * Clean npm package from unnecessary docs. ## 5.0.21 * Fix support with input source mao with `utf8` encoding name. ## 5.0.20 * Fix between raw value parsing (by David Clark). * Update TypeScript definitions (by Jed Mao). * Clean fake node.source after `append(string)`. ## 5.0.19 * Fix indent-based syntaxes support. ## 5.0.18 * Parse new lines according W3C CSS syntax specification. ## 5.0.17 * Fix options argument in `Node#warn` (by Ben Briggs). * Fix TypeScript definitions (by Jed Mao). ## 5.0.16 * Fix CSS syntax error position on unclosed quotes. ## 5.0.15 * Fix `Node#clone()` on `null` value somewhere in node. ## 5.0.14 * Allow to use PostCSS in webpack bundle without JSON loader. ## 5.0.13 * Fix `index` and `word` options in `Warning#toString` (by Bogdan Chadkin). * Fix input source content loading in errors. * Fix map options on using `LazyResult` as input CSS. * 100% test coverage. * Use Babel 6. ## 5.0.12 * Allow passing a previous map with no mappings (by Andreas Lind). ## 5.0.11 * Increase plugins performance by 1.5 times. ## 5.0.10 * Fix warning from nodes without source. ## 5.0.9 * Fix source map type detection (by @asan). ## 5.0.8 * Fixed a missed step in `5.0.7` that caused the module to be published as ES6 code. ## 5.0.7 * PostCSS now requires that node 0.12 is installed via the engines property in package.json (by Howard Zuo). ## 5.0.6 * Fix parsing nested at-rule without semicolon (by Matt Drake). * Trim `Declaration#value` (by Bogdan Chadkin). ## 5.0.5 * Fix multi-tokens property parsing (by Matt Drake). ## 5.0.4 * Fix start position in `Root#source`. * Fix source map annotation, when CSS uses `\r\n` (by Mohammad Younes). ## 5.0.3 * Fix `url()` parsing. * Fix using `selectors` in `Rule` constructor. * Add start source to `Root` node. ## 5.0.2 * Fix `remove(index)` to be compatible with 4.x plugin. ## 5.0.1 * Fix PostCSS 4.x plugins compatibility. * Fix type definition loading (by Jed Mao). ## 5.0 “President Valac” * Remove `safe` option. Move Safe Parser to separate project. * `Node#toString` does not include `before` for root nodes. * Remove plugin returning `Root` API. * Remove Promise polyfill for node.js 0.10. * Deprecate `eachInside`, `eachDecl`, `eachRule`, `eachAtRule` and `eachComment` in favor of `walk`, `walkDecls`, `walkRules`, `walkAtRules` and `walkComments` (by Jed Mao). * Deprecate `Container#remove` and `Node#removeSelf` in favor of `Container#removeChild` and `Node#remove` (by Ben Briggs). * Deprecate `Node#replace` in favor of `replaceWith` (by Ben Briggs). * Deprecate raw properties in favor of `Node#raws` object. * Deprecate `Node#style` in favor of `raw`. * Deprecate `CssSyntaxError#generated` in favor of `input`. * Deprecate `Node#cleanStyles` in favor of `cleanRaws`. * Deprecate `Root#prevMap` in favor of `Root.source.input.map`. * Add `syntax`, `parser` and `stringifier` options for Custom Syntaxes. * Add stringifier option to `Node#toString`. * Add `Result#content` alias for non-CSS syntaxes. * Add `plugin.process(css)` shortcut to every plugin function (by Ben Briggs). * Add multiple nodes support to insert methods (by Jonathan Neal). * Add `Node#warn` shortcut (by Ben Briggs). * Add `word` and `index` options to errors and warnings (by David Clark). * Add `line`, `column` properties to `Warning`. * Use `supports-color` library to detect color support in error output. * Add type definitions for TypeScript plugin developers (by Jed Mao). * `Rule#selectors` setter detects separators. * Add `postcss.stringify` method. * Throw descriptive errors for incorrectly formatted plugins. * Add docs to npm release. * Fix `url()` parsing. * Fix Windows support (by Jed Mao). ## 4.1.16 * Fix errors without stack trace. ## 4.1.15 * Allow asynchronous plugins to change processor plugins list (by Ben Briggs). ## 4.1.14 * Fix for plugins packs defined by `postcss.plugin`. ## 4.1.13 * Fix input inlined source maps with UTF-8 encoding. ## 4.1.12 * Update Promise polyfill. ## 4.1.11 * Fix error message on wrong plugin format. ## 4.1.10 * Fix Promise behavior on sync plugin errors. * Automatically fill `plugin` field in `CssSyntaxError`. * Fix warning message (by Ben Briggs). ## 4.1.9 * Speed up `node.clone()`. ## 4.1.8 * Accepts `Processor` instance in `postcss()` constructor too. ## 4.1.7 * Speed up `postcss.list` (by Bogdan Chadkin). ## 4.1.6 * Fix Promise behavior on parsing error. ## 4.1.5 * Parse at-words in declaration values. ## 4.1.4 * Fix Promise polyfill dependency (by Anton Yakushev and Matija Marohnić). ## 4.1.3 * Add Promise polyfill for node.js 0.10 and IE. ## 4.1.2 * List helpers can be accessed independently `var space = postcss.list.space`. ## 4.1.1 * Show deprecated message only once. ## 4.1 “Marquis Andras” * Asynchronous plugin support. * Add warnings from plugins and `Result#messages`. * Add `postcss.plugin()` to create plugins with a standard API. * Insert nodes by CSS string. * Show version warning message on error from an outdated plugin. * Send `Result` instance to plugins as the second argument. * Add `CssSyntaxError#plugin`. * Add `CssSyntaxError#showSourceCode()`. * Add `postcss.list` and `postcss.vendor` aliases. * Add `Processor#version`. * Parse wrong closing bracket. * Parse `!important` statement with spaces and comments inside (by Ben Briggs). * Throw an error on declaration without `prop` or `value` (by Philip Peterson). * Fix source map mappings position. * Add indexed source map support. * Always set `error.generated`. * Clean all source map annotation comments. ## 4.0.6 * Remove `babel` from released package dependencies (by Andres Suarez). ## 4.0.5 * Fix error message on double colon in declaration. ## 4.0.4 * Fix indent detection in some rare cases. ## 4.0.3 * Faster API with 6to5 Loose mode. * Fix indexed source maps support. ## 4.0.2 * Do not copy IE hacks to code style. ## 4.0.1 * Add `source.input` to `Root` too. ## 4.0 “Duke Flauros” * Rename `Container#childs` to `nodes`. * Rename `PostCSS#processors` to `plugins`. * Add `Node#replaceValues()` method. * Add `Node#moveTo()`, `moveBefore()` and `moveAfter()` methods. * Add `Node#cloneBefore()` and `cloneAfter()` shortcuts. * Add `Node#next()`, `prev()` and `root()` shortcuts. * Add `Node#replaceWith()` method. * Add `Node#error()` method. * Add `Container#removeAll()` method. * Add filter argument to `eachDecl()` and `eachAtRule()`. * Add `Node#source.input` and move `source.file` or `source.id` to `input`. * Change code indent, when node was moved. * Better fix code style on `Rule`, `AtRule` and `Comment` nodes changes. * Allow to create rules and at-rules by hash shortcut in append methods. * Add class name to CSS syntax error output. ## 3.0.7 * Fix IE filter parsing with multiple commands. * Safer way to consume PostCSS object as plugin (by Maxime Thirouin). ## 3.0.6 * Fix missing semicolon when comment comes after last declaration. * Fix Safe Mode declaration parsing on unclosed blocks. ## 3.0.5 * Fix parser to support difficult cases with backslash escape and brackets. * Add `CssSyntaxError#stack` (by Maxime Thirouin). ## 3.0.4 * Fix Safe Mode on unknown word before declaration. ## 3.0.3 * Increase tokenizer speed (by Roman Dvornov). ## 3.0.2 * Fix empty comment parsing. * Fix `Root#normalize` in some inserts. ## 3.0.1 * Fix Rhino JS runtime support. * Typo in deprecated warning (by Maxime Thirouin). ## 3.0 “Marquis Andrealphus” * New parser, which become the fastest ever CSS parser written in JavaScript. * Parser can now parse declarations and rules in one parent (like in `@page`) and nested declarations for plugins like `postcss-nested`. * Child nodes array is now in `childs` property, instead of `decls` and `rules`. * `map.inline` and `map.sourcesContent` options are now `true` by default. * Fix iterators (`each`, `insertAfter`) on children array changes. * Use previous source map to show origin source of CSS syntax error. * Use 6to5 ES6 compiler, instead of ES6 Transpiler. * Use code style for manually added rules from existing rules. * Use `from` option from previous source map `file` field. * Set `to` value to `from` if `to` option is missing. * Use better node source name when missing `from` option. * Show a syntax error when `;` is missed between declarations. * Allow to pass `PostCSS` instance or list of plugins to `use()` method. * Allow to pass `Result` instance to `process()` method. * Trim Unicode BOM on source maps parsing. * Parse at-rules without spaces like `@import"file"`. * Better previous `sourceMappingURL` annotation comment cleaning. * Do not remove previous `sourceMappingURL` comment on `map.annotation: false`. * Parse nameless at-rules in Safe Mode. * Fix source map generation for nodes without source. * Fix next child `before` if `Root` first child got removed. ## 2.2.6 * Fix map generation for nodes without source (by Josiah Savary). ## 2.2.5 * Fix source map with BOM marker support (by Mohammad Younes). * Fix source map paths (by Mohammad Younes). ## 2.2.4 * Fix `prepend()` on empty `Root`. ## 2.2.3 * Allow to use object shortcut in `use()` with functions like `autoprefixer`. ## 2.2.2 * Add shortcut to set processors in `use()` via object with `.postcss` property. ## 2.2.1 * Send `opts` from `Processor#process(css, opts)` to processors. ## 2.2 “Marquis Cimeies” * Use GNU style syntax error messages. * Add `Node#replace` method. * Add `CssSyntaxError#reason` property. ## 2.1.2 * Fix UTF-8 support in inline source map. * Fix source map `sourcesContent` if there is no `from` and `to` options. ## 2.1.1 * Allow to miss `to` and `from` options for inline source maps. * Add `Node#source.id` if file name is unknown. * Better detect splitter between rules in CSS concatenation tools. * Automatically clone node in insert methods. ## 2.1 “King Amdusias” * Change Traceur ES6 compiler to ES6 Transpiler. * Show broken CSS line in syntax error. ## 2.0 “King Belial” * Project was rewritten from CoffeeScript to ES6. * Add Safe Mode to works with live input or with hacks from legacy code. * More safer parser to pass all hacks from Browserhacks.com. * Use real properties instead of magic getter/setter for raw properties. ## 1.0 “Marquis Decarabia” * Save previous source map for each node to support CSS concatenation with multiple previous maps. * Add `map.sourcesContent` option to add origin content to `sourcesContent` inside map. * Allow to set different place of output map in annotation comment. * Allow to use arrays and `Root` in `Container#append` and same methods. * Add `Root#prevMap` with information about previous map. * Allow to use latest PostCSS from GitHub by npm. * `Result` now is lazy and it will generate output CSS only if you use `css` or `map` property. * Use separated `map.prev` option to set previous map. * Rename `inlineMap` option to `map.inline`. * Rename `mapAnnotation` option to `map.annotation`. * `Result#map` now return `SourceMapGenerator` object, instead of string. * Run previous map autodetect only if input CSS contains annotation comment. * Add `map: 'inline'` shortcut for `map: { inline: true }` option. * `Node#source.file` now will contains absolute path. * Clean `Declaration#between` style on node clone. ## 0.3.5 * Allow to use `Root` or `Result` as first argument in `process()`. * Save parsed AST to `Result#root`. ## 0.3.4 * Better space symbol detect to read UTF-8 BOM correctly. ## 0.3.3 * Remove source map hacks by using new Mozilla’s `source-map` (by Simon Lydell). ## 0.3.2 * Add URI encoding support for inline source maps. ## 0.3.1 * Fix relative paths from previous source map. * Safer space split in `Rule#selectors` (by Simon Lydell). ## 0.3 “Prince Seere” * Add `Comment` node for comments between declarations or rules. * Add source map annotation comment to output CSS. * Allow to inline source map to annotation comment by data:uri. * Fix source maps on Windows. * Fix source maps for subdirectory (by Dmitry Nikitenko and Simon Lydell). * Autodetect previous source map. * Add `first` and `last` shortcuts to container nodes. * Parse `!important` to separated property in `Declaration`. * Allow to break iteration by returning `false`. * Copy code style to new nodes. * Add `eachInside` method to recursively iterate all nodes. * Add `selectors` shortcut to get selectors array. * Add `toResult` method to `Rule` to simplify work with several input files. * Clean declaration’s `value`, rule’s `selector` and at-rule’s `params` by storing spaces in `between` property. ## 0.2 “Duke Dantalion” * Add source map support. * Add shortcuts to create nodes. * Method `process()` now returns object with `css` and `map` keys. * Origin CSS file option was renamed from `file` to `from`. * Rename `Node#remove()` method to `removeSelf()` to fix name conflict. * Node source was moved to `source` property with origin file and node end position. * You can set own CSS generate function. ## 0.1 “Count Andromalius” * Initial release. postcss-8.4.6/LICENSE000066400000000000000000000021071417621533600142440ustar00rootroot00000000000000The MIT License (MIT) Copyright 2013 Andrey Sitnik 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-8.4.6/README.md000066400000000000000000000443771417621533600145350ustar00rootroot00000000000000# PostCSS [![Gitter][chat-img]][chat] Philosopher’s stone, logo of PostCSS [chat-img]: https://img.shields.io/badge/Gitter-Join_the_PostCSS_chat-brightgreen.svg [chat]: https://gitter.im/postcss/postcss PostCSS is a tool for transforming styles with JS plugins. These plugins can lint your CSS, support variables and mixins, transpile future CSS syntax, inline images, and more. PostCSS is used by industry leaders including Wikipedia, Twitter, Alibaba, and JetBrains. The [Autoprefixer] PostCSS plugin is one of the most popular CSS processors. PostCSS takes a CSS file and provides an API to analyze and modify its rules (by transforming them into an [Abstract Syntax Tree]). This API can then be used by [plugins] to do a lot of useful things, e.g., to find errors automatically, or to insert vendor prefixes. **Support / Discussion:** [Gitter](https://gitter.im/postcss/postcss)
**Twitter account:** [@postcss](https://twitter.com/postcss)
**VK.com page:** [postcss](https://vk.com/postcss)
**中文翻译**: [`docs/README-cn.md`](./docs/README-cn.md) For PostCSS commercial support (consulting, improving the front-end culture of your company, PostCSS plugins), contact [Evil Martians] at . [Abstract Syntax Tree]: https://en.wikipedia.org/wiki/Abstract_syntax_tree [Evil Martians]: https://evilmartians.com/?utm_source=postcss [Autoprefixer]: https://github.com/postcss/autoprefixer [plugins]: https://github.com/postcss/postcss#plugins Sponsored by Evil Martians ## Sponsorship PostCSS needs your support. We are accepting donations [at Open Collective](https://opencollective.com/postcss/). Sponsored by Tailwind CSS        Sponsored by ThemeIsle ## Plugins Currently, PostCSS has more than 200 plugins. You can find all of the plugins in the [plugins list] or in the [searchable catalog]. Below is a list of our favorite plugins — the best demonstrations of what can be built on top of PostCSS. If you have any new ideas, [PostCSS plugin development] is really easy. [searchable catalog]: https://www.postcss.parts/ [plugins list]: https://github.com/postcss/postcss/blob/main/docs/plugins.md ### Solve Global CSS Problem * [`postcss-use`] allows you to explicitly set PostCSS plugins within CSS and execute them only for the current file. * [`postcss-modules`] and [`react-css-modules`] automatically isolate selectors within components. * [`postcss-autoreset`] is an alternative to using a global reset that is better for isolatable components. * [`postcss-initial`] adds `all: initial` support, which resets all inherited styles. * [`cq-prolyfill`] adds container query support, allowing styles that respond to the width of the parent. ### Use Future CSS, Today * [`autoprefixer`] adds vendor prefixes, using data from Can I Use. * [`postcss-preset-env`] allows you to use future CSS features today. ### Better CSS Readability * [`postcss-nested`] unwraps nested rules the way Sass does. * [`postcss-sorting`] sorts the content of rules and at-rules. * [`postcss-utilities`] includes the most commonly used shortcuts and helpers. * [`short`] adds and extends numerous shorthand properties. ### Images and Fonts * [`postcss-assets`] inserts image dimensions and inlines files. * [`postcss-sprites`] generates image sprites. * [`font-magician`] generates all the `@font-face` rules needed in CSS. * [`postcss-inline-svg`] allows you to inline SVG and customize its styles. * [`postcss-write-svg`] allows you to write simple SVG directly in your CSS. * [`webp-in-css`] to use WebP image format in CSS background. * [`avif-in-css`] to use AVIF image format in CSS background. ### Linters * [`stylelint`] is a modular stylesheet linter. * [`stylefmt`] is a tool that automatically formats CSS according `stylelint` rules. * [`doiuse`] lints CSS for browser support, using data from Can I Use. * [`colorguard`] helps you maintain a consistent color palette. ### Other * [`postcss-rtl`] combines both-directional (left-to-right and right-to-left) styles in one CSS file. * [`cssnano`] is a modular CSS minifier. * [`lost`] is a feature-rich `calc()` grid system. * [`rtlcss`] mirrors styles for right-to-left locales. [PostCSS plugin development]: https://github.com/postcss/postcss/blob/main/docs/writing-a-plugin.md [`postcss-inline-svg`]: https://github.com/TrySound/postcss-inline-svg [`postcss-preset-env`]: https://github.com/jonathantneal/postcss-preset-env [`react-css-modules`]: https://github.com/gajus/react-css-modules [`postcss-autoreset`]: https://github.com/maximkoretskiy/postcss-autoreset [`postcss-write-svg`]: https://github.com/jonathantneal/postcss-write-svg [`postcss-utilities`]: https://github.com/ismamz/postcss-utilities [`postcss-initial`]: https://github.com/maximkoretskiy/postcss-initial [`postcss-sprites`]: https://github.com/2createStudio/postcss-sprites [`postcss-modules`]: https://github.com/outpunk/postcss-modules [`postcss-sorting`]: https://github.com/hudochenkov/postcss-sorting [`postcss-assets`]: https://github.com/assetsjs/postcss-assets [`font-magician`]: https://github.com/jonathantneal/postcss-font-magician [`autoprefixer`]: https://github.com/postcss/autoprefixer [`cq-prolyfill`]: https://github.com/ausi/cq-prolyfill [`postcss-rtl`]: https://github.com/vkalinichev/postcss-rtl [`postcss-use`]: https://github.com/postcss/postcss-use [`css-modules`]: https://github.com/css-modules/css-modules [`webp-in-css`]: https://github.com/ai/webp-in-css [`avif-in-css`]: https://github.com/nucliweb/avif-in-css [`colorguard`]: https://github.com/SlexAxton/css-colorguard [`stylelint`]: https://github.com/stylelint/stylelint [`stylefmt`]: https://github.com/morishitter/stylefmt [`cssnano`]: https://cssnano.co/ [`postcss-nested`]: https://github.com/postcss/postcss-nested [`doiuse`]: https://github.com/anandthakker/doiuse [`rtlcss`]: https://github.com/MohammadYounes/rtlcss [`short`]: https://github.com/jonathantneal/postcss-short [`lost`]: https://github.com/peterramsing/lost ## Syntaxes PostCSS can transform styles in any syntax, not just CSS. If there is not yet support for your favorite syntax, you can write a parser and/or stringifier to extend PostCSS. * [`sugarss`] is a indent-based syntax like Sass or Stylus. * [`postcss-syntax`] switch syntax automatically by file extensions. * [`postcss-html`] parsing styles in `' * ) * document.type //=> 'document' * document.nodes.length //=> 2 * ``` */ export default class Document extends Container { type: 'document' parent: undefined constructor(defaults?: DocumentProps) /** * Returns a `Result` instance representing the document’s CSS roots. * * ```js * const root1 = postcss.parse(css1, { from: 'a.css' }) * const root2 = postcss.parse(css2, { from: 'b.css' }) * const document = postcss.document() * document.append(root1) * document.append(root2) * const result = document.toResult({ to: 'all.css', map: true }) * ``` * * @param opts Options. * @return Result with current document’s CSS. */ toResult(options?: ProcessOptions): Result } postcss-8.4.6/lib/document.js000066400000000000000000000012161417621533600161610ustar00rootroot00000000000000'use strict' let Container = require('./container') let LazyResult, Processor class Document extends Container { constructor(defaults) { // type needs to be passed to super, otherwise child roots won't be normalized correctly super({ type: 'document', ...defaults }) if (!this.nodes) { this.nodes = [] } } toResult(opts = {}) { let lazy = new LazyResult(new Processor(), this, opts) return lazy.stringify() } } Document.registerLazyResult = dependant => { LazyResult = dependant } Document.registerProcessor = dependant => { Processor = dependant } module.exports = Document Document.default = Document postcss-8.4.6/lib/fromJSON.d.ts000066400000000000000000000001531417621533600162330ustar00rootroot00000000000000import { JSONHydrator } from './postcss.js' declare const fromJSON: JSONHydrator export default fromJSON postcss-8.4.6/lib/fromJSON.js000066400000000000000000000027421417621533600160050ustar00rootroot00000000000000'use strict' let Declaration = require('./declaration') let PreviousMap = require('./previous-map') let Comment = require('./comment') let AtRule = require('./at-rule') let Input = require('./input') let Root = require('./root') let Rule = require('./rule') function fromJSON(json, inputs) { if (Array.isArray(json)) return json.map(n => fromJSON(n)) let { inputs: ownInputs, ...defaults } = json if (ownInputs) { inputs = [] for (let input of ownInputs) { let inputHydrated = { ...input, __proto__: Input.prototype } if (inputHydrated.map) { inputHydrated.map = { ...inputHydrated.map, __proto__: PreviousMap.prototype } } inputs.push(inputHydrated) } } if (defaults.nodes) { defaults.nodes = json.nodes.map(n => fromJSON(n, inputs)) } if (defaults.source) { let { inputId, ...source } = defaults.source defaults.source = source if (inputId != null) { defaults.source.input = inputs[inputId] } } if (defaults.type === 'root') { return new Root(defaults) } else if (defaults.type === 'decl') { return new Declaration(defaults) } else if (defaults.type === 'rule') { return new Rule(defaults) } else if (defaults.type === 'comment') { return new Comment(defaults) } else if (defaults.type === 'atrule') { return new AtRule(defaults) } else { throw new Error('Unknown node type: ' + json.type) } } module.exports = fromJSON fromJSON.default = fromJSON postcss-8.4.6/lib/input.d.ts000066400000000000000000000066121417621533600157430ustar00rootroot00000000000000import { ProcessOptions } from './postcss.js' import PreviousMap from './previous-map.js' export interface FilePosition { /** * URL for the source file. */ url: string /** * Absolute path to the source file. */ file?: string /** * Line of inclusive start position in source file. */ line: number /** * Column of inclusive start position in source file. */ column: number /** * Line of exclusive end position in source file. */ endLine?: number /** * Column of exclusive end position in source file. */ endColumn?: number /** * Source code. */ source?: string } /** * Represents the source CSS. * * ```js * const root = postcss.parse(css, { from: file }) * const input = root.source.input * ``` */ export default class Input { /** * Input CSS source. * * ```js * const input = postcss.parse('a{}', { from: file }).input * input.css //=> "a{}" * ``` */ css: string /** * The input source map passed from a compilation step before PostCSS * (for example, from Sass compiler). * * ```js * root.source.input.map.consumer().sources //=> ['a.sass'] * ``` */ map: PreviousMap /** * The absolute path to the CSS source file defined * with the `from` option. * * ```js * const root = postcss.parse(css, { from: 'a.css' }) * root.source.input.file //=> '/home/ai/a.css' * ``` */ file?: string /** * The unique ID of the CSS source. It will be created if `from` option * is not provided (because PostCSS does not know the file path). * * ```js * const root = postcss.parse(css) * root.source.input.file //=> undefined * root.source.input.id //=> "" * ``` */ id?: string /** * The flag to indicate whether or not the source code has Unicode BOM. */ hasBOM: boolean /** * @param css Input CSS source. * @param opts Process options. */ constructor(css: string, opts?: ProcessOptions) /** * The CSS source identifier. Contains `Input#file` if the user * set the `from` option, or `Input#id` if they did not. * * ```js * const root = postcss.parse(css, { from: 'a.css' }) * root.source.input.from //=> "/home/ai/a.css" * * const root = postcss.parse(css) * root.source.input.from //=> "" * ``` */ get from(): string /** * Reads the input source map and returns a symbol position * in the input source (e.g., in a Sass file that was compiled * to CSS before being passed to PostCSS). Optionally takes an * end position, exclusive. * * ```js * root.source.input.origin(1, 1) //=> { file: 'a.css', line: 3, column: 1 } * root.source.input.origin(1, 1, 1, 4) * //=> { file: 'a.css', line: 3, column: 1, endLine: 3, endColumn: 4 } * ``` * * @param line Line for inclusive start position in input CSS. * @param column Column for inclusive start position in input CSS. * @param endLine Line for exclusive end position in input CSS. * @param endColumn Column for exclusive end position in input CSS. * * @return Position in input source. */ origin( line: number, column: number, endLine?: number, endColumn?: number ): FilePosition | false /** * Converts source offset to line and column. * * @param offset Source offset. */ fromOffset(offset: number): { line: number; col: number } | null } postcss-8.4.6/lib/input.js000066400000000000000000000140551417621533600155070ustar00rootroot00000000000000'use strict' let { SourceMapConsumer, SourceMapGenerator } = require('source-map-js') let { fileURLToPath, pathToFileURL } = require('url') let { resolve, isAbsolute } = require('path') let { nanoid } = require('nanoid/non-secure') let terminalHighlight = require('./terminal-highlight') let CssSyntaxError = require('./css-syntax-error') let PreviousMap = require('./previous-map') let fromOffsetCache = Symbol('fromOffsetCache') let sourceMapAvailable = Boolean(SourceMapConsumer && SourceMapGenerator) let pathAvailable = Boolean(resolve && isAbsolute) class Input { constructor(css, opts = {}) { if ( css === null || typeof css === 'undefined' || (typeof css === 'object' && !css.toString) ) { throw new Error(`PostCSS received ${css} instead of CSS string`) } this.css = css.toString() if (this.css[0] === '\uFEFF' || this.css[0] === '\uFFFE') { this.hasBOM = true this.css = this.css.slice(1) } else { this.hasBOM = false } if (opts.from) { if ( !pathAvailable || /^\w+:\/\//.test(opts.from) || isAbsolute(opts.from) ) { this.file = opts.from } else { this.file = resolve(opts.from) } } if (pathAvailable && sourceMapAvailable) { let map = new PreviousMap(this.css, opts) if (map.text) { this.map = map let file = map.consumer().file if (!this.file && file) this.file = this.mapResolve(file) } } if (!this.file) { this.id = '' } if (this.map) this.map.file = this.from } fromOffset(offset) { let lastLine, lineToIndex if (!this[fromOffsetCache]) { let lines = this.css.split('\n') lineToIndex = new Array(lines.length) let prevIndex = 0 for (let i = 0, l = lines.length; i < l; i++) { lineToIndex[i] = prevIndex prevIndex += lines[i].length + 1 } this[fromOffsetCache] = lineToIndex } else { lineToIndex = this[fromOffsetCache] } lastLine = lineToIndex[lineToIndex.length - 1] let min = 0 if (offset >= lastLine) { min = lineToIndex.length - 1 } else { let max = lineToIndex.length - 2 let mid while (min < max) { mid = min + ((max - min) >> 1) if (offset < lineToIndex[mid]) { max = mid - 1 } else if (offset >= lineToIndex[mid + 1]) { min = mid + 1 } else { min = mid break } } } return { line: min + 1, col: offset - lineToIndex[min] + 1 } } error(message, line, column, opts = {}) { let result, endLine, endColumn if (line && typeof line === 'object') { let start = line let end = column if (typeof line.offset === 'number') { let pos = this.fromOffset(start.offset) line = pos.line column = pos.col } else { line = start.line column = start.column } if (typeof end.offset === 'number') { let pos = this.fromOffset(end.offset) endLine = pos.line endColumn = pos.col } else { endLine = end.line endColumn = end.column } } else if (!column) { let pos = this.fromOffset(line) line = pos.line column = pos.col } let origin = this.origin(line, column, endLine, endColumn) if (origin) { result = new CssSyntaxError( message, origin.endLine === undefined ? origin.line : { line: origin.line, column: origin.column }, origin.endLine === undefined ? origin.column : { line: origin.endLine, column: origin.endColumn }, origin.source, origin.file, opts.plugin ) } else { result = new CssSyntaxError( message, endLine === undefined ? line : { line, column }, endLine === undefined ? column : { line: endLine, column: endColumn }, this.css, this.file, opts.plugin ) } result.input = { line, column, endLine, endColumn, source: this.css } if (this.file) { if (pathToFileURL) { result.input.url = pathToFileURL(this.file).toString() } result.input.file = this.file } return result } origin(line, column, endLine, endColumn) { if (!this.map) return false let consumer = this.map.consumer() let from = consumer.originalPositionFor({ line, column }) if (!from.source) return false let to if (typeof endLine === 'number') { to = consumer.originalPositionFor({ line: endLine, column: endColumn }) } let fromUrl if (isAbsolute(from.source)) { fromUrl = pathToFileURL(from.source) } else { fromUrl = new URL( from.source, this.map.consumer().sourceRoot || pathToFileURL(this.map.mapFile) ) } let result = { url: fromUrl.toString(), line: from.line, column: from.column, endLine: to && to.line, endColumn: to && to.column } if (fromUrl.protocol === 'file:') { if (fileURLToPath) { result.file = fileURLToPath(fromUrl) } else { /* c8 ignore next 2 */ throw new Error(`file: protocol is not available in this PostCSS build`) } } let source = consumer.sourceContentFor(from.source) if (source) result.source = source return result } mapResolve(file) { if (/^\w+:\/\//.test(file)) { return file } return resolve(this.map.consumer().sourceRoot || this.map.root || '.', file) } get from() { return this.file || this.id } toJSON() { let json = {} for (let name of ['hasBOM', 'css', 'file', 'id']) { if (this[name] != null) { json[name] = this[name] } } if (this.map) { json.map = { ...this.map } if (json.map.consumerCache) { json.map.consumerCache = undefined } } return json } } module.exports = Input Input.default = Input if (terminalHighlight && terminalHighlight.registerInput) { terminalHighlight.registerInput(Input) } postcss-8.4.6/lib/lazy-result.d.ts000066400000000000000000000110261417621533600170720ustar00rootroot00000000000000import Result, { Message, ResultOptions } from './result.js' import { SourceMap } from './postcss.js' import Processor from './processor.js' import Warning from './warning.js' import Root from './root.js' /** * A Promise proxy for the result of PostCSS transformations. * * A `LazyResult` instance is returned by `Processor#process`. * * ```js * const lazy = postcss([autoprefixer]).process(css) * ``` */ export default class LazyResult implements PromiseLike { /** * Processes input CSS through synchronous and asynchronous plugins * and calls `onFulfilled` with a Result instance. If a plugin throws * an error, the `onRejected` callback will be executed. * * It implements standard Promise API. * * ```js * postcss([autoprefixer]).process(css, { from: cssPath }).then(result => { * console.log(result.css) * }) * ``` */ then: Promise['then'] /** * Processes input CSS through synchronous and asynchronous plugins * and calls onRejected for each error thrown in any plugin. * * It implements standard Promise API. * * ```js * postcss([autoprefixer]).process(css).then(result => { * console.log(result.css) * }).catch(error => { * console.error(error) * }) * ``` */ catch: Promise['catch'] /** * Processes input CSS through synchronous and asynchronous plugins * and calls onFinally on any error or when all plugins will finish work. * * It implements standard Promise API. * * ```js * postcss([autoprefixer]).process(css).finally(() => { * console.log('processing ended') * }) * ``` */ finally: Promise['finally'] /** * @param processor Processor used for this transformation. * @param css CSS to parse and transform. * @param opts Options from the `Processor#process` or `Root#toResult`. */ constructor(processor: Processor, css: string, opts: ResultOptions) /** * Returns the default string description of an object. * Required to implement the Promise interface. */ get [Symbol.toStringTag](): string /** * Returns a `Processor` instance, which will be used * for CSS transformations. */ get processor(): Processor /** * Options from the `Processor#process` call. */ get opts(): ResultOptions /** * Processes input CSS through synchronous plugins, converts `Root` * to a CSS string and returns `Result#css`. * * This property will only work with synchronous plugins. * If the processor contains any asynchronous plugins * it will throw an error. * * PostCSS runners should always use `LazyResult#then`. */ get css(): string /** * An alias for the `css` property. Use it with syntaxes * that generate non-CSS output. * * This property will only work with synchronous plugins. * If the processor contains any asynchronous plugins * it will throw an error. * * PostCSS runners should always use `LazyResult#then`. */ get content(): string /** * Processes input CSS through synchronous plugins * and returns `Result#map`. * * This property will only work with synchronous plugins. * If the processor contains any asynchronous plugins * it will throw an error. * * PostCSS runners should always use `LazyResult#then`. */ get map(): SourceMap /** * Processes input CSS through synchronous plugins * and returns `Result#root`. * * This property will only work with synchronous plugins. If the processor * contains any asynchronous plugins it will throw an error. * * PostCSS runners should always use `LazyResult#then`. */ get root(): Root /** * Processes input CSS through synchronous plugins * and returns `Result#messages`. * * This property will only work with synchronous plugins. If the processor * contains any asynchronous plugins it will throw an error. * * PostCSS runners should always use `LazyResult#then`. */ get messages(): Message[] /** * Processes input CSS through synchronous plugins * and calls `Result#warnings`. * * @return Warnings from plugins. */ warnings(): Warning[] /** * Alias for the `LazyResult#css` property. * * ```js * lazy + '' === lazy.css * ``` * * @return Output CSS. */ toString(): string /** * Run plugin in sync way and return `Result`. * * @return Result with output content. */ sync(): Result /** * Run plugin in async way and return `Result`. * * @return Result with output content. */ async(): Promise } postcss-8.4.6/lib/lazy-result.js000066400000000000000000000323721417621533600166450ustar00rootroot00000000000000'use strict' let { isClean, my } = require('./symbols') let MapGenerator = require('./map-generator') let stringify = require('./stringify') let Container = require('./container') let Document = require('./document') let warnOnce = require('./warn-once') let Result = require('./result') let parse = require('./parse') let Root = require('./root') const TYPE_TO_CLASS_NAME = { document: 'Document', root: 'Root', atrule: 'AtRule', rule: 'Rule', decl: 'Declaration', comment: 'Comment' } const PLUGIN_PROPS = { postcssPlugin: true, prepare: true, Once: true, Document: true, Root: true, Declaration: true, Rule: true, AtRule: true, Comment: true, DeclarationExit: true, RuleExit: true, AtRuleExit: true, CommentExit: true, RootExit: true, DocumentExit: true, OnceExit: true } const NOT_VISITORS = { postcssPlugin: true, prepare: true, Once: true } const CHILDREN = 0 function isPromise(obj) { return typeof obj === 'object' && typeof obj.then === 'function' } function getEvents(node) { let key = false let type = TYPE_TO_CLASS_NAME[node.type] if (node.type === 'decl') { key = node.prop.toLowerCase() } else if (node.type === 'atrule') { key = node.name.toLowerCase() } if (key && node.append) { return [ type, type + '-' + key, CHILDREN, type + 'Exit', type + 'Exit-' + key ] } else if (key) { return [type, type + '-' + key, type + 'Exit', type + 'Exit-' + key] } else if (node.append) { return [type, CHILDREN, type + 'Exit'] } else { return [type, type + 'Exit'] } } function toStack(node) { let events if (node.type === 'document') { events = ['Document', CHILDREN, 'DocumentExit'] } else if (node.type === 'root') { events = ['Root', CHILDREN, 'RootExit'] } else { events = getEvents(node) } return { node, events, eventIndex: 0, visitors: [], visitorIndex: 0, iterator: 0 } } function cleanMarks(node) { node[isClean] = false if (node.nodes) node.nodes.forEach(i => cleanMarks(i)) return node } let postcss = {} class LazyResult { constructor(processor, css, opts) { this.stringified = false this.processed = false let root if ( typeof css === 'object' && css !== null && (css.type === 'root' || css.type === 'document') ) { root = cleanMarks(css) } else if (css instanceof LazyResult || css instanceof Result) { root = cleanMarks(css.root) if (css.map) { if (typeof opts.map === 'undefined') opts.map = {} if (!opts.map.inline) opts.map.inline = false opts.map.prev = css.map } } else { let parser = parse if (opts.syntax) parser = opts.syntax.parse if (opts.parser) parser = opts.parser if (parser.parse) parser = parser.parse try { root = parser(css, opts) } catch (error) { this.processed = true this.error = error } if (root && !root[my]) { /* c8 ignore next 2 */ Container.rebuild(root) } } this.result = new Result(processor, root, opts) this.helpers = { ...postcss, result: this.result, postcss } this.plugins = this.processor.plugins.map(plugin => { if (typeof plugin === 'object' && plugin.prepare) { return { ...plugin, ...plugin.prepare(this.result) } } else { return plugin } }) } get [Symbol.toStringTag]() { return 'LazyResult' } get processor() { return this.result.processor } get opts() { return this.result.opts } get css() { return this.stringify().css } get content() { return this.stringify().content } get map() { return this.stringify().map } get root() { return this.sync().root } get messages() { return this.sync().messages } warnings() { return this.sync().warnings() } toString() { return this.css } then(onFulfilled, onRejected) { if (process.env.NODE_ENV !== 'production') { if (!('from' in this.opts)) { warnOnce( 'Without `from` option PostCSS could generate wrong source map ' + 'and will not find Browserslist config. Set it to CSS file path ' + 'or to `undefined` to prevent this warning.' ) } } return this.async().then(onFulfilled, onRejected) } catch(onRejected) { return this.async().catch(onRejected) } finally(onFinally) { return this.async().then(onFinally, onFinally) } async() { if (this.error) return Promise.reject(this.error) if (this.processed) return Promise.resolve(this.result) if (!this.processing) { this.processing = this.runAsync() } return this.processing } sync() { if (this.error) throw this.error if (this.processed) return this.result this.processed = true if (this.processing) { throw this.getAsyncError() } for (let plugin of this.plugins) { let promise = this.runOnRoot(plugin) if (isPromise(promise)) { throw this.getAsyncError() } } this.prepareVisitors() if (this.hasListener) { let root = this.result.root while (!root[isClean]) { root[isClean] = true this.walkSync(root) } if (this.listeners.OnceExit) { if (root.type === 'document') { for (let subRoot of root.nodes) { this.visitSync(this.listeners.OnceExit, subRoot) } } else { this.visitSync(this.listeners.OnceExit, root) } } } return this.result } stringify() { if (this.error) throw this.error if (this.stringified) return this.result this.stringified = true this.sync() let opts = this.result.opts let str = stringify if (opts.syntax) str = opts.syntax.stringify if (opts.stringifier) str = opts.stringifier if (str.stringify) str = str.stringify let map = new MapGenerator(str, this.result.root, this.result.opts) let data = map.generate() this.result.css = data[0] this.result.map = data[1] return this.result } walkSync(node) { node[isClean] = true let events = getEvents(node) for (let event of events) { if (event === CHILDREN) { if (node.nodes) { node.each(child => { if (!child[isClean]) this.walkSync(child) }) } } else { let visitors = this.listeners[event] if (visitors) { if (this.visitSync(visitors, node.toProxy())) return } } } } visitSync(visitors, node) { for (let [plugin, visitor] of visitors) { this.result.lastPlugin = plugin let promise try { promise = visitor(node, this.helpers) } catch (e) { throw this.handleError(e, node.proxyOf) } if (node.type !== 'root' && node.type !== 'document' && !node.parent) { return true } if (isPromise(promise)) { throw this.getAsyncError() } } } runOnRoot(plugin) { this.result.lastPlugin = plugin try { if (typeof plugin === 'object' && plugin.Once) { if (this.result.root.type === 'document') { let roots = this.result.root.nodes.map(root => plugin.Once(root, this.helpers) ) if (isPromise(roots[0])) { return Promise.all(roots) } return roots } return plugin.Once(this.result.root, this.helpers) } else if (typeof plugin === 'function') { return plugin(this.result.root, this.result) } } catch (error) { throw this.handleError(error) } } getAsyncError() { throw new Error('Use process(css).then(cb) to work with async plugins') } handleError(error, node) { let plugin = this.result.lastPlugin try { if (node) node.addToError(error) this.error = error if (error.name === 'CssSyntaxError' && !error.plugin) { error.plugin = plugin.postcssPlugin error.setMessage() } else if (plugin.postcssVersion) { if (process.env.NODE_ENV !== 'production') { let pluginName = plugin.postcssPlugin let pluginVer = plugin.postcssVersion let runtimeVer = this.result.processor.version let a = pluginVer.split('.') let b = runtimeVer.split('.') if (a[0] !== b[0] || parseInt(a[1]) > parseInt(b[1])) { // eslint-disable-next-line no-console console.error( 'Unknown error from PostCSS plugin. Your current PostCSS ' + 'version is ' + runtimeVer + ', but ' + pluginName + ' uses ' + pluginVer + '. Perhaps this is the source of the error below.' ) } } } } catch (err) { /* c8 ignore next 3 */ // eslint-disable-next-line no-console if (console && console.error) console.error(err) } return error } async runAsync() { this.plugin = 0 for (let i = 0; i < this.plugins.length; i++) { let plugin = this.plugins[i] let promise = this.runOnRoot(plugin) if (isPromise(promise)) { try { await promise } catch (error) { throw this.handleError(error) } } } this.prepareVisitors() if (this.hasListener) { let root = this.result.root while (!root[isClean]) { root[isClean] = true let stack = [toStack(root)] while (stack.length > 0) { let promise = this.visitTick(stack) if (isPromise(promise)) { try { await promise } catch (e) { let node = stack[stack.length - 1].node throw this.handleError(e, node) } } } } if (this.listeners.OnceExit) { for (let [plugin, visitor] of this.listeners.OnceExit) { this.result.lastPlugin = plugin try { if (root.type === 'document') { let roots = root.nodes.map(subRoot => visitor(subRoot, this.helpers) ) await Promise.all(roots) } else { await visitor(root, this.helpers) } } catch (e) { throw this.handleError(e) } } } } this.processed = true return this.stringify() } prepareVisitors() { this.listeners = {} let add = (plugin, type, cb) => { if (!this.listeners[type]) this.listeners[type] = [] this.listeners[type].push([plugin, cb]) } for (let plugin of this.plugins) { if (typeof plugin === 'object') { for (let event in plugin) { if (!PLUGIN_PROPS[event] && /^[A-Z]/.test(event)) { throw new Error( `Unknown event ${event} in ${plugin.postcssPlugin}. ` + `Try to update PostCSS (${this.processor.version} now).` ) } if (!NOT_VISITORS[event]) { if (typeof plugin[event] === 'object') { for (let filter in plugin[event]) { if (filter === '*') { add(plugin, event, plugin[event][filter]) } else { add( plugin, event + '-' + filter.toLowerCase(), plugin[event][filter] ) } } } else if (typeof plugin[event] === 'function') { add(plugin, event, plugin[event]) } } } } } this.hasListener = Object.keys(this.listeners).length > 0 } visitTick(stack) { let visit = stack[stack.length - 1] let { node, visitors } = visit if (node.type !== 'root' && node.type !== 'document' && !node.parent) { stack.pop() return } if (visitors.length > 0 && visit.visitorIndex < visitors.length) { let [plugin, visitor] = visitors[visit.visitorIndex] visit.visitorIndex += 1 if (visit.visitorIndex === visitors.length) { visit.visitors = [] visit.visitorIndex = 0 } this.result.lastPlugin = plugin try { return visitor(node.toProxy(), this.helpers) } catch (e) { throw this.handleError(e, node) } } if (visit.iterator !== 0) { let iterator = visit.iterator let child while ((child = node.nodes[node.indexes[iterator]])) { node.indexes[iterator] += 1 if (!child[isClean]) { child[isClean] = true stack.push(toStack(child)) return } } visit.iterator = 0 delete node.indexes[iterator] } let events = visit.events while (visit.eventIndex < events.length) { let event = events[visit.eventIndex] visit.eventIndex += 1 if (event === CHILDREN) { if (node.nodes && node.nodes.length) { node[isClean] = true visit.iterator = node.getIterator() } return } else if (this.listeners[event]) { visit.visitors = this.listeners[event] return } } stack.pop() } } LazyResult.registerPostcss = dependant => { postcss = dependant } module.exports = LazyResult LazyResult.default = LazyResult Root.registerLazyResult(LazyResult) Document.registerLazyResult(LazyResult) postcss-8.4.6/lib/list.d.ts000066400000000000000000000023561417621533600155600ustar00rootroot00000000000000export type List = { /** * Safely splits values. * * ```js * Once (root, { list }) { * list.split('1px calc(10% + 1px)', [' ', '\n', '\t']) //=> ['1px', 'calc(10% + 1px)'] * } * ``` * * @param string separated values. * @param separators array of separators. * @param last boolean indicator. * @return Split values. */ split(string: string, separators: string[], last: boolean): string[] /** * Safely splits space-separated values (such as those for `background`, * `border-radius`, and other shorthand properties). * * ```js * Once (root, { list }) { * list.space('1px calc(10% + 1px)') //=> ['1px', 'calc(10% + 1px)'] * } * ``` * * @param str Space-separated values. * @return Split values. */ space(str: string): string[] /** * Safely splits comma-separated values (such as those for `transition-*` * and `background` properties). * * ```js * Once (root, { list }) { * list.comma('black, linear-gradient(white, black)') * //=> ['black', 'linear-gradient(white, black)'] * } * ``` * * @param str Comma-separated values. * @return Split values. */ comma(str: string): string[] } declare const list: List export default list postcss-8.4.6/lib/list.js000066400000000000000000000022171417621533600153200ustar00rootroot00000000000000'use strict' let list = { split(string, separators, last) { let array = [] let current = '' let split = false let func = 0 let quote = false let escape = false for (let letter of string) { if (escape) { escape = false } else if (letter === '\\') { escape = true } else if (quote) { if (letter === quote) { quote = false } } else if (letter === '"' || letter === "'") { quote = letter } else if (letter === '(') { func += 1 } else if (letter === ')') { if (func > 0) func -= 1 } else if (func === 0) { if (separators.includes(letter)) split = true } if (split) { if (current !== '') array.push(current.trim()) current = '' split = false } else { current += letter } } if (last || current !== '') array.push(current.trim()) return array }, space(string) { let spaces = [' ', '\n', '\t'] return list.split(string, spaces) }, comma(string) { return list.split(string, [','], true) } } module.exports = list list.default = list postcss-8.4.6/lib/map-generator.js000066400000000000000000000211221417621533600171020ustar00rootroot00000000000000'use strict' let { SourceMapConsumer, SourceMapGenerator } = require('source-map-js') let { dirname, resolve, relative, sep } = require('path') let { pathToFileURL } = require('url') let Input = require('./input') let sourceMapAvailable = Boolean(SourceMapConsumer && SourceMapGenerator) let pathAvailable = Boolean(dirname && resolve && relative && sep) class MapGenerator { constructor(stringify, root, opts, cssString) { this.stringify = stringify this.mapOpts = opts.map || {} this.root = root this.opts = opts this.css = cssString } isMap() { if (typeof this.opts.map !== 'undefined') { return !!this.opts.map } return this.previous().length > 0 } previous() { if (!this.previousMaps) { this.previousMaps = [] if (this.root) { this.root.walk(node => { if (node.source && node.source.input.map) { let map = node.source.input.map if (!this.previousMaps.includes(map)) { this.previousMaps.push(map) } } }) } else { let input = new Input(this.css, this.opts) if (input.map) this.previousMaps.push(input.map) } } return this.previousMaps } isInline() { if (typeof this.mapOpts.inline !== 'undefined') { return this.mapOpts.inline } let annotation = this.mapOpts.annotation if (typeof annotation !== 'undefined' && annotation !== true) { return false } if (this.previous().length) { return this.previous().some(i => i.inline) } return true } isSourcesContent() { if (typeof this.mapOpts.sourcesContent !== 'undefined') { return this.mapOpts.sourcesContent } if (this.previous().length) { return this.previous().some(i => i.withContent()) } return true } clearAnnotation() { if (this.mapOpts.annotation === false) return if (this.root) { let node for (let i = this.root.nodes.length - 1; i >= 0; i--) { node = this.root.nodes[i] if (node.type !== 'comment') continue if (node.text.indexOf('# sourceMappingURL=') === 0) { this.root.removeChild(i) } } } else if (this.css) { this.css = this.css.replace(/(\n)?\/\*#[\S\s]*?\*\/$/gm, '') } } setSourcesContent() { let already = {} if (this.root) { this.root.walk(node => { if (node.source) { let from = node.source.input.from if (from && !already[from]) { already[from] = true this.map.setSourceContent( this.toUrl(this.path(from)), node.source.input.css ) } } }) } else if (this.css) { let from = this.opts.from ? this.toUrl(this.path(this.opts.from)) : '' this.map.setSourceContent(from, this.css) } } applyPrevMaps() { for (let prev of this.previous()) { let from = this.toUrl(this.path(prev.file)) let root = prev.root || dirname(prev.file) let map if (this.mapOpts.sourcesContent === false) { map = new SourceMapConsumer(prev.text) if (map.sourcesContent) { map.sourcesContent = map.sourcesContent.map(() => null) } } else { map = prev.consumer() } this.map.applySourceMap(map, from, this.toUrl(this.path(root))) } } isAnnotation() { if (this.isInline()) { return true } if (typeof this.mapOpts.annotation !== 'undefined') { return this.mapOpts.annotation } if (this.previous().length) { return this.previous().some(i => i.annotation) } return true } toBase64(str) { if (Buffer) { return Buffer.from(str).toString('base64') } else { return window.btoa(unescape(encodeURIComponent(str))) } } addAnnotation() { let content if (this.isInline()) { content = 'data:application/json;base64,' + this.toBase64(this.map.toString()) } else if (typeof this.mapOpts.annotation === 'string') { content = this.mapOpts.annotation } else if (typeof this.mapOpts.annotation === 'function') { content = this.mapOpts.annotation(this.opts.to, this.root) } else { content = this.outputFile() + '.map' } let eol = '\n' if (this.css.includes('\r\n')) eol = '\r\n' this.css += eol + '/*# sourceMappingURL=' + content + ' */' } outputFile() { if (this.opts.to) { return this.path(this.opts.to) } else if (this.opts.from) { return this.path(this.opts.from) } else { return 'to.css' } } generateMap() { if (this.root) { this.generateString() } else if (this.previous().length === 1) { let prev = this.previous()[0].consumer() prev.file = this.outputFile() this.map = SourceMapGenerator.fromSourceMap(prev) } else { this.map = new SourceMapGenerator({ file: this.outputFile() }) this.map.addMapping({ source: this.opts.from ? this.toUrl(this.path(this.opts.from)) : '', generated: { line: 1, column: 0 }, original: { line: 1, column: 0 } }) } if (this.isSourcesContent()) this.setSourcesContent() if (this.root && this.previous().length > 0) this.applyPrevMaps() if (this.isAnnotation()) this.addAnnotation() if (this.isInline()) { return [this.css] } else { return [this.css, this.map] } } path(file) { if (file.indexOf('<') === 0) return file if (/^\w+:\/\//.test(file)) return file if (this.mapOpts.absolute) return file let from = this.opts.to ? dirname(this.opts.to) : '.' if (typeof this.mapOpts.annotation === 'string') { from = dirname(resolve(from, this.mapOpts.annotation)) } file = relative(from, file) return file } toUrl(path) { if (sep === '\\') { path = path.replace(/\\/g, '/') } return encodeURI(path).replace(/[#?]/g, encodeURIComponent) } sourcePath(node) { if (this.mapOpts.from) { return this.toUrl(this.mapOpts.from) } else if (this.mapOpts.absolute) { if (pathToFileURL) { return pathToFileURL(node.source.input.from).toString() } else { throw new Error( '`map.absolute` option is not available in this PostCSS build' ) } } else { return this.toUrl(this.path(node.source.input.from)) } } generateString() { this.css = '' this.map = new SourceMapGenerator({ file: this.outputFile() }) let line = 1 let column = 1 let noSource = '' let mapping = { source: '', generated: { line: 0, column: 0 }, original: { line: 0, column: 0 } } let lines, last this.stringify(this.root, (str, node, type) => { this.css += str if (node && type !== 'end') { mapping.generated.line = line mapping.generated.column = column - 1 if (node.source && node.source.start) { mapping.source = this.sourcePath(node) mapping.original.line = node.source.start.line mapping.original.column = node.source.start.column - 1 this.map.addMapping(mapping) } else { mapping.source = noSource mapping.original.line = 1 mapping.original.column = 0 this.map.addMapping(mapping) } } lines = str.match(/\n/g) if (lines) { line += lines.length last = str.lastIndexOf('\n') column = str.length - last } else { column += str.length } if (node && type !== 'start') { let p = node.parent || { raws: {} } if (node.type !== 'decl' || node !== p.last || p.raws.semicolon) { if (node.source && node.source.end) { mapping.source = this.sourcePath(node) mapping.original.line = node.source.end.line mapping.original.column = node.source.end.column - 1 mapping.generated.line = line mapping.generated.column = column - 2 this.map.addMapping(mapping) } else { mapping.source = noSource mapping.original.line = 1 mapping.original.column = 0 mapping.generated.line = line mapping.generated.column = column - 1 this.map.addMapping(mapping) } } } }) } generate() { this.clearAnnotation() if (pathAvailable && sourceMapAvailable && this.isMap()) { return this.generateMap() } else { let result = '' this.stringify(this.root, i => { result += i }) return [result] } } } module.exports = MapGenerator postcss-8.4.6/lib/no-work-result.d.ts000066400000000000000000000024531417621533600175130ustar00rootroot00000000000000import Result, { Message, ResultOptions } from './result.js' import { SourceMap } from './postcss.js' import Processor from './processor.js' import Warning from './warning.js' import Root from './root.js' import LazyResult from './lazy-result.js' /** * A Promise proxy for the result of PostCSS transformations. * This lazy result instance doesn't parse css unless `NoWorkResult#root` or `Result#root` * are accessed. See the example below for details. * A `NoWork` instance is returned by `Processor#process` ONLY when no plugins defined. * * ```js * const noWorkResult = postcss().process(css) // No plugins are defined. * // CSS is not parsed * let root = noWorkResult.root // now css is parsed because we accessed the root * ``` */ export default class NoWorkResult implements LazyResult { then: Promise['then'] catch: Promise['catch'] finally: Promise['finally'] constructor(processor: Processor, css: string, opts: ResultOptions) get [Symbol.toStringTag](): string get processor(): Processor get opts(): ResultOptions get css(): string get content(): string get map(): SourceMap get root(): Root get messages(): Message[] warnings(): Warning[] toString(): string sync(): Result async(): Promise } postcss-8.4.6/lib/no-work-result.js000066400000000000000000000047671417621533600172710ustar00rootroot00000000000000'use strict' let MapGenerator = require('./map-generator') let stringify = require('./stringify') let warnOnce = require('./warn-once') let parse = require('./parse') const Result = require('./result') class NoWorkResult { constructor(processor, css, opts) { css = css.toString() this.stringified = false this._processor = processor this._css = css this._opts = opts this._map = undefined let root let str = stringify this.result = new Result(this._processor, root, this._opts) this.result.css = css let self = this Object.defineProperty(this.result, 'root', { get() { return self.root } }) let map = new MapGenerator(str, root, this._opts, css) if (map.isMap()) { let [generatedCSS, generatedMap] = map.generate() if (generatedCSS) { this.result.css = generatedCSS } if (generatedMap) { this.result.map = generatedMap } } } get [Symbol.toStringTag]() { return 'NoWorkResult' } get processor() { return this.result.processor } get opts() { return this.result.opts } get css() { return this.result.css } get content() { return this.result.css } get map() { return this.result.map } get root() { if (this._root) { return this._root } let root let parser = parse try { root = parser(this._css, this._opts) } catch (error) { this.error = error } if (this.error) { throw this.error } else { this._root = root return root } } get messages() { return [] } warnings() { return [] } toString() { return this._css } then(onFulfilled, onRejected) { if (process.env.NODE_ENV !== 'production') { if (!('from' in this._opts)) { warnOnce( 'Without `from` option PostCSS could generate wrong source map ' + 'and will not find Browserslist config. Set it to CSS file path ' + 'or to `undefined` to prevent this warning.' ) } } return this.async().then(onFulfilled, onRejected) } catch(onRejected) { return this.async().catch(onRejected) } finally(onFinally) { return this.async().then(onFinally, onFinally) } async() { if (this.error) return Promise.reject(this.error) return Promise.resolve(this.result) } sync() { if (this.error) throw this.error return this.result } } module.exports = NoWorkResult NoWorkResult.default = NoWorkResult postcss-8.4.6/lib/node.d.ts000066400000000000000000000302351417621533600155270ustar00rootroot00000000000000import Declaration, { DeclarationProps } from './declaration.js' import Comment, { CommentProps } from './comment.js' import { Stringifier, Syntax } from './postcss.js' import AtRule, { AtRuleProps } from './at-rule.js' import Rule, { RuleProps } from './rule.js' import { WarningOptions } from './warning.js' import CssSyntaxError from './css-syntax-error.js' import Result from './result.js' import Input from './input.js' import Root from './root.js' import Document from './document.js' import Container from './container.js' export type ChildNode = AtRule | Rule | Declaration | Comment export type AnyNode = AtRule | Rule | Declaration | Comment | Root | Document export type ChildProps = | AtRuleProps | RuleProps | DeclarationProps | CommentProps export interface Position { /** * Source offset in file. It starts from 0. */ offset: number /** * Source line in file. In contrast to `offset` it starts from 1. */ column: number /** * Source column in file. */ line: number } export interface Range { /** * Start position, inclusive. */ start: Position /** * End position, exclusive. */ end: Position } export interface Source { /** * The file source of the node. */ input: Input /** * The inclusive starting position of the node’s source. */ start?: Position /** * The inclusive ending position of the node's source. */ end?: Position } export interface NodeProps { source?: Source } interface NodeErrorOptions { /** * Plugin name that created this error. PostCSS will set it automatically. */ plugin?: string /** * A word inside a node's string, that should be highlighted as source * of error. */ word?: string /** * An index inside a node's string that should be highlighted as source * of error. */ index?: number /** * An ending index inside a node's string that should be highlighted as * source of error. */ endIndex?: number } /** * All node classes inherit the following common methods. * * You should not extend this classes to create AST for selector or value * parser. */ export default abstract class Node { /** * tring representing the node’s type. Possible values are `root`, `atrule`, * `rule`, `decl`, or `comment`. * * ```js * new Declaration({ prop: 'color', value: 'black' }).type //=> 'decl' * ``` */ type: string /** * The node’s parent node. * * ```js * root.nodes[0].parent === root * ``` */ parent: Document | Container | undefined /** * The input source of the node. * * The property is used in source map generation. * * If you create a node manually (e.g., with `postcss.decl()`), * that node will not have a `source` property and will be absent * from the source map. For this reason, the plugin developer should * consider cloning nodes to create new ones (in which case the new node’s * source will reference the original, cloned node) or setting * the `source` property manually. * * ```js * decl.source.input.from //=> '/home/ai/a.sass' * decl.source.start //=> { line: 10, column: 2 } * decl.source.end //=> { line: 10, column: 12 } * ``` * * ```js * // Bad * const prefixed = postcss.decl({ * prop: '-moz-' + decl.prop, * value: decl.value * }) * * // Good * const prefixed = decl.clone({ prop: '-moz-' + decl.prop }) * ``` * * ```js * if (atrule.name === 'add-link') { * const rule = postcss.rule({ selector: 'a', source: atrule.source }) * atrule.parent.insertBefore(atrule, rule) * } * ``` */ source?: Source /** * Information to generate byte-to-byte equal node string as it was * in the origin input. * * Every parser saves its own properties, * but the default CSS parser uses: * * * `before`: the space symbols before the node. It also stores `*` * and `_` symbols before the declaration (IE hack). * * `after`: the space symbols after the last child of the node * to the end of the node. * * `between`: the symbols between the property and value * for declarations, selector and `{` for rules, or last parameter * and `{` for at-rules. * * `semicolon`: contains true if the last child has * an (optional) semicolon. * * `afterName`: the space between the at-rule name and its parameters. * * `left`: the space symbols between `/*` and the comment’s text. * * `right`: the space symbols between the comment’s text * and */. * * `important`: the content of the important statement, * if it is not just `!important`. * * PostCSS cleans selectors, declaration values and at-rule parameters * from comments and extra spaces, but it stores origin content in raws * properties. As such, if you don’t change a declaration’s value, * PostCSS will use the raw value with comments. * * ```js * const root = postcss.parse('a {\n color:black\n}') * root.first.first.raws //=> { before: '\n ', between: ':' } * ``` */ raws: any /** * @param defaults Value for node properties. */ constructor(defaults?: object) /** * Returns a `CssSyntaxError` instance containing the original position * of the node in the source, showing line and column numbers and also * a small excerpt to facilitate debugging. * * If present, an input source map will be used to get the original position * of the source, even from a previous compilation step * (e.g., from Sass compilation). * * This method produces very useful error messages. * * ```js * if (!variables[name]) { * throw decl.error(`Unknown variable ${name}`, { word: name }) * // CssSyntaxError: postcss-vars:a.sass:4:3: Unknown variable $black * // color: $black * // a * // ^ * // background: white * } * ``` * * @param message Error description. * @param opts Options. * * @return Error object to throw it. */ error(message: string, options?: NodeErrorOptions): CssSyntaxError /** * This method is provided as a convenience wrapper for `Result#warn`. * * ```js * Declaration: { * bad: (decl, { result }) => { * decl.warn(result, 'Deprecated property bad') * } * } * ``` * * @param result The `Result` instance that will receive the warning. * @param text Warning message. * @param opts Warning Options. * * @return Created warning object. */ warn(result: Result, text: string, opts?: WarningOptions): void /** * Removes the node from its parent and cleans the parent properties * from the node and its children. * * ```js * if (decl.prop.match(/^-webkit-/)) { * decl.remove() * } * ``` * * @return Node to make calls chain. */ remove(): this /** * Returns a CSS string representing the node. * * ```js * new Rule({ selector: 'a' }).toString() //=> "a {}" * ``` * * @param stringifier A syntax to use in string generation. * @return CSS string of this node. */ toString(stringifier?: Stringifier | Syntax): string /** * Assigns properties to the current node. * * ```js * decl.assign({ prop: 'word-wrap', value: 'break-word' }) * ``` * * @param overrides New properties to override the node. * @return Current node to methods chain. */ assign(overrides: object): this /** * Returns an exact clone of the node. * * The resulting cloned node and its (cloned) children will retain * code style properties. * * ```js * decl.raws.before //=> "\n " * const cloned = decl.clone({ prop: '-moz-' + decl.prop }) * cloned.raws.before //=> "\n " * cloned.toString() //=> -moz-transform: scale(0) * ``` * * @param overrides New properties to override in the clone. * @return Clone of the node. */ clone(overrides?: object): this /** * Shortcut to clone the node and insert the resulting cloned node * before the current node. * * ```js * decl.cloneBefore({ prop: '-moz-' + decl.prop }) * ``` * * @param overrides Mew properties to override in the clone. * * @return New node */ cloneBefore(overrides?: object): this /** * Shortcut to clone the node and insert the resulting cloned node * after the current node. * * @param overrides New properties to override in the clone. * @return New node. */ cloneAfter(overrides?: object): this /** * Inserts node(s) before the current node and removes the current node. * * ```js * AtRule: { * mixin: atrule => { * atrule.replaceWith(mixinRules[atrule.params]) * } * } * ``` * * @param nodes Mode(s) to replace current one. * @return Current node to methods chain. */ replaceWith( ...nodes: (ChildNode | ChildProps | ChildNode[] | ChildProps[])[] ): this /** * Returns the next child of the node’s parent. * Returns `undefined` if the current node is the last child. * * ```js * if (comment.text === 'delete next') { * const next = comment.next() * if (next) { * next.remove() * } * } * ``` * * @return Next node. */ next(): ChildNode | undefined /** * Returns the previous child of the node’s parent. * Returns `undefined` if the current node is the first child. * * ```js * const annotation = decl.prev() * if (annotation.type === 'comment') { * readAnnotation(annotation.text) * } * ``` * * @return Previous node. */ prev(): ChildNode | undefined /** * Insert new node before current node to current node’s parent. * * Just alias for `node.parent.insertBefore(node, add)`. * * ```js * decl.before('content: ""') * ``` * * @param newNode New node. * @return This node for methods chain. */ before(newNode: Node | ChildProps | string | Node[]): this /** * Insert new node after current node to current node’s parent. * * Just alias for `node.parent.insertAfter(node, add)`. * * ```js * decl.after('color: black') * ``` * * @param newNode New node. * @return This node for methods chain. */ after(newNode: Node | ChildProps | string | Node[]): this /** * Finds the Root instance of the node’s tree. * * ```js * root.nodes[0].nodes[0].root() === root * ``` * * @return Root parent. */ root(): Root /** * Returns a `Node#raws` value. If the node is missing * the code style property (because the node was manually built or cloned), * PostCSS will try to autodetect the code style property by looking * at other nodes in the tree. * * ```js * const root = postcss.parse('a { background: white }') * root.nodes[0].append({ prop: 'color', value: 'black' }) * root.nodes[0].nodes[1].raws.before //=> undefined * root.nodes[0].nodes[1].raw('before') //=> ' ' * ``` * * @param prop Name of code style property. * @param defaultType Name of default value, it can be missed * if the value is the same as prop. * @return {string} Code style value. */ raw(prop: string, defaultType?: string): string /** * Clear the code style properties for the node and its children. * * ```js * node.raws.before //=> ' ' * node.cleanRaws() * node.raws.before //=> undefined * ``` * * @param keepBetween Keep the `raws.between` symbols. */ cleanRaws(keepBetween?: boolean): void /** * Fix circular links on `JSON.stringify()`. * * @return Cleaned object. */ toJSON(): object /** * Convert string index to line/column. * * @param index The symbol number in the node’s string. * @return Symbol position in file. */ positionInside(index: number): Position /** * Get the position for a word or an index inside the node. * * @param opts Options. * @return Position. */ positionBy(opts?: Pick): Position /** * Get the range for a word or start and end index inside the node. * The start index is inclusive; the end index is exclusive. * * @param opts Options. * @return Range. */ rangeBy(opts?: Pick): Range } postcss-8.4.6/lib/node.js000066400000000000000000000204451417621533600152750ustar00rootroot00000000000000'use strict' let { isClean, my } = require('./symbols') let CssSyntaxError = require('./css-syntax-error') let Stringifier = require('./stringifier') let stringify = require('./stringify') function cloneNode(obj, parent) { let cloned = new obj.constructor() for (let i in obj) { if (!Object.prototype.hasOwnProperty.call(obj, i)) { /* c8 ignore next 2 */ continue } if (i === 'proxyCache') continue let value = obj[i] let type = typeof value if (i === 'parent' && type === 'object') { if (parent) cloned[i] = parent } else if (i === 'source') { cloned[i] = value } else if (Array.isArray(value)) { cloned[i] = value.map(j => cloneNode(j, cloned)) } else { if (type === 'object' && value !== null) value = cloneNode(value) cloned[i] = value } } return cloned } class Node { constructor(defaults = {}) { this.raws = {} this[isClean] = false this[my] = true for (let name in defaults) { if (name === 'nodes') { this.nodes = [] for (let node of defaults[name]) { if (typeof node.clone === 'function') { this.append(node.clone()) } else { this.append(node) } } } else { this[name] = defaults[name] } } } error(message, opts = {}) { if (this.source) { let { start, end } = this.rangeBy(opts) return this.source.input.error( message, { line: start.line, column: start.column }, { line: end.line, column: end.column }, opts ) } return new CssSyntaxError(message) } warn(result, text, opts) { let data = { node: this } for (let i in opts) data[i] = opts[i] return result.warn(text, data) } remove() { if (this.parent) { this.parent.removeChild(this) } this.parent = undefined return this } toString(stringifier = stringify) { if (stringifier.stringify) stringifier = stringifier.stringify let result = '' stringifier(this, i => { result += i }) return result } assign(overrides = {}) { for (let name in overrides) { this[name] = overrides[name] } return this } clone(overrides = {}) { let cloned = cloneNode(this) for (let name in overrides) { cloned[name] = overrides[name] } return cloned } cloneBefore(overrides = {}) { let cloned = this.clone(overrides) this.parent.insertBefore(this, cloned) return cloned } cloneAfter(overrides = {}) { let cloned = this.clone(overrides) this.parent.insertAfter(this, cloned) return cloned } replaceWith(...nodes) { if (this.parent) { let bookmark = this let foundSelf = false for (let node of nodes) { if (node === this) { foundSelf = true } else if (foundSelf) { this.parent.insertAfter(bookmark, node) bookmark = node } else { this.parent.insertBefore(bookmark, node) } } if (!foundSelf) { this.remove() } } return this } next() { if (!this.parent) return undefined let index = this.parent.index(this) return this.parent.nodes[index + 1] } prev() { if (!this.parent) return undefined let index = this.parent.index(this) return this.parent.nodes[index - 1] } before(add) { this.parent.insertBefore(this, add) return this } after(add) { this.parent.insertAfter(this, add) return this } root() { let result = this while (result.parent && result.parent.type !== 'document') { result = result.parent } return result } raw(prop, defaultType) { let str = new Stringifier() return str.raw(this, prop, defaultType) } cleanRaws(keepBetween) { delete this.raws.before delete this.raws.after if (!keepBetween) delete this.raws.between } toJSON(_, inputs) { let fixed = {} let emitInputs = inputs == null inputs = inputs || new Map() let inputsNextIndex = 0 for (let name in this) { if (!Object.prototype.hasOwnProperty.call(this, name)) { /* c8 ignore next 2 */ continue } if (name === 'parent' || name === 'proxyCache') continue let value = this[name] if (Array.isArray(value)) { fixed[name] = value.map(i => { if (typeof i === 'object' && i.toJSON) { return i.toJSON(null, inputs) } else { return i } }) } else if (typeof value === 'object' && value.toJSON) { fixed[name] = value.toJSON(null, inputs) } else if (name === 'source') { let inputId = inputs.get(value.input) if (inputId == null) { inputId = inputsNextIndex inputs.set(value.input, inputsNextIndex) inputsNextIndex++ } fixed[name] = { inputId, start: value.start, end: value.end } } else { fixed[name] = value } } if (emitInputs) { fixed.inputs = [...inputs.keys()].map(input => input.toJSON()) } return fixed } positionInside(index) { let string = this.toString() let column = this.source.start.column let line = this.source.start.line for (let i = 0; i < index; i++) { if (string[i] === '\n') { column = 1 line += 1 } else { column += 1 } } return { line, column } } positionBy(opts) { let pos = this.source.start if (opts.index) { pos = this.positionInside(opts.index) } else if (opts.word) { let index = this.toString().indexOf(opts.word) if (index !== -1) pos = this.positionInside(index) } return pos } rangeBy(opts) { let start = { line: this.source.start.line, column: this.source.start.column } let end = this.source.end ? { line: this.source.end.line, column: this.source.end.column + 1 } : { line: start.line, column: start.column + 1 } if (opts.word) { let index = this.toString().indexOf(opts.word) if (index !== -1) { start = this.positionInside(index) end = this.positionInside(index + opts.word.length) } } else { if (opts.start) { start = { line: opts.start.line, column: opts.start.column } } else if (opts.index) { start = this.positionInside(opts.index) } if (opts.end) { end = { line: opts.end.line, column: opts.end.column } } else if (opts.endIndex) { end = this.positionInside(opts.endIndex) } else if (opts.index) { end = this.positionInside(opts.index + 1) } } if ( end.line < start.line || (end.line === start.line && end.column <= start.column) ) { end = { line: start.line, column: start.column + 1 } } return { start, end } } getProxyProcessor() { return { set(node, prop, value) { if (node[prop] === value) return true node[prop] = value if ( prop === 'prop' || prop === 'value' || prop === 'name' || prop === 'params' || prop === 'important' || /* c8 ignore next */ prop === 'text' ) { node.markDirty() } return true }, get(node, prop) { if (prop === 'proxyOf') { return node } else if (prop === 'root') { return () => node.root().toProxy() } else { return node[prop] } } } } toProxy() { if (!this.proxyCache) { this.proxyCache = new Proxy(this, this.getProxyProcessor()) } return this.proxyCache } addToError(error) { error.postcssNode = this if (error.stack && this.source && /\n\s{4}at /.test(error.stack)) { let s = this.source error.stack = error.stack.replace( /\n\s{4}at /, `$&${s.input.from}:${s.start.line}:${s.start.column}$&` ) } return error } markDirty() { if (this[isClean]) { this[isClean] = false let next = this while ((next = next.parent)) { next[isClean] = false } } } get proxyOf() { return this } } module.exports = Node Node.default = Node postcss-8.4.6/lib/parse.d.ts000066400000000000000000000001311417621533600157040ustar00rootroot00000000000000import { Parser } from './postcss.js' declare const parse: Parser export default parse postcss-8.4.6/lib/parse.js000066400000000000000000000021731417621533600154600ustar00rootroot00000000000000'use strict' let Container = require('./container') let Parser = require('./parser') let Input = require('./input') function parse(css, opts) { let input = new Input(css, opts) let parser = new Parser(input) try { parser.parse() } catch (e) { if (process.env.NODE_ENV !== 'production') { if (e.name === 'CssSyntaxError' && opts && opts.from) { if (/\.scss$/i.test(opts.from)) { e.message += '\nYou tried to parse SCSS with ' + 'the standard CSS parser; ' + 'try again with the postcss-scss parser' } else if (/\.sass/i.test(opts.from)) { e.message += '\nYou tried to parse Sass with ' + 'the standard CSS parser; ' + 'try again with the postcss-sass parser' } else if (/\.less$/i.test(opts.from)) { e.message += '\nYou tried to parse Less with ' + 'the standard CSS parser; ' + 'try again with the postcss-less parser' } } } throw e } return parser.root } module.exports = parse parse.default = parse Container.registerParse(parse) postcss-8.4.6/lib/parser.js000066400000000000000000000333201417621533600156400ustar00rootroot00000000000000'use strict' let Declaration = require('./declaration') let tokenizer = require('./tokenize') let Comment = require('./comment') let AtRule = require('./at-rule') let Root = require('./root') let Rule = require('./rule') class Parser { constructor(input) { this.input = input this.root = new Root() this.current = this.root this.spaces = '' this.semicolon = false this.customProperty = false this.createTokenizer() this.root.source = { input, start: { offset: 0, line: 1, column: 1 } } } createTokenizer() { this.tokenizer = tokenizer(this.input) } parse() { let token while (!this.tokenizer.endOfFile()) { token = this.tokenizer.nextToken() switch (token[0]) { case 'space': this.spaces += token[1] break case ';': this.freeSemicolon(token) break case '}': this.end(token) break case 'comment': this.comment(token) break case 'at-word': this.atrule(token) break case '{': this.emptyRule(token) break default: this.other(token) break } } this.endFile() } comment(token) { let node = new Comment() this.init(node, token[2]) node.source.end = this.getPosition(token[3] || token[2]) let text = token[1].slice(2, -2) if (/^\s*$/.test(text)) { node.text = '' node.raws.left = text node.raws.right = '' } else { let match = text.match(/^(\s*)([^]*\S)(\s*)$/) node.text = match[2] node.raws.left = match[1] node.raws.right = match[3] } } emptyRule(token) { let node = new Rule() this.init(node, token[2]) node.selector = '' node.raws.between = '' this.current = node } other(start) { let end = false let type = null let colon = false let bracket = null let brackets = [] let customProperty = start[1].startsWith('--') let tokens = [] let token = start while (token) { type = token[0] tokens.push(token) if (type === '(' || type === '[') { if (!bracket) bracket = token brackets.push(type === '(' ? ')' : ']') } else if (customProperty && colon && type === '{') { if (!bracket) bracket = token brackets.push('}') } else if (brackets.length === 0) { if (type === ';') { if (colon) { this.decl(tokens, customProperty) return } else { break } } else if (type === '{') { this.rule(tokens) return } else if (type === '}') { this.tokenizer.back(tokens.pop()) end = true break } else if (type === ':') { colon = true } } else if (type === brackets[brackets.length - 1]) { brackets.pop() if (brackets.length === 0) bracket = null } token = this.tokenizer.nextToken() } if (this.tokenizer.endOfFile()) end = true if (brackets.length > 0) this.unclosedBracket(bracket) if (end && colon) { if (!customProperty) { while (tokens.length) { token = tokens[tokens.length - 1][0] if (token !== 'space' && token !== 'comment') break this.tokenizer.back(tokens.pop()) } } this.decl(tokens, customProperty) } else { this.unknownWord(tokens) } } rule(tokens) { tokens.pop() let node = new Rule() this.init(node, tokens[0][2]) node.raws.between = this.spacesAndCommentsFromEnd(tokens) this.raw(node, 'selector', tokens) this.current = node } decl(tokens, customProperty) { let node = new Declaration() this.init(node, tokens[0][2]) let last = tokens[tokens.length - 1] if (last[0] === ';') { this.semicolon = true tokens.pop() } node.source.end = this.getPosition(last[3] || last[2]) while (tokens[0][0] !== 'word') { if (tokens.length === 1) this.unknownWord(tokens) node.raws.before += tokens.shift()[1] } node.source.start = this.getPosition(tokens[0][2]) node.prop = '' while (tokens.length) { let type = tokens[0][0] if (type === ':' || type === 'space' || type === 'comment') { break } node.prop += tokens.shift()[1] } node.raws.between = '' let token while (tokens.length) { token = tokens.shift() if (token[0] === ':') { node.raws.between += token[1] break } else { if (token[0] === 'word' && /\w/.test(token[1])) { this.unknownWord([token]) } node.raws.between += token[1] } } if (node.prop[0] === '_' || node.prop[0] === '*') { node.raws.before += node.prop[0] node.prop = node.prop.slice(1) } let firstSpaces = [] let next while (tokens.length) { next = tokens[0][0] if (next !== 'space' && next !== 'comment') break firstSpaces.push(tokens.shift()) } this.precheckMissedSemicolon(tokens) for (let i = tokens.length - 1; i >= 0; i--) { token = tokens[i] if (token[1].toLowerCase() === '!important') { node.important = true let string = this.stringFrom(tokens, i) string = this.spacesFromEnd(tokens) + string if (string !== ' !important') node.raws.important = string break } else if (token[1].toLowerCase() === 'important') { let cache = tokens.slice(0) let str = '' for (let j = i; j > 0; j--) { let type = cache[j][0] if (str.trim().indexOf('!') === 0 && type !== 'space') { break } str = cache.pop()[1] + str } if (str.trim().indexOf('!') === 0) { node.important = true node.raws.important = str tokens = cache } } if (token[0] !== 'space' && token[0] !== 'comment') { break } } let hasWord = tokens.some(i => i[0] !== 'space' && i[0] !== 'comment') if (hasWord) { node.raws.between += firstSpaces.map(i => i[1]).join('') firstSpaces = [] } this.raw(node, 'value', firstSpaces.concat(tokens), customProperty) if (node.value.includes(':') && !customProperty) { this.checkMissedSemicolon(tokens) } } atrule(token) { let node = new AtRule() node.name = token[1].slice(1) if (node.name === '') { this.unnamedAtrule(node, token) } this.init(node, token[2]) let type let prev let shift let last = false let open = false let params = [] let brackets = [] while (!this.tokenizer.endOfFile()) { token = this.tokenizer.nextToken() type = token[0] if (type === '(' || type === '[') { brackets.push(type === '(' ? ')' : ']') } else if (type === '{' && brackets.length > 0) { brackets.push('}') } else if (type === brackets[brackets.length - 1]) { brackets.pop() } if (brackets.length === 0) { if (type === ';') { node.source.end = this.getPosition(token[2]) this.semicolon = true break } else if (type === '{') { open = true break } else if (type === '}') { if (params.length > 0) { shift = params.length - 1 prev = params[shift] while (prev && prev[0] === 'space') { prev = params[--shift] } if (prev) { node.source.end = this.getPosition(prev[3] || prev[2]) } } this.end(token) break } else { params.push(token) } } else { params.push(token) } if (this.tokenizer.endOfFile()) { last = true break } } node.raws.between = this.spacesAndCommentsFromEnd(params) if (params.length) { node.raws.afterName = this.spacesAndCommentsFromStart(params) this.raw(node, 'params', params) if (last) { token = params[params.length - 1] node.source.end = this.getPosition(token[3] || token[2]) this.spaces = node.raws.between node.raws.between = '' } } else { node.raws.afterName = '' node.params = '' } if (open) { node.nodes = [] this.current = node } } end(token) { if (this.current.nodes && this.current.nodes.length) { this.current.raws.semicolon = this.semicolon } this.semicolon = false this.current.raws.after = (this.current.raws.after || '') + this.spaces this.spaces = '' if (this.current.parent) { this.current.source.end = this.getPosition(token[2]) this.current = this.current.parent } else { this.unexpectedClose(token) } } endFile() { if (this.current.parent) this.unclosedBlock() if (this.current.nodes && this.current.nodes.length) { this.current.raws.semicolon = this.semicolon } this.current.raws.after = (this.current.raws.after || '') + this.spaces } freeSemicolon(token) { this.spaces += token[1] if (this.current.nodes) { let prev = this.current.nodes[this.current.nodes.length - 1] if (prev && prev.type === 'rule' && !prev.raws.ownSemicolon) { prev.raws.ownSemicolon = this.spaces this.spaces = '' } } } // Helpers getPosition(offset) { let pos = this.input.fromOffset(offset) return { offset, line: pos.line, column: pos.col } } init(node, offset) { this.current.push(node) node.source = { start: this.getPosition(offset), input: this.input } node.raws.before = this.spaces this.spaces = '' if (node.type !== 'comment') this.semicolon = false } raw(node, prop, tokens, customProperty) { let token, type let length = tokens.length let value = '' let clean = true let next, prev for (let i = 0; i < length; i += 1) { token = tokens[i] type = token[0] if (type === 'space' && i === length - 1 && !customProperty) { clean = false } else if (type === 'comment') { prev = tokens[i - 1] next = tokens[i + 1] if (prev && next && prev[0] !== 'space' && next[0] !== 'space') { value += token[1] } else { clean = false } } else { value += token[1] } } if (!clean) { let raw = tokens.reduce((all, i) => all + i[1], '') node.raws[prop] = { value, raw } } node[prop] = value } spacesAndCommentsFromEnd(tokens) { let lastTokenType let spaces = '' while (tokens.length) { lastTokenType = tokens[tokens.length - 1][0] if (lastTokenType !== 'space' && lastTokenType !== 'comment') break spaces = tokens.pop()[1] + spaces } return spaces } spacesAndCommentsFromStart(tokens) { let next let spaces = '' while (tokens.length) { next = tokens[0][0] if (next !== 'space' && next !== 'comment') break spaces += tokens.shift()[1] } return spaces } spacesFromEnd(tokens) { let lastTokenType let spaces = '' while (tokens.length) { lastTokenType = tokens[tokens.length - 1][0] if (lastTokenType !== 'space') break spaces = tokens.pop()[1] + spaces } return spaces } stringFrom(tokens, from) { let result = '' for (let i = from; i < tokens.length; i++) { result += tokens[i][1] } tokens.splice(from, tokens.length - from) return result } colon(tokens) { let brackets = 0 let token, type, prev for (let [i, element] of tokens.entries()) { token = element type = token[0] if (type === '(') { brackets += 1 } if (type === ')') { brackets -= 1 } if (brackets === 0 && type === ':') { if (!prev) { this.doubleColon(token) } else if (prev[0] === 'word' && prev[1] === 'progid') { continue } else { return i } } prev = token } return false } // Errors unclosedBracket(bracket) { throw this.input.error( 'Unclosed bracket', { offset: bracket[2] }, { offset: bracket[2] + 1 } ) } unknownWord(tokens) { throw this.input.error( 'Unknown word', { offset: tokens[0][2] }, { offset: tokens[0][2] + tokens[0][1].length } ) } unexpectedClose(token) { throw this.input.error( 'Unexpected }', { offset: token[2] }, { offset: token[2] + 1 } ) } unclosedBlock() { let pos = this.current.source.start throw this.input.error('Unclosed block', pos.line, pos.column) } doubleColon(token) { throw this.input.error( 'Double colon', { offset: token[2] }, { offset: token[2] + token[1].length } ) } unnamedAtrule(node, token) { throw this.input.error( 'At-rule without name', { offset: token[2] }, { offset: token[2] + token[1].length } ) } precheckMissedSemicolon(/* tokens */) { // Hook for Safe Parser } checkMissedSemicolon(tokens) { let colon = this.colon(tokens) if (colon === false) return let founded = 0 let token for (let j = colon - 1; j >= 0; j--) { token = tokens[j] if (token[0] !== 'space') { founded += 1 if (founded === 2) break } } // If the token is a word, e.g. `!important`, `red` or any other valid property's value. // Then we need to return the colon after that word token. [3] is the "end" colon of that word. // And because we need it after that one we do +1 to get the next one. throw this.input.error( 'Missed semicolon', token[0] === 'word' ? token[3] + 1 : token[2] ) } } module.exports = Parser postcss-8.4.6/lib/postcss.d.ts000066400000000000000000000261351417621533600163040ustar00rootroot00000000000000import { SourceMapGenerator, RawSourceMap } from 'source-map-js' import Node, { Position, Source, ChildNode, NodeErrorOptions, NodeProps, ChildProps, AnyNode } from './node.js' import Declaration, { DeclarationProps } from './declaration.js' import Container, { ContainerProps } from './container.js' import Document, { DocumentProps } from './document.js' import Warning, { WarningOptions } from './warning.js' import Comment, { CommentProps } from './comment.js' import AtRule, { AtRuleProps } from './at-rule.js' import Input, { FilePosition } from './input.js' import Result, { Message } from './result.js' import Root, { RootProps } from './root.js' import Rule, { RuleProps } from './rule.js' import CssSyntaxError from './css-syntax-error.js' import list, { List } from './list.js' import LazyResult from './lazy-result.js' import Processor from './processor.js' export { NodeErrorOptions, DeclarationProps, CssSyntaxError, ContainerProps, WarningOptions, DocumentProps, FilePosition, CommentProps, AtRuleProps, Declaration, ChildProps, LazyResult, ChildNode, NodeProps, Processor, RuleProps, RootProps, Container, Position, Document, AnyNode, Warning, Message, Comment, Source, AtRule, Result, Input, Node, list, Rule, Root } export type SourceMap = SourceMapGenerator & { toJSON(): RawSourceMap } export type Helpers = { result: Result; postcss: Postcss } & Postcss type DocumentProcessor = ( document: Document, helper: Helpers ) => Promise | void type RootProcessor = (root: Root, helper: Helpers) => Promise | void type DeclarationProcessor = ( decl: Declaration, helper: Helpers ) => Promise | void type RuleProcessor = (rule: Rule, helper: Helpers) => Promise | void type AtRuleProcessor = (atRule: AtRule, helper: Helpers) => Promise | void type CommentProcessor = ( comment: Comment, helper: Helpers ) => Promise | void interface Processors { /** * Will be called on `Document` node. * * Will be called again on children changes. */ Document?: DocumentProcessor /** * Will be called on `Document` node, when all children will be processed. * * Will be called again on children changes. */ DocumentExit?: DocumentProcessor /** * Will be called on `Root` node once. */ Once?: RootProcessor /** * Will be called on `Root` node once, when all children will be processed. */ OnceExit?: RootProcessor /** * Will be called on `Root` node. * * Will be called again on children changes. */ Root?: RootProcessor /** * Will be called on `Root` node, when all children will be processed. * * Will be called again on children changes. */ RootExit?: RootProcessor /** * Will be called on all `Declaration` nodes after listeners * for `Declaration` event. * * Will be called again on node or children changes. */ Declaration?: DeclarationProcessor | { [prop: string]: DeclarationProcessor } /** * Will be called on all `Declaration` nodes. * * Will be called again on node or children changes. */ DeclarationExit?: | DeclarationProcessor | { [prop: string]: DeclarationProcessor } /** * Will be called on all `Rule` nodes. * * Will be called again on node or children changes. */ Rule?: RuleProcessor /** * Will be called on all `Rule` nodes, when all children will be processed. * * Will be called again on node or children changes. */ RuleExit?: RuleProcessor /** * Will be called on all`AtRule` nodes. * * Will be called again on node or children changes. */ AtRule?: AtRuleProcessor | { [name: string]: AtRuleProcessor } /** * Will be called on all `AtRule` nodes, when all children will be processed. * * Will be called again on node or children changes. */ AtRuleExit?: AtRuleProcessor | { [name: string]: AtRuleProcessor } /** * Will be called on all `Comment` nodes. * * Will be called again on node or children changes. */ Comment?: CommentProcessor /** * Will be called on all `Comment` nodes after listeners * for `Comment` event. * * Will be called again on node or children changes. */ CommentExit?: CommentProcessor /** * Will be called when all other listeners processed the document. * * This listener will not be called again. */ Exit?: RootProcessor } export interface Plugin extends Processors { postcssPlugin: string prepare?: (result: Result) => Processors } export interface PluginCreator { (opts?: PluginOptions): Plugin | Processor postcss: true } export interface Transformer extends TransformCallback { postcssPlugin: string postcssVersion: string } export interface TransformCallback { (root: Root, result: Result): Promise | void } export interface OldPlugin extends Transformer { (opts?: T): Transformer postcss: Transformer } export type AcceptedPlugin = | Plugin | PluginCreator | OldPlugin | TransformCallback | { postcss: TransformCallback | Processor } | Processor export interface Parser { ( css: string | { toString(): string }, opts?: Pick ): RootNode } export interface Builder { (part: string, node?: AnyNode, type?: 'start' | 'end'): void } export interface Stringifier { (node: AnyNode, builder: Builder): void } export interface JSONHydrator { (data: object[]): Node[] (data: object): Node } export interface Syntax { /** * Function to generate AST by string. */ parse?: Parser /** * Class to generate string by AST. */ stringify?: Stringifier } export interface SourceMapOptions { /** * Indicates that the source map should be embedded in the output CSS * as a Base64-encoded comment. By default, it is `true`. * But if all previous maps are external, not inline, PostCSS will not embed * the map even if you do not set this option. * * If you have an inline source map, the result.map property will be empty, * as the source map will be contained within the text of `result.css`. */ inline?: boolean /** * Source map content from a previous processing step (e.g., Sass). * * PostCSS will try to read the previous source map * automatically (based on comments within the source CSS), but you can use * this option to identify it manually. * * If desired, you can omit the previous map with prev: `false`. */ prev?: string | boolean | object | ((file: string) => string) /** * Indicates that PostCSS should set the origin content (e.g., Sass source) * of the source map. By default, it is true. But if all previous maps do not * contain sources content, PostCSS will also leave it out even if you * do not set this option. */ sourcesContent?: boolean /** * Indicates that PostCSS should add annotation comments to the CSS. * By default, PostCSS will always add a comment with a path * to the source map. PostCSS will not add annotations to CSS files * that do not contain any comments. * * By default, PostCSS presumes that you want to save the source map as * `opts.to + '.map'` and will use this path in the annotation comment. * A different path can be set by providing a string value for annotation. * * If you have set `inline: true`, annotation cannot be disabled. */ annotation?: string | boolean | ((file: string, root: Root) => string) /** * Override `from` in map’s sources. */ from?: string /** * Use absolute path in generated source map. */ absolute?: boolean } export interface ProcessOptions { /** * The path of the CSS source file. You should always set `from`, * because it is used in source map generation and syntax error messages. */ from?: string /** * The path where you'll put the output CSS file. You should always set `to` * to generate correct source maps. */ to?: string /** * Function to generate AST by string. */ parser?: Syntax | Parser /** * Class to generate string by AST. */ stringifier?: Syntax | Stringifier /** * Object with parse and stringify. */ syntax?: Syntax /** * Source map options */ map?: SourceMapOptions | boolean } export interface Postcss { /** * Create a new `Processor` instance that will apply `plugins` * as CSS processors. * * ```js * let postcss = require('postcss') * * postcss(plugins).process(css, { from, to }).then(result => { * console.log(result.css) * }) * ``` * * @param plugins PostCSS plugins. * @return Processor to process multiple CSS. */ (plugins?: AcceptedPlugin[]): Processor (...plugins: AcceptedPlugin[]): Processor /** * Default function to convert a node tree into a CSS string. */ stringify: Stringifier /** * Parses source css and returns a new `Root` or `Document` node, * which contains the source CSS nodes. * * ```js * // Simple CSS concatenation with source map support * const root1 = postcss.parse(css1, { from: file1 }) * const root2 = postcss.parse(css2, { from: file2 }) * root1.append(root2).toResult().css * ``` */ parse: Parser /** * Rehydrate a JSON AST (from `Node#toJSON`) back into the AST classes. * * ```js * const json = root.toJSON() * // save to file, send by network, etc * const root2 = postcss.fromJSON(json) * ``` */ fromJSON: JSONHydrator /** * Contains the `list` module. */ list: List /** * Creates a new `Comment` node. * * @param defaults Properties for the new node. * @return New comment node */ comment(defaults?: CommentProps): Comment /** * Creates a new `AtRule` node. * * @param defaults Properties for the new node. * @return New at-rule node. */ atRule(defaults?: AtRuleProps): AtRule /** * Creates a new `Declaration` node. * * @param defaults Properties for the new node. * @return New declaration node. */ decl(defaults?: DeclarationProps): Declaration /** * Creates a new `Rule` node. * * @param default Properties for the new node. * @return New rule node. */ rule(defaults?: RuleProps): Rule /** * Creates a new `Root` node. * * @param defaults Properties for the new node. * @return New root node. */ root(defaults?: RootProps): Root /** * Creates a new `Document` node. * * @param defaults Properties for the new node. * @return New document node. */ document(defaults?: DocumentProps): Document CssSyntaxError: typeof CssSyntaxError Declaration: typeof Declaration Container: typeof Container Comment: typeof Comment Warning: typeof Warning AtRule: typeof AtRule Result: typeof Result Input: typeof Input Rule: typeof Rule Root: typeof Root Node: typeof Node } export const stringify: Stringifier export const parse: Parser export const fromJSON: JSONHydrator export const comment: Postcss['comment'] export const atRule: Postcss['atRule'] export const decl: Postcss['decl'] export const rule: Postcss['rule'] export const root: Postcss['root'] declare const postcss: Postcss export default postcss postcss-8.4.6/lib/postcss.js000066400000000000000000000053421417621533600160450ustar00rootroot00000000000000'use strict' let CssSyntaxError = require('./css-syntax-error') let Declaration = require('./declaration') let LazyResult = require('./lazy-result') let Container = require('./container') let Processor = require('./processor') let stringify = require('./stringify') let fromJSON = require('./fromJSON') let Document = require('./document') let Warning = require('./warning') let Comment = require('./comment') let AtRule = require('./at-rule') let Result = require('./result.js') let Input = require('./input') let parse = require('./parse') let list = require('./list') let Rule = require('./rule') let Root = require('./root') let Node = require('./node') function postcss(...plugins) { if (plugins.length === 1 && Array.isArray(plugins[0])) { plugins = plugins[0] } return new Processor(plugins) } postcss.plugin = function plugin(name, initializer) { // eslint-disable-next-line no-console if (console && console.warn) { // eslint-disable-next-line no-console console.warn( name + ': postcss.plugin was deprecated. Migration guide:\n' + 'https://evilmartians.com/chronicles/postcss-8-plugin-migration' ) if (process.env.LANG && process.env.LANG.startsWith('cn')) { /* c8 ignore next 7 */ // eslint-disable-next-line no-console console.warn( name + ': 里面 postcss.plugin 被弃用. 迁移指南:\n' + 'https://www.w3ctech.com/topic/2226' ) } } function creator(...args) { let transformer = initializer(...args) transformer.postcssPlugin = name transformer.postcssVersion = new Processor().version return transformer } let cache Object.defineProperty(creator, 'postcss', { get() { if (!cache) cache = creator() return cache } }) creator.process = function (css, processOpts, pluginOpts) { return postcss([creator(pluginOpts)]).process(css, processOpts) } return creator } postcss.stringify = stringify postcss.parse = parse postcss.fromJSON = fromJSON postcss.list = list postcss.comment = defaults => new Comment(defaults) postcss.atRule = defaults => new AtRule(defaults) postcss.decl = defaults => new Declaration(defaults) postcss.rule = defaults => new Rule(defaults) postcss.root = defaults => new Root(defaults) postcss.document = defaults => new Document(defaults) postcss.CssSyntaxError = CssSyntaxError postcss.Declaration = Declaration postcss.Container = Container postcss.Processor = Processor postcss.Document = Document postcss.Comment = Comment postcss.Warning = Warning postcss.AtRule = AtRule postcss.Result = Result postcss.Input = Input postcss.Rule = Rule postcss.Root = Root postcss.Node = Node LazyResult.registerPostcss(postcss) module.exports = postcss postcss.default = postcss postcss-8.4.6/lib/postcss.mjs000066400000000000000000000017241417621533600162220ustar00rootroot00000000000000import postcss from './postcss.js' export default postcss export const stringify = postcss.stringify export const fromJSON = postcss.fromJSON export const plugin = postcss.plugin export const parse = postcss.parse export const list = postcss.list export const document = postcss.document export const comment = postcss.comment export const atRule = postcss.atRule export const rule = postcss.rule export const decl = postcss.decl export const root = postcss.root export const CssSyntaxError = postcss.CssSyntaxError export const Declaration = postcss.Declaration export const Container = postcss.Container export const Processor = postcss.Processor export const Document = postcss.Document export const Comment = postcss.Comment export const Warning = postcss.Warning export const AtRule = postcss.AtRule export const Result = postcss.Result export const Input = postcss.Input export const Rule = postcss.Rule export const Root = postcss.Root export const Node = postcss.Node postcss-8.4.6/lib/previous-map.d.ts000066400000000000000000000031221417621533600172240ustar00rootroot00000000000000import { SourceMapConsumer } from 'source-map-js' import { ProcessOptions } from './postcss.js' /** * Source map information from input CSS. * For example, source map after Sass compiler. * * This class will automatically find source map in input CSS or in file system * near input file (according `from` option). * * ```js * const root = parse(css, { from: 'a.sass.css' }) * root.input.map //=> PreviousMap * ``` */ export default class PreviousMap { /** * Was source map inlined by data-uri to input CSS. */ inline: boolean /** * `sourceMappingURL` content. */ annotation?: string /** * Source map file content. */ text?: string /** * The directory with source map file, if source map is in separated file. */ root?: string /** * The CSS source identifier. Contains `Input#file` if the user * set the `from` option, or `Input#id` if they did not. */ file?: string /** * Path to source map file. */ mapFile?: string /** * @param css Input CSS source. * @param opts Process options. */ constructor(css: string, opts?: ProcessOptions) /** * Create a instance of `SourceMapGenerator` class * from the `source-map` library to work with source map information. * * It is lazy method, so it will create object only on first call * and then it will use cache. * * @return Object with source map information. */ consumer(): SourceMapConsumer /** * Does source map contains `sourcesContent` with input source text. * * @return Is `sourcesContent` present. */ withContent(): boolean } postcss-8.4.6/lib/previous-map.js000066400000000000000000000075231417621533600170010ustar00rootroot00000000000000'use strict' let { SourceMapConsumer, SourceMapGenerator } = require('source-map-js') let { existsSync, readFileSync } = require('fs') let { dirname, join } = require('path') function fromBase64(str) { if (Buffer) { return Buffer.from(str, 'base64').toString() } else { /* c8 ignore next 2 */ return window.atob(str) } } class PreviousMap { constructor(css, opts) { if (opts.map === false) return this.loadAnnotation(css) this.inline = this.startWith(this.annotation, 'data:') let prev = opts.map ? opts.map.prev : undefined let text = this.loadMap(opts.from, prev) if (!this.mapFile && opts.from) { this.mapFile = opts.from } if (this.mapFile) this.root = dirname(this.mapFile) if (text) this.text = text } consumer() { if (!this.consumerCache) { this.consumerCache = new SourceMapConsumer(this.text) } return this.consumerCache } withContent() { return !!( this.consumer().sourcesContent && this.consumer().sourcesContent.length > 0 ) } startWith(string, start) { if (!string) return false return string.substr(0, start.length) === start } getAnnotationURL(sourceMapString) { return sourceMapString.replace(/^\/\*\s*# sourceMappingURL=/, '').trim() } loadAnnotation(css) { let comments = css.match(/\/\*\s*# sourceMappingURL=/gm) if (!comments) return // sourceMappingURLs from comments, strings, etc. let start = css.lastIndexOf(comments.pop()) let end = css.indexOf('*/', start) if (start > -1 && end > -1) { // Locate the last sourceMappingURL to avoid pickin this.annotation = this.getAnnotationURL(css.substring(start, end)) } } decodeInline(text) { let baseCharsetUri = /^data:application\/json;charset=utf-?8;base64,/ let baseUri = /^data:application\/json;base64,/ let charsetUri = /^data:application\/json;charset=utf-?8,/ let uri = /^data:application\/json,/ if (charsetUri.test(text) || uri.test(text)) { return decodeURIComponent(text.substr(RegExp.lastMatch.length)) } if (baseCharsetUri.test(text) || baseUri.test(text)) { return fromBase64(text.substr(RegExp.lastMatch.length)) } let encoding = text.match(/data:application\/json;([^,]+),/)[1] throw new Error('Unsupported source map encoding ' + encoding) } loadFile(path) { this.root = dirname(path) if (existsSync(path)) { this.mapFile = path return readFileSync(path, 'utf-8').toString().trim() } } loadMap(file, prev) { if (prev === false) return false if (prev) { if (typeof prev === 'string') { return prev } else if (typeof prev === 'function') { let prevPath = prev(file) if (prevPath) { let map = this.loadFile(prevPath) if (!map) { throw new Error( 'Unable to load previous source map: ' + prevPath.toString() ) } return map } } else if (prev instanceof SourceMapConsumer) { return SourceMapGenerator.fromSourceMap(prev).toString() } else if (prev instanceof SourceMapGenerator) { return prev.toString() } else if (this.isMap(prev)) { return JSON.stringify(prev) } else { throw new Error( 'Unsupported previous source map format: ' + prev.toString() ) } } else if (this.inline) { return this.decodeInline(this.annotation) } else if (this.annotation) { let map = this.annotation if (file) map = join(dirname(file), map) return this.loadFile(map) } } isMap(map) { if (typeof map !== 'object') return false return ( typeof map.mappings === 'string' || typeof map._mappings === 'string' || Array.isArray(map.sections) ) } } module.exports = PreviousMap PreviousMap.default = PreviousMap postcss-8.4.6/lib/processor.d.ts000066400000000000000000000057201417621533600166220ustar00rootroot00000000000000import { AcceptedPlugin, Plugin, ProcessOptions, Transformer, TransformCallback } from './postcss.js' import LazyResult from './lazy-result.js' import Result from './result.js' import Root from './root.js' import NoWorkResult from './no-work-result.js' /** * Contains plugins to process CSS. Create one `Processor` instance, * initialize its plugins, and then use that instance on numerous CSS files. * * ```js * const processor = postcss([autoprefixer, postcssNested]) * processor.process(css1).then(result => console.log(result.css)) * processor.process(css2).then(result => console.log(result.css)) * ``` */ export default class Processor { /** * Current PostCSS version. * * ```js * if (result.processor.version.split('.')[0] !== '6') { * throw new Error('This plugin works only with PostCSS 6') * } * ``` */ version: string /** * Plugins added to this processor. * * ```js * const processor = postcss([autoprefixer, postcssNested]) * processor.plugins.length //=> 2 * ``` */ plugins: (Plugin | Transformer | TransformCallback)[] /** * @param plugins PostCSS plugins */ constructor(plugins?: AcceptedPlugin[]) /** * Adds a plugin to be used as a CSS processor. * * PostCSS plugin can be in 4 formats: * * A plugin in `Plugin` format. * * A plugin creator function with `pluginCreator.postcss = true`. * PostCSS will call this function without argument to get plugin. * * A function. PostCSS will pass the function a @{link Root} * as the first argument and current `Result` instance * as the second. * * Another `Processor` instance. PostCSS will copy plugins * from that instance into this one. * * Plugins can also be added by passing them as arguments when creating * a `postcss` instance (see [`postcss(plugins)`]). * * Asynchronous plugins should return a `Promise` instance. * * ```js * const processor = postcss() * .use(autoprefixer) * .use(postcssNested) * ``` * * @param plugin PostCSS plugin or `Processor` with plugins. * @return {Processes} Current processor to make methods chain. */ use(plugin: AcceptedPlugin): this /** * Parses source CSS and returns a `LazyResult` Promise proxy. * Because some plugins can be asynchronous it doesn’t make * any transformations. Transformations will be applied * in the `LazyResult` methods. * * ```js * processor.process(css, { from: 'a.css', to: 'a.out.css' }) * .then(result => { * console.log(result.css) * }) * ``` * * @param css String with input CSS or any object with a `toString()` method, * like a Buffer. Optionally, senda `Result` instance * and the processor will take the `Root` from it. * @param opts Options. * @return Promise proxy. */ process( css: string | { toString(): string } | Result | LazyResult | Root, options?: ProcessOptions ): LazyResult | NoWorkResult } postcss-8.4.6/lib/processor.js000066400000000000000000000034211417621533600163620ustar00rootroot00000000000000'use strict' let NoWorkResult = require('./no-work-result') let LazyResult = require('./lazy-result') let Document = require('./document') let Root = require('./root') class Processor { constructor(plugins = []) { this.version = '8.4.6' this.plugins = this.normalize(plugins) } use(plugin) { this.plugins = this.plugins.concat(this.normalize([plugin])) return this } process(css, opts = {}) { if ( this.plugins.length === 0 && typeof opts.parser === 'undefined' && typeof opts.stringifier === 'undefined' && typeof opts.syntax === 'undefined' ) { return new NoWorkResult(this, css, opts) } else { return new LazyResult(this, css, opts) } } normalize(plugins) { let normalized = [] for (let i of plugins) { if (i.postcss === true) { i = i() } else if (i.postcss) { i = i.postcss } if (typeof i === 'object' && Array.isArray(i.plugins)) { normalized = normalized.concat(i.plugins) } else if (typeof i === 'object' && i.postcssPlugin) { normalized.push(i) } else if (typeof i === 'function') { normalized.push(i) } else if (typeof i === 'object' && (i.parse || i.stringify)) { if (process.env.NODE_ENV !== 'production') { throw new Error( 'PostCSS syntaxes cannot be used as plugins. Instead, please use ' + 'one of the syntax/parser/stringifier options as outlined ' + 'in your PostCSS runner documentation.' ) } } else { throw new Error(i + ' is not a PostCSS plugin') } } return normalized } } module.exports = Processor Processor.default = Processor Root.registerProcessor(Processor) Document.registerProcessor(Processor) postcss-8.4.6/lib/result.d.ts000066400000000000000000000100231417621533600161110ustar00rootroot00000000000000import { ProcessOptions, Plugin, SourceMap, TransformCallback, Root, Document, Node, Warning, WarningOptions } from './postcss.js' import Processor from './processor.js' export interface Message { /** * Message type. */ type: string /** * Source PostCSS plugin name. */ plugin?: string [others: string]: any } export interface ResultOptions extends ProcessOptions { /** * The CSS node that was the source of the warning. */ node?: Node /** * Name of plugin that created this warning. `Result#warn` will fill it * automatically with `Plugin#postcssPlugin` value. */ plugin?: string } /** * Provides the result of the PostCSS transformations. * * A Result instance is returned by `LazyResult#then` * or `Root#toResult` methods. * * ```js * postcss([autoprefixer]).process(css).then(result => { * console.log(result.css) * }) * ``` * * ```js * const result2 = postcss.parse(css).toResult() * ``` */ export default class Result { /** * The Processor instance used for this transformation. * * ```js * for (const plugin of result.processor.plugins) { * if (plugin.postcssPlugin === 'postcss-bad') { * throw 'postcss-good is incompatible with postcss-bad' * } * }) * ``` */ processor: Processor /** * Contains messages from plugins (e.g., warnings or custom messages). * Each message should have type and plugin properties. * * ```js * AtRule: { * import: (atRule, { result }) { * const importedFile = parseImport(atRule) * result.messages.push({ * type: 'dependency', * plugin: 'postcss-import', * file: importedFile, * parent: result.opts.from * }) * } * } * ``` */ messages: Message[] /** * Root node after all transformations. * * ```js * root.toResult().root === root * ``` */ root: Root | Document /** * Options from the `Processor#process` or `Root#toResult` call * that produced this Result instance.] * * ```js * root.toResult(opts).opts === opts * ``` */ opts: ResultOptions /** * A CSS string representing of `Result#root`. * * ```js * postcss.parse('a{}').toResult().css //=> "a{}" * ``` */ css: string /** * An instance of `SourceMapGenerator` class from the `source-map` library, * representing changes to the `Result#root` instance. * * ```js * result.map.toJSON() //=> { version: 3, file: 'a.css', … } * ``` * * ```js * if (result.map) { * fs.writeFileSync(result.opts.to + '.map', result.map.toString()) * } * ``` */ map: SourceMap /** * Last runned PostCSS plugin. */ lastPlugin: Plugin | TransformCallback /** * @param processor Processor used for this transformation. * @param root Root node after all transformations. * @param opts Options from the `Processor#process` or `Root#toResult`. */ constructor(processor: Processor, root: Root | Document, opts: ResultOptions) /** * An alias for the `Result#css` property. * Use it with syntaxes that generate non-CSS output. * * ```js * result.css === result.content * ``` */ get content(): string /** * Returns for `Result#css` content. * * ```js * result + '' === result.css * ``` * * @return String representing of `Result#root`. */ toString(): string /** * Creates an instance of `Warning` and adds it to `Result#messages`. * * ```js * if (decl.important) { * result.warn('Avoid !important', { node: decl, word: '!important' }) * } * ``` * * @param text Warning message. * @param opts Warning options. * @return Created warning. */ warn(message: string, options?: WarningOptions): Warning /** * Returns warnings from plugins. Filters `Warning` instances * from `Result#messages`. * * ```js * result.warnings().forEach(warn => { * console.warn(warn.toString()) * }) * ``` * * @return Warnings from plugins. */ warnings(): Warning[] } postcss-8.4.6/lib/result.js000066400000000000000000000013511417621533600156610ustar00rootroot00000000000000'use strict' let Warning = require('./warning') class Result { constructor(processor, root, opts) { this.processor = processor this.messages = [] this.root = root this.opts = opts this.css = undefined this.map = undefined } toString() { return this.css } warn(text, opts = {}) { if (!opts.plugin) { if (this.lastPlugin && this.lastPlugin.postcssPlugin) { opts.plugin = this.lastPlugin.postcssPlugin } } let warning = new Warning(text, opts) this.messages.push(warning) return warning } warnings() { return this.messages.filter(i => i.type === 'warning') } get content() { return this.css } } module.exports = Result Result.default = Result postcss-8.4.6/lib/root.d.ts000066400000000000000000000035001417621533600155600ustar00rootroot00000000000000import Container, { ContainerProps } from './container.js' import Document from './document.js' import { ProcessOptions } from './postcss.js' import Result from './result.js' interface RootRaws extends Record { /** * The space symbols after the last child to the end of file. */ after?: string /** * Non-CSS code before `Root`, when `Root` is inside `Document`. * * **Experimental:** some aspects of this node could change within minor * or patch version releases. */ codeBefore?: string /** * Non-CSS code after `Root`, when `Root` is inside `Document`. * * **Experimental:** some aspects of this node could change within minor * or patch version releases. */ codeAfter?: string /** * Is the last child has an (optional) semicolon. */ semicolon?: boolean } export interface RootProps extends ContainerProps { /** * Information used to generate byte-to-byte equal node string * as it was in the origin input. * */ raws?: RootRaws } /** * Represents a CSS file and contains all its parsed nodes. * * ```js * const root = postcss.parse('a{color:black} b{z-index:2}') * root.type //=> 'root' * root.nodes.length //=> 2 * ``` */ export default class Root extends Container { type: 'root' parent: Document | undefined raws: RootRaws /** * Returns a `Result` instance representing the root’s CSS. * * ```js * const root1 = postcss.parse(css1, { from: 'a.css' }) * const root2 = postcss.parse(css2, { from: 'b.css' }) * root1.append(root2) * const result = root1.toResult({ to: 'all.css', map: true }) * ``` * * @param opts Options. * @return Result with current root’s CSS. */ toResult(options?: ProcessOptions): Result constructor(defaults?: RootProps) assign(overrides: object | RootProps): this } postcss-8.4.6/lib/root.js000066400000000000000000000022711417621533600153300ustar00rootroot00000000000000'use strict' let Container = require('./container') let LazyResult, Processor class Root extends Container { constructor(defaults) { super(defaults) this.type = 'root' if (!this.nodes) this.nodes = [] } removeChild(child, ignore) { let index = this.index(child) if (!ignore && index === 0 && this.nodes.length > 1) { this.nodes[1].raws.before = this.nodes[index].raws.before } return super.removeChild(child) } normalize(child, sample, type) { let nodes = super.normalize(child) if (sample) { if (type === 'prepend') { if (this.nodes.length > 1) { sample.raws.before = this.nodes[1].raws.before } else { delete sample.raws.before } } else if (this.first !== sample) { for (let node of nodes) { node.raws.before = sample.raws.before } } } return nodes } toResult(opts = {}) { let lazy = new LazyResult(new Processor(), this, opts) return lazy.stringify() } } Root.registerLazyResult = dependant => { LazyResult = dependant } Root.registerProcessor = dependant => { Processor = dependant } module.exports = Root Root.default = Root postcss-8.4.6/lib/rule.d.ts000066400000000000000000000045331417621533600155530ustar00rootroot00000000000000import Container, { ContainerProps } from './container.js' interface RuleRaws extends Record { /** * The space symbols before the node. It also stores `*` * and `_` symbols before the declaration (IE hack). */ before?: string /** * The space symbols after the last child of the node to the end of the node. */ after?: string /** * The symbols between the selector and `{` for rules. */ between?: string /** * Contains `true` if the last child has an (optional) semicolon. */ semicolon?: boolean /** * Contains `true` if there is semicolon after rule. */ ownSemicolon?: string /** * The rule’s selector with comments. */ selector?: { value: string raw: string } } export interface RuleProps extends ContainerProps { /** Selector or selectors of the rule. */ selector?: string /** Selectors of the rule represented as an array of strings. */ selectors?: string[] /** Information used to generate byte-to-byte equal node string as it was in the origin input. */ raws?: RuleRaws } /** * Represents a CSS rule: a selector followed by a declaration block. * * ```js * Once (root, { Rule }) { * let a = new Rule({ selector: 'a' }) * a.append(…) * root.append(a) * } * ``` * * ```js * const root = postcss.parse('a{}') * const rule = root.first * rule.type //=> 'rule' * rule.toString() //=> 'a{}' * ``` */ export default class Rule extends Container { type: 'rule' parent: Container | undefined raws: RuleRaws /** * The rule’s full selector represented as a string. * * ```js * const root = postcss.parse('a, b { }') * const rule = root.first * rule.selector //=> 'a, b' * ``` */ selector: string /** * An array containing the rule’s individual selectors. * Groups of selectors are split at commas. * * ```js * const root = postcss.parse('a, b { }') * const rule = root.first * * rule.selector //=> 'a, b' * rule.selectors //=> ['a', 'b'] * * rule.selectors = ['a', 'strong'] * rule.selector //=> 'a, strong' * ``` */ selectors: string[] constructor(defaults?: RuleProps) assign(overrides: object | RuleProps): this clone(overrides?: Partial): this cloneBefore(overrides?: Partial): this cloneAfter(overrides?: Partial): this } postcss-8.4.6/lib/rule.js000066400000000000000000000010711417621533600153110ustar00rootroot00000000000000'use strict' let Container = require('./container') let list = require('./list') class Rule extends Container { constructor(defaults) { super(defaults) this.type = 'rule' if (!this.nodes) this.nodes = [] } get selectors() { return list.comma(this.selector) } set selectors(values) { let match = this.selector ? this.selector.match(/,\s*/) : null let sep = match ? match[0] : ',' + this.raw('between', 'beforeOpen') this.selector = values.join(sep) } } module.exports = Rule Rule.default = Rule Container.registerRule(Rule) postcss-8.4.6/lib/stringifier.d.ts000066400000000000000000000022621417621533600171260ustar00rootroot00000000000000import { Document, Root, Comment, Declaration, Builder, AnyNode, Rule, AtRule, Container } from './postcss.js' export default class Stringifier { builder: Builder constructor(builder: Builder) stringify(node: AnyNode, semicolon?: boolean): void document(node: Document): void root(node: Root): void comment(node: Comment): void decl(node: Declaration, semicolon?: boolean): void rule(node: Rule): void atrule(node: AtRule, semicolon?: boolean): void body(node: Container): void block(node: AnyNode, start: string): void raw(node: AnyNode, own: string | null, detect?: string): string rawSemicolon(root: Root): boolean | undefined rawEmptyBody(root: Root): string | undefined rawIndent(root: Root): string | undefined rawBeforeComment(root: Root, node: Comment): string | undefined rawBeforeDecl(root: Root, node: Declaration): string | undefined rawBeforeRule(root: Root): string | undefined rawBeforeClose(root: Root): string | undefined rawBeforeOpen(root: Root): string | undefined rawColon(root: Root): string | undefined beforeAfter(node: AnyNode, detect: 'before' | 'after'): string rawValue(node: AnyNode, prop: string): string } postcss-8.4.6/lib/stringifier.js000066400000000000000000000200341417621533600166670ustar00rootroot00000000000000'use strict' const DEFAULT_RAW = { colon: ': ', indent: ' ', beforeDecl: '\n', beforeRule: '\n', beforeOpen: ' ', beforeClose: '\n', beforeComment: '\n', after: '\n', emptyBody: '', commentLeft: ' ', commentRight: ' ', semicolon: false } function capitalize(str) { return str[0].toUpperCase() + str.slice(1) } class Stringifier { constructor(builder) { this.builder = builder } stringify(node, semicolon) { /* c8 ignore start */ if (!this[node.type]) { throw new Error( 'Unknown AST node type ' + node.type + '. ' + 'Maybe you need to change PostCSS stringifier.' ) } /* c8 ignore stop */ this[node.type](node, semicolon) } document(node) { this.body(node) } root(node) { this.body(node) if (node.raws.after) this.builder(node.raws.after) } comment(node) { let left = this.raw(node, 'left', 'commentLeft') let right = this.raw(node, 'right', 'commentRight') this.builder('/*' + left + node.text + right + '*/', node) } decl(node, semicolon) { let between = this.raw(node, 'between', 'colon') let string = node.prop + between + this.rawValue(node, 'value') if (node.important) { string += node.raws.important || ' !important' } if (semicolon) string += ';' this.builder(string, node) } rule(node) { this.block(node, this.rawValue(node, 'selector')) if (node.raws.ownSemicolon) { this.builder(node.raws.ownSemicolon, node, 'end') } } atrule(node, semicolon) { let name = '@' + node.name let params = node.params ? this.rawValue(node, 'params') : '' if (typeof node.raws.afterName !== 'undefined') { name += node.raws.afterName } else if (params) { name += ' ' } if (node.nodes) { this.block(node, name + params) } else { let end = (node.raws.between || '') + (semicolon ? ';' : '') this.builder(name + params + end, node) } } body(node) { let last = node.nodes.length - 1 while (last > 0) { if (node.nodes[last].type !== 'comment') break last -= 1 } let semicolon = this.raw(node, 'semicolon') for (let i = 0; i < node.nodes.length; i++) { let child = node.nodes[i] let before = this.raw(child, 'before') if (before) this.builder(before) this.stringify(child, last !== i || semicolon) } } block(node, start) { let between = this.raw(node, 'between', 'beforeOpen') this.builder(start + between + '{', node, 'start') let after if (node.nodes && node.nodes.length) { this.body(node) after = this.raw(node, 'after') } else { after = this.raw(node, 'after', 'emptyBody') } if (after) this.builder(after) this.builder('}', node, 'end') } raw(node, own, detect) { let value if (!detect) detect = own // Already had if (own) { value = node.raws[own] if (typeof value !== 'undefined') return value } let parent = node.parent if (detect === 'before') { // Hack for first rule in CSS if (!parent || (parent.type === 'root' && parent.first === node)) { return '' } // `root` nodes in `document` should use only their own raws if (parent && parent.type === 'document') { return '' } } // Floating child without parent if (!parent) return DEFAULT_RAW[detect] // Detect style by other nodes let root = node.root() if (!root.rawCache) root.rawCache = {} if (typeof root.rawCache[detect] !== 'undefined') { return root.rawCache[detect] } if (detect === 'before' || detect === 'after') { return this.beforeAfter(node, detect) } else { let method = 'raw' + capitalize(detect) if (this[method]) { value = this[method](root, node) } else { root.walk(i => { value = i.raws[own] if (typeof value !== 'undefined') return false }) } } if (typeof value === 'undefined') value = DEFAULT_RAW[detect] root.rawCache[detect] = value return value } rawSemicolon(root) { let value root.walk(i => { if (i.nodes && i.nodes.length && i.last.type === 'decl') { value = i.raws.semicolon if (typeof value !== 'undefined') return false } }) return value } rawEmptyBody(root) { let value root.walk(i => { if (i.nodes && i.nodes.length === 0) { value = i.raws.after if (typeof value !== 'undefined') return false } }) return value } rawIndent(root) { if (root.raws.indent) return root.raws.indent let value root.walk(i => { let p = i.parent if (p && p !== root && p.parent && p.parent === root) { if (typeof i.raws.before !== 'undefined') { let parts = i.raws.before.split('\n') value = parts[parts.length - 1] value = value.replace(/\S/g, '') return false } } }) return value } rawBeforeComment(root, node) { let value root.walkComments(i => { if (typeof i.raws.before !== 'undefined') { value = i.raws.before if (value.includes('\n')) { value = value.replace(/[^\n]+$/, '') } return false } }) if (typeof value === 'undefined') { value = this.raw(node, null, 'beforeDecl') } else if (value) { value = value.replace(/\S/g, '') } return value } rawBeforeDecl(root, node) { let value root.walkDecls(i => { if (typeof i.raws.before !== 'undefined') { value = i.raws.before if (value.includes('\n')) { value = value.replace(/[^\n]+$/, '') } return false } }) if (typeof value === 'undefined') { value = this.raw(node, null, 'beforeRule') } else if (value) { value = value.replace(/\S/g, '') } return value } rawBeforeRule(root) { let value root.walk(i => { if (i.nodes && (i.parent !== root || root.first !== i)) { if (typeof i.raws.before !== 'undefined') { value = i.raws.before if (value.includes('\n')) { value = value.replace(/[^\n]+$/, '') } return false } } }) if (value) value = value.replace(/\S/g, '') return value } rawBeforeClose(root) { let value root.walk(i => { if (i.nodes && i.nodes.length > 0) { if (typeof i.raws.after !== 'undefined') { value = i.raws.after if (value.includes('\n')) { value = value.replace(/[^\n]+$/, '') } return false } } }) if (value) value = value.replace(/\S/g, '') return value } rawBeforeOpen(root) { let value root.walk(i => { if (i.type !== 'decl') { value = i.raws.between if (typeof value !== 'undefined') return false } }) return value } rawColon(root) { let value root.walkDecls(i => { if (typeof i.raws.between !== 'undefined') { value = i.raws.between.replace(/[^\s:]/g, '') return false } }) return value } beforeAfter(node, detect) { let value if (node.type === 'decl') { value = this.raw(node, null, 'beforeDecl') } else if (node.type === 'comment') { value = this.raw(node, null, 'beforeComment') } else if (detect === 'before') { value = this.raw(node, null, 'beforeRule') } else { value = this.raw(node, null, 'beforeClose') } let buf = node.parent let depth = 0 while (buf && buf.type !== 'root') { depth += 1 buf = buf.parent } if (value.includes('\n')) { let indent = this.raw(node, null, 'indent') if (indent.length) { for (let step = 0; step < depth; step++) value += indent } } return value } rawValue(node, prop) { let value = node[prop] let raw = node.raws[prop] if (raw && raw.value === value) { return raw.raw } return value } } module.exports = Stringifier Stringifier.default = Stringifier postcss-8.4.6/lib/stringify.d.ts000066400000000000000000000001531417621533600166140ustar00rootroot00000000000000import { Stringifier } from './postcss.js' declare const stringify: Stringifier export default stringify postcss-8.4.6/lib/stringify.js000066400000000000000000000003251417621533600163610ustar00rootroot00000000000000'use strict' let Stringifier = require('./stringifier') function stringify(node, builder) { let str = new Stringifier(builder) str.stringify(node) } module.exports = stringify stringify.default = stringify postcss-8.4.6/lib/symbols.js000066400000000000000000000001331417621533600160300ustar00rootroot00000000000000'use strict' module.exports.isClean = Symbol('isClean') module.exports.my = Symbol('my') postcss-8.4.6/lib/terminal-highlight.js000066400000000000000000000025671417621533600201350ustar00rootroot00000000000000'use strict' let pico = require('picocolors') let tokenizer = require('./tokenize') let Input function registerInput(dependant) { Input = dependant } const HIGHLIGHT_THEME = { 'brackets': pico.cyan, 'at-word': pico.cyan, 'comment': pico.gray, 'string': pico.green, 'class': pico.yellow, 'hash': pico.magenta, 'call': pico.cyan, '(': pico.cyan, ')': pico.cyan, '{': pico.yellow, '}': pico.yellow, '[': pico.yellow, ']': pico.yellow, ':': pico.yellow, ';': pico.yellow } function getTokenType([type, value], processor) { if (type === 'word') { if (value[0] === '.') { return 'class' } if (value[0] === '#') { return 'hash' } } if (!processor.endOfFile()) { let next = processor.nextToken() processor.back(next) if (next[0] === 'brackets' || next[0] === '(') return 'call' } return type } function terminalHighlight(css) { let processor = tokenizer(new Input(css), { ignoreErrors: true }) let result = '' while (!processor.endOfFile()) { let token = processor.nextToken() let color = HIGHLIGHT_THEME[getTokenType(token, processor)] if (color) { result += token[1] .split(/\r?\n/) .map(i => color(i)) .join('\n') } else { result += token[1] } } return result } terminalHighlight.registerInput = registerInput module.exports = terminalHighlight postcss-8.4.6/lib/tokenize.js000066400000000000000000000146101417621533600161750ustar00rootroot00000000000000'use strict' const SINGLE_QUOTE = "'".charCodeAt(0) const DOUBLE_QUOTE = '"'.charCodeAt(0) const BACKSLASH = '\\'.charCodeAt(0) const SLASH = '/'.charCodeAt(0) const NEWLINE = '\n'.charCodeAt(0) const SPACE = ' '.charCodeAt(0) const FEED = '\f'.charCodeAt(0) const TAB = '\t'.charCodeAt(0) const CR = '\r'.charCodeAt(0) const OPEN_SQUARE = '['.charCodeAt(0) const CLOSE_SQUARE = ']'.charCodeAt(0) const OPEN_PARENTHESES = '('.charCodeAt(0) const CLOSE_PARENTHESES = ')'.charCodeAt(0) const OPEN_CURLY = '{'.charCodeAt(0) const CLOSE_CURLY = '}'.charCodeAt(0) const SEMICOLON = ';'.charCodeAt(0) const ASTERISK = '*'.charCodeAt(0) const COLON = ':'.charCodeAt(0) const AT = '@'.charCodeAt(0) const RE_AT_END = /[\t\n\f\r "#'()/;[\\\]{}]/g const RE_WORD_END = /[\t\n\f\r !"#'():;@[\\\]{}]|\/(?=\*)/g const RE_BAD_BRACKET = /.[\n"'(/\\]/ const RE_HEX_ESCAPE = /[\da-f]/i module.exports = function tokenizer(input, options = {}) { let css = input.css.valueOf() let ignore = options.ignoreErrors let code, next, quote, content, escape let escaped, escapePos, prev, n, currentToken let length = css.length let pos = 0 let buffer = [] let returned = [] function position() { return pos } function unclosed(what) { throw input.error('Unclosed ' + what, pos) } function endOfFile() { return returned.length === 0 && pos >= length } function nextToken(opts) { if (returned.length) return returned.pop() if (pos >= length) return let ignoreUnclosed = opts ? opts.ignoreUnclosed : false code = css.charCodeAt(pos) switch (code) { case NEWLINE: case SPACE: case TAB: case CR: case FEED: { next = pos do { next += 1 code = css.charCodeAt(next) } while ( code === SPACE || code === NEWLINE || code === TAB || code === CR || code === FEED ) currentToken = ['space', css.slice(pos, next)] pos = next - 1 break } case OPEN_SQUARE: case CLOSE_SQUARE: case OPEN_CURLY: case CLOSE_CURLY: case COLON: case SEMICOLON: case CLOSE_PARENTHESES: { let controlChar = String.fromCharCode(code) currentToken = [controlChar, controlChar, pos] break } case OPEN_PARENTHESES: { prev = buffer.length ? buffer.pop()[1] : '' n = css.charCodeAt(pos + 1) if ( prev === 'url' && n !== SINGLE_QUOTE && n !== DOUBLE_QUOTE && n !== SPACE && n !== NEWLINE && n !== TAB && n !== FEED && n !== CR ) { next = pos do { escaped = false next = css.indexOf(')', next + 1) if (next === -1) { if (ignore || ignoreUnclosed) { next = pos break } else { unclosed('bracket') } } escapePos = next while (css.charCodeAt(escapePos - 1) === BACKSLASH) { escapePos -= 1 escaped = !escaped } } while (escaped) currentToken = ['brackets', css.slice(pos, next + 1), pos, next] pos = next } else { next = css.indexOf(')', pos + 1) content = css.slice(pos, next + 1) if (next === -1 || RE_BAD_BRACKET.test(content)) { currentToken = ['(', '(', pos] } else { currentToken = ['brackets', content, pos, next] pos = next } } break } case SINGLE_QUOTE: case DOUBLE_QUOTE: { quote = code === SINGLE_QUOTE ? "'" : '"' next = pos do { escaped = false next = css.indexOf(quote, next + 1) if (next === -1) { if (ignore || ignoreUnclosed) { next = pos + 1 break } else { unclosed('string') } } escapePos = next while (css.charCodeAt(escapePos - 1) === BACKSLASH) { escapePos -= 1 escaped = !escaped } } while (escaped) currentToken = ['string', css.slice(pos, next + 1), pos, next] pos = next break } case AT: { RE_AT_END.lastIndex = pos + 1 RE_AT_END.test(css) if (RE_AT_END.lastIndex === 0) { next = css.length - 1 } else { next = RE_AT_END.lastIndex - 2 } currentToken = ['at-word', css.slice(pos, next + 1), pos, next] pos = next break } case BACKSLASH: { next = pos escape = true while (css.charCodeAt(next + 1) === BACKSLASH) { next += 1 escape = !escape } code = css.charCodeAt(next + 1) if ( escape && code !== SLASH && code !== SPACE && code !== NEWLINE && code !== TAB && code !== CR && code !== FEED ) { next += 1 if (RE_HEX_ESCAPE.test(css.charAt(next))) { while (RE_HEX_ESCAPE.test(css.charAt(next + 1))) { next += 1 } if (css.charCodeAt(next + 1) === SPACE) { next += 1 } } } currentToken = ['word', css.slice(pos, next + 1), pos, next] pos = next break } default: { if (code === SLASH && css.charCodeAt(pos + 1) === ASTERISK) { next = css.indexOf('*/', pos + 2) + 1 if (next === 0) { if (ignore || ignoreUnclosed) { next = css.length } else { unclosed('comment') } } currentToken = ['comment', css.slice(pos, next + 1), pos, next] pos = next } else { RE_WORD_END.lastIndex = pos + 1 RE_WORD_END.test(css) if (RE_WORD_END.lastIndex === 0) { next = css.length - 1 } else { next = RE_WORD_END.lastIndex - 2 } currentToken = ['word', css.slice(pos, next + 1), pos, next] buffer.push(currentToken) pos = next } break } } pos++ return currentToken } function back(token) { returned.push(token) } return { back, nextToken, endOfFile, position } } postcss-8.4.6/lib/warn-once.js000066400000000000000000000004001417621533600162260ustar00rootroot00000000000000/* eslint-disable no-console */ 'use strict' let printed = {} module.exports = function warnOnce(message) { if (printed[message]) return printed[message] = true if (typeof console !== 'undefined' && console.warn) { console.warn(message) } } postcss-8.4.6/lib/warning.d.ts000066400000000000000000000052571417621533600162550ustar00rootroot00000000000000import { RangePosition } from './css-syntax-error.js' import Node from './node.js' export interface WarningOptions { /** * CSS node that caused the warning. */ node?: Node /** * Word in CSS source that caused the warning. */ word?: string /** * Start index, inclusive, in CSS node string that caused the warning. */ index?: number /** * End index, exclusive, in CSS node string that caused the warning. */ endIndex?: number /** * Start position, inclusive, in CSS node string that caused the warning. */ start?: RangePosition /** * End position, exclusive, in CSS node string that caused the warning. */ end?: RangePosition /** * Name of the plugin that created this warning. `Result#warn` fills * this property automatically. */ plugin?: string } /** * Represents a plugin’s warning. It can be created using `Node#warn`. * * ```js * if (decl.important) { * decl.warn(result, 'Avoid !important', { word: '!important' }) * } * ``` */ export default class Warning { /** * Type to filter warnings from `Result#messages`. * Always equal to `"warning"`. */ type: 'warning' /** * The warning message. * * ```js * warning.text //=> 'Try to avoid !important' * ``` */ text: string /** * The name of the plugin that created this warning. * When you call `Node#warn` it will fill this property automatically. * * ```js * warning.plugin //=> 'postcss-important' * ``` */ plugin: string /** * Contains the CSS node that caused the warning. * * ```js * warning.node.toString() //=> 'color: white !important' * ``` */ node: Node /** * Line for inclusive start position in the input file with this warning’s source. * * ```js * warning.line //=> 5 * ``` */ line: number /** * Column for inclusive start position in the input file with this warning’s source. * * ```js * warning.column //=> 6 * ``` */ column: number /** * Line for exclusive end position in the input file with this warning’s source. * * ```js * warning.endLine //=> 6 * ``` */ endLine?: number /** * Column for exclusive end position in the input file with this warning’s source. * * ```js * warning.endColumn //=> 4 * ``` */ endColumn?: number /** * @param text Warning message. * @param opts Warning options. */ constructor(text: string, opts?: WarningOptions) /** * Returns a warning position and message. * * ```js * warning.toString() //=> 'postcss-lint:a.css:10:14: Avoid !important' * ``` * * @return Warning position and message. */ toString(): string } postcss-8.4.6/lib/warning.js000066400000000000000000000013431417621533600160110ustar00rootroot00000000000000'use strict' class Warning { constructor(text, opts = {}) { this.type = 'warning' this.text = text if (opts.node && opts.node.source) { let range = opts.node.rangeBy(opts) this.line = range.start.line this.column = range.start.column this.endLine = range.end.line this.endColumn = range.end.column } for (let opt in opts) this[opt] = opts[opt] } toString() { if (this.node) { return this.node.error(this.text, { plugin: this.plugin, index: this.index, word: this.word }).message } if (this.plugin) { return this.plugin + ': ' + this.text } return this.text } } module.exports = Warning Warning.default = Warning postcss-8.4.6/package.json000077500000000000000000000107051417621533600155330ustar00rootroot00000000000000{ "name": "postcss", "version": "8.4.6", "description": "Tool for transforming styles with JS plugins", "engines": { "node": "^10 || ^12 || >=14" }, "exports": { ".": { "require": "./lib/postcss.js", "import": "./lib/postcss.mjs", "types": "./lib/postcss.d.ts" }, "./lib/at-rule": "./lib/at-rule.js", "./lib/comment": "./lib/comment.js", "./lib/container": "./lib/container.js", "./lib/css-syntax-error": "./lib/css-syntax-error.js", "./lib/declaration": "./lib/declaration.js", "./lib/fromJSON": "./lib/fromJSON.js", "./lib/input": "./lib/input.js", "./lib/lazy-result": "./lib/lazy-result.js", "./lib/no-work-result": "./lib/no-work-result.js", "./lib/list": "./lib/list.js", "./lib/map-generator": "./lib/map-generator.js", "./lib/node": "./lib/node.js", "./lib/parse": "./lib/parse.js", "./lib/parser": "./lib/parser.js", "./lib/postcss": "./lib/postcss.js", "./lib/previous-map": "./lib/previous-map.js", "./lib/processor": "./lib/processor.js", "./lib/result": "./lib/result.js", "./lib/root": "./lib/root.js", "./lib/rule": "./lib/rule.js", "./lib/stringifier": "./lib/stringifier.js", "./lib/stringify": "./lib/stringify.js", "./lib/symbols": "./lib/symbols.js", "./lib/terminal-highlight": "./lib/terminal-highlight.js", "./lib/tokenize": "./lib/tokenize.js", "./lib/warn-once": "./lib/warn-once.js", "./lib/warning": "./lib/warning.js", "./package.json": "./package.json" }, "main": "./lib/postcss.js", "types": "./lib/postcss.d.ts", "keywords": [ "css", "postcss", "rework", "preprocessor", "parser", "source map", "transform", "manipulation", "transpiler" ], "scripts": { "test": "c8 pnpm unit && eslint . && node ./test/version.js && check-dts && node ./test/integration.js && size-limit", "unit": "uvu -r ts-node/register/transpile-only test \"\\.test\\.(ts|js)$\"" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/postcss/" }, "author": "Andrey Sitnik ", "license": "MIT", "homepage": "https://postcss.org/", "repository": "postcss/postcss", "bugs": { "url": "https://github.com/postcss/postcss/issues" }, "dependencies": { "nanoid": "^3.2.0", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" }, "devDependencies": { "@logux/eslint-config": "^46.1.1", "@size-limit/preset-small-lib": "^7.0.5", "@types/fs-extra": "^9.0.13", "@types/node": "^17.0.14", "@typescript-eslint/eslint-plugin": "^5.10.2", "@typescript-eslint/parser": "^5.10.2", "c8": "^7.11.0", "check-dts": "^0.6.6", "clean-publish": "^4.0.0", "concat-with-sourcemaps": "^1.1.0", "eslint": "^8.8.0", "eslint-config-standard": "^16.0.3", "eslint-plugin-import": "^2.25.4", "eslint-plugin-node": "^11.1.0", "eslint-plugin-prefer-let": "^3.0.1", "eslint-plugin-promise": "^6.0.0", "fs-extra": "^10.0.0", "nanodelay": "^1.0.8", "nanospy": "^0.4.0", "postcss-parser-tests": "^8.4.0", "simple-git-hooks": "^2.7.0", "size-limit": "^7.0.5", "strip-ansi": "^6.0.1", "ts-node": "^10.4.0", "typescript": "^4.5.5", "uvu": "^0.5.3" }, "c8": { "exclude": [ "**/*.test.*", "lib/map-generator.js" ], "lines": 100, "reporter": "lcov", "check-coverage": true }, "simple-git-hooks": { "pre-commit": "./test/version.js" }, "prettier": { "arrowParens": "avoid", "jsxSingleQuote": false, "quoteProps": "consistent", "semi": false, "singleQuote": true, "trailingComma": "none" }, "browser": { "./lib/terminal-highlight": false, "source-map-js": false, "path": false, "url": false, "fs": false }, "size-limit": [ { "path": "lib/postcss.js", "limit": "16 KB" } ], "eslintConfig": { "extends": "@logux/eslint-config/ts", "rules": { "@typescript-eslint/no-explicit-any": "off", "consistent-return": "off", "global-require": "off" }, "overrides": [ { "files": [ "*.test.*" ], "rules": { "@typescript-eslint/no-unused-expressions": "off", "no-unused-expressions": "off", "no-console": "off", "func-style": "off" } } ] }, "eslintIgnore": [ "docs/api/assets/", "errors.ts" ], "clean-publish": { "cleanDocs": true } } postcss-8.4.6/pnpm-lock.yaml000066400000000000000000002233061417621533600160310ustar00rootroot00000000000000lockfileVersion: 5.3 specifiers: '@logux/eslint-config': ^46.1.1 '@size-limit/preset-small-lib': ^7.0.5 '@types/fs-extra': ^9.0.13 '@types/node': ^17.0.14 '@typescript-eslint/eslint-plugin': ^5.10.2 '@typescript-eslint/parser': ^5.10.2 c8: ^7.11.0 check-dts: ^0.6.6 clean-publish: ^4.0.0 concat-with-sourcemaps: ^1.1.0 eslint: ^8.8.0 eslint-config-standard: ^16.0.3 eslint-plugin-import: ^2.25.4 eslint-plugin-node: ^11.1.0 eslint-plugin-prefer-let: ^3.0.1 eslint-plugin-promise: ^6.0.0 fs-extra: ^10.0.0 nanodelay: ^1.0.8 nanoid: ^3.2.0 nanospy: ^0.4.0 picocolors: ^1.0.0 postcss-parser-tests: ^8.4.0 simple-git-hooks: ^2.7.0 size-limit: ^7.0.5 source-map-js: ^1.0.2 strip-ansi: ^6.0.1 ts-node: ^10.4.0 typescript: ^4.5.5 uvu: ^0.5.3 dependencies: nanoid: 3.2.0 picocolors: 1.0.0 source-map-js: 1.0.2 devDependencies: '@logux/eslint-config': 46.1.1_78f08d0053c073645909d39bd7f54d5e '@size-limit/preset-small-lib': 7.0.5_size-limit@7.0.5 '@types/fs-extra': 9.0.13 '@types/node': 17.0.14 '@typescript-eslint/eslint-plugin': 5.10.2_2595c2126aec4d4b6e944b931dabb4c2 '@typescript-eslint/parser': 5.10.2_eslint@8.8.0+typescript@4.5.5 c8: 7.11.0 check-dts: 0.6.6_typescript@4.5.5 clean-publish: 4.0.0 concat-with-sourcemaps: 1.1.0 eslint: 8.8.0 eslint-config-standard: 16.0.3_3fa03ca42f6626059a4867a76f65b153 eslint-plugin-import: 2.25.4_eslint@8.8.0 eslint-plugin-node: 11.1.0_eslint@8.8.0 eslint-plugin-prefer-let: 3.0.1 eslint-plugin-promise: 6.0.0_eslint@8.8.0 fs-extra: 10.0.0 nanodelay: 1.0.8 nanospy: 0.4.0 postcss-parser-tests: 8.4.0 simple-git-hooks: 2.7.0 size-limit: 7.0.5 strip-ansi: 6.0.1 ts-node: 10.4.0_43d2036524ce97aa8076ce68340fa9ec typescript: 4.5.5 uvu: 0.5.3 packages: /@bcoe/v8-coverage/0.2.3: resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} dev: true /@cspotcode/source-map-consumer/0.8.0: resolution: {integrity: sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==} engines: {node: '>= 12'} dev: true /@cspotcode/source-map-support/0.7.0: resolution: {integrity: sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA==} engines: {node: '>=12'} dependencies: '@cspotcode/source-map-consumer': 0.8.0 dev: true /@eslint/eslintrc/1.0.5: resolution: {integrity: sha512-BLxsnmK3KyPunz5wmCCpqy0YelEoxxGmH73Is+Z74oOTMtExcjkr3dDR6quwrjh1YspA8DH9gnX1o069KiS9AQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: ajv: 6.12.6 debug: 4.3.3 espree: 9.3.0 globals: 13.12.0 ignore: 4.0.6 import-fresh: 3.3.0 js-yaml: 4.1.0 minimatch: 3.0.4 strip-json-comments: 3.1.1 transitivePeerDependencies: - supports-color dev: true /@humanwhocodes/config-array/0.9.3: resolution: {integrity: sha512-3xSMlXHh03hCcCmFc0rbKp3Ivt2PFEJnQUJDDMTJQ2wkECZWdq4GePs2ctc5H8zV+cHPaq8k2vU8mrQjA6iHdQ==} engines: {node: '>=10.10.0'} dependencies: '@humanwhocodes/object-schema': 1.2.1 debug: 4.3.3 minimatch: 3.0.4 transitivePeerDependencies: - supports-color dev: true /@humanwhocodes/object-schema/1.2.1: resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==} dev: true /@istanbuljs/schema/0.1.3: resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} engines: {node: '>=8'} dev: true /@logux/eslint-config/46.1.1_78f08d0053c073645909d39bd7f54d5e: resolution: {integrity: sha512-FSSiEj6yGGmoI+ccK8ET093OL2G9ar1izQtixB62SWGouas096VpqQoz+FuFW8f4iCb4wuYrXYuv0uOLuvc+LA==} engines: {node: '>=10.0.0'} peerDependencies: eslint: ^8.5.0 eslint-config-standard: ^16.0.3 eslint-plugin-import: ^2.25.3 eslint-plugin-node: ^11.1.0 eslint-plugin-prefer-let: ^3.0.1 eslint-plugin-promise: ^6.0.0 dependencies: eslint: 8.8.0 eslint-config-standard: 16.0.3_3fa03ca42f6626059a4867a76f65b153 eslint-plugin-import: 2.25.4_eslint@8.8.0 eslint-plugin-node: 11.1.0_eslint@8.8.0 eslint-plugin-prefer-let: 3.0.1 eslint-plugin-promise: 6.0.0_eslint@8.8.0 dev: true /@nodelib/fs.scandir/2.1.5: resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} dependencies: '@nodelib/fs.stat': 2.0.5 run-parallel: 1.2.0 dev: true /@nodelib/fs.stat/2.0.5: resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} engines: {node: '>= 8'} dev: true /@nodelib/fs.walk/1.2.8: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} dependencies: '@nodelib/fs.scandir': 2.1.5 fastq: 1.13.0 dev: true /@size-limit/esbuild/7.0.5_size-limit@7.0.5: resolution: {integrity: sha512-ec/XfgTHcfXFflEDgs83gs3XMfB8sn4BISZM7CPHCS72tNkcjVwNRxrKWisb11JZ2kN4glBgCmsXZpoSaEGzXg==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} peerDependencies: size-limit: 7.0.5 dependencies: esbuild: 0.14.16 nanoid: 3.2.0 size-limit: 7.0.5 dev: true /@size-limit/file/7.0.5_size-limit@7.0.5: resolution: {integrity: sha512-DqyuUkmCSHwML6GVmeRr0v6Ih/P3pwmCu6RDWh2QxdDSec1ZnShmFUmcC6rLQDX7KW5aCjK3cs5FNd22Eaqapw==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} peerDependencies: size-limit: 7.0.5 dependencies: semver: 7.3.5 size-limit: 7.0.5 dev: true /@size-limit/preset-small-lib/7.0.5_size-limit@7.0.5: resolution: {integrity: sha512-cWwXDCx9BEpHIjbpHlhpS0JBt+J1U5LCaHHyBhAxevOX7W0aX7nCJwPUmd5liGHq9ui5VyWOtV3lhxce96Qd8A==} peerDependencies: size-limit: 7.0.5 dependencies: '@size-limit/esbuild': 7.0.5_size-limit@7.0.5 '@size-limit/file': 7.0.5_size-limit@7.0.5 size-limit: 7.0.5 dev: true /@tsconfig/node10/1.0.8: resolution: {integrity: sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==} dev: true /@tsconfig/node12/1.0.9: resolution: {integrity: sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw==} dev: true /@tsconfig/node14/1.0.1: resolution: {integrity: sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==} dev: true /@tsconfig/node16/1.0.2: resolution: {integrity: sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==} dev: true /@types/fs-extra/9.0.13: resolution: {integrity: sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==} dependencies: '@types/node': 17.0.14 dev: true /@types/istanbul-lib-coverage/2.0.4: resolution: {integrity: sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==} dev: true /@types/json-schema/7.0.9: resolution: {integrity: sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==} dev: true /@types/json5/0.0.29: resolution: {integrity: sha1-7ihweulOEdK4J7y+UnC86n8+ce4=} dev: true /@types/node/17.0.14: resolution: {integrity: sha512-SbjLmERksKOGzWzPNuW7fJM7fk3YXVTFiZWB/Hs99gwhk+/dnrQRPBQjPW9aO+fi1tAffi9PrwFvsmOKmDTyng==} dev: true /@types/unist/2.0.6: resolution: {integrity: sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==} dev: true /@typescript-eslint/eslint-plugin/5.10.2_2595c2126aec4d4b6e944b931dabb4c2: resolution: {integrity: sha512-4W/9lLuE+v27O/oe7hXJKjNtBLnZE8tQAFpapdxwSVHqtmIoPB1gph3+ahNwVuNL37BX7YQHyGF9Xv6XCnIX2Q==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: '@typescript-eslint/parser': ^5.0.0 eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 typescript: '*' peerDependenciesMeta: typescript: optional: true dependencies: '@typescript-eslint/parser': 5.10.2_eslint@8.8.0+typescript@4.5.5 '@typescript-eslint/scope-manager': 5.10.2 '@typescript-eslint/type-utils': 5.10.2_eslint@8.8.0+typescript@4.5.5 '@typescript-eslint/utils': 5.10.2_eslint@8.8.0+typescript@4.5.5 debug: 4.3.3 eslint: 8.8.0 functional-red-black-tree: 1.0.1 ignore: 5.2.0 regexpp: 3.2.0 semver: 7.3.5 tsutils: 3.21.0_typescript@4.5.5 typescript: 4.5.5 transitivePeerDependencies: - supports-color dev: true /@typescript-eslint/parser/5.10.2_eslint@8.8.0+typescript@4.5.5: resolution: {integrity: sha512-JaNYGkaQVhP6HNF+lkdOr2cAs2wdSZBoalE22uYWq8IEv/OVH0RksSGydk+sW8cLoSeYmC+OHvRyv2i4AQ7Czg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 typescript: '*' peerDependenciesMeta: typescript: optional: true dependencies: '@typescript-eslint/scope-manager': 5.10.2 '@typescript-eslint/types': 5.10.2 '@typescript-eslint/typescript-estree': 5.10.2_typescript@4.5.5 debug: 4.3.3 eslint: 8.8.0 typescript: 4.5.5 transitivePeerDependencies: - supports-color dev: true /@typescript-eslint/scope-manager/5.10.2: resolution: {integrity: sha512-39Tm6f4RoZoVUWBYr3ekS75TYgpr5Y+X0xLZxXqcZNDWZdJdYbKd3q2IR4V9y5NxxiPu/jxJ8XP7EgHiEQtFnw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: '@typescript-eslint/types': 5.10.2 '@typescript-eslint/visitor-keys': 5.10.2 dev: true /@typescript-eslint/type-utils/5.10.2_eslint@8.8.0+typescript@4.5.5: resolution: {integrity: sha512-uRKSvw/Ccs5FYEoXW04Z5VfzF2iiZcx8Fu7DGIB7RHozuP0VbKNzP1KfZkHBTM75pCpsWxIthEH1B33dmGBKHw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: '*' typescript: '*' peerDependenciesMeta: typescript: optional: true dependencies: '@typescript-eslint/utils': 5.10.2_eslint@8.8.0+typescript@4.5.5 debug: 4.3.3 eslint: 8.8.0 tsutils: 3.21.0_typescript@4.5.5 typescript: 4.5.5 transitivePeerDependencies: - supports-color dev: true /@typescript-eslint/types/5.10.2: resolution: {integrity: sha512-Qfp0qk/5j2Rz3p3/WhWgu4S1JtMcPgFLnmAKAW061uXxKSa7VWKZsDXVaMXh2N60CX9h6YLaBoy9PJAfCOjk3w==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: true /@typescript-eslint/typescript-estree/5.10.2_typescript@4.5.5: resolution: {integrity: sha512-WHHw6a9vvZls6JkTgGljwCsMkv8wu8XU8WaYKeYhxhWXH/atZeiMW6uDFPLZOvzNOGmuSMvHtZKd6AuC8PrwKQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: typescript: '*' peerDependenciesMeta: typescript: optional: true dependencies: '@typescript-eslint/types': 5.10.2 '@typescript-eslint/visitor-keys': 5.10.2 debug: 4.3.3 globby: 11.1.0 is-glob: 4.0.3 semver: 7.3.5 tsutils: 3.21.0_typescript@4.5.5 typescript: 4.5.5 transitivePeerDependencies: - supports-color dev: true /@typescript-eslint/utils/5.10.2_eslint@8.8.0+typescript@4.5.5: resolution: {integrity: sha512-vuJaBeig1NnBRkf7q9tgMLREiYD7zsMrsN1DA3wcoMDvr3BTFiIpKjGiYZoKPllfEwN7spUjv7ZqD+JhbVjEPg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 dependencies: '@types/json-schema': 7.0.9 '@typescript-eslint/scope-manager': 5.10.2 '@typescript-eslint/types': 5.10.2 '@typescript-eslint/typescript-estree': 5.10.2_typescript@4.5.5 eslint: 8.8.0 eslint-scope: 5.1.1 eslint-utils: 3.0.0_eslint@8.8.0 transitivePeerDependencies: - supports-color - typescript dev: true /@typescript-eslint/visitor-keys/5.10.2: resolution: {integrity: sha512-zHIhYGGGrFJvvyfwHk5M08C5B5K4bewkm+rrvNTKk1/S15YHR+SA/QUF8ZWscXSfEaB8Nn2puZj+iHcoxVOD/Q==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: '@typescript-eslint/types': 5.10.2 eslint-visitor-keys: 3.2.0 dev: true /acorn-jsx/5.3.2_acorn@8.7.0: resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 dependencies: acorn: 8.7.0 dev: true /acorn-walk/8.2.0: resolution: {integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==} engines: {node: '>=0.4.0'} dev: true /acorn/8.7.0: resolution: {integrity: sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==} engines: {node: '>=0.4.0'} hasBin: true dev: true /ajv/6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} dependencies: fast-deep-equal: 3.1.3 fast-json-stable-stringify: 2.1.0 json-schema-traverse: 0.4.1 uri-js: 4.4.1 dev: true /ansi-regex/5.0.1: resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} engines: {node: '>=8'} dev: true /ansi-styles/4.3.0: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} dependencies: color-convert: 2.0.1 dev: true /anymatch/3.1.2: resolution: {integrity: sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==} engines: {node: '>= 8'} dependencies: normalize-path: 3.0.0 picomatch: 2.3.1 dev: true /arg/4.1.3: resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} dev: true /argparse/2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} dev: true /array-includes/3.1.4: resolution: {integrity: sha512-ZTNSQkmWumEbiHO2GF4GmWxYVTiQyJy2XOTa15sdQSrvKn7l+180egQMqlrMOUMCyLMD7pmyQe4mMDUT6Behrw==} engines: {node: '>= 0.4'} dependencies: call-bind: 1.0.2 define-properties: 1.1.3 es-abstract: 1.19.1 get-intrinsic: 1.1.1 is-string: 1.0.7 dev: true /array-union/2.1.0: resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} engines: {node: '>=8'} dev: true /array.prototype.flat/1.2.5: resolution: {integrity: sha512-KaYU+S+ndVqyUnignHftkwc58o3uVU1jzczILJ1tN2YaIZpFIKBiP/x/j97E5MVPsaCloPbqWLB/8qCTVvT2qg==} engines: {node: '>= 0.4'} dependencies: call-bind: 1.0.2 define-properties: 1.1.3 es-abstract: 1.19.1 dev: true /balanced-match/1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} dev: true /binary-extensions/2.2.0: resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} engines: {node: '>=8'} dev: true /brace-expansion/1.1.11: resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} dependencies: balanced-match: 1.0.2 concat-map: 0.0.1 dev: true /braces/3.0.2: resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} engines: {node: '>=8'} dependencies: fill-range: 7.0.1 dev: true /bytes-iec/3.1.1: resolution: {integrity: sha512-fey6+4jDK7TFtFg/klGSvNKJctyU7n2aQdnM+CO0ruLPbqqMOM8Tio0Pc+deqUeVKX1tL5DQep1zQ7+37aTAsA==} engines: {node: '>= 0.8'} dev: true /c8/7.11.0: resolution: {integrity: sha512-XqPyj1uvlHMr+Y1IeRndC2X5P7iJzJlEJwBpCdBbq2JocXOgJfr+JVfJkyNMGROke5LfKrhSFXGFXnwnRJAUJw==} engines: {node: '>=10.12.0'} hasBin: true dependencies: '@bcoe/v8-coverage': 0.2.3 '@istanbuljs/schema': 0.1.3 find-up: 5.0.0 foreground-child: 2.0.0 istanbul-lib-coverage: 3.2.0 istanbul-lib-report: 3.0.0 istanbul-reports: 3.1.3 rimraf: 3.0.2 test-exclude: 6.0.0 v8-to-istanbul: 8.1.1 yargs: 16.2.0 yargs-parser: 20.2.9 dev: true /call-bind/1.0.2: resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==} dependencies: function-bind: 1.1.1 get-intrinsic: 1.1.1 dev: true /callsites/3.1.0: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} dev: true /chalk/4.1.2: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} dependencies: ansi-styles: 4.3.0 supports-color: 7.2.0 dev: true /check-dts/0.6.6_typescript@4.5.5: resolution: {integrity: sha512-2KzynoH1f8wVhZXUeqxeW2dOOFliktitYlyyOsLfZBk5K5n1U1B3uzJLFiJfwqlwoT1Ug7RNbi8xmMpUKKmwhg==} engines: {node: '>=12.16.0'} hasBin: true peerDependencies: typescript: '>=4.0.0' dependencies: fast-glob: 3.2.11 nanospinner: 0.6.0 picocolors: 1.0.0 typescript: 4.5.5 vfile-location: 4.0.1 dev: true /chokidar/3.5.3: resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} engines: {node: '>= 8.10.0'} dependencies: anymatch: 3.1.2 braces: 3.0.2 glob-parent: 5.1.2 is-binary-path: 2.1.0 is-glob: 4.0.3 normalize-path: 3.0.0 readdirp: 3.6.0 optionalDependencies: fsevents: 2.3.2 dev: true /ci-job-number/1.2.2: resolution: {integrity: sha512-CLOGsVDrVamzv8sXJGaILUVI6dsuAkouJP/n6t+OxLPeeA4DDby7zn9SB6EUpa1H7oIKoE+rMmkW80zYsFfUjA==} dev: true /clean-publish/4.0.0: resolution: {integrity: sha512-PcOxJSnPgncx/ANmgPw8hj9DDtdLHTxIc6Vh/yXCX7IA9w1oUSx2POL0Vno/7omhyrKxMKTpnRh2wlzwH5zaCw==} hasBin: true dependencies: cross-spawn: 7.0.3 fast-glob: 3.2.11 lilconfig: 2.0.4 micromatch: 4.0.4 dev: true /cliui/7.0.4: resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} dependencies: string-width: 4.2.3 strip-ansi: 6.0.1 wrap-ansi: 7.0.0 dev: true /color-convert/2.0.1: resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} engines: {node: '>=7.0.0'} dependencies: color-name: 1.1.4 dev: true /color-name/1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} dev: true /concat-map/0.0.1: resolution: {integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=} dev: true /concat-with-sourcemaps/1.1.0: resolution: {integrity: sha512-4gEjHJFT9e+2W/77h/DS5SGUgwDaOwprX8L/gl5+3ixnzkVJJsZWDSelmN3Oilw3LNDZjZV0yqH1hLG3k6nghg==} dependencies: source-map: 0.6.1 dev: true /convert-source-map/1.8.0: resolution: {integrity: sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==} dependencies: safe-buffer: 5.1.2 dev: true /create-require/1.1.1: resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} dev: true /cross-spawn/7.0.3: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} engines: {node: '>= 8'} dependencies: path-key: 3.1.1 shebang-command: 2.0.0 which: 2.0.2 dev: true /debug/2.6.9: resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} dependencies: ms: 2.0.0 dev: true /debug/3.2.7: resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} dependencies: ms: 2.1.3 dev: true /debug/4.3.3: resolution: {integrity: sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==} engines: {node: '>=6.0'} peerDependencies: supports-color: '*' peerDependenciesMeta: supports-color: optional: true dependencies: ms: 2.1.2 dev: true /deep-is/0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} dev: true /define-properties/1.1.3: resolution: {integrity: sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==} engines: {node: '>= 0.4'} dependencies: object-keys: 1.1.1 dev: true /dequal/2.0.2: resolution: {integrity: sha512-q9K8BlJVxK7hQYqa6XISGmBZbtQQWVXSrRrWreHC94rMt1QL/Impruc+7p2CYSYuVIUr+YCt6hjrs1kkdJRTug==} engines: {node: '>=6'} dev: true /diff/4.0.2: resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} engines: {node: '>=0.3.1'} dev: true /diff/5.0.0: resolution: {integrity: sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==} engines: {node: '>=0.3.1'} dev: true /dir-glob/3.0.1: resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} engines: {node: '>=8'} dependencies: path-type: 4.0.0 dev: true /doctrine/2.1.0: resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} engines: {node: '>=0.10.0'} dependencies: esutils: 2.0.3 dev: true /doctrine/3.0.0: resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} engines: {node: '>=6.0.0'} dependencies: esutils: 2.0.3 dev: true /emoji-regex/8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} dev: true /es-abstract/1.19.1: resolution: {integrity: sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w==} engines: {node: '>= 0.4'} dependencies: call-bind: 1.0.2 es-to-primitive: 1.2.1 function-bind: 1.1.1 get-intrinsic: 1.1.1 get-symbol-description: 1.0.0 has: 1.0.3 has-symbols: 1.0.2 internal-slot: 1.0.3 is-callable: 1.2.4 is-negative-zero: 2.0.2 is-regex: 1.1.4 is-shared-array-buffer: 1.0.1 is-string: 1.0.7 is-weakref: 1.0.2 object-inspect: 1.12.0 object-keys: 1.1.1 object.assign: 4.1.2 string.prototype.trimend: 1.0.4 string.prototype.trimstart: 1.0.4 unbox-primitive: 1.0.1 dev: true /es-to-primitive/1.2.1: resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} engines: {node: '>= 0.4'} dependencies: is-callable: 1.2.4 is-date-object: 1.0.5 is-symbol: 1.0.4 dev: true /esbuild-android-arm64/0.14.16: resolution: {integrity: sha512-9qRiUXiV0qIa4Dfv+GLKsk/HHOq3U9qh8yZK9iX0awlzLPFb38NJrNTGtb/TeI6AyyZqsGgwLm/JeJ1UtEN9Aw==} engines: {node: '>=12'} cpu: [arm64] os: [android] requiresBuild: true dev: true optional: true /esbuild-darwin-64/0.14.16: resolution: {integrity: sha512-1Xa86DpTJFRffA7go0pqUdC0ggxxGxjsrnrvA2nHBVHNf9Ix/cgGuPfxZwf3fRZxDDAT2RdqF5SRZzLYvUCtZQ==} engines: {node: '>=12'} cpu: [x64] os: [darwin] requiresBuild: true dev: true optional: true /esbuild-darwin-arm64/0.14.16: resolution: {integrity: sha512-a0Tp0tec/s5hYT6OiJ2zvfH/6IfXFCH406yqFfXe5u8Nfo6l6IG33L7nqCYCEPnBLF7oYfZk6Re0VDwpgK18kQ==} engines: {node: '>=12'} cpu: [arm64] os: [darwin] requiresBuild: true dev: true optional: true /esbuild-freebsd-64/0.14.16: resolution: {integrity: sha512-FqEdOphRS5kJ8MFqQ21Y0yducmwcFHmpkceLkup1kpsGChr3PGO7DfzXmF5fECNnMxRpk/jgk7e6nV4zXTau/A==} engines: {node: '>=12'} cpu: [x64] os: [freebsd] requiresBuild: true dev: true optional: true /esbuild-freebsd-arm64/0.14.16: resolution: {integrity: sha512-4Au4zR0//Df1v6FuWJEMZFRzaF69FvxHgSmKjikq7x6Ect+h4TbJKkblC3eDrfTA8L6l5bB1vhh0dbKq4zBy5Q==} engines: {node: '>=12'} cpu: [arm64] os: [freebsd] requiresBuild: true dev: true optional: true /esbuild-linux-32/0.14.16: resolution: {integrity: sha512-HundAiQCa0ut7PXq3lmRZY7H3/OYh27wkJ97S7jjCgWmcd5To6Bs8UBVB7I4Qi9lNk/Yty0INnqq9on1WR8JUA==} engines: {node: '>=12'} cpu: [ia32] os: [linux] requiresBuild: true dev: true optional: true /esbuild-linux-64/0.14.16: resolution: {integrity: sha512-fG8MgVmQknIuYCHFOq+9iKLyygjPun+VkNH9ZIdRQrSzb3CFdEkNm+Suq5w8W+WjA/P0OIdrQ/mXXCoHCQTWSQ==} engines: {node: '>=12'} cpu: [x64] os: [linux] requiresBuild: true dev: true optional: true /esbuild-linux-arm/0.14.16: resolution: {integrity: sha512-0NDVeuvWska0d4Rd8R3+lWEyKaIbAxDuRAeeU6a2xaUXrTG2IPhGNLWc4NbVMbnkGqRqKB4PLdk/YaTUZjKFHQ==} engines: {node: '>=12'} cpu: [arm] os: [linux] requiresBuild: true dev: true optional: true /esbuild-linux-arm64/0.14.16: resolution: {integrity: sha512-7WF1rHsPVXhme2B6ceZZABxFwCiZfMRIJO7yRiLahIdDkwfhSTR6M0a6OwO/NsLJH9fax5GdwBOIBoG5Hkz4gA==} engines: {node: '>=12'} cpu: [arm64] os: [linux] requiresBuild: true dev: true optional: true /esbuild-linux-mips64le/0.14.16: resolution: {integrity: sha512-RLNaTRdcQ81QckeIjbk1hCrgmrL6VoZBsYT8ak9ObNQzXEJNMlxOBixaF6rhW8UUYRpTpFuoYHeNya8xY884/A==} engines: {node: '>=12'} cpu: [mips64el] os: [linux] requiresBuild: true dev: true optional: true /esbuild-linux-ppc64le/0.14.16: resolution: {integrity: sha512-ky0Ii2Jmyc00FzGT2audU0UmnBVrVevYmKW10DXLPcHGhbhzJdFRemXLvvzhDM8WD9IMJK3uV6ifJzkKrv8IQA==} engines: {node: '>=12'} cpu: [ppc64] os: [linux] requiresBuild: true dev: true optional: true /esbuild-linux-s390x/0.14.16: resolution: {integrity: sha512-DuW9MPGJAzUUBPI/olMkMMepCasTbPN1Xr2cKZZEEDIibcdRnuFrMYVk3G3I8/Qb6SZBNTSnZMAyhvYFrwAkqw==} engines: {node: '>=12'} cpu: [s390x] os: [linux] requiresBuild: true dev: true optional: true /esbuild-netbsd-64/0.14.16: resolution: {integrity: sha512-l8+mnz8iVsV0iL5v5JCuP0UTv2LwO1ORdJ/scMkGUl8WrC6cBmUrrHhg+pwREqjbD8TxjfUJVM1Vvt5E8SaTsg==} engines: {node: '>=12'} cpu: [x64] os: [netbsd] requiresBuild: true dev: true optional: true /esbuild-openbsd-64/0.14.16: resolution: {integrity: sha512-8SbZNAV902FmcGnc+j86HWY8PyTD1H7T39RsPXXS5IC1psi3yzFr2d8NoOxb6cQd5XUVHmHT1naJsbtEAyKIPA==} engines: {node: '>=12'} cpu: [x64] os: [openbsd] requiresBuild: true dev: true optional: true /esbuild-sunos-64/0.14.16: resolution: {integrity: sha512-pMhe4uOaGjA/5YgeNoB0PRZi1V73D8sx876uFzuAxaZcYzLA5BsSbQeEccH182X6cBybE4Pm79kYedTSGOfwog==} engines: {node: '>=12'} cpu: [x64] os: [sunos] requiresBuild: true dev: true optional: true /esbuild-windows-32/0.14.16: resolution: {integrity: sha512-M68/EFCgji0DI+DgULx2ytUUSxwwODJDpiVc0YsiWKdyB4umKTu1GGxFfdZhXrWtPxB4aZFoIgJyDhsFxnHC4g==} engines: {node: '>=12'} cpu: [ia32] os: [win32] requiresBuild: true dev: true optional: true /esbuild-windows-64/0.14.16: resolution: {integrity: sha512-rmSal1Co749CXSNyFJ62J5Fz/nZiFWhwMfYN9SwZazutKZ6s0QDRIhnupa93bJmzMzz4C2dqUV/VL1tqOI3y9g==} engines: {node: '>=12'} cpu: [x64] os: [win32] requiresBuild: true dev: true optional: true /esbuild-windows-arm64/0.14.16: resolution: {integrity: sha512-VMfEf+MDgO+rulAuSeu3HNebSHa1TDn0lJp+QRk7E2WVg9OCSwuXUEkSbqIbkif3ZjASy7h9sTCGyHcqgKQTrg==} engines: {node: '>=12'} cpu: [arm64] os: [win32] requiresBuild: true dev: true optional: true /esbuild/0.14.16: resolution: {integrity: sha512-niiWy7nesZFGCiDr0NR9/JLEhtZPYHG/ABYTqveNWvocw/gGI5rKHOj3+5yUv3yH10/geTlZiyVaNvjJWL9Xbw==} engines: {node: '>=12'} hasBin: true requiresBuild: true optionalDependencies: esbuild-android-arm64: 0.14.16 esbuild-darwin-64: 0.14.16 esbuild-darwin-arm64: 0.14.16 esbuild-freebsd-64: 0.14.16 esbuild-freebsd-arm64: 0.14.16 esbuild-linux-32: 0.14.16 esbuild-linux-64: 0.14.16 esbuild-linux-arm: 0.14.16 esbuild-linux-arm64: 0.14.16 esbuild-linux-mips64le: 0.14.16 esbuild-linux-ppc64le: 0.14.16 esbuild-linux-s390x: 0.14.16 esbuild-netbsd-64: 0.14.16 esbuild-openbsd-64: 0.14.16 esbuild-sunos-64: 0.14.16 esbuild-windows-32: 0.14.16 esbuild-windows-64: 0.14.16 esbuild-windows-arm64: 0.14.16 dev: true /escalade/3.1.1: resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} engines: {node: '>=6'} dev: true /escape-string-regexp/4.0.0: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} dev: true /eslint-config-standard/16.0.3_3fa03ca42f6626059a4867a76f65b153: resolution: {integrity: sha512-x4fmJL5hGqNJKGHSjnLdgA6U6h1YW/G2dW9fA+cyVur4SK6lyue8+UgNKWlZtUDTXvgKDD/Oa3GQjmB5kjtVvg==} peerDependencies: eslint: ^7.12.1 eslint-plugin-import: ^2.22.1 eslint-plugin-node: ^11.1.0 eslint-plugin-promise: ^4.2.1 || ^5.0.0 dependencies: eslint: 8.8.0 eslint-plugin-import: 2.25.4_eslint@8.8.0 eslint-plugin-node: 11.1.0_eslint@8.8.0 eslint-plugin-promise: 6.0.0_eslint@8.8.0 dev: true /eslint-import-resolver-node/0.3.6: resolution: {integrity: sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw==} dependencies: debug: 3.2.7 resolve: 1.22.0 dev: true /eslint-module-utils/2.7.3: resolution: {integrity: sha512-088JEC7O3lDZM9xGe0RerkOMd0EjFl+Yvd1jPWIkMT5u3H9+HC34mWWPnqPrN13gieT9pBOO+Qt07Nb/6TresQ==} engines: {node: '>=4'} dependencies: debug: 3.2.7 find-up: 2.1.0 dev: true /eslint-plugin-es/3.0.1_eslint@8.8.0: resolution: {integrity: sha512-GUmAsJaN4Fc7Gbtl8uOBlayo2DqhwWvEzykMHSCZHU3XdJ+NSzzZcVhXh3VxX5icqQ+oQdIEawXX8xkR3mIFmQ==} engines: {node: '>=8.10.0'} peerDependencies: eslint: '>=4.19.1' dependencies: eslint: 8.8.0 eslint-utils: 2.1.0 regexpp: 3.2.0 dev: true /eslint-plugin-import/2.25.4_eslint@8.8.0: resolution: {integrity: sha512-/KJBASVFxpu0xg1kIBn9AUa8hQVnszpwgE7Ld0lKAlx7Ie87yzEzCgSkekt+le/YVhiaosO4Y14GDAOc41nfxA==} engines: {node: '>=4'} peerDependencies: eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 dependencies: array-includes: 3.1.4 array.prototype.flat: 1.2.5 debug: 2.6.9 doctrine: 2.1.0 eslint: 8.8.0 eslint-import-resolver-node: 0.3.6 eslint-module-utils: 2.7.3 has: 1.0.3 is-core-module: 2.8.1 is-glob: 4.0.3 minimatch: 3.0.4 object.values: 1.1.5 resolve: 1.22.0 tsconfig-paths: 3.12.0 dev: true /eslint-plugin-node/11.1.0_eslint@8.8.0: resolution: {integrity: sha512-oUwtPJ1W0SKD0Tr+wqu92c5xuCeQqB3hSCHasn/ZgjFdA9iDGNkNf2Zi9ztY7X+hNuMib23LNGRm6+uN+KLE3g==} engines: {node: '>=8.10.0'} peerDependencies: eslint: '>=5.16.0' dependencies: eslint: 8.8.0 eslint-plugin-es: 3.0.1_eslint@8.8.0 eslint-utils: 2.1.0 ignore: 5.2.0 minimatch: 3.0.4 resolve: 1.22.0 semver: 6.3.0 dev: true /eslint-plugin-prefer-let/3.0.1: resolution: {integrity: sha512-vbznkkBSXB63d4o1o0NIm5C2ey3V5wKr/25dAvPdydQXdowAcnr69cbLgxd2YAG81IV5eddCO55Lp6gL7wSE4w==} engines: {node: '>=0.10.0'} dependencies: requireindex: 1.2.0 dev: true /eslint-plugin-promise/6.0.0_eslint@8.8.0: resolution: {integrity: sha512-7GPezalm5Bfi/E22PnQxDWH2iW9GTvAlUNTztemeHb6c1BniSyoeTrM87JkC0wYdi6aQrZX9p2qEiAno8aTcbw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^7.0.0 || ^8.0.0 dependencies: eslint: 8.8.0 dev: true /eslint-scope/5.1.1: resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} engines: {node: '>=8.0.0'} dependencies: esrecurse: 4.3.0 estraverse: 4.3.0 dev: true /eslint-scope/7.1.0: resolution: {integrity: sha512-aWwkhnS0qAXqNOgKOK0dJ2nvzEbhEvpy8OlJ9kZ0FeZnA6zpjv1/Vei+puGFFX7zkPCkHHXb7IDX3A+7yPrRWg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: esrecurse: 4.3.0 estraverse: 5.3.0 dev: true /eslint-utils/2.1.0: resolution: {integrity: sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==} engines: {node: '>=6'} dependencies: eslint-visitor-keys: 1.3.0 dev: true /eslint-utils/3.0.0_eslint@8.8.0: resolution: {integrity: sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==} engines: {node: ^10.0.0 || ^12.0.0 || >= 14.0.0} peerDependencies: eslint: '>=5' dependencies: eslint: 8.8.0 eslint-visitor-keys: 2.1.0 dev: true /eslint-visitor-keys/1.3.0: resolution: {integrity: sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==} engines: {node: '>=4'} dev: true /eslint-visitor-keys/2.1.0: resolution: {integrity: sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==} engines: {node: '>=10'} dev: true /eslint-visitor-keys/3.2.0: resolution: {integrity: sha512-IOzT0X126zn7ALX0dwFiUQEdsfzrm4+ISsQS8nukaJXwEyYKRSnEIIDULYg1mCtGp7UUXgfGl7BIolXREQK+XQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dev: true /eslint/8.8.0: resolution: {integrity: sha512-H3KXAzQGBH1plhYS3okDix2ZthuYJlQQEGE5k0IKuEqUSiyu4AmxxlJ2MtTYeJ3xB4jDhcYCwGOg2TXYdnDXlQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} hasBin: true dependencies: '@eslint/eslintrc': 1.0.5 '@humanwhocodes/config-array': 0.9.3 ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.3 debug: 4.3.3 doctrine: 3.0.0 escape-string-regexp: 4.0.0 eslint-scope: 7.1.0 eslint-utils: 3.0.0_eslint@8.8.0 eslint-visitor-keys: 3.2.0 espree: 9.3.0 esquery: 1.4.0 esutils: 2.0.3 fast-deep-equal: 3.1.3 file-entry-cache: 6.0.1 functional-red-black-tree: 1.0.1 glob-parent: 6.0.2 globals: 13.12.0 ignore: 5.2.0 import-fresh: 3.3.0 imurmurhash: 0.1.4 is-glob: 4.0.3 js-yaml: 4.1.0 json-stable-stringify-without-jsonify: 1.0.1 levn: 0.4.1 lodash.merge: 4.6.2 minimatch: 3.0.4 natural-compare: 1.4.0 optionator: 0.9.1 regexpp: 3.2.0 strip-ansi: 6.0.1 strip-json-comments: 3.1.1 text-table: 0.2.0 v8-compile-cache: 2.3.0 transitivePeerDependencies: - supports-color dev: true /espree/9.3.0: resolution: {integrity: sha512-d/5nCsb0JcqsSEeQzFZ8DH1RmxPcglRWh24EFTlUEmCKoehXGdpsx0RkHDubqUI8LSAIKMQp4r9SzQ3n+sm4HQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: acorn: 8.7.0 acorn-jsx: 5.3.2_acorn@8.7.0 eslint-visitor-keys: 3.2.0 dev: true /esquery/1.4.0: resolution: {integrity: sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==} engines: {node: '>=0.10'} dependencies: estraverse: 5.3.0 dev: true /esrecurse/4.3.0: resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} engines: {node: '>=4.0'} dependencies: estraverse: 5.3.0 dev: true /estraverse/4.3.0: resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} engines: {node: '>=4.0'} dev: true /estraverse/5.3.0: resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} engines: {node: '>=4.0'} dev: true /esutils/2.0.3: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} dev: true /fast-deep-equal/3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} dev: true /fast-glob/3.2.11: resolution: {integrity: sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==} engines: {node: '>=8.6.0'} dependencies: '@nodelib/fs.stat': 2.0.5 '@nodelib/fs.walk': 1.2.8 glob-parent: 5.1.2 merge2: 1.4.1 micromatch: 4.0.4 dev: true /fast-json-stable-stringify/2.1.0: resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} dev: true /fast-levenshtein/2.0.6: resolution: {integrity: sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=} dev: true /fastq/1.13.0: resolution: {integrity: sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==} dependencies: reusify: 1.0.4 dev: true /file-entry-cache/6.0.1: resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} engines: {node: ^10.12.0 || >=12.0.0} dependencies: flat-cache: 3.0.4 dev: true /fill-range/7.0.1: resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} engines: {node: '>=8'} dependencies: to-regex-range: 5.0.1 dev: true /find-up/2.1.0: resolution: {integrity: sha1-RdG35QbHF93UgndaK3eSCjwMV6c=} engines: {node: '>=4'} dependencies: locate-path: 2.0.0 dev: true /find-up/5.0.0: resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} engines: {node: '>=10'} dependencies: locate-path: 6.0.0 path-exists: 4.0.0 dev: true /flat-cache/3.0.4: resolution: {integrity: sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==} engines: {node: ^10.12.0 || >=12.0.0} dependencies: flatted: 3.2.5 rimraf: 3.0.2 dev: true /flatted/3.2.5: resolution: {integrity: sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==} dev: true /foreground-child/2.0.0: resolution: {integrity: sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==} engines: {node: '>=8.0.0'} dependencies: cross-spawn: 7.0.3 signal-exit: 3.0.6 dev: true /fs-extra/10.0.0: resolution: {integrity: sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==} engines: {node: '>=12'} dependencies: graceful-fs: 4.2.9 jsonfile: 6.1.0 universalify: 2.0.0 dev: true /fs.realpath/1.0.0: resolution: {integrity: sha1-FQStJSMVjKpA20onh8sBQRmU6k8=} dev: true /fsevents/2.3.2: resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} os: [darwin] requiresBuild: true dev: true optional: true /function-bind/1.1.1: resolution: {integrity: sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==} dev: true /functional-red-black-tree/1.0.1: resolution: {integrity: sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=} dev: true /get-caller-file/2.0.5: resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} engines: {node: 6.* || 8.* || >= 10.*} dev: true /get-intrinsic/1.1.1: resolution: {integrity: sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==} dependencies: function-bind: 1.1.1 has: 1.0.3 has-symbols: 1.0.2 dev: true /get-symbol-description/1.0.0: resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==} engines: {node: '>= 0.4'} dependencies: call-bind: 1.0.2 get-intrinsic: 1.1.1 dev: true /glob-parent/5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} dependencies: is-glob: 4.0.3 dev: true /glob-parent/6.0.2: resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} engines: {node: '>=10.13.0'} dependencies: is-glob: 4.0.3 dev: true /glob/7.2.0: resolution: {integrity: sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==} dependencies: fs.realpath: 1.0.0 inflight: 1.0.6 inherits: 2.0.4 minimatch: 3.0.4 once: 1.4.0 path-is-absolute: 1.0.1 dev: true /globals/13.12.0: resolution: {integrity: sha512-uS8X6lSKN2JumVoXrbUz+uG4BYG+eiawqm3qFcT7ammfbUHeCBoJMlHcec/S3krSk73/AE/f0szYFmgAA3kYZg==} engines: {node: '>=8'} dependencies: type-fest: 0.20.2 dev: true /globby/11.1.0: resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} engines: {node: '>=10'} dependencies: array-union: 2.1.0 dir-glob: 3.0.1 fast-glob: 3.2.11 ignore: 5.2.0 merge2: 1.4.1 slash: 3.0.0 dev: true /graceful-fs/4.2.9: resolution: {integrity: sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==} dev: true /has-bigints/1.0.1: resolution: {integrity: sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==} dev: true /has-flag/4.0.0: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} dev: true /has-symbols/1.0.2: resolution: {integrity: sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==} engines: {node: '>= 0.4'} dev: true /has-tostringtag/1.0.0: resolution: {integrity: sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==} engines: {node: '>= 0.4'} dependencies: has-symbols: 1.0.2 dev: true /has/1.0.3: resolution: {integrity: sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==} engines: {node: '>= 0.4.0'} dependencies: function-bind: 1.1.1 dev: true /html-escaper/2.0.2: resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} dev: true /ignore/4.0.6: resolution: {integrity: sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==} engines: {node: '>= 4'} dev: true /ignore/5.2.0: resolution: {integrity: sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==} engines: {node: '>= 4'} dev: true /import-fresh/3.3.0: resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} engines: {node: '>=6'} dependencies: parent-module: 1.0.1 resolve-from: 4.0.0 dev: true /imurmurhash/0.1.4: resolution: {integrity: sha1-khi5srkoojixPcT7a21XbyMUU+o=} engines: {node: '>=0.8.19'} dev: true /inflight/1.0.6: resolution: {integrity: sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=} dependencies: once: 1.4.0 wrappy: 1.0.2 dev: true /inherits/2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} dev: true /internal-slot/1.0.3: resolution: {integrity: sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==} engines: {node: '>= 0.4'} dependencies: get-intrinsic: 1.1.1 has: 1.0.3 side-channel: 1.0.4 dev: true /is-bigint/1.0.4: resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} dependencies: has-bigints: 1.0.1 dev: true /is-binary-path/2.1.0: resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} engines: {node: '>=8'} dependencies: binary-extensions: 2.2.0 dev: true /is-boolean-object/1.1.2: resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} engines: {node: '>= 0.4'} dependencies: call-bind: 1.0.2 has-tostringtag: 1.0.0 dev: true /is-buffer/2.0.5: resolution: {integrity: sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==} engines: {node: '>=4'} dev: true /is-callable/1.2.4: resolution: {integrity: sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==} engines: {node: '>= 0.4'} dev: true /is-core-module/2.8.1: resolution: {integrity: sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==} dependencies: has: 1.0.3 dev: true /is-date-object/1.0.5: resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} engines: {node: '>= 0.4'} dependencies: has-tostringtag: 1.0.0 dev: true /is-extglob/2.1.1: resolution: {integrity: sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=} engines: {node: '>=0.10.0'} dev: true /is-fullwidth-code-point/3.0.0: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} dev: true /is-glob/4.0.3: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} dependencies: is-extglob: 2.1.1 dev: true /is-negative-zero/2.0.2: resolution: {integrity: sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==} engines: {node: '>= 0.4'} dev: true /is-number-object/1.0.6: resolution: {integrity: sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==} engines: {node: '>= 0.4'} dependencies: has-tostringtag: 1.0.0 dev: true /is-number/7.0.0: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} dev: true /is-regex/1.1.4: resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} engines: {node: '>= 0.4'} dependencies: call-bind: 1.0.2 has-tostringtag: 1.0.0 dev: true /is-shared-array-buffer/1.0.1: resolution: {integrity: sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA==} dev: true /is-string/1.0.7: resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} engines: {node: '>= 0.4'} dependencies: has-tostringtag: 1.0.0 dev: true /is-symbol/1.0.4: resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} engines: {node: '>= 0.4'} dependencies: has-symbols: 1.0.2 dev: true /is-weakref/1.0.2: resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} dependencies: call-bind: 1.0.2 dev: true /isexe/2.0.0: resolution: {integrity: sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=} dev: true /istanbul-lib-coverage/3.2.0: resolution: {integrity: sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==} engines: {node: '>=8'} dev: true /istanbul-lib-report/3.0.0: resolution: {integrity: sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==} engines: {node: '>=8'} dependencies: istanbul-lib-coverage: 3.2.0 make-dir: 3.1.0 supports-color: 7.2.0 dev: true /istanbul-reports/3.1.3: resolution: {integrity: sha512-x9LtDVtfm/t1GFiLl3NffC7hz+I1ragvgX1P/Lg1NlIagifZDKUkuuaAxH/qpwj2IuEfD8G2Bs/UKp+sZ/pKkg==} engines: {node: '>=8'} dependencies: html-escaper: 2.0.2 istanbul-lib-report: 3.0.0 dev: true /js-yaml/4.1.0: resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} hasBin: true dependencies: argparse: 2.0.1 dev: true /json-schema-traverse/0.4.1: resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} dev: true /json-stable-stringify-without-jsonify/1.0.1: resolution: {integrity: sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=} dev: true /json5/1.0.1: resolution: {integrity: sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==} hasBin: true dependencies: minimist: 1.2.5 dev: true /jsonfile/6.1.0: resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} dependencies: universalify: 2.0.0 optionalDependencies: graceful-fs: 4.2.9 dev: true /kleur/4.1.4: resolution: {integrity: sha512-8QADVssbrFjivHWQU7KkMgptGTl6WAcSdlbBPY4uNF+mWr6DGcKrvY2w4FQJoXch7+fKMjj0dRrL75vk3k23OA==} engines: {node: '>=6'} dev: true /levn/0.4.1: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} dependencies: prelude-ls: 1.2.1 type-check: 0.4.0 dev: true /lilconfig/2.0.4: resolution: {integrity: sha512-bfTIN7lEsiooCocSISTWXkiWJkRqtL9wYtYy+8EK3Y41qh3mpwPU0ycTOgjdY9ErwXCc8QyrQp82bdL0Xkm9yA==} engines: {node: '>=10'} dev: true /locate-path/2.0.0: resolution: {integrity: sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=} engines: {node: '>=4'} dependencies: p-locate: 2.0.0 path-exists: 3.0.0 dev: true /locate-path/6.0.0: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} engines: {node: '>=10'} dependencies: p-locate: 5.0.0 dev: true /lodash.merge/4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} dev: true /lru-cache/6.0.0: resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} engines: {node: '>=10'} dependencies: yallist: 4.0.0 dev: true /make-dir/3.1.0: resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} engines: {node: '>=8'} dependencies: semver: 6.3.0 dev: true /make-error/1.3.6: resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} dev: true /merge2/1.4.1: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} dev: true /micromatch/4.0.4: resolution: {integrity: sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==} engines: {node: '>=8.6'} dependencies: braces: 3.0.2 picomatch: 2.3.1 dev: true /minimatch/3.0.4: resolution: {integrity: sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==} dependencies: brace-expansion: 1.1.11 dev: true /minimist/1.2.5: resolution: {integrity: sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==} dev: true /mkdirp/1.0.4: resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} engines: {node: '>=10'} hasBin: true dev: true /mri/1.2.0: resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} engines: {node: '>=4'} dev: true /ms/2.0.0: resolution: {integrity: sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=} dev: true /ms/2.1.2: resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} dev: true /ms/2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} dev: true /nanodelay/1.0.8: resolution: {integrity: sha512-mfVn7t26m4mVoUuWdUevZccq0saIh5T4Lu3cAzbZ6j03yc4sIDwM3Dof0LS70YwflPZtGJ92BGhNYV862wXRvg==} dev: true /nanoid/3.2.0: resolution: {integrity: sha512-fmsZYa9lpn69Ad5eDn7FMcnnSR+8R34W9qJEijxYhTbfOWzr22n1QxCMzXLK+ODyW2973V3Fux959iQoUxzUIA==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true /nanospinner/0.6.0: resolution: {integrity: sha512-G2QQwVJListXbtsBW5r5kJs8WXybsO9/SQxzcvSmPRSIOQOeR0v/ETI9hncOna0tzWscdjjcCZUVCJoR4eJlag==} dependencies: picocolors: 1.0.0 dev: true /nanospy/0.4.0: resolution: {integrity: sha512-PUdss1inwE0/ti+X9FKuEBLLWQusaHnLBuwYn0cjJNM446DafMS3tbTWV9C9T/NEnD+BPL0zHdnNF/FWvHelvw==} engines: {node: ^8.0.0 || ^10.0.0 || ^12.0.0 || ^14.0.0 || >=16.0.0} dev: true /natural-compare/1.4.0: resolution: {integrity: sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=} dev: true /normalize-path/3.0.0: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} dev: true /object-inspect/1.12.0: resolution: {integrity: sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g==} dev: true /object-keys/1.1.1: resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} engines: {node: '>= 0.4'} dev: true /object.assign/4.1.2: resolution: {integrity: sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==} engines: {node: '>= 0.4'} dependencies: call-bind: 1.0.2 define-properties: 1.1.3 has-symbols: 1.0.2 object-keys: 1.1.1 dev: true /object.values/1.1.5: resolution: {integrity: sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg==} engines: {node: '>= 0.4'} dependencies: call-bind: 1.0.2 define-properties: 1.1.3 es-abstract: 1.19.1 dev: true /once/1.4.0: resolution: {integrity: sha1-WDsap3WWHUsROsF9nFC6753Xa9E=} dependencies: wrappy: 1.0.2 dev: true /optionator/0.9.1: resolution: {integrity: sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==} engines: {node: '>= 0.8.0'} dependencies: deep-is: 0.1.4 fast-levenshtein: 2.0.6 levn: 0.4.1 prelude-ls: 1.2.1 type-check: 0.4.0 word-wrap: 1.2.3 dev: true /p-limit/1.3.0: resolution: {integrity: sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==} engines: {node: '>=4'} dependencies: p-try: 1.0.0 dev: true /p-limit/3.1.0: resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} engines: {node: '>=10'} dependencies: yocto-queue: 0.1.0 dev: true /p-locate/2.0.0: resolution: {integrity: sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=} engines: {node: '>=4'} dependencies: p-limit: 1.3.0 dev: true /p-locate/5.0.0: resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} engines: {node: '>=10'} dependencies: p-limit: 3.1.0 dev: true /p-try/1.0.0: resolution: {integrity: sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=} engines: {node: '>=4'} dev: true /parent-module/1.0.1: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} engines: {node: '>=6'} dependencies: callsites: 3.1.0 dev: true /path-exists/3.0.0: resolution: {integrity: sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=} engines: {node: '>=4'} dev: true /path-exists/4.0.0: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} dev: true /path-is-absolute/1.0.1: resolution: {integrity: sha1-F0uSaHNVNP+8es5r9TpanhtcX18=} engines: {node: '>=0.10.0'} dev: true /path-key/3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} dev: true /path-parse/1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} dev: true /path-type/4.0.0: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} dev: true /picocolors/1.0.0: resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} /picomatch/2.3.1: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} dev: true /postcss-parser-tests/8.4.0: resolution: {integrity: sha512-ETlKYAGwwVRMZCKO+mKJOEPpky/Q0oMr55ZBs5snMCALe+IFiuIWppohUddx1bWhmlCX1NQviggkQUU3zEEDcg==} dependencies: picocolors: 1.0.0 dev: true /prelude-ls/1.2.1: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} dev: true /punycode/2.1.1: resolution: {integrity: sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==} engines: {node: '>=6'} dev: true /queue-microtask/1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} dev: true /readdirp/3.6.0: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} dependencies: picomatch: 2.3.1 dev: true /regexpp/3.2.0: resolution: {integrity: sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==} engines: {node: '>=8'} dev: true /require-directory/2.1.1: resolution: {integrity: sha1-jGStX9MNqxyXbiNE/+f3kqam30I=} engines: {node: '>=0.10.0'} dev: true /requireindex/1.2.0: resolution: {integrity: sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww==} engines: {node: '>=0.10.5'} dev: true /resolve-from/4.0.0: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} dev: true /resolve/1.22.0: resolution: {integrity: sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==} hasBin: true dependencies: is-core-module: 2.8.1 path-parse: 1.0.7 supports-preserve-symlinks-flag: 1.0.0 dev: true /reusify/1.0.4: resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} dev: true /rimraf/3.0.2: resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} hasBin: true dependencies: glob: 7.2.0 dev: true /run-parallel/1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} dependencies: queue-microtask: 1.2.3 dev: true /sade/1.8.1: resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==} engines: {node: '>=6'} dependencies: mri: 1.2.0 dev: true /safe-buffer/5.1.2: resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} dev: true /semver/6.3.0: resolution: {integrity: sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==} hasBin: true dev: true /semver/7.3.5: resolution: {integrity: sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==} engines: {node: '>=10'} hasBin: true dependencies: lru-cache: 6.0.0 dev: true /shebang-command/2.0.0: resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} engines: {node: '>=8'} dependencies: shebang-regex: 3.0.0 dev: true /shebang-regex/3.0.0: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} dev: true /side-channel/1.0.4: resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} dependencies: call-bind: 1.0.2 get-intrinsic: 1.1.1 object-inspect: 1.12.0 dev: true /signal-exit/3.0.6: resolution: {integrity: sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==} dev: true /simple-git-hooks/2.7.0: resolution: {integrity: sha512-nQe6ASMO9zn5/htIrU37xEIHGr9E6wikXelLbOeTcfsX2O++DHaVug7RSQoq+kO7DvZTH37WA5gW49hN9HTDmQ==} hasBin: true requiresBuild: true dev: true /size-limit/7.0.5: resolution: {integrity: sha512-dve+Vaq/a6H7QZhFbozAUBKNO9ZnZkPX3EF1ETI8yv3YCMdC7e63HmVZDXKB//o3FCTHqtZQ0p3ZtOwN/PSiqQ==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} hasBin: true dependencies: bytes-iec: 3.1.1 chokidar: 3.5.3 ci-job-number: 1.2.2 globby: 11.1.0 lilconfig: 2.0.4 mkdirp: 1.0.4 nanospinner: 0.6.0 picocolors: 1.0.0 dev: true /slash/3.0.0: resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} engines: {node: '>=8'} dev: true /source-map-js/1.0.2: resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} engines: {node: '>=0.10.0'} dev: false /source-map/0.6.1: resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} engines: {node: '>=0.10.0'} dev: true /source-map/0.7.3: resolution: {integrity: sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==} engines: {node: '>= 8'} dev: true /string-width/4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} dependencies: emoji-regex: 8.0.0 is-fullwidth-code-point: 3.0.0 strip-ansi: 6.0.1 dev: true /string.prototype.trimend/1.0.4: resolution: {integrity: sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==} dependencies: call-bind: 1.0.2 define-properties: 1.1.3 dev: true /string.prototype.trimstart/1.0.4: resolution: {integrity: sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==} dependencies: call-bind: 1.0.2 define-properties: 1.1.3 dev: true /strip-ansi/6.0.1: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} dependencies: ansi-regex: 5.0.1 dev: true /strip-bom/3.0.0: resolution: {integrity: sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=} engines: {node: '>=4'} dev: true /strip-json-comments/3.1.1: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} dev: true /supports-color/7.2.0: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} dependencies: has-flag: 4.0.0 dev: true /supports-preserve-symlinks-flag/1.0.0: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} dev: true /test-exclude/6.0.0: resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} engines: {node: '>=8'} dependencies: '@istanbuljs/schema': 0.1.3 glob: 7.2.0 minimatch: 3.0.4 dev: true /text-table/0.2.0: resolution: {integrity: sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=} dev: true /to-regex-range/5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} dependencies: is-number: 7.0.0 dev: true /ts-node/10.4.0_43d2036524ce97aa8076ce68340fa9ec: resolution: {integrity: sha512-g0FlPvvCXSIO1JDF6S232P5jPYqBkRL9qly81ZgAOSU7rwI0stphCgd2kLiCrU9DjQCrJMWEqcNSjQL02s6d8A==} hasBin: true peerDependencies: '@swc/core': '>=1.2.50' '@swc/wasm': '>=1.2.50' '@types/node': '*' typescript: '>=2.7' peerDependenciesMeta: '@swc/core': optional: true '@swc/wasm': optional: true dependencies: '@cspotcode/source-map-support': 0.7.0 '@tsconfig/node10': 1.0.8 '@tsconfig/node12': 1.0.9 '@tsconfig/node14': 1.0.1 '@tsconfig/node16': 1.0.2 '@types/node': 17.0.14 acorn: 8.7.0 acorn-walk: 8.2.0 arg: 4.1.3 create-require: 1.1.1 diff: 4.0.2 make-error: 1.3.6 typescript: 4.5.5 yn: 3.1.1 dev: true /tsconfig-paths/3.12.0: resolution: {integrity: sha512-e5adrnOYT6zqVnWqZu7i/BQ3BnhzvGbjEjejFXO20lKIKpwTaupkCPgEfv4GZK1IBciJUEhYs3J3p75FdaTFVg==} dependencies: '@types/json5': 0.0.29 json5: 1.0.1 minimist: 1.2.5 strip-bom: 3.0.0 dev: true /tslib/1.14.1: resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} dev: true /tsutils/3.21.0_typescript@4.5.5: resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} engines: {node: '>= 6'} peerDependencies: typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta' dependencies: tslib: 1.14.1 typescript: 4.5.5 dev: true /type-check/0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} engines: {node: '>= 0.8.0'} dependencies: prelude-ls: 1.2.1 dev: true /type-fest/0.20.2: resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} engines: {node: '>=10'} dev: true /typescript/4.5.5: resolution: {integrity: sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==} engines: {node: '>=4.2.0'} hasBin: true dev: true /unbox-primitive/1.0.1: resolution: {integrity: sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==} dependencies: function-bind: 1.1.1 has-bigints: 1.0.1 has-symbols: 1.0.2 which-boxed-primitive: 1.0.2 dev: true /unist-util-stringify-position/3.0.0: resolution: {integrity: sha512-SdfAl8fsDclywZpfMDTVDxA2V7LjtRDTOFd44wUJamgl6OlVngsqWjxvermMYf60elWHbxhuRCZml7AnuXCaSA==} dependencies: '@types/unist': 2.0.6 dev: true /universalify/2.0.0: resolution: {integrity: sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==} engines: {node: '>= 10.0.0'} dev: true /uri-js/4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} dependencies: punycode: 2.1.1 dev: true /uvu/0.5.3: resolution: {integrity: sha512-brFwqA3FXzilmtnIyJ+CxdkInkY/i4ErvP7uV0DnUVxQcQ55reuHphorpF+tZoVHK2MniZ/VJzI7zJQoc9T9Yw==} engines: {node: '>=8'} hasBin: true dependencies: dequal: 2.0.2 diff: 5.0.0 kleur: 4.1.4 sade: 1.8.1 dev: true /v8-compile-cache/2.3.0: resolution: {integrity: sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==} dev: true /v8-to-istanbul/8.1.1: resolution: {integrity: sha512-FGtKtv3xIpR6BYhvgH8MI/y78oT7d8Au3ww4QIxymrCtZEh5b8gCw2siywE+puhEmuWKDtmfrvF5UlB298ut3w==} engines: {node: '>=10.12.0'} dependencies: '@types/istanbul-lib-coverage': 2.0.4 convert-source-map: 1.8.0 source-map: 0.7.3 dev: true /vfile-location/4.0.1: resolution: {integrity: sha512-JDxPlTbZrZCQXogGheBHjbRWjESSPEak770XwWPfw5mTc1v1nWGLB/apzZxsx8a0SJVfF8HK8ql8RD308vXRUw==} dependencies: '@types/unist': 2.0.6 vfile: 5.3.0 dev: true /vfile-message/3.1.0: resolution: {integrity: sha512-4QJbBk+DkPEhBXq3f260xSaWtjE4gPKOfulzfMFF8ZNwaPZieWsg3iVlcmF04+eebzpcpeXOOFMfrYzJHVYg+g==} dependencies: '@types/unist': 2.0.6 unist-util-stringify-position: 3.0.0 dev: true /vfile/5.3.0: resolution: {integrity: sha512-Tj44nY/48OQvarrE4FAjUfrv7GZOYzPbl5OD65HxVKwLJKMPU7zmfV8cCgCnzKWnSfYG2f3pxu+ALqs7j22xQQ==} dependencies: '@types/unist': 2.0.6 is-buffer: 2.0.5 unist-util-stringify-position: 3.0.0 vfile-message: 3.1.0 dev: true /which-boxed-primitive/1.0.2: resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} dependencies: is-bigint: 1.0.4 is-boolean-object: 1.1.2 is-number-object: 1.0.6 is-string: 1.0.7 is-symbol: 1.0.4 dev: true /which/2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} hasBin: true dependencies: isexe: 2.0.0 dev: true /word-wrap/1.2.3: resolution: {integrity: sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==} engines: {node: '>=0.10.0'} dev: true /wrap-ansi/7.0.0: resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} engines: {node: '>=10'} dependencies: ansi-styles: 4.3.0 string-width: 4.2.3 strip-ansi: 6.0.1 dev: true /wrappy/1.0.2: resolution: {integrity: sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=} dev: true /y18n/5.0.8: resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} engines: {node: '>=10'} dev: true /yallist/4.0.0: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} dev: true /yargs-parser/20.2.9: resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==} engines: {node: '>=10'} dev: true /yargs/16.2.0: resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==} engines: {node: '>=10'} dependencies: cliui: 7.0.4 escalade: 3.1.1 get-caller-file: 2.0.5 require-directory: 2.1.1 string-width: 4.2.3 y18n: 5.0.8 yargs-parser: 20.2.9 dev: true /yn/3.1.1: resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} engines: {node: '>=6'} dev: true /yocto-queue/0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} dev: true postcss-8.4.6/test/000077500000000000000000000000001417621533600142165ustar00rootroot00000000000000postcss-8.4.6/test/at-rule.test.ts000077500000000000000000000022451417621533600171230ustar00rootroot00000000000000import { test } from 'uvu' import { is, type } from 'uvu/assert' import { AtRule, parse } from '../lib/postcss.js' test('initializes with properties', () => { let rule = new AtRule({ name: 'encoding', params: '"utf-8"' }) is(rule.name, 'encoding') is(rule.params, '"utf-8"') is(rule.toString(), '@encoding "utf-8"') }) test('does not fall on childless at-rule', () => { let rule = new AtRule() rule.each(() => { throw new Error('AtRule has no children') }) }) test('creates nodes property on prepend()', () => { let rule = new AtRule() type(rule.nodes, 'undefined') rule.prepend('color: black') is(rule.nodes.length, 1) }) test('creates nodes property on append()', () => { let rule = new AtRule() type(rule.nodes, 'undefined') rule.append('color: black') is(rule.nodes.length, 1) }) test('inserts default spaces', () => { let rule = new AtRule({ name: 'page', params: 1, nodes: [] }) is(rule.toString(), '@page 1 {}') }) test('clone spaces from another at-rule', () => { let root = parse('@page{}a{}') let rule = new AtRule({ name: 'page', params: 1, nodes: [] }) root.append(rule) is(rule.toString(), '@page 1{}') }) test.run() postcss-8.4.6/test/comment.test.ts000077500000000000000000000007401417621533600172120ustar00rootroot00000000000000import { test } from 'uvu' import { is } from 'uvu/assert' import { Comment, parse } from '../lib/postcss.js' test('toString() inserts default spaces', () => { let comment = new Comment({ text: 'hi' }) is(comment.toString(), '/* hi */') }) test('toString() clones spaces from another comment', () => { let root = parse('a{} /*hello*/') let comment = new Comment({ text: 'world' }) root.append(comment) is(root.toString(), 'a{} /*hello*/ /*world*/') }) test.run() postcss-8.4.6/test/container.test.ts000077500000000000000000000460711417621533600175410ustar00rootroot00000000000000import { test } from 'uvu' import { is, equal, throws, type, match } from 'uvu/assert' import { Declaration, Root, Rule, AtRule, parse } from '../lib/postcss.js' let example = 'a { a: 1; b: 2 }' + '/* a */' + '@keyframes anim {' + '/* b */' + 'to { c: 3 }' + '}' + '@media all and (min-width: 100) {' + 'em { d: 4 }' + '@page {' + 'e: 5;' + '/* c */' + '}' + '}' test('throws error on declaration without value', () => { throws(() => { // @ts-expect-error new Rule().append({ prop: 'color', vlaue: 'black' }) }, /Value field is missed/) }) test('throws error on unknown node type', () => { throws(() => { // @ts-expect-error new Rule().append({ foo: 'bar' }) }, /Unknown node type/) }) test('push() adds child without checks', () => { let rule = parse('a { a: 1; b: 2 }').first as Rule rule.push(new Declaration({ prop: 'c', value: '3' })) is(rule.toString(), 'a { a: 1; b: 2; c: 3 }') is(rule.nodes.length, 3) type(rule.last?.raws.before, 'undefined') }) test('each() iterates', () => { let rule = parse('a { a: 1; b: 2 }').first as Rule let indexes: number[] = [] let result = rule.each((decl, i) => { indexes.push(i) is(decl, rule.nodes[i]) }) type(result, 'undefined') equal(indexes, [0, 1]) }) test('each() iterates with prepend', () => { let rule = parse('a { a: 1; b: 2 }').first as Rule let size = 0 rule.each(() => { rule.prepend({ prop: 'color', value: 'aqua' }) size += 1 }) is(size, 2) }) test('each() iterates with prepend insertBefore', () => { let rule = parse('a { a: 1; b: 2 }').first as Rule let size = 0 rule.each(decl => { if (decl.type === 'decl' && decl.prop === 'a') { rule.insertBefore(decl, { prop: 'c', value: '3' }) } size += 1 }) is(size, 2) }) test('each() iterates with append insertBefore', () => { let rule = parse('a { a: 1; b: 2 }').first as Rule let size = 0 rule.each((decl, i) => { if (decl.type === 'decl' && decl.prop === 'a') { rule.insertBefore(i + 1, { prop: 'c', value: '3' }) } size += 1 }) is(size, 3) }) test('each() iterates with prepend insertAfter', () => { let rule = parse('a { a: 1; b: 2 }').first as Rule let size = 0 rule.each((decl, i) => { rule.insertAfter(i - 1, { prop: 'c', value: '3' }) size += 1 }) is(size, 2) }) test('each() iterates with append insertAfter', () => { let rule = parse('a { a: 1; b: 2 }').first as Rule let size = 0 rule.each((decl, i) => { if (decl.type === 'decl' && decl.prop === 'a') { rule.insertAfter(i, { prop: 'c', value: '3' }) } size += 1 }) is(size, 3) }) test('each() iterates with remove', () => { let rule = parse('a { a: 1; b: 2 }').first as Rule let size = 0 rule.each(() => { rule.removeChild(0) size += 1 }) is(size, 2) }) test('each() breaks iteration', () => { let rule = parse('a { a: 1; b: 2 }').first as Rule let indexes: number[] = [] let result = rule.each((decl, i) => { indexes.push(i) return false }) is(result, false) equal(indexes, [0]) }) test('each() allows to change children', () => { let rule = parse('a { a: 1; b: 2 }').first as Rule let props: string[] = [] rule.each(decl => { if (decl.type === 'decl') { props.push(decl.prop) rule.nodes = [rule.last as any, rule.first as any] } }) equal(props, ['a', 'a']) }) test('walk() iterates', () => { let types: string[] = [] let indexes: number[] = [] let result = parse(example).walk((node, i) => { types.push(node.type) indexes.push(i) }) type(result, 'undefined') equal(types, [ 'rule', 'decl', 'decl', 'comment', 'atrule', 'comment', 'rule', 'decl', 'atrule', 'rule', 'decl', 'atrule', 'decl', 'comment' ]) equal(indexes, [0, 0, 1, 1, 2, 0, 1, 0, 3, 0, 0, 1, 0, 1]) }) test('walk() breaks iteration', () => { let indexes: number[] = [] let result = parse(example).walk((decl, i) => { indexes.push(i) return false }) is(result, false) equal(indexes, [0]) }) test('walk() adds CSS position to error stack', () => { let error = new Error('T') error.stack = 'Error: T\n at b (b.js:2:4)\n at a (a.js:2:1)' let root = parse(example, { from: '/c.css' }) let catched: any try { root.walk(() => { throw error }) } catch (e) { catched = e } is(catched, error) is(catched.postcssNode.toString(), 'a { a: 1; b: 2 }') is( catched.stack.replace(/.:\\/i, '/'), 'Error: T\n at /c.css:1:1\n at b (b.js:2:4)\n at a (a.js:2:1)' ) }) test('walkDecls() iterates', () => { let props: string[] = [] let indexes: number[] = [] let result = parse(example).walkDecls((decl, i) => { props.push(decl.prop) indexes.push(i) }) type(result, 'undefined') equal(props, ['a', 'b', 'c', 'd', 'e']) equal(indexes, [0, 1, 0, 0, 0]) }) test('walkDecls() iterates with changes', () => { let size = 0 parse(example).walkDecls((decl, i) => { decl.parent?.removeChild(i) size += 1 }) is(size, 5) }) test('walkDecls() breaks iteration', () => { let indexes: number[] = [] let result = parse(example).walkDecls((decl, i) => { indexes.push(i) return false }) is(result, false) equal(indexes, [0]) }) test('walkDecls() filters declarations by property name', () => { let css = parse('@page{a{one:1}}b{one:1;two:2}') let size = 0 css.walkDecls('one', decl => { is(decl.prop, 'one') size += 1 }) is(size, 2) }) test('walkDecls() breaks declarations filter by name', () => { let css = parse('@page{a{one:1}}b{one:1;two:2}') let size = 0 css.walkDecls('one', () => { size += 1 return false }) is(size, 1) }) test('walkDecls() filters declarations by property regexp', () => { let css = parse('@page{a{one:1}}b{one-x:1;two:2}') let size = 0 css.walkDecls(/one(-x)?/, () => { size += 1 }) is(size, 2) }) test('walkDecls() breaks declarations filters by regexp', () => { let css = parse('@page{a{one:1}}b{one-x:1;two:2}') let size = 0 css.walkDecls(/one(-x)?/, () => { size += 1 return false }) is(size, 1) }) test('walkComments() iterates', () => { let texts: string[] = [] let indexes: number[] = [] let result = parse(example).walkComments((comment, i) => { texts.push(comment.text) indexes.push(i) }) type(result, 'undefined') equal(texts, ['a', 'b', 'c']) equal(indexes, [1, 0, 1]) }) test('walkComments() iterates with changes', () => { let size = 0 parse(example).walkComments((comment, i) => { comment.parent?.removeChild(i) size += 1 }) is(size, 3) }) test('walkComments() breaks iteration', () => { let indexes: number[] = [] let result = parse(example).walkComments((comment, i) => { indexes.push(i) return false }) is(result, false) equal(indexes, [1]) }) test('walkRules() iterates', () => { let selectors: string[] = [] let indexes: number[] = [] let result = parse(example).walkRules((rule, i) => { selectors.push(rule.selector) indexes.push(i) }) type(result, 'undefined') equal(selectors, ['a', 'to', 'em']) equal(indexes, [0, 1, 0]) }) test('walkRules() iterates with changes', () => { let size = 0 parse(example).walkRules((rule, i) => { rule.parent?.removeChild(i) size += 1 }) is(size, 3) }) test('walkRules() breaks iteration', () => { let indexes: number[] = [] let result = parse(example).walkRules((rule, i) => { indexes.push(i) return false }) is(result, false) equal(indexes, [0]) }) test('walkRules() filters by selector', () => { let size = 0 parse('a{}b{}a{}').walkRules('a', rule => { is(rule.selector, 'a') size += 1 }) is(size, 2) }) test('walkRules() breaks selector filters', () => { let size = 0 parse('a{}b{}a{}').walkRules('a', () => { size += 1 return false }) is(size, 1) }) test('walkRules() filters by regexp', () => { let size = 0 parse('a{}a b{}b a{}').walkRules(/^a/, rule => { match(rule.selector, /^a/) size += 1 }) is(size, 2) }) test('walkRules() breaks selector regexp', () => { let size = 0 parse('a{}b a{}b a{}').walkRules(/^a/, () => { size += 1 return false }) is(size, 1) }) test('walkAtRules() iterates', () => { let names: string[] = [] let indexes: number[] = [] let result = parse(example).walkAtRules((atrule, i) => { names.push(atrule.name) indexes.push(i) }) type(result, 'undefined') equal(names, ['keyframes', 'media', 'page']) equal(indexes, [2, 3, 1]) }) test('walkAtRules() iterates with changes', () => { let size = 0 parse(example).walkAtRules((atrule, i) => { atrule.parent?.removeChild(i) size += 1 }) is(size, 3) }) test('walkAtRules() breaks iteration', () => { let indexes: number[] = [] let result = parse(example).walkAtRules((atrule, i) => { indexes.push(i) return false }) is(result, false) equal(indexes, [2]) }) test('walkAtRules() filters at-rules by name', () => { let css = parse('@page{@page 2{}}@media print{@page{}}') let size = 0 css.walkAtRules('page', atrule => { is(atrule.name, 'page') size += 1 }) is(size, 3) }) test('walkAtRules() breaks name filter', () => { let size = 0 parse('@page{@page{@page{}}}').walkAtRules('page', () => { size += 1 return false }) is(size, 1) }) test('walkAtRules() filters at-rules by name regexp', () => { let css = parse('@page{@page 2{}}@media print{@pages{}}') let size = 0 css.walkAtRules(/page/, () => { size += 1 }) is(size, 3) }) test('walkAtRules() breaks regexp filter', () => { let size = 0 parse('@page{@pages{@page{}}}').walkAtRules(/page/, () => { size += 1 return false }) is(size, 1) }) test('append() appends child', () => { let rule = parse('a { a: 1; b: 2 }').first as Rule rule.append({ prop: 'c', value: '3' }) is(rule.toString(), 'a { a: 1; b: 2; c: 3 }') is(rule.last?.raws.before, ' ') }) test('append() appends multiple children', () => { let rule = parse('a { a: 1; b: 2 }').first as Rule rule.append({ prop: 'c', value: '3' }, { prop: 'd', value: '4' }) is(rule.toString(), 'a { a: 1; b: 2; c: 3; d: 4 }') is(rule.last?.raws.before, ' ') }) test('append() has declaration shortcut', () => { let rule = parse('a { a: 1; b: 2 }').first as Rule rule.append({ prop: 'c', value: '3' }) is(rule.toString(), 'a { a: 1; b: 2; c: 3 }') }) test('append() has rule shortcut', () => { let root = new Root() root.append({ selector: 'a' }) is(root.first?.toString(), 'a {}') }) test('append() has at-rule shortcut', () => { let root = new Root() root.append({ name: 'encoding', params: '"utf-8"' }) is(root.first?.toString(), '@encoding "utf-8"') }) test('append() has comment shortcut', () => { let root = new Root() root.append({ text: 'ok' }) is(root.first?.toString(), '/* ok */') }) test('append() receives root', () => { let css = parse('a {}') css.append(parse('b {}')) is(css.toString(), 'a {}b {}') }) test('append() reveives string', () => { let root = new Root() root.append('a{}b{}') let a = root.first as Rule a.append('color:black') is(root.toString(), 'a{color:black}b{}') type(a.first?.source, 'undefined') }) test('append() receives array', () => { let a = parse('a{ z-index: 1 }') let b = parse('b{ width: 1px; height: 2px }') let aRule = a.first as Rule let bRule = b.first as Rule aRule.append(bRule.nodes) is(a.toString(), 'a{ z-index: 1; width: 1px; height: 2px }') is(b.toString(), 'b{ }') }) test('append() move node on insert', () => { let a = parse('a{}') let b = parse('b{}') b.append(a.first as Rule) let bLast = b.last as Rule bLast.selector = 'b a' is(a.toString(), '') is(b.toString(), 'b{}b a{}') }) test('prepend() prepends child', () => { let rule = parse('a { a: 1; b: 2 }').first as Rule rule.prepend({ prop: 'c', value: '3' }) is(rule.toString(), 'a { c: 3; a: 1; b: 2 }') is(rule.first?.raws.before, ' ') }) test('prepend() prepends multiple children', () => { let rule = parse('a { a: 1; b: 2 }').first as Rule rule.prepend({ prop: 'c', value: '3' }, { prop: 'd', value: '4' }) is(rule.toString(), 'a { c: 3; d: 4; a: 1; b: 2 }') is(rule.first?.raws.before, ' ') }) test('prepend() receive hash instead of declaration', () => { let rule = parse('a { a: 1; b: 2 }').first as Rule rule.prepend({ prop: 'c', value: '3' }) is(rule.toString(), 'a { c: 3; a: 1; b: 2 }') }) test('prepend() receives root', () => { let css = parse('a {}') css.prepend(parse('b {}')) is(css.toString(), 'b {}\na {}') }) test('prepend() receives string', () => { let css = parse('a {}') css.prepend('b {}') is(css.toString(), 'b {}\na {}') }) test('prepend() receives array', () => { let a = parse('a{ z-index: 1 }') let b = parse('b{ width: 1px; height: 2px }') let aRule = a.first as Rule let bRule = b.first as Rule aRule.prepend(bRule.nodes) is(a.toString(), 'a{ width: 1px; height: 2px; z-index: 1 }') }) test('prepend() works on empty container', () => { let root = parse('') root.prepend(new Rule({ selector: 'a' })) is(root.toString(), 'a {}') }) test('insertBefore() inserts child', () => { let rule = parse('a { a: 1; b: 2 }').first as Rule rule.insertBefore(1, { prop: 'c', value: '3' }) is(rule.toString(), 'a { a: 1; c: 3; b: 2 }') is(rule.nodes[1].raws.before, ' ') }) test('insertBefore() works with nodes too', () => { let rule = parse('a { a: 1; b: 2 }').first as Rule rule.insertBefore(rule.nodes[1], { prop: 'c', value: '3' }) is(rule.toString(), 'a { a: 1; c: 3; b: 2 }') }) test('insertBefore() receive hash instead of declaration', () => { let rule = parse('a { a: 1; b: 2 }').first as Rule rule.insertBefore(1, { prop: 'c', value: '3' }) is(rule.toString(), 'a { a: 1; c: 3; b: 2 }') }) test('insertBefore() receives array', () => { let a = parse('a{ color: red; z-index: 1 }') let b = parse('b{ width: 1; height: 2 }') let aRule = a.first as Rule let bRule = b.first as Rule aRule.insertBefore(1, bRule.nodes) is(a.toString(), 'a{ color: red; width: 1; height: 2; z-index: 1 }') }) test('insertAfter() inserts child', () => { let rule = parse('a { a: 1; b: 2 }').first as Rule rule.insertAfter(0, { prop: 'c', value: '3' }) is(rule.toString(), 'a { a: 1; c: 3; b: 2 }') is(rule.nodes[1].raws.before, ' ') }) test('insertAfter() works with nodes too', () => { let rule = parse('a { a: 1; b: 2 }').first as Rule let aDecl = rule.first as Declaration rule.insertAfter(aDecl, { prop: 'c', value: '3' }) is(rule.toString(), 'a { a: 1; c: 3; b: 2 }') }) test('insertAfter() receive hash instead of declaration', () => { let rule = parse('a { a: 1; b: 2 }').first as Rule rule.insertAfter(0, { prop: 'c', value: '3' }) is(rule.toString(), 'a { a: 1; c: 3; b: 2 }') }) test('insertAfter() receives array', () => { let a = parse('a{ color: red; z-index: 1 }') let b = parse('b{ width: 1; height: 2 }') let aRule = a.first as Rule let bRule = b.first as Rule aRule.insertAfter(0, bRule.nodes) is(a.toString(), 'a{ color: red; width: 1; height: 2; z-index: 1 }') }) test('removeChild() removes by index', () => { let rule = parse('a { a: 1; b: 2 }').first as Rule rule.removeChild(1) is(rule.toString(), 'a { a: 1 }') }) test('removeChild() removes by node', () => { let rule = parse('a { a: 1; b: 2 }').first as Rule let bDecl = rule.last as Declaration rule.removeChild(bDecl) is(rule.toString(), 'a { a: 1 }') }) test('removeChild() cleans parent in removed node', () => { let rule = parse('a { a: 1; b: 2 }').first as Rule let aDecl = rule.first as Declaration rule.removeChild(aDecl) type(aDecl.parent, 'undefined') }) test('removeAll() removes all children', () => { let rule = parse('a { a: 1; b: 2 }').first as Rule let decl = rule.first as Declaration rule.removeAll() type(decl.parent, 'undefined') is(rule.toString(), 'a { }') }) test('replaceValues() replaces strings', () => { let css = parse('a{one:1}b{two:1 2}') let result = css.replaceValues('1', 'A') equal(result, css) is(css.toString(), 'a{one:A}b{two:A 2}') }) test('replaceValues() replaces regpexp', () => { let css = parse('a{one:1}b{two:1 2}') css.replaceValues(/\d/g, i => i + 'A') is(css.toString(), 'a{one:1A}b{two:1A 2A}') }) test('replaceValues() filters properties', () => { let css = parse('a{one:1}b{two:1 2}') css.replaceValues('1', { props: ['one'] }, 'A') is(css.toString(), 'a{one:A}b{two:1 2}') }) test('replaceValues() uses fast check', () => { let css = parse('a{one:1}b{two:1 2}') css.replaceValues('1', { fast: '2' }, 'A') is(css.toString(), 'a{one:1}b{two:A 2}') }) test('any() return true if all children return true', () => { let rule = parse('a { a: 1; b: 2 }').first as Rule is( rule.every(i => i.type === 'decl' && /a|b/.test(i.prop)), true ) is( rule.every(i => i.type === 'decl' && /b/.test(i.prop)), false ) }) test('some() return true if all children return true', () => { let rule = parse('a { a: 1; b: 2 }').first as Rule is( rule.some(i => i.type === 'decl' && i.prop === 'b'), true ) is( rule.some(i => i.type === 'decl' && i.prop === 'c'), false ) }) test('index() returns child index', () => { let rule = parse('a { a: 1; b: 2 }').first as Rule is(rule.index(rule.nodes[1]), 1) }) test('index() returns argument if it is number', () => { let rule = parse('a { a: 1; b: 2 }').first as Rule is(rule.index(2), 2) }) test('first() works for children-less nodes', () => { let atRule = parse('@charset "UTF-*"').first as AtRule type(atRule.first, 'undefined') }) test('last() works for children-less nodes', () => { let atRule = parse('@charset "UTF-*"').first as AtRule type(atRule.last, 'undefined') }) test('returns first child', () => { let rule = parse('a { a: 1; b: 2 }').first as Rule let aDecl = rule.first as Declaration is(aDecl.prop, 'a') }) test('returns last child', () => { let rule = parse('a { a: 1; b: 2 }').first as Rule let bDecl = rule.last as Declaration is(bDecl.prop, 'b') }) test('normalize() does not normalize new children with exists before', () => { let rule = parse('a { a: 1; b: 2 }').first as Rule rule.append({ prop: 'c', value: '3', raws: { before: '\n ' } }) is(rule.toString(), 'a { a: 1; b: 2;\n c: 3 }') }) test('forces Declaration#value to be string', () => { let rule = parse('a { a: 1; b: 2 }').first as Rule // @ts-expect-error rule.append({ prop: 'c', value: 3 }) let aDecl = rule.first as Declaration let cDecl = rule.last as Declaration type(aDecl.value, 'string') type(cDecl.value, 'string') }) test('updates parent in overrides.nodes in constructor', () => { let root = new Root({ nodes: [{ selector: 'a' }] }) let a = root.first as Rule equal(a.parent, root) root.append({ selector: 'b', nodes: [{ prop: 'color', value: 'black' }] }) let b = root.last as Rule let color = b.first as Declaration equal(color.parent, root.last) }) test('allows to clone nodes', () => { let root1 = parse('a { color: black; z-index: 1 } b {}') let root2 = new Root({ nodes: root1.nodes }) is(root1.toString(), 'a { color: black; z-index: 1 } b {}') is(root2.toString(), 'a { color: black; z-index: 1 } b {}') }) test.run() postcss-8.4.6/test/css-syntax-error.test.ts000077500000000000000000000201551417621533600210150ustar00rootroot00000000000000import pico from 'picocolors' import { join, resolve as pathResolve } from 'path' import { pathToFileURL } from 'url' import stripAnsi from 'strip-ansi' import Concat from 'concat-with-sourcemaps' import { test } from 'uvu' import { is, equal, match, type } from 'uvu/assert' import postcss, { ProcessOptions, CssSyntaxError, Plugin, Rule } from '../lib/postcss.js' function isSyntaxError(e: unknown): e is CssSyntaxError { return e instanceof Error && e.name === 'CssSyntaxError' } async function catchError(cb: () => Promise): Promise { try { await cb() } catch (e) { if (isSyntaxError(e)) { return e } else { throw e } } throw new Error('Error was not thrown') } function parseError( css: string, opts?: Pick ): CssSyntaxError { try { postcss.parse(css, opts) } catch (e) { if (isSyntaxError(e)) { return e } else { throw e } } throw new Error('Error was not thrown') } test('saves source', () => { let error = parseError('a {\n content: "\n}') is(error instanceof CssSyntaxError, true) is(error.name, 'CssSyntaxError') is(error.message, ':2:12: Unclosed string') is(error.reason, 'Unclosed string') is(error.line, 2) is(error.column, 12) is(error.source, 'a {\n content: "\n}') equal(error.input, { line: error.line, column: error.column, source: error.source, endLine: error.endLine, endColumn: error.endColumn, }) }) test('saves source with ranges', () => { let error = parseError('badword') is(error instanceof CssSyntaxError, true) is(error.name, 'CssSyntaxError') is(error.message, ':1:1: Unknown word') is(error.reason, 'Unknown word') is(error.line, 1) is(error.column, 1) is(error.endLine, 1) is(error.endColumn, 8) is(error.source, 'badword') equal(error.input, { line: error.line, column: error.column, endLine: error.endLine, endColumn: error.endColumn, source: error.source }) }) test('has stack trace', () => { match(parseError('a {\n content: "\n}').stack, /css-syntax-error\.test\.ts/ ) }) test('saves source with ranges', () => { let error = parseError('badword') is(error instanceof CssSyntaxError, true) is(error.name, 'CssSyntaxError') is(error.message, ':1:1: Unknown word') is(error.reason, 'Unknown word') is(error.line, 1) is(error.column, 1) is(error.endLine, 1) is(error.endColumn, 8) is(error.source, 'badword') equal(error.input, { line: error.line, column: error.column, endLine: error.endLine, endColumn: error.endColumn, source: error.source }) }) test('saves source with ranges', () => { let error = parseError('badword') is(error instanceof CssSyntaxError, true) is(error.name, 'CssSyntaxError') is(error.message, ':1:1: Unknown word') is(error.reason, 'Unknown word') is(error.line, 1) is(error.column, 1) is(error.endLine, 1) is(error.endColumn, 8) is(error.source, 'badword') equal(error.input, { line: error.line, column: error.column, endLine: error.endLine, endColumn: error.endColumn, source: error.source }) }) test('highlights broken line with colors', () => { is( parseError('#a .b c() {').showSourceCode(true), pico.bold(pico.red('>')) + pico.gray(' 1 | ') + pico.magenta('#a') + ' ' + pico.yellow('.b') + ' ' + pico.cyan('c') + pico.cyan('()') + ' ' + pico.yellow('{') + '\n ' + pico.gray(' | ') + pico.bold(pico.red('^')) ) }) test('highlights broken line', () => { is( parseError('a {\n content: "\n}').showSourceCode(false), ' 1 | a {\n' + '> 2 | content: "\n' + ' | ^\n' + ' 3 | }' ) }) test('highlights broken line, when indented with tabs', () => { is( parseError('a {\n\t \t content:\t"\n}').showSourceCode(false), ' 1 | a {\n' + '> 2 | \t \t content:\t"\n' + ' | \t \t \t^\n' + ' 3 | }' ) }) test('highlights small code example', () => { is(parseError('a {').showSourceCode(false), '> 1 | a {\n' + ' | ^') }) test('add leading space for line numbers', () => { let css = '\n\n\n\n\n\n\na {\n content: "\n}\n\n\n' is( parseError(css).showSourceCode(false), ' 7 | \n' + ' 8 | a {\n' + '> 9 | content: "\n' + ' | ^\n' + ' 10 | }\n' + ' 11 | ' ) }) test('prints with highlight', () => { is( stripAnsi(parseError('a {').toString()), 'CssSyntaxError: :1:1: Unclosed block\n' + '\n' + '> 1 | a {\n' + ' | ^\n' ) }) test('misses highlights without source content', () => { let error = parseError('a {') error.source = undefined is(error.toString(), 'CssSyntaxError: :1:1: Unclosed block') }) test('misses position without source', () => { let decl = postcss.decl({ prop: 'color', value: 'black' }) let error = decl.error('Test') is(error.toString(), 'CssSyntaxError: : Test') }) test('uses source map', () => { function urlOf(file: string): string { return pathToFileURL(join(__dirname, file)).toString() } let concat = new Concat(true, join(__dirname, 'build', 'all.css')) concat.add(urlOf('a.css'), 'a { }\n') concat.add(urlOf('b.css'), '\nb {\n') let error = parseError(concat.content.toString(), { from: join(__dirname, 'build', 'all.css'), map: { prev: concat.sourceMap } }) is(error.file, join(__dirname, 'b.css')) is(error.line, 2) type(error.source, 'undefined') equal(error.input, { url: urlOf(join('build', 'all.css')), file: join(__dirname, 'build', 'all.css'), line: 3, column: 1, source: 'a { }\n\nb {\n', endLine: error.endLine, endColumn: error.endColumn, }) }) test('works with path in sources', () => { function pathOf(file: string): string { return join(__dirname, file) } let concat = new Concat(true, join(__dirname, 'build', 'all.css')) concat.add(pathOf('a.css'), 'a { }\n') concat.add(pathOf('b.css'), '\nb {\n') let error = parseError(concat.content.toString(), { from: join(__dirname, 'build', 'all.css'), map: { prev: concat.sourceMap } }) is(error.file, join(__dirname, 'b.css')) is(error.line, 2) type(error.source, 'undefined') equal(error.input, { url: pathToFileURL(pathOf(join('build', 'all.css'))).toString(), file: join(__dirname, 'build', 'all.css'), line: 3, column: 1, source: 'a { }\n\nb {\n', endLine: error.endLine, endColumn: error.endColumn, }) }) test('shows origin source', () => { let input = postcss([() => {}]).process('a{}', { from: '/a.css', to: '/b.css', map: { inline: false } }) let error = parseError('a{', { from: '/b.css', map: { prev: input.map } }) is(error.source, 'a{}') }) test('does not uses wrong source map', () => { let error = parseError('a { }\nb {', { from: 'build/all.css', map: { prev: { version: 3, file: 'build/all.css', sources: ['a.css', 'b.css'], mappings: 'A' } } }) is(error.file, pathResolve('build/all.css')) }) test('set source plugin', () => { let a = postcss.parse('a{}').first as Rule let error = a.error('Error', { plugin: 'PL' }) is(error.plugin, 'PL') match(error.toString(), /^CssSyntaxError: PL: :1:1: Error/) }) test('set source plugin automatically', async () => { let plugin: Plugin = { postcssPlugin: 'test-plugin', Once(css) { if (css.first) { throw css.first.error('Error') } } } let error = await catchError(() => postcss([plugin]).process('a{}', { from: undefined }) ) is(error.plugin, 'test-plugin') match(error.toString(), /test-plugin/) }) test('set plugin automatically in async', async () => { let plugin: Plugin = { postcssPlugin: 'async-plugin', Once(css) { return new Promise((resolve, reject) => { if (css.first) { reject(css.first.error('Error')) } }) } } let error = await catchError(() => postcss([plugin]).process('a{}', { from: undefined }) ) is(error.plugin, 'async-plugin') }) test.run() postcss-8.4.6/test/declaration.test.ts000077500000000000000000000026221417621533600200360ustar00rootroot00000000000000import { test } from 'uvu' import { is } from 'uvu/assert' import { Declaration, parse, Rule } from '../lib/postcss.js' test('initializes with properties', () => { let decl = new Declaration({ prop: 'color', value: 'black' }) is(decl.prop, 'color') is(decl.value, 'black') }) test('returns boolean important', () => { let decl = new Declaration({ prop: 'color', value: 'black' }) decl.important = true is(decl.toString(), 'color: black !important') }) test('inserts default spaces', () => { let decl = new Declaration({ prop: 'color', value: 'black' }) let rule = new Rule({ selector: 'a' }) rule.append(decl) is(rule.toString(), 'a {\n color: black\n}') }) test('clones spaces from another declaration', () => { let root = parse('a{color:black}') let rule = root.first as Rule let decl = new Declaration({ prop: 'margin', value: '0' }) rule.append(decl) is(root.toString(), 'a{color:black;margin:0}') }) test('converts value to string', () => { // @ts-expect-error let decl = new Declaration({ prop: 'color', value: 1 }) is(decl.value, '1') }) test('detects variable declarations', () => { let prop = new Declaration({ prop: '--color', value: 'black' }) is(prop.variable, true) let sass = new Declaration({ prop: '$color', value: 'black' }) is(sass.variable, true) let decl = new Declaration({ prop: 'color', value: 'black' }) is(decl.variable, false) }) test.run() postcss-8.4.6/test/document.test.ts000077500000000000000000000012411417621533600173630ustar00rootroot00000000000000import { test } from 'uvu' import { is, match } from 'uvu/assert' import { Result, parse } from '../lib/postcss.js' import Document from '../lib/document.js' test('generates result without map', () => { let root = parse('a {}') let document = new Document() document.append(root) let result = document.toResult() is(result instanceof Result, true) is(result.css, 'a {}') }) test('generates result with map', () => { let root = parse('a {}') let document = new Document() document.append(root) let result = document.toResult({ map: true }) is(result instanceof Result, true) match(result.css, /a {}\n\/\*# sourceMappingURL=/) }) test.run() postcss-8.4.6/test/errors.ts000066400000000000000000000012041417621533600160770ustar00rootroot00000000000000import { PluginCreator } from '../lib/postcss.js' const plugin: PluginCreator<{ a: number }> = opts => { // THROWS Object is possibly 'undefined' console.log(opts.a) // THROWS Property 'b' does not exist on type '{ a: number; }' console.log(opts?.b) return { postcssPlugin: 'remover', // THROWS Property 'Decl' does not exist on type 'Helpers'. Comment(decl, { Decl }) { // THROWS Property 'prop' does not exist on type 'Comment' console.log(decl.prop) // THROWS Property 'removeChild' does not exist on type 'Comment' decl.removeChild(1) } } } plugin.postcss = true export default plugin postcss-8.4.6/test/fromJSON.test.ts000077500000000000000000000033751417621533600172140ustar00rootroot00000000000000import v8 from 'v8' import { test } from 'uvu' import { is, instance, throws } from 'uvu/assert' import postcss, { Root, Declaration, Input, Rule } from '../lib/postcss.js' test('rehydrates a JSON AST', () => { let cssWithMap = postcss().process( '.foo { color: red; font-size: 12pt; } /* abc */ @media (width: 60em) { }', { from: 'x.css', map: { inline: true }, stringifier: postcss.stringify } ).css let root = postcss.parse(cssWithMap) let json = root.toJSON() let serialized = v8.serialize(json) let deserialized = v8.deserialize(serialized) let rehydrated = postcss.fromJSON(deserialized as object) as Root rehydrated.nodes[0].remove() is(rehydrated.nodes.length, 3) is( postcss().process(rehydrated, { from: undefined, map: { inline: true }, stringifier: postcss.stringify }).css, `/* abc */ @media (width: 60em) { } /*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInguY3NzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFzQyxRQUFRLEVBQUUsdUJBQXVCIiwiZmlsZSI6InRvLmNzcyIsInNvdXJjZXNDb250ZW50IjpbIi5mb28geyBjb2xvcjogcmVkOyBmb250LXNpemU6IDEycHQ7IH0gLyogYWJjICovIEBtZWRpYSAod2lkdGg6IDYwZW0pIHsgfSJdfQ== */` ) }) test('rehydrates an array of Nodes via JSON.stringify', () => { let root = postcss.parse('.cls { color: orange; }') let rule = root.first as Rule let json = JSON.stringify(rule.nodes) let rehydrated = postcss.fromJSON(JSON.parse(json) as object[]) instance(rehydrated[0], Declaration) instance(rehydrated[0].source?.input, Input) }) test('throws when rehydrating an invalid JSON AST', () => { throws(() => { postcss.fromJSON({ type: 'not-a-node-type' }) }, 'Unknown node type: not-a-node-type') }) test.run() postcss-8.4.6/test/integration.js000077500000000000000000000002621417621533600171020ustar00rootroot00000000000000#!/usr/bin/env node let { testOnReal } = require('postcss-parser-tests') let { parse } = require('../') testOnReal(css => parse(css).toResult({ map: { annotation: false } })) postcss-8.4.6/test/lazy-result.test.ts000077500000000000000000000035641417621533600200520ustar00rootroot00000000000000import { is, equal, type } from 'uvu/assert' import { test } from 'uvu' import mozilla from 'source-map-js' import LazyResult from '../lib/lazy-result.js' import Processor from '../lib/processor.js' let processor = new Processor() test('contains AST', () => { let result = new LazyResult(processor, 'a {}', {}) is(result.root.type, 'root') }) test('will stringify css', () => { let result = new LazyResult(processor, 'a {}', {}) is(result.css, 'a {}') }) test('stringifies css', () => { let result = new LazyResult(processor, 'a {}', {}) is(`${result}`, result.css) }) test('has content alias for css', () => { let result = new LazyResult(processor, 'a {}', {}) is(result.content, 'a {}') }) test('has map only if necessary', () => { let result1 = new LazyResult(processor, '', {}) type(result1.map, 'undefined') let result2 = new LazyResult(processor, '', {}) type(result2.map, 'undefined') let result3 = new LazyResult(processor, '', { map: { inline: false } }) is(result3.map instanceof mozilla.SourceMapGenerator, true) }) test('contains options', () => { let result = new LazyResult(processor, 'a {}', { to: 'a.css' }) equal(result.opts, { to: 'a.css' }) }) test('contains warnings', () => { let result = new LazyResult(processor, 'a {}', {}) equal(result.warnings(), []) }) test('contains messages', () => { let result = new LazyResult(processor, 'a {}', {}) equal(result.messages, []) }) test('executes on finally callback', () => { let callbackHaveBeenCalled = 0 let mockCallback = (): void => { callbackHaveBeenCalled++ } return new LazyResult(processor, 'a {}', {}) .finally(mockCallback) .then(() => { is(callbackHaveBeenCalled, 1) }) }) test('prints its object type', () => { let result = new LazyResult(processor, 'a {}', {}) is(Object.prototype.toString.call(result), '[object LazyResult]') }) test.run() postcss-8.4.6/test/list.test.ts000077500000000000000000000024161417621533600165250ustar00rootroot00000000000000import { test } from 'uvu' import { equal } from 'uvu/assert' import { list } from '../lib/postcss.js' test('space() splits list by spaces', () => { equal(list.space('a b'), ['a', 'b']) }) test('space() trims values', () => { equal(list.space(' a b '), ['a', 'b']) }) test('space() checks quotes', () => { equal(list.space('"a b\\"" \'\''), ['"a b\\""', "''"]) }) test('space() checks functions', () => { equal(list.space('f( )) a( () )'), ['f( ))', 'a( () )']) }) test('space() does not split on escaped spaces', () => { equal(list.space('a\\ b'), ['a\\ b']) }) test('space() works from variable', () => { let space = list.space equal(space('a b'), ['a', 'b']) }) test('comma() splits list by spaces', () => { equal(list.comma('a, b'), ['a', 'b']) }) test('comma() adds last empty', () => { equal(list.comma('a, b,'), ['a', 'b', '']) }) test('comma() checks quotes', () => { equal(list.comma('"a,b\\"", \'\''), ['"a,b\\""', "''"]) }) test('comma() checks functions', () => { equal(list.comma('f(,)), a(,(),)'), ['f(,))', 'a(,(),)']) }) test('comma() does not split on escaped commas', () => { equal(list.comma('a\\, b'), ['a\\, b']) }) test('comma() works from variable', () => { let comma = list.comma equal(comma('a, b'), ['a', 'b']) }) test.run() postcss-8.4.6/test/map.test.ts000077500000000000000000000417071417621533600163350ustar00rootroot00000000000000import { SourceMapConsumer, SourceMapGenerator } from 'source-map-js' import { removeSync, outputFileSync } from 'fs-extra' import { is, type, equal, match } from 'uvu/assert' import { join, resolve, parse } from 'path' import { existsSync } from 'fs' import { test } from 'uvu' import postcss, { SourceMap, Rule, Root } from '../lib/postcss.js' import PreviousMap from '../lib/previous-map.js' function consumer(map: SourceMap): any { return (SourceMapConsumer as any).fromSourceMap(map) } function read(result: { css: string }): any { let prev = new PreviousMap(result.css, {}) return prev.consumer() } let dir = join(__dirname, 'map-fixtures') let doubler = postcss((css: Root) => { css.walkDecls(decl => { decl.parent?.prepend(decl.clone()) }) }) let lighter = postcss((css: Root) => { css.walkDecls(decl => { decl.value = 'white' }) }) test.after.each(() => { if (existsSync(dir)) removeSync(dir) }) test('adds map field only on request', () => { type(postcss([() => {}]).process('a {}').map, 'undefined') }) test('return map generator', () => { let map = postcss([() => {}]).process('a {}', { map: { inline: false } }).map is(map instanceof SourceMapGenerator, true) }) test('generate right source map', () => { let css = 'a {\n color: black;\n }' let processor = postcss((root: Root) => { root.walkRules(rule => { rule.selector = 'strong' }) root.walkDecls(decl => { decl.parent?.prepend(decl.clone({ prop: 'background', value: 'black' })) }) }) let result = processor.process(css, { from: 'a.css', to: 'b.css', map: true }) let map = read(result) is(map.file, 'b.css') equal(map.originalPositionFor({ line: 1, column: 0 }), { source: 'a.css', line: 1, column: 0, name: null }) equal(map.originalPositionFor({ line: 1, column: 2 }), { source: 'a.css', line: 1, column: 0, name: null }) equal(map.originalPositionFor({ line: 2, column: 2 }), { source: 'a.css', line: 2, column: 2, name: null }) equal(map.originalPositionFor({ line: 3, column: 2 }), { source: 'a.css', line: 2, column: 2, name: null }) equal(map.originalPositionFor({ line: 3, column: 14 }), { source: 'a.css', line: 2, column: 14, name: null }) equal(map.originalPositionFor({ line: 4, column: 2 }), { source: 'a.css', line: 3, column: 2, name: null }) }) test('changes previous source map', () => { let css = 'a { color: black }' let doubled = doubler.process(css, { from: 'a.css', to: 'b.css', map: { inline: false } }) let lighted = lighter.process(doubled.css, { from: 'b.css', to: 'c.css', map: { prev: doubled.map } }) let map = consumer(lighted.map) equal(map.originalPositionFor({ line: 1, column: 18 }), { source: 'a.css', line: 1, column: 4, name: null }) }) test('adds source map annotation', () => { let css = 'a { }/*# sourceMappingURL=a.css.map */' let result = postcss([() => {}]).process(css, { from: 'a.css', to: 'b.css', map: { inline: false } }) is(result.css, 'a { }\n/*# sourceMappingURL=b.css.map */') }) test('misses source map annotation, if user ask', () => { let css = 'a { }' let result = postcss([() => {}]).process(css, { from: 'a.css', to: 'b.css', map: { annotation: false } }) is(result.css, css) }) test('misses source map annotation, if previous map missed it', () => { let css = 'a { }' let step1 = postcss([() => {}]).process(css, { from: 'a.css', to: 'b.css', map: { annotation: false } }) let step2 = postcss([() => {}]).process(step1.css, { from: 'b.css', to: 'c.css', map: { prev: step1.map } }) is(step2.css, css) }) test('uses user path in annotation, relative to options.to', () => { let result = postcss([() => {}]).process('a { }', { from: 'source/a.css', to: 'build/b.css', map: { annotation: 'maps/b.map' } }) is(result.css, 'a { }\n/*# sourceMappingURL=maps/b.map */') let map = consumer(result.map) is(map.file, join('..', 'b.css')) is( map.originalPositionFor({ line: 1, column: 0 }).source, '../../source/a.css' ) }) test('generates inline map', () => { let css = 'a { }' let inline = postcss([() => {}]).process(css, { from: 'a.css', to: 'b.css', map: { inline: true } }) type(inline.map, 'undefined') match(inline.css, /# sourceMappingURL=data:/) let separated = postcss([() => {}]).process(css, { from: 'a.css', to: 'b.css', map: { inline: false } }) let base64 = Buffer.from(separated.map.toString()).toString('base64') let end = inline.css.slice(-base64.length - 3) is(end, base64 + ' */') }) test('generates inline map by default', () => { let inline = postcss([() => {}]).process('a { }', { from: 'a.css', to: 'b.css', map: true }) match(inline.css, /# sourceMappingURL=data:/) }) test('generates separated map if previous map was not inlined', () => { let step1 = doubler.process('a { color: black }', { from: 'a.css', to: 'b.css', map: { inline: false } }) let step2 = lighter.process(step1.css, { from: 'b.css', to: 'c.css', map: { prev: step1.map } }) type(step2.map, 'object') }) test('generates separated map on annotation option', () => { let result = postcss([() => {}]).process('a { }', { from: 'a.css', to: 'b.css', map: { annotation: false } }) type(result.map, 'object') }) test('allows change map type', () => { let step1 = postcss([() => {}]).process('a { }', { from: 'a.css', to: 'b.css', map: { inline: true } }) let step2 = postcss([() => {}]).process(step1.css, { from: 'b.css', to: 'c.css', map: { inline: false } }) type(step2.map, 'object') match(step2.css, /# sourceMappingURL=c\.css\.map/) }) test('misses check files on requires', () => { let file = join(dir, 'a.css') let step1 = doubler.process('a { }', { from: 'a.css', to: file, map: { inline: false } }) outputFileSync(file + '.map', step1.map.toString()) let step2 = lighter.process(step1.css, { from: file, to: 'b.css', map: false }) type(step2.map, 'undefined') }) test('works in subdirs', () => { let result = doubler.process('a { }', { from: 'from/a.css', to: 'out/b.css', map: { inline: false } }) match(result.css, /sourceMappingURL=b.css.map/) let map = consumer(result.map) is(map.file, 'b.css') equal(map.sources, ['../from/a.css']) }) test('uses map from subdir', () => { let step1 = doubler.process('a { }', { from: 'a.css', to: 'out/b.css', map: { inline: false } }) let step2 = doubler.process(step1.css, { from: 'out/b.css', to: 'out/two/c.css', map: { prev: step1.map } }) let source = consumer(step2.map).originalPositionFor({ line: 1, column: 0 }).source is(source, '../../a.css') let step3 = doubler.process(step2.css, { from: 'c.css', to: 'd.css', map: { prev: step2.map } }) source = consumer(step3.map).originalPositionFor({ line: 1, column: 0 }).source is(source, '../../a.css') }) test('uses map from subdir if it inlined', () => { let step1 = doubler.process('a { }', { from: 'a.css', to: 'out/b.css', map: true }) let step2 = doubler.process(step1.css, { from: 'out/b.css', to: 'out/two/c.css', map: { inline: false } }) let source = consumer(step2.map).originalPositionFor({ line: 1, column: 0 }).source is(source, '../../a.css') }) test('uses map from subdir if it written as a file', () => { let step1 = doubler.process('a { }', { from: 'source/a.css', to: 'one/b.css', map: { annotation: 'maps/b.css.map', inline: false } }) let source = consumer(step1.map).originalPositionFor({ line: 1, column: 0 }).source is(source, '../../source/a.css') let file = join(dir, 'one', 'maps', 'b.css.map') outputFileSync(file, step1.map.toString()) let step2 = doubler.process(step1.css, { from: join(dir, 'one', 'b.css'), to: join(dir, 'two', 'c.css'), map: true }) source = consumer(step2.map).originalPositionFor({ line: 1, column: 0 }).source is(source, '../source/a.css') }) test('works with different types of maps', () => { let step1 = doubler.process('a { }', { from: 'a.css', to: 'b.css', map: { inline: false } }) let map = step1.map let maps = [map, consumer(map), map.toJSON(), map.toString()] for (let i of maps) { let step2 = doubler.process(step1.css, { from: 'b.css', to: 'c.css', map: { prev: i } }) let source = consumer(step2.map).originalPositionFor({ line: 1, column: 0 }).source is(source, 'a.css') } }) test('sets source content by default', () => { let result = doubler.process('a { }', { from: 'a.css', to: 'out/b.css', map: true }) is(read(result).sourceContentFor('../a.css'), 'a { }') }) test('misses source content on request', () => { let result = doubler.process('a { }', { from: 'a.css', to: 'out/b.css', map: { sourcesContent: false } }) is(read(result).sourceContentFor('../a.css'), null) }) test('misses source content if previous not have', () => { let step1 = doubler.process('a { }', { from: 'a.css', to: 'out/a.css', map: { sourcesContent: false } }) let file1 = postcss.parse(step1.css, { from: 'a.css', map: { prev: step1.map } }) let file2 = postcss.parse('b { }', { from: 'b.css', map: true }) if (file1.first) file2.append(file1.first.clone()) let step2 = file2.toResult({ to: 'c.css', map: true }) is(read(step2).sourceContentFor('b.css'), null) }) test('misses source content on request in multiple steps', () => { let step1 = doubler.process('a { }', { from: 'a.css', to: 'out/a.css', map: { sourcesContent: true } }) let file1 = postcss.parse(step1.css, { from: 'a.css', map: { prev: step1.map } }) let file2 = postcss.parse('b { }', { from: 'b.css', map: true }) if (file1.first) file2.append(file1.first.clone()) let step2 = file2.toResult({ to: 'c.css', map: { sourcesContent: false } }) let map = read(step2) is(map.sourceContentFor('b.css'), null) is(map.sourceContentFor('../a.css'), null) }) test('detects input file name from map', () => { let one = doubler.process('a { }', { to: 'a.css', map: true }) let two = doubler.process(one.css, { map: { prev: one.map } }) is(two.root.first?.source?.input.file, resolve('a.css')) }) test('works without file names', () => { let step1 = doubler.process('a { }', { map: true }) let step2 = doubler.process(step1.css) match(step2.css, /a { }\n\/\*/) }) test('supports UTF-8', () => { let step1 = doubler.process('a { }', { from: 'вход.css', to: 'шаг1.css', map: true }) let step2 = doubler.process(step1.css, { from: 'шаг1.css', to: 'выход.css' }) is(read(step2).file, 'выход.css') }) test('generates map for node created manually', () => { let contenter = postcss((css: Root) => { if (css.first && css.first.type === 'rule') { css.first.prepend({ selector: 'b' }) } }) let result = contenter.process('a:after{\n}', { map: true }) let map = read(result) equal(map.originalPositionFor({ line: 2, column: 5 }), { source: '', column: 0, line: 1, name: null }) }) test('uses input file name as output file name', () => { let result = doubler.process('a{}', { from: 'a.css', map: { inline: false } }) is(result.map.toJSON().file, 'a.css') }) test('uses to.css as default output name', () => { let result = doubler.process('a{}', { map: { inline: false } }) is(result.map.toJSON().file, 'to.css') }) test('supports annotation comment in any place', () => { let css = '/*# sourceMappingURL=a.css.map */a { }' let result = postcss([() => {}]).process(css, { from: 'a.css', to: 'b.css', map: { inline: false } }) is(result.css, 'a { }\n/*# sourceMappingURL=b.css.map */') }) test('does not update annotation on request', () => { let css = 'a { }/*# sourceMappingURL=a.css.map */' let result = postcss([() => {}]).process(css, { from: 'a.css', to: 'b.css', map: { annotation: false, inline: false } }) is(result.css, 'a { }/*# sourceMappingURL=a.css.map */') }) test('clears source map', () => { let css1 = postcss.root().toResult({ map: true }).css let css2 = postcss.root().toResult({ map: true }).css let root = postcss.root() root.append(css1) root.append(css2) let css = root.toResult({ map: true }).css is(css.match(/sourceMappingURL/g)?.length, 1) }) test('uses Windows line separation too', () => { let result = postcss([() => {}]).process('a {\r\n}', { map: true }) match(result.css, /a {\r\n}\r\n\/\*# sourceMappingURL=/) }) test('`map.from` should override the source map sources', () => { let result = postcss([() => {}]).process('a{}', { map: { inline: false, from: 'file:///dir/a.css' } }) equal(result.map.toJSON().sources, ['file:///dir/a.css']) }) test('preserves absolute urls in `to`', () => { let result = postcss([() => {}]).process('a{}', { from: '/dir/to/a.css', to: 'http://example.com/a.css', map: { inline: false } }) is(result.map.toJSON().file, 'http://example.com/a.css') }) test('preserves absolute urls in sources', () => { let result = postcss([() => {}]).process('a{}', { from: 'file:///dir/a.css', to: 'http://example.com/a.css', map: { inline: false } }) equal(result.map.toJSON().sources, ['file:///dir/a.css']) }) test('uses absolute path on request', () => { let result = postcss([() => {}]).process('a{}', { from: '/dir/a.css', to: '/dir/b.css', map: { inline: false, absolute: true } }) let root = '/' if (process.platform === 'win32') { root = '/' + parse(process.cwd()).root.replace(/\\/g, '/') } equal(result.map.toJSON().sources, [`file://${root}dir/a.css`]) }) test('preserves absolute urls in sources from previous map', () => { let result1 = postcss([() => {}]).process('a{}', { from: 'http://example.com/a.css', to: 'http://example.com/b.css', map: true }) let result2 = postcss([() => {}]).process(result1.css, { to: 'http://example.com/c.css', map: { inline: false } }) is(result2.root.source?.input.file, 'http://example.com/b.css') equal(result2.map.toJSON().sources, ['http://example.com/a.css']) }) test('allows dynamic annotations', () => { let result = postcss([() => {}]).process('a{}', { to: 'out.css', map: { annotation(to, root) { let rule = root.first as Rule return to + '-' + rule.selector + '.map' } } }) is(result.css, 'a{}\n/*# sourceMappingURL=out.css-a.map */') }) test('uses URLs in sources', () => { let result = postcss([() => {}]).process('a{}', { from: 'a b.css', to: 'dir/b.css', map: { inline: false } }) equal(result.map.toJSON().sources, ['../a%20b.css']) }) test('generates correct inline map with empty processor', () => { let result = postcss().process('a {} /*hello world*/', { map: true }) match(result.css, /a {} \/\*hello world\*\/\n\/\*# sourceMappingURL=/) }) test('generates correct inline map and multiple comments', () => { let css = 'a {}/*# sourceMappingURL=a.css.map */\n' + '/*# sourceMappingURL=b.css.map */\n' + 'b {}\n/*# sourceMappingURL=c.css.map */' let result = postcss().process(css, { map: true }) match(result.css, /a {}\nb {}\n\/\*# sourceMappingURL=/) }) test('generates correct sources with empty processor', () => { let result = postcss().process('a {} /*hello world*/', { from: 'a.css', to: 'b.css', map: { inline: false } }) equal(result.map.toJSON().sources, ['a.css']) }) test('generates map object with empty processor', () => { let result = postcss().process('a {} /*hello world*/', { from: 'a.css', to: 'b.css', map: true }) let map = read(result) equal(map.originalPositionFor({ line: 1, column: 0 }), { source: 'a.css', line: 1, column: 0, name: null }) }) test('supports previous map with empty processor', () => { let result1 = postcss().process('a{}', { from: '/a.css', to: '/b.css', map: { sourcesContent: true, inline: false } }) equal(result1.map.toJSON(), { version: 3, sources: ['a.css'], names: [], mappings: 'AAAA', file: 'b.css', sourcesContent: ['a{}'] }) let result2 = postcss().process(result1.css, { from: '/b.css', to: '/c.css', map: { prev: result1.map } }) equal(result2.map.toJSON().sources, ['a.css']) equal(result2.map.toJSON().sourcesContent, ['a{}']) }) test('supports previous inline map with empty processor', () => { let result1 = postcss().process('a{}', { from: '/a.css', to: '/b.css', map: true }) let result2 = postcss().process(result1.css, { from: '/b.css', to: '/c.css' }) let root3 = postcss.parse(result2.css, { from: '/c.css' }) match((root3.source?.input.origin(1, 0) as any).file, 'a.css') }) test.run() postcss-8.4.6/test/no-work-result.test.ts000066400000000000000000000053071417621533600204610ustar00rootroot00000000000000import { is, type, equal, throws, not, instance } from 'uvu/assert' import { test } from 'uvu' import mozilla from 'source-map-js' import { spy } from 'nanospy' import NoWorkResult from '../lib/no-work-result.js' import Processor from '../lib/processor.js' let processor = new Processor() test('contains AST on root access', () => { let result = new NoWorkResult(processor, 'a {}', { from: '/a.css' }) is(result.root.nodes.length, 1) }) test('has async() method', async () => { let noWorkResult = new NoWorkResult(processor, 'a {}', { from: '/a.css' }) let result1 = await noWorkResult let result2 = await noWorkResult equal(result1, result2) }) test('has sync() method', () => { let result = new NoWorkResult(processor, 'a {}', { from: '/a.css' }).sync() is(result.root.nodes.length, 1) }) test('throws error on sync()', () => { let noWorkResult = new NoWorkResult(processor, 'a {', { from: '/a.css' }) try { noWorkResult.root } catch {} throws(() => noWorkResult.sync(), 'AAA') }) test('returns cached root on second access', async () => { let result = new NoWorkResult(processor, 'a {}', { from: '/a.css' }) result.root is(result.root.nodes.length, 1) not.throws(() => result.sync()) }) test('contains css', () => { let result = new NoWorkResult(processor, 'a {}', { from: '/a.css' }) is(result.css, 'a {}') }) test('stringifies css', () => { let result = new NoWorkResult(processor, 'a {}', { from: '/a.css' }) equal(`${result}`, result.css) }) test('has content alias for css', () => { let result = new NoWorkResult(processor, 'a {}', { from: '/a.css' }) is(result.content, 'a {}') }) test('has map only if necessary', () => { let result1 = new NoWorkResult(processor, '', { from: '/a.css' }) type(result1.map, 'undefined') let result2 = new NoWorkResult(processor, '', { from: '/a.css' }) type(result2.map, 'undefined') let result3 = new NoWorkResult(processor, '', { from: '/a.css', map: { inline: false } }) is(result3.map instanceof mozilla.SourceMapGenerator, true) }) test('contains simple properties', () => { let result = new NoWorkResult(processor, 'a {}', { from: '/a.css', to: 'a.css' }) instance(result.processor, Processor) equal(result.opts, { from: '/a.css', to: 'a.css' }) equal(result.messages, []) equal(result.warnings(), []) }) test('executes on finally callback', () => { let cb = spy() return new NoWorkResult(processor, 'a {}', { from: '/a.css' }) .finally(cb) .then(() => { equal(cb.callCount, 1) }) }) test('prints its object type', () => { let result = new NoWorkResult(processor, 'a {}', { from: '/a.css' }) is(Object.prototype.toString.call(result), '[object NoWorkResult]') }) test.run() postcss-8.4.6/test/node.test.ts000077500000000000000000000300211417621533600164700ustar00rootroot00000000000000import { resolve } from 'path' import { test } from 'uvu' import { is, equal, type, not } from 'uvu/assert' import postcss, { AnyNode, AtRule, Root, Rule, CssSyntaxError, Declaration, parse, Result, Plugin, Document } from '../lib/postcss.js' function stringify(node: AnyNode, builder: (str: string) => void): void { if (node.type === 'rule') { builder(node.selector) } } test('error() generates custom error', () => { let file = resolve('a.css') let css = parse('a{}', { from: file }) let a = css.first as Rule let error = a.error('Test') is(error instanceof CssSyntaxError, true) is(error.message, file + ':1:1: Test') }) test('error() generates custom error for nodes without source', () => { let rule = new Rule({ selector: 'a' }) let error = rule.error('Test') is(error.message, ': Test') }) test('error() highlights index', () => { let root = parse('a { b: c }') let a = root.first as Rule let b = a.first as Declaration let error = b.error('Bad semicolon', { index: 1 }) is(error.showSourceCode(false), '> 1 | a { b: c }\n' + ' | ^') }) test('error() highlights word', () => { let root = parse('a { color: x red }') let a = root.first as Rule let color = a.first as Declaration let error = color.error('Wrong color', { word: 'x' }) is( error.showSourceCode(false), '> 1 | a { color: x red }\n' + ' | ^' ) }) test('error() highlights word in multiline string', () => { let root = parse('a { color: red\n x }') let a = root.first as Rule let color = a.first as Declaration let error = color.error('Wrong color', { word: 'x' }) is( error.showSourceCode(false), ' 1 | a { color: red\n' + '> 2 | x }\n' + ' | ^' ) }) test('warn() attaches a warning to the result object', async () => { let warning: any let warner: Plugin = { postcssPlugin: 'warner', Once(css, { result }) { warning = css.first?.warn(result, 'FIRST!') } } let result = await postcss([warner]).process('a{}', { from: undefined }) is(warning.type, 'warning') is(warning.text, 'FIRST!') is(warning.plugin, 'warner') equal(result.warnings(), [warning]) }) test('warn() accepts options', () => { let warner = (css: Root, result: Result): void => { css.first?.warn(result, 'FIRST!', { index: 1 }) } let result = postcss([warner]).process('a{}') is(result.warnings().length, 1) let warning = result.warnings()[0] as any is(warning.index, 1) }) test('remove() removes node from parent', () => { let rule = new Rule({ selector: 'a' }) let decl = new Declaration({ prop: 'color', value: 'black' }) rule.append(decl) decl.remove() is(rule.nodes.length, 0) type(decl.parent, 'undefined') }) test('replaceWith() inserts new node', () => { let rule = new Rule({ selector: 'a' }) rule.append({ prop: 'color', value: 'black' }) rule.append({ prop: 'width', value: '1px' }) rule.append({ prop: 'height', value: '1px' }) let node = new Declaration({ prop: 'min-width', value: '1px' }) let width = rule.nodes[1] let result = width.replaceWith(node) equal(result, width) is( rule.toString(), 'a {\n' + ' color: black;\n' + ' min-width: 1px;\n' + ' height: 1px\n' + '}' ) }) test('replaceWith() inserts new root', () => { let root = new Root() root.append(new AtRule({ name: 'import', params: '"a.css"' })) let a = new Root() a.append(new Rule({ selector: 'a' })) a.append(new Rule({ selector: 'b' })) root.first?.replaceWith(a) is(root.toString(), 'a {}\nb {}') }) test('replaceWith() replaces node', () => { let css = parse('a{one:1;two:2}') let a = css.first as Rule let one = a.first as Declaration let result = one.replaceWith({ prop: 'fix', value: 'fixed' }) is(result.prop, 'one') type(result.parent, 'undefined') is(css.toString(), 'a{fix:fixed;two:2}') }) test('replaceWith() can include itself', () => { let css = parse('a{one:1;two:2}') let a = css.first as Rule let one = a.first as Declaration let beforeDecl = { prop: 'fix1', value: 'fixedOne' } let afterDecl = { prop: 'fix2', value: 'fixedTwo' } one.replaceWith(beforeDecl, one, afterDecl) is(css.toString(), 'a{fix1:fixedOne;one:1;fix2:fixedTwo;two:2}') }) test('toString() accepts custom stringifier', () => { is(new Rule({ selector: 'a' }).toString(stringify), 'a') }) test('toString() accepts custom syntax', () => { is(new Rule({ selector: 'a' }).toString({ stringify }), 'a') }) test('assign() assigns to node', () => { let decl = new Declaration({ prop: 'white-space', value: 'overflow-wrap' }) is(decl.prop, 'white-space') is(decl.value, 'overflow-wrap') decl.assign({ prop: 'word-wrap', value: 'break-word' }) is(decl.prop, 'word-wrap') is(decl.value, 'break-word') }) test('clone() clones nodes', () => { let rule = new Rule({ selector: 'a' }) rule.append({ prop: 'color', value: '/**/black' }) let clone = rule.clone() type(clone.parent, 'undefined') equal(rule.first?.parent, rule) equal(clone.first?.parent, clone) clone.append({ prop: 'z-index', value: '1' }) is(rule.nodes.length, 1) }) test('clone() overrides properties', () => { let rule = new Rule({ selector: 'a' }) let clone = rule.clone({ selector: 'b' }) is(clone.selector, 'b') }) test('clone() keeps code style', () => { let css = parse('@page 1{a{color:black;}}') is(css.clone().toString(), '@page 1{a{color:black;}}') }) test('clone() works with null in raws', () => { let decl = new Declaration({ prop: 'color', value: 'black', // @ts-expect-error raws: { value: null } }) let clone = decl.clone() equal(Object.keys(clone.raws), ['value']) }) test('cloneBefore() clones and insert before current node', () => { let rule = new Rule({ selector: 'a', raws: { after: '' } }) rule.append({ prop: 'z-index', value: '1', raws: { before: '' } }) let result = rule.first?.cloneBefore({ value: '2' }) equal(result, rule.first) is(rule.toString(), 'a {z-index: 2;z-index: 1}') }) test('cloneAfter() clones and insert after current node', () => { let rule = new Rule({ selector: 'a', raws: { after: '' } }) rule.append({ prop: 'z-index', value: '1', raws: { before: '' } }) let result = rule.first?.cloneAfter({ value: '2' }) equal(result, rule.last) is(rule.toString(), 'a {z-index: 1;z-index: 2}') }) test('before() insert before current node', () => { let rule = new Rule({ selector: 'a', raws: { after: '' } }) rule.append({ prop: 'z-index', value: '1', raws: { before: '' } }) let result = rule.first?.before('color: black') equal(result, rule.last) is(rule.toString(), 'a {color: black;z-index: 1}') }) test('after() insert after current node', () => { let rule = new Rule({ selector: 'a', raws: { after: '' } }) rule.append({ prop: 'z-index', value: '1', raws: { before: '' } }) let result = rule.first?.after('color: black') equal(result, rule.first) is(rule.toString(), 'a {z-index: 1;color: black}') }) test('next() returns next node', () => { let css = parse('a{one:1;two:2}') let a = css.first as Rule equal(a.first?.next(), a.last) type(a.last?.next(), 'undefined') }) test('next() returns undefined on no parent', () => { let css = parse('') type(css.next(), 'undefined') }) test('prev() returns previous node', () => { let css = parse('a{one:1;two:2}') let a = css.first as Rule equal(a.last?.prev(), a.first) type(a.first?.prev(), 'undefined') }) test('prev() returns undefined on no parent', () => { let css = parse('') type(css.prev(), 'undefined') }) test('toJSON() cleans parents inside', () => { let rule = new Rule({ selector: 'a' }) rule.append({ prop: 'color', value: 'b' }) let json = rule.toJSON() as any type(json.parent, 'undefined') type(json.nodes[0].parent, 'undefined') is( JSON.stringify(rule), '{"raws":{},"selector":"a","type":"rule","nodes":[' + '{"raws":{},"prop":"color","value":"b","type":"decl"}' + '],"inputs":[]}' ) }) test('toJSON() converts custom properties', () => { let root = new Root() as any root._cache = [1] root._hack = { toJSON() { return 'hack' } } equal(root.toJSON(), { type: 'root', nodes: [], raws: {}, _hack: 'hack', inputs: [], _cache: [1] }) }) test('raw() has shortcut to stringifier', () => { let rule = new Rule({ selector: 'a' }) is(rule.raw('before'), '') }) test('root() returns root', () => { let css = parse('@page{a{color:black}}') let page = css.first as AtRule let a = page.first as Rule let color = a.first as Declaration equal(color.root(), css) }) test('root() returns parent of parents', () => { let rule = new Rule({ selector: 'a' }) rule.append({ prop: 'color', value: 'black' }) equal(rule.first?.root(), rule) }) test('root() returns self on root', () => { let rule = new Rule({ selector: 'a' }) equal(rule.root(), rule) }) test('root() returns root in document', () => { let css = new Document({ nodes: [parse('@page{a{color:black}}')] }) let root = css.first as Root let page = root.first as AtRule let a = page.first as Rule let color = a.first as Declaration equal(color.root(), root) }) test('root() on root in document returns same root', () => { let document = new Document() let root = new Root() document.append(root) equal(document.first?.root(), root) }) test('root() returns self on document', () => { let document = new Document() equal(document.root(), document) }) test('cleanRaws() cleans style recursivelly', () => { let css = parse('@page{a{color:black}}') css.cleanRaws() is(css.toString(), '@page {\n a {\n color: black\n }\n}') let page = css.first as AtRule let a = page.first as Rule let color = a.first as Declaration type(page.raws.before, 'undefined') type(color.raws.before, 'undefined') type(page.raws.between, 'undefined') type(color.raws.between, 'undefined') type(page.raws.after, 'undefined') }) test('cleanRaws() keeps between on request', () => { let css = parse('@page{a{color:black}}') css.cleanRaws(true) is(css.toString(), '@page{\n a{\n color:black\n }\n}') let page = css.first as AtRule let a = page.first as Rule let color = a.first as Declaration not.type(page.raws.between, 'undefined') not.type(color.raws.between, 'undefined') type(page.raws.before, 'undefined') type(color.raws.before, 'undefined') type(page.raws.after, 'undefined') }) test('positionInside() returns position when node starts mid-line', () => { let css = parse('a { one: X }') let a = css.first as Rule let one = a.first as Declaration equal(one.positionInside(6), { line: 1, column: 12 }) }) test('positionInside() returns position when before contains newline', () => { let css = parse('a {\n one: X}') let a = css.first as Rule let one = a.first as Declaration equal(one.positionInside(6), { line: 2, column: 9 }) }) test('positionInside() returns position when node contains newlines', () => { let css = parse('a {\n\tone: 1\n\t\tX\n3}') let a = css.first as Rule let one = a.first as Declaration equal(one.positionInside(10), { line: 3, column: 4 }) }) test('positionBy() returns position for word', () => { let css = parse('a { one: X }') let a = css.first as Rule let one = a.first as Declaration equal(one.positionBy({ word: 'one' }), { line: 1, column: 6 }) }) test('positionBy() returns position for index', () => { let css = parse('a { one: X }') let a = css.first as Rule let one = a.first as Declaration equal(one.positionBy({ index: 1 }), { line: 1, column: 7 }) }) test('rangeBy() returns range for word', () => { let css = parse('a { one: X }') let a = css.first as Rule let one = a.first as Declaration equal(one.rangeBy({ word: 'one' }), { start: { line: 1, column: 6 }, end: { line: 1, column: 9 } }) }) test('rangeBy() returns range for index and endIndex', () => { let css = parse('a { one: X }') let a = css.first as Rule let one = a.first as Declaration equal(one.rangeBy({ index: 1, endIndex: 3 }), { start: { line: 1, column: 7 }, end: { line: 1, column: 9 } }) }) test.run() postcss-8.4.6/test/parse.test.ts000077500000000000000000000133551417621533600166700ustar00rootroot00000000000000import { equal, is, match, not, throws } from 'uvu/assert' import { testPath, jsonify, eachTest } from 'postcss-parser-tests' import { readFileSync } from 'fs' import { resolve } from 'path' import { test } from 'uvu' import { Declaration, AtRule, parse, Root, Rule } from '../lib/postcss.js' test('works with file reads', () => { let stream = readFileSync(testPath('atrule-empty.css')) is(parse(stream) instanceof Root, true) }) eachTest((name, css, json) => { test(`parses ${name}`, () => { css = css.replace(/\r\n/g, '\n') let parsed = jsonify(parse(css, { from: name })) equal(JSON.parse(parsed), JSON.parse(json)) }) }) test('parses UTF-8 BOM', () => { let css = parse('\uFEFF@host { a {\f} }') equal(css.nodes[0].raws.before, '') }) test('should has true at hasBOM property', () => { let css = parse('\uFEFF@host { a {\f} }') is(css.first?.source?.input.hasBOM, true) }) test('should has false at hasBOM property', () => { let css = parse('@host { a {\f} }') is(css.first?.source?.input.hasBOM, false) }) test('saves source file', () => { let css = parse('a {}', { from: 'a.css' }) is(css.first?.source?.input.css, 'a {}') is(css.first?.source?.input.file, resolve('a.css')) is(css.first?.source?.input.from, resolve('a.css')) }) test('keeps absolute path in source', () => { let css = parse('a {}', { from: 'http://example.com/a.css' }) is(css.first?.source?.input.file, 'http://example.com/a.css') is(css.first?.source?.input.from, 'http://example.com/a.css') }) test('saves source file on previous map', () => { let root1 = parse('a {}', { map: { inline: true } }) let css = root1.toResult({ map: { inline: true } }).css let root2 = parse(css) is(root2.first?.source?.input.file, resolve('to.css')) }) test('sets unique ID for file without name', () => { let css1 = parse('a {}') let css2 = parse('a {}') match(String(css1.first?.source?.input.id), /^$/) match(String(css1.first?.source?.input.from), /^$/) is.not(css2.first?.source?.input.id, css1.first?.source?.input.id) }) test('sets parent node', () => { let file = testPath('atrule-rules.css') let css = parse(readFileSync(file)) let support = css.first as AtRule let keyframes = support.first as AtRule let from = keyframes.first as Rule let decl = from.first as Declaration is(decl.parent, from) is(from.parent, keyframes) is(support.parent, css) is(keyframes.parent, support) }) test('ignores wrong close bracket', () => { let root = parse('a { p: ()) }') let a = root.first as Rule let decl = a.first as Declaration is(decl.value, '())') }) test('parses unofficial --mixins', () => { let root = parse(':root { --x { color: pink; }; }') let rule = root.first as Rule let prop = rule.first as Rule is(prop.selector, '--x') }) test('ignores symbols before declaration', () => { let root = parse('a { :one: 1 }') let a = root.first as Rule let prop = a.first as Declaration is(prop.raws.before, ' :') }) test('parses double semicolon after rule', () => { is(parse('a { };;').toString(), 'a { };;') }) test('throws on unclosed blocks', () => { throws(() => { parse('\na {\n') }, /:2:1: Unclosed block/) }) test('throws on unnecessary block close', () => { throws(() => { parse('a {\n} }') }, /:2:3: Unexpected }/) }) test('throws on unclosed comment', () => { throws(() => { parse('\n/*\n ') }, /:2:1: Unclosed comment/) }) test('throws on unclosed quote', () => { throws(() => { parse('\n"\n\na ') }, /:2:1: Unclosed string/) }) test('throws on unclosed bracket', () => { throws(() => { parse(':not(one() { }') }, /:1:5: Unclosed bracket/) }) test('throws on property without value', () => { throws(() => { parse('a { b;}') }, /:1:5: Unknown word/) throws(() => { parse('a { b b }') }, /:1:5: Unknown word/) }) test('throws on nameless at-rule', () => { throws(() => { parse('@') }, /:1:1: At-rule without name/) }) test('throws on property without semicolon', () => { throws(() => { parse('a { one: filter(a:"") two: 2 }') }, /:1:21: Missed semicolon/) }) test('throws on double colon', () => { throws(() => { parse('a { one:: 1 }') }, /:1:9: Double colon/) }) test('do not throws on comment in between', () => { parse('a { b/* c */: 1 }') }) test('throws on two words in between', () => { throws(() => { parse('a { b c: 1 }') }, /:1:7: Unknown word/) }) test('throws on just colon', () => { throws(() => { parse(':') }, /:1:1: Unknown word/) throws(() => { parse(' : ') }, /:1:2: Unknown word/) }) test('does not suggest different parsers for CSS', () => { let error: any try { parse('a { one:: 1 }', { from: 'app.css' }) } catch (e) { error = e } not.match(error.message, /postcss-less|postcss-scss/) }) test('suggests postcss-scss for SCSS sources', () => { throws(() => { parse('a { #{var}: 1 }', { from: 'app.scss' }) }, /postcss-scss/) }) test('suggests postcss-sass for Sass sources', () => { throws(() => { parse('a\n #{var}: 1', { from: 'app.sass' }) }, /postcss-sass/) }) test('suggests postcss-less for Less sources', () => { throws(() => { parse('.@{my-selector} { }', { from: 'app.less' }) }, /postcss-less/) }) test('should give the correct column of missed semicolon with !important', () => { let error: any try { parse('a { \n color: red !important\n background-color: black;\n}') } catch (e) { error = e } match(error.message, /2:26: Missed semicolon/) }) test('should give the correct column of missed semicolon without !important', () => { let error: any try { parse('a { \n color: red\n background-color: black;\n}') } catch (e) { error = e } match(error.message, /2:15: Missed semicolon/) }) test.run() postcss-8.4.6/test/postcss.test.ts000077500000000000000000000111111417621533600172400ustar00rootroot00000000000000import { is, type, equal, match, throws } from 'uvu/assert' import { spyOn, restoreAll } from 'nanospy' import { test } from 'uvu' import postcss, { Root, PluginCreator } from '../lib/postcss.js' import Processor from '../lib/processor.js' test.after.each(() => { restoreAll() }) test('creates plugins list', () => { let processor = postcss() is(processor instanceof Processor, true) equal(processor.plugins, []) }) test('saves plugins list', () => { let a = (): void => {} let b = (): void => {} equal(postcss(a, b).plugins, [a, b]) }) test('saves plugins list as array', () => { let a = (): void => {} let b = (): void => {} equal(postcss([a, b]).plugins, [a, b]) }) test('takes plugin from other processor', () => { let a = (): void => {} let b = (): void => {} let c = (): void => {} let other = postcss([a, b]) equal(postcss([other, c]).plugins, [a, b, c]) }) test('takes plugins from a a plugin returning a processor', () => { let a = (): void => {} let b = (): void => {} let c = (): void => {} let other = postcss([a, b]) let meta = (() => other) as PluginCreator meta.postcss = true equal(postcss([other, c]).plugins, [a, b, c]) }) test('contains parser', () => { is(postcss.parse('').type, 'root') }) test('contains stringifier', () => { type(postcss.stringify, 'function') }) test('allows to build own CSS', () => { let root = postcss.root({ raws: { after: '\n' } }) let comment = postcss.comment({ text: 'Example' }) let media = postcss.atRule({ name: 'media', params: 'screen' }) let rule = postcss.rule({ selector: 'a' }) let decl = postcss.decl({ prop: 'color', value: 'black' }) root.append(comment) rule.append(decl) media.append(rule) root.append(media) is( root.toString(), '/* Example */\n' + '@media screen {\n' + ' a {\n' + ' color: black\n' + ' }\n' + '}\n' ) }) test('allows to build own CSS with Document', () => { let document = postcss.document() let root = postcss.root({ raws: { after: '\n' } }) let comment = postcss.comment({ text: 'Example' }) let media = postcss.atRule({ name: 'media', params: 'screen' }) let rule = postcss.rule({ selector: 'a' }) let decl = postcss.decl({ prop: 'color', value: 'black' }) root.append(comment) rule.append(decl) media.append(rule) root.append(media) document.append(root) is( document.toString(), '/* Example */\n' + '@media screen {\n' + ' a {\n' + ' color: black\n' + ' }\n' + '}\n' ) }) test('contains list module', () => { equal(postcss.list.space('a b'), ['a', 'b']) }) test('works with null', () => { throws(() => { // @ts-expect-error postcss([() => {}]).process(null).css }, /PostCSS received null instead of CSS string/) }) test('has deprecated method to creat plugins', () => { let warn = spyOn(console, 'warn', () => {}) let plugin = (postcss as any).plugin('test', (filter?: string) => { return (root: Root) => { root.walkDecls(filter ?? 'two', i => { i.remove() }) } }) equal(warn.callCount, 1) match(warn.calls[0][0], /postcss\.plugin was deprecated/) let func1: any = postcss(plugin).plugins[0] is(func1.postcssPlugin, 'test') match(func1.postcssVersion, /\d+.\d+.\d+/) let func2: any = postcss(plugin()).plugins[0] equal(func2.postcssPlugin, func1.postcssPlugin) equal(func2.postcssVersion, func1.postcssVersion) let result1 = postcss(plugin('one')).process('a{ one: 1; two: 2 }') is(result1.css, 'a{ two: 2 }') let result2 = postcss(plugin).process('a{ one: 1; two: 2 }') is(result2.css, 'a{ one: 1 }') }) test('creates a shortcut to process css', async () => { let warn = spyOn(console, 'warn', () => {}) let plugin = (postcss as any).plugin('test', (str?: string) => { return (root: Root) => { root.walkDecls(i => { i.value = str ?? 'bar' }) } }) equal(warn.callCount, 1) let result1 = plugin.process('a{value:foo}') is(result1.css, 'a{value:bar}') let result2 = plugin.process('a{value:foo}', {}, 'baz') is(result2.css, 'a{value:baz}') let result = await plugin.process('a{value:foo}', { from: 'a' }, 'baz') equal(result.opts, { from: 'a' }) is(result.css, 'a{value:baz}') }) test('does not call plugin constructor', () => { let warn = spyOn(console, 'warn', () => {}) let calls = 0 let plugin = (postcss as any).plugin('test', () => { calls += 1 return () => {} }) is(calls, 0) equal(warn.callCount, 1) postcss(plugin).process('a{}') is(calls, 1) postcss(plugin()).process('a{}') is(calls, 2) }) test.run() postcss-8.4.6/test/previous-map.test.ts000077500000000000000000000201671417621533600202040ustar00rootroot00000000000000import { removeSync, outputFileSync } from 'fs-extra' import { SourceMapConsumer } from 'source-map-js' import { pathToFileURL } from 'url' import { existsSync } from 'fs' import { join } from 'path' import { test } from 'uvu' import { is, type, equal, match, throws, not } from 'uvu/assert' import { parse } from '../lib/postcss.js' let dir = join(__dirname, 'prevmap-fixtures') let mapObj = { version: 3, file: null, sources: [], names: [], mappings: '' } let map = JSON.stringify(mapObj) test.after.each(() => { if (existsSync(dir)) removeSync(dir) }) test('misses property if no map', () => { type(parse('a{}').source?.input.map, 'undefined') }) test('creates property if map present', () => { let root = parse('a{}', { map: { prev: map } }) is(root.source?.input.map.text, map) }) test('returns consumer', () => { let obj = parse('a{}', { map: { prev: map } }).source?.input.map.consumer() is(obj instanceof SourceMapConsumer, true) }) test('sets annotation property', () => { let mapOpts = { map: { prev: map } } let root1 = parse('a{}', mapOpts) type(root1.source?.input.map.annotation, 'undefined') let root2 = parse('a{}/*# sourceMappingURL=a.css.map */', mapOpts) is(root2.source?.input.map.annotation, 'a.css.map') }) test('checks previous sources content', () => { let map2: any = { version: 3, file: 'b', sources: ['a'], names: [], mappings: '' } let opts = { map: { prev: map2 } } is(parse('a{}', opts).source?.input.map.withContent(), false) map2.sourcesContent = ['a{}'] is(parse('a{}', opts).source?.input.map.withContent(), true) }) test('decodes base64 maps', () => { let b64 = Buffer.from(map).toString('base64') let css = 'a{}\n' + `/*# sourceMappingURL=data:application/json;base64,${b64} */` is(parse(css).source?.input.map.text, map) }) test('decodes base64 UTF-8 maps', () => { let b64 = Buffer.from(map).toString('base64') let css = 'a{}\n/*# sourceMappingURL=data:application/json;' + 'charset=utf-8;base64,' + b64 + ' */' is(parse(css).source?.input.map.text, map) }) test('accepts different name for base64 maps with UTF-8 encoding', () => { let b64 = Buffer.from(map).toString('base64') let css = 'a{}\n/*# sourceMappingURL=data:application/json;' + 'charset=utf8;base64,' + b64 + ' */' is(parse(css).source?.input.map.text, map) }) test('decodes URI maps', () => { let uri = 'data:application/json,' + decodeURI(map) let css = `a{}\n/*# sourceMappingURL=${uri} */` is(parse(css).source?.input.map.text, map) }) test('decodes URI UTF-8 maps', () => { let uri = decodeURI(map) let css = 'a{}\n/*# sourceMappingURL=data:application/json;' + 'charset=utf-8,' + uri + ' */' is(parse(css).source?.input.map.text, map) }) test('accepts different name for URI maps with UTF-8 encoding', () => { let uri = decodeURI(map) let css = 'a{}\n/*# sourceMappingURL=data:application/json;' + 'charset=utf8,' + uri + ' */' is(parse(css).source?.input.map.text, map) }) test('removes map on request', () => { let uri = 'data:application/json,' + decodeURI(map) let css = `a{}\n/*# sourceMappingURL=${uri} */` let input = parse(css, { map: { prev: false } }).source?.input type(input?.map, 'undefined') }) test('raises on unknown inline encoding', () => { let css = 'a { }\n/*# sourceMappingURL=data:application/json;' + 'md5,68b329da9893e34099c7d8ad5cb9c940*/' throws(() => { parse(css) }, 'Unsupported source map encoding md5') }) test('raises on unknown map format', () => { throws(() => { // @ts-expect-error parse('a{}', { map: { prev: 1 } }) }, 'Unsupported previous source map format: 1') }) test('reads map from annotation', () => { let file = join(dir, 'a.map') outputFileSync(file, map) let root = parse('a{}\n/*# sourceMappingURL=a.map */', { from: file }) is(root.source?.input.map.text, map) is(root.source?.input.map.root, dir) }) test('reads only the last map from annotation', () => { let file = join(dir, 'c.map') outputFileSync(file, map) let root = parse( 'a{}' + '\n/*# sourceMappingURL=a.map */' + '\n/*# sourceMappingURL=b.map */' + '\n/*# sourceMappingURL=c.map */', { from: file } ) is(root.source?.input.map.text, map) is(root.source?.input.map.root, dir) }) test('sets unique name for inline map', () => { let map2 = { version: 3, sources: ['a'], names: [], mappings: '' } let opts = { map: { prev: map2 } } let file1 = parse('a{}', opts).source?.input.map.file let file2 = parse('a{}', opts).source?.input.map.file match(String(file1), /^$/) is.not(file1, file2) }) test('accepts an empty mappings string', () => { not.throws(() => { let emptyMap = { version: 3, sources: [], names: [], mappings: '' } parse('body{}', { map: { prev: emptyMap } }) }) }) test('accepts a function', () => { let css = 'body{}\n/*# sourceMappingURL=a.map */' let file = join(dir, 'previous-sourcemap-function.map') outputFileSync(file, map) let opts = { map: { prev: () => file } } let root = parse(css, opts) is(root.source?.input.map.text, map) is(root.source?.input.map.annotation, 'a.map') }) test('calls function with opts.from', () => { let css = 'body{}\n/*# sourceMappingURL=a.map */' let file = join(dir, 'previous-sourcemap-function.map') outputFileSync(file, map) parse(css, { from: 'a.css', map: { prev: from => { is(from, 'a.css') return file } } }) }) test('raises when function returns invalid path', () => { let css = 'body{}\n/*# sourceMappingURL=a.map */' let fakeMap = Number.MAX_SAFE_INTEGER.toString() + '.map' let fakePath = join(dir, fakeMap) let opts = { map: { prev: () => fakePath } } throws(() => { parse(css, opts) }, 'Unable to load previous source map: ' + fakePath) }) test('uses source map path as a root', () => { let from = join(dir, 'a.css') outputFileSync( join(dir, 'maps', 'a.map'), JSON.stringify({ version: 3, file: 'test.css', sources: ['../../test.scss'], mappings: 'AACA,CAAC,CACG,GAAG,CAAC;EACF,KAAK,EAAE,GAAI;CACZ', names: [] }) ) let root = parse( '* div {\n color: red;\n }\n/*# sourceMappingURL=maps/a.map */', { from } ) equal(root.source?.input.origin(1, 3, 1, 5), { url: pathToFileURL(join(dir, '..', 'test.scss')).href, file: join(dir, '..', 'test.scss'), line: 3, column: 4, endLine: 3, endColumn: 7 }) }) test('uses current file path for source map', () => { let root = parse('a{b:1}', { from: join(__dirname, 'dir', 'subdir', 'a.css'), map: { prev: { version: 3, mappings: 'AAAA,CAAC;EAAC,CAAC,EAAC,CAAC', sources: ['../test.scss'], names: [], file: 'test.css' } } }) equal(root.source?.input.origin(1, 1), { url: pathToFileURL(join(__dirname, 'dir', 'test.scss')).href, file: join(__dirname, 'dir', 'test.scss'), line: 1, column: 1, endLine: undefined, endColumn: undefined }) }) test('works with non-file sources', () => { let root = parse('a{b:1}', { from: join(__dirname, 'dir', 'subdir', 'a.css'), map: { prev: { version: 3, mappings: 'AAAA,CAAC;EAAC,CAAC,EAAC,CAAC', sources: ['http://example.com/test.scss'], names: [], file: 'test.css' } } }) equal(root.source?.input.origin(1, 1), { url: 'http://example.com/test.scss', line: 1, column: 1, endLine: undefined, endColumn: undefined }) }) test('works with index map', () => { let root = parse('body {\nwidth:100%;\n}', { from: join(__dirname, 'a.css'), map: { prev: { version: 3, sections: [ { offset: { line: 0, column: 0 }, map: { version: 3, mappings: 'AAAA;AACA;AACA;', sources: ['b.css'], sourcesContent: ['body {\nwidth:100%;\n}'] } } ] } } }) is((root as any).source.input.origin(1, 1).file, join(__dirname, 'b.css')) }) test.run() postcss-8.4.6/test/processor.test.ts000077500000000000000000000360221417621533600175710ustar00rootroot00000000000000import { is, type, equal, match, throws, not, instance } from 'uvu/assert' import { resolve as pathResolve } from 'path' import { spyOn, restoreAll } from 'nanospy' import { delay } from 'nanodelay' import { test } from 'uvu' import postcss, { Plugin, Result, Node, Root, parse, PluginCreator, Document, Parser, Stringifier } from '../lib/postcss.js' import CssSyntaxError from '../lib/css-syntax-error.js' import LazyResult from '../lib/lazy-result.js' import NoWorkResult from '../lib/no-work-result.js' import Processor from '../lib/processor.js' import Rule from '../lib/rule.js' test.after.each(() => { restoreAll() }) function prs(): Root { return new Root({ raws: { after: 'ok' } }) } function str(node: Node, builder: (s: string) => void): void { builder(`${node.raws.after}!`) } async function catchError(cb: () => Promise): Promise { try { await cb() } catch (e) { if (e instanceof Error) return e } throw new Error('Error was not thrown') } let beforeFix = new Processor([ (root: Root) => { root.walkRules(rule => { if (!rule.selector.match(/::(before|after)/)) return if (!rule.some(i => i.type === 'decl' && i.prop === 'content')) { rule.prepend({ prop: 'content', value: '""' }) } }) } ]) test('adds new plugins', () => { let a = (): void => {} let processor = new Processor() processor.use(a) equal(processor.plugins, [a]) }) test('adds new plugin by object', () => { let a = (): void => {} let processor = new Processor() processor.use({ postcss: a }) equal(processor.plugins, [a]) }) test('adds new plugin by object-function', () => { let a = (): void => {} let obj: any = () => {} obj.postcss = a let processor = new Processor() processor.use(obj) equal(processor.plugins, [a]) }) test('adds new processors of another postcss instance', () => { let a = (): void => {} let processor = new Processor() let other = new Processor([a]) processor.use(other) equal(processor.plugins, [a]) }) test('adds new processors from object', () => { let a = (): void => {} let processor = new Processor() let other = new Processor([a]) processor.use({ postcss: other }) equal(processor.plugins, [a]) }) test('returns itself', () => { let a = (): void => {} let b = (): void => {} let processor = new Processor() equal(processor.use(a).use(b).plugins, [a, b]) }) test('throws on wrong format', () => { let pr = new Processor() throws(() => { // @ts-expect-error pr.use(1) }, /1 is not a PostCSS plugin/) }) test('processes CSS', () => { let result = beforeFix.process('a::before{top:0}') is(result.css, 'a::before{content:"";top:0}') }) test('processes parsed AST', () => { let root = parse('a::before{top:0}') let result = beforeFix.process(root) is(result.css, 'a::before{content:"";top:0}') }) test('processes previous result', () => { let result = new Processor([() => {}]).process('a::before{top:0}') result = beforeFix.process(result) is(result.css, 'a::before{content:"";top:0}') }) test('takes maps from previous result', () => { let one = new Processor([() => {}]).process('a{}', { from: 'a.css', to: 'b.css', map: { inline: false } }) let two = new Processor([() => {}]).process(one, { to: 'c.css' }) equal(two.map.toJSON().sources, ['a.css']) }) test('inlines maps from previous result', () => { let one = new Processor([() => {}]).process('a{}', { from: 'a.css', to: 'b.css', map: { inline: false } }) let two = new Processor([() => {}]).process(one, { to: 'c.css', map: { inline: true } }) type(two.map, 'undefined') }) test('throws with file name', () => { let error: CssSyntaxError | undefined try { new Processor([() => {}]).process('a {', { from: 'a.css' }).css } catch (e) { if (e instanceof CssSyntaxError) { error = e } else { throw e } } is(error?.file, pathResolve('a.css')) match(String(error?.message), /a.css:1:1: Unclosed block$/) }) test('allows to replace Root', () => { let processor = new Processor([ (css, result) => { result.root = new Root() } ]) is(processor.process('a {}').css, '') }) test('returns LazyResult object', () => { let result = new Processor([() => {}]).process('a{}') is(result instanceof LazyResult, true) is(result.css, 'a{}') is(result.toString(), 'a{}') }) test('calls all plugins once', async () => { let calls = '' let a = (): void => { calls += 'a' } let b = (): void => { calls += 'b' } let result = new Processor([a, b]).process('', { from: undefined }) result.css result.map result.root await result is(calls, 'ab') }) test('parses, converts and stringifies CSS', () => { is( typeof new Processor([ (css: Root) => { equal(css instanceof Root, true) } ]).process('a {}').css, 'string' ) }) test('send result to plugins', () => { let processor = new Processor([() => {}]) processor .use((css, result) => { is(result instanceof Result, true) equal(result.processor, processor) equal(result.opts, { map: true }) equal(result.root, css) }) .process('a {}', { map: true, from: undefined }) }) test('accepts source map from PostCSS', () => { let one = new Processor([() => {}]).process('a{}', { from: 'a.css', to: 'b.css', map: { inline: false } }) let two = new Processor([() => {}]).process(one.css, { from: 'b.css', to: 'c.css', map: { prev: one.map, inline: false } }) equal(two.map.toJSON().sources, ['a.css']) }) test('supports async plugins', async () => { let starts = 0 let finish = 0 let async1 = (css: Root): Promise => new Promise(resolve => { starts += 1 setTimeout(() => { equal(starts, 1) css.append('a {}') finish += 1 resolve() }, 1) }) let async2 = (css: Root): Promise => new Promise(resolve => { equal(starts, 1) equal(finish, 1) starts += 1 setTimeout(() => { css.append('b {}') finish += 1 resolve() }, 1) }) let r = await new Processor([async1, async2]).process('', { from: 'a' }) is(starts, 2) is(finish, 2) is(r.css, 'a {}b {}') }) test('works async without plugins', async () => { let r = await new Processor([() => {}]).process('a {}', { from: 'a' }) is(r.css, 'a {}') }) test('runs async plugin only once', async () => { let calls = 0 let async = (): Promise => { return new Promise(resolve => { setTimeout(() => { calls += 1 resolve() }, 1) }) } let result = new Processor([async]).process('a {}', { from: undefined }) result.then(() => {}) await result await result is(calls, 1) }) test('supports async errors', async () => { let error = new Error('Async') let async = (): Promise => { return new Promise((resolve, reject) => { reject(error) }) } let result = new Processor([async]).process('', { from: undefined }) let err1 = await catchError(async () => await result) equal(err1, error) let err2: Error | undefined result.catch(catched => { err2 = catched }) await delay(10) equal(err2, error) }) test('supports sync errors in async mode', async () => { let error = new Error('Async') let async = (): void => { throw error } let err = await catchError(() => new Processor([async]).process('', { from: undefined }) ) equal(err, error) }) test('throws parse error in async', async () => { let err = await catchError(() => new Processor([() => {}]).process('a{', { from: undefined }) ) is(err.message, ':1:1: Unclosed block') }) test('throws error on sync method to async plugin', () => { let async = (): Promise => { return new Promise(resolve => { resolve() }) } throws(() => { new Processor([async]).process('a{}').css }, /async/) }) test('throws a sync call in async running', async () => { let async = (): Promise => new Promise(resolve => setTimeout(resolve, 1)) let processor = new Processor([async]).process('a{}', { from: 'a.css' }) processor.async() throws(() => { processor.sync() }, /then/) }) test('remembers errors', async () => { let calls = 0 let plugin: Plugin = { postcssPlugin: 'plugin', Once() { calls += 1 throw new Error('test') } } let processing = postcss([plugin]).process('a{}', { from: undefined }) throws(() => { processing.css }, 'test') throws(() => { processing.css }, 'test') throws(() => { processing.root }, 'test') let asyncError: any try { await processing } catch (e) { asyncError = e } is(asyncError.message, 'test') is(calls, 1) }) test('checks plugin compatibility', () => { let error = spyOn(console, 'error', () => {}) let warn = spyOn(console, 'warn', () => {}) let plugin = (postcss as any).plugin('test', () => { return () => { throw new Error('Er') } }) equal(warn.callCount, 1) let func = plugin() func.postcssVersion = '2.1.5' function processBy(version: string): void { let processor = new Processor([func]) processor.version = version processor.process('a{}').css } throws(() => { processBy('1.0.0') }, 'Er') equal(error.callCount, 1) equal(error.calls, [ [ 'Unknown error from PostCSS plugin. ' + 'Your current PostCSS version is 1.0.0, but test uses 2.1.5. ' + 'Perhaps this is the source of the error below.' ] ]) throws(() => { processBy('3.0.0') }, 'Er') equal(error.callCount, 2) throws(() => { processBy('2.0.0') }, 'Er') equal(error.callCount, 3) throws(() => { processBy('2.1.0') }, 'Er') equal(error.callCount, 3) }) test('sets last plugin to result', async () => { let plugin1 = (css: Root, result: Result): void => { equal(result.lastPlugin, plugin1) } let plugin2 = (css: Root, result: Result): void => { equal(result.lastPlugin, plugin2) } let processor = new Processor([plugin1, plugin2]) let result = await processor.process('a{}', { from: undefined }) equal(result.lastPlugin, plugin2) }) test('uses custom parsers', async () => { let processor = new Processor([]) let result = await processor.process('a{}', { parser: prs, from: undefined }) is(result.css, 'ok') }) test('uses custom parsers from object', async () => { let processor = new Processor([]) let syntax = { parse: prs, stringify: str } let result = await processor.process('a{}', { parser: syntax, from: 'a' }) equal(result.css, 'ok') }) test('uses custom stringifier', async () => { let processor = new Processor([]) let result = await processor.process('a{}', { stringifier: str, from: 'a' }) is(result.css, '!') }) test('uses custom stringifier from object', async () => { let processor = new Processor([]) let syntax = { parse: prs, stringify: str } let result = await processor.process('', { stringifier: syntax, from: 'a' }) is(result.css, '!') }) test('uses custom stringifier with source maps', async () => { let processor = new Processor([]) let result = await processor.process('a{}', { map: true, stringifier: str, from: undefined }) match(result.css, /!\n\/\*# sourceMap/) }) test('uses custom syntax', async () => { let processor = new Processor([() => {}]) let result = await processor.process('a{}', { syntax: { parse: prs, stringify: str }, from: undefined }) is(result.css, 'ok!') }) test('contains PostCSS version', () => { match(new Processor().version, /\d+.\d+.\d+/) }) test('throws on syntax as plugin', () => { let processor = new Processor([() => {}]) throws(() => { processor.use({ // @ts-expect-error parse() {} }) }, /syntax/) }) test('warns about missed from', async () => { let warn = spyOn(console, 'warn', () => {}) let processor = new Processor([() => {}]) processor.process('a{}').css equal(warn.calls, []) await processor.process('a{}') equal(warn.calls, [ [ 'Without `from` option PostCSS could generate wrong source map ' + 'and will not find Browserslist config. Set it to CSS file path ' + 'or to `undefined` to prevent this warning.' ] ]) }) test('returns NoWorkResult object', async () => { let result = new Processor().process('a{}') instance(result, NoWorkResult) }) test('without plugins parses CSS only on root access', async () => { let noWorkResult = new Processor().process('a{}') let result = await noWorkResult // @ts-expect-error type(noWorkResult._root, 'undefined') is(result.root.nodes.length, 1) // @ts-expect-error not.type(noWorkResult._root, 'undefined') is(noWorkResult.root.nodes.length, 1) }) test('catches error with empty processor', async () => { let noWorkResult = new Processor().process('a {') try { noWorkResult.root } catch {} let err = await catchError(async () => await noWorkResult) noWorkResult.catch(e => { instance(e, CssSyntaxError) }) instance(err, CssSyntaxError) }) test('throws an error on root access on no plugins mode', () => { throws(() => { postcss().process('// invalid', { from: 'a' }).root }, 'Unknown word') }) test('supports plugins returning processors', () => { let warn = spyOn(console, 'warn', () => {}) let a = (): void => {} let processor = new Processor() let other: any = (postcss as any).plugin('test', () => { return new Processor([a]) }) equal(warn.callCount, 1) processor.use(other) equal(processor.plugins, [a]) }) test('supports plugin creators returning processors', () => { let a = (): void => {} let processor = new Processor() let other = (() => { return new Processor([a]) }) as PluginCreator other.postcss = true processor.use(other) equal(processor.plugins, [a]) }) test('uses custom syntax for document', async () => { let customParser: Parser = () => { return new Document({ nodes: [ new Root({ raws: { codeBefore: '\n\n\n\n' }, nodes: [new Rule({ selector: 'b' })] }) ] }) } let customStringifier: Stringifier = (doc, builder) => { if (doc.type === 'document') { for (let root of doc.nodes) { if (root.raws.codeBefore) { builder(root.raws.codeBefore, root) } builder(root.toString(), root) if (root.raws.codeAfter) { builder(root.raws.codeAfter, root) } } } } let processor = new Processor([() => {}]) let result = await processor.process('a{}', { syntax: { parse: customParser, stringify: customStringifier }, from: undefined }) is( result.css, '\n\n\n\n' ) }) test.run() postcss-8.4.6/test/result.test.ts000077500000000000000000000031351417621533600170670ustar00rootroot00000000000000import { test } from 'uvu' import { is, equal } from 'uvu/assert' import postcss, { Warning, Result, Root, Plugin } from '../lib/postcss.js' import Processor from '../lib/processor.js' let processor = new Processor() let root = new Root() test('stringifies', () => { let result = new Result(processor, root, {}) result.css = 'a{}' is(`${result}`, result.css) }) test('adds warning', () => { let warning let plugin: Plugin = { postcssPlugin: 'test-plugin', Once(css, { result }) { warning = result.warn('test', { node: css.first }) } } let result = postcss([plugin]).process('a{}').sync() equal( warning, new Warning('test', { plugin: 'test-plugin', node: result.root.first }) ) equal(result.messages, [warning]) }) test('allows to override plugin', () => { let plugin: Plugin = { postcssPlugin: 'test-plugin', Once(css, { result }) { result.warn('test', { plugin: 'test-plugin#one' }) } } let result = postcss([plugin]).process('a{}').sync() is(result.messages[0].plugin, 'test-plugin#one') }) test('allows Root', () => { let css = postcss.parse('a{}') let result = new Result(processor, css, {}) result.warn('TT', { node: css.first }) is(result.messages[0].toString(), ':1:1: TT') }) test('returns only warnings', () => { let result = new Result(processor, root, {}) result.messages = [ { type: 'warning', text: 'a' }, { type: 'custom' }, { type: 'warning', text: 'b' } ] equal(result.warnings(), [ { type: 'warning', text: 'a' }, { type: 'warning', text: 'b' } ]) }) test.run() postcss-8.4.6/test/root.test.ts000077500000000000000000000034441417621533600165370ustar00rootroot00000000000000import { test } from 'uvu' import { is, type, match } from 'uvu/assert' import { Result, parse } from '../lib/postcss.js' test('prepend() fixes spaces on insert before first', () => { let css = parse('a {} b {}') css.prepend({ selector: 'em' }) is(css.toString(), 'em {} a {} b {}') }) test('prepend() fixes spaces on multiple inserts before first', () => { let css = parse('a {} b {}') css.prepend({ selector: 'em' }, { selector: 'strong' }) is(css.toString(), 'em {} strong {} a {} b {}') }) test('prepend() uses default spaces on only first', () => { let css = parse('a {}') css.prepend({ selector: 'em' }) is(css.toString(), 'em {}\na {}') }) test('append() sets new line between rules in multiline files', () => { let a = parse('a {}\n\na {}\n') let b = parse('b {}\n') is(a.append(b).toString(), 'a {}\n\na {}\n\nb {}\n') }) test('insertAfter() does not use before of first rule', () => { let css = parse('a{} b{}') css.insertAfter(0, { selector: '.a' }) css.insertAfter(2, { selector: '.b' }) type(css.nodes[1].raws.before, 'undefined') is(css.nodes[3].raws.before, ' ') is(css.toString(), 'a{} .a{} b{} .b{}') }) test('fixes spaces on removing first rule', () => { let css = parse('a{}\nb{}\n') if (!css.first) throw new Error('No nodes were parsed') css.first.remove() is(css.toString(), 'b{}\n') }) test('keeps spaces on moving root', () => { let css1 = parse('a{}\nb{}\n') let css2 = parse('') css2.append(css1) is(css2.toString(), 'a{}\nb{}') let css3 = parse('\n') css3.append(css2.nodes) is(css3.toString(), 'a{}\nb{}\n') }) test('generates result with map', () => { let root = parse('a {}') let result = root.toResult({ map: true }) is(result instanceof Result, true) match(result.css, /a {}\n\/\*# sourceMappingURL=/) }) test.run() postcss-8.4.6/test/rule.test.ts000077500000000000000000000043221417621533600165170ustar00rootroot00000000000000import { test } from 'uvu' import { is, equal } from 'uvu/assert' import { Rule, parse } from '../lib/postcss.js' test('initializes with properties', () => { let rule = new Rule({ selector: 'a' }) is(rule.selector, 'a') }) test('returns array in selectors', () => { let rule = new Rule({ selector: 'a,b' }) equal(rule.selectors, ['a', 'b']) }) test('trims selectors', () => { let rule = new Rule({ selector: '.a\n, .b , .c' }) equal(rule.selectors, ['.a', '.b', '.c']) }) test('is smart about selectors commas', () => { let rule = new Rule({ selector: "[foo='a, b'], a:-moz-any(:focus, [href*=','])" }) equal(rule.selectors, ["[foo='a, b']", "a:-moz-any(:focus, [href*=','])"]) }) test('receive array in selectors', () => { let rule = new Rule({ selector: 'i, b' }) rule.selectors = ['em', 'strong'] is(rule.selector, 'em, strong') }) test('saves separator in selectors', () => { let rule = new Rule({ selector: 'i,\nb' }) rule.selectors = ['em', 'strong'] is(rule.selector, 'em,\nstrong') }) test('uses between to detect separator in selectors', () => { let rule = new Rule({ selector: 'b', raws: { between: '' } }) rule.selectors = ['b', 'strong'] is(rule.selector, 'b,strong') }) test('uses space in separator be default in selectors', () => { let rule = new Rule({ selector: 'b' }) rule.selectors = ['b', 'strong'] is(rule.selector, 'b, strong') }) test('selectors works in constructor', () => { let rule = new Rule({ selectors: ['a', 'b'] }) is(rule.selector, 'a, b') }) test('inserts default spaces', () => { let rule = new Rule({ selector: 'a' }) is(rule.toString(), 'a {}') rule.append({ prop: 'color', value: 'black' }) is(rule.toString(), 'a {\n color: black\n}') }) test('clones spaces from another rule', () => { let root = parse('b{\n }') let rule = new Rule({ selector: 'em' }) root.append(rule) is(root.toString(), 'b{\n }\nem{\n }') }) test('uses different spaces for empty rules', () => { let root = parse('a{}\nb{\n a:1\n}') let rule = new Rule({ selector: 'em' }) root.append(rule) is(root.toString(), 'a{}\nb{\n a:1\n}\nem{}') rule.append({ prop: 'top', value: '0' }) is(root.toString(), 'a{}\nb{\n a:1\n}\nem{\n top:0\n}') }) test.run() postcss-8.4.6/test/stringifier.test.js000077500000000000000000000164271417621533600200740ustar00rootroot00000000000000let { test } = require('uvu') let { is } = require('uvu/assert') let { Declaration, AtRule, Node, Root, Rule, Document, parse } = require('../lib/postcss') let Stringifier = require('../lib/stringifier') let str test.before.each(() => { str = new Stringifier() }) test('creates trimmed/raw property', () => { let b = new Node({ one: 'trim' }) b.raws.one = { value: 'trim', raw: 'raw' } is(str.rawValue(b, 'one'), 'raw') b.one = 'trim1' is(str.rawValue(b, 'one'), 'trim1') }) test('works without rawValue magic', () => { let b = new Node() b.one = '1' is(b.one, '1') is(str.rawValue(b, 'one'), '1') }) test('uses node raw', () => { let rule = new Rule({ selector: 'a', raws: { between: '\n' } }) is(str.raw(rule, 'between', 'beforeOpen'), '\n') }) test('hacks before for nodes without parent', () => { let rule = new Rule({ selector: 'a' }) is(str.raw(rule, 'before'), '') }) test('hacks before for first node', () => { let root = new Root() root.append(new Rule({ selector: 'a' })) is(str.raw(root.first, 'before'), '') }) test('hacks before for first decl', () => { let decl = new Declaration({ prop: 'color', value: 'black' }) is(str.raw(decl, 'before'), '') let rule = new Rule({ selector: 'a' }) rule.append(decl) is(str.raw(decl, 'before'), '\n ') }) test('detects after raw', () => { let root = new Root() root.append({ selector: 'a', raws: { after: ' ' } }) root.first.append({ prop: 'color', value: 'black' }) root.append({ selector: 'a' }) is(str.raw(root.last, 'after'), ' ') }) test('uses defaults without parent', () => { let rule = new Rule({ selector: 'a' }) is(str.raw(rule, 'between', 'beforeOpen'), ' ') }) test('uses defaults for unique node', () => { let root = new Root() root.append(new Rule({ selector: 'a' })) is(str.raw(root.first, 'between', 'beforeOpen'), ' ') }) test('clones raw from first node', () => { let root = new Root() root.append(new Rule({ selector: 'a', raws: { between: '' } })) root.append(new Rule({ selector: 'b' })) is(str.raw(root.last, 'between', 'beforeOpen'), '') }) test('indents by default', () => { let root = new Root() root.append(new AtRule({ name: 'page' })) root.first.append(new Rule({ selector: 'a' })) root.first.first.append({ prop: 'color', value: 'black' }) is( root.toString(), '@page {\n' + ' a {\n' + ' color: black\n' + ' }\n' + '}' ) }) test('clones style', () => { let compress = parse('@page{ a{ } }') let spaces = parse('@page {\n a {\n }\n}') compress.first.first.append({ prop: 'color', value: 'black' }) is(compress.toString(), '@page{ a{ color: black } }') spaces.first.first.append({ prop: 'color', value: 'black' }) is(spaces.toString(), '@page {\n a {\n color: black\n }\n}') }) test('clones indent', () => { let root = parse('a{\n}') root.first.append({ text: 'a' }) root.first.append({ text: 'b', raws: { before: '\n\n ' } }) is(root.toString(), 'a{\n\n /* a */\n\n /* b */\n}') }) test('clones declaration before for comment', () => { let root = parse('a{\n}') root.first.append({ text: 'a' }) root.first.append({ prop: 'a', value: '1', raws: { before: '\n\n ' } }) is(root.toString(), 'a{\n\n /* a */\n\n a: 1\n}') }) test('clones indent by types', () => { let css = parse('a {\n *color: black\n}\n\nb {\n}') css.append(new Rule({ selector: 'em' })) css.last.append({ prop: 'z-index', value: '1' }) is(css.last.first.raw('before'), '\n ') }) test('ignores non-space symbols in indent cloning', () => { let css = parse('a {\n color: black\n}\n\nb {\n}') css.append(new Rule({ selector: 'em' })) css.last.append({ prop: 'z-index', value: '1' }) is(css.last.raw('before'), '\n\n') is(css.last.first.raw('before'), '\n ') }) test('clones indent by before and after', () => { let css = parse('@page{\n\n a{\n color: black}}') css.first.append(new Rule({ selector: 'b' })) css.first.last.append({ prop: 'z-index', value: '1' }) is(css.first.last.raw('before'), '\n\n ') is(css.first.last.raw('after'), '') }) test('clones semicolon only from rules with children', () => { let css = parse('a{}b{one:1;}') is(str.raw(css.first, 'semicolon'), true) }) test('clones only spaces in before', () => { let css = parse('a{*one:1}') css.first.append({ prop: 'two', value: '2' }) css.append({ name: 'keyframes', params: 'a' }) css.last.append({ selector: 'from' }) is(css.toString(), 'a{*one:1;two:2}\n@keyframes a{\nfrom{}}') }) test('clones only spaces in between', () => { let css = parse('a{one/**/:1}') css.first.append({ prop: 'two', value: '2' }) is(css.toString(), 'a{one/**/:1;two:2}') }) test('uses optional raws.indent', () => { let rule = new Rule({ selector: 'a', raws: { indent: ' ' } }) rule.append({ prop: 'color', value: 'black' }) is(rule.toString(), 'a {\n color: black\n}') }) test('handles nested roots', () => { let root = new Root() let subRoot = new Root() subRoot.append(new AtRule({ name: 'foo' })) root.append(subRoot) is(root.toString(), '@foo') }) test('handles root', () => { let root = new Root() root.append(new AtRule({ name: 'foo' })) let s = root.toString() is(s, '@foo') }) test('handles root with after', () => { let root = new Root({ raws: { after: ' ' } }) root.append(new AtRule({ name: 'foo' })) let s = root.toString() is(s, '@foo ') }) test('pass nodes to document', () => { let root = new Root() let document = new Document({ nodes: [root] }) is(document.toString(), '') }) test('handles document with one root', () => { let root = new Root() root.append(new AtRule({ name: 'foo' })) let document = new Document() document.append(root) let s = document.toString() is(s, '@foo') }) test('handles document with one root and after raw', () => { let document = new Document() let root = new Root({ raws: { after: ' ' } }) root.append(new AtRule({ name: 'foo' })) document.append(root) let s = document.toString() is(s, '@foo ') }) test('handles document with one root and before and after', () => { let document = new Document() let root = new Root({ raws: { after: 'AFTER' } }) root.append(new AtRule({ name: 'foo' })) document.append(root) let s = document.toString() is(s, '@fooAFTER') }) test('handles document with three roots without raws', () => { let root1 = new Root() root1.append(new AtRule({ name: 'foo' })) let root2 = new Root() root2.append(new Rule({ selector: 'a' })) let root3 = new Root() root3.append(new Declaration({ prop: 'color', value: 'black' })) let document = new Document() document.append(root1) document.append(root2) document.append(root3) let s = document.toString() is(s, '@fooa {}color: black') }) test('handles document with three roots, with before and after raws', () => { let root1 = new Root({ raws: { after: 'AFTER_ONE' } }) root1.append(new Rule({ selector: 'a.one' })) let root2 = new Root({ raws: { after: 'AFTER_TWO' } }) root2.append(new Rule({ selector: 'a.two' })) let root3 = new Root({ raws: { after: 'AFTER_THREE' } }) root3.append(new Rule({ selector: 'a.three' })) let document = new Document() document.append(root1) document.append(root2) document.append(root3) let s = document.toString() is(s, 'a.one {}AFTER_ONEa.two {}AFTER_TWOa.three {}AFTER_THREE') }) test.run() postcss-8.4.6/test/stringify.test.ts000077500000000000000000000006161417621533600175700ustar00rootroot00000000000000import { eachTest } from 'postcss-parser-tests' import { test } from 'uvu' import { is } from 'uvu/assert' import { stringify, parse } from '../lib/postcss.js' eachTest((name, css) => { if (name === 'bom.css') return test(`stringifies ${name}`, () => { let root = parse(css) let result = '' stringify(root, i => { result += i }) is(result, css) }) }) test.run() postcss-8.4.6/test/tokenize.test.js000077500000000000000000000150101417621533600173620ustar00rootroot00000000000000let { test } = require('uvu') let { equal, throws, is } = require('uvu/assert') let tokenizer = require('../lib/tokenize') let { Input } = require('../lib/postcss') function tokenize(css, opts) { let processor = tokenizer(new Input(css), opts) let tokens = [] while (!processor.endOfFile()) { tokens.push(processor.nextToken()) } return tokens } function run(css, tokens, opts) { equal(tokenize(css, opts), tokens) } test('tokenizes empty file', () => { run('', []) }) test('tokenizes space', () => { run('\r\n \f\t', [['space', '\r\n \f\t']]) }) test('tokenizes word', () => { run('ab', [['word', 'ab', 0, 1]]) }) test('splits word by !', () => { run('aa!bb', [ ['word', 'aa', 0, 1], ['word', '!bb', 2, 4] ]) }) test('changes lines in spaces', () => { run('a \n b', [ ['word', 'a', 0, 0], ['space', ' \n '], ['word', 'b', 4, 4] ]) }) test('tokenizes control chars', () => { run('{:;}', [ ['{', '{', 0], [':', ':', 1], [';', ';', 2], ['}', '}', 3] ]) }) test('escapes control symbols', () => { run('\\(\\{\\"\\@\\\\""', [ ['word', '\\(', 0, 1], ['word', '\\{', 2, 3], ['word', '\\"', 4, 5], ['word', '\\@', 6, 7], ['word', '\\\\', 8, 9], ['string', '""', 10, 11] ]) }) test('escapes backslash', () => { run('\\\\\\\\{', [ ['word', '\\\\\\\\', 0, 3], ['{', '{', 4] ]) }) test('tokenizes simple brackets', () => { run('(ab)', [['brackets', '(ab)', 0, 3]]) }) test('tokenizes square brackets', () => { run('a[bc]', [ ['word', 'a', 0, 0], ['[', '[', 1], ['word', 'bc', 2, 3], [']', ']', 4] ]) }) test('tokenizes complicated brackets', () => { run('(())("")(/**/)(\\\\)(\n)(', [ ['(', '(', 0], ['brackets', '()', 1, 2], [')', ')', 3], ['(', '(', 4], ['string', '""', 5, 6], [')', ')', 7], ['(', '(', 8], ['comment', '/**/', 9, 12], [')', ')', 13], ['(', '(', 14], ['word', '\\\\', 15, 16], [')', ')', 17], ['(', '(', 18], ['space', '\n'], [')', ')', 20], ['(', '(', 21] ]) }) test('tokenizes string', () => { run('\'"\'"\\""', [ ['string', "'\"'", 0, 2], ['string', '"\\""', 3, 6] ]) }) test('tokenizes escaped string', () => { run('"\\\\"', [['string', '"\\\\"', 0, 3]]) }) test('changes lines in strings', () => { run('"\n\n""\n\n"', [ ['string', '"\n\n"', 0, 3], ['string', '"\n\n"', 4, 7] ]) }) test('tokenizes at-word', () => { run('@word ', [ ['at-word', '@word', 0, 4], ['space', ' '] ]) }) test('tokenizes at-word end', () => { run('@one{@two()@three""@four;', [ ['at-word', '@one', 0, 3], ['{', '{', 4], ['at-word', '@two', 5, 8], ['brackets', '()', 9, 10], ['at-word', '@three', 11, 16], ['string', '""', 17, 18], ['at-word', '@four', 19, 23], [';', ';', 24] ]) }) test('tokenizes urls', () => { run('url(/*\\))', [ ['word', 'url', 0, 2], ['brackets', '(/*\\))', 3, 8] ]) }) test('tokenizes quoted urls', () => { run('url(")")', [ ['word', 'url', 0, 2], ['(', '(', 3], ['string', '")"', 4, 6], [')', ')', 7] ]) }) test('tokenizes at-symbol', () => { run('@', [['at-word', '@', 0, 0]]) }) test('tokenizes comment', () => { run('/* a\nb */', [['comment', '/* a\nb */', 0, 8]]) }) test('changes lines in comments', () => { run('a/* \n */b', [ ['word', 'a', 0, 0], ['comment', '/* \n */', 1, 7], ['word', 'b', 8, 8] ]) }) test('supports line feed', () => { run('a\fb', [ ['word', 'a', 0, 0], ['space', '\f'], ['word', 'b', 2, 2] ]) }) test('supports carriage return', () => { run('a\rb\r\nc', [ ['word', 'a', 0, 0], ['space', '\r'], ['word', 'b', 2, 2], ['space', '\r\n'], ['word', 'c', 5, 5] ]) }) test('tokenizes CSS', () => { let css = 'a {\n' + ' content: "a";\n' + ' width: calc(1px;)\n' + ' }\n' + '/* small screen */\n' + '@media screen {}' run(css, [ ['word', 'a', 0, 0], ['space', ' '], ['{', '{', 2], ['space', '\n '], ['word', 'content', 6, 12], [':', ':', 13], ['space', ' '], ['string', '"a"', 15, 17], [';', ';', 18], ['space', '\n '], ['word', 'width', 22, 26], [':', ':', 27], ['space', ' '], ['word', 'calc', 29, 32], ['brackets', '(1px;)', 33, 38], ['space', '\n '], ['}', '}', 42], ['space', '\n'], ['comment', '/* small screen */', 44, 61], ['space', '\n'], ['at-word', '@media', 63, 68], ['space', ' '], ['word', 'screen', 70, 75], ['space', ' '], ['{', '{', 77], ['}', '}', 78] ]) }) test('throws error on unclosed string', () => { throws(() => { tokenize(' "') }, /:1:2: Unclosed string/) }) test('throws error on unclosed comment', () => { throws(() => { tokenize(' /*') }, /:1:2: Unclosed comment/) }) test('throws error on unclosed url', () => { throws(() => { tokenize('url(') }, /:1:4: Unclosed bracket/) }) test('ignores unclosing string on request', () => { run( ' "', [ ['space', ' '], ['string', '"', 1, 2] ], { ignoreErrors: true } ) }) test('ignores unclosing comment on request', () => { run( ' /*', [ ['space', ' '], ['comment', '/*', 1, 3] ], { ignoreErrors: true } ) }) test('ignores unclosing function on request', () => { run( 'url(', [ ['word', 'url', 0, 2], ['brackets', '(', 3, 3] ], { ignoreErrors: true } ) }) test('tokenizes hexadecimal escape', () => { run('\\0a \\09 \\z ', [ ['word', '\\0a ', 0, 3], ['word', '\\09 ', 4, 7], ['word', '\\z', 8, 9], ['space', ' '] ]) }) test('ignore unclosed per token request', () => { function token(css, opts) { let processor = tokenizer(new Input(css), opts) let tokens = [] while (!processor.endOfFile()) { tokens.push(processor.nextToken({ ignoreUnclosed: true })) } return tokens } let css = "How's it going (" let tokens = token(css, {}) let expected = [ ['word', 'How', 0, 2], ['string', "'s", 3, 4], ['space', ' '], ['word', 'it', 6, 7], ['space', ' '], ['word', 'going', 9, 13], ['space', ' '], ['(', '(', 15] ] equal(tokens, expected) }) test('provides correct position', () => { let css = 'Three tokens' let processor = tokenizer(new Input(css)) is(processor.position(), 0) processor.nextToken() is(processor.position(), 5) processor.nextToken() is(processor.position(), 6) processor.nextToken() is(processor.position(), 12) processor.nextToken() is(processor.position(), 12) }) test.run() postcss-8.4.6/test/types.ts000066400000000000000000000011511417621533600157300ustar00rootroot00000000000000import postcss, { Result, PluginCreator } from '../lib/postcss.js' const plugin: PluginCreator = prop => { return { postcssPlugin: 'remover', Declaration: (decl, { result, Comment }) => { if (decl.prop === prop) { decl.warn(result, `${decl.prop} found`) decl.replaceWith(new Comment({ text: `${decl.prop} removed` })) } } } } plugin.postcss = true const processResult: Promise | Result = postcss([ plugin ]).process('h1{color: black;}', { from: undefined }) processResult.then((result: Result) => { console.log(result.css) }) export default plugin postcss-8.4.6/test/version.js000077500000000000000000000003621417621533600162450ustar00rootroot00000000000000#!/usr/bin/env node let Processor = require('../lib/processor') let pkg = require('../package') let instance = new Processor() if (pkg.version !== instance.version) { throw new Error('Version in Processor is not equal to package.json') } postcss-8.4.6/test/visitor.test.ts000077500000000000000000001115251417621533600172530ustar00rootroot00000000000000import { resolve, basename } from 'path' import { delay } from 'nanodelay' import { test } from 'uvu' import { is, type, equal, throws } from 'uvu/assert' import postcss, { Container, Root, Rule, Declaration, Plugin, PluginCreator, AnyNode, Helpers } from '../lib/postcss.js' function hasAlready(parent: Container | undefined, selector: string): boolean { if (typeof parent === 'undefined') return false return parent.nodes.some(i => { return i.type === 'rule' && i.selectors.includes(selector) }) } function addIndex(array: any[][]): any[][] { return array.map((i, index) => { return [index, ...i] }) } function buildVisitor(): [[string, string][], Plugin] { let visits: [string, string][] = [] let visitor: Plugin = { postcssPlugin: 'visitor', Document(i) { visits.push(['Document', `${i.nodes.length}`]) }, Once(i) { visits.push(['Once', `${i.nodes.length}`]) }, Root(i) { visits.push(['Root', `${i.nodes.length}`]) }, RootExit(i) { visits.push(['RootExit', `${i.nodes.length}`]) }, AtRule(i) { visits.push(['AtRule', i.name]) }, AtRuleExit(i) { visits.push(['AtRuleExit', i.name]) }, Rule(i) { visits.push(['Rule', i.selector]) }, RuleExit(i) { visits.push(['RuleExit', i.selector]) }, Declaration(i) { visits.push(['Declaration', i.prop + ': ' + i.value]) }, DeclarationExit(i) { visits.push(['DeclarationExit', i.prop + ': ' + i.value]) }, Comment(i) { visits.push(['Comment', i.text]) }, CommentExit(i) { visits.push(['CommentExit', i.text]) }, OnceExit(i) { visits.push(['OnceExit', `${i.nodes.length}`]) }, DocumentExit(i) { visits.push(['DocumentExit', `${i.nodes.length}`]) } } return [visits, visitor] } let replaceColorGreenClassic: Plugin = { postcssPlugin: 'replace-color', Once(root) { root.walkDecls('color', decl => { decl.value = 'green' }) } } let willChangeVisitor: Plugin = { postcssPlugin: 'will-change', Declaration(node) { if (node.prop !== 'will-change') return if (!node.parent) return let already = node.parent.some(i => { return i.type === 'decl' && i.prop === 'backface-visibility' }) if (already) return node.cloneBefore({ prop: 'backface-visibility', value: 'hidden' }) } } let addPropsVisitor: Plugin = { postcssPlugin: 'add-props', Declaration(node) { if (node.prop !== 'will-change') return node.root().walkDecls('color', decl => { if (!decl.parent) return let already = decl.parent.some(i => { return i.type === 'decl' && i.prop === 'will-change' }) if (already) return decl.cloneBefore({ prop: 'will-change', value: 'transform' }) }) } } let replaceAllButRedToGreen: Plugin = { postcssPlugin: 'replace-not-red-to-green', Declaration(node) { if (node.prop === 'color' && node.value !== 'red') { node.value = 'green' } } } let replaceGreenToRed: Plugin = { postcssPlugin: 'replace-green-to-red', Declaration(node) { if (node.prop === 'color' && node.value === 'green') { node.value = 'red' } } } let replacePrintToMobile: Plugin = { postcssPlugin: 'replace-to-mobile', AtRule(node) { if (node.params === '(print)') { node.params = '(mobile)' } } } let replaceScreenToPrint: Plugin = { postcssPlugin: 'replace-to-print', AtRule(node) { if (node.params === '(screen)') { node.params = '(print)' } } } let postcssFocus: Plugin = { postcssPlugin: 'postcss-focus', Rule(rule) { if (rule.selector.includes(':hover')) { let focuses: string[] = [] rule.selectors.forEach(selector => { if (selector.includes(':hover')) { let replaced = selector.replace(/:hover/g, ':focus') if (!hasAlready(rule.parent, replaced)) { focuses.push(replaced) } } }) if (focuses.length) { rule.selectors = rule.selectors.concat(focuses) } } } } let hidden: Plugin = { postcssPlugin: 'hidden', Declaration(decl) { if (decl.prop !== 'display') return let value = decl.value let rule = decl.parent as Rule if (value.includes('disappear')) { decl.cloneBefore({ prop: 'display', value: 'none !important' }) decl.cloneBefore({ prop: 'visibility', value: 'hidden' }) decl.remove() } if (value.includes('hidden')) { let ruleSelectors = rule.selectors.map(i => { return `${i}.focusable:active,${i}.focusable:focus` }) let newRule = rule.cloneAfter({ selectors: ruleSelectors }).removeAll() newRule.append('display: table; position: static; clear: both;') decl.cloneBefore({ prop: 'position', value: 'absolute' }) decl.cloneBefore({ prop: 'width', value: '1px' }) decl.cloneBefore({ prop: 'height', value: '1px' }) decl.cloneBefore({ prop: 'margin', value: '-1px' }) decl.cloneBefore({ prop: 'padding', value: '0' }) decl.cloneBefore({ prop: 'border', value: '0' }) decl.cloneBefore({ prop: 'overflow', value: 'hidden' }) decl.cloneBefore({ prop: 'clip', value: 'rect(0 0 0 0)' }) decl.remove() } if (value.includes('invisible')) { decl.cloneBefore({ prop: 'visibility', value: 'hidden' }) decl.remove() } } } function createPlugin(creator: () => Plugin): PluginCreator { let result = creator as PluginCreator result.postcss = true return result } let postcssAlias = createPlugin(() => { let aliases: any = {} return { postcssPlugin: 'postcss-alias', Once(root) { root.walkAtRules('alias', rule => { rule.walkDecls(decl => { aliases[decl.prop] = decl.value }) rule.remove() }) }, Declaration(decl) { let value = aliases[decl.prop] if (value !== undefined) { decl.replaceWith({ prop: value, value: decl.value, important: decl.important }) } } } }) test('works classic plugin replace-color', async () => { let { css } = await postcss([replaceColorGreenClassic]).process( '.a{ color: red; } ' + '.b{ will-change: transform; }', { from: 'a.css' } ) is(css, '.a{ color: green; } ' + '.b{ will-change: transform; }') }) test('works visitor plugin will-change', async () => { let { css } = postcss([willChangeVisitor]).process( '.foo { will-change: transform; }', { from: 'a.css' } ) is(css, '.foo { backface-visibility: hidden; will-change: transform; }') }) test('works visitor plugin add-prop', async () => { let { css } = await postcss([addPropsVisitor]).process( '.a{ color: red; } .b{ will-change: transform; }', { from: 'a.css' } ) is( css, '.a{ will-change: transform; color: red; } ' + '.b{ will-change: transform; }' ) }) test('works visitor plugin add-prop in document with single root', async () => { let document = postcss.document({ nodes: [postcss.parse('.a{ color: red; } .b{ will-change: transform; }')] }) let { css } = await postcss([addPropsVisitor]).process(document, { from: 'a.css' }) is( css, '.a{ will-change: transform; color: red; } ' + '.b{ will-change: transform; }' ) }) test('works visitor plugin add-prop in document with two roots', async () => { let document = postcss.document({ nodes: [ postcss.parse('.a{ color: red; }'), postcss.parse('.b{ will-change: transform; }') ] }) let { css } = await postcss([addPropsVisitor]).process(document, { from: 'a.css' }) is(css, '.a{ color: red; }' + '.b{ will-change: transform; }') }) test('works with at-rule params', () => { let { css } = postcss([replacePrintToMobile, replaceScreenToPrint]).process( '@media (screen) {}', { from: 'a.css' } ) is(css, '@media (mobile) {}') }) test('wraps node to proxies', () => { let proxy: any let root: Root | undefined postcss({ postcssPlugin: 'proxyCatcher', Once(node) { root = node }, Rule(node) { proxy = node } }).process('a{color:black}', { from: 'a.css' }).css if (!root) throw new Error('Nodes were not catched') let rule = root.first as Rule equal(proxy.proxyOf, rule) equal(proxy.root().proxyOf, rule.root()) equal(proxy.nodes[0].proxyOf, rule.first) equal(proxy.first.proxyOf, rule.first) type(proxy.unknown, 'undefined') is( proxy.some((decl: Declaration) => decl.prop === 'color'), true ) is( proxy.every((decl: Declaration) => decl.prop === 'color'), true ) let props: string[] = [] proxy.walkDecls((decl: Declaration) => props.push(decl.prop)) equal(props, ['color']) }) const cssThree = '.a{ color: red; } .b{ will-change: transform; }' const expectedThree = '.a{ ' + 'backface-visibility: hidden; ' + 'will-change: transform; ' + 'color: green; ' + '} ' + '.b{ backface-visibility: hidden; will-change: transform; }' test('work of three plug-ins; sequence 1', async () => { let { css } = await postcss([ replaceColorGreenClassic, willChangeVisitor, addPropsVisitor ]).process(cssThree, { from: 'a.css' }) is(css, expectedThree) }) test('work of three plug-ins; sequence 2', async () => { let { css } = await postcss([ addPropsVisitor, replaceColorGreenClassic, willChangeVisitor ]).process(cssThree, { from: 'a.css' }) is(css, expectedThree) }) const cssThreeDocument = postcss.document({ nodes: [ postcss.parse('.a{ color: red; }'), postcss.parse('.b{ will-change: transform; }') ] }) const expectedThreeDocument = '.a{ color: green; }' + '.b{ backface-visibility: hidden; will-change: transform; }' test('work of three plug-ins in a document; sequence 1', async () => { let { css } = await postcss([ replaceColorGreenClassic, willChangeVisitor, addPropsVisitor ]).process(cssThreeDocument, { from: 'a.css' }) is(css, expectedThreeDocument) }) test('work of three plug-ins in a document; sequence 2', async () => { let { css } = await postcss([ addPropsVisitor, replaceColorGreenClassic, willChangeVisitor ]).process(cssThreeDocument, { from: 'a.css' }) is(css, expectedThreeDocument) }) const cssThroughProps = '.a{color: yellow;}' const expectedThroughProps = '.a{color: red;}' test('change in node values through props; sequence 1', async () => { let { css } = await postcss([ replaceGreenToRed, replaceAllButRedToGreen ]).process(cssThroughProps, { from: 'a.css' }) is(css, expectedThroughProps) }) test('change in node values through props; sequence 2', async () => { let { css } = await postcss([ replaceAllButRedToGreen, replaceGreenToRed ]).process(cssThroughProps, { from: 'a.css' }) is(css, expectedThroughProps) }) test('works visitor plugin postcss-focus', async () => { let input = '*:focus { outline: 0; }.button:hover { background: red; }' let expected = '*:focus { outline: 0; }' + '.button:hover, .button:focus { background: red; }' let { css } = await postcss([postcssFocus]).process(input, { from: 'a.css' }) is(css, expected) }) test('works visitor plugin hidden', async () => { let input = 'h2{' + 'display: hidden;' + '}' let expected = 'h2{' + 'position: absolute;' + 'width: 1px;' + 'height: 1px;' + 'margin: -1px;' + 'padding: 0;' + 'border: 0;' + 'overflow: hidden;' + 'clip: rect(0 0 0 0);' + '}' + 'h2.focusable:active,' + 'h2.focusable:focus{' + 'display: table;' + 'position: static;' + 'clear: both;' + '}' let { css } = await postcss([hidden]).process(input, { from: 'a.css' }) is(css, expected) }) let cssFocusHidden = '*:focus { outline: 0; }' + '.button:hover { background: red; }' + 'h2:hover{' + 'display: hidden;' + '}' let expectedFocusHidden = '*:focus { outline: 0; }' + '.button:hover, .button:focus { background: red; }' + 'h2:hover,h2:focus{' + 'position: absolute;' + 'width: 1px;' + 'height: 1px;' + 'margin: -1px;' + 'padding: 0;' + 'border: 0;' + 'overflow: hidden;' + 'clip: rect(0 0 0 0);' + '}' + 'h2:hover.focusable:active,' + 'h2:hover.focusable:focus,' + 'h2:focus.focusable:active,' + 'h2:focus.focusable:focus{' + 'display: table;' + 'position: static;' + 'clear: both;' + '}' test('works visitor plugins postcss-focus and hidden; sequence 1', async () => { let { css } = await postcss([hidden, postcssFocus]).process(cssFocusHidden, { from: 'a.css' }) is(css, expectedFocusHidden) }) test('works visitor plugins postcss-focus and hidden; sequence 2', async () => { let { css } = await postcss([postcssFocus, hidden]).process(cssFocusHidden, { from: 'a.css' }) is(css, expectedFocusHidden) }) test('works visitor plugin postcss-alias', async () => { let input = '@alias { fs: font-size; bg: background; }' + '.aliased { fs: 16px; bg: white; }' let expected = '.aliased { font-size: 16px; background: white; }' let { css } = postcss([postcssAlias]).process(input, { from: 'a.css' }) is(css, expected) }) test('adds plugin to error', async () => { let broken: Plugin = { postcssPlugin: 'broken', Rule(rule) { throw rule.error('test') } } let error: any try { postcss([broken]).process('a{}', { from: 'broken.css' }).css } catch (e) { error = e } is(error.message, `broken: ${resolve('broken.css')}:1:1: test`) is(error.postcssNode.toString(), 'a{}') is(error.stack.includes('broken.css:1:1'), true) }) test('adds plugin to async error', async () => { let broken: Plugin = { postcssPlugin: 'broken', async Rule(rule) { await delay(1) throw rule.error('test') } } let error: any try { await postcss([broken]).process('a{}', { from: 'broken.css' }) } catch (e) { error = e } is(error.message, `broken: ${resolve('broken.css')}:1:1: test`) is(error.postcssNode.toString(), 'a{}') is(error.stack.includes('broken.css:1:1'), true) }) test('adds sync plugin to async error', async () => { let broken: Plugin = { postcssPlugin: 'broken', Rule(rule) { throw rule.error('test') } } let error: any try { await postcss([broken]).process('a{}', { from: 'broken.css' }) } catch (e) { error = e } is(error.message, `broken: ${resolve('broken.css')}:1:1: test`) is(error.postcssNode.toString(), 'a{}') is(error.stack.includes('broken.css:1:1'), true) }) test('adds node to error', async () => { let broken: Plugin = { postcssPlugin: 'broken', Rule() { throw new Error('test') } } let error: any try { postcss([broken]).process('a{}', { from: 'broken.css' }).css } catch (e) { error = e } is(error.message, 'test') is(error.postcssNode.toString(), 'a{}') is(error.stack.includes('broken.css:1:1'), true) }) test('adds node to async error', async () => { let broken: Plugin = { postcssPlugin: 'broken', async Rule() { await delay(1) throw new Error('test') } } let error: any try { await postcss([broken]).process('a{}', { from: 'broken.css' }) } catch (e) { error = e } is(error.message, 'test') is(error.postcssNode.toString(), 'a{}') is(error.stack.includes('broken.css:1:1'), true) }) test('shows error on sync call async plugins', () => { let asyncPlugin: Plugin = { postcssPlugin: 'asyncPlugin', async Rule() {} } let error: any try { postcss([asyncPlugin]).process('a{}', { from: 'broken.css' }).css } catch (e) { error = e } is(error.message.includes('work with async plugins'), true) }) test('passes helpers', async () => { function check(node: AnyNode, helpers: Helpers): void { equal(helpers.result.messages, []) is(typeof helpers.postcss, 'function') is(helpers.comment().type, 'comment') is(new helpers.Comment().type, 'comment') equal(helpers.list, postcss.list) } let syncPlugin: Plugin = { postcssPlugin: 'syncPlugin', Once: check, Rule: check, RuleExit: check, OnceExit: check } let asyncPlugin: Plugin = { postcssPlugin: 'syncPlugin', async Once(node, helpers) { await delay(1) check(node, helpers) }, async Rule(node, helpers) { await delay(1) check(node, helpers) }, async OnceExit(node, helpers) { await delay(1) check(node, helpers) } } postcss([syncPlugin]).process('a{}', { from: 'a.css' }).css await postcss([asyncPlugin]).process('a{}', { from: 'a.css' }) }) test('passes helpers in a document', async () => { function check(node: AnyNode, helpers: Helpers): void { equal(helpers.result.messages, []) type(helpers.postcss, 'function') is(helpers.comment().type, 'comment') is(new helpers.Comment().type, 'comment') equal(helpers.list, postcss.list) } let syncPlugin: Plugin = { postcssPlugin: 'syncPlugin', Once: check, Rule: check, RuleExit: check, OnceExit: check } let asyncPlugin: Plugin = { postcssPlugin: 'syncPlugin', async Once(node, helpers) { await delay(1) check(node, helpers) }, async Rule(node, helpers) { await delay(1) check(node, helpers) }, async OnceExit(node, helpers) { await delay(1) check(node, helpers) } } postcss([syncPlugin]).process( postcss.document({ nodes: [postcss.parse('a{}')] }), { from: 'a.css' } ).css await postcss([asyncPlugin]).process( postcss.document({ nodes: [postcss.parse('a{}')] }), { from: 'a.css' } ) }) test('detects non-changed values', () => { let plugin: Plugin = { postcssPlugin: 'test', Declaration(decl) { decl.value = 'red' } } is( postcss([plugin]).process('a{ color: black; background: white; }', { from: 'a.css' }).css, 'a{ color: red; background: red; }' ) }) test('allows runtime listeners', () => { let root = false let plugin: Plugin = { postcssPlugin: 'test', prepare(result) { return { Once() { root = true }, Rule(rule) { rule.selector = basename(result.opts.from ?? '') } } }, Declaration(decl) { decl.value = 'red' } } is( postcss([plugin]).process('a{ color: black }', { from: 'a.css' }).css, 'a.css{ color: red }' ) is(root, true) }) test('works correctly with nodes changes', () => { let plugin: Plugin = { postcssPlugin: 'test', Rule(rule) { if (!rule.some(i => i.type === 'decl' && i.prop === 'z-index')) { rule.prepend({ prop: 'z-index', value: '1' }) } } } is( postcss([plugin]).process('a{ color: black }', { from: 'a.css' }).css, 'a{ z-index: 1; color: black }' ) }) test('throws error on unknown plugin property', () => { let plugin: any = { postcssPlugin: 'test', NO: true } throws(() => { postcss([plugin]).process('').css }, /Unknown event NO in test\. Try to update PostCSS \(\d/) }) test('unwraps nodes on inserting', () => { let moveNode: Plugin = { postcssPlugin: 'moveNode', Declaration: { color: decl => { if (decl.parent?.type !== 'root') { decl.root().append(decl) } } } } let root = postcss([moveNode]).process('a{color:red}').root equal((root.last as any).proxyOf, root.last) }) let redToGreen: Plugin = { postcssPlugin: 'redToGreen', Declaration: { color: decl => { if (decl.value === 'red') { decl.value = 'green' } } } } let greenToBlue: Plugin = { postcssPlugin: 'greenToBlue', Declaration(decl) { if (decl.value === 'green') { decl.value = 'blue' } } } let fooToBar: Plugin = { postcssPlugin: 'fooToBar', Rule(rule) { if (rule.selector === '.foo') { rule.selectors = ['.bar'] } } } let mixins: Plugin = { postcssPlugin: 'mixin', prepare() { let mixin: AnyNode | undefined return { AtRule: { 'define-mixin': atRule => { if (atRule.first) mixin = atRule.first atRule.remove() }, 'apply-mixin': atRule => { if (mixin) atRule.replaceWith(mixin) } } } } } let insertFirst: Plugin = { postcssPlugin: 'insertFirst', AtRule: { 'insert-first': atRule => { let first = atRule.root().first if (first) atRule.replaceWith(first) } } } for (let funcType of ['sync', 'async']) { test(`walks ${funcType} through tree`, async () => { let [visits, visitor] = buildVisitor() let processor = postcss([visitor]).process( `@media screen { body { /* comment */ background: white; padding: 10px; } a { color: blue; } }`, { from: 'a.css' } ) if (funcType === 'sync') { processor.css } else { await processor } equal( addIndex(visits), addIndex([ ['Once', '1'], ['Root', '1'], ['AtRule', 'media'], ['Rule', 'body'], ['Comment', 'comment'], ['CommentExit', 'comment'], ['Declaration', 'background: white'], ['DeclarationExit', 'background: white'], ['Declaration', 'padding: 10px'], ['DeclarationExit', 'padding: 10px'], ['RuleExit', 'body'], ['Rule', 'a'], ['Declaration', 'color: blue'], ['DeclarationExit', 'color: blue'], ['RuleExit', 'a'], ['AtRuleExit', 'media'], ['RootExit', '1'], ['OnceExit', '1'] ]) ) }) test(`walks ${funcType} through tree in a document`, async () => { let document = postcss.document({ nodes: [ postcss.parse(`@media screen { body { /* comment */ background: white; padding: 10px; } a { color: blue; } }`) ] }) let [visits, visitor] = buildVisitor() let processor = postcss([visitor]).process(document, { from: 'a.css' }) if (funcType === 'sync') { processor.css } else { await processor } equal( addIndex(visits), addIndex([ ['Once', '1'], ['Document', '1'], ['Root', '1'], ['AtRule', 'media'], ['Rule', 'body'], ['Comment', 'comment'], ['CommentExit', 'comment'], ['Declaration', 'background: white'], ['DeclarationExit', 'background: white'], ['Declaration', 'padding: 10px'], ['DeclarationExit', 'padding: 10px'], ['RuleExit', 'body'], ['Rule', 'a'], ['Declaration', 'color: blue'], ['DeclarationExit', 'color: blue'], ['RuleExit', 'a'], ['AtRuleExit', 'media'], ['RootExit', '1'], ['DocumentExit', '1'], ['OnceExit', '1'] ]) ) }) test(`walks ${funcType} during transformations`, async () => { let [visits, visitor] = buildVisitor() let result = postcss([ visitor, redToGreen, greenToBlue, mixins, fooToBar, insertFirst ]).process( `.first { color: red; } @define-mixin { b { color: red; } } a { color: red; } @media (screen) { @insert-first; } .foo { background: red; } @apply-mixin;`, { from: 'a.css' } ) let output if (funcType === 'sync') { output = result.css } else { output = (await result).css } is( output, `a { color: blue; } @media (screen) {.first { color: blue; } } .bar { background: red; } b { color: blue; }` ) equal( addIndex(visits), addIndex([ ['Once', '6'], ['Root', '6'], ['Rule', '.first'], ['Declaration', 'color: red'], ['DeclarationExit', 'color: green'], ['RuleExit', '.first'], ['AtRule', 'define-mixin'], ['Rule', 'a'], ['Declaration', 'color: red'], ['DeclarationExit', 'color: green'], ['RuleExit', 'a'], ['AtRule', 'media'], ['AtRule', 'insert-first'], ['AtRuleExit', 'media'], ['Rule', '.foo'], ['Declaration', 'background: red'], ['DeclarationExit', 'background: red'], ['RuleExit', '.bar'], ['AtRule', 'apply-mixin'], ['RootExit', '4'], ['Root', '4'], ['Rule', 'a'], ['Declaration', 'color: green'], ['DeclarationExit', 'color: blue'], ['RuleExit', 'a'], ['AtRule', 'media'], ['Rule', '.first'], ['Declaration', 'color: green'], ['DeclarationExit', 'color: blue'], ['RuleExit', '.first'], ['AtRuleExit', 'media'], ['Rule', 'b'], ['Declaration', 'color: red'], ['DeclarationExit', 'color: green'], ['RuleExit', 'b'], ['RootExit', '4'], ['Root', '4'], ['Rule', 'a'], ['Declaration', 'color: blue'], ['DeclarationExit', 'color: blue'], ['RuleExit', 'a'], ['AtRule', 'media'], ['Rule', '.first'], ['Declaration', 'color: blue'], ['DeclarationExit', 'color: blue'], ['RuleExit', '.first'], ['AtRuleExit', 'media'], ['Rule', 'b'], ['Declaration', 'color: green'], ['DeclarationExit', 'color: blue'], ['RuleExit', 'b'], ['RootExit', '4'], ['Root', '4'], ['Rule', 'b'], ['Declaration', 'color: blue'], ['DeclarationExit', 'color: blue'], ['RuleExit', 'b'], ['RootExit', '4'], ['OnceExit', '4'] ]) ) }) test(`walks ${funcType} during transformations in a document`, async () => { let document = postcss.document({ nodes: [ postcss.parse( `.first { color: red; } @define-mixin { b { color: red; } } a { color: red; } @media (screen) { @insert-first; } .foo { background: red; } @apply-mixin;` ) ] }) let [visits, visitor] = buildVisitor() let result = postcss([ visitor, redToGreen, greenToBlue, mixins, fooToBar, insertFirst ]).process(document, { from: 'a.css' }) let output if (funcType === 'sync') { output = result.css } else { output = (await result).css } is( output, `a { color: blue; } @media (screen) {.first { color: blue; } } .bar { background: red; } b { color: blue; }` ) equal( addIndex(visits), addIndex([ ['Once', '6'], ['Document', '1'], ['Root', '6'], ['Rule', '.first'], ['Declaration', 'color: red'], ['DeclarationExit', 'color: green'], ['RuleExit', '.first'], ['AtRule', 'define-mixin'], ['Rule', 'a'], ['Declaration', 'color: red'], ['DeclarationExit', 'color: green'], ['RuleExit', 'a'], ['AtRule', 'media'], ['AtRule', 'insert-first'], ['AtRuleExit', 'media'], ['Rule', '.foo'], ['Declaration', 'background: red'], ['DeclarationExit', 'background: red'], ['RuleExit', '.bar'], ['AtRule', 'apply-mixin'], ['RootExit', '4'], ['DocumentExit', '1'], ['Document', '1'], ['Root', '4'], ['Rule', 'a'], ['Declaration', 'color: green'], ['DeclarationExit', 'color: blue'], ['RuleExit', 'a'], ['AtRule', 'media'], ['Rule', '.first'], ['Declaration', 'color: green'], ['DeclarationExit', 'color: blue'], ['RuleExit', '.first'], ['AtRuleExit', 'media'], ['Rule', 'b'], ['Declaration', 'color: red'], ['DeclarationExit', 'color: green'], ['RuleExit', 'b'], ['RootExit', '4'], ['DocumentExit', '1'], ['Document', '1'], ['Root', '4'], ['Rule', 'a'], ['Declaration', 'color: blue'], ['DeclarationExit', 'color: blue'], ['RuleExit', 'a'], ['AtRule', 'media'], ['Rule', '.first'], ['Declaration', 'color: blue'], ['DeclarationExit', 'color: blue'], ['RuleExit', '.first'], ['AtRuleExit', 'media'], ['Rule', 'b'], ['Declaration', 'color: green'], ['DeclarationExit', 'color: blue'], ['RuleExit', 'b'], ['RootExit', '4'], ['DocumentExit', '1'], ['Document', '1'], ['Root', '4'], ['Rule', 'b'], ['Declaration', 'color: blue'], ['DeclarationExit', 'color: blue'], ['RuleExit', 'b'], ['RootExit', '4'], ['DocumentExit', '1'], ['OnceExit', '4'] ]) ) }) test(`has ${funcType} property and at-rule name filters`, async () => { let filteredDecls: string[] = [] let allDecls: string[] = [] let filteredAtRules: string[] = [] let allAtRules: string[] = [] let allExits: string[] = [] let filteredExits: string[] = [] let scanner: Plugin = { postcssPlugin: 'test', Declaration: { 'color': decl => { filteredDecls.push(decl.prop) }, '*': decl => { allDecls.push(decl.prop) } }, DeclarationExit: { 'color': decl => { filteredExits.push(decl.prop) }, '*': decl => { allExits.push(decl.prop) } }, AtRule: { 'media': atRule => { filteredAtRules.push(atRule.name) }, '*': atRule => { allAtRules.push(atRule.name) } } } let result = postcss([scanner]).process( `@charset "UTF-8"; @media (screen) { COLOR: black; z-index: 1 }`, { from: 'a.css' } ) if (funcType === 'sync') { result.css } else { await result } equal(filteredDecls, ['COLOR']) equal(allDecls, ['COLOR', 'z-index']) equal(filteredExits, ['COLOR']) equal(allExits, ['COLOR', 'z-index']) equal(filteredAtRules, ['media']) equal(allAtRules, ['charset', 'media']) }) test(`has ${funcType} property and at-rule name filters in a document`, async () => { let filteredDecls: string[] = [] let allDecls: string[] = [] let filteredAtRules: string[] = [] let allAtRules: string[] = [] let allExits: string[] = [] let filteredExits: string[] = [] let scanner: Plugin = { postcssPlugin: 'test', Declaration: { 'color': decl => { filteredDecls.push(decl.prop) }, '*': decl => { allDecls.push(decl.prop) } }, DeclarationExit: { 'color': decl => { filteredExits.push(decl.prop) }, '*': decl => { allExits.push(decl.prop) } }, AtRule: { 'media': atRule => { filteredAtRules.push(atRule.name) }, '*': atRule => { allAtRules.push(atRule.name) } } } let document = postcss.document({ nodes: [ postcss.parse( `@charset "UTF-8"; @media (screen) { COLOR: black; z-index: 1 }` ) ] }) let result = postcss([scanner]).process(document, { from: 'a.css' }) if (funcType === 'sync') { result.css } else { await result } equal(filteredDecls, ['COLOR']) equal(allDecls, ['COLOR', 'z-index']) equal(filteredExits, ['COLOR']) equal(allExits, ['COLOR', 'z-index']) equal(filteredAtRules, ['media']) equal(allAtRules, ['charset', 'media']) }) test(`has ${funcType} OnceExit listener`, async () => { let rootExit = 0 let OnceExit = 0 let plugin: Plugin = { postcssPlugin: 'test', Rule(rule) { rule.remove() }, RootExit() { rootExit += 1 }, OnceExit() { OnceExit += 1 } } let result = postcss([plugin]).process('a{}', { from: 'a.css' }) if (funcType === 'sync') { result.css } else { await result } is(rootExit, 2) is(OnceExit, 1) }) test(`has ${funcType} OnceExit listener in a document with one root`, async () => { let RootExit = 0 let OnceExit = 0 let DocumentExit = 0 let plugin: Plugin = { postcssPlugin: 'test', Rule(rule) { rule.remove() }, RootExit() { RootExit += 1 }, DocumentExit() { DocumentExit += 1 }, OnceExit() { OnceExit += 1 } } let document = postcss.document({ nodes: [postcss.parse('a{}')] }) let result = postcss([plugin]).process(document, { from: 'a.css' }) if (funcType === 'sync') { result.css } else { await result } is(RootExit, 2) is(DocumentExit, 2) is(OnceExit, 1) }) test(`has ${funcType} OnceExit listener in a document with two roots`, async () => { let RootExit = 0 let OnceExit = 0 let DocumentExit = 0 let plugin: Plugin = { postcssPlugin: 'test', Rule(rule) { rule.remove() }, RootExit() { RootExit += 1 }, DocumentExit() { DocumentExit += 1 }, OnceExit() { OnceExit += 1 } } let document = postcss.document({ nodes: [postcss.parse('a{}'), postcss.parse('b{}')] }) let result = postcss([plugin]).process(document, { from: 'a.css' }) if (funcType === 'sync') { result.css } else { await result } is(RootExit, 4) is(DocumentExit, 2) is(OnceExit, 2) // 2 roots === 2 OnceExit }) } test('throws error from async OnceExit', async () => { let plugin: Plugin = { postcssPlugin: 'test', OnceExit() { throw new Error('test Exit error') } } let result = postcss([plugin]).process('a{ color: black }', { from: 'a.css' }) let error: any try { await result } catch (e) { error = e } is(error.message, 'test Exit error') }) test('rescan Root in another processor', () => { let [visits, visitor] = buildVisitor() let root = postcss([visitor]).process('a{z-index:1}', { from: 'a.css' }).root visits.splice(0, visits.length) postcss([visitor]).process(root, { from: 'a.css' }).root equal(visits, [ ['Once', '1'], ['Root', '1'], ['Rule', 'a'], ['Declaration', 'z-index: 1'], ['DeclarationExit', 'z-index: 1'], ['RuleExit', 'a'], ['RootExit', '1'], ['OnceExit', '1'] ]) }) test('rescan Root in another processor in a document', () => { let [visits, visitor] = buildVisitor() let root = postcss([visitor]).process('a{z-index:1}', { from: 'a.css' }).root let document = postcss.document({ nodes: [root] }) visits.splice(0, visits.length) postcss([visitor]).process(document, { from: 'a.css' }).root equal(visits, [ ['Once', '1'], ['Document', '1'], ['Root', '1'], ['Rule', 'a'], ['Declaration', 'z-index: 1'], ['DeclarationExit', 'z-index: 1'], ['RuleExit', 'a'], ['RootExit', '1'], ['DocumentExit', '1'], ['OnceExit', '1'] ]) }) test('marks cleaned nodes as dirty on moving', () => { let mover: Plugin = { postcssPlugin: 'mover', Rule(rule) { if (rule.selector === 'b') { let a = rule.prev() if (a) rule.append(a) } } } let [visits, visitor] = buildVisitor() postcss([mover, visitor]).process('a { color: black } b { }', { from: 'a.css' }).root equal(visits, [ ['Once', '2'], ['Root', '2'], ['Rule', 'a'], ['Declaration', 'color: black'], ['DeclarationExit', 'color: black'], ['RuleExit', 'a'], ['Rule', 'b'], ['Rule', 'a'], ['Declaration', 'color: black'], ['DeclarationExit', 'color: black'], ['RuleExit', 'a'], ['RuleExit', 'b'], ['RootExit', '1'], ['Root', '1'], ['Rule', 'b'], ['RuleExit', 'b'], ['RootExit', '1'], ['OnceExit', '1'] ]) }) test('marks cleaned nodes as dirty on moving in a document', () => { let mover: Plugin = { postcssPlugin: 'mover', Rule(rule) { if (rule.selector === 'b') { let a = rule.prev() if (a) rule.append(a) } } } let [visits, visitor] = buildVisitor() let document = postcss.document({ nodes: [postcss.parse('a { color: black } b { }')] }) postcss([mover, visitor]).process(document, { from: 'a.css' }).root equal(visits, [ ['Once', '2'], ['Document', '1'], ['Root', '2'], ['Rule', 'a'], ['Declaration', 'color: black'], ['DeclarationExit', 'color: black'], ['RuleExit', 'a'], ['Rule', 'b'], ['Rule', 'a'], ['Declaration', 'color: black'], ['DeclarationExit', 'color: black'], ['RuleExit', 'a'], ['RuleExit', 'b'], ['RootExit', '1'], ['DocumentExit', '1'], ['Document', '1'], ['Root', '1'], ['Rule', 'b'], ['RuleExit', 'b'], ['RootExit', '1'], ['DocumentExit', '1'], ['OnceExit', '1'] ]) }) test.run() postcss-8.4.6/test/warning.test.ts000066400000000000000000000105701417621533600172140ustar00rootroot00000000000000import { resolve } from 'path' import { test } from 'uvu' import { is, type } from 'uvu/assert' import { Warning, parse, decl } from '../lib/postcss.js' test('outputs simple warning', () => { let warning = new Warning('text') is(warning.toString(), 'text') }) test('outputs warning with plugin', () => { let warning = new Warning('text', { plugin: 'plugin' }) is(warning.toString(), 'plugin: text') }) test('outputs warning with position', () => { let root = parse('a{}') let warning = new Warning('text', { node: root.first }) is(warning.toString(), ':1:1: text') }) test('outputs warning with plugin and node', () => { let file = resolve('a.css') let root = parse('a{}', { from: file }) let warning = new Warning('text', { plugin: 'plugin', node: root.first }) is(warning.toString(), `plugin: ${file}:1:1: text`) }) test('outputs warning with index', () => { let file = resolve('a.css') let root = parse('@rule param {}', { from: file }) let warning = new Warning('text', { plugin: 'plugin', node: root.first, index: 7 }) is(warning.toString(), `plugin: ${file}:1:8: text`) }) test('outputs warning with word', () => { let file = resolve('a.css') let root = parse('@rule param {}', { from: file }) let warning = new Warning('text', { plugin: 'plugin', node: root.first, word: 'am' }) is(warning.toString(), `plugin: ${file}:1:10: text`) }) test('generates warning without source', () => { let node = decl({ prop: 'color', value: 'black' }) let warning = new Warning('text', { node }) is(warning.toString(), ': text') }) test('has line and column is undefined by default', () => { let warning = new Warning('text') type(warning.line, 'undefined') type(warning.column, 'undefined') type(warning.endLine, 'undefined') type(warning.endColumn, 'undefined') }) test('gets range from node', () => { let root = parse('a{}') let warning = new Warning('text', { node: root.first }) is(warning.line, 1) is(warning.column, 1) is(warning.endLine, 1) is(warning.endColumn, 4) }) test('gets range from node without end', () => { let root = parse('a{}') root.first!.source!.end = undefined let warning = new Warning('text', { node: root.first }) is(warning.line, 1) is(warning.column, 1) is(warning.endLine, 1) is(warning.endColumn, 2) }) test('gets range from word', () => { let root = parse('a b{}') let warning = new Warning('text', { node: root.first, word: 'b' }) is(warning.line, 1) is(warning.column, 3) is(warning.endLine, 1) is(warning.endColumn, 4) }) test('gets range from index', () => { let root = parse('a b{}') let warning = new Warning('text', { node: root.first, index: 2 }) is(warning.line, 1) is(warning.column, 3) is(warning.endLine, 1) is(warning.endColumn, 4) }) test('gets range from index and endIndex', () => { let root = parse('a b{}') let warning = new Warning('text', { node: root.first, index: 2, endIndex: 3 }) is(warning.line, 1) is(warning.column, 3) is(warning.endLine, 1) is(warning.endColumn, 4) }) test('gets range from start', () => { let root = parse('a b{}') let warning = new Warning('text', { node: root.first, start: { line: 1, column: 3 } }) is(warning.line, 1) is(warning.column, 3) is(warning.endLine, 1) is(warning.endColumn, 6) }) test('gets range from end', () => { let root = parse('a b{}') let warning = new Warning('text', { node: root.first, end: { line: 1, column: 3 } }) is(warning.line, 1) is(warning.column, 1) is(warning.endLine, 1) is(warning.endColumn, 3) }) test('gets range from start and end', () => { let root = parse('a b{}') let warning = new Warning('text', { node: root.first, start: { line: 1, column: 3 }, end: { line: 1, column: 4 } }) is(warning.line, 1) is(warning.column, 3) is(warning.endLine, 1) is(warning.endColumn, 4) }) test('always returns exclusive ends', () => { let root = parse('a b{}') let warning = new Warning('text', { node: root.first, index: 1, endIndex: 1 }) is(warning.line, 1) is(warning.column, 2) is(warning.endLine, 1) is(warning.endColumn, 3) }) test('always returns valid ranges', () => { let root = parse('a b{}') let warning = new Warning('text', { node: root.first, index: 2, endIndex: 1 }) is(warning.line, 1) is(warning.column, 3) is(warning.endLine, 1) is(warning.endColumn, 4) }) test.run() postcss-8.4.6/tsconfig.json000066400000000000000000000002521417621533600157450ustar00rootroot00000000000000{ "compilerOptions": { "target": "es2018", "module": "commonjs", "allowJs": true, "strict": true, "noEmit": true, "esModuleInterop": true } }