Commit 92c77a7d authored by Christian Heimes's avatar Christian Heimes

Fixed 1349: HEAD doesn't have rest-header-level

Updated docutils including a fix for 1426:  System locale breaks reStructuredText horribly
Added rest-language-code to zope.conf schema. it's used instead of the locales
parent bb67215b
...@@ -93,3 +93,4 @@ class DefaultConfiguration: ...@@ -93,3 +93,4 @@ class DefaultConfiguration:
self.rest_input_encoding = default_enc self.rest_input_encoding = default_enc
self.rest_output_encoding = default_enc self.rest_output_encoding = default_enc
self.rest_header_level = 3 self.rest_header_level = 3
self.rest_language_code = 'en'
...@@ -19,7 +19,7 @@ def trim_doc_string(text): ...@@ -19,7 +19,7 @@ def trim_doc_string(text):
min_indent=indent min_indent=indent
for line in lines[1:]: for line in lines[1:]:
nlines.append(line[min_indent:]) nlines.append(line[min_indent:])
return '\n'.join(nlines, '\n') return '\n'.join(nlines)
......
...@@ -83,6 +83,14 @@ def rest_output_encoding(value): ...@@ -83,6 +83,14 @@ def rest_output_encoding(value):
value and _setenv('REST_OUTPUT_ENCODING' , value) value and _setenv('REST_OUTPUT_ENCODING' , value)
return value return value
def rest_header_level(value):
value and _setenv('REST_DEFAULT_LEVEL' , value)
return value
def rest_language_code(value):
value and _setenv('REST_LANGUAGE_CODE' , value)
return value
# server handlers # server handlers
def root_handler(config): def root_handler(config):
......
...@@ -482,6 +482,25 @@ ...@@ -482,6 +482,25 @@
<metadefault>unset</metadefault> <metadefault>unset</metadefault>
</key> </key>
<key name="rest-header-level" datatype="integer" default="3"
handler="rest_header_level">
<description>
Set the default starting HTML header level for restructured text
documents. The default is 3, which implies that top-level headers
will be created with an H3 HTML tag.
</description>
<metadefault>3</metadefault>
</key>
<key name="rest-language-code" handler="rest_language_code" default="en">
<description>
Language code used for some internal translations inside of the docutils
package and for DTD bibliographic elements mapping. See
lib/python/docutils/languages/ for a list of supported language codes.
</description>
<metadefault>en</metadefault>
</key>
<key name="publisher-profile-file"> <key name="publisher-profile-file">
<description> <description>
Causing this directive to point to a file on the filesystem will Causing this directive to point to a file on the filesystem will
......
...@@ -52,13 +52,11 @@ Subpackages: ...@@ -52,13 +52,11 @@ Subpackages:
__docformat__ = 'reStructuredText' __docformat__ = 'reStructuredText'
__version__ = '0.3.4' __version__ = '0.3.4'
"""``major.minor.micro`` version number. The micro number is bumped """``major.minor.micro`` version number. The micro number is bumped for API
any time there's a change in the API incompatible with one of the changes, for new functionality, and for interim project releases. The minor
front ends or significant new functionality, and at any alpha or beta number is bumped whenever there is a significant project release. The major
release. The minor number is bumped whenever there is a stable number will be bumped when the project is feature-complete, and perhaps if
project release. The major number will be bumped when the project is there is a major change in the design."""
feature-complete, and perhaps if there is a major change in the
design."""
class ApplicationError(StandardError): pass class ApplicationError(StandardError): pass
...@@ -76,22 +74,36 @@ class SettingsSpec: ...@@ -76,22 +74,36 @@ class SettingsSpec:
settings_spec = () settings_spec = ()
"""Runtime settings specification. Override in subclasses. """Runtime settings specification. Override in subclasses.
Specifies runtime settings and associated command-line options, as used by Defines runtime settings and associated command-line options, as used by
`docutils.frontend.OptionParser`. This tuple contains one or more sets of `docutils.frontend.OptionParser`. This is a tuple of:
option group title, description, and a list/tuple of tuples: ``('help
text', [list of option strings], {keyword arguments})``. Group title - Option group title (string or `None` which implies no group, just a list
and/or description may be `None`; a group title of `None` implies no of single options).
group, just a list of single options. The "keyword arguments" dictionary
contains arguments to the OptionParser/OptionGroup ``add_option`` method, - Description (string or `None`).
with the addition of a "validator" keyword (see the
`docutils.frontend.OptionParser.validators` instance attribute). Runtime - A sequence of option tuples. Each consists of:
settings names are derived implicitly from long option names
("--a-setting" becomes ``settings.a_setting``) or explicitly from the - Help text (string)
"dest" keyword argument."""
- List of option strings (e.g. ``['-Q', '--quux']``).
- Dictionary of keyword arguments. It contains arguments to the
OptionParser/OptionGroup ``add_option`` method, possibly with the
addition of a 'validator' keyword (see the
`docutils.frontend.OptionParser.validators` instance attribute). Runtime
settings names are derived implicitly from long option names
('--a-setting' becomes ``settings.a_setting``) or explicitly from the
'dest' keyword argument. See optparse docs for more details.
- More triples of group title, description, options, as many times as
needed. Thus, `settings_spec` tuples can be simply concatenated.
"""
settings_defaults = None settings_defaults = None
"""A dictionary of defaults for internal or inaccessible (by command-line """A dictionary of defaults for settings not in `settings_spec` (internal
or config file) settings. Override in subclasses.""" settings, intended to be inaccessible by command-line and config file).
Override in subclasses."""
settings_default_overrides = None settings_default_overrides = None
"""A dictionary of auxiliary defaults, to override defaults for settings """A dictionary of auxiliary defaults, to override defaults for settings
...@@ -126,14 +138,21 @@ class TransformSpec: ...@@ -126,14 +138,21 @@ class TransformSpec:
"""Transforms required by this class. Override in subclasses.""" """Transforms required by this class. Override in subclasses."""
unknown_reference_resolvers = () unknown_reference_resolvers = ()
"""List of functions to try to resolve unknown references. Called when """List of functions to try to resolve unknown references. Unknown
FinalCheckVisitor is unable to find a correct target. The list should references have a 'refname' attribute which doesn't correspond to any
contain functions which will try to resolve unknown references, with the target in the document. Called when FinalCheckVisitor is unable to find a
following signature:: correct target. The list should contain functions which will try to
resolve unknown references, with the following signature::
def reference_resolver(node): def reference_resolver(node):
'''Returns boolean: true if resolved, false if not.''' '''Returns boolean: true if resolved, false if not.'''
If the function is able to resolve the reference, it should also remove
the 'refname' attribute and mark the node as resolved::
del node['refname']
node.resolved = 1
Each function must have a "priority" attribute which will affect the order Each function must have a "priority" attribute which will affect the order
the unknown_reference_resolvers are run:: the unknown_reference_resolvers are run::
......
This diff is collapsed.
...@@ -43,7 +43,7 @@ from optparse import Values, SUPPRESS_HELP ...@@ -43,7 +43,7 @@ from optparse import Values, SUPPRESS_HELP
def store_multiple(option, opt, value, parser, *args, **kwargs): def store_multiple(option, opt, value, parser, *args, **kwargs):
""" """
Store multiple values in `parser.values`. (Option callback.) Store multiple values in `parser.values`. (Option callback.)
Store `None` for each attribute named in `args`, and store the value for Store `None` for each attribute named in `args`, and store the value for
each key (attribute name) in `kwargs`. each key (attribute name) in `kwargs`.
""" """
...@@ -77,10 +77,10 @@ def validate_encoding_error_handler(setting, value, option_parser, ...@@ -77,10 +77,10 @@ def validate_encoding_error_handler(setting, value, option_parser,
try: try:
codecs.lookup_error(value) codecs.lookup_error(value)
except AttributeError: # prior to Python 2.3 except AttributeError: # prior to Python 2.3
if value not in ('strict', 'ignore', 'replace'): if value not in ('strict', 'ignore', 'replace', 'xmlcharrefreplace'):
raise (LookupError( raise (LookupError(
'unknown encoding error handler: "%s" (choices: ' 'unknown encoding error handler: "%s" (choices: '
'"strict", "ignore", or "replace")' % value), '"strict", "ignore", "replace", or "xmlcharrefreplace")' % value),
None, sys.exc_info()[2]) None, sys.exc_info()[2])
except LookupError: except LookupError:
raise (LookupError( raise (LookupError(
...@@ -143,6 +143,15 @@ def validate_colon_separated_string_list( ...@@ -143,6 +143,15 @@ def validate_colon_separated_string_list(
value.extend(last.split(':')) value.extend(last.split(':'))
return value return value
def validate_url_trailing_slash(
setting, value, option_parser, config_parser=None, config_section=None):
if not value:
return './'
elif value.endswith('/'):
return value
else:
return value + '/'
def make_paths_absolute(pathdict, keys, base_path=None): def make_paths_absolute(pathdict, keys, base_path=None):
""" """
Interpret filesystem path settings relative to the `base_path` given. Interpret filesystem path settings relative to the `base_path` given.
...@@ -311,8 +320,9 @@ class OptionParser(optparse.OptionParser, docutils.SettingsSpec): ...@@ -311,8 +320,9 @@ class OptionParser(optparse.OptionParser, docutils.SettingsSpec):
['--quiet', '-q'], {'action': 'store_const', 'const': 'none', ['--quiet', '-q'], {'action': 'store_const', 'const': 'none',
'dest': 'report_level'}), 'dest': 'report_level'}),
('Set the threshold (<level>) at or above which system messages are ' ('Set the threshold (<level>) at or above which system messages are '
'converted to exceptions, halting execution immediately. Levels ' 'converted to exceptions, halting execution immediately by '
'as in --report. Default is 4 (severe).', 'exiting (or propagating the exception if --traceback set). '
'Levels as in --report. Default is 4 (severe).',
['--halt'], {'choices': threshold_choices, 'dest': 'halt_level', ['--halt'], {'choices': threshold_choices, 'dest': 'halt_level',
'default': 4, 'metavar': '<level>', 'default': 4, 'metavar': '<level>',
'validator': validate_threshold}), 'validator': validate_threshold}),
...@@ -323,9 +333,10 @@ class OptionParser(optparse.OptionParser, docutils.SettingsSpec): ...@@ -323,9 +333,10 @@ class OptionParser(optparse.OptionParser, docutils.SettingsSpec):
'system messages (at or above <level>) were generated. Levels as ' 'system messages (at or above <level>) were generated. Levels as '
'in --report. Default is 5 (disabled). Exit status is the maximum ' 'in --report. Default is 5 (disabled). Exit status is the maximum '
'system message level plus 10 (11 for INFO, etc.).', 'system message level plus 10 (11 for INFO, etc.).',
['--exit'], {'choices': threshold_choices, 'dest': 'exit_level', ['--exit-status'], {'choices': threshold_choices,
'default': 5, 'metavar': '<level>', 'dest': 'exit_status_level',
'validator': validate_threshold}), 'default': 5, 'metavar': '<level>',
'validator': validate_threshold}),
('Report debug-level system messages and generate diagnostic output.', ('Report debug-level system messages and generate diagnostic output.',
['--debug'], {'action': 'store_true', 'validator': validate_boolean}), ['--debug'], {'action': 'store_true', 'validator': validate_boolean}),
('Do not report debug-level system messages or generate diagnostic ' ('Do not report debug-level system messages or generate diagnostic '
...@@ -333,7 +344,9 @@ class OptionParser(optparse.OptionParser, docutils.SettingsSpec): ...@@ -333,7 +344,9 @@ class OptionParser(optparse.OptionParser, docutils.SettingsSpec):
['--no-debug'], {'action': 'store_false', 'dest': 'debug'}), ['--no-debug'], {'action': 'store_false', 'dest': 'debug'}),
('Send the output of system messages (warnings) to <file>.', ('Send the output of system messages (warnings) to <file>.',
['--warnings'], {'dest': 'warning_stream', 'metavar': '<file>'}), ['--warnings'], {'dest': 'warning_stream', 'metavar': '<file>'}),
('Enable Python tracebacks when an error occurs.', ('Enable Python tracebacks when halt-level system messages and '
'other exceptions occur. Useful for debugging, and essential for '
'issue reports.',
['--traceback'], {'action': 'store_true', 'default': None, ['--traceback'], {'action': 'store_true', 'default': None,
'validator': validate_boolean}), 'validator': validate_boolean}),
('Disable Python tracebacks when errors occur; report just the error ' ('Disable Python tracebacks when errors occur; report just the error '
...@@ -343,23 +356,31 @@ class OptionParser(optparse.OptionParser, docutils.SettingsSpec): ...@@ -343,23 +356,31 @@ class OptionParser(optparse.OptionParser, docutils.SettingsSpec):
['--input-encoding', '-i'], ['--input-encoding', '-i'],
{'metavar': '<name>', 'validator': validate_encoding}), {'metavar': '<name>', 'validator': validate_encoding}),
('Specify the text encoding for output. Default is UTF-8. ' ('Specify the text encoding for output. Default is UTF-8. '
'Optionally also specify the encoding error handler for unencodable ' 'Optionally also specify the error handler for unencodable '
'characters (see "--error-encoding"); default is "strict".', 'characters, after a colon (":"); default is "strict". (See '
'"--output-encoding-error-encoding".)',
['--output-encoding', '-o'], ['--output-encoding', '-o'],
{'metavar': '<name[:handler]>', 'default': 'utf-8', {'metavar': '<name[:handler]>', 'default': 'utf-8',
'validator': validate_encoding_and_error_handler}), 'validator': validate_encoding_and_error_handler}),
(SUPPRESS_HELP, # usually handled by --output-encoding ('Specify the error handler for unencodable characters in '
'the output. Acceptable values include "strict", "ignore", '
'"replace", "xmlcharrefreplace", and '
'"backslashreplace" (in Python 2.3+). Default is "strict". '
'Usually specified as part of --output-encoding.',
['--output-encoding-error-handler'], ['--output-encoding-error-handler'],
{'default': 'strict', 'validator': validate_encoding_error_handler}), {'default': 'strict', 'validator': validate_encoding_error_handler}),
('Specify the text encoding for error output. Default is ASCII. ' ('Specify the text encoding for error output. Default is ASCII. '
'Optionally also specify the encoding error handler for unencodable ' 'Optionally also specify the error handler for unencodable '
'characters, after a colon (":"). Acceptable values are the same ' 'characters, after a colon (":"); default is "%s". (See '
'as for the "error" parameter of Python\'s ``encode`` string ' '"--output-encoding-error-encoding".'
'method. Default is "%s".' % default_error_encoding_error_handler, % default_error_encoding_error_handler,
['--error-encoding', '-e'], ['--error-encoding', '-e'],
{'metavar': '<name[:handler]>', 'default': 'ascii', {'metavar': '<name[:handler]>', 'default': 'ascii',
'validator': validate_encoding_and_error_handler}), 'validator': validate_encoding_and_error_handler}),
(SUPPRESS_HELP, # usually handled by --error-encoding ('Specify the error handler for unencodable characters in '
'error output. See --output-encoding-error-handler for acceptable '
'values. Default is "%s". Usually specified as part of '
'--error-encoding.' % default_error_encoding_error_handler,
['--error-encoding-error-handler'], ['--error-encoding-error-handler'],
{'default': default_error_encoding_error_handler, {'default': default_error_encoding_error_handler,
'validator': validate_encoding_error_handler}), 'validator': validate_encoding_error_handler}),
...@@ -386,7 +407,9 @@ class OptionParser(optparse.OptionParser, docutils.SettingsSpec): ...@@ -386,7 +407,9 @@ class OptionParser(optparse.OptionParser, docutils.SettingsSpec):
ends. Setting specs specific to individual Docutils components are also ends. Setting specs specific to individual Docutils components are also
used (see `populate_from_components()`).""" used (see `populate_from_components()`)."""
settings_defaults = {'_disable_config': None} settings_defaults = {'_disable_config': None,
'_source': None,
'_destination': None}
"""Defaults for settings that don't have command-line option equivalents.""" """Defaults for settings that don't have command-line option equivalents."""
relative_path_settings = ('warning_stream',) relative_path_settings = ('warning_stream',)
...@@ -425,16 +448,13 @@ class OptionParser(optparse.OptionParser, docutils.SettingsSpec): ...@@ -425,16 +448,13 @@ class OptionParser(optparse.OptionParser, docutils.SettingsSpec):
self.relative_path_settings = list(self.relative_path_settings) self.relative_path_settings = list(self.relative_path_settings)
self.components = (self,) + tuple(components) self.components = (self,) + tuple(components)
self.populate_from_components(self.components) self.populate_from_components(self.components)
defaults = defaults or {} self.set_defaults(**(defaults or {}))
if read_config_files and not self.defaults['_disable_config']: if read_config_files and not self.defaults['_disable_config']:
try: try:
config_settings = self.get_standard_config_settings() config_settings = self.get_standard_config_settings()
except ValueError, error: except ValueError, error:
self.error(error) self.error(error)
defaults.update(config_settings.__dict__) self.set_defaults(**config_settings.__dict__)
# Internal settings with no defaults from settings specifications;
# initialize manually:
self.set_defaults(_source=None, _destination=None, **defaults)
def populate_from_components(self, components): def populate_from_components(self, components):
""" """
...@@ -446,11 +466,10 @@ class OptionParser(optparse.OptionParser, docutils.SettingsSpec): ...@@ -446,11 +466,10 @@ class OptionParser(optparse.OptionParser, docutils.SettingsSpec):
for component in components: for component in components:
if component is None: if component is None:
continue continue
i = 0
settings_spec = component.settings_spec settings_spec = component.settings_spec
self.relative_path_settings.extend( self.relative_path_settings.extend(
component.relative_path_settings) component.relative_path_settings)
while i < len(settings_spec): for i in range(0, len(settings_spec), 3):
title, description, option_spec = settings_spec[i:i+3] title, description, option_spec = settings_spec[i:i+3]
if title: if title:
group = optparse.OptionGroup(self, title, description) group = optparse.OptionGroup(self, title, description)
...@@ -472,7 +491,6 @@ class OptionParser(optparse.OptionParser, docutils.SettingsSpec): ...@@ -472,7 +491,6 @@ class OptionParser(optparse.OptionParser, docutils.SettingsSpec):
self.lists[option.dest] = 1 self.lists[option.dest] = 1
if component.settings_defaults: if component.settings_defaults:
self.defaults.update(component.settings_defaults) self.defaults.update(component.settings_defaults)
i += 3
for component in components: for component in components:
if component and component.settings_default_overrides: if component and component.settings_default_overrides:
self.defaults.update(component.settings_default_overrides) self.defaults.update(component.settings_default_overrides)
...@@ -552,8 +570,8 @@ class ConfigParser(CP.ConfigParser): ...@@ -552,8 +570,8 @@ class ConfigParser(CP.ConfigParser):
old_warning = """ old_warning = """
The "[option]" section is deprecated. Support for old-format configuration The "[option]" section is deprecated. Support for old-format configuration
files may be removed in a future Docutils release. Please revise your files may be removed in a future Docutils release. Please revise your
configuration files. See <http://docutils.sf.net/docs/config.html>, section configuration files. See <http://docutils.sf.net/docs/user/config.html>,
"Old-Format Configuration Files". section "Old-Format Configuration Files".
""" """
def read(self, filenames, option_parser): def read(self, filenames, option_parser):
......
...@@ -121,13 +121,32 @@ class Output(TransformSpec): ...@@ -121,13 +121,32 @@ class Output(TransformSpec):
% (self.__class__, self.destination, self.destination_path)) % (self.__class__, self.destination, self.destination_path))
def write(self, data): def write(self, data):
"""`data` is a Unicode string, to be encoded by `self.encode`."""
raise NotImplementedError raise NotImplementedError
def encode(self, data): def encode(self, data):
if self.encoding and self.encoding.lower() == 'unicode': if self.encoding and self.encoding.lower() == 'unicode':
return data return data
else: else:
return data.encode(self.encoding, self.error_handler) try:
return data.encode(self.encoding, self.error_handler)
except ValueError:
# ValueError is raised if there are unencodable chars
# in data and the error_handler isn't found.
if self.error_handler == 'xmlcharrefreplace':
# We are using xmlcharrefreplace with a Python
# version that doesn't support it (2.1 or 2.2), so
# we emulate its behavior.
return ''.join([self.xmlcharref_encode(char) for char in data])
else:
raise
def xmlcharref_encode(self, char):
"""Emulate Python 2.3's 'xmlcharrefreplace' encoding error handler."""
try:
return char.encode(self.encoding, 'strict')
except UnicodeError:
return '&#%i;' % ord(char)
class FileInput(Input): class FileInput(Input):
...@@ -172,7 +191,9 @@ class FileInput(Input): ...@@ -172,7 +191,9 @@ class FileInput(Input):
pass pass
def read(self): def read(self):
"""Read and decode a single file and return the data.""" """
Read and decode a single file and return the data (Unicode string).
"""
data = self.source.read() data = self.source.read()
if self.autoclose: if self.autoclose:
self.close() self.close()
......
...@@ -18,6 +18,9 @@ _languages = {} ...@@ -18,6 +18,9 @@ _languages = {}
def get_language(language_code): def get_language(language_code):
if _languages.has_key(language_code): if _languages.has_key(language_code):
return _languages[language_code] return _languages[language_code]
module = __import__(language_code, globals(), locals()) try:
module = __import__(language_code, globals(), locals())
except ImportError:
return None
_languages[language_code] = module _languages[language_code] = module
return module return module
...@@ -20,43 +20,43 @@ labels = { ...@@ -20,43 +20,43 @@ labels = {
# fixed: language-dependent # fixed: language-dependent
'author': u'Autor', 'author': u'Autor',
'authors': u'Autores', 'authors': u'Autores',
'organization': unicode('Organizao', 'latin1'), 'organization': u'Organiza\u00E7\u00E3o',
'address': unicode('Endereo', 'latin1'), 'address': u'Endere\u00E7o',
'contact': u'Contato', 'contact': u'Contato',
'version': unicode('Verso', 'latin1'), 'version': u'Vers\u00E3o',
'revision': unicode('Reviso', 'latin1'), 'revision': u'Revis\u00E3o',
'status': u'Estado', 'status': u'Estado',
'date': u'Data', 'date': u'Data',
'copyright': u'Copyright', 'copyright': u'Copyright',
'dedication': unicode('Dedicatria', 'latin1'), 'dedication': u'Dedicat\u00F3ria',
'abstract': u'Resumo', 'abstract': u'Resumo',
'attention': unicode('Atteno!', 'latin1'), 'attention': u'Atten\u00E7\u00E3o!',
'caution': u'Cuidado!', 'caution': u'Cuidado!',
'danger': u'PERIGO!', 'danger': u'PERIGO!',
'error': u'Erro', 'error': u'Erro',
'hint': unicode('Sugesto', 'latin1'), 'hint': u'Sugest\u00E3o',
'important': u'Importante', 'important': u'Importante',
'note': u'Nota', 'note': u'Nota',
'tip': u'Dica', 'tip': u'Dica',
'warning': u'Aviso', 'warning': u'Aviso',
'contents': unicode('Sumrio', 'latin1')} 'contents': u'Sum\u00E1rio'}
"""Mapping of node class name to label text.""" """Mapping of node class name to label text."""
bibliographic_fields = { bibliographic_fields = {
# language-dependent: fixed # language-dependent: fixed
u'autor': 'author', u'autor': 'author',
u'autores': 'authors', u'autores': 'authors',
unicode('organizao', 'latin1'): 'organization', u'organiza\u00E7\u00E3o': 'organization',
unicode('endereo', 'latin1'): 'address', u'endere\u00E7o': 'address',
u'contato': 'contact', u'contato': 'contact',
unicode('verso', 'latin1'): 'version', u'vers\u00E3o': 'version',
unicode('reviso', 'latin1'): 'revision', u'revis\u00E3o': 'revision',
u'estado': 'status', u'estado': 'status',
u'data': 'date', u'data': 'date',
u'copyright': 'copyright', u'copyright': 'copyright',
unicode('dedicatria', 'latin1'): 'dedication', u'dedicat\u00F3ria': 'dedication',
u'resumo': 'abstract'} u'resumo': 'abstract'}
"""English (lowcased) to canonical name mapping for bibliographic fields.""" """Brazilian Portuguese (lowcased) to canonical name mapping for bibliographic fields."""
author_separators = [';', ','] author_separators = [';', ',']
"""List of separator strings for the 'Authors' bibliographic field. Tried in """List of separator strings for the 'Authors' bibliographic field. Tried in
......
...@@ -18,7 +18,7 @@ is represented by abstract base classes (`Root`, `Structural`, `Body`, ...@@ -18,7 +18,7 @@ is represented by abstract base classes (`Root`, `Structural`, `Body`,
``isinstance(node, base_class)`` to determine the position of the node in the ``isinstance(node, base_class)`` to determine the position of the node in the
hierarchy. hierarchy.
.. _DTD: http://docutils.sourceforge.net/spec/docutils.dtd .. _DTD: http://docutils.sourceforge.net/docs/ref/docutils.dtd
""" """
__docformat__ = 'reStructuredText' __docformat__ = 'reStructuredText'
...@@ -1123,8 +1123,8 @@ class pending(Special, Invisible, PreBibliographic, Element): ...@@ -1123,8 +1123,8 @@ class pending(Special, Invisible, PreBibliographic, Element):
But the "contents" directive can't do its work until the entire document But the "contents" directive can't do its work until the entire document
has been parsed and possibly transformed to some extent. So the directive has been parsed and possibly transformed to some extent. So the directive
code leaves a placeholder behind that will trigger the second phase of the code leaves a placeholder behind that will trigger the second phase of its
its processing, something like this:: processing, something like this::
<pending ...public attributes...> + internal attributes <pending ...public attributes...> + internal attributes
......
...@@ -88,12 +88,21 @@ class Parser(docutils.parsers.Parser): ...@@ -88,12 +88,21 @@ class Parser(docutils.parsers.Parser):
settings_spec = ( settings_spec = (
'reStructuredText Parser Options', 'reStructuredText Parser Options',
None, None,
(('Recognize and link to PEP references (like "PEP 258").', (('Recognize and link to standalone PEP references (like "PEP 258").',
['--pep-references'], ['--pep-references'],
{'action': 'store_true', 'validator': frontend.validate_boolean}), {'action': 'store_true', 'validator': frontend.validate_boolean}),
('Recognize and link to RFC references (like "RFC 822").', ('Base URL for PEP references '
'(default "http://www.python.org/peps/").',
['--pep-base-url'],
{'metavar': '<URL>', 'default': 'http://www.python.org/peps/',
'validator': frontend.validate_url_trailing_slash}),
('Recognize and link to standalone RFC references (like "RFC 822").',
['--rfc-references'], ['--rfc-references'],
{'action': 'store_true', 'validator': frontend.validate_boolean}), {'action': 'store_true', 'validator': frontend.validate_boolean}),
('Base URL for RFC references (default "http://www.faqs.org/rfcs/").',
['--rfc-base-url'],
{'metavar': '<URL>', 'default': 'http://www.faqs.org/rfcs/',
'validator': frontend.validate_url_trailing_slash}),
('Set number of spaces for tab expansion (default 8).', ('Set number of spaces for tab expansion (default 8).',
['--tab-width'], ['--tab-width'],
{'metavar': '<width>', 'type': 'int', 'default': 8}), {'metavar': '<width>', 'type': 'int', 'default': 8}),
......
...@@ -20,11 +20,12 @@ The interface for directive functions is as follows:: ...@@ -20,11 +20,12 @@ The interface for directive functions is as follows::
Parameters: Parameters:
- ``name`` is the directive type or name. - ``name`` is the directive type or name (string).
- ``arguments`` is a list of positional arguments. - ``arguments`` is a list of positional arguments (strings).
- ``options`` is a dictionary mapping option names to values. - ``options`` is a dictionary mapping option names (strings) to values (type
depends on option conversion functions; see below).
- ``content`` is a list of strings, the directive content. - ``content`` is a list of strings, the directive content.
...@@ -63,6 +64,10 @@ directive function): ...@@ -63,6 +64,10 @@ directive function):
options to parse. Several directive option conversion functions are defined options to parse. Several directive option conversion functions are defined
in this module. in this module.
Option conversion functions take a single parameter, the option argument (a
string or ``None``), validate it and/or convert it to the appropriate form.
Conversion functions may raise ``ValueError`` and ``TypeError`` exceptions.
- ``content``: A boolean; true if content is allowed. Client code must handle - ``content``: A boolean; true if content is allowed. Client code must handle
the case where content is required but not supplied (an empty content list the case where content is required but not supplied (an empty content list
will be supplied). will be supplied).
...@@ -74,11 +79,12 @@ empty list). ...@@ -74,11 +79,12 @@ empty list).
See `Creating reStructuredText Directives`_ for more information. See `Creating reStructuredText Directives`_ for more information.
.. _Creating reStructuredText Directives: .. _Creating reStructuredText Directives:
http://docutils.sourceforge.net/spec/howto/rst-directives.html http://docutils.sourceforge.net/docs/howto/rst-directives.html
""" """
__docformat__ = 'reStructuredText' __docformat__ = 'reStructuredText'
import re
from docutils import nodes from docutils import nodes
from docutils.parsers.rst.languages import en as _fallback_language_module from docutils.parsers.rst.languages import en as _fallback_language_module
...@@ -102,8 +108,9 @@ _directive_registry = { ...@@ -102,8 +108,9 @@ _directive_registry = {
'epigraph': ('body', 'epigraph'), 'epigraph': ('body', 'epigraph'),
'highlights': ('body', 'highlights'), 'highlights': ('body', 'highlights'),
'pull-quote': ('body', 'pull_quote'), 'pull-quote': ('body', 'pull_quote'),
'table': ('body', 'table'),
#'questions': ('body', 'question_list'), #'questions': ('body', 'question_list'),
'table': ('tables', 'table'),
'csv-table': ('tables', 'csv_table'),
'image': ('images', 'image'), 'image': ('images', 'image'),
'figure': ('images', 'figure'), 'figure': ('images', 'figure'),
'contents': ('parts', 'contents'), 'contents': ('parts', 'contents'),
...@@ -193,12 +200,12 @@ def directive(directive_name, language_module, document): ...@@ -193,12 +200,12 @@ def directive(directive_name, language_module, document):
return None, messages return None, messages
return function, messages return function, messages
def register_directive(name, directive): def register_directive(name, directive_function):
""" """
Register a nonstandard application-defined directive function. Register a nonstandard application-defined directive function.
Language lookups are not needed for such functions. Language lookups are not needed for such functions.
""" """
_directives[name] = directive _directives[name] = directive_function
def flag(argument): def flag(argument):
""" """
...@@ -278,6 +285,60 @@ def class_option(argument): ...@@ -278,6 +285,60 @@ def class_option(argument):
raise ValueError('cannot make "%s" into a class name' % argument) raise ValueError('cannot make "%s" into a class name' % argument)
return class_name return class_name
unicode_pattern = re.compile(
r'(?:0x|x|\\x|U\+?|\\u)([0-9a-f]+)$|&#x([0-9a-f]+);$', re.IGNORECASE)
def unicode_code(code):
r"""
Convert a Unicode character code to a Unicode character.
Codes may be decimal numbers, hexadecimal numbers (prefixed by ``0x``,
``x``, ``\x``, ``U+``, ``u``, or ``\u``; e.g. ``U+262E``), or XML-style
numeric character entities (e.g. ``&#x262E;``). Other text remains as-is.
"""
try:
if code.isdigit(): # decimal number
return unichr(int(code))
else:
match = unicode_pattern.match(code)
if match: # hex number
value = match.group(1) or match.group(2)
return unichr(int(value, 16))
else: # other text
return code
except OverflowError, detail:
raise ValueError('code too large (%s)' % detail)
def single_char_or_unicode(argument):
char = unicode_code(argument)
if len(char) > 1:
raise ValueError('%r invalid; must be a single character or '
'a Unicode code' % char)
return char
def single_char_or_whitespace_or_unicode(argument):
if argument == 'tab':
char = '\t'
elif argument == 'space':
char = ' '
else:
char = single_char_or_unicode(argument)
return char
def positive_int(argument):
value = int(argument)
if value < 1:
raise ValueError('negative or zero value; must be positive')
return value
def positive_int_list(argument):
if ',' in argument:
entries = argument.split(',')
else:
entries = argument.split()
return [positive_int(entry) for entry in entries]
def format_values(values): def format_values(values):
return '%s, or "%s"' % (', '.join(['"%s"' % s for s in values[:-1]]), return '%s, or "%s"' % (', '.join(['"%s"' % s for s in values[:-1]]),
values[-1]) values[-1])
......
...@@ -15,7 +15,7 @@ import sys ...@@ -15,7 +15,7 @@ import sys
from docutils import nodes from docutils import nodes
from docutils.parsers.rst import directives from docutils.parsers.rst import directives
def topic(name, arguments, options, content, lineno, def topic(name, arguments, options, content, lineno,
content_offset, block_text, state, state_machine, content_offset, block_text, state, state_machine,
node_class=nodes.topic): node_class=nodes.topic):
...@@ -74,6 +74,7 @@ def line_block(name, arguments, options, content, lineno, ...@@ -74,6 +74,7 @@ def line_block(name, arguments, options, content, lineno,
text = '\n'.join(content) text = '\n'.join(content)
text_nodes, messages = state.inline_text(text, lineno) text_nodes, messages = state.inline_text(text, lineno)
node = node_class(text, '', *text_nodes, **options) node = node_class(text, '', *text_nodes, **options)
node.line = content_offset + 1
return [node] + messages return [node] + messages
line_block.options = {'class': directives.class_option} line_block.options = {'class': directives.class_option}
...@@ -121,38 +122,3 @@ def pull_quote(name, arguments, options, content, lineno, ...@@ -121,38 +122,3 @@ def pull_quote(name, arguments, options, content, lineno,
return [block_quote] + messages return [block_quote] + messages
pull_quote.content = 1 pull_quote.content = 1
def table(name, arguments, options, content, lineno,
content_offset, block_text, state, state_machine):
if not content:
warning = state_machine.reporter.warning(
'Content block expected for the "%s" directive; none found.'
% name, nodes.literal_block(block_text, block_text),
line=lineno)
return [warning]
if arguments:
title_text = arguments[0]
text_nodes, messages = state.inline_text(title_text, lineno)
title = nodes.title(title_text, '', *text_nodes)
else:
title = None
node = nodes.Element() # anonymous container for parsing
text = '\n'.join(content)
state.nested_parse(content, content_offset, node)
if len(node) != 1 or not isinstance(node[0], nodes.table):
error = state_machine.reporter.error(
'Error parsing content block for the "%s" directive: '
'exactly one table expected.'
% name, nodes.literal_block(block_text, block_text),
line=lineno)
return [error]
table_node = node[0]
if options.has_key('class'):
table_node.set_class(options['class'])
if title:
table_node.insert(0, title)
return [table_node]
table.arguments = (0, 1, 1)
table.options = {'class': directives.class_option}
table.content = 1
...@@ -28,6 +28,7 @@ def align(argument): ...@@ -28,6 +28,7 @@ def align(argument):
def image(name, arguments, options, content, lineno, def image(name, arguments, options, content, lineno,
content_offset, block_text, state, state_machine): content_offset, block_text, state, state_machine):
messages = []
reference = ''.join(arguments[0].split('\n')) reference = ''.join(arguments[0].split('\n'))
if reference.find(' ') != -1: if reference.find(' ') != -1:
error = state_machine.reporter.error( error = state_machine.reporter.error(
...@@ -35,23 +36,26 @@ def image(name, arguments, options, content, lineno, ...@@ -35,23 +36,26 @@ def image(name, arguments, options, content, lineno,
nodes.literal_block(block_text, block_text), line=lineno) nodes.literal_block(block_text, block_text), line=lineno)
return [error] return [error]
options['uri'] = reference options['uri'] = reference
reference_node = None
if options.has_key('target'): if options.has_key('target'):
block = states.escape2null(options['target']).splitlines() block = states.escape2null(options['target']).splitlines()
block = [line for line in block] block = [line for line in block]
target_type, data = state.parse_target(block, block_text, lineno) target_type, data = state.parse_target(block, block_text, lineno)
if target_type == 'refuri': if target_type == 'refuri':
node_list = nodes.reference(refuri=data) reference_node = nodes.reference(refuri=data)
elif target_type == 'refname': elif target_type == 'refname':
node_list = nodes.reference( reference_node = nodes.reference(
refname=data, name=whitespace_normalize_name(options['target'])) refname=data, name=whitespace_normalize_name(options['target']))
state.document.note_refname(node_list) state.document.note_refname(reference_node)
else: # malformed target else: # malformed target
node_list = [data] # data is a system message messages.append(data) # data is a system message
del options['target'] del options['target']
image_node = nodes.image(block_text, **options)
if reference_node:
reference_node += image_node
return messages + [reference_node]
else: else:
node_list = [] return messages + [image_node]
node_list.append(nodes.image(block_text, **options))
return node_list
image.arguments = (1, 0, 1) image.arguments = (1, 0, 1)
image.options = {'alt': directives.unchanged, image.options = {'alt': directives.unchanged,
......
...@@ -117,7 +117,7 @@ def raw(name, arguments, options, content, lineno, ...@@ -117,7 +117,7 @@ def raw(name, arguments, options, content, lineno,
nodes.literal_block(block_text, block_text), line=lineno) nodes.literal_block(block_text, block_text), line=lineno)
return [severe] return [severe]
text = raw_file.read() text = raw_file.read()
raw_file.close() raw_file.close()
attributes['source'] = options['file'] attributes['source'] = options['file']
else: else:
error = state_machine.reporter.warning( error = state_machine.reporter.warning(
...@@ -185,29 +185,19 @@ def unicode_directive(name, arguments, options, content, lineno, ...@@ -185,29 +185,19 @@ def unicode_directive(name, arguments, options, content, lineno,
element = nodes.Element() element = nodes.Element()
for code in codes: for code in codes:
try: try:
if code.isdigit(): decoded = directives.unicode_code(code)
element += nodes.Text(unichr(int(code))) except ValueError, err:
else:
match = unicode_pattern.match(code)
if match:
value = match.group(1) or match.group(2)
element += nodes.Text(unichr(int(value, 16)))
else:
element += nodes.Text(code)
except (ValueError, OverflowError), err:
error = state_machine.reporter.error( error = state_machine.reporter.error(
'Invalid character code: %s\n%s: %s' 'Invalid character code: %s\n%s: %s'
% (code, err.__class__.__name__, err), % (code, err.__class__.__name__, err),
nodes.literal_block(block_text, block_text), line=lineno) nodes.literal_block(block_text, block_text), line=lineno)
return [error] return [error]
element += nodes.Text(decoded)
return element.children return element.children
unicode_directive.arguments = (1, 0, 1) unicode_directive.arguments = (1, 0, 1)
unicode_pattern = re.compile(
r'(?:0x|x|\\x|U\+?|\\u)([0-9a-f]+)$|&#x([0-9a-f]+);$', re.IGNORECASE)
unicode_comment_pattern = re.compile(r'( |\n|^).. ') unicode_comment_pattern = re.compile(r'( |\n|^).. ')
def class_directive(name, arguments, options, content, lineno, def class_directive(name, arguments, options, content, lineno,
content_offset, block_text, state, state_machine): content_offset, block_text, state, state_machine):
"""""" """"""
...@@ -259,7 +249,7 @@ def role(name, arguments, options, content, lineno, ...@@ -259,7 +249,7 @@ def role(name, arguments, options, content, lineno,
return messages + [error] return messages + [error]
else: else:
base_role = roles.generic_custom_role base_role = roles.generic_custom_role
assert not hasattr(base_role, 'arguments'), ( assert not hasattr(base_role, 'arguments'), (
'Supplemental directive arguments for "%s" directive not supported' 'Supplemental directive arguments for "%s" directive not supported'
'(specified by "%r" role).' % (name, base_role)) '(specified by "%r" role).' % (name, base_role))
try: try:
......
This diff is collapsed.
...@@ -36,10 +36,11 @@ directives = { ...@@ -36,10 +36,11 @@ directives = {
'epigraaf': 'epigraph', 'epigraaf': 'epigraph',
'hoogtepunte': 'highlights', 'hoogtepunte': 'highlights',
'pull-quote (translation required)': 'pull-quote', 'pull-quote (translation required)': 'pull-quote',
'table (translation required)': 'table',
#'vrae': 'questions', #'vrae': 'questions',
#'qa': 'questions', #'qa': 'questions',
#'faq': 'questions', #'faq': 'questions',
'table (translation required)': 'table',
'csv-table (translation required)': 'csv-table',
'meta': 'meta', 'meta': 'meta',
#'beeldkaart': 'imagemap', #'beeldkaart': 'imagemap',
'beeld': 'image', 'beeld': 'image',
......
...@@ -37,10 +37,11 @@ directives = { ...@@ -37,10 +37,11 @@ directives = {
u'moto': 'epigraph', u'moto': 'epigraph',
u'highlights': 'highlights', u'highlights': 'highlights',
u'pull-quote': 'pull-quote', u'pull-quote': 'pull-quote',
u'table (translation required)': 'table',
#'questions': 'questions', #'questions': 'questions',
#'qa': 'questions', #'qa': 'questions',
#'faq': 'questions', #'faq': 'questions',
u'table (translation required)': 'table',
u'csv-table (translation required)': 'csv-table',
u'meta': 'meta', u'meta': 'meta',
#'imagemap': 'imagemap', #'imagemap': 'imagemap',
u'image': 'image', # obrazek u'image': 'image', # obrazek
......
...@@ -37,10 +37,11 @@ directives = { ...@@ -37,10 +37,11 @@ directives = {
'epigraph (translation required)': 'epigraph', 'epigraph (translation required)': 'epigraph',
'highlights (translation required)': 'highlights', 'highlights (translation required)': 'highlights',
'pull-quote (translation required)': 'pull-quote', # kasten too ? 'pull-quote (translation required)': 'pull-quote', # kasten too ?
'table (translation required)': 'table',
#'questions': 'questions', #'questions': 'questions',
#'qa': 'questions', #'qa': 'questions',
#'faq': 'questions', #'faq': 'questions',
'table (translation required)': 'table',
'csv-table (translation required)': 'csv-table',
'meta': 'meta', 'meta': 'meta',
#'imagemap': 'imagemap', #'imagemap': 'imagemap',
'bild': 'image', 'bild': 'image',
......
...@@ -37,8 +37,9 @@ directives = { ...@@ -37,8 +37,9 @@ directives = {
'epigraph': 'epigraph', 'epigraph': 'epigraph',
'highlights': 'highlights', 'highlights': 'highlights',
'pull-quote': 'pull-quote', 'pull-quote': 'pull-quote',
'table': 'table',
#'questions': 'questions', #'questions': 'questions',
'table': 'table',
'csv-table': 'csv-table',
#'qa': 'questions', #'qa': 'questions',
#'faq': 'questions', #'faq': 'questions',
'meta': 'meta', 'meta': 'meta',
......
...@@ -40,10 +40,12 @@ directives = { ...@@ -40,10 +40,12 @@ directives = {
u'elstara\u0135oj': 'highlights', u'elstara\u0135oj': 'highlights',
u'ekstera-citajxo': 'pull-quote', u'ekstera-citajxo': 'pull-quote',
u'ekstera-cita\u0135o': 'pull-quote', u'ekstera-cita\u0135o': 'pull-quote',
u'tabelo': 'table',
#'questions': 'questions', #'questions': 'questions',
#'qa': 'questions', #'qa': 'questions',
#'faq': 'questions', #'faq': 'questions',
u'tabelo': 'table',
u'tabelo-vdk': 'csv-table', # "valoroj disigitaj per komoj"
u'tabelo-csv': 'csv-table',
u'meta': 'meta', u'meta': 'meta',
#'imagemap': 'imagemap', #'imagemap': 'imagemap',
u'bildo': 'image', u'bildo': 'image',
......
...@@ -42,10 +42,12 @@ directives = { ...@@ -42,10 +42,12 @@ directives = {
u'epigrafe': 'epigraph', u'epigrafe': 'epigraph',
u'destacado': 'highlights', u'destacado': 'highlights',
u'cita-destacada': 'pull-quote', u'cita-destacada': 'pull-quote',
u'tabla': 'table',
#'questions': 'questions', #'questions': 'questions',
#'qa': 'questions', #'qa': 'questions',
#'faq': 'questions', #'faq': 'questions',
u'tabla': 'table',
u'tabla-vsc': 'csv-table',
u'tabla-csv': 'csv-table',
u'meta': 'meta', u'meta': 'meta',
#'imagemap': 'imagemap', #'imagemap': 'imagemap',
u'imagen': 'image', u'imagen': 'image',
......
...@@ -38,10 +38,11 @@ directives = { ...@@ -38,10 +38,11 @@ directives = {
u'\u00E9pigraphe': 'epigraph', u'\u00E9pigraphe': 'epigraph',
u'chapeau': 'highlights', u'chapeau': 'highlights',
u'accroche': 'pull-quote', u'accroche': 'pull-quote',
u'tableau': 'table',
#u'questions': 'questions', #u'questions': 'questions',
#u'qr': 'questions', #u'qr': 'questions',
#u'faq': 'questions', #u'faq': 'questions',
u'tableau': 'table',
u'csv-table (translation required)': 'csv-table',
u'm\u00E9ta': 'meta', u'm\u00E9ta': 'meta',
#u'imagemap (translation required)': 'imagemap', #u'imagemap (translation required)': 'imagemap',
u'image': 'image', u'image': 'image',
......
...@@ -31,10 +31,11 @@ directives = { ...@@ -31,10 +31,11 @@ directives = {
'epigrafe': 'epigraph', 'epigrafe': 'epigraph',
'evidenzia': 'highlights', 'evidenzia': 'highlights',
'pull-quote (translation required)': 'pull-quote', 'pull-quote (translation required)': 'pull-quote',
'tabella': 'table',
#'questions': 'questions', #'questions': 'questions',
#'qa': 'questions', #'qa': 'questions',
#'faq': 'questions', #'faq': 'questions',
'tabella': 'table',
'csv-table (translation required)': 'csv-table',
'meta': 'meta', 'meta': 'meta',
#'imagemap': 'imagemap', #'imagemap': 'imagemap',
'immagine': 'image', 'immagine': 'image',
......
...@@ -20,78 +20,79 @@ __docformat__ = 'reStructuredText' ...@@ -20,78 +20,79 @@ __docformat__ = 'reStructuredText'
directives = { directives = {
# language-dependent: fixed # language-dependent: fixed
u'ateno': 'attention', u'aten\u00E7\u00E3o': 'attention',
'cuidado': 'caution', 'cuidado': 'caution',
'perigo': 'danger', 'perigo': 'danger',
'erro': 'error', 'erro': 'error',
u'sugesto': 'hint', u'sugest\u00E3o': 'hint',
'importante': 'important', 'importante': 'important',
'nota': 'note', 'nota': 'note',
'dica': 'tip', 'dica': 'tip',
'aviso': 'warning', 'aviso': 'warning',
u'exortao': 'admonition', u'exorta\u00E7\u00E3o': 'admonition',
'barra-lateral': 'sidebar', 'barra-lateral': 'sidebar',
u'tpico': 'topic', u't\u00F3pico': 'topic',
'bloco-de-linhas': 'line-block', 'bloco-de-linhas': 'line-block',
'literal-interpretado': 'parsed-literal', 'literal-interpretado': 'parsed-literal',
'rubrica': 'rubric', 'rubrica': 'rubric',
u'epgrafo': 'epigraph', u'ep\u00EDgrafo': 'epigraph',
'destaques': 'highlights', 'destaques': 'highlights',
u'citao-destacada': 'pull-quote', u'cita\u00E7\u00E3o-destacada': 'pull-quote',
u'table (translation required)': 'table',
#'perguntas': 'questions', #'perguntas': 'questions',
#'qa': 'questions', #'qa': 'questions',
#'faq': 'questions', #'faq': 'questions',
u'table (translation required)': 'table',
u'csv-table (translation required)': 'csv-table',
'meta': 'meta', 'meta': 'meta',
#'imagemap': 'imagemap', #'imagemap': 'imagemap',
'imagem': 'image', 'imagem': 'image',
'figura': 'figure', 'figura': 'figure',
u'incluso': 'include', u'inclus\u00E3o': 'include',
'cru': 'raw', 'cru': 'raw',
u'substituio': 'replace', u'substitui\u00E7\u00E3o': 'replace',
'unicode': 'unicode', 'unicode': 'unicode',
'classe': 'class', 'classe': 'class',
'role (translation required)': 'role', 'role (translation required)': 'role',
u'ndice': 'contents', u'\u00EDndice': 'contents',
'numsec': 'sectnum', 'numsec': 'sectnum',
u'numerao-de-sees': 'sectnum', u'numera\u00E7\u00E3o-de-se\u00E7\u00F5es': 'sectnum',
#u'notas-de-rorap': 'footnotes', #u'notas-de-rorap\u00E9': 'footnotes',
#u'citaes': 'citations', #u'cita\u00E7\u00F5es': 'citations',
u'links-no-rodap': 'target-notes', u'links-no-rodap\u00E9': 'target-notes',
'restructuredtext-test-directive': 'restructuredtext-test-directive'} 'restructuredtext-test-directive': 'restructuredtext-test-directive'}
"""English name to registered (in directives/__init__.py) directive name """Brazilian Portuguese name to registered (in directives/__init__.py)
mapping.""" directive name mapping."""
roles = { roles = {
# language-dependent: fixed # language-dependent: fixed
u'abbreviao': 'abbreviation', u'abbrevia\u00E7\u00E3o': 'abbreviation',
'ab': 'abbreviation', 'ab': 'abbreviation',
u'acrnimo': 'acronym', u'acr\u00F4nimo': 'acronym',
'ac': 'acronym', 'ac': 'acronym',
u'ndice-remissivo': 'index', u'\u00EDndice-remissivo': 'index',
'i': 'index', 'i': 'index',
'subscrito': 'subscript', 'subscrito': 'subscript',
'sub': 'subscript', 'sub': 'subscript',
'sobrescrito': 'superscript', 'sobrescrito': 'superscript',
'sob': 'superscript', 'sob': 'superscript',
u'referncia-a-ttulo': 'title-reference', u'refer\u00EAncia-a-t\u00EDtulo': 'title-reference',
u'ttulo': 'title-reference', u't\u00EDtulo': 'title-reference',
't': 'title-reference', 't': 'title-reference',
u'referncia-a-pep': 'pep-reference', u'refer\u00EAncia-a-pep': 'pep-reference',
'pep': 'pep-reference', 'pep': 'pep-reference',
u'referncia-a-rfc': 'rfc-reference', u'refer\u00EAncia-a-rfc': 'rfc-reference',
'rfc': 'rfc-reference', 'rfc': 'rfc-reference',
u'nfase': 'emphasis', u'\u00EAnfase': 'emphasis',
'forte': 'strong', 'forte': 'strong',
'literal': 'literal', 'literal': 'literal',
u'referncia-por-nome': 'named-reference', u'refer\u00EAncia-por-nome': 'named-reference',
u'referncia-annima': 'anonymous-reference', u'refer\u00EAncia-an\u00F4nima': 'anonymous-reference',
u'referncia-a-nota-de-rodap': 'footnote-reference', u'refer\u00EAncia-a-nota-de-rodap\u00E9': 'footnote-reference',
u'referncia-a-citao': 'citation-reference', u'refer\u00EAncia-a-cita\u00E7\u00E3o': 'citation-reference',
u'referncia-a-substituio': 'substitution-reference', u'refer\u00EAncia-a-substitui\u00E7\u00E3o': 'substitution-reference',
'alvo': 'target', 'alvo': 'target',
u'referncia-a-uri': 'uri-reference', u'refer\u00EAncia-a-uri': 'uri-reference',
'uri': 'uri-reference', 'uri': 'uri-reference',
'url': 'uri-reference',} 'url': 'uri-reference',}
"""Mapping of English role names to canonical role names for interpreted text. """Mapping of Brazilian Portuguese role names to canonical role names
""" for interpreted text."""
...@@ -24,6 +24,7 @@ directives = { ...@@ -24,6 +24,7 @@ directives = {
u'\u0432\u044b\u0434\u0435\u043b\u0435\u043d\u043d\u0430\u044f-\u0446\u0438\u0442\u0430\u0442\u0430': u'\u0432\u044b\u0434\u0435\u043b\u0435\u043d\u043d\u0430\u044f-\u0446\u0438\u0442\u0430\u0442\u0430':
u'pull-quote', u'pull-quote',
u'table (translation required)': 'table', u'table (translation required)': 'table',
u'csv-table (translation required)': 'csv-table',
u'\u0441\u044b\u0440\u043e\u0439': u'raw', u'\u0441\u044b\u0440\u043e\u0439': u'raw',
u'\u0437\u0430\u043c\u0435\u043d\u0430': u'replace', u'\u0437\u0430\u043c\u0435\u043d\u0430': u'replace',
u'\u0442\u0435\u0441\u0442\u043e\u0432\u0430\u044f-\u0434\u0438\u0440\u0435\u043a\u0442\u0438\u0432\u0430-restructuredtext': u'\u0442\u0435\u0441\u0442\u043e\u0432\u0430\u044f-\u0434\u0438\u0440\u0435\u043a\u0442\u0438\u0432\u0430-restructuredtext':
......
...@@ -36,10 +36,11 @@ directives = { ...@@ -36,10 +36,11 @@ directives = {
u'epigraph (translation required)': 'epigraph', u'epigraph (translation required)': 'epigraph',
u'highlights (translation required)': 'highlights', u'highlights (translation required)': 'highlights',
u'pull-quote (translation required)': 'pull-quote', u'pull-quote (translation required)': 'pull-quote',
u'table (translation required)': 'table',
#u'questions': 'questions', #u'questions': 'questions',
#u'qa': 'questions', #u'qa': 'questions',
#u'faq': 'questions', #u'faq': 'questions',
u'table (translation required)': 'table',
u'csv-table (translation required)': 'csv-table',
u'meta': 'meta', u'meta': 'meta',
#u'imagemap': 'imagemap', #u'imagemap': 'imagemap',
u'obr\xe1zok': 'image', u'obr\xe1zok': 'image',
......
...@@ -35,11 +35,12 @@ directives = { ...@@ -35,11 +35,12 @@ directives = {
u'epigraph (translation required)': 'epigraph', u'epigraph (translation required)': 'epigraph',
u'highlights (translation required)': 'highlights', u'highlights (translation required)': 'highlights',
u'pull-quote (translation required)': 'pull-quote', u'pull-quote (translation required)': 'pull-quote',
u'table (translation required)': 'table',
# u'fr\u00e5gor': 'questions', # u'fr\u00e5gor': 'questions',
# NOTE: A bit long, but recommended by http://www.nada.kth.se/dataterm/: # NOTE: A bit long, but recommended by http://www.nada.kth.se/dataterm/:
# u'fr\u00e5gor-och-svar': 'questions', # u'fr\u00e5gor-och-svar': 'questions',
# u'vanliga-fr\u00e5gor': 'questions', # u'vanliga-fr\u00e5gor': 'questions',
u'table (translation required)': 'table',
u'csv-table (translation required)': 'csv-table',
u'meta': 'meta', u'meta': 'meta',
# u'bildkarta': 'imagemap', # FIXME: Translation might be too literal. # u'bildkarta': 'imagemap', # FIXME: Translation might be too literal.
u'bild': 'image', u'bild': 'image',
......
...@@ -263,7 +263,7 @@ def pep_reference_role(role, rawtext, text, lineno, inliner, ...@@ -263,7 +263,7 @@ def pep_reference_role(role, rawtext, text, lineno, inliner,
prb = inliner.problematic(rawtext, rawtext, msg) prb = inliner.problematic(rawtext, rawtext, msg)
return [prb], [msg] return [prb], [msg]
# Base URL mainly used by inliner.pep_reference; so this is correct: # Base URL mainly used by inliner.pep_reference; so this is correct:
ref = inliner.pep_url % pepnum ref = inliner.document.settings.pep_base_url + inliner.pep_url % pepnum
return [nodes.reference(rawtext, 'PEP ' + text, refuri=ref, **options)], [] return [nodes.reference(rawtext, 'PEP ' + text, refuri=ref, **options)], []
register_canonical_role('pep-reference', pep_reference_role) register_canonical_role('pep-reference', pep_reference_role)
...@@ -281,7 +281,7 @@ def rfc_reference_role(role, rawtext, text, lineno, inliner, ...@@ -281,7 +281,7 @@ def rfc_reference_role(role, rawtext, text, lineno, inliner,
prb = inliner.problematic(rawtext, rawtext, msg) prb = inliner.problematic(rawtext, rawtext, msg)
return [prb], [msg] return [prb], [msg]
# Base URL mainly used by inliner.rfc_reference, so this is correct: # Base URL mainly used by inliner.rfc_reference, so this is correct:
ref = inliner.rfc_url % rfcnum ref = inliner.document.settings.rfc_base_url + inliner.rfc_url % rfcnum
node = nodes.reference(rawtext, 'RFC ' + text, refuri=ref, **options) node = nodes.reference(rawtext, 'RFC ' + text, refuri=ref, **options)
return [node], [] return [node], []
......
...@@ -556,14 +556,19 @@ class Inliner: ...@@ -556,14 +556,19 @@ class Inliner:
# Valid URI characters (see RFC 2396 & RFC 2732); # Valid URI characters (see RFC 2396 & RFC 2732);
# final \x00 allows backslash escapes in URIs: # final \x00 allows backslash escapes in URIs:
uric = r"""[-_.!~*'()[\];/:@&=+$,%a-zA-Z0-9\x00]""" uric = r"""[-_.!~*'()[\];/:@&=+$,%a-zA-Z0-9\x00]"""
# Delimiter indicating the end of a URI (not part of the URI):
uri_end_delim = r"""[>]"""
# Last URI character; same as uric but no punctuation: # Last URI character; same as uric but no punctuation:
urilast = r"""[_~/a-zA-Z0-9]""" urilast = r"""[_~*/=+a-zA-Z0-9]"""
# End of a URI (either 'urilast' or 'uric followed by a
# uri_end_delim'):
uri_end = r"""(?:%(urilast)s|%(uric)s(?=%(uri_end_delim)s))""" % locals()
emailc = r"""[-_!~*'{|}/#?^`&=+$%a-zA-Z0-9\x00]""" emailc = r"""[-_!~*'{|}/#?^`&=+$%a-zA-Z0-9\x00]"""
email_pattern = r""" email_pattern = r"""
%(emailc)s+(?:\.%(emailc)s+)* # name %(emailc)s+(?:\.%(emailc)s+)* # name
@ # at @ # at
%(emailc)s+(?:\.%(emailc)s*)* # host %(emailc)s+(?:\.%(emailc)s*)* # host
%(urilast)s # final URI char %(uri_end)s # final URI char
""" """
parts = ('initial_inline', start_string_prefix, '', parts = ('initial_inline', start_string_prefix, '',
[('start', '', non_whitespace_after, # simple start-strings [('start', '', non_whitespace_after, # simple start-strings
...@@ -642,15 +647,15 @@ class Inliner: ...@@ -642,15 +647,15 @@ class Inliner:
( # either: ( # either:
(//?)? # hierarchical URI (//?)? # hierarchical URI
%(uric)s* # URI characters %(uric)s* # URI characters
%(urilast)s # final URI char %(uri_end)s # final URI char
) )
( # optional query ( # optional query
\?%(uric)s* \?%(uric)s*
%(urilast)s %(uri_end)s
)? )?
( # optional fragment ( # optional fragment
\#%(uric)s* \#%(uric)s*
%(urilast)s %(uri_end)s
)? )?
) )
) )
...@@ -954,9 +959,7 @@ class Inliner: ...@@ -954,9 +959,7 @@ class Inliner:
else: # not a valid scheme else: # not a valid scheme
raise MarkupMismatch raise MarkupMismatch
pep_url_local = 'pep-%04d.html' pep_url = 'pep-%04d.html'
pep_url_absolute = 'http://www.python.org/peps/pep-%04d.html'
pep_url = pep_url_absolute
def pep_reference(self, match, lineno): def pep_reference(self, match, lineno):
text = match.group(0) text = match.group(0)
...@@ -966,17 +969,17 @@ class Inliner: ...@@ -966,17 +969,17 @@ class Inliner:
pepnum = int(match.group('pepnum2')) pepnum = int(match.group('pepnum2'))
else: else:
raise MarkupMismatch raise MarkupMismatch
ref = self.pep_url % pepnum ref = self.document.settings.pep_base_url + self.pep_url % pepnum
unescaped = unescape(text, 0) unescaped = unescape(text, 0)
return [nodes.reference(unescape(text, 1), unescaped, refuri=ref)] return [nodes.reference(unescape(text, 1), unescaped, refuri=ref)]
rfc_url = 'http://www.faqs.org/rfcs/rfc%d.html' rfc_url = 'rfc%d.html'
def rfc_reference(self, match, lineno): def rfc_reference(self, match, lineno):
text = match.group(0) text = match.group(0)
if text.startswith('RFC'): if text.startswith('RFC'):
rfcnum = int(match.group('rfcnum')) rfcnum = int(match.group('rfcnum'))
ref = self.rfc_url % rfcnum ref = self.document.settings.rfc_base_url + self.rfc_url % rfcnum
else: else:
raise MarkupMismatch raise MarkupMismatch
unescaped = unescape(text, 0) unescaped = unescape(text, 0)
...@@ -2542,9 +2545,10 @@ class Text(RSTState): ...@@ -2542,9 +2545,10 @@ class Text(RSTState):
indented.trim_end() indented.trim_end()
if not indented: if not indented:
return self.quoted_literal_block() return self.quoted_literal_block()
nodelist = []
data = '\n'.join(indented) data = '\n'.join(indented)
nodelist.append(nodes.literal_block(data, data)) literal_block = nodes.literal_block(data, data)
literal_block.line = offset + 1
nodelist = [literal_block]
if not blank_finish: if not blank_finish:
nodelist.append(self.unindent_warning('Literal block')) nodelist.append(self.unindent_warning('Literal block'))
return nodelist return nodelist
......
...@@ -16,15 +16,6 @@ from docutils.transforms import peps, references ...@@ -16,15 +16,6 @@ from docutils.transforms import peps, references
from docutils.parsers import rst from docutils.parsers import rst
class Inliner(rst.states.Inliner):
"""
Extend `rst.Inliner` for local PEP references.
"""
pep_url = rst.states.Inliner.pep_url_local
class Reader(standalone.Reader): class Reader(standalone.Reader):
supported = ('pep',) supported = ('pep',)
...@@ -52,7 +43,7 @@ class Reader(standalone.Reader): ...@@ -52,7 +43,7 @@ class Reader(standalone.Reader):
settings_default_overrides = {'pep_references': 1, 'rfc_references': 1} settings_default_overrides = {'pep_references': 1, 'rfc_references': 1}
inliner_class = Inliner inliner_class = rst.states.Inliner
def __init__(self, parser=None, parser_name=None): def __init__(self, parser=None, parser_name=None):
"""`parser` should be ``None``.""" """`parser` should be ``None``."""
......
# Author: David Goodger # Author: David Goodger
# Contact: goodger@users.sourceforge.net # Contact: goodger@users.sourceforge.net
# Revision: $Revision: 1.3.2.1.8.1 $ # Revision: $Revision: 1.7 $
# Date: $Date: 2004/05/12 19:57:53 $ # Date: $Date: 2004/07/25 01:45:26 $
# Copyright: This module has been placed in the public domain. # Copyright: This module has been placed in the public domain.
""" """
This package contains the Python Source Reader modules. This package contains the Python Source Reader modules.
It requires Python 2.2 or higher (`moduleparser` depends on `compiler` and
`tokenizer` modules).
""" """
__docformat__ = 'reStructuredText' __docformat__ = 'reStructuredText'
......
# Author: David Goodger # Author: David Goodger
# Contact: goodger@users.sourceforge.net # Contact: goodger@users.sourceforge.net
# Revision: $Revision: 1.3.2.1.8.1 $ # Revision: $Revision: 1.14 $
# Date: $Date: 2004/05/12 19:57:53 $ # Date: $Date: 2004/07/25 01:45:26 $
# Copyright: This module has been placed in the public domain. # Copyright: This module has been placed in the public domain.
""" """
Parser for Python modules. Parser for Python modules. Requires Python 2.2 or higher.
The `parse_module()` function takes a module's text and file name, The `parse_module()` function takes a module's text and file name,
runs it through the module parser (using compiler.py and tokenize.py) runs it through the module parser (using compiler.py and tokenize.py)
......
...@@ -3,8 +3,8 @@ ...@@ -3,8 +3,8 @@
""" """
:Author: David Goodger :Author: David Goodger
:Contact: goodger@users.sourceforge.net :Contact: goodger@users.sourceforge.net
:Revision: $Revision: 1.1.2.1 $ :Revision: $Revision: 1.3 $
:Date: $Date: 2004/05/12 19:57:53 $ :Date: $Date: 2004/03/23 23:21:11 $
:Copyright: This module has been placed in the public domain. :Copyright: This module has been placed in the public domain.
""" """
......
...@@ -344,6 +344,10 @@ class StateMachine: ...@@ -344,6 +344,10 @@ class StateMachine:
finally: finally:
self.notify_observers() self.notify_observers()
def get_source(self, line_offset):
"""Return source of line at absolute line offset `line_offset`."""
return self.input_lines.source(line_offset - self.input_offset)
def abs_line_offset(self): def abs_line_offset(self):
"""Return line offset of current line, from beginning of file.""" """Return line offset of current line, from beginning of file."""
return self.line_offset + self.input_offset return self.line_offset + self.input_offset
......
...@@ -118,7 +118,9 @@ class Headers(Transform): ...@@ -118,7 +118,9 @@ class Headers(Transform):
for refpep in re.split(',?\s+', body.astext()): for refpep in re.split(',?\s+', body.astext()):
pepno = int(refpep) pepno = int(refpep)
newbody.append(nodes.reference( newbody.append(nodes.reference(
refpep, refpep, refuri=self.pep_url % pepno)) refpep, refpep,
refuri=(self.document.settings.pep_base_url
+ self.pep_url % pepno)))
newbody.append(space) newbody.append(space)
para[:] = newbody[:-1] # drop trailing space para[:] = newbody[:-1] # drop trailing space
elif name == 'last-modified': elif name == 'last-modified':
...@@ -128,7 +130,7 @@ class Headers(Transform): ...@@ -128,7 +130,7 @@ class Headers(Transform):
para[:] = [nodes.reference('', date, refuri=cvs_url)] para[:] = [nodes.reference('', date, refuri=cvs_url)]
elif name == 'content-type': elif name == 'content-type':
pep_type = para.astext() pep_type = para.astext()
uri = self.pep_url % 12 uri = self.document.settings.pep_base_url + self.pep_url % 12
para[:] = [nodes.reference('', pep_type, refuri=uri)] para[:] = [nodes.reference('', pep_type, refuri=uri)]
elif name == 'version' and len(body): elif name == 'version' and len(body):
utils.clean_rcs_keywords(para, self.rcs_keyword_substitutions) utils.clean_rcs_keywords(para, self.rcs_keyword_substitutions)
...@@ -266,7 +268,8 @@ class PEPZeroSpecial(nodes.SparseNodeVisitor): ...@@ -266,7 +268,8 @@ class PEPZeroSpecial(nodes.SparseNodeVisitor):
text = p.astext() text = p.astext()
try: try:
pep = int(text) pep = int(text)
ref = self.pep_url % pep ref = (self.document.settings.pep_base_url
+ self.pep_url % pep)
p[0] = nodes.reference(text, text, refuri=ref) p[0] = nodes.reference(text, text, refuri=ref)
except ValueError: except ValueError:
pass pass
......
...@@ -25,6 +25,9 @@ class SystemMessage(ApplicationError): ...@@ -25,6 +25,9 @@ class SystemMessage(ApplicationError):
self.level = level self.level = level
class SystemMessagePropagation(ApplicationError): pass
class Reporter: class Reporter:
""" """
...@@ -52,7 +55,7 @@ class Reporter: ...@@ -52,7 +55,7 @@ class Reporter:
is compared to the thresholds stored in the category, and a warning or is compared to the thresholds stored in the category, and a warning or
error is generated as appropriate. Debug messages are produced iff the error is generated as appropriate. Debug messages are produced iff the
stored debug switch is on. Message output is sent to the stored warning stored debug switch is on. Message output is sent to the stored warning
stream. stream if not set to ''.
The default category is '' (empty string). By convention, Writers should The default category is '' (empty string). By convention, Writers should
retrieve reporting conditions from the 'writer' category (which, unless retrieve reporting conditions from the 'writer' category (which, unless
...@@ -89,7 +92,8 @@ class Reporter: ...@@ -89,7 +92,8 @@ class Reporter:
exceptions will be raised, halting execution. exceptions will be raised, halting execution.
- `debug`: Show debug (level=0) system messages? - `debug`: Show debug (level=0) system messages?
- `stream`: Where warning output is sent. Can be file-like (has a - `stream`: Where warning output is sent. Can be file-like (has a
``.write`` method), a string (file name, opened for writing), or ``.write`` method), a string (file name, opened for writing),
'' (empty string, for discarding all stream messages) or
`None` (implies `sys.stderr`; default). `None` (implies `sys.stderr`; default).
- `encoding`: The encoding for stderr output. - `encoding`: The encoding for stderr output.
- `error_handler`: The error handler for stderr output encoding. - `error_handler`: The error handler for stderr output encoding.
...@@ -100,7 +104,12 @@ class Reporter: ...@@ -100,7 +104,12 @@ class Reporter:
if stream is None: if stream is None:
stream = sys.stderr stream = sys.stderr
elif type(stream) in (StringType, UnicodeType): elif type(stream) in (StringType, UnicodeType):
raise NotImplementedError('This should open a file for writing.') # Leave stream untouched if it's ''.
if stream != '':
if type(stream) == StringType:
stream = open(stream, 'w')
elif type(stream) == UnicodeType:
stream = open(stream.encode(), 'w')
self.encoding = encoding self.encoding = encoding
"""The character encoding for the stderr output.""" """The character encoding for the stderr output."""
...@@ -175,7 +184,7 @@ class Reporter: ...@@ -175,7 +184,7 @@ class Reporter:
type=self.levels[level], type=self.levels[level],
*children, **attributes) *children, **attributes)
debug, report_level, halt_level, stream = self[category].astuple() debug, report_level, halt_level, stream = self[category].astuple()
if level >= report_level or debug and level == 0: if (level >= report_level or debug and level == 0) and stream:
msgtext = msg.astext().encode(self.encoding, self.error_handler) msgtext = msg.astext().encode(self.encoding, self.error_handler)
if category: if category:
print >>stream, msgtext, '[%s]' % category print >>stream, msgtext, '[%s]' % category
...@@ -265,6 +274,8 @@ def extract_extension_options(field_list, options_spec): ...@@ -265,6 +274,8 @@ def extract_extension_options(field_list, options_spec):
- `KeyError` for unknown option names. - `KeyError` for unknown option names.
- `ValueError` for invalid option values (raised by the conversion - `ValueError` for invalid option values (raised by the conversion
function). function).
- `TypeError` for invalid option value types (raised by conversion
function).
- `DuplicateOptionError` for duplicate options. - `DuplicateOptionError` for duplicate options.
- `BadOptionError` for invalid fields. - `BadOptionError` for invalid fields.
- `BadOptionDataError` for invalid option data (missing name, - `BadOptionDataError` for invalid option data (missing name,
...@@ -321,6 +332,8 @@ def assemble_option_dict(option_list, options_spec): ...@@ -321,6 +332,8 @@ def assemble_option_dict(option_list, options_spec):
- `DuplicateOptionError` for duplicate options. - `DuplicateOptionError` for duplicate options.
- `ValueError` for invalid option values (raised by conversion - `ValueError` for invalid option values (raised by conversion
function). function).
- `TypeError` for invalid option value types (raised by conversion
function).
""" """
options = {} options = {}
for name, value in option_list: for name, value in option_list:
......
...@@ -36,13 +36,15 @@ class Writer(Component): ...@@ -36,13 +36,15 @@ class Writer(Component):
"""The document to write (Docutils doctree); set by `write`.""" """The document to write (Docutils doctree); set by `write`."""
output = None output = None
"""Final translated form of `document`; set by `translate`.""" """Final translated form of `document` (Unicode string);
set by `translate`."""
language = None language = None
"""Language module for the document; set by `write`.""" """Language module for the document; set by `write`."""
destination = None destination = None
"""`docutils.io` IO object; where to write the document. Set by `write`.""" """`docutils.io` Output object; where to write the document.
Set by `write`."""
def __init__(self): def __init__(self):
...@@ -73,8 +75,8 @@ class Writer(Component): ...@@ -73,8 +75,8 @@ class Writer(Component):
def translate(self): def translate(self):
""" """
Do final translation of `self.document` into `self.output`. Do final translation of `self.document` into `self.output` (Unicode
Called from `write`. Override in subclasses. string). Called from `write`. Override in subclasses.
Usually done with a `docutils.nodes.NodeVisitor` subclass, in Usually done with a `docutils.nodes.NodeVisitor` subclass, in
combination with a call to `docutils.nodes.Node.walk()` or combination with a call to `docutils.nodes.Node.walk()` or
......
...@@ -50,7 +50,7 @@ class Writer(writers.Writer): ...@@ -50,7 +50,7 @@ class Writer(writers.Writer):
doctype = ( doctype = (
'<!DOCTYPE document PUBLIC' '<!DOCTYPE document PUBLIC'
' "+//IDN docutils.sourceforge.net//DTD Docutils Generic//EN//XML"' ' "+//IDN docutils.sourceforge.net//DTD Docutils Generic//EN//XML"'
' "http://docutils.sourceforge.net/spec/docutils.dtd">\n') ' "http://docutils.sourceforge.net/docs/ref/docutils.dtd">\n')
generator = '<!-- Generated by Docutils %s -->\n' generator = '<!-- Generated by Docutils %s -->\n'
def translate(self): def translate(self):
......
...@@ -418,7 +418,6 @@ class HTMLTranslator(nodes.NodeVisitor): ...@@ -418,7 +418,6 @@ class HTMLTranslator(nodes.NodeVisitor):
self.body.append(self.starttag(node, 'table', CLASS='citation', self.body.append(self.starttag(node, 'table', CLASS='citation',
frame="void", rules="none")) frame="void", rules="none"))
self.body.append('<colgroup><col class="label" /><col /></colgroup>\n' self.body.append('<colgroup><col class="label" /><col /></colgroup>\n'
'<col />\n'
'<tbody valign="top">\n' '<tbody valign="top">\n'
'<tr>') '<tr>')
self.footnote_backrefs(node) self.footnote_backrefs(node)
...@@ -1143,7 +1142,7 @@ class HTMLTranslator(nodes.NodeVisitor): ...@@ -1143,7 +1142,7 @@ class HTMLTranslator(nodes.NodeVisitor):
self.body.append( self.body.append(
# "border=None" is a boolean attribute; # "border=None" is a boolean attribute;
# it means "standard border", not "no border": # it means "standard border", not "no border":
self.starttag(node, 'table', CLASS="table", border=None)) self.starttag(node, 'table', CLASS="table", border="1"))
def depart_table(self, node): def depart_table(self, node):
self.body.append('</table>\n') self.body.append('</table>\n')
......
This diff is collapsed.
...@@ -15,6 +15,19 @@ ...@@ -15,6 +15,19 @@
This implementation requires docutils 0.3.4+ from http://docutils.sf.net/ This implementation requires docutils 0.3.4+ from http://docutils.sf.net/
""" """
try:
import docutils
except ImportError:
raise ImportError, 'Please install docutils 0.3.3+ from http://docutils.sourceforge.net/#download.'
version = docutils.__version__.split('.')
if version < ['0', '3', '3']:
raise ImportError, """Old version of docutils found:
Got: %(version)s, required: 0.3.3+
Please remove docutils from %(path)s and replace it with a new version. You
can download docutils at http://docutils.sourceforge.net/#download.
""" % {'version' : docutils.__version__, 'path' : docutils.__path__[0] }
import sys, os, locale import sys, os, locale
from App.config import getConfiguration from App.config import getConfiguration
from docutils.core import publish_parts from docutils.core import publish_parts
...@@ -28,10 +41,10 @@ default_input_encoding = getConfiguration().rest_input_encoding or default_enc ...@@ -28,10 +41,10 @@ default_input_encoding = getConfiguration().rest_input_encoding or default_enc
default_level = 3 default_level = 3
initial_header_level = getConfiguration().rest_header_level or default_level initial_header_level = getConfiguration().rest_header_level or default_level
# default language # default language used for internal translations and language mappings for DTD
default_lang = getConfiguration().locale or locale.getdefaultlocale()[0] # elements
if default_lang and '_' in default_lang: default_lang = 'en'
default_lang = default_lang[:default_lang.index('_')] default_language_code = getConfiguration().rest_language_code or default_language
class Warnings: class Warnings:
...@@ -48,7 +61,7 @@ def render(src, ...@@ -48,7 +61,7 @@ def render(src,
stylesheet='default.css', stylesheet='default.css',
input_encoding=default_input_encoding, input_encoding=default_input_encoding,
output_encoding=default_output_encoding, output_encoding=default_output_encoding,
language_code=default_lang, language_code=default_language_code,
initial_header_level = initial_header_level, initial_header_level = initial_header_level,
settings = {}): settings = {}):
"""get the rendered parts of the document the and warning object """get the rendered parts of the document the and warning object
...@@ -60,7 +73,7 @@ def render(src, ...@@ -60,7 +73,7 @@ def render(src,
settings['stylesheet'] = stylesheet settings['stylesheet'] = stylesheet
settings['language_code'] = language_code settings['language_code'] = language_code
# starting level for <H> elements: # starting level for <H> elements:
settings['initial_header_level'] = initial_header_level settings['initial_header_level'] = initial_header_level + 1
# set the reporting level to something sane: # set the reporting level to something sane:
settings['report_level'] = report_level settings['report_level'] = report_level
# don't break if we get errors: # don't break if we get errors:
...@@ -80,7 +93,7 @@ def HTML(src, ...@@ -80,7 +93,7 @@ def HTML(src,
stylesheet='default.css', stylesheet='default.css',
input_encoding=default_input_encoding, input_encoding=default_input_encoding,
output_encoding=default_output_encoding, output_encoding=default_output_encoding,
language_code=default_lang, language_code=default_language_code,
initial_header_level = initial_header_level, initial_header_level = initial_header_level,
warnings = None, warnings = None,
settings = {}): settings = {}):
...@@ -119,17 +132,23 @@ def HTML(src, ...@@ -119,17 +132,23 @@ def HTML(src,
initial_header_level = initial_header_level, initial_header_level = initial_header_level,
settings = settings) settings = settings)
output = ('<h%(level)s class="title">%(title)s</h%(level)s>\n' header = '<h%(level)s class="title">%(title)s</h%(level)s>\n' % {
'%(docinfo)s%(body)s' % {
'level': initial_header_level, 'level': initial_header_level,
'title': parts['title'], 'title': parts['title'],
}
body = '%(docinfo)s%(body)s' % {
'docinfo': parts['docinfo'], 'docinfo': parts['docinfo'],
'body': parts['body'] 'body': parts['body'],
}).encode(output_encoding) }
warnings = ''.join(warning_stream.messages) if parts['title']:
output = header + body
else:
output = body
return output warnings = ''.join(warning_stream.messages)
return output.encode(output_encoding)
__all__ = ("HTML", 'render') __all__ = ("HTML", 'render')
...@@ -335,6 +335,32 @@ instancehome $INSTANCE ...@@ -335,6 +335,32 @@ instancehome $INSTANCE
# #
# rest-output-encoding iso-8859-15 # rest-output-encoding iso-8859-15
# Directive: rest-header-level
#
# Description:
# Set the default starting HTML header level for restructured text
# documents. The default is 3, which implies that top-level headers
# will be created with an <H3> tag.
#
# Default: 3
#
# Example:
#
# rest-header-level 2
# Directive: rest-language-code
#
# Description:
# Language code used for some internal translations inside of the docutils
# package and for DTD bibliographic elements mapping. See
# lib/python/docutils/languages/ for a list of supported language codes.
#
# Default: en
#
# Example:
#
# rest-language-code de
# Directive: cgi-environment # Directive: cgi-environment
# #
# Description: # Description:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment