From bcc87058e0718b52ce20e570b1b0588718e6003c Mon Sep 17 00:00:00 2001
From: Eric Hansander <ehdr@erichansander.com>
Date: Mon, 24 Jan 2022 22:35:33 +0100
Subject: [PATCH] Add command to show link URL without opening it

You may want to see the URL of a link before you open it with `f`/`F`. This
change introduces a new `LinkHints.activateModeToShowLinkUrl` mode, bound
to `sf` by default, that lets you choose a link on the page, and will
show the corresponding URL in the HUD.
---
 background_scripts/commands.js |  4 ++++
 content_scripts/link_hints.js  | 19 +++++++++++++++++--
 content_scripts/mode_normal.js |  3 ++-
 3 files changed, 23 insertions(+), 3 deletions(-)

diff --git a/background_scripts/commands.js b/background_scripts/commands.js
index a6715f5f8..b77829a93 100644
--- a/background_scripts/commands.js
+++ b/background_scripts/commands.js
@@ -213,6 +213,7 @@ const Commands = {
       "LinkHints.activateModeToDownloadLink",
       "LinkHints.activateModeToOpenIncognito",
       "LinkHints.activateModeToCopyLinkUrl",
+      "LinkHints.activateModeToShowLinkUrl",
       "goPrevious",
       "goNext",
       "nextFrame",
@@ -267,6 +268,7 @@ const Commands = {
     "Vomnibar.activateEditUrlInNewTab",
     "LinkHints.activateModeToOpenIncognito",
     "LinkHints.activateModeToCopyLinkUrl",
+    "LinkHints.activateModeToShowLinkUrl",
     "goNext",
     "goPrevious",
     "Marks.activateCreateMode",
@@ -315,6 +317,7 @@ const defaultKeyMappings = {
   "F": "LinkHints.activateModeToOpenInNewTab",
   "<a-f>": "LinkHints.activateModeWithQueue",
   "yf": "LinkHints.activateModeToCopyLinkUrl",
+  "sf": "LinkHints.activateModeToShowLinkUrl",
 
   // Using find
   "/": "enterFindMode",
@@ -403,6 +406,7 @@ const commandDescriptions = {
   "LinkHints.activateModeToOpenIncognito": ["Open a link in incognito window"],
   "LinkHints.activateModeToDownloadLink": ["Download link url"],
   "LinkHints.activateModeToCopyLinkUrl": ["Copy a link URL to the clipboard"],
+  "LinkHints.activateModeToShowLinkUrl": ["Show the URL of a link, without opening it"],
 
   enterFindMode: ["Enter find mode", { noRepeat: true }],
   performFind: ["Cycle forward to the next find match"],
diff --git a/content_scripts/link_hints.js b/content_scripts/link_hints.js
index 610afb71f..8af7ca997 100644
--- a/content_scripts/link_hints.js
+++ b/content_scripts/link_hints.js
@@ -48,6 +48,20 @@ const COPY_LINK_URL = {
     }
   }
 };
+const SHOW_LINK_URL = {
+  name: "link",
+  indicator: "Show link URL",
+  linkActivator(link) {
+    if (link.href != null) {
+      let url = link.href;
+      if (url.slice(0, 7) === "mailto:") { url = url.slice(7); }
+      if (28 < url.length) { url = url.slice(0, 23) + "...."; }
+      HUD.showForDuration(`Link URL: ${url}`, 5000);
+    } else {
+      HUD.showForDuration("No link to show.", 2000);
+    }
+  }
+};
 const OPEN_INCOGNITO = {
   name: "incognito",
   indicator: "Open link in incognito window",
@@ -91,7 +105,7 @@ const FOCUS_LINK = {
 };
 
 const availableModes = [OPEN_IN_CURRENT_TAB, OPEN_IN_NEW_BG_TAB, OPEN_IN_NEW_FG_TAB, OPEN_WITH_QUEUE, COPY_LINK_URL,
-  OPEN_INCOGNITO, DOWNLOAD_LINK_URL, COPY_LINK_TEXT, HOVER_LINK, FOCUS_LINK];
+  SHOW_LINK_URL, OPEN_INCOGNITO, DOWNLOAD_LINK_URL, COPY_LINK_TEXT, HOVER_LINK, FOCUS_LINK];
 
 const HintCoordinator = {
   onExit: [],
@@ -134,7 +148,7 @@ const HintCoordinator = {
   getHintDescriptors({modeIndex, isVimiumHelpDialog}) {
     // Ensure that the document is ready and that the settings are loaded.
     DomUtils.documentReady(() => { return Settings.onLoaded(() => {
-      const requireHref = [COPY_LINK_URL, OPEN_INCOGNITO].includes(availableModes[modeIndex]);
+      const requireHref = [COPY_LINK_URL, SHOW_LINK_URL, OPEN_INCOGNITO].includes(availableModes[modeIndex]);
       // If link hints is launched within the help dialog, then we only offer hints from that frame.  This
       // improves the usability of the help dialog on the options page (particularly for selecting command
       // names).
@@ -241,6 +255,7 @@ var LinkHints = {
   activateModeToOpenInNewTab(count) { this.activateMode(count, {mode: OPEN_IN_NEW_BG_TAB}); },
   activateModeToOpenInNewForegroundTab(count) { this.activateMode(count, {mode: OPEN_IN_NEW_FG_TAB}); },
   activateModeToCopyLinkUrl(count) { this.activateMode(count, {mode: COPY_LINK_URL}); },
+  activateModeToShowLinkUrl(count) { this.activateMode(count, {mode: SHOW_LINK_URL}); },
   activateModeWithQueue() { this.activateMode(1, {mode: OPEN_WITH_QUEUE}); },
   activateModeToOpenIncognito(count) { this.activateMode(count, {mode: OPEN_INCOGNITO}); },
   activateModeToDownloadLink(count) { this.activateMode(count, {mode: DOWNLOAD_LINK_URL}); }
diff --git a/content_scripts/mode_normal.js b/content_scripts/mode_normal.js
index ad6abd5dd..f89d869fd 100644
--- a/content_scripts/mode_normal.js
+++ b/content_scripts/mode_normal.js
@@ -265,7 +265,8 @@ if (typeof LinkHints !== 'undefined') {
     "LinkHints.activateModeWithQueue": LinkHints.activateModeWithQueue.bind(LinkHints),
     "LinkHints.activateModeToOpenIncognito": LinkHints.activateModeToOpenIncognito.bind(LinkHints),
     "LinkHints.activateModeToDownloadLink": LinkHints.activateModeToDownloadLink.bind(LinkHints),
-    "LinkHints.activateModeToCopyLinkUrl": LinkHints.activateModeToCopyLinkUrl.bind(LinkHints)
+    "LinkHints.activateModeToCopyLinkUrl": LinkHints.activateModeToCopyLinkUrl.bind(LinkHints),
+    "LinkHints.activateModeToShowLinkUrl": LinkHints.activateModeToShowLinkUrl.bind(LinkHints)
   });
 }