nitdoc: create js module utils
[nit.git] / lib / html.nit
index c8e1949..48de688 100644 (file)
@@ -93,7 +93,13 @@ end
 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
@@ -124,7 +130,7 @@ class HTMLTag
                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
@@ -158,7 +164,7 @@ class HTMLTag
        # 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
 
@@ -169,14 +175,27 @@ class HTMLTag
 
        # 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))
                return self
        end
 
+       # Append raw HTML to element
+       #     var p = new HTMLTag("p")
+       #     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
+               add(new HTMLRaw(txt))
+               return self
+       end
+
        # Render the element as HTML string
        fun html: String do
                var res = new Array[String]
@@ -184,6 +203,17 @@ class HTMLTag
                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])
@@ -191,7 +221,7 @@ class HTMLTag
                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 ">"
@@ -206,11 +236,11 @@ class HTMLTag
                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
@@ -220,13 +250,13 @@ class HTMLTag
                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 "\""
@@ -237,9 +267,9 @@ class HTMLTag
                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