242 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			242 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| var override = require('../utils/override');
 | |
| 
 | |
| function getSystemLineBreak() {
 | |
|   var systemLineBreak = '\n';
 | |
|   try {
 | |
|     var os = require('os');
 | |
|     systemLineBreak = os.EOL;
 | |
|   } catch (_) {
 | |
|     // no op
 | |
|   }
 | |
|   return systemLineBreak;
 | |
| }
 | |
| 
 | |
| var Breaks = {
 | |
|   AfterAtRule: 'afterAtRule',
 | |
|   AfterBlockBegins: 'afterBlockBegins',
 | |
|   AfterBlockEnds: 'afterBlockEnds',
 | |
|   AfterComment: 'afterComment',
 | |
|   AfterProperty: 'afterProperty',
 | |
|   AfterRuleBegins: 'afterRuleBegins',
 | |
|   AfterRuleEnds: 'afterRuleEnds',
 | |
|   BeforeBlockEnds: 'beforeBlockEnds',
 | |
|   BetweenSelectors: 'betweenSelectors'
 | |
| };
 | |
| 
 | |
| var BreakWith = {
 | |
|   CarriageReturnLineFeed: '\r\n',
 | |
|   LineFeed: '\n',
 | |
|   System: getSystemLineBreak()
 | |
| };
 | |
| 
 | |
| var IndentWith = {
 | |
|   Space: ' ',
 | |
|   Tab: '\t'
 | |
| };
 | |
| 
 | |
| var Spaces = {
 | |
|   AroundSelectorRelation: 'aroundSelectorRelation',
 | |
|   BeforeBlockBegins: 'beforeBlockBegins',
 | |
|   BeforeValue: 'beforeValue'
 | |
| };
 | |
| 
 | |
| var DEFAULTS = {
 | |
|   breaks: breaks(false),
 | |
|   breakWith: BreakWith.System,
 | |
|   indentBy: 0,
 | |
|   indentWith: IndentWith.Space,
 | |
|   spaces: spaces(false),
 | |
|   wrapAt: false,
 | |
|   semicolonAfterLastProperty: false
 | |
| };
 | |
| 
 | |
| var BEAUTIFY_ALIAS = 'beautify';
 | |
| var KEEP_BREAKS_ALIAS = 'keep-breaks';
 | |
| 
 | |
| var OPTION_SEPARATOR = ';';
 | |
| var OPTION_NAME_VALUE_SEPARATOR = ':';
 | |
| var HASH_VALUES_OPTION_SEPARATOR = ',';
 | |
| var HASH_VALUES_NAME_VALUE_SEPARATOR = '=';
 | |
| 
 | |
| var FALSE_KEYWORD_1 = 'false';
 | |
| var FALSE_KEYWORD_2 = 'off';
 | |
| var TRUE_KEYWORD_1 = 'true';
 | |
| var TRUE_KEYWORD_2 = 'on';
 | |
| 
 | |
| function breaks(value) {
 | |
|   var breakOptions = {};
 | |
| 
 | |
|   breakOptions[Breaks.AfterAtRule] = value;
 | |
|   breakOptions[Breaks.AfterBlockBegins] = value;
 | |
|   breakOptions[Breaks.AfterBlockEnds] = value;
 | |
|   breakOptions[Breaks.AfterComment] = value;
 | |
|   breakOptions[Breaks.AfterProperty] = value;
 | |
|   breakOptions[Breaks.AfterRuleBegins] = value;
 | |
|   breakOptions[Breaks.AfterRuleEnds] = value;
 | |
|   breakOptions[Breaks.BeforeBlockEnds] = value;
 | |
|   breakOptions[Breaks.BetweenSelectors] = value;
 | |
| 
 | |
|   return breakOptions;
 | |
| }
 | |
| 
 | |
| function spaces(value) {
 | |
|   var spaceOptions = {};
 | |
| 
 | |
|   spaceOptions[Spaces.AroundSelectorRelation] = value;
 | |
|   spaceOptions[Spaces.BeforeBlockBegins] = value;
 | |
|   spaceOptions[Spaces.BeforeValue] = value;
 | |
| 
 | |
|   return spaceOptions;
 | |
| }
 | |
| 
 | |
| function formatFrom(source) {
 | |
|   if (source === undefined || source === false) {
 | |
|     return false;
 | |
|   }
 | |
| 
 | |
|   if (typeof source == 'object' && 'breakWith' in source) {
 | |
|     source = override(source, { breakWith: mapBreakWith(source.breakWith) });
 | |
|   }
 | |
| 
 | |
|   if (typeof source == 'object' && 'indentBy' in source) {
 | |
|     source = override(source, { indentBy: parseInt(source.indentBy) });
 | |
|   }
 | |
| 
 | |
|   if (typeof source == 'object' && 'indentWith' in source) {
 | |
|     source = override(source, { indentWith: mapIndentWith(source.indentWith) });
 | |
|   }
 | |
| 
 | |
|   if (typeof source == 'object') {
 | |
|     return remapBreaks(override(DEFAULTS, source));
 | |
|   }
 | |
| 
 | |
|   if (typeof source == 'string' && source == BEAUTIFY_ALIAS) {
 | |
|     return remapBreaks(
 | |
|       override(DEFAULTS, {
 | |
|         breaks: breaks(true),
 | |
|         indentBy: 2,
 | |
|         spaces: spaces(true)
 | |
|       })
 | |
|     );
 | |
|   }
 | |
| 
 | |
|   if (typeof source == 'string' && source == KEEP_BREAKS_ALIAS) {
 | |
|     return remapBreaks(
 | |
|       override(DEFAULTS, {
 | |
|         breaks: {
 | |
|           afterAtRule: true,
 | |
|           afterBlockBegins: true,
 | |
|           afterBlockEnds: true,
 | |
|           afterComment: true,
 | |
|           afterRuleEnds: true,
 | |
|           beforeBlockEnds: true
 | |
|         }
 | |
|       })
 | |
|     );
 | |
|   }
 | |
| 
 | |
|   if (typeof source == 'string') {
 | |
|     return remapBreaks(override(DEFAULTS, toHash(source)));
 | |
|   }
 | |
| 
 | |
|   return DEFAULTS;
 | |
| }
 | |
| 
 | |
| function toHash(string) {
 | |
|   return string
 | |
|     .split(OPTION_SEPARATOR)
 | |
|     .reduce(function(accumulator, directive) {
 | |
|       var parts = directive.split(OPTION_NAME_VALUE_SEPARATOR);
 | |
|       var name = parts[0];
 | |
|       var value = parts[1];
 | |
| 
 | |
|       if (name == 'breaks' || name == 'spaces') {
 | |
|         accumulator[name] = hashValuesToHash(value);
 | |
|       } else if (name == 'indentBy' || name == 'wrapAt') {
 | |
|         accumulator[name] = parseInt(value);
 | |
|       } else if (name == 'indentWith') {
 | |
|         accumulator[name] = mapIndentWith(value);
 | |
|       } else if (name == 'breakWith') {
 | |
|         accumulator[name] = mapBreakWith(value);
 | |
|       }
 | |
| 
 | |
|       return accumulator;
 | |
|     }, {});
 | |
| }
 | |
| 
 | |
| function hashValuesToHash(string) {
 | |
|   return string
 | |
|     .split(HASH_VALUES_OPTION_SEPARATOR)
 | |
|     .reduce(function(accumulator, directive) {
 | |
|       var parts = directive.split(HASH_VALUES_NAME_VALUE_SEPARATOR);
 | |
|       var name = parts[0];
 | |
|       var value = parts[1];
 | |
| 
 | |
|       accumulator[name] = normalizeValue(value);
 | |
| 
 | |
|       return accumulator;
 | |
|     }, {});
 | |
| }
 | |
| 
 | |
| function normalizeValue(value) {
 | |
|   switch (value) {
 | |
|   case FALSE_KEYWORD_1:
 | |
|   case FALSE_KEYWORD_2:
 | |
|     return false;
 | |
|   case TRUE_KEYWORD_1:
 | |
|   case TRUE_KEYWORD_2:
 | |
|     return true;
 | |
|   default:
 | |
|     return value;
 | |
|   }
 | |
| }
 | |
| 
 | |
| function mapBreakWith(value) {
 | |
|   switch (value) {
 | |
|   case 'windows':
 | |
|   case 'crlf':
 | |
|   case BreakWith.CarriageReturnLineFeed:
 | |
|     return BreakWith.CarriageReturnLineFeed;
 | |
|   case 'unix':
 | |
|   case 'lf':
 | |
|   case BreakWith.LineFeed:
 | |
|     return BreakWith.LineFeed;
 | |
|   default:
 | |
|     return BreakWith.System;
 | |
|   }
 | |
| }
 | |
| 
 | |
| function mapIndentWith(value) {
 | |
|   switch (value) {
 | |
|   case 'space':
 | |
|     return IndentWith.Space;
 | |
|   case 'tab':
 | |
|     return IndentWith.Tab;
 | |
|   default:
 | |
|     return value;
 | |
|   }
 | |
| }
 | |
| 
 | |
| function remapBreaks(source) {
 | |
|   for (var key in Breaks) {
 | |
|     var breakName = Breaks[key];
 | |
|     var breakValue = source.breaks[breakName];
 | |
| 
 | |
|     if (breakValue === true) {
 | |
|       source.breaks[breakName] = source.breakWith;
 | |
|     } else if (breakValue === false) {
 | |
|       source.breaks[breakName] = '';
 | |
|     } else {
 | |
|       source.breaks[breakName] = source.breakWith.repeat(parseInt(breakValue));
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return source;
 | |
| }
 | |
| 
 | |
| module.exports = {
 | |
|   Breaks: Breaks,
 | |
|   Spaces: Spaces,
 | |
|   formatFrom: formatFrom
 | |
| };
 |