prettier 0.15.1 → 0.16.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.
@@ -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