Giter Club home page Giter Club logo

reduce-css-calc's Introduction

reduce-css-calc

Build Status

Reduce CSS calc() function to the maximum.

Particularly useful for packages like rework-calc or postcss-calc.

Installation

npm install reduce-css-calc

Usage

var reducedString = reduceCSSCalc(string, precision)

var reduceCSSCalc = require('reduce-css-calc')

reduceCSSCalc("calc(1 + 1)")
// 2

reduceCSSCalc("calc((6 / 2) - (4 * 2) + 1)")
// -4

reduceCSSCalc("calc(1/3)")
// 0.33333

reduceCSSCalc("calc(1/3)", 10)
// 0.3333333333

reduceCSSCalc("calc(3rem * 2 - 1rem)")
// 5rem

reduceCSSCalc("calc(2 * 50%)")
// 100%

reduceCSSCalc("calc(120% * 50%)")
// 60%

reduceCSSCalc("a calc(1 + 1) b calc(1 - 1) c")
// a 2 b 0 c

reduceCSSCalc("calc(calc(calc(1rem * 0.75) * 1.5) - 1rem)")
// 0.125rem

reduceCSSCalc("calc(calc(calc(1rem * 0.75) * 1.5) - 1px)")
// calc(1.125rem - 1px)

reduceCSSCalc("-moz-calc(100px / 2)")
// 50px

reduceCSSCalc("-moz-calc(50% - 2em)")
// -moz-calc(50% - 2em)

See unit tests for others examples.


Contributing

Work on a branch, install dev-dependencies, respect coding style & run tests before submitting a bug fix or a feature.

git clone https://github.com/MoOx/reduce-css-calc.git
git checkout -b patch-1
npm install
npm test

reduce-css-calc's People

Contributors

andyjansson avatar ben-eb avatar davidgovea avatar dennisfrank avatar dependabot[bot] avatar dlee avatar gyoshev avatar justineo avatar moox avatar pbevin avatar scrum avatar semigradsky avatar snowystinger avatar sylvainpolletvillard avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

reduce-css-calc's Issues

Strange unit math in 2.x

calc(100vw - (100vw - 100%))

I'm using this hack to solve ios scroll bug.

1.3.0: calc(100vw - (100vw - 100%))
2.0: calc(0vw - 100%)

Can't understand new math with different units. This is totally incorrect. I can understand calc(0vw + 100%), but current behavior looks very suspicious.

Cannot handle nested calc()?

Using reduce-css-calc via cssnano via optimize-cssnano-plugin.

The input CSS I believe is coming from Bootstrap 4, possibly this line, but it's hard to pinpoint based on the error.

height: calc(calc(2.25rem + 2px) - 1px * 2);

Getting:

 ERROR  Error: CSS minification error: Parse error on line 1:
 auto - 1px * 2
              ^
Expecting 'SUB', 'LPAREN', 'NESTED_CALC', 'NUMBER', 'CSS_VAR', 'LENGTH', 'ANGLE', 'TIME', 'FREQ', 'RES', 'EMS', 'EXS', 'CHS', 'REMS', 'VHS', 'VWS', 'VMINS', 'VMAXS', 'PERCENTAGE', got 'PREFIX'. File: css/app.a46e10bb.css
Error: CSS minification error: Parse error on line 1:
auto - 1px * 2
^
Expecting 'SUB', 'LPAREN', 'NESTED_CALC', 'NUMBER', 'CSS_VAR', 'LENGTH', 'ANGLE', 'TIME', 'FREQ', 'RES', 'EMS', 'EXS', 'CHS', 'REMS', 'VHS', 'VWS', 'VMINS', 'VMAXS', 'PERCENTAGE', got 'PREFIX'. File: css/app.a46e10bb.css
    at /develop/node_modules/@intervolga/optimize-cssnano-plugin/index.js:106:21
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] build-prod: `vue-cli-service build && /bin/bash build/prod-server-replace-vars.sh`
npm ERR! Exit status 1
npm ERR! 
npm ERR! Failed at the [email protected] build-prod script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR!     /root/.npm/_logs/2018-10-02T18_06_56_983Z-debug.log

Any ideas?

Error when building

When trying to use this library within create-react-app and performing a yarn build, I'm getting the following error:
image

It looks to be caused by template literals here:
image
which are not being transpiled out. I was going to use the es6 src instead of dist but it's omitted from the npm package.

I see the build target is for node 4+ and not browser. Any chance of supporting a browser target or exposing the es6 for browser libraries. Btw, version 1.3.0 works fine and is what I'm currently using my react-svg-text component

Evaluation of mis-matching units

Hi, in reviewing the tests it looks like mis-matching units are evaluated, for example:

test(
  'should reduce nested expression',
  testFixture,
  'calc( (1em - calc( 10px + 1em)) / 2)',
  '-5px'
)

I'm unsure how this equates to 5px unless you are also converting em to px.

Based on current browser implementations, mis-matching units are not evaluated and this would get converted to calc((1em - (10px + 1em)) / 2). I am wondering if this evaluation is intentional or a a bug.

calc(...)rem adds space between number and unit

I'm not sure if this is a dumb thing, but I'm having issue while using cssnext with reduce-css-calc

My Code:
height: calc(20 / 1.618)rem;

Output:
height: 12.36094 rem

Expected Output:
height: 12.36094rem

Is my syntax wrong?

constant + calc

might be related to #34. but 100% is transformed to 1, only in the body of @supports while the condition stays 100%
input

@supports (width:calc(100% - constant(safe-area-inset-left))){
  .a{
    width:calc(100% - constant(safe-area-inset-left))
  }
}

output

@supports (width:calc(100% - constant(safe-area-inset-left))){
  .a{
    width:calc(1- constant(safe-area-inset-left))
  }
}

Could not reduce expression: calc(0.25em - 1px)?

Hi, I am using postcss-calc (which uses reduce-css-calc if I'm correct), thanks for your work.

I was under the impression that mixed units should work (I even saw some tests for it) so I am confused why the following throws an error:

Could not reduce expression: calc(.25em - 1px) [postcss-calc]

I am simply using it as:

.c-linklist a {
    display: block;
    padding-top: .25em;
    padding-bottom: calc(.25em - 1px);
}

Am I missing something?

Parse error on custom property fallback

The parser will fail if using nested custom properties with fallbacks which themselves are custom properties.

This code:

.my-class {
  width: calc(var(--xxx, var(--yyy)) / 2);
}

Will throw this error:

  Error: Parse error on line 1:
  ...ar(--xxx, var(--yyy)) / 2
  -----------------------^
  Expecting 'EOF', 'ADD', 'SUB', 'MUL', 'DIV', got 'RPAREN'

I tried putting together a PR using recursive rules for the parser but realized someone else with a better understanding of Bison syntax could do a better job than me.

The best I could come up with is a regex which handles two levels of nesting which is enough for my use case but not really fool proof. I figured I should open an issue before submitting a PR with the following change to the parser:

- (var\([^\)]*\))                        return 'CSS_VAR';
+ (var\((?:[^)(]+|\((?:[^)(]+|\([^)(]*\))*\))*\))  return 'CSS_VAR';

Constant values not supported

iOS Safari 11 introduces constant values to account for the safe zone, which in browser is supported in calc. When a constant value is used in a calc with this plug in, the compiler fails with the following error:

Expecting 'SUB', 'LPAREN', 'NESTED_CALC', 'NUMBER', 'CSS_VAR', 'LENGTH', 'ANGLE', 'TIME', 'FREQ', 'RES', 'EMS', 'EXS', 'CHS', 'REMS', 'VHS', 'VWS', 'VMINS', 'VMAXS', 'PERCENTAGE', got 'PREFIX']
message: 'Parse error on line 1:\nconstant(safe-area-i\n^\nExpecting \'SUB\', \'LPAREN\', \'NESTED_CALC\', \'NUMBER\', \'CSS_VAR\', \'LENGTH\', \'ANGLE\', \'TIME\', \'FREQ\', \'RES\', \'EMS\', \'EXS\', \'CHS\', \'REMS\', \'VHS\', \'VWS\', \'VMINS\', \'VMAXS\', \'PERCENTAGE\', got \'PREFIX\'',
showStack: false,
showProperties: true,
plugin: 'gulp-postcss',

A percent is a not a unit of measure

Version 2.0.0 included a breaking change that makes sense but has an error. That change was:

  • reduce-css-calc will now throw when trying to multiply or divide by the same unit (e.g. calc(200px * 20px)), and also when trying to divide by zero.

While a unit like "px" times "px" should throw an error, a percent ("%") is not a unit; it denotes a fraction of 100. It is legitimate to multiple 50% by 50%, as it is the exact same mathematical meaning as 50/100 * 50/100.

I may be wrong here, but I'm pretty sure. Thoughts?

Standards or not?

Now this library reducing correct calc expressions.

For some people it would be convenient to write shorter but incorrect calc expressions.
For example

div {
  margin-left: -calc(2px *2);
}

instead

div {
  margin-left: calc(-1*(2px * 2));
}

There are some issues about this: #30, #32

I think that we should decide: use ONLY the correct syntax or start supporting an informal syntax.
If we choose the second option, we need to agree on what it will be.

Incorrect reduction of nested expression

Reducing the expression calc( (1em - calc( 10px + 1em)) / 2) reduces incorrectly to calc(1em - 5px) (the correct one should be -5px).

A workaround is to add another operation, however this is far from ideal: calc( (1em + (-1 * calc( 10px + 1em))) / 2).

I know the expressions look weird, but these actually are real-world examples from SASS-generated CSS (the inner calc expression is stored in a variable).

Slow resolution time for certain expressions

Using postcss-calc wrapper, I've found a case that the library seems to struggle to resolve:

font-size: calc(26.140174776426555px + (43.56695796071093 - 26.140174776426555) * ((100vw - 600px) / (1140 - 600)));

If there's anything I can do to give more info let me know! The symptom I get is a (very very) long resolution time when the plug-in is on (500s vs 7s for a webpack run)

Plugin is removing comments and it shouldn't do it

So, I'm having an issue related to comments that are deleted when those are typed inside the property value.

In my case, I need to use comments in order to use some RTLCSS features.

.title {
      margin-top: calc(2rem * 2) /*rtl:2rem*/;
}

Expected Output:

.title {
      margin-top: 4rem /*rtl:2rem*/;
}

Actual Output:

.title {
   margin-top: 4rem;
}

Would it be possible to fix that?

Thank you.

Complex calc function simplifying incorrectly

This was reported in postcss-cssnext, but it was recommended to be reported here. The post below is nearly identical to the link below:

MoOx/postcss-cssnext#450

In version 2.11.0 of postcss-cssnext, complex calc functions would not be simplified, so they would remain as is when compiled. However, I upgraded postcss-cssnext and in version 3.1.0, postcss-cssnext tries to simplify the calc function, but does so incorrectly. Maybe I'm doing something wrong on my end, but upgrading from 2.11.0 to 3.1.0 seems to mess up the result. For example:

calc(100% + (2 * 100px) - ((75.37% - 63.5px) - 900px));

incorrectly simplifies and compiles to:

calc(100% + 200px - 75.37% - 963.5px));

The double negative here is not handled properly.

Also, the following:

calc(((((100% + (2 * 30px) + 63.5px) / 0.7537) - (100vw - 60px)) / 2) + 30px);

incorrectly simplifies and compiles to:

calc((176.0366% + 217.4052px - 100vw - 60px) / 2 + 30px);

I have no idea what is happening here, but it's completely wrong.

I know I could simplify my calcs, but there are some semantics behind organizing it this way in my code.

In version 2.11.0, when the compiled calcs were sent to the browser without being simplified, they worked as expected.

Discard calc operations that operate on zero values

Would it be possible to discard parts of the calc() function that operate on zero values? For example:

div {
    width: calc(100vw / 2 - 6px + 0px);
}

Can be:

div {
    width: calc(100vw / 2 - 6px);
}

And:

div {
    width: calc(500px - 0px);
}

Can be:

div {
    width: 500px;
}

It's from this edge case in CSSO:

css/csso#222

1.2.5 triggers circular reference in grunt config

I haven't created a cut down replication case for this yet, but while I do I thought you might want to start looking into it.

Stack trace from grunt:

Warning: Circular reference detected (.files.src[0]) Use --force to continue.
Error: Circular reference detected (.files.src[0])
  at recurse (/home/ephox/jenkins/workspace/fusebox/node_modules/grunt-legacy-util/index.js:99:15)
  at /home/ephox/jenkins/workspace/fusebox/node_modules/grunt-legacy-util/index.js:110:16
  at Array.map (native)
  at recurse (/home/ephox/jenkins/workspace/fusebox/node_modules/grunt-legacy-util/index.js:109:20)
  at recurse (/home/ephox/jenkins/workspace/fusebox/node_modules/grunt-legacy-util/index.js:119:20)
  at recurse (/home/ephox/jenkins/workspace/fusebox/node_modules/grunt-legacy-util/index.js:119:20)
  at Object.util.recurse (/home/ephox/jenkins/workspace/fusebox/node_modules/grunt-legacy-util/index.js:130:10)
  at Function.config.process (/home/ephox/jenkins/workspace/fusebox/node_modules/grunt/lib/grunt/config.js:52:21)
  at Function.config.get (/home/ephox/jenkins/workspace/fusebox/node_modules/grunt/lib/grunt/config.js:46:17)
  at /home/ephox/jenkins/workspace/fusebox/node_modules/grunt/lib/grunt/config.js:98:19
  at Array.filter (native)
  at Object.config.requires [as requiresConfig] (/home/ephox/jenkins/workspace/fusebox/node_modules/grunt/lib/grunt/config.js:97:40)
  at Object.<anonymous> (/home/ephox/jenkins/workspace/fusebox/node_modules/grunt/lib/grunt/task.js:225:10)
  at Object.thisTask.fn (/home/ephox/jenkins/workspace/fusebox/node_modules/grunt/lib/grunt/task.js:73:16)
  at Object.<anonymous> (/home/ephox/jenkins/workspace/fusebox/node_modules/grunt/lib/util/task.js:294:30)
  at Task.runTaskFn (/home/ephox/jenkins/workspace/fusebox/node_modules/grunt/lib/util/task.js:244:24)
  at Task.<anonymous> (/home/ephox/jenkins/workspace/fusebox/node_modules/grunt/lib/util/task.js:293:12)
  at /home/ephox/jenkins/workspace/fusebox/node_modules/grunt/lib/util/task.js:220:11
  at _combinedTickCallback (internal/process/next_tick.js:67:7)
  at process._tickCallback (internal/process/next_tick.js:98:9)
  at Function.Module.runMain (module.js:449:11)
  at startup (node.js:148:18)
  at node.js:405:3

Analysing my build server logs, the only change in my node dependencies is:

--- passing.txt 2016-08-22 17:29:32.000000000 +1000
+++ failing.txt 2016-08-22 17:28:51.000000000 +1000
@@ -177,8 +177,9 @@
 ├── [email protected]
 ├─┬ [email protected]
 │ ├── [email protected]
-│ └─┬ [email protected]
+│ └─┬ [email protected]
 │   ├── [email protected]
+│   ├── [email protected]
 │   └─┬ [email protected]
 │     └── [email protected]
 ├─┬ [email protected]

and I confirmed rolling back to 1.2.4 resolves the grunt error.

error PX

"reduce-css-calc": "^2.1.8"

var reduceCSSCalc = require('reduce-css-calc')
console.log(reduceCSSCalc("calc(100% + 2px)"))
console.log(reduceCSSCalc("calc(100% + 2PX)")) // error

unitless zero value bug

Hi :)

I'm using postcss and have following expression:

div {
    width: calc(100% - $width - $margin);
}

and I found strange behavior when try to use zero values:

// $width: 200px;
// $margin: 0; or $margin: 0px; or $margin: 0px;
// output: 
div {
    width: calc(100% - 200px - 0); // this is not valid expression inside 'calc' and browsers don't calculate it
}

but these are valid expressions:

width: calc(100% - 200px - 0px);
width: calc(100% - 200px - 0%);

so my question is: Could you fix this? Or this is a normal behavior?
thank you :)

Document use of `eval()` to parse calculations

I noticed that the way math expressions are reduced is by using eval() (

result = eval(toEvaluate)
), however this isn't documented anywhere. Technically, the w3c spec calls for calc to only accept simple binary operators (https://www.w3.org/TR/css3-values/#calc-notation), but with this you could also do things like

.foo {
  width: calc(2.5px >>> 0);
}

See this codepen as an example.

Personally I view this as a feature, and feel like it should be documented rather than just being an implementation detail. What do you think?

Negating values broken in 2.X

The following CSS transform used to work in 1.X

/* source */
foo {
  left: calc(-(100px - 10px));
}
/* expected */
foo {
  left: -90px;
}

However, as of 2.X, this just throws an error.

If you past the source example above into http://cssnext.io/playground/, you can see that nothing is produced (which I take to mean it couldn't compile).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.