Ebook viewer: handle self closed tags in XHTML docs correctly. Fixes #3727 (Ebook-viewer problems with valid xhtml)

This commit is contained in:
Kovid Goyal 2009-10-20 16:22:04 -06:00
parent 2e6b286a81
commit f279fcb5c3
3 changed files with 28 additions and 8 deletions

View File

@ -270,6 +270,7 @@ class Spine(ResourceCollection):
Resource.__init__(self, *args, **kwargs) Resource.__init__(self, *args, **kwargs)
self.is_linear = True self.is_linear = True
self.id = idfunc(self.path) self.id = idfunc(self.path)
self.idref = None
@staticmethod @staticmethod
def from_opf_spine_element(itemrefs, manifest): def from_opf_spine_element(itemrefs, manifest):
@ -281,6 +282,7 @@ class Spine(ResourceCollection):
if path: if path:
r = Spine.Item(s.manifest.id_for_path, path, is_path=True) r = Spine.Item(s.manifest.id_for_path, path, is_path=True)
r.is_linear = itemref.get('linear', 'yes') == 'yes' r.is_linear = itemref.get('linear', 'yes') == 'yes'
r.idref = idref
s.append(r) s.append(r)
return s return s

View File

@ -19,6 +19,7 @@ from calibre.utils.zipfile import safe_replace, ZipFile
from calibre.utils.config import DynamicConfig from calibre.utils.config import DynamicConfig
from calibre.utils.logging import Log from calibre.utils.logging import Log
from calibre.ebooks.epub.output import EPUBOutput from calibre.ebooks.epub.output import EPUBOutput
from calibre import guess_type
TITLEPAGE = EPUBOutput.TITLEPAGE_COVER.decode('utf-8') TITLEPAGE = EPUBOutput.TITLEPAGE_COVER.decode('utf-8')
@ -39,20 +40,20 @@ class UnsupportedFormatError(Exception):
class SpineItem(unicode): class SpineItem(unicode):
def __new__(cls, *args): def __new__(cls, path, mime_type=None):
args = list(args)
path = args[0]
ppath = path.partition('#')[0] ppath = path.partition('#')[0]
if not os.path.exists(path) and os.path.exists(ppath): if not os.path.exists(path) and os.path.exists(ppath):
path = ppath path = ppath
args[0] = path obj = super(SpineItem, cls).__new__(cls, path)
obj = super(SpineItem, cls).__new__(cls, *args)
raw = open(path, 'rb').read() raw = open(path, 'rb').read()
raw, obj.encoding = xml_to_unicode(raw) raw, obj.encoding = xml_to_unicode(raw)
obj.character_count = character_count(raw) obj.character_count = character_count(raw)
obj.start_page = -1 obj.start_page = -1
obj.pages = -1 obj.pages = -1
obj.max_page = -1 obj.max_page = -1
if mime_type is None:
mime_type = guess_type(obj)[0]
obj.mime_type = mime_type
return obj return obj
class FakeOpts(object): class FakeOpts(object):
@ -150,8 +151,17 @@ class EbookIterator(object):
self.language = self.opf.language self.language = self.opf.language
if self.language: if self.language:
self.language = self.language.lower() self.language = self.language.lower()
self.spine = [SpineItem(i.path) for i in self.opf.spine if i.is_linear] ordered = [i for i in self.opf.spine if i.is_linear] + \
self.spine += [SpineItem(i.path) for i in self.opf.spine if not i.is_linear] [i for i in self.opf.spine if not i.is_linear]
self.spine = []
for i in ordered:
spath = i.path
mt = None
if i.idref is not None:
mt = self.opf.manifest.type_for_id(i.idref)
if mt is None:
mt = guess_type(spath)[0]
self.spine.append(SpineItem(spath, mime_type=mt))
cover = self.opf.cover cover = self.opf.cover
if self.ebook_ext in ('lit', 'mobi', 'prc', 'opf') and cover: if self.ebook_ext in ('lit', 'mobi', 'prc', 'opf') and cover:

View File

@ -18,7 +18,7 @@ from calibre.gui2.viewer.config_ui import Ui_Dialog
from calibre.gui2.viewer.js import bookmarks, referencing, hyphenation from calibre.gui2.viewer.js import bookmarks, referencing, hyphenation
from calibre.ptempfile import PersistentTemporaryFile from calibre.ptempfile import PersistentTemporaryFile
from calibre.constants import iswindows from calibre.constants import iswindows
from calibre import prints from calibre import prints, guess_type
def load_builtin_fonts(): def load_builtin_fonts():
base = P('fonts/liberation/*.ttf') base = P('fonts/liberation/*.ttf')
@ -352,6 +352,8 @@ class DocumentView(QWebView):
def __init__(self, *args): def __init__(self, *args):
QWidget.__init__(self, *args) QWidget.__init__(self, *args)
self.debug_javascript = False self.debug_javascript = False
self.self_closing_pat = re.compile(r'<([a-z]+)\s+([^>]+)/>',
re.IGNORECASE)
self.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)) self.setSizePolicy(QSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding))
self._size_hint = QSize(510, 680) self._size_hint = QSize(510, 680)
self.initial_pos = 0.0 self.initial_pos = 0.0
@ -447,8 +449,14 @@ class DocumentView(QWebView):
def load_path(self, path, pos=0.0): def load_path(self, path, pos=0.0):
self.initial_pos = pos self.initial_pos = pos
mt = getattr(path, 'mime_type', None)
if mt is None:
mt = guess_type(path)[0]
html = open(path, 'rb').read().decode(path.encoding, 'replace') html = open(path, 'rb').read().decode(path.encoding, 'replace')
html = EntityDeclarationProcessor(html).processed_html html = EntityDeclarationProcessor(html).processed_html
if 'xhtml' in mt:
html = self.self_closing_pat.sub(r'<\1 \2></\1>', html)
#self.setContent(QByteArray(html.encode(path.encoding)), mt, QUrl.fromLocalFile(path))
self.setHtml(html, QUrl.fromLocalFile(path)) self.setHtml(html, QUrl.fromLocalFile(path))
self.turn_off_internal_scrollbars() self.turn_off_internal_scrollbars()