1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
|
# Author: David Goodger
# Contact: goodger@users.sourceforge.net
# Revision: $Revision: 4234 $
# Date: $Date: 2005-12-29 02:14:21 +0100 (Thu, 29 Dec 2005) $
# Copyright: This module has been placed in the public domain.
"""
Directives for figures and simple images.
"""
__docformat__ = 'reStructuredText'
import sys
from docutils import nodes, utils
from docutils.parsers.rst import directives, states
from docutils.nodes import fully_normalize_name, whitespace_normalize_name
from docutils.parsers.rst.roles import set_classes
try:
import Image # PIL
except ImportError:
Image = None
align_h_values = ('left', 'center', 'right')
align_v_values = ('top', 'middle', 'bottom')
align_values = align_v_values + align_h_values
def align(argument):
return directives.choice(argument, align_values)
def image(name, arguments, options, content, lineno,
content_offset, block_text, state, state_machine):
if options.has_key('align'):
# check for align_v values only
if isinstance(state, states.SubstitutionDef):
if options['align'] not in align_v_values:
error = state_machine.reporter.error(
'Error in "%s" directive: "%s" is not a valid value for '
'the "align" option within a substitution definition. '
'Valid values for "align" are: "%s".'
% (name, options['align'], '", "'.join(align_v_values)),
nodes.literal_block(block_text, block_text), line=lineno)
return [error]
elif options['align'] not in align_h_values:
error = state_machine.reporter.error(
'Error in "%s" directive: "%s" is not a valid value for '
'the "align" option. Valid values for "align" are: "%s".'
% (name, options['align'], '", "'.join(align_h_values)),
nodes.literal_block(block_text, block_text), line=lineno)
return [error]
messages = []
reference = directives.uri(arguments[0])
options['uri'] = reference
reference_node = None
if options.has_key('target'):
block = states.escape2null(options['target']).splitlines()
block = [line for line in block]
target_type, data = state.parse_target(block, block_text, lineno)
if target_type == 'refuri':
reference_node = nodes.reference(refuri=data)
elif target_type == 'refname':
reference_node = nodes.reference(
refname=fully_normalize_name(data),
name=whitespace_normalize_name(data))
reference_node.indirect_reference_name = data
state.document.note_refname(reference_node)
else: # malformed target
messages.append(data) # data is a system message
del options['target']
set_classes(options)
image_node = nodes.image(block_text, **options)
if reference_node:
reference_node += image_node
return messages + [reference_node]
else:
return messages + [image_node]
image.arguments = (1, 0, 1)
image.options = {'alt': directives.unchanged,
'height': directives.length_or_unitless,
'width': directives.length_or_percentage_or_unitless,
'scale': directives.nonnegative_int,
'align': align,
'target': directives.unchanged_required,
'class': directives.class_option}
def figure_align(argument):
return directives.choice(argument, align_h_values)
def figure(name, arguments, options, content, lineno,
content_offset, block_text, state, state_machine):
figwidth = options.get('figwidth')
if figwidth:
del options['figwidth']
figclasses = options.get('figclass')
if figclasses:
del options['figclass']
align = options.get('align')
if align:
del options['align']
(image_node,) = image(name, arguments, options, content, lineno,
content_offset, block_text, state, state_machine)
if isinstance(image_node, nodes.system_message):
return [image_node]
figure_node = nodes.figure('', image_node)
if figwidth == 'image':
if Image and state.document.settings.file_insertion_enabled:
# PIL doesn't like Unicode paths:
try:
i = Image.open(str(image_node['uri']))
except (IOError, UnicodeError):
pass
else:
state.document.settings.record_dependencies.add(image_node['uri'])
figure_node['width'] = i.size[0]
elif figwidth is not None:
figure_node['width'] = figwidth
if figclasses:
figure_node['classes'] += figclasses
if align:
figure_node['align'] = align
if content:
node = nodes.Element() # anonymous container for parsing
state.nested_parse(content, content_offset, node)
first_node = node[0]
if isinstance(first_node, nodes.paragraph):
caption = nodes.caption(first_node.rawsource, '',
*first_node.children)
figure_node += caption
elif not (isinstance(first_node, nodes.comment)
and len(first_node) == 0):
error = state_machine.reporter.error(
'Figure caption must be a paragraph or empty comment.',
nodes.literal_block(block_text, block_text), line=lineno)
return [figure_node, error]
if len(node) > 1:
figure_node += nodes.legend('', *node[1:])
return [figure_node]
def figwidth_value(argument):
if argument.lower() == 'image':
return 'image'
else:
return directives.nonnegative_int(argument)
figure.arguments = (1, 0, 1)
figure.options = {'figwidth': figwidth_value,
'figclass': directives.class_option}
figure.options.update(image.options)
figure.options['align'] = figure_align
figure.content = 1
|