format.js 5.0 KB

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