blob: 13fc06c7b09d6a85bcf8fe1f11123e2f83e10163 [file] [log] [blame]
# $Id: body.py 5618 2008-07-28 08:37:32Z strank $
# Author: David Goodger <goodger@python.org>
# 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]