parts.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. # $Id: parts.py 8993 2022-01-29 13:20:04Z milde $
  2. # Authors: David Goodger <goodger@python.org>; Dmitry Jemerov
  3. # Copyright: This module has been placed in the public domain.
  4. """
  5. Directives for document parts.
  6. """
  7. __docformat__ = 'reStructuredText'
  8. from docutils import nodes, languages
  9. from docutils.transforms import parts
  10. from docutils.parsers.rst import Directive
  11. from docutils.parsers.rst import directives
  12. class Contents(Directive):
  13. """
  14. Table of contents.
  15. The table of contents is generated in two passes: initial parse and
  16. transform. During the initial parse, a 'pending' element is generated
  17. which acts as a placeholder, storing the TOC title and any options
  18. internally. At a later stage in the processing, the 'pending' element is
  19. replaced by a 'topic' element, a title and the table of contents proper.
  20. """
  21. backlinks_values = ('top', 'entry', 'none')
  22. def backlinks(arg):
  23. value = directives.choice(arg, Contents.backlinks_values)
  24. if value == 'none':
  25. return None
  26. else:
  27. return value
  28. optional_arguments = 1
  29. final_argument_whitespace = True
  30. option_spec = {'depth': directives.nonnegative_int,
  31. 'local': directives.flag,
  32. 'backlinks': backlinks,
  33. 'class': directives.class_option}
  34. def run(self):
  35. if not (self.state_machine.match_titles
  36. or isinstance(self.state_machine.node, nodes.sidebar)):
  37. raise self.error('The "%s" directive may not be used within '
  38. 'topics or body elements.' % self.name)
  39. document = self.state_machine.document
  40. language = languages.get_language(document.settings.language_code,
  41. document.reporter)
  42. if self.arguments:
  43. title_text = self.arguments[0]
  44. text_nodes, messages = self.state.inline_text(title_text,
  45. self.lineno)
  46. title = nodes.title(title_text, '', *text_nodes)
  47. else:
  48. messages = []
  49. if 'local' in self.options:
  50. title = None
  51. else:
  52. title = nodes.title('', language.labels['contents'])
  53. topic = nodes.topic(classes=['contents'])
  54. topic['classes'] += self.options.get('class', [])
  55. # the latex2e writer needs source and line for a warning:
  56. topic.source, topic.line = self.state_machine.get_source_and_line()
  57. topic.line -= 1
  58. if 'local' in self.options:
  59. topic['classes'].append('local')
  60. if title:
  61. name = title.astext()
  62. topic += title
  63. else:
  64. name = language.labels['contents']
  65. name = nodes.fully_normalize_name(name)
  66. if not document.has_name(name):
  67. topic['names'].append(name)
  68. document.note_implicit_target(topic)
  69. pending = nodes.pending(parts.Contents, rawsource=self.block_text)
  70. pending.details.update(self.options)
  71. document.note_pending(pending)
  72. topic += pending
  73. return [topic] + messages
  74. class Sectnum(Directive):
  75. """Automatic section numbering."""
  76. option_spec = {'depth': int,
  77. 'start': int,
  78. 'prefix': directives.unchanged_required,
  79. 'suffix': directives.unchanged_required}
  80. def run(self):
  81. pending = nodes.pending(parts.SectNum)
  82. pending.details.update(self.options)
  83. self.state_machine.document.note_pending(pending)
  84. return [pending]
  85. class Header(Directive):
  86. """Contents of document header."""
  87. has_content = True
  88. def run(self):
  89. self.assert_has_content()
  90. header = self.state_machine.document.get_decoration().get_header()
  91. self.state.nested_parse(self.content, self.content_offset, header)
  92. return []
  93. class Footer(Directive):
  94. """Contents of document footer."""
  95. has_content = True
  96. def run(self):
  97. self.assert_has_content()
  98. footer = self.state_machine.document.get_decoration().get_footer()
  99. self.state.nested_parse(self.content, self.content_offset, footer)
  100. return []