prettier 1.6.1 → 2.0.0.pre.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +316 -293
- data/CONTRIBUTING.md +6 -9
- data/LICENSE +1 -1
- data/README.md +11 -12
- data/dist/haml/embed.js +53 -0
- data/dist/haml/parser.js +31 -0
- data/{src → dist}/haml/parser.rb +0 -0
- data/dist/haml/printer.js +336 -0
- data/dist/parser/getInfo.js +17 -0
- data/{src → dist}/parser/netcat.js +1 -0
- data/dist/parser/parseSync.js +128 -0
- data/dist/parser/server.rb +140 -0
- data/dist/plugin.js +143 -0
- data/dist/prettier.js +15 -0
- data/dist/rbs/parser.js +34 -0
- data/{src → dist}/rbs/parser.rb +0 -0
- data/dist/rbs/printer.js +517 -0
- data/dist/ruby/embed.js +110 -0
- data/dist/ruby/nodes/alias.js +59 -0
- data/{src → dist}/ruby/nodes/aref.js +26 -35
- data/dist/ruby/nodes/args.js +165 -0
- data/dist/ruby/nodes/arrays.js +126 -0
- data/dist/ruby/nodes/assign.js +41 -0
- data/dist/ruby/nodes/blocks.js +68 -0
- data/dist/ruby/nodes/calls.js +220 -0
- data/dist/ruby/nodes/case.js +50 -0
- data/dist/ruby/nodes/class.js +54 -0
- data/dist/ruby/nodes/commands.js +124 -0
- data/dist/ruby/nodes/conditionals.js +242 -0
- data/dist/ruby/nodes/constants.js +38 -0
- data/dist/ruby/nodes/flow.js +66 -0
- data/dist/ruby/nodes/hashes.js +130 -0
- data/dist/ruby/nodes/heredocs.js +30 -0
- data/dist/ruby/nodes/hooks.js +35 -0
- data/dist/ruby/nodes/ints.js +27 -0
- data/dist/ruby/nodes/lambdas.js +69 -0
- data/dist/ruby/nodes/loops.js +73 -0
- data/dist/ruby/nodes/massign.js +73 -0
- data/dist/ruby/nodes/methods.js +70 -0
- data/dist/ruby/nodes/operators.js +70 -0
- data/dist/ruby/nodes/params.js +89 -0
- data/dist/ruby/nodes/patterns.js +109 -0
- data/dist/ruby/nodes/regexp.js +45 -0
- data/dist/ruby/nodes/rescue.js +82 -0
- data/dist/ruby/nodes/return.js +75 -0
- data/dist/ruby/nodes/statements.js +111 -0
- data/dist/ruby/nodes/strings.js +218 -0
- data/dist/ruby/nodes/super.js +30 -0
- data/dist/ruby/nodes/undef.js +26 -0
- data/dist/ruby/nodes.js +151 -0
- data/dist/ruby/parser.js +34 -0
- data/{src → dist}/ruby/parser.rb +1215 -252
- data/dist/ruby/printer.js +125 -0
- data/dist/ruby/toProc.js +93 -0
- data/dist/types/haml.js +4 -0
- data/dist/types/plugin.js +3 -0
- data/dist/types/rbs.js +4 -0
- data/dist/types/ruby.js +4 -0
- data/dist/types/utils.js +2 -0
- data/dist/types.js +30 -0
- data/dist/utils/containsAssignment.js +15 -0
- data/dist/utils/getTrailingComma.js +6 -0
- data/dist/utils/hasAncestor.js +15 -0
- data/{src → dist}/utils/inlineEnsureParens.js +16 -17
- data/dist/utils/isEmptyBodyStmt.js +10 -0
- data/dist/utils/isEmptyStmts.js +10 -0
- data/dist/utils/literal.js +8 -0
- data/dist/utils/literallineWithoutBreakParent.js +8 -0
- data/dist/utils/makeCall.js +13 -0
- data/dist/utils/noIndent.js +11 -0
- data/dist/utils/printEmptyCollection.js +44 -0
- data/dist/utils/skipAssignIndent.js +15 -0
- data/dist/utils.js +30 -0
- data/node_modules/prettier/bin-prettier.js +313 -190
- data/node_modules/prettier/doc.js +191 -323
- data/node_modules/prettier/index.js +2753 -3677
- data/node_modules/prettier/package.json +1 -1
- data/node_modules/prettier/parser-angular.js +13 -14
- data/node_modules/prettier/parser-babel.js +7 -7
- data/node_modules/prettier/parser-espree.js +7 -7
- data/node_modules/prettier/parser-flow.js +7 -7
- data/node_modules/prettier/parser-glimmer.js +1 -1
- data/node_modules/prettier/parser-graphql.js +1 -1
- data/node_modules/prettier/parser-html.js +17 -17
- data/node_modules/prettier/parser-markdown.js +9 -9
- data/node_modules/prettier/parser-meriyah.js +7 -7
- data/node_modules/prettier/parser-postcss.js +2 -2
- data/node_modules/prettier/parser-typescript.js +7 -7
- data/node_modules/prettier/parser-yaml.js +2 -2
- data/node_modules/prettier/third-party.js +143 -78
- data/package.json +26 -18
- metadata +74 -67
- data/src/haml/embed.js +0 -87
- data/src/haml/parser.js +0 -23
- data/src/haml/printer.js +0 -438
- data/src/parser/parseSync.js +0 -172
- data/src/parser/server.rb +0 -66
- data/src/plugin.js +0 -148
- data/src/prettier.js +0 -16
- data/src/rbs/parser.js +0 -37
- data/src/rbs/printer.js +0 -643
- data/src/ruby/embed.js +0 -142
- data/src/ruby/nodes/alias.js +0 -73
- data/src/ruby/nodes/args.js +0 -222
- data/src/ruby/nodes/arrays.js +0 -162
- data/src/ruby/nodes/assign.js +0 -47
- data/src/ruby/nodes/blocks.js +0 -90
- data/src/ruby/nodes/calls.js +0 -246
- data/src/ruby/nodes/case.js +0 -65
- data/src/ruby/nodes/class.js +0 -64
- data/src/ruby/nodes/commands.js +0 -131
- data/src/ruby/nodes/conditionals.js +0 -282
- data/src/ruby/nodes/constants.js +0 -43
- data/src/ruby/nodes/flow.js +0 -74
- data/src/ruby/nodes/hashes.js +0 -155
- data/src/ruby/nodes/heredocs.js +0 -36
- data/src/ruby/nodes/hooks.js +0 -34
- data/src/ruby/nodes/ints.js +0 -31
- data/src/ruby/nodes/lambdas.js +0 -76
- data/src/ruby/nodes/loops.js +0 -98
- data/src/ruby/nodes/massign.js +0 -98
- data/src/ruby/nodes/methods.js +0 -74
- data/src/ruby/nodes/operators.js +0 -83
- data/src/ruby/nodes/params.js +0 -106
- data/src/ruby/nodes/patterns.js +0 -157
- data/src/ruby/nodes/regexp.js +0 -56
- data/src/ruby/nodes/rescue.js +0 -101
- data/src/ruby/nodes/return.js +0 -94
- data/src/ruby/nodes/statements.js +0 -142
- data/src/ruby/nodes/strings.js +0 -272
- data/src/ruby/nodes/super.js +0 -35
- data/src/ruby/nodes/undef.js +0 -42
- data/src/ruby/nodes.js +0 -34
- data/src/ruby/parser.js +0 -37
- data/src/ruby/printer.js +0 -147
- data/src/ruby/toProc.js +0 -105
- data/src/utils/containsAssignment.js +0 -11
- data/src/utils/getTrailingComma.js +0 -5
- data/src/utils/hasAncestor.js +0 -17
- data/src/utils/isEmptyBodyStmt.js +0 -7
- data/src/utils/isEmptyStmts.js +0 -11
- data/src/utils/literal.js +0 -7
- data/src/utils/literallineWithoutBreakParent.js +0 -7
- data/src/utils/makeCall.js +0 -14
- data/src/utils/noIndent.js +0 -10
- data/src/utils/printEmptyCollection.js +0 -49
- data/src/utils/skipAssignIndent.js +0 -17
- data/src/utils.js +0 -13
data/src/haml/parser.js
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
const parseSync = require("../parser/parseSync");
|
2
|
-
|
3
|
-
function parse(text, _parsers, opts) {
|
4
|
-
return parseSync("haml", text, opts);
|
5
|
-
}
|
6
|
-
|
7
|
-
function hasPragma(text) {
|
8
|
-
return /^\s*-#\s*@(prettier|format)/.test(text);
|
9
|
-
}
|
10
|
-
|
11
|
-
// These functions are just placeholders until we can actually perform this
|
12
|
-
// properly. The functions are necessary otherwise the format with cursor
|
13
|
-
// functions break.
|
14
|
-
const locStart = (_node) => 0;
|
15
|
-
const locEnd = (_node) => 0;
|
16
|
-
|
17
|
-
module.exports = {
|
18
|
-
parse,
|
19
|
-
astFormat: "haml",
|
20
|
-
hasPragma,
|
21
|
-
locStart,
|
22
|
-
locEnd
|
23
|
-
};
|
data/src/haml/printer.js
DELETED
@@ -1,438 +0,0 @@
|
|
1
|
-
const {
|
2
|
-
align,
|
3
|
-
concat,
|
4
|
-
fill,
|
5
|
-
group,
|
6
|
-
hardline,
|
7
|
-
ifBreak,
|
8
|
-
indent,
|
9
|
-
join,
|
10
|
-
line,
|
11
|
-
softline
|
12
|
-
} = require("../prettier");
|
13
|
-
const embed = require("./embed");
|
14
|
-
|
15
|
-
const docTypes = {
|
16
|
-
basic: "Basic",
|
17
|
-
frameset: "Frameset",
|
18
|
-
mobile: "Mobile",
|
19
|
-
rdfa: "RDFa",
|
20
|
-
strict: "Strict",
|
21
|
-
xml: "XML"
|
22
|
-
};
|
23
|
-
|
24
|
-
const docVersions = ["1.1", "5"];
|
25
|
-
|
26
|
-
// Prints out a hash key according to the configured prettier options.
|
27
|
-
function printHashKey(key, opts) {
|
28
|
-
let quoted = key;
|
29
|
-
const joiner = opts.rubyHashLabel ? ":" : " =>";
|
30
|
-
|
31
|
-
if (key.includes(":") || key.includes("-")) {
|
32
|
-
const quote = opts.rubySingleQuote ? "'" : '"';
|
33
|
-
quoted = `${quote}${key}${quote}`;
|
34
|
-
}
|
35
|
-
|
36
|
-
return `${opts.rubyHashLabel ? "" : ":"}${quoted}${joiner}`;
|
37
|
-
}
|
38
|
-
|
39
|
-
// Prints out the value inside of a hash key-value pair according to the
|
40
|
-
// configured prettier options.
|
41
|
-
function printHashValue(value, opts) {
|
42
|
-
if (typeof value !== "string") {
|
43
|
-
return value.toString();
|
44
|
-
}
|
45
|
-
|
46
|
-
// This is a very special syntax created by the parser to let us know that
|
47
|
-
// this should be printed literally instead of as a string.
|
48
|
-
if (value.startsWith("&")) {
|
49
|
-
return value.slice(1);
|
50
|
-
}
|
51
|
-
|
52
|
-
const quote = opts.rubySingleQuote && !value.includes("#{") ? "'" : '"';
|
53
|
-
return `${quote}${value}${quote}`;
|
54
|
-
}
|
55
|
-
|
56
|
-
// This will print an attributes object to a Doc node. It handles nesting on
|
57
|
-
// multiple levels and will print out according to whether or not the version of
|
58
|
-
// HAML being used supports multi-line attributes.
|
59
|
-
function printAttributes(object, opts, level = 0) {
|
60
|
-
if (typeof object !== "object") {
|
61
|
-
return printHashValue(object, opts);
|
62
|
-
}
|
63
|
-
|
64
|
-
const boundary = level === 0 ? softline : line;
|
65
|
-
const parts = Object.keys(object).map((key) =>
|
66
|
-
concat([
|
67
|
-
printHashKey(key, opts),
|
68
|
-
" ",
|
69
|
-
printAttributes(object[key], opts, level + 1)
|
70
|
-
])
|
71
|
-
);
|
72
|
-
|
73
|
-
// If we have support for multi-line attributes laid out like a regular hash,
|
74
|
-
// then we print them that way here.
|
75
|
-
if (opts.supportsMultiline) {
|
76
|
-
return group(
|
77
|
-
concat([
|
78
|
-
"{",
|
79
|
-
indent(group(concat([boundary, join(concat([",", line]), parts)]))),
|
80
|
-
boundary,
|
81
|
-
"}"
|
82
|
-
])
|
83
|
-
);
|
84
|
-
}
|
85
|
-
|
86
|
-
// Otherwise, if we only have one attribute, then just print it inline
|
87
|
-
// regardless of how long it is.
|
88
|
-
if (parts.length === 0) {
|
89
|
-
return group(concat(["{", parts[0], "}"]));
|
90
|
-
}
|
91
|
-
|
92
|
-
// Otherwise, depending on how long the line is it will split the content into
|
93
|
-
// multi-line attributes that old Haml understands.
|
94
|
-
return group(
|
95
|
-
concat([
|
96
|
-
"{",
|
97
|
-
parts[0],
|
98
|
-
",",
|
99
|
-
align(
|
100
|
-
opts.headerLength + 1,
|
101
|
-
concat([line, join(concat([",", line]), parts.slice(1))])
|
102
|
-
),
|
103
|
-
"}"
|
104
|
-
])
|
105
|
-
);
|
106
|
-
}
|
107
|
-
|
108
|
-
// A utility function used in a silent script that is meant to determine if a
|
109
|
-
// child node is a continuation of a parent node (as in a when clause within a
|
110
|
-
// case statement or an else clause within an if).
|
111
|
-
function isContinuation(parentNode, childNode) {
|
112
|
-
if (childNode.type !== "silent_script") {
|
113
|
-
return false;
|
114
|
-
}
|
115
|
-
|
116
|
-
const parent = parentNode.value.keyword;
|
117
|
-
const child = childNode.value.keyword;
|
118
|
-
|
119
|
-
return (
|
120
|
-
(parent === "case" && ["when", "else"].includes(child)) ||
|
121
|
-
(["if", "unless"].includes(parent) && ["elsif", "else"].includes(child))
|
122
|
-
);
|
123
|
-
}
|
124
|
-
|
125
|
-
// This is our printer's main print function that will switch on the type of
|
126
|
-
// node and print it out by returning a Doc tree.
|
127
|
-
function printNode(path, opts, print) {
|
128
|
-
const node = path.getValue();
|
129
|
-
const { value } = node;
|
130
|
-
|
131
|
-
switch (node.type) {
|
132
|
-
case "comment":
|
133
|
-
return printComment();
|
134
|
-
case "doctype":
|
135
|
-
return printDoctype();
|
136
|
-
case "filter":
|
137
|
-
return printFilter();
|
138
|
-
case "haml_comment":
|
139
|
-
return printHamlComment();
|
140
|
-
case "plain":
|
141
|
-
return printPlain();
|
142
|
-
case "root":
|
143
|
-
return printRoot();
|
144
|
-
case "script":
|
145
|
-
return printScript();
|
146
|
-
case "silent_script":
|
147
|
-
return printSilentScript();
|
148
|
-
case "tag":
|
149
|
-
return printTag();
|
150
|
-
default:
|
151
|
-
throw new Error(`Unsupported node encountered: ${node.type}`);
|
152
|
-
}
|
153
|
-
|
154
|
-
// It's common to a couple of nodes to attach nested child nodes on the
|
155
|
-
// children property. This utility prints them out grouped together with their
|
156
|
-
// parent node docs.
|
157
|
-
function printWithChildren(docs) {
|
158
|
-
if (node.children.length === 0) {
|
159
|
-
return docs;
|
160
|
-
}
|
161
|
-
|
162
|
-
return group(
|
163
|
-
concat([
|
164
|
-
docs,
|
165
|
-
indent(concat([hardline, join(hardline, path.map(print, "children"))]))
|
166
|
-
])
|
167
|
-
);
|
168
|
-
}
|
169
|
-
|
170
|
-
// https://haml.info/docs/yardoc/file.REFERENCE.html#html-comments-
|
171
|
-
function printComment() {
|
172
|
-
const parts = ["/"];
|
173
|
-
|
174
|
-
if (value.revealed) {
|
175
|
-
parts.push("!");
|
176
|
-
}
|
177
|
-
|
178
|
-
if (value.conditional) {
|
179
|
-
parts.push(value.conditional);
|
180
|
-
} else if (value.text) {
|
181
|
-
parts.push(" ", value.text);
|
182
|
-
}
|
183
|
-
|
184
|
-
return printWithChildren(group(concat(parts)));
|
185
|
-
}
|
186
|
-
|
187
|
-
// https://haml.info/docs/yardoc/file.REFERENCE.html#doctype-
|
188
|
-
function printDoctype() {
|
189
|
-
const parts = ["!!!"];
|
190
|
-
|
191
|
-
if (value.type in docTypes) {
|
192
|
-
parts.push(docTypes[value.type]);
|
193
|
-
} else if (docVersions.includes(value.version)) {
|
194
|
-
parts.push(value.version);
|
195
|
-
} else {
|
196
|
-
parts.push(value.type);
|
197
|
-
}
|
198
|
-
|
199
|
-
if (value.encoding) {
|
200
|
-
parts.push(value.encoding);
|
201
|
-
}
|
202
|
-
|
203
|
-
return group(join(" ", parts));
|
204
|
-
}
|
205
|
-
|
206
|
-
// https://haml.info/docs/yardoc/file.REFERENCE.html#filters
|
207
|
-
function printFilter() {
|
208
|
-
return group(
|
209
|
-
concat([
|
210
|
-
":",
|
211
|
-
value.name,
|
212
|
-
indent(
|
213
|
-
concat([hardline, join(hardline, value.text.trim().split("\n"))])
|
214
|
-
)
|
215
|
-
])
|
216
|
-
);
|
217
|
-
}
|
218
|
-
|
219
|
-
// https://haml.info/docs/yardoc/file.REFERENCE.html#haml-comments--
|
220
|
-
function printHamlComment() {
|
221
|
-
const parts = ["-#"];
|
222
|
-
|
223
|
-
if (value.text) {
|
224
|
-
if (opts.originalText.split("\n")[node.line - 1].trim() === "-#") {
|
225
|
-
const lines = value.text.trim().split("\n");
|
226
|
-
|
227
|
-
parts.push(indent(concat([hardline, join(hardline, lines)])));
|
228
|
-
} else {
|
229
|
-
parts.push(" ", value.text.trim());
|
230
|
-
}
|
231
|
-
}
|
232
|
-
|
233
|
-
return concat(parts);
|
234
|
-
}
|
235
|
-
|
236
|
-
// https://haml.info/docs/yardoc/file.REFERENCE.html#plain-text
|
237
|
-
function printPlain() {
|
238
|
-
return value.text;
|
239
|
-
}
|
240
|
-
|
241
|
-
// The root node in the AST that we build in the parser.
|
242
|
-
function printRoot() {
|
243
|
-
return concat([join(hardline, path.map(print, "children")), hardline]);
|
244
|
-
}
|
245
|
-
|
246
|
-
// https://haml.info/docs/yardoc/file.REFERENCE.html#inserting_ruby
|
247
|
-
function printScript() {
|
248
|
-
const parts = [];
|
249
|
-
|
250
|
-
if (value.escape_html) {
|
251
|
-
parts.unshift("&");
|
252
|
-
}
|
253
|
-
|
254
|
-
if (value.preserve) {
|
255
|
-
parts.push("~");
|
256
|
-
} else if (!value.interpolate) {
|
257
|
-
parts.push("=");
|
258
|
-
}
|
259
|
-
|
260
|
-
if (value.escape_html && !value.preserve && value.interpolate) {
|
261
|
-
parts.push(" ", value.text.trim().slice(1, -1));
|
262
|
-
} else {
|
263
|
-
parts.push(" ", value.text.trim());
|
264
|
-
}
|
265
|
-
|
266
|
-
return printWithChildren(group(concat(parts)));
|
267
|
-
}
|
268
|
-
|
269
|
-
// https://haml.info/docs/yardoc/file.REFERENCE.html#running-ruby--
|
270
|
-
function printSilentScript() {
|
271
|
-
const parts = [`- ${value.text.trim()}`];
|
272
|
-
|
273
|
-
if (node.children.length > 0) {
|
274
|
-
parts.push(
|
275
|
-
concat(
|
276
|
-
path.map((childPath) => {
|
277
|
-
const child = childPath.getValue();
|
278
|
-
const concated = concat([hardline, print(childPath)]);
|
279
|
-
|
280
|
-
return isContinuation(node, child) ? concated : indent(concated);
|
281
|
-
}, "children")
|
282
|
-
)
|
283
|
-
);
|
284
|
-
}
|
285
|
-
|
286
|
-
return group(concat(parts));
|
287
|
-
}
|
288
|
-
|
289
|
-
// https://haml.info/docs/yardoc/file.REFERENCE.html#element-name-
|
290
|
-
function printTag() {
|
291
|
-
const { attributes, dynamic_attributes } = value;
|
292
|
-
const parts = [];
|
293
|
-
|
294
|
-
// If we have a tag that isn't a div, then we need to print out that name of
|
295
|
-
// that tag first. If it is a div, first we'll check if there are any other
|
296
|
-
// things that would force us to print out the div explicitly, and otherwise
|
297
|
-
// we'll leave it off.
|
298
|
-
if (value.name !== "div") {
|
299
|
-
parts.push(`%${value.name}`);
|
300
|
-
}
|
301
|
-
|
302
|
-
// If we have a class attribute, then we're going to print that here using
|
303
|
-
// the special class syntax.
|
304
|
-
if (attributes.class) {
|
305
|
-
parts.push(`.${attributes.class.replace(/ /g, ".")}`);
|
306
|
-
}
|
307
|
-
|
308
|
-
// If we have an id attribute, then we're going to print that here using the
|
309
|
-
// special id syntax.
|
310
|
-
if (attributes.id) {
|
311
|
-
parts.push(`#${attributes.id}`);
|
312
|
-
}
|
313
|
-
|
314
|
-
// If we're using dynamic attributes on this tag, then they come in as a
|
315
|
-
// string that looks like the output of Hash#inspect from Ruby. So here
|
316
|
-
// we're going to split it all up and print it out nicely.
|
317
|
-
if (dynamic_attributes.new) {
|
318
|
-
const pairs = dynamic_attributes.new
|
319
|
-
.slice(1, -2)
|
320
|
-
.split(",")
|
321
|
-
.map((pair) => join("=", pair.slice(1).split('" => ')));
|
322
|
-
|
323
|
-
parts.push(
|
324
|
-
group(
|
325
|
-
concat([
|
326
|
-
"(",
|
327
|
-
align(parts.join("").length + 1, fill(join(line, pairs).parts)),
|
328
|
-
")"
|
329
|
-
])
|
330
|
-
)
|
331
|
-
);
|
332
|
-
}
|
333
|
-
|
334
|
-
// If there are any static attributes that are not class or id (because we
|
335
|
-
// already took care of those), then we're going to print them out here.
|
336
|
-
const staticAttributes = Object.keys(attributes).filter(
|
337
|
-
(name) => !["class", "id"].includes(name)
|
338
|
-
);
|
339
|
-
|
340
|
-
if (staticAttributes.length > 0) {
|
341
|
-
const docs = staticAttributes.reduce((accum, key) => {
|
342
|
-
const doc = `${printHashKey(key, opts)} ${printHashValue(
|
343
|
-
attributes[key],
|
344
|
-
opts
|
345
|
-
)}`;
|
346
|
-
|
347
|
-
return accum.length === 0 ? [doc] : accum.concat(",", line, doc);
|
348
|
-
}, []);
|
349
|
-
|
350
|
-
parts.push(
|
351
|
-
group(concat(["{", align(parts.join("").length + 1, fill(docs)), "}"]))
|
352
|
-
);
|
353
|
-
}
|
354
|
-
|
355
|
-
// If there are dynamic attributes that don't use the newer syntax, then
|
356
|
-
// we're going to print them out here.
|
357
|
-
if (dynamic_attributes.old) {
|
358
|
-
if (parts.length === 0) {
|
359
|
-
parts.push("%div");
|
360
|
-
}
|
361
|
-
|
362
|
-
if (typeof dynamic_attributes.old === "string") {
|
363
|
-
parts.push(dynamic_attributes.old);
|
364
|
-
} else {
|
365
|
-
const attrOptions = {
|
366
|
-
// This is kind of a total hack in that I don't think you're really
|
367
|
-
// supposed to directly use `path.stack`, but it's the easiest way to
|
368
|
-
// get the root node without having to know how many levels deep we
|
369
|
-
// are.
|
370
|
-
supportsMultiline: path.stack[0].supports_multiline,
|
371
|
-
headerLength: parts.join("").length
|
372
|
-
};
|
373
|
-
|
374
|
-
parts.push(
|
375
|
-
printAttributes(
|
376
|
-
dynamic_attributes.old,
|
377
|
-
Object.assign({}, opts, attrOptions)
|
378
|
-
)
|
379
|
-
);
|
380
|
-
}
|
381
|
-
}
|
382
|
-
|
383
|
-
// https://haml.info/docs/yardoc/file.REFERENCE.html#object-reference-
|
384
|
-
if (value.object_ref) {
|
385
|
-
if (parts.length === 0) {
|
386
|
-
parts.push("%div");
|
387
|
-
}
|
388
|
-
parts.push(value.object_ref);
|
389
|
-
}
|
390
|
-
|
391
|
-
// https://haml.info/docs/yardoc/file.REFERENCE.html#whitespace-removal--and-
|
392
|
-
if (value.nuke_outer_whitespace) {
|
393
|
-
parts.push(">");
|
394
|
-
}
|
395
|
-
|
396
|
-
if (value.nuke_inner_whitespace) {
|
397
|
-
parts.push("<");
|
398
|
-
}
|
399
|
-
|
400
|
-
// https://haml.info/docs/yardoc/file.REFERENCE.html#empty-void-tags-
|
401
|
-
if (value.self_closing) {
|
402
|
-
parts.push("/");
|
403
|
-
}
|
404
|
-
|
405
|
-
if (value.value) {
|
406
|
-
const prefix = value.parse ? "= " : ifBreak("", " ");
|
407
|
-
|
408
|
-
return printWithChildren(
|
409
|
-
group(
|
410
|
-
concat([
|
411
|
-
group(concat(parts)),
|
412
|
-
indent(concat([softline, prefix, value.value]))
|
413
|
-
])
|
414
|
-
)
|
415
|
-
);
|
416
|
-
}
|
417
|
-
|
418
|
-
// In case none of the other if statements have matched and we're printing
|
419
|
-
// a div, we need to explicitly add it back into the array.
|
420
|
-
if (parts.length === 0 && value.name === "div") {
|
421
|
-
parts.push("%div");
|
422
|
-
}
|
423
|
-
|
424
|
-
return printWithChildren(group(concat(parts)));
|
425
|
-
}
|
426
|
-
}
|
427
|
-
|
428
|
-
// This function handles adding the format pragma to a source string. This is an
|
429
|
-
// optional workflow for incremental adoption.
|
430
|
-
function insertPragma(text) {
|
431
|
-
return `-# @format${text.startsWith("-#") ? "\n" : "\n\n"}${text}`;
|
432
|
-
}
|
433
|
-
|
434
|
-
module.exports = {
|
435
|
-
embed,
|
436
|
-
print: printNode,
|
437
|
-
insertPragma
|
438
|
-
};
|
data/src/parser/parseSync.js
DELETED
@@ -1,172 +0,0 @@
|
|
1
|
-
const { spawn, spawnSync, execSync } = require("child_process");
|
2
|
-
const { existsSync, mkdtempSync } = require("fs");
|
3
|
-
const os = require("os");
|
4
|
-
const path = require("path");
|
5
|
-
const process = require("process");
|
6
|
-
|
7
|
-
let sockfile = process.env.PRETTIER_RUBY_HOST;
|
8
|
-
let netcat;
|
9
|
-
|
10
|
-
// In order to properly parse ruby code, we need to tell the ruby process to
|
11
|
-
// parse using UTF-8. Unfortunately, the way that you accomplish this looks
|
12
|
-
// differently depending on your platform.
|
13
|
-
/* istanbul ignore next */
|
14
|
-
function getLang() {
|
15
|
-
const { env, platform } = process;
|
16
|
-
const envValue = env.LC_ALL || env.LC_CTYPE || env.LANG;
|
17
|
-
|
18
|
-
// If an env var is set for the locale that already includes UTF-8 in the
|
19
|
-
// name, then assume we can go with that.
|
20
|
-
if (envValue && envValue.includes("UTF-8")) {
|
21
|
-
return envValue;
|
22
|
-
}
|
23
|
-
|
24
|
-
// Otherwise, we're going to guess which encoding to use based on the system.
|
25
|
-
// This is probably not the best approach in the world, as you could be on
|
26
|
-
// linux and not have C.UTF-8, but in that case you're probably passing an env
|
27
|
-
// var for it. This object below represents all of the possible values of
|
28
|
-
// process.platform per:
|
29
|
-
// https://nodejs.org/api/process.html#process_process_platform
|
30
|
-
return {
|
31
|
-
aix: "C.UTF-8",
|
32
|
-
darwin: "en_US.UTF-8",
|
33
|
-
freebsd: "C.UTF-8",
|
34
|
-
linux: "C.UTF-8",
|
35
|
-
openbsd: "C.UTF-8",
|
36
|
-
sunos: "C.UTF-8",
|
37
|
-
win32: ".UTF-8"
|
38
|
-
}[platform];
|
39
|
-
}
|
40
|
-
|
41
|
-
// Spawn the parser.rb subprocess. We do this since booting Ruby is slow, and we
|
42
|
-
// can re-use the parser process multiple times since it is statelesss.
|
43
|
-
function spawnParseServer() {
|
44
|
-
const tmpDir = mkdtempSync(path.join(os.tmpdir(), "prettier-ruby"));
|
45
|
-
const tmpFile = path.join(tmpDir, `${process.pid}.sock`);
|
46
|
-
|
47
|
-
const server = spawn("ruby", [path.join(__dirname, "./server.rb"), tmpFile], {
|
48
|
-
env: Object.assign({}, process.env, { LANG: getLang() }),
|
49
|
-
detached: true,
|
50
|
-
stdio: "inherit"
|
51
|
-
});
|
52
|
-
|
53
|
-
process.on("exit", () => {
|
54
|
-
try {
|
55
|
-
process.kill(-server.pid);
|
56
|
-
} catch (e) {
|
57
|
-
// ignore
|
58
|
-
}
|
59
|
-
});
|
60
|
-
|
61
|
-
server.unref();
|
62
|
-
const now = new Date();
|
63
|
-
|
64
|
-
// Wait for server to go live.
|
65
|
-
while (!existsSync(tmpFile) && new Date() - now < 3000) {
|
66
|
-
execSync("sleep 0.1");
|
67
|
-
}
|
68
|
-
|
69
|
-
return tmpFile;
|
70
|
-
}
|
71
|
-
|
72
|
-
// Checks to see if an executable is available.
|
73
|
-
function hasCommand(name) {
|
74
|
-
let result;
|
75
|
-
|
76
|
-
if (os.type() === "Windows_NT") {
|
77
|
-
result = spawnSync("where", [name]);
|
78
|
-
} else {
|
79
|
-
result = spawnSync("command", ["-v", name]);
|
80
|
-
}
|
81
|
-
|
82
|
-
return result.status === 0;
|
83
|
-
}
|
84
|
-
|
85
|
-
// Finds a netcat-like adapter to use for sending data to a socket. We order
|
86
|
-
// these by likelihood of being found so we can avoid some shell-outs.
|
87
|
-
function findNetcat(opts) {
|
88
|
-
if (opts.rubyNetcatCommand) {
|
89
|
-
const splits = opts.rubyNetcatCommand.split(" ");
|
90
|
-
return { command: splits[0], args: splits.slice(1) };
|
91
|
-
}
|
92
|
-
|
93
|
-
if (hasCommand("nc")) {
|
94
|
-
return { command: "nc", args: ["-U"] };
|
95
|
-
}
|
96
|
-
|
97
|
-
if (hasCommand("telnet")) {
|
98
|
-
return { command: "telnet", args: ["-u"] };
|
99
|
-
}
|
100
|
-
|
101
|
-
if (hasCommand("ncat")) {
|
102
|
-
return { command: "ncat", args: ["-U"] };
|
103
|
-
}
|
104
|
-
|
105
|
-
if (hasCommand("socat")) {
|
106
|
-
return { command: "socat", args: ["-"] };
|
107
|
-
}
|
108
|
-
|
109
|
-
return { command: "node", args: [require.resolve("./netcat.js")] };
|
110
|
-
}
|
111
|
-
|
112
|
-
// Formats and sends a request to the parser server. We use netcat (or something
|
113
|
-
// like it) here since Prettier requires the results of `parse` to be
|
114
|
-
// synchronous and Node.js does not offer a mechanism for synchronous socket
|
115
|
-
// requests.
|
116
|
-
function parseSync(parser, source, opts) {
|
117
|
-
if (!sockfile) {
|
118
|
-
sockfile = spawnParseServer();
|
119
|
-
}
|
120
|
-
|
121
|
-
if (!netcat) {
|
122
|
-
netcat = findNetcat(opts);
|
123
|
-
}
|
124
|
-
|
125
|
-
const response = spawnSync(netcat.command, netcat.args.concat(sockfile), {
|
126
|
-
input: `${parser}|${source}`,
|
127
|
-
maxBuffer: 15 * 1024 * 1024
|
128
|
-
});
|
129
|
-
|
130
|
-
const stdout = response.stdout.toString();
|
131
|
-
const stderr = response.stderr.toString();
|
132
|
-
const { status } = response;
|
133
|
-
|
134
|
-
// We need special handling in case the user's version of nc doesn't support
|
135
|
-
// using unix sockets.
|
136
|
-
if (
|
137
|
-
stderr.includes("invalid option -- U") ||
|
138
|
-
stderr.includes("invalid option -- 'u'") ||
|
139
|
-
stderr.includes("Protocol not supported")
|
140
|
-
) {
|
141
|
-
throw new Error(`
|
142
|
-
@prettier/plugin-ruby uses unix sockets to communicate between the node.js
|
143
|
-
process running prettier and an underlying Ruby process used for parsing.
|
144
|
-
Unfortunately the command that it tried to use to do that
|
145
|
-
(${netcat.command}) does not support unix sockets. To solve this either
|
146
|
-
uninstall the version of ${netcat.command} that you're using and use a
|
147
|
-
different implementation, or change the value of the rubyNetcatCommand
|
148
|
-
option in your prettier configuration.
|
149
|
-
`);
|
150
|
-
}
|
151
|
-
|
152
|
-
// If we didn't receive anything over stdout or we have a bad exit status,
|
153
|
-
// then throw whatever we can.
|
154
|
-
if (stdout.length === 0 || (status !== null && status !== 0)) {
|
155
|
-
throw new Error(stderr || "An unknown error occurred");
|
156
|
-
}
|
157
|
-
|
158
|
-
const parsed = JSON.parse(stdout);
|
159
|
-
|
160
|
-
if (parsed.error) {
|
161
|
-
const error = new Error(parsed.error);
|
162
|
-
if (parsed.loc) {
|
163
|
-
error.loc = parsed.loc;
|
164
|
-
}
|
165
|
-
|
166
|
-
throw error;
|
167
|
-
}
|
168
|
-
|
169
|
-
return parsed;
|
170
|
-
}
|
171
|
-
|
172
|
-
module.exports = parseSync;
|
data/src/parser/server.rb
DELETED
@@ -1,66 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'bundler/setup' if ENV['PLUGIN_RUBY_CI']
|
4
|
-
require 'socket'
|
5
|
-
require 'json'
|
6
|
-
|
7
|
-
require_relative '../ruby/parser'
|
8
|
-
require_relative '../rbs/parser'
|
9
|
-
require_relative '../haml/parser'
|
10
|
-
|
11
|
-
# Set the program name so that it's easy to find if we need it
|
12
|
-
$PROGRAM_NAME = 'prettier-ruby-parser'
|
13
|
-
|
14
|
-
# Make sure we trap these signals to be sure we get the quit command coming from
|
15
|
-
# the parent node process
|
16
|
-
quit = false
|
17
|
-
trap(:QUIT) { quit = true } if RUBY_PLATFORM != 'java'
|
18
|
-
trap(:INT) { quit = true }
|
19
|
-
trap(:TERM) { quit = true }
|
20
|
-
|
21
|
-
sockfile = ARGV.first || "/tmp/#{$PROGRAM_NAME}.sock"
|
22
|
-
server = UNIXServer.new(sockfile)
|
23
|
-
|
24
|
-
at_exit do
|
25
|
-
server.close
|
26
|
-
File.unlink(sockfile)
|
27
|
-
end
|
28
|
-
|
29
|
-
loop do
|
30
|
-
break if quit
|
31
|
-
|
32
|
-
# Start up a new thread that will handle each successive connection.
|
33
|
-
Thread.new(server.accept_nonblock) do |socket|
|
34
|
-
parser, source = socket.read.force_encoding('UTF-8').split('|', 2)
|
35
|
-
|
36
|
-
response =
|
37
|
-
case parser
|
38
|
-
when 'ruby'
|
39
|
-
Prettier::Parser.parse(source)
|
40
|
-
when 'rbs'
|
41
|
-
Prettier::RBSParser.parse(source)
|
42
|
-
when 'haml'
|
43
|
-
Prettier::HAMLParser.parse(source)
|
44
|
-
end
|
45
|
-
|
46
|
-
if response
|
47
|
-
socket.write(JSON.fast_generate(response))
|
48
|
-
else
|
49
|
-
socket.write('{ "error": true }')
|
50
|
-
end
|
51
|
-
rescue Prettier::Parser::ParserError => error
|
52
|
-
loc = { start: { line: error.lineno, column: error.column } }
|
53
|
-
socket.write(JSON.fast_generate(error: error.message, loc: loc))
|
54
|
-
rescue StandardError => error
|
55
|
-
socket.write(JSON.fast_generate(error: error.message))
|
56
|
-
ensure
|
57
|
-
socket.close
|
58
|
-
end
|
59
|
-
rescue IO::WaitReadable, Errno::EINTR
|
60
|
-
# Wait for select(2) to give us a connection that has content for 1 second.
|
61
|
-
# Otherwise timeout and continue on (so that we hit our "break if quit"
|
62
|
-
# pretty often).
|
63
|
-
IO.select([server], nil, nil, 1)
|
64
|
-
|
65
|
-
retry unless quit
|
66
|
-
end
|