├── .editorconfig ├── .eslintrc ├── .gitignore ├── LICENSE.txt ├── README.md ├── package.json ├── postcss-automath.js └── yarn.lock /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | # Unix-style newlines with a newline ending every file 4 | [*] 5 | end_of_line = lf 6 | insert_final_newline = true 7 | trim_trailing_whitespace = true 8 | indent_style = space 9 | indent_size = 4 10 | 11 | # Configs 12 | [*.{json,yml,ini}] 13 | indent_style = space 14 | indent_size = 2 15 | 16 | # Markdown 17 | [*.{md,markdown}] 18 | trim_trailing_whitespace = false 19 | indent_style = tab 20 | indent_size = 4 21 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "pospi" 3 | } 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | /npm-debug.log 3 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | Copyright © 2016 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy 5 | of this software and associated documentation files (the “Software”), to deal 6 | in the Software without restriction, including without limitation the rights 7 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the Software is 9 | furnished to do so, subject to the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be included in 12 | all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PostCSS Auto-Math 2 | 3 | [PostCSS]: https://github.com/postcss/postcss 4 | 5 | [PostCSS] plugin for evaluating math expressions in your CSS sources. 6 | 7 | This plug-in uses the [LESS](http://lesscss.org/) parser internally, in an 8 | (intentionally) very limited way- just to parse mathematical expressions. 9 | As such, all unit handling mechanics are the same as in LESS. 10 | 11 | If you want full LESS parsing functionality in your project, see 12 | [postcss-less-engine](https://www.npmjs.com/package/postcss-less-engine). 13 | 14 | 15 | ```scss 16 | .foo { 17 | font-size: 2 * 8px; 18 | margin: 4px + 2 * 3px; 19 | } 20 | ``` 21 | 22 | ```css 23 | .foo { 24 | font-size: 16px; 25 | margin: 10px; 26 | } 27 | ``` 28 | 29 | ## Usage 30 | 31 | ```js 32 | postcss([ require('postcss-automath') ]) 33 | ``` 34 | 35 | For best results, add the plugin after any variable parsing, mixin processing or 36 | function handling plugins. Since `postcss-automath` works on the final numeric 37 | values of your CSS you need to process all variables, mixins and other dynamic 38 | data *beforehand*. 39 | 40 | See [PostCSS] docs for examples for your environment. 41 | 42 | ## How does this differ to `postcss-calc`? 43 | 44 | They're (deliberately) trying to work towards the calc(...) standard, so for 45 | instance it doesn't support things like exponentials at the moment. 46 | 47 | ## How does this differ to `postcss-math` & `postcss-mathjs`? 48 | 49 | Those plugins want you to add non-standard function wrappers (the `resolve()` 50 | function) around each expression you want evaluated. This module allows you 51 | to write normal math expressions you'd be used to from using SASS, SCSS or LESS. 52 | 53 | Since the variable handling is deferred to another plugin, you are free to use 54 | this module with SCSS, LESS, W3C or even your own custom syntax. 55 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "postcss-automath", 3 | "version": "1.0.1", 4 | "description": "Automatically evaluate mathematical expressions in your CSS source files, like in SASS or LESS. No special function calls needed as with `postcss-mathjs`.", 5 | "main": "postcss-automath.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+ssh://git@github.com/EverledgerIO/postcss-automath.git" 12 | }, 13 | "keywords": [ 14 | "PostCSS", 15 | "math", 16 | "LESS" 17 | ], 18 | "author": "Everledger.io", 19 | "license": "MIT", 20 | "bugs": { 21 | "url": "https://github.com/EverledgerIO/postcss-automath/issues" 22 | }, 23 | "homepage": "https://github.com/EverledgerIO/postcss-automath#readme", 24 | "dependencies": { 25 | "less": "^2.7.1", 26 | "postcss": "^5.2.4", 27 | "postcss-message-helpers": "^2.0.0" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /postcss-automath.js: -------------------------------------------------------------------------------- 1 | /** 2 | * PostCSS automatic mathjs plugin 3 | * 4 | * @see https://github.com/less/less.js/blob/3.x/lib/less/render.js 5 | * @see https://github.com/shauns/postcss-math 6 | * 7 | * @package: postcss-automath 8 | * @author: pospi 9 | * @since: 2016-10-17 10 | */ 11 | 12 | var postcss = require('postcss'); 13 | var helpers = require('postcss-message-helpers'); 14 | var less = require('less'); 15 | 16 | var lessParse = less.parse; 17 | var ParseTree = less.ParseTree; 18 | 19 | function transformMath(argString) { 20 | return new Promise(function(resolve, reject) { 21 | lessParse('.c{p:' + argString + '}', {}, function(err, root, imports, options) { 22 | if (err) { return reject(err); } 23 | 24 | try { 25 | var parseTree = new ParseTree(root, imports); 26 | var result = parseTree.toCSS(options); 27 | 28 | resolve(result.css.replace(/^\s*\.c\s*\{\s*p:\s*/gm, '').replace(/;\s*\}\s*$/gm, '')); 29 | } catch (err) { 30 | reject(err); 31 | } 32 | }); 33 | }); 34 | } 35 | 36 | module.exports = postcss.plugin('postcss-math', function () { 37 | return function (css) { 38 | 39 | // Transform CSS AST here 40 | css.walk(function (node) { 41 | var nodeProp; 42 | 43 | if (node.type === 'decl') { 44 | nodeProp = 'value'; 45 | } 46 | else if (node.type === 'atrule' && node.name === 'media') { 47 | nodeProp = 'params'; 48 | } 49 | else { 50 | return; 51 | } 52 | 53 | if (!node[nodeProp] // no value 54 | || !node[nodeProp].match(/\d/) // no numbers 55 | || !node[nodeProp].match(/\*|\+|\/|-|%/) // no math 56 | || node[nodeProp].match(/^\s*calc\s*\(/) // exclude in-browser calc() statements 57 | || node[nodeProp].match(/^\d+\w*%$/)) { // exclude special case for single percentage values 58 | return; 59 | } 60 | 61 | return transformMath(node[nodeProp]) 62 | .then(function(computed) { 63 | node[nodeProp] = computed; 64 | }) 65 | .catch(function(e) { 66 | // Silently discard Mathjs errors and leave the output alone. 67 | // Important for ignoring generated classnames containing dashes. 68 | }); 69 | }) 70 | }; 71 | }); 72 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | ansi-regex@^2.0.0: 4 | version "2.0.0" 5 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.0.0.tgz#c5061b6e0ef8a81775e50f5d66151bf6bf371107" 6 | 7 | ansi-styles@^2.2.1: 8 | version "2.2.1" 9 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" 10 | 11 | asap@~2.0.3: 12 | version "2.0.5" 13 | resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.5.tgz#522765b50c3510490e52d7dcfe085ef9ba96958f" 14 | 15 | chalk@^1.1.3: 16 | version "1.1.3" 17 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" 18 | dependencies: 19 | ansi-styles "^2.2.1" 20 | escape-string-regexp "^1.0.2" 21 | has-ansi "^2.0.0" 22 | strip-ansi "^3.0.0" 23 | supports-color "^2.0.0" 24 | 25 | errno@^0.1.1: 26 | version "0.1.4" 27 | resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.4.tgz#b896e23a9e5e8ba33871fc996abd3635fc9a1c7d" 28 | dependencies: 29 | prr "~0.0.0" 30 | 31 | escape-string-regexp@^1.0.2: 32 | version "1.0.5" 33 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" 34 | 35 | graceful-fs@^4.1.2: 36 | version "4.1.10" 37 | resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.10.tgz#f2d720c22092f743228775c75e3612632501f131" 38 | 39 | has-ansi@^2.0.0: 40 | version "2.0.0" 41 | resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" 42 | dependencies: 43 | ansi-regex "^2.0.0" 44 | 45 | has-flag@^1.0.0: 46 | version "1.0.0" 47 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-1.0.0.tgz#9d9e793165ce017a00f00418c43f942a7b1d11fa" 48 | 49 | image-size@~0.5.0: 50 | version "0.5.0" 51 | resolved "https://registry.yarnpkg.com/image-size/-/image-size-0.5.0.tgz#be7aed1c37b5ac3d9ba1d66a24b4c47ff8397651" 52 | 53 | js-base64@^2.1.9: 54 | version "2.1.9" 55 | resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.1.9.tgz#f0e80ae039a4bd654b5f281fc93f04a914a7fcce" 56 | 57 | less@^2.7.1: 58 | version "2.7.1" 59 | resolved "https://registry.yarnpkg.com/less/-/less-2.7.1.tgz#6cbfea22b3b830304e9a5fb371d54fa480c9d7cf" 60 | optionalDependencies: 61 | errno "^0.1.1" 62 | graceful-fs "^4.1.2" 63 | image-size "~0.5.0" 64 | mime "^1.2.11" 65 | mkdirp "^0.5.0" 66 | promise "^7.1.1" 67 | source-map "^0.5.3" 68 | 69 | mime@^1.2.11: 70 | version "1.3.4" 71 | resolved "https://registry.yarnpkg.com/mime/-/mime-1.3.4.tgz#115f9e3b6b3daf2959983cb38f149a2d40eb5d53" 72 | 73 | minimist@0.0.8: 74 | version "0.0.8" 75 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" 76 | 77 | mkdirp@^0.5.0: 78 | version "0.5.1" 79 | resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" 80 | dependencies: 81 | minimist "0.0.8" 82 | 83 | postcss-message-helpers@^2.0.0: 84 | version "2.0.0" 85 | resolved "https://registry.yarnpkg.com/postcss-message-helpers/-/postcss-message-helpers-2.0.0.tgz#a4f2f4fab6e4fe002f0aed000478cdf52f9ba60e" 86 | 87 | postcss@^5.2.4: 88 | version "5.2.5" 89 | resolved "https://registry.yarnpkg.com/postcss/-/postcss-5.2.5.tgz#ec428c27dffc7fac65961340a9b022fa4af5f056" 90 | dependencies: 91 | chalk "^1.1.3" 92 | js-base64 "^2.1.9" 93 | source-map "^0.5.6" 94 | supports-color "^3.1.2" 95 | 96 | promise@^7.1.1: 97 | version "7.1.1" 98 | resolved "https://registry.yarnpkg.com/promise/-/promise-7.1.1.tgz#489654c692616b8aa55b0724fa809bb7db49c5bf" 99 | dependencies: 100 | asap "~2.0.3" 101 | 102 | prr@~0.0.0: 103 | version "0.0.0" 104 | resolved "https://registry.yarnpkg.com/prr/-/prr-0.0.0.tgz#1a84b85908325501411853d0081ee3fa86e2926a" 105 | 106 | source-map@^0.5.3, source-map@^0.5.6: 107 | version "0.5.6" 108 | resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412" 109 | 110 | strip-ansi@^3.0.0: 111 | version "3.0.1" 112 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" 113 | dependencies: 114 | ansi-regex "^2.0.0" 115 | 116 | supports-color@^2.0.0: 117 | version "2.0.0" 118 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" 119 | 120 | supports-color@^3.1.2: 121 | version "3.1.2" 122 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.1.2.tgz#72a262894d9d408b956ca05ff37b2ed8a6e2a2d5" 123 | dependencies: 124 | has-flag "^1.0.0" 125 | 126 | --------------------------------------------------------------------------------