hot_module 1.0.0.alpha1 → 1.0.0.alpha2
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.
- checksums.yaml +4 -4
- data/Gemfile.lock +3 -2
- data/benchmark.rb +14 -0
- data/hot_module.gemspec +1 -1
- data/lib/hot_module/fragment.rb +4 -2
- data/lib/hot_module/petite.rb +20 -124
- data/lib/hot_module/query_selection.rb +2 -1
- data/lib/hot_module/version.rb +1 -1
- data/lib/hot_module.rb +148 -18
- metadata +6 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 213948e4061c8dfb1da32e9621365caaa4d5594125f03c63802ff3fb53aa3b24
|
4
|
+
data.tar.gz: b4077c814479ea1d65d2143eaf6f6b7abba996787408846474c3933ffccf1fa9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 76b4783da63ac259d17c0fa78c1a30b51f2919fbbbe1a5e007c315d3facb3249ffab2c0538d42322654868faf5b45f342a70b79f4b91c64ee67638644583a283
|
7
|
+
data.tar.gz: 00c1db27bd91bc5ea110af3bc26db58dc254b43960b182f327f938ea2f6e1eb440cde6ff4c9e40c2732d215600d671c0e73eeb005178174aa9005e6a3bdfb746
|
data/Gemfile.lock
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
hot_module (1.0.0.
|
5
|
-
|
4
|
+
hot_module (1.0.0.alpha2)
|
5
|
+
nokolexbor (~> 0.3)
|
6
6
|
|
7
7
|
GEM
|
8
8
|
remote: https://rubygems.org/
|
@@ -33,6 +33,7 @@ GEM
|
|
33
33
|
racc (~> 1.4)
|
34
34
|
nokogiri (1.13.8-x86_64-linux)
|
35
35
|
racc (~> 1.4)
|
36
|
+
nokolexbor (0.3.7-arm64-darwin)
|
36
37
|
parallel (1.22.1)
|
37
38
|
parser (3.1.2.1)
|
38
39
|
ast (~> 2.4.1)
|
data/benchmark.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
$LOAD_PATH.unshift File.expand_path("lib", __dir__)
|
2
|
+
require "hot_module"
|
3
|
+
|
4
|
+
require_relative "test/fixtures/classes"
|
5
|
+
|
6
|
+
require "benchmark"
|
7
|
+
|
8
|
+
Benchmark.bmbm do |x|
|
9
|
+
x.report("render") do
|
10
|
+
1000.times do |i|
|
11
|
+
Templated.new(name: i.to_s).()
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
data/hot_module.gemspec
CHANGED
data/lib/hot_module/fragment.rb
CHANGED
@@ -22,15 +22,17 @@ module HoTModuLe
|
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
|
-
def process_attribute_bindings(node)
|
25
|
+
def process_attribute_bindings(node) # rubocop:todo Metrics
|
26
26
|
node.attributes.each do |name, attr_node|
|
27
27
|
@attribute_bindings.each do |attribute_binding|
|
28
|
+
next if attribute_binding.only_for_tag && node.name != attribute_binding.only_for_tag.to_s
|
28
29
|
next unless attribute_binding.matcher.match?(name)
|
30
|
+
next if attribute_binding.method.receiver._check_stack(node)
|
29
31
|
|
30
32
|
break unless attribute_binding.method.(attribute: attr_node, node: node)
|
31
33
|
end
|
32
34
|
rescue Exception => e # rubocop:disable Lint/RescueException
|
33
|
-
raise e.class, e.message.lines.first, ["#{@html_module}:#{attr_node
|
35
|
+
raise e.class, e.message.lines.first, ["#{@html_module}:#{attr_node}", *e.backtrace]
|
34
36
|
end
|
35
37
|
end
|
36
38
|
end
|
data/lib/hot_module/petite.rb
CHANGED
@@ -2,95 +2,41 @@
|
|
2
2
|
|
3
3
|
require "hot_module"
|
4
4
|
|
5
|
-
module JSStrings
|
6
|
-
refine Kernel do
|
7
|
-
def `(str)
|
8
|
-
str
|
9
|
-
end
|
10
|
-
end
|
11
|
-
refine String do
|
12
|
-
def underscore
|
13
|
-
gsub(/([A-Z]+)(?=[A-Z][a-z])|([a-z\d])(?=[A-Z])/) do
|
14
|
-
(::Regexp.last_match(1) || ::Regexp.last_match(2)) << "_"
|
15
|
-
end.tr("-", "_").downcase
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
5
|
module HoTModuLe
|
21
6
|
module Petite
|
22
|
-
using JSStrings
|
23
|
-
|
24
7
|
# @param klass [Class]
|
25
8
|
# @return [void]
|
26
9
|
def self.included(klass)
|
27
|
-
klass.attribute_binding "v-for", :
|
28
|
-
klass.attribute_binding "v-text", :
|
29
|
-
klass.attribute_binding "v-html", :
|
30
|
-
klass.attribute_binding "v-bind", :
|
31
|
-
klass.attribute_binding %r{^:}, :
|
10
|
+
klass.attribute_binding "v-for", :_petite_for_binding, only: :template
|
11
|
+
klass.attribute_binding "v-text", :_petite_text_binding
|
12
|
+
klass.attribute_binding "v-html", :_petite_html_binding
|
13
|
+
klass.attribute_binding "v-bind", :_petite_bound_attribute
|
14
|
+
klass.attribute_binding %r{^:}, :_petite_bound_attribute
|
32
15
|
end
|
33
16
|
|
34
17
|
protected
|
35
18
|
|
36
|
-
def
|
37
|
-
|
38
|
-
|
39
|
-
@_locals.keys.reverse_each do |name|
|
40
|
-
eval_code = "#{name} = @_locals[\"#{name}\"];" + eval_code
|
41
|
-
end
|
42
|
-
instance_eval(eval_code, self.class.html_module, attribute.line)
|
43
|
-
rescue NameError => e
|
44
|
-
bad_name = e.message.match(/`(.*?)'/)[1]
|
45
|
-
suggestion = bad_name.underscore
|
46
|
-
eval_code.gsub!(bad_name, suggestion)
|
47
|
-
instance_eval(eval_code, self.class.html_module, attribute.line)
|
48
|
-
end
|
49
|
-
|
50
|
-
def _locals_stack
|
51
|
-
@_locals_stack ||= []
|
52
|
-
end
|
53
|
-
|
54
|
-
def _check_stack(node) # rubocop:disable Metrics/AbcSize
|
55
|
-
node_and_ancestors = [node, *node.ancestors.to_a]
|
56
|
-
stack_misses = 0
|
57
|
-
|
58
|
-
stack_nodes = _locals_stack.map { _1[:node] }
|
59
|
-
stack_nodes.each do |stack_node|
|
60
|
-
if node_and_ancestors.none? { _1["v-if"] == "!hydrated" } && node_and_ancestors.none? { _1 == stack_node }
|
61
|
-
stack_misses += 1
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
stack_misses.times { _locals_stack.pop }
|
66
|
-
|
67
|
-
!((node_and_ancestors & _locals_stack.map { _1[:node] }).empty?) # rubocop:disable Style/RedundantParentheses
|
68
|
-
end
|
69
|
-
|
70
|
-
def _for_binding(attribute:, node:)
|
71
|
-
return unless node.name == "template"
|
72
|
-
|
73
|
-
return if _check_stack(node)
|
19
|
+
def _petite_for_binding(attribute:, node:)
|
20
|
+
delimiter = node["v-for"].include?(" of ") ? " of " : " in "
|
21
|
+
expression = node["v-for"].split(delimiter)
|
74
22
|
|
75
|
-
|
76
|
-
|
23
|
+
process_list(
|
24
|
+
attribute: attribute,
|
25
|
+
node: node,
|
26
|
+
item_node: node.children[0].children.find(&:element?),
|
27
|
+
for_in: expression
|
28
|
+
)
|
77
29
|
end
|
78
30
|
|
79
|
-
def
|
80
|
-
|
81
|
-
|
82
|
-
node.content = evaluate_attribute_expression(attribute)
|
31
|
+
def _petite_text_binding(attribute:, node:)
|
32
|
+
node.content = evaluate_attribute_expression(attribute).to_s
|
83
33
|
end
|
84
34
|
|
85
|
-
def
|
86
|
-
|
87
|
-
|
88
|
-
node.content = evaluate_attribute_expression(attribute)
|
35
|
+
def _petite_html_binding(attribute:, node:)
|
36
|
+
node.inner_html = evaluate_attribute_expression(attribute).to_s
|
89
37
|
end
|
90
38
|
|
91
|
-
def
|
92
|
-
return if _check_stack(node)
|
93
|
-
|
39
|
+
def _petite_bound_attribute(attribute:, node:) # rubocop:disable Metrics
|
94
40
|
return if attribute.name == ":key"
|
95
41
|
|
96
42
|
real_attribute = if attribute.name.start_with?(":")
|
@@ -102,60 +48,10 @@ module HoTModuLe
|
|
102
48
|
obj = evaluate_attribute_expression(attribute)
|
103
49
|
|
104
50
|
if real_attribute == "class"
|
105
|
-
|
106
|
-
when Hash
|
107
|
-
obj.filter { |_k, v| v == true }.keys
|
108
|
-
when Array
|
109
|
-
# TODO: handle objects inside of an array
|
110
|
-
obj
|
111
|
-
else
|
112
|
-
Array[obj]
|
113
|
-
end
|
114
|
-
node[real_attribute] = class_names.join(" ")
|
51
|
+
node[real_attribute] = class_list_for(obj)
|
115
52
|
elsif real_attribute != "style" # style bindings aren't SSRed
|
116
53
|
node[real_attribute] = obj if obj
|
117
54
|
end
|
118
55
|
end
|
119
|
-
|
120
|
-
def _process_list(attribute:, node:) # rubocop:disable Metrics
|
121
|
-
item_node = node.element_children.first
|
122
|
-
|
123
|
-
delimiter = node["v-for"].include?(" of ") ? " of " : " in "
|
124
|
-
expression = node["v-for"].split(delimiter)
|
125
|
-
lh = expression[0].strip.delete_prefix("(").delete_suffix(")").split(",").map!(&:strip)
|
126
|
-
rh = expression[1].strip
|
127
|
-
|
128
|
-
list_items = evaluate_attribute_expression(attribute, rh)
|
129
|
-
|
130
|
-
# TODO: handle object style
|
131
|
-
# https://vuejs.org/guide/essentials/list.html#v-for-with-an-object
|
132
|
-
|
133
|
-
return unless list_items
|
134
|
-
|
135
|
-
_in_locals_stack do
|
136
|
-
list_items.each_with_index do |list_item, index|
|
137
|
-
new_node = item_node.clone
|
138
|
-
node.parent << new_node
|
139
|
-
new_node["v-if"] = "!hydrated"
|
140
|
-
|
141
|
-
local_items = { **(prev_items || {}) }
|
142
|
-
local_items[lh[0]] = list_item
|
143
|
-
local_items[lh[1]] = index if lh[1]
|
144
|
-
|
145
|
-
@_locals = local_items
|
146
|
-
|
147
|
-
Fragment.new(
|
148
|
-
new_node, self.class.attribute_bindings,
|
149
|
-
html_module: self.class.html_module
|
150
|
-
).process
|
151
|
-
end
|
152
|
-
end
|
153
|
-
end
|
154
|
-
|
155
|
-
def _in_locals_stack
|
156
|
-
prev_items = @_locals
|
157
|
-
yield
|
158
|
-
@_locals = prev_items
|
159
|
-
end
|
160
56
|
end
|
161
57
|
end
|
@@ -12,5 +12,6 @@ module HoTModuLe
|
|
12
12
|
def query_selector_all(selector) = css(selector)
|
13
13
|
end
|
14
14
|
|
15
|
-
|
15
|
+
# TODO: do we need this, or no?
|
16
|
+
# Nokogiri::XML::Node.include QuerySelection unless Nokogiri::XML::Node.instance_methods.include?(:query_selector)
|
16
17
|
end
|
data/lib/hot_module/version.rb
CHANGED
data/lib/hot_module.rb
CHANGED
@@ -2,16 +2,26 @@
|
|
2
2
|
|
3
3
|
require_relative "hot_module/version"
|
4
4
|
|
5
|
-
require "
|
5
|
+
require "nokolexbor"
|
6
6
|
|
7
7
|
# Include this module into your own component class
|
8
8
|
module HoTModuLe
|
9
9
|
class Error < StandardError; end
|
10
10
|
|
11
|
-
|
11
|
+
module JSTemplateLiterals
|
12
|
+
refine Kernel do
|
13
|
+
def `(str)
|
14
|
+
str
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
using JSTemplateLiterals
|
20
|
+
|
21
|
+
AttributeBinding = Struct.new(:matcher, :method_name, :method, :only_for_tag, keyword_init: true) # rubocop:disable Lint/StructNewOverride
|
12
22
|
|
13
23
|
require_relative "hot_module/fragment"
|
14
|
-
require_relative "hot_module/query_selection"
|
24
|
+
# require_relative "hot_module/query_selection"
|
15
25
|
|
16
26
|
# @param klass [Class]
|
17
27
|
# @return [void]
|
@@ -25,7 +35,11 @@ module HoTModuLe
|
|
25
35
|
|
26
36
|
# Extends the component class
|
27
37
|
module ClassMethods
|
28
|
-
def
|
38
|
+
def camelcased(method_symbol)
|
39
|
+
alias_method(method_symbol.to_s.gsub(/(?!^)_[a-z0-9]/) { |match| match[1].upcase }, method_symbol)
|
40
|
+
end
|
41
|
+
|
42
|
+
def html_file_extensions = %w[module.html tmpl.html html].freeze
|
29
43
|
def processed_css_extension = "css-local"
|
30
44
|
|
31
45
|
# @param tag_name [String]
|
@@ -76,19 +90,20 @@ module HoTModuLe
|
|
76
90
|
|
77
91
|
# @return [Nokogiri::XML::Element]
|
78
92
|
def doc
|
79
|
-
@doc ||=
|
80
|
-
"<#{tag_name}>#{File.read(html_module)}</#{tag_name}>"
|
81
|
-
).
|
93
|
+
@doc ||= Nokolexbor::DocumentFragment.parse(
|
94
|
+
"<#{tag_name}>#{File.read(html_module).strip}</#{tag_name}>"
|
95
|
+
).children.find(&:element?)
|
82
96
|
end
|
83
97
|
|
84
98
|
def attribute_bindings
|
85
99
|
@attribute_bindings ||= []
|
86
100
|
end
|
87
101
|
|
88
|
-
def attribute_binding(matcher, method_name)
|
102
|
+
def attribute_binding(matcher, method_name, only: nil)
|
89
103
|
attribute_bindings << AttributeBinding.new(
|
90
104
|
matcher: Regexp.new(matcher),
|
91
|
-
method_name: method_name
|
105
|
+
method_name: method_name,
|
106
|
+
only_for_tag: only
|
92
107
|
)
|
93
108
|
end
|
94
109
|
end
|
@@ -110,12 +125,24 @@ module HoTModuLe
|
|
110
125
|
# @param return_node [Boolean]
|
111
126
|
def render_element(attributes: self.attributes, content: self.content, return_node: false) # rubocop:disable Metrics
|
112
127
|
doc = self.class.doc.clone
|
128
|
+
|
129
|
+
# NOTE: have to fix cloned templates
|
130
|
+
doc.css("template").each do |bad_tmpl|
|
131
|
+
frag = bad_tmpl.children.last
|
132
|
+
new_tmpl = doc.document.create_element("template")
|
133
|
+
bad_tmpl.attributes.each do |k, v|
|
134
|
+
new_tmpl[k] = v
|
135
|
+
end
|
136
|
+
new_tmpl.children[0].children = frag
|
137
|
+
bad_tmpl.swap(new_tmpl)
|
138
|
+
end
|
139
|
+
|
113
140
|
tmpl_el = doc.css("> template").find { _1.attributes.length.zero? }
|
114
141
|
|
115
142
|
unless tmpl_el
|
116
143
|
tmpl_el = doc.document.create_element("template")
|
117
144
|
immediate_children = doc.css("> :not(style):not(script)")
|
118
|
-
tmpl_el << immediate_children
|
145
|
+
tmpl_el.children[0] << immediate_children
|
119
146
|
doc.prepend_child(tmpl_el)
|
120
147
|
end
|
121
148
|
|
@@ -123,7 +150,7 @@ module HoTModuLe
|
|
123
150
|
process_fragment(tmpl_el)
|
124
151
|
|
125
152
|
# Set attributes on the custom element
|
126
|
-
attributes.each { |k, v| doc[k.to_s.tr("_", "-")] = v }
|
153
|
+
attributes.each { |k, v| doc[k.to_s.tr("_", "-")] = value_to_attribute(v) if v }
|
127
154
|
|
128
155
|
# Look for external and internal styles
|
129
156
|
output_styles = ""
|
@@ -160,13 +187,13 @@ module HoTModuLe
|
|
160
187
|
|
161
188
|
if self.class.shadow_root
|
162
189
|
# Guess what? We can reuse the same template tag! =)
|
163
|
-
tmpl_el["
|
164
|
-
tmpl_el << style_tag if style_tag
|
190
|
+
tmpl_el["shadowrootmode"] = "open"
|
191
|
+
tmpl_el.children[0] << style_tag if style_tag
|
165
192
|
doc << content if content
|
166
193
|
else
|
167
|
-
tmpl_el << style_tag if style_tag
|
168
|
-
tmpl_el.at_css("slot:not([name])")&.swap(content) if content
|
169
|
-
tmpl_el.children.each do |node|
|
194
|
+
tmpl_el.children[0] << style_tag if style_tag
|
195
|
+
tmpl_el.children[0].at_css("slot:not([name])")&.swap(content) if content
|
196
|
+
tmpl_el.children[0].children.each do |node|
|
170
197
|
doc << node
|
171
198
|
end
|
172
199
|
tmpl_el.remove
|
@@ -180,6 +207,21 @@ module HoTModuLe
|
|
180
207
|
render_element(...)
|
181
208
|
end
|
182
209
|
|
210
|
+
def inspect
|
211
|
+
"#<#{self.class.name} #{attributes}>"
|
212
|
+
end
|
213
|
+
|
214
|
+
def value_to_attribute(val)
|
215
|
+
case val
|
216
|
+
when String, Numeric
|
217
|
+
val
|
218
|
+
when TrueClass
|
219
|
+
""
|
220
|
+
else
|
221
|
+
val.to_json
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
183
225
|
# Override in component if need be, otherwise we'll use the node walker/binding pipeline
|
184
226
|
#
|
185
227
|
# @param fragment [Nokogiri::XML::Element]
|
@@ -191,7 +233,95 @@ module HoTModuLe
|
|
191
233
|
).process
|
192
234
|
end
|
193
235
|
|
194
|
-
def
|
195
|
-
|
236
|
+
def process_list(attribute:, node:, item_node:, for_in:) # rubocop:disable Metrics
|
237
|
+
_context_nodes.push(node)
|
238
|
+
|
239
|
+
lh = for_in[0].strip.delete_prefix("(").delete_suffix(")").split(",").map!(&:strip)
|
240
|
+
rh = for_in[1].strip
|
241
|
+
|
242
|
+
list_items = evaluate_attribute_expression(attribute, rh)
|
243
|
+
|
244
|
+
# TODO: handle object style
|
245
|
+
# https://vuejs.org/guide/essentials/list.html#v-for-with-an-object
|
246
|
+
|
247
|
+
return unless list_items
|
248
|
+
|
249
|
+
_in_context_nodes do |previous_context|
|
250
|
+
list_items.each_with_index do |list_item, index|
|
251
|
+
new_node = item_node.clone
|
252
|
+
|
253
|
+
# NOTE: have to fix cloned templates
|
254
|
+
new_node.css("template").each do |bad_tmpl|
|
255
|
+
frag = bad_tmpl.children.last
|
256
|
+
new_tmpl = item_node.document.create_element("template")
|
257
|
+
bad_tmpl.attributes.each do |k, v|
|
258
|
+
new_tmpl[k] = v
|
259
|
+
end
|
260
|
+
new_tmpl.children[0].children = frag
|
261
|
+
bad_tmpl.swap(new_tmpl)
|
262
|
+
end
|
263
|
+
|
264
|
+
node.parent << new_node
|
265
|
+
new_node["hmod-added"] = ""
|
266
|
+
|
267
|
+
@_context_locals = { **(previous_context || {}) }
|
268
|
+
_context_locals[lh[0]] = list_item
|
269
|
+
_context_locals[lh[1]] = index if lh[1]
|
270
|
+
|
271
|
+
Fragment.new(
|
272
|
+
new_node, self.class.attribute_bindings,
|
273
|
+
html_module: self.class.html_module
|
274
|
+
).process
|
275
|
+
end
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
279
|
+
def evaluate_attribute_expression(attribute, eval_code = attribute.value)
|
280
|
+
eval_code = eval_code.gsub(/\${(.*)}/, "\#{\\1}")
|
281
|
+
_context_locals.keys.reverse_each do |name|
|
282
|
+
eval_code = "#{name} = _context_locals[\"#{name}\"];" + eval_code
|
283
|
+
end
|
284
|
+
instance_eval(eval_code, self.class.html_module) # , attribute.line)
|
285
|
+
end
|
286
|
+
|
287
|
+
def class_list_for(obj)
|
288
|
+
case obj
|
289
|
+
when Hash
|
290
|
+
obj.filter { |_k, v| v }.keys
|
291
|
+
when Array
|
292
|
+
# TODO: handle objects inside of an array?
|
293
|
+
obj
|
294
|
+
else
|
295
|
+
Array[obj]
|
296
|
+
end.join(" ")
|
297
|
+
end
|
298
|
+
|
299
|
+
def _context_nodes
|
300
|
+
@_context_nodes ||= []
|
301
|
+
end
|
302
|
+
|
303
|
+
def _context_locals
|
304
|
+
@_context_locals ||= {}
|
305
|
+
end
|
306
|
+
|
307
|
+
def _check_stack(node)
|
308
|
+
node_and_ancestors = [node, *node.ancestors.to_a]
|
309
|
+
stack_misses = 0
|
310
|
+
|
311
|
+
_context_nodes.each do |stack_node|
|
312
|
+
if node_and_ancestors.none? { _1["hmod-added"] } && node_and_ancestors.none? { _1 == stack_node }
|
313
|
+
stack_misses += 1
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
317
|
+
stack_misses.times { _context_nodes.pop }
|
318
|
+
|
319
|
+
node_and_ancestors.any? { _context_nodes.include?(_1) }
|
320
|
+
end
|
321
|
+
|
322
|
+
def _in_context_nodes
|
323
|
+
previous_context = _context_locals
|
324
|
+
yield previous_context
|
325
|
+
@_context_locals = previous_context
|
196
326
|
end
|
197
327
|
end
|
metadata
CHANGED
@@ -1,29 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hot_module
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.0.
|
4
|
+
version: 1.0.0.alpha2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jared White
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-03-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: nokolexbor
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '0.3'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '0.3'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: hash_with_dot_access
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -53,6 +53,7 @@ files:
|
|
53
53
|
- LICENSE.txt
|
54
54
|
- README.md
|
55
55
|
- Rakefile
|
56
|
+
- benchmark.rb
|
56
57
|
- hot_module.gemspec
|
57
58
|
- lib/hot_module.rb
|
58
59
|
- lib/hot_module/fragment.rb
|