coffeehaml 0.7.3 → 0.7.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,309 @@
1
+ // Generated by CoffeeScript 2.7.0
2
+ // coffeescript-formatter.coffee — CoffeeScript token-based expression formatter
3
+ var DEFAULT_OPTS, EXPR_STARTERS, FOR_KEYWORDS, KEYWORD_SPACE_AFTER, NO_SPACE_AFTER, NO_SPACE_BEFORE, SPACE_AFTER, SPACE_BOTH, _require, getTokenText, hasImplicitTokens, hasMethodChain, isUnaryOp, lineWrap, loadCoffeeScript, needsSpaceBetween, normalizeSpacing, wrapMethodChain;
4
+
5
+ import {
6
+ createRequire
7
+ } from 'module';
8
+
9
+ _require = createRequire(import.meta.url);
10
+
11
+ loadCoffeeScript = function() {
12
+ try {
13
+ return _require('coffeescript');
14
+ } catch (error) {
15
+ return null;
16
+ }
17
+ };
18
+
19
+ // ─── Token types ──────────────────────────────────────────
20
+ // CSToken: { type, value, range, generated?, originalText? }
21
+
22
+ // ─── Spacing categories ───────────────────────────────────
23
+ NO_SPACE_BEFORE = new Set([',', ':', ';', '.', '?.', '::', ')', ']', '}', 'CALL_END', 'PARAM_END', 'INDEX_END', 'POST_IF', 'POST_FOR', 'POST_WHILE', 'TERMINATOR']);
24
+
25
+ NO_SPACE_AFTER = new Set(['.', '?.', '::', '...', '..', '(', '[', '{', 'CALL_START', 'PARAM_START', 'INDEX_START', 'STRING_START', 'INTERPOLATION_START', 'INDENT', '@']);
26
+
27
+ SPACE_AFTER = new Set([',', ':']);
28
+
29
+ SPACE_BOTH = new Set(['=', '?=', '+', '-', 'MATH', '**', 'SHIFT', '&', '|', '^', '&&', '||', '?', '=>', '->', 'COMPARE', 'COMPOUND_ASSIGN', 'RELATION', 'FOR', 'ELSE', 'IF', 'WHILE']);
30
+
31
+ KEYWORD_SPACE_AFTER = new Set(['RETURN', 'THROW', 'NEW', 'TYPEOF', 'INSTANCEOF', 'DELETE', 'CLASS', 'EXTENDS', 'DEFAULT', 'IMPORT', 'EXPORT', 'AWAIT', 'YIELD', 'BREAK', 'CONTINUE', 'SWITCH']);
32
+
33
+ FOR_KEYWORDS = new Set(['FORIN', 'FOROF', 'WHEN', 'BY']);
34
+
35
+ EXPR_STARTERS = new Set(['(', '[', '{', ',', ':', '=', '?=', '+', '-', 'MATH', '**', 'SHIFT', '&', '|', '^', '&&', '||', '?', '=>', '->', 'COMPARE', 'COMPOUND_ASSIGN', 'RETURN', 'INDENT', 'OUTDENT', 'TERMINATOR', 'FOR', 'FORIN', 'FOROF', 'WHILE', 'IF', 'ELSE', 'THROW', 'NEW', 'TYPEOF', 'INSTANCEOF', 'DELETE', 'EXTENDS', 'DEFAULT', 'CALL_START', 'PARAM_START', 'INDEX_START', 'UNARY']);
36
+
37
+ DEFAULT_OPTS = {
38
+ printWidth: 80,
39
+ methodChainAlign: true,
40
+ enabled: true
41
+ };
42
+
43
+ // ─── Public API ───────────────────────────────────────────
44
+ export var formatCoffeeScript = function(source, options = {}) {
45
+ var cs, normalized, opts, rawTokens, tokens;
46
+ opts = {...DEFAULT_OPTS, ...options};
47
+ if (!opts.enabled) {
48
+ return source;
49
+ }
50
+ if (!(source && source.trim() !== '')) {
51
+ return source;
52
+ }
53
+ try {
54
+ cs = loadCoffeeScript();
55
+ if (!(cs && typeof cs.tokens === 'function')) {
56
+ return source;
57
+ }
58
+ rawTokens = cs.tokens(source);
59
+ if (!(rawTokens && rawTokens.length > 0)) {
60
+ return source;
61
+ }
62
+ tokens = rawTokens.map(function(t) {
63
+ var ref, ref1, ref2, ref3;
64
+ return {
65
+ type: t[0],
66
+ value: t[1],
67
+ range: (ref = (ref1 = t[2]) != null ? ref1.range : void 0) != null ? ref : [0, 0],
68
+ generated: !!((ref2 = t[2]) != null ? ref2.generated : void 0),
69
+ originalText: ((ref3 = t[2]) != null ? ref3.range : void 0) && t[2].range[0] < t[2].range[1] ? source.slice(t[2].range[0], t[2].range[1]) : t[1]
70
+ };
71
+ });
72
+ if (hasImplicitTokens(tokens)) {
73
+ return source;
74
+ }
75
+ normalized = normalizeSpacing(tokens, source);
76
+ if (normalized.length > opts.printWidth) {
77
+ return lineWrap(normalized, opts, source);
78
+ }
79
+ return normalized;
80
+ } catch (error) {
81
+ return source;
82
+ }
83
+ };
84
+
85
+ // ─── Block formatting ─────────────────────────────────────
86
+ export var formatCoffeeScriptBlock = function(source, options = {}) {
87
+ var formatted, lines, opts;
88
+ opts = {...DEFAULT_OPTS, ...options};
89
+ if (!opts.enabled) {
90
+ return source;
91
+ }
92
+ if (!(source && source.trim() !== '')) {
93
+ return source;
94
+ }
95
+ lines = source.split('\n');
96
+ formatted = lines.map(function(line) {
97
+ var formattedExpr, leading, ref, ref1, trimmed;
98
+ trimmed = line.trim();
99
+ if (!trimmed) {
100
+ return '';
101
+ }
102
+ leading = (ref = (ref1 = line.match(/^(\s*)/)) != null ? ref1[1] : void 0) != null ? ref : '';
103
+ try {
104
+ formattedExpr = formatCoffeeScript(trimmed, options);
105
+ return leading + formattedExpr;
106
+ } catch (error) {
107
+ return line;
108
+ }
109
+ });
110
+ return formatted.join('\n');
111
+ };
112
+
113
+ // ─── Implicit token detection ─────────────────────────────
114
+ hasImplicitTokens = function(tokens) {
115
+ var j, len, ref, t;
116
+ for (j = 0, len = tokens.length; j < len; j++) {
117
+ t = tokens[j];
118
+ if ((ref = t.type) === 'INDENT' || ref === 'OUTDENT' || ref === 'TERMINATOR') {
119
+ continue;
120
+ }
121
+ if (t.generated) {
122
+ return true;
123
+ }
124
+ if (t.range && t.range[0] >= t.range[1]) {
125
+ return true;
126
+ }
127
+ }
128
+ return false;
129
+ };
130
+
131
+ // ─── Spacing normalization ────────────────────────────────
132
+ normalizeSpacing = function(tokens, originalSource = null) {
133
+ var afterPrevIsExprStart, cur, j, len, parts, prevVisible, prevWasAtExprStart, ref, ref1, ref2, text, trimmed;
134
+ parts = [];
135
+ prevVisible = null;
136
+ prevWasAtExprStart = true;
137
+ afterPrevIsExprStart = true;
138
+ for (j = 0, len = tokens.length; j < len; j++) {
139
+ cur = tokens[j];
140
+ // Skip implicit CALL/PARAM tokens
141
+ if ((ref = cur.type) === 'CALL_START' || ref === 'CALL_END') {
142
+ if (cur.generated) {
143
+ continue;
144
+ }
145
+ if (cur.range && cur.range[0] >= cur.range[1]) {
146
+ continue;
147
+ }
148
+ }
149
+ if ((ref1 = cur.type) === 'PARAM_START' || ref1 === 'PARAM_END') {
150
+ if (cur.generated) {
151
+ continue;
152
+ }
153
+ if (cur.range && cur.range[0] >= cur.range[1]) {
154
+ continue;
155
+ }
156
+ }
157
+ // Handle INDENT — represents inline then/when/else/etc from CoffeeScript
158
+ if (cur.type === 'INDENT') {
159
+ text = getTokenText(cur, originalSource);
160
+ trimmed = text != null ? text.trim() : void 0;
161
+ if (trimmed && trimmed !== '') {
162
+ parts.push(' ' + trimmed + ' ');
163
+ prevWasAtExprStart = false;
164
+ afterPrevIsExprStart = true;
165
+ prevVisible = cur;
166
+ }
167
+ continue;
168
+ }
169
+ if (cur.type === 'OUTDENT') {
170
+ continue;
171
+ }
172
+ // Skip TERMINATOR
173
+ if (cur.type === 'TERMINATOR') {
174
+ continue;
175
+ }
176
+ // Space before this token
177
+ if (prevVisible && ((ref2 = prevVisible.type) !== 'INDENT' && ref2 !== 'OUTDENT')) {
178
+ if (needsSpaceBetween(prevVisible, cur, prevWasAtExprStart)) {
179
+ parts.push(' ');
180
+ }
181
+ }
182
+ parts.push(getTokenText(cur, originalSource));
183
+ prevWasAtExprStart = afterPrevIsExprStart;
184
+ afterPrevIsExprStart = EXPR_STARTERS.has(cur.type);
185
+ prevVisible = cur;
186
+ }
187
+ return parts.join('');
188
+ };
189
+
190
+ getTokenText = function(token, originalSource = null) {
191
+ if (token.generated) {
192
+ return token.value;
193
+ }
194
+ if (!(token.range && token.range[0] < token.range[1])) {
195
+ return token.value;
196
+ }
197
+ if (originalSource) {
198
+ return originalSource.slice(token.range[0], token.range[1]);
199
+ }
200
+ return token.value;
201
+ };
202
+
203
+ needsSpaceBetween = function(prev, cur, prevAtExprStart) {
204
+ var text;
205
+ if (NO_SPACE_AFTER.has(prev.type)) {
206
+ return false;
207
+ }
208
+ if (NO_SPACE_BEFORE.has(cur.type)) {
209
+ return false;
210
+ }
211
+ if (prev.type === '@') {
212
+ return false;
213
+ }
214
+ if (SPACE_AFTER.has(prev.type)) {
215
+ return true;
216
+ }
217
+ if (FOR_KEYWORDS.has(prev.type) || FOR_KEYWORDS.has(cur.type)) {
218
+ return true;
219
+ }
220
+ if (KEYWORD_SPACE_AFTER.has(prev.type)) {
221
+ return true;
222
+ }
223
+ if (prev.type === 'UNARY') {
224
+ text = prev.originalText || prev.value;
225
+ if (text === '!' || text === '!!') {
226
+ return false;
227
+ }
228
+ return true;
229
+ }
230
+ if (SPACE_BOTH.has(prev.type) || SPACE_BOTH.has(cur.type)) {
231
+ if (isUnaryOp(prev, prevAtExprStart)) {
232
+ return false;
233
+ }
234
+ return true;
235
+ }
236
+ if (prev.type === 'IDENTIFIER' && cur.type === 'IDENTIFIER') {
237
+ return true;
238
+ }
239
+ return false;
240
+ };
241
+
242
+ isUnaryOp = function(prev, prevAtExprStart) {
243
+ var ref;
244
+ if ((ref = prev.type) !== '+' && ref !== '-') {
245
+ return false;
246
+ }
247
+ if (prevAtExprStart) {
248
+ return true;
249
+ }
250
+ if (prev.range && prev.range[0] === 0) {
251
+ return true;
252
+ }
253
+ return false;
254
+ };
255
+
256
+ // ─── Line wrapping ────────────────────────────────────────
257
+ lineWrap = function(source, opts, fallback) {
258
+ if (opts.methodChainAlign && hasMethodChain(source)) {
259
+ return wrapMethodChain(source, opts);
260
+ }
261
+ return fallback;
262
+ };
263
+
264
+ hasMethodChain = function(source) {
265
+ return (source.match(/\.[a-zA-Z_$]/g) || []).length >= 2;
266
+ };
267
+
268
+ wrapMethodChain = function(source, _opts) {
269
+ var ch, chars, current, depth, i, indent, result;
270
+ indent = ' ';
271
+ result = [];
272
+ chars = [...source];
273
+ depth = 0;
274
+ current = '';
275
+ i = 0;
276
+ while (i < chars.length) {
277
+ ch = chars[i];
278
+ if (ch === '(' || ch === '[' || ch === '{') {
279
+ depth++;
280
+ }
281
+ if (ch === ')' || ch === ']' || ch === '}') {
282
+ depth--;
283
+ }
284
+ if (ch === '.' && depth === 0 && i > 0 && chars[i - 1] !== '?' && current.trim().length > 0) {
285
+ if (result.length === 0) {
286
+ result.push(current.trimEnd());
287
+ } else {
288
+ result.push(indent + current.trimEnd());
289
+ }
290
+ current = ch;
291
+ i++;
292
+ continue;
293
+ }
294
+ current += ch;
295
+ i++;
296
+ }
297
+ if (current.trim().length > 0) {
298
+ if (result.length === 0) {
299
+ result.push(current.trim());
300
+ } else {
301
+ result.push(indent + current.trim());
302
+ }
303
+ }
304
+ if (result.length > 1) {
305
+ return result.join('\n');
306
+ } else {
307
+ return source;
308
+ }
309
+ };
package/dist/lexer.js CHANGED
@@ -1,7 +1,7 @@
1
1
  // Generated by CoffeeScript 2.7.0
2
2
  // lexer.coffee — CoffeeHaml tokenizer
3
3
  // Converts raw .chaml source into a token stream with INDENT/DEDENT
4
- var countIndent, dedentToken, extractBracketed, indentToken, isHamlConstruct, parseModifiersAndAttrs, preMergeBracketLines, tokenizeLine;
4
+ var countIndent, dedentToken, extractBracketed, indentToken, isHamlConstruct, looksLikeBareAttributes, parseModifiersAndAttrs, preMergeBracketLines, tokenizeLine;
5
5
 
6
6
  import {
7
7
  SourceLocation
@@ -14,6 +14,7 @@ export var TokenType = {
14
14
  ID: 'ID',
15
15
  ATTRS_PAREN: 'ATTRS_PAREN',
16
16
  ATTRS_BRACE: 'ATTRS_BRACE',
17
+ ATTRS_BARE: 'ATTRS_BARE',
17
18
  OUTPUT: 'OUTPUT',
18
19
  OUTPUT_UNESC: 'OUTPUT_UNESC',
19
20
  CONTROL: 'CONTROL',
@@ -222,6 +223,12 @@ tokenizeLine = function(content, lineStartOffset, _lineLength, filename = null,
222
223
  value: remaining.slice(2).trimStart(),
223
224
  location: loc(trimmedOffset + 2, content.length)
224
225
  });
226
+ } else if (looksLikeBareAttributes(remaining)) {
227
+ tokens.push({
228
+ type: TokenType.ATTRS_BARE,
229
+ value: remaining,
230
+ location: loc(trimmedOffset, content.length)
231
+ });
225
232
  } else if (!(remaining.startsWith('{') || remaining.startsWith('('))) {
226
233
  tokens.push({
227
234
  type: TokenType.TEXT,
@@ -261,6 +268,12 @@ tokenizeLine = function(content, lineStartOffset, _lineLength, filename = null,
261
268
  value: remaining.slice(2).trimStart(),
262
269
  location: loc(trimmedOffset + 2, content.length)
263
270
  });
271
+ } else if (looksLikeBareAttributes(remaining)) {
272
+ tokens.push({
273
+ type: TokenType.ATTRS_BARE,
274
+ value: remaining,
275
+ location: loc(trimmedOffset, content.length)
276
+ });
264
277
  } else if (!(remaining.startsWith('{') || remaining.startsWith('('))) {
265
278
  tokens.push({
266
279
  type: TokenType.TEXT,
@@ -468,6 +481,38 @@ parseModifiersAndAttrs = function(content, startPos, lineStartOffset, filename =
468
481
  };
469
482
 
470
483
  // ─── Helpers ───────────────────────────────────────────────
484
+
485
+ // Detects bare HTML-style attributes: key="val", key='val', key={expr}
486
+ looksLikeBareAttributes = function(text) {
487
+ var j, len, part, parts, ref;
488
+ if (!(text && text.length > 0)) {
489
+ return false;
490
+ }
491
+ if (!text.includes('=')) {
492
+ // Must contain at least one = sign
493
+ return false;
494
+ }
495
+ // Split on whitespace, skip empty
496
+ parts = (ref = text.match(/\S+/g)) != null ? ref : [];
497
+ if (parts.length === 0) {
498
+ return false;
499
+ }
500
+ // At least one part must look like key=value or be {expr}
501
+ for (j = 0, len = parts.length; j < len; j++) {
502
+ part = parts[j];
503
+ if (/^[\w-]+=/.test(part)) { // key="val" or key='val' or key={expr}
504
+ return true;
505
+ }
506
+ if (/^[\w-]+\{/.test(part)) { // key{...} alternative
507
+ return true;
508
+ }
509
+ if (/^=\{/.test(part)) { // ={expr}
510
+ return true;
511
+ }
512
+ }
513
+ return false;
514
+ };
515
+
471
516
  isHamlConstruct = function(content) {
472
517
  var fc;
473
518
  fc = content[0];
@@ -0,0 +1,232 @@
1
+ // Generated by CoffeeScript 2.7.0
2
+ // options.coffee — CoffeeHaml Prettier formatting options
3
+ export var CAT = {
4
+ STRUCTURE: 'CoffeeHaml: Structure',
5
+ ATTRIBUTES: 'CoffeeHaml: Attributes',
6
+ COFFEESCRIPT: 'CoffeeHaml: CoffeeScript',
7
+ WHITESPACE: 'CoffeeHaml: Whitespace',
8
+ CONTROL_FLOW: 'CoffeeHaml: Control Flow',
9
+ COMMENTS: 'CoffeeHaml: Comments'
10
+ };
11
+
12
+ export var options = {
13
+ tagCase: {
14
+ category: CAT.STRUCTURE,
15
+ type: 'choice',
16
+ description: 'Normalize HTML tag casing. Component tags (%MyComponent) never affected.',
17
+ choices: [
18
+ {
19
+ value: 'preserve',
20
+ description: 'Leave tag case as written'
21
+ },
22
+ {
23
+ value: 'lowercase',
24
+ description: '%DIV to %div (HTML tags only)'
25
+ }
26
+ ]
27
+ },
28
+ implicitDivExpansion: {
29
+ category: CAT.STRUCTURE,
30
+ type: 'boolean',
31
+ description: 'Expand .class to %div.class (anti-idiomatic in HAML).'
32
+ },
33
+ maxChainLength: {
34
+ category: CAT.STRUCTURE,
35
+ type: 'int',
36
+ description: 'Max .class chain length before breaking into indented hierarchy. 0 = always break.'
37
+ },
38
+ inlineThreshold: {
39
+ category: CAT.STRUCTURE,
40
+ type: 'int',
41
+ description: 'Try single-line if estimated width <= this. -1 = never inline children.'
42
+ },
43
+ voidElementStyle: {
44
+ category: CAT.STRUCTURE,
45
+ type: 'choice',
46
+ description: 'How void elements (%br, %img, etc.) are formatted.',
47
+ choices: [
48
+ {
49
+ value: 'self-closing',
50
+ description: 'Self-closing (no children)'
51
+ },
52
+ {
53
+ value: 'explicit',
54
+ description: 'Preserve %br/ syntax, otherwise self-close'
55
+ }
56
+ ]
57
+ },
58
+ attributeStyle: {
59
+ category: CAT.ATTRIBUTES,
60
+ type: 'choice',
61
+ description: 'Enforce attribute syntax: {braces}, (parens), bare, or preserve.',
62
+ choices: [
63
+ {
64
+ value: 'preserve',
65
+ description: 'Keep as written'
66
+ },
67
+ {
68
+ value: 'braces',
69
+ description: 'Convert to {CoffeeScript} style'
70
+ },
71
+ {
72
+ value: 'parens',
73
+ description: 'Convert to HTML (parens) style'
74
+ },
75
+ {
76
+ value: 'bare',
77
+ description: 'Convert to bare HAML style'
78
+ }
79
+ ]
80
+ },
81
+ attributeMultilineThreshold: {
82
+ category: CAT.ATTRIBUTES,
83
+ type: 'int',
84
+ description: 'Break attributes across lines when count >= this. 0 = always multiline.'
85
+ },
86
+ attributeSort: {
87
+ category: CAT.ATTRIBUTES,
88
+ type: 'choice',
89
+ description: 'Sort attribute keys (spread attributes always last).',
90
+ choices: [
91
+ {
92
+ value: 'none',
93
+ description: 'Preserve author order'
94
+ },
95
+ {
96
+ value: 'alphabetical',
97
+ description: 'Sort A to Z'
98
+ },
99
+ {
100
+ value: 'idiomatic',
101
+ description: 'id first, class second, rest A to Z'
102
+ }
103
+ ]
104
+ },
105
+ quoteStyle: {
106
+ category: CAT.ATTRIBUTES,
107
+ type: 'choice',
108
+ description: 'Quote style for bare/HAML attributes.',
109
+ choices: [
110
+ {
111
+ value: 'preserve',
112
+ description: 'Keep as written'
113
+ },
114
+ {
115
+ value: 'double',
116
+ description: 'Force double quotes'
117
+ },
118
+ {
119
+ value: 'single',
120
+ description: 'Force single quotes'
121
+ }
122
+ ]
123
+ },
124
+ coffeeScriptFormat: {
125
+ category: CAT.COFFEESCRIPT,
126
+ type: 'boolean',
127
+ description: 'Format CoffeeScript expressions using prettier/plugins/coffeescript.'
128
+ },
129
+ methodChainAlign: {
130
+ category: CAT.COFFEESCRIPT,
131
+ type: 'boolean',
132
+ description: 'Align .method chains on newlines for = expressions.'
133
+ },
134
+ blankLineHandling: {
135
+ category: CAT.WHITESPACE,
136
+ type: 'choice',
137
+ description: 'How blank lines between sibling elements are treated.',
138
+ choices: [
139
+ {
140
+ value: 'preserve',
141
+ description: 'Keep single; collapse multiples'
142
+ },
143
+ {
144
+ value: 'collapse',
145
+ description: 'Remove all blank lines between siblings'
146
+ },
147
+ {
148
+ value: 'respect',
149
+ description: 'Keep exactly as written'
150
+ }
151
+ ]
152
+ },
153
+ trailingWhitespace: {
154
+ category: CAT.WHITESPACE,
155
+ type: 'choice',
156
+ description: 'Handle trailing whitespace.',
157
+ choices: [
158
+ {
159
+ value: 'remove',
160
+ description: 'Strip trailing whitespace'
161
+ },
162
+ {
163
+ value: 'preserve',
164
+ description: 'Leave as written'
165
+ }
166
+ ]
167
+ },
168
+ continuationStyle: {
169
+ category: CAT.CONTROL_FLOW,
170
+ type: 'choice',
171
+ description: 'How \\ continuations are formatted.',
172
+ choices: [
173
+ {
174
+ value: 'preserve',
175
+ description: 'Keep as written'
176
+ },
177
+ {
178
+ value: 'indent',
179
+ description: 'Always use indented continuation'
180
+ },
181
+ {
182
+ value: 'backslash',
183
+ description: 'Always use \\ continuation'
184
+ }
185
+ ]
186
+ },
187
+ controlFlowInline: {
188
+ category: CAT.CONTROL_FLOW,
189
+ type: 'boolean',
190
+ description: 'Allow - if x then .ok one-liners (anti-Prettier by default).'
191
+ },
192
+ statementMerging: {
193
+ category: CAT.CONTROL_FLOW,
194
+ type: 'choice',
195
+ description: 'Merge consecutive - lines into a single indented block. Only childless statements.',
196
+ choices: [
197
+ {
198
+ value: 'preserve',
199
+ description: 'Keep each - line separate'
200
+ },
201
+ {
202
+ value: 'merge',
203
+ description: 'Merge consecutive childless statements into one indented block'
204
+ }
205
+ ]
206
+ },
207
+ commentFormat: {
208
+ category: CAT.COMMENTS,
209
+ type: 'boolean',
210
+ description: 'Reflow/word-wrap comment text (experimental).'
211
+ }
212
+ };
213
+
214
+ export var defaultOptions = {
215
+ tagCase: 'preserve',
216
+ implicitDivExpansion: false,
217
+ maxChainLength: 4,
218
+ inlineThreshold: -1,
219
+ voidElementStyle: 'self-closing',
220
+ attributeStyle: 'preserve',
221
+ attributeMultilineThreshold: 1,
222
+ attributeSort: 'none',
223
+ quoteStyle: 'preserve',
224
+ coffeeScriptFormat: true,
225
+ methodChainAlign: true,
226
+ blankLineHandling: 'preserve',
227
+ trailingWhitespace: 'remove',
228
+ continuationStyle: 'indent',
229
+ controlFlowInline: false,
230
+ statementMerging: 'preserve',
231
+ commentFormat: false
232
+ };