prettier 1.2.1 → 1.3.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 (76) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +61 -1
  3. data/CONTRIBUTING.md +2 -2
  4. data/README.md +21 -91
  5. data/lib/prettier.rb +2 -2
  6. data/node_modules/prettier/index.js +54 -54
  7. data/package.json +3 -4
  8. data/rubocop.yml +26 -0
  9. data/src/haml/embed.js +87 -0
  10. data/src/haml/nodes/comment.js +27 -0
  11. data/src/haml/nodes/doctype.js +34 -0
  12. data/src/haml/nodes/filter.js +16 -0
  13. data/src/haml/nodes/hamlComment.js +21 -0
  14. data/src/haml/nodes/plain.js +6 -0
  15. data/src/haml/nodes/root.js +8 -0
  16. data/src/haml/nodes/script.js +33 -0
  17. data/src/haml/nodes/silentScript.js +59 -0
  18. data/src/haml/nodes/tag.js +193 -0
  19. data/src/haml/parser.js +33 -0
  20. data/src/haml/parser.rb +141 -0
  21. data/src/haml/printer.js +28 -0
  22. data/src/{ruby.js → plugin.js} +25 -4
  23. data/src/prettier.js +1 -0
  24. data/src/rbs/parser.js +51 -0
  25. data/src/rbs/parser.rb +91 -0
  26. data/src/rbs/printer.js +605 -0
  27. data/src/{embed.js → ruby/embed.js} +6 -2
  28. data/src/{nodes.js → ruby/nodes.js} +0 -0
  29. data/src/{nodes → ruby/nodes}/alias.js +1 -1
  30. data/src/{nodes → ruby/nodes}/aref.js +8 -1
  31. data/src/{nodes → ruby/nodes}/args.js +2 -2
  32. data/src/{nodes → ruby/nodes}/arrays.js +2 -3
  33. data/src/{nodes → ruby/nodes}/assign.js +7 -3
  34. data/src/ruby/nodes/blocks.js +90 -0
  35. data/src/{nodes → ruby/nodes}/calls.js +18 -11
  36. data/src/{nodes → ruby/nodes}/case.js +1 -1
  37. data/src/{nodes → ruby/nodes}/class.js +1 -1
  38. data/src/ruby/nodes/commands.js +131 -0
  39. data/src/{nodes → ruby/nodes}/conditionals.js +3 -3
  40. data/src/{nodes → ruby/nodes}/constants.js +2 -2
  41. data/src/{nodes → ruby/nodes}/flow.js +2 -2
  42. data/src/{nodes → ruby/nodes}/hashes.js +32 -10
  43. data/src/{nodes → ruby/nodes}/heredocs.js +2 -2
  44. data/src/ruby/nodes/hooks.js +34 -0
  45. data/src/{nodes → ruby/nodes}/ints.js +0 -0
  46. data/src/{nodes → ruby/nodes}/lambdas.js +2 -2
  47. data/src/{nodes → ruby/nodes}/loops.js +10 -7
  48. data/src/{nodes → ruby/nodes}/massign.js +8 -1
  49. data/src/{nodes → ruby/nodes}/methods.js +10 -9
  50. data/src/{nodes → ruby/nodes}/operators.js +2 -2
  51. data/src/{nodes → ruby/nodes}/params.js +31 -16
  52. data/src/{nodes → ruby/nodes}/patterns.js +17 -6
  53. data/src/{nodes → ruby/nodes}/regexp.js +2 -2
  54. data/src/{nodes → ruby/nodes}/rescue.js +2 -2
  55. data/src/ruby/nodes/return.js +94 -0
  56. data/src/{nodes → ruby/nodes}/statements.js +6 -9
  57. data/src/{nodes → ruby/nodes}/strings.js +27 -36
  58. data/src/{nodes → ruby/nodes}/super.js +2 -2
  59. data/src/{nodes → ruby/nodes}/undef.js +1 -1
  60. data/src/{parser.js → ruby/parser.js} +4 -3
  61. data/src/{parser.rb → ruby/parser.rb} +450 -501
  62. data/src/{printer.js → ruby/printer.js} +33 -1
  63. data/src/{toProc.js → ruby/toProc.js} +4 -8
  64. data/src/utils.js +10 -93
  65. data/src/utils/containsAssignment.js +11 -0
  66. data/src/utils/getTrailingComma.js +5 -0
  67. data/src/utils/hasAncestor.js +17 -0
  68. data/src/utils/literal.js +7 -0
  69. data/src/utils/makeCall.js +14 -0
  70. data/src/utils/noIndent.js +11 -0
  71. data/src/utils/skipAssignIndent.js +10 -0
  72. metadata +65 -41
  73. data/src/nodes/blocks.js +0 -85
  74. data/src/nodes/commands.js +0 -91
  75. data/src/nodes/hooks.js +0 -44
  76. data/src/nodes/return.js +0 -72
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@prettier/plugin-ruby",
3
- "version": "1.2.1",
3
+ "version": "1.3.0",
4
4
  "description": "prettier plugin for the Ruby programming language",
5
- "main": "src/ruby.js",
5
+ "main": "src/plugin.js",
6
6
  "scripts": {
7
7
  "check-format": "prettier --check '**/*'",
8
8
  "lint": "eslint --cache .",
9
- "test": "jest"
9
+ "test": "PORT=$(bin/port) jest"
10
10
  },
11
11
  "repository": {
12
12
  "type": "git",
@@ -22,7 +22,6 @@
22
22
  "prettier": ">=1.10"
23
23
  },
24
24
  "devDependencies": {
25
- "all-contributors-cli": "^6.14.1",
26
25
  "eslint": "^7.8.1",
27
26
  "eslint-config-prettier": "^7.0.0",
28
27
  "husky": "^4.3.5",
@@ -0,0 +1,26 @@
1
+ # Disabling all Layout/* rules, as they're unnecessary when the user is using
2
+ # prettier to handle all of the formatting.
3
+
4
+ Layout:
5
+ Enabled: false
6
+
7
+ # Disabling all of the following options because they could conflict with a
8
+ # prettier configuration setting.
9
+
10
+ Style/MultilineIfModifier: # rubyModifier
11
+ Enabled: false
12
+
13
+ Style/SymbolArray: # rubyArrayLiteral
14
+ Enabled: false
15
+
16
+ Style/WordArray: # rubyArrayLiteral
17
+ Enabled: false
18
+
19
+ Style/TrailingCommaInArguments: # trailingComma
20
+ Enabled: false
21
+
22
+ Style/TrailingCommaInArrayLiteral: # trailingComma
23
+ Enabled: false
24
+
25
+ Style/TrailingCommaInHashLiteral: # trailingComma
26
+ Enabled: false
@@ -0,0 +1,87 @@
1
+ const {
2
+ concat,
3
+ hardline,
4
+ indent,
5
+ literalline,
6
+ markAsRoot,
7
+ mapDoc,
8
+ stripTrailingHardline
9
+ } = require("../prettier");
10
+
11
+ // Get the name of the parser that is represented by the given element node,
12
+ // return null if a matching parser cannot be found
13
+ function getParser(name, opts) {
14
+ let parser = name;
15
+
16
+ // We don't want to deal with some weird recursive parser situation, so we
17
+ // need to explicitly call out the HAML parser here and just return null
18
+ if (parser === "haml") {
19
+ return null;
20
+ }
21
+
22
+ // In HAML the name of the JS filter is :javascript, whereas in prettier the
23
+ // name of the JS parser is babel. Here we explicitly handle that conversion.
24
+ if (parser === "javascript") {
25
+ parser = "babel";
26
+ }
27
+
28
+ // If there is a plugin that has a parser that matches the name of this
29
+ // element, then we're going to assume that's correct for embedding and go
30
+ // ahead and switch to that parser
31
+ if (
32
+ opts.plugins.some(
33
+ (plugin) =>
34
+ plugin.parsers &&
35
+ Object.prototype.hasOwnProperty.call(plugin.parsers, parser)
36
+ )
37
+ ) {
38
+ return parser;
39
+ }
40
+
41
+ return null;
42
+ }
43
+
44
+ // This function is in here because it handles embedded parser values. I don't
45
+ // have a test that exercises it because I'm not sure for which parser it is
46
+ // necessary, but since it's in prettier core I'm keeping it here.
47
+ /* istanbul ignore next */
48
+ function replaceNewlines(doc) {
49
+ return mapDoc(doc, (currentDoc) =>
50
+ typeof currentDoc === "string" && currentDoc.includes("\n")
51
+ ? concat(
52
+ currentDoc
53
+ .split(/(\n)/g)
54
+ .map((v, i) => (i % 2 === 0 ? v : literalline))
55
+ )
56
+ : currentDoc
57
+ );
58
+ }
59
+
60
+ function embed(path, _print, textToDoc, opts) {
61
+ const node = path.getValue();
62
+ if (node.type !== "filter") {
63
+ return null;
64
+ }
65
+
66
+ const parser = getParser(node.value.name, opts);
67
+ if (!parser) {
68
+ return null;
69
+ }
70
+
71
+ return markAsRoot(
72
+ concat([
73
+ ":",
74
+ node.value.name,
75
+ indent(
76
+ concat([
77
+ hardline,
78
+ replaceNewlines(
79
+ stripTrailingHardline(textToDoc(node.value.text, { parser }))
80
+ )
81
+ ])
82
+ )
83
+ ])
84
+ );
85
+ }
86
+
87
+ module.exports = embed;
@@ -0,0 +1,27 @@
1
+ const { concat, group, hardline, indent, join } = require("../../prettier");
2
+
3
+ // https://haml.info/docs/yardoc/file.REFERENCE.html#html-comments-
4
+ function comment(path, _opts, print) {
5
+ const { children, value } = path.getValue();
6
+ const parts = ["/"];
7
+
8
+ if (value.revealed) {
9
+ parts.push("!");
10
+ }
11
+
12
+ if (value.conditional) {
13
+ parts.push(value.conditional);
14
+ } else if (value.text) {
15
+ parts.push(" ", value.text);
16
+ }
17
+
18
+ if (children.length > 0) {
19
+ parts.push(
20
+ indent(concat([hardline, join(hardline, path.map(print, "children"))]))
21
+ );
22
+ }
23
+
24
+ return group(concat(parts));
25
+ }
26
+
27
+ module.exports = comment;
@@ -0,0 +1,34 @@
1
+ const { join } = require("../../prettier");
2
+
3
+ const types = {
4
+ basic: "Basic",
5
+ frameset: "Frameset",
6
+ mobile: "Mobile",
7
+ rdfa: "RDFa",
8
+ strict: "Strict",
9
+ xml: "XML"
10
+ };
11
+
12
+ const versions = ["1.1", "5"];
13
+
14
+ // https://haml.info/docs/yardoc/file.REFERENCE.html#doctype-
15
+ function doctype(path, _opts, _print) {
16
+ const { value } = path.getValue();
17
+ const parts = ["!!!"];
18
+
19
+ if (value.type in types) {
20
+ parts.push(types[value.type]);
21
+ } else if (versions.includes(value.version)) {
22
+ parts.push(value.version);
23
+ } else {
24
+ parts.push(value.type);
25
+ }
26
+
27
+ if (value.encoding) {
28
+ parts.push(value.encoding);
29
+ }
30
+
31
+ return join(" ", parts);
32
+ }
33
+
34
+ module.exports = doctype;
@@ -0,0 +1,16 @@
1
+ const { concat, group, hardline, indent, join } = require("../../prettier");
2
+
3
+ // https://haml.info/docs/yardoc/file.REFERENCE.html#filters
4
+ function filter(path, _opts, _print) {
5
+ const { value } = path.getValue();
6
+
7
+ return group(
8
+ concat([
9
+ ":",
10
+ value.name,
11
+ indent(concat([hardline, join(hardline, value.text.trim().split("\n"))]))
12
+ ])
13
+ );
14
+ }
15
+
16
+ module.exports = filter;
@@ -0,0 +1,21 @@
1
+ const { concat, hardline, indent, join } = require("../../prettier");
2
+
3
+ // https://haml.info/docs/yardoc/file.REFERENCE.html#haml-comments--
4
+ function hamlComment(path, opts, _print) {
5
+ const node = path.getValue();
6
+ const parts = ["-#"];
7
+
8
+ if (node.value.text) {
9
+ if (opts.originalText.split("\n")[node.line - 1].trim() === "-#") {
10
+ const lines = node.value.text.trim().split("\n");
11
+
12
+ parts.push(indent(concat([hardline, join(hardline, lines)])));
13
+ } else {
14
+ parts.push(" ", node.value.text.trim());
15
+ }
16
+ }
17
+
18
+ return concat(parts);
19
+ }
20
+
21
+ module.exports = hamlComment;
@@ -0,0 +1,6 @@
1
+ // https://haml.info/docs/yardoc/file.REFERENCE.html#plain-text
2
+ function plain(path, _opts, _print) {
3
+ return path.getValue().value.text;
4
+ }
5
+
6
+ module.exports = plain;
@@ -0,0 +1,8 @@
1
+ const { concat, hardline, join } = require("../../prettier");
2
+
3
+ // The root node in the AST
4
+ function root(path, _opts, print) {
5
+ return concat([join(hardline, path.map(print, "children")), hardline]);
6
+ }
7
+
8
+ module.exports = root;
@@ -0,0 +1,33 @@
1
+ const { concat, group, hardline, indent, join } = require("../../prettier");
2
+
3
+ // https://haml.info/docs/yardoc/file.REFERENCE.html#inserting_ruby
4
+ function script(path, opts, print) {
5
+ const { children, value } = path.getValue();
6
+ const parts = [];
7
+
8
+ if (value.escape_html) {
9
+ parts.unshift("&");
10
+ }
11
+
12
+ if (value.preserve) {
13
+ parts.push("~");
14
+ } else if (!value.interpolate) {
15
+ parts.push("=");
16
+ }
17
+
18
+ if (value.escape_html && !value.preserve && value.interpolate) {
19
+ parts.push(" ", value.text.trim().slice(1, -1));
20
+ } else {
21
+ parts.push(" ", value.text.trim());
22
+ }
23
+
24
+ if (children.length > 0) {
25
+ parts.push(
26
+ indent(concat([hardline, join(hardline, path.map(print, "children"))]))
27
+ );
28
+ }
29
+
30
+ return group(concat(parts));
31
+ }
32
+
33
+ module.exports = script;
@@ -0,0 +1,59 @@
1
+ const { concat, group, hardline, indent, join } = require("../../prettier");
2
+
3
+ function findKeywordIndices(children, keywords) {
4
+ const indices = [];
5
+
6
+ children.forEach((child, index) => {
7
+ if (child.type !== "silent_script") {
8
+ return;
9
+ }
10
+
11
+ if (keywords.includes(child.value.keyword)) {
12
+ indices.push(index);
13
+ }
14
+ });
15
+
16
+ return indices;
17
+ }
18
+
19
+ // https://haml.info/docs/yardoc/file.REFERENCE.html#running-ruby--
20
+ function silentScript(path, _opts, print) {
21
+ const { children, value } = path.getValue();
22
+ const parts = [`- ${value.text.trim()}`];
23
+
24
+ if (children.length > 0) {
25
+ const scripts = path.map(print, "children");
26
+
27
+ if (value.keyword === "case") {
28
+ const keywordIndices = findKeywordIndices(children, ["when", "else"]);
29
+
30
+ parts.push(
31
+ concat(
32
+ scripts.map((script, index) => {
33
+ const concated = concat([hardline, script]);
34
+
35
+ return keywordIndices.includes(index) ? concated : indent(concated);
36
+ })
37
+ )
38
+ );
39
+ } else if (["if", "unless"].includes(value.keyword)) {
40
+ const keywordIndices = findKeywordIndices(children, ["elsif", "else"]);
41
+
42
+ parts.push(
43
+ concat(
44
+ scripts.map((script, index) => {
45
+ const concated = concat([hardline, script]);
46
+
47
+ return keywordIndices.includes(index) ? concated : indent(concated);
48
+ })
49
+ )
50
+ );
51
+ } else {
52
+ parts.push(indent(concat([hardline, join(hardline, scripts)])));
53
+ }
54
+ }
55
+
56
+ return group(concat(parts));
57
+ }
58
+
59
+ module.exports = silentScript;
@@ -0,0 +1,193 @@
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
+
14
+ function getDynamicAttributes(header, attributes) {
15
+ const pairs = attributes
16
+ .slice(1, -2)
17
+ .split(",")
18
+ .map((pair) => pair.slice(1).split('" => '));
19
+
20
+ const parts = [concat([pairs[0][0], "=", pairs[0][1]])];
21
+ pairs.slice(1).forEach((pair) => {
22
+ parts.push(line, concat([pair[0], "=", pair[1]]));
23
+ });
24
+
25
+ return group(concat(["(", align(header + 1, fill(parts)), ")"]));
26
+ }
27
+
28
+ function getHashValue(value, opts) {
29
+ if (typeof value !== "string") {
30
+ return value.toString();
31
+ }
32
+
33
+ // This is a very special syntax created by the parser to let us know that
34
+ // this should be printed literally instead of as a string.
35
+ if (value.startsWith("&")) {
36
+ return value.slice(1);
37
+ }
38
+
39
+ const quote = opts.rubySingleQuote ? "'" : '"';
40
+ return `${quote}${value}${quote}`;
41
+ }
42
+
43
+ function getHashKey(key, opts) {
44
+ let quoted = key;
45
+ const joiner = opts.rubyHashLabel ? ":" : " =>";
46
+
47
+ if (key.includes(":") || key.includes("-")) {
48
+ const quote = opts.rubySingleQuote ? "'" : '"';
49
+ quoted = `${quote}${key}${quote}`;
50
+ }
51
+
52
+ return `${opts.rubyHashLabel ? "" : ":"}${quoted}${joiner}`;
53
+ }
54
+
55
+ function getKeyValuePair(key, value, opts) {
56
+ return `${getHashKey(key, opts)} ${getHashValue(value, opts)}`;
57
+ }
58
+
59
+ function getStaticAttributes(header, attributes, opts) {
60
+ const keys = Object.keys(attributes).filter(
61
+ (name) => !["class", "id"].includes(name)
62
+ );
63
+
64
+ const parts = [getKeyValuePair(keys[0], attributes[keys[0]], opts)];
65
+
66
+ keys.slice(1).forEach((key) => {
67
+ parts.push(",", line, getKeyValuePair(key, attributes[key], opts));
68
+ });
69
+
70
+ return group(concat(["{", align(header + 1, fill(parts)), "}"]));
71
+ }
72
+
73
+ function getAttributesObject(object, opts, level = 0) {
74
+ if (typeof object !== "object") {
75
+ return getHashValue(object, opts);
76
+ }
77
+
78
+ const boundary = level === 0 ? softline : line;
79
+ const parts = Object.keys(object).map((key) =>
80
+ concat([
81
+ getHashKey(key, opts),
82
+ " ",
83
+ getAttributesObject(object[key], opts, level + 1)
84
+ ])
85
+ );
86
+
87
+ return group(
88
+ concat([
89
+ "{",
90
+ indent(group(concat([boundary, join(concat([",", line]), parts)]))),
91
+ boundary,
92
+ "}"
93
+ ])
94
+ );
95
+ }
96
+
97
+ function getHeader(value, opts) {
98
+ const { attributes } = value;
99
+ const parts = [];
100
+
101
+ if (value.name !== "div") {
102
+ parts.push(`%${value.name}`);
103
+ }
104
+
105
+ if (attributes.class) {
106
+ parts.push(`.${attributes.class.replace(/ /g, ".")}`);
107
+ }
108
+
109
+ if (attributes.id) {
110
+ parts.push(`#${attributes.id}`);
111
+ }
112
+
113
+ if (value.dynamic_attributes.new) {
114
+ parts.push(
115
+ getDynamicAttributes(parts.join("").length, value.dynamic_attributes.new)
116
+ );
117
+ }
118
+
119
+ if (
120
+ Object.keys(attributes).some((name) => name !== "class" && name !== "id")
121
+ ) {
122
+ parts.push(getStaticAttributes(parts.join("").length, attributes, opts));
123
+ }
124
+
125
+ if (value.dynamic_attributes.old) {
126
+ if (parts.length === 0) {
127
+ parts.push("%div");
128
+ }
129
+
130
+ if (typeof value.dynamic_attributes.old === "string") {
131
+ parts.push(value.dynamic_attributes.old);
132
+ } else {
133
+ parts.push(getAttributesObject(value.dynamic_attributes.old, opts));
134
+ }
135
+ }
136
+
137
+ if (value.object_ref) {
138
+ if (parts.length === 0) {
139
+ parts.push("%div");
140
+ }
141
+ parts.push(value.object_ref);
142
+ }
143
+
144
+ if (value.nuke_outer_whitespace) {
145
+ parts.push(">");
146
+ }
147
+
148
+ if (value.nuke_inner_whitespace) {
149
+ parts.push("<");
150
+ }
151
+
152
+ if (value.self_closing) {
153
+ parts.push("/");
154
+ }
155
+
156
+ if (value.value) {
157
+ const prefix = value.parse ? "= " : ifBreak("", " ");
158
+
159
+ return group(
160
+ concat([
161
+ group(concat(parts)),
162
+ indent(concat([softline, prefix, value.value]))
163
+ ])
164
+ );
165
+ }
166
+
167
+ // In case none of the other if statements have matched and we're printing a
168
+ // div, we need to explicitly add it back into the array.
169
+ if (parts.length === 0 && value.name === "div") {
170
+ parts.push("%div");
171
+ }
172
+
173
+ return group(concat(parts));
174
+ }
175
+
176
+ // https://haml.info/docs/yardoc/file.REFERENCE.html#element-name-
177
+ function tag(path, opts, print) {
178
+ const { children, value } = path.getValue();
179
+ const header = getHeader(value, opts);
180
+
181
+ if (children.length === 0) {
182
+ return header;
183
+ }
184
+
185
+ return group(
186
+ concat([
187
+ header,
188
+ indent(concat([hardline, join(hardline, path.map(print, "children"))]))
189
+ ])
190
+ );
191
+ }
192
+
193
+ module.exports = tag;