class HTMLTag
# HTML tagname: 'div' for <div></div>
var tag: String
- init(tag: String) do self.tag = tag
+ init(tag: String) do
+ self.tag = tag
+ self.is_void = (once ["area", "base", "br", "col", "command", "embed", "hr", "img", "input", "keygen", "link", "meta", "param", "source", "track", "wbr"]).has(tag)
+ end
+
+ # Is the HTML element a void element?
+ var is_void: Bool
init with_attrs(tag: String, attrs: Map[String, String]) do
self.tag = tag
classes.add(klass)
return self
end
- private var classes: Set[String] = new HashSet[String]
+ var classes: Set[String] = new HashSet[String]
# Add multiple CSS classes
fun add_classes(classes: Collection[String]): HTMLTag do
# Clear all child and set the text of element
# var p = new HTMLTag("p")
# p.text("Hello World!")
- # p.html # -> "<p>Hello World!</p>"
+ # assert p.html == "<p>Hello World!</p>"
# Text is escaped see: `standard::String::html_escape`
fun text(txt: String): HTMLTag do
# Append text to element
# var p = new HTMLTag("p")
- # p.append("Hello").add(new HTMLTag("br")).append("World!")
- # p.html # -> "<p>Hello<br/>World!</p>"
+ # p.append("Hello")
+ # p.add(new HTMLTag("br"))
+ # p.append("World!")
+ # assert p.html == "<p>Hello<br/>World!</p>"
# Text is escaped see: standard::String::html_escape
fun append(txt: String): HTMLTag do
add(new HTMLRaw(txt.html_escape))
# Append raw HTML to element
# var p = new HTMLTag("p")
- # p.append("Hello").add_raw_html("<bla/>")
+ # p.append("Hello")
+ # p.add_raw_html("<bla/>")
# p.html #- "<p>Hello<bla/></p>"
# Note: the HTML in insered as it, no verification is done
fun add_raw_html(txt: String): HTMLTag do
return res.to_s
end
+ # Save html page in the specified file
+ fun save(file: String) do
+ var out = new OFStream.open(file)
+ var res = new Array[String]
+ render_in(res)
+ for r in res do
+ out.write(r)
+ end
+ out.close
+ end
+
# In order to avoid recursive concatenation,
# this function collects in `res` all the small fragments of `String`
private fun render_in(res: Sequence[String])
res.add "<"
res.add tag
render_attrs_in(res)
- if tag != "script" and children.is_empty then
+ if is_void and children.is_empty then
res.add "/>"
else
res.add ">"
if attrs.has_key("class") or not classes.is_empty then
res.add " class=\""
for cls in classes do
- res.add cls
+ res.add cls.html_escape
res.add " "
end
if attrs.has_key("class") then
- res.add attrs["class"]
+ res.add attrs["class"].html_escape
res.add " "
end
if res.last == " " then res.pop
if attrs.has_key("style") or not css_props.is_empty then
res.add " style=\""
for k, v in attrs do
- res.add k
+ res.add k.html_escape
res.add ": "
- res.add v
+ res.add v.html_escape
res.add "; "
end
if attrs.has_key("style") then
- res.add(attrs["style"])
+ res.add(attrs["style"].html_escape)
end
if res.last == "; " then res.pop
res.add "\""
for key, value in attrs do
if key == "class" or key == "style" then continue
res.add " "
- res.add key
+ res.add key.html_escape
res.add "=\""
- res.add value
+ res.add value.html_escape
res.add "\""
end
end