1var systemLineBreak = require('os').EOL; 2 3var override = require('../utils/override'); 4 5var Breaks = { 6 AfterAtRule: 'afterAtRule', 7 AfterBlockBegins: 'afterBlockBegins', 8 AfterBlockEnds: 'afterBlockEnds', 9 AfterComment: 'afterComment', 10 AfterProperty: 'afterProperty', 11 AfterRuleBegins: 'afterRuleBegins', 12 AfterRuleEnds: 'afterRuleEnds', 13 BeforeBlockEnds: 'beforeBlockEnds', 14 BetweenSelectors: 'betweenSelectors' 15}; 16 17var BreakWith = { 18 CarriageReturnLineFeed: '\r\n', 19 LineFeed: '\n', 20 System: systemLineBreak 21}; 22 23var IndentWith = { 24 Space: ' ', 25 Tab: '\t' 26}; 27 28var Spaces = { 29 AroundSelectorRelation: 'aroundSelectorRelation', 30 BeforeBlockBegins: 'beforeBlockBegins', 31 BeforeValue: 'beforeValue' 32}; 33 34var DEFAULTS = { 35 breaks: breaks(false), 36 breakWith: BreakWith.System, 37 indentBy: 0, 38 indentWith: IndentWith.Space, 39 spaces: spaces(false), 40 wrapAt: false, 41 semicolonAfterLastProperty: false 42}; 43 44var BEAUTIFY_ALIAS = 'beautify'; 45var KEEP_BREAKS_ALIAS = 'keep-breaks'; 46 47var OPTION_SEPARATOR = ';'; 48var OPTION_NAME_VALUE_SEPARATOR = ':'; 49var HASH_VALUES_OPTION_SEPARATOR = ','; 50var HASH_VALUES_NAME_VALUE_SEPARATOR = '='; 51 52var FALSE_KEYWORD_1 = 'false'; 53var FALSE_KEYWORD_2 = 'off'; 54var TRUE_KEYWORD_1 = 'true'; 55var TRUE_KEYWORD_2 = 'on'; 56 57function breaks(value) { 58 var breakOptions = {}; 59 60 breakOptions[Breaks.AfterAtRule] = value; 61 breakOptions[Breaks.AfterBlockBegins] = value; 62 breakOptions[Breaks.AfterBlockEnds] = value; 63 breakOptions[Breaks.AfterComment] = value; 64 breakOptions[Breaks.AfterProperty] = value; 65 breakOptions[Breaks.AfterRuleBegins] = value; 66 breakOptions[Breaks.AfterRuleEnds] = value; 67 breakOptions[Breaks.BeforeBlockEnds] = value; 68 breakOptions[Breaks.BetweenSelectors] = value; 69 70 return breakOptions; 71} 72 73function spaces(value) { 74 var spaceOptions = {}; 75 76 spaceOptions[Spaces.AroundSelectorRelation] = value; 77 spaceOptions[Spaces.BeforeBlockBegins] = value; 78 spaceOptions[Spaces.BeforeValue] = value; 79 80 return spaceOptions; 81} 82 83function formatFrom(source) { 84 if (source === undefined || source === false) { 85 return false; 86 } 87 88 if (typeof source == 'object' && 'breakWith' in source) { 89 source = override(source, { breakWith: mapBreakWith(source.breakWith) }); 90 } 91 92 if (typeof source == 'object' && 'indentBy' in source) { 93 source = override(source, { indentBy: parseInt(source.indentBy) }); 94 } 95 96 if (typeof source == 'object' && 'indentWith' in source) { 97 source = override(source, { indentWith: mapIndentWith(source.indentWith) }); 98 } 99 100 if (typeof source == 'object') { 101 return override(DEFAULTS, source); 102 } 103 104 if (typeof source == 'object') { 105 return override(DEFAULTS, source); 106 } 107 108 if (typeof source == 'string' && source == BEAUTIFY_ALIAS) { 109 return override(DEFAULTS, { 110 breaks: breaks(true), 111 indentBy: 2, 112 spaces: spaces(true) 113 }); 114 } 115 116 if (typeof source == 'string' && source == KEEP_BREAKS_ALIAS) { 117 return override(DEFAULTS, { 118 breaks: { 119 afterAtRule: true, 120 afterBlockBegins: true, 121 afterBlockEnds: true, 122 afterComment: true, 123 afterRuleEnds: true, 124 beforeBlockEnds: true 125 } 126 }); 127 } 128 129 if (typeof source == 'string') { 130 return override(DEFAULTS, toHash(source)); 131 } 132 133 return DEFAULTS; 134} 135 136function toHash(string) { 137 return string 138 .split(OPTION_SEPARATOR) 139 .reduce(function (accumulator, directive) { 140 var parts = directive.split(OPTION_NAME_VALUE_SEPARATOR); 141 var name = parts[0]; 142 var value = parts[1]; 143 144 if (name == 'breaks' || name == 'spaces') { 145 accumulator[name] = hashValuesToHash(value); 146 } else if (name == 'indentBy' || name == 'wrapAt') { 147 accumulator[name] = parseInt(value); 148 } else if (name == 'indentWith') { 149 accumulator[name] = mapIndentWith(value); 150 } else if (name == 'breakWith') { 151 accumulator[name] = mapBreakWith(value); 152 } 153 154 return accumulator; 155 }, {}); 156} 157 158function hashValuesToHash(string) { 159 return string 160 .split(HASH_VALUES_OPTION_SEPARATOR) 161 .reduce(function (accumulator, directive) { 162 var parts = directive.split(HASH_VALUES_NAME_VALUE_SEPARATOR); 163 var name = parts[0]; 164 var value = parts[1]; 165 166 accumulator[name] = normalizeValue(value); 167 168 return accumulator; 169 }, {}); 170} 171 172 173function normalizeValue(value) { 174 switch (value) { 175 case FALSE_KEYWORD_1: 176 case FALSE_KEYWORD_2: 177 return false; 178 case TRUE_KEYWORD_1: 179 case TRUE_KEYWORD_2: 180 return true; 181 default: 182 return value; 183 } 184} 185 186function mapBreakWith(value) { 187 switch (value) { 188 case 'windows': 189 case 'crlf': 190 case BreakWith.CarriageReturnLineFeed: 191 return BreakWith.CarriageReturnLineFeed; 192 case 'unix': 193 case 'lf': 194 case BreakWith.LineFeed: 195 return BreakWith.LineFeed; 196 default: 197 return systemLineBreak; 198 } 199} 200 201function mapIndentWith(value) { 202 switch (value) { 203 case 'space': 204 return IndentWith.Space; 205 case 'tab': 206 return IndentWith.Tab; 207 default: 208 return value; 209 } 210} 211 212module.exports = { 213 Breaks: Breaks, 214 Spaces: Spaces, 215 formatFrom: formatFrom 216}; 217