From fd34926c1bb6ec96b2a03cbbf32c85b2dab0f220 Mon Sep 17 00:00:00 2001
From: Antonio Laguna
Date: Wed, 11 May 2022 06:54:12 +0200
Subject: [PATCH 01/17] Getting plugin started
---
package-lock.json | 22 +++
.../.gitignore | 6 +
.../postcss-trigonometric-functions/.nvmrc | 1 +
.../postcss-trigonometric-functions/.tape.mjs | 8 +
.../CHANGELOG.md | 5 +
.../INSTALL.md | 176 ++++++++++++++++++
.../LICENSE.md | 108 +++++++++++
.../postcss-trigonometric-functions/README.md | 97 ++++++++++
.../docs/README.md | 51 +++++
.../package.json | 87 +++++++++
.../src/asin.ts | 34 ++++
.../src/cos.ts | 28 +++
.../src/index.ts | 61 ++++++
.../src/sin.ts | 28 +++
.../src/tan.ts | 28 +++
.../src/utils.ts | 94 ++++++++++
.../test/_import.mjs | 6 +
.../test/_require.cjs | 6 +
.../test/basic.css | 82 ++++++++
.../test/basic.expect.css | 63 +++++++
.../test/examples/example.css | 7 +
.../test/examples/example.expect.css | 7 +
.../examples/example.preserve-true.expect.css | 8 +
.../tsconfig.json | 9 +
24 files changed, 1022 insertions(+)
create mode 100644 plugins/postcss-trigonometric-functions/.gitignore
create mode 100644 plugins/postcss-trigonometric-functions/.nvmrc
create mode 100644 plugins/postcss-trigonometric-functions/.tape.mjs
create mode 100644 plugins/postcss-trigonometric-functions/CHANGELOG.md
create mode 100644 plugins/postcss-trigonometric-functions/INSTALL.md
create mode 100644 plugins/postcss-trigonometric-functions/LICENSE.md
create mode 100644 plugins/postcss-trigonometric-functions/README.md
create mode 100644 plugins/postcss-trigonometric-functions/docs/README.md
create mode 100644 plugins/postcss-trigonometric-functions/package.json
create mode 100644 plugins/postcss-trigonometric-functions/src/asin.ts
create mode 100644 plugins/postcss-trigonometric-functions/src/cos.ts
create mode 100644 plugins/postcss-trigonometric-functions/src/index.ts
create mode 100644 plugins/postcss-trigonometric-functions/src/sin.ts
create mode 100644 plugins/postcss-trigonometric-functions/src/tan.ts
create mode 100644 plugins/postcss-trigonometric-functions/src/utils.ts
create mode 100644 plugins/postcss-trigonometric-functions/test/_import.mjs
create mode 100644 plugins/postcss-trigonometric-functions/test/_require.cjs
create mode 100644 plugins/postcss-trigonometric-functions/test/basic.css
create mode 100644 plugins/postcss-trigonometric-functions/test/basic.expect.css
create mode 100644 plugins/postcss-trigonometric-functions/test/examples/example.css
create mode 100644 plugins/postcss-trigonometric-functions/test/examples/example.expect.css
create mode 100644 plugins/postcss-trigonometric-functions/test/examples/example.preserve-true.expect.css
create mode 100644 plugins/postcss-trigonometric-functions/tsconfig.json
diff --git a/package-lock.json b/package-lock.json
index 122285017..da3ed720e 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1808,6 +1808,10 @@
"resolved": "packages/postcss-tape",
"link": true
},
+ "node_modules/@csstools/postcss-trigonometric-functions": {
+ "resolved": "plugins/postcss-trigonometric-functions",
+ "link": true
+ },
"node_modules/@csstools/postcss-unset-value": {
"resolved": "plugins/postcss-unset-value",
"link": true
@@ -7221,6 +7225,20 @@
"postcss": "^8.3"
}
},
+ "plugins/postcss-trigonometric-functions": {
+ "version": "1.0.0",
+ "license": "CC0-1.0",
+ "engines": {
+ "node": "^12 || ^14 || >=16"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ },
+ "peerDependencies": {
+ "postcss": "^8.3"
+ }
+ },
"plugins/postcss-unset-value": {
"name": "@csstools/postcss-unset-value",
"version": "1.0.0",
@@ -8505,6 +8523,10 @@
"postcss-8.2": "npm:postcss@~8.2"
}
},
+ "@csstools/postcss-trigonometric-functions": {
+ "version": "file:plugins/postcss-trigonometric-functions",
+ "requires": {}
+ },
"@csstools/postcss-unset-value": {
"version": "file:plugins/postcss-unset-value",
"requires": {}
diff --git a/plugins/postcss-trigonometric-functions/.gitignore b/plugins/postcss-trigonometric-functions/.gitignore
new file mode 100644
index 000000000..7172b04f1
--- /dev/null
+++ b/plugins/postcss-trigonometric-functions/.gitignore
@@ -0,0 +1,6 @@
+node_modules
+package-lock.json
+yarn.lock
+*.result.css
+*.result.css.map
+dist/*
diff --git a/plugins/postcss-trigonometric-functions/.nvmrc b/plugins/postcss-trigonometric-functions/.nvmrc
new file mode 100644
index 000000000..f0b10f153
--- /dev/null
+++ b/plugins/postcss-trigonometric-functions/.nvmrc
@@ -0,0 +1 @@
+v16.13.1
diff --git a/plugins/postcss-trigonometric-functions/.tape.mjs b/plugins/postcss-trigonometric-functions/.tape.mjs
new file mode 100644
index 000000000..cda74a20c
--- /dev/null
+++ b/plugins/postcss-trigonometric-functions/.tape.mjs
@@ -0,0 +1,8 @@
+import postcssTape from '../../packages/postcss-tape/dist/index.mjs';
+import plugin from '@csstools/postcss-trigonometric-functions';
+
+postcssTape(plugin)({
+ basic: {
+ message: "supports basic usage",
+ },
+});
diff --git a/plugins/postcss-trigonometric-functions/CHANGELOG.md b/plugins/postcss-trigonometric-functions/CHANGELOG.md
new file mode 100644
index 000000000..4b356ffb0
--- /dev/null
+++ b/plugins/postcss-trigonometric-functions/CHANGELOG.md
@@ -0,0 +1,5 @@
+# Changes to PostCSS Trigonometric Functions
+
+### 1.0.0 (Unreleased)
+
+- Initial version
diff --git a/plugins/postcss-trigonometric-functions/INSTALL.md b/plugins/postcss-trigonometric-functions/INSTALL.md
new file mode 100644
index 000000000..dab91f1a1
--- /dev/null
+++ b/plugins/postcss-trigonometric-functions/INSTALL.md
@@ -0,0 +1,176 @@
+# Installing PostCSS Trigonometric Functions
+
+[PostCSS Trigonometric Functions] runs in all Node environments, with special instructions for:
+
+| [Node](#node) | [PostCSS CLI](#postcss-cli) | [Webpack](#webpack) | [Create React App](#create-react-app) | [Gulp](#gulp) | [Grunt](#grunt) |
+| --- | --- | --- | --- | --- | --- |
+
+## Node
+
+Add [PostCSS Trigonometric Functions] to your project:
+
+```bash
+npm install postcss @csstools/postcss-trigonometric-functions --save-dev
+```
+
+Use it as a [PostCSS] plugin:
+
+```js
+const postcss = require('postcss');
+const postcssBasePlugin = require('@csstools/postcss-trigonometric-functions');
+
+postcss([
+ postcssBasePlugin(/* pluginOptions */)
+]).process(YOUR_CSS /*, processOptions */);
+```
+
+## PostCSS CLI
+
+Add [PostCSS CLI] to your project:
+
+```bash
+npm install postcss-cli @csstools/postcss-trigonometric-functions --save-dev
+```
+
+Use [PostCSS Trigonometric Functions] in your `postcss.config.js` configuration file:
+
+```js
+const postcssBasePlugin = require('@csstools/postcss-trigonometric-functions');
+
+module.exports = {
+ plugins: [
+ postcssBasePlugin(/* pluginOptions */)
+ ]
+}
+```
+
+## Webpack
+
+_Webpack version 5_
+
+Add [PostCSS Loader] to your project:
+
+```bash
+npm install postcss-loader @csstools/postcss-trigonometric-functions --save-dev
+```
+
+Use [PostCSS Trigonometric Functions] in your Webpack configuration:
+
+```js
+module.exports = {
+ module: {
+ rules: [
+ {
+ test: /\.css$/i,
+ use: [
+ "style-loader",
+ {
+ loader: "css-loader",
+ options: { importLoaders: 1 },
+ },
+ {
+ loader: "postcss-loader",
+ options: {
+ postcssOptions: {
+ plugins: [
+ [
+ "@csstools/postcss-trigonometric-functions",
+ {
+ // Options
+ },
+ ],
+ ],
+ },
+ },
+ },
+ ],
+ },
+ ],
+ },
+};
+```
+
+## Create React App
+
+Add [React App Rewired] and [React App Rewire PostCSS] to your project:
+
+```bash
+npm install react-app-rewired react-app-rewire-postcss @csstools/postcss-trigonometric-functions --save-dev
+```
+
+Use [React App Rewire PostCSS] and [PostCSS Trigonometric Functions] in your
+`config-overrides.js` file:
+
+```js
+const reactAppRewirePostcss = require('react-app-rewire-postcss');
+const postcssBasePlugin = require('@csstools/postcss-trigonometric-functions');
+
+module.exports = config => reactAppRewirePostcss(config, {
+ plugins: () => [
+ postcssBasePlugin(/* pluginOptions */)
+ ]
+});
+```
+
+## Gulp
+
+Add [Gulp PostCSS] to your project:
+
+```bash
+npm install gulp-postcss @csstools/postcss-trigonometric-functions --save-dev
+```
+
+Use [PostCSS Trigonometric Functions] in your Gulpfile:
+
+```js
+const postcss = require('gulp-postcss');
+const postcssBasePlugin = require('@csstools/postcss-trigonometric-functions');
+
+gulp.task('css', function () {
+ var plugins = [
+ postcssBasePlugin(/* pluginOptions */)
+ ];
+
+ return gulp.src('./src/*.css')
+ .pipe(postcss(plugins))
+ .pipe(gulp.dest('.'));
+});
+```
+
+## Grunt
+
+Add [Grunt PostCSS] to your project:
+
+```bash
+npm install grunt-postcss @csstools/postcss-trigonometric-functions --save-dev
+```
+
+Use [PostCSS Trigonometric Functions] in your Gruntfile:
+
+```js
+const postcssBasePlugin = require('@csstools/postcss-trigonometric-functions');
+
+grunt.loadNpmTasks('grunt-postcss');
+
+grunt.initConfig({
+ postcss: {
+ options: {
+ processors: [
+ postcssBasePlugin(/* pluginOptions */)
+ ]
+ },
+ dist: {
+ src: '*.css'
+ }
+ }
+});
+```
+
+[Gulp PostCSS]: https://github.com/postcss/gulp-postcss
+[Grunt PostCSS]: https://github.com/nDmitry/grunt-postcss
+[PostCSS]: https://github.com/postcss/postcss
+[PostCSS CLI]: https://github.com/postcss/postcss-cli
+[PostCSS Loader]: https://github.com/postcss/postcss-loader
+[PostCSS Trigonometric Functions]: https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-trigonometric-functions
+[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-trigonometric-functions/LICENSE.md b/plugins/postcss-trigonometric-functions/LICENSE.md
new file mode 100644
index 000000000..0bc1fa706
--- /dev/null
+++ b/plugins/postcss-trigonometric-functions/LICENSE.md
@@ -0,0 +1,108 @@
+# CC0 1.0 Universal
+
+## Statement of Purpose
+
+The laws of most jurisdictions throughout the world automatically confer
+exclusive Copyright and Related Rights (defined below) upon the creator and
+subsequent owner(s) (each and all, an “owner”) of an original work of
+authorship and/or a database (each, a “Work”).
+
+Certain owners wish to permanently relinquish those rights to a Work for the
+purpose of contributing to a commons of creative, cultural and scientific works
+(“Commons”) that the public can reliably and without fear of later claims of
+infringement build upon, modify, incorporate in other works, reuse and
+redistribute as freely as possible in any form whatsoever and for any purposes,
+including without limitation commercial purposes. These owners may contribute
+to the Commons to promote the ideal of a free culture and the further
+production of creative, cultural and scientific works, or to gain reputation or
+greater distribution for their Work in part through the use and efforts of
+others.
+
+For these and/or other purposes and motivations, and without any expectation of
+additional consideration or compensation, the person associating CC0 with a
+Work (the “Affirmer”), to the extent that he or she is an owner of Copyright
+and Related Rights in the Work, voluntarily elects to apply CC0 to the Work and
+publicly distribute the Work under its terms, with knowledge of his or her
+Copyright and Related Rights in the Work and the meaning and intended legal
+effect of CC0 on those rights.
+
+1. Copyright and Related Rights. A Work made available under CC0 may be
+ protected by copyright and related or neighboring rights (“Copyright and
+ Related Rights”). Copyright and Related Rights include, but are not limited
+ to, the following:
+ 1. the right to reproduce, adapt, distribute, perform, display, communicate,
+ and translate a Work;
+ 2. moral rights retained by the original author(s) and/or performer(s);
+ 3. publicity and privacy rights pertaining to a person’s image or likeness
+ depicted in a Work;
+ 4. rights protecting against unfair competition in regards to a Work,
+ subject to the limitations in paragraph 4(i), below;
+ 5. rights protecting the extraction, dissemination, use and reuse of data in
+ a Work;
+ 6. database rights (such as those arising under Directive 96/9/EC of the
+ European Parliament and of the Council of 11 March 1996 on the legal
+ protection of databases, and under any national implementation thereof,
+ including any amended or successor version of such directive); and
+ 7. other similar, equivalent or corresponding rights throughout the world
+ based on applicable law or treaty, and any national implementations
+ thereof.
+
+2. Waiver. To the greatest extent permitted by, but not in contravention of,
+ applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and
+ unconditionally waives, abandons, and surrenders all of Affirmer’s Copyright
+ and Related Rights and associated claims and causes of action, whether now
+ known or unknown (including existing as well as future claims and causes of
+ action), in the Work (i) in all territories worldwide, (ii) for the maximum
+ duration provided by applicable law or treaty (including future time
+ extensions), (iii) in any current or future medium and for any number of
+ copies, and (iv) for any purpose whatsoever, including without limitation
+ commercial, advertising or promotional purposes (the “Waiver”). Affirmer
+ makes the Waiver for the benefit of each member of the public at large and
+ to the detriment of Affirmer’s heirs and successors, fully intending that
+ such Waiver shall not be subject to revocation, rescission, cancellation,
+ termination, or any other legal or equitable action to disrupt the quiet
+ enjoyment of the Work by the public as contemplated by Affirmer’s express
+ Statement of Purpose.
+
+3. Public License Fallback. Should any part of the Waiver for any reason be
+ judged legally invalid or ineffective under applicable law, then the Waiver
+ shall be preserved to the maximum extent permitted taking into account
+ Affirmer’s express Statement of Purpose. In addition, to the extent the
+ Waiver is so judged Affirmer hereby grants to each affected person a
+ royalty-free, non transferable, non sublicensable, non exclusive,
+ irrevocable and unconditional license to exercise Affirmer’s Copyright and
+ Related Rights in the Work (i) in all territories worldwide, (ii) for the
+ maximum duration provided by applicable law or treaty (including future time
+ extensions), (iii) in any current or future medium and for any number of
+ copies, and (iv) for any purpose whatsoever, including without limitation
+ commercial, advertising or promotional purposes (the “License”). The License
+ shall be deemed effective as of the date CC0 was applied by Affirmer to the
+ Work. Should any part of the License for any reason be judged legally
+ invalid or ineffective under applicable law, such partial invalidity or
+ ineffectiveness shall not invalidate the remainder of the License, and in
+ such case Affirmer hereby affirms that he or she will not (i) exercise any
+ of his or her remaining Copyright and Related Rights in the Work or (ii)
+ assert any associated claims and causes of action with respect to the Work,
+ in either case contrary to Affirmer’s express Statement of Purpose.
+
+4. Limitations and Disclaimers.
+ 1. No trademark or patent rights held by Affirmer are waived, abandoned,
+ surrendered, licensed or otherwise affected by this document.
+ 2. Affirmer offers the Work as-is and makes no representations or warranties
+ of any kind concerning the Work, express, implied, statutory or
+ otherwise, including without limitation warranties of title,
+ merchantability, fitness for a particular purpose, non infringement, or
+ the absence of latent or other defects, accuracy, or the present or
+ absence of errors, whether or not discoverable, all to the greatest
+ extent permissible under applicable law.
+ 3. Affirmer disclaims responsibility for clearing rights of other persons
+ that may apply to the Work or any use thereof, including without
+ limitation any person’s Copyright and Related Rights in the Work.
+ Further, Affirmer disclaims responsibility for obtaining any necessary
+ consents, permissions or other rights required for any use of the Work.
+ 4. Affirmer understands and acknowledges that Creative Commons is not a
+ party to this document and has no duty or obligation with respect to this
+ CC0 or use of the Work.
+
+For more information, please see
+http://creativecommons.org/publicdomain/zero/1.0/.
diff --git a/plugins/postcss-trigonometric-functions/README.md b/plugins/postcss-trigonometric-functions/README.md
new file mode 100644
index 000000000..4a81de958
--- /dev/null
+++ b/plugins/postcss-trigonometric-functions/README.md
@@ -0,0 +1,97 @@
+# PostCSS Trigonometric Functions [
][postcss]
+
+[
][npm-url]
+[
][css-url]
+[
][cli-url]
+[
][discord]
+
+[PostCSS Trigonometric Functions] lets easily create new plugins following some [CSS Specification].
+
+```pcss
+.foo {
+ color: red;
+}
+
+.baz {
+ color: green;
+}
+
+/* becomes */
+
+.foo {
+ color: blue;
+}
+
+.baz {
+ color: green;
+}
+```
+
+## Usage
+
+Add [PostCSS Trigonometric Functions] to your project:
+
+```bash
+npm install postcss @csstools/postcss-trigonometric-functions --save-dev
+```
+
+Use it as a [PostCSS] plugin:
+
+```js
+const postcss = require('postcss');
+const postcssBasePlugin = require('@csstools/postcss-trigonometric-functions');
+
+postcss([
+ postcssBasePlugin(/* pluginOptions */)
+]).process(YOUR_CSS /*, processOptions */);
+```
+
+[PostCSS Trigonometric Functions] runs in all Node environments, with special
+instructions for:
+
+| [Node](INSTALL.md#node) | [PostCSS CLI](INSTALL.md#postcss-cli) | [Webpack](INSTALL.md#webpack) | [Create React App](INSTALL.md#create-react-app) | [Gulp](INSTALL.md#gulp) | [Grunt](INSTALL.md#grunt) |
+| --- | --- | --- | --- | --- | --- |
+
+## Options
+
+### preserve
+
+The `preserve` option determines whether the original notation
+is preserved. By default, it is not preserved.
+
+```js
+postcssBasePlugin({ preserve: true })
+```
+
+```pcss
+.foo {
+ color: red;
+}
+
+.baz {
+ color: green;
+}
+
+/* becomes */
+
+.foo {
+ color: blue;
+ color: red;
+}
+
+.baz {
+ color: green;
+}
+```
+
+[cli-url]: https://github.com/csstools/postcss-plugins/actions/workflows/test.yml?query=workflow/test
+[css-url]: https://cssdb.org/#TODO
+[discord]: https://discord.gg/bUadyRwkJS
+[npm-url]: https://www.npmjs.com/package/@csstools/postcss-trigonometric-functions
+
+[Gulp PostCSS]: https://github.com/postcss/gulp-postcss
+[Grunt PostCSS]: https://github.com/nDmitry/grunt-postcss
+[PostCSS]: https://github.com/postcss/postcss
+[PostCSS Loader]: https://github.com/postcss/postcss-loader
+[PostCSS Trigonometric Functions]: https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-trigonometric-functions
+[CSS Specification]: #TODO
diff --git a/plugins/postcss-trigonometric-functions/docs/README.md b/plugins/postcss-trigonometric-functions/docs/README.md
new file mode 100644
index 000000000..3bc455892
--- /dev/null
+++ b/plugins/postcss-trigonometric-functions/docs/README.md
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+[] lets easily create new plugins following some [CSS Specification].
+
+```pcss
+
+
+/* becomes */
+
+
+```
+
+
+
+
+
+## Options
+
+### preserve
+
+The `preserve` option determines whether the original notation
+is preserved. By default, it is not preserved.
+
+```js
+({ preserve: true })
+```
+
+```pcss
+
+
+/* becomes */
+
+
+```
+
+
+[CSS Specification]:
diff --git a/plugins/postcss-trigonometric-functions/package.json b/plugins/postcss-trigonometric-functions/package.json
new file mode 100644
index 000000000..566cef784
--- /dev/null
+++ b/plugins/postcss-trigonometric-functions/package.json
@@ -0,0 +1,87 @@
+{
+ "name": "@csstools/postcss-trigonometric-functions",
+ "description": "TODO: Add description for Trigonometric Functions",
+ "version": "1.0.0",
+ "contributors": [
+ {
+ "name": "Antonio Laguna",
+ "email": "antonio@laguna.es",
+ "url": "https://antonio.laguna.es"
+ },
+ {
+ "name": "Romain Menke ",
+ "email": "romainmenke@gmail.com"
+ }
+ ],
+ "license": "CC0-1.0",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ },
+ "engines": {
+ "node": "^12 || ^14 || >=16"
+ },
+ "main": "dist/index.cjs",
+ "module": "dist/index.mjs",
+ "types": "dist/index.d.ts",
+ "exports": {
+ ".": {
+ "import": "./dist/index.mjs",
+ "require": "./dist/index.cjs",
+ "default": "./dist/index.mjs"
+ }
+ },
+ "files": [
+ "CHANGELOG.md",
+ "LICENSE.md",
+ "README.md",
+ "dist"
+ ],
+ "dependencies": {
+ "postcss-value-parser": "^4.2.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.3"
+ },
+ "scripts": {
+ "build": "rollup -c ../../rollup/default.js",
+ "clean": "node -e \"fs.rmSync('./dist', { recursive: true, force: true });\"",
+ "docs": "node ../../.github/bin/generate-docs/install.mjs && node ../../.github/bin/generate-docs/readme.mjs",
+ "lint": "npm run lint:eslint && npm run lint:package-json",
+ "lint:eslint": "eslint ./src --ext .js --ext .ts --ext .mjs --no-error-on-unmatched-pattern",
+ "lint:package-json": "node ../../.github/bin/format-package-json.mjs",
+ "prepublishOnly": "npm run clean && npm run build && npm run test",
+ "stryker": "stryker run --logLevel error",
+ "test": "node .tape.mjs && npm run test:exports",
+ "test:exports": "node ./test/_import.mjs && node ./test/_require.cjs",
+ "test:rewrite-expects": "REWRITE_EXPECTS=true node .tape.mjs"
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/csstools/postcss-plugins.git",
+ "directory": "plugins/postcss-trigonometric-functions"
+ },
+ "keywords": [
+ "postcss-plugin",
+ "trigonometric",
+ "css",
+ "sin",
+ "cos",
+ "tan",
+ "asin",
+ "atan",
+ "acos",
+ "acos2"
+ ],
+ "csstools": {
+ "cssdbId": "trigonometric-functions",
+ "exportName": "postcssTrigonometricFunctions",
+ "humanReadableName": "PostCSS Trigonometric Functions",
+ "specUrl": "https://www.w3.org/TR/css-values-4/#trig-funcs"
+ },
+ "volta": {
+ "extends": "../../package.json"
+ },
+ "homepage": "https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-trigonometric-functions#readme",
+ "bugs": "https://github.com/csstools/postcss-plugins/issues"
+}
diff --git a/plugins/postcss-trigonometric-functions/src/asin.ts b/plugins/postcss-trigonometric-functions/src/asin.ts
new file mode 100644
index 000000000..acbc150b5
--- /dev/null
+++ b/plugins/postcss-trigonometric-functions/src/asin.ts
@@ -0,0 +1,34 @@
+import type { Declaration } from 'postcss';
+import valueParser from 'postcss-value-parser';
+import { formatResultingNumber, radToDeg, validateNode } from './utils';
+
+const asinFunctionCheck = 'asin(';
+
+function transformAsinFunction(decl: Declaration): string | undefined {
+ const parsedValue = valueParser(decl.value);
+
+ parsedValue.walk(node => {
+ if (node.type !== 'function' || node.value !== 'asin') {
+ return;
+ }
+
+ const validated = validateNode(node, false);
+
+ if (!validated) {
+ return;
+ }
+
+ const [transformedNode, number] = validated;
+ let value: string | number = Math.asin(number);
+
+ if (!Number.isNaN(value) && typeof value === 'number') {
+ value = `${formatResultingNumber(radToDeg(value), 2)}deg`;
+ }
+
+ transformedNode.value = value + '';
+ });
+
+ return parsedValue.toString();
+}
+
+export { asinFunctionCheck, transformAsinFunction };
diff --git a/plugins/postcss-trigonometric-functions/src/cos.ts b/plugins/postcss-trigonometric-functions/src/cos.ts
new file mode 100644
index 000000000..489401589
--- /dev/null
+++ b/plugins/postcss-trigonometric-functions/src/cos.ts
@@ -0,0 +1,28 @@
+import type { Declaration } from 'postcss';
+import valueParser from 'postcss-value-parser';
+import { formatResultingNumber, validateNode } from './utils';
+
+const cosFunctionCheck = 'cos(';
+
+function transformCosFunction(decl: Declaration): string | undefined {
+ const parsedValue = valueParser(decl.value);
+
+ parsedValue.walk(node => {
+ if (node.type !== 'function' || node.value !== 'cos') {
+ return;
+ }
+
+ const validated = validateNode(node);
+
+ if (!validated) {
+ return;
+ }
+
+ const [transformedNode, number] = validated;
+ transformedNode.value = formatResultingNumber(Math.cos(number), 5);
+ });
+
+ return parsedValue.toString();
+}
+
+export { cosFunctionCheck, transformCosFunction };
diff --git a/plugins/postcss-trigonometric-functions/src/index.ts b/plugins/postcss-trigonometric-functions/src/index.ts
new file mode 100644
index 000000000..69fd21367
--- /dev/null
+++ b/plugins/postcss-trigonometric-functions/src/index.ts
@@ -0,0 +1,61 @@
+import type { PluginCreator } from 'postcss';
+import { sinFunctionCheck, transformSinFunction } from './sin';
+import { cosFunctionCheck, transformCosFunction } from './cos';
+import { tanFunctionCheck, transformTanFunction } from './tan';
+import { asinFunctionCheck, transformAsinFunction } from './asin';
+
+type pluginOptions = { preserve?: boolean };
+
+const Transformations = [
+ { check: sinFunctionCheck, transform: transformSinFunction },
+ { check: cosFunctionCheck, transform: transformCosFunction },
+ { check: tanFunctionCheck, transform: transformTanFunction },
+ { check: asinFunctionCheck, transform: transformAsinFunction },
+];
+
+const creator: PluginCreator = (opts?: pluginOptions) => {
+ const options = Object.assign(
+ // Default options
+ {
+ preserve: false,
+ },
+ // Provided options
+ opts,
+ );
+
+ return {
+ postcssPlugin: 'postcss-trigonometric-functions',
+ Declaration(decl) {
+ const transformations = Transformations.filter(
+ transformation => decl.value.includes(transformation.check),
+ );
+
+ if (!decl || transformations.length === 0) {
+ return;
+ }
+
+ const newDeclaration = decl.clone();
+
+ transformations.forEach(transformation => {
+ const modValue = transformation.transform(newDeclaration);
+
+ if (modValue) {
+ newDeclaration.value = modValue;
+ }
+ });
+
+ if (decl.value !== newDeclaration.value) {
+ if (options.preserve) {
+ decl.cloneBefore({ value: newDeclaration.value });
+ } else {
+ decl.value = newDeclaration.value;
+ }
+ }
+ },
+ };
+};
+
+creator.postcss = true;
+
+export default creator;
+
diff --git a/plugins/postcss-trigonometric-functions/src/sin.ts b/plugins/postcss-trigonometric-functions/src/sin.ts
new file mode 100644
index 000000000..53dad263f
--- /dev/null
+++ b/plugins/postcss-trigonometric-functions/src/sin.ts
@@ -0,0 +1,28 @@
+import type { Declaration } from 'postcss';
+import valueParser from 'postcss-value-parser';
+import { formatResultingNumber, validateNode } from './utils';
+
+const sinFunctionCheck = 'sin(';
+
+function transformSinFunction(decl: Declaration): string | undefined {
+ const parsedValue = valueParser(decl.value);
+
+ parsedValue.walk(node => {
+ if (node.type !== 'function' || node.value !== 'sin') {
+ return;
+ }
+
+ const validated = validateNode(node);
+
+ if (!validated) {
+ return;
+ }
+
+ const [transformedNode, number] = validated;
+ transformedNode.value = formatResultingNumber(Math.sin(number), 5);
+ });
+
+ return parsedValue.toString();
+}
+
+export { sinFunctionCheck, transformSinFunction };
diff --git a/plugins/postcss-trigonometric-functions/src/tan.ts b/plugins/postcss-trigonometric-functions/src/tan.ts
new file mode 100644
index 000000000..18685f684
--- /dev/null
+++ b/plugins/postcss-trigonometric-functions/src/tan.ts
@@ -0,0 +1,28 @@
+import type { Declaration } from 'postcss';
+import valueParser from 'postcss-value-parser';
+import { formatResultingNumber, validateNode } from './utils';
+
+const tanFunctionCheck = 'tan(';
+
+function transformTanFunction(decl: Declaration): string | undefined {
+ const parsedValue = valueParser(decl.value);
+
+ parsedValue.walk(node => {
+ if (node.type !== 'function' || node.value !== 'tan') {
+ return;
+ }
+
+ const validated = validateNode(node);
+
+ if (!validated) {
+ return;
+ }
+
+ const [transformedNode, number] = validated;
+ transformedNode.value = formatResultingNumber(Math.tan(number), 5);
+ });
+
+ return parsedValue.toString();
+}
+
+export { tanFunctionCheck, transformTanFunction };
diff --git a/plugins/postcss-trigonometric-functions/src/utils.ts b/plugins/postcss-trigonometric-functions/src/utils.ts
new file mode 100644
index 000000000..3f8e8ecff
--- /dev/null
+++ b/plugins/postcss-trigonometric-functions/src/utils.ts
@@ -0,0 +1,94 @@
+import type { FunctionNode, WordNode, Node } from 'postcss-value-parser';
+import valueParser from 'postcss-value-parser';
+
+export function turnToRad(turn: number): number {
+ return turn * 2 * Math.PI;
+}
+
+export function degToRad(deg: number): number {
+ return deg * (Math.PI / 180);
+}
+
+export function gradToRad(grad: number): number {
+ return grad * (Math.PI / 200);
+}
+
+export function radToDeg(rad: number): number {
+ return rad * ( 180 / Math.PI );
+}
+
+const toRad = {
+ turn: turnToRad,
+ deg: degToRad,
+ grad: gradToRad,
+};
+
+export function functionNodeToWordNode(fn: FunctionNode): WordNode {
+ delete fn.nodes;
+ const node = fn as Node;
+ node.type = 'word';
+
+ return node as WordNode;
+}
+
+export function formatResultingNumber(number: number, decimals: number): string {
+ if (!Number.isNaN(number)) {
+ if (number > Number.MAX_SAFE_INTEGER) {
+ return 'infinity';
+ } else if (number < Number.MIN_SAFE_INTEGER) {
+ return '-infinity';
+ }
+ }
+
+ return Number(number.toFixed(decimals)).toString();
+}
+
+export function validateNode(
+ node: FunctionNode,
+ parseUnit = true,
+ args = 1,
+): [WordNode,number] | undefined {
+ const words = node.nodes.filter(childNode => childNode.type === 'word');
+
+ if (words.length !== args) {
+ return;
+ }
+
+ const { value } = words[0];
+
+ const parsed = valueParser.unit(value);
+ let number;
+
+ if (value.toLowerCase() === 'infinity' ) {
+ number = Infinity;
+ } else if (value.toLowerCase() === '-infinity') {
+ number = Infinity * -1;
+ }
+
+ if (!parsed && !number) {
+ return;
+ }
+
+ if (parsed) {
+ number = Number(parsed.number);
+
+ if (parseUnit) {
+ if (parsed.unit && parsed.unit !== 'rad') {
+ if (toRad[parsed.unit]) {
+ number = toRad[parsed.unit](number);
+ } else {
+ return;
+ }
+ }
+ } else if (parsed.unit) {
+ return;
+ }
+ }
+
+ return [
+ functionNodeToWordNode(node),
+ number,
+ ];
+}
+
+export { toRad };
diff --git a/plugins/postcss-trigonometric-functions/test/_import.mjs b/plugins/postcss-trigonometric-functions/test/_import.mjs
new file mode 100644
index 000000000..a4098fe21
--- /dev/null
+++ b/plugins/postcss-trigonometric-functions/test/_import.mjs
@@ -0,0 +1,6 @@
+import assert from 'assert';
+import plugin from '@csstools/postcss-trigonometric-functions';
+plugin();
+
+assert.ok(plugin.postcss, 'should have "postcss flag"');
+assert.equal(typeof plugin, 'function', 'should return a function');
diff --git a/plugins/postcss-trigonometric-functions/test/_require.cjs b/plugins/postcss-trigonometric-functions/test/_require.cjs
new file mode 100644
index 000000000..52fb12fd2
--- /dev/null
+++ b/plugins/postcss-trigonometric-functions/test/_require.cjs
@@ -0,0 +1,6 @@
+const assert = require('assert');
+const plugin = require('@csstools/postcss-trigonometric-functions');
+plugin();
+
+assert.ok(plugin.postcss, 'should have "postcss flag"');
+assert.equal(typeof plugin, 'function', 'should return a function');
diff --git a/plugins/postcss-trigonometric-functions/test/basic.css b/plugins/postcss-trigonometric-functions/test/basic.css
new file mode 100644
index 000000000..3aa39fd41
--- /dev/null
+++ b/plugins/postcss-trigonometric-functions/test/basic.css
@@ -0,0 +1,82 @@
+.sin {
+ order: sin(45deg);
+ order: sin(.125turn);
+ order: sin(50grad);
+ order: sin(0.785398rad);
+ order: sin(0.785398);
+ order: sin(-45deg);
+ order: sin(-.125turn);
+ order: sin(-50grad);
+ order: sin(-0.785398rad);
+ order: sin(-0.785398);
+ order: sin(0);
+ order: sin(sin(0.785398));
+ order: sin(sin(sin(sin(0.785398))));
+ order: sin(1px);
+ order: sin(foo);
+ order: sin(Infinity);
+ order: sin(InFiNiTy);
+ order: sin(-infinity);
+ order: sin(3.14159 / 4);
+}
+
+.cos {
+ order: cos(45deg);
+ order: cos(.125turn);
+ order: cos(50grad);
+ order: cos(1rad);
+ order: cos(1);
+ order: cos(-45deg);
+ order: cos(-.125turn);
+ order: cos(-50grad);
+ order: cos(-0.785398rad);
+ order: cos(-0.785398);
+ order: cos(cos(0.785398));
+ order: cos(cos(cos(cos(0.785398))));
+ order: cos(1px);
+ order: cos(foo);
+ order: cos(Infinity);
+ order: cos(InFiNiTy);
+ order: cos(-infinity);
+ order: cos(3.14159 / 4);
+}
+
+.tan {
+ order: tan(45deg);
+ order: tan(90deg);
+ order: tan(-90deg);
+ order: tan(.125turn);
+ order: tan(50grad);
+ order: tan(1rad);
+ order: tan(1);
+ order: tan(-45deg);
+ order: tan(-.125turn);
+ order: tan(-50grad);
+ order: tan(-0.785398rad);
+ order: tan(-0.785398);
+ order: tan(0);
+ order: tan(tan(0.785398));
+ order: tan(tan(tan(tan(0.785398))));
+ order: tan(1px);
+ order: tan(foo);
+ order: tan(Infinity);
+ order: tan(InFiNiTy);
+ order: tan(-infinity);
+ order: tan(3.14159 / 4);
+}
+
+.asin {
+ order: asin(sin(45deg));
+ order: asin(-1);
+ order: asin(-0.5);
+ order: asin(0);
+ order: asin(0.5);
+ order: asin(1);
+ order: asin(2);
+ order: asin(-20);
+ order: asin(45deg);
+ order: asin(1rad);
+ order: asin(foo);
+ order: asin(infinity);
+ order: asin(-infinity);
+}
diff --git a/plugins/postcss-trigonometric-functions/test/basic.expect.css b/plugins/postcss-trigonometric-functions/test/basic.expect.css
new file mode 100644
index 000000000..d71b9d90f
--- /dev/null
+++ b/plugins/postcss-trigonometric-functions/test/basic.expect.css
@@ -0,0 +1,63 @@
+.sin {
+ order: 0.70711;
+ order: 0.70711;
+ order: 0.70711;
+ order: 0.70711;
+ order: 0.70711;
+ order: -0.70711;
+ order: -0.70711;
+ order: -0.70711;
+ order: -0.70711;
+ order: -0.70711;
+ order: 0;
+ order: 0.64964;
+ order: 0.56868;
+ order: sin(1px);
+ order: sin(foo);
+ order: NaN;
+ order: NaN;
+ order: sin(3.14159 / 4);
+}
+
+.cos {
+ order: 0.70711;
+ order: 0.70711;
+ order: 0.70711;
+ order: 0.5403;
+ order: 0.5403;
+ order: 0.70711;
+ order: 0.70711;
+ order: 0.70711;
+ order: 0.70711;
+ order: 0.70711;
+ order: 0.76024;
+ order: 0.74872;
+ order: cos(1px);
+ order: cos(foo);
+ order: NaN;
+ order: NaN;
+ order: cos(3.14159 / 4);
+}
+
+.tan {
+ order: 1;
+ order: infinity;
+ order: -infinity;
+ order: 1;
+ order: 1;
+ order: 1.55741;
+ order: 1.55741;
+ order: -1;
+ order: -1;
+ order: -1;
+ order: -1;
+ order: -1;
+ order: 0;
+ order: 1.55741;
+ order: -0.84159;
+ order: tan(1px);
+ order: tan(foo);
+ order: NaN;
+ order: NaN;
+ order: tan(3.14159 / 4);
+}
diff --git a/plugins/postcss-trigonometric-functions/test/examples/example.css b/plugins/postcss-trigonometric-functions/test/examples/example.css
new file mode 100644
index 000000000..181f83a54
--- /dev/null
+++ b/plugins/postcss-trigonometric-functions/test/examples/example.css
@@ -0,0 +1,7 @@
+.foo {
+ color: red;
+}
+
+.baz {
+ color: green;
+}
diff --git a/plugins/postcss-trigonometric-functions/test/examples/example.expect.css b/plugins/postcss-trigonometric-functions/test/examples/example.expect.css
new file mode 100644
index 000000000..9d738d5ac
--- /dev/null
+++ b/plugins/postcss-trigonometric-functions/test/examples/example.expect.css
@@ -0,0 +1,7 @@
+.foo {
+ color: blue;
+}
+
+.baz {
+ color: green;
+}
diff --git a/plugins/postcss-trigonometric-functions/test/examples/example.preserve-true.expect.css b/plugins/postcss-trigonometric-functions/test/examples/example.preserve-true.expect.css
new file mode 100644
index 000000000..8b020470a
--- /dev/null
+++ b/plugins/postcss-trigonometric-functions/test/examples/example.preserve-true.expect.css
@@ -0,0 +1,8 @@
+.foo {
+ color: blue;
+ color: red;
+}
+
+.baz {
+ color: green;
+}
diff --git a/plugins/postcss-trigonometric-functions/tsconfig.json b/plugins/postcss-trigonometric-functions/tsconfig.json
new file mode 100644
index 000000000..e0d06239c
--- /dev/null
+++ b/plugins/postcss-trigonometric-functions/tsconfig.json
@@ -0,0 +1,9 @@
+{
+ "extends": "../../tsconfig.json",
+ "compilerOptions": {
+ "outDir": "dist",
+ "declarationDir": "."
+ },
+ "include": ["./src/**/*"],
+ "exclude": ["dist"],
+}
From b16ffcd23b08029e731ea70965cf12ad13d65cae Mon Sep 17 00:00:00 2001
From: Antonio Laguna
Date: Mon, 16 May 2022 07:54:28 +0200
Subject: [PATCH 02/17] Lots of work
Plugin should mostly be stable but needs lots of tests around calculations and unexpected values just to be sure
---
package-lock.json | 8 +-
.../src/acos.ts | 34 +++
.../src/atan.ts | 34 +++
.../src/atan2.ts | 78 ++++++
.../src/index.ts | 6 +
.../src/tan.ts | 19 +-
.../src/utils.ts | 263 ++++++++++++++++--
.../test/basic.css | 159 ++++++++---
.../test/basic.expect.css | 134 ++++++---
.../test/temporal.css | 172 ++++++++++++
10 files changed, 810 insertions(+), 97 deletions(-)
create mode 100644 plugins/postcss-trigonometric-functions/src/acos.ts
create mode 100644 plugins/postcss-trigonometric-functions/src/atan.ts
create mode 100644 plugins/postcss-trigonometric-functions/src/atan2.ts
create mode 100644 plugins/postcss-trigonometric-functions/test/temporal.css
diff --git a/package-lock.json b/package-lock.json
index 78cafab07..d9bcd377c 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -7363,8 +7363,12 @@
}
},
"plugins/postcss-trigonometric-functions": {
+ "name": "@csstools/postcss-trigonometric-functions",
"version": "1.0.0",
"license": "CC0-1.0",
+ "dependencies": {
+ "postcss-value-parser": "^4.2.0"
+ },
"engines": {
"node": "^12 || ^14 || >=16"
},
@@ -8673,7 +8677,9 @@
},
"@csstools/postcss-trigonometric-functions": {
"version": "file:plugins/postcss-trigonometric-functions",
- "requires": {}
+ "requires": {
+ "postcss-value-parser": "^4.2.0"
+ }
},
"@csstools/postcss-unset-value": {
"version": "file:plugins/postcss-unset-value",
diff --git a/plugins/postcss-trigonometric-functions/src/acos.ts b/plugins/postcss-trigonometric-functions/src/acos.ts
new file mode 100644
index 000000000..e1362e9fb
--- /dev/null
+++ b/plugins/postcss-trigonometric-functions/src/acos.ts
@@ -0,0 +1,34 @@
+import type { Declaration } from 'postcss';
+import valueParser from 'postcss-value-parser';
+import { formatResultingNumber, radToDeg, validateNode } from './utils';
+
+const acosFunctionCheck = 'acos(';
+
+function transformAcosFunction(decl: Declaration): string | undefined {
+ const parsedValue = valueParser(decl.value);
+
+ parsedValue.walk(node => {
+ if (node.type !== 'function' || node.value !== 'acos') {
+ return;
+ }
+
+ const validated = validateNode(node, false);
+
+ if (!validated) {
+ return;
+ }
+
+ const [transformedNode, number] = validated;
+ let value: string | number = Math.acos(number);
+
+ if (!Number.isNaN(value) && typeof value === 'number') {
+ value = `${formatResultingNumber(radToDeg(value), 2)}deg`;
+ }
+
+ transformedNode.value = value + '';
+ });
+
+ return parsedValue.toString();
+}
+
+export { acosFunctionCheck, transformAcosFunction };
diff --git a/plugins/postcss-trigonometric-functions/src/atan.ts b/plugins/postcss-trigonometric-functions/src/atan.ts
new file mode 100644
index 000000000..89b73ef86
--- /dev/null
+++ b/plugins/postcss-trigonometric-functions/src/atan.ts
@@ -0,0 +1,34 @@
+import type { Declaration } from 'postcss';
+import valueParser from 'postcss-value-parser';
+import { formatResultingNumber, radToDeg, validateNode } from './utils';
+
+const atanFunctionCheck = 'atan(';
+
+function transformAtanFunction(decl: Declaration): string | undefined {
+ const parsedValue = valueParser(decl.value);
+
+ parsedValue.walk(node => {
+ if (node.type !== 'function' || node.value !== 'atan') {
+ return;
+ }
+
+ const validated = validateNode(node, false);
+
+ if (!validated) {
+ return;
+ }
+
+ const [transformedNode, number] = validated;
+ let value: string | number = Math.atan(number);
+
+ if (!Number.isNaN(value) && typeof value === 'number') {
+ value = `${formatResultingNumber(radToDeg(value), 2)}deg`;
+ }
+
+ transformedNode.value = value + '';
+ });
+
+ return parsedValue.toString();
+}
+
+export { atanFunctionCheck, transformAtanFunction };
diff --git a/plugins/postcss-trigonometric-functions/src/atan2.ts b/plugins/postcss-trigonometric-functions/src/atan2.ts
new file mode 100644
index 000000000..5c0448f61
--- /dev/null
+++ b/plugins/postcss-trigonometric-functions/src/atan2.ts
@@ -0,0 +1,78 @@
+import type { Declaration } from 'postcss';
+import valueParser from 'postcss-value-parser';
+import {
+ computeCalculation,
+ filterOnlyWords,
+ formatResultingNumber,
+ functionNodeToWordNode,
+ parseNumber,
+ radToDeg,
+} from './utils';
+
+const atan2FunctionCheck = 'atan2(';
+
+function transformAtan2Function(decl: Declaration): string | undefined {
+ const parsedValue = valueParser(decl.value);
+
+ parsedValue.walk(node => {
+ if (node.type !== 'function' || node.value !== 'atan2') {
+ return;
+ }
+
+ const commaIndex = node.nodes.findIndex(
+ childNode => childNode.type === 'div' && childNode.value === ',',
+ );
+
+ if (commaIndex < 0) {
+ return;
+ }
+
+ let first = node.nodes.slice(0, commaIndex).filter(filterOnlyWords);
+ let second = node.nodes.slice(commaIndex + 1).filter(filterOnlyWords);
+
+ if (first.length === 0 || second.length === 0) {
+ return;
+ }
+
+ // Compute calculations first
+ if (first.length > 1) {
+ first = computeCalculation(first);
+ }
+
+ if (second.length > 1) {
+ second = computeCalculation(second);
+ }
+
+ if (first.length !== 1 || second.length !== 1) {
+ return;
+ }
+
+ const firstParsed = parseNumber(first[0].value);
+ const secondParsed = parseNumber(second[0].value);
+
+ if (!firstParsed || !secondParsed) {
+ return;
+ }
+
+ // Units must match
+ if (firstParsed.unit !== secondParsed.unit) {
+ return;
+ }
+
+ let value: string | number = Math.atan2(
+ firstParsed.number,
+ secondParsed.number,
+ );
+
+ if (!Number.isNaN(value) && typeof value === 'number') {
+ value = `${formatResultingNumber(radToDeg(value), 2)}deg`;
+ }
+
+ const transformedNode = functionNodeToWordNode(node);
+ transformedNode.value = value + '';
+ });
+
+ return parsedValue.toString();
+}
+
+export { atan2FunctionCheck, transformAtan2Function };
diff --git a/plugins/postcss-trigonometric-functions/src/index.ts b/plugins/postcss-trigonometric-functions/src/index.ts
index 69fd21367..c257adbe0 100644
--- a/plugins/postcss-trigonometric-functions/src/index.ts
+++ b/plugins/postcss-trigonometric-functions/src/index.ts
@@ -3,6 +3,9 @@ import { sinFunctionCheck, transformSinFunction } from './sin';
import { cosFunctionCheck, transformCosFunction } from './cos';
import { tanFunctionCheck, transformTanFunction } from './tan';
import { asinFunctionCheck, transformAsinFunction } from './asin';
+import { acosFunctionCheck, transformAcosFunction } from './acos';
+import { atanFunctionCheck, transformAtanFunction } from './atan';
+import { atan2FunctionCheck, transformAtan2Function } from './atan2';
type pluginOptions = { preserve?: boolean };
@@ -11,6 +14,9 @@ const Transformations = [
{ check: cosFunctionCheck, transform: transformCosFunction },
{ check: tanFunctionCheck, transform: transformTanFunction },
{ check: asinFunctionCheck, transform: transformAsinFunction },
+ { check: acosFunctionCheck, transform: transformAcosFunction },
+ { check: atanFunctionCheck, transform: transformAtanFunction },
+ { check: atan2FunctionCheck, transform: transformAtan2Function },
];
const creator: PluginCreator = (opts?: pluginOptions) => {
diff --git a/plugins/postcss-trigonometric-functions/src/tan.ts b/plugins/postcss-trigonometric-functions/src/tan.ts
index 18685f684..7cc802293 100644
--- a/plugins/postcss-trigonometric-functions/src/tan.ts
+++ b/plugins/postcss-trigonometric-functions/src/tan.ts
@@ -1,6 +1,6 @@
import type { Declaration } from 'postcss';
import valueParser from 'postcss-value-parser';
-import { formatResultingNumber, validateNode } from './utils';
+import { formatResultingNumber, gradToDeg, radToDeg, validateNode } from './utils';
const tanFunctionCheck = 'tan(';
@@ -19,6 +19,23 @@ function transformTanFunction(decl: Declaration): string | undefined {
}
const [transformedNode, number] = validated;
+
+ /*
+ Asymptotes treatment
+
+ Given at this stage the number is in radians, convert to degrees which
+ should give enough precision with the given methods.
+ */
+ const degrees = Number(formatResultingNumber(radToDeg(number), 2));
+ const isNinetyMultiple = degrees % 90 === 0;
+ const timesNinety = degrees / 90;
+ const isAsymptote = isNinetyMultiple && timesNinety % 2 !== 0;
+
+ if (isAsymptote) {
+ transformedNode.value = timesNinety > 0 ? 'infinity' : '-infinity';
+ return;
+ }
+
transformedNode.value = formatResultingNumber(Math.tan(number), 5);
});
diff --git a/plugins/postcss-trigonometric-functions/src/utils.ts b/plugins/postcss-trigonometric-functions/src/utils.ts
index 3f8e8ecff..dce516a5e 100644
--- a/plugins/postcss-trigonometric-functions/src/utils.ts
+++ b/plugins/postcss-trigonometric-functions/src/utils.ts
@@ -1,5 +1,6 @@
import type { FunctionNode, WordNode, Node } from 'postcss-value-parser';
import valueParser from 'postcss-value-parser';
+import vm from 'node:vm';
export function turnToRad(turn: number): number {
return turn * 2 * Math.PI;
@@ -17,12 +18,187 @@ export function radToDeg(rad: number): number {
return rad * ( 180 / Math.PI );
}
+export function gradToDeg(grad: number): number {
+ return grad * 180 / 200;
+}
+
+export function turnToDeg(turn: number): number {
+ return turn * 360;
+}
+
const toRad = {
turn: turnToRad,
deg: degToRad,
grad: gradToRad,
};
+const toDeg = {
+ grad: gradToDeg,
+ turn: turnToDeg,
+ rad: radToDeg,
+};
+
+export function filterOnlyWords(node: Node): boolean {
+ return node.type === 'word';
+}
+
+const ALLOWED_OPERATIONS = [
+ '+',
+ '-',
+ '*',
+ '/',
+];
+
+enum ExpressionPart {
+ Number,
+ Operation
+}
+
+/**
+ * Try to compute a calculation from a Node.
+ *
+ * This validates that the calculation has a valid order which is:
+ * - `{Number} {Operation} {Number} ...`
+ *
+ * Only basic arithmetic operations are allowed, and it has to be separate words
+ * similarly to how CSS calc works:
+ *
+ * - `sin(3.14159 * 2)` -> is valid
+ * - `sin(3.14159*2)` -> is not valid
+ *
+ *
+ * @param {FunctionNode} nodes Nodes to be parsed
+ * @param {Boolean} ignoreUnit Whether units are ignored or converted to radians
+ * @return {FunctionNode} Returns the node, if it managed to calculate, it will
+ * simplify inner nodes.
+ * @see https://www.w3.org/TR/css-values-4/#trig-funcs
+ */
+export function computeCalculation(nodes: Node[], ignoreUnit = false) {
+ let isValid = true;
+ const expression = [];
+ const words = nodes.filter(filterOnlyWords);
+ let operationPart = ExpressionPart.Number;
+ let detectedUnit;
+
+ const addToExpression = (part: string, type: ExpressionPart) => {
+ if (operationPart !== type) {
+ isValid = false;
+ return;
+ }
+
+ expression.push(part);
+ operationPart = type === ExpressionPart.Number
+ ? ExpressionPart.Operation
+ : ExpressionPart.Number;
+ };
+
+ for (let i = 0, len = words.length; i < len && isValid; i++) {
+ const word = words[i];
+
+ if (ALLOWED_OPERATIONS.includes(word.value)) {
+ addToExpression(word.value, ExpressionPart.Operation);
+ continue;
+ }
+
+ const parsed = valueParser.unit(word.value);
+
+ // This could be an unsupported expression
+ if (!parsed) {
+ isValid = false;
+ break;
+ }
+
+ if (ignoreUnit) {
+ if (!detectedUnit) {
+ detectedUnit = parsed.unit;
+ }
+
+ // Can't calculate from different units when unit is ignored
+ if (detectedUnit !== parsed.unit) {
+ isValid = false;
+ break;
+ }
+
+ addToExpression(word.value, ExpressionPart.Operation);
+ continue;
+ }
+
+ // Is it unitless? Assume radians
+ if (!parsed.unit) {
+ addToExpression(word.value, ExpressionPart.Number);
+ continue;
+ }
+
+ if (parsed.unit === 'rad') {
+ addToExpression(parsed.number, ExpressionPart.Number);
+ continue;
+ }
+
+ if (typeof toRad[parsed.unit] === 'function') {
+ const number = toRad[parsed.unit](Number(parsed.number));
+
+ if (!Number.isNaN(number) && Number.isFinite(number)) {
+ addToExpression(number.toString(), ExpressionPart.Number);
+ continue;
+ } else {
+ isValid = false;
+ break;
+ }
+ }
+
+ isValid = false;
+ }
+
+ if (!isValid) {
+ return nodes;
+ }
+
+ // For expressions to be valid they have to be either 3
+ // or subsequent even numbers of elements
+ // {Number} {Operation} {Number} -> 3
+ // {Number} {Operation} {Number} {Operation} {Number} -> 5
+ // ... and so on
+ // Otherwise don't bother computing
+ if (expression.length % 2 === 0 || expression.length < 3) {
+ return nodes;
+ }
+
+ let result;
+
+ try {
+ const context = vm.createContext({ result: NaN });
+ const calculation = new vm.Script(`result = ${expression.join(' ')}`);
+ calculation.runInContext(context);
+
+ if (typeof context.result === 'number' && !Number.isNaN(context.result) && Number.isFinite(context.result)) {
+ result = context.result;
+ }
+ } catch(error) {
+ // Error silently
+ }
+
+ if (typeof result !== 'undefined') {
+ let value = result.toString();
+
+ if (detectedUnit) {
+ value += detectedUnit;
+ }
+
+ const sourceIndex = nodes[0].sourceIndex;
+ const sourceEndIndex = value.length;
+
+ nodes.length = 0;
+ nodes.push({
+ type: 'word',
+ value,
+ sourceIndex,
+ sourceEndIndex,
+ });
+ }
+
+ return nodes;
+}
+
export function functionNodeToWordNode(fn: FunctionNode): WordNode {
delete fn.nodes;
const node = fn as Node;
@@ -31,6 +207,20 @@ export function functionNodeToWordNode(fn: FunctionNode): WordNode {
return node as WordNode;
}
+/**
+ * Formats a number that's intended to be put into CSS.
+ *
+ * Due to processing of Number(number.toFixed(decimals)) this will get
+ * rid of ending zeroes, usually helping with the rounding which is the
+ * intended effect.
+ *
+ * For example, converting 4.71238898038469 radians into deg leads to
+ * 270.000000000669786 which is going to result as 270 unless a
+ * precision of 10 is chosen.
+ *
+ * @param {Number} number Number to be formatted
+ * @param {Number} decimals Precision of decimals, CSS doesn't usually handle further than 5.
+ */
export function formatResultingNumber(number: number, decimals: number): string {
if (!Number.isNaN(number)) {
if (number > Number.MAX_SAFE_INTEGER) {
@@ -43,46 +233,69 @@ export function formatResultingNumber(number: number, decimals: number): string
return Number(number.toFixed(decimals)).toString();
}
+export function parseNumber(value: string) {
+ let number;
+ let unit = '';
+
+ if (value.toLowerCase() === 'infinity' ) {
+ number = Infinity;
+ } else if (value.toLowerCase() === '-infinity') {
+ number = Infinity * -1;
+ }
+
+ if (!number) {
+ const parsed = valueParser.unit(value);
+
+ if (!parsed) {
+ return false;
+ }
+
+ number = Number(parsed.number);
+
+ if (!Number.isNaN(number)) {
+ unit = parsed.unit;
+ }
+ }
+
+ return {
+ number,
+ unit,
+ };
+}
+
+type validateNodeReturn = [WordNode, number] | undefined;
+
export function validateNode(
node: FunctionNode,
parseUnit = true,
- args = 1,
-): [WordNode,number] | undefined {
- const words = node.nodes.filter(childNode => childNode.type === 'word');
+): validateNodeReturn {
+ node.nodes = computeCalculation(node.nodes);
+ const words = node.nodes.filter(filterOnlyWords);
- if (words.length !== args) {
+ if (words.length !== 1) {
return;
}
const { value } = words[0];
- const parsed = valueParser.unit(value);
- let number;
-
- if (value.toLowerCase() === 'infinity' ) {
- number = Infinity;
- } else if (value.toLowerCase() === '-infinity') {
- number = Infinity * -1;
- }
+ const parsed = parseNumber(value);
- if (!parsed && !number) {
+ if (!parsed) {
return;
}
- if (parsed) {
- number = Number(parsed.number);
+ let number = parsed.number;
- if (parseUnit) {
- if (parsed.unit && parsed.unit !== 'rad') {
- if (toRad[parsed.unit]) {
- number = toRad[parsed.unit](number);
- } else {
- return;
- }
+ if (parseUnit) {
+ if (parsed.unit && parsed.unit !== 'rad') {
+ if (toRad[parsed.unit]) {
+ number = toRad[parsed.unit](number);
+ } else {
+ return;
}
- } else if (parsed.unit) {
- return;
}
+ } else if (parsed.unit) {
+ return;
}
return [
@@ -91,4 +304,4 @@ export function validateNode(
];
}
-export { toRad };
+export { toRad, toDeg };
diff --git a/plugins/postcss-trigonometric-functions/test/basic.css b/plugins/postcss-trigonometric-functions/test/basic.css
index 3aa39fd41..629149352 100644
--- a/plugins/postcss-trigonometric-functions/test/basic.css
+++ b/plugins/postcss-trigonometric-functions/test/basic.css
@@ -1,14 +1,14 @@
.sin {
- order: sin(45deg);
- order: sin(.125turn);
- order: sin(50grad);
- order: sin(0.785398rad);
- order: sin(0.785398);
- order: sin(-45deg);
- order: sin(-.125turn);
- order: sin(-50grad);
- order: sin(-0.785398rad);
- order: sin(-0.785398);
+ order: sin(45deg); /* 45deg */
+ order: sin(.125turn); /* 45deg */
+ order: sin(50grad); /* 45deg */
+ order: sin(0.785398rad); /* 45deg */
+ order: sin(0.785398); /* 45deg */
+ order: sin(-45deg); /* -45deg */
+ order: sin(-.125turn); /* -45deg */
+ order: sin(-50grad); /* -45deg */
+ order: sin(-0.785398rad); /* -45deg */
+ order: sin(-0.785398); /* -45deg */
order: sin(0);
order: sin(sin(0.785398));
order: sin(sin(sin(sin(0.785398))));
@@ -17,20 +17,19 @@
order: sin(Infinity);
order: sin(InFiNiTy);
order: sin(-infinity);
- order: sin(3.14159 / 4);
}
.cos {
- order: cos(45deg);
- order: cos(.125turn);
- order: cos(50grad);
- order: cos(1rad);
- order: cos(1);
- order: cos(-45deg);
- order: cos(-.125turn);
- order: cos(-50grad);
- order: cos(-0.785398rad);
- order: cos(-0.785398);
+ order: cos(45deg); /* 45deg */
+ order: cos(.125turn); /* 45deg */
+ order: cos(50grad); /* 45deg */
+ order: cos(0.785398rad); /* 45deg */
+ order: cos(0.785398); /* 45deg */
+ order: cos(-45deg); /* -45deg */
+ order: cos(-.125turn); /* -45deg */
+ order: cos(-50grad); /* -45deg */
+ order: cos(-0.785398rad); /* -45deg */
+ order: cos(-0.785398); /* -45deg */
order: cos(cos(0.785398));
order: cos(cos(cos(cos(0.785398))));
order: cos(1px);
@@ -38,35 +37,46 @@
order: cos(Infinity);
order: cos(InFiNiTy);
order: cos(-infinity);
- order: cos(3.14159 / 4);
}
.tan {
- order: tan(45deg);
- order: tan(90deg);
- order: tan(-90deg);
- order: tan(.125turn);
- order: tan(50grad);
- order: tan(1rad);
- order: tan(1);
- order: tan(-45deg);
- order: tan(-.125turn);
- order: tan(-50grad);
- order: tan(-0.785398rad);
- order: tan(-0.785398);
+ order: tan(45deg); /* 45deg */
+ order: tan(.125turn); /* 45deg */
+ order: tan(50grad); /* 45deg */
+ order: tan(0.785398rad); /* 45deg */
+ order: tan(0.785398); /* 45deg */
+ order: tan(-45deg); /* -45deg */
+ order: tan(-.125turn); /* -45deg */
+ order: tan(-50grad); /* -45deg */
+ order: tan(-0.785398rad); /* -45deg */
+ order: tan(-0.785398); /* -45deg */
order: tan(0);
order: tan(tan(0.785398));
order: tan(tan(tan(tan(0.785398))));
+ /* Asymptotes */
+ order: tan(90deg);
+ order: tan(100grad);
+ order: tan(270deg);
+ order: tan(300grad);
+ order: tan(-270deg);
+ order: tan(-100grad);
+ order: tan(-450deg);
+ order: tan(-300grad);
+ /* Non Asymptotes */
+ order: tan(180deg);
+ order: tan(200grad);
+ order: tan(360deg);
+ order: tan(400grad);
order: tan(1px);
order: tan(foo);
order: tan(Infinity);
order: tan(InFiNiTy);
order: tan(-infinity);
- order: tan(3.14159 / 4);
}
.asin {
order: asin(sin(45deg));
+ order: asin(sin(90deg));
order: asin(-1);
order: asin(-0.5);
order: asin(0);
@@ -80,3 +90,82 @@
order: asin(infinity);
order: asin(-infinity);
}
+
+.acos {
+ order: acos(cos(45deg));
+ order: acos(cos(90deg));
+ order: acos(-1);
+ order: acos(-0.5);
+ order: acos(0);
+ order: acos(0.5);
+ order: acos(1);
+ order: acos(2);
+ order: acos(-20);
+ order: acos(45deg);
+ order: acos(1rad);
+ order: acos(foo);
+ order: acos(infinity);
+ order: acos(-infinity);
+}
+
+.atan {
+ order: atan(infinity);
+ order: atan(-infinity);
+ order: atan(1);
+ order: atan(0);
+ order: atan(-0);
+ order: atan(tan(45deg)); /* 45deg */
+ order: atan(tan(.125turn)); /* 45deg */
+ order: atan(tan(50grad)); /* 45deg */
+ order: atan(tan(0.785398rad)); /* 45deg */
+ order: atan(tan(0.785398)); /* 45deg */
+ order: atan(tan(-45deg)); /* -45deg */
+ order: atan(tan(-.125turn)); /* -45deg */
+ order: atan(tan(-50grad)); /* -45deg */
+ order: atan(tan(-0.785398rad)); /* -45deg */
+ order: atan(tan(-0.785398)); /* -45deg */
+}
+
+.atan2 {
+ order: atan2(-infinity, -infinity);
+ order: atan2(-infinity, -1);
+ order: atan2(-infinity, -0);
+ order: atan2(-infinity, 0);
+ order: atan2(-infinity, 1);
+ order: atan2(-infinity, infinity);
+
+ order: atan2(-1, -infinity);
+ order: atan2(-1, -1);
+ order: atan2(-1, -0);
+ order: atan2(-1, 0);
+ order: atan2(-1, 1);
+ order: atan2(-1, infinity);
+
+ order: atan2(-0, -infinity);
+ order: atan2(-0, -1);
+ order: atan2(-0, -0);
+ order: atan2(-0, 0);
+ order: atan2(-0, 1);
+ order: atan2(-0, infinity);
+
+ order: atan2(0, -infinity);
+ order: atan2(0, -1);
+ order: atan2(0, -0);
+ order: atan2(0, 0);
+ order: atan2(0, 1);
+ order: atan2(0, infinity);
+
+ order: atan2(1, -infinity);
+ order: atan2(1, -1);
+ order: atan2(1, -0);
+ order: atan2(1, 0);
+ order: atan2(1, 1);
+ order: atan2(1, infinity);
+
+ order: atan2(infinity, -infinity);
+ order: atan2(infinity, -1);
+ order: atan2(infinity, -0);
+ order: atan2(infinity, 0);
+ order: atan2(infinity, 1);
+ order: atan2(infinity, infinity);
+}
diff --git a/plugins/postcss-trigonometric-functions/test/basic.expect.css b/plugins/postcss-trigonometric-functions/test/basic.expect.css
index d71b9d90f..549d16c8b 100644
--- a/plugins/postcss-trigonometric-functions/test/basic.expect.css
+++ b/plugins/postcss-trigonometric-functions/test/basic.expect.css
@@ -1,14 +1,14 @@
.sin {
- order: 0.70711;
- order: 0.70711;
- order: 0.70711;
- order: 0.70711;
- order: 0.70711;
- order: -0.70711;
- order: -0.70711;
- order: -0.70711;
- order: -0.70711;
- order: -0.70711;
+ order: 0.70711; /* 45deg */
+ order: 0.70711; /* 45deg */
+ order: 0.70711; /* 45deg */
+ order: 0.70711; /* 45deg */
+ order: 0.70711; /* 45deg */
+ order: -0.70711; /* -45deg */
+ order: -0.70711; /* -45deg */
+ order: -0.70711; /* -45deg */
+ order: -0.70711; /* -45deg */
+ order: -0.70711; /* -45deg */
order: 0;
order: 0.64964;
order: 0.56868;
@@ -16,48 +16,112 @@
order: sin(foo);
order: NaN;
order: NaN;
- order: sin(3.14159 / 4);
+ order: NaN;
}
.cos {
- order: 0.70711;
- order: 0.70711;
- order: 0.70711;
- order: 0.5403;
- order: 0.5403;
- order: 0.70711;
- order: 0.70711;
- order: 0.70711;
- order: 0.70711;
- order: 0.70711;
+ order: 0.70711; /* 45deg */
+ order: 0.70711; /* 45deg */
+ order: 0.70711; /* 45deg */
+ order: 0.70711; /* 45deg */
+ order: 0.70711; /* 45deg */
+ order: 0.70711; /* -45deg */
+ order: 0.70711; /* -45deg */
+ order: 0.70711; /* -45deg */
+ order: 0.70711; /* -45deg */
+ order: 0.70711; /* -45deg */
order: 0.76024;
order: 0.74872;
order: cos(1px);
order: cos(foo);
order: NaN;
order: NaN;
- order: cos(3.14159 / 4);
+ order: NaN;
}
.tan {
- order: 1;
- order: infinity;
- order: -infinity;
- order: 1;
- order: 1;
- order: 1.55741;
- order: 1.55741;
- order: -1;
- order: -1;
- order: -1;
- order: -1;
- order: -1;
+ order: 1; /* 45deg */
+ order: 1; /* 45deg */
+ order: 1; /* 45deg */
+ order: 1; /* 45deg */
+ order: 1; /* 45deg */
+ order: -1; /* -45deg */
+ order: -1; /* -45deg */
+ order: -1; /* -45deg */
+ order: -1; /* -45deg */
+ order: -1; /* -45deg */
order: 0;
order: 1.55741;
order: -0.84159;
+ /* Asymptotes */
+ order: infinity;
+ order: infinity;
+ order: infinity;
+ order: infinity;
+ order: -infinity;
+ order: -infinity;
+ order: -infinity;
+ order: -infinity;
+ /* Non Asymptotes */
+ order: 0;
+ order: 0;
+ order: 0;
+ order: 0;
order: tan(1px);
order: tan(foo);
order: NaN;
order: NaN;
- order: tan(3.14159 / 4);
+ order: NaN;
+}
+
+.asin {
+ order: 45deg;
+ order: 90deg;
+ order: -90deg;
+ order: -30deg;
+ order: 0deg;
+ order: 30deg;
+ order: 90deg;
+ order: NaN;
+ order: NaN;
+ order: asin(45deg);
+ order: asin(1rad);
+ order: asin(foo);
+ order: NaN;
+ order: NaN;
+}
+
+.acos {
+ order: 45deg;
+ order: 90deg;
+ order: 180deg;
+ order: 120deg;
+ order: 90deg;
+ order: 60deg;
+ order: 0deg;
+ order: NaN;
+ order: NaN;
+ order: acos(45deg);
+ order: acos(1rad);
+ order: acos(foo);
+ order: NaN;
+ order: NaN;
+}
+
+.atan {
+ order: 90deg;
+ order: -90deg;
+ order: 45deg;
+ order: 0deg;
+ order: 0deg;
+ order: 45deg; /* 45deg */
+ order: 45deg; /* 45deg */
+ order: 45deg; /* 45deg */
+ order: 45deg; /* 45deg */
+ order: 45deg; /* 45deg */
+ order: -45deg; /* -45deg */
+ order: -45deg; /* -45deg */
+ order: -45deg; /* -45deg */
+ order: -45deg; /* -45deg */
+ order: -45deg; /* -45deg */
}
diff --git a/plugins/postcss-trigonometric-functions/test/temporal.css b/plugins/postcss-trigonometric-functions/test/temporal.css
new file mode 100644
index 000000000..d122b105e
--- /dev/null
+++ b/plugins/postcss-trigonometric-functions/test/temporal.css
@@ -0,0 +1,172 @@
+.sin {
+ order: sin(45deg); /* 45deg */
+ order: sin(.125turn); /* 45deg */
+ order: sin(50grad); /* 45deg */
+ order: sin(0.785398rad); /* 45deg */
+ order: sin(0.785398); /* 45deg */
+ order: sin(-45deg); /* -45deg */
+ order: sin(-.125turn); /* -45deg */
+ order: sin(-50grad); /* -45deg */
+ order: sin(-0.785398rad); /* -45deg */
+ order: sin(-0.785398); /* -45deg */
+ order: sin(0);
+ order: sin(sin(0.785398));
+ order: sin(sin(sin(sin(0.785398))));
+ order: sin(1px);
+ order: sin(foo);
+ order: sin(Infinity);
+ order: sin(InFiNiTy);
+ order: sin(-infinity);
+}
+
+.cos {
+ order: cos(45deg); /* 45deg */
+ order: cos(.125turn); /* 45deg */
+ order: cos(50grad); /* 45deg */
+ order: cos(0.785398rad); /* 45deg */
+ order: cos(0.785398); /* 45deg */
+ order: cos(-45deg); /* -45deg */
+ order: cos(-.125turn); /* -45deg */
+ order: cos(-50grad); /* -45deg */
+ order: cos(-0.785398rad); /* -45deg */
+ order: cos(-0.785398); /* -45deg */
+ order: cos(cos(0.785398));
+ order: cos(cos(cos(cos(0.785398))));
+ order: cos(1px);
+ order: cos(foo);
+ order: cos(Infinity);
+ order: cos(InFiNiTy);
+ order: cos(-infinity);
+}
+
+.tan {
+ order: tan(45deg); /* 45deg */
+ order: tan(.125turn); /* 45deg */
+ order: tan(50grad); /* 45deg */
+ order: tan(0.785398rad); /* 45deg */
+ order: tan(0.785398); /* 45deg */
+ order: tan(-45deg); /* -45deg */
+ order: tan(-.125turn); /* -45deg */
+ order: tan(-50grad); /* -45deg */
+ order: tan(-0.785398rad); /* -45deg */
+ order: tan(-0.785398); /* -45deg */
+ order: tan(0);
+ order: tan(tan(0.785398));
+ order: tan(tan(tan(tan(0.785398))));
+ /* Asymptotes */
+ order: tan(90deg);
+ order: tan(100grad);
+ order: tan(270deg);
+ order: tan(300grad);
+ order: tan(-270deg);
+ order: tan(-100grad);
+ order: tan(-450deg);
+ order: tan(-300grad);
+ /* Non Asymptotes */
+ order: tan(180deg);
+ order: tan(200grad);
+ order: tan(360deg);
+ order: tan(400grad);
+ order: tan(1px);
+ order: tan(foo);
+ order: tan(Infinity);
+ order: tan(InFiNiTy);
+ order: tan(-infinity);
+}
+
+.asin {
+ order: asin(sin(45deg));
+ order: asin(sin(90deg));
+ order: asin(-1);
+ order: asin(-0.5);
+ order: asin(0);
+ order: asin(0.5);
+ order: asin(1);
+ order: asin(2);
+ order: asin(-20);
+ order: asin(45deg);
+ order: asin(1rad);
+ order: asin(foo);
+ order: asin(infinity);
+ order: asin(-infinity);
+}
+
+.acos {
+ order: acos(cos(45deg));
+ order: acos(cos(90deg));
+ order: acos(-1);
+ order: acos(-0.5);
+ order: acos(0);
+ order: acos(0.5);
+ order: acos(1);
+ order: acos(2);
+ order: acos(-20);
+ order: acos(45deg);
+ order: acos(1rad);
+ order: acos(foo);
+ order: acos(infinity);
+ order: acos(-infinity);
+}
+
+.atan {
+ order: atan(infinity);
+ order: atan(-infinity);
+ order: atan(1);
+ order: atan(0);
+ order: atan(-0);
+ order: atan(tan(45deg)); /* 45deg */
+ order: atan(tan(.125turn)); /* 45deg */
+ order: atan(tan(50grad)); /* 45deg */
+ order: atan(tan(0.785398rad)); /* 45deg */
+ order: atan(tan(0.785398)); /* 45deg */
+ order: atan(tan(-45deg)); /* -45deg */
+ order: atan(tan(-.125turn)); /* -45deg */
+ order: atan(tan(-50grad)); /* -45deg */
+ order: atan(tan(-0.785398rad)); /* -45deg */
+ order: atan(tan(-0.785398)); /* -45deg */
+}
+
+.atan2 {
+ order: atan2(-infinity, -infinity);
+ order: atan2(-infinity, -1);
+ order: atan2(-infinity, -0);
+ order: atan2(-infinity, 0);
+ order: atan2(-infinity, 1);
+ order: atan2(-infinity, infinity);
+
+ order: atan2(-1, -infinity);
+ order: atan2(-1, -1);
+ order: atan2(-1, -0);
+ order: atan2(-1, 0);
+ order: atan2(-1, 1);
+ order: atan2(-1, infinity);
+
+ order: atan2(-0, -infinity);
+ order: atan2(-0, -1);
+ order: atan2(-0, -0);
+ order: atan2(-0, 0);
+ order: atan2(-0, 1);
+ order: atan2(-0, infinity);
+
+ order: atan2(0, -infinity);
+ order: atan2(0, -1);
+ order: atan2(0, -0);
+ order: atan2(0, 0);
+ order: atan2(0, 1);
+ order: atan2(0, infinity);
+
+ order: atan2(1, -infinity);
+ order: atan2(1, -1);
+ order: atan2(1, -0);
+ order: atan2(1, 0);
+ order: atan2(1, 1);
+ order: atan2(1, infinity);
+
+ order: atan2(infinity, -infinity);
+ order: atan2(infinity, -1);
+ order: atan2(infinity, -0);
+ order: atan2(infinity, 0);
+ order: atan2(infinity, 1);
+ order: atan2(infinity, infinity);
+}
+
From 8a5e9427b8e04ae45f664a63580c6f2ae9ecb0d5 Mon Sep 17 00:00:00 2001
From: Antonio Laguna
Date: Mon, 16 May 2022 18:44:39 +0200
Subject: [PATCH 03/17] Less strict filtering
---
plugins/postcss-trigonometric-functions/src/utils.ts | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/plugins/postcss-trigonometric-functions/src/utils.ts b/plugins/postcss-trigonometric-functions/src/utils.ts
index dce516a5e..ee33983ee 100644
--- a/plugins/postcss-trigonometric-functions/src/utils.ts
+++ b/plugins/postcss-trigonometric-functions/src/utils.ts
@@ -76,7 +76,9 @@ enum ExpressionPart {
export function computeCalculation(nodes: Node[], ignoreUnit = false) {
let isValid = true;
const expression = [];
- const words = nodes.filter(filterOnlyWords);
+ const filteredNodes = nodes.filter(
+ node => node.type === 'word' || ALLOWED_OPERATIONS.includes(node.value)
+ );
let operationPart = ExpressionPart.Number;
let detectedUnit;
From 6f2828ec6f2859416a3611ec47503a38f9bdbccb Mon Sep 17 00:00:00 2001
From: Antonio Laguna
Date: Mon, 16 May 2022 18:44:59 +0200
Subject: [PATCH 04/17] Handling pi and e
---
.../src/utils.ts | 18 ++++++++++++++++--
1 file changed, 16 insertions(+), 2 deletions(-)
diff --git a/plugins/postcss-trigonometric-functions/src/utils.ts b/plugins/postcss-trigonometric-functions/src/utils.ts
index ee33983ee..7c278520b 100644
--- a/plugins/postcss-trigonometric-functions/src/utils.ts
+++ b/plugins/postcss-trigonometric-functions/src/utils.ts
@@ -94,14 +94,24 @@ export function computeCalculation(nodes: Node[], ignoreUnit = false) {
: ExpressionPart.Number;
};
- for (let i = 0, len = words.length; i < len && isValid; i++) {
- const word = words[i];
+ for (let i = 0, len = filteredNodes.length; i < len && isValid; i++) {
+ const word = filteredNodes[i];
if (ALLOWED_OPERATIONS.includes(word.value)) {
addToExpression(word.value, ExpressionPart.Operation);
continue;
}
+ if (word.value === 'pi') {
+ addToExpression(Math.PI.toString(), ExpressionPart.Number);
+ continue;
+ }
+
+ if (word.value === 'e') {
+ addToExpression(Math.E.toString(), ExpressionPart.Number);
+ continue;
+ }
+
const parsed = valueParser.unit(word.value);
// This could be an unsupported expression
@@ -243,6 +253,10 @@ export function parseNumber(value: string) {
number = Infinity;
} else if (value.toLowerCase() === '-infinity') {
number = Infinity * -1;
+ } else if (value === 'pi') {
+ number = Math.PI;
+ } else if (value === 'e') {
+ number = Math.E;
}
if (!number) {
From 8b6c3e713958be21c0bec546f8a9ca4cd89a7170 Mon Sep 17 00:00:00 2001
From: Antonio Laguna
Date: Mon, 16 May 2022 18:45:06 +0200
Subject: [PATCH 05/17] Better ordering
---
plugins/postcss-trigonometric-functions/src/index.ts | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/plugins/postcss-trigonometric-functions/src/index.ts b/plugins/postcss-trigonometric-functions/src/index.ts
index c257adbe0..a5610d70c 100644
--- a/plugins/postcss-trigonometric-functions/src/index.ts
+++ b/plugins/postcss-trigonometric-functions/src/index.ts
@@ -10,13 +10,13 @@ import { atan2FunctionCheck, transformAtan2Function } from './atan2';
type pluginOptions = { preserve?: boolean };
const Transformations = [
- { check: sinFunctionCheck, transform: transformSinFunction },
- { check: cosFunctionCheck, transform: transformCosFunction },
- { check: tanFunctionCheck, transform: transformTanFunction },
{ check: asinFunctionCheck, transform: transformAsinFunction },
{ check: acosFunctionCheck, transform: transformAcosFunction },
{ check: atanFunctionCheck, transform: transformAtanFunction },
{ check: atan2FunctionCheck, transform: transformAtan2Function },
+ { check: sinFunctionCheck, transform: transformSinFunction },
+ { check: cosFunctionCheck, transform: transformCosFunction },
+ { check: tanFunctionCheck, transform: transformTanFunction },
];
const creator: PluginCreator = (opts?: pluginOptions) => {
From 1437ea8c051f717abce88bd9a0609e5d7dd80c24 Mon Sep 17 00:00:00 2001
From: Antonio Laguna
Date: Mon, 16 May 2022 18:45:14 +0200
Subject: [PATCH 06/17] Enabling WPT tests
---
.../postcss-trigonometric-functions/.tape.mjs | 3 +
.../test/basic.css | 4 +
.../test/basic.expect.css | 48 +++++
.../test/temporal.css | 172 ------------------
.../test/wpt.css | 44 +++++
.../test/wpt.expect.css | 44 +++++
6 files changed, 143 insertions(+), 172 deletions(-)
delete mode 100644 plugins/postcss-trigonometric-functions/test/temporal.css
create mode 100644 plugins/postcss-trigonometric-functions/test/wpt.css
create mode 100644 plugins/postcss-trigonometric-functions/test/wpt.expect.css
diff --git a/plugins/postcss-trigonometric-functions/.tape.mjs b/plugins/postcss-trigonometric-functions/.tape.mjs
index cda74a20c..b675809b4 100644
--- a/plugins/postcss-trigonometric-functions/.tape.mjs
+++ b/plugins/postcss-trigonometric-functions/.tape.mjs
@@ -5,4 +5,7 @@ postcssTape(plugin)({
basic: {
message: "supports basic usage",
},
+ wpt: {
+ message: "supports wpt cases",
+ },
});
diff --git a/plugins/postcss-trigonometric-functions/test/basic.css b/plugins/postcss-trigonometric-functions/test/basic.css
index 629149352..085fa3457 100644
--- a/plugins/postcss-trigonometric-functions/test/basic.css
+++ b/plugins/postcss-trigonometric-functions/test/basic.css
@@ -17,6 +17,7 @@
order: sin(Infinity);
order: sin(InFiNiTy);
order: sin(-infinity);
+ order: sin(var(--foo));
}
.cos {
@@ -168,4 +169,7 @@
order: atan2(infinity, 0);
order: atan2(infinity, 1);
order: atan2(infinity, infinity);
+
+ order: atan2(90, 15);
+ order: atan2(15, 90);
}
diff --git a/plugins/postcss-trigonometric-functions/test/basic.expect.css b/plugins/postcss-trigonometric-functions/test/basic.expect.css
index 549d16c8b..320b61e34 100644
--- a/plugins/postcss-trigonometric-functions/test/basic.expect.css
+++ b/plugins/postcss-trigonometric-functions/test/basic.expect.css
@@ -17,6 +17,7 @@
order: NaN;
order: NaN;
order: NaN;
+ order: sin(var(--foo));
}
.cos {
@@ -125,3 +126,50 @@
order: -45deg; /* -45deg */
order: -45deg; /* -45deg */
}
+
+.atan2 {
+ order: -135deg;
+ order: -90deg;
+ order: -90deg;
+ order: -90deg;
+ order: -90deg;
+ order: -45deg;
+
+ order: -180deg;
+ order: -135deg;
+ order: -90deg;
+ order: -90deg;
+ order: -45deg;
+ order: 0deg;
+
+ order: -180deg;
+ order: -180deg;
+ order: -180deg;
+ order: 0deg;
+ order: 0deg;
+ order: 0deg;
+
+ order: 180deg;
+ order: 180deg;
+ order: 180deg;
+ order: 0deg;
+ order: 0deg;
+ order: 0deg;
+
+ order: 180deg;
+ order: 135deg;
+ order: 90deg;
+ order: 90deg;
+ order: 45deg;
+ order: 0deg;
+
+ order: 135deg;
+ order: 90deg;
+ order: 90deg;
+ order: 90deg;
+ order: 90deg;
+ order: 45deg;
+
+ order: 80.54deg;
+ order: 9.46deg;
+}
diff --git a/plugins/postcss-trigonometric-functions/test/temporal.css b/plugins/postcss-trigonometric-functions/test/temporal.css
deleted file mode 100644
index d122b105e..000000000
--- a/plugins/postcss-trigonometric-functions/test/temporal.css
+++ /dev/null
@@ -1,172 +0,0 @@
-.sin {
- order: sin(45deg); /* 45deg */
- order: sin(.125turn); /* 45deg */
- order: sin(50grad); /* 45deg */
- order: sin(0.785398rad); /* 45deg */
- order: sin(0.785398); /* 45deg */
- order: sin(-45deg); /* -45deg */
- order: sin(-.125turn); /* -45deg */
- order: sin(-50grad); /* -45deg */
- order: sin(-0.785398rad); /* -45deg */
- order: sin(-0.785398); /* -45deg */
- order: sin(0);
- order: sin(sin(0.785398));
- order: sin(sin(sin(sin(0.785398))));
- order: sin(1px);
- order: sin(foo);
- order: sin(Infinity);
- order: sin(InFiNiTy);
- order: sin(-infinity);
-}
-
-.cos {
- order: cos(45deg); /* 45deg */
- order: cos(.125turn); /* 45deg */
- order: cos(50grad); /* 45deg */
- order: cos(0.785398rad); /* 45deg */
- order: cos(0.785398); /* 45deg */
- order: cos(-45deg); /* -45deg */
- order: cos(-.125turn); /* -45deg */
- order: cos(-50grad); /* -45deg */
- order: cos(-0.785398rad); /* -45deg */
- order: cos(-0.785398); /* -45deg */
- order: cos(cos(0.785398));
- order: cos(cos(cos(cos(0.785398))));
- order: cos(1px);
- order: cos(foo);
- order: cos(Infinity);
- order: cos(InFiNiTy);
- order: cos(-infinity);
-}
-
-.tan {
- order: tan(45deg); /* 45deg */
- order: tan(.125turn); /* 45deg */
- order: tan(50grad); /* 45deg */
- order: tan(0.785398rad); /* 45deg */
- order: tan(0.785398); /* 45deg */
- order: tan(-45deg); /* -45deg */
- order: tan(-.125turn); /* -45deg */
- order: tan(-50grad); /* -45deg */
- order: tan(-0.785398rad); /* -45deg */
- order: tan(-0.785398); /* -45deg */
- order: tan(0);
- order: tan(tan(0.785398));
- order: tan(tan(tan(tan(0.785398))));
- /* Asymptotes */
- order: tan(90deg);
- order: tan(100grad);
- order: tan(270deg);
- order: tan(300grad);
- order: tan(-270deg);
- order: tan(-100grad);
- order: tan(-450deg);
- order: tan(-300grad);
- /* Non Asymptotes */
- order: tan(180deg);
- order: tan(200grad);
- order: tan(360deg);
- order: tan(400grad);
- order: tan(1px);
- order: tan(foo);
- order: tan(Infinity);
- order: tan(InFiNiTy);
- order: tan(-infinity);
-}
-
-.asin {
- order: asin(sin(45deg));
- order: asin(sin(90deg));
- order: asin(-1);
- order: asin(-0.5);
- order: asin(0);
- order: asin(0.5);
- order: asin(1);
- order: asin(2);
- order: asin(-20);
- order: asin(45deg);
- order: asin(1rad);
- order: asin(foo);
- order: asin(infinity);
- order: asin(-infinity);
-}
-
-.acos {
- order: acos(cos(45deg));
- order: acos(cos(90deg));
- order: acos(-1);
- order: acos(-0.5);
- order: acos(0);
- order: acos(0.5);
- order: acos(1);
- order: acos(2);
- order: acos(-20);
- order: acos(45deg);
- order: acos(1rad);
- order: acos(foo);
- order: acos(infinity);
- order: acos(-infinity);
-}
-
-.atan {
- order: atan(infinity);
- order: atan(-infinity);
- order: atan(1);
- order: atan(0);
- order: atan(-0);
- order: atan(tan(45deg)); /* 45deg */
- order: atan(tan(.125turn)); /* 45deg */
- order: atan(tan(50grad)); /* 45deg */
- order: atan(tan(0.785398rad)); /* 45deg */
- order: atan(tan(0.785398)); /* 45deg */
- order: atan(tan(-45deg)); /* -45deg */
- order: atan(tan(-.125turn)); /* -45deg */
- order: atan(tan(-50grad)); /* -45deg */
- order: atan(tan(-0.785398rad)); /* -45deg */
- order: atan(tan(-0.785398)); /* -45deg */
-}
-
-.atan2 {
- order: atan2(-infinity, -infinity);
- order: atan2(-infinity, -1);
- order: atan2(-infinity, -0);
- order: atan2(-infinity, 0);
- order: atan2(-infinity, 1);
- order: atan2(-infinity, infinity);
-
- order: atan2(-1, -infinity);
- order: atan2(-1, -1);
- order: atan2(-1, -0);
- order: atan2(-1, 0);
- order: atan2(-1, 1);
- order: atan2(-1, infinity);
-
- order: atan2(-0, -infinity);
- order: atan2(-0, -1);
- order: atan2(-0, -0);
- order: atan2(-0, 0);
- order: atan2(-0, 1);
- order: atan2(-0, infinity);
-
- order: atan2(0, -infinity);
- order: atan2(0, -1);
- order: atan2(0, -0);
- order: atan2(0, 0);
- order: atan2(0, 1);
- order: atan2(0, infinity);
-
- order: atan2(1, -infinity);
- order: atan2(1, -1);
- order: atan2(1, -0);
- order: atan2(1, 0);
- order: atan2(1, 1);
- order: atan2(1, infinity);
-
- order: atan2(infinity, -infinity);
- order: atan2(infinity, -1);
- order: atan2(infinity, -0);
- order: atan2(infinity, 0);
- order: atan2(infinity, 1);
- order: atan2(infinity, infinity);
-}
-
diff --git a/plugins/postcss-trigonometric-functions/test/wpt.css b/plugins/postcss-trigonometric-functions/test/wpt.css
new file mode 100644
index 000000000..c792a4c02
--- /dev/null
+++ b/plugins/postcss-trigonometric-functions/test/wpt.css
@@ -0,0 +1,44 @@
+/* https://wpt.fyi/results/css/css-values/acos-asin-atan-atan2-computed.html?label=experimental&label=master&aligned&q=sin */
+.test {
+ order: acos(1); /* Should be 0deg */
+ order: atan(0); /* Should be 0deg */
+ order: asin(0); /* Should be 0deg */
+ order: atan2(0, 0); /* Should be 0deg */
+ order: asin(sin(pi / 2)); /* Should be 90deg */
+ order: acos(cos(pi - 3.14159265358979323846)); /* Should be 0deg */
+ order: atan(e - 2.7182818284590452354); /* Should be 0deg */
+ order: asin(sin(30deg + 1.0471967rad)); /* Should be 90deg */
+ order: acos(cos(30deg - 0.523599rad)); /* Should be 0deg */
+ order: asin(sin(3.14159 / 2 + 1 - 1)); /* Should be 90deg */
+ order: asin(sin(100grad)); /* Should be 90deg */
+ order: acos(cos(0 / 2 + 1 - 1)); /* Should be 0deg */
+ order: atan(tan(30deg + 0.261799rad)); /* Should be 45deg */
+ order: atan(tan(0.7853975rad)); /* Should be 45deg */
+ order: atan(tan(3.14159 / 4 + 1 - 1)); /* Should be 45deg */
+ order: asin(sin(0.25turn)); /* Should be 90deg */
+ order: atan2(0,1); /* Should be 0deg */
+ order: atan2(0,-1); /* Should be 180deg */
+ order: atan2(1,-1); /* Should be 135deg */
+ order: atan2(-1,1); /* Should be -45deg */
+ order: cos(sin(acos(cos(pi)))); /* Should be 1 */
+ order: sin(atan(tan(pi/2))); /* Should be 1 */
+ order: atan2(1px, -1px); /* Should be 135deg */
+ order: atan2(1cm, -1cm); /* Should be 135deg */
+ order: atan2(1mm, -1mm); /* Should be 135deg */
+ order: atan2(1Q, -1Q); /* Should be 135deg */
+ order: atan2(1in, -1in); /* Should be 135deg */
+ order: atan2(1pc, -1pc); /* Should be 135deg */
+ order: atan2(1pt, -1pt); /* Should be 135deg */
+ order: atan2(1em, -1em); /* Should be 135deg */
+ order: atan2(1ex, -1ex); /* Should be 135deg */
+ order: atan2(1ch, -1ch); /* Should be 135deg */
+ order: atan2(1rem, -1rem); /* Should be 135deg */
+ order: atan2(1vh, -1vh); /* Should be 135deg */
+ order: atan2(1vw, -1vw); /* Should be 135deg */
+ order: atan2(1deg, -1deg); /* Should be 135deg */
+ order: atan2(1grad, -1grad); /* Should be 135deg */
+ order: atan2(1turn, -1turn); /* Should be 135deg */
+ order: atan2(1rad, -1rad); /* Should be 135deg */
+ order: atan2(1s, -1s); /* Should be 135deg */
+ order: atan2(1ms, -1ms); /* Should be 135deg */
+}
diff --git a/plugins/postcss-trigonometric-functions/test/wpt.expect.css b/plugins/postcss-trigonometric-functions/test/wpt.expect.css
new file mode 100644
index 000000000..253ae9267
--- /dev/null
+++ b/plugins/postcss-trigonometric-functions/test/wpt.expect.css
@@ -0,0 +1,44 @@
+/* https://wpt.fyi/results/css/css-values/acos-asin-atan-atan2-computed.html?label=experimental&label=master&aligned&q=sin */
+.test {
+ order: 0deg; /* Should be 0deg */
+ order: 0deg; /* Should be 0deg */
+ order: 0deg; /* Should be 0deg */
+ order: 0deg; /* Should be 0deg */
+ order: 90deg; /* Should be 90deg */
+ order: 0deg; /* Should be 0deg */
+ order: 0deg; /* Should be 0deg */
+ order: 90deg; /* Should be 90deg */
+ order: 0deg; /* Should be 0deg */
+ order: 90deg; /* Should be 90deg */
+ order: 90deg; /* Should be 90deg */
+ order: 0deg; /* Should be 0deg */
+ order: 45deg; /* Should be 45deg */
+ order: 45deg; /* Should be 45deg */
+ order: 45deg; /* Should be 45deg */
+ order: 90deg; /* Should be 90deg */
+ order: 0deg; /* Should be 0deg */
+ order: 180deg; /* Should be 180deg */
+ order: 135deg; /* Should be 135deg */
+ order: -45deg; /* Should be -45deg */
+ order: 1; /* Should be 1 */
+ order: 1; /* Should be 1 */
+ order: 135deg; /* Should be 135deg */
+ order: 135deg; /* Should be 135deg */
+ order: 135deg; /* Should be 135deg */
+ order: 135deg; /* Should be 135deg */
+ order: 135deg; /* Should be 135deg */
+ order: 135deg; /* Should be 135deg */
+ order: 135deg; /* Should be 135deg */
+ order: 135deg; /* Should be 135deg */
+ order: 135deg; /* Should be 135deg */
+ order: 135deg; /* Should be 135deg */
+ order: 135deg; /* Should be 135deg */
+ order: 135deg; /* Should be 135deg */
+ order: 135deg; /* Should be 135deg */
+ order: 135deg; /* Should be 135deg */
+ order: 135deg; /* Should be 135deg */
+ order: 135deg; /* Should be 135deg */
+ order: 135deg; /* Should be 135deg */
+ order: 135deg; /* Should be 135deg */
+ order: 135deg; /* Should be 135deg */
+}
From 53a4571057f0163f8f41c3bbf19e1065d890357b Mon Sep 17 00:00:00 2001
From: Antonio Laguna
Date: Tue, 17 May 2022 06:51:45 +0200
Subject: [PATCH 07/17] Ignore units for `atan2`
---
plugins/postcss-trigonometric-functions/src/atan2.ts | 4 ++--
plugins/postcss-trigonometric-functions/test/test.css | 3 +++
2 files changed, 5 insertions(+), 2 deletions(-)
create mode 100644 plugins/postcss-trigonometric-functions/test/test.css
diff --git a/plugins/postcss-trigonometric-functions/src/atan2.ts b/plugins/postcss-trigonometric-functions/src/atan2.ts
index 5c0448f61..01d1707a4 100644
--- a/plugins/postcss-trigonometric-functions/src/atan2.ts
+++ b/plugins/postcss-trigonometric-functions/src/atan2.ts
@@ -36,11 +36,11 @@ function transformAtan2Function(decl: Declaration): string | undefined {
// Compute calculations first
if (first.length > 1) {
- first = computeCalculation(first);
+ first = computeCalculation(first, true);
}
if (second.length > 1) {
- second = computeCalculation(second);
+ second = computeCalculation(second, true);
}
if (first.length !== 1 || second.length !== 1) {
diff --git a/plugins/postcss-trigonometric-functions/test/test.css b/plugins/postcss-trigonometric-functions/test/test.css
new file mode 100644
index 000000000..0060207d4
--- /dev/null
+++ b/plugins/postcss-trigonometric-functions/test/test.css
@@ -0,0 +1,3 @@
+.test {
+ order: tan(((1 + 2) * 3) * 1deg);
+}
From a5b6fb2a87e58fd0b51bec97dbd900ddd2677094 Mon Sep 17 00:00:00 2001
From: Antonio Laguna
Date: Tue, 17 May 2022 06:51:56 +0200
Subject: [PATCH 08/17] Housekeeping
---
plugins/postcss-trigonometric-functions/src/utils.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/plugins/postcss-trigonometric-functions/src/utils.ts b/plugins/postcss-trigonometric-functions/src/utils.ts
index 7c278520b..da526d4d5 100644
--- a/plugins/postcss-trigonometric-functions/src/utils.ts
+++ b/plugins/postcss-trigonometric-functions/src/utils.ts
@@ -77,7 +77,7 @@ export function computeCalculation(nodes: Node[], ignoreUnit = false) {
let isValid = true;
const expression = [];
const filteredNodes = nodes.filter(
- node => node.type === 'word' || ALLOWED_OPERATIONS.includes(node.value)
+ node => node.type === 'word' || ALLOWED_OPERATIONS.includes(node.value),
);
let operationPart = ExpressionPart.Number;
let detectedUnit;
From a230e80ea65a9d42c75a797f3372a7917ec50bdb Mon Sep 17 00:00:00 2001
From: Antonio Laguna
Date: Tue, 17 May 2022 06:52:43 +0200
Subject: [PATCH 09/17] Early exit
---
plugins/postcss-trigonometric-functions/src/utils.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/plugins/postcss-trigonometric-functions/src/utils.ts b/plugins/postcss-trigonometric-functions/src/utils.ts
index da526d4d5..7d32f00e5 100644
--- a/plugins/postcss-trigonometric-functions/src/utils.ts
+++ b/plugins/postcss-trigonometric-functions/src/utils.ts
@@ -288,7 +288,7 @@ export function validateNode(
node.nodes = computeCalculation(node.nodes);
const words = node.nodes.filter(filterOnlyWords);
- if (words.length !== 1) {
+ if (node.nodes.length !== 1 || words.length !== 1) {
return;
}
From a1cade27ebe6e952a66c8b1fcb6b76c51c5159db Mon Sep 17 00:00:00 2001
From: Antonio Laguna
Date: Tue, 17 May 2022 06:52:58 +0200
Subject: [PATCH 10/17] Wrong broken tests
---
.../test/wpt.css | 64 +++++++++++++++++++
1 file changed, 64 insertions(+)
diff --git a/plugins/postcss-trigonometric-functions/test/wpt.css b/plugins/postcss-trigonometric-functions/test/wpt.css
index c792a4c02..0466255fe 100644
--- a/plugins/postcss-trigonometric-functions/test/wpt.css
+++ b/plugins/postcss-trigonometric-functions/test/wpt.css
@@ -42,3 +42,67 @@
order: atan2(1s, -1s); /* Should be 135deg */
order: atan2(1ms, -1ms); /* Should be 135deg */
}
+
+/* https://wpt.fyi/results/css/css-values/acos-asin-atan-atan2-invalid.html?label=master&label=experimental&aligned&q=sin */
+.wrong {
+ order: asin());
+ order: asin( ));
+ order: asin(,));
+ order: asin(1dag));
+ order: asin(1deg, ));
+ order: asin(, 1deg));
+ order: asin(1deg + ));
+ order: asin(1deg - ));
+ order: asin(1deg * ));
+ order: asin(1deg / ));
+ order: asin(1deg 2deg));
+ order: asin(1deg, , 2deg));
+ order: acos());
+ order: acos( ));
+ order: acos(,));
+ order: acos(1dag));
+ order: acos(1deg, ));
+ order: acos(, 1deg));
+ order: acos(1deg + ));
+ order: acos(1deg - ));
+ order: acos(1deg * ));
+ order: acos(1deg / ));
+ order: acos(1deg 2deg));
+ order: acos(1deg, , 2deg));
+ order: atan());
+ order: atan( ));
+ order: atan(,));
+ order: atan(1dag));
+ order: atan(1deg, ));
+ order: atan(, 1deg));
+ order: atan(1deg + ));
+ order: atan(1deg - ));
+ order: atan(1deg * ));
+ order: atan(1deg / ));
+ order: atan(1deg 2deg));
+ order: atan(1deg, , 2deg));
+ order: asin(90px));
+ order: asin(30deg + 1.0471967rad, 0));
+ order: acos( 0 ,));
+ order: acos( () 30deg - 0.523599rad ));
+ order: atan(45deg ));
+ order: atan(30deg, + 0.261799rad));
+ order: atan2());
+ order: atan2( ));
+ order: atan2(,));
+ order: atan2(1dag));
+ order: atan2(1deg, ));
+ order: atan2(, 1deg));
+ order: atan2(1deg + ));
+ order: atan2(1deg - ));
+ order: atan2(1deg * ));
+ order: atan2(1deg / ));
+ order: atan2(1deg 2deg));
+ order: atan2(1deg, , 2deg));
+ order: atan2(90px));
+ order: atan2(30deg + 1.0471967rad, 0));
+ order: atan2( 0 ,));
+ order: atan2( () 30deg - 0.523599rad ));
+ order: atan2(45deg ));
+ order: atan2(30deg, + 0.261799rad));
+}
From 7f7edd08a5f70a6b508e50b9e3ae5d228fec01ff Mon Sep 17 00:00:00 2001
From: Antonio Laguna
Date: Fri, 20 May 2022 02:42:57 +0200
Subject: [PATCH 11/17] Accounting for wrong tests
---
.../test/wpt.expect.css | 64 +++++++++++++++++++
1 file changed, 64 insertions(+)
diff --git a/plugins/postcss-trigonometric-functions/test/wpt.expect.css b/plugins/postcss-trigonometric-functions/test/wpt.expect.css
index 253ae9267..a414c7d5f 100644
--- a/plugins/postcss-trigonometric-functions/test/wpt.expect.css
+++ b/plugins/postcss-trigonometric-functions/test/wpt.expect.css
@@ -42,3 +42,67 @@
order: 135deg; /* Should be 135deg */
order: 135deg; /* Should be 135deg */
}
+
+/* https://wpt.fyi/results/css/css-values/acos-asin-atan-atan2-invalid.html?label=master&label=experimental&aligned&q=sin */
+.wrong {
+ order: asin());
+ order: asin( ));
+ order: asin(,));
+ order: asin(1dag));
+ order: asin(1deg, ));
+ order: asin(, 1deg));
+ order: asin(1deg + ));
+ order: asin(1deg - ));
+ order: asin(1deg * ));
+ order: asin(1deg / ));
+ order: asin(1deg 2deg));
+ order: asin(1deg, , 2deg));
+ order: acos());
+ order: acos( ));
+ order: acos(,));
+ order: acos(1dag));
+ order: acos(1deg, ));
+ order: acos(, 1deg));
+ order: acos(1deg + ));
+ order: acos(1deg - ));
+ order: acos(1deg * ));
+ order: acos(1deg / ));
+ order: acos(1deg 2deg));
+ order: acos(1deg, , 2deg));
+ order: atan());
+ order: atan( ));
+ order: atan(,));
+ order: atan(1dag));
+ order: atan(1deg, ));
+ order: atan(, 1deg));
+ order: atan(1deg + ));
+ order: atan(1deg - ));
+ order: atan(1deg * ));
+ order: atan(1deg / ));
+ order: atan(1deg 2deg));
+ order: atan(1deg, , 2deg));
+ order: asin(90px));
+ order: asin(30deg + 1.0471967rad, 0));
+ order: acos( 0 ,));
+ order: acos( () 30deg - 0.523599rad ));
+ order: atan(45deg ));
+ order: 38.15deg);
+ order: atan2());
+ order: atan2( ));
+ order: atan2(,));
+ order: atan2(1dag));
+ order: atan2(1deg, ));
+ order: atan2(, 1deg));
+ order: atan2(1deg + ));
+ order: atan2(1deg - ));
+ order: atan2(1deg * ));
+ order: atan2(1deg / ));
+ order: atan2(1deg 2deg));
+ order: 26.57deg);
+ order: atan2(90px));
+ order: atan2(30deg + 1.0471967rad, 0));
+ order: atan2( 0 ,));
+ order: atan2( () 30deg - 0.523599rad ));
+ order: atan2(45deg ));
+ order: atan2(30deg, + 0.261799rad));
+}
From ab27e059c90c1246638556bbf5be379ea0e1abec Mon Sep 17 00:00:00 2001
From: Antonio Laguna
Date: Fri, 20 May 2022 02:43:18 +0200
Subject: [PATCH 12/17] Support for even more complex calculations
---
.../src/utils.ts | 105 +++++++++++++++---
1 file changed, 92 insertions(+), 13 deletions(-)
diff --git a/plugins/postcss-trigonometric-functions/src/utils.ts b/plugins/postcss-trigonometric-functions/src/utils.ts
index 7d32f00e5..9eed0fcea 100644
--- a/plugins/postcss-trigonometric-functions/src/utils.ts
+++ b/plugins/postcss-trigonometric-functions/src/utils.ts
@@ -54,6 +54,10 @@ enum ExpressionPart {
Operation
}
+function isFiniteNumber(number: number) {
+ return !Number.isNaN(number) && Number.isFinite(number);
+}
+
/**
* Try to compute a calculation from a Node.
*
@@ -76,18 +80,63 @@ enum ExpressionPart {
export function computeCalculation(nodes: Node[], ignoreUnit = false) {
let isValid = true;
const expression = [];
+
+ // Compute functions first, this will go as deep as it needs to resolve parenthesis first
+ // recursion happening here if any parsed value isn't valid everything bails out
+ nodes.filter(node => node.type === 'function').forEach((functionNode: FunctionNode) => {
+ if (!isValid) {
+ return;
+ }
+
+ if (functionNode.value !== '') {
+ isValid = false;
+ return;
+ }
+
+ const clonedNodes = functionNode.nodes.slice(0);
+ const result = computeCalculation(clonedNodes, ignoreUnit);
+ const hasOneItem = result.length === 1;
+ const itemValue = Number(result[0]?.value || '');
+ const isValidResult = hasOneItem && result[0].type === 'word' && !Number.isNaN(itemValue);
+
+ if (!isValidResult) {
+ isValid = false;
+ return;
+ }
+
+ functionNodeToWordNode(functionNode);
+ functionNode.value = result[0].value;
+ });
+
+ if (!isValid) {
+ return nodes;
+ }
+
const filteredNodes = nodes.filter(
node => node.type === 'word' || ALLOWED_OPERATIONS.includes(node.value),
);
let operationPart = ExpressionPart.Number;
+ const expressionUnits = [];
let detectedUnit;
- const addToExpression = (part: string, type: ExpressionPart) => {
+ const addToExpression = (part: string, type: ExpressionPart, unit?: string) => {
if (operationPart !== type) {
isValid = false;
return;
}
+ if (type === ExpressionPart.Number) {
+ const normalizedUnit = unit || '';
+
+ if (!expressionUnits.includes(normalizedUnit)) {
+ expressionUnits.push({
+ number: part,
+ unit: normalizedUnit,
+ index: expression.length,
+ });
+ }
+ }
+
expression.push(part);
operationPart = type === ExpressionPart.Number
? ExpressionPart.Operation
@@ -142,20 +191,13 @@ export function computeCalculation(nodes: Node[], ignoreUnit = false) {
}
if (parsed.unit === 'rad') {
- addToExpression(parsed.number, ExpressionPart.Number);
+ addToExpression(parsed.number, ExpressionPart.Number, parsed.unit);
continue;
}
if (typeof toRad[parsed.unit] === 'function') {
- const number = toRad[parsed.unit](Number(parsed.number));
-
- if (!Number.isNaN(number) && Number.isFinite(number)) {
- addToExpression(number.toString(), ExpressionPart.Number);
- continue;
- } else {
- isValid = false;
- break;
- }
+ addToExpression(parsed.number, ExpressionPart.Number, parsed.unit);
+ continue;
}
isValid = false;
@@ -178,12 +220,49 @@ export function computeCalculation(nodes: Node[], ignoreUnit = false) {
let result;
try {
+ let expressionConversion = '';
+ const differentUnits = new Set(expressionUnits.map(part => part.unit));
+
+ if (differentUnits.size > 1) {
+ // If there's no empty unit this means is computing operations
+ // such as 15deg + 0.25turn
+ // among different units At this stage we're certain they're
+ // degrees, but we need to convert them first to radians
+ if (!differentUnits.has('')) {
+ expressionUnits.forEach(part => {
+ if (part.unit !== 'rad') {
+ const converted = toRad[part.unit](Number(part.number));
+
+ if (isFiniteNumber(converted)) {
+ expression[part.index] = converted.toString();
+ } else {
+ // Bail out
+ throw new Error();
+ }
+ }
+ });
+ } else if (differentUnits.size === 2) {
+ // Now we can only calculate if we don't have more than 2 units
+ // having empty unit and more than 1 is not calculable
+ [expressionConversion] = Array.from(differentUnits).filter(v => v !== '');
+ } else {
+ // Bail out
+ throw new Error();
+ }
+ }
+
const context = vm.createContext({ result: NaN });
const calculation = new vm.Script(`result = ${expression.join(' ')}`);
calculation.runInContext(context);
- if (typeof context.result === 'number' && !Number.isNaN(context.result) && Number.isFinite(context.result)) {
- result = context.result;
+ if (typeof context.result === 'number' && isFiniteNumber(context.result)) {
+ if (expressionConversion) {
+ context.result = toRad[expressionConversion](context.result);
+ }
+
+ if (isFiniteNumber(context.result)) {
+ result = context.result;
+ }
}
} catch(error) {
// Error silently
From a61409dbec6c1d5969a483f19e680244c91fab55 Mon Sep 17 00:00:00 2001
From: Antonio Laguna
Date: Fri, 20 May 2022 02:52:40 +0200
Subject: [PATCH 13/17] More tests
---
.../test/basic.css | 15 +++++++++++++++
.../test/basic.expect.css | 15 +++++++++++++++
.../postcss-trigonometric-functions/test/test.css | 7 +++++--
.../test/test.expect.css | 0
4 files changed, 35 insertions(+), 2 deletions(-)
create mode 100644 plugins/postcss-trigonometric-functions/test/test.expect.css
diff --git a/plugins/postcss-trigonometric-functions/test/basic.css b/plugins/postcss-trigonometric-functions/test/basic.css
index 085fa3457..63ddad0de 100644
--- a/plugins/postcss-trigonometric-functions/test/basic.css
+++ b/plugins/postcss-trigonometric-functions/test/basic.css
@@ -1,7 +1,10 @@
.sin {
order: sin(45deg); /* 45deg */
+ order: sin(15 * 3deg); /* 45deg */
order: sin(.125turn); /* 45deg */
+ order: sin(1 / 8turn); /* 45deg */
order: sin(50grad); /* 45deg */
+ order: sin(10 + 4 * 10grad); /* 45deg */
order: sin(0.785398rad); /* 45deg */
order: sin(0.785398); /* 45deg */
order: sin(-45deg); /* -45deg */
@@ -54,6 +57,8 @@
order: tan(0);
order: tan(tan(0.785398));
order: tan(tan(tan(tan(0.785398))));
+ order: tan(61deg); /* 61deg */
+ order: tan(1 + 2 * 3 * 10deg); /* 61deg should be similar to above */
/* Asymptotes */
order: tan(90deg);
order: tan(100grad);
@@ -63,6 +68,10 @@
order: tan(-100grad);
order: tan(-450deg);
order: tan(-300grad);
+ /* 1 + 2 -> 3 */
+ /* 3 * 3 -> 9 */
+ /* 9 * 10deg -> 90deg */
+ order: tan(((1 + 2) * 3) * 10deg); /* Is asymptotic */
/* Non Asymptotes */
order: tan(180deg);
order: tan(200grad);
@@ -173,3 +182,9 @@
order: atan2(90, 15);
order: atan2(15, 90);
}
+
+.complex-calculations {
+ order: sin(1deg + 3 + .25turn); /* Mixed units, should not calculate */
+ order: sin((1deg + 3) + .25turn); /* Mixed units but separated, should calculate */
+ order: sin(var(--foo) * 3deg);
+}
diff --git a/plugins/postcss-trigonometric-functions/test/basic.expect.css b/plugins/postcss-trigonometric-functions/test/basic.expect.css
index 320b61e34..bb71613d2 100644
--- a/plugins/postcss-trigonometric-functions/test/basic.expect.css
+++ b/plugins/postcss-trigonometric-functions/test/basic.expect.css
@@ -4,6 +4,9 @@
order: 0.70711; /* 45deg */
order: 0.70711; /* 45deg */
order: 0.70711; /* 45deg */
+ order: 0.70711; /* 45deg */
+ order: 0.70711; /* 45deg */
+ order: 0.70711; /* 45deg */
order: -0.70711; /* -45deg */
order: -0.70711; /* -45deg */
order: -0.70711; /* -45deg */
@@ -54,6 +57,8 @@
order: 0;
order: 1.55741;
order: -0.84159;
+ order: 1.80405; /* 61deg */
+ order: 1.80405; /* 61deg should be similar to above */
/* Asymptotes */
order: infinity;
order: infinity;
@@ -63,6 +68,10 @@
order: -infinity;
order: -infinity;
order: -infinity;
+ /* 1 + 2 -> 3 */
+ /* 3 * 3 -> 9 */
+ /* 9 * 10deg -> 90deg */
+ order: infinity; /* Is asymptotic */
/* Non Asymptotes */
order: 0;
order: 0;
@@ -173,3 +182,9 @@
order: 80.54deg;
order: 9.46deg;
}
+
+.complex-calculations {
+ order: sin(1deg + 3 + .25turn); /* Mixed units, should not calculate */
+ order: 0.90533; /* Mixed units but separated, should calculate */
+ order: sin(var(--foo) * 3deg);
+}
diff --git a/plugins/postcss-trigonometric-functions/test/test.css b/plugins/postcss-trigonometric-functions/test/test.css
index 0060207d4..3dcc90ece 100644
--- a/plugins/postcss-trigonometric-functions/test/test.css
+++ b/plugins/postcss-trigonometric-functions/test/test.css
@@ -1,3 +1,6 @@
-.test {
- order: tan(((1 + 2) * 3) * 1deg);
+.calculations {
+ /* 1 + 2 -> 3 */
+ /* 3 * 3 -> 9 */
+ /* 9 * 10deg -> 90deg */
+ order: tan(((1 + 2) * 3) * 10deg); /* Is asymptotic */
}
diff --git a/plugins/postcss-trigonometric-functions/test/test.expect.css b/plugins/postcss-trigonometric-functions/test/test.expect.css
new file mode 100644
index 000000000..e69de29bb
From 8e0042b51adf28ce3d116da365668dd034919afb Mon Sep 17 00:00:00 2001
From: Antonio Laguna
Date: Fri, 20 May 2022 02:57:52 +0200
Subject: [PATCH 14/17] Linting
---
.../package.json | 21 +++++++++----------
1 file changed, 10 insertions(+), 11 deletions(-)
diff --git a/plugins/postcss-trigonometric-functions/package.json b/plugins/postcss-trigonometric-functions/package.json
index 566cef784..146fd3199 100644
--- a/plugins/postcss-trigonometric-functions/package.json
+++ b/plugins/postcss-trigonometric-functions/package.json
@@ -51,27 +51,28 @@
"lint:eslint": "eslint ./src --ext .js --ext .ts --ext .mjs --no-error-on-unmatched-pattern",
"lint:package-json": "node ../../.github/bin/format-package-json.mjs",
"prepublishOnly": "npm run clean && npm run build && npm run test",
- "stryker": "stryker run --logLevel error",
"test": "node .tape.mjs && npm run test:exports",
"test:exports": "node ./test/_import.mjs && node ./test/_require.cjs",
"test:rewrite-expects": "REWRITE_EXPECTS=true node .tape.mjs"
},
+ "homepage": "https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-trigonometric-functions#readme",
"repository": {
"type": "git",
"url": "https://github.com/csstools/postcss-plugins.git",
"directory": "plugins/postcss-trigonometric-functions"
},
+ "bugs": "https://github.com/csstools/postcss-plugins/issues",
"keywords": [
- "postcss-plugin",
- "trigonometric",
+ "acos",
+ "acos2",
+ "asin",
+ "atan",
+ "cos",
"css",
+ "postcss-plugin",
"sin",
- "cos",
"tan",
- "asin",
- "atan",
- "acos",
- "acos2"
+ "trigonometric"
],
"csstools": {
"cssdbId": "trigonometric-functions",
@@ -81,7 +82,5 @@
},
"volta": {
"extends": "../../package.json"
- },
- "homepage": "https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-trigonometric-functions#readme",
- "bugs": "https://github.com/csstools/postcss-plugins/issues"
+ }
}
From b9c207e8cdeb871ebbbb73eeb8ac241ba6ab2967 Mon Sep 17 00:00:00 2001
From: Antonio Laguna
Date: Fri, 20 May 2022 08:55:16 +0200
Subject: [PATCH 15/17] Adding documentation
---
.../docs/README.md | 2 +-
.../postcss-trigonometric-functions/.tape.mjs | 15 +
.../INSTALL.md | 20 +-
.../postcss-trigonometric-functions/README.md | 128 ++++--
.../docs/README.md | 24 +-
.../package.json | 6 +-
.../test/basic.preserve-true.expect.css | 363 ++++++++++++++++++
.../test/examples/example.css | 20 +-
.../test/examples/example.expect.css | 20 +-
.../examples/example.preserve-true.expect.css | 36 +-
.../test/test.css | 6 -
.../test/test.expect.css | 0
12 files changed, 567 insertions(+), 73 deletions(-)
create mode 100644 plugins/postcss-trigonometric-functions/test/basic.preserve-true.expect.css
delete mode 100644 plugins/postcss-trigonometric-functions/test/test.css
delete mode 100644 plugins/postcss-trigonometric-functions/test/test.expect.css
diff --git a/plugins/postcss-stepped-value-functions/docs/README.md b/plugins/postcss-stepped-value-functions/docs/README.md
index 4ddef9ee4..a486bfa7a 100644
--- a/plugins/postcss-stepped-value-functions/docs/README.md
+++ b/plugins/postcss-stepped-value-functions/docs/README.md
@@ -30,7 +30,7 @@
## ⚠️ About custom properties
-Given the dynamic nature of custom properties it's impossible to know what the variable value is which means the plugin can't compute a final value for the stylesheet.
+Given the dynamic nature of custom properties it's impossible to know what the variable value is, which means the plugin can't compute a final value for the stylesheet.
Because of that, any usage that contains a `var` is skipped.
diff --git a/plugins/postcss-trigonometric-functions/.tape.mjs b/plugins/postcss-trigonometric-functions/.tape.mjs
index b675809b4..6783d575c 100644
--- a/plugins/postcss-trigonometric-functions/.tape.mjs
+++ b/plugins/postcss-trigonometric-functions/.tape.mjs
@@ -5,6 +5,21 @@ postcssTape(plugin)({
basic: {
message: "supports basic usage",
},
+ 'basic:preserve-true': {
+ message: 'supports { preserve: true } usage',
+ options: {
+ preserve: true
+ },
+ },
+ 'examples/example': {
+ message: 'minimal example',
+ },
+ 'examples/example:preserve-true': {
+ message: 'minimal example',
+ options: {
+ preserve: true
+ }
+ },
wpt: {
message: "supports wpt cases",
},
diff --git a/plugins/postcss-trigonometric-functions/INSTALL.md b/plugins/postcss-trigonometric-functions/INSTALL.md
index dab91f1a1..d07645d54 100644
--- a/plugins/postcss-trigonometric-functions/INSTALL.md
+++ b/plugins/postcss-trigonometric-functions/INSTALL.md
@@ -17,10 +17,10 @@ Use it as a [PostCSS] plugin:
```js
const postcss = require('postcss');
-const postcssBasePlugin = require('@csstools/postcss-trigonometric-functions');
+const postcssTrigonometricFunctions = require('@csstools/postcss-trigonometric-functions');
postcss([
- postcssBasePlugin(/* pluginOptions */)
+ postcssTrigonometricFunctions(/* pluginOptions */)
]).process(YOUR_CSS /*, processOptions */);
```
@@ -35,11 +35,11 @@ npm install postcss-cli @csstools/postcss-trigonometric-functions --save-dev
Use [PostCSS Trigonometric Functions] in your `postcss.config.js` configuration file:
```js
-const postcssBasePlugin = require('@csstools/postcss-trigonometric-functions');
+const postcssTrigonometricFunctions = require('@csstools/postcss-trigonometric-functions');
module.exports = {
plugins: [
- postcssBasePlugin(/* pluginOptions */)
+ postcssTrigonometricFunctions(/* pluginOptions */)
]
}
```
@@ -103,11 +103,11 @@ Use [React App Rewire PostCSS] and [PostCSS Trigonometric Functions] in your
```js
const reactAppRewirePostcss = require('react-app-rewire-postcss');
-const postcssBasePlugin = require('@csstools/postcss-trigonometric-functions');
+const postcssTrigonometricFunctions = require('@csstools/postcss-trigonometric-functions');
module.exports = config => reactAppRewirePostcss(config, {
plugins: () => [
- postcssBasePlugin(/* pluginOptions */)
+ postcssTrigonometricFunctions(/* pluginOptions */)
]
});
```
@@ -124,11 +124,11 @@ Use [PostCSS Trigonometric Functions] in your Gulpfile:
```js
const postcss = require('gulp-postcss');
-const postcssBasePlugin = require('@csstools/postcss-trigonometric-functions');
+const postcssTrigonometricFunctions = require('@csstools/postcss-trigonometric-functions');
gulp.task('css', function () {
var plugins = [
- postcssBasePlugin(/* pluginOptions */)
+ postcssTrigonometricFunctions(/* pluginOptions */)
];
return gulp.src('./src/*.css')
@@ -148,7 +148,7 @@ npm install grunt-postcss @csstools/postcss-trigonometric-functions --save-dev
Use [PostCSS Trigonometric Functions] in your Gruntfile:
```js
-const postcssBasePlugin = require('@csstools/postcss-trigonometric-functions');
+const postcssTrigonometricFunctions = require('@csstools/postcss-trigonometric-functions');
grunt.loadNpmTasks('grunt-postcss');
@@ -156,7 +156,7 @@ grunt.initConfig({
postcss: {
options: {
processors: [
- postcssBasePlugin(/* pluginOptions */)
+ postcssTrigonometricFunctions(/* pluginOptions */)
]
},
dist: {
diff --git a/plugins/postcss-trigonometric-functions/README.md b/plugins/postcss-trigonometric-functions/README.md
index 4a81de958..5b5973d2b 100644
--- a/plugins/postcss-trigonometric-functions/README.md
+++ b/plugins/postcss-trigonometric-functions/README.md
@@ -1,29 +1,45 @@
# PostCSS Trigonometric Functions [
][postcss]
[
][npm-url]
-[
][css-url]
+[
][css-url]
[
][cli-url]
[
][discord]
-[PostCSS Trigonometric Functions] lets easily create new plugins following some [CSS Specification].
+[PostCSS Trigonometric Functions] lets you use `sin`, `cos`, `tan`, `asin`, `acos`, `atan` and `atan2` to be able to compute trigonometric relationships following the [CSS Values 4] specification.
```pcss
-.foo {
- color: red;
-}
-
-.baz {
- color: green;
+.trigonometry {
+ line-height: sin(pi / 4);
+ line-height: cos(.125turn);
+ line-height: tan(50grad);
+ transform: rotate(asin(-1));
+ transform: rotate(asin(sin(30deg + 1.0471967rad)));
+ transform: rotate(acos(-1));
+ transform: rotate(acos(cos(0 / 2 + 1 - 1)));
+ transform: rotate(atan(infinity));
+ transform: rotate(atan(e - 2.7182818284590452354));
+ transform: rotate(atan2(-infinity,-infinity));
+ transform: rotate(atan2(-infinity,infinity));
+ transform: rotate(atan2(-infinity,infinity));
+ transform: rotate(atan2(90, 15));
}
/* becomes */
-.foo {
- color: blue;
-}
-
-.baz {
- color: green;
+.trigonometry {
+ line-height: 0.70711;
+ line-height: 0.70711;
+ line-height: 1;
+ transform: rotate(-90deg);
+ transform: rotate(90deg);
+ transform: rotate(180deg);
+ transform: rotate(0deg);
+ transform: rotate(90deg);
+ transform: rotate(0deg);
+ transform: rotate(-135deg);
+ transform: rotate(-45deg);
+ transform: rotate(-45deg);
+ transform: rotate(80.54deg);
}
```
@@ -39,10 +55,10 @@ Use it as a [PostCSS] plugin:
```js
const postcss = require('postcss');
-const postcssBasePlugin = require('@csstools/postcss-trigonometric-functions');
+const postcssTrigonometricFunctions = require('@csstools/postcss-trigonometric-functions');
postcss([
- postcssBasePlugin(/* pluginOptions */)
+ postcssTrigonometricFunctions(/* pluginOptions */)
]).process(YOUR_CSS /*, processOptions */);
```
@@ -52,6 +68,24 @@ instructions for:
| [Node](INSTALL.md#node) | [PostCSS CLI](INSTALL.md#postcss-cli) | [Webpack](INSTALL.md#webpack) | [Create React App](INSTALL.md#create-react-app) | [Gulp](INSTALL.md#gulp) | [Grunt](INSTALL.md#grunt) |
| --- | --- | --- | --- | --- | --- |
+## ⚠️ About custom properties
+
+Given the dynamic nature of custom properties it's impossible to know what the variable value is, which means the plugin can't compute a final value for the stylesheet.
+
+Because of that, any usage that contains a `var` is skipped.
+
+## Units
+
+[PostCSS Trigonometric Functions] lets you use different special units that are within the spec and computed at run time to be able to calculate the result of the trigonometric function.
+
+The following units are supported:
+
+* `pi`: Computes to `Math.PI` which is `3.141592653589793`
+* `e`: Computes to `Math.E` which is `2.718281828459045`
+* `infinity`, `-infinity`: Compute to `Infinity` and `-Infinity` respectively. Note that the usage is case insensitive so `InFiNiTy` is a valid value.
+
+Some calculations (such as `sin(-infinity)`) might return `NaN` as per the spec. Given that `NaN` can't be replaced with a value that's useful to CSS it is left as is, as the result will be effectively ignored by the browser.
+
## Options
### preserve
@@ -60,32 +94,62 @@ The `preserve` option determines whether the original notation
is preserved. By default, it is not preserved.
```js
-postcssBasePlugin({ preserve: true })
+postcssTrigonometricFunctions({ preserve: true })
```
```pcss
-.foo {
- color: red;
-}
-
-.baz {
- color: green;
+.trigonometry {
+ line-height: sin(pi / 4);
+ line-height: cos(.125turn);
+ line-height: tan(50grad);
+ transform: rotate(asin(-1));
+ transform: rotate(asin(sin(30deg + 1.0471967rad)));
+ transform: rotate(acos(-1));
+ transform: rotate(acos(cos(0 / 2 + 1 - 1)));
+ transform: rotate(atan(infinity));
+ transform: rotate(atan(e - 2.7182818284590452354));
+ transform: rotate(atan2(-infinity,-infinity));
+ transform: rotate(atan2(-infinity,infinity));
+ transform: rotate(atan2(-infinity,infinity));
+ transform: rotate(atan2(90, 15));
}
/* becomes */
-.foo {
- color: blue;
- color: red;
-}
-
-.baz {
- color: green;
+.trigonometry {
+ line-height: 0.70711;
+ line-height: sin(pi / 4);
+ line-height: 0.70711;
+ line-height: cos(.125turn);
+ line-height: 1;
+ line-height: tan(50grad);
+ transform: rotate(-90deg);
+ transform: rotate(asin(-1));
+ transform: rotate(90deg);
+ transform: rotate(asin(1));
+ transform: rotate(asin(sin(30deg + 1.0471967rad)));
+ transform: rotate(180deg);
+ transform: rotate(acos(-1));
+ transform: rotate(0deg);
+ transform: rotate(acos(1));
+ transform: rotate(acos(cos(0 / 2 + 1 - 1)));
+ transform: rotate(90deg);
+ transform: rotate(atan(infinity));
+ transform: rotate(0deg);
+ transform: rotate(atan(e - 2.7182818284590452354));
+ transform: rotate(-135deg);
+ transform: rotate(atan2(-infinity,-infinity));
+ transform: rotate(-45deg);
+ transform: rotate(atan2(-infinity,infinity));
+ transform: rotate(-45deg);
+ transform: rotate(atan2(-infinity,infinity));
+ transform: rotate(80.54deg);
+ transform: rotate(atan2(90, 15));
}
```
[cli-url]: https://github.com/csstools/postcss-plugins/actions/workflows/test.yml?query=workflow/test
-[css-url]: https://cssdb.org/#TODO
+[css-url]: https://cssdb.org/#trigonometric-functions
[discord]: https://discord.gg/bUadyRwkJS
[npm-url]: https://www.npmjs.com/package/@csstools/postcss-trigonometric-functions
@@ -94,4 +158,4 @@ postcssBasePlugin({ preserve: true })
[PostCSS]: https://github.com/postcss/postcss
[PostCSS Loader]: https://github.com/postcss/postcss-loader
[PostCSS Trigonometric Functions]: https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-trigonometric-functions
-[CSS Specification]: #TODO
+[CSS Values 4]: https://www.w3.org/TR/css-values-4/#trig-funcs
diff --git a/plugins/postcss-trigonometric-functions/docs/README.md b/plugins/postcss-trigonometric-functions/docs/README.md
index 3bc455892..05a3bee28 100644
--- a/plugins/postcss-trigonometric-functions/docs/README.md
+++ b/plugins/postcss-trigonometric-functions/docs/README.md
@@ -14,7 +14,7 @@
-[] lets easily create new plugins following some [CSS Specification].
+[] lets you use `sin`, `cos`, `tan`, `asin`, `acos`, `atan` and `atan2` to be able to compute trigonometric relationships following the [CSS Values 4] specification.
```pcss
@@ -28,6 +28,26 @@
+## ⚠️ About custom properties
+
+Given the dynamic nature of custom properties it's impossible to know what the variable value is, which means the plugin can't compute a final value for the stylesheet.
+
+Because of that, any usage that contains a `var` is skipped.
+
+## Units
+
+[] lets you use different special units that are within the spec and computed at run time to be able to calculate the result of the trigonometric function.
+
+The following units are supported:
+
+* `pi`: Computes to `Math.PI` which is `3.141592653589793`
+* `e`: Computes to `Math.E` which is `2.718281828459045`
+* `infinity`, `-infinity`: Compute to `Infinity` and `-Infinity` respectively. Note that the usage is case insensitive so `InFiNiTy` is a valid value.
+
+Some calculations (such as `sin(-infinity)`) might return `NaN` as per the spec. Given that `NaN` can't be replaced with a value that's useful to CSS it is left as is, as the result will be effectively ignored by the browser.
+
+
+
## Options
### preserve
@@ -48,4 +68,4 @@ is preserved. By default, it is not preserved.
```
-[CSS Specification]:
+[CSS Values 4]:
diff --git a/plugins/postcss-trigonometric-functions/package.json b/plugins/postcss-trigonometric-functions/package.json
index 146fd3199..f28fb7395 100644
--- a/plugins/postcss-trigonometric-functions/package.json
+++ b/plugins/postcss-trigonometric-functions/package.json
@@ -1,6 +1,6 @@
{
"name": "@csstools/postcss-trigonometric-functions",
- "description": "TODO: Add description for Trigonometric Functions",
+ "description": "Use sin(), cos(), tan(), acos(), atan(), and atan2() to compute trigonometric relationships",
"version": "1.0.0",
"contributors": [
{
@@ -19,7 +19,7 @@
"url": "https://opencollective.com/csstools"
},
"engines": {
- "node": "^12 || ^14 || >=16"
+ "node": "^14 || >=16"
},
"main": "dist/index.cjs",
"module": "dist/index.mjs",
@@ -41,7 +41,7 @@
"postcss-value-parser": "^4.2.0"
},
"peerDependencies": {
- "postcss": "^8.3"
+ "postcss": "^8.4"
},
"scripts": {
"build": "rollup -c ../../rollup/default.js",
diff --git a/plugins/postcss-trigonometric-functions/test/basic.preserve-true.expect.css b/plugins/postcss-trigonometric-functions/test/basic.preserve-true.expect.css
new file mode 100644
index 000000000..54b142288
--- /dev/null
+++ b/plugins/postcss-trigonometric-functions/test/basic.preserve-true.expect.css
@@ -0,0 +1,363 @@
+.sin {
+ order: 0.70711;
+ order: sin(45deg); /* 45deg */
+ order: 0.70711;
+ order: sin(15 * 3deg); /* 45deg */
+ order: 0.70711;
+ order: sin(.125turn); /* 45deg */
+ order: 0.70711;
+ order: sin(1 / 8turn); /* 45deg */
+ order: 0.70711;
+ order: sin(50grad); /* 45deg */
+ order: 0.70711;
+ order: sin(10 + 4 * 10grad); /* 45deg */
+ order: 0.70711;
+ order: sin(0.785398rad); /* 45deg */
+ order: 0.70711;
+ order: sin(0.785398); /* 45deg */
+ order: -0.70711;
+ order: sin(-45deg); /* -45deg */
+ order: -0.70711;
+ order: sin(-.125turn); /* -45deg */
+ order: -0.70711;
+ order: sin(-50grad); /* -45deg */
+ order: -0.70711;
+ order: sin(-0.785398rad); /* -45deg */
+ order: -0.70711;
+ order: sin(-0.785398); /* -45deg */
+ order: 0;
+ order: sin(0);
+ order: 0.64964;
+ order: sin(0.70711);
+ order: sin(sin(0.785398));
+ order: 0.56868;
+ order: sin(0.6049);
+ order: sin(sin(0.64964));
+ order: sin(sin(sin(0.70711)));
+ order: sin(sin(sin(sin(0.785398))));
+ order: sin(1px);
+ order: sin(foo);
+ order: NaN;
+ order: sin(Infinity);
+ order: NaN;
+ order: sin(InFiNiTy);
+ order: NaN;
+ order: sin(-infinity);
+ order: sin(var(--foo));
+}
+
+.cos {
+ order: 0.70711;
+ order: cos(45deg); /* 45deg */
+ order: 0.70711;
+ order: cos(.125turn); /* 45deg */
+ order: 0.70711;
+ order: cos(50grad); /* 45deg */
+ order: 0.70711;
+ order: cos(0.785398rad); /* 45deg */
+ order: 0.70711;
+ order: cos(0.785398); /* 45deg */
+ order: 0.70711;
+ order: cos(-45deg); /* -45deg */
+ order: 0.70711;
+ order: cos(-.125turn); /* -45deg */
+ order: 0.70711;
+ order: cos(-50grad); /* -45deg */
+ order: 0.70711;
+ order: cos(-0.785398rad); /* -45deg */
+ order: 0.70711;
+ order: cos(-0.785398); /* -45deg */
+ order: 0.76024;
+ order: cos(0.70711);
+ order: cos(cos(0.785398));
+ order: 0.74872;
+ order: cos(0.72467);
+ order: cos(cos(0.76024));
+ order: cos(cos(cos(0.70711)));
+ order: cos(cos(cos(cos(0.785398))));
+ order: cos(1px);
+ order: cos(foo);
+ order: NaN;
+ order: cos(Infinity);
+ order: NaN;
+ order: cos(InFiNiTy);
+ order: NaN;
+ order: cos(-infinity);
+}
+
+.tan {
+ order: 1;
+ order: tan(45deg); /* 45deg */
+ order: 1;
+ order: tan(.125turn); /* 45deg */
+ order: 1;
+ order: tan(50grad); /* 45deg */
+ order: 1;
+ order: tan(0.785398rad); /* 45deg */
+ order: 1;
+ order: tan(0.785398); /* 45deg */
+ order: -1;
+ order: tan(-45deg); /* -45deg */
+ order: -1;
+ order: tan(-.125turn); /* -45deg */
+ order: -1;
+ order: tan(-50grad); /* -45deg */
+ order: -1;
+ order: tan(-0.785398rad); /* -45deg */
+ order: -1;
+ order: tan(-0.785398); /* -45deg */
+ order: 0;
+ order: tan(0);
+ order: 1.55741;
+ order: tan(1);
+ order: tan(tan(0.785398));
+ order: -0.84159;
+ order: tan(74.69863);
+ order: tan(tan(1.55741));
+ order: tan(tan(tan(1)));
+ order: tan(tan(tan(tan(0.785398))));
+ order: 1.80405;
+ order: tan(61deg); /* 61deg */
+ order: 1.80405;
+ order: tan(1 + 2 * 3 * 10deg); /* 61deg should be similar to above */
+ /* Asymptotes */
+ order: infinity;
+ order: tan(90deg);
+ order: infinity;
+ order: tan(100grad);
+ order: infinity;
+ order: tan(270deg);
+ order: infinity;
+ order: tan(300grad);
+ order: -infinity;
+ order: tan(-270deg);
+ order: -infinity;
+ order: tan(-100grad);
+ order: -infinity;
+ order: tan(-450deg);
+ order: -infinity;
+ order: tan(-300grad);
+ /* 1 + 2 -> 3 */
+ /* 3 * 3 -> 9 */
+ /* 9 * 10deg -> 90deg */
+ order: infinity;
+ order: tan(((1 + 2) * 3) * 10deg); /* Is asymptotic */
+ /* Non Asymptotes */
+ order: 0;
+ order: tan(180deg);
+ order: 0;
+ order: tan(200grad);
+ order: 0;
+ order: tan(360deg);
+ order: 0;
+ order: tan(400grad);
+ order: tan(1px);
+ order: tan(foo);
+ order: NaN;
+ order: tan(Infinity);
+ order: NaN;
+ order: tan(InFiNiTy);
+ order: NaN;
+ order: tan(-infinity);
+}
+
+.asin {
+ order: 45deg;
+ order: asin(0.70711);
+ order: asin(sin(45deg));
+ order: 90deg;
+ order: asin(1);
+ order: asin(sin(90deg));
+ order: -90deg;
+ order: asin(-1);
+ order: -30deg;
+ order: asin(-0.5);
+ order: 0deg;
+ order: asin(0);
+ order: 30deg;
+ order: asin(0.5);
+ order: 90deg;
+ order: asin(1);
+ order: NaN;
+ order: asin(2);
+ order: NaN;
+ order: asin(-20);
+ order: asin(45deg);
+ order: asin(1rad);
+ order: asin(foo);
+ order: NaN;
+ order: asin(infinity);
+ order: NaN;
+ order: asin(-infinity);
+}
+
+.acos {
+ order: 45deg;
+ order: acos(0.70711);
+ order: acos(cos(45deg));
+ order: 90deg;
+ order: acos(0);
+ order: acos(cos(90deg));
+ order: 180deg;
+ order: acos(-1);
+ order: 120deg;
+ order: acos(-0.5);
+ order: 90deg;
+ order: acos(0);
+ order: 60deg;
+ order: acos(0.5);
+ order: 0deg;
+ order: acos(1);
+ order: NaN;
+ order: acos(2);
+ order: NaN;
+ order: acos(-20);
+ order: acos(45deg);
+ order: acos(1rad);
+ order: acos(foo);
+ order: NaN;
+ order: acos(infinity);
+ order: NaN;
+ order: acos(-infinity);
+}
+
+.atan {
+ order: 90deg;
+ order: atan(infinity);
+ order: -90deg;
+ order: atan(-infinity);
+ order: 45deg;
+ order: atan(1);
+ order: 0deg;
+ order: atan(0);
+ order: 0deg;
+ order: atan(-0);
+ order: 45deg;
+ order: atan(1);
+ order: atan(tan(45deg)); /* 45deg */
+ order: 45deg;
+ order: atan(1);
+ order: atan(tan(.125turn)); /* 45deg */
+ order: 45deg;
+ order: atan(1);
+ order: atan(tan(50grad)); /* 45deg */
+ order: 45deg;
+ order: atan(1);
+ order: atan(tan(0.785398rad)); /* 45deg */
+ order: 45deg;
+ order: atan(1);
+ order: atan(tan(0.785398)); /* 45deg */
+ order: -45deg;
+ order: atan(-1);
+ order: atan(tan(-45deg)); /* -45deg */
+ order: -45deg;
+ order: atan(-1);
+ order: atan(tan(-.125turn)); /* -45deg */
+ order: -45deg;
+ order: atan(-1);
+ order: atan(tan(-50grad)); /* -45deg */
+ order: -45deg;
+ order: atan(-1);
+ order: atan(tan(-0.785398rad)); /* -45deg */
+ order: -45deg;
+ order: atan(-1);
+ order: atan(tan(-0.785398)); /* -45deg */
+}
+
+.atan2 {
+ order: -135deg;
+ order: atan2(-infinity, -infinity);
+ order: -90deg;
+ order: atan2(-infinity, -1);
+ order: -90deg;
+ order: atan2(-infinity, -0);
+ order: -90deg;
+ order: atan2(-infinity, 0);
+ order: -90deg;
+ order: atan2(-infinity, 1);
+ order: -45deg;
+ order: atan2(-infinity, infinity);
+
+ order: -180deg;
+
+ order: atan2(-1, -infinity);
+ order: -135deg;
+ order: atan2(-1, -1);
+ order: -90deg;
+ order: atan2(-1, -0);
+ order: -90deg;
+ order: atan2(-1, 0);
+ order: -45deg;
+ order: atan2(-1, 1);
+ order: 0deg;
+ order: atan2(-1, infinity);
+
+ order: -180deg;
+
+ order: atan2(-0, -infinity);
+ order: -180deg;
+ order: atan2(-0, -1);
+ order: -180deg;
+ order: atan2(-0, -0);
+ order: 0deg;
+ order: atan2(-0, 0);
+ order: 0deg;
+ order: atan2(-0, 1);
+ order: 0deg;
+ order: atan2(-0, infinity);
+
+ order: 180deg;
+
+ order: atan2(0, -infinity);
+ order: 180deg;
+ order: atan2(0, -1);
+ order: 180deg;
+ order: atan2(0, -0);
+ order: 0deg;
+ order: atan2(0, 0);
+ order: 0deg;
+ order: atan2(0, 1);
+ order: 0deg;
+ order: atan2(0, infinity);
+
+ order: 180deg;
+
+ order: atan2(1, -infinity);
+ order: 135deg;
+ order: atan2(1, -1);
+ order: 90deg;
+ order: atan2(1, -0);
+ order: 90deg;
+ order: atan2(1, 0);
+ order: 45deg;
+ order: atan2(1, 1);
+ order: 0deg;
+ order: atan2(1, infinity);
+
+ order: 135deg;
+
+ order: atan2(infinity, -infinity);
+ order: 90deg;
+ order: atan2(infinity, -1);
+ order: 90deg;
+ order: atan2(infinity, -0);
+ order: 90deg;
+ order: atan2(infinity, 0);
+ order: 90deg;
+ order: atan2(infinity, 1);
+ order: 45deg;
+ order: atan2(infinity, infinity);
+
+ order: 80.54deg;
+
+ order: atan2(90, 15);
+ order: 9.46deg;
+ order: atan2(15, 90);
+}
+
+.complex-calculations {
+ order: sin(1deg + 3 + .25turn); /* Mixed units, should not calculate */
+ order: 0.90533;
+ order: sin((1deg + 3) + .25turn); /* Mixed units but separated, should calculate */
+ order: sin(var(--foo) * 3deg);
+}
diff --git a/plugins/postcss-trigonometric-functions/test/examples/example.css b/plugins/postcss-trigonometric-functions/test/examples/example.css
index 181f83a54..962618a56 100644
--- a/plugins/postcss-trigonometric-functions/test/examples/example.css
+++ b/plugins/postcss-trigonometric-functions/test/examples/example.css
@@ -1,7 +1,15 @@
-.foo {
- color: red;
-}
-
-.baz {
- color: green;
+.trigonometry {
+ line-height: sin(pi / 4);
+ line-height: cos(.125turn);
+ line-height: tan(50grad);
+ transform: rotate(asin(-1));
+ transform: rotate(asin(sin(30deg + 1.0471967rad)));
+ transform: rotate(acos(-1));
+ transform: rotate(acos(cos(0 / 2 + 1 - 1)));
+ transform: rotate(atan(infinity));
+ transform: rotate(atan(e - 2.7182818284590452354));
+ transform: rotate(atan2(-infinity,-infinity));
+ transform: rotate(atan2(-infinity,infinity));
+ transform: rotate(atan2(-infinity,infinity));
+ transform: rotate(atan2(90, 15));
}
diff --git a/plugins/postcss-trigonometric-functions/test/examples/example.expect.css b/plugins/postcss-trigonometric-functions/test/examples/example.expect.css
index 9d738d5ac..bbc2903ab 100644
--- a/plugins/postcss-trigonometric-functions/test/examples/example.expect.css
+++ b/plugins/postcss-trigonometric-functions/test/examples/example.expect.css
@@ -1,7 +1,15 @@
-.foo {
- color: blue;
-}
-
-.baz {
- color: green;
+.trigonometry {
+ line-height: 0.70711;
+ line-height: 0.70711;
+ line-height: 1;
+ transform: rotate(-90deg);
+ transform: rotate(90deg);
+ transform: rotate(180deg);
+ transform: rotate(0deg);
+ transform: rotate(90deg);
+ transform: rotate(0deg);
+ transform: rotate(-135deg);
+ transform: rotate(-45deg);
+ transform: rotate(-45deg);
+ transform: rotate(80.54deg);
}
diff --git a/plugins/postcss-trigonometric-functions/test/examples/example.preserve-true.expect.css b/plugins/postcss-trigonometric-functions/test/examples/example.preserve-true.expect.css
index 8b020470a..7010ba6a8 100644
--- a/plugins/postcss-trigonometric-functions/test/examples/example.preserve-true.expect.css
+++ b/plugins/postcss-trigonometric-functions/test/examples/example.preserve-true.expect.css
@@ -1,8 +1,30 @@
-.foo {
- color: blue;
- color: red;
-}
-
-.baz {
- color: green;
+.trigonometry {
+ line-height: 0.70711;
+ line-height: sin(pi / 4);
+ line-height: 0.70711;
+ line-height: cos(.125turn);
+ line-height: 1;
+ line-height: tan(50grad);
+ transform: rotate(-90deg);
+ transform: rotate(asin(-1));
+ transform: rotate(90deg);
+ transform: rotate(asin(1));
+ transform: rotate(asin(sin(30deg + 1.0471967rad)));
+ transform: rotate(180deg);
+ transform: rotate(acos(-1));
+ transform: rotate(0deg);
+ transform: rotate(acos(1));
+ transform: rotate(acos(cos(0 / 2 + 1 - 1)));
+ transform: rotate(90deg);
+ transform: rotate(atan(infinity));
+ transform: rotate(0deg);
+ transform: rotate(atan(e - 2.7182818284590452354));
+ transform: rotate(-135deg);
+ transform: rotate(atan2(-infinity,-infinity));
+ transform: rotate(-45deg);
+ transform: rotate(atan2(-infinity,infinity));
+ transform: rotate(-45deg);
+ transform: rotate(atan2(-infinity,infinity));
+ transform: rotate(80.54deg);
+ transform: rotate(atan2(90, 15));
}
diff --git a/plugins/postcss-trigonometric-functions/test/test.css b/plugins/postcss-trigonometric-functions/test/test.css
deleted file mode 100644
index 3dcc90ece..000000000
--- a/plugins/postcss-trigonometric-functions/test/test.css
+++ /dev/null
@@ -1,6 +0,0 @@
-.calculations {
- /* 1 + 2 -> 3 */
- /* 3 * 3 -> 9 */
- /* 9 * 10deg -> 90deg */
- order: tan(((1 + 2) * 3) * 10deg); /* Is asymptotic */
-}
diff --git a/plugins/postcss-trigonometric-functions/test/test.expect.css b/plugins/postcss-trigonometric-functions/test/test.expect.css
deleted file mode 100644
index e69de29bb..000000000
From 186d542bbeb83a9505c9d7829daf38fa7135bc38 Mon Sep 17 00:00:00 2001
From: Antonio Laguna
Date: Fri, 20 May 2022 09:14:00 +0200
Subject: [PATCH 16/17] Missing labeler
---
.github/labeler.yml | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/.github/labeler.yml b/.github/labeler.yml
index c511a6ae8..b8d4202e3 100644
--- a/.github/labeler.yml
+++ b/.github/labeler.yml
@@ -188,5 +188,9 @@
- plugins/postcss-stepped-value-functions/**
- experimental/postcss-stepped-value-functions/**
+"plugins/postcss-trigonometric-functions":
+ - plugins/postcss-trigonometric-functions/**
+ - experimental/postcss-trigonometric-functions/**
+
"sites/postcss-preset-env":
- sites/postcss-preset-env/**
From d7a075c3d07bdd145a1db096f4988f916490306c Mon Sep 17 00:00:00 2001
From: romainmenke
Date: Fri, 20 May 2022 09:16:59 +0200
Subject: [PATCH 17/17] add tests for the same keywords but as non-functions or
without args
---
.../test/basic.css | 20 +++++++++++++++++++
.../test/basic.expect.css | 20 +++++++++++++++++++
.../test/basic.preserve-true.expect.css | 20 +++++++++++++++++++
3 files changed, 60 insertions(+)
diff --git a/plugins/postcss-trigonometric-functions/test/basic.css b/plugins/postcss-trigonometric-functions/test/basic.css
index 63ddad0de..18ed707e3 100644
--- a/plugins/postcss-trigonometric-functions/test/basic.css
+++ b/plugins/postcss-trigonometric-functions/test/basic.css
@@ -188,3 +188,23 @@
order: sin((1deg + 3) + .25turn); /* Mixed units but separated, should calculate */
order: sin(var(--foo) * 3deg);
}
+
+.ignore-not-a-function {
+ order: sin;
+ order: cos;
+ order: tan;
+ order: asin;
+ order: acos;
+ order: atan;
+ order: atan2;
+}
+
+.ignore-no-arguments {
+ order: sin();
+ order: cos();
+ order: tan();
+ order: asin();
+ order: acos();
+ order: atan();
+ order: atan2();
+}
diff --git a/plugins/postcss-trigonometric-functions/test/basic.expect.css b/plugins/postcss-trigonometric-functions/test/basic.expect.css
index bb71613d2..d2b8ddfd1 100644
--- a/plugins/postcss-trigonometric-functions/test/basic.expect.css
+++ b/plugins/postcss-trigonometric-functions/test/basic.expect.css
@@ -188,3 +188,23 @@
order: 0.90533; /* Mixed units but separated, should calculate */
order: sin(var(--foo) * 3deg);
}
+
+.ignore-not-a-function {
+ order: sin;
+ order: cos;
+ order: tan;
+ order: asin;
+ order: acos;
+ order: atan;
+ order: atan2;
+}
+
+.ignore-no-arguments {
+ order: sin();
+ order: cos();
+ order: tan();
+ order: asin();
+ order: acos();
+ order: atan();
+ order: atan2();
+}
diff --git a/plugins/postcss-trigonometric-functions/test/basic.preserve-true.expect.css b/plugins/postcss-trigonometric-functions/test/basic.preserve-true.expect.css
index 54b142288..9f2554cdd 100644
--- a/plugins/postcss-trigonometric-functions/test/basic.preserve-true.expect.css
+++ b/plugins/postcss-trigonometric-functions/test/basic.preserve-true.expect.css
@@ -361,3 +361,23 @@
order: sin((1deg + 3) + .25turn); /* Mixed units but separated, should calculate */
order: sin(var(--foo) * 3deg);
}
+
+.ignore-not-a-function {
+ order: sin;
+ order: cos;
+ order: tan;
+ order: asin;
+ order: acos;
+ order: atan;
+ order: atan2;
+}
+
+.ignore-no-arguments {
+ order: sin();
+ order: cos();
+ order: tan();
+ order: asin();
+ order: acos();
+ order: atan();
+ order: atan2();
+}