#! /usr/bin/env python # Copyright 2024 Tomas Brabec # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. try: import locale locale.setlocale(locale.LC_ALL, '') except: pass import docutils.frontend import docutils.utils import docutils.parsers import docutils.parsers.rst import docutils.parsers.rst.directives # this is merely to specifically identify elements derived # from the `my_extension` directive class mydirective(docutils.nodes.Element): pass class MyExtensionDirective(docutils.parsers.rst.Directive): required_arguments = 1; optional_arguments = 0; final_argument_whitespace = True; has_content = True; option_spec = {'my_attr': docutils.parsers.rst.directives.unchanged, } def run(self): self.assert_has_content() text = '\n'.join(self.content) n = mydirective(text, **self.options) self.add_name(n) # this will turn the directive argument into a title node # (as we generally allow the title to contain inline markup, # we use the inline parser to get (`textnodes`) list of inline # elements/nodes) title_text = self.arguments[0] textnodes, messages = self.state.inline_text(title_text, self.lineno) # the following would end up calling TextElement(rawsource,text,*children) constructor title = docutils.nodes.title(title_text, '', *textnodes) title.source, title.line = ( self.state_machine.get_source_and_line(self.lineno)) # add a new sub-node and any system messages from the inline parsing n += title n += messages # This will parse the directive content self.state.nested_parse(self.content, self.content_offset, n) return [n] # This overrides what directive class will be used to process the `my_extension` directive docutils.parsers.rst.directives._directives['my_extension'] = MyExtensionDirective; settings = docutils.frontend.OptionParser().get_default_values() parser_class = docutils.parsers.get_parser_class('restructuredtext') parser = parser_class() option_parser = docutils.frontend.OptionParser( components=(parser,), read_config_files=True, description='') settings = option_parser.parse_args() document = docutils.utils.new_document('', settings) text = ''' My title ======== 1st paragraph Subtitle -------- 2nd paragraph .. my_extension:: This is my extension :my_attr: 1 2 3 4 5 6 1st extension paragraph #. 1st numbered item #. 2nd numbered item 3rd paragraph - a - b ''' parser.parse(text, document) print(document.pformat())