Merge: doc: fixed some typos and other misc. corrections
[nit.git] / src / nitweb.nit
index 355fd6a..8baf1e8 100644 (file)
 module nitweb
 
 import frontend
-import web
+import doc::api
 
 redef class ToolContext
 
-       # Host name to bind on.
+       # Path to app config file.
+       var opt_config = new OptionString("Path to app config file", "--config")
+
+       # Host name to bind on (will overwrite the config one).
        var opt_host = new OptionString("Host to bind the server on", "--host")
 
-       # Port number to bind on.
-       var opt_port = new OptionInt("Port number to use", 3000, "--port")
+       # Port number to bind on (will overwrite the config one).
+       var opt_port = new OptionInt("Port number to use", -1, "--port")
+
+       # --no-private
+       var opt_no_private = new OptionBool("Do not show private entities", "--no-private")
+
+       # --no-fictive
+       var opt_no_fictive = new OptionBool("Do not show fictive entities", "--no-fictive")
+
+       # --no-test
+       var opt_no_test = new OptionBool("Do not show test related entities", "--no-test")
+
+       # --no-attribute
+       var opt_no_attribute = new OptionBool("Do not show attributes", "--no-attribute")
+
+       # --no-empty-doc
+       var opt_no_empty_doc = new OptionBool("Do not undocumented entities", "--no-empty-doc")
 
        # Web rendering phase.
        var webphase: Phase = new NitwebPhase(self, null)
 
        init do
                super
-               option_context.add_option(opt_host, opt_port)
+               option_context.add_option(opt_config, opt_host, opt_port, opt_no_private,
+                       opt_no_fictive, opt_no_test, opt_no_attribute, opt_no_empty_doc)
        end
 end
 
 # Phase that builds the model and wait for http request to serve pages.
 private class NitwebPhase
        super Phase
-       redef fun process_mainmodule(mainmodule, mmodules)
-       do
-               var model = mainmodule.model
-               var modelbuilder = toolcontext.modelbuilder
 
-               # Build catalog
-               var catalog = new Catalog(modelbuilder)
-               for mpackage in model.mpackages do
-                       catalog.deps.add_node(mpackage)
-                       for mgroup in mpackage.mgroups do
-                               for mmodule in mgroup.mmodules do
-                                       for imported in mmodule.in_importation.direct_greaters do
-                                               var ip = imported.mpackage
-                                               if ip == null or ip == mpackage then continue
-                                               catalog.deps.add_edge(mpackage, ip)
-                                       end
-                               end
-                       end
-                       catalog.git_info(mpackage)
-                       catalog.package_page(mpackage)
-               end
+       # Build the nitweb config from `toolcontext` options.
+       fun build_config(toolcontext: ToolContext, mainmodule: MModule): NitwebConfig do
+
+               var model = toolcontext.modelbuilder.model
+
+               var filter = new ModelFilter(
+                       if toolcontext.opt_no_private.value then protected_visibility else private_visibility,
+                       accept_fictive = not toolcontext.opt_no_fictive.value,
+                       accept_empty_doc = not toolcontext.opt_no_empty_doc.value,
+                       accept_test = not toolcontext.opt_no_test.value,
+                       accept_attribute = not toolcontext.opt_no_attribute.value
+               )
+
+               var catalog = build_catalog(toolcontext.modelbuilder, filter)
+
+               var config = new NitwebConfig(model, mainmodule, toolcontext.modelbuilder, filter, catalog)
+               var config_file = toolcontext.opt_config.value
+               if config_file == null then config.default_config_file = "nitweb.ini"
+               config.parse_options(args)
+               var opt_host = toolcontext.opt_host.value
+               if opt_host != null then config.ini["app.host"] = opt_host
+               var opt_port = toolcontext.opt_port.value
+               if opt_port >= 0 then config.ini["app.port"] = opt_port.to_s
+               return config
+       end
 
-               # Run the server
-               var host = toolcontext.opt_host.value or else "localhost"
-               var port = toolcontext.opt_port.value
+       redef fun process_mainmodule(mainmodule, mmodules)
+       do
+               var config = build_config(toolcontext, mainmodule)
+               config.model.index # pre load model index
+               config.model.nitdoc_md_processor = config.md_processor
 
                var app = new App
 
+               app.use_before("/*", new SessionInit)
                app.use_before("/*", new RequestClock)
-               app.use("/api", new APIRouter(model, modelbuilder, mainmodule, catalog))
-               app.use("/doc/:namespace", new DocAction(model, mainmodule, modelbuilder))
+               app.use("/api", new APIRouter(config))
+               app.use("/login", new GithubLogin(config.github_client_id))
+               app.use("/oauth", new GithubOAuthCallBack(config.github_client_id, config.github_client_secret))
+               app.use("/logout", new GithubLogout)
                app.use("/*", new StaticHandler(toolcontext.share_dir / "nitweb", "index.html"))
-               app.use_after("/*", new ConsoleLog)
+               app.use_after("/*", new PopLogger(info_level))
 
-               app.listen(host, port.to_i)
+               app.listen(config.app_host, config.app_port)
        end
-end
-
-# Group all api handlers in one router.
-class APIRouter
-       super Router
-
-       # Model to pass to handlers.
-       var model: Model
-
-       # ModelBuilder to pass to handlers.
-       var modelbuilder: ModelBuilder
-
-       # Mainmodule to pass to handlers.
-       var mainmodule: MModule
-
-       # Catalog to pass to handlers.
-       var catalog: Catalog
 
-       init do
-               use("/catalog", new APICatalogRouter(model, mainmodule, catalog))
-               use("/list", new APIList(model, mainmodule))
-               use("/search", new APISearch(model, mainmodule))
-               use("/random", new APIRandom(model, mainmodule))
-               use("/entity/:id", new APIEntity(model, mainmodule))
-               use("/code/:id", new APIEntityCode(model, mainmodule, modelbuilder))
-               use("/uml/:id", new APIEntityUML(model, mainmodule))
-               use("/linearization/:id", new APIEntityLinearization(model, mainmodule))
-               use("/defs/:id", new APIEntityDefs(model, mainmodule))
-               use("/inheritance/:id", new APIEntityInheritance(model, mainmodule))
-               use("/graph/", new APIGraphRouter(model, mainmodule))
+       # Build the catalog
+       #
+       # This method should be called at nitweb startup.
+       fun build_catalog(modelbuilder: ModelBuilder, filter: nullable ModelFilter): Catalog do
+               var catalog = new Catalog(modelbuilder)
+               var mpackages = modelbuilder.model.collect_mpackages(filter)
+               # Compute the poset
+               for p in mpackages do
+                       var g = p.root
+                       assert g != null
+                       modelbuilder.scan_group(g)
+               end
+               # Build the catalog
+               for mpackage in mpackages do
+                       catalog.package_page(mpackage)
+                       catalog.git_info(mpackage)
+                       catalog.mpackage_stats(mpackage)
+               end
+               return catalog
        end
+
 end
 
 # build toolcontext
 var toolcontext = new ToolContext
 var tpl = new Template
 tpl.add "Usage: nitweb [OPTION]... <file.nit>...\n"
-tpl.add "Run a webserver based on nitcorn that serve pages about model."
+tpl.add "Run a webserver based on nitcorn that serves pages about model."
 toolcontext.tooldescription = tpl.write_to_string
 
 # process options