From f743bffcaec58177256ec8c75bd334c0d921e3a5 Mon Sep 17 00:00:00 2001 From: Alexandre Terrasa Date: Fri, 19 Jul 2013 17:51:16 -0400 Subject: [PATCH] ni_nitdoc: get rid of HTML lib for performances considerations Signed-off-by: Alexandre Terrasa --- src/ni_nitdoc.nit | 657 ++++++++++++++++++++++++++--------------------------- 1 file changed, 317 insertions(+), 340 deletions(-) diff --git a/src/ni_nitdoc.nit b/src/ni_nitdoc.nit index 6198890..8b6a8e5 100644 --- a/src/ni_nitdoc.nit +++ b/src/ni_nitdoc.nit @@ -18,7 +18,6 @@ module ni_nitdoc import model_utils import abstract_compiler -import html class Nitdoc private var toolcontext: ToolContext @@ -173,82 +172,76 @@ end # Nitdoc base page abstract class NitdocPage - super HTMLPage var dot_dir: nullable String var source: nullable String - redef fun head do - add("meta").attr("charset", "utf-8") - add("script").attr("type", "text/javascript").attr("src", "scripts/jquery-1.7.1.min.js") - add("script").attr("type", "text/javascript").attr("src", "quicksearch-list.js") - add("script").attr("type", "text/javascript").attr("src", "scripts/js-facilities.js") - add("link").attr("rel", "stylesheet").attr("href", "styles/main.css").attr("type", "text/css").attr("media", "screen") - end + init do end - redef fun body do - header - open("div").add_class("page") - content - close("div") - footer + fun append(str: String) do html.append(str) + var html = new Buffer + + fun head do + append("") + append("") + append("") + append("") + append("") end fun menu is abstract fun header do - open("header") - open("nav").add_class("main") - open("ul") + append("
") + append("") + append("
") end fun content is abstract fun footer do - add("footer").text("Nit standard library. Version jenkins-component=stdlib-19.") + append("
Nit standard library. Version jenkins-component=stdlib-19.
") end # Generate a clickable graphviz image using a dot content @@ -259,11 +252,11 @@ abstract class NitdocPage file.write(dot) file.close sys.system("\{ test -f {output_dir}/{name}.png && test -f {output_dir}/{name}.s.dot && diff {output_dir}/{name}.dot {output_dir}/{name}.s.dot >/dev/null 2>&1 ; \} || \{ cp {output_dir}/{name}.dot {output_dir}/{name}.s.dot && dot -Tpng -o{output_dir}/{name}.png -Tcmapx -o{output_dir}/{name}.map {output_dir}/{name}.s.dot ; \}") - open("article").add_class("graph") - add("img").attr("src", "{name}.png").attr("usemap", "#{name}").attr("style", "margin:auto").attr("alt", "{alt}") - close("article") + append("
") + append("{alt}") + append("
") var fmap = new IFStream.open("{output_dir}/{name}.map") - add_html(fmap.read_all) + append(fmap.read_all) fmap.close end @@ -283,6 +276,29 @@ abstract class NitdocPage return " (show code)" end end + + # Render the page as a html string + fun render: String do + append("") + append("") + head + append("") + append("") + header + append("
") + content + append("
") + footer + append("") + return html.to_s + end + + # Save html page in the specified file + fun save(file: String) do + var out = new OFStream.open(file) + out.write(render) + out.close + end end # The overview page @@ -312,37 +328,31 @@ class NitdocOverview redef fun head do super - add("title").text("Overview | Nit Standard Library") + append("Overview | Nit Standard Library") end redef fun menu do - add("li").add_class("current").text("Overview") - open("li") - add("a").attr("href", "full-index.html").text("Full Index") - close("li") + append("
  • Overview
  • ") + append("
  • Full Index
  • ") end redef fun content do - open("div").add_class("content fullpage") - add("h1").text("Nit Standard Library") - open("article").add_class("overview") - add_html("

    Documentation for the standard library of Nit
    Version jenkins-component=stdlib-19
    Date: TODAY

    ") - close("article") - open("article").add_class("overview") + append("
    ") + append("

    Nit Standard Library

    ") + append("

    Documentation for the standard library of Nit
    Version jenkins-component=stdlib-19
    Date: TODAY

    ") + append("
    ") # module list - add("h2").text("Modules") - open("ul") + append("

    Modules

    ") + append("
      ") for mmodule in mmodules do var amodule = mbuilder.mmodule2nmodule[mmodule] - open("li") - add_html("{mmodule.link(amodule)} {amodule.short_comment}") - close("li") + append("
    • {mmodule.link(mbuilder)} {amodule.short_comment}
    • ") end - close("ul") + append("
    ") # module graph process_generate_dot - close("article") - close("div") + append("
    ") + append("
    ") end fun process_generate_dot do @@ -374,23 +384,21 @@ class NitdocFullindex redef fun head do super - add("title").text("Full Index | Nit Standard Library") + append("Full Index | Nit Standard Library") end redef fun menu do - open("li") - add("a").attr("href", "index.html").text("Overview") - close("li") - add("li").add_class("current").text("Full Index") + append("
  • Overview
  • ") + append("
  • Full Index
  • ") end redef fun content do - open("div").add_class("content fullpage") - add("h1").text("Full Index") + append("
    ") + append("

    Full Index

    ") module_column classes_column properties_column - close("div") + append("
    ") end # Add to content modules column @@ -399,19 +407,17 @@ class NitdocFullindex var sorted = mmodules var sorterp = new ComparableSorter[MModule] sorterp.sort(sorted) - open("article").add_class("modules filterable") - add("h2").text("Modules") - open("ul") + append("
    ") + append("

    Modules

    ") + append("") + append("") end # Add to content classes modules @@ -419,25 +425,21 @@ class NitdocFullindex var sorted = mmodules.first.imported_mclasses.to_a var sorterp = new ComparableSorter[MClass] sorterp.sort(sorted) - open("article").add_class("classes filterable") - add("h2").text("Classes") - open("ul") - + append("
    ") + append("

    Classes

    ") + append("
      ") for mclass in sorted do - open("li") - add("a").attr("href", "{mclass}.html").text(mclass.name) - close("li") + append("
    • (mclass.name)
    • ") end - - close("ul") - close("article") + append("
    ") + append("
    ") end # Insert the properties column of fullindex page fun properties_column do - open("article").add_class("properties filterable") - add("h2").text("Properties") - open("ul") + append("
    ") + append("

    Properties

    ") + append("
      ") var sorted_imported = mmodules.first.imported_methods.to_a var sorted_redef = mmodules.first.redef_methods.to_a var sorterp = new ComparableSorter[MProperty] @@ -446,24 +448,21 @@ class NitdocFullindex for method in sorted_imported do if method.visibility is none_visibility or method.visibility is intrude_visibility then continue - open("li").add_class("intro") - add("span").attr("title", "introduction").text("I") - add_html(" ") - add("a").attr("href", "{method.local_class.name}.html").attr("title", "").text("{method.name} ({method.local_class.name})") - close("li") + append("
    • ") + append("I ") + append("{method.name} ({method.local_class.name})") + append("
    • ") end for method in sorted_redef do if method.visibility is none_visibility or method.visibility is intrude_visibility then continue - open("li").add_class("redef") - add("span").attr("title", "redefinition").text("R") - add_html(" ") - add("a").attr("href", "{method.local_class.name}.html").attr("title", "").text("{method.name} ({method.local_class.name})") - close("li") + append("
    • ") + append("R ") + append("{method.name} ({method.local_class.name})") + append("
    • ") end - - close("ul") - close("article") + append("
    ") + append("
    ") end end @@ -484,43 +483,25 @@ class NitdocModule redef fun head do super var amodule = mbuilder.mmodule2nmodule[mmodule] - add("title").text("{mmodule.name} module | {amodule.short_comment}") + append("{mmodule.name} module | {amodule.short_comment}") end redef fun menu do - open("li") - add("a").attr("href", "index.html").text("Overview") - close("li") - add("li").add_class("current").text(mmodule.name) - open("li") - add("a").attr("href", "full-index.html").text("Full Index") - close("li") + append("
  • Overview
  • ") + append("
  • {mmodule.name}
  • ") + append("
  • Full Index
  • ") end redef fun content do sidebar - open("div").add_class("content") - add("h1").text(mmodule.name) - add("div").add_class("subtitle") - add_html("module {mmodule.namespace(mbuilder)}") - module_comment + append("
    ") + append("

    {mmodule.name}

    ") + append("
    {mmodule.html_signature(mbuilder)}
    ") + append(mmodule.html_full_comment(mbuilder)) process_generate_dot classes properties - close("div") - end - - # Insert module comment in the content - fun module_comment do - var amodule = mbuilder.mmodule2nmodule[mmodule] - var doc = amodule.comment - open("div").attr("id", "description") - add("pre").add_class("text_label").text(doc) - add("textarea").add_class("edit").attr("rows", "1").attr("cols", "76").attr("id", "fileContent").text(" ") - add("a").attr("id", "cancelBtn").text("Cancel") - add("a").attr("id", "commitBtn").text("Commit") - add("pre").add_class("text_label").attr("id", "preSave").attr("type", "2") - close("div") + append("
    ") end fun process_generate_dot do @@ -549,16 +530,16 @@ class NitdocModule fun sidebar do var amodule = mbuilder.mmodule2nmodule[mmodule] - open("div").add_class("menu") - open("nav") - add("h3").text("Module Hierarchy") + append("") end private fun display_module_list(list: Array[MModule]) do - open("ul") + append("") end fun classes do @@ -609,25 +585,25 @@ class NitdocModule sorted.add_all(all_mclasses) var sorter = new ComparableSorter[MClass] sorter.sort(sorted) - open("div").add_class("module") - open("article").add_class("classes filterable") - add("h2").text("Classes") - open("ul") + append("
    ") + append("
    ") + append("

    Classes

    ") + append("
      ") for c in sorted do var nclass = mbuilder.mclassdef2nclassdef[c.intro].as(AStdClassdef) if redef_mclasses.has(c) and c.intro_mmodule.public_owner != mmodule then - open("li").add_class("redef") - add("span").attr("title", "refined in this module").text("R ") + append("
    • ") + append("R ") else - open("li").add_class("intro") - add("span").attr("title", "introduced in this module").text("I ") + append("
    • ") + append("I ") end - add_html(c.link(nclass)) - close("li") + append(c.link(nclass)) + append("
    • ") end - close("ul") - close("article") - close("div") + append("
    ") + append("
    ") + append("
    ") end fun properties do @@ -640,26 +616,26 @@ class NitdocModule var sorted = mpropdefs.to_a var sorter = new ComparableSorter[MPropDef] sorter.sort(sorted) - open("article").add_class("properties filterable") - add("h2").text("Properties") - open("ul") + append("
    ") + append("

    Properties

    ") + append("
      ") for p in sorted do if p isa MAttributeDef then continue if p.mproperty.visibility <= none_visibility then continue if not mbuilder.mpropdef2npropdef.has_key(p) then continue var nprop = mbuilder.mpropdef2npropdef[p] if p.is_intro then - open("li").add_class("intro") - add("span").attr("title", "introduction").text("I") + append("
    • ") + append("I {p.link(nprop)} ({p.mclassdef.mclass.name})") + append("
    • ") else - open("li").add_class("redef") - add("span").attr("title", "redefinition").text("R") + append("
    • ") + append("R {p.link(nprop)} ({p.mclassdef.mclass.name})") + append("
    • ") end - add_html(" {p.link(nprop)} ({p.mclassdef.mclass.name})") - close("li") end - close("ul") - close("article") + append("
    ") + append("
    ") end end @@ -683,46 +659,38 @@ class NitdocClass super var nclass = mbuilder.mclassdef2nclassdef[mclass.intro] if nclass isa AStdClassdef then - add("title").text("{mclass.name} class | {nclass.short_comment}") + append("{mclass.name} class | {nclass.short_comment}") else - add("title").text("{mclass.name} class") + append("{mclass.name} class") end end redef fun menu do - open("li") - add("a").attr("href", "index.html").text("Overview") - close("li") - open("li") + append("
  • Overview
  • ") var public_owner = mclass.public_owner if public_owner is null then - var am = mbuilder.mmodule2nmodule[mclass.intro_mmodule] - add_html(mclass.intro_mmodule.link(am)) + append("
  • {mclass.intro_mmodule.link(mbuilder)}
  • ") else - var am = mbuilder.mmodule2nmodule[public_owner] - add_html(public_owner.link(am)) + append("
  • {public_owner.link(mbuilder)}
  • ") end - close("li") - add("li").add_class("current").text(mclass.name) - open("li") - add("a").attr("href", "full-index.html").text("Full Index") - close("li") + append("
  • {mclass.name}
  • ") + append("
  • Full Index
  • ") end redef fun content do - open("div").add_class("menu") + append("") + append("
    ") class_doc - close("div") + append("
    ") end fun properties_column do var sorter = new ComparableSorter[MPropDef] - open("nav").add_class("properties filterable") - add("h3").text("Properties") + append("") end private fun display_mpropdef_list(list: Array[MPropDef]) do - open("ul") + append("") end fun inheritance_column do var sorted = new Array[MClass] var sorterp = new ComparableSorter[MClass] - open("nav") - add("h3").text("Inheritance") + append("") end fun class_doc do # title - add("h1").text(mclass.to_s) - open("div").add_class("subtitle") + append("

    {mclass.to_s}

    ") + append("
    ") var subtitle = "" if mclass.visibility is none_visibility then subtitle += "private " - subtitle += "{mclass.kind} {mclass.public_owner.namespace(mbuilder)}::{mclass}" - add_html(subtitle) - close("div") + subtitle += "{mclass.kind} {mclass.public_owner.html_namespace(mbuilder)}::{mclass}" + append(subtitle) + append("
    ") # comment var nclass = mbuilder.mclassdef2nclassdef[mclass.intro] - add_html("
    ") - open("section").add_class("description") - if nclass isa AStdClassdef and not nclass.comment.is_empty then add_html("
    {nclass.comment}
    CancelCommit
    ")
    +		append("
    ") + append("
    ") + if nclass isa AStdClassdef and not nclass.comment.is_empty then append("
    {nclass.comment}
    CancelCommit
    ")
     		process_generate_dot
    -		close("section")
    +		append("
    ") # concerns var sorted = new Array[MModule] sorted.add_all(mclass.concerns.keys) var sorterp = new ComparableSorter[MModule] sorterp.sort(sorted) - open("section").add_class("concerns") - add("h2").add_class("section-header").text("Concerns") - open("ul") + append("
    ") + append("

    Concerns

    ") + append("
      ") for owner in sorted do var nmodule = mbuilder.mmodule2nmodule[owner] var childs = mclass.concerns[owner] - open("li") - add_html("{owner.name}: {nmodule.short_comment}") + append("
    • ") + append("{owner.name}: {nmodule.short_comment}") if not childs is null then - open("ul") + append("
        ") var sortedc = childs.to_a var sorterpc = new ComparableSorter[MModule] sorterpc.sort(sortedc) for child in sortedc do var nchild = mbuilder.mmodule2nmodule[child] - add_html("
      • {child.name}: {nchild.short_comment}
      • ") + append("
      • {child.name}: {nchild.short_comment}
      • ") end - close("ul") + append("
      ") end - close("li") + append("
    • ") end - close("ul") - close("section") + append("
    ") + append("
    ") # properties var sorterprop = new ComparableSorter[MProperty] var sorterc = new ComparableSorter[MClass] var lmmodule = new List[MModule] # virtual and formal types if mclass.virtual_types.length > 0 or mclass.arity > 0 then - open("section").add_class("types") - add("h2").text("Formal and Virtual Types") + append("
    ") + append("

    Formal and Virtual Types

    ") if mclass.virtual_types.length > 0 then for prop in mclass.virtual_types do description(prop) #TODO this is incorrect if mclass.arity > 0 and nclass isa AStdClassdef then for prop in nclass.n_formaldefs do - open("article").attr("id", "FT_Object_{prop.collect_text}") - open("h3").add_class("signature").text("{prop.collect_text}: nullable ") - add_html("Object") - close("h3") - add_html("
    formal generic type
    ") - close("article") + append("
    ") + append("

    {prop.collect_text}: nullable ") + append("Object") + append("

    ") + append("
    formal generic type
    ") + append("
    ") end end - close("section") + append("
    ") end # constructors if mclass.constructors.length > 0 then var sortedc = mclass.constructors.to_a sorterprop.sort(sortedc) - open("section").add_class("constructors") - add("h2").add_class("section-header").text("Constructors") + append("
    ") + append("

    Constructors

    ") for prop in sortedc do description(prop) - close("section") + append("
    ") end # methods - open("section").add_class("methods") - add("h2").add_class("section-header").text("Methods") + append("
    ") + append("

    Methods

    ") for mmodule, mmethods in mclass.all_methods do var nmodule = mbuilder.mmodule2nmodule[mmodule] - add_html("") + append("") if mmodule != mclass.intro_mmodule and mmodule != mclass.public_owner then if mclass.has_mmodule(mmodule) then - add_html("

    {mmodule.name}: {nmodule.short_comment}

    ") + append("

    {mmodule.name}: {nmodule.short_comment}

    ") else - add_html("

    Methods refined in {mmodule.link(nmodule)}

    {mmodule.name}: {nmodule.short_comment}

    ") + append("

    Methods refined in {mmodule.link(mbuilder)}

    {mmodule.name}: {nmodule.short_comment}

    ") end end var sortedc = mmethods.to_a @@ -941,22 +903,21 @@ class NitdocClass var sortedc = new Array[MClass] sortedc.add_all(mclass.inherited.keys) sorterc.sort(sortedc) - add("h3").text("Inherited Methods") + append("

    Inherited Methods

    ") for imclass in sortedc do var inclass = mbuilder.mclassdef2nclassdef[imclass.intro].as(AStdClassdef) var sortedp = mclass.inherited[imclass].to_a sorterprop.sort(sortedp) - open("p") - add_html("Defined in {imclass.link(inclass)}: ") + append("

    Defined in {imclass.link(inclass)}: ") for method in sortedp do #TODO link to inherited propdef - add_html("{method.name}") - if method != sortedp.last then add_html(", ") + append("{method.name}") + if method != sortedp.last then append(", ") end - close("p") + append("

    ") end end - close("section") + append("
    ") end fun description(prop: MProperty) do @@ -977,41 +938,35 @@ class NitdocClass else classes.add("public") end - open("article").add_classes(classes).attr("id", "{prop.anchor}") + append("
    ") var sign = prop.name - open("h3").add_class("signature") - add_html("{prop.name}{nprop.signature}") - close("h3") - open("div").add_class("info") - add_html("{if prop.is_redef then "redef" else ""} fun {prop.intro_mclassdef.namespace(mclass)}::{prop.name}
    ") - close("div") - open("div").add_class("description") + append("

    {prop.name}{nprop.signature}

    ") + append("
    ") + append("{if prop.is_redef then "redef" else ""} fun {prop.intro_mclassdef.namespace(mclass)}::{prop.name}
    ") + append("
    ") + append("
    ") if nprop.comment == "" then - add_html("New Comment") + append("New Comment") else - add_html("
    {nprop.comment}
    ") + append("
    {nprop.comment}
    ") end - add_html("CancelCommit
    ")
    -		open("p")
    +		append("CancelCommit
    ")
    +		append("

    ") if prop.local_class != mclass then var mredef = prop.local_class.intro_mmodule - var nredef = mbuilder.mmodule2nmodule[mredef] - add_html("inherited from {mredef.link(nredef)} ") + append("inherited from {mredef.link(mbuilder)} ") end #TODO display show code if doc github var mintro = prop.intro_mclassdef.mmodule - var nintro = mbuilder.mmodule2nmodule[mintro] - add_html("defined by the module {mintro.link(nintro)}{if prop.apropdef is null then "" else show_source(prop.apropdef.location)}.") + append("defined by the module {mintro.link(mbuilder)}{if prop.apropdef is null then "" else show_source(prop.apropdef.location)}.") for parent in mclass.parents do var mparent = parent.intro_mmodule - var nparent = mbuilder.mmodule2nmodule[mparent] - if prop isa MMethod then if parent.constructors.has(prop) then add_html(" Previously defined by: {mparent.link(nparent)} for {parent.name}.") + if prop isa MMethod then if parent.constructors.has(prop) then append(" Previously defined by: {mparent.link(mbuilder)} for {parent.name}.") end - close("p") - close("div") - - close("article") + append("

    ") + append("
    ") + append("
    ") end fun process_generate_dot do @@ -1069,7 +1024,7 @@ redef class AModule for t in n_moduledecl.n_doc.n_comment do ret.append(t.text.substring_from(1)) end - return ret.to_s + return ret.to_s.html_escape end private fun short_comment: String do @@ -1077,7 +1032,7 @@ redef class AModule if n_moduledecl != null and n_moduledecl.n_doc != null then ret.append(n_moduledecl.n_doc.n_comment.first.text.substring_from(2).replace("\n", "")) end - return ret.to_s + return ret.to_s.html_escape end end @@ -1109,22 +1064,40 @@ redef class MModule end # Return a link (html a tag) to the nitdoc module page - fun link(amodule: AModule): String do - return "{name}" + fun link(mbuilder: ModelBuilder): String do + return "{name}" + end + + # Return the module signature decorated with html + fun html_signature(mbuilder: ModelBuilder): String do + return "module {html_namespace(mbuilder)}" end # Return the module namespace decorated with html - fun namespace(mbuilder: ModelBuilder): String do - var str = new Buffer + fun html_namespace(mbuilder: ModelBuilder): String do + var res = new Buffer + res.append("") var mowner = public_owner if mowner != null then - var nowner = mbuilder.mmodule2nmodule[mowner] - str.append(public_owner.link(nowner)) - str.append("::") - end - var nmodule = mbuilder.mmodule2nmodule[self] - str.append(self.link(nmodule)) - return str.to_s + res.append(public_owner.html_namespace(mbuilder)) + res.append("::") + end + res.append(self.link(mbuilder)) + res.append("") + return res.to_s + end + + # Return the full comment of the module decorated with html + fun html_full_comment(mbuilder: ModelBuilder): String do + var res = new Buffer + res.append("
    ") + res.append("
    {mbuilder.mmodule2nmodule[self].comment}
    ") + res.append("") + res.append("Cancel") + res.append("Commit") + res.append("
    ")
    +		res.append("
    ") + return res.to_s end end redef class MPropDef @@ -1134,7 +1107,7 @@ redef class MPropDef # Return a link (html a tag) to the nitdoc class page fun link(nprop: APropdef): String do - return "{mproperty}" + return "{mproperty.name}" end end @@ -1161,6 +1134,8 @@ redef class MProperty return "PROP_{c_name}" end + # Escape name for html output + redef fun name do return super.html_escape end redef class MClass @@ -1169,7 +1144,7 @@ redef class MClass redef fun <(other: OTHER): Bool do return self.name < other.name # Add type parameters - redef fun to_s do + fun html_signature: String do if arity > 0 then return "{name}[{intro.parameter_names.join(", ")}]" else @@ -1179,7 +1154,7 @@ redef class MClass # Return a link (html a tag) to the nitdoc class page fun link(aclass: AStdClassdef): String do - return "{self}" + return "{html_signature}" end # Associate all MMethods to each MModule concerns @@ -1274,6 +1249,8 @@ redef class MClass return "{name}.html" end + # Escape name for html output + redef fun name do return super.html_escape end redef class AStdClassdef @@ -1282,13 +1259,13 @@ redef class AStdClassdef if n_doc != null then for t in n_doc.n_comment do ret.append(t.text.substring_from(1)) end - return ret.to_s + return ret.to_s.html_escape end private fun short_comment: String do var ret = new Buffer if n_doc != null then ret.append(n_doc.n_comment.first.text.substring_from(2).replace("\n", "")) - return ret.to_s + return ret.to_s.html_escape end end @@ -1334,7 +1311,7 @@ redef class AAttrPropdef redef fun short_comment do var ret = new Buffer if n_doc != null then ret.append(n_doc.n_comment.first.text.substring_from(1)) - return ret.to_s + return ret.to_s.html_escape end end @@ -1342,7 +1319,7 @@ redef class AMethPropdef redef fun short_comment do var ret = new Buffer if n_doc != null then ret.append(n_doc.n_comment.first.text.substring_from(2).replace("\n", "")) - return ret.to_s + return ret.to_s.html_escape end redef fun signature: String do @@ -1356,7 +1333,7 @@ redef class AMethPropdef if n_doc != null then for t in n_doc.n_comment do ret.append(t.text.substring_from(1)) end - return ret.to_s + return ret.to_s.html_escape end end -- 1.7.9.5