Subject: Re: bug#58118: 29.0.50; Follow #target links in eww without re-rendering page

From: Visuwesh <[email-masked]>
Date: Wed, 28 Sep 2022 08:12:51 +0530

[செவ்வாய் செப்டம்பர் 27, 2022] Lars Ingebrigtsen wrote:

> Visuwesh <[email-masked]> writes:
>
>> eww-follow-link currently follows #target links in the same URL by
>> re-rendering the page.  Whilst this is fine for small HTML files, the
>> 1.9M HTML file that I'm currently visiting takes a couple seconds to
>> render.
>
> That's a regression, I think -- following #target links used to work
> without re-rendering.  (At least it did at one point.)

That's what I seem to remember as well.

>> I see that eww-display-html follows #target links by a text property
>> search, why don't we do the same in eww-follow-link as well?  I have one
>> question though: what do we about non-existent #targets?  Chrome and
>> Firefox seem to not scroll when I add a non-existent #target to the
>> current URL and say RET, and it seems to specially handle #top to mean
>> to go to the top even if the HTML has no hits for "#top".  Should we
>> handle the special #top target?
>
> Sure, makes sense.

Now done.

>> +        (setq match (text-property-search-forward 'shr-target-id target #'member))
>> +        (if match
>> +            (goto-char (prop-match-beginning match))
>
> This is more conveniently expressed as
>
> (when-let ((text-property-search-forward 'shr-target-id target #'member))
>   (goto-char (prop-match-beginning match)))

Thanks.  Revised patch attached,

>From 4b7280340de897137e1f4272219dddde292e5a4b Mon Sep 17 00:00:00 2001
From: Visuwesh <[email-masked]>
Date: Wed, 28 Sep 2022 08:11:42 +0530
Subject: [PATCH] Follow #target links in eww without re-rendering

* lisp/net/eww.el (eww-follow-link): Do a text property search instead
of re-rendering to follow #target links in the same page.  (bug#58118)
(eww-link-keymap): Bind <mouse-2> to eww-follow-link as well.
---
 lisp/net/eww.el | 17 ++++++++++++-----
 1 file changed, 12 insertions(+), 5 deletions(-)

diff --git a/lisp/net/eww.el b/lisp/net/eww.el
index 61b1b75068..624958915a 100644
--- a/lisp/net/eww.el
+++ b/lisp/net/eww.el
@@ -315,7 +315,8 @@ eww-accept-content-types
 
 (defvar-keymap eww-link-keymap
   :parent shr-map
-  "RET" #'eww-follow-link)
+  "RET" #'eww-follow-link
+  "<mouse-2>" #'eww-follow-link)
 
 (defvar-keymap eww-image-link-keymap
   :parent shr-map
@@ -1901,7 +1902,8 @@ eww-follow-link
    eww-mode)
   (mouse-set-point mouse-event)
   (let* ((orig-url (get-text-property (point) 'shr-url))
-         (url (eww--transform-url orig-url)))
+         (url (eww--transform-url orig-url))
+         target)
     (cond
      ((not url)
       (message "No link under point"))
@@ -1913,12 +1915,17 @@ eww-follow-link
       (funcall browse-url-secondary-browser-function url)
       (shr--blink-link))
      ;; This is a #target url in the same page as the current one.
-     ((and (url-target (url-generic-parse-url url))
+     ((and (setq target (url-target (url-generic-parse-url url)))
 	   (eww-same-page-p url (plist-get eww-data :url)))
-      (let ((dom (plist-get eww-data :dom)))
+      (let ((point (point)))
 	(eww-save-history)
 	(plist-put eww-data :url url)
-	(eww-display-html 'utf-8 url dom nil (current-buffer))))
+        (goto-char (point-min))
+        (if-let ((match (text-property-search-forward 'shr-target-id target #'member)))
+            (goto-char (prop-match-beginning match))
+          (goto-char (if (equal target "top")
+                         (point-min)
+                       point)))))
      (t
       (eww-browse-url orig-url external)))))
 
-- 
2.35.1