mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
183 lines
5.9 KiB
Python
183 lines
5.9 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""
|
|
sphinx.directives.patches
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
:copyright: Copyright 2007-2018 by the Sphinx team, see AUTHORS.
|
|
:license: BSD, see LICENSE for details.
|
|
"""
|
|
|
|
from typing import cast
|
|
|
|
from docutils import nodes
|
|
from docutils.nodes import make_id
|
|
from docutils.parsers.rst import directives
|
|
from docutils.parsers.rst.directives import images, html, tables
|
|
|
|
from sphinx import addnodes
|
|
from sphinx.util.docutils import SphinxDirective
|
|
from sphinx.util.nodes import set_source_info
|
|
|
|
if False:
|
|
# For type annotation
|
|
from typing import Dict, List, Tuple # NOQA
|
|
from sphinx.application import Sphinx # NOQA
|
|
from sphinx.util.typing import unicode # NOQA
|
|
|
|
|
|
class Figure(images.Figure):
|
|
"""The figure directive which applies `:name:` option to the figure node
|
|
instead of the image node.
|
|
"""
|
|
|
|
def run(self):
|
|
# type: () -> List[nodes.Node]
|
|
name = self.options.pop('name', None)
|
|
result = super(Figure, self).run()
|
|
if len(result) == 2 or isinstance(result[0], nodes.system_message):
|
|
return result
|
|
|
|
assert len(result) == 1
|
|
figure_node = cast(nodes.figure, result[0])
|
|
if name:
|
|
# set ``name`` to figure_node if given
|
|
self.options['name'] = name
|
|
self.add_name(figure_node)
|
|
|
|
# copy lineno from image node
|
|
if figure_node.line is None and len(figure_node) == 2:
|
|
caption = cast(nodes.caption, figure_node[1])
|
|
figure_node.line = caption.line
|
|
|
|
return [figure_node]
|
|
|
|
|
|
class Meta(html.Meta, SphinxDirective):
|
|
def run(self):
|
|
# type: () -> List[nodes.Node]
|
|
result = super(Meta, self).run()
|
|
for node in result:
|
|
if (isinstance(node, nodes.pending) and
|
|
isinstance(node.details['nodes'][0], html.MetaBody.meta)):
|
|
meta = node.details['nodes'][0]
|
|
meta.source = self.env.doc2path(self.env.docname)
|
|
meta.line = self.lineno
|
|
meta.rawcontent = meta['content'] # type: ignore
|
|
|
|
# docutils' meta nodes aren't picklable because the class is nested
|
|
meta.__class__ = addnodes.meta # type: ignore
|
|
|
|
return result
|
|
|
|
|
|
class RSTTable(tables.RSTTable):
|
|
"""The table directive which sets source and line information to its caption.
|
|
|
|
Only for docutils-0.13 or older version."""
|
|
|
|
def make_title(self):
|
|
# type: () -> Tuple[nodes.title, List[nodes.system_message]]
|
|
title, message = super(RSTTable, self).make_title()
|
|
if title:
|
|
set_source_info(self, title)
|
|
|
|
return title, message
|
|
|
|
|
|
class CSVTable(tables.CSVTable):
|
|
"""The csv-table directive which sets source and line information to its caption.
|
|
|
|
Only for docutils-0.13 or older version."""
|
|
|
|
def make_title(self):
|
|
# type: () -> Tuple[nodes.title, List[nodes.system_message]]
|
|
title, message = super(CSVTable, self).make_title()
|
|
if title:
|
|
set_source_info(self, title)
|
|
|
|
return title, message
|
|
|
|
|
|
class ListTable(tables.ListTable):
|
|
"""The list-table directive which sets source and line information to its caption.
|
|
|
|
Only for docutils-0.13 or older version."""
|
|
|
|
def make_title(self):
|
|
# type: () -> Tuple[nodes.title, List[nodes.system_message]]
|
|
title, message = super(ListTable, self).make_title()
|
|
if title:
|
|
set_source_info(self, title)
|
|
|
|
return title, message
|
|
|
|
|
|
class MathDirective(SphinxDirective):
|
|
has_content = True
|
|
required_arguments = 0
|
|
optional_arguments = 1
|
|
final_argument_whitespace = True
|
|
option_spec = {
|
|
'label': directives.unchanged,
|
|
'name': directives.unchanged,
|
|
'nowrap': directives.flag,
|
|
}
|
|
|
|
def run(self):
|
|
# type: () -> List[nodes.Node]
|
|
latex = '\n'.join(self.content)
|
|
if self.arguments and self.arguments[0]:
|
|
latex = self.arguments[0] + '\n\n' + latex
|
|
node = nodes.math_block(latex, latex,
|
|
docname=self.env.docname,
|
|
number=self.options.get('name'),
|
|
label=self.options.get('label'),
|
|
nowrap='nowrap' in self.options)
|
|
ret = [node] # type: List[nodes.Node]
|
|
set_source_info(self, node)
|
|
self.add_target(ret)
|
|
return ret
|
|
|
|
def add_target(self, ret):
|
|
# type: (List[nodes.Node]) -> None
|
|
node = cast(nodes.math_block, ret[0])
|
|
|
|
# assign label automatically if math_number_all enabled
|
|
if node['label'] == '' or (self.config.math_number_all and not node['label']):
|
|
seq = self.env.new_serialno('sphinx.ext.math#equations')
|
|
node['label'] = "%s:%d" % (self.env.docname, seq)
|
|
|
|
# no targets and numbers are needed
|
|
if not node['label']:
|
|
return
|
|
|
|
# register label to domain
|
|
domain = self.env.get_domain('math')
|
|
try:
|
|
eqno = domain.add_equation(self.env, self.env.docname, node['label']) # type: ignore # NOQA
|
|
node['number'] = eqno
|
|
|
|
# add target node
|
|
node_id = make_id('equation-%s' % node['label'])
|
|
target = nodes.target('', '', ids=[node_id])
|
|
self.state.document.note_explicit_target(target)
|
|
ret.insert(0, target)
|
|
except UserWarning as exc:
|
|
self.state_machine.reporter.warning(exc.args[0], line=self.lineno)
|
|
|
|
|
|
def setup(app):
|
|
# type: (Sphinx) -> Dict
|
|
directives.register_directive('figure', Figure)
|
|
directives.register_directive('meta', Meta)
|
|
directives.register_directive('table', RSTTable)
|
|
directives.register_directive('csv-table', CSVTable)
|
|
directives.register_directive('list-table', ListTable)
|
|
directives.register_directive('math', MathDirective)
|
|
|
|
return {
|
|
'version': 'builtin',
|
|
'parallel_read_safe': True,
|
|
'parallel_write_safe': True,
|
|
}
|