Created
February 2, 2014 10:10
-
-
Save GoalSmashers/8765857 to your computer and use it in GitHub Desktop.
clean-css patch 1
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| commit 29fbb23145254bab63a83e261a02fcf5dc09b5fd | |
| Author: Jakub Pawlowicz <contact@jakubpawlowicz.com> | |
| Date: Sun Jan 19 16:51:07 2014 +0000 | |
| Cleaned up line breaks. | |
| diff --git a/lib/properties/compact.js b/lib/properties/compact.js | |
| index d3f5884..af51026 100644 | |
| --- a/lib/properties/compact.js | |
| +++ b/lib/properties/compact.js | |
| @@ -15,14 +15,14 @@ module.exports = (function () { | |
| var makeDefaultProperties = function (props, important) { | |
| return props.map(function(prop) { return makeDefaultProperty(prop, important); }); | |
| }; | |
| - | |
| + | |
| // Regexes used for stuff | |
| var cssUnitRegexStr = '(\\.?\\d+(px|%|em|rem|in|cm|mm|ex|pt|pc|)|auto|inherit)'; | |
| var cssFunctionNoVendorRegexStr = '[A-Z]?(\\-|[A-Z]|[0-9])+\\(([A-Z]|[0-9]| |\\+|\\-|%|\\.)*\\)'; | |
| var cssFunctionVendorRegexStr = '\\-(\\-|[A-Z]|[0-9])+\\(([A-Z]|[0-9]| |\\+|\\-|%|\\.)*\\)'; | |
| var cssFunctionAnyRegexStr = '(' + cssFunctionNoVendorRegexStr + '|' + cssFunctionVendorRegexStr + ')'; | |
| var cssUnitAnyRegexStr = '(' + cssUnitRegexStr + '|' + cssFunctionNoVendorRegexStr + '|' + cssFunctionVendorRegexStr + ')'; | |
| - | |
| + | |
| // Validator | |
| // NOTE: The point here is not semantical but syntactical validity | |
| var validator = { | |
| @@ -96,7 +96,7 @@ module.exports = (function () { | |
| } | |
| }; | |
| validator = Object.freeze(validator); | |
| - | |
| + | |
| // Merge functions | |
| var canMerge = { | |
| // Use when two tokens of the same property can always be merged | |
| @@ -113,17 +113,17 @@ module.exports = (function () { | |
| // The idea here is that 'more understandable' values override 'less understandable' values, but not vice versa | |
| // Understandability: (unit without functions) > (vendor prefixed functions) > (standard functions) > anything else | |
| // NOTE: vendor-specific property values are not taken into consideration here at the moment | |
| - | |
| + | |
| if (validator.isValidFunctionWithVendorPrefix(t2.value)) | |
| return true; | |
| if (validator.isValidFunctionWithVendorPrefix(t1.value)) | |
| return false; | |
| - | |
| + | |
| if (validator.isValidFunctionWithoutVendorPrefix(t2.value)) | |
| return true; | |
| if (validator.isValidFunctionWithoutVendorPrefix(t1.value)) | |
| return false; | |
| - | |
| + | |
| return t1.value === t2.value; | |
| }, | |
| // Use for color properties (color, background-color, border-color, etc.) | |
| @@ -131,19 +131,19 @@ module.exports = (function () { | |
| // The idea here is that 'more understandable' values override 'less understandable' values, but not vice versa | |
| // Understandability: (hex | named) > (rgba | hsla) > anything else | |
| // NOTE: at this point rgb and hsl are replaced by hex values by clean-css | |
| - | |
| + | |
| // (hex | named) | |
| if (validator.isValidNamedColor(t2.value) || validator.isValidHexColor(t2.value)) | |
| return true; | |
| if (validator.isValidNamedColor(t1.value) || validator.isValidHexColor(t1.value)) | |
| return false; | |
| - | |
| + | |
| // (rgba|hsla) | |
| if (validator.isValidRgbaColor(t2.value) || validator.isValidHslColor(t2.value) || validator.isValidHslaColor(t2.value)) | |
| return true; | |
| if (validator.isValidRgbaColor(t1.value) || validator.isValidHslColor(t1.value) || validator.isValidHslaColor(t1.value)) | |
| return false; | |
| - | |
| + | |
| // anything else | |
| return t1.value === t2.value; | |
| }, | |
| @@ -151,24 +151,24 @@ module.exports = (function () { | |
| backgroundImage: function (t1, t2) { | |
| // The idea here is that 'more understandable' values override 'less understandable' values, but not vice versa | |
| // Understandability: (none | url) > anything else > none --- yes, none both overrides anything and is overridden by anyting | |
| - | |
| + | |
| // none | |
| if (t1.value === 'none') | |
| return true; | |
| - | |
| + | |
| // (none | url) | |
| if (t2.value === 'none' || validator.isValidUrl(t2.value)) | |
| return true; | |
| if (t1.value === 'none' || validator.isValidUrl(t1.value)) | |
| return false; | |
| - | |
| + | |
| // anything else | |
| return t1.value === t2.value; | |
| } | |
| // TODO: add more | |
| }; | |
| canMerge = Object.freeze(canMerge); | |
| - | |
| + | |
| // Functions for breaking up shorthands to components | |
| var breakUp = { | |
| // Use this for properties with 4 unit values (like margin or padding) | |
| @@ -177,7 +177,7 @@ module.exports = (function () { | |
| var descriptor = processable[token.prop]; | |
| var result = []; | |
| var splitval = token.value.match(new RegExp(cssUnitAnyRegexStr, 'gi')); | |
| - | |
| + | |
| if (splitval.length === 0 || (splitval.length < descriptor.components.length && descriptor.components.length > 4)) { | |
| // This token is malformed and we have no idea how to fix it. So let's just keep it intact | |
| return [token]; | |
| @@ -196,7 +196,7 @@ module.exports = (function () { | |
| // foo{margin:1px 2px 3px} -> foo{margin:1px 2px 3px 2px} | |
| splitval[3] = splitval[1]; | |
| } | |
| - | |
| + | |
| // Now break it up to its components | |
| for (var i = 0; i < descriptor.components.length; i++) { | |
| var t = { | |
| @@ -206,7 +206,7 @@ module.exports = (function () { | |
| }; | |
| result.push(t); | |
| } | |
| - | |
| + | |
| return result; | |
| }, | |
| // Breaks up a background property value | |
| @@ -214,23 +214,23 @@ module.exports = (function () { | |
| // Default values | |
| var result = makeDefaultProperties(['background-color', 'background-image', 'background-repeat', 'background-position', 'background-attachment'], token.isImportant); | |
| var color = result[0], image = result[1], repeat = result[2], position = result[3], attachment = result[4]; | |
| - | |
| + | |
| // Take care of inherit | |
| if (token.value === 'inherit') { | |
| // NOTE: 'inherit' is not a valid value for background-attachment so there we'll leave the default value | |
| color.value = image.value = repeat.value = position.value = 'inherit'; | |
| return result; | |
| } | |
| - | |
| + | |
| // Break the background up into parts | |
| var parts = token.value.split(' '); | |
| if (parts.length === 0) { | |
| return result; | |
| } | |
| - | |
| + | |
| // The trick here is that we start going through the parts from the end, then stop after background repeat, | |
| // then start from the from the beginning until we find a valid color value. What remains will be treated as background-image. | |
| - | |
| + | |
| var currentIndex = parts.length - 1; | |
| var current = parts[currentIndex]; | |
| // Attachment | |
| @@ -277,15 +277,15 @@ module.exports = (function () { | |
| // Default values | |
| var result = makeDefaultProperties(['list-style-type', 'list-style-position', 'list-style-image'], token.isImportant); | |
| var type = result[0], position = result[1], image = result[2]; | |
| - | |
| + | |
| if (token.value === 'inherit') { | |
| type.value = position.value = image.value = 'inherit'; | |
| return result; | |
| } | |
| - | |
| + | |
| var parts = token.value.split(' '); | |
| var ci = 0; | |
| - | |
| + | |
| // Type | |
| if (ci < parts.length && validator.isValidListStyleType(parts[ci])) { | |
| type.value = parts[ci]; | |
| @@ -300,7 +300,7 @@ module.exports = (function () { | |
| if (ci < parts.length) { | |
| image.value = parts.splice(ci, parts.length - ci + 1).join(' '); | |
| } | |
| - | |
| + | |
| return result; | |
| }, | |
| // Breaks up outline | |
| @@ -308,22 +308,22 @@ module.exports = (function () { | |
| // Default values | |
| var result = makeDefaultProperties(['outline-color', 'outline-style', 'outline-width'], token.isImportant); | |
| var color = result[0], style = result[1], width = result[2]; | |
| - | |
| + | |
| // Take care of inherit | |
| if (token.value === 'inherit' || token.value === 'inherit inherit inherit') { | |
| color.value = style.value = width.value = 'inherit'; | |
| return result; | |
| } | |
| - | |
| + | |
| // NOTE: usually users don't follow the required order of parts in this shorthand, | |
| // so we'll try to parse it caring as little about order as possible | |
| - | |
| + | |
| var parts = token.value.split(' '), w; | |
| - | |
| + | |
| if (parts.length === 0) { | |
| return result; | |
| } | |
| - | |
| + | |
| if (parts.length >= 1) { | |
| // Try to find outline-width, excluding inherit because that can be anything | |
| w = parts.filter(function(p) { return p !== 'inherit' && validator.isValidOutlineWidth(p); }); | |
| @@ -354,18 +354,18 @@ module.exports = (function () { | |
| // * if there was any value (including 'inherit') that could be the color, we already got it | |
| // * we already found any suitable value for outline-style and outline-width, excluding 'inherit' | |
| // Conclusion: if there are parts left, that could only mean that outline-style and possibly outline-width is 'inherit' | |
| - | |
| + | |
| style.value = 'inherit'; | |
| if (parts.length >= 2) { | |
| width.value = 'inherit'; | |
| } | |
| } | |
| - | |
| + | |
| return result; | |
| } | |
| }; | |
| breakUp = Object.freeze(breakUp); | |
| - | |
| + | |
| // Contains functions that can put together shorthands from their components | |
| var putTogether = { | |
| // Use this for properties which have four unit values (margin, padding, etc.) | |
| @@ -401,7 +401,7 @@ module.exports = (function () { | |
| value: '', | |
| isImportant: isImportant | |
| }; | |
| - | |
| + | |
| // Go through all tokens and concatenate their values as necessary | |
| for (var i = 0; i < tokens.length; i++) { | |
| var token = tokens[i]; | |
| @@ -411,24 +411,24 @@ module.exports = (function () { | |
| result.defaultsOut[token.prop] = true; | |
| continue; | |
| } | |
| - | |
| + | |
| result.value += ' ' + token.value; | |
| } | |
| - | |
| + | |
| result.value = result.value.trim(); | |
| if (!result.value) { | |
| result.defaultsOutAll = true; | |
| result.value = processable[prop].defaultValue; | |
| } | |
| - | |
| + | |
| return result; | |
| } | |
| }; | |
| putTogether = Object.freeze(putTogether); | |
| - | |
| + | |
| // Properties to process | |
| // Extend this object in order to add support for more properties in the optimizer. | |
| - // | |
| + // | |
| // Each key in this object represents a CSS property and should be an object. | |
| // Such an object contains properties that describe how the represented CSS property should be handled. | |
| // Possible options: | |
| @@ -603,36 +603,36 @@ module.exports = (function () { | |
| // TODO: add more | |
| }; | |
| processable = Object.freeze(processable); | |
| - | |
| + | |
| var isHackValue = function(t) { return t.value === '__hack'; }; | |
| var important = '!important'; | |
| - | |
| + | |
| // Breaks up the CSS properties so that they can be handled more easily | |
| var tokenize = function (input) { | |
| // Split the input by semicolons and parse the parts | |
| var tokens = input.split(';').map(function(fullProp) { | |
| - // Find first colon | |
| + // Find first colon | |
| var colonPos = fullProp.indexOf(':'); | |
| - | |
| + | |
| if (colonPos < 0) { | |
| // This property doesn't have a colon, it's invalid. Let's keep it intact anyway. | |
| return { | |
| value: fullProp | |
| }; | |
| } | |
| - | |
| + | |
| // Parse parts of the property | |
| var prop = fullProp.substr(0, colonPos).trim(); | |
| var value = fullProp.substr(colonPos + 1).trim(); | |
| var isImportant = false; | |
| var importantPos = value.indexOf(important); | |
| - | |
| + | |
| // Check if the property is important | |
| if (importantPos >= 1 && importantPos === value.length - important.length) { | |
| value = value.substr(0, importantPos).trim(); | |
| isImportant = true; | |
| } | |
| - | |
| + | |
| // Return result | |
| return { | |
| prop: prop, | |
| @@ -640,15 +640,15 @@ module.exports = (function () { | |
| isImportant: isImportant | |
| }; | |
| }); | |
| - | |
| + | |
| return tokens; | |
| }; | |
| - | |
| + | |
| // Transforms tokens back into CSS properties | |
| var detokenize = function(tokens) { | |
| var str = tokens.map(function(token) { | |
| var result = ''; | |
| - | |
| + | |
| // NOTE: malformed tokens will not have a 'prop' property | |
| if (token.prop) { | |
| result += token.prop + ':'; | |
| @@ -659,20 +659,20 @@ module.exports = (function () { | |
| if (token.isImportant) { | |
| result += important; | |
| } | |
| - | |
| + | |
| return result; | |
| }).join(';'); | |
| - | |
| + | |
| return str; | |
| }; | |
| - | |
| + | |
| // Breaks up shorthand properties into their components | |
| var breakUpShorthands = function(tokens) { | |
| var result = []; | |
| - | |
| + | |
| for (var i = 0; i < tokens.length; i++) { | |
| var token = tokens[i]; | |
| - | |
| + | |
| if (!token.prop) { | |
| // Malformed token, but keep it intact | |
| result.push(token); | |
| @@ -684,10 +684,10 @@ module.exports = (function () { | |
| result.push(token); | |
| continue; | |
| } | |
| - | |
| + | |
| // We know how to break it up, so let's do it | |
| var components = processable[token.prop].breakUp(token); | |
| - | |
| + | |
| for (var j = 0; j < components.length; j++) { | |
| result.push(components[j]); | |
| } | |
| @@ -697,21 +697,21 @@ module.exports = (function () { | |
| result.push(token); | |
| } | |
| } | |
| - | |
| + | |
| return result; | |
| }; | |
| - | |
| + | |
| // Merges same properties | |
| // https://github.com/GoalSmashers/clean-css/issues/173 | |
| // https://github.com/GoalSmashers/clean-css/issues/168 | |
| var mergeSame = function(tokens) { | |
| var result = []; | |
| - | |
| + | |
| // Variables used inside the array | |
| var can, token; | |
| // Function used for finding the alreadyThere list | |
| var alreadyThereFilter = function(t) { return t.prop === token.prop && can(t, token); }; | |
| - | |
| + | |
| for (var i = 0; i < tokens.length; i++) { | |
| token = tokens[i]; | |
| // Skip malformed tokens that have no property name, but keep them intact | |
| @@ -719,12 +719,12 @@ module.exports = (function () { | |
| result.push(token); | |
| continue; | |
| } | |
| - | |
| + | |
| // Get the function that determines if this token can be merged with others, default is same name and value | |
| can = (processable[token.prop] && processable[token.prop].canMerge) || canMerge.sameValue; | |
| // Find the definition that's mergable with token and is already there | |
| var alreadyThere = result.filter(alreadyThereFilter); | |
| - | |
| + | |
| // alreadyThere contains at most 1 item because we already merged those that came before it and might be mergeable with this one | |
| if (alreadyThere.length) { | |
| if (!alreadyThere[0].isImportant || token.isImportant) { | |
| @@ -737,10 +737,10 @@ module.exports = (function () { | |
| result.push(token); | |
| } | |
| } | |
| - | |
| + | |
| return result; | |
| }; | |
| - | |
| + | |
| // Compacts the tokens by transforming properties into their shorthand notations when possible | |
| // https://github.com/GoalSmashers/clean-css/issues/134 | |
| var compactToShorthands = function(tokens, important) { | |
| @@ -749,19 +749,19 @@ module.exports = (function () { | |
| // Filter functions used inside the loop | |
| var foundFilterFunc = function(t) { return t.isImportant === important && cc === t.prop; }; | |
| var importantTrickFunc = function(t) { return t.isImportant === true && cc === t.prop; }; | |
| - | |
| + | |
| // Go through all possible shorthand notations | |
| shorthandsLoop: | |
| for (var i in processable) { | |
| // Omit current token if it's unknown or isn't a shorthand or if it's a shorthand but we don't know how to put it together | |
| if (!processable.hasOwnProperty(i) || !processable[i].components || !processable[i].components.length || !processable[i].putTogether) | |
| continue; | |
| - | |
| + | |
| // The shorthand we currently work with | |
| var sh = processable[i]; | |
| // The last compacted shorthand | |
| var lastCompacted = null; | |
| - | |
| + | |
| // Same shorthand can occour multiple times; so we only stop this loop if no sufficient components can be found for one more | |
| while (true) { | |
| // Components found among the tokens | |
| @@ -770,7 +770,7 @@ module.exports = (function () { | |
| var trickComps = []; | |
| // Position of new shorthand | |
| var shorthandPosition = -1; | |
| - | |
| + | |
| // Find the first definition of every component | |
| for (var j = 0; j < sh.components.length; j++) { | |
| cc = sh.components[j]; | |
| @@ -804,20 +804,20 @@ module.exports = (function () { | |
| continue shorthandsLoop; | |
| } | |
| } | |
| - | |
| + | |
| if (shorthandPosition === -1 || comps.length < sh.components.length) { | |
| // There are not enough components and no amount of trickery could help it | |
| continue shorthandsLoop; | |
| } | |
| - | |
| + | |
| var compacted = processable[i].putTogether(i, comps, important); | |
| - | |
| + | |
| // If no components are tricked, the shorthand is always shorter; otherwise we should check if it's truly shorter | |
| // NOTE: this is the place where we also forcibly get rid of the hacked-in default for list-style-type | |
| if (trickComps.length === 0 || detokenize([compacted]).length <= detokenize(comps).length || comps.some(isHackValue)) { | |
| // Put the compacted token in the place of the first component | |
| tokens[shorthandPosition] = compacted; | |
| - | |
| + | |
| // Remove other tokens | |
| for (var k = 0; k < comps.length; k++) { | |
| index = tokens.indexOf(comps[k]); | |
| @@ -826,18 +826,18 @@ module.exports = (function () { | |
| } | |
| } | |
| } | |
| - | |
| + | |
| lastCompacted = compacted; | |
| } | |
| } | |
| - | |
| + | |
| return tokens; | |
| }; | |
| // Processes the input by calling the other functions | |
| // input is the content of a selector block (excluding the braces), NOT a full selector | |
| var process = function (input) { | |
| - | |
| + | |
| // The algorithm here is designed to optimize properties in a CSS selector block | |
| // and output the smallest possible equivalent code. Here are the steps: | |
| // | |
| @@ -853,9 +853,9 @@ module.exports = (function () { | |
| // * Removes default values from shorthand declarations | |
| // * Opens up opportunities for further optimalizations because granular components of shorthands are much easier to compare/process individually | |
| // | |
| - | |
| + | |
| var tokens = tokenize(input); | |
| - | |
| + | |
| //console.log('\n> initial tokenization: ----------\n', JSON.stringify(tokens, 2, 2)); | |
| //console.log('\n> initial tokenization: ----------\n', detokenize(tokens)); | |
| tokens = breakUpShorthands(tokens); | |
| @@ -870,10 +870,10 @@ module.exports = (function () { | |
| tokens = compactToShorthands(tokens, true); | |
| //console.log('\n> after compacting important shorthands ----------\n', JSON.stringify(tokens, 2, 2)); | |
| //console.log('\n> after compacting important shorthands ----------\n', detokenize(tokens)); | |
| - | |
| + | |
| return detokenize(tokens); | |
| }; | |
| - | |
| + | |
| // Return the process function as module.exports | |
| return process; | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment