From d2ed476f1c7da02e60089c86b1ea8e6997fb29fd Mon Sep 17 00:00:00 2001 From: stephann <3025661+stephannv@users.noreply.github.com> Date: Mon, 9 Sep 2024 17:18:00 -0300 Subject: [PATCH] feat: Add raw html renderer --- spec/blueprint/raw_html_spec.cr | 138 ++++++++++++++++++++++++++++++++ src/blueprint/raw_html.cr | 48 +++++++++++ 2 files changed, 186 insertions(+) create mode 100644 spec/blueprint/raw_html_spec.cr create mode 100644 src/blueprint/raw_html.cr diff --git a/spec/blueprint/raw_html_spec.cr b/spec/blueprint/raw_html_spec.cr new file mode 100644 index 0000000..f52706f --- /dev/null +++ b/spec/blueprint/raw_html_spec.cr @@ -0,0 +1,138 @@ +require "../spec_helper" +require "../../src/blueprint/raw_html" + +private class BaseLayout + include Blueprint::RawHTML + + private def blueprint(&) + doctype + + html lang: "en" do + head do + title "Test page" + + meta charset: "utf-8" + meta name: "viewport", content: "width=device-width,initial-scale=1" + + link href: "app.css", rel: "stylesheet" + script type: "text/javascript", src: "app.js" + end + + body do + yield + end + end + end +end + +private class NavbarComponent + include Blueprint::RawHTML + + private def blueprint + nav do + ul do + li { a("Home", href: "/home") } + li { a("About", href: "/about") } + li { a("Contact", href: "/contact") } + end + end + end +end + +private class ArticleComponent + include Blueprint::RawHTML + + def initialize(@title : String); end + + private def blueprint(&) + div class: "flex flex-col gap-2 bg-white border shadow" do + title + yield + end + end + + def title + div @title, class: "p-2 text-lg font-bold" + end + + def body(&) + div class: "p-4" do + yield + end + end +end + +private class ExamplePage + include Blueprint::RawHTML + + private def blueprint + render BaseLayout.new do + render NavbarComponent.new + + div do + article("Hello World", "Welcome to blueprint") + article("Blueprint", "Blueprint is an Html builder") + div(class: { hello: "world" }) { "" } + a "Click me!", class: "bg-red\" onclick=\"alert('danger!')" + end + end + end + + private def article(title : String, content : String) + render ArticleComponent.new(title) do |article| + article.body { content } + end + end +end + +describe Blueprint::RawHTML do + describe "#to_html" do + it "renders html" do + page = ExamplePage.new + expected_html = <<-HTML.strip.gsub(/\R\s+/, "") + + + + Test page + + + + + + + + + + + +
+
+
Hello World
+
Welcome to blueprint
+
+ +
+
Blueprint
+
Blueprint is an Html builder
+
+ +
+ + Click me! +
+ + + HTML + + html = page.to_html + + html.should eq expected_html + end + end +end diff --git a/src/blueprint/raw_html.cr b/src/blueprint/raw_html.cr new file mode 100644 index 0000000..f282c84 --- /dev/null +++ b/src/blueprint/raw_html.cr @@ -0,0 +1,48 @@ +require "html" + +require "./html" + +module Blueprint::RawHTML + include Blueprint::HTML + + private def append_attribute(attribute_name, attribute_value) : Nil + @buffer << " " + @buffer << attribute_name.to_s + @buffer << %(=") + @buffer << attribute_value.to_s + @buffer << %(") + end + + private def render_block(&) : Nil + buffer_size_before_block_evaluation = @buffer.bytesize + content = with self yield + @buffer << content.to_s if buffer_size_before_block_evaluation == @buffer.bytesize + end + + private def element(_tag_name : String | Symbol, __content__ : String, **attributes) : Nil + @buffer << "<" + @buffer << _tag_name + parse_attributes(attributes) + @buffer << ">" + @buffer << __content__ + @buffer << "" + end + + private def plain(content : String) : Nil + @buffer << content + end + + private def comment(&) : Nil + @buffer << "" + end + + private def comment(content : String) : Nil + @buffer << "" + end +end