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.
- package/dist/coffeescript-formatter.js +309 -0
- package/dist/lexer.js +46 -1
- package/dist/options.js +232 -0
- package/dist/parser.js +117 -3
- package/dist/prettier/coffeescript-formatter.js +2 -1
- package/dist/prettier/printer.js +55 -29
- package/dist/printer.js +583 -0
- package/package.json +1 -1
package/dist/printer.js
ADDED
|
@@ -0,0 +1,583 @@
|
|
|
1
|
+
// Generated by CoffeeScript 2.7.0
|
|
2
|
+
// printer.coffee — AST → Prettier Doc IR
|
|
3
|
+
// Core formatting engine for CoffeeHaml Prettier plugin
|
|
4
|
+
var MergedStatements, VOID_ELEMENTS, _prettier, _require, analyzeBlankLines, defaultOpts, detectStyle, formatAttributes, formatTag, group, hardline, indent, isSingleInlineChild, isVoidElement, join, joinChildrenWithBlanks, mergeAllStatements, opts, printComment, printControlFlow, printDoc, printDoctype, printElement, printFilter, printFlow, printImplicitDiv, printMergedFlow, printNode, printOutput, reflowCommentText;
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
Document,
|
|
8
|
+
Element,
|
|
9
|
+
ImplicitDiv,
|
|
10
|
+
Text,
|
|
11
|
+
Output,
|
|
12
|
+
ControlFlow,
|
|
13
|
+
Comment,
|
|
14
|
+
Filter,
|
|
15
|
+
Doctype,
|
|
16
|
+
Node,
|
|
17
|
+
Expression,
|
|
18
|
+
Attribute,
|
|
19
|
+
SpreadAttribute
|
|
20
|
+
} from '../ast.js';
|
|
21
|
+
|
|
22
|
+
import {
|
|
23
|
+
formatCoffeeScript,
|
|
24
|
+
formatCoffeeScriptBlock
|
|
25
|
+
} from './coffeescript-formatter.js';
|
|
26
|
+
|
|
27
|
+
import {
|
|
28
|
+
createRequire
|
|
29
|
+
} from 'module';
|
|
30
|
+
|
|
31
|
+
_require = createRequire(import.meta.url);
|
|
32
|
+
|
|
33
|
+
_prettier = _require('prettier');
|
|
34
|
+
|
|
35
|
+
({group, indent, hardline, join} = _prettier.doc.builders);
|
|
36
|
+
|
|
37
|
+
// ─── Format Options ────────────────────────────────────────
|
|
38
|
+
// CoffeeHamlFormatOptions shape (runtime):
|
|
39
|
+
// tagCase, implicitDivExpansion, maxChainLength, inlineThreshold
|
|
40
|
+
// voidElementStyle, attributeStyle, attributeMultilineThreshold
|
|
41
|
+
// attributeSort, quoteStyle, coffeeScriptFormat, methodChainAlign
|
|
42
|
+
// blankLineHandling, trailingWhitespace, continuationStyle
|
|
43
|
+
// controlFlowInline, statementMerging, commentFormat
|
|
44
|
+
// tabWidth, useTabs, printWidth, originalText?
|
|
45
|
+
defaultOpts = {
|
|
46
|
+
tagCase: 'preserve',
|
|
47
|
+
implicitDivExpansion: false,
|
|
48
|
+
maxChainLength: 4,
|
|
49
|
+
inlineThreshold: -1,
|
|
50
|
+
voidElementStyle: 'self-closing',
|
|
51
|
+
attributeStyle: 'preserve',
|
|
52
|
+
attributeMultilineThreshold: 1,
|
|
53
|
+
attributeSort: 'none',
|
|
54
|
+
quoteStyle: 'preserve',
|
|
55
|
+
coffeeScriptFormat: true,
|
|
56
|
+
methodChainAlign: true,
|
|
57
|
+
blankLineHandling: 'preserve',
|
|
58
|
+
trailingWhitespace: 'remove',
|
|
59
|
+
continuationStyle: 'indent',
|
|
60
|
+
controlFlowInline: false,
|
|
61
|
+
statementMerging: 'preserve',
|
|
62
|
+
commentFormat: false,
|
|
63
|
+
tabWidth: 2,
|
|
64
|
+
useTabs: false,
|
|
65
|
+
printWidth: 80,
|
|
66
|
+
originalText: void 0
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
opts = function(p) {
|
|
70
|
+
return p.__opts || defaultOpts;
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
MergedStatements = (function() {
|
|
74
|
+
// ─── MergedStatements wrapper ──────────────────────────────
|
|
75
|
+
class MergedStatements {
|
|
76
|
+
constructor(statements) {
|
|
77
|
+
this.statements = statements;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
MergedStatements.prototype.kind = 'MergedStatements';
|
|
83
|
+
|
|
84
|
+
MergedStatements.prototype.statements = [];
|
|
85
|
+
|
|
86
|
+
return MergedStatements;
|
|
87
|
+
|
|
88
|
+
}).call(this);
|
|
89
|
+
|
|
90
|
+
// ─── Constants ─────────────────────────────────────────────
|
|
91
|
+
VOID_ELEMENTS = new Set(['area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'link', 'meta', 'param', 'source', 'track', 'wbr']);
|
|
92
|
+
|
|
93
|
+
isVoidElement = function(tag) {
|
|
94
|
+
return VOID_ELEMENTS.has(tag.toLowerCase());
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
isSingleInlineChild = function(children) {
|
|
98
|
+
return children.length === 1 && (children[0] instanceof Text || children[0] instanceof Output);
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
// ─── Blank-line-aware join ─────────────────────────────────
|
|
102
|
+
joinChildrenWithBlanks = function(nodes, docs, o) {
|
|
103
|
+
var hasBlank, i, k, ref, ref1, result;
|
|
104
|
+
if (docs.length === 0) {
|
|
105
|
+
return '';
|
|
106
|
+
}
|
|
107
|
+
if (docs.length === 1) {
|
|
108
|
+
return docs[0];
|
|
109
|
+
}
|
|
110
|
+
result = [];
|
|
111
|
+
for (i = k = 0, ref = docs.length; (0 <= ref ? k < ref : k > ref); i = 0 <= ref ? ++k : --k) {
|
|
112
|
+
if (i > 0) {
|
|
113
|
+
hasBlank = ((ref1 = nodes[i]) != null ? ref1._blankBefore : void 0) || false;
|
|
114
|
+
result.push(hasBlank ? [hardline, hardline] : hardline);
|
|
115
|
+
}
|
|
116
|
+
result.push(docs[i]);
|
|
117
|
+
}
|
|
118
|
+
return result;
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
analyzeBlankLines = function(children, originalText, locations) {
|
|
122
|
+
var between, currStartOffset, i, k, node, prev, prevEndOffset, ref, results;
|
|
123
|
+
if (!(originalText && children.length > 1)) {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
results = [];
|
|
127
|
+
for (i = k = 0, ref = children.length; (0 <= ref ? k < ref : k > ref); i = 0 <= ref ? ++k : --k) {
|
|
128
|
+
node = children[i];
|
|
129
|
+
if (!(node != null ? node.location : void 0)) {
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
prev = children[i - 1];
|
|
133
|
+
if (!(prev != null ? prev.location : void 0)) {
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
// Check for blank line in source between prev end and this node start
|
|
137
|
+
prevEndOffset = prev.location.offset + prev.location.length;
|
|
138
|
+
currStartOffset = node.location.offset;
|
|
139
|
+
between = originalText.slice(prevEndOffset, currStartOffset);
|
|
140
|
+
if (/\n\s*\n/.test(between)) {
|
|
141
|
+
results.push(node._blankBefore = true);
|
|
142
|
+
} else {
|
|
143
|
+
results.push(void 0);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return results;
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
// ─── Merge consecutive statements ──────────────────────────
|
|
150
|
+
mergeAllStatements = function(children) {
|
|
151
|
+
var child, i, j, next, result;
|
|
152
|
+
if (!((children != null ? children.length : void 0) > 1)) {
|
|
153
|
+
return children;
|
|
154
|
+
}
|
|
155
|
+
result = [];
|
|
156
|
+
i = 0;
|
|
157
|
+
while (i < children.length) {
|
|
158
|
+
child = children[i];
|
|
159
|
+
if (child instanceof ControlFlow && child.controlKind === 'statement' && child.children.length === 0) {
|
|
160
|
+
group = [child];
|
|
161
|
+
j = i + 1;
|
|
162
|
+
while (j < children.length) {
|
|
163
|
+
next = children[j];
|
|
164
|
+
if (next instanceof ControlFlow && next.controlKind === 'statement' && next.children.length === 0) {
|
|
165
|
+
group.push(next);
|
|
166
|
+
j++;
|
|
167
|
+
} else {
|
|
168
|
+
break;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
if (group.length > 1) {
|
|
172
|
+
result.push(new MergedStatements(group));
|
|
173
|
+
i = j;
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
result.push(child);
|
|
178
|
+
i++;
|
|
179
|
+
}
|
|
180
|
+
return result;
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
// ─── Main entry ────────────────────────────────────────────
|
|
184
|
+
export var print = function(path, o, printFn) {
|
|
185
|
+
var node;
|
|
186
|
+
node = path.node;
|
|
187
|
+
if (!node) {
|
|
188
|
+
return '';
|
|
189
|
+
}
|
|
190
|
+
// Hang options on path for nested lookups
|
|
191
|
+
path.__opts = o;
|
|
192
|
+
return printNode(path, o, printFn);
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
printNode = function(path, o, printFn) {
|
|
196
|
+
var node;
|
|
197
|
+
node = path.node;
|
|
198
|
+
if (!node) {
|
|
199
|
+
return '';
|
|
200
|
+
}
|
|
201
|
+
if (node instanceof Document) {
|
|
202
|
+
return printDoc(path, o, printFn);
|
|
203
|
+
}
|
|
204
|
+
if (node instanceof Element) {
|
|
205
|
+
return printElement(path, o, printFn);
|
|
206
|
+
}
|
|
207
|
+
if (node instanceof ImplicitDiv) {
|
|
208
|
+
return printImplicitDiv(path, o, printFn);
|
|
209
|
+
}
|
|
210
|
+
if (node instanceof Text) {
|
|
211
|
+
return node.value;
|
|
212
|
+
}
|
|
213
|
+
if (node instanceof Output) {
|
|
214
|
+
return printOutput(path, o, printFn);
|
|
215
|
+
}
|
|
216
|
+
if (node instanceof ControlFlow) {
|
|
217
|
+
return printControlFlow(path, o, printFn);
|
|
218
|
+
}
|
|
219
|
+
if (node instanceof MergedStatements) {
|
|
220
|
+
return printMergedFlow(path, o, printFn);
|
|
221
|
+
}
|
|
222
|
+
if (node instanceof Comment) {
|
|
223
|
+
return printComment(path, o, printFn);
|
|
224
|
+
}
|
|
225
|
+
if (node instanceof Filter) {
|
|
226
|
+
return printFilter(path, o, printFn);
|
|
227
|
+
}
|
|
228
|
+
if (node instanceof Doctype) {
|
|
229
|
+
return printDoctype(path, o);
|
|
230
|
+
}
|
|
231
|
+
return '';
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
// ─── Document ──────────────────────────────────────────────
|
|
235
|
+
printDoc = function(path, o, printFn) {
|
|
236
|
+
var childDocs, k, len, n, next, node, ref, ref1;
|
|
237
|
+
node = path.node;
|
|
238
|
+
// Pre-pass: merge statements if enabled
|
|
239
|
+
if (o.statementMerging === 'merge') {
|
|
240
|
+
node.children = mergeAllStatements(node.children);
|
|
241
|
+
}
|
|
242
|
+
// Pre-pass: analyze blank lines
|
|
243
|
+
if (o.blankLineHandling === 'preserve' && o.originalText) {
|
|
244
|
+
ref = node.children;
|
|
245
|
+
for (k = 0, len = ref.length; k < len; k++) {
|
|
246
|
+
n = ref[k];
|
|
247
|
+
next = node.children[node.children.indexOf(n) + 1];
|
|
248
|
+
if (next) {
|
|
249
|
+
analyzeBlankLines([n, next], o.originalText);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
// Print children
|
|
254
|
+
childDocs = (ref1 = path.map(printFn, 'children')) != null ? ref1 : [];
|
|
255
|
+
return join(hardline, childDocs);
|
|
256
|
+
};
|
|
257
|
+
|
|
258
|
+
// ─── Element ───────────────────────────────────────────────
|
|
259
|
+
printElement = function(path, o, printFn) {
|
|
260
|
+
var attrStyle, attrs, childDoc, childDocs, children, classes, header, id, isVoid, joined, node, ref, ref1, ref2, ref3, selfClose, tag;
|
|
261
|
+
node = path.node;
|
|
262
|
+
tag = formatTag(node.tag, o);
|
|
263
|
+
// Classes and ID
|
|
264
|
+
classes = node.classes.map(function(c) {
|
|
265
|
+
return `.${c}`;
|
|
266
|
+
}).join('');
|
|
267
|
+
id = node.id ? `#${node.id}` : '';
|
|
268
|
+
// Attributes
|
|
269
|
+
attrStyle = detectStyle(node, o);
|
|
270
|
+
attrs = formatAttributes(node, attrStyle, o);
|
|
271
|
+
// Self-close marker
|
|
272
|
+
isVoid = typeof node.tag === 'string' && isVoidElement(node.tag);
|
|
273
|
+
selfClose = '';
|
|
274
|
+
if (isVoid) {
|
|
275
|
+
if (o.voidElementStyle === 'self-closing') {
|
|
276
|
+
selfClose = '/';
|
|
277
|
+
} else if (node.isSelfClosing) {
|
|
278
|
+
selfClose = '/';
|
|
279
|
+
}
|
|
280
|
+
} else if (node.isSelfClosing) {
|
|
281
|
+
selfClose = '/';
|
|
282
|
+
}
|
|
283
|
+
header = `%${tag}${classes}${id}${attrs}${selfClose}`;
|
|
284
|
+
// Children
|
|
285
|
+
children = (ref = node.children) != null ? ref : [];
|
|
286
|
+
if (children.length === 0) {
|
|
287
|
+
return header;
|
|
288
|
+
}
|
|
289
|
+
// Inline child
|
|
290
|
+
if (isSingleInlineChild(children) && o.controlFlowInline !== false) {
|
|
291
|
+
childDoc = (ref1 = (ref2 = path.map(printFn, 'children')) != null ? ref2[0] : void 0) != null ? ref1 : '';
|
|
292
|
+
return `${header} ${childDoc}`;
|
|
293
|
+
}
|
|
294
|
+
childDocs = (ref3 = path.map(printFn, 'children')) != null ? ref3 : [];
|
|
295
|
+
joined = joinChildrenWithBlanks(children, childDocs, o);
|
|
296
|
+
return [header, indent([hardline, joined])];
|
|
297
|
+
};
|
|
298
|
+
|
|
299
|
+
// ─── ImplicitDiv ───────────────────────────────────────────
|
|
300
|
+
printImplicitDiv = function(path, o, printFn) {
|
|
301
|
+
var attrStyle, attrs, childDoc, childDocs, children, classes, header, id, joined, node, ref, ref1, ref2, ref3;
|
|
302
|
+
node = path.node;
|
|
303
|
+
classes = node.classes.map(function(c) {
|
|
304
|
+
return `.${c}`;
|
|
305
|
+
}).join('');
|
|
306
|
+
id = node.id ? `#${node.id}` : '';
|
|
307
|
+
attrStyle = detectStyle(node, o);
|
|
308
|
+
attrs = formatAttributes(node, attrStyle, o);
|
|
309
|
+
header = `${classes}${id}${attrs}`;
|
|
310
|
+
children = (ref = node.children) != null ? ref : [];
|
|
311
|
+
if (children.length === 0) {
|
|
312
|
+
return header;
|
|
313
|
+
}
|
|
314
|
+
if (isSingleInlineChild(children)) {
|
|
315
|
+
childDoc = (ref1 = (ref2 = path.map(printFn, 'children')) != null ? ref2[0] : void 0) != null ? ref1 : '';
|
|
316
|
+
return `${header} ${childDoc}`;
|
|
317
|
+
}
|
|
318
|
+
childDocs = (ref3 = path.map(printFn, 'children')) != null ? ref3 : [];
|
|
319
|
+
joined = joinChildrenWithBlanks(children, childDocs, o);
|
|
320
|
+
return [header, indent([hardline, joined])];
|
|
321
|
+
};
|
|
322
|
+
|
|
323
|
+
// ─── Output ────────────────────────────────────────────────
|
|
324
|
+
printOutput = function(path, o, printFn) {
|
|
325
|
+
var childDocs, children, expr, joined, marker, node, ref, ref1, ref2;
|
|
326
|
+
node = path.node;
|
|
327
|
+
marker = node.outputKind === 'unescaped' ? '!=' : '=';
|
|
328
|
+
expr = (ref = node.expression.source) != null ? ref : '';
|
|
329
|
+
if (o.coffeeScriptFormat) {
|
|
330
|
+
expr = formatCoffeeScript(expr, o);
|
|
331
|
+
}
|
|
332
|
+
children = (ref1 = node.children) != null ? ref1 : [];
|
|
333
|
+
if (children.length === 0) {
|
|
334
|
+
return `${marker} ${expr}`;
|
|
335
|
+
}
|
|
336
|
+
childDocs = (ref2 = path.map(printFn, 'children')) != null ? ref2 : [];
|
|
337
|
+
joined = joinChildrenWithBlanks(children, childDocs, o);
|
|
338
|
+
return [`${marker} ${expr}`, indent([hardline, joined])];
|
|
339
|
+
};
|
|
340
|
+
|
|
341
|
+
// ─── Control Flow ──────────────────────────────────────────
|
|
342
|
+
printControlFlow = function(path, o, printFn) {
|
|
343
|
+
return printFlow(path, o, printFn);
|
|
344
|
+
};
|
|
345
|
+
|
|
346
|
+
printFlow = function(path, o, printFn) {
|
|
347
|
+
var childLines, children, expr, header, kind, node, ref, ref1, ref2, sep;
|
|
348
|
+
node = path.node;
|
|
349
|
+
kind = node.controlKind;
|
|
350
|
+
// Format expression
|
|
351
|
+
expr = (ref = node.expression.source) != null ? ref : '';
|
|
352
|
+
if (o.coffeeScriptFormat && kind !== 'statement') {
|
|
353
|
+
expr = formatCoffeeScript(expr, o);
|
|
354
|
+
}
|
|
355
|
+
// Build header
|
|
356
|
+
header = (function() {
|
|
357
|
+
switch (kind) {
|
|
358
|
+
case 'statement':
|
|
359
|
+
if (expr) {
|
|
360
|
+
return `- ${expr}`;
|
|
361
|
+
} else {
|
|
362
|
+
return '-';
|
|
363
|
+
}
|
|
364
|
+
break;
|
|
365
|
+
case 'else':
|
|
366
|
+
return '- else';
|
|
367
|
+
case 'else if':
|
|
368
|
+
return `- else if ${expr}`;
|
|
369
|
+
default:
|
|
370
|
+
return `- ${kind} ${expr}`;
|
|
371
|
+
}
|
|
372
|
+
})();
|
|
373
|
+
children = (ref1 = node.children) != null ? ref1 : [];
|
|
374
|
+
// Inline expansion (controlFlowInline)
|
|
375
|
+
if (o.controlFlowInline && children.length > 0 && (kind === 'if' || kind === 'unless' || kind === 'for' || kind === 'while')) {
|
|
376
|
+
if (children.length === 1 && (children[0] instanceof Element || children[0] instanceof ImplicitDiv)) {
|
|
377
|
+
sep = kind === 'if' || kind === 'unless' ? ' then ' : ' ';
|
|
378
|
+
return `${header}${sep}${printNode(path.map(printFn, 'children.0'), o, printFn)}`;
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
if (children.length === 0) {
|
|
382
|
+
return header;
|
|
383
|
+
}
|
|
384
|
+
// Re-parsed merged statements: statement-kind with empty expr + TEXT children
|
|
385
|
+
// Use baked indentation (matching printMergedFlow) to avoid Prettier indent quirks
|
|
386
|
+
if (kind === 'statement' && !expr && children.every(function(c) {
|
|
387
|
+
return c instanceof Text || c instanceof Output;
|
|
388
|
+
})) {
|
|
389
|
+
childLines = children.map(function(c) {
|
|
390
|
+
var val;
|
|
391
|
+
val = (function() {
|
|
392
|
+
var ref2, ref3;
|
|
393
|
+
switch (false) {
|
|
394
|
+
case !(c instanceof Text):
|
|
395
|
+
return c.value;
|
|
396
|
+
case !(c instanceof Output):
|
|
397
|
+
return (ref2 = (ref3 = c.expression) != null ? ref3.source : void 0) != null ? ref2 : '';
|
|
398
|
+
default:
|
|
399
|
+
return '';
|
|
400
|
+
}
|
|
401
|
+
})();
|
|
402
|
+
return ' ' + val;
|
|
403
|
+
});
|
|
404
|
+
return join(hardline, ['-', childLines.join('\n')]);
|
|
405
|
+
}
|
|
406
|
+
return [header, indent([hardline, join(hardline, (ref2 = path.map(printFn, 'children')) != null ? ref2 : [])])];
|
|
407
|
+
};
|
|
408
|
+
|
|
409
|
+
printMergedFlow = function(path, o, printFn) {
|
|
410
|
+
var lines, node;
|
|
411
|
+
node = path.node;
|
|
412
|
+
lines = node.statements.map(function(stmt) {
|
|
413
|
+
var expr, ref;
|
|
414
|
+
expr = (ref = stmt.expression.source) != null ? ref : '';
|
|
415
|
+
if (o.coffeeScriptFormat) {
|
|
416
|
+
expr = formatCoffeeScript(expr, o);
|
|
417
|
+
}
|
|
418
|
+
return ' ' + expr;
|
|
419
|
+
});
|
|
420
|
+
return join(hardline, ['-', lines.join('\n')]);
|
|
421
|
+
};
|
|
422
|
+
|
|
423
|
+
// ─── Comment ───────────────────────────────────────────────
|
|
424
|
+
printComment = function(path, o, _printFn) {
|
|
425
|
+
var node, text;
|
|
426
|
+
node = path.node;
|
|
427
|
+
if (node.commentKind === 'html') {
|
|
428
|
+
return `/ ${node.text}`;
|
|
429
|
+
}
|
|
430
|
+
text = node.text || '';
|
|
431
|
+
if (o.commentFormat && text.length > o.printWidth * 0.7) {
|
|
432
|
+
text = reflowCommentText(text, o.printWidth);
|
|
433
|
+
}
|
|
434
|
+
return `-# ${text}`;
|
|
435
|
+
};
|
|
436
|
+
|
|
437
|
+
reflowCommentText = function(text, width) {
|
|
438
|
+
var current, k, len, lines, word, words;
|
|
439
|
+
words = text.split(/\s+/);
|
|
440
|
+
lines = [];
|
|
441
|
+
current = '';
|
|
442
|
+
for (k = 0, len = words.length; k < len; k++) {
|
|
443
|
+
word = words[k];
|
|
444
|
+
if (current.length + word.length + 1 > width - 3) { // 3 = "-# "
|
|
445
|
+
if (current) {
|
|
446
|
+
lines.push(current.trim());
|
|
447
|
+
}
|
|
448
|
+
current = word;
|
|
449
|
+
} else {
|
|
450
|
+
current += current ? ' ' + word : word;
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
if (current) {
|
|
454
|
+
lines.push(current.trim());
|
|
455
|
+
}
|
|
456
|
+
return lines.join('\n-# ');
|
|
457
|
+
};
|
|
458
|
+
|
|
459
|
+
// ─── Filter ────────────────────────────────────────────────
|
|
460
|
+
printFilter = function(path, o, _printFn) {
|
|
461
|
+
var header, indented, node;
|
|
462
|
+
node = path.node;
|
|
463
|
+
header = `:${node.filterName}`;
|
|
464
|
+
if (node.content) {
|
|
465
|
+
indented = node.content.split('\n').map(function(l) {
|
|
466
|
+
return ' ' + l;
|
|
467
|
+
}).join('\n');
|
|
468
|
+
return `${header}\n${indented}`;
|
|
469
|
+
} else {
|
|
470
|
+
return header;
|
|
471
|
+
}
|
|
472
|
+
};
|
|
473
|
+
|
|
474
|
+
// ─── Doctype ───────────────────────────────────────────────
|
|
475
|
+
printDoctype = function(path, o) {
|
|
476
|
+
var node;
|
|
477
|
+
node = path.node;
|
|
478
|
+
return `!!! ${node.value || 'html'}`;
|
|
479
|
+
};
|
|
480
|
+
|
|
481
|
+
// ─── Tag formatting ────────────────────────────────────────
|
|
482
|
+
formatTag = function(tag, o) {
|
|
483
|
+
if (tag instanceof Expression) {
|
|
484
|
+
return tag.source;
|
|
485
|
+
}
|
|
486
|
+
if (o.tagCase === 'lowercase' && /^[a-z]/.test(tag)) {
|
|
487
|
+
return tag.toLowerCase();
|
|
488
|
+
}
|
|
489
|
+
return tag;
|
|
490
|
+
};
|
|
491
|
+
|
|
492
|
+
// ─── Attribute style detection ─────────────────────────────
|
|
493
|
+
detectStyle = function(node, o) {
|
|
494
|
+
var ref;
|
|
495
|
+
if (o.attributeStyle !== 'preserve') {
|
|
496
|
+
return o.attributeStyle;
|
|
497
|
+
}
|
|
498
|
+
return (ref = node.attrStyle) != null ? ref : 'bare';
|
|
499
|
+
};
|
|
500
|
+
|
|
501
|
+
formatAttributes = function(node, style, o) {
|
|
502
|
+
var attr, attrs, bareParts, expr, k, len, name, parts, ref, ref1, ref2, val;
|
|
503
|
+
attrs = (ref = node.attributes) != null ? ref : [];
|
|
504
|
+
if (!(attrs.length > 0)) {
|
|
505
|
+
return '';
|
|
506
|
+
}
|
|
507
|
+
// Bare style: HTML-style key="val" key2={expr} — space-separated
|
|
508
|
+
if (style === 'bare') {
|
|
509
|
+
bareParts = (function() {
|
|
510
|
+
var k, len, ref1, ref2, results;
|
|
511
|
+
results = [];
|
|
512
|
+
for (k = 0, len = attrs.length; k < len; k++) {
|
|
513
|
+
attr = attrs[k];
|
|
514
|
+
if (attr.spread) {
|
|
515
|
+
expr = (ref1 = attr.expression.source) != null ? ref1 : '';
|
|
516
|
+
if (o.coffeeScriptFormat) {
|
|
517
|
+
expr = formatCoffeeScript(expr, o);
|
|
518
|
+
}
|
|
519
|
+
results.push(`{${expr}...}`);
|
|
520
|
+
} else if (attr.shorthand) {
|
|
521
|
+
results.push(attr.name);
|
|
522
|
+
} else {
|
|
523
|
+
results.push(`${attr.name}=${(ref2 = attr.value.source) != null ? ref2 : ''}`);
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
return results;
|
|
527
|
+
})();
|
|
528
|
+
return ` ${bareParts.join(' ')}`;
|
|
529
|
+
} else {
|
|
530
|
+
parts = [];
|
|
531
|
+
for (k = 0, len = attrs.length; k < len; k++) {
|
|
532
|
+
attr = attrs[k];
|
|
533
|
+
if (attr.spread) {
|
|
534
|
+
expr = (ref1 = attr.expression.source) != null ? ref1 : '';
|
|
535
|
+
if (o.coffeeScriptFormat) {
|
|
536
|
+
expr = formatCoffeeScript(expr, o);
|
|
537
|
+
}
|
|
538
|
+
parts.push(style === 'parens' ? `...${expr}` : `{${expr}...}`);
|
|
539
|
+
continue;
|
|
540
|
+
}
|
|
541
|
+
name = attr.name;
|
|
542
|
+
val = (ref2 = attr.value.source) != null ? ref2 : '';
|
|
543
|
+
if (o.coffeeScriptFormat) {
|
|
544
|
+
val = formatCoffeeScript(val, o);
|
|
545
|
+
}
|
|
546
|
+
if (attr.shorthand) {
|
|
547
|
+
parts.push(name);
|
|
548
|
+
} else {
|
|
549
|
+
parts.push(`${name}: ${val}`);
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
switch (style) {
|
|
553
|
+
case 'braces':
|
|
554
|
+
return `{ ${parts.join(', ')} }`;
|
|
555
|
+
case 'parens':
|
|
556
|
+
return `( ${parts.join(', ')} )`;
|
|
557
|
+
default:
|
|
558
|
+
return parts.join(', ');
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
};
|
|
562
|
+
|
|
563
|
+
// ─── CoffeeScript Embed (for Prettier embed) ───────────────
|
|
564
|
+
export var embedCoffeeScript = function(path, _print) {
|
|
565
|
+
var expr, node, ref;
|
|
566
|
+
node = path.node;
|
|
567
|
+
if (!node) {
|
|
568
|
+
return null;
|
|
569
|
+
}
|
|
570
|
+
if (node instanceof Output || node instanceof ControlFlow) {
|
|
571
|
+
expr = (ref = node.expression) != null ? ref.source : void 0;
|
|
572
|
+
if (!(expr && /[\u0000-\u00ff]/.test(expr))) {
|
|
573
|
+
return null;
|
|
574
|
+
}
|
|
575
|
+
null;
|
|
576
|
+
}
|
|
577
|
+
return null;
|
|
578
|
+
};
|
|
579
|
+
|
|
580
|
+
export {
|
|
581
|
+
MergedStatements,
|
|
582
|
+
mergeAllStatements
|
|
583
|
+
};
|