|
1 # $Id: body.py 4667 2006-07-12 21:40:56Z wiemann $ |
|
2 # Author: David Goodger <goodger@python.org> |
|
3 # Copyright: This module has been placed in the public domain. |
|
4 |
|
5 """ |
|
6 Directives for additional body elements. |
|
7 |
|
8 See `docutils.parsers.rst.directives` for API details. |
|
9 """ |
|
10 |
|
11 __docformat__ = 'reStructuredText' |
|
12 |
|
13 |
|
14 import sys |
|
15 from docutils import nodes |
|
16 from docutils.parsers.rst import Directive |
|
17 from docutils.parsers.rst import directives |
|
18 from docutils.parsers.rst.roles import set_classes |
|
19 |
|
20 |
|
21 class BasePseudoSection(Directive): |
|
22 |
|
23 required_arguments = 1 |
|
24 optional_arguments = 0 |
|
25 final_argument_whitespace = True |
|
26 option_spec = {'class': directives.class_option} |
|
27 has_content = True |
|
28 |
|
29 node_class = None |
|
30 """Node class to be used (must be set in subclasses).""" |
|
31 |
|
32 def run(self): |
|
33 if not (self.state_machine.match_titles |
|
34 or isinstance(self.state_machine.node, nodes.sidebar)): |
|
35 raise self.error('The "%s" directive may not be used within ' |
|
36 'topics or body elements.' % self.name) |
|
37 self.assert_has_content() |
|
38 title_text = self.arguments[0] |
|
39 textnodes, messages = self.state.inline_text(title_text, self.lineno) |
|
40 titles = [nodes.title(title_text, '', *textnodes)] |
|
41 # Sidebar uses this code. |
|
42 if self.options.has_key('subtitle'): |
|
43 textnodes, more_messages = self.state.inline_text( |
|
44 self.options['subtitle'], self.lineno) |
|
45 titles.append(nodes.subtitle(self.options['subtitle'], '', |
|
46 *textnodes)) |
|
47 messages.extend(more_messages) |
|
48 text = '\n'.join(self.content) |
|
49 node = self.node_class(text, *(titles + messages)) |
|
50 node['classes'] += self.options.get('class', []) |
|
51 if text: |
|
52 self.state.nested_parse(self.content, self.content_offset, node) |
|
53 return [node] |
|
54 |
|
55 |
|
56 class Topic(BasePseudoSection): |
|
57 |
|
58 node_class = nodes.topic |
|
59 |
|
60 |
|
61 class Sidebar(BasePseudoSection): |
|
62 |
|
63 node_class = nodes.sidebar |
|
64 |
|
65 option_spec = BasePseudoSection.option_spec.copy() |
|
66 option_spec['subtitle'] = directives.unchanged_required |
|
67 |
|
68 def run(self): |
|
69 if isinstance(self.state_machine.node, nodes.sidebar): |
|
70 raise self.error('The "%s" directive may not be used within a ' |
|
71 'sidebar element.' % self.name) |
|
72 return BasePseudoSection.run(self) |
|
73 |
|
74 |
|
75 class LineBlock(Directive): |
|
76 |
|
77 option_spec = {'class': directives.class_option} |
|
78 has_content = True |
|
79 |
|
80 def run(self): |
|
81 self.assert_has_content() |
|
82 block = nodes.line_block(classes=self.options.get('class', [])) |
|
83 node_list = [block] |
|
84 for line_text in self.content: |
|
85 text_nodes, messages = self.state.inline_text( |
|
86 line_text.strip(), self.lineno + self.content_offset) |
|
87 line = nodes.line(line_text, '', *text_nodes) |
|
88 if line_text.strip(): |
|
89 line.indent = len(line_text) - len(line_text.lstrip()) |
|
90 block += line |
|
91 node_list.extend(messages) |
|
92 self.content_offset += 1 |
|
93 self.state.nest_line_block_lines(block) |
|
94 return node_list |
|
95 |
|
96 |
|
97 class ParsedLiteral(Directive): |
|
98 |
|
99 option_spec = {'class': directives.class_option} |
|
100 has_content = True |
|
101 |
|
102 def run(self): |
|
103 set_classes(self.options) |
|
104 self.assert_has_content() |
|
105 text = '\n'.join(self.content) |
|
106 text_nodes, messages = self.state.inline_text(text, self.lineno) |
|
107 node = nodes.literal_block(text, '', *text_nodes, **self.options) |
|
108 node.line = self.content_offset + 1 |
|
109 return [node] + messages |
|
110 |
|
111 |
|
112 class Rubric(Directive): |
|
113 |
|
114 required_arguments = 1 |
|
115 optional_arguments = 0 |
|
116 final_argument_whitespace = True |
|
117 option_spec = {'class': directives.class_option} |
|
118 |
|
119 def run(self): |
|
120 set_classes(self.options) |
|
121 rubric_text = self.arguments[0] |
|
122 textnodes, messages = self.state.inline_text(rubric_text, self.lineno) |
|
123 rubric = nodes.rubric(rubric_text, '', *textnodes, **self.options) |
|
124 return [rubric] + messages |
|
125 |
|
126 |
|
127 class BlockQuote(Directive): |
|
128 |
|
129 has_content = True |
|
130 classes = [] |
|
131 |
|
132 def run(self): |
|
133 self.assert_has_content() |
|
134 elements = self.state.block_quote(self.content, self.content_offset) |
|
135 for element in elements: |
|
136 if isinstance(element, nodes.block_quote): |
|
137 element['classes'] += self.classes |
|
138 return elements |
|
139 |
|
140 |
|
141 class Epigraph(BlockQuote): |
|
142 |
|
143 classes = ['epigraph'] |
|
144 |
|
145 |
|
146 class Highlights(BlockQuote): |
|
147 |
|
148 classes = ['highlights'] |
|
149 |
|
150 |
|
151 class PullQuote(BlockQuote): |
|
152 |
|
153 classes = ['pull-quote'] |
|
154 |
|
155 |
|
156 class Compound(Directive): |
|
157 |
|
158 option_spec = {'class': directives.class_option} |
|
159 has_content = True |
|
160 |
|
161 def run(self): |
|
162 self.assert_has_content() |
|
163 text = '\n'.join(self.content) |
|
164 node = nodes.compound(text) |
|
165 node['classes'] += self.options.get('class', []) |
|
166 self.state.nested_parse(self.content, self.content_offset, node) |
|
167 return [node] |
|
168 |
|
169 |
|
170 class Container(Directive): |
|
171 |
|
172 required_arguments = 0 |
|
173 optional_arguments = 1 |
|
174 final_argument_whitespace = True |
|
175 has_content = True |
|
176 |
|
177 def run(self): |
|
178 self.assert_has_content() |
|
179 text = '\n'.join(self.content) |
|
180 try: |
|
181 if self.arguments: |
|
182 classes = directives.class_option(self.arguments[0]) |
|
183 else: |
|
184 classes = [] |
|
185 except ValueError: |
|
186 raise self.error( |
|
187 'Invalid class attribute value for "%s" directive: "%s".' |
|
188 % (self.name, self.arguments[0])) |
|
189 node = nodes.container(text) |
|
190 node['classes'].extend(classes) |
|
191 self.state.nested_parse(self.content, self.content_offset, node) |
|
192 return [node] |