home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2011 January / maximum-cd-2011-01.iso / DiscContents / calibre-0.7.26.msi / file_869 (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2010-10-31  |  29.8 KB  |  456 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.6)
  3.  
  4. __license__ = 'GPL v3'
  5. __copyright__ = '2009, Kovid Goyal <kovid@kovidgoyal.net>'
  6. __docformat__ = 'restructuredtext en'
  7. import functools
  8. import re
  9. from calibre import entity_to_unicode
  10. XMLDECL_RE = re.compile('^\\s*<[?]xml.*?[?]>')
  11. SVG_NS = 'http://www.w3.org/2000/svg'
  12. XLINK_NS = 'http://www.w3.org/1999/xlink'
  13. convert_entities = functools.partial(entity_to_unicode, result_exceptions = {
  14.     u'<': '<',
  15.     u'>': '>',
  16.     u"'": ''',
  17.     u'"': '"',
  18.     u'&': '&' })
  19. _span_pat = re.compile('<span.*?</span>', re.DOTALL | re.IGNORECASE)
  20. LIGATURES = {
  21.     u'∩¼Ç': u'ff',
  22.     u'∩¼ü': u'fi',
  23.     u'∩¼é': u'fl',
  24.     u'∩¼â': u'ffi',
  25.     u'∩¼ä': u'ffl',
  26.     u'∩¼à': u'ft',
  27.     u'∩¼å': u'st' }
  28. _ligpat = re.compile(u'|'.join(LIGATURES))
  29.  
  30. def sanitize_head(match):
  31.     x = match.group(1)
  32.     x = _span_pat.sub('', x)
  33.     return '<head>\n%s\n</head>' % x
  34.  
  35.  
  36. def chap_head(match):
  37.     chap = match.group('chap')
  38.     title = match.group('title')
  39.     if not title:
  40.         return '<h1>' + chap + '</h1><br/>\n'
  41.     return '<h1>' + chap + '</h1>\n<h3>' + title + '</h3>\n'
  42.  
  43.  
  44. def wrap_lines(match):
  45.     ital = match.group('ital')
  46.     if not ital:
  47.         return ' '
  48.     return ital + ' '
  49.  
  50.  
  51. class DocAnalysis(object):
  52.     
  53.     def __init__(self, format = 'html', raw = ''):
  54.         raw = raw.replace(' ', ' ')
  55.         if format == 'html':
  56.             linere = re.compile('(?<=<p)(?![^>]*>\\s*</p>).*?(?=</p>)', re.DOTALL)
  57.         elif format == 'pdf':
  58.             linere = re.compile('(?<=<br>)(?!\\s*<br>).*?(?=<br>)', re.DOTALL)
  59.         elif format == 'spanned_html':
  60.             linere = re.compile('(?<=<span).*?(?=</span>)', re.DOTALL)
  61.         
  62.         self.lines = linere.findall(raw)
  63.  
  64.     
  65.     def line_length(self, percent):
  66.         lengths = []
  67.         for line in self.lines:
  68.             if len(line) > 0:
  69.                 lengths.append(len(line))
  70.                 continue
  71.         
  72.         if not lengths:
  73.             return 0
  74.         lengths = list(set(lengths))
  75.         total = sum(lengths)
  76.         avg = total / len(lengths)
  77.         max_line = avg * 2
  78.         lengths = sorted(lengths)
  79.         for i in range(len(lengths) - 1, -1, -1):
  80.             if lengths[i] > max_line:
  81.                 del lengths[i]
  82.                 continue
  83.             lengths
  84.         
  85.         if percent > 1:
  86.             percent = 1
  87.         
  88.         if percent < 0:
  89.             percent = 0
  90.         
  91.         index = int(len(lengths) * percent) - 1
  92.         return lengths[index]
  93.  
  94.     
  95.     def line_histogram(self, percent):
  96.         minLineLength = 20
  97.         maxLineLength = 1900
  98.         buckets = 20
  99.         hRaw = [ 0 for i in range(0, buckets) ]
  100.         for line in self.lines:
  101.             l = len(line)
  102.             if l > minLineLength and l < maxLineLength:
  103.                 l = int(l / 100)
  104.                 hRaw[l] += 1
  105.                 continue
  106.             []
  107.         
  108.         totalLines = len(self.lines)
  109.         h = [ float(count) / totalLines for count in hRaw ]
  110.         maxValue = 0
  111.         for i in range(0, len(h)):
  112.             if h[i] > maxValue:
  113.                 maxValue = h[i]
  114.                 continue
  115.             []
  116.         
  117.         if maxValue < percent:
  118.             return False
  119.         return True
  120.  
  121.  
  122.  
  123. class Dehyphenator(object):
  124.     
  125.     def __init__(self):
  126.         self.removesuffixes = re.compile("((ed)?ly|('e)?s|a?(t|s)?ion(s|al(ly)?)?|ings?|er|(i)?ous|(i|a)ty|(it)?ies|ive|gence|istic(ally)?|(e|a)nce|ment(s)?|ism|ated|(e|u)ct(ed)?|ed|(i|ed)?ness|(e|a)ncy|ble|ier|al|ex)$", re.IGNORECASE)
  127.         self.prefixes = re.compile('^(dis|re|un|in|ex)$', re.IGNORECASE)
  128.         self.removeprefix = re.compile('^(dis|re|un|in|ex)', re.IGNORECASE)
  129.  
  130.     
  131.     def dehyphenate(self, match):
  132.         firsthalf = match.group('firstpart')
  133.         secondhalf = match.group('secondpart')
  134.         
  135.         try:
  136.             wraptags = match.group('wraptags')
  137.         except:
  138.             wraptags = ''
  139.  
  140.         hyphenated = unicode(firsthalf) + '-' + unicode(secondhalf)
  141.         dehyphenated = unicode(firsthalf) + unicode(secondhalf)
  142.         lookupword = self.removesuffixes.sub('', dehyphenated)
  143.         if self.prefixes.match(firsthalf) is None:
  144.             lookupword = self.removeprefix.sub('', lookupword)
  145.         
  146.         
  147.         try:
  148.             searchresult = self.html.find(lookupword.lower())
  149.         except:
  150.             return hyphenated
  151.  
  152.         if self.format == 'html_cleanup':
  153.             if self.html.find(lookupword) != -1 or searchresult != -1:
  154.                 return dehyphenated
  155.             if self.html.find(hyphenated) != -1:
  156.                 return hyphenated
  157.             return firsthalf + u'ΓÇö' + wraptags + secondhalf
  158.         self.format == 'html_cleanup'
  159.         if self.html.find(lookupword) != -1 or searchresult != -1:
  160.             return dehyphenated
  161.         return hyphenated
  162.  
  163.     
  164.     def __call__(self, html, format, length = 1):
  165.         self.html = html
  166.         self.format = format
  167.         if format == 'html':
  168.             intextmatch = re.compile(u'(?<=.{%i})(?P<firstpart>[^\\[\\]\\\\^\\$\\.\\|\\?\\*\\+\\(\\)ΓÇ£"\\s>]+)-\\s*(?=<)(?P<wraptags></span>\\s*(</[iubp]>\\s*<[iubp][^>]*>\\s*)?<span[^>]*>|</[iubp]>\\s*<[iubp][^>]*>)?\\s*(?P<secondpart>[\\w\\d]+)' % length)
  169.         elif format == 'pdf':
  170.             intextmatch = re.compile(u'(?<=.{%i})(?P<firstpart>[^\\[\\]\\\\^\\$\\.\\|\\?\\*\\+\\(\\)ΓÇ£"\\s>]+)-\\s*(?P<wraptags><p>|</[iub]>\\s*<p>\\s*<[iub]>)\\s*(?P<secondpart>[\\w\\d]+)' % length)
  171.         elif format == 'individual_words':
  172.             intextmatch = re.compile(u'>[^<]*\x08(?P<firstpart>[^\\[\\]\\\\^\\$\\.\\|\\?\\*\\+\\(\\)"\\s>]+)-(?P<secondpart)\\w+)\x08[^<]*<')
  173.         elif format == 'html_cleanup':
  174.             intextmatch = re.compile(u'(?P<firstpart>[^\\[\\]\\\\^\\$\\.\\|\\?\\*\\+\\(\\)ΓÇ£"\\s>]+)-\\s*(?=<)(?P<wraptags></span>\\s*(</[iubp]>\\s*<[iubp][^>]*>\\s*)?<span[^>]*>|</[iubp]>\\s*<[iubp][^>]*>)?\\s*(?P<secondpart>[\\w\\d]+)')
  175.         
  176.         html = intextmatch.sub(self.dehyphenate, html)
  177.         return html
  178.  
  179.  
  180.  
  181. class CSSPreProcessor(object):
  182.     PAGE_PAT = re.compile('@page[^{]*?{[^}]*?}')
  183.     
  184.     def __call__(self, data, add_namespace = False):
  185.         XHTML_CSS_NAMESPACE = XHTML_CSS_NAMESPACE
  186.         import calibre.ebooks.oeb.base
  187.         data = self.PAGE_PAT.sub('', data)
  188.         if not add_namespace:
  189.             return data
  190.         ans = []
  191.         namespaced = False
  192.         for line in data.splitlines():
  193.             ll = line.lstrip()
  194.             if not namespaced and ll.startswith('@import') or ll.startswith('@charset'):
  195.                 ans.append(XHTML_CSS_NAMESPACE.strip())
  196.                 namespaced = True
  197.             
  198.             ans.append(line)
  199.         
  200.         return u'\n'.join(ans)
  201.  
  202.  
  203.  
  204. class HTMLPreProcessor(object):
  205.     PREPROCESS = [
  206.         (re.compile('<head[^>]*>\\n*(.*?)\\n*</head>', re.IGNORECASE | re.DOTALL), sanitize_head),
  207.         (re.compile('&(\\S+?);'), convert_entities),
  208.         (re.compile('</{0,1}!\\[(end){0,1}if\\]{0,1}>', re.IGNORECASE), (lambda match: ''))]
  209.     PDFTOHTML = [
  210.         (re.compile(u'┬¿\\s*(<br.*?>)*\\s*a', re.UNICODE), (lambda match: u'├ñ')),
  211.         (re.compile(u'┬¿\\s*(<br.*?>)*\\s*A', re.UNICODE), (lambda match: u'├ä')),
  212.         (re.compile(u'┬¿\\s*(<br.*?>)*\\s*e', re.UNICODE), (lambda match: u'├½')),
  213.         (re.compile(u'┬¿\\s*(<br.*?>)*\\s*E', re.UNICODE), (lambda match: u'├ï')),
  214.         (re.compile(u'┬¿\\s*(<br.*?>)*\\s*i', re.UNICODE), (lambda match: u'├»')),
  215.         (re.compile(u'┬¿\\s*(<br.*?>)*\\s*I', re.UNICODE), (lambda match: u'├Å')),
  216.         (re.compile(u'┬¿\\s*(<br.*?>)*\\s*o', re.UNICODE), (lambda match: u'├╢')),
  217.         (re.compile(u'┬¿\\s*(<br.*?>)*\\s*O', re.UNICODE), (lambda match: u'├û')),
  218.         (re.compile(u'┬¿\\s*(<br.*?>)*\\s*u', re.UNICODE), (lambda match: u'├╝')),
  219.         (re.compile(u'┬¿\\s*(<br.*?>)*\\s*U', re.UNICODE), (lambda match: u'├£')),
  220.         (re.compile(u'`\\s*(<br.*?>)*\\s*a', re.UNICODE), (lambda match: u'├á')),
  221.         (re.compile(u'`\\s*(<br.*?>)*\\s*A', re.UNICODE), (lambda match: u'├Ç')),
  222.         (re.compile(u'`\\s*(<br.*?>)*\\s*e', re.UNICODE), (lambda match: u'├¿')),
  223.         (re.compile(u'`\\s*(<br.*?>)*\\s*E', re.UNICODE), (lambda match: u'├ê')),
  224.         (re.compile(u'`\\s*(<br.*?>)*\\s*i', re.UNICODE), (lambda match: u'├¼')),
  225.         (re.compile(u'`\\s*(<br.*?>)*\\s*I', re.UNICODE), (lambda match: u'├î')),
  226.         (re.compile(u'`\\s*(<br.*?>)*\\s*o', re.UNICODE), (lambda match: u'├▓')),
  227.         (re.compile(u'`\\s*(<br.*?>)*\\s*O', re.UNICODE), (lambda match: u'├Æ')),
  228.         (re.compile(u'`\\s*(<br.*?>)*\\s*u', re.UNICODE), (lambda match: u'├╣')),
  229.         (re.compile(u'`\\s*(<br.*?>)*\\s*U', re.UNICODE), (lambda match: u'├Ö')),
  230.         (re.compile(u'a\\s*(<br.*?>)*\\s*`', re.UNICODE), (lambda match: u'├á')),
  231.         (re.compile(u'A\\s*(<br.*?>)*\\s*`', re.UNICODE), (lambda match: u'├Ç')),
  232.         (re.compile(u'e\\s*(<br.*?>)*\\s*`', re.UNICODE), (lambda match: u'├¿')),
  233.         (re.compile(u'E\\s*(<br.*?>)*\\s*`', re.UNICODE), (lambda match: u'├ê')),
  234.         (re.compile(u'i\\s*(<br.*?>)*\\s*`', re.UNICODE), (lambda match: u'├¼')),
  235.         (re.compile(u'I\\s*(<br.*?>)*\\s*`', re.UNICODE), (lambda match: u'├î')),
  236.         (re.compile(u'o\\s*(<br.*?>)*\\s*`', re.UNICODE), (lambda match: u'├▓')),
  237.         (re.compile(u'O\\s*(<br.*?>)*\\s*`', re.UNICODE), (lambda match: u'├Æ')),
  238.         (re.compile(u'u\\s*(<br.*?>)*\\s*`', re.UNICODE), (lambda match: u'├╣')),
  239.         (re.compile(u'U\\s*(<br.*?>)*\\s*`', re.UNICODE), (lambda match: u'├Ö')),
  240.         (re.compile(u'┬┤\\s*(<br.*?>)*\\s*a', re.UNICODE), (lambda match: u'├í')),
  241.         (re.compile(u'┬┤\\s*(<br.*?>)*\\s*A', re.UNICODE), (lambda match: u'├ü')),
  242.         (re.compile(u'┬┤\\s*(<br.*?>)*\\s*c', re.UNICODE), (lambda match: u'─ç')),
  243.         (re.compile(u'┬┤\\s*(<br.*?>)*\\s*C', re.UNICODE), (lambda match: u'─å')),
  244.         (re.compile(u'┬┤\\s*(<br.*?>)*\\s*e', re.UNICODE), (lambda match: u'├⌐')),
  245.         (re.compile(u'┬┤\\s*(<br.*?>)*\\s*E', re.UNICODE), (lambda match: u'├ë')),
  246.         (re.compile(u'┬┤\\s*(<br.*?>)*\\s*i', re.UNICODE), (lambda match: u'├¡')),
  247.         (re.compile(u'┬┤\\s*(<br.*?>)*\\s*I', re.UNICODE), (lambda match: u'├ì')),
  248.         (re.compile(u'┬┤\\s*(<br.*?>)*\\s*o', re.UNICODE), (lambda match: u'├│')),
  249.         (re.compile(u'┬┤\\s*(<br.*?>)*\\s*O', re.UNICODE), (lambda match: u'├ô')),
  250.         (re.compile(u'┬┤\\s*(<br.*?>)*\\s*n', re.UNICODE), (lambda match: u'┼ä')),
  251.         (re.compile(u'┬┤\\s*(<br.*?>)*\\s*N', re.UNICODE), (lambda match: u'┼â')),
  252.         (re.compile(u'┬┤\\s*(<br.*?>)*\\s*s', re.UNICODE), (lambda match: u'┼¢')),
  253.         (re.compile(u'┬┤\\s*(<br.*?>)*\\s*S', re.UNICODE), (lambda match: u'┼Ü')),
  254.         (re.compile(u'┬┤\\s*(<br.*?>)*\\s*u', re.UNICODE), (lambda match: u'├║')),
  255.         (re.compile(u'┬┤\\s*(<br.*?>)*\\s*U', re.UNICODE), (lambda match: u'├Ü')),
  256.         (re.compile(u'┬┤\\s*(<br.*?>)*\\s*z', re.UNICODE), (lambda match: u'┼║')),
  257.         (re.compile(u'┬┤\\s*(<br.*?>)*\\s*Z', re.UNICODE), (lambda match: u'┼╣')),
  258.         (re.compile(u'╦å\\s*(<br.*?>)*\\s*a', re.UNICODE), (lambda match: u'├ó')),
  259.         (re.compile(u'╦å\\s*(<br.*?>)*\\s*A', re.UNICODE), (lambda match: u'├é')),
  260.         (re.compile(u'╦å\\s*(<br.*?>)*\\s*e', re.UNICODE), (lambda match: u'├¬')),
  261.         (re.compile(u'╦å\\s*(<br.*?>)*\\s*E', re.UNICODE), (lambda match: u'├è')),
  262.         (re.compile(u'╦å\\s*(<br.*?>)*\\s*i', re.UNICODE), (lambda match: u'├«')),
  263.         (re.compile(u'╦å\\s*(<br.*?>)*\\s*I', re.UNICODE), (lambda match: u'├Ä')),
  264.         (re.compile(u'╦å\\s*(<br.*?>)*\\s*o', re.UNICODE), (lambda match: u'├┤')),
  265.         (re.compile(u'╦å\\s*(<br.*?>)*\\s*O', re.UNICODE), (lambda match: u'├ö')),
  266.         (re.compile(u'╦å\\s*(<br.*?>)*\\s*u', re.UNICODE), (lambda match: u'├╗')),
  267.         (re.compile(u'╦å\\s*(<br.*?>)*\\s*U', re.UNICODE), (lambda match: u'├¢')),
  268.         (re.compile(u'┬╕\\s*(<br.*?>)*\\s*c', re.UNICODE), (lambda match: u'├º')),
  269.         (re.compile(u'┬╕\\s*(<br.*?>)*\\s*C', re.UNICODE), (lambda match: u'├ç')),
  270.         (re.compile(u'\\s*╦¢\\s*(<br.*?>)*\\s*a', re.UNICODE), (lambda match: u'─à')),
  271.         (re.compile(u'\\s*╦¢\\s*(<br.*?>)*\\s*A', re.UNICODE), (lambda match: u'─ä')),
  272.         (re.compile(u'╦¢\\s*(<br.*?>)*\\s*e', re.UNICODE), (lambda match: u'─Ö')),
  273.         (re.compile(u'╦¢\\s*(<br.*?>)*\\s*E', re.UNICODE), (lambda match: u'─ÿ')),
  274.         (re.compile(u'╦Ö\\s*(<br.*?>)*\\s*z', re.UNICODE), (lambda match: u'┼╝')),
  275.         (re.compile(u'╦Ö\\s*(<br.*?>)*\\s*Z', re.UNICODE), (lambda match: u'┼╗')),
  276.         (re.compile('((?<=</a>)\\s*file:////?[A-Z].*<br>|file:////?[A-Z].*<br>(?=\\s*<hr>))', re.IGNORECASE), (lambda match: '')),
  277.         (re.compile(u'<br>\\s*(?P<break>([*#ΓÇó]+\\s*)+)\\s*<br>'), (lambda match: '<p>\n<p style="text-align:center">' + match.group(1) + '</p>')),
  278.         (re.compile('<a name=\\d+></a>', re.IGNORECASE), (lambda match: '')),
  279.         (re.compile('<hr.*?>', re.IGNORECASE), (lambda match: '<br>')),
  280.         (re.compile('<BODY[^<>]+>'), (lambda match: '<BODY>')),
  281.         (re.compile('<br>\\s*(?P<chap>(<[ibu]>){0,2}\\s*.?(Introduction|Chapter|Kapitel|Epilogue|Prologue|Book|Part|Dedication|Volume|Preface|Acknowledgments)\\s*([\\d\\w-]+\\s*){0,3}\\s*(</[ibu]>){0,2})\\s*(<br>\\s*){1,3}\\s*(?P<title>(<[ibu]>){0,2}(\\s*\\w+){1,4}\\s*(</[ibu]>){0,2}\\s*<br>)?', re.IGNORECASE), chap_head),
  282.         (re.compile('<br>\\s*(?P<chap>([A-Z]\\s+){4,}\\s*([\\d\\w-]+\\s*){0,3}\\s*)\\s*(<br>\\s*){1,3}\\s*(?P<title>(<[ibu]>){0,2}(\\s*\\w+){1,4}\\s*(</[ibu]>){0,2}\\s*(<br>))?'), chap_head),
  283.         (re.compile('<br.*?>'), (lambda match: '<p>')),
  284.         (re.compile(u'(?<=[\\.,;\\?!ΓÇ¥"\'])[\\s^ ]*(?=<)'), (lambda match: ' ')),
  285.         (re.compile(u'(?<!ΓÇ£)<i>'), (lambda match: ' <i>')),
  286.         (re.compile('</i>(?=\\w)'), (lambda match: '</i> '))]
  287.     BOOK_DESIGNER = [
  288.         (re.compile('<hr>', re.IGNORECASE), (lambda match: '<span style="page-break-after:always"> </span>')),
  289.         (re.compile('<h2[^><]*?id=BookTitle[^><]*?(align=)*(?(1)(\\w+))*[^><]*?>[^><]*?</h2>', re.IGNORECASE), (lambda match: None % ('<h1 id="BookTitle" align="%s">%s</h1>' if match.group(2) else 'center', match.group(3)))),
  290.         (re.compile('<h2[^><]*?id=BookAuthor[^><]*?(align=)*(?(1)(\\w+))*[^><]*?>[^><]*?</h2>', re.IGNORECASE), (lambda match: None % ('<h2 id="BookAuthor" align="%s">%s</h2>' if match.group(2) else 'center', match.group(3)))),
  291.         (re.compile('<span[^><]*?id=title[^><]*?>(.*?)</span>', re.IGNORECASE | re.DOTALL), (lambda match: '<h2 class="title">%s</h2>' % (match.group(1),))),
  292.         (re.compile('<span[^><]*?id=subtitle[^><]*?>(.*?)</span>', re.IGNORECASE | re.DOTALL), (lambda match: '<h3 class="subtitle">%s</h3>' % (match.group(1),)))]
  293.     
  294.     def __init__(self, input_plugin_preprocess, plugin_preprocess, extra_opts = None):
  295.         self.input_plugin_preprocess = input_plugin_preprocess
  296.         self.plugin_preprocess = plugin_preprocess
  297.         self.extra_opts = extra_opts
  298.  
  299.     
  300.     def is_baen(self, src):
  301.         return re.compile('<meta\\s+name="Publisher"\\s+content=".*?Baen.*?"', re.IGNORECASE).search(src) is not None
  302.  
  303.     
  304.     def is_book_designer(self, raw):
  305.         return re.search('<H2[^><]*id=BookTitle', raw) is not None
  306.  
  307.     
  308.     def is_pdftohtml(self, src):
  309.         return "<!-- created by calibre's pdftohtml -->" in src[:1000]
  310.  
  311.     
  312.     def __call__(self, html, remove_special_chars = None, get_preprocess_html = False):
  313.         if remove_special_chars is not None:
  314.             html = remove_special_chars.sub('', html)
  315.         
  316.         html = html.replace('\x00', '')
  317.         is_pdftohtml = self.is_pdftohtml(html)
  318.         if self.is_baen(html):
  319.             rules = []
  320.         elif self.is_book_designer(html):
  321.             rules = self.BOOK_DESIGNER
  322.         elif is_pdftohtml:
  323.             rules = self.PDFTOHTML
  324.         else:
  325.             rules = []
  326.         start_rules = []
  327.         if is_pdftohtml:
  328.             start_rules.append((re.compile(u'┬á'), (lambda match: ' ')))
  329.         
  330.         if not getattr(self.extra_opts, 'keep_ligatures', False):
  331.             html = _ligpat.sub((lambda m: LIGATURES[m.group()]), html)
  332.         
  333.         end_rules = []
  334.         if getattr(self.extra_opts, 'remove_header', None):
  335.             
  336.             try:
  337.                 rules.insert(0, (re.compile(self.extra_opts.header_regex), (lambda match: '')))
  338.             import traceback
  339.             print 'Failed to parse remove_header regexp'
  340.             traceback.print_exc()
  341.  
  342.         
  343.         if getattr(self.extra_opts, 'remove_footer', None):
  344.             
  345.             try:
  346.                 rules.insert(0, (re.compile(self.extra_opts.footer_regex), (lambda match: '')))
  347.             import traceback
  348.             print 'Failed to parse remove_footer regexp'
  349.             traceback.print_exc()
  350.  
  351.         
  352.         if is_pdftohtml:
  353.             end_rules.append((re.compile(u'[┬¡](\\s*<p>)+\\s*(?=[[a-z\\d])'), (lambda match: '')))
  354.             end_rules.append((re.compile(u'[┬¡]\\s*(</(i|u|b)>)+(\\s*<p>)+\\s*(<(i|u|b)>)+\\s*(?=[[a-z\\d])'), (lambda match: '')))
  355.         
  356.         if getattr(self.extra_opts, 'preprocess_html', None):
  357.             if is_pdftohtml:
  358.                 end_rules.append((re.compile('<p>\\s*(?P<chap>(<[ibu]>){0,2}\\s*([A-Z \\\'"!]{3,})\\s*([\\dA-Z:]+\\s){0,4}\\s*(</[ibu]>){0,2})\\s*<p>\\s*(?P<title>(<[ibu]>){0,2}(\\s*\\w+){1,4}\\s*(</[ibu]>){0,2}\\s*<p>)?'), chap_head))
  359.             
  360.         
  361.         length = -1
  362.         if getattr(self.extra_opts, 'unwrap_factor', 0) > 0.01:
  363.             docanalysis = DocAnalysis('pdf', html)
  364.             length = docanalysis.line_length(getattr(self.extra_opts, 'unwrap_factor'))
  365.             if length:
  366.                 end_rules.append((re.compile(u'(?<=.{%i}[ΓÇôΓÇö])\\s*<p>\\s*(?=[[a-z\\d])' % length), (lambda match: '')))
  367.                 end_rules.append((re.compile(u'(?<=.{%i}([a-z,:)\\IA├ƒ]|(?<!\\&\\w{4});))\\s*(?P<ital></(i|b|u)>)?\\s*(<p.*?>\\s*)+\\s*(?=(<(i|b|u)>)?\\s*[\\w\\d$(])' % length, re.UNICODE), wrap_lines))
  368.             
  369.         
  370.         for rule in self.PREPROCESS + start_rules:
  371.             html = rule[0].sub(rule[1], html)
  372.         
  373.         if get_preprocess_html:
  374.             return html
  375.         
  376.         def dump(raw, where):
  377.             import os
  378.             dp = getattr(self.extra_opts, 'debug_pipeline', None)
  379.             if dp and os.path.exists(dp):
  380.                 odir = os.path.join(dp, 'input')
  381.                 if os.path.exists(odir):
  382.                     odir = os.path.join(odir, where)
  383.                     if not os.path.exists(odir):
  384.                         os.makedirs(odir)
  385.                     
  386.                     (name, i) = (None, 0)
  387.                     while not name or os.path.exists(os.path.join(odir, name)):
  388.                         i += 1
  389.                         name = '%04d.html' % i
  390.                     
  391.                     try:
  392.                         f = _[1]
  393.                         f.write(raw.encode('utf-8'))
  394.                     finally:
  395.                         pass
  396.  
  397.                 
  398.             
  399.  
  400.         for rule in rules + end_rules:
  401.             html = rule[0].sub(rule[1], html)
  402.         
  403.         if is_pdftohtml and length > -1:
  404.             dehyphenator = Dehyphenator()
  405.             html = dehyphenator(html, 'pdf', length)
  406.         
  407.         if 'svg:' in html and SVG_NS not in html:
  408.             html = html.replace('<html', '<html xmlns:svg="%s"' % SVG_NS, 1)
  409.         
  410.         if 'xlink:' in html and XLINK_NS not in html:
  411.             html = html.replace('<html', '<html xmlns:xlink="%s"' % XLINK_NS, 1)
  412.         
  413.         html = XMLDECL_RE.sub('', html)
  414.         if getattr(self.extra_opts, 'asciiize', False):
  415.             Unidecoder = Unidecoder
  416.             import calibre.ebooks.unidecode.unidecoder
  417.             unidecoder = Unidecoder()
  418.             html = unidecoder.decode(html)
  419.         
  420.         if self.plugin_preprocess:
  421.             html = self.input_plugin_preprocess(self.extra_opts, html)
  422.         
  423.         if getattr(self.extra_opts, 'smarten_punctuation', False):
  424.             html = self.smarten_punctuation(html)
  425.         
  426.         unsupported_unicode_chars = self.extra_opts.output_profile.unsupported_unicode_chars
  427.         if unsupported_unicode_chars:
  428.             Unidecoder = Unidecoder
  429.             import calibre.ebooks.unidecode.unidecoder
  430.             unidecoder = Unidecoder()
  431.             for char in unsupported_unicode_chars:
  432.                 asciichar = unidecoder.decode(char)
  433.                 html = html.replace(char, asciichar)
  434.             
  435.         
  436.         return html
  437.  
  438.     
  439.     def smarten_punctuation(self, html):
  440.         smartyPants = smartyPants
  441.         import calibre.utils.smartypants
  442.         substitute_entites = substitute_entites
  443.         import calibre.ebooks.chardet
  444.         uuid4 = uuid4
  445.         import uuid
  446.         start = 'calibre-smartypants-' + str(uuid4())
  447.         stop = 'calibre-smartypants-' + str(uuid4())
  448.         html = html.replace('<!--', start)
  449.         html = html.replace('-->', stop)
  450.         html = smartyPants(html)
  451.         html = html.replace(start, '<!--')
  452.         html = html.replace(stop, '-->')
  453.         return substitute_entites(html)
  454.  
  455.  
  456.