Source code for sphinx.parsers

"""A Base class for additional parsers."""

from __future__ import annotations

from typing import TYPE_CHECKING, Any

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 import Transform
from docutils.transforms.universal import SmartQuotes

from sphinx.config import Config
from sphinx.environment import BuildEnvironment
from sphinx.util.rst import append_epilog, prepend_prolog

if TYPE_CHECKING:
    from sphinx.application import Sphinx


[docs]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 sphinx core runtime objects (app, config and env). """ #: The config object config: Config #: The environment object env: BuildEnvironment
[docs] 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
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 its own refs: sphinx.io.SphinxStandaloneReader """ transforms = super().get_transforms() transforms.remove(SmartQuotes) return transforms def parse(self, inputstring: 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, }