diff --git a/Changelog.yaml b/Changelog.yaml
index 699aa3a531..82b335bbdd 100644
--- a/Changelog.yaml
+++ b/Changelog.yaml
@@ -4,6 +4,100 @@
# for important features/bug fixes.
# Also, each release can have new and improved recipes.
+- version: 0.7.38
+ date: 2011-01-07
+
+ new features:
+ - title: "Reduce startup time when using a composite custom column"
+
+ - title: "Template language: Add a list_item function for use with tags like columns. See User Manual for details"
+
+ - title: "TXT Input: Attempt to detect the input encoding when not specified. Auto detect paragraph structure and formatting markup."
+
+ - title: "Search & replace: Add ability to manipulate number and boolean columns."
+
+ - title: "Add type ahead completion to the advanced search dialog."
+ tickets: [8035]
+
+ - title: "Double click on plugin in Preferences dialog to customize"
+ tickets: [8175]
+
+ - title: "Allow customization of the SONY driver to send thumbnail to the device. Useful with newer SONY readers"
+ tickets: [8161]
+
+ - title: "Smarten punctuation: Convert double dashes to em dashes. Preprocessing: Various tweaks"
+
+ bug fixes:
+ - title: "Fix regression causing the template formatter to intepret a missing format letter as ERROR instead of 's'."
+
+ - title: "Fix regression that broke conversion of PNG images in PDF files on OS X."
+ tickets: [8215]
+
+ - title: "Content server: Fix improper XML escaping of category titles in the OPDS feeds"
+ tickets: [8225]
+
+ - title: "When decoding XML if the XML starts with a UTF-8 BOM decode as UTF-8. Fixes parsing of FB2 files with UTF-8 BOMs"
+
+ - title: "E-book viewer: When scrolling to a bookmark and the content is wider than the window, do not scroll in the horizontal direction"
+
+ - title: "E-book viewer: Fix next page skipping the bottom of chapters when the content is wider than the window."
+ tickets: [8153]
+
+ - title: " FB2 Output: Insert covers."
+ tickets: [8172]
+
+ - title: "Content server: When serving OPDS feeds handle html descriptions that have namespaced attributes."
+ tickets: [7938]
+
+ - title: "When downloading metadata from isbndb.com, download a maximum of 30 results rather than 1000"
+
+ - title: "Fix sorting of tags column"
+
+ - title: "Change search/replace to show commas instead of vertical bars as the separator for multiple authors"
+
+ - title: "Template language: Make all column names case insensitive"
+
+ - title: "Fix bug that prevent the Disabled option for Tag Browser partiotining from working in the Preferences dialog"
+
+ - title: "Fix bug when using tags like custom column in the template language"
+
+ - title: "Fix bug where composite custom columns using general_program_mode fields are not evaluated correctly when used in a template."
+
+ - title: "ImageMagick interface: Don't crash when asked to open empty image files"
+
+ - title: "Kobo driver: Add TXT,CBZ,CBR to supported formats list"
+ tickets: [8124]
+
+ - title: "Don't uneccessarily scroll the book list horizontally when re-selcting previously selected rows."
+
+ new recipes:
+ - title: "New London Day"
+ author: "Being"
+
+ - title: "Walla"
+ author: "marbs"
+
+ - title: "New Journal of Physics"
+ author: "Chema Cortes"
+
+ - title: "The Baltimore Sun"
+ author: "Josh Hall"
+
+ - title: "Arabian Business and Sunday Times (UK)"
+ author: "Darko Miletic"
+
+ - title: "Deia"
+ author: "Gerardo Diez"
+
+ - title: "Smarter Planet"
+ author: "Jack Mason"
+
+
+ improved recipes:
+ - The Atlantic
+ - Danas
+ - Ledevoir
+
- version: 0.7.37
date: 2011-01-02
diff --git a/resources/recipes/new_london_day.recipe b/resources/recipes/new_london_day.recipe
new file mode 100644
index 0000000000..bc8c44e40e
--- /dev/null
+++ b/resources/recipes/new_london_day.recipe
@@ -0,0 +1,74 @@
+__license__ = 'GPL 3'
+__copyright__ = '2009, Kovid Goyal \n ' + match.group(1) + ' \n ' + match.group(1) + ''+chap+'
\n'
+ return ''+chap+'
\n'
else:
- return ''+chap+'
\n'+title+'
\n'
+ return ''+chap+'
\n'+title+'
\n'
def wrap_lines(match):
ital = match.group('ital')
if not ital:
- return ' '
+ return ' '
else:
- return ital+' '
+ return ital+' '
class DocAnalysis(object):
'''
@@ -191,7 +191,7 @@ class Dehyphenator(object):
dehyphenated = unicode(firsthalf) + unicode(secondhalf)
lookupword = self.removesuffixes.sub('', dehyphenated)
if self.prefixes.match(firsthalf) is None:
- lookupword = self.removeprefix.sub('', lookupword)
+ lookupword = self.removeprefix.sub('', lookupword)
#print "lookup word is: "+str(lookupword)+", orig is: " + str(hyphenated)
try:
searchresult = self.html.find(lookupword.lower())
@@ -353,7 +353,7 @@ class HTMLPreProcessor(object):
(re.compile(r'((?<=)\s*file:////?[A-Z].*
|file:////?[A-Z].*
(?=\s*
))', re.IGNORECASE), lambda match: ''),
# Center separator lines
- (re.compile(u'
\s*(?P
'), lambda match: '
\s*(?P
'), lambda match: '
\s*(?P
\s*){1,3}\s*(?P
)?', re.IGNORECASE), chap_head),
- # Cover the case where every letter in a chapter title is separated by a space
- (re.compile(r'
\s*(?P
\s*){1,3}\s*(?P
))?'), chap_head),
+ # Convert line breaks to paragraphs
+ (re.compile(r'
]*>\s*'), lambda match : '
'), + (re.compile(r'
]*>\s*'), lambda match : '\n'), + (re.compile(r'\s*'), lambda match : '
\n'), - # Have paragraphs show better - (re.compile(r''), # Clean up spaces (re.compile(u'(?<=[\.,;\?!鈥"\'])[\s^ ]*(?=<)'), lambda match: ' '), # Add space before and after italics @@ -455,9 +453,9 @@ class HTMLPreProcessor(object): # delete soft hyphens - moved here so it's executed after header/footer removal if is_pdftohtml: # unwrap/delete soft hyphens - end_rules.append((re.compile(u'[颅](\s*
)+\s*(?=[[a-z\d])'), lambda match: '')) + end_rules.append((re.compile(u'[颅](
\s*\s*)+\s*(?=[[a-z\d])'), lambda match: '')) # unwrap/delete soft hyphens with formatting - end_rules.append((re.compile(u'[颅]\s*((i|u|b)>)+(\s*
)+\s*(<(i|u|b)>)+\s*(?=[[a-z\d])'), lambda match: '')) + end_rules.append((re.compile(u'[颅]\s*((i|u|b)>)+(
\s*\s*)+\s*(<(i|u|b)>)+\s*(?=[[a-z\d])'), lambda match: '')) # Make the more aggressive chapter marking regex optional with the preprocess option to # reduce false positives and move after header/footer removal @@ -475,7 +473,7 @@ class HTMLPreProcessor(object): end_rules.append((re.compile(u'(?<=.{%i}[鈥撯擼)\s*
\s*(?=[[a-z\d])' % length), lambda match: '')) end_rules.append( # Un wrap using punctuation - (re.compile(u'(?<=.{%i}([a-z盲毛茂枚眉脿猫矛貌霉谩膰茅铆贸艅艣煤芒锚卯么没莽膮臋偶谋,:)\IA\u00DF]|(?(i|b|u)>)?\s*(
\s*)+\s*(?=(<(i|b|u)>)?\s*[\w\d$(])' % length, re.UNICODE), wrap_lines),
)
for rule in self.PREPROCESS + start_rules:
@@ -508,7 +506,15 @@ class HTMLPreProcessor(object):
if is_pdftohtml and length > -1:
# Dehyphenate
dehyphenator = Dehyphenator()
- html = dehyphenator(html,'pdf', length)
+ html = dehyphenator(html,'html', length)
+
+ if is_pdftohtml:
+ from calibre.ebooks.conversion.utils import PreProcessor
+ pdf_markup = PreProcessor(self.extra_opts, None)
+ totalwords = 0
+ totalwords = pdf_markup.get_word_count(html)
+ if totalwords > 7000:
+ html = pdf_markup.markup_chapters(html, totalwords, True)
#dump(html, 'post-preprocess')
@@ -554,5 +560,9 @@ class HTMLPreProcessor(object):
html = smartyPants(html)
html = html.replace(start, '')
+ # convert ellipsis to entities to prevent wrapping
+ html = re.sub('(?u)(?<=\w)\s?(\.\s?){2}\.', '…', html)
+ # convert double dashes to em-dash
+ html = re.sub('\s--\s', u'\u2014', html)
return substitute_entites(html)
diff --git a/src/calibre/ebooks/conversion/utils.py b/src/calibre/ebooks/conversion/utils.py
index 11979b933c..1bb232c911 100644
--- a/src/calibre/ebooks/conversion/utils.py
+++ b/src/calibre/ebooks/conversion/utils.py
@@ -6,8 +6,10 @@ __copyright__ = '2010, Kovid Goyal
]*>\s*
){0,2}\s*" + else: + blank_lines = "" + opt_title_open = "(" + opt_title_close = ")?" + n_lookahead_open = "\s+(?!" + n_lookahead_close = ")" + + default_title = r"(<[ibu][^>]*>)?\s{0,3}([\w\'\"-]+\s{0,3}){1,5}?([ibu][^>]*>)?(?=<)" + + chapter_types = [ + [r"[^'\"]?(Introduction|Synopsis|Acknowledgements|Chapter|Kapitel|Epilogue|Volume\s|Prologue|Book\s|Part\s|Dedication|Preface)\s*([\d\w-]+\:?\s*){0,4}", True, "Searching for common Chapter Headings"], + [r"]*>\s*(]*>)?\s*(?!([*#鈥+\s*)+)(\s*(?=[\d.\w#\-*\s]+<)([\d.\w#-*]+\s*){1,5}\s*)(?!\.)()?\s*", True, "Searching for emphasized lines"], # Emphasized lines + [r"[^'\"]?(\d+(\.|:)|CHAPTER)\s*([\dA-Z\-\'\"#,]+\s*){0,7}\s*", True, "Searching for numeric chapter headings"], # Numeric Chapters + [r"([A-Z]\s+){3,}\s*([\d\w-]+\s*){0,3}\s*", True, "Searching for letter spaced headings"], # Spaced Lettering + [r"[^'\"]?(\d+\.?\s+([\d\w-]+\:?\'?-?\s?){0,5})\s*", True, "Searching for numeric chapters with titles"], # Numeric Titles + [r"[^'\"]?(\d+|CHAPTER)\s*([\dA-Z\-\'\"\?!#,]+\s*){0,7}\s*", True, "Searching for simple numeric chapter headings"], # Numeric Chapters, no dot or colon + [r"\s*[^'\"]?([A-Z#]+(\s|-){0,3}){1,5}\s*", False, "Searching for chapters with Uppercase Characters" ] # Uppercase Chapters + ] + + # Start with most typical chapter headings, get more aggressive until one works + for [chapter_type, lookahead_ignorecase, log_message] in chapter_types: + if self.html_preprocess_sections >= self.min_chapters: + break + full_chapter_line = chapter_line_open+chapter_header_open+chapter_type+chapter_header_close+chapter_line_close + n_lookahead = re.sub("(ou|in|cha)", "lookahead_", full_chapter_line) + self.log("Marked " + unicode(self.html_preprocess_sections) + " headings, " + log_message) + if lookahead_ignorecase: + chapter_marker = init_lookahead+full_chapter_line+blank_lines+n_lookahead_open+n_lookahead+n_lookahead_close+opt_title_open+title_line_open+title_header_open+default_title+title_header_close+title_line_close+opt_title_close + chapdetect = re.compile(r'%s' % chapter_marker, re.IGNORECASE) + else: + chapter_marker = init_lookahead+full_chapter_line+blank_lines+opt_title_open+title_line_open+title_header_open+default_title+title_header_close+title_line_close+opt_title_close+n_lookahead_open+n_lookahead+n_lookahead_close + chapdetect = re.compile(r'%s' % chapter_marker, re.UNICODE) + html = chapdetect.sub(self.chapter_head, html) + + words_per_chptr = wordcount + if words_per_chptr > 0 and self.html_preprocess_sections > 0: + words_per_chptr = wordcount / self.html_preprocess_sections + self.log("Total wordcount is: "+ str(wordcount)+", Average words per section is: "+str(words_per_chptr)+", Marked up "+str(self.html_preprocess_sections)+" chapters") + return html + + + def __call__(self, html): self.log("********* Preprocessing HTML *********") + # Count the words in the document to estimate how many chapters to look for and whether + # other types of processing are attempted + totalwords = 0 + totalwords = self.get_word_count(html) + + if totalwords < 20: + self.log("not enough text, not preprocessing") + return html + # Arrange line feeds and tags so the line_length and no_markup functions work correctly - html = re.sub(r"\s*", "\n", html) - html = re.sub(r"\s*[^>]*)>\s*", "\n
"+">", html)
+ html = re.sub(r"\s*(?P