New builder for Qt help collections, by Antonio Valentino.

(This is not finished work yet.)
This commit is contained in:
Georg Brandl 2008-12-29 00:51:51 +01:00
parent f13c3a00cd
commit 04348edcee
10 changed files with 310 additions and 11 deletions

View File

@ -52,6 +52,13 @@ New features added
- The new ``html_show_sourcelink`` config value can be used to - The new ``html_show_sourcelink`` config value can be used to
switch off the links to the reST sources in the sidebar. switch off the links to the reST sources in the sidebar.
- The default value for ``htmlhelp_basename`` is now the project
title, cleaned up as a filename.
* Builders:
- New builder for Qt help collections, by Antonio Valentino.
- The new ``html_link_suffix`` config value can be used to select - The new ``html_link_suffix`` config value can be used to select
the suffix of generated links between HTML files. the suffix of generated links between HTML files.

View File

@ -11,7 +11,7 @@ PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS = -d _build/doctrees $(PAPEROPT_$(PAPER)) \ ALLSPHINXOPTS = -d _build/doctrees $(PAPEROPT_$(PAPER)) \
$(SPHINXOPTS) . $(SPHINXOPTS) .
.PHONY: help clean html web htmlhelp latex changes linkcheck .PHONY: help clean html pickle htmlhelp qthelp latex changes linkcheck doctest
help: help:
@echo "Please use \`make <target>' where <target> is one of" @echo "Please use \`make <target>' where <target> is one of"
@ -48,6 +48,16 @@ htmlhelp:
@echo "Build finished; now you can run HTML Help Workshop with the" \ @echo "Build finished; now you can run HTML Help Workshop with the" \
".hhp project file in _build/htmlhelp." ".hhp project file in _build/htmlhelp."
qthelp:
mkdir -p _build/qthelp _build/doctrees
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) _build/qthelp
@echo
@echo "Build finished; now you can run qcollectiongenerator with the" \
".qhcp project file in build/qthelp."
@echo "# qcollectiongenerator _build/qthelp/Sphinx.qhcp"
@echo "To view the help collection:"
@echo "# assistant -collectionFile _build/qthelp/Sphinx.qhc"
latex: latex:
mkdir -p _build/latex _build/doctrees mkdir -p _build/latex _build/doctrees
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) _build/latex $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) _build/latex

View File

@ -338,6 +338,7 @@ BUILTIN_BUILDERS = {
'json': ('html', 'JSONHTMLBuilder'), 'json': ('html', 'JSONHTMLBuilder'),
'web': ('html', 'PickleHTMLBuilder'), 'web': ('html', 'PickleHTMLBuilder'),
'htmlhelp': ('htmlhelp', 'HTMLHelpBuilder'), 'htmlhelp': ('htmlhelp', 'HTMLHelpBuilder'),
'qthelp': ('qthelp', 'QtHelpBuilder'),
'latex': ('latex', 'LaTeXBuilder'), 'latex': ('latex', 'LaTeXBuilder'),
'text': ('text', 'TextBuilder'), 'text': ('text', 'TextBuilder'),
'changes': ('changes', 'ChangesBuilder'), 'changes': ('changes', 'ChangesBuilder'),

View File

@ -55,6 +55,7 @@ class StandaloneHTMLBuilder(Builder):
'image/jpeg'] 'image/jpeg']
searchindex_filename = 'searchindex.js' searchindex_filename = 'searchindex.js'
add_permalinks = True add_permalinks = True
embedded = False # for things like HTML help or Qt help: suppresses sidebar
# This is a class attribute because it is mutated by Sphinx.add_javascript. # This is a class attribute because it is mutated by Sphinx.add_javascript.
script_files = ['_static/jquery.js', '_static/doctools.js'] script_files = ['_static/jquery.js', '_static/doctools.js']
@ -136,6 +137,7 @@ class StandaloneHTMLBuilder(Builder):
rellinks.append(('modindex', _('Global Module Index'), 'M', _('modules'))) rellinks.append(('modindex', _('Global Module Index'), 'M', _('modules')))
self.globalcontext = dict( self.globalcontext = dict(
embedded = self.embedded,
project = self.config.project, project = self.config.project,
release = self.config.release, release = self.config.release,
version = self.config.version, version = self.config.version,

View File

@ -133,6 +133,8 @@ class HTMLHelpBuilder(StandaloneHTMLBuilder):
# don't add links # don't add links
add_permalinks = False add_permalinks = False
# don't add sidebar etc.
embedded = True
def init(self): def init(self):
StandaloneHTMLBuilder.init(self) StandaloneHTMLBuilder.init(self)

261
sphinx/builders/qthelp.py Normal file
View File

@ -0,0 +1,261 @@
# -*- coding: utf-8 -*-
"""
sphinx.builders.qthelp
~~~~~~~~~~~~~~~~~~~~~~
Build input files for the Qt collection generator.
:copyright: 2008 by Antonio Valentino.
:license: BSD, see LICENSE for details.
"""
import os
import re
import cgi
from os import path
from docutils import nodes
from sphinx import addnodes
from sphinx.builders.html import StandaloneHTMLBuilder
_idpattern = re.compile('(?P<title>.+) (\((?P<id>[\w\.]+)( (?P<descr>\w+))?\))$')
# Qt Help Collection Project (.qhcp).
# Is the input file for the help collection generator.
# It contains references to compressed help files which should be
# included in the collection.
# It may contain various other information for customizing Qt Assistant.
collection_template = '''\
<?xml version="1.0" encoding="utf-8" ?>
<QHelpCollectionProject version="1.0">
<docFiles>
<generate>
<file>
<input>%(outname)s.qhp</input>
<output>%(outname)s.qch</output>
</file>
</generate>
<register>
<file>%(outname)s.qch</file>
</register>
</docFiles>
</QHelpCollectionProject>
'''
# Qt Help Project (.qhp)
# This is the input file for the help generator.
# It contains the table of contents, indices and references to the
# actual documentation files (*.html).
# In addition it defines a unique namespace for the documentation.
project_template = '''\
<?xml version="1.0" encoding="UTF-8"?>
<QtHelpProject version="1.0">
<namespace>%(outname)s.org.%(outname)s.%(nversion)s</namespace>
<virtualFolder>doc</virtualFolder>
<customFilter name="%(project)s %(version)s">
<filterAttribute>%(outname)s</filterAttribute>
<filterAttribute>%(version)s</filterAttribute>
</customFilter>
<filterSection>
<filterAttribute>%(outname)s</filterAttribute>
<filterAttribute>%(version)s</filterAttribute>
<toc>
<section title="%(title)s" ref="%(masterdoc)s.html">
%(sections)s
</section>
</toc>
<keywords>
%(keywords)s
</keywords>
<files>
%(files)s
</files>
</filterSection>
</QtHelpProject>
'''
section_template = '<section title="%(title)s" ref="%(ref)s"/>'
file_template = ' '*12 + '<file>%(filename)s</file>'
class QtHelpBuilder(StandaloneHTMLBuilder):
"""
Builder that also outputs Qt help project, contents and index files.
"""
name = 'qthelp'
# don't copy the reST source
copysource = False
supported_image_types = ['image/svg+xml', 'image/png', 'image/gif',
'image/jpeg']
# don't add links
add_permalinks = False
# don't add sidebar etc.
embedded = True
def init(self):
StandaloneHTMLBuilder.init(self)
# the output files for HTML help must be .html only
self.out_suffix = '.html'
#self.config.html_style = 'traditional.css'
def handle_finish(self):
self.build_qhcp(self.outdir, self.config.qthelp_basename)
self.build_qhp(self.outdir, self.config.qthelp_basename)
def build_qhcp(self, outdir, outname):
self.info('writing collection project file...')
f = open(path.join(outdir, outname+'.qhcp'), 'w')
try:
f.write(collection_template % {'outname': outname})
finally:
f.close()
def build_qhp(self, outdir, outname):
self.info('writing project file...')
# sections
tocdoc = self.env.get_and_resolve_doctree(self.config.master_doc, self,
prune_toctrees=False)
istoctree = lambda node: (
isinstance(node, addnodes.compact_paragraph)
and node.has_key('toctree'))
sections = []
for node in tocdoc.traverse(istoctree):
sections.extend(self.write_toc(node))
if self.config.html_use_modindex:
item = section_template % {'title': _('Global Module Index'),
'ref': 'modindex.html'}
sections.append(' '*4*4 + item)
sections = '\n'.join(sections)
# keywords
keywords = []
index = self.env.create_index(self)
for (key, group) in index:
for title, (refs, subitems) in group:
keywords.extend(self.build_keywords(title, refs, subitems))
keywords = '\n'.join(keywords)
# files
if not outdir.endswith(os.sep):
outdir += os.sep
olen = len(outdir)
projectfiles = []
for root, dirs, files in os.walk(outdir):
staticdir = (root == path.join(outdir, '_static'))
for fn in files:
if (staticdir and not fn.endswith('.js')) or fn.endswith('.html'):
filename = path.join(root, fn)[olen:]
#filename = filename.replace(os.sep, '\\') # XXX
projectfiles.append(file_template % {'filename': filename})
projectfiles = '\n'.join(projectfiles)
# write the project file
f = open(path.join(outdir, outname+'.qhp'), 'w')
try:
nversion = self.config.version.replace('.', '_')
nversion = nversion.replace(' ', '_')
f.write(project_template % {'outname': outname,
'title': self.config.html_title,
'version': self.config.version,
'project': self.config.project,
'nversion': nversion,
'masterdoc': self.config.master_doc,
'sections': sections,
'keywords': keywords,
'files': projectfiles})
finally:
f.close()
def isdocnode(self, node):
if not isinstance(node, nodes.list_item):
return False
if len(node.children) != 2:
return False
if not isinstance(node.children[0], addnodes.compact_paragraph):
return False
if not isinstance(node.children[0][0], nodes.reference):
return False
if not isinstance(node.children[1], nodes.bullet_list):
return False
return True
def write_toc(self, node, indentlevel=4):
parts = []
if self.isdocnode(node):
refnode = node.children[0][0]
link = refnode['refuri']
title = cgi.escape(refnode.astext()).replace('"','&quot;')
item = '<section title="%(title)s" ref="%(ref)s">' % {
'title': title,
'ref': link}
parts.append(' '*4*indentlevel + item)
for subnode in node.children[1]:
parts.extend(self.write_toc(subnode, indentlevel+1))
parts.append(' '*4*indentlevel + '</section>')
elif isinstance(node, nodes.list_item):
for subnode in node:
parts.extend(self.write_toc(subnode, indentlevel))
elif isinstance(node, nodes.reference):
link = node['refuri']
title = cgi.escape(node.astext()).replace('"','&quot;')
item = section_template % {'title': title, 'ref': link}
item = ' '*4*indentlevel + item.encode('ascii', 'xmlcharrefreplace')
parts.append(item.encode('ascii', 'xmlcharrefreplace'))
elif isinstance(node, nodes.bullet_list):
for subnode in node:
parts.extend(self.write_toc(subnode, indentlevel))
elif isinstance(node, addnodes.compact_paragraph):
for subnode in node:
parts.extend(self.write_toc(subnode, indentlevel))
return parts
def keyword_item(self, name, ref):
matchobj = _idpattern.match(name)
if matchobj:
groupdict = matchobj.groupdict()
shortname = groupdict['title']
id = groupdict.get('id')
# descr = groupdict.get('descr')
if shortname.endswith('()'):
shortname = shortname[:-2]
id = '%s.%s' % (id, shortname)
else:
id = descr = None
if id:
item = ' '*12 + '<keyword name="%s" id="%s" ref="%s"/>' % (
name, id, ref)
else:
item = ' '*12 + '<keyword name="%s" ref="%s"/>' % (name, ref)
item.encode('ascii', 'xmlcharrefreplace')
return item
def build_keywords(self, title, refs, subitems):
keywords = []
title = cgi.escape(title)
# if len(refs) == 0: # XXX
# write_param('See Also', title)
if len(refs) == 1:
keywords.append(self.keyword_item(title, refs[0]))
elif len(refs) > 1:
for i, ref in enumerate(refs): # XXX
# item = (' '*12 +
# '<keyword name="%s [%d]" ref="%s"/>' % (
# title, i, ref))
# item.encode('ascii', 'xmlcharrefreplace')
# keywords.append(item)
keywords.append(self.keyword_item(title, ref))
if subitems:
for subitem in subitems:
keywords.extend(self.build_keywords(subitem[0], subitem[1], []))
return keywords

View File

@ -12,6 +12,8 @@
import os import os
from os import path from os import path
from sphinx.util import make_filename
class Config(object): class Config(object):
"""Configuration file abstraction.""" """Configuration file abstraction."""
@ -77,7 +79,10 @@ class Config(object):
html_context = ({}, False), html_context = ({}, False),
# HTML help only options # HTML help only options
htmlhelp_basename = ('pydoc', False), htmlhelp_basename = (lambda self: make_filename(self.project), False),
# Qt help only options
qthelp_basename = (lambda self: make_filename(self.project), False),
# LaTeX options # LaTeX options
latex_documents = ([], False), latex_documents = ([], False),

View File

@ -257,7 +257,7 @@ PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS = -d %(rbuilddir)s/doctrees $(PAPEROPT_$(PAPER)) \ ALLSPHINXOPTS = -d %(rbuilddir)s/doctrees $(PAPEROPT_$(PAPER)) \
$(SPHINXOPTS) %(rsrcdir)s $(SPHINXOPTS) %(rsrcdir)s
.PHONY: help clean html web pickle htmlhelp latex changes linkcheck .PHONY: help clean html pickle json htmlhelp qthelp latex changes linkcheck
help: help:
\t@echo "Please use \\`make <target>' where <target> is one of" \t@echo "Please use \\`make <target>' where <target> is one of"
@ -265,6 +265,7 @@ help:
\t@echo " pickle to make pickle files" \t@echo " pickle to make pickle files"
\t@echo " json to make JSON files" \t@echo " json to make JSON files"
\t@echo " htmlhelp to make HTML files and a HTML help project" \t@echo " htmlhelp to make HTML files and a HTML help project"
\t@echo " qthelp to make HTML files and a qthelp project"
\t@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" \t@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
\t@echo " changes to make an overview over all changed/added/deprecated items" \t@echo " changes to make an overview over all changed/added/deprecated items"
\t@echo " linkcheck to check all external links for integrity" \t@echo " linkcheck to check all external links for integrity"
@ -284,8 +285,6 @@ pickle:
\t@echo \t@echo
\t@echo "Build finished; now you can process the pickle files." \t@echo "Build finished; now you can process the pickle files."
web: pickle
json: json:
\tmkdir -p %(rbuilddir)s/json %(rbuilddir)s/doctrees \tmkdir -p %(rbuilddir)s/json %(rbuilddir)s/doctrees
\t$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) %(rbuilddir)s/json \t$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) %(rbuilddir)s/json
@ -299,6 +298,16 @@ htmlhelp:
\t@echo "Build finished; now you can run HTML Help Workshop with the" \\ \t@echo "Build finished; now you can run HTML Help Workshop with the" \\
\t ".hhp project file in %(rbuilddir)s/htmlhelp." \t ".hhp project file in %(rbuilddir)s/htmlhelp."
qthelp:
\tmkdir -p %(rbuilddir)s/qthelp %(rbuilddir)s/doctrees
\t$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) %(rbuilddir)s/qthelp
\t@echo
\t@echo "Build finished; now you can run "qcollectiongenerator" with the" \\
\t ".qhcp project file in %(rbuilddir)s/qthelp, like this:"
\t@echo "# qcollectiongenerator %(rbuilddir)s/qthelp/Sphinx.qhcp"
\t@echo "To view the help file:"
\t@echo "# assistant -collectionFile %(rbuilddir)s/qthelp/%(project)s.qhc"
latex: latex:
\tmkdir -p %(rbuilddir)s/latex %(rbuilddir)s/doctrees \tmkdir -p %(rbuilddir)s/latex %(rbuilddir)s/doctrees
\t$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) %(rbuilddir)s/latex \t$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) %(rbuilddir)s/latex

View File

@ -25,7 +25,7 @@
</div> </div>
{%- endmacro %} {%- endmacro %}
{%- macro sidebar() %} {%- macro sidebar() %}
{%- if builder != 'htmlhelp' %} {%- if not embedded %}
<div class="sphinxsidebar"> <div class="sphinxsidebar">
<div class="sphinxsidebarwrapper"> <div class="sphinxsidebarwrapper">
{%- block sidebarlogo %} {%- block sidebarlogo %}
@ -82,13 +82,15 @@
<head> <head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
{{ metatags }} {{ metatags }}
{%- if builder != 'htmlhelp' %} {%- if not embedded %}
{%- set titlesuffix = " &mdash; "|safe + docstitle|e %} {%- set titlesuffix = " &mdash; "|safe + docstitle|e %}
{%- else %}
{%- set titlesuffix = "" %}
{%- endif %} {%- endif %}
<title>{{ title|striptags }}{{ titlesuffix }}</title> <title>{{ title|striptags }}{{ titlesuffix }}</title>
<link rel="stylesheet" href="{{ pathto('_static/' + style, 1) }}" type="text/css" /> <link rel="stylesheet" href="{{ pathto('_static/' + style, 1) }}" type="text/css" />
<link rel="stylesheet" href="{{ pathto('_static/pygments.css', 1) }}" type="text/css" /> <link rel="stylesheet" href="{{ pathto('_static/pygments.css', 1) }}" type="text/css" />
{%- if builder != 'htmlhelp' %} {%- if not embedded %}
<script type="text/javascript"> <script type="text/javascript">
var DOCUMENTATION_OPTIONS = { var DOCUMENTATION_OPTIONS = {
URL_ROOT: '{{ pathto("", 1) }}', URL_ROOT: '{{ pathto("", 1) }}',
@ -141,13 +143,13 @@
{%- block document %} {%- block document %}
<div class="document"> <div class="document">
<div class="documentwrapper"> <div class="documentwrapper">
{%- if builder != 'htmlhelp' %} {%- if not embedded %}
<div class="bodywrapper"> <div class="bodywrapper">
{%- endif %} {%- endif %}
<div class="body"> <div class="body">
{% block body %} {% endblock %} {% block body %} {% endblock %}
</div> </div>
{%- if builder != 'htmlhelp' %} {%- if not embedded %}
</div> </div>
{%- endif %} {%- endif %}
</div> </div>

View File

@ -2,7 +2,7 @@
{% set title = _('Global Module Index') %} {% set title = _('Global Module Index') %}
{% block extrahead %} {% block extrahead %}
{{ super() }} {{ super() }}
{% if builder != 'htmlhelp' and collapse_modindex %} {% if not embedded and collapse_modindex %}
<script type="text/javascript"> <script type="text/javascript">
DOCUMENTATION_OPTIONS.COLLAPSE_MODINDEX = true; DOCUMENTATION_OPTIONS.COLLAPSE_MODINDEX = true;
</script> </script>