mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Merge branch 'stable'
This commit is contained in:
commit
e64ee7e330
10
CHANGES
10
CHANGES
@ -126,12 +126,20 @@ Documentation
|
|||||||
-------------
|
-------------
|
||||||
|
|
||||||
|
|
||||||
Release 1.4.6 (in development)
|
Release 1.4.7 (in development)
|
||||||
==============================
|
==============================
|
||||||
|
|
||||||
Bugs fixed
|
Bugs fixed
|
||||||
----------
|
----------
|
||||||
|
|
||||||
|
* #2870: flatten genindex columns' heights.
|
||||||
|
* #2856: Search on generated HTML site doesnt find some symbols
|
||||||
|
* #2882: Fall back to a GET request on 403 status in linkcheck
|
||||||
|
* #2902: jsdump.loads fails to load search index if keywords starts with
|
||||||
|
underscore
|
||||||
|
* #2900: Fix epub content.opf: add auto generated orphan files to spine.
|
||||||
|
* #2899: Fix ``hasdoc()`` function in Jinja2 template. It can detect ``genindex``, ``search`` collectly.
|
||||||
|
* #2901: Fix epub result: skip creating links from image tags to original image files.
|
||||||
|
|
||||||
Release 1.4.6 (released Aug 20, 2016)
|
Release 1.4.6 (released Aug 20, 2016)
|
||||||
=====================================
|
=====================================
|
||||||
|
@ -86,33 +86,28 @@ Builtin themes
|
|||||||
+--------------------+--------------------+
|
+--------------------+--------------------+
|
||||||
| **Theme overview** | |
|
| **Theme overview** | |
|
||||||
+--------------------+--------------------+
|
+--------------------+--------------------+
|
||||||
| |alabaster| | |sphinx_rtd_theme| |
|
| |alabaster| | |classic| |
|
||||||
| | |
|
| | |
|
||||||
| *alabaster* | *sphinx_rtd_theme* |
|
| *alabaster* | *classic* |
|
||||||
+--------------------+--------------------+
|
+--------------------+--------------------+
|
||||||
| |classic| | |sphinxdoc| |
|
| |sphinxdoc| | |scrolls| |
|
||||||
| | |
|
| | |
|
||||||
| *classic* | *sphinxdoc* |
|
| *sphinxdoc* | *scrolls* |
|
||||||
+--------------------+--------------------+
|
+--------------------+--------------------+
|
||||||
| |scrolls| | |agogo| |
|
| |agogo| | |traditional| |
|
||||||
| | |
|
| | |
|
||||||
| *scrolls* | *agogo* |
|
| *agogo* | *traditional* |
|
||||||
+--------------------+--------------------+
|
+--------------------+--------------------+
|
||||||
| |traditional| | |nature| |
|
| |nature| | |haiku| |
|
||||||
| | |
|
| | |
|
||||||
| *traditional* | *nature* |
|
| *nature* | *haiku* |
|
||||||
+--------------------+--------------------+
|
+--------------------+--------------------+
|
||||||
| |haiku| | |pyramid| |
|
| |pyramid| | |bizstyle| |
|
||||||
| | |
|
| | |
|
||||||
| *haiku* | *pyramid* |
|
| *pyramid* | *bizstyle* |
|
||||||
+--------------------+--------------------+
|
|
||||||
| |bizstyle| | |
|
|
||||||
| | |
|
|
||||||
| *bizstyle* | |
|
|
||||||
+--------------------+--------------------+
|
+--------------------+--------------------+
|
||||||
|
|
||||||
.. |alabaster| image:: themes/alabaster.png
|
.. |alabaster| image:: themes/alabaster.png
|
||||||
.. |sphinx_rtd_theme| image:: themes/sphinx_rtd_theme.png
|
|
||||||
.. |classic| image:: themes/classic.png
|
.. |classic| image:: themes/classic.png
|
||||||
.. |sphinxdoc| image:: themes/sphinxdoc.png
|
.. |sphinxdoc| image:: themes/sphinxdoc.png
|
||||||
.. |scrolls| image:: themes/scrolls.png
|
.. |scrolls| image:: themes/scrolls.png
|
||||||
@ -147,13 +142,6 @@ These themes are:
|
|||||||
|
|
||||||
.. _Alabaster theme: https://pypi.python.org/pypi/alabaster
|
.. _Alabaster theme: https://pypi.python.org/pypi/alabaster
|
||||||
|
|
||||||
* **sphinx_rtd_theme** -- `Read the Docs Sphinx Theme`_.
|
|
||||||
This is a mobile-friendly sphinx theme that was made for readthedocs.org.
|
|
||||||
View a working demo over on readthedocs.org. You can get options information
|
|
||||||
at `Read the Docs Sphinx Theme`_ page.
|
|
||||||
|
|
||||||
.. _Read the Docs Sphinx Theme: https://pypi.python.org/pypi/sphinx_rtd_theme
|
|
||||||
|
|
||||||
* **classic** -- This is the classic theme, which looks like `the Python 2
|
* **classic** -- This is the classic theme, which looks like `the Python 2
|
||||||
documentation <https://docs.python.org/2/>`_. It can be customized via
|
documentation <https://docs.python.org/2/>`_. It can be customized via
|
||||||
these options:
|
these options:
|
||||||
@ -359,3 +347,28 @@ is built with the classic theme, the output directory will contain a
|
|||||||
.. [1] It is not an executable Python file, as opposed to :file:`conf.py`,
|
.. [1] It is not an executable Python file, as opposed to :file:`conf.py`,
|
||||||
because that would pose an unnecessary security risk if themes are
|
because that would pose an unnecessary security risk if themes are
|
||||||
shared.
|
shared.
|
||||||
|
|
||||||
|
Third Party Themes
|
||||||
|
------------------
|
||||||
|
|
||||||
|
.. cssclass:: longtable
|
||||||
|
|
||||||
|
+--------------------+--------------------+
|
||||||
|
| **Theme overview** | |
|
||||||
|
+--------------------+--------------------+
|
||||||
|
| |sphinx_rtd_theme| | |
|
||||||
|
| | |
|
||||||
|
| *sphinx_rtd_theme* | |
|
||||||
|
+--------------------+--------------------+
|
||||||
|
|
||||||
|
.. |sphinx_rtd_theme| image:: themes/sphinx_rtd_theme.png
|
||||||
|
|
||||||
|
* **sphinx_rtd_theme** -- `Read the Docs Sphinx Theme`_.
|
||||||
|
This is a mobile-friendly sphinx theme that was made for readthedocs.org.
|
||||||
|
View a working demo over on readthedocs.org. You can get install and options
|
||||||
|
information at `Read the Docs Sphinx Theme`_ page.
|
||||||
|
|
||||||
|
.. _Read the Docs Sphinx Theme: https://pypi.python.org/pypi/sphinx_rtd_theme
|
||||||
|
|
||||||
|
.. versionchanged:: 1.4
|
||||||
|
**sphinx_rtd_theme** has become optional.
|
||||||
|
@ -123,6 +123,9 @@ FILE_TEMPLATE = u'''\
|
|||||||
SPINE_TEMPLATE = u'''\
|
SPINE_TEMPLATE = u'''\
|
||||||
<itemref idref="%(idref)s" />'''
|
<itemref idref="%(idref)s" />'''
|
||||||
|
|
||||||
|
NO_LINEAR_SPINE_TEMPLATE = u'''\
|
||||||
|
<itemref idref="%(idref)s" linear="no" />'''
|
||||||
|
|
||||||
GUIDE_TEMPLATE = u'''\
|
GUIDE_TEMPLATE = u'''\
|
||||||
<reference type="%(type)s" title="%(title)s" href="%(uri)s" />'''
|
<reference type="%(type)s" title="%(title)s" href="%(uri)s" />'''
|
||||||
|
|
||||||
@ -189,7 +192,8 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
|||||||
embedded = True
|
embedded = True
|
||||||
# disable download role
|
# disable download role
|
||||||
download_support = False
|
download_support = False
|
||||||
|
# dont' create links to original images from images
|
||||||
|
html_scaled_image_link = False
|
||||||
# don't generate search index or include search page
|
# don't generate search index or include search page
|
||||||
search = False
|
search = False
|
||||||
|
|
||||||
@ -204,6 +208,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
|||||||
coverpage_name = COVERPAGE_NAME
|
coverpage_name = COVERPAGE_NAME
|
||||||
file_template = FILE_TEMPLATE
|
file_template = FILE_TEMPLATE
|
||||||
spine_template = SPINE_TEMPLATE
|
spine_template = SPINE_TEMPLATE
|
||||||
|
no_linear_spine_template = NO_LINEAR_SPINE_TEMPLATE
|
||||||
guide_template = GUIDE_TEMPLATE
|
guide_template = GUIDE_TEMPLATE
|
||||||
toctree_template = TOCTREE_TEMPLATE
|
toctree_template = TOCTREE_TEMPLATE
|
||||||
doctype = DOCTYPE
|
doctype = DOCTYPE
|
||||||
@ -588,6 +593,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
|||||||
|
|
||||||
# spine
|
# spine
|
||||||
spine = []
|
spine = []
|
||||||
|
spinefiles = set()
|
||||||
for item in self.refnodes:
|
for item in self.refnodes:
|
||||||
if '#' in item['refuri']:
|
if '#' in item['refuri']:
|
||||||
continue
|
continue
|
||||||
@ -596,14 +602,23 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
|||||||
spine.append(self.spine_template % {
|
spine.append(self.spine_template % {
|
||||||
'idref': self.esc(self.make_id(item['refuri']))
|
'idref': self.esc(self.make_id(item['refuri']))
|
||||||
})
|
})
|
||||||
|
spinefiles.add(item['refuri'])
|
||||||
for info in self.domain_indices:
|
for info in self.domain_indices:
|
||||||
spine.append(self.spine_template % {
|
spine.append(self.spine_template % {
|
||||||
'idref': self.esc(self.make_id(info[0] + self.out_suffix))
|
'idref': self.esc(self.make_id(info[0] + self.out_suffix))
|
||||||
})
|
})
|
||||||
|
spinefiles.add(info[0] + self.out_suffix)
|
||||||
if self.use_index:
|
if self.use_index:
|
||||||
spine.append(self.spine_template % {
|
spine.append(self.spine_template % {
|
||||||
'idref': self.esc(self.make_id('genindex' + self.out_suffix))
|
'idref': self.esc(self.make_id('genindex' + self.out_suffix))
|
||||||
})
|
})
|
||||||
|
spinefiles.add('genindex' + self.out_suffix)
|
||||||
|
# add auto generated files
|
||||||
|
for name in self.files:
|
||||||
|
if name not in spinefiles and name.endswith(self.out_suffix):
|
||||||
|
spine.append(self.no_linear_spine_template % {
|
||||||
|
'idref': self.esc(self.make_id(name))
|
||||||
|
})
|
||||||
|
|
||||||
# add the optional cover
|
# add the optional cover
|
||||||
content_tmpl = self.content_template
|
content_tmpl = self.content_template
|
||||||
@ -630,6 +645,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
|
|||||||
ctx = {'image': self.esc(image), 'title': self.config.project}
|
ctx = {'image': self.esc(image), 'title': self.config.project}
|
||||||
self.handle_page(
|
self.handle_page(
|
||||||
path.splitext(self.coverpage_name)[0], ctx, html_tmpl)
|
path.splitext(self.coverpage_name)[0], ctx, html_tmpl)
|
||||||
|
spinefiles.add(self.coverpage_name)
|
||||||
|
|
||||||
guide = []
|
guide = []
|
||||||
auto_add_cover = True
|
auto_add_cover = True
|
||||||
|
@ -76,6 +76,8 @@ class StandaloneHTMLBuilder(Builder):
|
|||||||
link_suffix = '.html' # defaults to matching out_suffix
|
link_suffix = '.html' # defaults to matching out_suffix
|
||||||
indexer_format = js_index
|
indexer_format = js_index
|
||||||
indexer_dumps_unicode = True
|
indexer_dumps_unicode = True
|
||||||
|
# create links to original images from images [True/False]
|
||||||
|
html_scaled_image_link = True
|
||||||
supported_image_types = ['image/svg+xml', 'image/png',
|
supported_image_types = ['image/svg+xml', 'image/png',
|
||||||
'image/gif', 'image/jpeg']
|
'image/gif', 'image/jpeg']
|
||||||
searchindex_filename = 'searchindex.js'
|
searchindex_filename = 'searchindex.js'
|
||||||
@ -676,7 +678,7 @@ class StandaloneHTMLBuilder(Builder):
|
|||||||
"""
|
"""
|
||||||
Builder.post_process_images(self, doctree)
|
Builder.post_process_images(self, doctree)
|
||||||
|
|
||||||
if self.config.html_scaled_image_link:
|
if self.config.html_scaled_image_link and self.html_scaled_image_link:
|
||||||
for node in doctree.traverse(nodes.image):
|
for node in doctree.traverse(nodes.image):
|
||||||
scale_keys = ('scale', 'width', 'height')
|
scale_keys = ('scale', 'width', 'height')
|
||||||
if not any((key in node) for key in scale_keys) or \
|
if not any((key in node) for key in scale_keys) or \
|
||||||
@ -786,7 +788,17 @@ class StandaloneHTMLBuilder(Builder):
|
|||||||
uri = relative_uri(baseuri, otheruri) or '#'
|
uri = relative_uri(baseuri, otheruri) or '#'
|
||||||
return uri
|
return uri
|
||||||
ctx['pathto'] = pathto
|
ctx['pathto'] = pathto
|
||||||
ctx['hasdoc'] = lambda name: name in self.env.all_docs
|
|
||||||
|
def hasdoc(name):
|
||||||
|
if name in self.env.all_docs:
|
||||||
|
return True
|
||||||
|
elif name == 'search' and self.search:
|
||||||
|
return True
|
||||||
|
elif name == 'genindex' and self.get_builder_config('use_index', 'html'):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
ctx['hasdoc'] = hasdoc
|
||||||
|
|
||||||
if self.name != 'htmlhelp':
|
if self.name != 'htmlhelp':
|
||||||
ctx['encoding'] = encoding = self.config.html_output_encoding
|
ctx['encoding'] = encoding = self.config.html_output_encoding
|
||||||
else:
|
else:
|
||||||
|
@ -35,6 +35,27 @@ def _toint(val):
|
|||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
def _slice_index(values, slices):
|
||||||
|
seq = list(values)
|
||||||
|
length = 0
|
||||||
|
for value in values:
|
||||||
|
length += 1 + len(value[1][1]) # count includes subitems
|
||||||
|
items_per_slice = length // slices
|
||||||
|
offset = 0
|
||||||
|
for slice_number in range(slices):
|
||||||
|
count = 0
|
||||||
|
start = offset
|
||||||
|
if slices == slice_number + 1: # last column
|
||||||
|
offset = len(seq)
|
||||||
|
else:
|
||||||
|
for value in values[offset:]:
|
||||||
|
count += 1 + len(value[1][1])
|
||||||
|
offset += 1
|
||||||
|
if count >= items_per_slice:
|
||||||
|
break
|
||||||
|
yield seq[start:offset]
|
||||||
|
|
||||||
|
|
||||||
def accesskey(context, key):
|
def accesskey(context, key):
|
||||||
"""Helper to output each access key only once."""
|
"""Helper to output each access key only once."""
|
||||||
if '_accesskeys' not in context:
|
if '_accesskeys' not in context:
|
||||||
@ -125,6 +146,7 @@ class BuiltinTemplateLoader(TemplateBridge, BaseLoader):
|
|||||||
extensions=extensions)
|
extensions=extensions)
|
||||||
self.environment.filters['tobool'] = _tobool
|
self.environment.filters['tobool'] = _tobool
|
||||||
self.environment.filters['toint'] = _toint
|
self.environment.filters['toint'] = _toint
|
||||||
|
self.environment.filters['slice_index'] = _slice_index
|
||||||
self.environment.globals['debug'] = contextfunction(pformat)
|
self.environment.globals['debug'] = contextfunction(pformat)
|
||||||
self.environment.globals['accesskey'] = contextfunction(accesskey)
|
self.environment.globals['accesskey'] = contextfunction(accesskey)
|
||||||
self.environment.globals['idgen'] = idgen
|
self.environment.globals['idgen'] = idgen
|
||||||
|
@ -42,7 +42,7 @@
|
|||||||
{%- for key, entries in genindexentries %}
|
{%- for key, entries in genindexentries %}
|
||||||
<h2 id="{{ key }}">{{ key }}</h2>
|
<h2 id="{{ key }}">{{ key }}</h2>
|
||||||
<table style="width: 100%" class="indextable genindextable"><tr>
|
<table style="width: 100%" class="indextable genindextable"><tr>
|
||||||
{%- for column in entries|slice(2) if column %}
|
{%- for column in entries|slice_index(2) if column %}
|
||||||
<td style="width: 33%; vertical-align: top;"><ul>
|
<td style="width: 33%; vertical-align: top;"><ul>
|
||||||
{%- for entryname, (links, subitems, _) in column %}
|
{%- for entryname, (links, subitems, _) in column %}
|
||||||
<li>{{ indexentries(entryname, links) }}
|
<li>{{ indexentries(entryname, links) }}
|
||||||
|
@ -145,7 +145,7 @@ var Search = {
|
|||||||
var searchterms = [];
|
var searchterms = [];
|
||||||
var excluded = [];
|
var excluded = [];
|
||||||
var hlterms = [];
|
var hlterms = [];
|
||||||
var tmp = query.split(/\s+/);
|
var tmp = query.split(/\W+/);
|
||||||
var objectterms = [];
|
var objectterms = [];
|
||||||
for (i = 0; i < tmp.length; i++) {
|
for (i = 0; i < tmp.length; i++) {
|
||||||
if (tmp[i] !== "") {
|
if (tmp[i] !== "") {
|
||||||
|
@ -18,7 +18,7 @@ from sphinx.util.pycompat import u
|
|||||||
|
|
||||||
_str_re = re.compile(r'"(\\\\|\\"|[^"])*"')
|
_str_re = re.compile(r'"(\\\\|\\"|[^"])*"')
|
||||||
_int_re = re.compile(r'\d+')
|
_int_re = re.compile(r'\d+')
|
||||||
_name_re = re.compile(r'[a-zA-Z]\w*')
|
_name_re = re.compile(r'[a-zA-Z_]\w*')
|
||||||
_nameonly_re = re.compile(r'[a-zA-Z_][a-zA-Z0-9_]*$')
|
_nameonly_re = re.compile(r'[a-zA-Z_][a-zA-Z0-9_]*$')
|
||||||
|
|
||||||
# escape \, ", control characters and everything outside ASCII
|
# escape \, ", control characters and everything outside ASCII
|
||||||
|
@ -1,9 +1,20 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
from sphinx.util.jsdump import dumps, loads
|
||||||
|
|
||||||
|
|
||||||
def test_jsdump():
|
def test_jsdump():
|
||||||
from sphinx.util.jsdump import dumps
|
data = {'1a': 1}
|
||||||
|
assert dumps(data) == '{"1a":1}'
|
||||||
|
assert data == loads(dumps(data))
|
||||||
|
|
||||||
assert dumps({'1a': 1}) == '{"1a":1}'
|
data = {'a1': 1}
|
||||||
assert dumps({'a1': 1}) == '{a1:1}'
|
assert dumps(data) == '{a1:1}'
|
||||||
|
assert data == loads(dumps(data))
|
||||||
|
|
||||||
assert dumps({u'a\xe8': 1}) == '{"a\\u00e8":1}'
|
data = {u'a\xe8': 1}
|
||||||
|
assert dumps(data) == '{"a\\u00e8":1}'
|
||||||
|
assert data == loads(dumps(data))
|
||||||
|
|
||||||
|
data = {'_foo': 1}
|
||||||
|
assert dumps(data) == '{_foo:1}'
|
||||||
|
assert data == loads(dumps(data))
|
||||||
|
Loading…
Reference in New Issue
Block a user