coffeehaml 0.7.0 → 0.7.2
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/README.md +21 -5
- package/dist/ast.js +334 -125
- package/dist/cli.js +363 -291
- package/dist/compiler.js +126 -89
- package/dist/emitter.js +771 -736
- package/dist/errors.js +5 -2
- package/dist/expressions.js +211 -154
- package/dist/index.js +22 -6
- package/dist/lexer.js +536 -340
- package/dist/parser.js +533 -438
- package/dist/prettier/coffeescript-formatter.js +292 -392
- package/dist/prettier/index.js +96 -60
- package/dist/prettier/options.js +179 -147
- package/dist/prettier/printer.js +549 -642
- package/dist/types.js +122 -12
- package/dist/vite-plugin.js +78 -63
- package/package.json +4 -9
- package/dist/ast.d.ts +0 -123
- package/dist/ast.d.ts.map +0 -1
- package/dist/ast.js.map +0 -1
- package/dist/cli.d.ts +0 -3
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js.map +0 -1
- package/dist/compiler.d.ts +0 -10
- package/dist/compiler.d.ts.map +0 -1
- package/dist/compiler.js.map +0 -1
- package/dist/emitter.d.ts +0 -4
- package/dist/emitter.d.ts.map +0 -1
- package/dist/emitter.js.map +0 -1
- package/dist/errors.d.ts +0 -3
- package/dist/errors.d.ts.map +0 -1
- package/dist/errors.js.map +0 -1
- package/dist/expressions.d.ts +0 -22
- package/dist/expressions.d.ts.map +0 -1
- package/dist/expressions.js.map +0 -1
- package/dist/index.d.ts +0 -7
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/lexer.d.ts +0 -30
- package/dist/lexer.d.ts.map +0 -1
- package/dist/lexer.js.map +0 -1
- package/dist/parser.d.ts +0 -10
- package/dist/parser.d.ts.map +0 -1
- package/dist/parser.js.map +0 -1
- package/dist/prettier/coffeescript-formatter.d.ts +0 -31
- package/dist/prettier/coffeescript-formatter.d.ts.map +0 -1
- package/dist/prettier/coffeescript-formatter.js.map +0 -1
- package/dist/prettier/index.d.ts +0 -8
- package/dist/prettier/index.d.ts.map +0 -1
- package/dist/prettier/index.js.map +0 -1
- package/dist/prettier/options.d.ts +0 -10
- package/dist/prettier/options.d.ts.map +0 -1
- package/dist/prettier/options.js.map +0 -1
- package/dist/prettier/printer.d.ts +0 -45
- package/dist/prettier/printer.d.ts.map +0 -1
- package/dist/prettier/printer.js.map +0 -1
- package/dist/types.d.ts +0 -76
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js.map +0 -1
- package/dist/vite-plugin.d.ts +0 -7
- package/dist/vite-plugin.d.ts.map +0 -1
- package/dist/vite-plugin.js.map +0 -1
package/dist/prettier/printer.js
CHANGED
|
@@ -1,652 +1,559 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
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
|
|
30
67
|
};
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
function formatInlineChild(child, o) {
|
|
69
|
-
if (child instanceof Text)
|
|
70
|
-
return child.value;
|
|
71
|
-
if (child instanceof Output) {
|
|
72
|
-
const prefix = child.outputKind === 'unescaped' ? '!= ' : '= ';
|
|
73
|
-
return prefix + (o.coffeeScriptFormat
|
|
74
|
-
? formatCS(child.expression.source, o)
|
|
75
|
-
: child.expression.source);
|
|
76
|
-
}
|
|
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) {
|
|
77
105
|
return '';
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
markBlankLines(path.getValue(), options.originalText);
|
|
142
|
-
}
|
|
143
|
-
return printNode(path, printFn);
|
|
144
|
-
}
|
|
145
|
-
/** Pre-pass: mark sibling nodes that had blank lines before them in source. */
|
|
146
|
-
function markBlankLines(node, source) {
|
|
147
|
-
if (!node || !node.children || !Array.isArray(node.children))
|
|
148
|
-
return;
|
|
149
|
-
const children = node.children;
|
|
150
|
-
for (let i = 1; i < children.length; i++) {
|
|
151
|
-
const prev = children[i - 1];
|
|
152
|
-
const curr = children[i];
|
|
153
|
-
const prevEnd = prev?.location?.offset + prev?.location?.length;
|
|
154
|
-
const currStart = curr?.location?.offset;
|
|
155
|
-
if (prevEnd != null && currStart != null && prevEnd < currStart) {
|
|
156
|
-
const between = source.slice(prevEnd, currStart);
|
|
157
|
-
// Two consecutive newlines (or more) = blank line
|
|
158
|
-
if (/\n\s*\n/.test(between)) {
|
|
159
|
-
curr._blankBefore = true;
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
// Recurse
|
|
164
|
-
for (const child of children) {
|
|
165
|
-
if (!(child instanceof MergedStatements)) {
|
|
166
|
-
markBlankLines(child, source);
|
|
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;
|
|
167
169
|
}
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
}
|
|
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
|
+
|
|
188
234
|
// ─── Document ──────────────────────────────────────────────
|
|
189
|
-
function
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
}
|
|
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
|
+
|
|
207
258
|
// ─── Element ───────────────────────────────────────────────
|
|
208
|
-
function
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
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 join(hardline, [header, indent(joined)]);
|
|
297
|
+
};
|
|
298
|
+
|
|
240
299
|
// ─── ImplicitDiv ───────────────────────────────────────────
|
|
241
|
-
function
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
return
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
if (i > 0)
|
|
265
|
-
docs.push(hardline);
|
|
266
|
-
const cls = node.classes[i];
|
|
267
|
-
const isLast = i === node.classes.length - 1;
|
|
268
|
-
const idPart = (isLast && node.id) ? '#' + node.id : '';
|
|
269
|
-
docs.push('.' + cls + idPart);
|
|
270
|
-
if (isLast) {
|
|
271
|
-
docs.push(printAttrs(node.attributes, o, node));
|
|
272
|
-
if (node.children.length > 0) {
|
|
273
|
-
const childDocs = path.map(printFn, 'children');
|
|
274
|
-
docs.push(indent([hardline, joinChildrenWithBlanks(node.children, childDocs, o)]));
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
return group(docs);
|
|
279
|
-
}
|
|
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 join(hardline, [header, indent(joined)]);
|
|
321
|
+
};
|
|
322
|
+
|
|
280
323
|
// ─── Output ────────────────────────────────────────────────
|
|
281
|
-
function
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
return group(['- ', keyword, ' ', exprDoc, thenPart, childDoc]);
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
const header = keyword === 'statement' ? ['-'] : ['- ', keyword];
|
|
325
|
-
if (node.expression.source) {
|
|
326
|
-
header.push(' ');
|
|
327
|
-
header.push(exprDoc);
|
|
328
|
-
}
|
|
329
|
-
const docs = [group(header)];
|
|
330
|
-
if (hasChildren) {
|
|
331
|
-
const childDocs = path.map(printFn, 'children');
|
|
332
|
-
docs.push(indent([hardline, joinChildrenWithBlanks(node.children, childDocs, o)]));
|
|
333
|
-
}
|
|
334
|
-
if (hasNext) {
|
|
335
|
-
docs.push(printNextFlow(node.next, o, printFn));
|
|
336
|
-
}
|
|
337
|
-
return group(docs);
|
|
338
|
-
}
|
|
339
|
-
function printNextFlow(next, o, printFn) {
|
|
340
|
-
const keyword = next.controlKind;
|
|
341
|
-
const exprDoc = o.coffeeScriptFormat
|
|
342
|
-
? formatCS(next.expression.source, o)
|
|
343
|
-
: next.expression.source;
|
|
344
|
-
const header = keyword === 'statement'
|
|
345
|
-
? [hardline, '-']
|
|
346
|
-
: [hardline, '- ', keyword];
|
|
347
|
-
if (next.expression.source) {
|
|
348
|
-
header.push(' ');
|
|
349
|
-
header.push(exprDoc);
|
|
350
|
-
}
|
|
351
|
-
const docs = [group(header)];
|
|
352
|
-
if (next.children.length > 0) {
|
|
353
|
-
docs.push(indent([hardline, printChildrenDirect(next.children, o, printFn)]));
|
|
354
|
-
}
|
|
355
|
-
if (next.next) {
|
|
356
|
-
docs.push(printNextFlow(next.next, o, printFn));
|
|
357
|
-
}
|
|
358
|
-
return group(docs);
|
|
359
|
-
}
|
|
360
|
-
// ─── Merged Statements (pre-pass) ──────────────────────────
|
|
361
|
-
function mergeAllStatements(node, o) {
|
|
362
|
-
if (!node || !node.children || !Array.isArray(node.children))
|
|
363
|
-
return;
|
|
364
|
-
node.children = mergeConsecutiveStatements(node.children, o);
|
|
365
|
-
for (const child of node.children) {
|
|
366
|
-
if (!(child instanceof MergedStatements)) {
|
|
367
|
-
mergeAllStatements(child, o);
|
|
368
|
-
}
|
|
369
|
-
}
|
|
370
|
-
}
|
|
371
|
-
function mergeConsecutiveStatements(children, o) {
|
|
372
|
-
if (o.statementMerging !== 'merge')
|
|
373
|
-
return children;
|
|
374
|
-
const result = [];
|
|
375
|
-
let stmtGroup = [];
|
|
376
|
-
for (const child of children) {
|
|
377
|
-
if (child instanceof ControlFlow &&
|
|
378
|
-
child.controlKind === 'statement' &&
|
|
379
|
-
child.children.length === 0 &&
|
|
380
|
-
!child.next) {
|
|
381
|
-
stmtGroup.push(child);
|
|
382
|
-
}
|
|
383
|
-
else {
|
|
384
|
-
flushGroup();
|
|
385
|
-
result.push(child);
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
flushGroup();
|
|
389
|
-
return result;
|
|
390
|
-
function flushGroup() {
|
|
391
|
-
if (stmtGroup.length > 1) {
|
|
392
|
-
result.push(new MergedStatements(stmtGroup));
|
|
393
|
-
}
|
|
394
|
-
else if (stmtGroup.length === 1) {
|
|
395
|
-
result.push(stmtGroup[0]);
|
|
396
|
-
}
|
|
397
|
-
stmtGroup = [];
|
|
398
|
-
}
|
|
399
|
-
}
|
|
400
|
-
function printMergedFlow(path, _printFn) {
|
|
401
|
-
const merged = path.getValue();
|
|
402
|
-
const o = opts(path);
|
|
403
|
-
const docs = ['-'];
|
|
404
|
-
for (const stmt of merged.statements) {
|
|
405
|
-
const exprDoc = o.coffeeScriptFormat
|
|
406
|
-
? formatCS(stmt.expression.source, o)
|
|
407
|
-
: stmt.expression.source;
|
|
408
|
-
docs.push(indent([hardline, exprDoc]));
|
|
409
|
-
}
|
|
410
|
-
return group(docs);
|
|
411
|
-
}
|
|
412
|
-
function printChildrenDirect(children, o, printFn) {
|
|
413
|
-
const docs = [];
|
|
414
|
-
for (let i = 0; i < children.length; i++) {
|
|
415
|
-
if (i > 0) {
|
|
416
|
-
const node = children[i];
|
|
417
|
-
const hasBlank = o.blankLineHandling === 'preserve' && node._blankBefore;
|
|
418
|
-
docs.push(hasBlank ? [hardline, hardline] : hardline);
|
|
419
|
-
}
|
|
420
|
-
docs.push(nodeToDoc(children[i], o, printFn));
|
|
421
|
-
}
|
|
422
|
-
return docs;
|
|
423
|
-
}
|
|
424
|
-
function nodeToDoc(node, o, printFn) {
|
|
425
|
-
if (node instanceof Text)
|
|
426
|
-
return node.value;
|
|
427
|
-
if (node instanceof Element) {
|
|
428
|
-
const prefix = buildTagPrefix(node.tag instanceof Expression ? null : node.tag, node.classes, node.id, o);
|
|
429
|
-
const attrsDoc = printAttrs(node.attributes, o, node);
|
|
430
|
-
if (isSingleInlineChild(node.children)) {
|
|
431
|
-
return group([prefix, attrsDoc, ' ', formatInlineChild(node.children[0], o)]);
|
|
432
|
-
}
|
|
433
|
-
const childrenDoc = node.children.length > 0
|
|
434
|
-
? indent([hardline, printChildrenDirect(node.children, o, printFn)])
|
|
435
|
-
: '';
|
|
436
|
-
return group([prefix, attrsDoc, childrenDoc]);
|
|
437
|
-
}
|
|
438
|
-
if (node instanceof ImplicitDiv) {
|
|
439
|
-
const prefix = buildTagPrefix(null, node.classes, node.id, o);
|
|
440
|
-
const attrsDoc = printAttrs(node.attributes, o, node);
|
|
441
|
-
if (isSingleInlineChild(node.children)) {
|
|
442
|
-
return group([prefix, attrsDoc, ' ', formatInlineChild(node.children[0], o)]);
|
|
443
|
-
}
|
|
444
|
-
const childrenDoc = node.children.length > 0
|
|
445
|
-
? indent([hardline, printChildrenDirect(node.children, o, printFn)])
|
|
446
|
-
: '';
|
|
447
|
-
return group([prefix, attrsDoc, childrenDoc]);
|
|
448
|
-
}
|
|
449
|
-
if (node instanceof Output) {
|
|
450
|
-
const prefix = node.outputKind === 'unescaped' ? '!= ' : '= ';
|
|
451
|
-
const exprDoc = o.coffeeScriptFormat
|
|
452
|
-
? formatCS(node.expression.source)
|
|
453
|
-
: node.expression.source;
|
|
454
|
-
const childrenDoc = node.children.length > 0
|
|
455
|
-
? indent([hardline, printChildrenDirect(node.children, o, printFn)])
|
|
456
|
-
: '';
|
|
457
|
-
return group([prefix, exprDoc, childrenDoc]);
|
|
458
|
-
}
|
|
459
|
-
if (node instanceof ControlFlow) {
|
|
460
|
-
const keyword = node.controlKind;
|
|
461
|
-
const exprDoc = o.coffeeScriptFormat
|
|
462
|
-
? formatCS(node.expression.source)
|
|
463
|
-
: node.expression.source;
|
|
464
|
-
const header = ['- ', keyword];
|
|
465
|
-
if (node.expression.source) {
|
|
466
|
-
header.push(' ');
|
|
467
|
-
header.push(exprDoc);
|
|
468
|
-
}
|
|
469
|
-
const childrenDoc = node.children.length > 0
|
|
470
|
-
? indent([hardline, printChildrenDirect(node.children, o, printFn)])
|
|
471
|
-
: '';
|
|
472
|
-
return group([...header, childrenDoc]);
|
|
473
|
-
}
|
|
474
|
-
return '';
|
|
475
|
-
}
|
|
476
|
-
// ─── Comment / Filter ──────────────────────────────────────
|
|
477
|
-
function printComm(path) {
|
|
478
|
-
const node = path.getValue();
|
|
479
|
-
const o = opts(path);
|
|
480
|
-
let text = node.text;
|
|
481
|
-
// Reflow long comment text to printWidth
|
|
482
|
-
if (o.commentFormat && text.length > o.printWidth - 3) {
|
|
483
|
-
text = reflowComment(text, o.printWidth - 3, 2);
|
|
484
|
-
}
|
|
485
|
-
return node.commentKind === 'html' ? '/ ' + text : '-# ' + text;
|
|
486
|
-
}
|
|
487
|
-
/** Simple word-wrap for comment text. Preserves existing newlines. */
|
|
488
|
-
function reflowComment(text, maxWidth, _indent) {
|
|
489
|
-
const paragraphs = text.split('\n');
|
|
490
|
-
const result = [];
|
|
491
|
-
for (const para of paragraphs) {
|
|
492
|
-
if (para.length <= maxWidth) {
|
|
493
|
-
result.push(para);
|
|
494
|
-
continue;
|
|
495
|
-
}
|
|
496
|
-
const words = para.split(/\s+/);
|
|
497
|
-
const lines = [];
|
|
498
|
-
let current = '';
|
|
499
|
-
for (const word of words) {
|
|
500
|
-
const candidate = current ? current + ' ' + word : word;
|
|
501
|
-
if (candidate.length <= maxWidth) {
|
|
502
|
-
current = candidate;
|
|
503
|
-
}
|
|
504
|
-
else {
|
|
505
|
-
if (current)
|
|
506
|
-
lines.push(current);
|
|
507
|
-
current = word;
|
|
508
|
-
}
|
|
509
|
-
}
|
|
510
|
-
if (current)
|
|
511
|
-
lines.push(current);
|
|
512
|
-
result.push(lines.join('\n'));
|
|
513
|
-
}
|
|
514
|
-
return result.join('\n');
|
|
515
|
-
}
|
|
516
|
-
function printFilt(path) {
|
|
517
|
-
const node = path.getValue();
|
|
518
|
-
const lines = node.content.split('\n');
|
|
519
|
-
const bodyDocs = [];
|
|
520
|
-
for (let i = 0; i < lines.length; i++) {
|
|
521
|
-
const l = lines[i];
|
|
522
|
-
// Skip leading empty line (from content starting with \n)
|
|
523
|
-
if (i === 0 && l === '')
|
|
524
|
-
continue;
|
|
525
|
-
bodyDocs.push(hardline);
|
|
526
|
-
bodyDocs.push(' ' + l);
|
|
527
|
-
}
|
|
528
|
-
if (bodyDocs.length > 0)
|
|
529
|
-
return [':' + node.filterName, ...bodyDocs];
|
|
530
|
-
return ':' + node.filterName;
|
|
531
|
-
}
|
|
532
|
-
// ─── Attributes ────────────────────────────────────────────
|
|
533
|
-
function printAttrs(attrs, o, element) {
|
|
534
|
-
if (attrs.length === 0)
|
|
535
|
-
return '';
|
|
536
|
-
const sorted = sortAttrs([...attrs], o);
|
|
537
|
-
const style = detectStyle(o, element);
|
|
538
|
-
if (style === 'bare')
|
|
539
|
-
return printBare(sorted, o);
|
|
540
|
-
const open = style === 'braces' ? '{' : '(';
|
|
541
|
-
const close = style === 'braces' ? '}' : ')';
|
|
542
|
-
if (sorted.length <= 1) {
|
|
543
|
-
const parts = [open];
|
|
544
|
-
for (let i = 0; i < sorted.length; i++) {
|
|
545
|
-
if (i > 0)
|
|
546
|
-
parts.push(', ');
|
|
547
|
-
parts.push(anyAttr(sorted[i]));
|
|
548
|
-
}
|
|
549
|
-
parts.push(close);
|
|
550
|
-
return group(parts);
|
|
551
|
-
}
|
|
552
|
-
return group([
|
|
553
|
-
open,
|
|
554
|
-
indent([hardline, join([',', hardline], sorted.map(a => anyAttr(a)))]),
|
|
555
|
-
hardline,
|
|
556
|
-
close,
|
|
557
|
-
]);
|
|
558
|
-
}
|
|
559
|
-
function anyAttr(attr) {
|
|
560
|
-
if ('spread' in attr && attr.spread)
|
|
561
|
-
return '...' + attr.expression.source;
|
|
562
|
-
return formatAttr(attr);
|
|
563
|
-
}
|
|
564
|
-
function detectStyle(o, element) {
|
|
565
|
-
// When preserving, respect the original syntax from the AST
|
|
566
|
-
if (o.attributeStyle === 'preserve') {
|
|
567
|
-
if (element?.attrStyle)
|
|
568
|
-
return element.attrStyle;
|
|
569
|
-
// Fallback: if element has attributes but no recorded style, assume braces
|
|
570
|
-
if (element?.attributes && element.attributes.length > 0)
|
|
571
|
-
return 'braces';
|
|
572
|
-
return 'braces'; // default for elements with attributes
|
|
573
|
-
}
|
|
574
|
-
if (o.attributeStyle === 'parens')
|
|
575
|
-
return 'parens';
|
|
576
|
-
if (o.attributeStyle === 'bare')
|
|
577
|
-
return 'bare';
|
|
578
|
-
return 'braces';
|
|
579
|
-
}
|
|
580
|
-
function printBare(attrs, o) {
|
|
581
|
-
const parts = [];
|
|
582
|
-
for (let i = 0; i < attrs.length; i++) {
|
|
583
|
-
if (i > 0)
|
|
584
|
-
parts.push(' ');
|
|
585
|
-
const attr = attrs[i];
|
|
586
|
-
if ('spread' in attr && attr.spread) {
|
|
587
|
-
parts.push('...' + attr.expression.source);
|
|
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 join(hardline, [`${marker} ${expr}`, indent(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 '-';
|
|
588
363
|
}
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
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 '';
|
|
592
400
|
}
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
}
|
|
596
|
-
// ─── CoffeeScript delegation (Phase 4) ────────────────────
|
|
597
|
-
/**
|
|
598
|
-
* Format a CoffeeScript expression string.
|
|
599
|
-
* Uses CoffeeScript's token-based formatter.
|
|
600
|
-
* Returns a Doc (string) that Prettier can embed.
|
|
601
|
-
*/
|
|
602
|
-
function formatCS(source, o) {
|
|
603
|
-
const pw = o?.printWidth ?? 80;
|
|
604
|
-
const mc = o?.methodChainAlign ?? true;
|
|
605
|
-
const enabled = o?.coffeeScriptFormat ?? true;
|
|
606
|
-
return formatCoffeeScript(source, {
|
|
607
|
-
printWidth: pw,
|
|
608
|
-
methodChainAlign: mc,
|
|
609
|
-
enabled,
|
|
401
|
+
})();
|
|
402
|
+
return ' ' + val;
|
|
610
403
|
});
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
404
|
+
return join(hardline, ['-', childLines.join('\n')]);
|
|
405
|
+
}
|
|
406
|
+
return join(hardline, [header, indent(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, 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
|
+
parts = [];
|
|
508
|
+
for (k = 0, len = attrs.length; k < len; k++) {
|
|
509
|
+
attr = attrs[k];
|
|
510
|
+
if (attr.spread) {
|
|
511
|
+
expr = (ref1 = attr.expression.source) != null ? ref1 : '';
|
|
512
|
+
if (o.coffeeScriptFormat) {
|
|
513
|
+
expr = formatCoffeeScript(expr, o);
|
|
514
|
+
}
|
|
515
|
+
parts.push(style === 'parens' ? `...${expr}` : `{${expr}...}`);
|
|
516
|
+
continue;
|
|
517
|
+
}
|
|
518
|
+
name = attr.name;
|
|
519
|
+
val = (ref2 = attr.value.source) != null ? ref2 : '';
|
|
520
|
+
if (o.coffeeScriptFormat) {
|
|
521
|
+
val = formatCoffeeScript(val, o);
|
|
522
|
+
}
|
|
523
|
+
if (attr.shorthand) {
|
|
524
|
+
parts.push(name);
|
|
525
|
+
} else {
|
|
526
|
+
parts.push(`${name}: ${val}`);
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
switch (style) {
|
|
530
|
+
case 'braces':
|
|
531
|
+
return `{ ${parts.join(', ')} }`;
|
|
532
|
+
case 'parens':
|
|
533
|
+
return `( ${parts.join(', ')} )`;
|
|
534
|
+
default:
|
|
535
|
+
return parts.join(', ');
|
|
536
|
+
}
|
|
537
|
+
};
|
|
538
|
+
|
|
539
|
+
// ─── CoffeeScript Embed (for Prettier embed) ───────────────
|
|
540
|
+
export var embedCoffeeScript = function(path, _print) {
|
|
541
|
+
var expr, node, ref;
|
|
542
|
+
node = path.node;
|
|
543
|
+
if (!node) {
|
|
544
|
+
return null;
|
|
545
|
+
}
|
|
546
|
+
if (node instanceof Output || node instanceof ControlFlow) {
|
|
547
|
+
expr = (ref = node.expression) != null ? ref.source : void 0;
|
|
548
|
+
if (!(expr && /[\u0000-\u00ff]/.test(expr))) {
|
|
549
|
+
return null;
|
|
550
|
+
}
|
|
551
|
+
null;
|
|
552
|
+
}
|
|
553
|
+
return null;
|
|
554
|
+
};
|
|
555
|
+
|
|
556
|
+
export {
|
|
557
|
+
MergedStatements,
|
|
558
|
+
mergeAllStatements
|
|
559
|
+
};
|