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