From ce4f695c260b2198afeb0c4e3ac3c5d291e64e6a Mon Sep 17 00:00:00 2001 From: romainmenke Date: Sat, 27 Nov 2021 13:30:29 +0100 Subject: [PATCH 1/4] Migrate postcss-image-set-function --- .../postcss-image-set-function/.editorconfig | 19 ------------------- .../.github/workflows/test.yml | 18 ------------------ .../postcss-image-set-function/package.json | 18 ++++++++++-------- 3 files changed, 10 insertions(+), 45 deletions(-) delete mode 100644 plugins/postcss-image-set-function/.editorconfig delete mode 100644 plugins/postcss-image-set-function/.github/workflows/test.yml diff --git a/plugins/postcss-image-set-function/.editorconfig b/plugins/postcss-image-set-function/.editorconfig deleted file mode 100644 index 7227e5a5f..000000000 --- a/plugins/postcss-image-set-function/.editorconfig +++ /dev/null @@ -1,19 +0,0 @@ -root = true - -[*] -charset = utf-8 -end_of_line = lf -indent_style = tab -insert_final_newline = true -trim_trailing_whitespace = true - -[*.md] -trim_trailing_whitespace = false - -[*.{json,md,yml}] -indent_size = 2 -indent_style = space - -[test/*.expect.css] -insert_final_newline = false -trim_trailing_whitespace = false diff --git a/plugins/postcss-image-set-function/.github/workflows/test.yml b/plugins/postcss-image-set-function/.github/workflows/test.yml deleted file mode 100644 index 4a287db8e..000000000 --- a/plugins/postcss-image-set-function/.github/workflows/test.yml +++ /dev/null @@ -1,18 +0,0 @@ -name: test -on: - push: - -jobs: - test: - runs-on: ubuntu-latest - strategy: - matrix: - node: [12, 16] - steps: - - uses: actions/checkout@v2 - - uses: actions/setup-node@v2 - with: - node-version: ${{ matrix.node }} - - - run: yarn install --ignore-scripts - - run: yarn run test diff --git a/plugins/postcss-image-set-function/package.json b/plugins/postcss-image-set-function/package.json index 41604ed3a..617e02780 100644 --- a/plugins/postcss-image-set-function/package.json +++ b/plugins/postcss-image-set-function/package.json @@ -4,7 +4,6 @@ "description": "Display resolution-dependent images using the image-set() function in CSS", "author": "Jonathan Neal ", "license": "CC0-1.0", - "repository": "jonathantneal/postcss-image-set-function", "homepage": "https://github.com/jonathantneal/postcss-image-set-function#readme", "bugs": "https://github.com/jonathantneal/postcss-image-set-function/issues", "main": "index.js", @@ -12,13 +11,14 @@ "lib/" ], "scripts": { - "prepublishOnly": "npm test", + "prepublishOnly": "npm run build --if-present && npm run test --if-present", "test": "echo 'Running tests...'; npm run test:js && npm run test:tape", "test:js": "eslint *.js --cache --ignore-path .gitignore --quiet", - "test:tape": "postcss-tape" + "test:tape": "postcss-tape", + "stryker": "stryker run --logLevel error" }, "engines": { - "node": ">=12" + "node": "^12 || ^14 || >=16" }, "dependencies": { "postcss-values-parser": "6.0.0" @@ -32,9 +32,6 @@ "postcss": "8.3.6", "postcss-tape": "6.0.1" }, - "eslintConfig": { - "extends": "dev" - }, "keywords": [ "postcss", "css", @@ -46,5 +43,10 @@ "resolution", "negotiation", "optimization" - ] + ], + "repository": { + "type": "git", + "url": "https://github.com/csstools/postcss-plugins.git", + "directory": "" + } } From fc61c71f11a06dca25d8967073261952c5703691 Mon Sep 17 00:00:00 2001 From: romainmenke Date: Sat, 27 Nov 2021 14:56:21 +0100 Subject: [PATCH 2/4] Migrate postcss-image-set-function --- plugins/postcss-image-set-function/.gitignore | 5 +- .../CONTRIBUTING.md | 65 ----- plugins/postcss-image-set-function/INSTALL.md | 12 +- plugins/postcss-image-set-function/README.md | 16 +- plugins/postcss-image-set-function/index.js | 57 ---- .../lib/get-comma.js | 2 - .../lib/get-image.js | 23 -- .../lib/get-media.js | 25 -- .../lib/handle-invalidation.js | 12 - .../lib/process-image-set.js | 82 ------ .../postcss-image-set-function/package.json | 37 ++- plugins/postcss-image-set-function/src/cli.ts | 16 + .../postcss-image-set-function/src/index.ts | 59 ++++ .../src/lib/get-comma.ts | 4 + .../src/lib/get-image.ts | 19 ++ .../src/lib/get-media.ts | 35 +++ .../src/lib/handle-invalidation.ts | 7 + .../src/lib/process-image-set.ts | 67 +++++ .../test/basic.expect.css | 276 ++++++++++-------- .../test/basic.no-preserve.expect.css | 165 ++++++----- .../tsconfig.json | 0 rollup/default.ts.js | 2 +- 22 files changed, 487 insertions(+), 499 deletions(-) delete mode 100644 plugins/postcss-image-set-function/CONTRIBUTING.md delete mode 100644 plugins/postcss-image-set-function/index.js delete mode 100644 plugins/postcss-image-set-function/lib/get-comma.js delete mode 100644 plugins/postcss-image-set-function/lib/get-image.js delete mode 100644 plugins/postcss-image-set-function/lib/get-media.js delete mode 100644 plugins/postcss-image-set-function/lib/handle-invalidation.js delete mode 100644 plugins/postcss-image-set-function/lib/process-image-set.js create mode 100644 plugins/postcss-image-set-function/src/cli.ts create mode 100644 plugins/postcss-image-set-function/src/index.ts create mode 100644 plugins/postcss-image-set-function/src/lib/get-comma.ts create mode 100644 plugins/postcss-image-set-function/src/lib/get-image.ts create mode 100644 plugins/postcss-image-set-function/src/lib/get-media.ts create mode 100644 plugins/postcss-image-set-function/src/lib/handle-invalidation.ts create mode 100644 plugins/postcss-image-set-function/src/lib/process-image-set.ts rename plugins/{postcss-base-plugin => postcss-image-set-function}/tsconfig.json (100%) diff --git a/plugins/postcss-image-set-function/.gitignore b/plugins/postcss-image-set-function/.gitignore index 5ef88dcc2..b5d13c8c0 100644 --- a/plugins/postcss-image-set-function/.gitignore +++ b/plugins/postcss-image-set-function/.gitignore @@ -1,10 +1,13 @@ node_modules +dist package-lock.json yarn.lock *.log* *.result.css -.* +*.result.css.map !.editorconfig !.gitignore +!.rollup.js !.tape.js +!.travis.yml !.github diff --git a/plugins/postcss-image-set-function/CONTRIBUTING.md b/plugins/postcss-image-set-function/CONTRIBUTING.md deleted file mode 100644 index c2c61d30c..000000000 --- a/plugins/postcss-image-set-function/CONTRIBUTING.md +++ /dev/null @@ -1,65 +0,0 @@ -# Contributing to PostCSS image-set() Function - -You want to help? You rock! Now, take a moment to be sure your contributions -make sense to everyone else. - -## Reporting Issues - -Found a problem? Want a new feature? - -- See if your issue or idea has [already been reported]. -- Provide a [reduced test case] or a [live example]. - -Remember, a bug is a _demonstrable problem_ caused by _our_ code. - -## Submitting Pull Requests - -Pull requests are the greatest contributions, so be sure they are focused in -scope and avoid unrelated commits. - -1. To begin; [fork this project], clone your fork, and add our upstream. - ```bash - # Clone your fork of the repo into the current directory - git clone git@github.com:YOUR_USER/postcss-image-set-function.git - - # Navigate to the newly cloned directory - cd postcss-image-set-function - - # Assign the original repo to a remote called "upstream" - git remote add upstream git@github.com:jonathantneal/postcss-image-set-function.git - - # Install the tools necessary for testing - npm install - ``` - -2. Create a branch for your feature or fix: - ```bash - # Move into a new branch for your feature - git checkout -b feature/thing - ``` - ```bash - # Move into a new branch for your fix - git checkout -b fix/something - ``` - -3. If your code follows our practices, then push your feature branch: - ```bash - # Test current code - npm test - ``` - ```bash - # Push the branch for your new feature - git push origin feature/thing - ``` - ```bash - # Or, push the branch for your update - git push origin update/something - ``` - -That’s it! Now [open a pull request] with a clear title and description. - -[already been reported]: issues -[fork this project]: fork -[live example]: https://codepen.io/pen -[open a pull request]: https://help.github.com/articles/using-pull-requests/ -[reduced test case]: https://css-tricks.com/reduced-test-cases/ diff --git a/plugins/postcss-image-set-function/INSTALL.md b/plugins/postcss-image-set-function/INSTALL.md index 5de51e4a0..1eaf2d2d8 100644 --- a/plugins/postcss-image-set-function/INSTALL.md +++ b/plugins/postcss-image-set-function/INSTALL.md @@ -13,15 +13,7 @@ Add [PostCSS image-set() Function] to your project: npm install postcss-image-set-function --save-dev ``` -Use [PostCSS image-set() Function] to process your CSS: - -```js -const postcssImageSetFunction = require('postcss-image-set-function'); - -postcssImageSetFunction.process(YOUR_CSS /*, processOptions, pluginOptions */); -``` - -Or use it as a [PostCSS] plugin: +Use [PostCSS image-set() Function] as a [PostCSS] plugin: ```js const postcss = require('postcss'); @@ -166,6 +158,6 @@ grunt.initConfig({ [PostCSS]: https://github.com/postcss/postcss [PostCSS CLI]: https://github.com/postcss/postcss-cli [PostCSS Loader]: https://github.com/postcss/postcss-loader -[PostCSS image-set() Function]: https://github.com/jonathantneal/postcss-image-set-function +[PostCSS image-set() Function]: https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-image-set-function [React App Rewire PostCSS]: https://github.com/csstools/react-app-rewire-postcss [React App Rewired]: https://github.com/timarney/react-app-rewired diff --git a/plugins/postcss-image-set-function/README.md b/plugins/postcss-image-set-function/README.md index d84ea1bd1..ef8ac74e4 100644 --- a/plugins/postcss-image-set-function/README.md +++ b/plugins/postcss-image-set-function/README.md @@ -56,15 +56,7 @@ Add [PostCSS image-set() Function] to your project: npm install postcss-image-set-function --save-dev ``` -Use [PostCSS image-set() Function] to process your CSS: - -```js -const postcssImageSetFunction = require('postcss-image-set-function'); - -postcssImageSetFunction.process(YOUR_CSS /*, processOptions, pluginOptions */); -``` - -Or use it as a [PostCSS] plugin: +Use [PostCSS image-set() Function] as a [PostCSS] plugin: ```js const postcss = require('postcss'); @@ -154,8 +146,8 @@ in, other factors can affect the chosen image. For example, if the user is on a slow mobile connection, the browser may prefer to select a lower-res image rather than wait for a larger, resolution-matching image to load. -[cli-img]: https://github.com/csstools/postcss-image-set-function/workflows/test/badge.svg -[cli-url]: https://github.com/csstools/postcss-image-set-function/actions/workflows/test.yml?query=workflow/test +[cli-img]: https://github.com/csstools/postcss-plugins/workflows/test/badge.svg +[cli-url]: https://github.com/csstools/postcss-plugins/actions/workflows/test.yml?query=workflow/test [css-img]: https://cssdb.org/badge/image-set-function.svg [css-url]: https://cssdb.org/#image-set-function [git-img]: https://img.shields.io/badge/support-chat-blue.svg @@ -168,4 +160,4 @@ rather than wait for a larger, resolution-matching image to load. [Grunt PostCSS]: https://github.com/nDmitry/grunt-postcss [PostCSS]: https://github.com/postcss/postcss [PostCSS Loader]: https://github.com/postcss/postcss-loader -[PostCSS image-set() Function]: https://github.com/jonathantneal/postcss-image-set-function +[PostCSS image-set() Function]: https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-image-set-function diff --git a/plugins/postcss-image-set-function/index.js b/plugins/postcss-image-set-function/index.js deleted file mode 100644 index 222874034..000000000 --- a/plugins/postcss-image-set-function/index.js +++ /dev/null @@ -1,57 +0,0 @@ -const { parse } = require('postcss-values-parser'); -const processImageSet = require('./lib/process-image-set'); - -const imageSetValueMatchRegExp = /(^|[^\w-])(-webkit-)?image-set\(/i; -const imageSetFunctionMatchRegExp = /^(-webkit-)?image-set$/i; - -/** - * @param {{preserve?: boolean, oninvalid?: string}} opts - * @returns {import('postcss').Plugin} - */ -module.exports = function creator(opts) { - // prepare options - const preserve = 'preserve' in Object(opts) ? Boolean(opts.preserve) : true; - const oninvalid = 'oninvalid' in Object(opts) ? opts.oninvalid : 'ignore'; - - return { - postcssPlugin: 'postcss-image-set-function', - Once(root, helpers) { - // for every declaration - root.walkDecls(decl => { - const {value} = decl; - - // if a declaration likely uses an image-set() function - if (imageSetValueMatchRegExp.test(value)) { - let valueAST - - try { - valueAST = parse(value, { ignoreUnknownWords: true }) - } catch (error) { - decl.warn( - helpers.result, - `Failed to parse value '${value}' as an image-set function. Leaving the original value intact.` - ) - } - - if (typeof valueAST === 'undefined') { - return - } - - // process every image-set() function - valueAST.walkFuncs(node => { - if (imageSetFunctionMatchRegExp.test(node.name)) { - processImageSet(node.nodes, decl, { - decl, - oninvalid, - preserve, - result: helpers.result, - }); - } - }); - } - }); - }, - }; -}; - -module.exports.postcss = true; diff --git a/plugins/postcss-image-set-function/lib/get-comma.js b/plugins/postcss-image-set-function/lib/get-comma.js deleted file mode 100644 index 537e04673..000000000 --- a/plugins/postcss-image-set-function/lib/get-comma.js +++ /dev/null @@ -1,2 +0,0 @@ -// return whether a node is a valid comma -module.exports = node => Object(node).type === 'punctuation' && Object(node).value === ','; diff --git a/plugins/postcss-image-set-function/lib/get-image.js b/plugins/postcss-image-set-function/lib/get-image.js deleted file mode 100644 index 8f26a5233..000000000 --- a/plugins/postcss-image-set-function/lib/get-image.js +++ /dev/null @@ -1,23 +0,0 @@ -const imageSetFunctionMatchRegExp = /^(-webkit-)?image-set$/i; - -const imageFuncRegexp = /^(cross-fade|image|(repeating-)?(conic|linear|radial)-gradient|url)$/i; - -/** - * return a valid image - * @param {import('postcss-values-parser').ChildNode} node - * @returns {string|*|boolean} - */ -module.exports = (node) => - // | | | - // the image-set() function can not be nested inside of itself - Object(node).type === 'func' && - imageFuncRegexp.test(node.name) && - !( - node.parent.parent && - node.parent.parent.type === 'func' && - imageSetFunctionMatchRegExp.test(node.parent.parent.name) - ) - ? (node.raws.before || '') + String(node) - : Object(node).type === 'quoted' - ? node.value - : false; diff --git a/plugins/postcss-image-set-function/lib/get-media.js b/plugins/postcss-image-set-function/lib/get-media.js deleted file mode 100644 index ad03c47aa..000000000 --- a/plugins/postcss-image-set-function/lib/get-media.js +++ /dev/null @@ -1,25 +0,0 @@ -const postcss = require('postcss'); - -const dpiRatios = { dpcm: 2.54, dpi: 1, dppx: 96, x: 96 }; - -// return a valid @media rule -module.exports = (node, mediasByDpr) => { - if (Object(node).type === 'numeric' && node.unit in dpiRatios) { - // calculate min-device-pixel-ratio and min-resolution - const dpi = Number(node.value) * dpiRatios[node.unit.toLowerCase()]; - const dpr = Math.floor(dpi / dpiRatios.x * 100) / 100; - - if (dpi in mediasByDpr) { - return false; - } else { - const media = mediasByDpr[dpi] = postcss.atRule({ - name: 'media', - params: `(-webkit-min-device-pixel-ratio: ${dpr}), (min-resolution: ${dpi}dpi)` - }); - - return media; - } - } else { - return false; - } -}; diff --git a/plugins/postcss-image-set-function/lib/handle-invalidation.js b/plugins/postcss-image-set-function/lib/handle-invalidation.js deleted file mode 100644 index 4f17abdbc..000000000 --- a/plugins/postcss-image-set-function/lib/handle-invalidation.js +++ /dev/null @@ -1,12 +0,0 @@ -/** - * @param {{ decl: import('postcss').Declaration, oninvalid: string, preserve: boolean, result: import('postcss').Result }} opts - * @param {string} message - * @param {import('postcss-values-parser').ChildNode} word - */ -module.exports = (opts, message, word) => { - if (opts.oninvalid === 'warn') { - opts.decl.warn(opts.result, message, { word: String(word) }); - } else if (opts.oninvalid === 'throw') { - throw opts.decl.error(message, { word: String(word) }); - } -}; diff --git a/plugins/postcss-image-set-function/lib/process-image-set.js b/plugins/postcss-image-set-function/lib/process-image-set.js deleted file mode 100644 index 0f9a76b65..000000000 --- a/plugins/postcss-image-set-function/lib/process-image-set.js +++ /dev/null @@ -1,82 +0,0 @@ -const getComma = require('./get-comma'); -const getImage = require('./get-image'); -const getMedia = require('./get-media'); -const handleInvalidation = require('./handle-invalidation'); - -/** - * @param {import('postcss-values-parser').ChildNode[]} imageSetOptionNodes - * @param {import('postcss').Declaration} decl - * @param {{ decl: import('postcss').Declaration, oninvalid: string, preserve: boolean, result: import('postcss').Result }} opts - * @returns {void} - */ -module.exports = (imageSetOptionNodes, decl, opts) => { - const parent = decl.parent; - const mediasByDpr = {}; - - let length = imageSetOptionNodes.length; - let index = -1; - - while (index < length) { - const [comma, value, media] = [ - index < 0 ? true : getComma(imageSetOptionNodes[index]), - getImage(imageSetOptionNodes[index + 1]), - getMedia(imageSetOptionNodes[index + 2], mediasByDpr) - ]; - - // handle invalidations - if (!comma) { - handleInvalidation(opts, 'unexpected comma', imageSetOptionNodes[index]); - return; - } else if (!value) { - handleInvalidation(opts, 'unexpected image', imageSetOptionNodes[index + 1]); - return; - } else if (!media) { - handleInvalidation(opts, 'unexpected resolution', imageSetOptionNodes[index + 2]); - return; - } - - // prepare @media { decl: } - const parentClone = parent.clone().removeAll(); - const declClone = decl.clone({ value }); - - parentClone.append(declClone); - media.append(parentClone); - - index += 3 - } - - const medias = Object.keys(mediasByDpr) - .sort((a, b) => a - b) - .map(params => mediasByDpr[params]); - - // conditionally prepend previous siblings - if (medias.length) { - const firstDecl = medias[0].nodes[0].nodes[0]; - - if (medias.length === 1) { - decl.value = firstDecl.value - } else { - const siblings = parent.nodes; - const previousSiblings = siblings.slice(0, siblings.indexOf(decl)).concat(firstDecl); - - if (previousSiblings.length) { - const parentClone = parent.cloneBefore().removeAll(); - - parentClone.append(previousSiblings); - } - - // prepend any @media { decl: } rules - parent.before(medias.slice(1)); - - // conditionally remove the current rule - if (!opts.preserve) { - decl.remove(); - - // and then conditionally remove its parent - if (!parent.nodes.length) { - parent.remove(); - } - } - } - } -} diff --git a/plugins/postcss-image-set-function/package.json b/plugins/postcss-image-set-function/package.json index dca856270..c18e19e57 100644 --- a/plugins/postcss-image-set-function/package.json +++ b/plugins/postcss-image-set-function/package.json @@ -4,17 +4,26 @@ "description": "Display resolution-dependent images using the image-set() function in CSS", "author": "Jonathan Neal ", "license": "CC0-1.0", - "homepage": "https://github.com/jonathantneal/postcss-image-set-function#readme", - "bugs": "https://github.com/jonathantneal/postcss-image-set-function/issues", - "main": "index.js", + "homepage": "https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-image-set-function#readme", + "bugs": "https://github.com/csstools/postcss-plugins/issues", + "main": "dist/index.cjs", + "module": "dist/index.mjs", + "types": "dist/index.d.ts", "files": [ - "lib/" + "CHANGELOG.md", + "INSTALL.md", + "LICENSE.md", + "README.md", + "dist" ], + "bin": { + "postcss-image-set-function": "dist/cli.mjs" + }, "scripts": { - "prepublishOnly": "npm run build --if-present && npm run test --if-present", - "test": "echo 'Running tests...'; npm run test:js && npm run test:tape", - "test:js": "eslint *.js --cache --ignore-path .gitignore --quiet", - "test:tape": "postcss-tape", + "prepublishOnly": "npm run build && npm run test", + "lint": "eslint src/**/*.js", + "test": "postcss-tape", + "build": "rollup -c ../../rollup/default.ts.js", "stryker": "stryker run --logLevel error" }, "engines": { @@ -23,15 +32,13 @@ "dependencies": { "postcss-values-parser": "6.0.1" }, + "devDependencies": { + "postcss": "8.3.6", + "postcss-tape": "6.0.1" + }, "peerDependencies": { "postcss": "^8.3" }, - "devDependencies": { - "eslint": "^8.2.0", - "eslint-config-dev": "^2.0.0", - "postcss": "^8.3.11", - "postcss-tape": "^6.0.1" - }, "keywords": [ "postcss", "css", @@ -47,6 +54,6 @@ "repository": { "type": "git", "url": "https://github.com/csstools/postcss-plugins.git", - "directory": "" + "directory": "plugins/postcss-image-set-function" } } diff --git a/plugins/postcss-image-set-function/src/cli.ts b/plugins/postcss-image-set-function/src/cli.ts new file mode 100644 index 000000000..e59b4e8a1 --- /dev/null +++ b/plugins/postcss-image-set-function/src/cli.ts @@ -0,0 +1,16 @@ +import plugin from './index'; +import { cli, helpTextLogger } from '@csstools/base-cli'; + +cli( + plugin, + ['oninvalid', 'preserve'], + helpTextLogger( + 'postcss-image-set-function', + 'PostCSS Image Set Function', + 'Lets you display resolution-dependent images using the image-set() function in CSS, following the CSS Images specification.', + { + preserve: true, + oninvalid: 'ignore|warn|throw', + }, + ), +); diff --git a/plugins/postcss-image-set-function/src/index.ts b/plugins/postcss-image-set-function/src/index.ts new file mode 100644 index 000000000..617f07cfd --- /dev/null +++ b/plugins/postcss-image-set-function/src/index.ts @@ -0,0 +1,59 @@ +import { parse } from 'postcss-values-parser'; +import { processImageSet } from './lib/process-image-set'; +import type { PluginCreator } from 'postcss'; + +const imageSetValueMatchRegExp = /(^|[^\w-])(-webkit-)?image-set\(/i; +const imageSetFunctionMatchRegExp = /^(-webkit-)?image-set$/i; + +const creator: PluginCreator<{ preserve: boolean, oninvalid: string }> = (opts?: { preserve: boolean, oninvalid: string }) => { + // prepare options + const preserve = 'preserve' in Object(opts) ? Boolean(opts.preserve) : true; + const oninvalid = 'oninvalid' in Object(opts) ? opts.oninvalid : 'ignore'; + + return { + postcssPlugin: 'postcss-image-set-function', + Declaration(decl, { result, postcss }) { + const value = decl.value; + + // if a declaration likely uses an image-set() function + if (!imageSetValueMatchRegExp.test(value)) { + return; + } + + let valueAST; + + try { + valueAST = parse(value, { ignoreUnknownWords: true }); + } catch (error) { + decl.warn( + result, + `Failed to parse value '${value}' as an image-set function. Leaving the original value intact.`, + ); + } + + if (typeof valueAST === 'undefined') { + return; + } + + // process every image-set() function + valueAST.walkFuncs((node) => { + if (!imageSetFunctionMatchRegExp.test(node.name)) { + return; + } + + processImageSet(node.nodes, decl, { + decl, + oninvalid, + preserve, + result: result, + postcss: postcss, + }); + }); + }, + }; +}; + +creator.postcss = true; + +export default creator; + diff --git a/plugins/postcss-image-set-function/src/lib/get-comma.ts b/plugins/postcss-image-set-function/src/lib/get-comma.ts new file mode 100644 index 000000000..f462049f2 --- /dev/null +++ b/plugins/postcss-image-set-function/src/lib/get-comma.ts @@ -0,0 +1,4 @@ +// return whether a node is a valid comma +export function getComma(node) { + return Object(node).type === 'punctuation' && Object(node).value === ','; +} diff --git a/plugins/postcss-image-set-function/src/lib/get-image.ts b/plugins/postcss-image-set-function/src/lib/get-image.ts new file mode 100644 index 000000000..4c2e82f6b --- /dev/null +++ b/plugins/postcss-image-set-function/src/lib/get-image.ts @@ -0,0 +1,19 @@ +const imageSetFunctionMatchRegExp = /^(-webkit-)?image-set$/i; + +const imageFuncRegexp = /^(cross-fade|image|(repeating-)?(conic|linear|radial)-gradient|url)$/i; + +export function getImage(node) { + // | | | + // the image-set() function can not be nested inside of itself + return Object(node).type === 'func' && + imageFuncRegexp.test(node.name) && + !( + node.parent.parent && + node.parent.parent.type === 'func' && + imageSetFunctionMatchRegExp.test(node.parent.parent.name) + ) + ? (node.raws.before || '') + String(node) + : Object(node).type === 'quoted' + ? node.value + : false; +} diff --git a/plugins/postcss-image-set-function/src/lib/get-media.ts b/plugins/postcss-image-set-function/src/lib/get-media.ts new file mode 100644 index 000000000..a0cc3d82c --- /dev/null +++ b/plugins/postcss-image-set-function/src/lib/get-media.ts @@ -0,0 +1,35 @@ +import type { Node, Numeric } from 'postcss-values-parser'; + +const dpiRatios = { dpcm: 2.54, dpi: 1, dppx: 96, x: 96 }; + +// return a valid @media rule +export function getMedia(dpi: number | false, postcss) { + if (typeof dpi === 'boolean') { + return false; + } + + // calculate min-device-pixel-ratio and min-resolution + const dpr = Math.floor(dpi / dpiRatios.x * 100) / 100; + + const media = postcss.atRule({ + name: 'media', + params: `(-webkit-min-device-pixel-ratio: ${dpr}), (min-resolution: ${dpi}dpi)`, + }); + + return media; +} + +export function getMediaDPI(node: Node) { + if (Object(node).type !== 'numeric') { + return false; + } + + const numeric = node as Numeric; + + if (numeric.unit in dpiRatios) { + // calculate min-device-pixel-ratio and min-resolution + return Number(numeric.value) * dpiRatios[numeric.unit.toLowerCase()]; + } else { + return false; + } +} diff --git a/plugins/postcss-image-set-function/src/lib/handle-invalidation.ts b/plugins/postcss-image-set-function/src/lib/handle-invalidation.ts new file mode 100644 index 000000000..b7ba04967 --- /dev/null +++ b/plugins/postcss-image-set-function/src/lib/handle-invalidation.ts @@ -0,0 +1,7 @@ +export const handleInvalidation = (opts, message, word) => { + if (opts.oninvalid === 'warn') { + opts.decl.warn(opts.result, message, { word: String(word) }); + } else if (opts.oninvalid === 'throw') { + throw opts.decl.error(message, { word: String(word) }); + } +}; diff --git a/plugins/postcss-image-set-function/src/lib/process-image-set.ts b/plugins/postcss-image-set-function/src/lib/process-image-set.ts new file mode 100644 index 000000000..41a2fb5fd --- /dev/null +++ b/plugins/postcss-image-set-function/src/lib/process-image-set.ts @@ -0,0 +1,67 @@ +import { getComma } from './get-comma'; +import { getImage } from './get-image'; +import { getMedia, getMediaDPI } from './get-media'; +import { handleInvalidation } from './handle-invalidation'; +import type { AtRule, Container, Declaration, Result, Postcss } from 'postcss'; + +export const processImageSet = (imageSetOptionNodes, decl: Declaration, opts: { decl: Declaration, oninvalid: string, preserve: boolean, result: Result, postcss: Postcss }) => { + const parent = decl.parent; + const mediasByDpr: Map = new Map(); + + const length = imageSetOptionNodes.length; + let index = -1; + + while (index < length) { + const comma = index < 0 ? true : getComma(imageSetOptionNodes[index]); + const value = getImage(imageSetOptionNodes[index + 1]); + const mediaDPI = getMediaDPI(imageSetOptionNodes[index + 2]); + + const media = getMedia(mediaDPI, opts.postcss); + + // handle invalidations + if (!comma) { + handleInvalidation(opts, 'unexpected comma', imageSetOptionNodes[index]); + return; + } else if (!value) { + handleInvalidation(opts, 'unexpected image', imageSetOptionNodes[index + 1]); + return; + } else if (!media || !mediaDPI || mediasByDpr.has(mediaDPI)) { + handleInvalidation(opts, 'unexpected resolution', imageSetOptionNodes[index + 2]); + return; + } + + mediasByDpr.set(mediaDPI, media); + + // prepare @media { decl: } + const parentClone = parent.clone().removeAll(); + const declClone = decl.clone({ value: value.trim() }); + + parentClone.append(declClone); + media.append(parentClone); + + index += 3; + } + + const medias = Array.from(mediasByDpr.keys()) + .sort((a, b) => a - b) + .map(params => mediasByDpr.get(params)); + + // conditionally prepend previous siblings + if (!medias.length) { + return; + } + + parent.after(medias); + + if (opts.preserve) { + const firstDecl = (medias[0].nodes[0] as Container).nodes[0] as Declaration; + decl.cloneBefore({ value: firstDecl.value.trim() }); + } else { + decl.remove(); + + // and then conditionally remove its parent + if (!parent.nodes.length) { + parent.remove(); + } + } +}; diff --git a/plugins/postcss-image-set-function/test/basic.expect.css b/plugins/postcss-image-set-function/test/basic.expect.css index a9c288200..994af8964 100644 --- a/plugins/postcss-image-set-function/test/basic.expect.css +++ b/plugins/postcss-image-set-function/test/basic.expect.css @@ -8,176 +8,206 @@ .test-changed-properties { order: 1; - background-image: - url(img/test.png); + background-image: url(img/test.png); + background-image: image-set( + url(img/test.png) 1x + ); order: 2; - background-image: - url(img/test.png); + background-image: url(img/test.png); + background-image: image-set( + url(img/test.png) 2x + ); order: 3; - background-image: - url(img/test.png); -} - -@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) { - -.test-changed-properties { - background-image: - url(img/test-2x.png); -} -} - -.test-changed-properties { + background-image: url(img/test.png); background-image: image-set( url(img/test.png) 1x, url(img/test-2x.png) 2x ); order: 4; - background-image: - url(img/test.png); + background-image: url(img/test.png); + background-image: image-set( + url(img/test.png) 1x, + url(img/test-2x.png) 2x, + url(my-img-print.png) 600dpi + ); + order: 5; +} + +@media (-webkit-min-device-pixel-ratio: 1), (min-resolution: 96dpi) { + +.test-changed-properties { + background-image: url(img/test.png); +} } @media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) { .test-changed-properties { - background-image: - url(img/test-2x.png); + background-image: url(img/test-2x.png); } } @media (-webkit-min-device-pixel-ratio: 6.25), (min-resolution: 600dpi) { .test-changed-properties { - background-image: - url(my-img-print.png); + background-image: url(my-img-print.png); } } +@media (-webkit-min-device-pixel-ratio: 1), (min-resolution: 96dpi) { + .test-changed-properties { - background-image: image-set( - url(img/test.png) 1x, - url(img/test-2x.png) 2x, - url(my-img-print.png) 600dpi - ); - order: 5; + background-image: url(img/test.png); +} } -.test-mixed-units { - order: 1; - background-image: - url(img/test.png); +@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) { + +.test-changed-properties { + background-image: url(img/test-2x.png); +} } @media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) { -.test-mixed-units { - background-image: - url(img/test-2x.png); +.test-changed-properties { + background-image: url(img/test.png); +} +} + +@media (-webkit-min-device-pixel-ratio: 1), (min-resolution: 96dpi) { + +.test-changed-properties { + background-image: url(img/test.png); } } .test-mixed-units { + order: 1; + background-image: url(img/test.png); background-image: image-set( url(img/test.png) 1x, url(img/test-2x.png) 2dppx ); order: 2; - background-image: - url(img/test-2x.png); + background-image: url(img/test-2x.png); + background-image: image-set( + url(img/test.png) 1x, + url(img/test-2x.png) 20dpcm + ); + order: 3; } -@media (-webkit-min-device-pixel-ratio: 1), (min-resolution: 96dpi) { +@media (-webkit-min-device-pixel-ratio: 0.52), (min-resolution: 50.8dpi) { .test-mixed-units { - background-image: - url(img/test.png); + background-image: url(img/test-2x.png); } } +@media (-webkit-min-device-pixel-ratio: 1), (min-resolution: 96dpi) { + .test-mixed-units { - background-image: image-set( - url(img/test.png) 1x, - url(img/test-2x.png) 20dpcm - ); - order: 3; + background-image: url(img/test.png); } - -.test-mixed-order { - order: 1; - background: - url(../images/bck.png); } -@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) { +@media (-webkit-min-device-pixel-ratio: 1), (min-resolution: 96dpi) { -.test-mixed-order { - background: - url(../images/bck@2x.png); +.test-mixed-units { + background-image: url(img/test.png); } } -@media (-webkit-min-device-pixel-ratio: 3), (min-resolution: 288dpi) { +@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) { -.test-mixed-order { - background: - url(../images/bck@3x.png); +.test-mixed-units { + background-image: url(img/test-2x.png); } } .test-mixed-order { + order: 1; + background: url(../images/bck.png); background: image-set( url(../images/bck@3x.png) 3x, url(../images/bck.png) 1x, url(../images/bck@2x.png) 2x ); order: 2; - background: - url(../images/bck.png); + background: url(../images/bck.png); + background: image-set( + url(../images/bck@2x.png) 2x, + url(../images/bck@3x.png) 3x, + url(../images/bck.png) 1x + ); + order: 3; +} + +@media (-webkit-min-device-pixel-ratio: 1), (min-resolution: 96dpi) { + +.test-mixed-order { + background: url(../images/bck.png); +} } @media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) { .test-mixed-order { - background: - url(../images/bck@2x.png); + background: url(../images/bck@2x.png); } } @media (-webkit-min-device-pixel-ratio: 3), (min-resolution: 288dpi) { .test-mixed-order { - background: - url(../images/bck@3x.png); + background: url(../images/bck@3x.png); } } +@media (-webkit-min-device-pixel-ratio: 1), (min-resolution: 96dpi) { + .test-mixed-order { - background: image-set( - url(../images/bck@2x.png) 2x, - url(../images/bck@3x.png) 3x, - url(../images/bck.png) 1x - ); - order: 3; + background: url(../images/bck.png); } - -.test-no-url { - order: 1; - background-image: "img/test.png"; } @media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) { -.test-no-url { - background-image: "img/test-2x.png"; +.test-mixed-order { + background: url(../images/bck@2x.png); +} +} + +@media (-webkit-min-device-pixel-ratio: 3), (min-resolution: 288dpi) { + +.test-mixed-order { + background: url(../images/bck@3x.png); } } .test-no-url { + order: 1; + background-image: "img/test.png"; background-image: image-set( "img/test.png" 1x, "img/test-2x.png" 2x ); order: 2; background-image: "img/test.png"; + background-image: image-set( + "img/test.png" 1x, + "img/test-2x.png" 2x, + "my-img-print.png" 600dpi + ); + order: 3; +} + +@media (-webkit-min-device-pixel-ratio: 1), (min-resolution: 96dpi) { + +.test-no-url { + background-image: "img/test.png"; +} } @media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) { @@ -194,95 +224,101 @@ } } +@media (-webkit-min-device-pixel-ratio: 1), (min-resolution: 96dpi) { + .test-no-url { - background-image: image-set( - "img/test.png" 1x, - "img/test-2x.png" 2x, - "my-img-print.png" 600dpi - ); - order: 3; + background-image: "img/test.png"; +} +} + +@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) { + +.test-no-url { + background-image: "img/test-2x.png"; +} } .test-webkit-prefix { order: 1; - background-image: - url(img/test.png); + background-image: url(img/test.png); + background-image: -webkit-image-set( + url(img/test.png) 1x, + url(img/test-2x.png) 2x, + url(my-img-print.png) 600dpi + ); + order: 2; } -@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) { +@media (-webkit-min-device-pixel-ratio: 1), (min-resolution: 96dpi) { .test-webkit-prefix { - background-image: - url(img/test-2x.png); + background-image: url(img/test.png); } } -@media (-webkit-min-device-pixel-ratio: 6.25), (min-resolution: 600dpi) { +@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) { .test-webkit-prefix { - background-image: - url(my-img-print.png); + background-image: url(img/test-2x.png); } } +@media (-webkit-min-device-pixel-ratio: 6.25), (min-resolution: 600dpi) { + .test-webkit-prefix { - background-image: -webkit-image-set( - url(img/test.png) 1x, - url(img/test-2x.png) 2x, - url(my-img-print.png) 600dpi - ); - order: 2; + background-image: url(my-img-print.png); +} } @media (min-width: 1000px) { .test-within-mq-1 { - background-image: - url(img/test.png); + background-image: url(img/test.png); + background-image: image-set( + url(img/test.png) 1x, + url(img/test-2x.png) 2x, + url(my-img-print.png) 600dpi + ); + } + @media (-webkit-min-device-pixel-ratio: 1), (min-resolution: 96dpi) { + .test-within-mq-1 { + background-image: url(img/test.png); + } } @media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) { .test-within-mq-1 { - background-image: - url(img/test-2x.png); + background-image: url(img/test-2x.png); } } @media (-webkit-min-device-pixel-ratio: 6.25), (min-resolution: 600dpi) { .test-within-mq-1 { - background-image: - url(my-img-print.png); + background-image: url(my-img-print.png); } } - .test-within-mq-1 { +} + +@media (min-width: 768px) and (max-width: 1024px) { + .test-within-mq-2 { + background-image: url(img/test.png); background-image: image-set( url(img/test.png) 1x, url(img/test-2x.png) 2x, url(my-img-print.png) 600dpi ); } -} - -@media (min-width: 768px) and (max-width: 1024px) { + @media (-webkit-min-device-pixel-ratio: 1), (min-resolution: 96dpi) { .test-within-mq-2 { - background-image: - url(img/test.png); + background-image: url(img/test.png); + } } @media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) { .test-within-mq-2 { - background-image: - url(img/test-2x.png); + background-image: url(img/test-2x.png); } } @media (-webkit-min-device-pixel-ratio: 6.25), (min-resolution: 600dpi) { .test-within-mq-2 { - background-image: - url(my-img-print.png); - } + background-image: url(my-img-print.png); } - .test-within-mq-2 { - background-image: image-set( - url(img/test.png) 1x, - url(img/test-2x.png) 2x, - url(my-img-print.png) 600dpi - ); } } diff --git a/plugins/postcss-image-set-function/test/basic.no-preserve.expect.css b/plugins/postcss-image-set-function/test/basic.no-preserve.expect.css index f97a6ccf3..aed324385 100644 --- a/plugins/postcss-image-set-function/test/basic.no-preserve.expect.css +++ b/plugins/postcss-image-set-function/test/basic.no-preserve.expect.css @@ -8,134 +8,155 @@ .test-changed-properties { order: 1; - background-image: - url(img/test.png); order: 2; - background-image: - url(img/test.png); order: 3; - background-image: - url(img/test.png); + order: 4; + order: 5; +} + +@media (-webkit-min-device-pixel-ratio: 1), (min-resolution: 96dpi) { + +.test-changed-properties { + background-image: url(img/test.png); +} } @media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) { .test-changed-properties { - background-image: - url(img/test-2x.png); + background-image: url(img/test-2x.png); } } +@media (-webkit-min-device-pixel-ratio: 6.25), (min-resolution: 600dpi) { + .test-changed-properties { - order: 4; - background-image: - url(img/test.png); + background-image: url(my-img-print.png); +} +} + +@media (-webkit-min-device-pixel-ratio: 1), (min-resolution: 96dpi) { + +.test-changed-properties { + background-image: url(img/test.png); +} } @media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) { .test-changed-properties { - background-image: - url(img/test-2x.png); + background-image: url(img/test-2x.png); } } -@media (-webkit-min-device-pixel-ratio: 6.25), (min-resolution: 600dpi) { +@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) { .test-changed-properties { - background-image: - url(my-img-print.png); + background-image: url(img/test.png); } } +@media (-webkit-min-device-pixel-ratio: 1), (min-resolution: 96dpi) { + .test-changed-properties { - order: 5; + background-image: url(img/test.png); +} } .test-mixed-units { order: 1; - background-image: - url(img/test.png); + order: 2; + order: 3; } -@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) { +@media (-webkit-min-device-pixel-ratio: 0.52), (min-resolution: 50.8dpi) { .test-mixed-units { - background-image: - url(img/test-2x.png); + background-image: url(img/test-2x.png); } } +@media (-webkit-min-device-pixel-ratio: 1), (min-resolution: 96dpi) { + .test-mixed-units { - order: 2; - background-image: - url(img/test-2x.png); + background-image: url(img/test.png); +} } @media (-webkit-min-device-pixel-ratio: 1), (min-resolution: 96dpi) { .test-mixed-units { - background-image: - url(img/test.png); + background-image: url(img/test.png); } } +@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) { + .test-mixed-units { - order: 3; + background-image: url(img/test-2x.png); +} } .test-mixed-order { order: 1; - background: - url(../images/bck.png); + order: 2; + order: 3; +} + +@media (-webkit-min-device-pixel-ratio: 1), (min-resolution: 96dpi) { + +.test-mixed-order { + background: url(../images/bck.png); +} } @media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) { .test-mixed-order { - background: - url(../images/bck@2x.png); + background: url(../images/bck@2x.png); } } @media (-webkit-min-device-pixel-ratio: 3), (min-resolution: 288dpi) { .test-mixed-order { - background: - url(../images/bck@3x.png); + background: url(../images/bck@3x.png); } } +@media (-webkit-min-device-pixel-ratio: 1), (min-resolution: 96dpi) { + .test-mixed-order { - order: 2; - background: - url(../images/bck.png); + background: url(../images/bck.png); +} } @media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) { .test-mixed-order { - background: - url(../images/bck@2x.png); + background: url(../images/bck@2x.png); } } @media (-webkit-min-device-pixel-ratio: 3), (min-resolution: 288dpi) { .test-mixed-order { - background: - url(../images/bck@3x.png); + background: url(../images/bck@3x.png); } } -.test-mixed-order { +.test-no-url { + order: 1; + order: 2; order: 3; } +@media (-webkit-min-device-pixel-ratio: 1), (min-resolution: 96dpi) { + .test-no-url { - order: 1; background-image: "img/test.png"; } +} @media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) { @@ -144,89 +165,85 @@ } } -.test-no-url { - order: 2; - background-image: "img/test.png"; -} - -@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) { +@media (-webkit-min-device-pixel-ratio: 6.25), (min-resolution: 600dpi) { .test-no-url { - background-image: "img/test-2x.png"; + background-image: "my-img-print.png"; } } -@media (-webkit-min-device-pixel-ratio: 6.25), (min-resolution: 600dpi) { +@media (-webkit-min-device-pixel-ratio: 1), (min-resolution: 96dpi) { .test-no-url { - background-image: "my-img-print.png"; + background-image: "img/test.png"; } } +@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) { + .test-no-url { - order: 3; + background-image: "img/test-2x.png"; +} } .test-webkit-prefix { order: 1; - background-image: - url(img/test.png); + order: 2; } -@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) { +@media (-webkit-min-device-pixel-ratio: 1), (min-resolution: 96dpi) { .test-webkit-prefix { - background-image: - url(img/test-2x.png); + background-image: url(img/test.png); } } -@media (-webkit-min-device-pixel-ratio: 6.25), (min-resolution: 600dpi) { +@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) { .test-webkit-prefix { - background-image: - url(my-img-print.png); + background-image: url(img/test-2x.png); } } +@media (-webkit-min-device-pixel-ratio: 6.25), (min-resolution: 600dpi) { + .test-webkit-prefix { - order: 2; + background-image: url(my-img-print.png); +} } @media (min-width: 1000px) { + @media (-webkit-min-device-pixel-ratio: 1), (min-resolution: 96dpi) { .test-within-mq-1 { - background-image: - url(img/test.png); + background-image: url(img/test.png); + } } @media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) { .test-within-mq-1 { - background-image: - url(img/test-2x.png); + background-image: url(img/test-2x.png); } } @media (-webkit-min-device-pixel-ratio: 6.25), (min-resolution: 600dpi) { .test-within-mq-1 { - background-image: - url(my-img-print.png); + background-image: url(my-img-print.png); } } } @media (min-width: 768px) and (max-width: 1024px) { + @media (-webkit-min-device-pixel-ratio: 1), (min-resolution: 96dpi) { .test-within-mq-2 { - background-image: - url(img/test.png); + background-image: url(img/test.png); + } } @media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) { .test-within-mq-2 { - background-image: - url(img/test-2x.png); + background-image: url(img/test-2x.png); } } @media (-webkit-min-device-pixel-ratio: 6.25), (min-resolution: 600dpi) { .test-within-mq-2 { - background-image: - url(my-img-print.png); + background-image: url(my-img-print.png); } } } diff --git a/plugins/postcss-base-plugin/tsconfig.json b/plugins/postcss-image-set-function/tsconfig.json similarity index 100% rename from plugins/postcss-base-plugin/tsconfig.json rename to plugins/postcss-image-set-function/tsconfig.json diff --git a/rollup/default.ts.js b/rollup/default.ts.js index 7d0df0606..769443ea5 100644 --- a/rollup/default.ts.js +++ b/rollup/default.ts.js @@ -31,7 +31,7 @@ export default [ }], ], }), - terser(), + // terser(), ], }, { From ef6ed60babef27f85c5e0d9a82d260b862ba46f0 Mon Sep 17 00:00:00 2001 From: romainmenke Date: Sat, 27 Nov 2021 15:00:10 +0100 Subject: [PATCH 3/4] cleanup --- rollup/default.ts.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rollup/default.ts.js b/rollup/default.ts.js index 769443ea5..7d0df0606 100644 --- a/rollup/default.ts.js +++ b/rollup/default.ts.js @@ -31,7 +31,7 @@ export default [ }], ], }), - // terser(), + terser(), ], }, { From d99b755ba2ef318ce78f055bda78bedc09a48b90 Mon Sep 17 00:00:00 2001 From: romainmenke Date: Sat, 27 Nov 2021 15:00:35 +0100 Subject: [PATCH 4/4] cleanup --- plugins/postcss-base-plugin/tsconfig.json | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 plugins/postcss-base-plugin/tsconfig.json diff --git a/plugins/postcss-base-plugin/tsconfig.json b/plugins/postcss-base-plugin/tsconfig.json new file mode 100644 index 000000000..68a2606f6 --- /dev/null +++ b/plugins/postcss-base-plugin/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "dist", + "declarationDir": "." + }, + "include": ["./src/**/*"], + "exclude": ["dist"], +}