--- a
+++ b/inst/generate_package_html.m
@@ -0,0 +1,174 @@
+## Copyright (C) 2008 Soren Hauberg
+##
+## This program is free software; you can redistribute it and/or modify it
+## under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or (at
+## your option) any later version.
+##
+## This program is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; see the file COPYING.  If not, see
+## <http://www.gnu.org/licenses/>.
+
+## -*- texinfo -*-
+## @deftypefn {Function File} generate_package_html (@var{name}, @var{outdir}, @var{options})
+## Generate @t{HTML} documentation for a package.
+##
+## The function reads information about package @var{name} using the
+## package system. This is then used to generate bunch of
+## @t{HTML} files; one for each function in the package, and one overview
+## page. The files are all placed in the directory @var{outdir}, which defaults
+## to the current directory. The @var{options} structure is used to control
+## the design of the web pages.
+##
+## As an example, the following code generates the web pages for the @t{image}
+## package, with a design suitable for the @t{Octave-Forge} project.
+##
+## @example
+## options = get_html_options ("octave-forge");
+## generate_package_html ("image", "image_html", options);
+## @end example
+##
+## The resulting files will be available in the @t{"image_html"} directory. The
+## overview page will be called @t{"image_html/image_overview.html"}.
+##
+## As a convenience, if @var{options} is a string, a structure will
+## be generated by calling @code{get_html_options}. This means the above
+## example can be reduced to the following.
+##
+## @example
+## generate_package_html ("image", "image_html", "octave-forge");
+## @end example
+##
+## It should be noted that the function only works for installed packages.
+## @seealso{get_html_options}
+## @end deftypefn
+
+function generate_package_html (name, outdir = ".", fundir = outdir, options = struct (), root = "")
+  ## Check input
+  if (ischar (name))
+    pkg ("load", name);
+    desc = pkg ("describe", name){1};
+  elseif (isstruct (name))
+    desc = name;
+  else
+    error (["generate_package_html: first input must either be the name of a ", \
+            "package, or a structure giving its description."]);
+  endif
+  
+  if (!ischar (outdir))
+    error ("generate_package_html: second input argument must be a string");
+  endif
+  
+  if (!ischar (fundir))
+    error ("generate_package_html: third input argument must be a string");
+  endif
+  
+  ## Create output directory if needed
+  if (!exist (outdir, "dir"))
+    mkdir (outdir);
+  endif
+  
+  if (!exist (fundir, "dir"))
+    mkdir (fundir);
+  endif
+  
+  ## If options is a string, call get_html_options
+  if (ischar (options))
+    options = get_html_options (options);
+  elseif (!isstruct (options))
+    error ("generate_package_html: fourth input argument must be a string or a structure");
+  endif
+  
+  ##################################################  
+  ## Generate html pages for individual functions ##
+  ##################################################
+
+  ## Set javascript startup
+  if (!isfield (options, "body_command"))
+    if (isfield (options, "pack_body_cmd"))
+      options.body_command = options.pack_body_cmd;
+    else
+      options.body_command = "";
+    endif
+  endif
+  
+  num_categories = length (desc.provides);
+  anchors = implemented = cell (1, num_categories);
+  for k = 1:num_categories
+    F = desc.provides {k}.functions;
+    category = desc.provides {k}.category;
+    anchors {k} = strrep (category, " ", ""); # anchor names
+   
+    ## For each function in category
+    num_functions = length (F);
+    implemented {k} = cell (1, num_functions);
+    for l = 1:num_functions
+      fun = F {l};
+      outname = fullfile (fundir, sprintf ("%s.html", fun));
+      try
+        html_help_text (fun, outname, options, root);
+        implemented {k}{l} = true;
+      catch
+        warning ("marking '%s' as not implemented", fun);
+        implemented {k}{l} = false;
+     end_try_catch
+    endfor
+  endfor  
+
+  #########################
+  ## Write overview file ##
+  #########################
+  overview_filename = get_overview_filename (options, desc.name);
+
+  fid = fopen (fullfile (outdir, overview_filename), "w");
+  if (fid < 0)
+    error ("generate_package_html: couldn't open overview file for writing");
+  endif
+  
+  [header, title, footer] = get_overview_header_title_and_footer (options, desc.name, root);
+
+  fprintf (fid, "%s\n", header);  
+  fprintf (fid, "<h2 class=\"tbdesc\">%s</h2>\n\n", desc.name);
+
+  fprintf (fid, "  <div class=\"package_description\">\n");
+  fprintf (fid, "    %s\n", desc.description);
+  fprintf (fid, "  </div>\n\n");
+  
+  fprintf (fid, "  <ul>\n");
+  for k = 1:num_categories
+    category = desc.provides {k}.category;
+    fprintf (fid, "    <li><a href=\"#%s\">%s</a></li>\n", anchors {k}, category);
+  endfor
+  fprintf (fid, "  </ul>\n\n");
+  
+  ## Generate function list by category
+  for k = 1:num_categories
+    F = desc.provides {k}.functions;
+    category = desc.provides {k}.category;
+    fprintf (fid, "  <h3 class=\"category\"><a name=\"%s\">%s</a></h3>\n\n",
+             anchors {k}, category);
+  
+    ## For each function in category
+    for l = 1:length (F)
+      fun = F {l};
+      if (implemented {k}{l})
+        link = sprintf ("%s/%s/%s.html", root, fundir, fun);
+        fprintf (fid, "    <div class=\"func\"><b><a href=\"%s\">%s</a></b></div>\n",
+                 link, fun);
+        fprintf (fid, "    <div class=\"ftext\">%s</div>\n\n",
+                 get_first_help_sentence (fun, 200));
+      else
+        fprintf (fid, "    <div class=\"func\"><b>%s</b></div>\n", fun);
+        fprintf (fid, "    <div class=\"ftext\">Not implemented.</div>\n\n");
+      endif
+    endfor
+  endfor
+  
+  fprintf (fid, "\n%s\n", footer);
+  fclose (fid);
+endfunction