prettier 1.5.1 → 1.6.0

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.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +55 -2
  3. data/CONTRIBUTING.md +2 -2
  4. data/README.md +41 -12
  5. data/node_modules/prettier/bin-prettier.js +13702 -11629
  6. data/node_modules/prettier/index.js +19191 -16565
  7. data/node_modules/prettier/parser-angular.js +67 -0
  8. data/node_modules/prettier/parser-babel.js +22 -0
  9. data/node_modules/prettier/parser-espree.js +22 -0
  10. data/node_modules/prettier/parser-flow.js +22 -0
  11. data/node_modules/prettier/parser-glimmer.js +1 -0
  12. data/node_modules/prettier/parser-graphql.js +1 -0
  13. data/node_modules/prettier/parser-html.js +132 -0
  14. data/node_modules/prettier/parser-markdown.js +34 -0
  15. data/node_modules/prettier/parser-meriyah.js +22 -0
  16. data/node_modules/prettier/parser-postcss.js +22 -0
  17. data/node_modules/prettier/parser-typescript.js +22 -0
  18. data/node_modules/prettier/parser-yaml.js +15 -0
  19. data/node_modules/prettier/third-party.js +1042 -833
  20. data/package.json +5 -5
  21. data/rubocop.yml +12 -0
  22. data/src/haml/parser.js +6 -5
  23. data/src/haml/parser.rb +8 -3
  24. data/src/haml/printer.js +428 -18
  25. data/src/parser/netcat.js +0 -2
  26. data/src/parser/parseSync.js +153 -14
  27. data/src/parser/server.rb +7 -2
  28. data/src/plugin.js +7 -1
  29. data/src/rbs/parser.js +3 -5
  30. data/src/rbs/parser.rb +7 -3
  31. data/src/rbs/printer.js +46 -8
  32. data/src/ruby/embed.js +7 -5
  33. data/src/ruby/nodes/args.js +111 -19
  34. data/src/ruby/nodes/calls.js +8 -1
  35. data/src/ruby/nodes/conditionals.js +47 -45
  36. data/src/ruby/nodes/hashes.js +5 -14
  37. data/src/ruby/nodes/heredocs.js +5 -3
  38. data/src/ruby/nodes/params.js +2 -9
  39. data/src/ruby/nodes/strings.js +95 -2
  40. data/src/ruby/parser.js +3 -5
  41. data/src/ruby/parser.rb +82 -31
  42. data/src/ruby/printer.js +10 -1
  43. data/src/utils.js +1 -1
  44. data/src/utils/inlineEnsureParens.js +1 -0
  45. data/src/utils/literallineWithoutBreakParent.js +7 -0
  46. data/src/utils/skipAssignIndent.js +8 -1
  47. metadata +15 -15
  48. data/src/haml/nodes/comment.js +0 -27
  49. data/src/haml/nodes/doctype.js +0 -34
  50. data/src/haml/nodes/filter.js +0 -16
  51. data/src/haml/nodes/hamlComment.js +0 -21
  52. data/src/haml/nodes/plain.js +0 -6
  53. data/src/haml/nodes/root.js +0 -8
  54. data/src/haml/nodes/script.js +0 -33
  55. data/src/haml/nodes/silentScript.js +0 -59
  56. data/src/haml/nodes/tag.js +0 -193
  57. data/src/parser/getLang.js +0 -32
  58. data/src/parser/getNetcat.js +0 -50
  59. data/src/parser/requestParse.js +0 -74
  60. data/src/utils/literalLineNoBreak.js +0 -7
data/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@prettier/plugin-ruby",
3
- "version": "1.5.1",
3
+ "version": "1.6.0",
4
4
  "description": "prettier plugin for the Ruby programming language",
5
5
  "main": "src/plugin.js",
6
6
  "scripts": {
@@ -22,10 +22,10 @@
22
22
  "prettier": ">=1.10"
23
23
  },
24
24
  "devDependencies": {
25
- "eslint": "^7.8.1",
26
- "eslint-config-prettier": "^7.0.0",
27
- "husky": "^4.3.5",
28
- "jest": "^26.0.0",
25
+ "eslint": "^7.22.0",
26
+ "eslint-config-prettier": "^8.0.0",
27
+ "husky": "^6.0.0",
28
+ "jest": "^27.0.1",
29
29
  "pretty-quick": "^3.1.0"
30
30
  },
31
31
  "eslintConfig": {
data/rubocop.yml CHANGED
@@ -4,6 +4,15 @@
4
4
  Layout:
5
5
  Enabled: false
6
6
 
7
+ # Re-enable Layout/LineLength because certain cops that most projects use
8
+ # (e.g. Style/IfUnlessModifier) require Layout/LineLength to be enabled.
9
+ # By leaving it disabled, those rules will mis-fire.
10
+ #
11
+ # Users can always override these defaults in their own rubocop.yml files.
12
+ # https://github.com/prettier/plugin-ruby/issues/825
13
+ Layout/LineLength:
14
+ Enabled: true
15
+
7
16
  # Disabling all of the following options because they could conflict with a
8
17
  # prettier configuration setting.
9
18
 
@@ -24,3 +33,6 @@ Style/TrailingCommaInArrayLiteral: # trailingComma
24
33
 
25
34
  Style/TrailingCommaInHashLiteral: # trailingComma
26
35
  Enabled: false
36
+
37
+ Style/Lambda:
38
+ Enabled: false
data/src/haml/parser.js CHANGED
@@ -1,11 +1,12 @@
1
1
  const parseSync = require("../parser/parseSync");
2
2
 
3
- const parse = (text, _parsers, _opts) => {
4
- return parseSync("haml", text);
5
- };
3
+ function parse(text, _parsers, opts) {
4
+ return parseSync("haml", text, opts);
5
+ }
6
6
 
7
- const pragmaPattern = /^\s*-#\s*@(prettier|format)/;
8
- const hasPragma = (text) => pragmaPattern.test(text);
7
+ function hasPragma(text) {
8
+ return /^\s*-#\s*@(prettier|format)/.test(text);
9
+ }
9
10
 
10
11
  // These functions are just placeholders until we can actually perform this
11
12
  // properly. The functions are necessary otherwise the format with cursor
data/src/haml/parser.rb CHANGED
@@ -86,7 +86,14 @@ class Haml::Parser::ParseNode
86
86
  json[:value][:text] = "\\#{text}" if text.match?(SPECIAL_START)
87
87
  end
88
88
  when :root
89
- to_h.tap { |json| json[:children] = children.map(&:as_json) }
89
+ to_h.tap do |json|
90
+ json[:children] = children.map(&:as_json)
91
+
92
+ # We need this information in the printer to know how to lay out
93
+ # multi-line attributes.
94
+ json[:supports_multiline] =
95
+ Gem::Version.new(Haml::VERSION) >= Gem::Version.new('5.2')
96
+ end
90
97
  when :script
91
98
  to_h.tap do |json|
92
99
  json.delete(:parent)
@@ -131,8 +138,6 @@ module Prettier
131
138
  class HAMLParser
132
139
  def self.parse(source)
133
140
  Haml::Parser.new({}).call(source).as_json
134
- rescue StandardError
135
- false
136
141
  end
137
142
  end
138
143
  end
data/src/haml/printer.js CHANGED
@@ -1,28 +1,438 @@
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");
1
13
  const embed = require("./embed");
2
- const nodes = {
3
- comment: require("./nodes/comment"),
4
- doctype: require("./nodes/doctype"),
5
- filter: require("./nodes/filter"),
6
- haml_comment: require("./nodes/hamlComment"),
7
- plain: require("./nodes/plain"),
8
- root: require("./nodes/root"),
9
- script: require("./nodes/script"),
10
- silent_script: require("./nodes/silentScript"),
11
- tag: require("./nodes/tag")
14
+
15
+ const docTypes = {
16
+ basic: "Basic",
17
+ frameset: "Frameset",
18
+ mobile: "Mobile",
19
+ rdfa: "RDFa",
20
+ strict: "Strict",
21
+ xml: "XML"
12
22
  };
13
23
 
14
- const genericPrint = (path, opts, print) => {
15
- const { type } = path.getValue();
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 ? ":" : " =>";
16
30
 
17
- /* istanbul ignore next */
18
- if (!(type in nodes)) {
19
- throw new Error(`Unsupported node encountered: ${type}`);
31
+ if (key.includes(":") || key.includes("-")) {
32
+ const quote = opts.rubySingleQuote ? "'" : '"';
33
+ quoted = `${quote}${key}${quote}`;
20
34
  }
21
35
 
22
- return nodes[type](path, opts, print);
23
- };
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
+ }
24
433
 
25
434
  module.exports = {
26
435
  embed,
27
- print: genericPrint
436
+ print: printNode,
437
+ insertPragma
28
438
  };