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 << ""
- @buffer << _tag_name
- @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 << ""
- @buffer << _tag_name
- @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 << ""
+ @buffer << _tag_name
+ @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 << ""
+ @buffer << _tag_name
+ @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 %}