prettier 0.15.1 → 0.16.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@prettier/plugin-ruby",
3
- "version": "0.15.1",
3
+ "version": "0.16.0",
4
4
  "description": "prettier plugin for the Ruby programming language",
5
5
  "main": "src/ruby.js",
6
6
  "scripts": {
@@ -19,7 +19,7 @@
19
19
  },
20
20
  "homepage": "https://github.com/prettier/plugin-ruby#readme",
21
21
  "dependencies": {
22
- "prettier": "^1.16.4"
22
+ "prettier": ">=1.10"
23
23
  },
24
24
  "devDependencies": {
25
25
  "all-contributors-cli": "^6.1.2",
@@ -0,0 +1,21 @@
1
+ const embed = require("./haml/embed");
2
+ const parse = require("./haml/parse");
3
+ const print = require("./haml/print");
4
+
5
+ const pragmaPattern = /^\s*-#\s*@(prettier|format)/;
6
+ const hasPragma = text => pragmaPattern.test(text);
7
+
8
+ // These functions are just placeholders until we can actually perform this
9
+ // properly. The functions are necessary otherwise the format with cursor
10
+ // functions break.
11
+ const locStart = _node => 0;
12
+ const locEnd = _node => 0;
13
+
14
+ module.exports = {
15
+ embed,
16
+ hasPragma,
17
+ locStart,
18
+ locEnd,
19
+ parse,
20
+ print
21
+ };
@@ -0,0 +1,58 @@
1
+ const {
2
+ concat,
3
+ hardline,
4
+ indent,
5
+ literalline,
6
+ mapDoc,
7
+ markAsRoot,
8
+ stripTrailingHardline
9
+ } = require("../prettier");
10
+
11
+ const parsers = {
12
+ css: "css",
13
+ javascript: "babel",
14
+ less: "less",
15
+ markdown: "markdown",
16
+ ruby: "ruby",
17
+ scss: "scss"
18
+ };
19
+
20
+ const replaceNewlines = doc =>
21
+ mapDoc(doc, currentDoc =>
22
+ typeof currentDoc === "string" && currentDoc.includes("\n")
23
+ ? concat(
24
+ currentDoc
25
+ .split(/(\n)/g)
26
+ .map((v, i) => (i % 2 === 0 ? v : literalline))
27
+ )
28
+ : currentDoc
29
+ );
30
+
31
+ const embed = (path, print, textToDoc, _opts) => {
32
+ const node = path.getValue();
33
+ if (node.type !== "filter") {
34
+ return null;
35
+ }
36
+
37
+ const parser = parsers[node.value.name];
38
+ if (!parser) {
39
+ return null;
40
+ }
41
+
42
+ return markAsRoot(
43
+ concat([
44
+ ":",
45
+ node.value.name,
46
+ indent(
47
+ concat([
48
+ hardline,
49
+ replaceNewlines(
50
+ stripTrailingHardline(textToDoc(node.value.text, { parser }))
51
+ )
52
+ ])
53
+ )
54
+ ])
55
+ );
56
+ };
57
+
58
+ module.exports = embed;
@@ -0,0 +1,27 @@
1
+ const { concat, group, hardline, indent, join } = require("../../prettier");
2
+
3
+ // http://haml.info/docs/yardoc/file.REFERENCE.html#html-comments-
4
+ const 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,32 @@
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
+ // http://haml.info/docs/yardoc/file.REFERENCE.html#doctype-
15
+ const 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 (value.version in versions) {
22
+ parts.push(versions[value.version]);
23
+ }
24
+
25
+ if (value.encoding) {
26
+ parts.push(value.encoding);
27
+ }
28
+
29
+ return join(" ", parts);
30
+ };
31
+
32
+ module.exports = doctype;
@@ -0,0 +1,16 @@
1
+ const { concat, group, hardline, indent, join } = require("../../prettier");
2
+
3
+ // http://haml.info/docs/yardoc/file.REFERENCE.html#filters
4
+ const 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
+ // http://haml.info/docs/yardoc/file.REFERENCE.html#haml-comments--
4
+ const 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,29 @@
1
+ const { concat, group, hardline, indent, join } = require("../../prettier");
2
+
3
+ // http://haml.info/docs/yardoc/file.REFERENCE.html#inserting-ruby-
4
+ const 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
+ parts.push(" ", value.text.trim());
19
+
20
+ if (children.length > 0) {
21
+ parts.push(
22
+ indent(concat([hardline, join(hardline, path.map(print, "children"))]))
23
+ );
24
+ }
25
+
26
+ return group(concat(parts));
27
+ };
28
+
29
+ module.exports = script;
@@ -0,0 +1,30 @@
1
+ const { concat, group, hardline, indent, join } = require("../../prettier");
2
+
3
+ // http://haml.info/docs/yardoc/file.REFERENCE.html#running-ruby--
4
+ const silentScript = (path, opts, print) => {
5
+ const { children, value } = path.getValue();
6
+ const parts = [`- ${value.text.trim()}`];
7
+
8
+ if (children.length > 0) {
9
+ const scripts = path.map(print, "children");
10
+
11
+ if (value.keyword === "case") {
12
+ parts.push(
13
+ join(
14
+ "",
15
+ scripts.map((script, index) => {
16
+ const concated = concat([hardline, script]);
17
+
18
+ return index % 2 === 0 ? concated : indent(concated);
19
+ })
20
+ )
21
+ );
22
+ } else {
23
+ parts.push(indent(concat([hardline, join(hardline, scripts)])));
24
+ }
25
+ }
26
+
27
+ return group(concat(parts));
28
+ };
29
+
30
+ module.exports = silentScript;
@@ -0,0 +1,151 @@
1
+ const {
2
+ align,
3
+ concat,
4
+ fill,
5
+ group,
6
+ hardline,
7
+ indent,
8
+ join,
9
+ line,
10
+ softline
11
+ } = require("../../prettier");
12
+
13
+ const getDynamicAttributes = (header, attributes) => {
14
+ const pairs = attributes
15
+ .slice(1, -2)
16
+ .split(",")
17
+ .map(pair => pair.slice(1).split('" => '));
18
+ const parts = [concat([pairs[0][0], "=", pairs[0][1]])];
19
+
20
+ pairs.slice(1).forEach(pair => {
21
+ parts.push(line, concat([pair[0], "=", pair[1]]));
22
+ });
23
+
24
+ return group(concat(["(", align(header + 1, fill(parts)), ")"]));
25
+ };
26
+
27
+ const getHashValue = (value, opts) => {
28
+ if (typeof value === "string") {
29
+ const quote = opts.preferSingleQuotes ? "'" : '"';
30
+ return `${quote}${value}${quote}`;
31
+ }
32
+
33
+ return value;
34
+ };
35
+
36
+ const getHashRocket = (key, value, opts) => {
37
+ const quote = opts.preferSingleQuotes ? "'" : '"';
38
+ const leftSide = key.includes(":") ? `:${quote}${key}${quote}` : `:${key}`;
39
+
40
+ return `${leftSide} => ${getHashValue(value, opts)}`;
41
+ };
42
+
43
+ const getHashLabel = (key, value, opts) => {
44
+ const quote = opts.preferSingleQuotes ? "'" : '"';
45
+ const leftSide = key.includes(":") ? `${quote}${key}${quote}` : key;
46
+
47
+ return `${leftSide}: ${getHashValue(value, opts)}`;
48
+ };
49
+
50
+ const getStaticAttributes = (header, attributes, opts) => {
51
+ const keys = Object.keys(attributes).filter(
52
+ name => !["class", "id"].includes(name)
53
+ );
54
+
55
+ const getKeyValuePair = opts.preferHashLabels ? getHashLabel : getHashRocket;
56
+ const parts = [getKeyValuePair(keys[0], attributes[keys[0]], opts)];
57
+
58
+ keys.slice(1).forEach(key => {
59
+ parts.push(",", line, getKeyValuePair(key, attributes[key], opts));
60
+ });
61
+
62
+ return group(concat(["{", align(header + 1, fill(parts)), "}"]));
63
+ };
64
+
65
+ const getHeader = (value, opts) => {
66
+ const { attributes } = value;
67
+ const parts = [];
68
+
69
+ if (value.name !== "div") {
70
+ parts.push(`%${value.name}`);
71
+ }
72
+
73
+ if (attributes.class) {
74
+ parts.push(`.${attributes.class.replace(" ", ".")}`);
75
+ }
76
+
77
+ if (attributes.id) {
78
+ parts.push(`#${attributes.id}`);
79
+ }
80
+
81
+ if (value.dynamic_attributes.new) {
82
+ parts.push(
83
+ getDynamicAttributes(parts.join("").length, value.dynamic_attributes.new)
84
+ );
85
+ }
86
+
87
+ if (Object.keys(attributes).some(name => name !== "class" && name !== "id")) {
88
+ parts.push(getStaticAttributes(parts.join("").length, attributes, opts));
89
+ }
90
+
91
+ if (value.dynamic_attributes.old) {
92
+ parts.push(value.dynamic_attributes.old);
93
+ }
94
+
95
+ if (value.object_ref) {
96
+ if (parts.length === 0) {
97
+ parts.push("%div");
98
+ }
99
+ parts.push(value.object_ref);
100
+ }
101
+
102
+ if (value.nuke_outer_whitespace) {
103
+ parts.push(">");
104
+ }
105
+
106
+ if (value.nuke_inner_whitespace) {
107
+ parts.push("<");
108
+ }
109
+
110
+ if (value.self_closing) {
111
+ parts.push("/");
112
+ }
113
+
114
+ if (value.value) {
115
+ const prefix = value.parse ? "=" : "";
116
+
117
+ return group(
118
+ concat([
119
+ group(concat(parts)),
120
+ indent(concat([softline, `${prefix} ${value.value}`]))
121
+ ])
122
+ );
123
+ }
124
+
125
+ // In case none of the other if statements have matched and we're printing a
126
+ // div, we need to explicitly add it back into the array.
127
+ if (parts.length === 0 && value.name === "div") {
128
+ parts.push("%div");
129
+ }
130
+
131
+ return group(concat(parts));
132
+ };
133
+
134
+ // http://haml.info/docs/yardoc/file.REFERENCE.html#element-name-
135
+ const tag = (path, opts, print) => {
136
+ const { children, value } = path.getValue();
137
+ const header = getHeader(value, opts);
138
+
139
+ if (children.length === 0) {
140
+ return header;
141
+ }
142
+
143
+ return group(
144
+ concat([
145
+ header,
146
+ indent(concat([hardline, join(hardline, path.map(print, "children"))]))
147
+ ])
148
+ );
149
+ };
150
+
151
+ module.exports = tag;
@@ -0,0 +1,18 @@
1
+ const { spawnSync } = require("child_process");
2
+ const path = require("path");
3
+
4
+ const parse = (text, _parsers, _opts) => {
5
+ const child = spawnSync("ruby", [path.join(__dirname, "./parse.rb")], {
6
+ input: text
7
+ });
8
+
9
+ const error = child.stderr.toString();
10
+ if (error) {
11
+ throw new Error(error);
12
+ }
13
+
14
+ const response = child.stdout.toString();
15
+ return JSON.parse(response);
16
+ };
17
+
18
+ module.exports = parse;
@@ -0,0 +1,65 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'json'
4
+ require 'haml'
5
+
6
+ class Haml::Parser::ParseNode
7
+ ESCAPE = /Haml::Helpers.html_escape\(\((.+)\)\)/.freeze
8
+
9
+ def as_json
10
+ case type
11
+ when :comment, :doctype, :plain, :silent_script
12
+ to_h.tap do |json|
13
+ json.delete(:parent)
14
+ json[:children] = children.map(&:as_json)
15
+ end
16
+ when :filter, :haml_comment
17
+ to_h.tap { |json| json.delete(:parent) }
18
+ when :root
19
+ to_h.tap { |json| json[:children] = children.map(&:as_json) }
20
+ when :script
21
+ to_h.tap do |json|
22
+ json.delete(:parent)
23
+ json[:children] = children.map(&:as_json)
24
+
25
+ if json[:value][:text].match?(ESCAPE)
26
+ json[:value][:text].gsub!(ESCAPE) { $1 }
27
+ json[:value].merge!(escape_html: 'escape_html', interpolate: true)
28
+ end
29
+ end
30
+ when :tag
31
+ to_h.tap do |json|
32
+ json.delete(:parent)
33
+
34
+ # For some reason this is actually using a symbol to represent a null
35
+ # object ref instead of nil itself, so just replacing it here for
36
+ # simplicity in the printer
37
+ json[:value][:object_ref] = nil if json[:value][:object_ref] == :nil
38
+
39
+ json.merge!(
40
+ children: children.map(&:as_json),
41
+ value:
42
+ value.merge(dynamic_attributes: value[:dynamic_attributes].to_h)
43
+ )
44
+ end
45
+ else
46
+ raise ArgumentError, "Unsupported type: #{type}"
47
+ end
48
+ end
49
+
50
+ def self.to_json(template)
51
+ parser = Haml::Parser.new({})
52
+ JSON.fast_generate(parser.call(template).as_json)
53
+ end
54
+ end
55
+
56
+ # If this is the main file we're executing, then most likely this is being
57
+ # executed from the haml.js spawn. In that case, read the ruby source from
58
+ # stdin and report back the AST over stdout.
59
+
60
+ if $0 == __FILE__
61
+ parser = Haml::Parser.new({})
62
+ template = $stdin.read
63
+
64
+ puts JSON.fast_generate(parser.call(template).as_json)
65
+ end