Merge branch 'apple-help' of git://github.com/al45tair/sphinx

This commit is contained in:
Georg Brandl 2015-03-08 15:35:04 +01:00
commit 705f6a997b
16 changed files with 591 additions and 19 deletions

View File

@ -14,6 +14,7 @@ Other co-maintainers:
Other contributors, listed alphabetically, are:
* Alastair Houghton -- Apple Help builder
* Andi Albrecht -- agogo theme
* Henrique Bastos -- SVG support for graphviz extension
* Daniel Bültmann -- todo extension

View File

@ -20,6 +20,8 @@ Features added
suffixes.
* Add the ability to specify source parsers by source suffix with the
:confval:`source_parsers` config value.
* #1675: A new builder, AppleHelpBuilder, has been added that builds Apple
Help Books.
Bugs fixed
----------

View File

@ -76,6 +76,30 @@ The builder's "name" must be given to the **-b** command-line option of
.. _Qt help: http://qt-project.org/doc/qt-4.8/qthelp-framework.html
.. module:: sphinx.builders.applehelp
.. class:: AppleHelpBuilder
This builder produces an Apple Help Book based on the same output as the
standalone HTML builder.
If the source directory contains any ``.lproj`` folders, the one
corresponding to the selected language will have its contents merged with
the generated output. These folders will be ignored by all other
documentation types.
In order to generate a valid help book, this builder requires the command
line tool :program:`hiutil`, which is only available on Mac OS X 10.6 and
above. You can disable the indexing step by setting
:confval:`applehelp_disable_external_tools` to ``True``, in which case the
output will not be valid until :program:`hiutil` has been run on all of the
``.lproj`` folders within the bundle.
.. autoattribute:: name
.. autoattribute:: supported_image_types
.. versionadded:: 1.3
.. module:: sphinx.builders.devhelp
.. class:: DevhelpBuilder

View File

@ -929,6 +929,170 @@ that use Sphinx's HTMLWriter class.
Output file base name for HTML help builder. Default is ``'pydoc'``.
.. _applehelp-options:
Options for Apple Help output
-----------------------------
.. versionadded:: 1.3
These options influence the Apple Help output. This builder derives from the
HTML builder, so the HTML options also apply where appropriate.
.. note::
Apple Help output will only work on Mac OS X 10.6 and higher, as it
requires the :program:`hiutil` and :program:`codesign` command line tools,
neither of which are Open Source.
You can disable the use of these tools using
:confval:`applehelp_disable_external_tools`, but the result will not be a
valid help book until the indexer is run over the ``.lproj`` folders within
the bundle.
.. confval:: applehelp_bundle_name
The basename for the Apple Help Book. Defaults to the :confval:`project`
name.
.. confval:: applehelp_bundle_id
The bundle ID for the help book bundle.
.. warning::
You *must* set this value in order to generate Apple Help.
.. confval:: applehelp_dev_region
The development region. Defaults to ``'en-us'``, which is Apples
recommended setting.
.. confval:: applehelp_bundle_version
The bundle version (as a string). Defaults to ``'1'``.
.. confval:: applehelp_icon
The help bundle icon file, or ``None`` for no icon. According to Apples
documentation, this should be a 16-by-16 pixel version of the applications
icon with a transparent background, saved as a PNG file.
.. confval:: applehelp_kb_product
The product tag for use with :confval:`applehelp_kb_url`. Defaults to
:samp:`'{<project>}-{<release>}'`.
.. confval:: applehelp_kb_url
The URL for your knowledgebase server,
e.g. ``https://example.com/kbsearch.py?p='product'&q='query'&l='lang'``.
Help Viewer will replace the values ``'product'``, ``'query'`` and
``'lang'`` at runtime with the contents of :confval:`applehelp_kb_product`,
the text entered by the user in the search box and the users system
language respectively.
Defaults to ``None`` for no remote search.
.. confval:: applehelp_remote_url
The URL for remote content. You can place a copy of your Help Books
``Resources`` folder at this location and Help Viewer will attempt to use
it to fetch updated content.
e.g. if you set it to ``https://example.com/help/Foo/`` and Help Viewer
wants a copy of ``index.html`` for an English speaking customer, it will
look at ``https://example.com/help/Foo/en.lproj/index.html``.
Defaults to ``None`` for no remote content.
.. confval:: applehelp_index_anchors
If ``True``, tell the help indexer to index anchors in the generated HTML.
This can be useful for jumping to a particular topic using the
``AHLookupAnchor`` function or the ``openHelpAnchor:inBook:`` method in
your code. It also allows you to use ``help:anchor`` URLs; see the Apple
documentation for more information on this topic.
.. confval:: applehelp_min_term_length
Controls the minimum term length for the help indexer. Defaults to
``None``, which means the default will be used.
.. confval:: applehelp_stopwords
Either a language specification (to use the built-in stopwords), or the
path to a stopwords plist, or ``None`` if you do not want to use stopwords.
The default stopwords plist can be found at
``/usr/share/hiutil/Stopwords.plist`` and contains, at time of writing,
stopwords for the following languages:
========= ====
Language Code
========= ====
English en
German de
Spanish es
French fr
Swedish sv
Hungarian hu
Italian it
========= ====
Defaults to :confval:`language`, or if that is not set, to :confval:`en`.
.. confval:: applehelp_locale
Specifies the locale to generate help for. This is used to determine
the name of the ``.lproj`` folder inside the Help Books ``Resources``, and
is passed to the help indexer.
Defaults to :confval:`language`, or if that is not set, to :confval:`en`.
.. confval:: applehelp_title
Specifies the help book title. Defaults to :samp:`'{<project>} Help'`.
.. confval:: applehelp_codesign_identity
Specifies the identity to use for code signing, or ``None`` if code signing
is not to be performed.
Defaults to the value of the environment variable ``CODE_SIGN_IDENTITY``,
which is set by Xcode for script build phases, or ``None`` if that variable
is not set.
.. confval:: applehelp_codesign_flags
A *list* of additional arguments to pass to :program:`codesign` when
signing the help book.
Defaults to a list based on the value of the environment variable
``OTHER_CODE_SIGN_FLAGS``, which is set by Xcode for script build phases,
or the empty list if that variable is not set.
.. confval:: applehelp_indexer_path
The path to the :program:`hiutil` program. Defaults to
``'/usr/bin/hiutil'``.
.. confval:: applehelp_codesign_path
The path to the :program:`codesign` program. Defaults to
``'/usr/bin/codesign'``.
.. confval:: applehelp_disable_external_tools
If ``True``, the builder will not run the indexer or the code signing tool,
no matter what other settings are specified.
This is mainly useful for testing, or where you want to run the Sphinx
build on a non-Mac OS X platform and then complete the final steps on OS X
for some reason.
Defaults to ``False``.
.. _epub-options:
Options for epub output

View File

@ -172,6 +172,11 @@ The :program:`sphinx-build` script has several options:
Build HTML files with additional information for building a documentation
collection in one of these formats.
**applehelp**
Build an Apple Help Book. Requires :program:`hiutil` and
:program:`codesign`, which are not Open Source and presently only
available on Mac OS X 10.6 and higher.
**latex**
Build LaTeX sources that can be compiled to a PDF document using
:program:`pdflatex`.

View File

@ -449,6 +449,7 @@ BUILTIN_BUILDERS = {
'htmlhelp': ('htmlhelp', 'HTMLHelpBuilder'),
'devhelp': ('devhelp', 'DevhelpBuilder'),
'qthelp': ('qthelp', 'QtHelpBuilder'),
'applehelp': ('applehelp', 'AppleHelpBuilder'),
'epub': ('epub', 'EpubBuilder'),
'latex': ('latex', 'LaTeXBuilder'),
'text': ('text', 'TextBuilder'),

View File

@ -0,0 +1,261 @@
# -*- coding: utf-8 -*-
"""
sphinx.builders.applehelp
~~~~~~~~~~~~~~~~~~~~~~~~~
Build Apple help books.
:copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
from __future__ import print_function
import os
import codecs
import errno
import pipes
from os import path
from sphinx.builders.html import StandaloneHTMLBuilder
from sphinx.util import copy_static_entry
from sphinx.util.osutil import copyfile, ensuredir, os_path
from sphinx.util.console import bold
from sphinx.util.pycompat import htmlescape
from sphinx.util.matching import compile_matchers
from sphinx.errors import SphinxError
import plistlib
import subprocess
# Use plistlib.dump in 3.4 and above
try:
write_plist = plistlib.dump
except AttributeError:
write_plist = plistlib.writePlist
# False access page (used because helpd expects strict XHTML)
access_page_template = '''\
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>%(title)s</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="robots" content="noindex" />
<meta http-equiv="refresh" content="0;url=%(toc)s" />
</head>
<body>
</body>
</html>
'''
class AppleHelpIndexerFailed(SphinxError):
category = 'Help indexer failed'
class AppleHelpCodeSigningFailed(SphinxError):
category = 'Code signing failed'
class AppleHelpBuilder(StandaloneHTMLBuilder):
"""
Builder that outputs an Apple help book. Requires Mac OS X as it relies
on the ``hiutil`` command line tool.
"""
name = 'applehelp'
# don't copy the reST source
copysource = False
supported_image_types = ['image/png', 'image/gif', 'image/jpeg',
'image/tiff', 'image/jp2', 'image/svg+xml']
# don't add links
add_permalinks = False
# this is an embedded HTML format
embedded = True
# don't generate the search index or include the search page
search = False
def init(self):
super(AppleHelpBuilder, self).init()
# the output files for HTML help must be .html only
self.out_suffix = '.html'
if self.config.applehelp_bundle_id is None:
raise SphinxError('You must set applehelp_bundle_id before ' \
'building Apple Help output')
self.bundle_path = path.join(self.outdir,
self.config.applehelp_bundle_name \
+ '.help')
self.outdir = path.join(self.bundle_path,
'Contents',
'Resources',
self.config.applehelp_locale + '.lproj')
def handle_finish(self):
super(AppleHelpBuilder, self).handle_finish()
self.finish_tasks.add_task(self.copy_localized_files)
self.finish_tasks.add_task(self.build_helpbook)
def copy_localized_files(self):
source_dir = path.join(self.confdir,
self.config.applehelp_locale + '.lproj')
target_dir = self.outdir
if path.isdir(source_dir):
self.info(bold('copying localized files... '), nonl=True)
ctx = self.globalcontext.copy()
matchers = compile_matchers(self.config.exclude_patterns)
copy_static_entry(source_dir, target_dir, self, ctx,
exclude_matchers=matchers)
self.info('done')
def build_helpbook(self):
contents_dir = path.join(self.bundle_path, 'Contents')
resources_dir = path.join(contents_dir, 'Resources')
language_dir = path.join(resources_dir,
self.config.applehelp_locale + '.lproj')
for d in [contents_dir, resources_dir, language_dir]:
ensuredir(d)
# Construct the Info.plist file
toc = self.config.master_doc + self.out_suffix
info_plist = {
'CFBundleDevelopmentRegion': self.config.applehelp_dev_region,
'CFBundleIdentifier': self.config.applehelp_bundle_id,
'CFBundleInfoDictionaryVersion': '6.0',
'CFBundlePackageType': 'BNDL',
'CFBundleShortVersionString': self.config.release,
'CFBundleSignature': 'hbwr',
'CFBundleVersion': self.config.applehelp_bundle_version,
'HPDBookAccessPath': '_access.html',
'HPDBookIndexPath': 'search.helpindex',
'HPDBookTitle': self.config.applehelp_title,
'HPDBookType': '3',
'HPDBookUsesExternalViewer': False,
}
if self.config.applehelp_icon is not None:
info_plist['HPDBookIconPath'] \
= path.basename(self.config.applehelp_icon)
if self.config.applehelp_kb_url is not None:
info_plist['HPDBookKBProduct'] = self.config.applehelp_kb_product
info_plist['HPDBookKBURL'] = self.config.applehelp_kb_url
if self.config.applehelp_remote_url is not None:
info_plist['HPDBookRemoteURL'] = self.config.applehelp_remote_url
self.info(bold('writing Info.plist... '), nonl=True)
with open(path.join(contents_dir, 'Info.plist'), 'wb') as f:
write_plist(info_plist, f)
self.info('done')
# Copy the icon, if one is supplied
if self.config.applehelp_icon:
self.info(bold('copying icon... '), nonl=True)
try:
copyfile(path.join(self.srcdir, self.config.applehelp_icon),
path.join(resources_dir, info_plist['HPDBookIconPath']))
self.info('done')
except Exception as err:
self.warn('cannot copy icon file %r: %s' %
(path.join(self.srcdir, self.config.applehelp_icon),
err))
del info_plist['HPDBookIconPath']
# Build the access page
self.info(bold('building access page...'), nonl=True)
f = codecs.open(path.join(language_dir, '_access.html'), 'w')
try:
f.write(access_page_template % {
'toc': htmlescape(toc, quote=True),
'title': htmlescape(self.config.applehelp_title)
})
finally:
f.close()
self.info('done')
# Generate the help index
self.info(bold('generating help index... '), nonl=True)
args = [
self.config.applehelp_indexer_path,
'-Cf',
path.join(language_dir, 'search.helpindex'),
language_dir
]
if self.config.applehelp_index_anchors is not None:
args.append('-a')
if self.config.applehelp_min_term_length is not None:
args += ['-m', '%s' % self.config.applehelp_min_term_length]
if self.config.applehelp_stopwords is not None:
args += ['-s', self.config.applehelp_stopwords]
if self.config.applehelp_locale is not None:
args += ['-l', self.config.applehelp_locale]
if self.config.applehelp_disable_external_tools:
self.info('skipping')
self.warn('you will need to index this help book with:\n %s'
% (' '.join([pipes.quote(arg) for arg in args])))
else:
p = subprocess.Popen(args,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
output = p.communicate()[0]
if p.returncode != 0:
raise AppleHelpIndexerFailed(output)
else:
self.info('done')
# If we've been asked to, sign the bundle
if self.config.applehelp_codesign_identity:
self.info(bold('signing help book... '), nonl=True)
args = [
self.config.applehelp_codesign_path,
'-s', self.config.applehelp_codesign_identity,
'-f'
]
args += self.config.applehelp_codesign_flags
args.append(self.bundle_path)
if self.config.applehelp_disable_external_tools:
self.info('skipping')
self.warn('you will need to sign this help book with:\n %s'
% (' '.join([pipes.quote(arg) for arg in args])))
else:
p = subprocess.Popen(args,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
output = p.communicate()[0]
if p.returncode != 0:
raise AppleHelpCodeSigningFailed(output)
else:
self.info('done')

View File

@ -78,7 +78,8 @@ class StandaloneHTMLBuilder(Builder):
searchindex_filename = 'searchindex.js'
add_permalinks = True
embedded = False # for things like HTML help or Qt help: suppresses sidebar
search = True # for things like HTML help and Apple help: suppress search
# This is a class attribute because it is mutated by Sphinx.add_javascript.
script_files = ['_static/jquery.js', '_static/underscore.js',
'_static/doctools.js']
@ -247,14 +248,16 @@ class StandaloneHTMLBuilder(Builder):
def prepare_writing(self, docnames):
# create the search indexer
from sphinx.search import IndexBuilder, languages
lang = self.config.html_search_language or self.config.language
if not lang or lang not in languages:
lang = 'en'
self.indexer = IndexBuilder(self.env, lang,
self.config.html_search_options,
self.config.html_search_scorer)
self.load_indexer(docnames)
self.indexer = None
if self.search:
from sphinx.search import IndexBuilder, languages
lang = self.config.html_search_language or self.config.language
if not lang or lang not in languages:
lang = 'en'
self.indexer = IndexBuilder(self.env, lang,
self.config.html_search_options,
self.config.html_search_scorer)
self.load_indexer(docnames)
self.docwriter = HTMLWriter(self)
self.docsettings = OptionParser(
@ -485,12 +488,12 @@ class StandaloneHTMLBuilder(Builder):
self.handle_page(pagename, {}, template)
# the search page
if self.name != 'htmlhelp':
if self.search:
self.info(' search', nonl=1)
self.handle_page('search', {}, 'search.html')
# the opensearch xml file
if self.config.html_use_opensearch and self.name != 'htmlhelp':
if self.config.html_use_opensearch and self.search:
self.info(' opensearch', nonl=1)
fn = path.join(self.outdir, '_static', 'opensearch.xml')
self.handle_page('opensearch', {}, 'opensearch.xml', outfilename=fn)
@ -580,9 +583,11 @@ class StandaloneHTMLBuilder(Builder):
copyfile(jsfile, path.join(self.outdir, '_static',
'translations.js'))
# add context items for search function used in searchtools.js_t
ctx = self.globalcontext.copy()
ctx.update(self.indexer.context_for_searchtool())
# add context items for search function used in searchtools.js_t
if self.indexer is not None:
ctx.update(self.indexer.context_for_searchtool())
# then, copy over theme-supplied static files
if self.theme:
@ -804,7 +809,8 @@ class StandaloneHTMLBuilder(Builder):
copyfile(self.env.doc2path(pagename), source_name)
def handle_finish(self):
self.finish_tasks.add_task(self.dump_search_index)
if self.indexer:
self.finish_tasks.add_task(self.dump_search_index)
self.finish_tasks.add_task(self.dump_inventory)
def dump_inventory(self):

View File

@ -173,6 +173,9 @@ class HTMLHelpBuilder(StandaloneHTMLBuilder):
# don't add sidebar etc.
embedded = True
# don't generate search index or include search page
search = False
lcid = 0x409
encoding = 'cp1252'

View File

@ -10,9 +10,11 @@
"""
import re
from os import path
from os import path, environ
import shlex
from six import PY3, iteritems, string_types, binary_type, integer_types
from six.moves.urllib.parse import quote as urlquote
from sphinx.errors import ConfigError
from sphinx.locale import l_
@ -131,6 +133,35 @@ class Config(object):
# Devhelp only options
devhelp_basename = (lambda self: make_filename(self.project), None),
# Apple help options
applehelp_bundle_name = (lambda self: make_filename(self.project),
'applehelp'),
applehelp_bundle_id = (None, 'applehelp'),
applehelp_dev_region = ('en-us', 'applehelp'),
applehelp_bundle_version = ('1', 'applehelp'),
applehelp_icon = (None, 'applehelp'),
applehelp_kb_product = (lambda self: '%s-%s' \
% (make_filename(self.project), self.release),
'applehelp'),
applehelp_kb_url = (None, 'applehelp'),
applehelp_remote_url = (None, 'applehelp'),
applehelp_index_anchors = (False, 'applehelp'),
applehelp_min_term_length = (None, 'applehelp'),
applehelp_stopwords = (lambda self: self.language or 'en', 'applehelp'),
applehelp_locale = (lambda self: self.language or 'en', 'applehelp'),
applehelp_title = (lambda self: self.project + ' Help', 'applehelp'),
applehelp_codesign_identity = (lambda self:
environ.get('CODE_SIGN_IDENTITY', None),
'applehelp'),
applehelp_codesign_flags = (lambda self:
shlex.split(
environ.get('OTHER_CODE_SIGN_FLAGS',
'')),
'applehelp'),
applehelp_indexer_path = ('/usr/bin/hiutil', 'applehelp'),
applehelp_codesign_path = ('/usr/bin/codesign', 'applehelp'),
applehelp_disable_external_tools = (False, None),
# Epub options
epub_basename = (lambda self: make_filename(self.project), None),
epub_theme = ('epub', 'html'),

View File

@ -460,7 +460,7 @@ class BuildEnvironment:
config.exclude_patterns[:] +
config.templates_path +
config.html_extra_path +
['**/_sources', '.#*']
['**/_sources', '.#*', '*.lproj/**']
)
self.found_docs = set(get_matching_docs(
self.srcdir, config.source_suffix, exclude_matchers=matchers))

View File

@ -32,6 +32,7 @@ except ImportError:
from six import PY2, PY3, text_type
from six.moves import input
from six.moves.urllib.parse import quote as urlquote
from docutils.utils import column_width
from sphinx import __version__
@ -86,6 +87,7 @@ QUICKSTART_CONF += u'''\
import sys
import os
import shlex
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
@ -496,6 +498,7 @@ help:
\t@echo " json to make JSON files"
\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 " applehelp to make an Apple Help Book"
\t@echo " devhelp to make HTML files and a Devhelp project"
\t@echo " epub to make an epub"
\t@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
@ -557,6 +560,14 @@ qthelp:
\t@echo "To view the help file:"
\t@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/%(project_fn)s.qhc"
applehelp:
\t$(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp
\t@echo
\t@echo "Build finished. The help book is in $(BUILDDIR)/applehelp."
\t@echo "N.B. You won't be able to view it unless you put it in" \\
\t "~/Library/Documentation/Help or install it in your application" \\
\t "bundle."
devhelp:
\t$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
\t@echo
@ -1278,6 +1289,7 @@ def generate(d, overwrite=True, silent=False):
d['mastertocmaxdepth'] = 2
d['project_fn'] = make_filename(d['project'])
d['project_url'] = urlquote(d['project'].encode('idna'))
d['project_manpage'] = d['project_fn'].lower()
d['now'] = time.asctime()
d['project_underline'] = column_width(d['project']) * '='

View File

@ -43,6 +43,9 @@ html_context = {'hckey': 'hcval', 'hckey_co': 'wrong_hcval_co'}
htmlhelp_basename = 'SphinxTestsdoc'
applehelp_bundle_id = 'org.sphinx-doc.Sphinx.help'
applehelp_disable_external_tools = True
latex_documents = [
('contents', 'SphinxTests.tex', 'Sphinx Tests Documentation',
'Georg Brandl \\and someone else', 'manual'),

View File

@ -0,0 +1,2 @@
This file should be included in the final bundle by the applehelp builder.
It should be ignored by other builders.

View File

@ -66,9 +66,10 @@ def test_build_all():
).encode('utf-8'))
# note: no 'html' - if it's ok with dirhtml it's ok with html
for buildername in ['dirhtml', 'singlehtml', 'latex', 'texinfo',
'pickle', 'json', 'text', 'htmlhelp', 'qthelp', 'epub',
'changes', 'xml', 'pseudoxml', 'man', 'linkcheck']:
for buildername in ['dirhtml', 'singlehtml', 'latex', 'texinfo', 'pickle',
'json', 'text', 'htmlhelp', 'qthelp', 'epub',
'applehelp', 'changes', 'xml', 'pseudoxml', 'man',
'linkcheck']:
yield verify_build, buildername, srcdir

View File

@ -0,0 +1,56 @@
# -*- coding: utf-8 -*-
"""
test_build_applehelp
~~~~~~~~~~~~~~~~~~~~
Test the Apple Help builder and check its output. We don't need to
test the HTML itself; that's already handled by
:file:`test_build_html.py`.
:copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
import os
import plistlib
from util import with_app
from path import path
# Use plistlib.load in 3.4 and above
try:
read_plist = plistlib.load
except AttributeError:
read_plist = plistlib.readPlist
def check_structure(outdir):
contentsdir = outdir / 'Contents'
assert contentsdir.isdir()
assert (contentsdir / 'Info.plist').isfile()
with open(contentsdir / 'Info.plist', 'rb') as f:
plist = read_plist(f)
assert plist
assert len(plist)
assert plist.get('CFBundleIdentifier', None) == 'org.sphinx-doc.Sphinx.help'
assert (contentsdir / 'Resources').isdir()
assert (contentsdir / 'Resources' / 'en.lproj').isdir()
def check_localization(outdir):
lprojdir = outdir / 'Contents' / 'Resources' / 'en.lproj'
assert (lprojdir / 'localized.txt').isfile()
@with_app(buildername='applehelp')
def test_applehelp_output(app, status, warning):
app.builder.build_all()
# Have to use bundle_path, not outdir, because we alter the latter
# to point to the lproj directory so that the HTML arrives in the
# correct location.
bundle_path = path(app.builder.bundle_path)
check_structure(bundle_path)
check_localization(bundle_path)