Created
March 8, 2021 21:24
-
-
Save pootsbook/09702fb05cbac6dbc507169a3a56fed3 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class HTMLDoc | |
def initialize | |
@node_id = 0 | |
@parent_id = 0 | |
@doc = [] | |
yield self if block_given? | |
end | |
def el(type, attributes = {}) | |
@node_id += 1 | |
grandparent_id = @parent_id | |
node = { | |
id: @node_id, | |
parent_id: @parent_id, | |
type: type, | |
attrs: attributes | |
} | |
case type | |
when :text | |
@doc << node.merge(content: yield) | |
else | |
@doc << node | |
@parent_id = @node_id | |
yield | |
end | |
@parent_id = grandparent_id | |
end | |
def ast | |
root = @doc.find {|el| el[:parent_id] == 0 } | |
{ type: root[:type], | |
attributes: root[:attrs], | |
children: gather_children(root[:id]) | |
} | |
end | |
def gather_children(node_id) | |
@doc.select do |el| | |
el[:parent_id] == node_id | |
end.map do |el| | |
if el[:type] == :text | |
children = [el[:content]] | |
else | |
children = gather_children(el[:id]) | |
end | |
{ type: el[:type], | |
attributes: el[:attrs], | |
children: children } | |
end | |
end | |
def to_s | |
puts @doc.inspect # DEBUG | |
puts ast.inspect # DEBUG | |
node(ast[:type], ast[:attributes], ast[:children]) | |
end | |
def node(type, attributes = {}, children = []) | |
case type | |
when :text | |
children.empty? ? "" : children.first | |
when :input | |
render_opening_tag(type, attributes) | |
else | |
[ | |
render_opening_tag(type, attributes), | |
render_children(children), | |
"</#{type}>" | |
].flatten.join("\n") | |
end | |
end | |
def render_children(children) | |
children.map do |child| | |
node(child[:type], child[:attributes], child[:children]) | |
end.flatten.join("\n") | |
end | |
def render_opening_tag(name, attrs) | |
if attrs.nil? || attrs.empty? | |
"<#{name}>" | |
else | |
"<#{name} #{stringify_attrs(attrs)}>" | |
end | |
end | |
def stringify_attrs(attrs) | |
attrs.map do |key, value| | |
%Q(#{key}="#{value}") | |
end.join(" ") | |
end | |
end | |
doc = HTMLDoc.new do |d| | |
d.el :html do | |
d.el :head do | |
d.el :title do | |
d.el :text do | |
"Hello," | |
end | |
d.el :text do | |
" World!" | |
end | |
end | |
end | |
d.el :body do | |
d.el :h1 do | |
d.el :text do | |
"TITLE" | |
end | |
end | |
d.el :p do | |
d.el :text do | |
"Paragraph 1" | |
end | |
end | |
d.el :p do | |
d.el :text do | |
"Paragraph 2" | |
end | |
end | |
end | |
end | |
end | |
puts doc.to_s |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment