From 45f14baad04c6288e7d1792766723b7b569c2b98 Mon Sep 17 00:00:00 2001 From: Kanezoh Date: Tue, 16 Nov 2021 19:45:41 +0900 Subject: [PATCH] add comment --- src/mechanize/form.cr | 6 +- src/mechanize/history.cr | 35 ++++---- src/mechanize/page.cr | 86 +++++++++--------- src/mechanize/utils/element_matcher.cr | 118 ++++++++++++------------- 4 files changed, 128 insertions(+), 117 deletions(-) diff --git a/src/mechanize/form.cr b/src/mechanize/form.cr index 6143ab5..a993e3d 100644 --- a/src/mechanize/form.cr +++ b/src/mechanize/form.cr @@ -9,11 +9,11 @@ require "./form/select_list" require "./utils/element_matcher" # THis class represents the form tag of html. -class MechanizeCr::Form - include MechanizeCr::ElementMatcher +class Mechanize::Form + include Mechanize::ElementMatcher getter node : Node | Lexbor::Node - # returns an array of `MechanizeCr::FormContent::Field` in the form. + # returns an array of `Mechanize::FormContent::Field` in the form. getter fields : Array(FormContent::Field) # returns an array of input tags whose type is checkbox in the form. getter checkboxes : Array(FormContent::CheckBox) diff --git a/src/mechanize/history.cr b/src/mechanize/history.cr index 6cebd10..5448079 100644 --- a/src/mechanize/history.cr +++ b/src/mechanize/history.cr @@ -1,12 +1,13 @@ require "./page" -# This class represents the history of http response you sent. +# This class represents the history of http response you sent. # If you send a request, mechanize saves the history. -class Mechanize::History - # max page size history can save. default is 100. - # as same as `agent.max_history`. - property max_size : Int32 - property array : Array(Mechanize::Page) +class Mechanize + class History + # max page size history can save. default is 100. + # as same as `agent.max_history`. + property max_size : Int32 + property array : Array(Mechanize::Page) delegate :size, :empty?, :last, to: array @@ -15,17 +16,21 @@ class Mechanize::History @array = array end - # add page to history. - def push(page, uri = nil) - @array.push(page) - while size > @max_size - @array.shift + # add page to history. + def push(page, uri = nil) + @array.push(page) + while size > @max_size + @array.shift + end + self end - # take the last page out from history. - def pop - if size == 0 - # TODO: raise error + # take the last page out from history. + def pop + if size == 0 + # TODO: raise error + end + page = @array.pop end end end diff --git a/src/mechanize/page.cr b/src/mechanize/page.cr index d10e60a..ff952be 100644 --- a/src/mechanize/page.cr +++ b/src/mechanize/page.cr @@ -2,16 +2,15 @@ require "./file" require "./utils/element_matcher" require "./page/link" -# This class represents the result of http response. -# If you send a request, it returns the instance of `Mechanize::Page`. +# This class represents the result of http response. +# If you send a request, it returns the instance of `Mechanize::Page`. # You can get status code, title, and page body, and search html node using css selector from page instance. -class Mechanize::Page < Mechanize::File - include Mechanize::ElementMatcher +class Mechanize + class Page < Mechanize::File + include Mechanize::ElementMatcher - # look at lexbor document.(https://github.com/kostya/lexbor#readme) - delegate :css, to: parser - - property mech : Mechanize + # look at lexbor document.(https://github.com/kostya/lexbor#readme) + delegate :css, to: parser property mech : Mechanize @@ -20,41 +19,48 @@ class Mechanize::Page < Mechanize::File super(uri, response, body, code) end - # return page title. - # ``` - # page.title # => String - # ``` - def title : String - title_node = css("title") - if title_node.empty? - "" - else - title_node.first.inner_text + # parser to parse response body. + # TODO: now it's Lexbor::Parser. I want to also support other parsers like JSON. + def parser : Lexbor::Parser + @parser ||= Lexbor::Parser.new(@body) end - # return all forms(`Mechanize::Form`) in the page. - # ``` - # page.forms # => Array(Mechanize::Form) - # ``` - def forms : Array(Mechanize::Form) - forms = css("form").map do |html_form| - form = Form.new(html_form, self) - form.action ||= @uri.to_s - form - end.to_a - end - - # return all links(`Mechanize::PageContent::Link`) in the page. - # ``` - # page.links # => Array(Mechanize::PageContent::Link) - # ``` - def links : Array(Mechanize::PageContent::Link) - links = %w{a area}.map do |tag| - css(tag).map do |node| - PageContent::Link.new(node, @mech, self) + # return page title. + # ``` + # page.title # => String + # ``` + def title : String + title_node = css("title") + if title_node.empty? + "" + else + title_node.first.inner_text end - end.flatten - end + end + + # return all forms(`Mechanize::Form`) in the page. + # ``` + # page.forms # => Array(Mechanize::Form) + # ``` + def forms : Array(Mechanize::Form) + forms = css("form").map do |html_form| + form = Form.new(html_form, self) + form.action ||= @uri.to_s + form + end.to_a + end + + # return all links(`Mechanize::PageContent::Link`) in the page. + # ``` + # page.links # => Array(Mechanize::PageContent::Link) + # ``` + def links : Array(Mechanize::PageContent::Link) + links = %w{a area}.map do |tag| + css(tag).map do |node| + PageContent::Link.new(node, @mech, self) + end + end.flatten + end elements_with "form" end diff --git a/src/mechanize/utils/element_matcher.cr b/src/mechanize/utils/element_matcher.cr index 5ca3f09..f36d262 100644 --- a/src/mechanize/utils/element_matcher.cr +++ b/src/mechanize/utils/element_matcher.cr @@ -1,71 +1,71 @@ class Mechanize module ElementMatcher macro elements_with(singular, plural = "") - {% plural = "#{singular.id}s" if plural.empty? %} - # search {{ plural.id }} which match condition. - # - # Examples - # ``` - # # if you specify String like "foo", it searches form which name is "foo". - {% if ["form", "button"].includes?("#{singular.id}") %} - # # like <{{ singular.id }} name="foo"> - {% elsif "#{singular.id}" == "field" %} - # # like - {% elsif "#{singular.id}" == "radiobutton" %} - # # like - {% else %} - # # like - {% end %} - # page.{{ plural.id }}_with("foo") - # # you can also specify tag's attribute and its' value by NamedTuple or Hash(String, String). - {% if ["form", "button"].includes?("#{singular.id}") %} - # # ex) <{{ singular.id }} class="foo"> - {% elsif "#{singular.id}" == "field" %} - # # ex) - {% elsif "#{singular.id}" == "radiobutton" %} - # # ex) - {% else %} - # # ex) - {% end %} - # page.{{ plural.id }}_with("class" => "foo") - # page.{{ plural.id }}_with(class: "foo") - # ``` - def {{plural.id}}_with(criteria : String | NamedTuple | Hash(String,String)) - {{plural.id}}_with(criteria){} - end + {% plural = "#{singular.id}s" if plural.empty? %} + # search {{ plural.id }} which match condition. + # + # Examples + # ``` + # # if you specify String like "foo", it searches form which name is "foo". + {% if ["form", "button"].includes?("#{singular.id}") %} + # # like <{{ singular.id }} name="foo"> + {% elsif "#{singular.id}" == "field" %} + # # like + {% elsif "#{singular.id}" == "radiobutton" %} + # # like + {% else %} + # # like + {% end %} + # page.{{ plural.id }}_with("foo") + # # you can also specify tag's attribute and its' value by NamedTuple or Hash(String, String). + {% if ["form", "button"].includes?("#{singular.id}") %} + # # ex) <{{ singular.id }} class="foo"> + {% elsif "#{singular.id}" == "field" %} + # # ex) + {% elsif "#{singular.id}" == "radiobutton" %} + # # ex) + {% else %} + # # ex) + {% end %} + # page.{{ plural.id }}_with("class" => "foo") + # page.{{ plural.id }}_with(class: "foo") + # ``` + def {{plural.id}}_with(criteria : String | NamedTuple | Hash(String,String)) + {{plural.id}}_with(criteria){} + end - def {{plural.id}}_with(criteria, &block) - if criteria.is_a?(NamedTuple) - criteria = criteria.to_h - end - if criteria.is_a?(String) - criteria = {"name" => criteria} - else - criteria = criteria.each_with_object(Hash(String,String).new) do |(k, v), h| - k = k.to_s - h[k] = v + def {{plural.id}}_with(criteria, &block) + if criteria.is_a?(NamedTuple) + criteria = criteria.to_h end - end - f = {{plural.id}}.select do |elm| - criteria.all? do |k,v| - if k == "text" - v == elm.node.inner_text - else - v == elm.node.fetch(k,"") + if criteria.is_a?(String) + criteria = {"name" => criteria} + else + criteria = criteria.each_with_object(Hash(String,String).new) do |(k, v), h| + k = k.to_s + h[k] = v end end + f = {{plural.id}}.select do |elm| + criteria.all? do |k,v| + if k == "text" + v == elm.node.inner_text + else + v == elm.node.fetch(k,"") + end + end + end + yield f + f end - yield f - f - end - # returns first element of `#{{ plural.id }}_with` - def {{singular.id}}_with(criteria) - f = {{plural.id}}_with(criteria) - # TODO: Write correct error message. - raise Mechanize::ElementNotFoundError.new(:{{singular.id}}, "") if f.empty? - f.first + # returns first element of `#{{ plural.id }}_with` + def {{singular.id}}_with(criteria) + f = {{plural.id}}_with(criteria) + # TODO: Write correct error message. + raise Mechanize::ElementNotFoundError.new(:{{singular.id}}, "") if f.empty? + f.first + end end end - end end