mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
net.html: add get_tags_by_class_name (#17024)
This commit is contained in:
parent
6688c0f3d7
commit
d850d3caba
@ -185,3 +185,8 @@ pub fn (dom DocumentObjectModel) get_root() &Tag {
|
|||||||
pub fn (dom DocumentObjectModel) get_tags() []&Tag {
|
pub fn (dom DocumentObjectModel) get_tags() []&Tag {
|
||||||
return dom.all_tags
|
return dom.all_tags
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// get_tags_by_class_name retrieves all the tags recursively in the document that has the given class name(s).
|
||||||
|
pub fn (dom DocumentObjectModel) get_tags_by_class_name(names ...string) []&Tag {
|
||||||
|
return dom.root.get_tags_by_class_name(...names)
|
||||||
|
}
|
||||||
|
@ -54,3 +54,33 @@ fn test_access_tag_fields() {
|
|||||||
assert id_tags[0].name == 'div'
|
assert id_tags[0].name == 'div'
|
||||||
assert id_tags[1].attributes['class'] == 'several-1'
|
assert id_tags[1].attributes['class'] == 'several-1'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn generate_temp_html_with_classes() string {
|
||||||
|
mut temp_html := strings.new_builder(400)
|
||||||
|
temp_html.write_string('<!doctype html><html><head><title>Giant String</title></head><body>')
|
||||||
|
temp_html.write_string("<div class='single'>Single</div>")
|
||||||
|
for counter := 0; counter < 4; counter++ {
|
||||||
|
temp_html.write_string("<div id='name_${counter}' ")
|
||||||
|
temp_html.write_string("class='common'>Common No. ${counter}</div>")
|
||||||
|
}
|
||||||
|
temp_html.write_string("<div class='complex-0 complex-1 complex-2'>Complex</div>")
|
||||||
|
temp_html.write_string("<div class='complex-0 complex-2'>Partial</div>")
|
||||||
|
temp_html.write_string('</body></html>')
|
||||||
|
return temp_html.str()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_search_by_class() {
|
||||||
|
dom := parse(generate_temp_html_with_classes())
|
||||||
|
single_class_tags := dom.get_tags_by_class_name('single')
|
||||||
|
common_class_tags := dom.get_tags_by_class_name('common')
|
||||||
|
complex_class_tags := dom.get_tags_by_class_name('complex-0', 'complex-1', 'complex-2')
|
||||||
|
partial_class_tags := dom.get_tags_by_class_name('complex-0', 'complex-2')
|
||||||
|
shuffled_class_tags := dom.get_tags_by_class_name('complex-2', 'complex-0', 'complex-1')
|
||||||
|
assert single_class_tags.len == 1
|
||||||
|
assert common_class_tags.len == 4
|
||||||
|
assert complex_class_tags.len == 1
|
||||||
|
assert complex_class_tags[0].attributes['class'] == 'complex-0 complex-1 complex-2'
|
||||||
|
assert partial_class_tags.len == 2
|
||||||
|
assert shuffled_class_tags.len == 1
|
||||||
|
assert shuffled_class_tags[0].attributes['class'] == 'complex-0 complex-1 complex-2'
|
||||||
|
}
|
||||||
|
@ -151,6 +151,13 @@ pub fn (mut parser Parser) split_parse(data string) {
|
|||||||
nval := temp_lexeme.substr(1, temp_lexeme.len - 1)
|
nval := temp_lexeme.substr(1, temp_lexeme.len - 1)
|
||||||
// parser.print_debug(lattr + " = " + temp_lexeme)
|
// parser.print_debug(lattr + " = " + temp_lexeme)
|
||||||
parser.lexical_attributes.current_tag.attributes[lattr] = nval
|
parser.lexical_attributes.current_tag.attributes[lattr] = nval
|
||||||
|
if lattr == 'class' {
|
||||||
|
for class_name in nval.split_any('\t\r\n \x0D') {
|
||||||
|
if class_name != '' {
|
||||||
|
parser.lexical_attributes.current_tag.class_set.add(class_name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
parser.lexical_attributes.current_tag.last_attribute = ''
|
parser.lexical_attributes.current_tag.last_attribute = ''
|
||||||
} else {
|
} else {
|
||||||
parser.lexical_attributes.current_tag.attributes[temp_lexeme.to_lower()] = ''
|
parser.lexical_attributes.current_tag.attributes[temp_lexeme.to_lower()] = ''
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
module html
|
module html
|
||||||
|
|
||||||
import strings
|
import strings
|
||||||
|
import datatypes
|
||||||
|
|
||||||
enum CloseTagType {
|
enum CloseTagType {
|
||||||
in_name
|
in_name
|
||||||
@ -16,6 +17,7 @@ pub mut:
|
|||||||
children []&Tag
|
children []&Tag
|
||||||
attributes map[string]string // attributes will be like map[name]value
|
attributes map[string]string // attributes will be like map[name]value
|
||||||
last_attribute string
|
last_attribute string
|
||||||
|
class_set datatypes.Set[string]
|
||||||
parent &Tag = unsafe { nil }
|
parent &Tag = unsafe { nil }
|
||||||
position_in_parent int
|
position_in_parent int
|
||||||
closed bool
|
closed bool
|
||||||
@ -102,3 +104,22 @@ pub fn (tag &Tag) get_tags_by_attribute_value(name string, value string) []&Tag
|
|||||||
}
|
}
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// get_tags_by_class_name retrieves all the child tags recursively in the tag that has the given class name(s).
|
||||||
|
pub fn (tag &Tag) get_tags_by_class_name(names ...string) []&Tag {
|
||||||
|
mut res := []&Tag{}
|
||||||
|
for child in tag.children {
|
||||||
|
mut matched := true
|
||||||
|
for name in names {
|
||||||
|
matched = child.class_set.exists(name)
|
||||||
|
if !matched {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if matched {
|
||||||
|
res << child
|
||||||
|
}
|
||||||
|
res << child.get_tags_by_class_name(...names)
|
||||||
|
}
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
module html
|
module html
|
||||||
|
|
||||||
|
import strings
|
||||||
|
|
||||||
const (
|
const (
|
||||||
html = '<!doctype html>
|
html = '<!doctype html>
|
||||||
<html>
|
<html>
|
||||||
@ -34,4 +36,36 @@ fn test_search_by_tag_type() {
|
|||||||
assert tag.get_tags('div').len == 5
|
assert tag.get_tags('div').len == 5
|
||||||
assert tag.get_tags_by_attribute('href')[2].content == 'vpm'
|
assert tag.get_tags_by_attribute('href')[2].content == 'vpm'
|
||||||
assert tag.get_tags_by_attribute_value('class', 'bar').len == 3
|
assert tag.get_tags_by_attribute_value('class', 'bar').len == 3
|
||||||
|
assert tag.get_tags_by_class_name('bar').len == 3
|
||||||
|
}
|
||||||
|
|
||||||
|
fn generate_temp_html_with_classes() string {
|
||||||
|
mut temp_html := strings.new_builder(400)
|
||||||
|
temp_html.write_string('<!doctype html><html><head><title>Giant String</title></head><body>')
|
||||||
|
temp_html.write_string("<div class='single'>Single</div>")
|
||||||
|
for counter := 0; counter < 4; counter++ {
|
||||||
|
temp_html.write_string("<div id='name_${counter}' ")
|
||||||
|
temp_html.write_string("class='common'>Common No. ${counter}</div>")
|
||||||
|
}
|
||||||
|
temp_html.write_string("<div class='complex-0 complex-1 complex-2'>Complex</div>")
|
||||||
|
temp_html.write_string("<div class='complex-0 complex-2'>Partial</div>")
|
||||||
|
temp_html.write_string('</body></html>')
|
||||||
|
return temp_html.str()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_search_by_class() {
|
||||||
|
mut dom := parse(generate_temp_html_with_classes())
|
||||||
|
tag := dom.get_tag('body')[0]
|
||||||
|
single_class_tags := tag.get_tags_by_class_name('single')
|
||||||
|
common_class_tags := tag.get_tags_by_class_name('common')
|
||||||
|
complex_class_tags := tag.get_tags_by_class_name('complex-0', 'complex-1', 'complex-2')
|
||||||
|
partial_class_tags := tag.get_tags_by_class_name('complex-0', 'complex-2')
|
||||||
|
shuffled_class_tags := tag.get_tags_by_class_name('complex-2', 'complex-0', 'complex-1')
|
||||||
|
assert single_class_tags.len == 1
|
||||||
|
assert common_class_tags.len == 4
|
||||||
|
assert complex_class_tags.len == 1
|
||||||
|
assert complex_class_tags[0].attributes['class'] == 'complex-0 complex-1 complex-2'
|
||||||
|
assert partial_class_tags.len == 2
|
||||||
|
assert shuffled_class_tags.len == 1
|
||||||
|
assert shuffled_class_tags[0].attributes['class'] == 'complex-0 complex-1 complex-2'
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user