diff --git a/demo/source/conf.py b/demo/source/conf.py
index 574b75d7..2749a20f 100644
--- a/demo/source/conf.py
+++ b/demo/source/conf.py
@@ -17,7 +17,12 @@
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
# Disabled: , 'sphinx.ext.intersphinx'
-extensions = ['sphinx.ext.autodoc', 'sphinx.ext.todo', 'sphinx.ext.ifconfig', 'sphinx.ext.viewcode']
+extensions = [
+ 'sphinx.ext.autodoc',
+ 'sphinx.ext.todo',
+ 'sphinx.ext.ifconfig',
+ 'sphinx.ext.viewcode'
+]
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
@@ -62,15 +67,15 @@
#default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
-#add_function_parentheses = True
+add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
-#add_module_names = True
+add_module_names = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
-#show_authors = False
+show_authors = True
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
@@ -81,8 +86,21 @@
# Enable todo output
todo_include_todos = True
+autoclass_content = 'class'
+autodoc_member_order = 'bysource'
+autodoc_default_flags = [
+ 'members',
+ 'undoc-members',
+ 'private-members',
+ # 'special-members',
+ # 'inherited-members',
+ 'show-inheritance'
+]
+
# -- Options for HTML output ---------------------------------------------------
+html_translator_class = 'sphinx_bootstrap_theme.BootstrapTranslator'
+
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
html_theme = 'bootstrap'
@@ -132,7 +150,7 @@
# Location of link to source.
# Options are "nav" (default), "footer" or anything else to exclude.
- 'source_link_position': "nav",
+ 'source_link_position': "footer",
# Bootswatch (http://bootswatch.com/) theme.
#
@@ -199,7 +217,10 @@
# Custom sidebar templates, maps document names to template names.
#html_sidebars = {}
-html_sidebars = {'sidebar': ['localtoc.html', 'sourcelink.html', 'searchbox.html']}
+html_sidebars = {
+ 'sidebar': ['localtoc.html', 'sourcelink.html', 'searchbox.html'],
+ 'examples': ['localtoc.html']
+}
# Additional templates that should be rendered to pages, maps page names to
# template names.
@@ -218,10 +239,10 @@
#html_show_sourcelink = True
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
-#html_show_sphinx = True
+html_show_sphinx = True
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
-#html_show_copyright = True
+html_show_copyright = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a tag referring to it. The value of this option must be the
diff --git a/demo/source/example_module.rst b/demo/source/example_module.rst
new file mode 100644
index 00000000..dfc86d86
--- /dev/null
+++ b/demo/source/example_module.rst
@@ -0,0 +1,8 @@
+Example Module (:mod:`ExampleModule`)
+=====================================
+
+.. automodule:: sphinx_bootstrap_theme.example_module
+ :members:
+ :undoc-members:
+ :private-members:
+ :special-members:
diff --git a/demo/source/examples.rst b/demo/source/examples.rst
index 06d695da..412e6be2 100644
--- a/demo/source/examples.rst
+++ b/demo/source/examples.rst
@@ -77,6 +77,18 @@ Danger
------
.. danger:: This is **danger**-ous.
+Attention
+---------
+.. attention:: This is a note.
+
+See Also
+--------
+.. seealso:: Probably a reference.
+
+Error
+-----
+.. error:: This is a error.
+
Footnotes
=========
I have footnoted a first item [#f1]_ and second item [#f2]_.
diff --git a/demo/source/html_bootstrap_translator.rst b/demo/source/html_bootstrap_translator.rst
new file mode 100644
index 00000000..121692a6
--- /dev/null
+++ b/demo/source/html_bootstrap_translator.rst
@@ -0,0 +1,8 @@
+HTML Bootstrap Translator (:mod:`html_bootstrap_translator`)
+============================================================
+
+.. automodule:: sphinx_bootstrap_theme.html_bootstrap_translator
+ :members:
+ :undoc-members:
+ :private-members:
+ :special-members:
diff --git a/demo/source/index.rst b/demo/source/index.rst
index f7a7b20a..53e76925 100644
--- a/demo/source/index.rst
+++ b/demo/source/index.rst
@@ -22,6 +22,9 @@ Setting up and using the theme.
examples
sidebar
subdir/index
+ example_module
+ html_bootstrap_translator
+
Development history and feature wish lists.
diff --git a/sphinx_bootstrap_theme/__init__.py b/sphinx_bootstrap_theme/__init__.py
index 08736913..37e08524 100644
--- a/sphinx_bootstrap_theme/__init__.py
+++ b/sphinx_bootstrap_theme/__init__.py
@@ -6,7 +6,10 @@
__version__ = ".".join(str(v) for v in VERSION)
__version_full__ = __version__
+
def get_html_theme_path():
"""Return list of HTML theme paths."""
cur_dir = os.path.abspath(os.path.dirname(__file__))
return [cur_dir]
+
+from sphinx_bootstrap_theme.html_bootstrap_translator import BootstrapTranslator
diff --git a/sphinx_bootstrap_theme/bootstrap/layout.html b/sphinx_bootstrap_theme/bootstrap/layout.html
index 18e16904..993d5381 100644
--- a/sphinx_bootstrap_theme/bootstrap/layout.html
+++ b/sphinx_bootstrap_theme/bootstrap/layout.html
@@ -14,6 +14,7 @@
{% if theme_bootstrap_version == "3" %}
{% set theme_css_files = theme_css_files + [
'_static/bootswatch-' + bootstrap_version + '/' + theme_bootswatch_theme + '/bootstrap.min.css',
+ '_static/font-awesome-4.0.3/css/font-awesome.min.css',
'_static/bootstrap-sphinx.css'
]
%}
@@ -21,6 +22,7 @@
{% set theme_css_files = theme_css_files + [
'_static/bootswatch-' + bootstrap_version + '/' + theme_bootswatch_theme + '/bootstrap.min.css',
'_static/bootstrap-' + bootstrap_version + '/css/bootstrap-' + bootstrap_additional_css + '.min.css',
+ '_static/font-awesome-4.0.3/css/font-awesome.min.css',
'_static/bootstrap-sphinx.css'
]
%}
@@ -29,6 +31,7 @@
{% set theme_css_files = theme_css_files + [
'_static/bootstrap-' + bootstrap_version + '/css/bootstrap.min.css',
'_static/bootstrap-' + bootstrap_version + '/css/bootstrap-' + bootstrap_additional_css + '.min.css',
+ '_static/font-awesome-4.0.3/css/font-awesome.min.css',
'_static/bootstrap-sphinx.css'
]
%}
@@ -102,7 +105,7 @@
{%- block content %}
{{ navBar() }}
-
+
{%- block sidebar1 %}{{ bsidebar() }}{% endblock %}
{% block body %}{% endblock %}
@@ -114,28 +117,91 @@
{%- block footer %}
')
+
+ # overridden
+ def visit_field_name(self, node):
+ self.body.append(
+ self.starttag(node, 'div', '',
+ CLASS='accordion-heading panel-heading field-name'))
+ self.body.append('
' % self.section_level)
+
+ # overridden
+ def depart_field_name(self, node):
+ self.body.append('' % self.section_level)
+
+ # overridden
+ def visit_field_body(self, node):
+ self.body.append(
+ self.starttag(node, 'div', '',
+ CLASS='accordion-inner panel-body field-body'))
+ if self.field_context[-1] in ['Parameters', 'Raises', 'Returns']:
+ self._print_parameters(node)
+
+ # overridden
+ def depart_field_body(self, node):
+ self.body.append('
')
+
+ # overridden
+ def visit_table(self, node):
+ self.context.append(self.compact_p)
+ self.compact_p = True
+ classes = ' '.join(['table', self.settings.table_style]).strip()
+ self.body.append(
+ self.starttag(node, 'table', CLASS=classes))
+
+ # overridden
+ def depart_table(self, node):
+ self.compact_p = self.context.pop()
+ self.body.append('\n')
+
+ def visit_desc(self, node):
+ if node['objtype'] in member_types.keys() \
+ and node['objtype'] != 'staticmethod':
+ node[0].insert(0,
+ addnodes
+ .desc_annotation(text=member_types[node['objtype']]))
+ self.body.append(
+ self.starttag(node, 'div',
+ CLASS=('accordion-group panel panel-default '
+ '%s' % node['objtype'])))
+ if node['objtype'] in ['class']:
+ self.collapse_context.append([node['objtype'],
+ '%s-id%d' % (node['objtype'],
+ self.collapse_id_count)])
+ self.collapse_id_count += 1
+ if len(self.collapse_context) > 0 \
+ and node['objtype'] in member_types.keys():
+ self.collapse_context[-1]\
+ .append('%s-id%d' % (node['objtype'], self.collapse_item_count))
+ self.collapse_item_count += 1
+ self.section_level += 1
+
+ def depart_desc(self, node):
+ self.section_level -= 1
+ if node['objtype'] in ['class']:
+ self.collapse_context.pop()
+ if len(self.collapse_context) > 0 \
+ and node['objtype'] in member_types.keys():
+ self.collapse_context[-1].pop()
+ self.body.append('
')
+
+ def visit_desc_signature(self, node):
+ self.body.append(
+ self.starttag(node, 'div',
+ CLASS=('accordion-heading panel-heading '
+ 'desc-signature')))
+ self.body.append('' % self.section_level)
+ if len(self.collapse_context) > 0 \
+ and self.collapse_context[-1][0] in ['class'] \
+ and len(self.collapse_context[-1]) == 3:
+ self.body.append(
+ '' % self.collapse_context[-1][2])
+
+ def depart_desc_signature(self, node):
+ if len(self.collapse_context) > 0 \
+ and self.collapse_context[-1][0] in ['class'] \
+ and len(self.collapse_context[-1]) == 3:
+ self.body.append('')
+ self.body.append('' % self.section_level)
+
+ def visit_desc_name(self, node):
+ self.body.append(self.starttag(node, 'tt', '', CLASS='desc-name'))
+
+ def depart_desc_name(self, node):
+ self.body.append('')
+
+ def visit_desc_addname(self, node):
+ self.body.append(
+ self.starttag(node, 'tt', '', CLASS='desc-addname'))
+ self.body.append('')
+
+ def depart_desc_addname(self, node):
+ self.body.append('')
+
+ def visit_desc_parameterlist(self, node):
+ """The list of parameters in a method signature.
+ Including the enclosing brackets.
+ """
+ self.body.append(
+ self.starttag(node, 'tt', '', CLASS='desc-parameterlist'))
+ self.body.append('(')
+ self.first_param = 1
+ self.optional_param_level = 0
+ # How many required parameters are left.
+ self.required_params_left = sum([isinstance(c, addnodes.desc_parameter)
+ for c in node.children])
+ self.param_separator = node.child_text_separator
+
+ def depart_desc_parameterlist(self, node):
+ self.body.append(')')
+ self.body.append('')
+
+ def visit_desc_parameter(self, node):
+ """A single parameter in a method signature
+ """
+ self.body.append(
+ self.starttag(node, 'span', '', CLASS='desc-parameter'))
+ if self.first_param:
+ self.first_param = 0
+ elif not self.required_params_left:
+ self.body.append(self.param_separator)
+ if self.optional_param_level == 0:
+ self.required_params_left -= 1
+ if not node.hasattr('noemph'):
+ self.body.append('')
+
+ def depart_desc_parameter(self, node):
+ if not node.hasattr('noemph'):
+ self.body.append('')
+ if self.required_params_left:
+ self.body.append(self.param_separator)
+ self.body.append('')
+
+ def visit_desc_optional(self, node):
+ """Optional parameters in a method signature.
+ """
+ self.body.append(self.starttag(node, 'span', '', CLASS='desc-optional'))
+ self.optional_param_level += 1
+ self.body.append('[')
+
+ def depart_desc_optional(self, node):
+ self.optional_param_level -= 1
+ self.body.append(']')
+
+ def visit_desc_returns(self, node):
+ self.body.append(self.starttag(node, 'tt', '', CLASS='desc-returns'))
+
+ def depart_desc_returns(self, node):
+ self.body.append('')
+
+ def visit_desc_content(self, node):
+ """The content of a class, method or attribute.
+ """
+ if len(self.collapse_context) > 0 \
+ and self.collapse_context[-1][0] in ['class'] \
+ and len(self.collapse_context[-1]) == 2:
+ self.body.append(
+ '' % self.collapse_context[-1][1])
+ self.collapse_id_count += 1
+
+ if len(self.collapse_context) > 0 \
+ and self.collapse_context[-1][0] in ['class'] \
+ and len(self.collapse_context[-1]) == 3:
+ self.body.append(
+ '
')
+ self.body.append(
+ self.starttag(node, 'div',
+ CLASS='accordion-inner panel-body desc-content'))
+
+ def depart_desc_content(self, node):
+ if len(self.collapse_context) > 0 \
+ and self.collapse_context[-1][0] in ['class'] \
+ and len(self.collapse_context[-1]) == 2:
+ self.body.append('
')
+
+ if len(self.collapse_context) > 0 \
+ and self.collapse_context[-1][0] in ['class'] \
+ and len(self.collapse_context[-1]) == 3:
+ self.body.append('
')
+ self.body.append('')
+
+ def visit_desc_annotation(self, node):
+ """Annotations in object signatures.
+
+ This is either the ``class``, ``method`` or ``attribute`` identifier or
+ the value of module or class attributes.
+ """
+ self.body.append(
+ self.starttag(node, 'tt', '',
+ CLASS='desc-annotation text-muted muted'))
+
+ def depart_desc_annotation(self, node):
+ self.body.append('')
+
+ def visit_toctree(self, node):
+ self.body.append(self.starttag(node, 'span', CLASS='toctree'))
+
+ def depart_toctree(self, node):
+ self.body.append('')
+
+ # the following four methods are taken from
+ # http://stackoverflow.com/a/15562804
+ def visit_displaymath(self, node):
+ import sphinx.ext.mathjax
+ sphinx.ext.mathjax.html_visit_displaymath(self, node)
+
+ def depart_displaymath(self, node):
+ return
+
+ # overridden
+ def visit_math(self, node):
+ import sphinx.ext.mathjax
+ sphinx.ext.mathjax.html_visit_math(self, node)
+
+ # overridden
+ def depart_math(self, node):
+ return
+
+ # overridden
+ def unknown_visit(self, node):
+ raise NotImplementedError('Unknown node: %s' % node.__class__.__name__)
+
+ def _print_parameters(self, node):
+ self.body.append(''
+ ''
+ ''
+ ''
+ ''
+ ''
+ '')
+
+ if isinstance(node.children[0], nodes.paragraph):
+ if self.field_context[-1] in ['Raises']:
+ if len(node.children) > 1:
+ if isinstance(node[1], nodes.bullet_list):
+ node[0].append(node[1].deepcopy())
+ node.remove(node[1])
+
+ self._print_single_parameter(node[0])
+ elif isinstance(node.children[0], nodes.bullet_list):
+ first = True
+ for _c in node.children[0]:
+ self._print_single_parameter(_c[0], first=first)
+ if first:
+ first = False
+ self.body.append('
')
+ node.clear()
+
+ def _print_single_parameter(self, node, first=False):
+ _do_name = True
+ _name = None
+ _do_type = False
+ _types = []
+ _do_desc = False
+ _desc = []
+ for _c in node.children:
+ if _do_desc:
+ _desc.append(_c)
+
+ elif _do_name and node.children.index(_c) == 0 \
+ and isinstance(_c, (nodes.strong, nodes.literal)):
+ _name = _c[0].astext()
+ _do_name = False
+
+ elif isinstance(_c, nodes.Text):
+ if _do_type is False and _c.astext() == ' (':
+ _do_type = True
+ if _c.astext() == ')':
+ _c.replace(')', '', 1)
+ _do_type = False
+ if _c.astext() in [' -- ', ' --'] \
+ or _c.astext().find(' --') != -1:
+ if len(_c.astext().replace(' --', '', 1).lstrip()) > 0:
+ _desc.append(
+ nodes.Text(
+ _c.astext().replace(' --', '', 1).lstrip()))
+ _do_desc = True
+ if ' of ' in _c.astext() and _do_type:
+ _types.append(_c)
+
+ elif isinstance(_c, (nodes.emphasis, nodes.literal,
+ nodes.reference)) \
+ and _do_type:
+ if isinstance(_c, (nodes.emphasis, nodes.literal)):
+ _types.append(_c[0])
+ else:
+ _types.append(_c)
+
+ _cls = 'parameter-name'
+ if first:
+ _cls += ' first-parameter'
+ self.body.append(
+ ''
+ '| '
+ ' %s ' % (_cls, _name))
+ _cls = 'parameter-type'
+ if first:
+ _cls += ' first-parameter'
+ self.body.append(' | '
+ ''
+ ' ' % _cls)
+ _of_type = False
+ for _ti in range(0, len(_types)):
+ if _types[_ti].astext() == ' of ':
+ self.body.append(_types[_ti].astext())
+ _of_type = True
+ else:
+ if len(_types) > 1 and _ti > 0 and not _of_type:
+ self.body.append(', ')
+ if _of_type:
+ _of_type = False
+ self.body.append('')
+ if isinstance(_types[_ti], nodes.reference):
+ if isinstance(_types[_ti][0], nodes.literal):
+ _type = nodes.Text(_types[_ti][0].astext())
+ _types[_ti].clear()
+ _types[_ti].append(_type)
+ _types[_ti].walkabout(self)
+ else:
+ self.body.append(_types[_ti].astext())
+ self.body.append('')
+
+ _cls = 'parameter-desc'
+ if first:
+ _cls += ' first-parameter'
+ self.body.append(' | '
+ ''
+ ' ' % _cls)
+
+ for _desc_elem in _desc:
+ _desc_elem.walkabout(self)
+ self.body.append(' '
+ ' | '
+ '
')