Skip to content

Commit

Permalink
feat: Support SVG rendering (#42)
Browse files Browse the repository at this point in the history
  • Loading branch information
stephannv authored Apr 21, 2023
1 parent e61e536 commit 17432d2
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 1 deletion.
29 changes: 29 additions & 0 deletions spec/blueprint/html/svg_spec.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
require "../../spec_helper"

private class Example
include Blueprint::HTML

private def blueprint
svg width: 30, height: 10 do
g fill: :red do
rect x: 0, y: 0, width: 10, height: 10
rect x: 20, y: 0, width: 10, height: 10
end
end
end
end

describe Blueprint::HTML do
it "allows SVG rendering" do
example = Example.new

example.to_html.should eq <<-HTML.strip.gsub(/\R\s+/, "")
<svg width="30" height="10">
<g fill="red">
<rect x="0" y="0" width="10" height="10"></rect>
<rect x="20" y="0" width="10" height="10"></rect>
</g>
</svg>
HTML
end
end
42 changes: 42 additions & 0 deletions spec/blueprint/svg/component_spec.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
require "../../spec_helper"

private ELEMENTS = %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
)

private class DummyPage
include Blueprint::HTML

private def blueprint
svg do
{% for element in ELEMENTS %}
{{element.id}}
{{element.id}}(attribute: "test")
{{element.id}} { "content" }
{{element.id}}(attribute: "test") { "content" }
{% end %}
end
end
end

describe "Bluprint::SVG::Component" do
it "defines all SVG element helper methods" do
page = DummyPage.new
expected_html = String.build do |io|
io << "<svg>"
ELEMENTS.each do |tag|
io << "<" << tag << ">" << "</" << tag << ">"
io << "<" << tag << " attribute=\"test\">" << "</" << tag << ">"
io << "<" << tag << ">content" << "</" << tag << ">"
io << "<" << tag << " attribute=\"test\">content" << "</" << tag << ">"
end
io << "</svg>"
end

page.to_html.should eq expected_html
end
end
3 changes: 2 additions & 1 deletion src/blueprint/html.cr
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
require "html"

require "./html/attributes_parser"
require "./html/builder"
require "./html/content_capture"
require "./html/element_registrar"
require "./html/renderer"
require "./html/standard_elements"
require "./html/svg"
require "./html/utils"
require "./html/builder"

module Blueprint::HTML
@buffer = IO::Memory.new
Expand Down
13 changes: 13 additions & 0 deletions src/blueprint/html/svg.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
require "../svg/component"

module Blueprint::HTML
def svg(**attributes, &)
render Blueprint::SVG::Component.new(**attributes) do |component|
with component yield
end
end

def svg(**attributes)
svg(**attributes) { }
end
end
24 changes: 24 additions & 0 deletions src/blueprint/svg/component.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
struct Blueprint::SVG::Component(T)
include Blueprint::HTML

@attributes : T

def self.new(**kwargs)
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 %}

def initialize(attributes : T)
{% T.raise "Expected T be NamedTuple, but got #{T}." unless T <= NamedTuple %}
@attributes = attributes
end

def blueprint(&)
element :svg, **@attributes do
yield
end
end
end

0 comments on commit 17432d2

Please sign in to comment.