vbsmin 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (6) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/bin/vbsmin +52 -0
  4. data/lib/vbsmin.rb +148 -0
  5. data/lib/vbsmin/version.rb +5 -0
  6. metadata +193 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: f20bc497c7112197f64f96e3c8c3da2011532550cc2b7394bda862f9f1202390
4
+ data.tar.gz: 6d15264fe085ef8ab8312aa50052a137b2b756a559064ee7defae8a32c51956d
5
+ SHA512:
6
+ metadata.gz: 04d51468991b87872b94e50a7941cd9836a4dda21f5354460359fed834362996a8be448e53db896951f7ac99008765b4ea622eadb5368916eba98c34e5fde863
7
+ data.tar.gz: 79666d44546ff04c6f6b8064d2cb779a61a4b044043d9b4396c96f49b70c7324a479f6f9e8eef55554cc7b1dcd199be1cb46b3a6126e3e78df4337f0dfc4dbea
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2020 Alexandre ZANNI
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,52 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # Ruby internal
5
+ require 'pp'
6
+ # Project internal
7
+ require 'vbsmin'
8
+ # External
9
+ require 'docopt'
10
+ require 'paint'
11
+
12
+ doc = <<~DOCOPT
13
+ vbsmin - VBScript minifier
14
+
15
+ Usage:
16
+ vbsmin [options] <filepath>
17
+ vbsmin -h | --help
18
+ vbsmin --version
19
+
20
+ Options:
21
+ --no-color Disable colorized output
22
+ --debug Display arguments
23
+ -h, --help Show this screen
24
+ --version Show version
25
+
26
+ Examples:
27
+ vbsmin samples/pyenv.vbs
28
+ vbsmin --no-color samples/pyenv.vbs
29
+ DOCOPT
30
+
31
+ begin
32
+ args = Docopt.docopt(doc, version: VBSMin::VERSION)
33
+ Paint.mode = 0 if args['--no-color']
34
+ pp args if args['--debug']
35
+ # use case 1, using the tool
36
+ if args['<filepath>']
37
+ vm = VBSMin.new
38
+ vm.minify(args['<filepath>'])
39
+ print Paint['Original file size: ', :bold]
40
+ puts Paint["#{vm.input_size} bytes", :red]
41
+ print Paint['Minified file size: ', :bold]
42
+ puts Paint["#{vm.output_size} bytes", :green]
43
+ print Paint['Size saved: ', :bold]
44
+ puts Paint["#{vm.diff_size} bytes", :green, :inverse]
45
+ puts "\nOriginal file path: #{vm.original_filepath}"
46
+ puts "Minified file path: #{vm.min_filepath}"
47
+ end
48
+ # use case 2, help: already handled by docopt
49
+ # use case 3, version: already handled by docopt
50
+ rescue Docopt::Exit => e
51
+ puts e.message
52
+ end
@@ -0,0 +1,148 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Ruby internal
4
+ require 'fileutils'
5
+ # Project internal
6
+ require 'vbsmin/version'
7
+
8
+ # Global VBSmin class
9
+ class VBSMin
10
+ # Constants
11
+ include Version
12
+
13
+ # @return [Integer] Size (in bytes) of the original file
14
+ attr_reader :input_size
15
+
16
+ # @return [Integer] Size (in bytes) of the minified file
17
+ attr_reader :output_size
18
+
19
+ # @return [Integer] Saved size (in bytes)
20
+ attr_reader :diff_size
21
+
22
+ # @return [String] Path of the original file
23
+ attr_reader :original_filepath
24
+
25
+ # @return [String] Path of the minified file
26
+ attr_reader :min_filepath
27
+
28
+ # Instantiate a VBSmin object
29
+ def initialize
30
+ @input_size = nil
31
+ @output_size = nil
32
+ @diff_size = nil
33
+ @original_filepath = nil
34
+ @min_filepath = nil
35
+ end
36
+
37
+ # Minify a VBScript file (make a minified copy: file.min.vbs)
38
+ # @param filepath [String] Path to the VBS file to minify
39
+ # @return [String] Path of the minified file
40
+ def minify(filepath)
41
+ @original_filepath = filepath
42
+ # Count number of line of input
43
+ input_lines = IO.readlines(filepath).length
44
+ # File streaming
45
+ File.open(min_ext, 'w') do |output|
46
+ File.foreach(filepath).with_index(1) do |line, i|
47
+ eol = ':' # End of file char
48
+ # Remove inline comment (must be before whitespace striping)
49
+ line = inline_comment(line)
50
+ # Remove leading and trailing whitespaces: null, horizontal tab, line feed,
51
+ # vertical tab, form feed, carriage return, space
52
+ line.strip!
53
+ # Remove comments except inline ones (must be after whitespace striping)
54
+ line = '' if line[0] == "'" || line[0..2].upcase == 'REM'
55
+ # Remove space when several spaces between two keywords
56
+ line = internal_space(line)
57
+ # Remove line splitting
58
+ line[-1] = '' && eol = '' if line[-2..] == ' _'
59
+ # Write processed line unless it is a blank line or the last line
60
+ unless line.empty?
61
+ output.write(line)
62
+ output.write(eol) unless i == input_lines
63
+ end
64
+ end
65
+ end
66
+ calc_size
67
+ return @min_filepath
68
+ end
69
+
70
+ private
71
+
72
+ # Create the path of the minified file from the path of the original file
73
+ def min_ext
74
+ extension = File.extname(@original_filepath).downcase
75
+ abort 'Not a .vbs file' unless extension == '.vbs'
76
+ min_filepath = @original_filepath.chomp(extension) + '.min.vbs'
77
+ @min_filepath = min_filepath
78
+ return min_filepath
79
+ end
80
+
81
+ # Calculate the size of the files and the saved size
82
+ def calc_size
83
+ @input_size = File.size(@original_filepath)
84
+ @output_size = File.size(@min_filepath)
85
+ @diff_size = @input_size - @output_size
86
+ end
87
+
88
+ # DO NOT USE, use internal_space instead()
89
+ def internal_space_old(line)
90
+ arr = []
91
+ single_quote = line.count('"')
92
+ # This method won't work when there is two consecutive double quote
93
+ # so we must replace them else they will get removed.
94
+ line.gsub!('""', '☠')
95
+ line.split('"').each_with_index do |item, i|
96
+ # if odd number of double quote we are in a string else we are out
97
+ # process only if out of a string
98
+ item.gsub!(/ +/, ' ') if i.even?
99
+ arr.push(item)
100
+ end
101
+ output = arr.join('"')
102
+ output.gsub!('☠', '""')
103
+ output += '"' unless single_quote == output.count('"')
104
+ return output
105
+ end
106
+
107
+ # Remove extra spaces (several spaces between two keywords except in a string)
108
+ # More reliable than internal_space_old which use string replacement and string
109
+ # split
110
+ def internal_space(line)
111
+ # For each single quote, if there is an odd number of double quote before
112
+ # we are in a string, but if there is an even number of double quote before
113
+ # we are out of a string.
114
+ double_quote = 0
115
+ previous_char = nil
116
+ output = ''
117
+ i = 0
118
+ line.each_char do |c|
119
+ double_quote += 1 if c == '"'
120
+ output += c unless previous_char == ' ' && c == ' ' && double_quote.even?
121
+ i += 1
122
+ previous_char = c
123
+ end
124
+ return output
125
+ end
126
+
127
+ # Remove inline comments
128
+ # In VBS there is no single quote strings so it's safe to remove until the end
129
+ # of string when ecountering a single quote.
130
+ # The only case to handle if is a single quote appears in a double quote string.
131
+ def inline_comment(line)
132
+ # For each single quote, if there is an odd number of double quote before
133
+ # we are in a string, but if there is an even number of double quote before
134
+ # we are out of a string so this is an inline comment and we can remove all
135
+ # that comes after.
136
+ double_quote = 0
137
+ i = 0
138
+ line.each_char do |c|
139
+ double_quote += 1 if c == '"'
140
+ if c == "'" && double_quote.even?
141
+ line = line[...i]
142
+ break
143
+ end
144
+ i += 1
145
+ end
146
+ return line
147
+ end
148
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Version
4
+ VERSION = '1.0.0'
5
+ end
metadata ADDED
@@ -0,0 +1,193 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: vbsmin
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Alexandre ZANNI
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-06-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: docopt
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.6'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: paint
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '2.2'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '2.2'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '2.1'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '2.1'
55
+ - !ruby/object:Gem::Dependency
56
+ name: commonmarker
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '0.21'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '0.21'
69
+ - !ruby/object:Gem::Dependency
70
+ name: github-markup
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '3.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '3.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: minitest
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '5.12'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '5.12'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rake
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '13.0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '13.0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: redcarpet
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '3.5'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '3.5'
125
+ - !ruby/object:Gem::Dependency
126
+ name: rubocop
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: '0.80'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: '0.80'
139
+ - !ruby/object:Gem::Dependency
140
+ name: yard
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - "~>"
144
+ - !ruby/object:Gem::Version
145
+ version: '0.9'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - "~>"
151
+ - !ruby/object:Gem::Version
152
+ version: '0.9'
153
+ description: VBScript minifier CLI tool and library
154
+ email: alexandre.zanni@engineer.com
155
+ executables:
156
+ - vbsmin
157
+ extensions: []
158
+ extra_rdoc_files: []
159
+ files:
160
+ - LICENSE
161
+ - bin/vbsmin
162
+ - lib/vbsmin.rb
163
+ - lib/vbsmin/version.rb
164
+ homepage: https://noraj.github.io/vbsmin/
165
+ licenses:
166
+ - MIT
167
+ metadata:
168
+ yard.run: yard
169
+ bug_tracker_uri: https://github.com/noraj/vbsmin/issues
170
+ changelog_uri: https://github.com/noraj/vbsmin/blob/master/docs/CHANGELOG.md
171
+ documentation_uri: https://noraj.github.io/vbsmin/
172
+ homepage_uri: https://noraj.github.io/vbsmin/
173
+ source_code_uri: https://github.com/noraj/vbsmin/
174
+ post_install_message:
175
+ rdoc_options: []
176
+ require_paths:
177
+ - lib
178
+ required_ruby_version: !ruby/object:Gem::Requirement
179
+ requirements:
180
+ - - "~>"
181
+ - !ruby/object:Gem::Version
182
+ version: '2.7'
183
+ required_rubygems_version: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - ">="
186
+ - !ruby/object:Gem::Version
187
+ version: '0'
188
+ requirements: []
189
+ rubygems_version: 3.1.2
190
+ signing_key:
191
+ specification_version: 4
192
+ summary: VBScript minifier
193
+ test_files: []