Skip to content

Commit

Permalink
Stopped comments and whitespace from being removed when a value conta…
Browse files Browse the repository at this point in the history
…ins gradients

Fixes #18.
  • Loading branch information
gilmoreorless committed May 23, 2017
1 parent 50dbf05 commit e62911a
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 22 deletions.
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]
### Fixed
- CSS comments in gradient values are no longer stripped out (#18)

## 1.0.3 - 2016-12-07
### Changed
- Updated color dependency
Expand All @@ -22,7 +26,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).

## 1.0.0 - 2016-02-20
### Changed
- Smarter calculation of gradient stop positions for smaller CSS output
- Smarter calculation of gradient stop positions for smaller CSS output (#1, #2)

## 0.1.0 - 2016-02-17
### Added
Expand Down
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
The MIT License (MIT)

Copyright 2016 Gilmore Davidson <gilmoreorless@gmail.com>
Copyright 2016-2017 Gilmore Davidson <gilmoreorless@gmail.com>

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
Expand Down
70 changes: 50 additions & 20 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,19 @@ function unitValue(node) {
return node ? valueParser.unit(node.value) : false;
}

/**
* Append one or more values to the end of `baseArr`.
* Acts the same as `baseArr.concat(value)` but mutates instead of returning a copy.
*/
function append(baseArr, value) {
if (Array.isArray(value)) {
baseArr.push.apply(baseArr, value);
} else {
baseArr.push(value);
}
return baseArr.length;
}

/**
* Generate a range of evenly-spaced numbers between start and end values (inclusive)
*/
Expand All @@ -71,9 +84,9 @@ function round(num, precision) {

function ColorStop() {
this.parent = null;
this.beforeNode = null;
this.beforeNodes = [];
this.colorNode = null;
this.separatorNode = null;
this.separatorNodes = [];
this.positionNode = null;
this.warning = null;
this.parsePosition();
Expand All @@ -82,7 +95,7 @@ function ColorStop() {
ColorStop.prototype.clone = function () {
var stop = new ColorStop();
var keys = [
'parent', 'beforeNode', 'colorNode', 'separatorNode', 'positionNode'
'parent', 'beforeNodes', 'colorNode', 'separatorNodes', 'positionNode'
];
keys.forEach(function (key) {
if (this[key] !== undefined) {
Expand All @@ -109,8 +122,8 @@ ColorStop.prototype.setPosition = function (positionString, unit) {
positionString = '' + positionString + unit;
}
var isDirty = false;
if (!this.separatorNode) {
this.separatorNode = { type: 'space', value: ' ' };
if (!this.separatorNodes.length) {
this.separatorNodes.push({ type: 'space', value: ' ' });
isDirty = true;
}
if (!this.positionNode) {
Expand Down Expand Up @@ -169,11 +182,12 @@ Object.defineProperties(ColorStop.prototype, {

nodes: {
get: function () {
var nodes = [];
if (this.beforeNode) nodes.push(this.beforeNode);
if (this.colorNode) nodes.push(this.colorNode);
if (this.separatorNode) nodes.push(this.separatorNode);
if (this.positionNode) nodes.push(this.positionNode);
var nodes = [].concat(
this.beforeNodes,
this.colorNode || [],
this.separatorNodes,
this.positionNode || []
);
return nodes;
}
}
Expand All @@ -186,6 +200,7 @@ function Gradient(parsedNode) {
this.node = {};
this.preludeNodes = [];
this.stops = [];
this.afterNodes = [];
this.setNode(parsedNode);

this._actionQueue = [];
Expand All @@ -200,14 +215,28 @@ Gradient.prototype.setNode = function (node) {
curStop.parent = this;
var isPrelude = false;
var isFirst = true;
var pendingNodes = [];
var movePendingNodesTo = function (appendTo) {
append(appendTo, pendingNodes);
pendingNodes = [];
};
node.nodes.forEach(function (subNode) {
// Make sure comments inside the gradient aren't counted as values
if (subNode.type === 'comment' || subNode.type === 'space') {
append(pendingNodes, subNode);
return;
}
// Dividers (commas) define the end of a stop
if (subNode.type === 'div') {
if (!isPrelude) {
if (isPrelude) {
movePendingNodesTo(this.preludeNodes);
append(pendingNodes, subNode);
} else {
stopList.push(curStop);
curStop = new ColorStop();
curStop.parent = this;
curStop.beforeNode = subNode;
movePendingNodesTo(curStop.beforeNodes);
append(curStop.beforeNodes, subNode);
}
isPrelude = false;
return;
Expand All @@ -221,23 +250,23 @@ Gradient.prototype.setNode = function (node) {
}
}
if (isPrelude) {
this.preludeNodes.push(subNode);
// Spaces are value separators
} else if (subNode.type === 'space') {
curStop.separatorNode = subNode;
// Function or word is either a colour or a stop position
movePendingNodesTo(this.preludeNodes);
append(this.preludeNodes, subNode);
} else if (subNode.type === 'function' || subNode.type === 'word') {
if (curStop.colorNode) {
movePendingNodesTo(curStop.separatorNodes);
curStop.positionNode = subNode;
curStop.parsePosition();
} else {
movePendingNodesTo(curStop.beforeNodes);
curStop.colorNode = subNode;
}
}
}, this);
if (curStop.colorNode) {
stopList.push(curStop);
}
movePendingNodesTo(this.afterNodes);
}
};

Expand All @@ -257,7 +286,7 @@ Gradient.prototype.walkStops = function (fn) {
Gradient.prototype.insertStopAfter = function (newStop, afterStop) {
var action = function () {
// Guarantee that the new stop has a comma node before it
newStop.beforeNode = { type: 'div', value: ',', before: '', after: ' ' };
newStop.beforeNodes = [{ type: 'div', value: ',', before: '', after: ' ' }];

// Add stop to stops list
var stopIndex = this.stops.indexOf(afterStop);
Expand All @@ -277,7 +306,7 @@ Gradient.prototype.syncNodes = function () {
var stopNodes = this.stops.reduce(function (memo, stop) {
return memo.concat(stop.nodes);
}, []);
this.node.nodes = [].concat(this.preludeNodes, stopNodes);
this.node.nodes = [].concat(this.preludeNodes, stopNodes, this.afterNodes);
};


Expand Down Expand Up @@ -466,7 +495,8 @@ module.exports = postcss.plugin('postcss-gradient-transparency-fix', function ()
return function (css, result) {
css.walkDecls(rProp, function (decl) {
if (hasGradient(decl.value) && hasTransparent(decl.value)) {
var fixedValue = fixAllGradients(decl.value);
var value = decl.raw('value') && decl.raw('value').raw || decl.value;
var fixedValue = fixAllGradients(value);
decl.value = fixedValue.value;
fixedValue.warnings.forEach(function (warning) {
decl.warn(result, warning);
Expand Down
31 changes: 31 additions & 0 deletions tests/core-tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -354,4 +354,35 @@ describe('postcss-gradient-transparency-fix', function () {
done);
});

it('preserves comments and whitespace', function (done) {
function makeValue(trans1, trans2) {
return `
/* before value */
linear-gradient(
/* before angle */
to right /* after angle */,
/* before stops */ red,
/* inside stops, before transparent */
${trans1},
/* inside stops, after transparent */
blue
),
/* between gradients */
radial-gradient(/* before stops */
lime
, ${trans2},
magenta
/* after stops */
)
/* after value */
`;
}

testProperty('background-image',
makeValue('transparent', 'transparent'),
makeValue('rgba(255, 0, 0, 0) 50%, rgba(0, 0, 255, 0) 50%',
'rgba(0, 255, 0, 0) 50%, rgba(255, 0, 255, 0) 50%'),
done);
});

});

0 comments on commit e62911a

Please sign in to comment.