diff --git a/src/calibre/ebooks/textile/functions.py b/src/calibre/ebooks/textile/functions.py index 88d27b036d..c3c82ef893 100755 --- a/src/calibre/ebooks/textile/functions.py +++ b/src/calibre/ebooks/textile/functions.py @@ -211,16 +211,6 @@ class Textile(object): (re.compile(r'(\d+\'?\"?)( ?)x( ?)(?=\d+)'), r'\1\2×\3'), # dimension sign (re.compile(r'(\d+)\'', re.I), r'\1′'), # prime (re.compile(r'(\d+)\"', re.I), r'\1″'), # prime-double - (re.compile(r'(\')\''), r'\1’'), # single closing - following another - (re.compile(r"(\w)\'(\w)"), r'\1’\2'), # apostrophe's - (re.compile(r'(\s)\'(\d+\w?)\b(?!\')'), r'\1’\2'), # back in '88 - (re.compile(r'(\s\[)\''), r'\1‘'), # single opening - following ws+[ - (re.compile(r'(\S)\'(?=\s|'+pnct+'|<|$)', re.M), r'\1’'), # single closing - (re.compile(r'\''), r'‘'), # single opening - (re.compile(r'(\")\"'), r'\1”'), # double closing - following another - (re.compile(r'(\s\[)\"'), r'\1“'), # double opening - following whitespace+[ - (re.compile(r'(\S)\"(?=\s|'+pnct+'|<|$)', re.M), r'\1”'), # double closing - (re.compile(r'"'), r'“'), # double opening (re.compile(r'\b([A-Z][A-Z0-9]{2,})\b(?:[(]([^)]*)[)])'), r'\1'), # 3+ uppercase acronym (re.compile(r'\b([A-Z][A-Z\'\-]+[A-Z])(?=[\s.,\)>])'), r'\1'), # 3+ uppercase (re.compile(r'\b(\s{0,1})?\.{3}'), r'\1…'), # ellipsis @@ -870,11 +860,11 @@ class Textile(object): 'hello span strong and bold goodbye' """ qtags = (r'\*\*', r'\*', r'\?\?', r'\-', r'__', r'_', r'%', r'\+', r'~', r'\^') - pnct = ".,\"'?!;:()" + pnct = ".,\"'?!;:" for qtag in qtags: pattern = re.compile(r""" - (?:^|(?<=[\s>%(pnct)s])|\[|([\]}])) + (?:^|(?<=[\s>%(pnct)s\(])|\[|([\]}])) (%(qtag)s)(?!%(qtag)s) (%(c)s) (?::(\S+))? diff --git a/src/calibre/ebooks/txt/input.py b/src/calibre/ebooks/txt/input.py index 99f7035800..7face4c24f 100644 --- a/src/calibre/ebooks/txt/input.py +++ b/src/calibre/ebooks/txt/input.py @@ -165,6 +165,7 @@ class TXTInput(InputFormatPlugin): elif options.formatting_type == 'textile': log.debug('Running text through textile conversion...') html = convert_textile(txt) + setattr(options, 'smarten_punctuation', True) else: log.debug('Running text through basic conversion...') flow_size = getattr(options, 'flow_size', 0) diff --git a/src/calibre/utils/smartypants.py b/src/calibre/utils/smartypants.py index 62845b8d7a..8763a313fc 100644 --- a/src/calibre/utils/smartypants.py +++ b/src/calibre/utils/smartypants.py @@ -584,6 +584,12 @@ def educateQuotes(str): #
He said, "'Quoted' words in a larger quote."
str = re.sub(r""""'(?=\w)""", """“‘""", str) str = re.sub(r"""'"(?=\w)""", """‘“""", str) + str = re.sub(r'''""(?=\w)''', """““""", str) + str = re.sub(r"""''(?=\w)""", """‘‘""", str) + str = re.sub(r'''\"\'''', """”’""", str) + str = re.sub(r'''\'\"''', """’”""", str) + str = re.sub(r'''""''', """””""", str) + str = re.sub(r"""''""", """’’""", str) # Special case for decade abbreviations (the '80s): str = re.sub(r"""\b'(?=\d{2}s)""", r"""’""", str)