logo

class

docCompiler::FandocToHtmlGenerator

sys::Obj
  fandoc::HtmlDocWriter
    docCompiler::HtmlGenerator
      docCompiler::FandocToHtmlGenerator
//
// Copyright (c) 2007, Brian Frank and Andy Frank
// Licensed under the Academic Free License version 3.0
//
// History:
//   5 May 07  Brian Frank  Creation
//

using compiler
using fandoc

**
** FandocToHtmlGenerator generates an HTML file for a standalone fandoc file
**
class FandocToHtmlGenerator : HtmlGenerator
{

//////////////////////////////////////////////////////////////////////////
// Constructor
//////////////////////////////////////////////////////////////////////////

  new make(DocCompiler compiler, Location loc, OutStream out, Doc doc)
    : super(compiler, loc, out)
  {
    this.doc = doc
  }

//////////////////////////////////////////////////////////////////////////
// Generator
//////////////////////////////////////////////////////////////////////////

  override Str title()
  {
    title := doc.meta["title"]
    if (title != null) return title
    compiler.err("WARNING: Missing title", loc)
    return super.title
  }

  override Void header()
  {
    out.print("<ul>\n")
    out.print("  <li><a href='../index.html'>$docHome</a></li>\n")
    out.print("  <li><a href='index.html'>$compiler.pod.name</a></li>\n")
    out.print("  <li>$title</li>\n")
    out.print("</ul>\n")
  }

  override Void content()
  {
    findPrevNext
    prevNext
    out.print("<h1 class='title'>$title</h1>\n")
    doc.children.each |DocNode node| { node.write(this) }
    prevNext
  }

  override Void sidebar()
  {
    // make a quick run thru to make sure we even
    // have any headers for the content sidebar
    temp := doc.children.find |DocNode node->Bool| { return node is Heading }
    if (temp == null) return

    // we found some so print them
    out.print("<h2>Contents</h2>\n")
    out.print("<ul>\n")
    curLevel := 1
    doc.children.each |DocNode node|
    {
      heading := node as Heading
      if (heading != null)
      {
        id := heading.anchorId
        if (heading.level > curLevel)
        {
          out.print("<li><ul>\n")
          curLevel++
        }
        else if (heading.level < curLevel)
        {
          out.print("</ul></li>\n")
          curLevel--
        }

        out.print("<li>")
        if (id != null) out.print("<a href='#$id'>")
        heading.children.each |DocNode n| { n.write(this) }
        if (id != null) out.print("</a>")
        out.print("</li>\n")
      }
    }
    while (curLevel > 1)
    {
      out.print("</ul></li>\n")
      curLevel--
    }
    out.print("</ul>\n")
  }

  Void prevNext()
  {
    if (prev == null && next == null) return
    out.print("<div class='prevNext'>\n")
    if (prev != null) out.print("<div class='prev'>&lt; <a href='${prev}.html'>$prev</a></div>\n")
    if (next != null) out.print("<div class='next'><a href='${next}.html'>$next</a> &gt;</div>\n")
    out.print("</div>\n")
  }

  Void findPrevNext()
  {
    if (compiler.fandocIndex == null) return

    // give something easier to work with
    index := [,]
    for (i:=0; i<compiler.fandocIndex.size; i++)
    {
      v := compiler.fandocIndex[i]
      if (v is Uri) index.push(v)
      else if (v is Obj[]) index.push((v as Obj[])[0] as Uri)
    }

    // try to find prev/next
    for (i:=0; i<index.size; i++)
      if (title == index[i].toStr)
      {
        if (i > 0) prev = index[i-1]
        if (i < index.size-1) next = index[i+1]
        break;
      }
  }

//////////////////////////////////////////////////////////////////////////
// Fields
//////////////////////////////////////////////////////////////////////////

  Doc doc
  Uri prev   // prev link if exists
  Uri next   // next link if exists

}