ruby2js 1.15.1 → 2.0.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.
- data/lib/ruby2js.rb +36 -36
- data/lib/ruby2js/converter.rb +59 -20
- data/lib/ruby2js/converter/arg.rb +1 -1
- data/lib/ruby2js/converter/args.rb +1 -1
- data/lib/ruby2js/converter/array.rb +3 -4
- data/lib/ruby2js/converter/begin.rb +15 -1
- data/lib/ruby2js/converter/block.rb +6 -5
- data/lib/ruby2js/converter/boolean.rb +1 -1
- data/lib/ruby2js/converter/break.rb +1 -1
- data/lib/ruby2js/converter/case.rb +27 -7
- data/lib/ruby2js/converter/casgn.rb +5 -2
- data/lib/ruby2js/converter/class.rb +41 -11
- data/lib/ruby2js/converter/const.rb +1 -1
- data/lib/ruby2js/converter/cvar.rb +4 -3
- data/lib/ruby2js/converter/cvasgn.rb +5 -6
- data/lib/ruby2js/converter/def.rb +15 -3
- data/lib/ruby2js/converter/defined.rb +1 -1
- data/lib/ruby2js/converter/defs.rb +7 -3
- data/lib/ruby2js/converter/dstr.rb +3 -3
- data/lib/ruby2js/converter/for.rb +7 -10
- data/lib/ruby2js/converter/hash.rb +70 -34
- data/lib/ruby2js/converter/if.rb +35 -13
- data/lib/ruby2js/converter/in.rb +1 -1
- data/lib/ruby2js/converter/ivasgn.rb +1 -1
- data/lib/ruby2js/converter/kwbegin.rb +20 -20
- data/lib/ruby2js/converter/literal.rb +1 -1
- data/lib/ruby2js/converter/logical.rb +4 -8
- data/lib/ruby2js/converter/next.rb +1 -1
- data/lib/ruby2js/converter/nil.rb +1 -1
- data/lib/ruby2js/converter/nthref.rb +1 -1
- data/lib/ruby2js/converter/opasgn.rb +3 -3
- data/lib/ruby2js/converter/regexp.rb +12 -9
- data/lib/ruby2js/converter/return.rb +3 -3
- data/lib/ruby2js/converter/self.rb +2 -2
- data/lib/ruby2js/converter/send.rb +31 -30
- data/lib/ruby2js/converter/super.rb +8 -11
- data/lib/ruby2js/converter/sym.rb +1 -1
- data/lib/ruby2js/converter/undef.rb +9 -2
- data/lib/ruby2js/converter/var.rb +1 -1
- data/lib/ruby2js/converter/vasgn.rb +13 -5
- data/lib/ruby2js/converter/while.rb +2 -1
- data/lib/ruby2js/converter/whilepost.rb +2 -1
- data/lib/ruby2js/converter/xstr.rb +4 -3
- data/lib/ruby2js/execjs.rb +3 -3
- data/lib/ruby2js/filter/camelCase.rb +8 -8
- data/lib/ruby2js/filter/functions.rb +64 -65
- data/lib/ruby2js/filter/react.rb +44 -16
- data/lib/ruby2js/filter/require.rb +4 -1
- data/lib/ruby2js/filter/underscore.rb +21 -21
- data/lib/ruby2js/serializer.rb +347 -0
- data/lib/ruby2js/version.rb +3 -3
- data/ruby2js.gemspec +3 -3
- metadata +3 -2
@@ -45,7 +45,10 @@ module Ruby2JS
|
|
45
45
|
end
|
46
46
|
|
47
47
|
@options[:file2] = filename
|
48
|
-
|
48
|
+
ast, comments = Ruby2JS.parse(File.read(filename), filename)
|
49
|
+
@comments.merge! Parser::Source::Comment.associate(ast, comments)
|
50
|
+
@comments[node] += @comments[ast]
|
51
|
+
process ast
|
49
52
|
ensure
|
50
53
|
if file2
|
51
54
|
@options[:file2] = file2
|
@@ -11,42 +11,42 @@ module Ruby2JS
|
|
11
11
|
if [:clone, :shuffle, :size, :compact, :flatten, :invert, :values,
|
12
12
|
:uniq].include? node.children[1]
|
13
13
|
if node.is_method? and node.children.length == 2
|
14
|
-
process
|
14
|
+
process S(:send, s(:lvar, :_), node.children[1], node.children[0])
|
15
15
|
else
|
16
16
|
super
|
17
17
|
end
|
18
18
|
elsif node.children[1] == :sample and node.children.length <= 3
|
19
|
-
process
|
19
|
+
process S(:send, s(:lvar, :_), :sample, node.children[0],
|
20
20
|
*node.children[2..-1])
|
21
21
|
elsif node.children[1] == :has_key? and node.children.length == 3
|
22
|
-
process
|
22
|
+
process S(:send, s(:lvar, :_), :has, node.children[0],
|
23
23
|
node.children[2])
|
24
24
|
elsif node.children[1] == :sort and node.children.length == 2
|
25
25
|
if node.is_method?
|
26
|
-
process
|
26
|
+
process S(:send, s(:lvar, :_), :sortBy, node.children[0],
|
27
27
|
s(:attr, s(:lvar, :_), :identity))
|
28
28
|
else
|
29
29
|
super
|
30
30
|
end
|
31
31
|
elsif node.children[1] == :map
|
32
32
|
if node.children.length == 3 and node.children[2].type == :block_pass
|
33
|
-
process
|
33
|
+
process S(:send, s(:lvar, :_), :pluck, node.children[0],
|
34
34
|
node.children[2].children.first)
|
35
35
|
else
|
36
36
|
super
|
37
37
|
end
|
38
38
|
elsif node.children[1] == :merge and node.children.length >= 3
|
39
|
-
process
|
39
|
+
process S(:send, s(:lvar, :_), :extend, s(:hash), node.children[0],
|
40
40
|
*node.children[2..-1])
|
41
41
|
elsif node.children[1] == :merge! and node.children.length >= 3
|
42
|
-
process
|
42
|
+
process S(:send, s(:lvar, :_), :extend, node.children[0],
|
43
43
|
*node.children[2..-1])
|
44
44
|
elsif node.children[1] == :zip and node.children.length >= 3
|
45
|
-
process
|
45
|
+
process S(:send, s(:lvar, :_), :zip, node.children[0],
|
46
46
|
*node.children[2..-1])
|
47
47
|
elsif node.children[1] == :invoke
|
48
48
|
if node.children.length >= 3 and node.children.last.type==:block_pass
|
49
|
-
process
|
49
|
+
process S(:send, s(:lvar, :_), :invoke, node.children[0],
|
50
50
|
node.children.last.children.first,
|
51
51
|
*node.children[2..-2])
|
52
52
|
else
|
@@ -54,7 +54,7 @@ module Ruby2JS
|
|
54
54
|
end
|
55
55
|
elsif [:where, :find_by].include? node.children[1]
|
56
56
|
method = node.children[1] == :where ? :where : :findWhere
|
57
|
-
process
|
57
|
+
process S(:send, s(:lvar, :_), method, node.children[0],
|
58
58
|
*node.children[2..-1])
|
59
59
|
elsif node.children[1] == :reduce
|
60
60
|
if node.children.length == 3 and node.children[2].type == :sym
|
@@ -62,7 +62,7 @@ module Ruby2JS
|
|
62
62
|
# output: _.reduce(_.rest(a),
|
63
63
|
# proc {|memo, item| return memo+item},
|
64
64
|
# a[0])
|
65
|
-
process
|
65
|
+
process S(:send, s(:lvar, :_), :reduce,
|
66
66
|
s(:send, s(:lvar, :_), :rest, node.children.first),
|
67
67
|
s(:block, s(:send, nil, :proc),
|
68
68
|
s(:args, s(:arg, :memo), s(:arg, :item)),
|
@@ -75,7 +75,7 @@ module Ruby2JS
|
|
75
75
|
elsif node.children.length == 4 and node.children[3].type == :sym
|
76
76
|
# input: a.reduce(n, :+)
|
77
77
|
# output: _.reduce(a, proc {|memo, item| return memo+item}, n)
|
78
|
-
process
|
78
|
+
process S(:send, s(:lvar, :_), :reduce, node.children.first,
|
79
79
|
s(:block, s(:send, nil, :proc),
|
80
80
|
s(:args, s(:arg, :memo), s(:arg, :item)),
|
81
81
|
s(:autoreturn, s(:send, s(:lvar, :memo),
|
@@ -90,7 +90,7 @@ module Ruby2JS
|
|
90
90
|
# input: a.compact!
|
91
91
|
# output: a.splice(0, a.length, *a.compact)
|
92
92
|
target = node.children.first
|
93
|
-
process
|
93
|
+
process S(:send, target, :splice, s(:int, 0),
|
94
94
|
s(:attr, target, :length), s(:splat, s(:send, target,
|
95
95
|
:"#{node.children[1].to_s[0..-2]}", *node.children[2..-1])))
|
96
96
|
else
|
@@ -104,14 +104,14 @@ module Ruby2JS
|
|
104
104
|
# input: a.sort_by {}
|
105
105
|
# output: _.sortBy {return expression}
|
106
106
|
method = call.children[1].to_s.sub(/\_by$/,'By').to_sym
|
107
|
-
process
|
107
|
+
process S(:block, s(:send, s(:lvar, :_), method,
|
108
108
|
call.children.first), node.children[1],
|
109
109
|
s(:autoreturn, node.children[2]))
|
110
110
|
elsif [:find, :reject].include? call.children[1]
|
111
111
|
if call.children.length == 2
|
112
112
|
# input: a.find {|item| item > 0}
|
113
113
|
# output: _.find(a) {|item| return item > 0}
|
114
|
-
process
|
114
|
+
process S(:block, s(:send, s(:lvar, :_), call.children[1],
|
115
115
|
call.children.first), node.children[1],
|
116
116
|
s(:autoreturn, node.children[2]))
|
117
117
|
else
|
@@ -121,7 +121,7 @@ module Ruby2JS
|
|
121
121
|
elsif call.children[1] == :times and call.children.length == 2
|
122
122
|
# input: 5.times {|i| console.log i}
|
123
123
|
# output: _.find(5) {|i| console.log(i)}
|
124
|
-
process
|
124
|
+
process S(:block, s(:send, s(:lvar, :_), call.children[1],
|
125
125
|
call.children.first), node.children[1], node.children[2])
|
126
126
|
|
127
127
|
elsif call.children[1] == :reduce
|
@@ -130,7 +130,7 @@ module Ruby2JS
|
|
130
130
|
# output: _.reduce(_.rest(a),
|
131
131
|
# proc {|memo, item| return memo+item},
|
132
132
|
# a[0])
|
133
|
-
process
|
133
|
+
process S(:call, s(:lvar, :_), :reduce,
|
134
134
|
s(:send, s(:lvar, :_), :rest, call.children.first),
|
135
135
|
s(:block, s(:send, nil, :proc),
|
136
136
|
node.children[1], s(:autoreturn, node.children[2])),
|
@@ -138,7 +138,7 @@ module Ruby2JS
|
|
138
138
|
elsif call.children.length == 3
|
139
139
|
# input: a.reduce(n) {|memo, item| memo+item}
|
140
140
|
# output: _.reduce(a, proc {|memo, item| return memo+item}, n)
|
141
|
-
process
|
141
|
+
process S(:call, s(:lvar, :_), :reduce, call.children.first,
|
142
142
|
s(:block, s(:send, nil, :proc),
|
143
143
|
node.children[1], s(:autoreturn, node.children[2])),
|
144
144
|
call.children[2])
|
@@ -149,7 +149,7 @@ module Ruby2JS
|
|
149
149
|
# output: a.splice(0, a.length, *a.map {expression})
|
150
150
|
method = :"#{call.children[1].to_s[0..-2]}"
|
151
151
|
target = call.children.first
|
152
|
-
process
|
152
|
+
process S(:call, target, :splice, s(:splat, s(:send, s(:array,
|
153
153
|
s(:int, 0), s(:attr, target, :length)), :concat,
|
154
154
|
s(:block, s(:send, target, method, *call.children[2..-1]),
|
155
155
|
*node.children[1..-1]))))
|
@@ -165,10 +165,10 @@ module Ruby2JS
|
|
165
165
|
|
166
166
|
def on_irange(node)
|
167
167
|
if node.children.last.type == :int
|
168
|
-
process
|
168
|
+
process S(:call, s(:lvar, :_), :range, node.children.first,
|
169
169
|
s(:int, node.children.last.children.last+1))
|
170
170
|
else
|
171
|
-
process
|
171
|
+
process S(:call, s(:lvar, :_), :range, node.children.first,
|
172
172
|
s(:send, node.children.last, :+, s(:int, 1)))
|
173
173
|
end
|
174
174
|
end
|
@@ -0,0 +1,347 @@
|
|
1
|
+
module Ruby2JS
|
2
|
+
class Token < String
|
3
|
+
attr_accessor :loc
|
4
|
+
attr_accessor :ast
|
5
|
+
|
6
|
+
def initialize(string, ast)
|
7
|
+
super(string.to_s)
|
8
|
+
@ast = ast
|
9
|
+
@loc = ast.location if ast
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class Line < Array
|
14
|
+
attr_accessor :indent
|
15
|
+
|
16
|
+
def initialize(*args)
|
17
|
+
super(args)
|
18
|
+
@indent = 0
|
19
|
+
end
|
20
|
+
|
21
|
+
def comment?
|
22
|
+
first = find {|token| !token.empty?}
|
23
|
+
first and first.start_with? '//'
|
24
|
+
end
|
25
|
+
|
26
|
+
def empty?
|
27
|
+
all? {|line| line.empty?}
|
28
|
+
end
|
29
|
+
|
30
|
+
def to_s
|
31
|
+
if empty?
|
32
|
+
''
|
33
|
+
elsif ['case ', 'default:'].include? self[0]
|
34
|
+
' ' * ([0,indent-2].max) + join
|
35
|
+
else
|
36
|
+
' ' * indent + join
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
class Serializer
|
42
|
+
attr_reader :timestamps
|
43
|
+
|
44
|
+
def initialize
|
45
|
+
@sep = '; '
|
46
|
+
@nl = ''
|
47
|
+
@ws = ' '
|
48
|
+
|
49
|
+
@width = 80
|
50
|
+
@indent = 0
|
51
|
+
|
52
|
+
@lines = [Line.new]
|
53
|
+
@line = @lines.last
|
54
|
+
@timestamps = {}
|
55
|
+
end
|
56
|
+
|
57
|
+
def timestamp(file)
|
58
|
+
@timestamps[file] = File.mtime(file) if file and File.exist?(file)
|
59
|
+
end
|
60
|
+
|
61
|
+
def uptodate?
|
62
|
+
return false if @timestamps.empty?
|
63
|
+
return @timestamps.all? {|file, mtime| File.mtime(file) == mtime}
|
64
|
+
end
|
65
|
+
|
66
|
+
def mtime
|
67
|
+
return Time.now if @timestamps.empty?
|
68
|
+
return @timestamps.values.max
|
69
|
+
end
|
70
|
+
|
71
|
+
def enable_vertical_whitespace
|
72
|
+
@sep = ";\n"
|
73
|
+
@nl = "\n"
|
74
|
+
@ws = @nl
|
75
|
+
@indent = 2
|
76
|
+
end
|
77
|
+
|
78
|
+
# indent multi-line parameter lists, array constants, blocks
|
79
|
+
def reindent(lines)
|
80
|
+
indent = 0
|
81
|
+
lines.each do |line|
|
82
|
+
first = line.find {|token| !token.empty?}
|
83
|
+
if first
|
84
|
+
last = line[line.rindex {|token| !token.empty?}]
|
85
|
+
indent -= @indent if ')}]'.include? first[0]
|
86
|
+
line.indent = indent
|
87
|
+
indent += @indent if '({['.include? last[-1]
|
88
|
+
else
|
89
|
+
line.indent = indent
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
# add horizontal (indentation) and vertical (blank lines) whitespace
|
95
|
+
def respace
|
96
|
+
return if @indent == 0
|
97
|
+
reindent @lines
|
98
|
+
|
99
|
+
(@lines.length-3).downto(0) do |i|
|
100
|
+
if
|
101
|
+
@lines[i].length == 0
|
102
|
+
then
|
103
|
+
@lines.delete i
|
104
|
+
elsif
|
105
|
+
@lines[i+1].comment? and not @lines[i].comment? and
|
106
|
+
@lines[i].indent == @lines[i+1].indent
|
107
|
+
then
|
108
|
+
# before a comment
|
109
|
+
@lines.insert i+1, Line.new
|
110
|
+
elsif
|
111
|
+
@lines[i].indent == @lines[i+1].indent and
|
112
|
+
@lines[i+1].indent < @lines[i+2].indent and
|
113
|
+
not @lines[i].comment?
|
114
|
+
then
|
115
|
+
# start of indented block
|
116
|
+
@lines.insert i+1, Line.new
|
117
|
+
elsif
|
118
|
+
@lines[i].indent > @lines[i+1].indent and
|
119
|
+
@lines[i+1].indent == @lines[i+2].indent and
|
120
|
+
not @lines[i+2].empty?
|
121
|
+
then
|
122
|
+
# end of indented block
|
123
|
+
@lines.insert i+2, Line.new
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
# add a single token to the current line
|
129
|
+
def put(string)
|
130
|
+
unless String === string and string.include? "\n"
|
131
|
+
@line << Token.new(string, @ast)
|
132
|
+
else
|
133
|
+
parts = string.split("\n")
|
134
|
+
@line << Token.new(parts.shift, @ast)
|
135
|
+
@lines += parts.map {|part| Line.new(Token.new(part, @ast))}
|
136
|
+
@lines << Line.new if string.end_with?("\n")
|
137
|
+
@line = @lines.last
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
# add a single token to the current line and then advance to next line
|
142
|
+
def puts(string)
|
143
|
+
unless String === string and string.include? "\n"
|
144
|
+
@line << Token.new(string, @ast)
|
145
|
+
else
|
146
|
+
put string
|
147
|
+
end
|
148
|
+
|
149
|
+
@line = Line.new
|
150
|
+
@lines << @line
|
151
|
+
end
|
152
|
+
|
153
|
+
# advance to next line and then add a single token to the current line
|
154
|
+
def sput(string)
|
155
|
+
unless String === string and string.include? "\n"
|
156
|
+
@line = Line.new(Token.new(string, @ast))
|
157
|
+
@lines << @line
|
158
|
+
else
|
159
|
+
@line = Line.new
|
160
|
+
@lines << @line
|
161
|
+
put string
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
# current location: [line number, token number]
|
166
|
+
def output_location
|
167
|
+
[@lines.length-1, @line.length]
|
168
|
+
end
|
169
|
+
|
170
|
+
# insert a line into the output
|
171
|
+
def insert(mark, line)
|
172
|
+
if mark.last == 0
|
173
|
+
@lines.insert(mark.first, Line.new(Token.new(line.chomp, @ast)))
|
174
|
+
else
|
175
|
+
@lines[mark.first].insert(mark.last, Token.new(line, @ast))
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
# capture (and remove) tokens from the output stream
|
180
|
+
def capture(&block)
|
181
|
+
mark = output_location
|
182
|
+
block.call
|
183
|
+
lines = @lines.slice!(mark.first+1..-1)
|
184
|
+
@line = @lines.last
|
185
|
+
|
186
|
+
if lines.empty?
|
187
|
+
lines = [@line.slice!(mark.last..-1)]
|
188
|
+
elsif @line.length != mark.last
|
189
|
+
lines.unshift @line.slice!(mark.last..-1)
|
190
|
+
end
|
191
|
+
|
192
|
+
lines.map(&:join).join(@ws)
|
193
|
+
end
|
194
|
+
|
195
|
+
# wrap long statements in curly braces
|
196
|
+
def wrap
|
197
|
+
puts '{'
|
198
|
+
mark = output_location
|
199
|
+
yield
|
200
|
+
|
201
|
+
if
|
202
|
+
@lines.length > mark.first+1 or
|
203
|
+
@lines[mark.first-1].join.length + @line.join.length >= @width
|
204
|
+
then
|
205
|
+
sput '}'
|
206
|
+
else
|
207
|
+
@line = @lines[mark.first-1]
|
208
|
+
@line[-1..-1] = @lines.pop
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
# compact small expressions into a single line
|
213
|
+
def compact
|
214
|
+
mark = output_location
|
215
|
+
yield
|
216
|
+
return unless @lines.length - mark.first > 1
|
217
|
+
return if @indent == 0
|
218
|
+
|
219
|
+
# survey what we have to work with, keeping track of a possible
|
220
|
+
# split of the last argument or value
|
221
|
+
work = []
|
222
|
+
indent = len = 0
|
223
|
+
trail = split = nil
|
224
|
+
slice = @lines[mark.first..-1]
|
225
|
+
reindent(slice)
|
226
|
+
slice.each_with_index do |line, index|
|
227
|
+
if line.first.start_with? '//'
|
228
|
+
len += @width # comments are a deal breaker
|
229
|
+
else
|
230
|
+
(work.push ' '; len += 1) if trail == line.indent and @indent > 0
|
231
|
+
len += line.map(&:length).inject(&:+)
|
232
|
+
work += line
|
233
|
+
|
234
|
+
if trail == @indent and line.indent == @indent
|
235
|
+
split = [len, work.length, index]
|
236
|
+
break if len >= @width - 10
|
237
|
+
end
|
238
|
+
trail = line.indent
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
if len < @width - 10
|
243
|
+
# full collapse
|
244
|
+
@lines[mark.first..-1] = [Line.new(*work)]
|
245
|
+
@line = @lines.last
|
246
|
+
elsif split and split[0] < @width-10
|
247
|
+
if slice[split[2]].indent < slice[split[2]+1].indent
|
248
|
+
# collapse all but the last argument (typically a hash or function)
|
249
|
+
close = slice.pop
|
250
|
+
slice[-1].push *close
|
251
|
+
@lines[mark.first] = Line.new(*work[0..split[1]-1])
|
252
|
+
@lines[mark.first+1..-1] = slice[split[2]+1..-1]
|
253
|
+
@line = @lines.last
|
254
|
+
end
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
# return the output as a string
|
259
|
+
def to_s
|
260
|
+
return @str if @str
|
261
|
+
respace
|
262
|
+
@lines.map(&:to_s).join(@nl)
|
263
|
+
end
|
264
|
+
|
265
|
+
def to_str
|
266
|
+
@str ||= to_s
|
267
|
+
end
|
268
|
+
|
269
|
+
def +(value)
|
270
|
+
to_s+value
|
271
|
+
end
|
272
|
+
|
273
|
+
BASE64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
|
274
|
+
|
275
|
+
# https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit
|
276
|
+
def vlq(*mark)
|
277
|
+
if @mark[0] == mark[0]
|
278
|
+
return if @mark[-3..-1] == mark[-3..-1]
|
279
|
+
@mappings << ',' unless @mappings == ''
|
280
|
+
end
|
281
|
+
|
282
|
+
while @mark[0] < mark[0]
|
283
|
+
@mappings << ';'
|
284
|
+
@mark[0] += 1
|
285
|
+
@mark[1] = 0
|
286
|
+
end
|
287
|
+
|
288
|
+
diffs = mark.zip(@mark).map {|a,b| a-b}
|
289
|
+
@mark = mark
|
290
|
+
|
291
|
+
diffs[1..4].each do |diff|
|
292
|
+
if diff < 0
|
293
|
+
data = (-diff << 1) + 1
|
294
|
+
else
|
295
|
+
data = diff << 1
|
296
|
+
end
|
297
|
+
|
298
|
+
encoded = ''
|
299
|
+
|
300
|
+
begin
|
301
|
+
digit = data & 0b11111
|
302
|
+
data >>= 5
|
303
|
+
digit |= 0b100000 if data > 0
|
304
|
+
encoded << BASE64[digit]
|
305
|
+
end while data > 0
|
306
|
+
|
307
|
+
@mappings << encoded
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
311
|
+
def sourcemap
|
312
|
+
respace
|
313
|
+
|
314
|
+
@mappings = ''
|
315
|
+
sources = []
|
316
|
+
@mark = [0, 0, 0, 0, 0]
|
317
|
+
|
318
|
+
@lines.each_with_index do |line, row|
|
319
|
+
col = line.indent
|
320
|
+
line.each do |token|
|
321
|
+
if token != ' ' and token.loc
|
322
|
+
pos = token.loc.expression.begin_pos
|
323
|
+
|
324
|
+
buffer = token.loc.expression.source_buffer
|
325
|
+
source_index = sources.index(buffer)
|
326
|
+
if not source_index
|
327
|
+
source_index = sources.length
|
328
|
+
timestamp buffer.name
|
329
|
+
sources << buffer
|
330
|
+
end
|
331
|
+
|
332
|
+
split = buffer.source[0...pos].split("\n")
|
333
|
+
vlq row, col, source_index, split.length-1, split.last.to_s.length
|
334
|
+
end
|
335
|
+
col += token.length
|
336
|
+
end
|
337
|
+
end
|
338
|
+
|
339
|
+
@sourcemap = {
|
340
|
+
version: 3,
|
341
|
+
file: @ast.loc.expression.source_buffer.name,
|
342
|
+
sources: sources.map(&:name),
|
343
|
+
mappings: @mappings
|
344
|
+
}
|
345
|
+
end
|
346
|
+
end
|
347
|
+
end
|