diff --git a/resources/compiled_coffeescript.zip b/resources/compiled_coffeescript.zip index bd1e285820..950086af8e 100644 Binary files a/resources/compiled_coffeescript.zip and b/resources/compiled_coffeescript.zip differ diff --git a/src/calibre/ebooks/oeb/polish/preview.coffee b/src/calibre/ebooks/oeb/polish/preview.coffee index 3dafdedd71..3d41ddb6d3 100644 --- a/src/calibre/ebooks/oeb/polish/preview.coffee +++ b/src/calibre/ebooks/oeb/polish/preview.coffee @@ -226,6 +226,11 @@ get_matched_css = (node, is_ancestor, all_properties) -> return ans.reverse() +scroll_to_node = (node) -> + if node is document.body + window.scrollTo(0, 0) + else + node.scrollIntoView() class PreviewIntegration @@ -244,11 +249,15 @@ class PreviewIntegration for node in document.querySelectorAll('[data-lnum="' + lnum + '"]') if is_hidden(node) continue - if node is document.body - window.scrollTo(0, 0) - else - node.scrollIntoView() - return + scroll_to_node(node) + + go_to_sourceline_address: (sourceline, tags) => + for node, index in document.querySelectorAll('[data-lnum="' + sourceline + '"]') + if index >= tags.length or node.tagName.toLowerCase() != tags[index] + break + if index == tags.length - 1 and not is_hidden(node) + return scroll_to_node(node) + this.go_to_line(sourceline) line_numbers: () => found_body = false @@ -300,14 +309,14 @@ class PreviewIntegration this.report_split(event.target) else e = event.target + address = get_sourceline_address(e) # Find the closest containing link, if any - lnum = e.getAttribute('data-lnum') href = tn = '' while e and e != document.body and e != document and (tn != 'a' or not href) tn = e.tagName?.toLowerCase() href = e.getAttribute('href') e = e.parentNode - window.py_bridge.request_sync(tn, href, lnum) + window.py_bridge.request_sync(tn, href, JSON.stringify(address)) return false go_to_anchor: (anchor, lnum) => diff --git a/src/calibre/gui2/tweak_book/boss.py b/src/calibre/gui2/tweak_book/boss.py index 78885afd9f..b3ca169765 100644 --- a/src/calibre/gui2/tweak_book/boss.py +++ b/src/calibre/gui2/tweak_book/boss.py @@ -1014,11 +1014,11 @@ class Boss(QObject): mt = current_container().mime_map.get(name, guess_type(name)) self.edit_file_requested(name, None, mt) - def sync_editor_to_preview(self, name, lnum): + def sync_editor_to_preview(self, name, sourceline_address): editor = self.edit_file(name, 'html') self.ignore_preview_to_editor_sync = True try: - editor.current_line = lnum + editor.goto_sourceline(*sourceline_address) finally: self.ignore_preview_to_editor_sync = False @@ -1029,7 +1029,7 @@ class Boss(QObject): if ed is not None: name = editor_name(ed) if name is not None and getattr(ed, 'syntax', None) == 'html': - self.gui.preview.sync_to_editor(name, ed.current_line) + self.gui.preview.sync_to_editor(name, ed.current_tag()) def sync_live_css_to_editor(self): ed = self.gui.central.current_editor diff --git a/src/calibre/gui2/tweak_book/preview.py b/src/calibre/gui2/tweak_book/preview.py index 757347b73e..baf7abd927 100644 --- a/src/calibre/gui2/tweak_book/preview.py +++ b/src/calibre/gui2/tweak_book/preview.py @@ -330,9 +330,9 @@ class WebPage(QWebPage): mf.evaluateJavaScript(self.js) @pyqtSlot(str, str, str) - def request_sync(self, tag_name, href, lnum): + def request_sync(self, tag_name, href, sourceline_address): try: - self.sync_requested.emit(unicode(tag_name), unicode(href), int(unicode(lnum))) + self.sync_requested.emit(unicode(tag_name), unicode(href), json.loads(unicode(sourceline_address))) except (TypeError, ValueError, OverflowError, AttributeError): pass @@ -369,6 +369,14 @@ class WebPage(QWebPage): self.mainFrame().evaluateJavaScript( 'window.calibre_preview_integration.go_to_line(%d)' % lnum) + def go_to_sourceline_address(self, sourceline_address): + lnum, tags = sourceline_address + if lnum is None: + return + tags = [x.lower() for x in tags] + self.mainFrame().evaluateJavaScript( + 'window.calibre_preview_integration.go_to_sourceline_address(%d, %s)' % (lnum, json.dumps(tags))) + def split_mode(self, enabled): self.mainFrame().evaluateJavaScript( 'window.calibre_preview_integration.split_mode(%s)' % ( @@ -538,8 +546,8 @@ class Preview(QWidget): if self.current_name: self.split_requested.emit(self.current_name, loc, totals) - def sync_to_editor(self, name, lnum): - self.current_sync_request = (name, lnum) + def sync_to_editor(self, name, sourceline_address): + self.current_sync_request = (name, sourceline_address) QTimer.singleShot(100, self._sync_to_editor) def _sync_to_editor(self): @@ -550,9 +558,9 @@ class Preview(QWidget): return QTimer.singleShot(100, self._sync_to_editor) except TypeError: return # Happens if current_sync_request is None - lnum = self.current_sync_request[1] + sourceline_address = self.current_sync_request[1] self.current_sync_request = None - self.view.page().go_to_line(lnum) + self.view.page().go_to_sourceline_address(sourceline_address) def show(self, name): if name != self.current_name: