From 6367e95832b5a9b4a4ed2878c05fb70163862ff7 Mon Sep 17 00:00:00 2001 From: stephann <3025661+stephannv@users.noreply.github.com> Date: Mon, 9 Sep 2024 14:31:02 -0300 Subject: [PATCH] refactor: Reorganize code in modules --- src/blueprint/html.cr | 18 ++- src/blueprint/html/attributes_parser.cr | 46 ++++--- .../{content_capture.cr => block_renderer.cr} | 4 +- src/blueprint/html/builder.cr | 5 +- .../{renderer.cr => component_renderer.cr} | 4 +- src/blueprint/html/element_registrar.cr | 31 +---- src/blueprint/html/element_renderer.cr | 30 +++++ src/blueprint/html/elements.cr | 116 ----------------- src/blueprint/html/standard_elements.cr | 118 ++++++++++++++++++ src/blueprint/html/svg.cr | 4 +- src/blueprint/html/utils.cr | 2 +- src/blueprint/svg/component.cr | 8 +- 12 files changed, 200 insertions(+), 186 deletions(-) rename src/blueprint/html/{content_capture.cr => block_renderer.cr} (74%) rename src/blueprint/html/{renderer.cr => component_renderer.cr} (85%) create mode 100644 src/blueprint/html/element_renderer.cr delete mode 100644 src/blueprint/html/elements.cr create mode 100644 src/blueprint/html/standard_elements.cr diff --git a/src/blueprint/html.cr b/src/blueprint/html.cr index a42de75..67fd1db 100644 --- a/src/blueprint/html.cr +++ b/src/blueprint/html.cr @@ -1,15 +1,25 @@ require "html" require "./html/attributes_parser" +require "./html/block_renderer" require "./html/builder" -require "./html/content_capture" +require "./html/component_renderer" require "./html/element_registrar" -require "./html/elements" -require "./html/renderer" +require "./html/element_renderer" +require "./html/standard_elements" require "./html/svg" require "./html/utils" module Blueprint::HTML + include Blueprint::HTML::AttributesParser + include Blueprint::HTML::BlockRenderer + include Blueprint::HTML::ComponentRenderer + include Blueprint::HTML::ElementRegistrar + include Blueprint::HTML::ElementRenderer + include Blueprint::HTML::StandardElements + include Blueprint::HTML::SVG + include Blueprint::HTML::Utils + @buffer = String::Builder.new def to_html : String @@ -24,7 +34,7 @@ module Blueprint::HTML return "" unless render? envelope do - blueprint { capture_content { yield } } + blueprint { render_block { yield } } end @buffer.to_s diff --git a/src/blueprint/html/attributes_parser.cr b/src/blueprint/html/attributes_parser.cr index f1636b0..22e84a9 100644 --- a/src/blueprint/html/attributes_parser.cr +++ b/src/blueprint/html/attributes_parser.cr @@ -1,49 +1,47 @@ -module Blueprint::HTML - private def parse_attributes(attributes : NamedTuple) : String - String.build do |io| - attributes.each do |name, value| - append_attribute(io, name, value) - end +module Blueprint::HTML::AttributesParser + private def parse_attributes(attributes : NamedTuple) + attributes.each do |name, value| + append_attribute(name, value) end end - private def append_attribute(io : String::Builder, attribute_name, attribute_value) : Nil + private def append_attribute(attribute_name, attribute_value) : Nil case attribute_value when Nil, false # does nothing when true - append_boolean_attribute(io, attribute_name) + append_boolean_attribute(attribute_name) when NamedTuple - process_named_tuple_attribute(io, attribute_name, attribute_value) + process_named_tuple_attribute(attribute_name, attribute_value) when Array - append_array_attribute(io, attribute_name, attribute_value) + append_array_attribute(attribute_name, attribute_value) else - append_normal_attribute(io, attribute_name, attribute_value) + append_normal_attribute(attribute_name, attribute_value) end end - private def append_normal_attribute(io : String::Builder, attribute_name, attribute_value) : Nil - io << " " - io << parse_attribute_name(attribute_name) - io << %(=") - ::HTML.escape(attribute_value.to_s, io) - io << %(") + private def append_normal_attribute(attribute_name, attribute_value) : Nil + @buffer << " " + @buffer << parse_attribute_name(attribute_name) + @buffer << %(=") + ::HTML.escape(attribute_value.to_s, @buffer) + @buffer << %(") end - private def append_boolean_attribute(io : String::Builder, attribute_name) : Nil - io << " " - io << parse_attribute_name(attribute_name) + private def append_boolean_attribute(attribute_name) : Nil + @buffer << " " + @buffer << parse_attribute_name(attribute_name) end - private def append_array_attribute(io : String::Builder, attribute_name, attribute_value : Array) : Nil - append_normal_attribute(io, attribute_name, attribute_value.flatten.compact.join(" ")) + private def append_array_attribute(attribute_name, attribute_value : Array) : Nil + append_normal_attribute(attribute_name, attribute_value.flatten.compact.join(" ")) end - private def process_named_tuple_attribute(io : String::Builder, attribute_name, attribute_value : NamedTuple) : Nil + private def process_named_tuple_attribute(attribute_name, attribute_value : NamedTuple) : Nil attribute_name_prefix = parse_attribute_name(attribute_name) attribute_value.each do |name, value| - append_attribute(io, "#{attribute_name_prefix}-#{parse_attribute_name(name)}", value) + append_attribute("#{attribute_name_prefix}-#{parse_attribute_name(name)}", value) end end diff --git a/src/blueprint/html/content_capture.cr b/src/blueprint/html/block_renderer.cr similarity index 74% rename from src/blueprint/html/content_capture.cr rename to src/blueprint/html/block_renderer.cr index f1106b4..6284f73 100644 --- a/src/blueprint/html/content_capture.cr +++ b/src/blueprint/html/block_renderer.cr @@ -1,5 +1,5 @@ -module Blueprint::HTML - private def capture_content(&) : Nil +module Blueprint::HTML::BlockRenderer + private def render_block(&) : Nil buffer_size_before_block_evaluation = @buffer.bytesize content = with self yield if buffer_size_before_block_evaluation == @buffer.bytesize diff --git a/src/blueprint/html/builder.cr b/src/blueprint/html/builder.cr index 0fe8363..872afae 100644 --- a/src/blueprint/html/builder.cr +++ b/src/blueprint/html/builder.cr @@ -1,10 +1,11 @@ module Blueprint::HTML - # EXPERIMENTAL + @[Experimental] def self.build(&) : String Builder.build { |builder| with builder yield } end - private struct Builder + @[Experimental] + struct Builder include Blueprint::HTML def self.build(&) : String diff --git a/src/blueprint/html/renderer.cr b/src/blueprint/html/component_renderer.cr similarity index 85% rename from src/blueprint/html/renderer.cr rename to src/blueprint/html/component_renderer.cr index ad0a409..0861058 100644 --- a/src/blueprint/html/renderer.cr +++ b/src/blueprint/html/component_renderer.cr @@ -1,5 +1,5 @@ # :nodoc: -module Blueprint::HTML +module Blueprint::HTML::ComponentRenderer private def render(blueprint : Blueprint::HTML) : Nil blueprint.render_to(@buffer) end @@ -21,6 +21,6 @@ module Blueprint::HTML return unless render? @buffer = buffer - blueprint { capture_content { yield } } + blueprint { render_block { yield } } end end diff --git a/src/blueprint/html/element_registrar.cr b/src/blueprint/html/element_registrar.cr index e83a7ae..132112d 100644 --- a/src/blueprint/html/element_registrar.cr +++ b/src/blueprint/html/element_registrar.cr @@ -1,4 +1,4 @@ -module Blueprint::HTML +module Blueprint::HTML::ElementRegistrar macro register_element(method_name, tag = nil) {% tag ||= method_name.tr("_", "-") %} @@ -30,33 +30,4 @@ module Blueprint::HTML void_element({{tag}}, **attributes) end end - - private def element(_tag_name : String | Symbol, **attributes, &block) : Nil - @buffer << "<" - @buffer << _tag_name - @buffer << parse_attributes(attributes) - @buffer << ">" - capture_content { with self yield } - @buffer << "" - end - - private def element(_tag_name : String | Symbol, __content__ : String, **attributes) : Nil - @buffer << "<" - @buffer << _tag_name - @buffer << parse_attributes(attributes) - @buffer << ">" - ::HTML.escape(__content__, @buffer) - @buffer << "" - end - - private def void_element(_tag_name : String | Symbol, **attributes) : Nil - @buffer << "<" - @buffer << _tag_name - @buffer << parse_attributes(attributes) - @buffer << ">" - end end diff --git a/src/blueprint/html/element_renderer.cr b/src/blueprint/html/element_renderer.cr new file mode 100644 index 0000000..7c9fd74 --- /dev/null +++ b/src/blueprint/html/element_renderer.cr @@ -0,0 +1,30 @@ +module Blueprint::HTML::ElementRenderer + private def element(_tag_name : String | Symbol, **attributes, &) : Nil + @buffer << "<" + @buffer << _tag_name + parse_attributes(attributes) + @buffer << ">" + render_block { with self yield } + @buffer << "" + end + + private def element(_tag_name : String | Symbol, __content__ : String, **attributes) : Nil + @buffer << "<" + @buffer << _tag_name + parse_attributes(attributes) + @buffer << ">" + ::HTML.escape(__content__, @buffer) + @buffer << "" + end + + private def void_element(_tag_name : String | Symbol, **attributes) : Nil + @buffer << "<" + @buffer << _tag_name + parse_attributes(attributes) + @buffer << ">" + end +end diff --git a/src/blueprint/html/elements.cr b/src/blueprint/html/elements.cr deleted file mode 100644 index 2cba8c7..0000000 --- a/src/blueprint/html/elements.cr +++ /dev/null @@ -1,116 +0,0 @@ -module Blueprint::HTML - register_element :a - register_element :abbr - register_element :address - register_element :article - register_element :aside - register_element :audio - register_element :b - register_element :bdi - register_element :bdo - register_element :blockquote - register_element :body - register_element :button - register_element :canvas - register_element :caption - register_element :cite - register_element :code - register_element :colgroup - register_element :data - register_element :datalist - register_element :dd - register_element :del - register_element :details - register_element :dfn - register_element :dialog - register_element :div - register_element :dl - register_element :dt - register_element :em - register_element :fieldset - register_element :figcaption - register_element :figure - register_element :footer - register_element :form - register_element :h1 - register_element :h2 - register_element :h3 - register_element :h4 - register_element :h5 - register_element :h6 - register_element :head - register_element :header - register_element :hgroup - register_element :html - register_element :i - register_element :ins - register_element :kbd - register_element :label - register_element :legend - register_element :li - register_element :main - register_element :map - register_element :mark - register_element :menu - register_element :meter - register_element :nav - register_element :noscript - register_element :object - register_element :ol - register_element :optgroup - register_element :option - register_element :output - register_element :p - register_element :picture - register_element :pre - register_element :progress - register_element :q - register_element :rp - register_element :rt - register_element :ruby - register_element :s - register_element :samp - register_element :script - register_element :section - register_element :select_tag, "select" - register_element :slot - register_element :small - register_element :span - register_element :strong - register_element :style - register_element :sub - register_element :summary - register_element :sup - register_element :table - register_element :tbody - register_element :td - register_element :template - register_element :textarea - register_element :tfoot - register_element :th - register_element :thead - register_element :time - register_element :title - register_element :tr - register_element :u - register_element :ul - register_element :var - register_element :video - - register_void_element :area - register_void_element :base - register_void_element :br - register_void_element :col - register_void_element :embed - register_void_element :hr - register_void_element :img - register_void_element :input - register_void_element :link - register_void_element :meta - register_void_element :source - register_void_element :track - register_void_element :wbr - - register_empty_element :iframe - register_empty_element :portal -end diff --git a/src/blueprint/html/standard_elements.cr b/src/blueprint/html/standard_elements.cr new file mode 100644 index 0000000..18d75db --- /dev/null +++ b/src/blueprint/html/standard_elements.cr @@ -0,0 +1,118 @@ +module Blueprint::HTML::StandardElements + macro included + register_element :a + register_element :abbr + register_element :address + register_element :article + register_element :aside + register_element :audio + register_element :b + register_element :bdi + register_element :bdo + register_element :blockquote + register_element :body + register_element :button + register_element :canvas + register_element :caption + register_element :cite + register_element :code + register_element :colgroup + register_element :data + register_element :datalist + register_element :dd + register_element :del + register_element :details + register_element :dfn + register_element :dialog + register_element :div + register_element :dl + register_element :dt + register_element :em + register_element :fieldset + register_element :figcaption + register_element :figure + register_element :footer + register_element :form + register_element :h1 + register_element :h2 + register_element :h3 + register_element :h4 + register_element :h5 + register_element :h6 + register_element :head + register_element :header + register_element :hgroup + register_element :html + register_element :i + register_element :ins + register_element :kbd + register_element :label + register_element :legend + register_element :li + register_element :main + register_element :map + register_element :mark + register_element :menu + register_element :meter + register_element :nav + register_element :noscript + register_element :object + register_element :ol + register_element :optgroup + register_element :option + register_element :output + register_element :p + register_element :picture + register_element :pre + register_element :progress + register_element :q + register_element :rp + register_element :rt + register_element :ruby + register_element :s + register_element :samp + register_element :script + register_element :section + register_element :select_tag, "select" + register_element :slot + register_element :small + register_element :span + register_element :strong + register_element :style + register_element :sub + register_element :summary + register_element :sup + register_element :table + register_element :tbody + register_element :td + register_element :template + register_element :textarea + register_element :tfoot + register_element :th + register_element :thead + register_element :time + register_element :title + register_element :tr + register_element :u + register_element :ul + register_element :var + register_element :video + + register_void_element :area + register_void_element :base + register_void_element :br + register_void_element :col + register_void_element :embed + register_void_element :hr + register_void_element :img + register_void_element :input + register_void_element :link + register_void_element :meta + register_void_element :source + register_void_element :track + register_void_element :wbr + + register_empty_element :iframe + register_empty_element :portal + end +end diff --git a/src/blueprint/html/svg.cr b/src/blueprint/html/svg.cr index a3718d1..3a7dc64 100644 --- a/src/blueprint/html/svg.cr +++ b/src/blueprint/html/svg.cr @@ -1,6 +1,6 @@ require "../svg/component" -module Blueprint::HTML +module Blueprint::HTML::SVG private def svg(**attributes, &) : Nil render Blueprint::SVG::Component.new(**attributes) do |component| with component yield @@ -8,6 +8,6 @@ module Blueprint::HTML end private def svg(**attributes) : Nil - svg(**attributes) { } + render Blueprint::SVG::Component.new(**attributes) end end diff --git a/src/blueprint/html/utils.cr b/src/blueprint/html/utils.cr index a907bb5..f4c6e8e 100644 --- a/src/blueprint/html/utils.cr +++ b/src/blueprint/html/utils.cr @@ -1,4 +1,4 @@ -module Blueprint::HTML +module Blueprint::HTML::Utils private def plain(content : String) : Nil ::HTML.escape(content, @buffer) end diff --git a/src/blueprint/svg/component.cr b/src/blueprint/svg/component.cr index 5f386b4..77510c8 100644 --- a/src/blueprint/svg/component.cr +++ b/src/blueprint/svg/component.cr @@ -7,9 +7,11 @@ struct Blueprint::SVG::Component(T) new kwargs end - {% for tag in %w(a animate animateMotion animateTransform circle clipPath defs desc discard ellipse feBlend feColorMatrix feComponentTransfer feComposite feConvolveMatrix feDiffuseLighting feDisplacementMap feDistantLight feDropShadow feFlood feFuncA feFuncB feFuncG feFuncR feGaussianBlur feImage feMerge feMergeNode feMorphology feOffset fePointLight feSpecularLighting feSpotLight feTile feTurbulence filter foreignObject g image line linearGradient marker mask metadata mpath path pattern polygon polyline radialGradient rect script set stop style svg switch symbol text textPath title tspan use view) %} - register_element {{tag}} - {% end %} + macro finished + {% for tag in %w(a animate animateMotion animateTransform circle clipPath defs desc discard ellipse feBlend feColorMatrix feComponentTransfer feComposite feConvolveMatrix feDiffuseLighting feDisplacementMap feDistantLight feDropShadow feFlood feFuncA feFuncB feFuncG feFuncR feGaussianBlur feImage feMerge feMergeNode feMorphology feOffset fePointLight feSpecularLighting feSpotLight feTile feTurbulence filter foreignObject g image line linearGradient marker mask metadata mpath path pattern polygon polyline radialGradient rect script set stop style svg switch symbol text textPath title tspan use view) %} + register_element {{tag}} + {% end %} + end def initialize(attributes : T) {% T.raise "Expected T be NamedTuple, but got #{T}." unless T <= NamedTuple %}