From: <mi...@us...> - 2012-10-11 22:13:41
|
Revision: 7525 http://docutils.svn.sourceforge.net/docutils/?rev=7525&view=rev Author: milde Date: 2012-10-11 22:13:35 +0000 (Thu, 11 Oct 2012) Log Message: ----------- Fix Py3k error writing to stdout with encoding differing from default. Cleanup of the workarounds for Py3k encoding problems. Modified Paths: -------------- trunk/docutils/HISTORY.txt trunk/docutils/docutils/io.py trunk/docutils/test/test_io.py Modified: trunk/docutils/HISTORY.txt =================================================================== --- trunk/docutils/HISTORY.txt 2012-10-03 02:56:55 UTC (rev 7524) +++ trunk/docutils/HISTORY.txt 2012-10-11 22:13:35 UTC (rev 7525) @@ -32,6 +32,7 @@ - FileInput/FileOutput: no system-exit on IOError. The `handle_io_errors` option is ignored and will be removed in a future release. + - Fix Py3k error writing to stdout with encoding differing from default. * docutils/parsers/rst/directives/misc.py Modified: trunk/docutils/docutils/io.py =================================================================== --- trunk/docutils/docutils/io.py 2012-10-03 02:56:55 UTC (rev 7524) +++ trunk/docutils/docutils/io.py 2012-10-11 22:13:35 UTC (rev 7525) @@ -191,7 +191,7 @@ 'a Unicode string') return data if not isinstance(data, unicode): - # Non-unicode (e.g. binary) output. + # Non-unicode (e.g. bytes) output. return data else: return data.encode(self.encoding, self.error_handler) @@ -335,7 +335,7 @@ elif (# destination is file-type object -> check mode: mode and hasattr(self.destination, 'mode') and mode != self.destination.mode): - print >>self._stderr, ('Destination mode "%s" ' + print >>self._stderr, ('Warning: Destination mode "%s" ' 'differs from specified mode "%s"' % (self.destination.mode, mode)) if not destination_path: @@ -343,22 +343,7 @@ self.destination_path = self.destination.name except AttributeError: pass - # Special cases under Python 3: different encoding or binary output - if sys.version_info >= (3,0): - if ('b' in self.mode - and self.destination in (sys.stdout, sys.stderr) - ): - self.destination = self.destination.buffer - if check_encoding(self.destination, self.encoding) is False: - if self.destination in (sys.stdout, sys.stderr): - self.destination = self.destination.buffer - else: # TODO: try the `write to .buffer` scheme instead? - raise ValueError('Encoding of %s (%s) differs \n' - ' from specified encoding (%s)' % - (self.destination_path or 'destination', - destination.encoding, encoding)) - def open(self): # Specify encoding in Python 3. if sys.version_info >= (3,0): @@ -381,17 +366,29 @@ """ if not self.opened: self.open() + if ('b' not in self.mode and sys.version_info < (3,0) + or check_encoding(self.destination, self.encoding) is False + ): + data = self.encode(data) + if sys.version_info >= (3,0) and os.linesep != '\n': + data = data.replace('\n', os.linesep) # fix endings + try: # In Python < 2.5, try...except has to be nested in try...finally. try: - if 'b' not in self.mode and (sys.version_info < (3,0) or - check_encoding(self.destination, self.encoding) is False): - data = self.encode(data) - if sys.version_info >= (3,0) and os.linesep != '\n': - # writing as binary data -> fix endings - data = data.replace('\n', os.linesep) - self.destination.write(data) - + except TypeError, e: + if sys.version_info >= (3,0) and isinstance(data, bytes): + try: + self.destination.buffer.write(data) + except AttributeError: + if check_encoding(self.destination, + self.encoding) is False: + raise ValueError('Encoding of %s (%s) differs \n' + ' from specified encoding (%s)' % + (self.destination_path or 'destination', + self.destination.encoding, self.encoding)) + else: + raise e except (UnicodeError, LookupError), err: raise UnicodeError( 'Unable to encode output data. output-encoding is: ' Modified: trunk/docutils/test/test_io.py =================================================================== --- trunk/docutils/test/test_io.py 2012-10-03 02:56:55 UTC (rev 7524) +++ trunk/docutils/test/test_io.py 2012-10-11 22:13:35 UTC (rev 7525) @@ -162,24 +162,26 @@ # Test for Python 3 features: if sys.version_info >= (3,0): def test_write_bytes_to_stdout(self): - # binary data is written to destination.buffer, if the - # destination is sys.stdout or sys.stdin - backup = sys.stdout - sys.stdout = self.mock_stdout - fo = io.FileOutput(destination=sys.stdout, mode='wb', - autoclose=False) + # try writing data to `destination.buffer`, if data is + # instance of `bytes` and writing to `destination` fails: + fo = io.FileOutput(destination=self.mock_stdout) fo.write(self.bdata) self.assertEqual(self.mock_stdout.buffer.getvalue(), self.bdata) - sys.stdout = backup - def test_encoding_clash(self): - # Raise error, if given and destination encodings differ - # TODO: try the `write to .buffer` scheme instead? - self.assertRaises(ValueError, - io.FileOutput, destination=self.mock_stdout, - encoding='latin1') + def test_encoding_clash_resolved(self): + fo = io.FileOutput(destination=self.mock_stdout, + encoding='latin1', autoclose=False) + fo.write(self.udata) + self.assertEqual(self.mock_stdout.buffer.getvalue(), + self.udata.encode('latin1')) + def test_encoding_clash_nonresolvable(self): + del(self.mock_stdout.buffer) + fo = io.FileOutput(destination=self.mock_stdout, + encoding='latin1', autoclose=False) + self.assertRaises(ValueError, fo.write, self.udata) + if __name__ == '__main__': unittest.main() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mi...@us...> - 2012-10-12 11:54:10
|
Revision: 7526 http://docutils.svn.sourceforge.net/docutils/?rev=7526&view=rev Author: milde Date: 2012-10-12 11:54:01 +0000 (Fri, 12 Oct 2012) Log Message: ----------- New setting validators, code cleanup. (validate_comma_separated_string_list, validate_ternary) Modified Paths: -------------- trunk/docutils/docs/user/config.txt trunk/docutils/docutils/frontend.py trunk/docutils/test/test_settings.py Modified: trunk/docutils/docs/user/config.txt =================================================================== --- trunk/docutils/docs/user/config.txt 2012-10-11 22:13:35 UTC (rev 7525) +++ trunk/docutils/docs/user/config.txt 2012-10-12 11:54:01 UTC (rev 7526) @@ -92,9 +92,12 @@ :On: "true", "yes", "on", "1" :Off: "false", "no", "off", "0", "" (no value) -List values are comma-delimited. Whitespace around list values is -stripped. :: +List values can be comma- or colon-delimited. +strip_classes_, strip_elements_with_classes_, stylesheet_, and +stylesheet_path_ use the comma as delimiter, +whitespace around list values is stripped. :: + strip-classes: ham,eggs, strip-elements-with-classes: sugar, salt, flour stylesheet: html4css1.css, @@ -102,8 +105,8 @@ style with spaces.css stylesheet-path: ../styles/my.css, ../styles/funny.css -expose_internals_ and prune_ use the colon as delimiter and do not strip -whitespace:: +expose_internals_, ignore_ and prune_ use the colon as delimiter and do not +strip whitespace:: expose_internals: b:c:d Modified: trunk/docutils/docutils/frontend.py =================================================================== --- trunk/docutils/docutils/frontend.py 2012-10-11 22:13:35 UTC (rev 7525) +++ trunk/docutils/docutils/frontend.py 2012-10-12 11:54:01 UTC (rev 7526) @@ -18,8 +18,10 @@ * Option callbacks: `store_multiple`, `read_config_file`. * Setting validators: `validate_encoding`, `validate_encoding_error_handler`, - `validate_encoding_and_error_handler`, `validate_boolean`, - `validate_threshold`, `validate_colon_separated_string_list`, + `validate_encoding_and_error_handler`, + `validate_boolean`, `validate_ternary`, `validate_threshold`, + `validate_colon_separated_string_list`, + `validate_comma_separated_string_list`, `validate_dependency_file`. * `make_paths_absolute`. * SettingSpec manipulation: `filter_settings_spec`. @@ -110,14 +112,34 @@ def validate_boolean(setting, value, option_parser, config_parser=None, config_section=None): - if isinstance(value, unicode): - try: - return option_parser.booleans[value.strip().lower()] - except KeyError: - raise (LookupError('unknown boolean value: "%s"' % value), - None, sys.exc_info()[2]) - return value + """Check/normalize boolean settings: + True: '1', 'on', 'yes', 'true' + False: '0', 'off', 'no','false', '' + """ + if isinstance(value, bool): + return value + try: + return option_parser.booleans[value.strip().lower()] + except KeyError: + raise (LookupError('unknown boolean value: "%s"' % value), + None, sys.exc_info()[2]) +def validate_ternary(setting, value, option_parser, + config_parser=None, config_section=None): + """Check/normalize three-value settings: + True: '1', 'on', 'yes', 'true' + False: '0', 'off', 'no','false', + None: any other value (including '') + """ + if isinstance(value, bool) or value is None: + return value + if value == '': + return None + try: + return option_parser.booleans[value.strip().lower()] + except KeyError: + return None + def validate_nonnegative_int(setting, value, option_parser, config_parser=None, config_section=None): value = int(value) @@ -145,6 +167,22 @@ value.extend(last.split(':')) return value +def validate_comma_separated_list(setting, value, option_parser, + config_parser=None, config_section=None): + """Check/normalize list arguments (split at "," and strip whitespace). + """ + # `value` is already a list when given as command line option + # and "action" is "append" + if isinstance(value, unicode): + value = [value] + # this function is called for every option added to `value` + # -> split the last item and apped the result: + last = value.pop() + classes = [cls.strip(u' \t\n') for cls in last.split(',') + if cls.strip(u' \t\n')] + value.extend(classes) + return value + def validate_url_trailing_slash( setting, value, option_parser, config_parser=None, config_section=None): if not value: @@ -163,17 +201,15 @@ def validate_strip_class(setting, value, option_parser, config_parser=None, config_section=None): - # convert to list: - if isinstance(value, unicode): - value = [value] - class_values = filter(None, [v.strip() for v in value.pop().split(',')]) - # validate: - for class_value in class_values: - normalized = docutils.nodes.make_id(class_value) - if class_value != normalized: + # value is a comma separated string list: + value = validate_comma_separated_list(setting, value, option_parser, + config_parser, config_section) + # validate list elements: + for cls in value: + normalized = docutils.nodes.make_id(cls) + if cls != normalized: raise ValueError('invalid class value %r (perhaps %r?)' - % (class_value, normalized)) - value.extend(class_values) + % (cls, normalized)) return value def make_paths_absolute(pathdict, keys, base_path=None): Modified: trunk/docutils/test/test_settings.py =================================================================== --- trunk/docutils/test/test_settings.py 2012-10-11 22:13:35 UTC (rev 7525) +++ trunk/docutils/test/test_settings.py 2012-10-12 11:54:01 UTC (rev 7526) @@ -44,7 +44,7 @@ u'python_home': u'http://www.python.org', u'source_link': 1, 'stylesheet': None, - u'stylesheet_path': fixpath(u'data/stylesheets/pep.css'), + u'stylesheet_path': [fixpath(u'data/stylesheets/pep.css')], 'template': fixpath(u'data/pep-html-template')}, 'one': {u'datestamp': u'%Y-%m-%d %H:%M UTC', u'generator': 1, @@ -54,15 +54,16 @@ 'record_dependencies': utils.DependencyList(), u'source_link': 1, 'stylesheet': None, - u'stylesheet_path': fixpath(u'data/stylesheets/pep.css'), + u'stylesheet_path': [fixpath(u'data/stylesheets/pep.css')], u'tab_width': 8, u'template': fixpath(u'data/pep-html-template'), - u'trim_footnote_reference_space': 1}, + u'trim_footnote_reference_space': 1, + }, 'two': {u'footnote_references': u'superscript', u'generator': 0, 'record_dependencies': utils.DependencyList(), u'stylesheet': None, - u'stylesheet_path': fixpath(u'data/test.css'), + u'stylesheet_path': [fixpath(u'data/test.css')], 'trim_footnote_reference_space': None}, 'list': {u'expose_internals': [u'a', u'b', u'c', u'd', u'e'], u'strip_classes': [u'spam', u'pan', u'fun', u'parrot'], This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <dku...@us...> - 2012-10-13 20:52:21
|
Revision: 7528 http://docutils.svn.sourceforge.net/docutils/?rev=7528&view=rev Author: dkuhlman Date: 2012-10-13 20:52:15 +0000 (Sat, 13 Oct 2012) Log Message: ----------- Fix to config file access and added note on config in documentation Modified Paths: -------------- trunk/docutils/docs/user/odt.txt trunk/docutils/docutils/writers/odf_odt/__init__.py Modified: trunk/docutils/docs/user/odt.txt =================================================================== --- trunk/docutils/docs/user/odt.txt 2012-10-12 12:21:18 UTC (rev 7527) +++ trunk/docutils/docs/user/odt.txt 2012-10-13 20:52:15 UTC (rev 7528) @@ -73,6 +73,21 @@ $ rst2odt.py --source-url=odtwriter.txt --generator --stylesheet=/myconfigs/styles.odt odtwriter.txt odtwriter.odt +Configuration file +------------------ + +The options described below can also be set in a configuration file. +Use section ``[odf_odt writer]`` to set options specific to the +``odtwriter``. For example:: + + [odf_odt writer] + stylesheet: styles1.odt + +See the "Docutils Configuration" document for more information on +Docutils configuration files, including locations which are +searched. + + Command line options -------------------- Modified: trunk/docutils/docutils/writers/odf_odt/__init__.py =================================================================== --- trunk/docutils/docutils/writers/odf_odt/__init__.py 2012-10-12 12:21:18 UTC (rev 7527) +++ trunk/docutils/docutils/writers/odf_odt/__init__.py 2012-10-13 20:52:15 UTC (rev 7528) @@ -21,13 +21,10 @@ import time import re import StringIO -import inspect -import imp import copy import urllib2 import docutils from docutils import frontend, nodes, utils, writers, languages -from docutils.parsers import rst from docutils.readers import standalone from docutils.transforms import references @@ -64,7 +61,8 @@ except ImportError, exp: pygments = None -try: # check for the Python Imaging Library +# check for the Python Imaging Library +try: import PIL.Image except ImportError: try: # sometimes PIL modules are put in PYTHONPATH's root @@ -136,7 +134,7 @@ 'oooc': 'http://openoffice.org/2004/calc', 'ooow': 'http://openoffice.org/2004/writer', 'presentation': 'urn:oasis:names:tc:opendocument:xmlns:presentation:1.0', - + 'script': 'urn:oasis:names:tc:opendocument:xmlns:script:1.0', 'style': 'urn:oasis:names:tc:opendocument:xmlns:style:1.0', 'svg': 'urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0', @@ -534,7 +532,7 @@ 'stylesheet_path', ) - config_section = 'opendocument odf writer' + config_section = 'odf_odt writer' config_section_dependencies = ( 'writers', ) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mi...@us...> - 2012-10-15 12:16:01
|
Revision: 7529 http://docutils.svn.sourceforge.net/docutils/?rev=7529&view=rev Author: milde Date: 2012-10-15 12:15:55 +0000 (Mon, 15 Oct 2012) Log Message: ----------- Add ``math.css`` stylesheet to data files (thanks to Dmitry Shachnev). Modified Paths: -------------- trunk/docutils/HISTORY.txt trunk/docutils/setup.py Modified: trunk/docutils/HISTORY.txt =================================================================== --- trunk/docutils/HISTORY.txt 2012-10-13 20:52:15 UTC (rev 7528) +++ trunk/docutils/HISTORY.txt 2012-10-15 12:15:55 UTC (rev 7529) @@ -38,16 +38,15 @@ - Fix [ 3546533 ] Unicode error with `date` directive. +* docutils/setup.py + + - Add ``math.css`` stylesheet to data files (thanks to Dmitry Shachnev). + * docutils/writers/html4css1/__init__.py - Use ``<code>`` tag for inline "code", do not drop nested inline nodes (syntax highlight tokens). -* docutils/tools/test/test_buildhtml.py - - - Fix [ 3521167 ] allow running in any directory. - - Fix [ 3521168 ] allow running with Python 3. - * docutils/writers/manpage.py - Apply [ 3527401 ] addmonition's don't preserve indentation @@ -66,7 +65,12 @@ - Fix [ 3552403 ] Prevent broken PyXML replacing stdlibs xml module. +* docutils/tools/test/test_buildhtml.py + - Fix [ 3521167 ] allow running in any directory. + - Fix [ 3521168 ] allow running with Python 3. + + Release 0.9.1 (2012-06-17) ========================== Modified: trunk/docutils/setup.py =================================================================== --- trunk/docutils/setup.py 2012-10-13 20:52:15 UTC (rev 7528) +++ trunk/docutils/setup.py 2012-10-15 12:15:55 UTC (rev 7529) @@ -147,6 +147,7 @@ glob.glob('docutils/parsers/rst/include/*.txt')), ('docutils/writers/html4css1', ['docutils/writers/html4css1/html4css1.css', + 'docutils/writers/html4css1/math.css', 'docutils/writers/html4css1/template.txt']), ('docutils/writers/latex2e', ['docutils/writers/latex2e/default.tex', This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mi...@us...> - 2012-10-16 12:40:48
|
Revision: 7530 http://docutils.svn.sourceforge.net/docutils/?rev=7530&view=rev Author: milde Date: 2012-10-16 12:40:36 +0000 (Tue, 16 Oct 2012) Log Message: ----------- Add SmartQuotes transform for typographic quotes and dashes. Modified Paths: -------------- trunk/docutils/COPYING.txt trunk/docutils/FAQ.txt trunk/docutils/HISTORY.txt trunk/docutils/docs/dev/todo.txt trunk/docutils/docs/ref/transforms.txt trunk/docutils/docutils/parsers/rst/__init__.py trunk/docutils/docutils/transforms/universal.py Added Paths: ----------- trunk/docutils/docutils/utils/smartquotes.py trunk/docutils/test/test_transforms/test_smartquotes.py Modified: trunk/docutils/COPYING.txt =================================================================== --- trunk/docutils/COPYING.txt 2012-10-15 12:15:55 UTC (rev 7529) +++ trunk/docutils/COPYING.txt 2012-10-16 12:40:36 UTC (rev 7530) @@ -53,17 +53,17 @@ that have not yet been invented or conceived. (This dedication is derived from the text of the `Creative Commons -Public Domain Dedication -<http://creativecommons.org/licenses/publicdomain>`_. [#]_) +Public Domain Dedication`. [#]_) .. [#] Creative Commons has `retired this legal tool`__ and does not recommend that it be applied to works: This tool is based on United - States law and may not be applicable outside the US. For dedicating - new works to the public domain, Creative Commons recommend CC0_. So - does the Free Software Foundation in its license-list_. + States law and may not be applicable outside the US. For dedicating new + works to the public domain, Creative Commons recommend the replacement + Public Domain Dedication CC0_ (CC zero, "No Rights Reserved"). So does + the Free Software Foundation in its license-list_. __ http://creativecommons.org/retiredlicenses - .. _CC0: http://creativecommons.org/publicdomain/zero/1.0/legalcode + .. _CC0: http://creativecommons.org/about/cc0 Exceptions ========== @@ -76,18 +76,30 @@ <http://www.twinhelix.com>. Free usage permitted as long as this notice remains intact. -* docutils/math/__init__.py, - docutils/math/latex2mathml.py, +* docutils/utils/math/__init__.py, + docutils/utils/math/latex2mathml.py, docutils/writers/xetex/__init__.py, docutils/writers/latex2e/docutils-05-compat.sty, docs/user/docutils-05-compat.sty.txt, - docutils/error_reporting.py: + docutils/utils/error_reporting.py, + docutils/test/transforms/test_smartquotes.py: Copyright © Günter Milde. Released under the terms of the `2-Clause BSD license`_ (`local copy <licenses/BSD-2-Clause.txt>`__). -* docutils/math/math2html.py, +* docutils/utils/smartquotes.py + + Copyright © 2011 Günter Milde, + based on `SmartyPants`_ © 2003 John Gruber + (released under a 3-Clause BSD license included in the file) + and smartypants.py © 2004, 2007 Chad Miller. + Released under the terms of the `2-Clause BSD license`_ + (`local copy <licenses/BSD-2-Clause.txt>`__). + + .. _SmartyPants: http://daringfireball.net/projects/smartypants/ + +* docutils/utils/math/math2html.py, docutils/writers/html4css1/math.css Copyright © Alex Fernández Modified: trunk/docutils/FAQ.txt =================================================================== --- trunk/docutils/FAQ.txt 2012-10-15 12:15:55 UTC (rev 7529) +++ trunk/docutils/FAQ.txt 2012-10-16 12:40:36 UTC (rev 7530) @@ -1223,3 +1223,25 @@ sentence-end-double-space: t fill-column: 70 End: + +.. Here's a code css to make a table colourful:: + + /* Table: */ + + th { + background-color: #ede; + } + + /* alternating colors in table rows */ + table.docutils tr:nth-child(even) { + background-color: #F3F3FF; + } + table.docutils tr:nth-child(odd) { + background-color: #FFFFEE; + } + + table.docutils tr { + border-style: solid none solid none; + border-width: 1px 0 1px 0; + border-color: #AAAAAA; + } Modified: trunk/docutils/HISTORY.txt =================================================================== --- trunk/docutils/HISTORY.txt 2012-10-15 12:15:55 UTC (rev 7529) +++ trunk/docutils/HISTORY.txt 2012-10-16 12:40:36 UTC (rev 7530) @@ -38,9 +38,9 @@ - Fix [ 3546533 ] Unicode error with `date` directive. -* docutils/setup.py +* docutils/transforms/universal.py - - Add ``math.css`` stylesheet to data files (thanks to Dmitry Shachnev). + - Add SmartQuotes transform for typographic quotes and dashes. * docutils/writers/html4css1/__init__.py @@ -65,8 +65,12 @@ - Fix [ 3552403 ] Prevent broken PyXML replacing stdlibs xml module. -* docutils/tools/test/test_buildhtml.py +* setup.py + - Tag ``math.css`` stylesheet as data file (patch by Dmitry Shachnev). + +* tools/test/test_buildhtml.py + - Fix [ 3521167 ] allow running in any directory. - Fix [ 3521168 ] allow running with Python 3. @@ -74,7 +78,7 @@ Release 0.9.1 (2012-06-17) ========================== -* docutils/setup.py +* setup.py - Fix [ 3527842 ]. Under Python 3, converted tests and tools were installed in the PYTHONPATH. Converted tests are now @@ -84,13 +88,13 @@ ``setup.py install`` under Python 3, remove the spurious ``test/`` and ``tools/`` directories in the site library root. -* docutils/test/ +* test/ - Make tests independent from the location of the ``test/`` directory. - Use converted sources (from the ``build/`` directory) for tests under Python 3. -* docutils/tools/ +* tools/ - Make tools compatible with both, Python 2 and 3 without 2to3-conversion. @@ -104,7 +108,7 @@ - Fix [ 3525847 ]. Catch and report UnicodeEncodeError with ``locale == C`` and 8-bit char in path argument of `include` directive. -* docutils/test/alltests.py +* test/alltests.py - class `Tee`: catch UnicodeError when writing to "ascii" stream or file under Python 3. @@ -211,7 +215,7 @@ - Fix [ 3364658 ] (Change last file with Apache license to BSD-2-Clause) and [ 3395920 ] (correct copyright info for rst.el). -* docutils/test/ +* test/ - Apply [ 3303733 ] and [ 3365041 ] to fix tests under Py3k. Modified: trunk/docutils/docs/dev/todo.txt =================================================================== --- trunk/docutils/docs/dev/todo.txt 2012-10-15 12:15:55 UTC (rev 7529) +++ trunk/docutils/docs/dev/todo.txt 2012-10-16 12:40:36 UTC (rev 7530) @@ -1925,13 +1925,15 @@ supports Zotero databases and CSL_ styles with Docutils with an ``xcite`` role. - .. _CSL: http://www.citationstyles.org/ + * `sphinxcontrib-bibtex`_ Sphinx extension with "bibliography" + directive and "cite" role supporting BibTeX databases. - * Automatically insert a "References" heading? .. _CrossTeX: http://www.cs.cornell.edu/people/egs/crosstex/ .. _Pybtex: http://pybtex.sourceforge.net/ +.. _CSL: http://www.citationstyles.org/ +.. _sphinxcontrib-bibtex: http://sphinxcontrib-bibtex.readthedocs.org/ * _`Reference Merging` @@ -2021,25 +2023,7 @@ * _`Index Generation` -* _`Beautify` - Convert quotes and dashes to typographically correct entities. - Sphinx does this with ``smartypants.py``. - - Write a generic version that uses Unicode chars - (let the writer replace these if required). - - Some arguments for "smart quotes" are collected in a `mail to - docutils-user by Jörg W. Mittag from 2006-03-13`__. - - Also see the "... Or Not To Do?" list entry for - `Character Processing`_ - -__ http://article.gmane.org/gmane.text.docutils.user/2765 - -.. _Character Processing: rst/alternatives.html#character-processing - - HTML Writer =========== Modified: trunk/docutils/docs/ref/transforms.txt =================================================================== --- trunk/docutils/docs/ref/transforms.txt 2012-10-15 12:15:55 UTC (rev 7529) +++ trunk/docutils/docs/ref/transforms.txt 2012-10-16 12:40:36 UTC (rev 7530) @@ -11,16 +11,39 @@ .. contents:: +Transforms change the document tree in-place, add to the tree, or prune it. +Transforms resolve references and footnote numbers, process interpreted +text, and do other context-sensitive processing. Each transform is a +subclass of ``docutils.tranforms.Transform``. -For background about transforms and the Transformer object, see `PEP -258`_. +There are `transforms added by components`_, others (e.g. +``parts.Contents``) are added by the parser, if a corresponding directive is +found in the document. +To add a transform, components (objects inheriting from +Docutils.Component like Readers, Parsers, Writers, Input, Output) overwrite +the ``get_transforms()`` method of their base class. After the Reader has +finished processing, the Publisher calls +``Transformer.populate_from_components()`` with a list of components and all +transforms returned by the component's ``get_transforms()`` method are +stored in a `transformer object` attached to the document tree. + + +For more about transforms and the Transformer object, see also `PEP +258`_. (The ``default_transforms()`` attribute of component classes mentioned +there is deprecated. Use the ``get_transforms()`` method instead.) + .. _PEP 258: ../peps/pep-0258.html#transformer Transforms Listed in Priority Order =================================== +Transform classes each have a default_priority attribute which is used by +the Transformer to apply transforms in order (low to high). The default +priority can be overridden when adding transforms to the Transformer object. + + ============================== ============================ ======== Transform: module.Class Added By Priority ============================== ============================ ======== @@ -83,12 +106,14 @@ universal.FilterMessages Writer (w) 870 +universal.SmartQuotes Parser 850 + universal.TestMessages DocutilsTestSupport 880 writer_aux.Compound newlatex2e (w) 910 writer_aux.Admonitions html4css1 (w), 920 - newlatex2e (w) + latex2e (w) misc.CallBack n/a 990 ============================== ============================ ======== @@ -119,3 +144,64 @@ 800 899 very late 900 999 very late (non-standard) ==== ==== ================================================ + + +Transforms added by components +=============================== + + +readers.Reader: + | universal.Decorations, + | universal.ExposeInternals, + | universal.StripComments + +readers.ReReader: + None + +readers.standalone.Reader: + | references.Substitutions, + | references.PropagateTargets, + | frontmatter.DocTitle, + | frontmatter.SectionSubTitle, + | frontmatter.DocInfo, + | references.AnonymousHyperlinks, + | references.IndirectHyperlinks, + | references.Footnotes, + | references.ExternalTargets, + | references.InternalTargets, + | references.DanglingReferences, + | misc.Transitions + +readers.pep.Reader: + | references.Substitutions, + | references.PropagateTargets, + | references.AnonymousHyperlinks, + | references.IndirectHyperlinks, + | references.Footnotes, + | references.ExternalTargets, + | references.InternalTargets, + | references.DanglingReferences, + | misc.Transitions, + | peps.Headers, + | peps.Contents, + | peps.TargetNotes + +parsers.rst.Parser + universal.SmartQuotes + +writers.Writer: + | universal.Messages, + | universal.FilterMessages, + | universal.StripClassesAndElements + +writers.UnfilteredWriter + None + +writers.latex2e.Writer + writer_aux.Admonitions + +writers.html4css1.Writer: + writer_aux.Admonitions + +writers.odf_odt.Writer: + removes references.DanglingReferences Modified: trunk/docutils/docutils/parsers/rst/__init__.py =================================================================== --- trunk/docutils/docutils/parsers/rst/__init__.py 2012-10-15 12:15:55 UTC (rev 7529) +++ trunk/docutils/docutils/parsers/rst/__init__.py 2012-10-16 12:40:36 UTC (rev 7530) @@ -73,7 +73,8 @@ import docutils.parsers import docutils.statemachine from docutils.parsers.rst import states -from docutils import frontend, nodes +from docutils import frontend, nodes, Component +from docutils.transforms import universal class Parser(docutils.parsers.Parser): @@ -136,7 +137,12 @@ '"long", "short", or "none (no parsing)". Default is "short".', ['--syntax-highlight'], {'choices': ['long', 'short', 'none'], - 'default': 'long', 'metavar': '<format>'}),)) + 'default': 'long', 'metavar': '<format>'}), + ('Change straight quotation marks to typographic form: ' + 'one of "yes", "no", "alt[ernative]" (default "no").', + ['--smart-quotes'], + {'default': False, 'validator': frontend.validate_ternary}), + )) config_section = 'restructuredtext parser' config_section_dependencies = ('parsers',) @@ -149,6 +155,10 @@ self.state_classes = states.state_classes self.inliner = inliner + def get_transforms(self): + return Component.get_transforms(self) + [ + universal.SmartQuotes] + def parse(self, inputstring, document): """Parse `inputstring` and populate `document`, a document tree.""" self.setup_parse(inputstring, document) @@ -321,7 +331,7 @@ and the line number added. Preferably use the `debug`, `info`, `warning`, `error`, or `severe` - wrapper methods, e.g. ``self.error(message)`` to generate an + wrapper methods, e.g. ``self.error(message)`` to generate an ERROR-level directive error. """ return DirectiveError(level, message) Modified: trunk/docutils/docutils/transforms/universal.py =================================================================== --- trunk/docutils/docutils/transforms/universal.py 2012-10-15 12:15:55 UTC (rev 7529) +++ trunk/docutils/docutils/transforms/universal.py 2012-10-16 12:40:36 UTC (rev 7530) @@ -19,8 +19,8 @@ import time from docutils import nodes, utils from docutils.transforms import TransformError, Transform +from docutils.utils import smartquotes - class Decorations(Transform): """ @@ -201,3 +201,25 @@ node['classes'].remove(class_value) if class_value in self.strip_elements: return 1 + +class SmartQuotes(Transform): + + """ + Replace ASCII quotation marks with typographic form. + + Also replace multiple dashes with em-dashes and en-dashes. + """ + + default_priority = 850 + + def apply(self): + if self.document.settings.smart_quotes is False: + return + for node in self.document.traverse(nodes.Text): + if isinstance(node.parent, + (nodes.FixedTextElement, nodes.literal)): + # print "literal", node + continue + newtext = smartquotes.smartyPants(node.astext(), attr='2') + node.parent.replace(node, nodes.Text(newtext)) + # print "smartquote", Added: trunk/docutils/docutils/utils/smartquotes.py =================================================================== --- trunk/docutils/docutils/utils/smartquotes.py (rev 0) +++ trunk/docutils/docutils/utils/smartquotes.py 2012-10-16 12:40:36 UTC (rev 7530) @@ -0,0 +1,830 @@ +#!/usr/bin/python +# -*- coding: utf8 -*- + +# :Id: $Id$ +# :Copyright: © 2011 Günter Milde, +# original `SmartyPants`_: © 2003 John Gruber +# smartypants.py: © 2004, 2007 Chad Miller +# :License: Released under the terms of the `2-Clause BSD license`_, in short: +# +# Copying and distribution of this file, with or without modification, +# are permitted in any medium without royalty provided the copyright +# notices and this notice are preserved. +# This file is offered as-is, without any warranty. +# +# .. _2-Clause BSD license: http://www.spdx.org/licenses/BSD-2-Clause + + +r""" +======================== +SmartyPants for Docutils +======================== + +Synopsis +======== + +Smart-quotes for Docutils. + +The original "SmartyPants" is a free web publishing plug-in for Movable Type, +Blosxom, and BBEdit that easily translates plain ASCII punctuation characters +into "smart" typographic punctuation characters. + +`smartypants.py`, endeavours to be a functional port of +SmartyPants to Python, for use with Pyblosxom_. + +`smartquotes.py` is an adaption of Smartypants to Docutils_. By using Unicode +characters instead of HTML entities for typographic quotes, it works for any +output format that supports Unicode. + +Authors +======= + +`John Gruber`_ did all of the hard work of writing this software in Perl for +`Movable Type`_ and almost all of this useful documentation. `Chad Miller`_ +ported it to Python to use with Pyblosxom_. +Adapted to Docutils_ by Günter Milde + +Additional Credits +================== + +Portions of the SmartyPants original work are based on Brad Choate's nifty +MTRegex plug-in. `Brad Choate`_ also contributed a few bits of source code to +this plug-in. Brad Choate is a fine hacker indeed. + +`Jeremy Hedley`_ and `Charles Wiltgen`_ deserve mention for exemplary beta +testing of the original SmartyPants. + +`Rael Dornfest`_ ported SmartyPants to Blosxom. + +.. _Brad Choate: http://bradchoate.com/ +.. _Jeremy Hedley: http://antipixel.com/ +.. _Charles Wiltgen: http://playbacktime.com/ +.. _Rael Dornfest: http://raelity.org/ + + +Copyright and License +===================== + +SmartyPants_ license (3-Clause BSD license): + + Copyright (c) 2003 John Gruber (http://daringfireball.net/) + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + * Neither the name "SmartyPants" nor the names of its contributors + may be used to endorse or promote products derived from this + software without specific prior written permission. + + This software is provided by the copyright holders and contributors + "as is" and any express or implied warranties, including, but not + limited to, the implied warranties of merchantability and fitness for + a particular purpose are disclaimed. In no event shall the copyright + owner or contributors be liable for any direct, indirect, incidental, + special, exemplary, or consequential damages (including, but not + limited to, procurement of substitute goods or services; loss of use, + data, or profits; or business interruption) however caused and on any + theory of liability, whether in contract, strict liability, or tort + (including negligence or otherwise) arising in any way out of the use + of this software, even if advised of the possibility of such damage. + +smartypants.py license (2-Clause BSD license): + + smartypants.py is a derivative work of SmartyPants. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + This software is provided by the copyright holders and contributors + "as is" and any express or implied warranties, including, but not + limited to, the implied warranties of merchantability and fitness for + a particular purpose are disclaimed. In no event shall the copyright + owner or contributors be liable for any direct, indirect, incidental, + special, exemplary, or consequential damages (including, but not + limited to, procurement of substitute goods or services; loss of use, + data, or profits; or business interruption) however caused and on any + theory of liability, whether in contract, strict liability, or tort + (including negligence or otherwise) arising in any way out of the use + of this software, even if advised of the possibility of such damage. + +.. _John Gruber: http://daringfireball.net/ +.. _Chad Miller: http://web.chad.org/ + +.. _Pyblosxom: http://pyblosxom.bluesock.org/ +.. _SmartyPants: http://daringfireball.net/projects/smartypants/ +.. _Movable Type: http://www.movabletype.org/ +.. _2-Clause BSD license: http://www.spdx.org/licenses/BSD-2-Clause +.. _Docutils: http://docutils.sf.net/ + +Description +=========== + +SmartyPants can perform the following transformations: + +- Straight quotes ( " and ' ) into "curly" quote characters +- Backticks-style quotes (\`\`like this'') into "curly" quote characters +- Dashes (``--`` and ``---``) into en- and em-dash entities +- Three consecutive dots (``...`` or ``. . .``) into an ellipsis entity + +This means you can write, edit, and save your posts using plain old +ASCII straight quotes, plain dashes, and plain dots, but your published +posts (and final HTML output) will appear with smart quotes, em-dashes, +and proper ellipses. + +SmartyPants does not modify characters within ``<pre>``, ``<code>``, ``<kbd>``, +``<math>`` or ``<script>`` tag blocks. Typically, these tags are used to +display text where smart quotes and other "smart punctuation" would not be +appropriate, such as source code or example markup. + + +Backslash Escapes +================= + +If you need to use literal straight quotes (or plain hyphens and +periods), SmartyPants accepts the following backslash escape sequences +to force non-smart punctuation. It does so by transforming the escape +sequence into a character: + +======== ===== ========= +Escape Value Character +======== ===== ========= +``\\\\`` \ \\ +\\" " " +\\' ' ' +\\. . . +\\- - \- +\\` ` \` +======== ===== ========= + +This is useful, for example, when you want to use straight quotes as +foot and inch marks: 6'2" tall; a 17" iMac. + +Options +======= + +For Pyblosxom users, the ``smartypants_attributes`` attribute is where you +specify configuration options. + +Numeric values are the easiest way to configure SmartyPants' behavior: + +"0" + Suppress all transformations. (Do nothing.) +"1" + Performs default SmartyPants transformations: quotes (including + \`\`backticks'' -style), em-dashes, and ellipses. "``--``" (dash dash) + is used to signify an em-dash; there is no support for en-dashes. + +"2" + Same as smarty_pants="1", except that it uses the old-school typewriter + shorthand for dashes: "``--``" (dash dash) for en-dashes, "``---``" + (dash dash dash) + for em-dashes. + +"3" + Same as smarty_pants="2", but inverts the shorthand for dashes: + "``--``" (dash dash) for em-dashes, and "``---``" (dash dash dash) for + en-dashes. + +"-1" + Stupefy mode. Reverses the SmartyPants transformation process, turning + the characters produced by SmartyPants into their ASCII equivalents. + E.g. "“" is turned into a simple double-quote ("), "—" is + turned into two dashes, etc. + + +The following single-character attribute values can be combined to toggle +individual transformations from within the smarty_pants attribute. For +example, to educate normal quotes and em-dashes, but not ellipses or +\`\`backticks'' -style quotes: + +``py['smartypants_attributes'] = "1"`` + +"q" + Educates normal quote characters: (") and ('). + +"b" + Educates \`\`backticks'' -style double quotes. + +"B" + Educates \`\`backticks'' -style double quotes and \`single' quotes. + +"d" + Educates em-dashes. + +"D" + Educates em-dashes and en-dashes, using old-school typewriter shorthand: + (dash dash) for en-dashes, (dash dash dash) for em-dashes. + +"i" + Educates em-dashes and en-dashes, using inverted old-school typewriter + shorthand: (dash dash) for em-dashes, (dash dash dash) for en-dashes. + +"e" + Educates ellipses. + +"w" + Translates any instance of ``"`` into a normal double-quote character. + This should be of no interest to most people, but of particular interest + to anyone who writes their posts using Dreamweaver, as Dreamweaver + inexplicably uses this entity to represent a literal double-quote + character. SmartyPants only educates normal quotes, not entities (because + ordinarily, entities are used for the explicit purpose of representing the + specific character they represent). The "w" option must be used in + conjunction with one (or both) of the other quote options ("q" or "b"). + Thus, if you wish to apply all SmartyPants transformations (quotes, en- + and em-dashes, and ellipses) and also translate ``"`` entities into + regular quotes so SmartyPants can educate them, you should pass the + following to the smarty_pants attribute: + + +Caveats +======= + +Why You Might Not Want to Use Smart Quotes in Your Weblog +--------------------------------------------------------- + +For one thing, you might not care. + +Most normal, mentally stable individuals do not take notice of proper +typographic punctuation. Many design and typography nerds, however, break +out in a nasty rash when they encounter, say, a restaurant sign that uses +a straight apostrophe to spell "Joe's". + +If you're the sort of person who just doesn't care, you might well want to +continue not caring. Using straight quotes -- and sticking to the 7-bit +ASCII character set in general -- is certainly a simpler way to live. + +Even if you I *do* care about accurate typography, you still might want to +think twice before educating the quote characters in your weblog. One side +effect of publishing curly quote characters is that it makes your +weblog a bit harder for others to quote from using copy-and-paste. What +happens is that when someone copies text from your blog, the copied text +contains the 8-bit curly quote characters (as well as the 8-bit characters +for em-dashes and ellipses, if you use these options). These characters +are not standard across different text encoding methods, which is why they +need to be encoded as characters. + +People copying text from your weblog, however, may not notice that you're +using curly quotes, and they'll go ahead and paste the unencoded 8-bit +characters copied from their browser into an email message or their own +weblog. When pasted as raw "smart quotes", these characters are likely to +get mangled beyond recognition. + +That said, my own opinion is that any decent text editor or email client +makes it easy to stupefy smart quote characters into their 7-bit +equivalents, and I don't consider it my problem if you're using an +indecent text editor or email client. + + +Algorithmic Shortcomings +------------------------ + +One situation in which quotes will get curled the wrong way is when +apostrophes are used at the start of leading contractions. For example: + +``'Twas the night before Christmas.`` + +In the case above, SmartyPants will turn the apostrophe into an opening +single-quote, when in fact it should be a closing one. I don't think +this problem can be solved in the general case -- every word processor +I've tried gets this wrong as well. In such cases, it's best to use the +proper character for closing single-quotes (``’``) by hand. + + +Version History +=============== + +1.6: 2010-08-26 + - Adaption to Docutils: + - Use Unicode instead of HTML entities, + - Remove code special to pyblosxom. + +1.5_1.6: Fri, 27 Jul 2007 07:06:40 -0400 + - Fixed bug where blocks of precious unalterable text was instead + interpreted. Thanks to Le Roux and Dirk van Oosterbosch. + +1.5_1.5: Sat, 13 Aug 2005 15:50:24 -0400 + - Fix bogus magical quotation when there is no hint that the + user wants it, e.g., in "21st century". Thanks to Nathan Hamblen. + - Be smarter about quotes before terminating numbers in an en-dash'ed + range. + +1.5_1.4: Thu, 10 Feb 2005 20:24:36 -0500 + - Fix a date-processing bug, as reported by jacob childress. + - Begin a test-suite for ensuring correct output. + - Removed import of "string", since I didn't really need it. + (This was my first every Python program. Sue me!) + +1.5_1.3: Wed, 15 Sep 2004 18:25:58 -0400 + - Abort processing if the flavour is in forbidden-list. Default of + [ "rss" ] (Idea of Wolfgang SCHNERRING.) + - Remove stray virgules from en-dashes. Patch by Wolfgang SCHNERRING. + +1.5_1.2: Mon, 24 May 2004 08:14:54 -0400 + - Some single quotes weren't replaced properly. Diff-tesuji played + by Benjamin GEIGER. + +1.5_1.1: Sun, 14 Mar 2004 14:38:28 -0500 + - Support upcoming pyblosxom 0.9 plugin verification feature. + +1.5_1.0: Tue, 09 Mar 2004 08:08:35 -0500 + - Initial release +""" + +default_smartypants_attr = "1" + +import re + +class smart(object): + """Smart quotes and dashes + + TODO: internationalization, see e.g. + http://de.wikipedia.org/wiki/Anf%C3%BChrungszeichen#Andere_Sprachen + """ + endash = u'–' # "–" EN DASH + emdash = u'—' # "—" EM DASH + lquote = u'‘' # "‘" LEFT SINGLE QUOTATION MARK + rquote = u'’' # "’" RIGHT SINGLE QUOTATION MARK + #lquote = u'‚' # "‚" SINGLE LOW-9 QUOTATION MARK (German) + ldquote = u'“' # "“" LEFT DOUBLE QUOTATION MARK + rdquote = u'”' # "”" RIGHT DOUBLE QUOTATION MARK + #ldquote = u'„' # "𔄤" DOUBLE LOW-9 QUOTATION MARK (German) + ellipsis = u'…' # "…" HORIZONTAL ELLIPSIS + +def smartyPants(text, attr=default_smartypants_attr): + convert_quot = False # translate " entities into normal quotes? + + # Parse attributes: + # 0 : do nothing + # 1 : set all + # 2 : set all, using old school en- and em- dash shortcuts + # 3 : set all, using inverted old school en and em- dash shortcuts + # + # q : quotes + # b : backtick quotes (``double'' only) + # B : backtick quotes (``double'' and `single') + # d : dashes + # D : old school dashes + # i : inverted old school dashes + # e : ellipses + # w : convert " entities to " for Dreamweaver users + + skipped_tag_stack = [] + do_dashes = "0" + do_backticks = "0" + do_quotes = "0" + do_ellipses = "0" + do_stupefy = "0" + + if attr == "0": + # Do nothing. + return text + elif attr == "1": + do_quotes = "1" + do_backticks = "1" + do_dashes = "1" + do_ellipses = "1" + elif attr == "2": + # Do everything, turn all options on, use old school dash shorthand. + do_quotes = "1" + do_backticks = "1" + do_dashes = "2" + do_ellipses = "1" + elif attr == "3": + # Do everything, turn all options on, use inverted old school dash shorthand. + do_quotes = "1" + do_backticks = "1" + do_dashes = "3" + do_ellipses = "1" + elif attr == "-1": + # Special "stupefy" mode. + do_stupefy = "1" + else: + for c in attr: + if c == "q": do_quotes = "1" + elif c == "b": do_backticks = "1" + elif c == "B": do_backticks = "2" + elif c == "d": do_dashes = "1" + elif c == "D": do_dashes = "2" + elif c == "i": do_dashes = "3" + elif c == "e": do_ellipses = "1" + elif c == "w": convert_quot = "1" + else: + pass + # ignore unknown option + + tokens = _tokenize(text) + result = [] + in_pre = False + + prev_token_last_char = "" + # This is a cheat, used to get some context + # for one-character tokens that consist of + # just a quote char. What we do is remember + # the last character of the previous text + # token, to use as context to curl single- + # character quote tokens correctly. + + for cur_token in tokens: + t = cur_token[1] + last_char = t[-1:] # Remember last char of this token before processing. + if not in_pre: + oldstr = t + t = processEscapes(t) + + if convert_quot != "0": + t = re.sub('"', '"', t) + + if do_dashes != "0": + if do_dashes == "1": + t = educateDashes(t) + if do_dashes == "2": + t = educateDashesOldSchool(t) + if do_dashes == "3": + t = educateDashesOldSchoolInverted(t) + + if do_ellipses != "0": + t = educateEllipses(t) + + # Note: backticks need to be processed before quotes. + if do_backticks != "0": + t = educateBackticks(t) + + if do_backticks == "2": + t = educateSingleBackticks(t) + + if do_quotes != "0": + if t == "'": + # Special case: single-character ' token + if re.match("\S", prev_token_last_char): + t = smart.rquote + else: + t = smart.lquote + elif t == '"': + # Special case: single-character " token + if re.match("\S", prev_token_last_char): + t = smart.rdquote + else: + t = smart.ldquote + + else: + # Normal case: + t = educateQuotes(t) + + if do_stupefy == "1": + t = stupefyEntities(t) + + prev_token_last_char = last_char + result.append(t) + + return "".join(result) + + +def educateQuotes(str): + """ + Parameter: String. + + Returns: The string, with "educated" curly quote characters. + + Example input: "Isn't this fun?" + Example output: “Isn’t this fun?“; + """ + + oldstr = str + punct_class = r"""[!"#\$\%'()*+,-.\/:;<=>?\@\[\\\]\^_`{|}~]""" + + # Special case if the very first character is a quote + # followed by punctuation at a non-word-break. Close the quotes by brute force: + str = re.sub(r"""^'(?=%s\\B)""" % (punct_class,), smart.rquote, str) + str = re.sub(r"""^"(?=%s\\B)""" % (punct_class,), smart.rdquote, str) + + # Special case for double sets of quotes, e.g.: + # <p>He said, "'Quoted' words in a larger quote."</p> + str = re.sub(r""""'(?=\w)""", smart.ldquote+smart.lquote, str) + str = re.sub(r"""'"(?=\w)""", smart.lquote+smart.ldquote, str) + + # Special case for decade abbreviations (the '80s): + str = re.sub(r"""\b'(?=\d{2}s)""", smart.rquote, str) + + close_class = r"""[^\ \t\r\n\[\{\(\-]""" + dec_dashes = r"""–|—""" + + # Get most opening single quotes: + opening_single_quotes_regex = re.compile(r""" + ( + \s | # a whitespace char, or + | # a non-breaking space entity, or + -- | # dashes, or + &[mn]dash; | # named dash entities + %s | # or decimal entities + &\#x201[34]; # or hex + ) + ' # the quote + (?=\w) # followed by a word character + """ % (dec_dashes,), re.VERBOSE) + str = opening_single_quotes_regex.sub(r'\1'+smart.lquote, str) + + closing_single_quotes_regex = re.compile(r""" + (%s) + ' + (?!\s | s\b | \d) + """ % (close_class,), re.VERBOSE) + str = closing_single_quotes_regex.sub(r'\1'+smart.rquote, str) + + closing_single_quotes_regex = re.compile(r""" + (%s) + ' + (\s | s\b) + """ % (close_class,), re.VERBOSE) + str = closing_single_quotes_regex.sub(r'\1%s\2' % smart.rquote, str) + + # Any remaining single quotes should be opening ones: + str = re.sub(r"""'""", smart.lquote, str) + + # Get most opening double quotes: + opening_double_quotes_regex = re.compile(r""" + ( + \s | # a whitespace char, or + | # a non-breaking space entity, or + -- | # dashes, or + &[mn]dash; | # named dash entities + %s | # or decimal entities + &\#x201[34]; # or hex + ) + " # the quote + (?=\w) # followed by a word character + """ % (dec_dashes,), re.VERBOSE) + str = opening_double_quotes_regex.sub(r'\1'+smart.ldquote, str) + + # Double closing quotes: + closing_double_quotes_regex = re.compile(r""" + #(%s)? # character that indicates the quote should be closing + " + (?=\s) + """ % (close_class,), re.VERBOSE) + str = closing_double_quotes_regex.sub(smart.rdquote, str) + + closing_double_quotes_regex = re.compile(r""" + (%s) # character that indicates the quote should be closing + " + """ % (close_class,), re.VERBOSE) + str = closing_double_quotes_regex.sub(r'\1'+smart.rdquote, str) + + # Any remaining quotes should be opening ones. + str = re.sub(r'"', smart.ldquote, str) + + return str + + +def educateBackticks(str): + """ + Parameter: String. + Returns: The string, with ``backticks'' -style double quotes + translated into HTML curly quote entities. + Example input: ``Isn't this fun?'' + Example output: “Isn't this fun?“; + """ + + str = re.sub(r"""``""", smart.ldquote, str) + str = re.sub(r"""''""", smart.rdquote, str) + return str + + +def educateSingleBackticks(str): + """ + Parameter: String. + Returns: The string, with `backticks' -style single quotes + translated into HTML curly quote entities. + + Example input: `Isn't this fun?' + Example output: ‘Isn’t this fun?’ + """ + + str = re.sub(r"""`""", smart.lquote, str) + str = re.sub(r"""'""", smart.rquote, str) + return str + + +def educateDashes(str): + """ + Parameter: String. + + Returns: The string, with each instance of "--" translated to + an em-dash character. + """ + + str = re.sub(r"""---""", smart.endash, str) # en (yes, backwards) + str = re.sub(r"""--""", smart.emdash, str) # em (yes, backwards) + return str + + +def educateDashesOldSchool(str): + """ + Parameter: String. + + Returns: The string, with each instance of "--" translated to + an en-dash character, and each "---" translated to + an em-dash character. + """ + + str = re.sub(r"""---""", smart.emdash, str) # em (yes, backwards) + str = re.sub(r"""--""", smart.endash, str) # en (yes, backwards) + return str + + +def educateDashesOldSchoolInverted(str): + """ + Parameter: String. + + Returns: The string, with each instance of "--" translated to + an em-dash character, and each "---" translated to + an en-dash character. Two reasons why: First, unlike the + en- and em-dash syntax supported by + EducateDashesOldSchool(), it's compatible with existing + entries written before SmartyPants 1.1, back when "--" was + only used for em-dashes. Second, em-dashes are more + common than en-dashes, and so it sort of makes sense that + the shortcut should be shorter to type. (Thanks to Aaron + Swartz for the idea.) + """ + str = re.sub(r"""---""", smart.endash, str) # em + str = re.sub(r"""--""", smart.emdash, str) # en + return str + + + +def educateEllipses(str): + """ + Parameter: String. + Returns: The string, with each instance of "..." translated to + an ellipsis character. + + Example input: Huh...? + Example output: Huh…? + """ + + str = re.sub(r"""\.\.\.""", smart.ellipsis, str) + str = re.sub(r"""\. \. \.""", smart.ellipsis, str) + return str + + +def stupefyEntities(str): + """ + Parameter: String. + Returns: The string, with each SmartyPants character translated to + its ASCII counterpart. + + Example input: “Hello — world.” + Example output: "Hello -- world." + """ + + str = re.sub(smart.endash, "-", str) # en-dash + str = re.sub(smart.emdash, "--", str) # em-dash + + str = re.sub(smart.lquote, "'", str) # open single quote + str = re.sub(smart.rquote, "'", str) # close single quote + + str = re.sub(smart.ldquote, '"', str) # open double quote + str = re.sub(smart.rdquote, '"', str) # close double quote + + str = re.sub(smart.ellipsis, '...', str)# ellipsis + + return str + + +def processEscapes(str): + r""" + Parameter: String. + Returns: The string, with after processing the following backslash + escape sequences. This is useful if you want to force a "dumb" + quote or other character to appear. + + Escape Value + ------ ----- + \\ \ + \" " + \' ' + \. . + \- - + \` ` + """ + str = re.sub(r"""\\\\""", r"""\""", str) + str = re.sub(r'''\\"''', r""""""", str) + str = re.sub(r"""\\'""", r"""'""", str) + str = re.sub(r"""\\\.""", r""".""", str) + str = re.sub(r"""\\-""", r"""-""", str) + str = re.sub(r"""\\`""", r"""`""", str) + + return str + + +def _tokenize(str): + """ + Parameter: String containing HTML markup. + Returns: Reference to an array of the tokens comprising the input + string. Each token is either a tag (possibly with nested, + tags contained therein, such as <a href="<MTFoo>">, or a + run of text between tags. Each element of the array is a + two-element array; the first is either 'tag' or 'text'; + the second is the actual value. + + Based on the _tokenize() subroutine from Brad Choate's MTRegex plugin. + <http://www.bradchoate.com/past/mtregex.php> + """ + + pos = 0 + length = len(str) + tokens = [] + + depth = 6 + nested_tags = "|".join(['(?:<(?:[^<>]',] * depth) + (')*>)' * depth) + #match = r"""(?: <! ( -- .*? -- \s* )+ > ) | # comments + # (?: <\? .*? \?> ) | # directives + # %s # nested tags """ % (nested_tags,) + tag_soup = re.compile(r"""([^<]*)(<[^>]*>)""") + + token_match = tag_soup.search(str) + + previous_end = 0 + while token_match is not None: + if token_match.group(1): + tokens.append(['text', token_match.group(1)]) + + tokens.append(['tag', token_match.group(2)]) + + previous_end = token_match.end() + token_match = tag_soup.search(str, token_match.end()) + + if previous_end < len(str): + tokens.append(['text', str[previous_end:]]) + + return tokens + + + +if __name__ == "__main__": + + import locale + + try: + locale.setlocale(locale.LC_ALL, '') + except: + pass + + from docutils.core import publish_string + docstring_html = publish_string(__doc__, writer_name='html') + + print docstring_html + + + # Unit test output goes out stderr. No worries. + import unittest + sp = smartyPants + + class TestSmartypantsAllAttributes(unittest.TestCase): + # the default attribute is "1", which means "all". + + def test_dates(self): + self.assertEqual(sp("1440-80's"), u"1440-80’s") + self.assertEqual(sp("1440-'80s"), u"1440-‘80s") + self.assertEqual(sp("1440---'80s"), u"1440–‘80s") + self.assertEqual(sp("1960s"), "1960s") # no effect. + self.assertEqual(sp("1960's"), u"1960’s") + self.assertEqual(sp("one two '60s"), u"one two ‘60s") + self.assertEqual(sp("'60s"), u"‘60s") + + def test_ordinal_numbers(self): + self.assertEqual(sp("21st century"), "21st century") # no effect. + self.assertEqual(sp("3rd"), "3rd") # no effect. + + def test_educated_quotes(self): + self.assertEqual(sp('''"Isn't this fun?"'''), u'“Isn’t this fun?”') + + unittest.main() + + + + +__author__ = "Chad Miller <sma...@ch...>" +__version__ = "1.5_1.6: Fri, 27 Jul 2007 07:06:40 -0400" +__url__ = "http://wiki.chad.org/SmartyPantsPy" +__description__ = "Smart-quotes, smart-ellipses, and smart-dashes for weblog entries in pyblosxom" Property changes on: trunk/docutils/docutils/utils/smartquotes.py ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision Added: svn:eol-style + native Added: trunk/docutils/test/test_transforms/test_smartquotes.py =================================================================== --- trunk/docutils/test/test_transforms/test_smartquotes.py (rev 0) +++ trunk/docutils/test/test_transforms/test_smartquotes.py 2012-10-16 12:40:36 UTC (rev 7530) @@ -0,0 +1,51 @@ +#!/usr/bin/env python +# -*- coding: utf8 -*- + +# $Id$ + +# :Copyright: © 2011 Günter Milde. +# :License: Released under the terms of the `2-Clause BSD license`_, in short: +# +# Copying and distribution of this file, with or without modification, +# are permitted in any medium without royalty provided the copyright +# notice and this notice are preserved. +# This file is offered as-is, without any warranty. +# +# .. _2-Clause BSD license: http://www.spdx.org/licenses/BSD-2-Clause + +""" +Test module for universal.SmartQuotes transform. +""" + + +from __init__ import DocutilsTestSupport # must be imported before docutils +from docutils.transforms.universal import SmartQuotes +from docutils.parsers.rst import Parser + +def suite(): + parser = Parser() + s = DocutilsTestSupport.TransformTestSuite( + parser, suite_settings={'smart_quotes': True}) + s.generateTests(totest) + return s + + +totest = {} + +totest['transitions'] = ((SmartQuotes,), [ +["""\ +Test "smart quotes", 'single smart quotes' +-- and ---also long--- dashes. +""", +u"""\ +<document source="test data"> + <paragraph> + Test “smart quotes”, ‘single smart quotes’ + – and —also long— dashes. +"""], +]) + + +if __name__ == '__main__': + import unittest + unittest.main(defaultTest='suite') Property changes on: trunk/docutils/test/test_transforms/test_smartquotes.py ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision Added: svn:eol-style + native This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mi...@us...> - 2012-10-18 23:13:52
|
Revision: 7532 http://docutils.svn.sourceforge.net/docutils/?rev=7532&view=rev Author: milde Date: 2012-10-18 23:13:45 +0000 (Thu, 18 Oct 2012) Log Message: ----------- Customizable MathJax URL (based on patch by Dmitry Shachnev). Also: No line break after opening inline math tag. Modified Paths: -------------- trunk/docutils/HISTORY.txt trunk/docutils/docs/user/config.txt trunk/docutils/docutils/writers/html4css1/__init__.py trunk/docutils/test/functional/expected/math_output_html.html trunk/docutils/test/functional/expected/math_output_latex.html trunk/docutils/test/functional/expected/math_output_mathjax.html trunk/docutils/test/functional/expected/standalone_rst_html4css1.html Modified: trunk/docutils/HISTORY.txt =================================================================== --- trunk/docutils/HISTORY.txt 2012-10-18 22:26:11 UTC (rev 7531) +++ trunk/docutils/HISTORY.txt 2012-10-18 23:13:45 UTC (rev 7532) @@ -46,6 +46,8 @@ - Use ``<code>`` tag for inline "code", do not drop nested inline nodes (syntax highlight tokens). + - Customizable MathJax URL (based on patch by Dmitry Shachnev). + - No line break after opening inline math tag. * docutils/writers/manpage.py Modified: trunk/docutils/docs/user/config.txt =================================================================== --- trunk/docutils/docs/user/config.txt 2012-10-18 22:26:11 UTC (rev 7531) +++ trunk/docutils/docs/user/config.txt 2012-10-18 23:13:45 UTC (rev 7532) @@ -797,6 +797,14 @@ fonts for high-quality typesetting that is scalable and prints at full resolution. + A custom URL can be appended after whitespace, + for example a local install + ``MathJax file:/usr/share/javascript/mathjax/MathJax.js`` or + `access the MathJax CDN using a https secure connection`__ + ``mathjax https://c328740.ssl.cf1.rackcdn.com/mathjax/latest/MathJax.js?config=config=TeX-AMS-MML_HTMLorMML``. + + __ http://www.mathjax.org/resources/faqs/#problem-https + Pro: Works 'out of the box' across multiple browsers and platforms. Modified: trunk/docutils/docutils/writers/html4css1/__init__.py =================================================================== --- trunk/docutils/docutils/writers/html4css1/__init__.py 2012-10-18 22:26:11 UTC (rev 7531) +++ trunk/docutils/docutils/writers/html4css1/__init__.py 2012-10-18 23:13:45 UTC (rev 7532) @@ -263,12 +263,7 @@ # __http://www.mathjax.org/download/mathjax-cdn-terms-of-service/ mathjax_url = ('http://cdn.mathjax.org/mathjax/latest/MathJax.js?' 'config=TeX-AMS-MML_HTMLorMML') - # TODO: make this configurable: - # - # a) as extra option or - # b) appended to math-output="MathJax"? - # - # If b), which delimiter/delimter-set (':', ',', ' ')? + # may be overwritten by custom URL appended to "mathjax" stylesheet_link = '<link rel="stylesheet" href="%s" type="text/css" />\n' embedded_stylesheet = '<style type="text/css">\n\n%s\n</style>\n' @@ -302,8 +297,14 @@ self.body_suffix = ['</body>\n</html>\n'] self.section_level = 0 self.initial_header_level = int(settings.initial_header_level) - - self.math_output = settings.math_output.lower() + + self.math_output = settings.math_output.split(None, 1) + if len(self.math_output) == 2: + self.math_output_option = self.math_output[1] + else: + self.math_output_option = None + self.math_output = self.math_output[0].lower() + # A heterogenous stack used in conjunction with the tree traversal. # Make sure that the pops correspond to the pushes: self.context = [] @@ -1168,7 +1169,7 @@ def visit_math(self, node, math_env=''): # If the method is called from visit_math_block(), math_env != ''. - + # As there is no native HTML math support, we provide alternatives: # LaTeX and MathJax math_output modes simply wrap the content, # HTML and MathML math_output modes also convert the math_code. @@ -1176,7 +1177,7 @@ self.document.reporter.error( 'math-output format "%s" not supported ' 'falling back to "latex"'% self.math_output) - self.math_output = 'latex' + self.math_output = 'latex' # # HTML container tags = {# math_output: (block, inline, class-arguments) @@ -1205,7 +1206,8 @@ if self.math_output in ('latex', 'mathjax'): math_code = self.encode(math_code) if self.math_output == 'mathjax': - self.math_header = self.mathjax_script % self.mathjax_url + self.math_header = self.mathjax_script % ( + self.math_output_option or self.mathjax_url) elif self.math_output == 'html': math_code = math2html(math_code) elif self.math_output == 'mathml': @@ -1228,7 +1230,9 @@ raise nodes.SkipNode # append to document body if tag: - self.body.append(self.starttag(node, tag, CLASS=clsarg)) + self.body.append(self.starttag(node, tag, + suffix='\n'*bool(math_env), + CLASS=clsarg)) self.body.append(math_code) if math_env: self.body.append('\n') Modified: trunk/docutils/test/functional/expected/math_output_html.html =================================================================== --- trunk/docutils/test/functional/expected/math_output_html.html 2012-10-18 22:26:11 UTC (rev 7531) +++ trunk/docutils/test/functional/expected/math_output_html.html 2012-10-18 23:13:45 UTC (rev 7532) @@ -13,10 +13,8 @@ <h1 class="title">Mathematics</h1> <p>Docutils supports inline math with the prefix or postfix <tt class="docutils literal">:math:</tt> -role specificator, <span class="formula"> -<i>n</i>! + sin(<i>x</i><span class="scripts"><sup class="script">2</sup><sub class="script"><i>n</i></sub></span>)</span> - and <span class="formula"> -<i>A</i><sub><span class="text">c</span></sub> = <span class="fraction"><span class="ignored">(</span><span class="numerator"><i>π</i></span><span class="ignored">)/(</span><span class="denominator">4</span><span class="ignored">)</span></span><i>d</i><sup>2</sup></span> +role specificator, <span class="formula"><i>n</i>! + sin(<i>x</i><span class="scripts"><sup class="script">2</sup><sub class="script"><i>n</i></sub></span>)</span> + and <span class="formula"><i>A</i><sub><span class="text">c</span></sub> = <span class="fraction"><span class="ignored">(</span><span class="numerator"><i>π</i></span><span class="ignored">)/(</span><span class="denominator">4</span><span class="ignored">)</span></span><i>d</i><sup>2</sup></span> , as well as displayed math via the <cite>math</cite> directive:</p> <div class="formula"> @@ -59,8 +57,7 @@ </span> </span><span class="array"><span class="arrayrow"><span class="bracket align-right">⎞</span></span><span class="arrayrow"><span class="bracket align-right">⎟</span></span><span class="arrayrow"><span class="bracket align-right">⎠</span></span></span> </div> -<p>is <span class="formula"> -|<b>M</b>| = <i>ad</i> − <i>bc</i></span> +<p>is <span class="formula">|<b>M</b>| = <i>ad</i> − <i>bc</i></span> .</p> <p>More than one display math block can be put in one math directive. For example, the following sum and integral with limits:</p> @@ -76,8 +73,7 @@ <div class="formula" id="eq-schrodinger"> <i>i</i>ℏ<span class="fraction"><span class="ignored">(</span><span class="numerator">∂</span><span class="ignored">)/(</span><span class="denominator">∂<i>t</i></span><span class="ignored">)</span></span>Ψ = <i>Ĥ</i>Ψ, </div> -<p>with the <em>wave function</em> <span class="formula"> -Ψ</span> +<p>with the <em>wave function</em> <span class="formula">Ψ</span> , describes how the quantum state of a physical system changes in time.</p> <dl class="docutils"> @@ -89,44 +85,32 @@ <col width="33%" /> </colgroup> <tbody valign="top"> -<tr><td><span class="formula"> -<i>á</i></span> +<tr><td><span class="formula"><i>á</i></span> <tt class="docutils literal">\acute{a}</tt></td> -<td><span class="formula"> -<i>ṫ</i></span> +<td><span class="formula"><i>ṫ</i></span> <tt class="docutils literal">\dot{t}</tt></td> -<td><span class="formula"> -<i>γ̂</i></span> +<td><span class="formula"><i>γ̂</i></span> <tt class="docutils literal"><span class="pre">\hat{\gamma}</span></tt></td> </tr> -<tr><td><span class="formula"> -<i>à</i></span> +<tr><td><span class="formula"><i>à</i></span> <tt class="docutils literal">\grave{a}</tt></td> -<td><span class="formula"> -<i>ẗ</i></span> +<td><span class="formula"><i>ẗ</i></span> <tt class="docutils literal">\ddot{t}</tt></td> -<td><span class="formula"> -<i>α̃</i></span> +<td><span class="formula"><i>α̃</i></span> <tt class="docutils literal"><span class="pre">\tilde{\alpha}</span></tt></td> </tr> -<tr><td><span class="formula"> -<i>x̆</i></span> +<tr><td><span class="formula"><i>x̆</i></span> <tt class="docutils literal">\breve{x}</tt></td> -<td><span class="formula"> -<i>t⃛</i></span> +<td><span class="formula"><i>t⃛</i></span> <tt class="docutils literal">\dddot{t}</tt></td> -<td><span class="formula"> -<i>ı⃗</i></span> +<td><span class="formula"><i>ı⃗</i></span> <tt class="docutils literal"><span class="pre">\vec{\imath}</span></tt></td> </tr> -<tr><td><span class="formula"> -<i>ǎ</i></span> +<tr><td><span class="formula"><i>ǎ</i></span> <tt class="docutils literal">\check{a}</tt></td> -<td><span class="formula"> -<span class="bar"><i>a</i></span></span> +<td><span class="formula"><span class="bar"><i>a</i></span></span> <tt class="docutils literal">\bar{a}</tt></td> -<td><span class="formula"> -<i>R⃗</i></span> +<td><span class="formula"><i>R⃗</i></span> <tt class="docutils literal">\vec{R}</tt></td> </tr> </tbody> Modified: trunk/docutils/test/functional/expected/math_output_latex.html =================================================================== --- trunk/docutils/test/functional/expected/math_output_latex.html 2012-10-18 22:26:11 UTC (rev 7531) +++ trunk/docutils/test/functional/expected/math_output_latex.html 2012-10-18 23:13:45 UTC (rev 7532) @@ -12,10 +12,8 @@ <h1 class="title">Mathematics</h1> <p>Docutils supports inline math with the prefix or postfix <tt class="docutils literal">:math:</tt> -role specificator, <tt class="math"> -n! + \sin(x_n^2)</tt> - and <tt class="math"> -A_\text{c} = +role specificator, <tt class="math">n! + \sin(x_n^2)</tt> + and <tt class="math">A_\text{c} = \frac{\pi}{4} d^2</tt> , as well as displayed math via the <cite>math</cite> directive:</p> @@ -32,8 +30,7 @@ <pre class="math" id="eq-m"> \mathbf{M} = \left(\begin{matrix}a&b\\c&d\end{matrix}\right) </pre> -<p>is <tt class="math"> -|\mathbf{M}| = ad - bc</tt> +<p>is <tt class="math">|\mathbf{M}| = ad - bc</tt> .</p> <p>More than one display math block can be put in one math directive. For example, the following sum and integral with limits:</p> @@ -49,8 +46,7 @@ <pre class="math" id="eq-schrodinger"> i\hbar \frac{\partial }{\partial t}\Psi = \hat{H}\Psi , </pre> -<p>with the <em>wave function</em> <tt class="math"> -\Psi </tt> +<p>with the <em>wave function</em> <tt class="math">\Psi </tt> , describes how the quantum state of a physical system changes in time.</p> <dl class="docutils"> @@ -62,44 +58,32 @@ <col width="33%" /> </colgroup> <tbody valign="top"> -<tr><td><tt class="math"> -\acute{a}</tt> +<tr><td><tt class="math">\acute{a}</tt> <tt class="docutils literal">\acute{a}</tt></td> -<td><tt class="math"> -\dot{t}</tt> +<td><tt class="math">\dot{t}</tt> <tt class="docutils literal">\dot{t}</tt></td> -<td><tt class="math"> -\hat{\gamma}</tt> +<td><tt class="math">\hat{\gamma}</tt> <tt class="docutils literal"><span class="pre">\hat{\gamma}</span></tt></td> </tr> -<tr><td><tt class="math"> -\grave{a}</tt> +<tr><td><tt class="math">\grave{a}</tt> <tt class="docutils literal">\grave{a}</tt></td> -<td><tt class="math"> -\ddot{t}</tt> +<td><tt class="math">\ddot{t}</tt> <tt class="docutils literal">\ddot{t}</tt></td> -<td><tt class="math"> -\tilde{\alpha}</tt> +<td><tt class="math">\tilde{\alpha}</tt> <tt class="docutils literal"><span class="pre">\tilde{\alpha}</span></tt></td> </tr> -<tr><td><tt class="math"> -\breve{x}</tt> +<tr><td><tt class="math">\breve{x}</tt> <tt class="docutils literal">\breve{x}</tt></td> -<td><tt class="math"> -\dddot{t}</tt> +<td><tt class="math">\dddot{t}</tt> <tt class="docutils literal">\dddot{t}</tt></td> -<td><tt class="math"> -\vec{\imath}</tt> +<td><tt class="math">\vec{\imath}</tt> <tt class="docutils literal"><span class="pre">\vec{\imath}</span></tt></td> </tr> -<tr><td><tt class="math"> -\check{a}</tt> +<tr><td><tt class="math">\check{a}</tt> <tt class="docutils literal">\check{a}</tt></td> -<td><tt class="math"> -\bar{a}</tt> +<td><tt class="math">\bar{a}</tt> <tt class="docutils literal">\bar{a}</tt></td> -<td><tt class="math"> -\vec{R}</tt> +<td><tt class="math">\vec{R}</tt> <tt class="docutils literal">\vec{R}</tt></td> </tr> </tbody> Modified: trunk/docutils/test/functional/expected/math_output_mathjax.html =================================================================== --- trunk/docutils/test/functional/expected/math_output_mathjax.html 2012-10-18 22:26:11 UTC (rev 7531) +++ trunk/docutils/test/functional/expected/math_output_mathjax.html 2012-10-18 23:13:45 UTC (rev 7532) @@ -13,10 +13,8 @@ <h1 class="title">Mathematics</h1> <p>Docutils supports inline math with the prefix or postfix <tt class="docutils literal">:math:</tt> -role specificator, <span class="math"> -\(n! + \sin(x_n^2)\)</span> - and <span class="math"> -\(A_\text{c} = +role specificator, <span class="math">\(n! + \sin(x_n^2)\)</span> + and <span class="math">\(A_\text{c} = \frac{\pi}{4} d^2\)</span> , as well as displayed math via the <cite>math</cite> directive:</p> @@ -39,8 +37,7 @@ \mathbf{M} = \left(\begin{matrix}a&b\\c&d\end{matrix}\right) \end{equation*} </div> -<p>is <span class="math"> -\(|\mathbf{M}| = ad - bc\)</span> +<p>is <span class="math">\(|\mathbf{M}| = ad - bc\)</span> .</p> <p>More than one display math block can be put in one math directive. For example, the following sum and integral with limits:</p> @@ -62,8 +59,7 @@ i\hbar \frac{\partial }{\partial t}\Psi = \hat{H}\Psi , \end{equation*} </div> -<p>with the <em>wave function</em> <span class="math"> -\(\Psi \)</span> +<p>with the <em>wave function</em> <span class="math">\(\Psi \)</span> , describes how the quantum state of a physical system changes in time.</p> <dl class="docutils"> @@ -75,44 +71,32 @@ <col width="33%" /> </colgroup> <tbody valign="top"> -<tr><td><span class="math"> -\(\acute{a}\)</span> +<tr><td><span class="math">\(\acute{a}\)</span> <tt class="docutils literal">\acute{a}</tt></td> -<td><span class="math"> -\(\dot{t}\)</span> +<td><span class="math">\(\dot{t}\)</span> <tt class="docutils literal">\dot{t}</tt></td> -<td><span class="math"> -\(\hat{\gamma}\)</span> +<td><span class="math">\(\hat{\gamma}\)</span> <tt class="docutils literal"><span class="pre">\hat{\gamma}</span></tt></td> </tr> -<tr><td><span class="math"> -\(\grave{a}\)</span> +<tr><td><span class="math">\(\grave{a}\)</span> <tt class="docutils literal">\grave{a}</tt></td> -<td><span class="math"> -\(\ddot{t}\)</span> +<td><span class="math">\(\ddot{t}\)</span> <tt class="docutils literal">\ddot{t}</tt></td> -<td><span class="math"> -\(\tilde{\alpha}\)</span> +<td><span class="math">\(\tilde{\alpha}\)</span> <tt class="docutils literal"><span class="pre">\tilde{\alpha}</span></tt></td> </tr> -<tr><td><span class="math"> -\(\breve{x}\)</span> +<tr><td><span class="math">\(\breve{x}\)</span> <tt class="docutils literal">\breve{x}</tt></td> -<td><span class="math"> -\(\dddot{t}\)</span> +<td><span class="math">\(\dddot{t}\)</span> <tt class="docutils literal">\dddot{t}</tt></td> -<td><span class="math"> -\(\vec{\imath}\)</span> +<td><span class="math">\(\vec{\imath}\)</span> <tt class="docutils literal"><span class="pre">\vec{\imath}</span></tt></td> </tr> -<tr><td><span class="math"> -\(\check{a}\)</span> +<tr><td><span class="math">\(\check{a}\)</span> <tt class="docutils literal">\check{a}</tt></td> -<td><span class="math"> -\(\bar{a}\)</span> +<td><span class="math">\(\bar{a}\)</span> <tt class="docutils literal">\bar{a}</tt></td> -<td><span class="math"> -\(\vec{R}\)</span> +<td><span class="math">\(\vec{R}\)</span> <tt class="docutils literal">\vec{R}</tt></td> </tr> </tbody> Modified: trunk/docutils/test/functional/expected/standalone_rst_html4css1.html =================================================================== --- trunk/docutils/test/functional/expected/standalone_rst_html4css1.html 2012-10-18 22:26:11 UTC (rev 7531) +++ trunk/docutils/test/functional/expected/standalone_rst_html4css1.html 2012-10-18 23:13:45 UTC (rev 7532) @@ -862,8 +862,7 @@ or as base for special code roles, e.g. the LaTeX code in the next paragraph.</p> <p>Docutils uses LaTeX syntax for math directives and roles: -<code class="tex">\alpha = f(x)</code> prints <span class="math"> -\(\alpha = f(x)\)</span> +<code class="tex">\alpha = f(x)</code> prints <span class="math">\(\alpha = f(x)\)</span> .</p> <p>The <tt class="docutils literal">:code:</tt> option of the <cite>include</cite> directive sets the included content as a code block, here the rst file <tt class="docutils literal">header_footer.txt</tt> with line numbers:</p> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mi...@us...> - 2012-10-25 11:48:40
|
Revision: 7534 http://docutils.svn.sourceforge.net/docutils/?rev=7534&view=rev Author: milde Date: 2012-10-25 11:48:32 +0000 (Thu, 25 Oct 2012) Log Message: ----------- Code cleanup and test html math output options. Based on patch by Dmitry Shachnev. Modified Paths: -------------- trunk/docutils/docutils/writers/html4css1/__init__.py trunk/docutils/test/DocutilsTestSupport.py trunk/docutils/test/test_writers/test_html4css1_misc.py Modified: trunk/docutils/docutils/writers/html4css1/__init__.py =================================================================== --- trunk/docutils/docutils/writers/html4css1/__init__.py 2012-10-21 17:24:53 UTC (rev 7533) +++ trunk/docutils/docutils/writers/html4css1/__init__.py 2012-10-25 11:48:32 UTC (rev 7534) @@ -298,11 +298,8 @@ self.section_level = 0 self.initial_header_level = int(settings.initial_header_level) - self.math_output = settings.math_output.split(None, 1) - if len(self.math_output) == 2: - self.math_output_option = self.math_output[1] - else: - self.math_output_option = None + self.math_output = settings.math_output.split() + self.math_output_options = self.math_output[1:] self.math_output = self.math_output[0].lower() # A heterogenous stack used in conjunction with the tree traversal. @@ -1206,8 +1203,9 @@ if self.math_output in ('latex', 'mathjax'): math_code = self.encode(math_code) if self.math_output == 'mathjax': - self.math_header = self.mathjax_script % ( - self.math_output_option or self.mathjax_url) + if self.math_output_options: + self.mathjax_url = self.math_output_options[0] + self.math_header = self.mathjax_script % self.mathjax_url elif self.math_output == 'html': math_code = math2html(math_code) elif self.math_output == 'mathml': Modified: trunk/docutils/test/DocutilsTestSupport.py =================================================================== --- trunk/docutils/test/DocutilsTestSupport.py 2012-10-21 17:24:53 UTC (rev 7533) +++ trunk/docutils/test/DocutilsTestSupport.py 2012-10-25 11:48:32 UTC (rev 7534) @@ -119,17 +119,29 @@ operator. """ if not first == second: - raise self.failureException, \ - (msg or '%s != %s' % _format_str(first, second)) + raise self.failureException, ( + msg or '%s != %s' % _format_str(first, second)) def assertNotEqual(self, first, second, msg=None): """Fail if the two objects are equal as determined by the '==' operator. """ if first == second: - raise self.failureException, \ - (msg or '%s == %s' % _format_str(first, second)) + raise self.failureException, ( + msg or '%s == %s' % _format_str(first, second)) + # assertIn and assertNotIn: new in Python 2.7: + + def assertIn(self, a, b, msg=None): + if a not in b: + raise self.failureException, ( + msg or '%s not in %s' % _format_str(a, b)) + + def assertNotIn(self, a, b, msg=None): + if a in b: + raise self.failureException, ( + msg or '%s in %s' % _format_str(a, b)) + # aliases for assertion methods, deprecated since Python 2.7 failUnlessEqual = assertEquals = assertEqual Modified: trunk/docutils/test/test_writers/test_html4css1_misc.py =================================================================== --- trunk/docutils/test/test_writers/test_html4css1_misc.py 2012-10-21 17:24:53 UTC (rev 7533) +++ trunk/docutils/test/test_writers/test_html4css1_misc.py 2012-10-25 11:48:32 UTC (rev 7534) @@ -1,7 +1,8 @@ #! /usr/bin/env python +# coding: utf-8 # $Id$ -# Author: Lea Wiemann +# Authors: Lea Wiemann, Dmitry Shachnev, Günter Milde # Maintainer: doc...@li... # Copyright: This module has been placed in the public domain. @@ -13,7 +14,6 @@ from docutils import core from docutils._compat import b - class EncodingTestCase(DocutilsTestSupport.StandardTestCase): def test_xmlcharrefreplace(self): @@ -28,9 +28,62 @@ settings_overrides=settings_overrides) # Encoding a euro sign with latin1 doesn't work, so the # xmlcharrefreplace handler is used. - self.assertNotEqual(result.find(b('EUR = €')), -1) + self.assertIn(b('EUR = €'), result) +class MathTestCase(DocutilsTestSupport.StandardTestCase): + + """Attention: This class tests the current implementation of maths support + which is open to change in future Docutils releases. """ + settings_overrides={'_disable_config': True,} + mathjax_script = '<script type="text/javascript" src="%s">' + default_mathjax_url = ('http://cdn.mathjax.org/mathjax/latest/MathJax.js' + '?config=TeX-AMS-MML_HTMLorMML') + custom_mathjax_url = ('file:///usr/share/javascript/mathjax/MathJax.js' + '?config=TeX-AMS-MML_HTMLorMML') + data = ':math:`42`' + + def test_math_output_default(self): + # Currently MathJax with default URL. Likely to change to HTML! + mysettings = self.settings_overrides + head = core.publish_parts(self.data, writer_name='html4css1', + settings_overrides=mysettings)['head'] + self.assertIn(self.mathjax_script % self.default_mathjax_url, head) + + def test_math_output_mathjax(self): + # Explicitly specifying math_output=MathJax, case insensitively + # use default MathJax URL + mysettings = self.settings_overrides.copy() + mysettings.update({'math_output': 'MathJax'}) + head = core.publish_parts(self.data, writer_name='html4css1', + settings_overrides=mysettings)['head'] + self.assertIn(self.mathjax_script % self.default_mathjax_url, head) + + def test_math_output_mathjax_custom(self): + # Customizing MathJax URL + mysettings = self.settings_overrides.copy() + mysettings.update({'math_output': + 'mathjax %s' % self.custom_mathjax_url}) + head = core.publish_parts(self.data, writer_name='html4css1', + settings_overrides=mysettings)['head'] + self.assertIn(self.mathjax_script % self.custom_mathjax_url, head) + + def test_math_output_html(self): + # There should be no MathJax script when math_output is not MathJax + mysettings = self.settings_overrides.copy() + mysettings.update({'math_output': 'HTML'}) + head = core.publish_parts(self.data, writer_name='html4css1', + settings_overrides=mysettings)['head'] + self.assertNotIn('MathJax.js', head) + + def test_math_output_mathjax_no_math(self): + mysettings = self.settings_overrides.copy() + mysettings.update({'math_output': 'MathJax'}) + # There should be no math script when text does not contain math + head = core.publish_parts('No math.', writer_name='html4css1')['head'] + self.assertNotIn('MathJax', head) + + if __name__ == '__main__': import unittest unittest.main() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mi...@us...> - 2012-11-06 13:49:37
|
Revision: 7536 http://docutils.svn.sourceforge.net/docutils/?rev=7536&view=rev Author: milde Date: 2012-11-06 13:49:27 +0000 (Tue, 06 Nov 2012) Log Message: ----------- Fix opening binary files under Py3k (thanks to Dominic Fitzpatrick). Modified Paths: -------------- trunk/docutils/HISTORY.txt trunk/docutils/docutils/io.py Modified: trunk/docutils/HISTORY.txt =================================================================== --- trunk/docutils/HISTORY.txt 2012-10-25 12:01:12 UTC (rev 7535) +++ trunk/docutils/HISTORY.txt 2012-11-06 13:49:27 UTC (rev 7536) @@ -33,6 +33,7 @@ - FileInput/FileOutput: no system-exit on IOError. The `handle_io_errors` option is ignored and will be removed in a future release. - Fix Py3k error writing to stdout with encoding differing from default. + - Fix opening binary files under Py3k (thanks to Dominic Fitzpatrick). * docutils/parsers/rst/directives/misc.py Modified: trunk/docutils/docutils/io.py =================================================================== --- trunk/docutils/docutils/io.py 2012-10-25 12:01:12 UTC (rev 7535) +++ trunk/docutils/docutils/io.py 2012-11-06 13:49:27 UTC (rev 7536) @@ -297,7 +297,7 @@ mode = 'w' """The mode argument for `open()`.""" - # 'wb' for binary (e.g. OpenOffice) files. + # 'wb' for binary (e.g. OpenOffice) files (see also `BinaryFileOutput`). # (Do not use binary mode ('wb') for text files, as this prevents the # conversion of newlines to the system specific default.) @@ -346,7 +346,7 @@ def open(self): # Specify encoding in Python 3. - if sys.version_info >= (3,0): + if sys.version_info >= (3,0) and 'b' not in self.mode: kwargs = {'encoding': self.encoding, 'errors': self.error_handler} else: This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mi...@us...> - 2012-11-18 22:11:59
|
Revision: 7537 http://docutils.svn.sourceforge.net/docutils/?rev=7537&view=rev Author: milde Date: 2012-11-18 22:11:49 +0000 (Sun, 18 Nov 2012) Log Message: ----------- Smartquotes: correct "educating" of quotes around inline markup. Modified Paths: -------------- trunk/docutils/docutils/transforms/universal.py trunk/docutils/docutils/utils/smartquotes.py trunk/docutils/test/test_transforms/test_smartquotes.py Modified: trunk/docutils/docutils/transforms/universal.py =================================================================== --- trunk/docutils/docutils/transforms/universal.py 2012-11-06 13:49:27 UTC (rev 7536) +++ trunk/docutils/docutils/transforms/universal.py 2012-11-18 22:11:49 UTC (rev 7537) @@ -207,23 +207,46 @@ """ Replace ASCII quotation marks with typographic form. - Also replace multiple dashes with em-dashes and en-dashes. + Also replace multiple dashes with em-dash/en-dash characters. """ default_priority = 850 + texttype = {True: 'literal', + False: 'plain'} + def apply(self): if self.document.settings.smart_quotes is False: return - for node in self.document.traverse(nodes.Text): - if isinstance(node.parent, - (nodes.FixedTextElement, - nodes.literal, - nodes.Special, - nodes.option_string - )): - # print "literal", node + + # "Educate" quotes in normal text. Handle each block of text + # (TextElement node) as a unit to keep context around inline nodes: + for node in self.document.traverse(nodes.TextElement): + # skip preformatted text blocks and special elements: + if isinstance(node, (nodes.FixedTextElement, nodes.Special)): continue - newtext = smartquotes.smartyPants(node.astext(), attr='2') - node.parent.replace(node, nodes.Text(newtext)) - # print "smartquote", + # nested TextElements are not "block-level" elements: + if isinstance(node.parent, nodes.TextElement): + continue + + # list of text nodes in the "text block": + txtnodes = [txtnode for txtnode in node.traverse(nodes.Text) + if not isinstance(txtnode.parent, + nodes.option_string)] + # smartquotes.educate_tokens() iterates over + # ``(texttype, nodetext)`` tuples. `texttype` is "literal" + # or "plain" where "literal" text is not changed: + tokens = [(self.texttype[isinstance(txtnode.parent, + (nodes.literal, + nodes.math, + nodes.image, + nodes.raw, + nodes.problematic))], + txtnode.astext()) for txtnode in txtnodes] + + # Iterator educating quotes in plain text + # 2 : set all, using old school en- and em- dash shortcuts + teacher = smartquotes.educate_tokens(tokens, attr='2') + + for txtnode, newtext in zip(txtnodes, teacher): + txtnode.parent.replace(txtnode, nodes.Text(newtext)) Modified: trunk/docutils/docutils/utils/smartquotes.py =================================================================== --- trunk/docutils/docutils/utils/smartquotes.py 2012-11-06 13:49:27 UTC (rev 7536) +++ trunk/docutils/docutils/utils/smartquotes.py 2012-11-18 22:11:49 UTC (rev 7537) @@ -2,7 +2,7 @@ # -*- coding: utf8 -*- # :Id: $Id$ -# :Copyright: © 2011 Günter Milde, +# :Copyright: © 2010 Günter Milde, # original `SmartyPants`_: © 2003 John Gruber # smartypants.py: © 2004, 2007 Chad Miller # :License: Released under the terms of the `2-Clause BSD license`_, in short: @@ -313,6 +313,10 @@ Version History =============== +1.6.1: 2012-11-06 + - Refactor code, code cleanup, + - `educate_tokens()` generator as interface for Docutils. + 1.6: 2010-08-26 - Adaption to Docutils: - Use Unicode instead of HTML entities, @@ -352,6 +356,7 @@ default_smartypants_attr = "1" + import re class smart(object): @@ -371,8 +376,15 @@ ellipsis = u'…' # "…" HORIZONTAL ELLIPSIS def smartyPants(text, attr=default_smartypants_attr): - convert_quot = False # translate " entities into normal quotes? + """Main function for "traditional" use.""" + return "".join([t for t in educate_tokens(tokenize(text), attr)]) + + +def educate_tokens(text_tokens, attr=default_smartypants_attr): + """Return iterator that "educates" `text_tokens`. + """ + # Parse attributes: # 0 : do nothing # 1 : set all @@ -388,142 +400,123 @@ # e : ellipses # w : convert " entities to " for Dreamweaver users - skipped_tag_stack = [] - do_dashes = "0" - do_backticks = "0" - do_quotes = "0" - do_ellipses = "0" - do_stupefy = "0" + convert_quot = False # translate " entities into normal quotes? + do_dashes = False + do_backticks = False + do_quotes = False + do_ellipses = False + do_stupefy = False - if attr == "0": - # Do nothing. - return text - elif attr == "1": - do_quotes = "1" - do_backticks = "1" - do_dashes = "1" - do_ellipses = "1" + if attr == "0": # Do nothing. + yield text + elif attr == "1": # Do everything, turn all options on. + do_quotes = True + do_backticks = True + do_dashes = 1 + do_ellipses = True elif attr == "2": # Do everything, turn all options on, use old school dash shorthand. - do_quotes = "1" - do_backticks = "1" - do_dashes = "2" - do_ellipses = "1" + do_quotes = True + do_backticks = True + do_dashes = 2 + do_ellipses = True elif attr == "3": - # Do everything, turn all options on, use inverted old school dash shorthand. - do_quotes = "1" - do_backticks = "1" - do_dashes = "3" - do_ellipses = "1" - elif attr == "-1": - # Special "stupefy" mode. - do_stupefy = "1" + # Do everything, use inverted old school dash shorthand. + do_quotes = True + do_backticks = True + do_dashes = 3 + do_ellipses = True + elif attr == "-1": # Special "stupefy" mode. + do_stupefy = True else: - for c in attr: - if c == "q": do_quotes = "1" - elif c == "b": do_backticks = "1" - elif c == "B": do_backticks = "2" - elif c == "d": do_dashes = "1" - elif c == "D": do_dashes = "2" - elif c == "i": do_dashes = "3" - elif c == "e": do_ellipses = "1" - elif c == "w": convert_quot = "1" - else: - pass - # ignore unknown option + if "q" in attr: do_quotes = True + if "b" in attr: do_backticks = True + if "B" in attr: do_backticks = 2 + if "d" in attr: do_dashes = 1 + if "D" in attr: do_dashes = 2 + if "i" in attr: do_dashes = 3 + if "e" in attr: do_ellipses = True + if "w" in attr: convert_quot = True - tokens = _tokenize(text) - result = [] - in_pre = False + prev_token_last_char = " " + # Get context around inline mark-up. (Remember the last character of the + # previous text token, to use as context to curl single-character quote + # tokens correctly.) - prev_token_last_char = "" - # This is a cheat, used to get some context - # for one-character tokens that consist of - # just a quote char. What we do is remember - # the last character of the previous text - # token, to use as context to curl single- - # character quote tokens correctly. - - for cur_token in tokens: + for cur_token in text_tokens: t = cur_token[1] + + # skip HTML and/or XML tags (do not update last character) + if cur_token[0] == 'tag': + yield t + continue + last_char = t[-1:] # Remember last char of this token before processing. - if not in_pre: - oldstr = t - t = processEscapes(t) - if convert_quot != "0": - t = re.sub('"', '"', t) + # skip literal text (math, literal, raw, ...) + if cur_token[0] == 'literal': + yield t + continue - if do_dashes != "0": - if do_dashes == "1": - t = educateDashes(t) - if do_dashes == "2": - t = educateDashesOldSchool(t) - if do_dashes == "3": - t = educateDashesOldSchoolInverted(t) + t = processEscapes(t) - if do_ellipses != "0": - t = educateEllipses(t) + if convert_quot: + t = re.sub('"', '"', t) - # Note: backticks need to be processed before quotes. - if do_backticks != "0": - t = educateBackticks(t) + if do_dashes == 1: + t = educateDashes(t) + elif do_dashes == 2: + t = educateDashesOldSchool(t) + elif do_dashes == 3: + t = educateDashesOldSchoolInverted(t) - if do_backticks == "2": - t = educateSingleBackticks(t) + if do_ellipses: + t = educateEllipses(t) - if do_quotes != "0": - if t == "'": - # Special case: single-character ' token - if re.match("\S", prev_token_last_char): - t = smart.rquote - else: - t = smart.lquote - elif t == '"': - # Special case: single-character " token - if re.match("\S", prev_token_last_char): - t = smart.rdquote - else: - t = smart.ldquote + # Note: backticks need to be processed before quotes. + if do_backticks: + t = educateBackticks(t) - else: - # Normal case: - t = educateQuotes(t) + if do_backticks == 2: + t = educateSingleBackticks(t) - if do_stupefy == "1": - t = stupefyEntities(t) + if do_quotes: + t = educateQuotes(prev_token_last_char+t)[1:] + if do_stupefy: + t = stupefyEntities(t) + + # print prev_token_last_char, t.encode('utf8') prev_token_last_char = last_char - result.append(t) - return "".join(result) + yield t -def educateQuotes(str): + +def educateQuotes(text): """ - Parameter: String. + Parameter: String (unicode or bytes). + Returns: The `text`, with "educated" curly quote characters. - Returns: The string, with "educated" curly quote characters. - Example input: "Isn't this fun?" Example output: “Isn’t this fun?“; """ - oldstr = str + # oldtext = text punct_class = r"""[!"#\$\%'()*+,-.\/:;<=>?\@\[\\\]\^_`{|}~]""" # Special case if the very first character is a quote # followed by punctuation at a non-word-break. Close the quotes by brute force: - str = re.sub(r"""^'(?=%s\\B)""" % (punct_class,), smart.rquote, str) - str = re.sub(r"""^"(?=%s\\B)""" % (punct_class,), smart.rdquote, str) + text = re.sub(r"""^'(?=%s\\B)""" % (punct_class,), smart.rquote, text) + text = re.sub(r"""^"(?=%s\\B)""" % (punct_class,), smart.rdquote, text) # Special case for double sets of quotes, e.g.: # <p>He said, "'Quoted' words in a larger quote."</p> - str = re.sub(r""""'(?=\w)""", smart.ldquote+smart.lquote, str) - str = re.sub(r"""'"(?=\w)""", smart.lquote+smart.ldquote, str) + text = re.sub(r""""'(?=\w)""", smart.ldquote+smart.lquote, text) + text = re.sub(r"""'"(?=\w)""", smart.lquote+smart.ldquote, text) # Special case for decade abbreviations (the '80s): - str = re.sub(r"""\b'(?=\d{2}s)""", smart.rquote, str) + text = re.sub(r"""\b'(?=\d{2}s)""", smart.rquote, text) close_class = r"""[^\ \t\r\n\[\{\(\-]""" dec_dashes = r"""–|—""" @@ -541,24 +534,24 @@ ' # the quote (?=\w) # followed by a word character """ % (dec_dashes,), re.VERBOSE) - str = opening_single_quotes_regex.sub(r'\1'+smart.lquote, str) + text = opening_single_quotes_regex.sub(r'\1'+smart.lquote, text) closing_single_quotes_regex = re.compile(r""" (%s) ' (?!\s | s\b | \d) """ % (close_class,), re.VERBOSE) - str = closing_single_quotes_regex.sub(r'\1'+smart.rquote, str) + text = closing_single_quotes_regex.sub(r'\1'+smart.rquote, text) closing_single_quotes_regex = re.compile(r""" (%s) ' (\s | s\b) """ % (close_class,), re.VERBOSE) - str = closing_single_quotes_regex.sub(r'\1%s\2' % smart.rquote, str) + text = closing_single_quotes_regex.sub(r'\1%s\2' % smart.rquote, text) # Any remaining single quotes should be opening ones: - str = re.sub(r"""'""", smart.lquote, str) + text = re.sub(r"""'""", smart.lquote, text) # Get most opening double quotes: opening_double_quotes_regex = re.compile(r""" @@ -573,7 +566,7 @@ " # the quote (?=\w) # followed by a word character """ % (dec_dashes,), re.VERBOSE) - str = opening_double_quotes_regex.sub(r'\1'+smart.ldquote, str) + text = opening_double_quotes_regex.sub(r'\1'+smart.ldquote, text) # Double closing quotes: closing_double_quotes_regex = re.compile(r""" @@ -581,81 +574,78 @@ " (?=\s) """ % (close_class,), re.VERBOSE) - str = closing_double_quotes_regex.sub(smart.rdquote, str) + text = closing_double_quotes_regex.sub(smart.rdquote, text) closing_double_quotes_regex = re.compile(r""" (%s) # character that indicates the quote should be closing " """ % (close_class,), re.VERBOSE) - str = closing_double_quotes_regex.sub(r'\1'+smart.rdquote, str) + text = closing_double_quotes_regex.sub(r'\1'+smart.rdquote, text) # Any remaining quotes should be opening ones. - str = re.sub(r'"', smart.ldquote, str) + text = re.sub(r'"', smart.ldquote, text) - return str + return text -def educateBackticks(str): +def educateBackticks(text): """ - Parameter: String. - Returns: The string, with ``backticks'' -style double quotes + Parameter: String (unicode or bytes). + Returns: The `text`, with ``backticks'' -style double quotes translated into HTML curly quote entities. Example input: ``Isn't this fun?'' Example output: “Isn't this fun?“; """ - str = re.sub(r"""``""", smart.ldquote, str) - str = re.sub(r"""''""", smart.rdquote, str) - return str + text = re.sub(r"""``""", smart.ldquote, text) + text = re.sub(r"""''""", smart.rdquote, text) + return text -def educateSingleBackticks(str): +def educateSingleBackticks(text): """ - Parameter: String. - Returns: The string, with `backticks' -style single quotes + Parameter: String (unicode or bytes). + Returns: The `text`, with `backticks' -style single quotes translated into HTML curly quote entities. Example input: `Isn't this fun?' Example output: ‘Isn’t this fun?’ """ - str = re.sub(r"""`""", smart.lquote, str) - str = re.sub(r"""'""", smart.rquote, str) - return str + text = re.sub(r"""`""", smart.lquote, text) + text = re.sub(r"""'""", smart.rquote, text) + return text -def educateDashes(str): +def educateDashes(text): """ - Parameter: String. - - Returns: The string, with each instance of "--" translated to + Parameter: String (unicode or bytes). + Returns: The `text`, with each instance of "--" translated to an em-dash character. """ - str = re.sub(r"""---""", smart.endash, str) # en (yes, backwards) - str = re.sub(r"""--""", smart.emdash, str) # em (yes, backwards) - return str + text = re.sub(r"""---""", smart.endash, text) # en (yes, backwards) + text = re.sub(r"""--""", smart.emdash, text) # em (yes, backwards) + return text -def educateDashesOldSchool(str): +def educateDashesOldSchool(text): """ - Parameter: String. - - Returns: The string, with each instance of "--" translated to + Parameter: String (unicode or bytes). + Returns: The `text`, with each instance of "--" translated to an en-dash character, and each "---" translated to an em-dash character. """ - str = re.sub(r"""---""", smart.emdash, str) # em (yes, backwards) - str = re.sub(r"""--""", smart.endash, str) # en (yes, backwards) - return str + text = re.sub(r"""---""", smart.emdash, text) # em (yes, backwards) + text = re.sub(r"""--""", smart.endash, text) # en (yes, backwards) + return text -def educateDashesOldSchoolInverted(str): +def educateDashesOldSchoolInverted(text): """ - Parameter: String. - - Returns: The string, with each instance of "--" translated to + Parameter: String (unicode or bytes). + Returns: The `text`, with each instance of "--" translated to an em-dash character, and each "---" translated to an en-dash character. Two reasons why: First, unlike the en- and em-dash syntax supported by @@ -666,55 +656,55 @@ the shortcut should be shorter to type. (Thanks to Aaron Swartz for the idea.) """ - str = re.sub(r"""---""", smart.endash, str) # em - str = re.sub(r"""--""", smart.emdash, str) # en - return str + text = re.sub(r"""---""", smart.endash, text) # em + text = re.sub(r"""--""", smart.emdash, text) # en + return text -def educateEllipses(str): +def educateEllipses(text): """ - Parameter: String. - Returns: The string, with each instance of "..." translated to + Parameter: String (unicode or bytes). + Returns: The `text`, with each instance of "..." translated to an ellipsis character. Example input: Huh...? Example output: Huh…? """ - str = re.sub(r"""\.\.\.""", smart.ellipsis, str) - str = re.sub(r"""\. \. \.""", smart.ellipsis, str) - return str + text = re.sub(r"""\.\.\.""", smart.ellipsis, text) + text = re.sub(r"""\. \. \.""", smart.ellipsis, text) + return text -def stupefyEntities(str): +def stupefyEntities(text): """ - Parameter: String. - Returns: The string, with each SmartyPants character translated to + Parameter: String (unicode or bytes). + Returns: The `text`, with each SmartyPants character translated to its ASCII counterpart. Example input: “Hello — world.” Example output: "Hello -- world." """ - str = re.sub(smart.endash, "-", str) # en-dash - str = re.sub(smart.emdash, "--", str) # em-dash + text = re.sub(smart.endash, "-", text) # en-dash + text = re.sub(smart.emdash, "--", text) # em-dash - str = re.sub(smart.lquote, "'", str) # open single quote - str = re.sub(smart.rquote, "'", str) # close single quote + text = re.sub(smart.lquote, "'", text) # open single quote + text = re.sub(smart.rquote, "'", text) # close single quote - str = re.sub(smart.ldquote, '"', str) # open double quote - str = re.sub(smart.rdquote, '"', str) # close double quote + text = re.sub(smart.ldquote, '"', text) # open double quote + text = re.sub(smart.rdquote, '"', text) # close double quote - str = re.sub(smart.ellipsis, '...', str)# ellipsis + text = re.sub(smart.ellipsis, '...', text)# ellipsis - return str + return text -def processEscapes(str): +def processEscapes(text): r""" - Parameter: String. - Returns: The string, with after processing the following backslash + Parameter: String (unicode or bytes). + Returns: The `text`, with after processing the following backslash escape sequences. This is useful if you want to force a "dumb" quote or other character to appear. @@ -727,24 +717,24 @@ \- - \` ` """ - str = re.sub(r"""\\\\""", r"""\""", str) - str = re.sub(r'''\\"''', r""""""", str) - str = re.sub(r"""\\'""", r"""'""", str) - str = re.sub(r"""\\\.""", r""".""", str) - str = re.sub(r"""\\-""", r"""-""", str) - str = re.sub(r"""\\`""", r"""`""", str) + text = re.sub(r"""\\\\""", r"""\""", text) + text = re.sub(r'''\\"''', r""""""", text) + text = re.sub(r"""\\'""", r"""'""", text) + text = re.sub(r"""\\\.""", r""".""", text) + text = re.sub(r"""\\-""", r"""-""", text) + text = re.sub(r"""\\`""", r"""`""", text) - return str + return text -def _tokenize(str): +def tokenize(text): """ Parameter: String containing HTML markup. - Returns: Reference to an array of the tokens comprising the input + Returns: An iterator that yields the tokens comprising the input string. Each token is either a tag (possibly with nested, tags contained therein, such as <a href="<MTFoo>">, or a - run of text between tags. Each element of the array is a - two-element array; the first is either 'tag' or 'text'; + run of text between tags. Each yielded element is a + two-element tuple; the first is either 'tag' or 'text'; the second is the actual value. Based on the _tokenize() subroutine from Brad Choate's MTRegex plugin. @@ -752,8 +742,8 @@ """ pos = 0 - length = len(str) - tokens = [] + length = len(text) + # tokens = [] depth = 6 nested_tags = "|".join(['(?:<(?:[^<>]',] * depth) + (')*>)' * depth) @@ -762,25 +752,23 @@ # %s # nested tags """ % (nested_tags,) tag_soup = re.compile(r"""([^<]*)(<[^>]*>)""") - token_match = tag_soup.search(str) + token_match = tag_soup.search(text) previous_end = 0 while token_match is not None: if token_match.group(1): - tokens.append(['text', token_match.group(1)]) + yield ('text', token_match.group(1)) - tokens.append(['tag', token_match.group(2)]) + yield ('tag', token_match.group(2)) previous_end = token_match.end() - token_match = tag_soup.search(str, token_match.end()) + token_match = tag_soup.search(text, token_match.end()) - if previous_end < len(str): - tokens.append(['text', str[previous_end:]]) + if previous_end < len(text): + yield ('text', text[previous_end:]) - return tokens - if __name__ == "__main__": import locale @@ -796,7 +784,7 @@ print docstring_html - # Unit test output goes out stderr. No worries. + # Unit test output goes out stderr. import unittest sp = smartyPants @@ -819,6 +807,10 @@ def test_educated_quotes(self): self.assertEqual(sp('''"Isn't this fun?"'''), u'“Isn’t this fun?”') + def test_html_tags(self): + text = '<a src="foo">more</a>' + self.assertEqual(sp(text), text) + unittest.main() Modified: trunk/docutils/test/test_transforms/test_smartquotes.py =================================================================== --- trunk/docutils/test/test_transforms/test_smartquotes.py 2012-11-06 13:49:27 UTC (rev 7536) +++ trunk/docutils/test/test_transforms/test_smartquotes.py 2012-11-18 22:11:49 UTC (rev 7537) @@ -34,15 +34,94 @@ totest['transitions'] = ((SmartQuotes,), [ ["""\ -Test "smart quotes", 'single smart quotes' +Test "smart quotes", 'single smart quotes', +"'nested' smart" quotes -- and ---also long--- dashes. """, u"""\ <document source="test data"> <paragraph> - Test “smart quotes”, ‘single smart quotes’ + Test “smart quotes”, ‘single smart quotes’, + “‘nested’ smart” quotes – and —also long— dashes. """], +["""\ +Do not "educate" quotes ``inside "literal" text`` and :: + + "literal" blocks. + +Keep quotes straight in code and math: +:code:`print "hello"` :math:`1' 12"`. + +.. code:: + + print "hello" + +.. math:: + + f'(x) = df(x)/dx + +""", +u"""\ +<document source="test data"> + <paragraph> + Do not “educate” quotes + <literal> + inside "literal" text + and + <literal_block xml:space="preserve"> + "literal" blocks. + <paragraph> + Keep quotes straight in code and math: + <literal classes="code"> + print "hello" + + <math> + 1' 12" + . + <literal_block classes="code" xml:space="preserve"> + print "hello" + <math_block xml:space="preserve"> + f'(x) = df(x)/dx +"""], +["""\ +Quotes and inline-elements: + +* Around "_`targets`", "*emphasized*" or "``literal``" text + and links to "targets_". + +* Inside *"emphasized"* or other `inline "roles"` +""", +u"""\ +<document source="test data"> + <paragraph> + Quotes and inline-elements: + <bullet_list bullet="*"> + <list_item> + <paragraph> + Around “ + <target ids="targets" names="targets"> + targets + ”, “ + <emphasis> + emphasized + ” or “ + <literal> + literal + ” text + and links to “ + <reference name="targets" refname="targets"> + targets + ”. + <list_item> + <paragraph> + Inside \n\ + <emphasis> + “emphasized” + or other \n\ + <title_reference> + inline “roles”\ +"""], ]) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mi...@us...> - 2012-11-23 01:18:57
|
Revision: 7538 http://docutils.svn.sourceforge.net/docutils/?rev=7538&view=rev Author: milde Date: 2012-11-23 01:18:49 +0000 (Fri, 23 Nov 2012) Log Message: ----------- normalize_language_tag() now returns `BCP 47`_ conformant tags Subtags separated by ``-``, not ``_``. Modified Paths: -------------- trunk/docutils/HISTORY.txt trunk/docutils/docutils/languages/__init__.py trunk/docutils/docutils/parsers/rst/languages/__init__.py trunk/docutils/docutils/utils/__init__.py trunk/docutils/docutils/writers/latex2e/__init__.py trunk/docutils/docutils/writers/xetex/__init__.py trunk/docutils/test/test_utils.py Modified: trunk/docutils/HISTORY.txt =================================================================== --- trunk/docutils/HISTORY.txt 2012-11-18 22:11:49 UTC (rev 7537) +++ trunk/docutils/HISTORY.txt 2012-11-23 01:18:49 UTC (rev 7538) @@ -43,6 +43,11 @@ - Add SmartQuotes transform for typographic quotes and dashes. +* docutils/utils/__init__.py + + - normalize_language_tag() now returns `BCP 47`_ conformant tags + with subtags separated by ``-``. + * docutils/writers/html4css1/__init__.py - Use ``<code>`` tag for inline "code", Modified: trunk/docutils/docutils/languages/__init__.py =================================================================== --- trunk/docutils/docutils/languages/__init__.py 2012-11-18 22:11:49 UTC (rev 7537) +++ trunk/docutils/docutils/languages/__init__.py 2012-11-23 01:18:49 UTC (rev 7538) @@ -27,6 +27,7 @@ """ # TODO: use a dummy module returning emtpy strings?, configurable? for tag in normalize_language_tag(language_code): + tag = tag.replace('-','_') # '-' not valid in module names if tag in _languages: return _languages[tag] try: Modified: trunk/docutils/docutils/parsers/rst/languages/__init__.py =================================================================== --- trunk/docutils/docutils/parsers/rst/languages/__init__.py 2012-11-18 22:11:49 UTC (rev 7537) +++ trunk/docutils/docutils/parsers/rst/languages/__init__.py 2012-11-23 01:18:49 UTC (rev 7538) @@ -22,6 +22,7 @@ def get_language(language_code): for tag in normalize_language_tag(language_code): + tag = tag.replace('-','_') # '-' not valid in module names if tag in _languages: return _languages[tag] try: Modified: trunk/docutils/docutils/utils/__init__.py =================================================================== --- trunk/docutils/docutils/utils/__init__.py 2012-11-18 22:11:49 UTC (rev 7537) +++ trunk/docutils/docutils/utils/__init__.py 2012-11-23 01:18:49 UTC (rev 7538) @@ -12,6 +12,7 @@ import sys import os import os.path +import re import warnings import unicodedata from docutils import ApplicationError, DataError @@ -642,20 +643,20 @@ Example: - >>> normalize_language_tag('de-AT-1901') - ['de_at_1901', 'de_at', 'de_1901', 'de'] + >>> normalize_language_tag('de_AT-1901') + ['de-at-1901', 'de-at', 'de-1901', 'de'] """ # normalize: - tag = tag.lower().replace('-','_') + tag = tag.lower().replace('_','-') + # split (except singletons, which mark the following tag as non-standard): + tag = re.sub(r'-([a-zA-Z0-9])-', r'-\1_', tag) + taglist = [] + subtags = [subtag.replace('_', '-') for subtag in tag.split('-')] + base_tag = [subtags.pop(0)] # find all combinations of subtags - taglist = [] - base_tag= tag.split('_')[:1] - subtags = tag.split('_')[1:] - # print base_tag, subtags for n in range(len(subtags), 0, -1): for tags in unique_combinations(subtags, n): - # print tags - taglist.append('_'.join(base_tag + tags)) + taglist.append('-'.join(base_tag+tags)) taglist += base_tag return taglist Modified: trunk/docutils/docutils/writers/latex2e/__init__.py =================================================================== --- trunk/docutils/docutils/writers/latex2e/__init__.py 2012-11-18 22:11:49 UTC (rev 7537) +++ trunk/docutils/docutils/writers/latex2e/__init__.py 2012-11-23 01:18:49 UTC (rev 7538) @@ -293,18 +293,18 @@ 'cy': 'welsh', 'da': 'danish', 'de': 'ngerman', # new spelling (de_1996) - 'de_1901': 'german', # old spelling - 'de_at': 'naustrian', - 'de_at_1901': 'austrian', + 'de-1901': 'german', # old spelling + 'de-AT': 'naustrian', + 'de-AT-1901': 'austrian', 'dsb': 'lowersorbian', 'el': 'greek', # monotonic (el-monoton) - 'el_polyton': 'polutonikogreek', + 'el-polyton': 'polutonikogreek', 'en': 'english', # TeX' default language - 'en_au': 'australian', - 'en_ca': 'canadian', - 'en_gb': 'british', - 'en_nz': 'newzealand', - 'en_us': 'american', + 'en-AU': 'australian', + 'en-CA': 'canadian', + 'en-GB': 'british', + 'en-NZ': 'newzealand', + 'en-US': 'american', 'eo': 'esperanto', # '^' is active 'es': 'spanish', 'et': 'estonian', @@ -312,10 +312,10 @@ # 'fa': 'farsi', 'fi': 'finnish', 'fr': 'french', - 'fr_ca': 'canadien', + 'fr-CA': 'canadien', 'ga': 'irish', # Irish Gaelic # 'grc': # Ancient Greek - 'grc_ibycus': 'ibycus', # Ibycus encoding + 'grc-ibycus': 'ibycus', # Ibycus encoding 'gl': 'galician', 'he': 'hebrew', 'hr': 'croatian', @@ -338,24 +338,27 @@ 'no': 'norsk', # Norwegian Bokmal 'pl': 'polish', 'pt': 'portuges', - 'pt_br': 'brazil', + 'pt-BR': 'brazil', 'ro': 'romanian', 'ru': 'russian', # '"' is active 'se': 'samin', # North Sami - # sh-cyrl: Serbo-Croatian, Cyrillic script - 'sh-latn': 'serbian', # Serbo-Croatian, Latin script + # sh-Cyrl: Serbo-Croatian, Cyrillic script + 'sh-Latn': 'serbian', # Serbo-Croatian, Latin script 'sk': 'slovak', 'sl': 'slovene', 'sq': 'albanian', - # 'sr-cyrl': Serbian, Cyrillic script (sr-cyrl) - 'sr-latn': 'serbian', # Serbian, Latin script, " active. + # 'sr-Cyrl': Serbian, Cyrillic script (sr-cyrl) + 'sr-Latn': 'serbian', # Serbian, Latin script, " active. 'sv': 'swedish', # 'th': 'thai', 'tr': 'turkish', 'uk': 'ukrainian', 'vi': 'vietnam', - # zh-latn: Chinese Pinyin + # zh-Latn: Chinese Pinyin } + # normalize (downcase) keys + language_codes = dict([(k.lower(), v) for (k,v) in language_codes.items()]) + warn_msg = 'Language "%s" not supported by LaTeX (babel)' def __init__(self, language_code, reporter=None): @@ -1595,8 +1598,12 @@ self.out.append( '%\n\\begin{list}{}{}\n' ) else: self.out.append( '%\n\\begin{itemize}\n' ) + # if node['classes']: + # self.visit_inline(node) def depart_bullet_list(self, node): + # if node['classes']: + # self.depart_inline(node) if self.is_toc_list: self.out.append( '\n\\end{list}\n' ) else: Modified: trunk/docutils/docutils/writers/xetex/__init__.py =================================================================== --- trunk/docutils/docutils/writers/xetex/__init__.py 2012-11-18 22:11:49 UTC (rev 7537) +++ trunk/docutils/docutils/writers/xetex/__init__.py 2012-11-23 01:18:49 UTC (rev 7538) @@ -76,30 +76,33 @@ # code Polyglossia-name comment 'cop': 'coptic', 'de': 'german', # new spelling (de_1996) - 'de_1901': 'ogerman', # old spelling + 'de-1901': 'ogerman', # old spelling 'dv': 'divehi', # Maldivian 'dsb': 'lsorbian', - 'el_polyton': 'polygreek', + 'el-polyton': 'polygreek', 'fa': 'farsi', 'grc': 'ancientgreek', 'hsb': 'usorbian', - 'sh-cyrl': 'serbian', # Serbo-Croatian, Cyrillic script - 'sh-latn': 'croatian', # Serbo-Croatian, Latin script + 'sh-Cyrl': 'serbian', # Serbo-Croatian, Cyrillic script + 'sh-Latn': 'croatian', # Serbo-Croatian, Latin script 'sq': 'albanian', - 'sr': 'serbian', # Cyrillic script (sr-cyrl) + 'sr': 'serbian', # Cyrillic script (sr-Cyrl) 'th': 'thai', 'vi': 'vietnamese', - # zh-latn: ??? # Chinese Pinyin + # zh-Latn: ??? # Chinese Pinyin }) + # normalize (downcase) keys + language_codes = dict([(k.lower(), v) for (k,v) in language_codes.items()]) + # Languages without Polyglossia support: for key in ('af', # 'afrikaans', - 'de_at', # 'naustrian', - 'de_at_1901', # 'austrian', - 'fr_ca', # 'canadien', - 'grc_ibycus', # 'ibycus', (Greek Ibycus encoding) - 'sr-latn', # 'serbian script=latin' + 'de-AT', # 'naustrian', + 'de-AT-1901', # 'austrian', + 'fr-CA', # 'canadien', + 'grc-ibycus', # 'ibycus', (Greek Ibycus encoding) + 'sr-Latn', # 'serbian script=latin' ): - del(language_codes[key]) + del(language_codes[key.lower()]) def __init__(self, language_code, reporter): self.language_code = language_code Modified: trunk/docutils/test/test_utils.py =================================================================== --- trunk/docutils/test/test_utils.py 2012-11-18 22:11:49 UTC (rev 7537) +++ trunk/docutils/test/test_utils.py 2012-11-23 01:18:49 UTC (rev 7538) @@ -240,12 +240,15 @@ def test_normalize_language_tag(self): self.assertEqual(utils.normalize_language_tag('de'), ['de']) self.assertEqual(utils.normalize_language_tag('de-AT'), - ['de_at', 'de']) + ['de-at', 'de']) self.assertEqual(utils.normalize_language_tag('de-AT-1901'), - ['de_at_1901', 'de_at', 'de_1901', 'de']) + ['de-at-1901', 'de-at', 'de-1901', 'de']) self.assertEqual(utils.normalize_language_tag('de-AT-1901-frak'), - ['de_at_1901_frak', 'de_at_1901', 'de_at_frak', - 'de_1901_frak', 'de_at', 'de_1901', 'de_frak', 'de']) + ['de-at-1901-frak', 'de-at-1901', 'de-at-frak', + 'de-1901-frak', 'de-at', 'de-1901', 'de-frak', 'de']) + self.assertEqual(utils.normalize_language_tag('grc-ibycus-x-altquot'), + ['grc-ibycus-x-altquot', 'grc-ibycus', + 'grc-x-altquot', 'grc']) def test_column_width(self): self.assertEqual(utils.column_width(u'de'), 2) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mi...@us...> - 2012-11-26 13:50:13
|
Revision: 7539 http://docutils.svn.sourceforge.net/docutils/?rev=7539&view=rev Author: milde Date: 2012-11-26 13:50:06 +0000 (Mon, 26 Nov 2012) Log Message: ----------- Use True/False for booleans. frontend.validate_ternary() returns True/False or value. Modified Paths: -------------- trunk/docutils/docutils/frontend.py trunk/docutils/test/DocutilsTestSupport.py trunk/docutils/test/test_functional.py trunk/docutils/test/test_pickle.py trunk/docutils/test/test_publisher.py trunk/docutils/test/test_settings.py Modified: trunk/docutils/docutils/frontend.py =================================================================== --- trunk/docutils/docutils/frontend.py 2012-11-23 01:18:49 UTC (rev 7538) +++ trunk/docutils/docutils/frontend.py 2012-11-26 13:50:06 UTC (rev 7539) @@ -128,17 +128,15 @@ config_parser=None, config_section=None): """Check/normalize three-value settings: True: '1', 'on', 'yes', 'true' - False: '0', 'off', 'no','false', - None: any other value (including '') + False: '0', 'off', 'no','false', '' + any other value: returned as-is. """ if isinstance(value, bool) or value is None: return value - if value == '': - return None try: return option_parser.booleans[value.strip().lower()] except KeyError: - return None + return value def validate_nonnegative_int(setting, value, option_parser, config_parser=None, config_section=None): @@ -349,8 +347,8 @@ thresholds = {'info': 1, 'warning': 2, 'error': 3, 'severe': 4, 'none': 5} """Lookup table for --report and --halt threshold values.""" - booleans={'1': 1, 'on': 1, 'yes': 1, 'true': 1, - '0': 0, 'off': 0, 'no': 0, 'false': 0, '': 0} + booleans={'1': True, 'on': True, 'yes': True, 'true': True, + '0': False, 'off': False, 'no': False, 'false': False, '': False} """Lookup table for boolean configuration file settings.""" default_error_encoding = getattr(sys.stderr, 'encoding', Modified: trunk/docutils/test/DocutilsTestSupport.py =================================================================== --- trunk/docutils/test/DocutilsTestSupport.py 2012-11-23 01:18:49 UTC (rev 7538) +++ trunk/docutils/test/DocutilsTestSupport.py 2012-11-26 13:50:06 UTC (rev 7539) @@ -706,8 +706,8 @@ Test case for publish. """ - settings_default_overrides = {'_disable_config': 1, - 'strict_visitor': 1} + settings_default_overrides = {'_disable_config': True, + 'strict_visitor': True} writer_name = '' # set in subclasses or constructor def __init__(self, *args, **kwargs): Modified: trunk/docutils/test/test_functional.py =================================================================== --- trunk/docutils/test/test_functional.py 2012-11-23 01:18:49 UTC (rev 7538) +++ trunk/docutils/test/test_functional.py 2012-11-26 13:50:06 UTC (rev 7539) @@ -123,7 +123,7 @@ namespace = {} # Initialize 'settings_overrides' for test settings scripts, # and disable configuration files: - namespace['settings_overrides'] = {'_disable_config': 1} + namespace['settings_overrides'] = {'_disable_config': True} # Read the variables set in the default config file and in # the current config file into namespace: defaultpy = open(join_path(datadir, 'tests', '_default.py')).read() Modified: trunk/docutils/test/test_pickle.py =================================================================== --- trunk/docutils/test/test_pickle.py 2012-11-23 01:18:49 UTC (rev 7538) +++ trunk/docutils/test/test_pickle.py 2012-11-26 13:50:06 UTC (rev 7539) @@ -18,7 +18,7 @@ def test_pickle(self): doctree = core.publish_doctree( source='Title\n=====\n\nparagraph\n', - settings_overrides={'_disable_config': 1}) + settings_overrides={'_disable_config': True}) dill = pickle.dumps(doctree) reconstituted = pickle.loads(dill) self.assertEqual(doctree.pformat(), reconstituted.pformat()) Modified: trunk/docutils/test/test_publisher.py =================================================================== --- trunk/docutils/test/test_publisher.py 2012-11-23 01:18:49 UTC (rev 7538) +++ trunk/docutils/test/test_publisher.py 2012-11-26 13:50:06 UTC (rev 7539) @@ -79,7 +79,7 @@ class PublishDoctreeTestCase(DocutilsTestSupport.StandardTestCase, docutils.SettingsSpec): settings_default_overrides = { - '_disable_config': 1, + '_disable_config': True, 'warning_stream': io.NullOutput()} def test_publish_doctree(self): Modified: trunk/docutils/test/test_settings.py =================================================================== --- trunk/docutils/test/test_settings.py 2012-11-23 01:18:49 UTC (rev 7538) +++ trunk/docutils/test/test_settings.py 2012-11-26 13:50:06 UTC (rev 7539) @@ -39,28 +39,28 @@ settings = { 'old': {u'datestamp': u'%Y-%m-%d %H:%M UTC', - u'generator': 1, - u'no_random': 1, + u'generator': True, + u'no_random': True, u'python_home': u'http://www.python.org', - u'source_link': 1, + u'source_link': True, 'stylesheet': None, u'stylesheet_path': [fixpath(u'data/stylesheets/pep.css')], 'template': fixpath(u'data/pep-html-template')}, 'one': {u'datestamp': u'%Y-%m-%d %H:%M UTC', - u'generator': 1, - u'no_random': 1, + u'generator': True, + u'no_random': True, u'python_home': u'http://www.python.org', - u'raw_enabled': 0, + u'raw_enabled': False, 'record_dependencies': utils.DependencyList(), - u'source_link': 1, + u'source_link': True, 'stylesheet': None, u'stylesheet_path': [fixpath(u'data/stylesheets/pep.css')], u'tab_width': 8, u'template': fixpath(u'data/pep-html-template'), - u'trim_footnote_reference_space': 1, + u'trim_footnote_reference_space': True, }, 'two': {u'footnote_references': u'superscript', - u'generator': 0, + u'generator': False, 'record_dependencies': utils.DependencyList(), u'stylesheet': None, u'stylesheet_path': [fixpath(u'data/test.css')], This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mi...@us...> - 2012-11-26 14:06:27
|
Revision: 7540 http://docutils.svn.sourceforge.net/docutils/?rev=7540&view=rev Author: milde Date: 2012-11-26 14:06:19 +0000 (Mon, 26 Nov 2012) Log Message: ----------- SmartQuotes transform: language-depended quote characters. Modified Paths: -------------- trunk/docutils/HISTORY.txt trunk/docutils/RELEASE-NOTES.txt trunk/docutils/docs/user/config.txt trunk/docutils/docutils/nodes.py trunk/docutils/docutils/transforms/universal.py trunk/docutils/docutils/utils/smartquotes.py trunk/docutils/test/test_transforms/test_smartquotes.py Modified: trunk/docutils/HISTORY.txt =================================================================== --- trunk/docutils/HISTORY.txt 2012-11-26 13:50:06 UTC (rev 7539) +++ trunk/docutils/HISTORY.txt 2012-11-26 14:06:19 UTC (rev 7540) @@ -5,7 +5,7 @@ ================== :Author: David Goodger; open to all Docutils developers -:Contact: go...@py... +:Contact: doc...@li... :Date: $Date$ :Revision: $Revision$ :Web site: http://docutils.sourceforge.net/ @@ -41,7 +41,7 @@ * docutils/transforms/universal.py - - Add SmartQuotes transform for typographic quotes and dashes. + - SmartQuotes transform for typographic quotes and dashes. * docutils/utils/__init__.py Modified: trunk/docutils/RELEASE-NOTES.txt =================================================================== --- trunk/docutils/RELEASE-NOTES.txt 2012-11-26 13:50:06 UTC (rev 7539) +++ trunk/docutils/RELEASE-NOTES.txt 2012-11-26 14:06:19 UTC (rev 7540) @@ -3,6 +3,7 @@ ======================== :Contact: gr...@us... +:Maintainer: doc...@li... :Date: $Date$ :Revision: $Revision$ :Web site: http://docutils.sourceforge.net/ @@ -40,6 +41,8 @@ * General: + - SmartQuotes transform for typographic quotes and dashes. + - ``docutils/math``, ``docutils/error_reporting.py``, and ``docutils/urischemes.py`` moved to the utils package. Code importing these modules needs to adapt, e.g.:: Modified: trunk/docutils/docs/user/config.txt =================================================================== --- trunk/docutils/docs/user/config.txt 2012-11-26 13:50:06 UTC (rev 7539) +++ trunk/docutils/docs/user/config.txt 2012-11-26 14:06:19 UTC (rev 7540) @@ -86,7 +86,7 @@ interchangably in entry names; hyphens are automatically converted to underscores. -For on/off switch settings (booleans), the following values are +For on/off switch settings (_`booleans`), the following values are recognized: :On: "true", "yes", "on", "1" @@ -94,8 +94,8 @@ List values can be comma- or colon-delimited. -strip_classes_, strip_elements_with_classes_, stylesheet_, and -stylesheet_path_ use the comma as delimiter, +strip_classes_, strip_elements_with_classes_, stylesheet, and +stylesheet_path use the comma as delimiter, whitespace around list values is stripped. :: strip-classes: ham,eggs, @@ -588,7 +588,6 @@ _`syntax_highlight` - Token type names used by Pygments_ when parsing contents of the code_ directive and role. @@ -605,12 +604,36 @@ Default: "long". Option: ``--syntax-highlight``. + New in Docutils 0.9. + .. _Pygments: http://pygments.org/ .. _code: ../ref/rst/directives.html#code .. _Pygments-generated stylesheets: http://pygments.org/docs/cmdline/#generating-styles +_`smart_quotes` + Change straight quotation marks to typographic form. `Quote characters`_ + are selected according to the language of the current block element (see + language_code_). Also changes consequtive runs of hyphen-minus and full + stops (``---``, ``--``, ``...``) to em-dash, en-dash and ellipsis + Unicode characters respectively. + Supported values: + + booleans_ (yes/no) + Use smart quotes? + + alt (or "alternative") + Use alternative quote set (if defined for the language). + + Default: "no". Option: ``--smart-quotes``. + + New in Docutils 0.10. + +.. _quote characters: + http://en.wikipedia.org/wiki/Non-English_usage_of_quotation_marks + + [readers] --------- Modified: trunk/docutils/docutils/nodes.py =================================================================== --- trunk/docutils/docutils/nodes.py 2012-11-26 13:50:06 UTC (rev 7539) +++ trunk/docutils/docutils/nodes.py 2012-11-26 14:06:19 UTC (rev 7540) @@ -269,7 +269,7 @@ index = node.parent.index(node) for sibling in node.parent[index+1:]: r.extend(sibling.traverse(include_self=True, - descend=descend, + descend=descend, siblings=False, ascend=False, condition=condition)) if not ascend: @@ -620,9 +620,24 @@ has_key = hasattr - # support operator in + # support operator ``in`` __contains__ = hasattr + def get_language_code(self, fallback=''): + """Return node's language tag. + + Look iteratively in self and parents for a class argument + starting with ``language-`` and return the remainder of it + (which should be a `BCP49` language tag) or the `fallback`. + """ + for cls in self.get('classes', []): + if cls.startswith('language-'): + return cls[9:] + try: + return self.parent.get_language(fallback) + except AttributeError: + return fallback + def append(self, item): self.setup_child(item) self.children.append(item) Modified: trunk/docutils/docutils/transforms/universal.py =================================================================== --- trunk/docutils/docutils/transforms/universal.py 2012-11-26 13:50:06 UTC (rev 7539) +++ trunk/docutils/docutils/transforms/universal.py 2012-11-26 14:06:19 UTC (rev 7540) @@ -1,5 +1,7 @@ # $Id$ -# Authors: David Goodger <go...@py...>; Ueli Schlaepfer +# -*- coding: utf8 -*- +# Authors: David Goodger <go...@py...>; Ueli Schlaepfer; Günter Milde +# Maintainer: doc...@li... # Copyright: This module has been placed in the public domain. """ @@ -212,13 +214,38 @@ default_priority = 850 - texttype = {True: 'literal', - False: 'plain'} + def __init__(self, document, startnode): + Transform.__init__(self, document, startnode=startnode) + self.unsupported_languages = set() + def get_tokens(self, txtnodes): + # A generator that yields ``(texttype, nodetext)`` tuples for a list + # of "Text" nodes (interface to ``smartquotes.educate_tokens()``). + + texttype = {True: 'literal', # "literal" text is not changed: + False: 'plain'} + for txtnode in txtnodes: + nodetype = texttype[isinstance(txtnode.parent, + (nodes.literal, + nodes.math, + nodes.image, + nodes.raw, + nodes.problematic))] + yield (nodetype, txtnode.astext()) + + def apply(self): - if self.document.settings.smart_quotes is False: + smart_quotes = self.document.settings.smart_quotes + if not smart_quotes: return - + try: + alternative = smart_quotes.startswith('alt') + except AttributeError: + alternative = False + # print repr(alternative) + + document_language = self.document.settings.language_code + # "Educate" quotes in normal text. Handle each block of text # (TextElement node) as a unit to keep context around inline nodes: for node in self.document.traverse(nodes.TextElement): @@ -233,20 +260,33 @@ txtnodes = [txtnode for txtnode in node.traverse(nodes.Text) if not isinstance(txtnode.parent, nodes.option_string)] - # smartquotes.educate_tokens() iterates over - # ``(texttype, nodetext)`` tuples. `texttype` is "literal" - # or "plain" where "literal" text is not changed: - tokens = [(self.texttype[isinstance(txtnode.parent, - (nodes.literal, - nodes.math, - nodes.image, - nodes.raw, - nodes.problematic))], - txtnode.astext()) for txtnode in txtnodes] - # Iterator educating quotes in plain text - # 2 : set all, using old school en- and em- dash shortcuts - teacher = smartquotes.educate_tokens(tokens, attr='2') + # language: use smart-quotes for language "lang" + lang = node.get_language_code(document_language) + # use alternative form if `smart-quotes` setting starts with "alt": + if alternative: + if '-x-altquot' in lang: + lang = lang.replace('-x-altquot', '') + else: + lang += '-x-altquot' + # drop subtags missing in quotes: + for tag in utils.normalize_language_tag(lang): + if tag in smartquotes.smartchars.quotes: + lang = tag + break + else: # language not supported: (keep ASCII quotes) + if lang not in self.unsupported_languages: + self.document.reporter.warning('No smart quotes ' + 'defined for language "%s".'%lang, base_node=node) + self.unsupported_languages.add(lang) + lang = '' + # Iterator educating quotes in plain text: + # '2': set all, using old school en- and em- dash shortcuts + teacher = smartquotes.educate_tokens(self.get_tokens(txtnodes), + attr='2', language=lang) + for txtnode, newtext in zip(txtnodes, teacher): txtnode.parent.replace(txtnode, nodes.Text(newtext)) + + self.unsupported_languages = set() # reset Modified: trunk/docutils/docutils/utils/smartquotes.py =================================================================== --- trunk/docutils/docutils/utils/smartquotes.py 2012-11-26 13:50:06 UTC (rev 7539) +++ trunk/docutils/docutils/utils/smartquotes.py 2012-11-26 14:06:19 UTC (rev 7540) @@ -5,6 +5,7 @@ # :Copyright: © 2010 Günter Milde, # original `SmartyPants`_: © 2003 John Gruber # smartypants.py: © 2004, 2007 Chad Miller +# :Maintainer: doc...@li... # :License: Released under the terms of the `2-Clause BSD license`_, in short: # # Copying and distribution of this file, with or without modification, @@ -176,7 +177,7 @@ ======== ===== ========= This is useful, for example, when you want to use straight quotes as -foot and inch marks: 6'2" tall; a 17" iMac. +foot and inch marks: 6\\'2\\" tall; a 17\\" iMac. Options ======= @@ -207,7 +208,7 @@ "-1" Stupefy mode. Reverses the SmartyPants transformation process, turning the characters produced by SmartyPants into their ASCII equivalents. - E.g. "“" is turned into a simple double-quote ("), "—" is + E.g. "“" is turned into a simple double-quote (\"), "—" is turned into two dashes, etc. @@ -313,6 +314,9 @@ Version History =============== +1.7 2012-11-19 + - Internationalization: language-dependent quotes. + 1.6.1: 2012-11-06 - Refactor code, code cleanup, - `educate_tokens()` generator as interface for Docutils. @@ -359,30 +363,88 @@ import re -class smart(object): +class smartchars(object): """Smart quotes and dashes + """ - TODO: internationalization, see e.g. - http://de.wikipedia.org/wiki/Anf%C3%BChrungszeichen#Andere_Sprachen - """ endash = u'–' # "–" EN DASH emdash = u'—' # "—" EM DASH - lquote = u'‘' # "‘" LEFT SINGLE QUOTATION MARK - rquote = u'’' # "’" RIGHT SINGLE QUOTATION MARK - #lquote = u'‚' # "‚" SINGLE LOW-9 QUOTATION MARK (German) - ldquote = u'“' # "“" LEFT DOUBLE QUOTATION MARK - rdquote = u'”' # "”" RIGHT DOUBLE QUOTATION MARK - #ldquote = u'„' # "𔄤" DOUBLE LOW-9 QUOTATION MARK (German) ellipsis = u'…' # "…" HORIZONTAL ELLIPSIS -def smartyPants(text, attr=default_smartypants_attr): + # quote characters (language-specific, set in __init__()) + # + # English smart quotes (open primary, close primary, open secondary, close + # secondary) are: + # opquote = u'“' # "“" LEFT DOUBLE QUOTATION MARK + # cpquote = u'”' # "”" RIGHT DOUBLE QUOTATION MARK + # osquote = u'‘' # "‘" LEFT SINGLE QUOTATION MARK + # csquote = u'’' # "’" RIGHT SINGLE QUOTATION MARK + # For other languages see: + # http://en.wikipedia.org/wiki/Non-English_usage_of_quotation_marks + # http://de.wikipedia.org/wiki/Anf%C3%BChrungszeichen#Andere_Sprachen + quotes = {'af': u'“”‘’', + 'af-x-altquot': u'„”‚’', + 'ca': u'«»“”', + 'ca-x-altquot': u'“”‘’', + 'cs': u'„“‚‘', + 'cs-x-altquot': u'»«›‹', + 'de': u'„“‚‘', + 'de-x-altquot': u'»«›‹', + 'de-ch': u'«»‹›', + 'el': u'«»“”', + 'en': u'“”‘’', + 'en-UK': u'‘’“”', + 'eo': u'“”‘’', + 'es': u'«»“”', + 'es-x-altquot': u'“”‘’', + 'fi': u'””’’', + 'fi-x-altquot': u'»»’’', + 'fr': (u'« ', u' »', u'‹ ', u' ›'), + 'fr-x-altquot': (u'“ ', u' ”', u'‘ ', u' ’'), + 'fr-ch': u'«»‹›', + 'he': u'”“»«', + 'he-x-altquot': u'„”‚’', + 'it': u'«»“”', + 'it-ch': u'«»‹›', + 'it-x-altquot': u'“”‘’', + 'ja': u'「」『』', + 'lt': u'„“‚‘', + 'nl': u'“”‘’', + 'nl-x-altquot': u'„”‚’', + 'pl': u'„”«»', + 'pl-x-altquot': u'«»“”', + 'pt': u'«»“”', + 'pt_br': u'“”‘’', + 'ro': u'„”«»', + 'ro-x-altquot': u'«»„”', + 'ru': u'«»„“', + 'sk': u'„“‚‘', + 'sk-x-altquot': u'»«›‹', + 'sv': u'„“‚‘', + 'sv-x-altquot': u'»«›‹', + 'zh_cn': u'“”‘’', + 'it': u'«»“”', + 'zh_tw': u'「」『』', + } + + def __init__(self, language='en'): + self.language = language + try: + (self.opquote, self.cpquote, + self.osquote, self.csquote) = self.quotes[language] + except KeyError: + self.opquote, self.cpquote, self.osquote, self.csquote = u'""\'\'' + + +def smartyPants(text, attr=default_smartypants_attr, language='en'): """Main function for "traditional" use.""" - return "".join([t for t in educate_tokens(tokenize(text), attr)]) + return "".join([t for t in educate_tokens(tokenize(text), + attr, language)]) -def educate_tokens(text_tokens, attr=default_smartypants_attr): - """Return iterator that "educates" `text_tokens`. +def educate_tokens(text_tokens, attr=default_smartypants_attr, language='en'): + """Return iterator that "educates" the items of `text_tokens`. """ # Parse attributes: @@ -439,84 +501,89 @@ if "w" in attr: convert_quot = True prev_token_last_char = " " - # Get context around inline mark-up. (Remember the last character of the - # previous text token, to use as context to curl single-character quote - # tokens correctly.) + # Last character of the previous text token. Used as + # context to curl leading quote characters correctly. - for cur_token in text_tokens: - t = cur_token[1] + for (ttype, text) in text_tokens: # skip HTML and/or XML tags (do not update last character) - if cur_token[0] == 'tag': - yield t + if ttype == 'tag': + yield text continue - last_char = t[-1:] # Remember last char of this token before processing. - # skip literal text (math, literal, raw, ...) - if cur_token[0] == 'literal': - yield t + if ttype == 'literal': + prev_token_last_char = text[-1] + yield text continue - t = processEscapes(t) + last_char = text[-1:] # Remember last char before processing. + text = processEscapes(text) + if convert_quot: - t = re.sub('"', '"', t) + text = re.sub('"', '"', text) if do_dashes == 1: - t = educateDashes(t) + text = educateDashes(text) elif do_dashes == 2: - t = educateDashesOldSchool(t) + text = educateDashesOldSchool(text) elif do_dashes == 3: - t = educateDashesOldSchoolInverted(t) + text = educateDashesOldSchoolInverted(text) if do_ellipses: - t = educateEllipses(t) + text = educateEllipses(text) # Note: backticks need to be processed before quotes. if do_backticks: - t = educateBackticks(t) + text = educateBackticks(text, language) if do_backticks == 2: - t = educateSingleBackticks(t) + text = educateSingleBackticks(text, language) if do_quotes: - t = educateQuotes(prev_token_last_char+t)[1:] + text = educateQuotes(prev_token_last_char+text, language)[1:] if do_stupefy: - t = stupefyEntities(t) + text = stupefyEntities(text, language) - # print prev_token_last_char, t.encode('utf8') + # Remember last char as context for the next token prev_token_last_char = last_char - yield t + text = processEscapes(text, restore=True) + yield text -def educateQuotes(text): + +def educateQuotes(text, language='en'): """ - Parameter: String (unicode or bytes). + Parameter: - text string (unicode or bytes). + - language (`BCP 47` language tag.) Returns: The `text`, with "educated" curly quote characters. Example input: "Isn't this fun?" Example output: “Isn’t this fun?“; """ + smart = smartchars(language) + # oldtext = text punct_class = r"""[!"#\$\%'()*+,-.\/:;<=>?\@\[\\\]\^_`{|}~]""" # Special case if the very first character is a quote - # followed by punctuation at a non-word-break. Close the quotes by brute force: - text = re.sub(r"""^'(?=%s\\B)""" % (punct_class,), smart.rquote, text) - text = re.sub(r"""^"(?=%s\\B)""" % (punct_class,), smart.rdquote, text) + # followed by punctuation at a non-word-break. + # Close the quotes by brute force: + text = re.sub(r"""^'(?=%s\\B)""" % (punct_class,), smart.csquote, text) + text = re.sub(r"""^"(?=%s\\B)""" % (punct_class,), smart.cpquote, text) # Special case for double sets of quotes, e.g.: # <p>He said, "'Quoted' words in a larger quote."</p> - text = re.sub(r""""'(?=\w)""", smart.ldquote+smart.lquote, text) - text = re.sub(r"""'"(?=\w)""", smart.lquote+smart.ldquote, text) + text = re.sub(r""""'(?=\w)""", smart.opquote+smart.osquote, text) + text = re.sub(r"""'"(?=\w)""", smart.osquote+smart.opquote, text) # Special case for decade abbreviations (the '80s): - text = re.sub(r"""\b'(?=\d{2}s)""", smart.rquote, text) + text = re.sub(r"""\b'(?=\d{2}s)""", smart.csquote, text) close_class = r"""[^\ \t\r\n\[\{\(\-]""" dec_dashes = r"""–|—""" @@ -534,24 +601,24 @@ ' # the quote (?=\w) # followed by a word character """ % (dec_dashes,), re.VERBOSE) - text = opening_single_quotes_regex.sub(r'\1'+smart.lquote, text) + text = opening_single_quotes_regex.sub(r'\1'+smart.osquote, text) closing_single_quotes_regex = re.compile(r""" (%s) ' (?!\s | s\b | \d) """ % (close_class,), re.VERBOSE) - text = closing_single_quotes_regex.sub(r'\1'+smart.rquote, text) + text = closing_single_quotes_regex.sub(r'\1'+smart.csquote, text) closing_single_quotes_regex = re.compile(r""" (%s) ' (\s | s\b) """ % (close_class,), re.VERBOSE) - text = closing_single_quotes_regex.sub(r'\1%s\2' % smart.rquote, text) + text = closing_single_quotes_regex.sub(r'\1%s\2' % smart.csquote, text) # Any remaining single quotes should be opening ones: - text = re.sub(r"""'""", smart.lquote, text) + text = re.sub(r"""'""", smart.osquote, text) # Get most opening double quotes: opening_double_quotes_regex = re.compile(r""" @@ -566,7 +633,7 @@ " # the quote (?=\w) # followed by a word character """ % (dec_dashes,), re.VERBOSE) - text = opening_double_quotes_regex.sub(r'\1'+smart.ldquote, text) + text = opening_double_quotes_regex.sub(r'\1'+smart.opquote, text) # Double closing quotes: closing_double_quotes_regex = re.compile(r""" @@ -574,21 +641,21 @@ " (?=\s) """ % (close_class,), re.VERBOSE) - text = closing_double_quotes_regex.sub(smart.rdquote, text) + text = closing_double_quotes_regex.sub(smart.cpquote, text) closing_double_quotes_regex = re.compile(r""" (%s) # character that indicates the quote should be closing " """ % (close_class,), re.VERBOSE) - text = closing_double_quotes_regex.sub(r'\1'+smart.rdquote, text) + text = closing_double_quotes_regex.sub(r'\1'+smart.cpquote, text) # Any remaining quotes should be opening ones. - text = re.sub(r'"', smart.ldquote, text) + text = re.sub(r'"', smart.opquote, text) return text -def educateBackticks(text): +def educateBackticks(text, language='en'): """ Parameter: String (unicode or bytes). Returns: The `text`, with ``backticks'' -style double quotes @@ -596,13 +663,14 @@ Example input: ``Isn't this fun?'' Example output: “Isn't this fun?“; """ + smart = smartchars(language) - text = re.sub(r"""``""", smart.ldquote, text) - text = re.sub(r"""''""", smart.rdquote, text) + text = re.sub(r"""``""", smart.opquote, text) + text = re.sub(r"""''""", smart.cpquote, text) return text -def educateSingleBackticks(text): +def educateSingleBackticks(text, language='en'): """ Parameter: String (unicode or bytes). Returns: The `text`, with `backticks' -style single quotes @@ -611,9 +679,10 @@ Example input: `Isn't this fun?' Example output: ‘Isn’t this fun?’ """ + smart = smartchars(language) - text = re.sub(r"""`""", smart.lquote, text) - text = re.sub(r"""'""", smart.rquote, text) + text = re.sub(r"""`""", smart.osquote, text) + text = re.sub(r"""'""", smart.csquote, text) return text @@ -624,8 +693,8 @@ an em-dash character. """ - text = re.sub(r"""---""", smart.endash, text) # en (yes, backwards) - text = re.sub(r"""--""", smart.emdash, text) # em (yes, backwards) + text = re.sub(r"""---""", smartchars.endash, text) # en (yes, backwards) + text = re.sub(r"""--""", smartchars.emdash, text) # em (yes, backwards) return text @@ -637,8 +706,8 @@ an em-dash character. """ - text = re.sub(r"""---""", smart.emdash, text) # em (yes, backwards) - text = re.sub(r"""--""", smart.endash, text) # en (yes, backwards) + text = re.sub(r"""---""", smartchars.emdash, text) + text = re.sub(r"""--""", smartchars.endash, text) return text @@ -656,8 +725,8 @@ the shortcut should be shorter to type. (Thanks to Aaron Swartz for the idea.) """ - text = re.sub(r"""---""", smart.endash, text) # em - text = re.sub(r"""--""", smart.emdash, text) # en + text = re.sub(r"""---""", smartchars.endash, text) # em + text = re.sub(r"""--""", smartchars.emdash, text) # en return text @@ -672,12 +741,12 @@ Example output: Huh…? """ - text = re.sub(r"""\.\.\.""", smart.ellipsis, text) - text = re.sub(r"""\. \. \.""", smart.ellipsis, text) + text = re.sub(r"""\.\.\.""", smartchars.ellipsis, text) + text = re.sub(r"""\. \. \.""", smartchars.ellipsis, text) return text -def stupefyEntities(text): +def stupefyEntities(text, language='en'): """ Parameter: String (unicode or bytes). Returns: The `text`, with each SmartyPants character translated to @@ -686,22 +755,23 @@ Example input: “Hello — world.” Example output: "Hello -- world." """ + smart = smartchars(language) text = re.sub(smart.endash, "-", text) # en-dash text = re.sub(smart.emdash, "--", text) # em-dash - text = re.sub(smart.lquote, "'", text) # open single quote - text = re.sub(smart.rquote, "'", text) # close single quote + text = re.sub(smart.osquote, "'", text) # open single quote + text = re.sub(smart.csquote, "'", text) # close single quote - text = re.sub(smart.ldquote, '"', text) # open double quote - text = re.sub(smart.rdquote, '"', text) # close double quote + text = re.sub(smart.opquote, '"', text) # open double quote + text = re.sub(smart.cpquote, '"', text) # close double quote text = re.sub(smart.ellipsis, '...', text)# ellipsis return text -def processEscapes(text): +def processEscapes(text, restore=False): r""" Parameter: String (unicode or bytes). Returns: The `text`, with after processing the following backslash @@ -717,12 +787,18 @@ \- - \` ` """ - text = re.sub(r"""\\\\""", r"""\""", text) - text = re.sub(r'''\\"''', r""""""", text) - text = re.sub(r"""\\'""", r"""'""", text) - text = re.sub(r"""\\\.""", r""".""", text) - text = re.sub(r"""\\-""", r"""-""", text) - text = re.sub(r"""\\`""", r"""`""", text) + replacements = ((r'\\', r'\'), + (r'\"', r'"'), + (r"\'", r'''), + (r'\.', r'.'), + (r'\-', r'-'), + (r'\`', r'`')) + if restore: + for (ch, rep) in replacements: + text = text.replace(rep, ch[1]) + else: + for (ch, rep) in replacements: + text = text.replace(ch, rep) return text Modified: trunk/docutils/test/test_transforms/test_smartquotes.py =================================================================== --- trunk/docutils/test/test_transforms/test_smartquotes.py 2012-11-26 13:50:06 UTC (rev 7539) +++ trunk/docutils/test/test_transforms/test_smartquotes.py 2012-11-26 14:06:19 UTC (rev 7540) @@ -1,9 +1,9 @@ #!/usr/bin/env python # -*- coding: utf8 -*- - # $Id$ - +# # :Copyright: © 2011 Günter Milde. +# :Maintainer: doc...@li... # :License: Released under the terms of the `2-Clause BSD license`_, in short: # # Copying and distribution of this file, with or without modification, @@ -24,13 +24,20 @@ def suite(): parser = Parser() + settings = {'smart_quotes': True} s = DocutilsTestSupport.TransformTestSuite( - parser, suite_settings={'smart_quotes': True}) + parser, suite_settings=settings) s.generateTests(totest) + settings['language_code'] = 'de' + s.generateTests(totest_de) + settings['smart_quotes'] = 'alternative' + s.generateTests(totest_de_alt) return s totest = {} +totest_de = {} +totest_de_alt = {} totest['transitions'] = ((SmartQuotes,), [ ["""\ @@ -47,7 +54,7 @@ """], ["""\ Do not "educate" quotes ``inside "literal" text`` and :: - + "literal" blocks. Keep quotes straight in code and math: @@ -56,11 +63,11 @@ .. code:: print "hello" - + .. math:: f'(x) = df(x)/dx - + """, u"""\ <document source="test data"> @@ -122,9 +129,73 @@ <title_reference> inline “roles”\ """], +["""\ +.. class:: language-de + +German "smart quotes" and 'single smart quotes'. + +.. class:: language-foo + +"Quoting style" for unknown languages is 'ASCII'. + +.. class:: language-de-x-altquot + +Alternative German "smart quotes" and 'single smart quotes'. +""", +u"""\ +<document source="test data"> + <paragraph classes="language-de"> + German „smart quotes“ and ‚single smart quotes‘. + <paragraph classes="language-foo"> + "Quoting style" for unknown languages is 'ASCII'. + <paragraph classes="language-de-x-altquot"> + Alternative German »smart quotes« and ›single smart quotes‹. + <system_message level="2" line="7" source="test data" type="WARNING"> + <paragraph> + No smart quotes defined for language "foo". +"""], ]) +totest_de['transitions'] = ((SmartQuotes,), [ +["""\ +German "smart quotes" and 'single smart quotes'. +.. class:: language-en-UK + +English "smart quotes" and 'single smart quotes'. +""", +u"""\ +<document source="test data"> + <paragraph> + German „smart quotes“ and ‚single smart quotes‘. + <paragraph classes="language-en-uk"> + English “smart quotes” and ‘single smart quotes’. +"""], +]) + +totest_de_alt['transitions'] = ((SmartQuotes,), [ +["""\ +Alternative German "smart quotes" and 'single smart quotes'. + +.. class:: language-en-UK + +English "smart quotes" and 'single smart quotes' have no alternative. + +.. class:: language-ro + +Alternative Romanian "smart quotes" and 'single' smart quotes. +""", +u"""\ +<document source="test data"> + <paragraph> + Alternative German »smart quotes« and ›single smart quotes‹. + <paragraph classes="language-en-uk"> + English “smart quotes” and ‘single smart quotes’ have no alternative. + <paragraph classes="language-ro"> + Alternative Romanian «smart quotes» and „single” smart quotes. +"""], +]) + if __name__ == '__main__': import unittest unittest.main(defaultTest='suite') This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mi...@us...> - 2012-12-12 22:06:39
|
Revision: 7545 http://docutils.svn.sourceforge.net/docutils/?rev=7545&view=rev Author: milde Date: 2012-12-12 22:06:32 +0000 (Wed, 12 Dec 2012) Log Message: ----------- Documentation update Modified Paths: -------------- trunk/docutils/docs/dev/todo.txt trunk/docutils/docutils/nodes.py Modified: trunk/docutils/docs/dev/todo.txt =================================================================== --- trunk/docutils/docs/dev/todo.txt 2012-12-12 22:04:49 UTC (rev 7544) +++ trunk/docutils/docs/dev/todo.txt 2012-12-12 22:06:32 UTC (rev 7545) @@ -555,8 +555,8 @@ .. _OpenOffice.org XML: http://xml.openoffice.org/ .. _object references: rst/alternatives.html#object-references -See also the `Modified rst2html -<http://www.loria.fr/~rougier/coding/article/rst2html.py>`__ +See also the `Modified rst2html +<http://www.loria.fr/~rougier/coding/article/rst2html.py>`__ by Nicolas Rougier for a sample implementation. @@ -1244,6 +1244,9 @@ * The Python module ASCIIMathML_ translates a string with ASCIIMath into a MathML tree. Used, e.g., by MultiMarkdown__. + A more comprehensive and implementation is ASCIIMathPython_ by + Paul Trembley (also used in his sandbox projects). + * For conversion to LaTeX, there is a JavaScript script at http://dlippman.imathas.com/asciimathtex/ASCIIMath2TeX.js @@ -1251,6 +1254,7 @@ .. _ASCIIMath tutorial: http://www.wjagray.co.uk/maths/ASCIIMathTutorial.html .. _ASCIIMathML: http://pypi.python.org/pypi/asciimathml/ + .. _ASCIIMathPython: http://sourceforge.net/projects/asciimathpython/ __ http://fletcherpenney.net/multimarkdown/ `Unicode Nearly Plain Text Encoding of Mathematics`_ @@ -1931,12 +1935,12 @@ * `sphinxcontrib-bibtex`_ Sphinx extension with "bibliography" directive and "cite" role supporting BibTeX databases. - - * `Modified rst2html - <http://www.loria.fr/~rougier/coding/article/rst2html.py>`__ by + + * `Modified rst2html + <http://www.loria.fr/~rougier/coding/article/rst2html.py>`__ by Nicolas Rougier. - + * Automatically insert a "References" heading? .. _CrossTeX: http://www.cs.cornell.edu/people/egs/crosstex/ Modified: trunk/docutils/docutils/nodes.py =================================================================== --- trunk/docutils/docutils/nodes.py 2012-12-12 22:04:49 UTC (rev 7544) +++ trunk/docutils/docutils/nodes.py 2012-12-12 22:06:32 UTC (rev 7545) @@ -1,5 +1,6 @@ # $Id$ # Author: David Goodger <go...@py...> +# Maintainer: doc...@li... # Copyright: This module has been placed in the public domain. """ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <gr...@us...> - 2012-12-13 09:04:06
|
Revision: 7547 http://docutils.svn.sourceforge.net/docutils/?rev=7547&view=rev Author: grubert Date: 2012-12-13 09:03:58 +0000 (Thu, 13 Dec 2012) Log Message: ----------- Release 0.10: closed "Changes Since ..." section Modified Paths: -------------- trunk/docutils/HISTORY.txt trunk/docutils/RELEASE-NOTES.txt Modified: trunk/docutils/HISTORY.txt =================================================================== --- trunk/docutils/HISTORY.txt 2012-12-13 09:01:26 UTC (rev 7546) +++ trunk/docutils/HISTORY.txt 2012-12-13 09:03:58 UTC (rev 7547) @@ -13,8 +13,8 @@ .. contents:: -Changes Since 0.9.1 -=================== +Release 0.10 (2012-12-13) +========================= * General Modified: trunk/docutils/RELEASE-NOTES.txt =================================================================== --- trunk/docutils/RELEASE-NOTES.txt 2012-12-13 09:01:26 UTC (rev 7546) +++ trunk/docutils/RELEASE-NOTES.txt 2012-12-13 09:03:58 UTC (rev 7547) @@ -29,8 +29,8 @@ element with class attribute and auto-generated title. -Changes Since 0.9.1 -=================== +Release 0.10 (2012-12-13) +========================= .. Note:: This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <gr...@us...> - 2012-12-16 17:41:14
|
Revision: 7558 http://docutils.svn.sourceforge.net/docutils/?rev=7558&view=rev Author: grubert Date: 2012-12-16 17:41:07 +0000 (Sun, 16 Dec 2012) Log Message: ----------- reset section names for release.sh Modified Paths: -------------- trunk/docutils/HISTORY.txt trunk/docutils/RELEASE-NOTES.txt Modified: trunk/docutils/HISTORY.txt =================================================================== --- trunk/docutils/HISTORY.txt 2012-12-16 16:04:45 UTC (rev 7557) +++ trunk/docutils/HISTORY.txt 2012-12-16 17:41:07 UTC (rev 7558) @@ -13,8 +13,8 @@ .. contents:: -Release 0.10 (2012-12-13) -========================= +Changes Since 0.9.1 +=================== * General Modified: trunk/docutils/RELEASE-NOTES.txt =================================================================== --- trunk/docutils/RELEASE-NOTES.txt 2012-12-16 16:04:45 UTC (rev 7557) +++ trunk/docutils/RELEASE-NOTES.txt 2012-12-16 17:41:07 UTC (rev 7558) @@ -29,8 +29,8 @@ element with class attribute and auto-generated title. -Release 0.10 (2012-12-13) -========================= +Changes Since 0.9.1 +=================== .. Note:: This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <gr...@us...> - 2012-12-16 18:02:54
|
Revision: 7563 http://docutils.svn.sourceforge.net/docutils/?rev=7563&view=rev Author: grubert Date: 2012-12-16 18:02:48 +0000 (Sun, 16 Dec 2012) Log Message: ----------- Release 0.10: closed "Changes Since ..." section Modified Paths: -------------- trunk/docutils/HISTORY.txt trunk/docutils/RELEASE-NOTES.txt Modified: trunk/docutils/HISTORY.txt =================================================================== --- trunk/docutils/HISTORY.txt 2012-12-16 18:01:56 UTC (rev 7562) +++ trunk/docutils/HISTORY.txt 2012-12-16 18:02:48 UTC (rev 7563) @@ -13,8 +13,8 @@ .. contents:: -Changes Since 0.9.1 -=================== +Release 0.10 (2012-12-16) +========================= * General Modified: trunk/docutils/RELEASE-NOTES.txt =================================================================== --- trunk/docutils/RELEASE-NOTES.txt 2012-12-16 18:01:56 UTC (rev 7562) +++ trunk/docutils/RELEASE-NOTES.txt 2012-12-16 18:02:48 UTC (rev 7563) @@ -29,8 +29,8 @@ element with class attribute and auto-generated title. -Changes Since 0.9.1 -=================== +Release 0.10 (2012-12-16) +========================= .. Note:: This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <gr...@us...> - 2012-12-16 18:28:47
|
Revision: 7568 http://docutils.svn.sourceforge.net/docutils/?rev=7568&view=rev Author: grubert Date: 2012-12-16 18:28:40 +0000 (Sun, 16 Dec 2012) Log Message: ----------- Release 0.10: added empty "Changes Since 0.10" section Modified Paths: -------------- trunk/docutils/HISTORY.txt trunk/docutils/RELEASE-NOTES.txt Modified: trunk/docutils/HISTORY.txt =================================================================== --- trunk/docutils/HISTORY.txt 2012-12-16 18:27:42 UTC (rev 7567) +++ trunk/docutils/HISTORY.txt 2012-12-16 18:28:40 UTC (rev 7568) @@ -13,6 +13,10 @@ .. contents:: +Changes Since 0.10 +================== + + Release 0.10 (2012-12-16) ========================= Modified: trunk/docutils/RELEASE-NOTES.txt =================================================================== --- trunk/docutils/RELEASE-NOTES.txt 2012-12-16 18:27:42 UTC (rev 7567) +++ trunk/docutils/RELEASE-NOTES.txt 2012-12-16 18:28:40 UTC (rev 7568) @@ -29,6 +29,10 @@ element with class attribute and auto-generated title. +Changes Since 0.10 +================== + + Release 0.10 (2012-12-16) ========================= This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <gr...@us...> - 2012-12-16 18:29:57
|
Revision: 7569 http://docutils.svn.sourceforge.net/docutils/?rev=7569&view=rev Author: grubert Date: 2012-12-16 18:29:50 +0000 (Sun, 16 Dec 2012) Log Message: ----------- Release 0.10: set version number to 0.11 Modified Paths: -------------- trunk/docutils/docutils/__init__.py trunk/docutils/setup.py trunk/docutils/test/functional/expected/compact_lists.html trunk/docutils/test/functional/expected/dangerous.html trunk/docutils/test/functional/expected/field_name_limit.html trunk/docutils/test/functional/expected/math_output_html.html trunk/docutils/test/functional/expected/math_output_latex.html trunk/docutils/test/functional/expected/math_output_mathjax.html trunk/docutils/test/functional/expected/math_output_mathml.xhtml trunk/docutils/test/functional/expected/misc_rst_html4css1.html trunk/docutils/test/functional/expected/pep_html.html trunk/docutils/test/functional/expected/standalone_rst_html4css1.html trunk/docutils/test/functional/expected/standalone_rst_s5_html_1.html trunk/docutils/test/functional/expected/standalone_rst_s5_html_2.html Modified: trunk/docutils/docutils/__init__.py =================================================================== --- trunk/docutils/docutils/__init__.py 2012-12-16 18:28:40 UTC (rev 7568) +++ trunk/docutils/docutils/__init__.py 2012-12-16 18:29:50 UTC (rev 7569) @@ -52,7 +52,7 @@ __docformat__ = 'reStructuredText' -__version__ = '0.10' +__version__ = '0.11' """``major.minor.micro`` version number. The micro number is bumped for API changes, for new functionality, and for interim project releases. The minor number is bumped whenever there is a significant project release. The major Modified: trunk/docutils/setup.py =================================================================== --- trunk/docutils/setup.py 2012-12-16 18:28:40 UTC (rev 7568) +++ trunk/docutils/setup.py 2012-12-16 18:29:50 UTC (rev 7569) @@ -113,7 +113,7 @@ input Docutils supports reStructuredText, an easy-to-read, what-you-see-is-what-you-get plaintext markup syntax.""", # wrap at col 60 'url': 'http://docutils.sourceforge.net/', - 'version': '0.10', + 'version': '0.11', 'author': 'David Goodger', 'author_email': 'go...@py...', 'maintainer': 'docutils-develop list', Modified: trunk/docutils/test/functional/expected/compact_lists.html =================================================================== --- trunk/docutils/test/functional/expected/compact_lists.html 2012-12-16 18:28:40 UTC (rev 7568) +++ trunk/docutils/test/functional/expected/compact_lists.html 2012-12-16 18:29:50 UTC (rev 7569) @@ -3,7 +3,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> -<meta name="generator" content="Docutils 0.10: http://docutils.sourceforge.net/" /> +<meta name="generator" content="Docutils 0.11: http://docutils.sourceforge.net/" /> <title></title> <link rel="stylesheet" href="../input/data/html4css1.css" type="text/css" /> </head> Modified: trunk/docutils/test/functional/expected/dangerous.html =================================================================== --- trunk/docutils/test/functional/expected/dangerous.html 2012-12-16 18:28:40 UTC (rev 7568) +++ trunk/docutils/test/functional/expected/dangerous.html 2012-12-16 18:29:50 UTC (rev 7569) @@ -3,7 +3,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> -<meta name="generator" content="Docutils 0.10: http://docutils.sourceforge.net/" /> +<meta name="generator" content="Docutils 0.11: http://docutils.sourceforge.net/" /> <title></title> <link rel="stylesheet" href="../input/data/html4css1.css" type="text/css" /> </head> Modified: trunk/docutils/test/functional/expected/field_name_limit.html =================================================================== --- trunk/docutils/test/functional/expected/field_name_limit.html 2012-12-16 18:28:40 UTC (rev 7568) +++ trunk/docutils/test/functional/expected/field_name_limit.html 2012-12-16 18:29:50 UTC (rev 7569) @@ -3,7 +3,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> -<meta name="generator" content="Docutils 0.10: http://docutils.sourceforge.net/" /> +<meta name="generator" content="Docutils 0.11: http://docutils.sourceforge.net/" /> <title></title> <link rel="stylesheet" href="../input/data/html4css1.css" type="text/css" /> </head> Modified: trunk/docutils/test/functional/expected/math_output_html.html =================================================================== --- trunk/docutils/test/functional/expected/math_output_html.html 2012-12-16 18:28:40 UTC (rev 7568) +++ trunk/docutils/test/functional/expected/math_output_html.html 2012-12-16 18:29:50 UTC (rev 7569) @@ -3,7 +3,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> -<meta name="generator" content="Docutils 0.10: http://docutils.sourceforge.net/" /> +<meta name="generator" content="Docutils 0.11: http://docutils.sourceforge.net/" /> <title>Mathematics</title> <link rel="stylesheet" href="../input/data/html4css1.css" type="text/css" /> <link rel="stylesheet" href="../input/data/math.css" type="text/css" /> Modified: trunk/docutils/test/functional/expected/math_output_latex.html =================================================================== --- trunk/docutils/test/functional/expected/math_output_latex.html 2012-12-16 18:28:40 UTC (rev 7568) +++ trunk/docutils/test/functional/expected/math_output_latex.html 2012-12-16 18:29:50 UTC (rev 7569) @@ -3,7 +3,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> -<meta name="generator" content="Docutils 0.10: http://docutils.sourceforge.net/" /> +<meta name="generator" content="Docutils 0.11: http://docutils.sourceforge.net/" /> <title>Mathematics</title> <link rel="stylesheet" href="../input/data/html4css1.css" type="text/css" /> </head> Modified: trunk/docutils/test/functional/expected/math_output_mathjax.html =================================================================== --- trunk/docutils/test/functional/expected/math_output_mathjax.html 2012-12-16 18:28:40 UTC (rev 7568) +++ trunk/docutils/test/functional/expected/math_output_mathjax.html 2012-12-16 18:29:50 UTC (rev 7569) @@ -3,7 +3,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> -<meta name="generator" content="Docutils 0.10: http://docutils.sourceforge.net/" /> +<meta name="generator" content="Docutils 0.11: http://docutils.sourceforge.net/" /> <title>Mathematics</title> <script type="text/javascript" src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script> <link rel="stylesheet" href="../input/data/html4css1.css" type="text/css" /> Modified: trunk/docutils/test/functional/expected/math_output_mathml.xhtml =================================================================== --- trunk/docutils/test/functional/expected/math_output_mathml.xhtml 2012-12-16 18:28:40 UTC (rev 7568) +++ trunk/docutils/test/functional/expected/math_output_mathml.xhtml 2012-12-16 18:29:50 UTC (rev 7569) @@ -3,7 +3,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <meta http-equiv="Content-Type" content="application/xhtml+xml; charset=utf-8" /> -<meta name="generator" content="Docutils 0.10: http://docutils.sourceforge.net/" /> +<meta name="generator" content="Docutils 0.11: http://docutils.sourceforge.net/" /> <title>Mathematics</title> <link rel="stylesheet" href="../input/data/html4css1.css" type="text/css" /> </head> Modified: trunk/docutils/test/functional/expected/misc_rst_html4css1.html =================================================================== --- trunk/docutils/test/functional/expected/misc_rst_html4css1.html 2012-12-16 18:28:40 UTC (rev 7568) +++ trunk/docutils/test/functional/expected/misc_rst_html4css1.html 2012-12-16 18:29:50 UTC (rev 7569) @@ -3,7 +3,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> -<meta name="generator" content="Docutils 0.10: http://docutils.sourceforge.net/" /> +<meta name="generator" content="Docutils 0.11: http://docutils.sourceforge.net/" /> <title></title> <link rel="stylesheet" href="foo&bar.css" type="text/css" /> </head> Modified: trunk/docutils/test/functional/expected/pep_html.html =================================================================== --- trunk/docutils/test/functional/expected/pep_html.html 2012-12-16 18:28:40 UTC (rev 7568) +++ trunk/docutils/test/functional/expected/pep_html.html 2012-12-16 18:29:50 UTC (rev 7569) @@ -8,7 +8,7 @@ --> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> - <meta name="generator" content="Docutils 0.10: http://docutils.sourceforge.net/" /> + <meta name="generator" content="Docutils 0.11: http://docutils.sourceforge.net/" /> <title>PEP 100 -- Test PEP</title> <link rel="stylesheet" href="../input/data/html4css1.css" type="text/css" /> </head> Modified: trunk/docutils/test/functional/expected/standalone_rst_html4css1.html =================================================================== --- trunk/docutils/test/functional/expected/standalone_rst_html4css1.html 2012-12-16 18:28:40 UTC (rev 7568) +++ trunk/docutils/test/functional/expected/standalone_rst_html4css1.html 2012-12-16 18:29:50 UTC (rev 7569) @@ -3,7 +3,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> -<meta name="generator" content="Docutils 0.10: http://docutils.sourceforge.net/" /> +<meta name="generator" content="Docutils 0.11: http://docutils.sourceforge.net/" /> <title>reStructuredText Test Document</title> <meta name="author" content="David Goodger" /> <meta name="authors" content="Me Myself I" /> Modified: trunk/docutils/test/functional/expected/standalone_rst_s5_html_1.html =================================================================== --- trunk/docutils/test/functional/expected/standalone_rst_s5_html_1.html 2012-12-16 18:28:40 UTC (rev 7568) +++ trunk/docutils/test/functional/expected/standalone_rst_s5_html_1.html 2012-12-16 18:29:50 UTC (rev 7569) @@ -3,7 +3,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> -<meta name="generator" content="Docutils 0.10: http://docutils.sourceforge.net/" /> +<meta name="generator" content="Docutils 0.11: http://docutils.sourceforge.net/" /> <meta name="version" content="S5 1.1" /> <title>Slide Shows</title> <meta name="author" content="David Goodger" /> Modified: trunk/docutils/test/functional/expected/standalone_rst_s5_html_2.html =================================================================== --- trunk/docutils/test/functional/expected/standalone_rst_s5_html_2.html 2012-12-16 18:28:40 UTC (rev 7568) +++ trunk/docutils/test/functional/expected/standalone_rst_s5_html_2.html 2012-12-16 18:29:50 UTC (rev 7569) @@ -3,7 +3,7 @@ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> -<meta name="generator" content="Docutils 0.10: http://docutils.sourceforge.net/" /> +<meta name="generator" content="Docutils 0.11: http://docutils.sourceforge.net/" /> <meta name="version" content="S5 1.1" /> <title>Slide Shows</title> <meta name="author" content="David Goodger" /> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mi...@us...> - 2012-12-27 00:08:51
|
Revision: 7578 http://docutils.svn.sourceforge.net/docutils/?rev=7578&view=rev Author: milde Date: 2012-12-27 00:08:38 +0000 (Thu, 27 Dec 2012) Log Message: ----------- Fix [ 3596884 ] exception importing ``docutils.io``. Modified Paths: -------------- trunk/docutils/HISTORY.txt trunk/docutils/docutils/utils/__init__.py Modified: trunk/docutils/HISTORY.txt =================================================================== --- trunk/docutils/HISTORY.txt 2012-12-18 08:25:37 UTC (rev 7577) +++ trunk/docutils/HISTORY.txt 2012-12-27 00:08:38 UTC (rev 7578) @@ -16,7 +16,10 @@ Changes Since 0.10 ================== +* docutils/utils/__init__.py + - Fix [ 3596884 ] exception importing ``docutils.io``. + Release 0.10 (2012-12-16) ========================= Modified: trunk/docutils/docutils/utils/__init__.py =================================================================== --- trunk/docutils/docutils/utils/__init__.py 2012-12-18 08:25:37 UTC (rev 7577) +++ trunk/docutils/docutils/utils/__init__.py 2012-12-27 00:08:38 UTC (rev 7578) @@ -17,7 +17,7 @@ import unicodedata from docutils import ApplicationError, DataError from docutils import nodes -from docutils.io import FileOutput +import docutils.io from docutils.utils.error_reporting import ErrorOutput, SafeString @@ -697,7 +697,7 @@ of = None else: of = output_file - self.file = FileOutput(destination_path=of, + self.file = docutils.io.FileOutput(destination_path=of, encoding='utf8', autoclose=False) else: self.file = None This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <gr...@us...> - 2012-12-31 13:05:34
|
Revision: 7583 http://docutils.svn.sourceforge.net/docutils/?rev=7583&view=rev Author: grubert Date: 2012-12-31 13:05:27 +0000 (Mon, 31 Dec 2012) Log Message: ----------- Fix: 3598893 --stylesheet and --stylesheet-path options broken, patch partially applied Modified Paths: -------------- trunk/docutils/docutils/frontend.py trunk/docutils/test/test_settings.py Modified: trunk/docutils/docutils/frontend.py =================================================================== --- trunk/docutils/docutils/frontend.py 2012-12-31 12:32:26 UTC (rev 7582) +++ trunk/docutils/docutils/frontend.py 2012-12-31 13:05:27 UTC (rev 7583) @@ -171,13 +171,11 @@ """ # `value` is already a list when given as command line option # and "action" is "append" - # TODO fix here or in buildhtml or process - # buildhtml.py:calls - # values=frontend.Values() - # and later - # optparse _process_args, _process_long_opt - # but then value is NOT unicode but str in python2 - if isinstance(value, unicode): + # in python2 buildhtml.py calls this once with str after several + # times with unicode. MAYBE fix somewhere else. + #if isinstance(value, unicode): #py3 + #if isinstance(value, basestr): # py3 and py2.7 + if not hasattr(value, 'pop'): value = [value] # this function is called for every option added to `value` # -> split the last item and append the result: Modified: trunk/docutils/test/test_settings.py =================================================================== --- trunk/docutils/test/test_settings.py 2012-12-31 12:32:26 UTC (rev 7582) +++ trunk/docutils/test/test_settings.py 2012-12-31 13:05:27 UTC (rev 7583) @@ -213,7 +213,7 @@ (u'a', ['a',] ), (u'a,12', ['a', '12'] ), ([u'a',], ['a',] ), - # TODO ("u'a',", ['a',] ), AttributeError: 'str' object has no attribute 'pop' + ('a,', ['a',] ), # in python3 this is unicode too ) for t in tests: self.assertEqual( This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mi...@us...> - 2013-01-01 20:00:28
|
Revision: 7584 http://docutils.svn.sourceforge.net/docutils/?rev=7584&view=rev Author: milde Date: 2013-01-01 20:00:21 +0000 (Tue, 01 Jan 2013) Log Message: ----------- Unify/simplify type testing in "validate_*_list". Circumvent the problem that the value may be "unicode" or "str" by testing for "not a list". Modified Paths: -------------- trunk/docutils/docutils/frontend.py trunk/docutils/test/test_settings.py Modified: trunk/docutils/docutils/frontend.py =================================================================== --- trunk/docutils/docutils/frontend.py 2012-12-31 13:05:27 UTC (rev 7583) +++ trunk/docutils/docutils/frontend.py 2013-01-01 20:00:21 UTC (rev 7584) @@ -158,7 +158,7 @@ def validate_colon_separated_string_list( setting, value, option_parser, config_parser=None, config_section=None): - if isinstance(value, unicode): + if not isinstance(value, list): value = value.split(':') else: last = value.pop() @@ -169,20 +169,15 @@ config_parser=None, config_section=None): """Check/normalize list arguments (split at "," and strip whitespace). """ - # `value` is already a list when given as command line option - # and "action" is "append" - # in python2 buildhtml.py calls this once with str after several - # times with unicode. MAYBE fix somewhere else. - #if isinstance(value, unicode): #py3 - #if isinstance(value, basestr): # py3 and py2.7 - if not hasattr(value, 'pop'): + # `value` is already a ``list`` when given as command line option + # and "action" is "append" and ``unicode`` or ``str`` else. + if not isinstance(value, list): value = [value] # this function is called for every option added to `value` # -> split the last item and append the result: last = value.pop() - classes = [cls.strip(u' \t\n') for cls in last.split(',') - if cls.strip(u' \t\n')] - value.extend(classes) + items = [i.strip(u' \t\n') for i in last.split(u',') if i.strip(u' \t\n')] + value.extend(items) return value def validate_url_trailing_slash( Modified: trunk/docutils/test/test_settings.py =================================================================== --- trunk/docutils/test/test_settings.py 2012-12-31 13:05:27 UTC (rev 7583) +++ trunk/docutils/test/test_settings.py 2013-01-01 20:00:21 UTC (rev 7584) @@ -198,9 +198,11 @@ def test_validate_colon_separated_string_list(self): tests = ( (u'a', ['a',] ), - (u'a:12', ['a', '12'] ), + ('a', ['a',] ), + (u'a:b', ['a', 'b'] ), + ('a:b', ['a', 'b'] ), ([u'a',], ['a',] ), - # TODO ("u'a',", ['a',] ), AttributeError: 'str' object has no attribute 'pop' + ([u'a', u'b:c'], ['a', 'b', 'c'] ), ) for t in tests: self.assertEqual( @@ -211,9 +213,12 @@ def test_validate_comma_separated_list(self): tests = ( (u'a', ['a',] ), - (u'a,12', ['a', '12'] ), + ('a', ['a',] ), + (u'a,b', ['a', 'b'] ), + ('a,b', ['a', 'b'] ), ([u'a',], ['a',] ), - ('a,', ['a',] ), # in python3 this is unicode too + ([u'a', u'b,c'], ['a', 'b', 'c'] ), + (['a', 'b,c'], ['a', 'b', 'c'] ), ) for t in tests: self.assertEqual( This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mi...@us...> - 2013-01-04 17:17:45
|
Revision: 7585 http://docutils.svn.sourceforge.net/docutils/?rev=7585&view=rev Author: milde Date: 2013-01-04 17:17:38 +0000 (Fri, 04 Jan 2013) Log Message: ----------- smartquotes: Skip emtpy text tokens without updating the last character. Modified Paths: -------------- trunk/docutils/docutils/transforms/universal.py trunk/docutils/docutils/utils/smartquotes.py trunk/docutils/test/test_transforms/test_smartquotes.py Modified: trunk/docutils/docutils/transforms/universal.py =================================================================== --- trunk/docutils/docutils/transforms/universal.py 2013-01-01 20:00:21 UTC (rev 7584) +++ trunk/docutils/docutils/transforms/universal.py 2013-01-04 17:17:38 UTC (rev 7585) @@ -261,7 +261,7 @@ if not isinstance(txtnode.parent, nodes.option_string)] - # language: use smart-quotes for language "lang" + # language: use typographical quotes for language "lang" lang = node.get_language_code(document_language) # use alternative form if `smart-quotes` setting starts with "alt": if alternative: Modified: trunk/docutils/docutils/utils/smartquotes.py =================================================================== --- trunk/docutils/docutils/utils/smartquotes.py 2013-01-01 20:00:21 UTC (rev 7584) +++ trunk/docutils/docutils/utils/smartquotes.py 2013-01-04 17:17:38 UTC (rev 7585) @@ -382,7 +382,7 @@ # For other languages see: # http://en.wikipedia.org/wiki/Non-English_usage_of_quotation_marks # http://de.wikipedia.org/wiki/Anf%C3%BChrungszeichen#Andere_Sprachen - quotes = {'af': u'“”‘’', + quotes = {'af': u'“”‘’', 'af-x-altquot': u'„”‚’', 'ca': u'«»“”', 'ca-x-altquot': u'“”‘’', @@ -507,14 +507,15 @@ for (ttype, text) in text_tokens: - # skip HTML and/or XML tags (do not update last character) - if ttype == 'tag': + # skip HTML and/or XML tags as well as emtpy text tokens + # without updating the last character + if ttype == 'tag' or not text: yield text continue # skip literal text (math, literal, raw, ...) if ttype == 'literal': - prev_token_last_char = text[-1] + prev_token_last_char = text[-1:] yield text continue Modified: trunk/docutils/test/test_transforms/test_smartquotes.py =================================================================== --- trunk/docutils/test/test_transforms/test_smartquotes.py 2013-01-01 20:00:21 UTC (rev 7584) +++ trunk/docutils/test/test_transforms/test_smartquotes.py 2013-01-04 17:17:38 UTC (rev 7585) @@ -95,9 +95,12 @@ Quotes and inline-elements: * Around "_`targets`", "*emphasized*" or "``literal``" text - and links to "targets_". + and links to "targets_". * Inside *"emphasized"* or other `inline "roles"` + +Do not drop characters from intra-word inline markup like +*re*\ ``Structured``\ *Text*. """, u"""\ <document source="test data"> @@ -127,7 +130,16 @@ “emphasized” or other \n\ <title_reference> - inline “roles”\ + inline “roles” + <paragraph> + Do not drop characters from intra-word inline markup like + <emphasis> + re + <literal> + Structured + <emphasis> + Text + .\ """], ["""\ .. class:: language-de This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mi...@us...> - 2013-01-05 17:00:59
|
Revision: 7586 http://docutils.svn.sourceforge.net/docutils/?rev=7586&view=rev Author: milde Date: 2013-01-05 17:00:50 +0000 (Sat, 05 Jan 2013) Log Message: ----------- latex2e: Drop the simple algorithm replacing straight double quotes. Modified Paths: -------------- trunk/docutils/HISTORY.txt trunk/docutils/RELEASE-NOTES.txt trunk/docutils/docutils/writers/latex2e/__init__.py trunk/docutils/test/functional/expected/cyrillic.tex trunk/docutils/test/functional/expected/standalone_rst_latex.tex trunk/docutils/test/functional/expected/standalone_rst_xetex.tex trunk/docutils/test/functional/tests/standalone_rst_latex.py trunk/docutils/test/functional/tests/standalone_rst_xetex.py trunk/docutils/test/test_writers/test_latex2e.py Modified: trunk/docutils/HISTORY.txt =================================================================== --- trunk/docutils/HISTORY.txt 2013-01-04 17:17:38 UTC (rev 7585) +++ trunk/docutils/HISTORY.txt 2013-01-05 17:00:50 UTC (rev 7586) @@ -20,19 +20,26 @@ - Fix [ 3596884 ] exception importing ``docutils.io``. +* docutils/writers/latex2e/__init__.py + + - Drop the simple algorithm replacing straight double quotes with + English typographic ones. Use the SmartQuotes transform + (``--smart-quotes=True``) instead. + + Release 0.10 (2012-12-16) ========================= * General - + - Dropped support for Python 2.3. - ``docutils/math``, ``docutils/error_reporting.py``, and ``docutils/urischemes.py`` moved to the utils package. - Fix [3541369] Relative __import__ also with Python 3.3. - - Fix [3559988] and [3560841] __import__ local writer, reader, languages + - Fix [3559988] and [3560841] __import__ local writer, reader, languages and parsers for Python 2.7 up. - Fix import of PIL.Image. - - Change default of "syntax highlight" option to "long", + - Change default of "syntax highlight" option to "long", basic syntax highlight styles for LaTeX and HTML. * docutils/io.py @@ -67,7 +74,7 @@ - Apply [ 3527401 ] addmonition's don't preserve indentation - Apply [ 3527397 ] Add indentation to literal blocks in manpage writer. -* docutils/writers/latex2e/__init__.py, docutils/writers/xetex/__init__.py +, docutils/writers/xetex/__init__.py - Apply [ 3555160 ] ensure order of "otherlanguages". - Fix section numbering by LaTeX. Modified: trunk/docutils/RELEASE-NOTES.txt =================================================================== --- trunk/docutils/RELEASE-NOTES.txt 2013-01-04 17:17:38 UTC (rev 7585) +++ trunk/docutils/RELEASE-NOTES.txt 2013-01-05 17:00:50 UTC (rev 7586) @@ -32,7 +32,13 @@ Changes Since 0.10 ================== +* docutils/writers/latex2e/__init__.py + - Drop the simple algorithm replacing straight double quotes with + English typographic ones. Use the SmartQuotes transform + (``--smart-quotes=True``) instead. + + Release 0.10 (2012-12-16) ========================= Modified: trunk/docutils/docutils/writers/latex2e/__init__.py =================================================================== --- trunk/docutils/docutils/writers/latex2e/__init__.py 2013-01-04 17:17:38 UTC (rev 7585) +++ trunk/docutils/docutils/writers/latex2e/__init__.py 2013-01-05 17:00:50 UTC (rev 7586) @@ -361,22 +361,37 @@ warn_msg = 'Language "%s" not supported by LaTeX (babel)' + # double quotes are "active" in some languages (e.g. German). + literal_double_quote = u'"' + # Languages with active ``"``, defining ``\dq``: + active_dq_languages = ('bulgarian', + 'czech', + 'estonian', + 'german', 'ngerman', 'austrian', 'naustrian', + 'icelandic', + 'norsk', 'nynorsk', + 'polish', + 'russian', + 'slovak', + 'swedish', + 'ukrainian', + 'uppersorbian',) + # Languages with active ``"``, not defining ``\dq`` + # TODO: complete set of languages with active ``"``, + # care for other active characters. + active_dq_languages_2 = ('danish', + 'dutch', + 'italian', 'latin') + def __init__(self, language_code, reporter=None): self.reporter = reporter self.language = self.language_name(language_code) self.otherlanguages = {} self.quote_index = 0 - self.quotes = ('``', "''") # language dependent configuration: - # double quotes are "active" in some languages (e.g. German). - self.literal_double_quote = u'"' - if self.language in ('ngerman', 'german', 'austrian', 'naustrian', - 'russian'): - self.quotes = (r'\glqq{}', r'\grqq{}') + if self.language in active_dq_languages: self.literal_double_quote = ur'\dq{}' - if self.language == 'french': - self.quotes = (r'\og{}', r'\fg{}') - if self.language == 'italian': + elif self.language in active_dq_languages_2: self.literal_double_quote = ur'{\char`\"}' def __call__(self): @@ -398,20 +413,6 @@ r'\noextrasfrench}' % self.language] return '\n'.join(self.setup) - def next_quote(self): - q = self.quotes[self.quote_index] - self.quote_index = (self.quote_index+1) % 2 - return q - - def quote_quotes(self,text): - t = None - for part in text.split('"'): - if t == None: - t = part - else: - t += self.next_quote() + part - return t - def language_name(self, language_code): """Return TeX language name for `language_code`""" for tag in utils.normalize_language_tag(language_code): @@ -424,8 +425,7 @@ return '' def get_language(self): - """Return `self.language` (for backwards compatibility with Sphinx). - """ + # Obsolete, kept for backwards compatibility with Sphinx return self.language @@ -1423,6 +1423,9 @@ # Set up the translation table: table = CharMaps.special.copy() + # double quotes are 'active' in some languages + # TODO: use \textquotedbl if font encoding is T1? + table[ord('"')] = self.babel.literal_double_quote # keep the underscore in citation references if self.inside_citation_reference_label: del(table[ord('_')]) @@ -1444,10 +1447,6 @@ table[ord('>')] = ur'\textgreater{}' if self.insert_non_breaking_blanks: table[ord(' ')] = ur'~' - if self.literal: - # double quotes are 'active' in some languages - # TODO: use \textquotedbl if font encoding starts with T? - table[ord('"')] = self.babel.literal_double_quote # Unicode replacements for 8-bit tex engines (not required with XeTeX/LuaTeX): if not self.is_xetex: table.update(CharMaps.unsupported_unicode) @@ -1484,8 +1483,6 @@ if not line.lstrip(): lines[i] += '~' text = (r'\\' + '\n').join(lines) - if not self.literal: - text = self.babel.quote_quotes(text) if self.literal and not self.insert_non_breaking_blanks: # preserve runs of spaces but allow wrapping text = text.replace(' ', ' ~') @@ -2317,14 +2314,14 @@ # depart_inline()): classes = node['classes'][:] self.context.append('}' * len(classes)) - # handle language specification: + # handle language specification: language_tags = [cls for cls in classes if cls.startswith('language-')] if language_tags: language = self.babel.language_name(language_tags[0][9:]) if language: self.babel.otherlanguages[language] = True - self.out.append(r'\otherlanguage{%s}{' % language) + self.out.append(r'\foreignlanguage{%s}{' % language) classes.pop(classes.index(language_tags[0])) if not classes: return Modified: trunk/docutils/test/functional/expected/cyrillic.tex =================================================================== --- trunk/docutils/test/functional/expected/cyrillic.tex 2013-01-04 17:17:38 UTC (rev 7585) +++ trunk/docutils/test/functional/expected/cyrillic.tex 2013-01-05 17:00:50 UTC (rev 7586) @@ -37,14 +37,14 @@ \label{id1}% } -первый пример: \glqq{}Здравствуй, мир!\grqq{} +первый пример: "Здравствуй, мир!" \section{Title% \label{title}% } -\otherlanguage{english}{first example: \glqq{}Hello world\grqq{}.} +\otherlanguage{english}{first example: "Hello world".} \section{Notes% Modified: trunk/docutils/test/functional/expected/standalone_rst_latex.tex =================================================================== --- trunk/docutils/test/functional/expected/standalone_rst_latex.tex 2013-01-04 17:17:38 UTC (rev 7585) +++ trunk/docutils/test/functional/expected/standalone_rst_latex.tex 2013-01-05 17:00:50 UTC (rev 7586) @@ -232,7 +232,7 @@ \textbf{Date}: & Now, or yesterday. Or maybe even \emph{before} yesterday. \\ \textbf{Status}: & - This is a ``work in progress'' \\ + This is a “work in progress” \\ \textbf{Revision}: & is managed by a version control system. \\ \textbf{Version}: & @@ -243,12 +243,12 @@ redistribute, reattribute, sell, buy, rent, lease, destroy, or improve it, quote it at length, excerpt, incorporate, collate, fold, staple, or mutilate it, or do -anything else to it that your or anyone else's heart +anything else to it that your or anyone else’s heart desires. \\ \textbf{field name}: & -This is a ``generic bibliographic field''. +This is a “generic bibliographic field”. \\ -\textbf{field name ``2''}: & +\textbf{field name “2”}: & Generic bibliographic fields may contain multiple body elements. Like this. @@ -310,7 +310,7 @@ \label{transitions}% } -Here's a transition: +Here’s a transition: %___________________________________________________________________________ @@ -360,12 +360,12 @@ some explicit interpreted text roles: a PEP reference (\href{http://www.python.org/dev/peps/pep-0287}{PEP 287}); an RFC reference (\href{http://www.faqs.org/rfcs/rfc2822.html}{RFC 2822}); an abbreviation (\DUrole{abbreviation}{abb.}), an acronym (\DUrole{acronym}{reST}), code (\texttt{\DUrole{code}{print "hello world"}}); a \textsubscript{subscript}; -a \textsuperscript{superscript} and explicit roles for \DUroletitlereference{Docutils}' +a \textsuperscript{superscript} and explicit roles for \DUroletitlereference{Docutils}’ \emph{standard} \textbf{inline} \texttt{markup}. % DO NOT RE-WRAP THE FOLLOWING PARAGRAPH! -Let's test wrapping and whitespace significance in inline literals: +Let’s test wrapping and whitespace significance in inline literals: \texttt{This is an example of -{}-inline-literal -{}-text, -{}-including some-{}- strangely-{}-hyphenated-words. ~Adjust-the-width-of-your-browser-window to see how the text is wrapped. ~-{}- -{}-{}-{}- -{}-{}-{}-{}-{}-{}-{}- ~Now note ~ ~the @@ -470,7 +470,7 @@ \end{list} \end{list} -\item Lists that don't start at 1: +\item Lists that don’t start at 1: \setcounter{listcnt1}{0} \begin{list}{\arabic{listcnt1}.} { @@ -554,7 +554,7 @@ \item[{credits:}] \DUrole{credits}{This paragraph has the \DUroletitlereference{credits} class set. (This is actually not about credits but just for ensuring that the class attribute -doesn't get stripped away.)} +doesn’t get stripped away.)} \end{DUfieldlist} @@ -567,7 +567,7 @@ % \begin{DUoptionlist} -\item[-a] command-line option ``a'' +\item[-a] command-line option “a” \item[-b file] options can have arguments and long descriptions @@ -582,7 +582,7 @@ The description may contain multiple body elements, regardless of where it starts. -\item[-x, -y, -z] Multiple options are an ``option group''. +\item[-x, -y, -z] Multiple options are an “option group”. \item[-v, -{}-verbose] Commonly-seen: short \& long options. @@ -600,7 +600,7 @@ \label{literal-blocks}% } -Literal blocks are indicated with a double-colon (``::'') at the end of +Literal blocks are indicated with a double-colon (“::”) at the end of the preceding paragraph (over there \texttt{-{}->}). They can be indented: % \begin{quote}{\ttfamily \raggedright \noindent @@ -633,7 +633,7 @@ \item[] This is a line block. It ends with a blank line. \item[] \begin{DUlineblock}{\DUlineblockindent} -\item[] New lines begin with a vertical bar (``|''). +\item[] New lines begin with a vertical bar (“|”). \item[] Line breaks and initial indent are significant, and preserved. \item[] \begin{DUlineblock}{\DUlineblockindent} @@ -648,16 +648,16 @@ \begin{DUlineblock}{0em} \item[] This is a second line block. \item[] -\item[] Blank lines are permitted internally, but they must begin with a ``|''. +\item[] Blank lines are permitted internally, but they must begin with a “|”. \end{DUlineblock} Another line block, surrounded by paragraphs: \begin{DUlineblock}{0em} -\item[] And it's no good waiting by the window -\item[] It's no good waiting for the sun +\item[] And it’s no good waiting by the window +\item[] It’s no good waiting for the sun \item[] Please believe me, the things you dream of -\item[] They don't fall in the lap of no-one +\item[] They don’t fall in the lap of no-one \end{DUlineblock} Take it away, Eric the Orchestra Leader! @@ -675,7 +675,7 @@ \item[] But half the bee has got to be, \item[] \begin{DUlineblock}{\DUlineblockindent} -\item[] \emph{vis a vis} its entity. D'you see? +\item[] \emph{vis a vis} its entity. D’you see? \item[] \end{DUlineblock} \item[] But can a bee be said to be @@ -692,7 +692,7 @@ \end{DUlineblock} \end{DUlineblock} \end{DUlineblock} -\item[] Singing... +\item[] Singing… \end{DUlineblock} \end{quote} @@ -770,19 +770,19 @@ A footnote contains body elements, consistently indented by at least 3 spaces. -This is the footnote's second paragraph. +This is the footnote’s second paragraph. } % \DUfootnotetext{label}{id3}{2}{\phantomsection\label{label}% Footnotes may be numbered, either manually (as in\DUfootnotemark{id9}{id8}{1}) or -automatically using a ``\#''-prefixed label. This footnote has a +automatically using a “\#”-prefixed label. This footnote has a label so it can be referred to from multiple places, both as a footnote reference (\DUfootnotemark{id10}{label}{2}) and as a \hyperref[label]{hyperlink reference}. } % \DUfootnotetext{id12}{id2}{3}{% This footnote is numbered automatically and anonymously using a -label of ``\#'' only. +label of “\#” only. This is the second paragraph. @@ -790,8 +790,8 @@ } % \DUfootnotetext{id13}{id4}{*}{% -Footnotes may also use symbols, specified with a ``*'' label. -Here's a reference to the next footnote:\DUfootnotemark{id14}{id15}{†}. +Footnotes may also use symbols, specified with a “*” label. +Here’s a reference to the next footnote:\DUfootnotemark{id14}{id15}{†}. } % \DUfootnotetext{id15}{id14}{†}{% @@ -799,7 +799,7 @@ } % \DUfootnotetext{id16}{id16}{4}{% -Here's an unreferenced footnote, with a reference to a +Here’s an unreferenced footnote, with a reference to a nonexistent footnote:% \raisebox{1em}{\hypertarget{id46}{}}% \raisebox{1em}{\hypertarget{id17}{}}\hyperlink{id45}{\textbf{\color{red}{[}5{]}\_}}. @@ -814,7 +814,7 @@ rendered separately and differently from footnotes. \end{figure} -Here's a reference to the above, \hyperlink{cit2002}{[CIT2002]}, and a % +Here’s a reference to the above, \hyperlink{cit2002}{[CIT2002]}, and a % \raisebox{1em}{\hypertarget{id48}{}}% \raisebox{1em}{\hypertarget{id19}{}}\hyperlink{id47}{\textbf{\color{red}{[}nonexistent{]}\_}} citation. @@ -826,7 +826,7 @@ } \phantomsection\label{example} -This paragraph is pointed to by the explicit ``example'' target. A +This paragraph is pointed to by the explicit “example” target. A reference can be found under \hyperref[inline-markup]{Inline Markup}, above. \hyperref[inline-hyperlink-targets]{Inline hyperlink targets} are also possible. @@ -834,12 +834,12 @@ \hyperref[targets]{Targets}, which is a subsection of \hyperref[body-elements]{Body Elements}. Explicit external targets are interpolated into references such as -``\href{http://www.python.org/}{Python}\DUfootnotemark{id31}{id29}{5}''. +“\href{http://www.python.org/}{Python}\DUfootnotemark{id31}{id29}{5}”. Targets may be indirect and anonymous. Thus \hyperref[targets]{this phrase} may also refer to the \hyperref[targets]{Targets} section. -Here's a % +Here’s a % \raisebox{1em}{\hypertarget{id50}{}}\hyperlink{id49}{\textbf{\color{red}`hyperlink reference without a target`\_}}, which generates an error. @@ -849,15 +849,15 @@ } Duplicate names in section headers or other implicit targets will -generate ``info'' (level-1) system messages. Duplicate names in -explicit targets will generate ``warning'' (level-2) system messages. +generate “info” (level-1) system messages. Duplicate names in +explicit targets will generate “warning” (level-2) system messages. \subsubsection{2.13.2~~~Duplicate Target Names% \label{id21}% } -Since there are two ``Duplicate Target Names'' section headers, we +Since there are two “Duplicate Target Names” section headers, we cannot uniquely refer to either of them by name. If we try to (like this: % \raisebox{1em}{\hypertarget{id52}{}}\hyperlink{id51}{\textbf{\color{red}`Duplicate Target Names`\_}}), an error is generated. @@ -877,7 +877,7 @@ \label{document-parts}% } -An example of the ``contents'' directive can be seen above this section +An example of the “contents” directive can be seen above this section (a local, untitled table of \hyperref[contents]{contents}) and at the beginning of the document (a document-wide \hyperref[table-of-contents]{table of contents}). @@ -886,7 +886,7 @@ \label{images-and-figures}% } -An image directive (also clickable -{}- a hyperlink reference): +An image directive (also clickable – a hyperlink reference): \hyperref[directives]{\includegraphics{../../../docs/user/rst/images/title.png}} @@ -948,7 +948,7 @@ re & -Revised, revisited, based on 're' module. +Revised, revisited, based on ‘re’ module. \\ \hline @@ -960,7 +960,7 @@ Text & -Well it is, isn't it? +Well it is, isn’t it? \\ \hline \end{longtable*} @@ -1029,7 +1029,7 @@ \DUadmonition[caution]{ \DUtitle[caution]{Caution!} -Don't take any wooden nickels. +Don’t take any wooden nickels. } \DUadmonition[danger]{ @@ -1047,7 +1047,7 @@ \DUadmonition[hint]{ \DUtitle[hint]{Hint} -It's bigger than a bread box. +It’s bigger than a bread box. } \DUadmonition[important]{ @@ -1086,7 +1086,7 @@ } \DUadmonition[admonition-and-by-the-way]{ -\DUtitle[admonition-and-by-the-way]{And, by the way...} +\DUtitle[admonition-and-by-the-way]{And, by the way…} You can make up your own admonition too. } @@ -1121,8 +1121,8 @@ This is a topic. } -A \emph{rubric} is like an informal heading that doesn't correspond to the -document's structure. It is typically highlighted in red (hence the name). +A \emph{rubric} is like an informal heading that doesn’t correspond to the +document’s structure. It is typically highlighted in red (hence the name). \DUrubric{This is a rubric} @@ -1197,8 +1197,8 @@ \end{quote} Compound 4, a paragraph. -Now something \emph{really} perverted -{}- a nested compound block. This is -just to test that it works at all; the results don't have to be +Now something \emph{really} perverted – a nested compound block. This is +just to test that it works at all; the results don’t have to be meaningful. Compound 5, block 1 (a paragraph). @@ -1311,7 +1311,7 @@ \label{comments}% } -Here's one: +Here’s one: % Comments begin with two dots and a space. Anything may % follow, except for the syntax of footnotes, hyperlink @@ -1330,7 +1330,7 @@ This does not necessarily look nice, because there may be missing white space. -It's just there to freeze the behavior. +It’s just there to freeze the behavior. A test. @@ -1437,7 +1437,7 @@ \label{rowspanning-tables}% } -Here's a table with cells spanning several rows: +Here’s a table with cells spanning several rows: \setlength{\DUtablewidth}{\linewidth} \begin{longtable*}[c]{|p{0.296\DUtablewidth}|p{0.156\DUtablewidth}|p{0.226\DUtablewidth}|} @@ -1512,7 +1512,7 @@ \item A language-switching role: -Let's count in German \otherlanguage{ngerman}{eins zwei drei}. +Let’s count in German \otherlanguage{ngerman}{eins zwei drei}. \item A role with multiple class attributes, styled with raw directives: @@ -1645,7 +1645,7 @@ s_{\mathrm{out}}(x) & = s_{\mathrm{in}}(x') * s_\delta (x-x') \\ & = \int s_{\mathrm{in}}(x')s_\delta (x-x')\mathrm{d}x' \end{align*} -Cases (``manually'', with \texttt{matrix} environment): +Cases (“manually”, with \texttt{matrix} environment): % \begin{equation*} \mathrm{sgn}(x) = \left\{\begin{matrix} @@ -2249,12 +2249,12 @@ \label{encoding-special-chars}% } -The LaTeX Info pages lists under ``2.18 Special Characters'' +The LaTeX Info pages lists under “2.18 Special Characters” % \begin{quote} The following characters play a special role in LaTeX and are called -``special printing characters'', or simply ``special characters''. +“special printing characters”, or simply “special characters”. % \begin{quote} @@ -2280,9 +2280,9 @@ In that case the contents between that bracket and the following closing bracket on the same grouping level are taken as the optional argument. What makes this unintuitive is the fact that -the square brackets aren't grouping characters themselves, so in -your last example item{[}{[}...{]}{]} the optional argument consists of -{[}... (without the closing bracket). +the square brackets aren’t grouping characters themselves, so in +your last example item{[}{[}…{]}{]} the optional argument consists of +{[}… (without the closing bracket). \end{quote} @@ -2374,11 +2374,11 @@ \end{description} -If the argument contains any ``\%'', ``\#'', or ``\textasciicircum{}\textasciicircum{}'', or ends with \texttt{\textbackslash{}}, it can't +If the argument contains any “\%”, “\#”, or “\textasciicircum{}\textasciicircum{}”, or ends with \texttt{\textbackslash{}}, it can’t be used in the argument to another command. The argument must not contain unbalanced braces. -The characters \textasciicircum{}, \{, \}, and \texttt{\textbackslash{}} are invalid in a ``http:'' or ``ftp:'' URL +The characters \textasciicircum{}, \{, \}, and \texttt{\textbackslash{}} are invalid in a “http:” or “ftp:” URL and not recognized as part of it: \begin{DUlineblock}{0em} @@ -2419,7 +2419,7 @@ % \begin{itemize} -\item \textasciicircum{}\textasciicircum{} LaTeX's special syntax for characters results in ``strange'' replacements +\item \textasciicircum{}\textasciicircum{} LaTeX’s special syntax for characters results in “strange” replacements (both with href and url). A warning is given. \href{../strange^^name}{file with \textasciicircum{}\textasciicircum{}}: @@ -2506,7 +2506,7 @@ Any errors caught during processing will generate system messages. There should be five messages in the following, auto-generated -section, ``Docutils System Messages'': +section, “Docutils System Messages”: % section should be added by Docutils automatically @@ -2521,7 +2521,7 @@ {\color{red}ERROR/3} in \texttt{functional/input/data/standard.txt}, line~104 \hyperlink{id28}{ -Undefined substitution referenced: ``problematic''. +Undefined substitution referenced: "problematic". }} \DUadmonition[system-message]{ @@ -2531,7 +2531,7 @@ {\color{red}ERROR/3} in \texttt{functional/input/data/standard.txt}, line~391 \hyperlink{id46}{ -Unknown target name: ``5''. +Unknown target name: "5". }} \DUadmonition[system-message]{ @@ -2541,7 +2541,7 @@ {\color{red}ERROR/3} in \texttt{functional/input/data/standard.txt}, line~400 \hyperlink{id48}{ -Unknown target name: ``nonexistent''. +Unknown target name: "nonexistent". }} \DUadmonition[system-message]{ @@ -2551,7 +2551,7 @@ {\color{red}ERROR/3} in \texttt{functional/input/data/standard.txt}, line~427 \hyperlink{id50}{ -Unknown target name: ``hyperlink reference without a target''. +Unknown target name: "hyperlink reference without a target". }} \DUadmonition[system-message]{ @@ -2561,7 +2561,7 @@ {\color{red}ERROR/3} in \texttt{functional/input/data/standard.txt}, line~440 \hyperlink{id52}{ -Duplicate target name, cannot be used as a unique reference: ``duplicate target names''. +Duplicate target name, cannot be used as a unique reference: "duplicate target names". }} \end{document} Modified: trunk/docutils/test/functional/expected/standalone_rst_xetex.tex =================================================================== --- trunk/docutils/test/functional/expected/standalone_rst_xetex.tex 2013-01-04 17:17:38 UTC (rev 7585) +++ trunk/docutils/test/functional/expected/standalone_rst_xetex.tex 2013-01-05 17:00:50 UTC (rev 7586) @@ -231,7 +231,7 @@ \textbf{Date}: & Now, or yesterday. Or maybe even \emph{before} yesterday. \\ \textbf{Status}: & - This is a "work in progress" \\ + This is a “work in progress” \\ \textbf{Revision}: & is managed by a version control system. \\ \textbf{Version}: & @@ -242,12 +242,12 @@ redistribute, reattribute, sell, buy, rent, lease, destroy, or improve it, quote it at length, excerpt, incorporate, collate, fold, staple, or mutilate it, or do -anything else to it that your or anyone else's heart +anything else to it that your or anyone else’s heart desires. \\ \textbf{field name}: & -This is a "generic bibliographic field". +This is a “generic bibliographic field”. \\ -\textbf{field name "2"}: & +\textbf{field name “2”}: & Generic bibliographic fields may contain multiple body elements. Like this. @@ -309,7 +309,7 @@ \label{transitions}% } -Here's a transition: +Here’s a transition: %___________________________________________________________________________ @@ -359,12 +359,12 @@ some explicit interpreted text roles: a PEP reference (\href{http://www.python.org/dev/peps/pep-0287}{PEP 287}); an RFC reference (\href{http://www.faqs.org/rfcs/rfc2822.html}{RFC 2822}); an abbreviation (\DUrole{abbreviation}{abb.}), an acronym (\DUrole{acronym}{reST}), code (\texttt{\DUrole{code}{print "hello world"}}); a \textsubscript{subscript}; -a \textsuperscript{superscript} and explicit roles for \DUroletitlereference{Docutils}' +a \textsuperscript{superscript} and explicit roles for \DUroletitlereference{Docutils}’ \emph{standard} \textbf{inline} \texttt{markup}. % DO NOT RE-WRAP THE FOLLOWING PARAGRAPH! -Let's test wrapping and whitespace significance in inline literals: +Let’s test wrapping and whitespace significance in inline literals: \texttt{This is an example of --inline-literal --text, --including some-- strangely--hyphenated-words. ~Adjust-the-width-of-your-browser-window to see how the text is wrapped. ~-- ---- -------- ~Now note ~ ~the @@ -469,7 +469,7 @@ \end{list} \end{list} -\item Lists that don't start at 1: +\item Lists that don’t start at 1: \setcounter{listcnt1}{0} \begin{list}{\arabic{listcnt1}.} { @@ -553,7 +553,7 @@ \item[{credits:}] \DUrole{credits}{This paragraph has the \DUroletitlereference{credits} class set. (This is actually not about credits but just for ensuring that the class attribute -doesn't get stripped away.)} +doesn’t get stripped away.)} \end{DUfieldlist} @@ -566,7 +566,7 @@ % \begin{DUoptionlist} -\item[-a] command-line option "a" +\item[-a] command-line option “a” \item[-b file] options can have arguments and long descriptions @@ -581,7 +581,7 @@ The description may contain multiple body elements, regardless of where it starts. -\item[-x, -y, -z] Multiple options are an "option group". +\item[-x, -y, -z] Multiple options are an “option group”. \item[-v, --verbose] Commonly-seen: short \& long options. @@ -599,7 +599,7 @@ \label{literal-blocks}% } -Literal blocks are indicated with a double-colon ("::") at the end of +Literal blocks are indicated with a double-colon (“::”) at the end of the preceding paragraph (over there \texttt{-->}). They can be indented: % \begin{quote}{\ttfamily \raggedright \noindent @@ -632,7 +632,7 @@ \item[] This is a line block. It ends with a blank line. \item[] \begin{DUlineblock}{\DUlineblockindent} -\item[] New lines begin with a vertical bar ("|"). +\item[] New lines begin with a vertical bar (“|”). \item[] Line breaks and initial indent are significant, and preserved. \item[] \begin{DUlineblock}{\DUlineblockindent} @@ -647,16 +647,16 @@ \begin{DUlineblock}{0em} \item[] This is a second line block. \item[] -\item[] Blank lines are permitted internally, but they must begin with a "|". +\item[] Blank lines are permitted internally, but they must begin with a “|”. \end{DUlineblock} Another line block, surrounded by paragraphs: \begin{DUlineblock}{0em} -\item[] And it's no good waiting by the window -\item[] It's no good waiting for the sun +\item[] And it’s no good waiting by the window +\item[] It’s no good waiting for the sun \item[] Please believe me, the things you dream of -\item[] They don't fall in the lap of no-one +\item[] They don’t fall in the lap of no-one \end{DUlineblock} Take it away, Eric the Orchestra Leader! @@ -674,7 +674,7 @@ \item[] But half the bee has got to be, \item[] \begin{DUlineblock}{\DUlineblockindent} -\item[] \emph{vis a vis} its entity. D'you see? +\item[] \emph{vis a vis} its entity. D’you see? \item[] \end{DUlineblock} \item[] But can a bee be said to be @@ -691,7 +691,7 @@ \end{DUlineblock} \end{DUlineblock} \end{DUlineblock} -\item[] Singing... +\item[] Singing… \end{DUlineblock} \end{quote} @@ -769,19 +769,19 @@ A footnote contains body elements, consistently indented by at least 3 spaces. -This is the footnote's second paragraph. +This is the footnote’s second paragraph. } % \DUfootnotetext{label}{id3}{2}{\phantomsection\label{label}% Footnotes may be numbered, either manually (as in\DUfootnotemark{id9}{id8}{1}) or -automatically using a "\#"-prefixed label. This footnote has a +automatically using a “\#”-prefixed label. This footnote has a label so it can be referred to from multiple places, both as a footnote reference (\DUfootnotemark{id10}{label}{2}) and as a \hyperref[label]{hyperlink reference}. } % \DUfootnotetext{id12}{id2}{3}{% This footnote is numbered automatically and anonymously using a -label of "\#" only. +label of “\#” only. This is the second paragraph. @@ -789,8 +789,8 @@ } % \DUfootnotetext{id13}{id4}{*}{% -Footnotes may also use symbols, specified with a "*" label. -Here's a reference to the next footnote:\DUfootnotemark{id14}{id15}{†}. +Footnotes may also use symbols, specified with a “*” label. +Here’s a reference to the next footnote:\DUfootnotemark{id14}{id15}{†}. } % \DUfootnotetext{id15}{id14}{†}{% @@ -798,7 +798,7 @@ } % \DUfootnotetext{id16}{id16}{4}{% -Here's an unreferenced footnote, with a reference to a +Here’s an unreferenced footnote, with a reference to a nonexistent footnote:% \raisebox{1em}{\hypertarget{id45}{}}% \raisebox{1em}{\hypertarget{id17}{}}\hyperlink{id44}{\textbf{\color{red}{[}5{]}\_}}. @@ -813,7 +813,7 @@ rendered separately and differently from footnotes. \end{figure} -Here's a reference to the above, \hyperlink{cit2002}{[CIT2002]}, and a % +Here’s a reference to the above, \hyperlink{cit2002}{[CIT2002]}, and a % \raisebox{1em}{\hypertarget{id47}{}}% \raisebox{1em}{\hypertarget{id19}{}}\hyperlink{id46}{\textbf{\color{red}{[}nonexistent{]}\_}} citation. @@ -825,7 +825,7 @@ } \phantomsection\label{example} -This paragraph is pointed to by the explicit "example" target. A +This paragraph is pointed to by the explicit “example” target. A reference can be found under \hyperref[inline-markup]{Inline Markup}, above. \hyperref[inline-hyperlink-targets]{Inline hyperlink targets} are also possible. @@ -833,12 +833,12 @@ \hyperref[targets]{Targets}, which is a subsection of \hyperref[body-elements]{Body Elements}. Explicit external targets are interpolated into references such as -"\href{http://www.python.org/}{Python}\DUfootnotemark{id31}{id29}{5}". +“\href{http://www.python.org/}{Python}\DUfootnotemark{id31}{id29}{5}”. Targets may be indirect and anonymous. Thus \hyperref[targets]{this phrase} may also refer to the \hyperref[targets]{Targets} section. -Here's a % +Here’s a % \raisebox{1em}{\hypertarget{id49}{}}\hyperlink{id48}{\textbf{\color{red}`hyperlink reference without a target`\_}}, which generates an error. @@ -848,15 +848,15 @@ } Duplicate names in section headers or other implicit targets will -generate "info" (level-1) system messages. Duplicate names in -explicit targets will generate "warning" (level-2) system messages. +generate “info” (level-1) system messages. Duplicate names in +explicit targets will generate “warning” (level-2) system messages. \subsubsection{2.13.2 Duplicate Target Names% \label{id21}% } -Since there are two "Duplicate Target Names" section headers, we +Since there are two “Duplicate Target Names” section headers, we cannot uniquely refer to either of them by name. If we try to (like this: % \raisebox{1em}{\hypertarget{id51}{}}\hyperlink{id50}{\textbf{\color{red}`Duplicate Target Names`\_}}), an error is generated. @@ -876,7 +876,7 @@ \label{document-parts}% } -An example of the "contents" directive can be seen above this section +An example of the “contents” directive can be seen above this section (a local, untitled table of \hyperref[contents]{contents}) and at the beginning of the document (a document-wide \hyperref[table-of-contents]{table of contents}). @@ -885,7 +885,7 @@ \label{images-and-figures}% } -An image directive (also clickable -- a hyperlink reference): +An image directive (also clickable – a hyperlink reference): \hyperref[directives]{\includegraphics{../../../docs/user/rst/images/title.png}} @@ -947,7 +947,7 @@ re & -Revised, revisited, based on 're' module. +Revised, revisited, based on ‘re’ module. \\ \hline @@ -959,7 +959,7 @@ Text & -Well it is, isn't it? +Well it is, isn’t it? \\ \hline \end{longtable*} @@ -1028,7 +1028,7 @@ \DUadmonition[caution]{ \DUtitle[caution]{Caution!} -Don't take any wooden nickels. +Don’t take any wooden nickels. } \DUadmonition[danger]{ @@ -1046,7 +1046,7 @@ \DUadmonition[hint]{ \DUtitle[hint]{Hint} -It's bigger than a bread box. +It’s bigger than a bread box. } \DUadmonition[important]{ @@ -1085,7 +1085,7 @@ } \DUadmonition[admonition-and-by-the-way]{ -\DUtitle[admonition-and-by-the-way]{And, by the way...} +\DUtitle[admonition-and-by-the-way]{And, by the way…} You can make up your own admonition too. } @@ -1120,8 +1120,8 @@ This is a topic. } -A \emph{rubric} is like an informal heading that doesn't correspond to the -document's structure. It is typically highlighted in red (hence the name). +A \emph{rubric} is like an informal heading that doesn’t correspond to the +document’s structure. It is typically highlighted in red (hence the name). \DUrubric{This is a rubric} @@ -1196,8 +1196,8 @@ \end{quote} Compound 4, a paragraph. -Now something \emph{really} perverted -- a nested compound block. This is -just to test that it works at all; the results don't have to be +Now something \emph{really} perverted – a nested compound block. This is +just to test that it works at all; the results don’t have to be meaningful. Compound 5, block 1 (a paragraph). @@ -1310,7 +1310,7 @@ \label{comments}% } -Here's one: +Here’s one: % Comments begin with two dots and a space. Anything may % follow, except for the syntax of footnotes, hyperlink @@ -1329,7 +1329,7 @@ This does not necessarily look nice, because there may be missing white space. -It's just there to freeze the behavior. +It’s just there to freeze the behavior. A test. @@ -1436,7 +1436,7 @@ \label{rowspanning-tables}% } -Here's a table with cells spanning several rows: +Here’s a table with cells spanning several rows: \setlength{\DUtablewidth}{\linewidth} \begin{longtable*}[c]{|p{0.296\DUtablewidth}|p{0.156\DUtablewidth}|p{0.226\DUtablewidth}|} @@ -1511,7 +1511,7 @@ \item A language-switching role: -Let's count in German \otherlanguage{german}{eins zwei drei}. +Let’s count in German \otherlanguage{german}{eins zwei drei}. \item A role with multiple class attributes, styled with raw directives: @@ -2060,12 +2060,12 @@ \label{encoding-special-chars}% } -The LaTeX Info pages lists under "2.18 Special Characters" +The LaTeX Info pages lists under “2.18 Special Characters” % \begin{quote} The following characters play a special role in LaTeX and are called -"special printing characters", or simply "special characters". +“special printing characters”, or simply “special characters”. % \begin{quote} @@ -2091,9 +2091,9 @@ In that case the contents between that bracket and the following closing bracket on the same grouping level are taken as the optional argument. What makes this unintuitive is the fact that -the square brackets aren't grouping characters themselves, so in -your last example item{[}{[}...{]}{]} the optional argument consists of -{[}... (without the closing bracket). +the square brackets aren’t grouping characters themselves, so in +your last example item{[}{[}…{]}{]} the optional argument consists of +{[}… (without the closing bracket). \end{quote} @@ -2185,11 +2185,11 @@ \end{description} -If the argument contains any "\%", "\#", or "\textasciicircum{}\textasciicircum{}", or ends with \texttt{\textbackslash{}}, it can't +If the argument contains any “\%”, “\#”, or “\textasciicircum{}\textasciicircum{}”, or ends with \texttt{\textbackslash{}}, it can’t be used in the argument to another command. The argument must not contain unbalanced braces. -The characters \textasciicircum{}, \{, \}, and \texttt{\textbackslash{}} are invalid in a "http:" or "ftp:" URL +The characters \textasciicircum{}, \{, \}, and \texttt{\textbackslash{}} are invalid in a “http:” or “ftp:” URL and not recognized as part of it: \begin{DUlineblock}{0em} @@ -2230,7 +2230,7 @@ % \begin{itemize} -\item \textasciicircum{}\textasciicircum{} LaTeX's special syntax for characters results in "strange" replacements +\item \textasciicircum{}\textasciicircum{} LaTeX’s special syntax for characters results in “strange” replacements (both with href and url). A warning is given. \href{../strange^^name}{file with \textasciicircum{}\textasciicircum{}}: @@ -2329,7 +2329,7 @@ Any errors caught during processing will generate system messages. There should be five messages in the following, auto-generated -section, "Docutils System Messages": +section, “Docutils System Messages”: % section should be added by Docutils automatically Modified: trunk/docutils/test/functional/tests/standalone_rst_latex.py =================================================================== --- trunk/docutils/test/functional/tests/standalone_rst_latex.py 2013-01-04 17:17:38 UTC (rev 7585) +++ trunk/docutils/test/functional/tests/standalone_rst_latex.py 2013-01-05 17:00:50 UTC (rev 7586) @@ -6,3 +6,7 @@ # Keyword parameters passed to publish_file. writer_name = "latex" + +# Settings +# use "smartquotes" transition: +settings_overrides['smart_quotes'] = True Modified: trunk/docutils/test/functional/tests/standalone_rst_xetex.py =================================================================== --- trunk/docutils/test/functional/tests/standalone_rst_xetex.py 2013-01-04 17:17:38 UTC (rev 7585) +++ trunk/docutils/test/functional/tests/standalone_rst_xetex.py 2013-01-05 17:00:50 UTC (rev 7586) @@ -6,3 +6,7 @@ # Keyword parameters passed to publish_file. writer_name = "xetex" + +# Settings +# use "smartquotes" transition: +settings_overrides['smart_quotes'] = True Modified: trunk/docutils/test/test_writers/test_latex2e.py =================================================================== --- trunk/docutils/test/test_writers/test_latex2e.py 2013-01-04 17:17:38 UTC (rev 7585) +++ trunk/docutils/test/test_writers/test_latex2e.py 2013-01-05 17:00:50 UTC (rev 7586) @@ -421,55 +421,10 @@ """], ] -# BUG: need to test for quote replacing if language is de (ngerman). +# TODO: need to test for quote replacing if the language uses "ASCII-quotes" +# as active character (e.g. de (ngerman)). -totest['quote_mangling'] = [ -# input -[""" -Depending on language quotes are converted for latex. -Expecting "en" here. -Inside literal blocks quotes should be left untouched -(use only two quotes in test code makes life easier for -the python interpreter running the test):: - - "" - This is left "untouched" also *this*. - "" - -.. parsed-literal:: - - should get "quotes" and *italics*. - - -Inline ``literal "quotes"`` should be kept. -""", -head + r""" -Depending on language quotes are converted for latex. -Expecting ``en'' here. - -Inside literal blocks quotes should be left untouched -(use only two quotes in test code makes life easier for -the python interpreter running the test): -% -\begin{quote}{\ttfamily \raggedright \noindent -"{}"\\ -This~is~left~"untouched"~also~*this*.\\ -"{}" -} -\end{quote} -% -\begin{quote}{\ttfamily \raggedright \noindent -should~get~"quotes"~and~\emph{italics}. -} -\end{quote} - -Inline \texttt{literal "quotes"} should be kept. - -\end{document} -"""], -] - totest['table_caption'] = [ # input ["""\ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mi...@us...> - 2013-01-17 15:48:39
|
Revision: 7589 http://docutils.svn.sourceforge.net/docutils/?rev=7589&view=rev Author: milde Date: 2013-01-17 15:48:30 +0000 (Thu, 17 Jan 2013) Log Message: ----------- Fix literal use of babel shorthands (straight quote, tilde, ...). Modified Paths: -------------- trunk/docutils/HISTORY.txt trunk/docutils/docutils/writers/latex2e/__init__.py trunk/docutils/test/functional/expected/cyrillic.tex trunk/docutils/test/functional/expected/standalone_rst_latex.tex trunk/docutils/test/functional/expected/standalone_rst_xetex.tex trunk/docutils/test/functional/expected/xetex-cyrillic.tex trunk/docutils/test/functional/input/cyrillic.txt trunk/docutils/test/functional/tests/latex_cyrillic.py trunk/docutils/test/functional/tests/xetex_cyrillic.py trunk/docutils/test/test_writers/test_latex2e.py Added Paths: ----------- trunk/docutils/test/functional/expected/latex_babel.tex trunk/docutils/test/functional/input/latex_babel.txt trunk/docutils/test/functional/tests/latex_babel.py Modified: trunk/docutils/HISTORY.txt =================================================================== --- trunk/docutils/HISTORY.txt 2013-01-17 15:41:35 UTC (rev 7588) +++ trunk/docutils/HISTORY.txt 2013-01-17 15:48:30 UTC (rev 7589) @@ -23,9 +23,11 @@ * docutils/writers/latex2e/__init__.py - Drop the simple algorithm replacing straight double quotes with - English typographic ones. Use the SmartQuotes transform - (``--smart-quotes=True``) instead. + English typographic ones. + Activate the SmartQuotes_ transform if you want this feature. + - Fix literal use of babel shorthands (straight quote, tilde, ...). +.. _SmartQuotes: docs/user/config.html#smart-quotes Release 0.10 (2012-12-16) ========================= Modified: trunk/docutils/docutils/writers/latex2e/__init__.py =================================================================== --- trunk/docutils/docutils/writers/latex2e/__init__.py 2013-01-17 15:41:35 UTC (rev 7588) +++ trunk/docutils/docutils/writers/latex2e/__init__.py 2013-01-17 15:48:30 UTC (rev 7589) @@ -305,7 +305,7 @@ 'en-GB': 'british', 'en-NZ': 'newzealand', 'en-US': 'american', - 'eo': 'esperanto', # '^' is active + 'eo': 'esperanto', 'es': 'spanish', 'et': 'estonian', 'eu': 'basque', @@ -335,12 +335,12 @@ 'nb': 'norsk', # Norwegian Bokmal 'nl': 'dutch', 'nn': 'nynorsk', # Norwegian Nynorsk - 'no': 'norsk', # Norwegian Bokmal + 'no': 'norsk', # Norwegian (Bokmal) 'pl': 'polish', 'pt': 'portuges', 'pt-BR': 'brazil', 'ro': 'romanian', - 'ru': 'russian', # '"' is active + 'ru': 'russian', 'se': 'samin', # North Sami # sh-Cyrl: Serbo-Croatian, Cyrillic script 'sh-Latn': 'serbian', # Serbo-Croatian, Latin script @@ -348,7 +348,7 @@ 'sl': 'slovene', 'sq': 'albanian', # 'sr-Cyrl': Serbian, Cyrillic script (sr-cyrl) - 'sr-Latn': 'serbian', # Serbian, Latin script, " active. + 'sr-Latn': 'serbian', # Serbian, Latin script 'sv': 'swedish', # 'th': 'thai', 'tr': 'turkish', @@ -361,49 +361,59 @@ warn_msg = 'Language "%s" not supported by LaTeX (babel)' - # double quotes are "active" in some languages (e.g. German). - literal_double_quote = u'"' - # Languages with active ``"``, defining ``\dq``: - active_dq_languages = ('bulgarian', - 'czech', - 'estonian', - 'german', 'ngerman', 'austrian', 'naustrian', - 'icelandic', - 'norsk', 'nynorsk', - 'polish', - 'russian', - 'slovak', - 'swedish', - 'ukrainian', - 'uppersorbian',) - # Languages with active ``"``, not defining ``\dq`` - # TODO: complete set of languages with active ``"``, - # care for other active characters. - active_dq_languages_2 = ('danish', - 'dutch', - 'italian', 'latin') + # "Active characters" are shortcuts that start a LaTeX macro and may need + # escaping for literals use. Characters that prevent literal use (e.g. + # starting accent macros like "a -> ä) will be deactivated if one of the + # defining languages is used in the document. + # Special cases: + # ~ (tilde) -- used in estonian, basque, galician, and old versions of + # spanish -- cannot be deactivated as it denotes a no-break space macro, + # " (straight quote) -- used in albanian, austrian, basque + # brazil, bulgarian, catalan, czech, danish, dutch, estonian, + # finnish, galician, german, icelandic, italian, latin, naustrian, + # ngerman, norsk, nynorsk, polish, portuges, russian, serbian, slovak, + # slovene, spanish, swedish, ukrainian, and uppersorbian -- + # is escaped as ``\textquotedbl``. + active_chars = {# TeX/Babel-name: active characters to deactivate + # 'breton': ':;!?' # ensure whitespace + # 'esperanto': '^', + # 'estonian': '~"`', + # 'french': ':;!?' # ensure whitespace + 'galician': '.<>', # also '~"' + # 'magyar': '`', # for special hyphenation cases + 'spanish': '.<>', # old versions also '~' + # 'turkish': ':!=' # ensure whitespace + } def __init__(self, language_code, reporter=None): self.reporter = reporter self.language = self.language_name(language_code) self.otherlanguages = {} - self.quote_index = 0 - # language dependent configuration: - if self.language in active_dq_languages: - self.literal_double_quote = ur'\dq{}' - elif self.language in active_dq_languages_2: - self.literal_double_quote = ur'{\char`\"}' def __call__(self): """Return the babel call with correct options and settings""" languages = sorted(self.otherlanguages.keys()) languages.append(self.language or 'english') self.setup = [r'\usepackage[%s]{babel}' % ','.join(languages)] - if 'spanish' in languages: - # reset active chars to the original meaning: - self.setup.append( - r'\addto\shorthandsspanish{\spanishdeactivate{."~<>}}') - # or prepend r'\def\spanishoptions{es-noshorthands}' + # Deactivate "active characters" + shorthands = [] + for c in ''.join([self.active_chars.get(l, '') for l in languages]): + if c not in shorthands: + shorthands.append(c) + if shorthands: + self.setup.append(r'\AtBeginDocument{\shorthandoff{%s}}' + % ''.join(shorthands)) + # Including '~' in shorthandoff prevents its use as no-break space + if 'galician' in languages: + self.setup.append(r'\deactivatetilden % restore ~ in Galician') + if 'estonian' in languages: + self.setup.extend([r'\makeatletter', + r' \addto\extrasestonian{\bbl@deactivate{~}}', + r'\makeatother']) + if 'basque' in languages: + self.setup.extend([r'\makeatletter', + r' \addto\extrasbasque{\bbl@deactivate{~}}', + r'\makeatother']) if (languages[-1] == 'english' and 'french' in self.otherlanguages.keys()): self.setup += ['% Prevent side-effects if French hyphenation ' @@ -702,6 +712,8 @@ ord('\\'): ur'\textbackslash{}', ord('{'): ur'\{', ord('}'): ur'\}', + # straight double quotes are 'active' in many languages + ord('"'): ur'\textquotedbl{}', # Square brackets are ordinary chars and cannot be escaped with '\', # so we put them in a group '{[}'. (Alternative: ensure that all # macros with optional arguments are terminated with {} and text @@ -710,7 +722,8 @@ # group, e.g. ``\item[{\hyperref[label]{text}}]``. ord('['): ur'{[}', ord(']'): ur'{]}', - # the soft hyphen is unknown in 8-bit text and not properly handled by XeTeX + # the soft hyphen is unknown in 8-bit text + # and not properly handled by XeTeX 0x00AD: ur'\-', # SOFT HYPHEN } # Unicode chars that are not recognized by LaTeX's utf8 encoding @@ -1261,9 +1274,19 @@ self.requirements['_inputenc'] = (r'\usepackage[%s]{inputenc}' % self.latex_encoding) # TeX font encoding - if self.font_encoding and not self.is_xetex: - self.requirements['_fontenc'] = (r'\usepackage[%s]{fontenc}' % - self.font_encoding) + if not self.is_xetex: + if self.font_encoding: + self.requirements['_fontenc'] = (r'\usepackage[%s]{fontenc}' % + self.font_encoding) + # ensure \textquotedbl is defined: + for enc in self.font_encoding.split(','): + enc = enc.strip() + if enc == 'OT1': + self.requirements['_textquotedblOT1'] = ( + r'\DeclareTextSymbol{\textquotedbl}{OT1}{`\"}') + elif enc not in ('T1', 'T2A', 'T2B', 'T2C', 'T4', 'T5'): + self.requirements['_textquotedbl'] = ( + r'\DeclareTextSymbolDefault{\textquotedbl}{T1}') # page layout with typearea (if there are relevant document options) if (settings.documentclass.find('scr') == -1 and (self.documentoptions.find('DIV') != -1 or @@ -1423,9 +1446,6 @@ # Set up the translation table: table = CharMaps.special.copy() - # double quotes are 'active' in some languages - # TODO: use \textquotedbl if font encoding is T1? - table[ord('"')] = self.babel.literal_double_quote # keep the underscore in citation references if self.inside_citation_reference_label: del(table[ord('_')]) Modified: trunk/docutils/test/functional/expected/cyrillic.tex =================================================================== --- trunk/docutils/test/functional/expected/cyrillic.tex 2013-01-17 15:41:35 UTC (rev 7588) +++ trunk/docutils/test/functional/expected/cyrillic.tex 2013-01-17 15:48:30 UTC (rev 7589) @@ -37,28 +37,28 @@ \label{id1}% } -первый пример: "Здравствуй, мир!" +первый пример: «Здравствуй, мир!» \section{Title% \label{title}% } -\otherlanguage{english}{first example: "Hello world".} +\foreignlanguage{english}{first example: “Hello world”.} \section{Notes% \label{notes}% } -This example tests rendering of Latin and Cyrillic characters by the LaTeX +\foreignlanguage{english}{This example tests rendering of Latin and Cyrillic characters by the LaTeX and XeTeX writers. Check the compiled PDF for garbage characters in text and -bookmarks. +bookmarks.} -To work around a problem with Cyrillic in PDF-bookmarks in \DUroletitlereference{hyperref} +\foreignlanguage{english}{To work around a problem with Cyrillic in PDF-bookmarks in \DUroletitlereference{hyperref} versions older than v6.79g 2009/11/20, the test caller \texttt{latex\_cyrillic.py} sets \texttt{hyperref\_options} to \texttt{'unicode=true'} while \texttt{xetex\_cyrillic.py} sets it to \texttt{'unicode=false'}. The recommended option for current -(2011-08-24) hyperref versions is \texttt{'pdfencoding=auto'}. +(2011-08-24) hyperref versions is \texttt{'pdfencoding=auto'}.} \end{document} Added: trunk/docutils/test/functional/expected/latex_babel.tex =================================================================== --- trunk/docutils/test/functional/expected/latex_babel.tex (rev 0) +++ trunk/docutils/test/functional/expected/latex_babel.tex 2013-01-17 15:48:30 UTC (rev 7589) @@ -0,0 +1,61 @@ +\documentclass[a4paper]{article} +% generated by Docutils <http://docutils.sourceforge.net/> +\usepackage{fixltx2e} % LaTeX patches, \textsubscript +\usepackage{cmap} % fix search and cut-and-paste in Acrobat +\usepackage{ifthen} +\usepackage[T1]{fontenc} +\usepackage[utf8]{inputenc} +\usepackage[basque,esperanto,estonian,galician,ngerman,english]{babel} +\AtBeginDocument{\shorthandoff{.<>}} +\deactivatetilden % restore ~ in Galician +\makeatletter + \addto\extrasestonian{\bbl@deactivate{~}} +\makeatother +\makeatletter + \addto\extrasbasque{\bbl@deactivate{~}} +\makeatother + +%%% Custom LaTeX preamble +% PDF Standard Fonts +\usepackage{mathptmx} % Times +\usepackage[scaled=.90]{helvet} +\usepackage{courier} + +%%% User specified packages and stylesheets + +%%% Fallback definitions for Docutils-specific commands + +% hyperlinks: +\ifthenelse{\isundefined{\hypersetup}}{ + \usepackage[colorlinks=true,linkcolor=blue,urlcolor=blue]{hyperref} + \urlstyle{same} % normal text font (alternatives: tt, rm, sf) +}{} + + +%%% Body +\begin{document} + +The \href{http://www.ctan.org/packages/babel}{babel} package introduces the concept of \textquotedbl{}shorthands\textquotedbl{}: additional +characters that introduce a latex macro. Most common is the active double +quote (\textquotedbl{}). Problematic is the tilde character (\textasciitilde{}) which is regularely used +for no-break spaces but redefined by some language definition files: + +English: 'an' \textquotedbl{}active\textquotedbl{}-quote, \textasciicircum{}circumflex, and~no-break~spaces + +\foreignlanguage{basque}{Basque: 'an' \textquotedbl{}active\textquotedbl{}-quote, \textasciicircum{}circumflex, and~no-break~spaces} + +\foreignlanguage{esperanto}{Esperanto: 'an' \textquotedbl{}active\textquotedbl{}-quote, \textasciicircum{}circumflex, and~no-break~spaces} + +\foreignlanguage{estonian}{Estonian: 'an' \textquotedbl{}active\textquotedbl{}-quote, \textasciicircum{}circumflex, and~no-break~spaces} + +\foreignlanguage{galician}{Galician: 'an' \textquotedbl{}active\textquotedbl{}-quote, \textasciicircum{}circumflex, and~no-break~spaces} + +\foreignlanguage{ngerman}{German: 'an' \textquotedbl{}active\textquotedbl{}-quote, \textasciicircum{}circumflex, and~no-break~spaces} + +Spanish: option clash with Galician! + +% .. class:: language-es +% +% Spanish: 'an' "active"-quote, ^circumflex, and no-break spaces + +\end{document} Property changes on: trunk/docutils/test/functional/expected/latex_babel.tex ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision Added: svn:eol-style + native Modified: trunk/docutils/test/functional/expected/standalone_rst_latex.tex =================================================================== --- trunk/docutils/test/functional/expected/standalone_rst_latex.tex 2013-01-17 15:41:35 UTC (rev 7588) +++ trunk/docutils/test/functional/expected/standalone_rst_latex.tex 2013-01-17 15:48:30 UTC (rev 7589) @@ -359,7 +359,7 @@ The default role for interpreted text is \DUroletitlereference{Title Reference}. Here are some explicit interpreted text roles: a PEP reference (\href{http://www.python.org/dev/peps/pep-0287}{PEP 287}); an RFC reference (\href{http://www.faqs.org/rfcs/rfc2822.html}{RFC 2822}); an abbreviation (\DUrole{abbreviation}{abb.}), an acronym -(\DUrole{acronym}{reST}), code (\texttt{\DUrole{code}{print "hello world"}}); a \textsubscript{subscript}; +(\DUrole{acronym}{reST}), code (\texttt{\DUrole{code}{print \textquotedbl{}hello world\textquotedbl{}}}); a \textsubscript{subscript}; a \textsuperscript{superscript} and explicit roles for \DUroletitlereference{Docutils}’ \emph{standard} \textbf{inline} \texttt{markup}. @@ -701,7 +701,7 @@ also be centre-aligned: \begin{DUlineblock}{0em} -\otherlanguage{ngerman}{\DUrole{align-center}{ +\foreignlanguage{ngerman}{\DUrole{align-center}{ \item[] \textbf{Die Trichter} \item[] \item[] Zwei Trichter wandeln durch die Nacht. @@ -742,7 +742,7 @@ % % \begin{quote} -\otherlanguage{french}{ +\foreignlanguage{french}{ ReStructuredText est un langage de balisage léger utilisé notamment dans la documentation du langage Python. } @@ -754,8 +754,8 @@ } % \begin{quote}{\ttfamily \raggedright \noindent ->{}>{}>~print~'Python-specific~usage~examples;~begun~with~">{}>{}>"'\\ -Python-specific~usage~examples;~begun~with~">{}>{}>"\\ +>{}>{}>~print~'Python-specific~usage~examples;~begun~with~\textquotedbl{}>{}>{}>\textquotedbl{}'\\ +Python-specific~usage~examples;~begun~with~\textquotedbl{}>{}>{}>\textquotedbl{}\\ >{}>{}>~print~'(cut~and~pasted~from~interactive~Python~sessions)'\\ (cut~and~pasted~from~interactive~Python~sessions) } @@ -1512,7 +1512,7 @@ \item A language-switching role: -Let’s count in German \otherlanguage{ngerman}{eins zwei drei}. +Let’s count in German \foreignlanguage{ngerman}{eins zwei drei}. \item A role with multiple class attributes, styled with raw directives: @@ -1525,14 +1525,14 @@ \begin{quote}{\ttfamily \raggedright \noindent ..~raw::~html\\ ~\\ -~~<style~type="text/css"><!-{}-\\ +~~<style~type=\textquotedbl{}text/css\textquotedbl{}><!-{}-\\ ~~~.green~\{color:~green;\}\\ ~~~.sc~\{font-variant:~small-caps;\}\\ ~~~-{}-></style> } \end{quote} -\otherlanguage{british}{\DUrole{green}{\DUrole{sc}{British colourful text in small-caps}}}. +\foreignlanguage{british}{\DUrole{green}{\DUrole{sc}{British colourful text in small-caps}}}. \end{itemize} @@ -1821,7 +1821,7 @@ These are all ASCII characters except a-zA-Z0-9 and space: -\texttt{!!!"{}"{}"\#\#\#\$\$\$\%\%\%\&\&\&'{}'{}'((()))***+++,{},{},-{}-{}-...///:::} +\texttt{!!!\textquotedbl{}\textquotedbl{}\textquotedbl{}\#\#\#\$\$\$\%\%\%\&\&\&'{}'{}'((()))***+++,{},{},-{}-{}-...///:::} \texttt{;;;<{}<{}<===>{}>{}>???@@@{[}{[}{[}\textbackslash{}\textbackslash{}\textbackslash{}{]}{]}{]}\textasciicircum{}\textasciicircum{}\textasciicircum{}\_\_\_`{}`{}`\{\{\{|||\}\}\}\textasciitilde{}\textasciitilde{}\textasciitilde{}} @@ -2521,7 +2521,7 @@ {\color{red}ERROR/3} in \texttt{functional/input/data/standard.txt}, line~104 \hyperlink{id28}{ -Undefined substitution referenced: "problematic". +Undefined substitution referenced: \textquotedbl{}problematic\textquotedbl{}. }} \DUadmonition[system-message]{ @@ -2531,7 +2531,7 @@ {\color{red}ERROR/3} in \texttt{functional/input/data/standard.txt}, line~391 \hyperlink{id46}{ -Unknown target name: "5". +Unknown target name: \textquotedbl{}5\textquotedbl{}. }} \DUadmonition[system-message]{ @@ -2541,7 +2541,7 @@ {\color{red}ERROR/3} in \texttt{functional/input/data/standard.txt}, line~400 \hyperlink{id48}{ -Unknown target name: "nonexistent". +Unknown target name: \textquotedbl{}nonexistent\textquotedbl{}. }} \DUadmonition[system-message]{ @@ -2551,7 +2551,7 @@ {\color{red}ERROR/3} in \texttt{functional/input/data/standard.txt}, line~427 \hyperlink{id50}{ -Unknown target name: "hyperlink reference without a target". +Unknown target name: \textquotedbl{}hyperlink reference without a target\textquotedbl{}. }} \DUadmonition[system-message]{ @@ -2561,7 +2561,7 @@ {\color{red}ERROR/3} in \texttt{functional/input/data/standard.txt}, line~440 \hyperlink{id52}{ -Duplicate target name, cannot be used as a unique reference: "duplicate target names". +Duplicate target name, cannot be used as a unique reference: \textquotedbl{}duplicate target names\textquotedbl{}. }} \end{document} Modified: trunk/docutils/test/functional/expected/standalone_rst_xetex.tex =================================================================== --- trunk/docutils/test/functional/expected/standalone_rst_xetex.tex 2013-01-17 15:41:35 UTC (rev 7588) +++ trunk/docutils/test/functional/expected/standalone_rst_xetex.tex 2013-01-17 15:48:30 UTC (rev 7589) @@ -28,7 +28,7 @@ % Linux Libertine (free, wide coverage, not only for Linux) \setmainfont{Linux Libertine O} \setsansfont{Linux Biolinum O} -\setmonofont[HyphenChar=None]{DejaVu Sans Mono} +\setmonofont[HyphenChar=None,Scale=MatchLowercase]{DejaVu Sans Mono} %%% User specified packages and stylesheets @@ -358,7 +358,7 @@ The default role for interpreted text is \DUroletitlereference{Title Reference}. Here are some explicit interpreted text roles: a PEP reference (\href{http://www.python.org/dev/peps/pep-0287}{PEP 287}); an RFC reference (\href{http://www.faqs.org/rfcs/rfc2822.html}{RFC 2822}); an abbreviation (\DUrole{abbreviation}{abb.}), an acronym -(\DUrole{acronym}{reST}), code (\texttt{\DUrole{code}{print "hello world"}}); a \textsubscript{subscript}; +(\DUrole{acronym}{reST}), code (\texttt{\DUrole{code}{print \textquotedbl{}hello world\textquotedbl{}}}); a \textsubscript{subscript}; a \textsuperscript{superscript} and explicit roles for \DUroletitlereference{Docutils}’ \emph{standard} \textbf{inline} \texttt{markup}. @@ -700,7 +700,7 @@ also be centre-aligned: \begin{DUlineblock}{0em} -\otherlanguage{german}{\DUrole{align-center}{ +\foreignlanguage{german}{\DUrole{align-center}{ \item[] \textbf{Die Trichter} \item[] \item[] Zwei Trichter wandeln durch die Nacht. @@ -741,7 +741,7 @@ % % \begin{quote} -\otherlanguage{french}{ +\foreignlanguage{french}{ ReStructuredText est un langage de balisage léger utilisé notamment dans la documentation du langage Python. } @@ -753,8 +753,8 @@ } % \begin{quote}{\ttfamily \raggedright \noindent ->>>~print~'Python-specific~usage~examples;~begun~with~">>>"'\\ -Python-specific~usage~examples;~begun~with~">>>"\\ +>>>~print~'Python-specific~usage~examples;~begun~with~\textquotedbl{}>>>\textquotedbl{}'\\ +Python-specific~usage~examples;~begun~with~\textquotedbl{}>>>\textquotedbl{}\\ >>>~print~'(cut~and~pasted~from~interactive~Python~sessions)'\\ (cut~and~pasted~from~interactive~Python~sessions) } @@ -1511,7 +1511,7 @@ \item A language-switching role: -Let’s count in German \otherlanguage{german}{eins zwei drei}. +Let’s count in German \foreignlanguage{german}{eins zwei drei}. \item A role with multiple class attributes, styled with raw directives: @@ -1524,14 +1524,14 @@ \begin{quote}{\ttfamily \raggedright \noindent ..~raw::~html\\ ~\\ -~~<style~type="text/css"><!--\\ +~~<style~type=\textquotedbl{}text/css\textquotedbl{}><!--\\ ~~~.green~\{color:~green;\}\\ ~~~.sc~\{font-variant:~small-caps;\}\\ ~~~--></style> } \end{quote} -\otherlanguage{british}{\DUrole{green}{\DUrole{sc}{British colourful text in small-caps}}}. +\foreignlanguage{british}{\DUrole{green}{\DUrole{sc}{British colourful text in small-caps}}}. \end{itemize} @@ -1632,7 +1632,7 @@ These are all ASCII characters except a-zA-Z0-9 and space: -\texttt{!!!"""\#\#\#\$\$\$\%\%\%\&\&\&'''((()))***+++,,,---...///:::} +\texttt{!!!\textquotedbl{}\textquotedbl{}\textquotedbl{}\#\#\#\$\$\$\%\%\%\&\&\&'''((()))***+++,,,---...///:::} \texttt{;;;<<<===>>>???@@@{[}{[}{[}\textbackslash{}\textbackslash{}\textbackslash{}{]}{]}{]}\textasciicircum{}\textasciicircum{}\textasciicircum{}\_\_\_```\{\{\{|||\}\}\}\textasciitilde{}\textasciitilde{}\textasciitilde{}} @@ -2344,7 +2344,7 @@ {\color{red}ERROR/3} in \texttt{functional/input/data/standard.txt}, line~104 \hyperlink{id28}{ -Undefined substitution referenced: "problematic". +Undefined substitution referenced: \textquotedbl{}problematic\textquotedbl{}. }} \DUadmonition[system-message]{ @@ -2354,7 +2354,7 @@ {\color{red}ERROR/3} in \texttt{functional/input/data/standard.txt}, line~391 \hyperlink{id45}{ -Unknown target name: "5". +Unknown target name: \textquotedbl{}5\textquotedbl{}. }} \DUadmonition[system-message]{ @@ -2364,7 +2364,7 @@ {\color{red}ERROR/3} in \texttt{functional/input/data/standard.txt}, line~400 \hyperlink{id47}{ -Unknown target name: "nonexistent". +Unknown target name: \textquotedbl{}nonexistent\textquotedbl{}. }} \DUadmonition[system-message]{ @@ -2374,7 +2374,7 @@ {\color{red}ERROR/3} in \texttt{functional/input/data/standard.txt}, line~427 \hyperlink{id49}{ -Unknown target name: "hyperlink reference without a target". +Unknown target name: \textquotedbl{}hyperlink reference without a target\textquotedbl{}. }} \DUadmonition[system-message]{ @@ -2384,7 +2384,7 @@ {\color{red}ERROR/3} in \texttt{functional/input/data/standard.txt}, line~440 \hyperlink{id51}{ -Duplicate target name, cannot be used as a unique reference: "duplicate target names". +Duplicate target name, cannot be used as a unique reference: \textquotedbl{}duplicate target names\textquotedbl{}. }} \end{document} Modified: trunk/docutils/test/functional/expected/xetex-cyrillic.tex =================================================================== --- trunk/docutils/test/functional/expected/xetex-cyrillic.tex 2013-01-17 15:41:35 UTC (rev 7588) +++ trunk/docutils/test/functional/expected/xetex-cyrillic.tex 2013-01-17 15:48:30 UTC (rev 7589) @@ -13,7 +13,7 @@ % Linux Libertine (free, wide coverage, not only for Linux) \setmainfont{Linux Libertine O} \setsansfont{Linux Biolinum O} -\setmonofont[HyphenChar=None]{DejaVu Sans Mono} +\setmonofont[HyphenChar=None,Scale=MatchLowercase]{DejaVu Sans Mono} %%% User specified packages and stylesheets @@ -37,28 +37,28 @@ \label{id1}% } -первый пример: "Здравствуй, мир!" +первый пример: «Здравствуй, мир!» \section{Title% \label{title}% } -\otherlanguage{english}{first example: "Hello world".} +\foreignlanguage{english}{first example: “Hello world”.} \section{Notes% \label{notes}% } -This example tests rendering of Latin and Cyrillic characters by the LaTeX +\foreignlanguage{english}{This example tests rendering of Latin and Cyrillic characters by the LaTeX and XeTeX writers. Check the compiled PDF for garbage characters in text and -bookmarks. +bookmarks.} -To work around a problem with Cyrillic in PDF-bookmarks in \DUroletitlereference{hyperref} +\foreignlanguage{english}{To work around a problem with Cyrillic in PDF-bookmarks in \DUroletitlereference{hyperref} versions older than v6.79g 2009/11/20, the test caller \texttt{latex\_cyrillic.py} sets \texttt{hyperref\_options} to \texttt{'unicode=true'} while \texttt{xetex\_cyrillic.py} sets it to \texttt{'unicode=false'}. The recommended option for current -(2011-08-24) hyperref versions is \texttt{'pdfencoding=auto'}. +(2011-08-24) hyperref versions is \texttt{'pdfencoding=auto'}.} \end{document} Modified: trunk/docutils/test/functional/input/cyrillic.txt =================================================================== --- trunk/docutils/test/functional/input/cyrillic.txt 2013-01-17 15:41:35 UTC (rev 7588) +++ trunk/docutils/test/functional/input/cyrillic.txt 2013-01-17 15:48:30 UTC (rev 7589) @@ -10,15 +10,17 @@ first example: "Hello world". -.. class:: language-en - Notes ----- +.. class:: language-en + This example tests rendering of Latin and Cyrillic characters by the LaTeX and XeTeX writers. Check the compiled PDF for garbage characters in text and bookmarks. +.. class:: language-en + To work around a problem with Cyrillic in PDF-bookmarks in `hyperref` versions older than v6.79g 2009/11/20, the test caller ``latex_cyrillic.py`` sets ``hyperref_options`` to ``'unicode=true'`` while ``xetex_cyrillic.py`` Added: trunk/docutils/test/functional/input/latex_babel.txt =================================================================== --- trunk/docutils/test/functional/input/latex_babel.txt (rev 0) +++ trunk/docutils/test/functional/input/latex_babel.txt 2013-01-17 15:48:30 UTC (rev 7589) @@ -0,0 +1,36 @@ +The babel_ package introduces the concept of "shorthands": additional +characters that introduce a latex macro. Most common is the active double +quote ("). Problematic is the tilde character (~) which is regularely used +for no-break spaces but redefined by some language definition files: + +English: 'an' "active"-quote, ^circumflex, and no-break spaces + +.. class:: language-eu + +Basque: 'an' "active"-quote, ^circumflex, and no-break spaces + +.. class:: language-eo + +Esperanto: 'an' "active"-quote, ^circumflex, and no-break spaces + +.. class:: language-et + +Estonian: 'an' "active"-quote, ^circumflex, and no-break spaces + +.. class:: language-gl + +Galician: 'an' "active"-quote, ^circumflex, and no-break spaces + +.. class:: language-de + +German: 'an' "active"-quote, ^circumflex, and no-break spaces + +Spanish: option clash with Galician! + +.. + .. class:: language-es + + Spanish: 'an' "active"-quote, ^circumflex, and no-break spaces + + +.. _babel: http://www.ctan.org/packages/babel Property changes on: trunk/docutils/test/functional/input/latex_babel.txt ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision Added: svn:eol-style + native Added: trunk/docutils/test/functional/tests/latex_babel.py =================================================================== --- trunk/docutils/test/functional/tests/latex_babel.py (rev 0) +++ trunk/docutils/test/functional/tests/latex_babel.py 2013-01-17 15:48:30 UTC (rev 7589) @@ -0,0 +1,10 @@ +# Source and destination file names. +test_source = "latex_babel.txt" +test_destination = "latex_babel.tex" + +# Keyword parameters passed to publish_file. +reader_name = "standalone" +parser_name = "rst" +writer_name = "latex" + +# Extra setting we need Property changes on: trunk/docutils/test/functional/tests/latex_babel.py ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision Added: svn:eol-style + native Modified: trunk/docutils/test/functional/tests/latex_cyrillic.py =================================================================== --- trunk/docutils/test/functional/tests/latex_cyrillic.py 2013-01-17 15:41:35 UTC (rev 7588) +++ trunk/docutils/test/functional/tests/latex_cyrillic.py 2013-01-17 15:48:30 UTC (rev 7589) @@ -13,3 +13,6 @@ settings_overrides['font_encoding'] = 'T1,T2A' settings_overrides['stylesheet'] = 'cmlgc' settings_overrides['language_code'] = 'ru' + +# use "smartquotes" transition: +settings_overrides['smart_quotes'] = True Modified: trunk/docutils/test/functional/tests/xetex_cyrillic.py =================================================================== --- trunk/docutils/test/functional/tests/xetex_cyrillic.py 2013-01-17 15:41:35 UTC (rev 7588) +++ trunk/docutils/test/functional/tests/xetex_cyrillic.py 2013-01-17 15:48:30 UTC (rev 7589) @@ -11,3 +11,5 @@ # language to work around a problem with cyrillic in PDF-bookmarks in # hyperref versions < v6.79g 2009/11/20 settings_overrides['hyperref_options'] = 'unicode=false' +# use "smartquotes" transition: +settings_overrides['smart_quotes'] = True Modified: trunk/docutils/test/test_writers/test_latex2e.py =================================================================== --- trunk/docutils/test/test_writers/test_latex2e.py 2013-01-17 15:41:35 UTC (rev 7588) +++ trunk/docutils/test/test_writers/test_latex2e.py 2013-01-17 15:48:30 UTC (rev 7589) @@ -116,9 +116,9 @@ \usepackage[T1]{fontenc} \usepackage[utf8]{inputenc} \usepackage[spanish,english]{babel} -\addto\shorthandsspanish{\spanishdeactivate{."~<>}} +\AtBeginDocument{\shorthandoff{.<>}} """)) + r""" -Und damit \otherlanguage{spanish}{basta}! +Und damit \foreignlanguage{spanish}{basta}! \end{document} """], @@ -605,7 +605,6 @@ """], ] - if __name__ == '__main__': import unittest unittest.main(defaultTest='suite') This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <mi...@us...> - 2013-01-21 15:19:28
|
Revision: 7592 http://docutils.svn.sourceforge.net/docutils/?rev=7592&view=rev Author: milde Date: 2013-01-21 15:19:18 +0000 (Mon, 21 Jan 2013) Log Message: ----------- Fix [ 3601607 ] node.__repr__() must return `str` instance. Modified Paths: -------------- trunk/docutils/docutils/nodes.py trunk/docutils/test/test_nodes.py Modified: trunk/docutils/docutils/nodes.py =================================================================== --- trunk/docutils/docutils/nodes.py 2013-01-20 12:30:53 UTC (rev 7591) +++ trunk/docutils/docutils/nodes.py 2013-01-21 15:19:18 UTC (rev 7592) @@ -299,15 +299,26 @@ if sys.version_info < (3,): class reprunicode(unicode): """ - A class that removes the initial u from unicode's repr. + A unicode sub-class that removes the initial u from unicode's repr. """ def __repr__(self): return unicode.__repr__(self)[1:] + + else: reprunicode = unicode +def ensure_str(s): + """ + Failsave conversion of `unicode` to `str`. + """ + if sys.version_info < (3,) and isinstance(s, unicode): + return s.encode('ascii', 'backslashreplace') + return s + + class Text(Node, reprunicode): """ @@ -341,7 +352,7 @@ data = self if len(data) > maxlen: data = data[:maxlen-4] + ' ...' - return '<%s: %s>' % (self.tagname, repr(reprunicode(data))) + return '<%s: %r>' % (self.tagname, reprunicode(data)) def __repr__(self): return self.shortrepr(maxlen=68) @@ -478,14 +489,14 @@ break if self['names']: return '<%s "%s": %s>' % (self.__class__.__name__, - '; '.join(self['names']), data) + '; '.join([ensure_str(n) for n in self['names']]), data) else: return '<%s: %s>' % (self.__class__.__name__, data) def shortrepr(self): if self['names']: return '<%s "%s"...>' % (self.__class__.__name__, - '; '.join(self['names'])) + '; '.join([ensure_str(n) for n in self['names']])) else: return '<%s...>' % self.tagname Modified: trunk/docutils/test/test_nodes.py =================================================================== --- trunk/docutils/test/test_nodes.py 2013-01-20 12:30:53 UTC (rev 7591) +++ trunk/docutils/test/test_nodes.py 2013-01-21 15:19:18 UTC (rev 7592) @@ -33,6 +33,11 @@ self.assertEqual(repr(self.text), r"<#text: 'Line 1.\nLine 2.'>") self.assertEqual(self.text.shortrepr(), r"<#text: 'Line 1.\nLine 2.'>") + self.assertEqual(nodes.reprunicode('foo'), u'foo') + if sys.version_info < (3,): + self.assertEqual(repr(self.unicode_text), r"<#text: 'M\xf6hren'>") + else: + self.assertEqual(repr(self.unicode_text), u"<#text: 'Möhren'>") def test_str(self): self.assertEqual(str(self.text), 'Line 1.\nLine 2.') @@ -42,10 +47,13 @@ self.assertEqual(str(self.unicode_text), 'M\xf6hren') def test_astext(self): - self.assertEqual(self.text.astext(), 'Line 1.\nLine 2.') + self.assertTrue(isinstance(self.text.astext(), unicode)) + self.assertEqual(self.text.astext(), u'Line 1.\nLine 2.') + self.assertEqual(self.unicode_text.astext(), u'Möhren') def test_pformat(self): - self.assertEqual(self.text.pformat(), 'Line 1.\nLine 2.\n') + self.assertTrue(isinstance(self.text.pformat(), unicode)) + self.assertEqual(self.text.pformat(), u'Line 1.\nLine 2.\n') def test_asciirestriction(self): if sys.version_info < (3,): @@ -88,11 +96,25 @@ dom = element.asdom() self.assertEqual(dom.toxml(), u'<Element mark="\u2022"/>') dom.unlink() + element['names'] = ['nobody', u'имя', u'näs'] + if sys.version_info < (3,): + self.assertEqual(repr(element), + '<Element "nobody; \\u0438\\u043c\\u044f; n\\xe4s": >') + else: + self.assertEqual(repr(element), u'<Element "nobody; имя; näs": >') + self.assertTrue(isinstance(repr(element), str)) def test_withtext(self): element = nodes.Element('text\nmore', nodes.Text('text\nmore')) + uelement = nodes.Element(u'grün', nodes.Text(u'grün')) self.assertEqual(repr(element), r"<Element: <#text: 'text\nmore'>>") + if sys.version_info < (3,): + self.assertEqual(repr(uelement), "<Element: <#text: 'gr\\xfcn'>>") + else: + self.assertEqual(repr(uelement), u"<Element: <#text: 'grün'>>") + self.assertTrue(isinstance(repr(uelement),str)) self.assertEqual(str(element), '<Element>text\nmore</Element>') + self.assertEqual(str(uelement), '<Element>gr\xfcn</Element>') dom = element.asdom() self.assertEqual(dom.toxml(), '<Element>text\nmore</Element>') dom.unlink() @@ -194,6 +216,25 @@ class MiscTests(unittest.TestCase): + def test_reprunicode(self): + # return `unicode` instance + self.assertTrue(isinstance(nodes.reprunicode('foo'), unicode)) + self.assertEqual(nodes.reprunicode('foo'), u'foo') + self.assertEqual(nodes.reprunicode(u'Möhre'), u'Möhre') + if sys.version_info < (3,): # strip leading "u" from representation + self.assertEqual(repr(nodes.reprunicode(u'Möhre')), + repr(u'Möhre')[1:]) + else: # no change to `unicode` under Python 3k + self.assertEqual(repr(nodes.reprunicode(u'Möhre')), repr(u'Möhre')) + + def test_ensure_str(self): + self.assertTrue(isinstance(nodes.ensure_str(u'über'), str)) + self.assertEqual(nodes.ensure_str('over'), 'over') + if sys.version_info < (3,): # strip leading "u" from representation + self.assertEqual(nodes.ensure_str(u'über'), r'\xfcber') + else: + self.assertEqual(nodes.ensure_str(u'über'), r'über') + def test_node_class_names(self): node_class_names = [] for x in dir(nodes): @@ -484,7 +525,7 @@ def compare_trees(self, one, two): self.assertEqual(one.__class__, two.__class__) - self.assertNotEquals(id(one), id(two)) + self.assertNotEqual(id(one), id(two)) self.assertEqual(len(one.children), len(two.children)) for i in range(len(one.children)): self.compare_trees(one.children[i], two.children[i]) @@ -534,7 +575,7 @@ element = nodes.Element() document.set_id(element) self.assertEqual(element['ids'], ['prefixauto1']) - + if __name__ == '__main__': unittest.main() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |