wovnrb 1.1.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.circleci/config.yml +1 -0
- data/.gitignore +2 -0
- data/.rubocop.yml +1 -0
- data/.rubocop_todo.yml +308 -0
- data/Rakefile +13 -14
- data/lib/wovnrb.rb +43 -98
- data/lib/wovnrb/api_translator.rb +143 -0
- data/lib/wovnrb/headers.rb +78 -92
- data/lib/wovnrb/helpers/nokogumbo_helper.rb +1 -1
- data/lib/wovnrb/lang.rb +93 -125
- data/lib/wovnrb/railtie.rb +5 -7
- data/lib/wovnrb/services/glob.rb +3 -3
- data/lib/wovnrb/services/html_converter.rb +192 -0
- data/lib/wovnrb/services/html_replace_marker.rb +38 -0
- data/lib/wovnrb/services/wovn_logger.rb +8 -4
- data/lib/wovnrb/settings.rb +5 -3
- data/lib/wovnrb/store.rb +35 -26
- data/lib/wovnrb/text_caches/cache_base.rb +3 -2
- data/lib/wovnrb/text_caches/memory_cache.rb +2 -2
- data/lib/wovnrb/version.rb +1 -1
- data/test/fixtures/html/test.html +8 -0
- data/test/fixtures/html/test_translated.html +8 -0
- data/test/lib/api_translator_test.rb +109 -0
- data/test/lib/headers_test.rb +84 -55
- data/test/lib/lang_test.rb +157 -357
- data/test/lib/services/glob_test.rb +1 -1
- data/test/lib/services/html_converter_test.rb +166 -0
- data/test/lib/services/html_replace_marker_test.rb +75 -0
- data/test/lib/services/wovn_logger_test.rb +6 -6
- data/test/lib/store_test.rb +25 -69
- data/test/lib/text_caches/cache_base_test.rb +1 -1
- data/test/lib/text_caches/memory_cache_test.rb +10 -11
- data/test/lib/wovnrb_test.rb +77 -310
- data/test/test_helper.rb +22 -32
- data/wovnrb.gemspec +35 -44
- metadata +86 -205
- data/ext/dom/Makefile +0 -239
- data/lib/wovnrb/api_data.rb +0 -59
- data/lib/wovnrb/html_replacers/image_replacer.rb +0 -69
- data/lib/wovnrb/html_replacers/input_replacer.rb +0 -38
- data/lib/wovnrb/html_replacers/link_replacer.rb +0 -78
- data/lib/wovnrb/html_replacers/meta_replacer.rb +0 -28
- data/lib/wovnrb/html_replacers/replacer_base.rb +0 -49
- data/lib/wovnrb/html_replacers/script_replacer.rb +0 -39
- data/lib/wovnrb/html_replacers/text_replacer.rb +0 -21
- data/lib/wovnrb/html_replacers/unified_values/dst_swapping_targets_creator.rb +0 -76
- data/lib/wovnrb/html_replacers/unified_values/element_category.rb +0 -242
- data/lib/wovnrb/html_replacers/unified_values/node_swapping_targets_creator.rb +0 -134
- data/lib/wovnrb/html_replacers/unified_values/text_replacer.rb +0 -35
- data/lib/wovnrb/html_replacers/unified_values/text_scraper.rb +0 -152
- data/lib/wovnrb/html_replacers/unified_values/values_stack.rb +0 -65
- data/lib/wovnrb/services/url.rb +0 -12
- data/lib/wovnrb/services/value_agent.rb +0 -9
- data/test/fixtures/unified_values/site_html/simple_actual.html +0 -96
- data/test/fixtures/unified_values/site_html/simple_expected.json +0 -251
- data/test/fixtures/unified_values/site_html/wovn.io_actual.html +0 -686
- data/test/fixtures/unified_values/site_html/wovn.io_expected.json +0 -543
- data/test/fixtures/unified_values/site_html/www.yahoo.co.jp_actual.html +0 -1024
- data/test/fixtures/unified_values/site_html/www.yahoo.co.jp_expected.json +0 -3345
- data/test/fixtures/unified_values/small_html/block_inside_inline_actual.html +0 -12
- data/test/fixtures/unified_values/small_html/block_inside_inline_expected.json +0 -22
- data/test/fixtures/unified_values/small_html/br_tag_actual.html +0 -10
- data/test/fixtures/unified_values/small_html/br_tag_expected.json +0 -12
- data/test/fixtures/unified_values/small_html/comment_tag_actual.html +0 -12
- data/test/fixtures/unified_values/small_html/comment_tag_expected.json +0 -10
- data/test/fixtures/unified_values/small_html/complex_text_with_html_entity_actual.html +0 -7
- data/test/fixtures/unified_values/small_html/complex_text_with_html_entity_expected.json +0 -11
- data/test/fixtures/unified_values/small_html/deep_nested_block_actual.html +0 -14
- data/test/fixtures/unified_values/small_html/deep_nested_block_expected.json +0 -8
- data/test/fixtures/unified_values/small_html/deep_nested_inline_actual.html +0 -20
- data/test/fixtures/unified_values/small_html/deep_nested_inline_expected.json +0 -20
- data/test/fixtures/unified_values/small_html/empty_tag_actual.html +0 -10
- data/test/fixtures/unified_values/small_html/empty_tag_expected.json +0 -12
- data/test/fixtures/unified_values/small_html/empty_text_actual.html +0 -12
- data/test/fixtures/unified_values/small_html/empty_text_expected.json +0 -1
- data/test/fixtures/unified_values/small_html/ignore_tag_actual.html +0 -12
- data/test/fixtures/unified_values/small_html/ignore_tag_expected.json +0 -16
- data/test/fixtures/unified_values/small_html/ignored_class_actual.html +0 -10
- data/test/fixtures/unified_values/small_html/ignored_class_expected.json +0 -13
- data/test/fixtures/unified_values/small_html/img_actual.html +0 -12
- data/test/fixtures/unified_values/small_html/img_expected.json +0 -23
- data/test/fixtures/unified_values/small_html/nested_and_complex_wovn_ignore_actual.html +0 -10
- data/test/fixtures/unified_values/small_html/nested_and_complex_wovn_ignore_expected.json +0 -16
- data/test/fixtures/unified_values/small_html/nested_text_value_actual.html +0 -10
- data/test/fixtures/unified_values/small_html/nested_text_value_expected.json +0 -12
- data/test/fixtures/unified_values/small_html/nested_text_value_mixed_plan_text_actual.html +0 -10
- data/test/fixtures/unified_values/small_html/nested_text_value_mixed_plan_text_expected.json +0 -14
- data/test/fixtures/unified_values/small_html/option_tag_actual.html +0 -9
- data/test/fixtures/unified_values/small_html/option_tag_expected.json +0 -13
- data/test/fixtures/unified_values/small_html/text_different_inline_each_other_actual.html +0 -10
- data/test/fixtures/unified_values/small_html/text_different_inline_each_other_expected.json +0 -22
- data/test/fixtures/unified_values/small_html/text_in_svg_actual.html +0 -9
- data/test/fixtures/unified_values/small_html/text_in_svg_expected.json +0 -8
- data/test/fixtures/unified_values/small_html/text_with_html_entity_actual.html +0 -6
- data/test/fixtures/unified_values/small_html/text_with_html_entity_expected.json +0 -8
- data/test/fixtures/unified_values/small_html/unknown_or_custom_tag_actual.html +0 -12
- data/test/fixtures/unified_values/small_html/unknown_or_custom_tag_expected.json +0 -24
- data/test/fixtures/unified_values/small_html/unnecessay_top_end_tag_actual.html +0 -12
- data/test/fixtures/unified_values/small_html/unnecessay_top_end_tag_expected.json +0 -14
- data/test/fixtures/unified_values/small_html/wovn_ignore_actual.html +0 -10
- data/test/fixtures/unified_values/small_html/wovn_ignore_expected.json +0 -13
- data/test/lib/api_data_test.rb +0 -83
- data/test/lib/html_replacers/image_replacer_test.rb +0 -165
- data/test/lib/html_replacers/input_replacer_test.rb +0 -140
- data/test/lib/html_replacers/link_replacer_test.rb +0 -328
- data/test/lib/html_replacers/meta_replacer_test.rb +0 -157
- data/test/lib/html_replacers/replacer_base_test.rb +0 -128
- data/test/lib/html_replacers/script_replacer_test.rb +0 -139
- data/test/lib/html_replacers/text_replacer_test.rb +0 -99
- data/test/lib/html_replacers/unified_values/dst_swapping_targets_creator_test.rb +0 -137
- data/test/lib/html_replacers/unified_values/element_category_test.rb +0 -49
- data/test/lib/html_replacers/unified_values/node_swapping_targets_creator_test.rb +0 -137
- data/test/lib/html_replacers/unified_values/text_replacer_test.rb +0 -270
- data/test/lib/html_replacers/unified_values/text_scraper_test.rb +0 -121
- data/test/lib/html_replacers/unified_values/values_stack_test.rb +0 -122
- data/test/lib/services/url_test.rb +0 -9
- data/test/lib/services/value_agent_test.rb +0 -32
- data/test/services/url_test.rb +0 -163
- data/values/values +0 -1
@@ -1,134 +0,0 @@
|
|
1
|
-
module Wovnrb
|
2
|
-
module UnifiedValues
|
3
|
-
class NodeSwappingTargetsCreator
|
4
|
-
# NOTE: `nodes_info` is the format like below
|
5
|
-
#
|
6
|
-
# [
|
7
|
-
# {:dst=>"an<span>apple is a good</span>foods",
|
8
|
-
# :nodes=>
|
9
|
-
# [
|
10
|
-
# (Text "an"),
|
11
|
-
# (Element:0x13e84e1334 { name = "span", children = [ #(Text "apple is a good")] }),
|
12
|
-
# (Text "apple is a good"),
|
13
|
-
# (Element:0x13e84e1334 { name = "span", childrelib/wovnrb/html_replacers/unified_values/node_swapping_targets_creator.rbn = [ #(Text "apple is a good")] }),
|
14
|
-
# (Text "\n foods\n \n \n")]}
|
15
|
-
# ]
|
16
|
-
# }
|
17
|
-
# ]
|
18
|
-
def initialize(nodes_info)
|
19
|
-
@nodes_info = nodes_info
|
20
|
-
end
|
21
|
-
|
22
|
-
# NOTE: `run` make a swapping_targets like below
|
23
|
-
#
|
24
|
-
# [
|
25
|
-
# {:dst=>"an<span>apple is a good</span>foods",
|
26
|
-
# :nodes=>
|
27
|
-
# [
|
28
|
-
# (Text "an"),
|
29
|
-
# (Element:0x13e84e1334 { name = "span", children = [ #(Text "apple is a good")] }),
|
30
|
-
# (Text "apple is a good"),
|
31
|
-
# (Element:0x13e84e1334 { name = "span", children = [ #(Text "apple is a good")] }),
|
32
|
-
# (Text "\n foods\n \n \n")]}
|
33
|
-
# ]
|
34
|
-
# :swapping_targets=>
|
35
|
-
# [
|
36
|
-
# (Text "an"),
|
37
|
-
# (Text "apple is a good"),
|
38
|
-
# (Text "\n foods\n \n \n")]}
|
39
|
-
# ]
|
40
|
-
# }
|
41
|
-
# ]
|
42
|
-
|
43
|
-
def run!
|
44
|
-
@nodes_info.each do |node_info|
|
45
|
-
mold = []
|
46
|
-
node_info[:nodes].each do |node|
|
47
|
-
mold_size = mold.size
|
48
|
-
mold.push create_dummy_empty_text_node(next_node: node) if mold_size.even? && node.element?
|
49
|
-
mold.push node
|
50
|
-
end
|
51
|
-
|
52
|
-
mold.push create_dummy_empty_text_node(previous_node: mold.last) if mold.last.element?
|
53
|
-
node_info[:swapping_targets] = remove_tag_element(mold)
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
def remove_tag_element(mold)
|
58
|
-
id_of_tag_with_wovn_ignore = nil
|
59
|
-
swapping_targets = []
|
60
|
-
mold.each do |node|
|
61
|
-
if id_of_tag_with_wovn_ignore.nil? && node.attributes.keys.include?('wovn-ignore')
|
62
|
-
id_of_tag_with_wovn_ignore = node.object_id
|
63
|
-
next
|
64
|
-
end
|
65
|
-
|
66
|
-
if node.object_id == id_of_tag_with_wovn_ignore
|
67
|
-
id_of_tag_with_wovn_ignore = nil
|
68
|
-
end
|
69
|
-
|
70
|
-
if id_of_tag_with_wovn_ignore.nil? && node.text?
|
71
|
-
swapping_targets << node
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
swapping_targets
|
76
|
-
end
|
77
|
-
|
78
|
-
def create_dummy_empty_text_node(option)
|
79
|
-
DummyEmpryTextNode.new(option)
|
80
|
-
end
|
81
|
-
|
82
|
-
class DummyEmpryTextNode
|
83
|
-
attr_reader :name
|
84
|
-
|
85
|
-
def initialize(next_node: nil, previous_node: nil)
|
86
|
-
@name = 'text'
|
87
|
-
@next_node = next_node
|
88
|
-
@previous_node = previous_node
|
89
|
-
@added_empty_text = nil
|
90
|
-
end
|
91
|
-
|
92
|
-
def text?
|
93
|
-
true
|
94
|
-
end
|
95
|
-
|
96
|
-
def content
|
97
|
-
''
|
98
|
-
end
|
99
|
-
|
100
|
-
def to_s
|
101
|
-
content
|
102
|
-
end
|
103
|
-
|
104
|
-
def attributes
|
105
|
-
{}
|
106
|
-
end
|
107
|
-
|
108
|
-
def parent
|
109
|
-
@next_node.try(:parent) || @previous_node.try(:parent)
|
110
|
-
end
|
111
|
-
|
112
|
-
def document
|
113
|
-
@next_node.try(:document) || @previous_node.try(:document)
|
114
|
-
end
|
115
|
-
|
116
|
-
def add_previous_sibling(comment_node)
|
117
|
-
@added_empty_text.try(:add_previous_sibling, comment_node)
|
118
|
-
end
|
119
|
-
|
120
|
-
def content=(text)
|
121
|
-
return if text == ''
|
122
|
-
|
123
|
-
if @next_node
|
124
|
-
@next_node.add_previous_sibling(text)
|
125
|
-
@added_empty_text = @next_node.previous
|
126
|
-
elsif @previous_node
|
127
|
-
@previous_node.add_next_sibling(text)
|
128
|
-
@added_empty_text = @previous_node.next
|
129
|
-
end
|
130
|
-
end
|
131
|
-
end
|
132
|
-
end
|
133
|
-
end
|
134
|
-
end
|
@@ -1,35 +0,0 @@
|
|
1
|
-
module Wovnrb
|
2
|
-
module UnifiedValues
|
3
|
-
class TextReplacer < ReplacerBase
|
4
|
-
def initialize(store, text_index)
|
5
|
-
super(store)
|
6
|
-
@text_index = text_index
|
7
|
-
end
|
8
|
-
|
9
|
-
def replace(dom, lang)
|
10
|
-
translated_nodes_with_targets = NodeSwappingTargetsCreator.new(TextScraper.new(@ignored_class_set).run(dom)).run!
|
11
|
-
text_index_with_targets = DstSwappingTargetsCreator.new(@text_index).run!
|
12
|
-
|
13
|
-
translated_nodes_with_targets.each do |translated_nodes_with_target|
|
14
|
-
dst_swapping_targets =
|
15
|
-
text_index_with_targets[translated_nodes_with_target[:dst]]
|
16
|
-
.try(:fetch, lang.lang_code, nil)
|
17
|
-
.try(:first)
|
18
|
-
.try(:fetch, 'swapping_targets', nil)
|
19
|
-
next unless dst_swapping_targets
|
20
|
-
|
21
|
-
translated_nodes_with_target[:swapping_targets].each_with_index do |node_swapping_target, index|
|
22
|
-
# NOTE: current logic to swap back search text node and find wovn-src base on the text node.
|
23
|
-
# if `translated_text` is empry string, translated html don't have text node. it means that widget can't find wovn-src and swap back
|
24
|
-
# so we use `\u200b`(ZERO WIDTH SPACE) instead of empty string
|
25
|
-
translated_text = dst_swapping_targets[index].blank? ? "\u200b" : dst_swapping_targets[index]
|
26
|
-
original_text = node_swapping_target.content
|
27
|
-
|
28
|
-
node_swapping_target.content = translated_text
|
29
|
-
add_comment_node(node_swapping_target, original_text)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
@@ -1,152 +0,0 @@
|
|
1
|
-
module Wovnrb
|
2
|
-
module UnifiedValues
|
3
|
-
class TextScraper
|
4
|
-
def initialize(ignored_class_set)
|
5
|
-
@ignored_class_set = ignored_class_set
|
6
|
-
@values = []
|
7
|
-
@values_stack = nil
|
8
|
-
end
|
9
|
-
|
10
|
-
def run(dom)
|
11
|
-
refresh_all!
|
12
|
-
@values_stack = ValuesStack.new(dom.path, 1)
|
13
|
-
scrape(dom)
|
14
|
-
end
|
15
|
-
|
16
|
-
def create_text_value(src, node_stack)
|
17
|
-
{ dst: ValueAgent.normalize_text(src.gsub(/ /i, ' ')), nodes: node_stack }
|
18
|
-
end
|
19
|
-
|
20
|
-
private
|
21
|
-
|
22
|
-
def scrape(dom)
|
23
|
-
type = stop_recursion_type(dom)
|
24
|
-
if type
|
25
|
-
case type
|
26
|
-
when 'ignore_element', 'skip_element'
|
27
|
-
next_stack = @values_stack.build_next_stack
|
28
|
-
build_src
|
29
|
-
@values_stack = next_stack
|
30
|
-
when 'text_element'
|
31
|
-
@values_stack.add_text_element(dom, dom.content)
|
32
|
-
when 'empty_element'
|
33
|
-
@values_stack.add(dom, empty_tag(dom))
|
34
|
-
when 'comment_element'
|
35
|
-
# do nothing
|
36
|
-
else
|
37
|
-
raise 'Unsupported type'
|
38
|
-
end
|
39
|
-
elsif inline_element?(dom)
|
40
|
-
@values_stack.add(dom, start_tag(dom))
|
41
|
-
scrape_children_of(dom)
|
42
|
-
@values_stack.add(dom, end_tag(dom)) unless @values_stack.blank?
|
43
|
-
elsif block_element?(dom)
|
44
|
-
next_stack = @values_stack.build_next_stack
|
45
|
-
build_src
|
46
|
-
@values_stack = ValuesStack.new(dom.path, 1)
|
47
|
-
scrape_children_of(dom)
|
48
|
-
build_src
|
49
|
-
@values_stack = next_stack
|
50
|
-
else
|
51
|
-
next_stack = @values_stack.build_next_stack
|
52
|
-
build_src
|
53
|
-
@values_stack = ValuesStack.new(dom.path, 1)
|
54
|
-
scrape_children_of(dom)
|
55
|
-
build_src
|
56
|
-
@values_stack = next_stack
|
57
|
-
end
|
58
|
-
|
59
|
-
@values
|
60
|
-
end
|
61
|
-
|
62
|
-
def scrape_children_of(dom)
|
63
|
-
dom.children.each { |c| scrape(c) } unless wovn_ignore_element?(dom)
|
64
|
-
end
|
65
|
-
|
66
|
-
def build_src
|
67
|
-
return nil if @values_stack.blank?
|
68
|
-
|
69
|
-
src = @values_stack.src
|
70
|
-
@values << create_text_value(src, @values_stack.node_stack) if src.present? && !tag_only?(src)
|
71
|
-
@values_stack = nil
|
72
|
-
end
|
73
|
-
|
74
|
-
def tag_only?(src)
|
75
|
-
Nokogiri::HTML5.fragment(src).text.blank?
|
76
|
-
end
|
77
|
-
|
78
|
-
def start_tag(dom)
|
79
|
-
if wovn_ignore_element?(dom)
|
80
|
-
"<#{dom.name} wovn-ignore>"
|
81
|
-
else
|
82
|
-
"<#{dom.name}>"
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
def end_tag(dom)
|
87
|
-
"</#{dom.name}>"
|
88
|
-
end
|
89
|
-
|
90
|
-
def empty_tag(dom)
|
91
|
-
start_tag(dom)
|
92
|
-
end
|
93
|
-
|
94
|
-
def block_element?(element)
|
95
|
-
ElementCategory::BLOCK_ELEMENTS.include?(element.name)
|
96
|
-
end
|
97
|
-
|
98
|
-
def inline_element?(element)
|
99
|
-
ElementCategory::INLINE_ELEMENTS.include?(element.name)
|
100
|
-
end
|
101
|
-
|
102
|
-
def empty_element?(element)
|
103
|
-
ElementCategory::EMPTY_ELEMENTS.include?(element.name)
|
104
|
-
end
|
105
|
-
|
106
|
-
def ignore_element?(element)
|
107
|
-
ElementCategory::IGNORE_ELEMENTS.include?(element.name)
|
108
|
-
end
|
109
|
-
|
110
|
-
def skip_element?(element)
|
111
|
-
ElementCategory::SKIP_ELEMENTS.include?(element.name)
|
112
|
-
end
|
113
|
-
|
114
|
-
def comment_element?(element)
|
115
|
-
element.comment?
|
116
|
-
end
|
117
|
-
|
118
|
-
def text_element?(element)
|
119
|
-
element.text?
|
120
|
-
end
|
121
|
-
|
122
|
-
def wovn_ignore_element?(element)
|
123
|
-
return false unless element
|
124
|
-
|
125
|
-
return true if element.attribute('wovn-ignore')
|
126
|
-
|
127
|
-
class_attribute = element.attribute('class')
|
128
|
-
return false unless class_attribute
|
129
|
-
class_attribute.value.split.any? { |c| @ignored_class_set.include?(c) }
|
130
|
-
end
|
131
|
-
|
132
|
-
def stop_recursion_type(element)
|
133
|
-
return 'ignore_element' if ignore_element?(element)
|
134
|
-
return 'skip_element' if skip_element?(element)
|
135
|
-
return 'text_element' if text_element?(element)
|
136
|
-
return 'empty_element' if empty_element?(element)
|
137
|
-
return 'comment_element' if comment_element?(element)
|
138
|
-
|
139
|
-
nil
|
140
|
-
end
|
141
|
-
|
142
|
-
def refresh_all!
|
143
|
-
@values_stack = nil
|
144
|
-
refresh_values!
|
145
|
-
end
|
146
|
-
|
147
|
-
def refresh_values!
|
148
|
-
@values = []
|
149
|
-
end
|
150
|
-
end
|
151
|
-
end
|
152
|
-
end
|
@@ -1,65 +0,0 @@
|
|
1
|
-
require 'wovnrb/services/value_agent'
|
2
|
-
|
3
|
-
module Wovnrb
|
4
|
-
module UnifiedValues
|
5
|
-
class ValuesStack
|
6
|
-
attr_reader :node_stack
|
7
|
-
|
8
|
-
# @param head_path [String]
|
9
|
-
# @param index [Number]
|
10
|
-
#
|
11
|
-
# Be careful xpath's index starts with 1
|
12
|
-
def initialize(head_path, index)
|
13
|
-
@head_path = head_path
|
14
|
-
@index = index
|
15
|
-
@node_stack = []
|
16
|
-
@src_stack = []
|
17
|
-
@src_without_tag_stack = []
|
18
|
-
end
|
19
|
-
|
20
|
-
# @param node [Nokogiri::XML::Element]
|
21
|
-
# @param src [String]
|
22
|
-
def add(node, src)
|
23
|
-
@node_stack << node if node.name != 'text' || node.content.present?
|
24
|
-
@src_stack << Wovnrb::ValueAgent.normalize_text(src)
|
25
|
-
end
|
26
|
-
|
27
|
-
# @param node [Nokogiri::XML::Element]
|
28
|
-
# @param dom_content [String]
|
29
|
-
def add_text_element(node, dom_content)
|
30
|
-
add(node, CGI.escapeHTML(dom_content))
|
31
|
-
@src_without_tag_stack << Wovnrb::ValueAgent.normalize_text(dom_content)
|
32
|
-
end
|
33
|
-
|
34
|
-
# @return [Bool]
|
35
|
-
def blank?
|
36
|
-
@src_stack.blank?
|
37
|
-
end
|
38
|
-
|
39
|
-
# @return [String]
|
40
|
-
def path
|
41
|
-
return @head_path if @head_path.end_with?('title')
|
42
|
-
|
43
|
-
# Ends with "text()" because some type checking takes path as a normal text when the path ends with "text()"
|
44
|
-
p = "#{@head_path}/text()"
|
45
|
-
|
46
|
-
@index == 1 ? p : "#{p}[#{@index}]"
|
47
|
-
end
|
48
|
-
|
49
|
-
# @return [String]
|
50
|
-
def src
|
51
|
-
@src_stack.inject(:+)
|
52
|
-
end
|
53
|
-
|
54
|
-
# @return [String]
|
55
|
-
def src_without_tag
|
56
|
-
@src_without_tag_stack.inject(:+)
|
57
|
-
end
|
58
|
-
|
59
|
-
# @return [ValuesStack]
|
60
|
-
def build_next_stack
|
61
|
-
ValuesStack.new(@head_path, @index + 1)
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
data/lib/wovnrb/services/url.rb
DELETED
@@ -1,9 +0,0 @@
|
|
1
|
-
module Wovnrb
|
2
|
-
class ValueAgent
|
3
|
-
def self.normalize_text(src)
|
4
|
-
src.gsub(/[\ufffd]/, "\b")
|
5
|
-
.gsub(/[\n \t\u0020\u0009\u000C\u200B\u000D\u000A]+/, ' ')
|
6
|
-
.gsub(/^[\s\u00A0\uFEFF\u1680\u180E\u2000-\u200A\u202F\u205F\u3000]+|[\s\u00A0\uFEFF\u1680\u180E\u2000-\u200A\u202F\u205F\u3000]+$/, '')
|
7
|
-
end
|
8
|
-
end
|
9
|
-
end
|
@@ -1,96 +0,0 @@
|
|
1
|
-
<html>
|
2
|
-
<script>console.log('hello')</script>
|
3
|
-
<title>SIMPLE TITLE</title>
|
4
|
-
<meta name="description" content="meta description">
|
5
|
-
<body>
|
6
|
-
<div>
|
7
|
-
<form role="search">
|
8
|
-
<div class="search-control">
|
9
|
-
<input type="search" id="site-search" name="q"
|
10
|
-
placeholder="Search the site..."
|
11
|
-
aria-label="Search through site content">
|
12
|
-
<button>Search</button>
|
13
|
-
</div>
|
14
|
-
</form>
|
15
|
-
|
16
|
-
<form role="search" method="get" class="search-form wb-flex" action="https://www.wovn.io/">
|
17
|
-
<label>
|
18
|
-
<span>Search for:</span>
|
19
|
-
<input type="search" placeholder="Search …" value="" name="s" title="Search for:">
|
20
|
-
</label>
|
21
|
-
</form>
|
22
|
-
</div>
|
23
|
-
<div>
|
24
|
-
<span>
|
25
|
-
<p>Well</p>
|
26
|
-
</span>
|
27
|
-
</div>
|
28
|
-
<a class="home">
|
29
|
-
<span><h1>scrap</h1>only
|
30
|
-
<img src="/assets/hedgehog.jpg">
|
31
|
-
this too</span>
|
32
|
-
</a><br>
|
33
|
-
<span href="/" class="home">
|
34
|
-
<a><img src="/assets/hedgehog.jpg"></a>
|
35
|
-
<a>"Storm hunters" it is to see.</a>
|
36
|
-
<a>BLABLA5</a>
|
37
|
-
</span>
|
38
|
-
<div>
|
39
|
-
<form class="ftr-locator-form">
|
40
|
-
<input name="hdr-ftr-locator-term" placeholder="Street, City, State or ZIP" type="text">
|
41
|
-
<input type="submit">
|
42
|
-
|
43
|
-
</form>
|
44
|
-
</div>
|
45
|
-
<h1>
|
46
|
-
<div style="opacity: 1;">Welcome to my Website!</div>
|
47
|
-
</h1>
|
48
|
-
<div>
|
49
|
-
<div class="content-asset"><div class="heading1">LOST AF?</div>
|
50
|
-
<div class="error-info">
|
51
|
-
<p>WE'LL TAKE THE BLAME.</p>
|
52
|
-
<p>LET US MAKE IT UP TO YOU WITH SOME LINKS.</p>
|
53
|
-
</div>
|
54
|
-
|
55
|
-
<div class="shopping-link">
|
56
|
-
<nav class="gender-links">
|
57
|
-
<ul>
|
58
|
-
<li class="link-text"><a href="https://www.abercrombie.co.jp/en_JP/mens/" class="nav-link">SHOP MENS</a></li>
|
59
|
-
<li class="link-text"><a href="https://www.abercrombie.co.jp/en_JP/womens/" class="nav-link">SHOP WOMENS</a></li>
|
60
|
-
<li class="link-text"><a href="https://www.abercrombie.co.jp/en_JP/kids/boys/" class="nav-link">shop boys</a></li>
|
61
|
-
<li class="link-text"><a href="https://www.abercrombie.co.jp/en_JP/kids/girls/" class="nav-link">shop girls</a></li>
|
62
|
-
</ul>
|
63
|
-
</nav>
|
64
|
-
</div></div>
|
65
|
-
<div class="error-custom-message noshow">"<div class="heading1">LOST AF?</div>
|
66
|
-
<div class="error-info">
|
67
|
-
<p>WE'LL TAKE THE BLAME.</p>
|
68
|
-
<p>LET US MAKE IT UP TO YOU WITH SOME LINKS.</p>
|
69
|
-
</div>
|
70
|
-
|
71
|
-
<div class="shopping-link">
|
72
|
-
<nav class="gender-links">
|
73
|
-
<ul>
|
74
|
-
<li class="link-text"><a href="https://www.abercrombie.co.jp/en_JP/mens/" class="nav-link">SHOP MENS</a></li>
|
75
|
-
<li class="link-text"><a href="https://www.abercrombie.co.jp/en_JP/womens/" class="nav-link">SHOP WOMENS</a></li>
|
76
|
-
<li class="link-text"><a href="https://www.abercrombie.co.jp/en_JP/kids/boys/" class="nav-link">shop boys</a></li>
|
77
|
-
<li class="link-text"><a href="https://www.abercrombie.co.jp/en_JP/kids/girls/" class="nav-link">shop girls</a></li>
|
78
|
-
</ul>
|
79
|
-
</nav>
|
80
|
-
</div></div>"
|
81
|
-
</div>
|
82
|
-
|
83
|
-
<p>This is a paragraph! Here's how you make a link: <a href="https://neocities.org">Neocities</a>.</p>
|
84
|
-
|
85
|
-
<p>Here's how you can make <strong>bold</strong> and <em>italic</em> text.</p>
|
86
|
-
<p>Here's how you can add an image:</p>
|
87
|
-
<p>Here's how to make a list:</p>
|
88
|
-
<ul>
|
89
|
-
<li href="/">First thing</li>
|
90
|
-
<li>Second thing</li>
|
91
|
-
<li>Third thing</li>
|
92
|
-
</ul>
|
93
|
-
|
94
|
-
<p>To learn more HTML/CSS, check out these <a href="https://neocities.org/tutorials">tutorials</a>!</p>
|
95
|
-
</body>
|
96
|
-
</html>
|