Skip to content

Instantly share code, notes, and snippets.

@pootsbook
Created March 18, 2021 03:41
Show Gist options
  • Save pootsbook/65819c79722d93c9baf53d984f1884b2 to your computer and use it in GitHub Desktop.
Save pootsbook/65819c79722d93c9baf53d984f1884b2 to your computer and use it in GitHub Desktop.
Fusion of HTMLDocument and Hypertext
class HTMLDocument
ENTITIES = {
"'" => ''',
'&' => '&',
'"' => '"',
'<' => '&lt;',
'>' => '&gt;',
}
def initialize(indent = " ", level = 0)
@doc = ""
@indent = indent
@level = level
yield self if block_given?
end
def text(string)
@doc << "#{@indent * @level}#{escape(string)}\n"
end
def el(type, attrs={})
indentation = @indent * @level
if block_given?
@doc << "#{indentation}<#{type}#{attributes(attrs)}>\n"
@level += 1
yield
@level -= 1
@doc << "#{indentation}</#{type}>\n"
else
@doc << "#{indentation}<#{type}#{attributes(attrs)} />\n"
end
end
def to_s
@doc
end
def attributes(attrs)
attrs.map do |key, value|
case value
when false
when true
%[ #{key}]
else
%[ #{key}="#{escape(value.to_s)}"]
end
end.join
end
def escape(str)
str.gsub(/['&\"<>]/, ENTITIES)
end
end
doc = HTMLDocument.new do |d|
d.el :html, lang: "en-GB" do
d.el :head do
d.el :title do
d.text "Hello, World!"
end
end
d.el :body do
d.el :input, { type: "text" }
end
end
end
puts doc.to_s
#=>
# <html lang="en-GB">
# <head>
# <title>
# Hello, World!
# </title>
# </head>
# <body>
# <input type="text" />
# </body>
# </html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment