1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
|
"""
sphinx.parsers
~~~~~~~~~~~~~~
A Base class for additional parsers.
:copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
import warnings
from typing import Any, Dict, List, Type, Union
from typing import TYPE_CHECKING
import docutils.parsers
import docutils.parsers.rst
from docutils import nodes
from docutils.parsers.rst import states
from docutils.statemachine import StringList
from docutils.transforms.universal import SmartQuotes
from sphinx.deprecation import RemovedInSphinx50Warning
from sphinx.util.rst import append_epilog, prepend_prolog
if TYPE_CHECKING:
from docutils.transforms import Transform # NOQA
from sphinx.application import Sphinx
class Parser(docutils.parsers.Parser):
"""
A base class of source parsers. The additional parsers should inherit this class instead
of ``docutils.parsers.Parser``. Compared with ``docutils.parsers.Parser``, this class
improves accessibility to Sphinx APIs.
The subclasses can access following objects and functions:
self.app
The application object (:class:`sphinx.application.Sphinx`)
self.config
The config object (:class:`sphinx.config.Config`)
self.env
The environment object (:class:`sphinx.environment.BuildEnvironment`)
self.warn()
Emit a warning. (Same as :meth:`sphinx.application.Sphinx.warn()`)
self.info()
Emit a informational message. (Same as :meth:`sphinx.application.Sphinx.info()`)
.. deprecated:: 1.6
``warn()`` and ``info()`` is deprecated. Use :mod:`sphinx.util.logging` instead.
.. deprecated:: 3.0
parser.app is deprecated.
"""
def set_application(self, app: "Sphinx") -> None:
"""set_application will be called from Sphinx to set app and other instance variables
:param sphinx.application.Sphinx app: Sphinx application object
"""
self._app = app
self.config = app.config
self.env = app.env
@property
def app(self) -> "Sphinx":
warnings.warn('parser.app is deprecated.', RemovedInSphinx50Warning, stacklevel=2)
return self._app
class RSTParser(docutils.parsers.rst.Parser, Parser):
"""A reST parser for Sphinx."""
def get_transforms(self) -> List[Type["Transform"]]:
"""Sphinx's reST parser replaces a transform class for smart-quotes by own's
refs: sphinx.io.SphinxStandaloneReader
"""
transforms = super().get_transforms()
transforms.remove(SmartQuotes)
return transforms
def parse(self, inputstring: Union[str, StringList], document: nodes.document) -> None:
"""Parse text and generate a document tree."""
self.setup_parse(inputstring, document) # type: ignore
self.statemachine = states.RSTStateMachine(
state_classes=self.state_classes,
initial_state=self.initial_state,
debug=document.reporter.debug_flag)
# preprocess inputstring
if isinstance(inputstring, str):
lines = docutils.statemachine.string2lines(
inputstring, tab_width=document.settings.tab_width,
convert_whitespace=True)
inputlines = StringList(lines, document.current_source)
else:
inputlines = inputstring
self.decorate(inputlines)
self.statemachine.run(inputlines, document, inliner=self.inliner)
self.finish_parse()
def decorate(self, content: StringList) -> None:
"""Preprocess reST content before parsing."""
prepend_prolog(content, self.config.rst_prolog)
append_epilog(content, self.config.rst_epilog)
def setup(app: "Sphinx") -> Dict[str, Any]:
app.add_source_parser(RSTParser)
return {
'version': 'builtin',
'parallel_read_safe': True,
'parallel_write_safe': True,
}
|