summaryrefslogtreecommitdiffstats
path: root/doc/extdev/markupapi.rst
blob: 072760c3f8305bf06669b642abbea4f4821e9a3a (plain)
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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
Docutils markup API
===================

This section describes the API for adding ReST markup elements (roles and
directives).

Roles
-----


Directives
----------

Directives are handled by classes derived from
``docutils.parsers.rst.Directive``.  They have to be registered by an extension
using :meth:`.Sphinx.add_directive` or :meth:`.Sphinx.add_directive_to_domain`.

.. module:: docutils.parsers.rst

.. class:: Directive

   The markup syntax of the new directive is determined by the follow five class
   attributes:

   .. autoattribute:: required_arguments
   .. autoattribute:: optional_arguments
   .. autoattribute:: final_argument_whitespace
   .. autoattribute:: option_spec

      Option validator functions take a single parameter, the option argument
      (or ``None`` if not given), and should validate it or convert it to the
      proper form.  They raise :exc:`ValueError` or :exc:`TypeError` to indicate
      failure.

      There are several predefined and possibly useful validators in the
      :mod:`docutils.parsers.rst.directives` module.

   .. autoattribute:: has_content

   New directives must implement the :meth:`run` method:

   .. method:: run()

      This method must process the directive arguments, options and content, and
      return a list of Docutils/Sphinx nodes that will be inserted into the
      document tree at the point where the directive was encountered.

   Instance attributes that are always set on the directive are:

   .. attribute:: name

      The directive name (useful when registering the same directive class under
      multiple names).

   .. attribute:: arguments

      The arguments given to the directive, as a list.

   .. attribute:: options

      The options given to the directive, as a dictionary mapping option names
      to validated/converted values.

   .. attribute:: content

      The directive content, if given, as a :class:`!ViewList`.

   .. attribute:: lineno

      The absolute line number on which the directive appeared.  This is not
      always a useful value; use :attr:`srcline` instead.

   .. attribute:: content_offset

      Internal offset of the directive content.  Used when calling
      ``nested_parse`` (see below).

   .. attribute:: block_text

      The string containing the entire directive.

   .. attribute:: state
                  state_machine

      The state and state machine which controls the parsing.  Used for
      ``nested_parse``.


ViewLists
^^^^^^^^^

Docutils represents document source lines in a class
``docutils.statemachine.ViewList``.  This is a list with extended functionality
-- for one, slicing creates views of the original list, and also the list
contains information about the source line numbers.

The :attr:`Directive.content` attribute is a ViewList.  If you generate content
to be parsed as ReST, you have to create a ViewList yourself.  Important for
content generation are the following points:

* The constructor takes a list of strings (lines) and a source (document) name.

* The ``.append()`` method takes a line and a source name as well.


Parsing directive content as ReST
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Many directives will contain more markup that must be parsed.  To do this, use
one of the following APIs from the :meth:`Directive.run` method:

* ``self.state.nested_parse``
* :func:`sphinx.util.nodes.nested_parse_with_titles` -- this allows titles in
  the parsed content.

Both APIs parse the content into a given node. They are used like this::

   node = docutils.nodes.paragraph()
   # either
   nested_parse_with_titles(self.state, self.result, node)
   # or
   self.state.nested_parse(self.result, 0, node)

.. note::

   ``sphinx.util.docutils.switch_source_input()`` allows to change a target file
   during nested_parse.  It is useful to mixed contents.  For example, ``sphinx.
   ext.autodoc`` uses it to parse docstrings::

       from sphinx.util.docutils import switch_source_input

       # Switch source_input between parsing content.
       # Inside this context, all parsing errors and warnings are reported as
       # happened in new source_input (in this case, ``self.result``).
       with switch_source_input(self.state, self.result):
           node = docutils.nodes.paragraph()
           self.state.nested_parse(self.result, 0, node)

   .. deprecated:: 1.7

      Until Sphinx 1.6, ``sphinx.ext.autodoc.AutodocReporter`` was used for this
      purpose.  It is replaced by ``switch_source_input()``.

If you don't need the wrapping node, you can use any concrete node type and
return ``node.children`` from the Directive.


.. seealso::

   `Creating directives`_ HOWTO of the Docutils documentation

.. _Creating directives: https://docutils.sourceforge.io/docs/howto/rst-directives.html