branch: elpa/hyperdrive
commit ae08015be95d50c518369eeac6af236fd2914b4c
Author: Adam Porter <[email protected]>
Commit: Adam Porter <[email protected]>

    Add: Markdown link support
---
 hyperdrive.el                     |  32 +++++++++++
 tests/test-hyperdrive-markdown.el | 115 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 147 insertions(+)

diff --git a/hyperdrive.el b/hyperdrive.el
index 9c10baacf8..d8da2b4d6c 100644
--- a/hyperdrive.el
+++ b/hyperdrive.el
@@ -1223,6 +1223,38 @@ The return value of this function is the retrieval 
buffer."
   (interactive)
   (info "(hyperdrive) Top"))
 
+;;;;; Markdown link support
+
+(defun hyperdrive--markdown-follow-link (url)
+  "Follow URL.
+For use in `markdown-follow-link-functions'."
+  (pcase (url-type (url-generic-parse-url url))
+    ((and `nil (guard (and hyperdrive-mode hyperdrive-current-entry)))
+     (hyperdrive-open (hyperdrive--markdown-url-entry url))
+     t)
+    (_ nil)))
+
+(defun hyperdrive--markdown-url-entry (url)
+  "Return hyperdrive entry for URL in `markdown-mode' buffer.
+Intended for relative (i.e. non-full) URLs."
+  (pcase-let (((cl-struct url filename) (url-generic-parse-url url))
+              ((cl-struct hyperdrive-entry hyperdrive path)
+               hyperdrive-current-entry))
+    ;; NOTE: Depending on the resolution of
+    ;; <https://github.com/jrblevin/markdown-mode/issues/805>, we may
+    ;; want to URL-decode paths.  For now, we won't.
+    (hyperdrive-entry-create
+     :hyperdrive hyperdrive
+     :path (expand-file-name filename (file-name-directory path))
+     ;; FIXME: Target.
+     ;; :etc `((target . ,FOO))
+     )))
+
+;;;###autoload
+(with-eval-after-load 'markdown-mode
+  (when (boundp 'markdown-follow-link-functions)
+    (cl-pushnew #'hyperdrive--markdown-follow-link 
markdown-follow-link-functions)))
+
 ;;;; Footer
 
 (provide 'hyperdrive)
diff --git a/tests/test-hyperdrive-markdown.el 
b/tests/test-hyperdrive-markdown.el
new file mode 100644
index 0000000000..58eb08b575
--- /dev/null
+++ b/tests/test-hyperdrive-markdown.el
@@ -0,0 +1,115 @@
+;;; test-hyperdrive-markdown.el --- Test Hyperdrive.el's integration with 
markdown-mode  -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2023 Joseph Turner <[email protected]>
+
+;; Author: Joseph Turner
+;; Author: Adam Porter <[email protected]>
+;; Maintainer: Joseph Turner <[email protected]>
+
+;; This program is free software; you can redistribute it and/or
+;; modify it under the terms of the GNU Affero General Public License
+;; as published by the Free Software Foundation; either version 3 of
+;; the License, or (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; Affero General Public License for more details.
+
+;; You should have received a copy of the GNU Affero General Public
+;; License along with this program. If not, see
+;; <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This file tests Hyperdrive.el's `markdown-mode' link functionality.
+
+;;; Code:
+
+;;;; Requirements
+
+(require 'cl-lib)
+(require 'ert)
+(require 'pcase)
+
+(require 'hyperdrive)
+(require 'markdown-mode)
+
+;;;; Tests
+
+;;;; Parse relative/absolute link into entry tests
+
+;; Neither full "hyper://"-prefixed URLs, nor links which are only search
+;; options, are handled by `hyperdrive--org-link-entry-at-point'.
+
+(defmacro hyperdrive-test-markdown-parse-link-deftest (name current-entry link 
parsed-entry)
+  (declare (indent defun))
+  (let ((test-name (intern (format "hyperdrive-test-markdown-parse-link/%s" 
name))))
+    `(ert-deftest ,test-name ()
+       (let ((hyperdrive-current-entry ,current-entry))
+         (with-temp-buffer
+           ;; FIXME: Use persistent buffer for performance.
+           (markdown-mode)
+           (erase-buffer)
+           (insert ,link)
+           (goto-char (point-min))
+           (should
+            (hyperdrive-entry-equal-p ,parsed-entry
+                                      (hyperdrive--markdown-url-entry 
(markdown-link-url)))))))))
+
+(hyperdrive-test-markdown-parse-link-deftest absolute/without-search-option
+  (hyperdrive-entry-create
+   :hyperdrive (hyperdrive-create :public-key "deadbeef")
+   :path "/foo/bar quux.md")
+  "[link](</foo/bar quux.md>)"
+  (hyperdrive-entry-create
+   :hyperdrive (hyperdrive-create :public-key "deadbeef")
+   :path "/foo/bar quux.md"))
+
+(hyperdrive-test-markdown-parse-link-deftest parent/without-search-option
+  (hyperdrive-entry-create
+   :hyperdrive (hyperdrive-create :public-key "deadbeef")
+   :path "/foo/bar quux.md")
+  "[link](<../foo/bar quux.md>)"
+  (hyperdrive-entry-create
+   :hyperdrive (hyperdrive-create :public-key "deadbeef")
+   :path "/foo/bar quux.md"))
+
+(hyperdrive-test-markdown-parse-link-deftest sibling/without-search-option
+  (hyperdrive-entry-create
+   :hyperdrive (hyperdrive-create :public-key "deadbeef")
+   :path "/foo/bar quux.md")
+  "[link](<./bar quux.md>)"
+  (hyperdrive-entry-create
+   :hyperdrive (hyperdrive-create :public-key "deadbeef")
+   :path "/foo/bar quux.md"))
+
+;; (hyperdrive-test-markdown-parse-link-deftest 
sibling/with-heading-text-search-option
+;;   (hyperdrive-entry-create
+;;    :hyperdrive (hyperdrive-create :public-key "deadbeef")
+;;    :path "/foo/bar quux.md")
+;;   "[link](<./bar quux.md::Heading A>)"
+;;   (hyperdrive-entry-create
+;;    :hyperdrive (hyperdrive-create :public-key "deadbeef")
+;;    :path "/foo/bar quux.md"
+;;    :etc '((target . "Heading A"))))
+
+;; (hyperdrive-test-markdown-parse-link-deftest 
sibling/with-heading-text*-search-option
+;;   (hyperdrive-entry-create
+;;    :hyperdrive (hyperdrive-create :public-key "deadbeef")
+;;    :path "/foo/bar quux.md")
+;;   "[link](<./bar quux.md::*Heading A>)"
+;;   (hyperdrive-entry-create
+;;    :hyperdrive (hyperdrive-create :public-key "deadbeef")
+;;    :path "/foo/bar quux.md"
+;;    :etc '((target . "*Heading A"))))
+
+;; (hyperdrive-test-markdown-parse-link-deftest 
sibling/with-custom-id-search-option
+;;   (hyperdrive-entry-create
+;;    :hyperdrive (hyperdrive-create :public-key "deadbeef")
+;;    :path "/foo/bar quux.md")
+;;   "[link](<./bar quux.md::#baz zot>)"
+;;   (hyperdrive-entry-create
+;;    :hyperdrive (hyperdrive-create :public-key "deadbeef")
+;;    :path "/foo/bar quux.md"
+;;    :etc '((target . "#baz zot"))))

Reply via email to