Skip to content

Commit 728d601

Browse files
Add experimental rbminify tool for .rb minification
1 parent 9c6df52 commit 728d601

File tree

2 files changed

+75
-0
lines changed

2 files changed

+75
-0
lines changed

tools/exe/rbminify

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#!/usr/bin/env ruby
2+
3+
$LOAD_PATH << File.join(File.dirname(__FILE__), "../lib")
4+
5+
require "syntax_tree"
6+
require "syntax_tree/cli"
7+
require "syntax_tree/minify_ruby"
8+
9+
# Override the default formatter with our own.
10+
SyntaxTree.register_handler(".rb", SyntaxTree::MinifyRuby)
11+
12+
exit(SyntaxTree::CLI.run(ARGV))

tools/lib/syntax_tree/minify_ruby.rb

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
require "syntax_tree"
2+
3+
module SyntaxTree
4+
module MinifyRuby
5+
6+
# This is a required API for syntax tree which just delegates to SyntaxTree.parse.
7+
def self.parse(source)
8+
::SyntaxTree.parse(source)
9+
end
10+
11+
# This is the main entrypoint for the formatter. It parses the source,
12+
# builds a formatter, then prints the result.
13+
def self.format(source, _maxwidth = nil)
14+
formatter = Formatter.new(source)
15+
program = parse(source)
16+
CommentStrippingVisitor.new.visit(program)
17+
program.format(formatter)
18+
19+
formatter.flush
20+
formatter.output.join
21+
end
22+
23+
# This is a required API for syntax tree which just delegates to SyntaxTree.read.
24+
def self.read(filepath)
25+
::SyntaxTree.read(filepath)
26+
end
27+
28+
class CommentStrippingVisitor < SyntaxTree::Visitor
29+
def visit(node)
30+
if node and node.comments.any?
31+
node.comments.clear
32+
end
33+
super(node)
34+
end
35+
36+
def visit_statements(node)
37+
node.body.delete_if { _1.is_a?(SyntaxTree::Comment) }
38+
super(node)
39+
end
40+
end
41+
42+
class Formatter < SyntaxTree::Formatter
43+
def initialize(source)
44+
super(source, [], Float::INFINITY) do |n|
45+
# This block, called `genspace`, is used to generate indentation for `n` depth.
46+
""
47+
end
48+
end
49+
50+
def breakable(
51+
separator = " ",
52+
_width = separator.length,
53+
indent: nil,
54+
force: nil
55+
)
56+
# Don't break when already broken
57+
return if target.last.is_a?(PrettierPrint::BreakParent)
58+
return if not force and separator == ""
59+
super(separator, _width, indent: indent, force: force)
60+
end
61+
end
62+
end
63+
end

0 commit comments

Comments
 (0)