branch: elpa/markdown-mode
commit 2335bf55094188dca8c7b1652fc7701de59968ce
Author: Shohei YOSHIDA <[email protected]>
Commit: Shohei YOSHIDA <[email protected]>

    Fix decoding percent characters in URL issue
    
    According to CommonMark specification, we should not decode percent
    encoded characters in URL except control characters and spaces.
---
 CHANGES.md             |  2 ++
 markdown-mode.el       | 24 +++++++++++++++++++++++-
 tests/markdown-test.el | 10 ++++++++++
 3 files changed, 35 insertions(+), 1 deletion(-)

diff --git a/CHANGES.md b/CHANGES.md
index 79221118fbf..707c25919b2 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -17,6 +17,7 @@
     - Fix list item bound calculation when tab indentation is used [GH-904][]
     - Fix `markdown-heading-at-point` at the end of line [GH-912][]
     - Catch an exception when `scan-sexp` fails [GH-917][]
+    - `markdown-link-at-pos` should decode both control characters and spaces 
[GH-921][]
 
 *   Improvements:
     - Support drag and drop features on Windows and multiple files' drag and 
drop
@@ -34,6 +35,7 @@
   [gh-910]: https://github.com/jrblevin/markdown-mode/issues/910
   [gh-912]: https://github.com/jrblevin/markdown-mode/issues/912
   [gh-917]: https://github.com/jrblevin/markdown-mode/issues/917
+  [gh-921]: https://github.com/jrblevin/markdown-mode/issues/921
 
 # Markdown Mode 2.7
 
diff --git a/markdown-mode.el b/markdown-mode.el
index ec886720abc..0dbc5d177e2 100644
--- a/markdown-mode.el
+++ b/markdown-mode.el
@@ -38,6 +38,7 @@
 (require 'thingatpt)
 (require 'cl-lib)
 (require 'url-parse)
+(require 'url-util)
 (require 'button)
 (require 'color)
 (require 'rx)
@@ -8167,6 +8168,27 @@ See `markdown-wiki-link-p' for more information."
             (thing-at-point-looking-at markdown-regex-uri)
             (thing-at-point-looking-at markdown-regex-angle-uri))))))
 
+(defun markdown--unhex-url-string (url)
+  "Unhex control characters and spaces in URL.
+This is similar to `url-unhex-string' but this doesn't unhex all 
percent-encoded
+characters."
+  (let ((str (or url ""))
+        (tmp "")
+        (case-fold-search t))
+    (while (string-match "%\\([01][0-9a-f]\\|20\\)" str)
+      (let* ((start (match-beginning 0))
+             (ch1 (url-unhex (elt str (+ start 1))))
+             (code (+ (* 16 ch1)
+                      (url-unhex (elt str (+ start 2))))))
+        (setq tmp (concat
+                   tmp (substring str 0 start)
+                   (cond
+                    ((or (= code ?\n) (= code ?\r))
+                     " ")
+                    (t (byte-to-string code))))
+              str (substring str (match-end 0)))))
+    (concat tmp str)))
+
 (defun markdown-link-at-pos (pos)
   "Return properties of link or image at position POS.
 Value is a list of elements describing the link:
@@ -8202,7 +8224,7 @@ Value is a list of elements describing the link:
                  (setq url (match-string-no-properties 1 destination-part)
                        title (substring (match-string-no-properties 2 
destination-part) 1 -1)))
                 (t (setq url destination-part)))
-          (setq url (url-unhex-string url))))
+          (setq url (markdown--unhex-url-string url))))
        ;; Reference link at point.
        ((thing-at-point-looking-at markdown-regex-link-reference)
         (setq bang (match-string-no-properties 1)
diff --git a/tests/markdown-test.el b/tests/markdown-test.el
index f843730d01e..dc91a2d709c 100644
--- a/tests/markdown-test.el
+++ b/tests/markdown-test.el
@@ -5703,6 +5703,16 @@ A link can contain spaces if it is wrapped with angle 
brackets"
   (markdown-test-string "[text](<bar%20baz.md>)"
     (should (equal (nth 3 (markdown-link-at-pos (point))) "bar baz.md"))))
 
+(ert-deftest test-markdown-link/inline-link-with-percent-encoded-characters ()
+  "Test URL decoding in `markdown-link-at-pos'.
+It should decode only control characters and spaces in URL according
+to CommonMark specification.
+
+Details: https://github.com/jrblevin/markdown-mode/issues/921";
+
+  (markdown-test-string "[text](bar%2F%30baz.md)"
+    (should (string= (nth 3 (markdown-link-at-pos (point))) 
"bar%2F%30baz.md"))))
+
 (ert-deftest test-markdown-link/reference-link-at-pos ()
   "Test `markdown-link-at-pos' return values with a reference link."
   (markdown-test-string "[text][ref]"

Reply via email to