wovnrb 3.11.0 → 3.13.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.
- checksums.yaml +4 -4
- data/.rubocop.yml +3 -0
- data/README.en.md +256 -256
- data/README.ja.md +218 -218
- data/docker/rails/TestSite/config/application.rb +1 -2
- data/docker/rails/TestSite/yarn.lock +7449 -7353
- data/lib/wovnrb/api_translator.rb +186 -183
- data/lib/wovnrb/headers.rb +192 -192
- data/lib/wovnrb/lang.rb +260 -260
- data/lib/wovnrb/services/html_converter.rb +240 -222
- data/lib/wovnrb/services/html_replace_marker.rb +48 -48
- data/lib/wovnrb/settings.rb +2 -2
- data/lib/wovnrb/store.rb +230 -222
- data/lib/wovnrb/version.rb +3 -3
- data/lib/wovnrb.rb +146 -145
- data/test/lib/api_translator_test.rb +228 -217
- data/test/lib/custom_domain/custom_domain_langs_test.rb +2 -2
- data/test/lib/lang_test.rb +59 -59
- data/test/lib/services/html_converter_test.rb +570 -532
- data/test/lib/services/html_replace_marker_test.rb +149 -149
- data/test/lib/url_language_switcher_test.rb +1097 -1097
- data/test/lib/wovnrb_test.rb +477 -454
- data/test/test_helper.rb +1 -0
- metadata +6 -6
|
@@ -1,222 +1,240 @@
|
|
|
1
|
-
module Wovnrb
|
|
2
|
-
class HtmlConverter
|
|
3
|
-
def initialize(dom, store, headers, url_lang_switcher)
|
|
4
|
-
@dom = dom
|
|
5
|
-
@headers = headers
|
|
6
|
-
@store = store
|
|
7
|
-
@url_lang_switcher = url_lang_switcher
|
|
8
|
-
end
|
|
9
|
-
|
|
10
|
-
def build
|
|
11
|
-
transform_html
|
|
12
|
-
html
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
def build_api_compatible_html
|
|
16
|
-
marker = HtmlReplaceMarker.new
|
|
17
|
-
converted_html = replace_dom(marker)
|
|
18
|
-
converted_html = remove_backend_wovn_ignore_comments(converted_html, marker)
|
|
19
|
-
[converted_html, marker]
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
private
|
|
23
|
-
|
|
24
|
-
def remove_backend_wovn_ignore_comments(html, marker)
|
|
25
|
-
backend_ignore_regex = /(<!--\s*backend-wovn-ignore\s*-->)(.+?)(<!--\s*\/backend-wovn-ignore\s*-->)/m
|
|
26
|
-
html.gsub(backend_ignore_regex) do |_match|
|
|
27
|
-
comment_start = Regexp.last_match(1)
|
|
28
|
-
ignored_content = Regexp.last_match(2)
|
|
29
|
-
comment_end = Regexp.last_match(3)
|
|
30
|
-
key = marker.add_comment_value(ignored_content)
|
|
31
|
-
comment_start + key + comment_end
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
def html
|
|
36
|
-
# Ensure a Content-Type declaration in the header. This mimics Nokogumbo
|
|
37
|
-
# 1.5.0 default serialization behavior.
|
|
38
|
-
@dom.meta_encoding = 'UTF-8' if @dom.respond_to?(:meta_encoding=)
|
|
39
|
-
|
|
40
|
-
@dom.to_html(save_with: 0).strip
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
def transform_html
|
|
44
|
-
replace_snippet
|
|
45
|
-
replace_hreflangs if @store.settings['insert_hreflangs']
|
|
46
|
-
inject_lang_html_tag
|
|
47
|
-
translate_canonical_tag if @store.settings['translate_canonical_tag']
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
def replace_snippet
|
|
51
|
-
strip_snippet
|
|
52
|
-
insert_snippet
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
def replace_dom(marker)
|
|
56
|
-
strip_snippet
|
|
57
|
-
strip_hreflangs if @store.settings['insert_hreflangs']
|
|
58
|
-
|
|
59
|
-
@dom.traverse { |node| transform_node(node, marker) }
|
|
60
|
-
|
|
61
|
-
insert_snippet(adds_backend_error_mark: true)
|
|
62
|
-
insert_hreflang_tags if @store.settings['insert_hreflangs']
|
|
63
|
-
inject_lang_html_tag
|
|
64
|
-
translate_canonical_tag if @store.settings['translate_canonical_tag']
|
|
65
|
-
|
|
66
|
-
html
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
def transform_node(node, marker)
|
|
70
|
-
strip_wovn_ignore(node, marker)
|
|
71
|
-
strip_custom_ignore(node, marker)
|
|
72
|
-
strip_form(node, marker)
|
|
73
|
-
strip_script(node, marker)
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
def strip_script(node, marker)
|
|
77
|
-
put_replace_marker(node, marker) if node.name.casecmp('script').zero?
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
def strip_form(node, marker)
|
|
81
|
-
if node.name.casecmp('form').zero?
|
|
82
|
-
put_replace_marker(node, marker)
|
|
83
|
-
return
|
|
84
|
-
end
|
|
85
|
-
|
|
86
|
-
if node.name.casecmp('input').zero? && node.get_attribute('type') == 'hidden'
|
|
87
|
-
original_text = node.get_attribute('value')
|
|
88
|
-
return if original_text.nil?
|
|
89
|
-
return if original_text.include?(HtmlReplaceMarker::KEY_PREFIX)
|
|
90
|
-
|
|
91
|
-
node.set_attribute('value', marker.add_value(original_text))
|
|
92
|
-
end
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
def strip_custom_ignore(node, marker)
|
|
96
|
-
classes = node.get_attribute('class')
|
|
97
|
-
return unless classes.present?
|
|
98
|
-
|
|
99
|
-
ignored_classes = @store.settings['ignore_class']
|
|
100
|
-
should_be_ignored = (ignored_classes & classes.split).present?
|
|
101
|
-
|
|
102
|
-
put_replace_marker(node, marker) if should_be_ignored
|
|
103
|
-
end
|
|
104
|
-
|
|
105
|
-
def strip_wovn_ignore(node, marker)
|
|
106
|
-
put_replace_marker(node, marker) if node && (node.get_attribute('wovn-ignore') || node.get_attribute('data-wovn-ignore'))
|
|
107
|
-
end
|
|
108
|
-
|
|
109
|
-
def put_replace_marker(node, marker)
|
|
110
|
-
original_text = node.inner_html
|
|
111
|
-
return if original_text.include?(HtmlReplaceMarker::KEY_PREFIX)
|
|
112
|
-
|
|
113
|
-
node.inner_html = marker.add_comment_value(original_text)
|
|
114
|
-
end
|
|
115
|
-
|
|
116
|
-
def strip_hreflangs
|
|
117
|
-
supported_langs = @store.supported_langs
|
|
118
|
-
@dom.xpath('//link') do |node|
|
|
119
|
-
node.remove if node['hreflang'] && supported_langs.include?(Lang.iso_639_1_normalization(node['hreflang']))
|
|
120
|
-
end
|
|
121
|
-
end
|
|
122
|
-
|
|
123
|
-
def inject_lang_html_tag
|
|
124
|
-
root = @dom.at_css('html')
|
|
125
|
-
return unless root
|
|
126
|
-
return if root['lang']
|
|
127
|
-
|
|
128
|
-
root['lang'] = @store.default_lang
|
|
129
|
-
end
|
|
130
|
-
|
|
131
|
-
def replace_hreflangs
|
|
132
|
-
strip_hreflang_tags
|
|
133
|
-
insert_hreflang_tags
|
|
134
|
-
end
|
|
135
|
-
|
|
136
|
-
def strip_hreflang_tags
|
|
137
|
-
@dom.xpath('//link').each do |node|
|
|
138
|
-
node.remove if node['hreflang'] && @store.supported_langs.include?(Lang.iso_639_1_normalization(node['hreflang']))
|
|
139
|
-
end
|
|
140
|
-
end
|
|
141
|
-
|
|
142
|
-
def insert_hreflang_tags
|
|
143
|
-
parent_node = @dom.at_css('head') || @dom.at_css('body') || @dom.at_css('html')
|
|
144
|
-
return unless parent_node
|
|
145
|
-
|
|
146
|
-
@store.supported_langs.each do |lang_code|
|
|
147
|
-
insert_node = Nokogiri::XML::Node.new('link', @dom)
|
|
148
|
-
insert_node['rel'] = 'alternate'
|
|
149
|
-
insert_node['hreflang'] = Lang.iso_639_1_normalization(lang_code)
|
|
150
|
-
insert_node['href'] = @headers.redirect_location(lang_code)
|
|
151
|
-
|
|
152
|
-
parent_node.add_child(insert_node.to_s)
|
|
153
|
-
end
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
1
|
+
module Wovnrb
|
|
2
|
+
class HtmlConverter
|
|
3
|
+
def initialize(dom, store, headers, url_lang_switcher)
|
|
4
|
+
@dom = dom
|
|
5
|
+
@headers = headers
|
|
6
|
+
@store = store
|
|
7
|
+
@url_lang_switcher = url_lang_switcher
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def build
|
|
11
|
+
transform_html
|
|
12
|
+
html
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def build_api_compatible_html
|
|
16
|
+
marker = HtmlReplaceMarker.new
|
|
17
|
+
converted_html = replace_dom(marker)
|
|
18
|
+
converted_html = remove_backend_wovn_ignore_comments(converted_html, marker)
|
|
19
|
+
[converted_html, marker]
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
|
|
24
|
+
def remove_backend_wovn_ignore_comments(html, marker)
|
|
25
|
+
backend_ignore_regex = /(<!--\s*backend-wovn-ignore\s*-->)(.+?)(<!--\s*\/backend-wovn-ignore\s*-->)/m
|
|
26
|
+
html.gsub(backend_ignore_regex) do |_match|
|
|
27
|
+
comment_start = Regexp.last_match(1)
|
|
28
|
+
ignored_content = Regexp.last_match(2)
|
|
29
|
+
comment_end = Regexp.last_match(3)
|
|
30
|
+
key = marker.add_comment_value(ignored_content)
|
|
31
|
+
comment_start + key + comment_end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def html
|
|
36
|
+
# Ensure a Content-Type declaration in the header. This mimics Nokogumbo
|
|
37
|
+
# 1.5.0 default serialization behavior.
|
|
38
|
+
@dom.meta_encoding = 'UTF-8' if @dom.respond_to?(:meta_encoding=)
|
|
39
|
+
|
|
40
|
+
@dom.to_html(save_with: 0).strip
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def transform_html
|
|
44
|
+
replace_snippet
|
|
45
|
+
replace_hreflangs if @store.settings['insert_hreflangs']
|
|
46
|
+
inject_lang_html_tag
|
|
47
|
+
translate_canonical_tag if @store.settings['translate_canonical_tag']
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def replace_snippet
|
|
51
|
+
strip_snippet
|
|
52
|
+
insert_snippet
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def replace_dom(marker)
|
|
56
|
+
strip_snippet
|
|
57
|
+
strip_hreflangs if @store.settings['insert_hreflangs']
|
|
58
|
+
|
|
59
|
+
@dom.traverse { |node| transform_node(node, marker) }
|
|
60
|
+
|
|
61
|
+
insert_snippet(adds_backend_error_mark: true)
|
|
62
|
+
insert_hreflang_tags if @store.settings['insert_hreflangs']
|
|
63
|
+
inject_lang_html_tag
|
|
64
|
+
translate_canonical_tag if @store.settings['translate_canonical_tag']
|
|
65
|
+
|
|
66
|
+
html
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def transform_node(node, marker)
|
|
70
|
+
strip_wovn_ignore(node, marker)
|
|
71
|
+
strip_custom_ignore(node, marker)
|
|
72
|
+
strip_form(node, marker)
|
|
73
|
+
strip_script(node, marker)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def strip_script(node, marker)
|
|
77
|
+
put_replace_marker(node, marker) if node.name.casecmp('script').zero?
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def strip_form(node, marker)
|
|
81
|
+
if node.name.casecmp('form').zero?
|
|
82
|
+
put_replace_marker(node, marker)
|
|
83
|
+
return
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
if node.name.casecmp('input').zero? && node.get_attribute('type') == 'hidden'
|
|
87
|
+
original_text = node.get_attribute('value')
|
|
88
|
+
return if original_text.nil?
|
|
89
|
+
return if original_text.include?(HtmlReplaceMarker::KEY_PREFIX)
|
|
90
|
+
|
|
91
|
+
node.set_attribute('value', marker.add_value(original_text))
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def strip_custom_ignore(node, marker)
|
|
96
|
+
classes = node.get_attribute('class')
|
|
97
|
+
return unless classes.present?
|
|
98
|
+
|
|
99
|
+
ignored_classes = @store.settings['ignore_class']
|
|
100
|
+
should_be_ignored = (ignored_classes & classes.split).present?
|
|
101
|
+
|
|
102
|
+
put_replace_marker(node, marker) if should_be_ignored
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def strip_wovn_ignore(node, marker)
|
|
106
|
+
put_replace_marker(node, marker) if node && (node.get_attribute('wovn-ignore') || node.get_attribute('data-wovn-ignore'))
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def put_replace_marker(node, marker)
|
|
110
|
+
original_text = node.inner_html
|
|
111
|
+
return if original_text.include?(HtmlReplaceMarker::KEY_PREFIX)
|
|
112
|
+
|
|
113
|
+
node.inner_html = marker.add_comment_value(original_text)
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def strip_hreflangs
|
|
117
|
+
supported_langs = @store.supported_langs
|
|
118
|
+
@dom.xpath('//link') do |node|
|
|
119
|
+
node.remove if node['hreflang'] && supported_langs.include?(Lang.iso_639_1_normalization(node['hreflang']))
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def inject_lang_html_tag
|
|
124
|
+
root = @dom.at_css('html')
|
|
125
|
+
return unless root
|
|
126
|
+
return if root['lang']
|
|
127
|
+
|
|
128
|
+
root['lang'] = @store.default_lang
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def replace_hreflangs
|
|
132
|
+
strip_hreflang_tags
|
|
133
|
+
insert_hreflang_tags
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def strip_hreflang_tags
|
|
137
|
+
@dom.xpath('//link').each do |node|
|
|
138
|
+
node.remove if node['hreflang'] && @store.supported_langs.include?(Lang.iso_639_1_normalization(node['hreflang']))
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def insert_hreflang_tags
|
|
143
|
+
parent_node = @dom.at_css('head') || @dom.at_css('body') || @dom.at_css('html')
|
|
144
|
+
return unless parent_node
|
|
145
|
+
|
|
146
|
+
@store.supported_langs.each do |lang_code|
|
|
147
|
+
insert_node = Nokogiri::XML::Node.new('link', @dom)
|
|
148
|
+
insert_node['rel'] = 'alternate'
|
|
149
|
+
insert_node['hreflang'] = Lang.iso_639_1_normalization(lang_code)
|
|
150
|
+
insert_node['href'] = @headers.redirect_location(lang_code)
|
|
151
|
+
|
|
152
|
+
parent_node.add_child(insert_node.to_s)
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
unless existing_x_default_hreflang?
|
|
156
|
+
insert_node = Nokogiri::XML::Node.new('link', @dom)
|
|
157
|
+
insert_node['rel'] = 'alternate'
|
|
158
|
+
insert_node['hreflang'] = 'x-default'
|
|
159
|
+
insert_node['data-wovn'] = 'true'
|
|
160
|
+
x_default_lang_code = @store.hreflang_x_default_lang_or_default
|
|
161
|
+
insert_node['href'] = @headers.redirect_location(x_default_lang_code)
|
|
162
|
+
parent_node.add_child(insert_node.to_s)
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
def existing_x_default_hreflang?
|
|
167
|
+
@dom.xpath('//link').each do |node|
|
|
168
|
+
return true if node['rel'].casecmp('alternate').zero? && node['hreflang'] && node['hreflang'].casecmp('x-default').zero?
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
false
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def translate_canonical_tag
|
|
175
|
+
canonical_node = @dom.at_css('link[rel="canonical"]')
|
|
176
|
+
return unless canonical_node
|
|
177
|
+
|
|
178
|
+
lang_code = @headers.lang_code
|
|
179
|
+
return if lang_code == @store.settings['default_lang'] && @store.settings['custom_lang_aliases'][lang_code].nil?
|
|
180
|
+
|
|
181
|
+
canonical_url = canonical_node['href']
|
|
182
|
+
|
|
183
|
+
translated_canonical_url = @url_lang_switcher.add_lang_code(canonical_url, lang_code, @headers)
|
|
184
|
+
canonical_node['href'] = translated_canonical_url
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
# Remove wovn snippet code from dom
|
|
188
|
+
def strip_snippet
|
|
189
|
+
@dom.xpath('//script').each do |script_node|
|
|
190
|
+
script_node.remove if (script_node['src'] && widget_urls.any? { |url| script_node['src'].include? url }) || script_node['data-wovnio'].present?
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
def widget_urls
|
|
195
|
+
["#{@store.settings['api_url']}/widget", 'j.wovn.io', 'j.dev-wovn.io:3000']
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
def insert_snippet(adds_backend_error_mark: true)
|
|
199
|
+
parent_node = @dom.at_css('head') || @dom.at_css('body') || @dom.at_css('html')
|
|
200
|
+
return unless parent_node
|
|
201
|
+
|
|
202
|
+
insert_node = Nokogiri::XML::Node.new('script', @dom)
|
|
203
|
+
insert_node['src'] = @store.widget_url
|
|
204
|
+
insert_node['async'] = true
|
|
205
|
+
insert_node['data-wovnio'] = data_wovnio
|
|
206
|
+
insert_node['data-wovnio-type'] = 'fallback_snippet' if adds_backend_error_mark
|
|
207
|
+
# do this so that there will be a closing tag (better compatibility with browsers)
|
|
208
|
+
insert_node.content = ''
|
|
209
|
+
|
|
210
|
+
if parent_node.children.empty?
|
|
211
|
+
parent_node.add_child(insert_node)
|
|
212
|
+
else
|
|
213
|
+
parent_node.children.first.add_previous_sibling(insert_node)
|
|
214
|
+
end
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
def data_wovnio
|
|
218
|
+
token = @store.settings['project_token']
|
|
219
|
+
current_lang = @headers.lang_code
|
|
220
|
+
default_lang = @store.settings['default_lang']
|
|
221
|
+
url_pattern = @store.settings['url_pattern']
|
|
222
|
+
lang_code_aliases_json = JSON.generate(@store.settings['custom_lang_aliases'])
|
|
223
|
+
lang_param_name = @store.settings['lang_param_name']
|
|
224
|
+
custom_domain_langs = @store.custom_domain_langs.to_html_swapper_hash
|
|
225
|
+
|
|
226
|
+
result = [
|
|
227
|
+
"key=#{token}",
|
|
228
|
+
'backend=true',
|
|
229
|
+
"currentLang=#{current_lang}",
|
|
230
|
+
"defaultLang=#{default_lang}",
|
|
231
|
+
"urlPattern=#{url_pattern}",
|
|
232
|
+
"langCodeAliases=#{lang_code_aliases_json}",
|
|
233
|
+
"langParamName=#{lang_param_name}",
|
|
234
|
+
"version=WOVN.rb_#{VERSION}"
|
|
235
|
+
]
|
|
236
|
+
result << "customDomainLangs=#{JSON.generate(custom_domain_langs)}" unless custom_domain_langs.empty?
|
|
237
|
+
result.join('&')
|
|
238
|
+
end
|
|
239
|
+
end
|
|
240
|
+
end
|
|
@@ -1,48 +1,48 @@
|
|
|
1
|
-
module Wovnrb
|
|
2
|
-
class HtmlReplaceMarker
|
|
3
|
-
KEY_PREFIX = '__wovn-backend-ignored-key-'.freeze
|
|
4
|
-
|
|
5
|
-
def initialize
|
|
6
|
-
@current_key_number = 0
|
|
7
|
-
@mapped_values = []
|
|
8
|
-
end
|
|
9
|
-
|
|
10
|
-
# Add argument's value to mapping information with comment style key
|
|
11
|
-
def add_comment_value(value)
|
|
12
|
-
key = "<!-- #{generate_key} -->"
|
|
13
|
-
@mapped_values << [key, value]
|
|
14
|
-
|
|
15
|
-
key
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
def add_value(value)
|
|
19
|
-
key = generate_key
|
|
20
|
-
@mapped_values << [key, value]
|
|
21
|
-
|
|
22
|
-
key
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
def revert(marked_html)
|
|
26
|
-
i = @mapped_values.size
|
|
27
|
-
while i > 0
|
|
28
|
-
i -= 1
|
|
29
|
-
key, value = @mapped_values[i]
|
|
30
|
-
marked_html = marked_html.sub(key, value)
|
|
31
|
-
end
|
|
32
|
-
marked_html
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
def keys
|
|
36
|
-
@mapped_values.map { |v| v[0] }
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
private
|
|
40
|
-
|
|
41
|
-
def generate_key
|
|
42
|
-
next_key = "#{KEY_PREFIX}#{@current_key_number}"
|
|
43
|
-
@current_key_number += 1
|
|
44
|
-
|
|
45
|
-
next_key
|
|
46
|
-
end
|
|
47
|
-
end
|
|
48
|
-
end
|
|
1
|
+
module Wovnrb
|
|
2
|
+
class HtmlReplaceMarker
|
|
3
|
+
KEY_PREFIX = '__wovn-backend-ignored-key-'.freeze
|
|
4
|
+
|
|
5
|
+
def initialize
|
|
6
|
+
@current_key_number = 0
|
|
7
|
+
@mapped_values = []
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
# Add argument's value to mapping information with comment style key
|
|
11
|
+
def add_comment_value(value)
|
|
12
|
+
key = "<!-- #{generate_key} -->"
|
|
13
|
+
@mapped_values << [key, value]
|
|
14
|
+
|
|
15
|
+
key
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def add_value(value)
|
|
19
|
+
key = generate_key
|
|
20
|
+
@mapped_values << [key, value]
|
|
21
|
+
|
|
22
|
+
key
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def revert(marked_html)
|
|
26
|
+
i = @mapped_values.size
|
|
27
|
+
while i > 0
|
|
28
|
+
i -= 1
|
|
29
|
+
key, value = @mapped_values[i]
|
|
30
|
+
marked_html = marked_html.sub(key, value)
|
|
31
|
+
end
|
|
32
|
+
marked_html
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def keys
|
|
36
|
+
@mapped_values.map { |v| v[0] }
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
private
|
|
40
|
+
|
|
41
|
+
def generate_key
|
|
42
|
+
next_key = "#{KEY_PREFIX}#{@current_key_number}"
|
|
43
|
+
@current_key_number += 1
|
|
44
|
+
|
|
45
|
+
next_key
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
data/lib/wovnrb/settings.rb
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
module Wovnrb
|
|
2
2
|
class Settings < Hash
|
|
3
3
|
def initialize(*args, **kwargs)
|
|
4
|
-
super
|
|
4
|
+
super
|
|
5
5
|
@dynamic_settings = {}
|
|
6
6
|
end
|
|
7
7
|
|
|
@@ -9,7 +9,7 @@ module Wovnrb
|
|
|
9
9
|
return @dynamic_settings[key] if @dynamic_settings.key?(key)
|
|
10
10
|
return IgnoreGlobsWrapper.new(ignore_globs) if key == 'ignore_globs'
|
|
11
11
|
|
|
12
|
-
super
|
|
12
|
+
super
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
def ignore_globs
|