Commits

Ronald Oussoren committed c84bcf4

Add code and templates to emit the documentation pages as well.

The site should now be complete, but needs more testing.

  • Participants
  • Parent commits 075ac8f
  • Branches pyobjc-ancient

Comments (0)

Files changed (10)

pyobjc-website/lib/docs.py

+"""
+docs - generating the online documentation
+
+This parses the documentation in the PyObjC 
+repository and generates the online documentation
+from that.
+
+TODO:
+- Cleanup and enhance the documentation
+
+- Update the inline documentation in the 
+  pyobjc Objective-C sources and include that 
+  as well.
+
+- Start a project to parse Apple's documentation
+  and transform that into PyObjC documentation for
+  the corresponding framework.
+"""
+import os, zipfile
+
+from pygments import highlight
+from pygments.lexers import get_lexer_for_filename
+from pygments.formatters import HtmlFormatter
+
+from docutils.core import publish_parts
+
+from distutils import log
+
+def nameForProject(project):
+    if project == 'pyobjc-core':
+        name = 'PyObjC Core'
+
+    elif project == 'pyobjc-metadata':
+        name = 'Metadata Generator'
+
+    elif project.startswith('pyobjc-framework-'):
+        name = project[17:]
+
+    else:
+        name = project
+
+    return name
+
+def makeBottomMenu(htmlroot, sourceroot, projects):
+    allProjects = []
+
+    for project in projects:
+        projroot = os.path.join(sourceroot, project, 'Doc')
+        if not os.path.exists(projroot):
+            continue
+
+        else:
+            name = nameForProject(project)
+            allProjects.append((name, os.path.join(htmlroot, project, 'index.html')))
+
+    return allProjects
+
+def generateProjectDocumentation(generator, projhtml, projroot, name, allProjects):
+    doclist = []
+    description = ''
+
+    for fn in os.listdir(projroot):
+        if fn.endswith('.html') or fn in ('.svn', 'CVS'):
+            continue
+
+        elif fn == 'index.txt':
+            # XXX: This is not quite right, but the index will always
+            # be generated at the moment.
+            continue
+
+        if fn.endswith('.txt'):
+            content = open(os.path.join(projroot, fn), 'r').read()
+
+            parts =  publish_parts(
+                source=content,
+                source_path=fn,
+                writer_name='html',
+                settings_overrides=dict(
+                    input_encoding='utf-8',
+                    initial_header_level=2,
+                ))
+
+            docurl = os.path.splitext(fn)[0] + '.html'
+            while docurl[0].isdigit():
+                docurl = docurl[1:]
+            docurl = os.path.join(projhtml, docurl)
+            title=parts['title']
+            if not title:
+                title = os.path.splitext(fn)[0]
+            doclist.append((title, docurl))
+
+            generator.emitHTML(
+                docurl,
+                'documentation-doc.html',
+
+                name=name,
+                title=title,
+                body=parts['body'],
+                bottommenu=allProjects,
+            )
+
+        elif os.path.isdir(os.path.join(projroot, fn)):
+            if not os.path.exists(os.path.join(projroot, fn, 'index.txt')):
+                print "WARNING: ignoring file", fn
+                continue
+
+            tutroot = os.path.join(projroot, fn)
+
+            tuthtml = fn
+            while tuthtml[0].isdigit():
+                tuthtml = tuthtml[1:]
+            tuthtml = os.path.join(projhtml, tuthtml)
+            for fn in os.listdir(tutroot):
+                if fn in ('.svn', 'CVS'):
+                    continue
+
+                if os.path.isdir(os.path.join(tutroot, fn)):
+                    indir = os.path.join(tutroot, fn)
+                    outfn = generator.localPathForSitePath(os.path.join(tuthtml, fn + '.zip'))
+                    zf = zipfile.ZipFile(outfn, 'w')
+                    for dirpath, dirnames, filenames in os.walk(indir):
+                        if '.svn' in dirnames:
+                            dirnames.remove('.svn')
+
+                        relpath = dirpath[len(indir):]
+                        for fn in filenames:
+                            if relpath:
+                                zipname = os.path.join(relpath, fn)
+                            else:
+                                zipname = fn
+
+                            zf.write(os.path.join(dirpath, fn), zipname, zipfile.ZIP_DEFLATED)
+                    zf.close()
+
+                elif fn.endswith('.html'):
+                    continue
+
+                elif fn.endswith('.txt'):
+                    content = open(os.path.join(tutroot, fn), 'r').read()
+
+                    parts =  publish_parts(
+                        source=content,
+                        source_path=fn,
+                        writer_name='html',
+                        settings_overrides=dict(
+                            input_encoding='utf-8',
+                            initial_header_level=2,
+                        ))
+
+                    tuturl = os.path.splitext(fn)[0] + '.html'
+                    tuturl = os.path.join(tuthtml, tuturl)
+                    title=parts['title']
+                    if not title:
+                        title = os.path.splitext(fn)[0]
+
+                    if fn == 'index.txt':
+                        doclist.append((title, tuturl))
+
+                    generator.emitHTML(
+                        tuturl,
+                        'documentation-doc.html',
+
+                        name=name,
+                        title=title,
+                        body=parts['body'],
+                        bottommenu=allProjects,
+                    )
+
+                else:
+                    fullpath = os.path.join(tutroot, fn)
+                    lexer = get_lexer_for_filename(fullpath)
+                    formatter = HtmlFormatter(linenos = False, cssclass='source')
+                    result = highlight(open(fullpath, 'r').read(), lexer, formatter)
+                    style=formatter.get_style_defs()
+
+                    tuturl = fn + '.html'
+                    tuturl = os.path.join(tuthtml, tuturl)
+
+                    generator.emitHTML(
+                        tuturl,
+                        'documentation-source.html',
+
+                        title=fn,
+                        body=result,
+                        style=style,
+                        bottommenu=allProjects,
+                    )
+                                                                                
+
+        else:
+            print "WARNING: ignoring file", fn
+
+    
+    generator.emitHTML(
+        os.path.join(projhtml, 'index.html'),
+        'documentation-project-index.html',
+
+        name=name,
+        documents=doclist,
+        description=description,
+
+        bottommenu=allProjects,
+    )
+
+    return description, doclist
+
+def generateDocs(generator, htmlroot, sourceroot, projects):
+    allProjects = makeBottomMenu(htmlroot, sourceroot, projects)
+    documentListing = []
+
+    log.info("Generating documentation")
+
+    for project in projects:
+        projroot = os.path.join(sourceroot, project, 'Doc')
+        if not os.path.exists(projroot):
+            continue
+
+        else:
+            name = nameForProject(project)
+            log.info(" - %s (%s)"%(name, project))
+
+            projhtml = os.path.join(htmlroot, project)
+
+            description, projdocs = generateProjectDocumentation(
+                generator, projhtml, projroot, name, allProjects)
+            documentListing.append((name, description, projdocs))
+
+    generator.emitHTML(
+        os.path.join(htmlroot, 'index.html'),
+        'documentation-index.html',
+
+        documentation_sections=documentListing,
+        bottommenu=allProjects)

pyobjc-website/lib/sitegen.py

 """
 A class that deals with generating the website.
+
+TODO: add a way to syntax-color embedded source code, possibly based
+on: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/252170
 """
 import os, shutil
 
 
 gTopMenu=[
     ('Home',            '/index.html'),
-    ('Documentation',   '/doc/index.html'),
+    ('Documentation',   '/documentation/index.html'),
     ('Development',     '/development/index.html'),
     ('Download',        '/software/index.html'),
     ('Examples',        '/examples/index.html'),

pyobjc-website/setup.py

 import sitegen
 import samples
 import news
+import docs
 
 
 
                 news=newsItems,
                 bottommenu=root_menu)
 
+        docs.generateDocs(generator, '/documentation', '..', ['pyobjc-core'] + frameworkList)
         samples.generateSamples(generator, '/examples', '..', frameworkList)
 
 class publishsite (Command):

pyobjc-website/templates/documentation-doc.html

+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml"
+  xmlns:py="http://genshi.edgewall.org/"
+  xmlns:xi="http://www.w3.org/2001/XInclude">
+  <xi:include href="layout.html" />
+  <head>
+    <title >PyObjC/${name} - ${title}</title>
+  </head>
+
+  <body class="index">
+    <h1 >PyObjC - ${title}</h1>
+    <div py:content="Markup(body)">Document goes here</div>
+  </body>
+</html>

pyobjc-website/templates/documentation-index.html

+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml"
+  xmlns:py="http://genshi.edgewall.org/"
+  xmlns:xi="http://www.w3.org/2001/XInclude">
+  <xi:include href="layout.html" />
+  <head>
+    <title>PyObjC - Documentation</title>
+  </head>
+
+  <body class="index">
+    <p>The documentation reflects the current development version
+       of PyObjC. This is currently moving towards a 2.1 release
+       and fully compatible with PyObjC 2.0 unless noted otherwise.</p>
+     <p>All documentats except the introduction need work</p>
+
+     <div py:for="section, description, links in documentation_sections">
+       <h2>${section}</h2>
+
+       <p py:if="description">${description}</p>
+
+       <ul>
+         <li py:for="title, link in links"><a href="${url(link)}">${title}</a></li>
+       </ul>
+     </div>
+  </body>
+</html>

pyobjc-website/templates/documentation-project-index.html

+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml"
+  xmlns:py="http://genshi.edgewall.org/"
+  xmlns:xi="http://www.w3.org/2001/XInclude">
+  <xi:include href="layout.html" />
+  <head>
+    <title>PyObjC - Documentation for ${name}</title>
+  </head>
+
+  <body class="index">
+    <h1>PyObjC - Documentation for ${name}</h1>
+
+    <p py:if="description">${description}</p>
+
+     <ul>
+       <li py:for="title, link in documents"><a href="${url(link)}">${title}</a></li>
+     </ul>
+
+  </body>
+</html>

pyobjc-website/templates/documentation-source.html

+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml"
+  xmlns:py="http://genshi.edgewall.org/"
+  xmlns:xi="http://www.w3.org/2001/XInclude">
+  <xi:include href="layout.html" />
+  <head>
+    <title py:content="title">Sample name</title>
+    <style py:content="Markup(style)"><!-- style goes here --></style>
+
+  </head>
+
+  <body>
+    <h1 py:content="title">file name</h1>
+
+    <p py:content="Markup(body)">The actual source code</p>
+  </body>
+</html>

pyobjc-website/templates/global/layout.html

         </title>
         <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
         <link rel="stylesheet" href="${url('/css/layout.css')}" type="text/css" />
+        <link rel="stylesheet" href="${url('/css/rest.css')}" type="text/css" />
+
         <link py:replace="select('link')" />
         <link rel="start" href="${url('/index.html')}" />
         <link rel="copyright" href="${url('/legal.html')}" />

pyobjc-website/templates/sample-index.html

   <xi:include href="layout.html" />
   <head>
     <title py:content="title">Sample name</title>
-    <link rel="stylesheet" href="${url('/css/rest.css')}" type="text/css" />
 
     <style>
       .readme {

pyobjc-website/templates/static-rest.html

   <xi:include href="layout.html" />
   <head>
     <title py:content="title">Page name</title>
-    <link rel="stylesheet" href="${url('/css/rest.css')}" type="text/css" />
   </head>
 
   <body class="index">