# $Id$ # Author: David Goodger # Copyright: This module has been placed in the public domain. """ Directives for additional body elements. See `docutils.parsers.rst.directives` for API details. """ __docformat__ = 'reStructuredText' import sys from docutils import nodes from docutils.parsers.rst import Directive from docutils.parsers.rst import directives from docutils.parsers.rst.roles import set_classes class BasePseudoSection(Directive): required_arguments = 1 optional_arguments = 0 final_argument_whitespace = True option_spec = {'class': directives.class_option} has_content = True node_class = None """Node class to be used (must be set in subclasses).""" def run(self): if not (self.state_machine.match_titles or isinstance(self.state_machine.node, nodes.sidebar)): raise self.error('The "%s" directive may not be used within ' 'topics or body elements.' % self.name) self.assert_has_content() title_text = self.arguments[0] textnodes, messages = self.state.inline_text(title_text, self.lineno) titles = [nodes.title(title_text, '', *textnodes)] # Sidebar uses this code. if 'subtitle' in self.options: textnodes, more_messages = self.state.inline_text( self.options['subtitle'], self.lineno) titles.append(nodes.subtitle(self.options['subtitle'], '', *textnodes)) messages.extend(more_messages) text = '\n'.join(self.content) node = self.node_class(text, *(titles + messages)) node['classes'] += self.options.get('class', []) if text: self.state.nested_parse(self.content, self.content_offset, node) return [node] class Topic(BasePseudoSection): node_class = nodes.topic class Sidebar(BasePseudoSection): node_class = nodes.sidebar option_spec = BasePseudoSection.option_spec.copy() option_spec['subtitle'] = directives.unchanged_required def run(self): if isinstance(self.state_machine.node, nodes.sidebar): raise self.error('The "%s" directive may not be used within a ' 'sidebar element.' % self.name) return BasePseudoSection.run(self) class LineBlock(Directive): option_spec = {'class': directives.class_option} has_content = True def run(self): self.assert_has_content() block = nodes.line_block(classes=self.options.get('class', [])) node_list = [block] for line_text in self.content: text_nodes, messages = self.state.inline_text( line_text.strip(), self.lineno + self.content_offset) line = nodes.line(line_text, '', *text_nodes) if line_text.strip(): line.indent = len(line_text) - len(line_text.lstrip()) block += line node_list.extend(messages) self.content_offset += 1 self.state.nest_line_block_lines(block) return node_list class ParsedLiteral(Directive): option_spec = {'class': directives.class_option} has_content = True def run(self): set_classes(self.options) self.assert_has_content() text = '\n'.join(self.content) text_nodes, messages = self.state.inline_text(text, self.lineno) node = nodes.literal_block(text, '', *text_nodes, **self.options) node.line = self.content_offset + 1 return [node] + messages class Rubric(Directive): required_arguments = 1 optional_arguments = 0 final_argument_whitespace = True option_spec = {'class': directives.class_option} def run(self): set_classes(self.options) rubric_text = self.arguments[0] textnodes, messages = self.state.inline_text(rubric_text, self.lineno) rubric = nodes.rubric(rubric_text, '', *textnodes, **self.options) return [rubric] + messages class BlockQuote(Directive): has_content = True classes = [] def run(self): self.assert_has_content() elements = self.state.block_quote(self.content, self.content_offset) for element in elements: if isinstance(element, nodes.block_quote): element['classes'] += self.classes return elements class Epigraph(BlockQuote): classes = ['epigraph'] class Highlights(BlockQuote): classes = ['highlights'] class PullQuote(BlockQuote): classes = ['pull-quote'] class Compound(Directive): option_spec = {'class': directives.class_option} has_content = True def run(self): self.assert_has_content() text = '\n'.join(self.content) node = nodes.compound(text) node['classes'] += self.options.get('class', []) self.state.nested_parse(self.content, self.content_offset, node) return [node] class Container(Directive): required_arguments = 0 optional_arguments = 1 final_argument_whitespace = True has_content = True def run(self): self.assert_has_content() text = '\n'.join(self.content) try: if self.arguments: classes = directives.class_option(self.arguments[0]) else: classes = [] except ValueError: raise self.error( 'Invalid class attribute value for "%s" directive: "%s".' % (self.name, self.arguments[0])) node = nodes.container(text) node['classes'].extend(classes) self.state.nested_parse(self.content, self.content_offset, node) return [node]