dotemacs

My Emacs configuration
git clone git://git.entf.net/dotemacs
Log | Files | Refs | LICENSE

markdown-test.el (303841B)


      1 ;;;; markdown-test.el --- Tests for markdown-mode  -*- lexical-binding: t; -*-
      2 
      3 ;; Copyright (C) 2013-2017 Jason R. Blevins <jblevins@xbeta.org>
      4 ;; Copyright (C) 2013 Makoto Motohashi <mkt.motohashi@gmail.com>
      5 ;; Copyright (C) 2015 Google, Inc. (Contributor: Samuel Freilich <sfreilich@google.com>)
      6 
      7 ;; This file is not part of GNU Emacs.
      8 
      9 ;; This program is free software; you can redistribute it and/or modify
     10 ;; it under the terms of the GNU General Public License as published by
     11 ;; the Free Software Foundation, either version 3 of the License, or
     12 ;; (at your option) any later version.
     13 
     14 ;; This program is distributed in the hope that it will be useful,
     15 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
     16 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     17 ;; GNU General Public License for more details.
     18 
     19 ;; You should have received a copy of the GNU General Public License
     20 ;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
     21 
     22 ;;; Commentary:
     23 
     24 ;; This file contains the `markdown-mode' test suite.  To run the tests:
     25 ;;
     26 ;;     M-x load-file RET markdown-test.el RET
     27 ;;     M-x markdown-test RET
     28 
     29 ;;; Code:
     30 
     31 (require 'markdown-mode)
     32 (require 'ert)
     33 (require 'cl-lib)
     34 (require 'ispell)
     35 
     36 (defvar electric-pair-pairs)
     37 
     38 (defconst markdown-test-dir
     39   (expand-file-name (file-name-directory
     40                      (or load-file-name buffer-file-name))))
     41 
     42 (defconst markdown-test-font-lock-function
     43   (if (fboundp 'font-lock-ensure)
     44       #'font-lock-ensure #'font-lock-fontify-buffer))
     45 
     46 (defmacro markdown-test-string-mode (mode string &rest body)
     47   "Run BODY in a temporary buffer containing STRING in MODE."
     48   (declare (indent 2))
     49   `(let ((win (selected-window)))
     50      (unwind-protect
     51          (with-temp-buffer
     52            (set-window-buffer win (current-buffer) t)
     53            (erase-buffer)
     54            (insert ,string)
     55            (funcall ,mode)
     56            (setq-default indent-tabs-mode nil)
     57            (goto-char (point-min))
     58            (funcall markdown-test-font-lock-function)
     59            (prog1 ,@body (kill-buffer))))))
     60 
     61 (defmacro markdown-test-file-mode (mode file &rest body)
     62   "Open FILE from `markdown-test-dir' in MODE and execute BODY."
     63   (declare (indent 2))
     64   `(let ((fn (concat markdown-test-dir ,file)))
     65      (save-window-excursion
     66        (with-temp-buffer
     67          (insert-file-contents fn)
     68          (funcall ,mode)
     69          (goto-char (point-min))
     70          (funcall markdown-test-font-lock-function)
     71          ,@body))))
     72 
     73 (defmacro markdown-test-string (string &rest body)
     74   "Run BODY in a temporary buffer containing STRING in `markdown-mode'."
     75   (declare (indent 1))
     76   `(markdown-test-string-mode 'markdown-mode ,string ,@body))
     77 (def-edebug-spec markdown-test-string (form body))
     78 
     79 (defmacro markdown-test-string-view (string &rest body)
     80   "Run BODY in a temporary buffer containing STRING in `markdown-view-mode'."
     81   (declare (indent 1))
     82   `(markdown-test-string-mode 'markdown-view-mode ,string ,@body))
     83 (def-edebug-spec markdown-test-string-view (form body))
     84 
     85 (defmacro markdown-test-file (file &rest body)
     86   "Open FILE from `markdown-test-dir' in `markdown-mode' and execute BODY."
     87   (declare (indent 1))
     88   `(markdown-test-file-mode 'markdown-mode ,file ,@body))
     89 (def-edebug-spec markdown-test-file (form body))
     90 
     91 (defmacro markdown-test-string-gfm (string &rest body)
     92   "Run BODY in a temporary buffer containing STRING in `gfm-mode'."
     93   (declare (indent 1))
     94   `(markdown-test-string-mode 'gfm-mode ,string ,@body))
     95 (def-edebug-spec markdown-test-string-gfm (form body))
     96 
     97 (defmacro markdown-test-string-gfm-view (string &rest body)
     98   "Run BODY in a temporary buffer containing STRING in `gfm-view-mode'."
     99   (declare (indent 1))
    100   `(markdown-test-string-mode 'gfm-view-mode ,string ,@body))
    101 (def-edebug-spec markdown-test-string-gfm-view (form body))
    102 
    103 (defmacro markdown-test-file-gfm (file &rest body)
    104   "Open FILE from `markdown-test-dir' in `gfm-mode' and execute BODY."
    105   (declare (indent 1))
    106   `(markdown-test-file-mode 'gfm-mode ,file ,@body))
    107 (def-edebug-spec markdown-test-file-gfm (form body))
    108 
    109 (defmacro markdown-test-temp-file (file &rest body)
    110   "Open FILE from `markdown-test-dir' visiting temp file and execute BODY.
    111 This file is not saved."
    112   (declare (indent 1))
    113   `(let ((fn (concat markdown-test-dir ,file))
    114          (tmp (make-temp-file "markdown-test" nil ".text"))
    115          buf)
    116      (save-window-excursion
    117        (unwind-protect
    118            (progn
    119              (setq buf (find-file tmp))
    120              (insert-file-contents fn)
    121              (markdown-mode)
    122              (goto-char (point-min))
    123              (funcall markdown-test-font-lock-function)
    124              ,@body)
    125          (when (buffer-live-p buf)
    126            (set-buffer-modified-p nil)
    127            (kill-buffer buf))
    128          (delete-file tmp)))))
    129 (def-edebug-spec markdown-test-temp-file (form body))
    130 
    131 (defun markdown-test-report-property-range (begin end prop)
    132   "Report buffer substring and property PROP from BEGIN to END."
    133   (message "Buffer substring: %s" (buffer-substring begin (1+ end)))
    134   (message "Properties in range are as follows:")
    135   (dolist (loc (number-sequence begin end))
    136     (message "%d: %s" loc (get-char-property loc prop))))
    137 
    138 (defun markdown-test-range-has-property (begin end prop value)
    139   "Verify that range BEGIN to END has PROP equal to or containing VALUE."
    140   (let (vals fail-loc)
    141     (setq fail-loc
    142           (catch 'fail
    143             (dolist (loc (number-sequence begin end))
    144               (setq vals (get-char-property loc prop))
    145               (if (and vals (listp vals))
    146                   (unless (memq value vals)
    147                     (throw 'fail loc))
    148                 (unless (eq vals value)
    149                   (throw 'fail loc))))))
    150     (when fail-loc
    151       (message "Testing range (%d,%d) for property %s equal to %s."
    152                begin end prop value)
    153       (message "Expected value (%s) not found in property (%s) at location %d" value prop fail-loc)
    154       (markdown-test-report-property-range begin end prop))
    155     (should-not fail-loc)))
    156 
    157 (defun markdown-test-range-property-equals (begin end prop value)
    158   "Verify that range BEGIN to END has property PROP equal to VALUE."
    159   (let ((fail-loc
    160          (catch 'fail
    161            (dolist (loc (number-sequence begin end))
    162              (unless (eq (get-char-property loc prop) value)
    163                (throw 'fail loc))))))
    164     (when fail-loc
    165       (message "Testing range (%d,%d) for property %s equal to %s."
    166                begin end prop value)
    167       (message "Expected value (%s) not found in property (%s) at location %d" value prop fail-loc)
    168       (markdown-test-report-property-range begin end prop))
    169     (should-not fail-loc)))
    170 
    171 (defun markdown-test-range-has-face (begin end face)
    172   "Verify that the range from BEGIN to END has face FACE."
    173   (markdown-test-range-has-property begin end 'face face))
    174 
    175 (defun markdown-test-range-face-equals (begin end face)
    176   "Verify that the range from BEGIN to END has face equal to FACE."
    177   (markdown-test-range-property-equals begin end 'face face))
    178 
    179 (defun markdown-test-goto-heading (title)
    180   "Move the point to section with TITLE."
    181   (let ((regexp (format "\\(^#+ %s\\( #+\\)?\\|^%s\n[=-]+\n\\)" title title)))
    182     (if (re-search-forward regexp nil t)
    183         (goto-char (match-end 0)))))
    184 
    185 (defun markdown-command-identity (begin end output-buffer)
    186   "A placeholder `markdown-command' function for testing.
    187 Extracts region from BEGIN to END and inserts in OUTPUT-BUFFER."
    188   (let ((text (buffer-substring-no-properties begin end)))
    189     (with-current-buffer output-buffer
    190       (erase-buffer)
    191       (insert text))))
    192 
    193 (defun markdown-test ()
    194   "Run all defined test cases for `markdown-mode'."
    195   (interactive)
    196   (ert "markdown"))
    197 
    198 ;;; major-mode tests:
    199 
    200 (ert-deftest test-markdown-major-mode ()
    201   "Test auto-mode-alist setting."
    202   (dolist (extension '(".md" ".markdown" ".mkd" ".mdown" ".mkdn" ".mdwn"))
    203     (let ((file (make-temp-file "a" nil extension)))
    204       (unwind-protect
    205           (with-current-buffer (find-file-noselect file)
    206             (should (eq major-mode 'markdown-mode)))
    207         (delete-file file)))))
    208 
    209 ;;; Example tests:
    210 
    211 (ert-deftest test-markdown-example/string ()
    212   "An example string test using the `ert' framework."
    213   (markdown-test-string "foo *bar* baz"
    214     (goto-char 5)
    215     (delete-char 1)
    216     (should (looking-at "bar"))))
    217 
    218 (ert-deftest test-markdown-example/file ()
    219   "An example file test using the `ert' framework."
    220   (markdown-test-file "inline.text"
    221     (goto-char 9)
    222     (should (looking-at "\*"))))
    223 
    224 ;;; Basic mode tests:
    225 
    226 (ert-deftest test-markdown-mode/variables ()
    227   "Test `markdown-mode' variables."
    228   (markdown-test-file "inline.text"
    229     (should (= tab-width 4))
    230     (should (eq font-lock-multiline t))
    231     (should (eq major-mode 'markdown-mode))))
    232 
    233 ;;; Element insertion tests:
    234 
    235 (ert-deftest test-markdown-insertion/blank-line-before-1 ()
    236   "Test function `markdown-ensure-blank-line-before' at beginning of line."
    237   (markdown-test-file "syntax.text"
    238     (search-forward "as plain text")
    239     (should (= (point) 1556))
    240     (beginning-of-line)
    241     (should (= (point) 1505))
    242     (should (looking-back "A Markdown-formatted\n" nil))
    243     (should (not (markdown-prev-line-blank-p)))
    244     (markdown-ensure-blank-line-before)
    245     (should (looking-back "A Markdown-formatted\n\n" nil))
    246     (should (markdown-prev-line-blank-p))))
    247 
    248 (ert-deftest test-markdown-insertion/blank-line-before-2 ()
    249   "Test function `markdown-ensure-blank-line-before' in middle of line."
    250   (markdown-test-file "syntax.text"
    251     (search-forward "as plain text")
    252     (should (= (point) 1556))
    253     (should (looking-back "as plain text" nil))
    254     (should (not (markdown-prev-line-blank-p)))
    255     (markdown-ensure-blank-line-before)
    256     (should (looking-back "as plain text\n\n" nil))
    257     (should (markdown-prev-line-blank-p))))
    258 
    259 (ert-deftest test-markdown-insertion/blank-line-before-3 ()
    260   "Test function `markdown-ensure-blank-line-before' with blank line before."
    261   (markdown-test-file "syntax.text"
    262     (search-forward "web.\n\nMarkdown is not a replacement for HTML")
    263     (beginning-of-line)
    264     (should (= (point) 2704))
    265     (should (looking-back "web.\n\n" nil))
    266     (should (markdown-prev-line-blank-p))
    267     (markdown-ensure-blank-line-before)
    268     (should (= (point) 2704))
    269     (should (looking-back "web.\n\n" nil))
    270     (should (markdown-prev-line-blank-p))))
    271 
    272 (ert-deftest test-markdown-insertion/blank-line-before-4 ()
    273   "Test function `markdown-ensure-blank-line-before' at beginning of buffer."
    274   (markdown-test-string "first line"
    275     (beginning-of-line)
    276     (should (bobp))
    277     (should (= (point-max) 11))
    278     (markdown-ensure-blank-line-before)
    279     (should (= (point-max) 11))
    280     (should (string-equal (buffer-substring (point-min) (point-max))
    281                           "first line"))
    282     (forward-word)
    283     (markdown-ensure-blank-line-before)
    284     (should (string-equal (buffer-substring (point-min) (point-max))
    285                           "first\n\n line"))))
    286 
    287 (ert-deftest test-markdown-insertion/blank-line-after-1 ()
    288   "Test function `markdown-ensure-blank-line-after' at end of line."
    289   (markdown-test-file "syntax.text"
    290     (search-forward "as plain text")
    291     (should (= (point) 1556))
    292     (end-of-line)
    293     (should (= (point) 1573))
    294     (should (looking-at "\nlike it's been"))
    295     (should (not (markdown-next-line-blank-p)))
    296     (markdown-ensure-blank-line-after)
    297     (should (looking-at "\n\nlike it's been"))
    298     (should (markdown-next-line-blank-p))))
    299 
    300 (ert-deftest test-markdown-insertion/blank-line-after-2 ()
    301   "Test function `markdown-ensure-blank-line-after' in middle of line."
    302   (markdown-test-file "syntax.text"
    303     (search-forward "as plain text")
    304     (should (= (point) 1556))
    305     (should (looking-at ", without looking"))
    306     (should (not (markdown-next-line-blank-p)))
    307     (markdown-ensure-blank-line-after)
    308     (should (looking-at "\n\n, without looking"))
    309     (should (markdown-next-line-blank-p))))
    310 
    311 (ert-deftest test-markdown-insertion/blank-line-after-3 ()
    312   "Test function `markdown-ensure-blank-line-after' with blank line after."
    313   (markdown-test-file "syntax.text"
    314     (search-forward "*writing* for the web.")
    315     (should (= (point) 2702))
    316     (should (looking-at "\n\nMarkdown is not a replacement for HTML"))
    317     (should (markdown-next-line-blank-p))
    318     (markdown-ensure-blank-line-after)
    319     (should (= (point) 2702))
    320     (should (looking-at "\n\nMarkdown is not a replacement for HTML"))
    321     (should (markdown-next-line-blank-p))))
    322 
    323 (ert-deftest test-markdown-insertion/blank-line-after-4 ()
    324   "Test function `markdown-ensure-blank-line-after' at end of buffer."
    325   (markdown-test-string "last line"
    326     (end-of-line)
    327     (should (eobp))
    328     (should (= (point-max) 10))
    329     (markdown-ensure-blank-line-after)
    330     (should (= (point-max) 10))
    331     (should (string-equal (buffer-substring (point-min) (point-max))
    332                           "last line"))
    333     (backward-word)
    334     (markdown-ensure-blank-line-after)
    335     (should (string-equal (buffer-substring (point-min) (point-max))
    336                           "last \n\nline"))))
    337 
    338 (ert-deftest test-markdown-insertion/point-after-unwrap ()
    339   "Test new point position calculations after unwrap operations."
    340   (markdown-test-string "line **one**\n"
    341     (let ((prefix (cons 6 8)) (suffix (cons 11 13)))
    342       ;; Prefix
    343       (should (eq (markdown-point-after-unwrap 6 prefix suffix) 6))
    344       (should (eq (markdown-point-after-unwrap 7 prefix suffix) 6))
    345       ;; Word
    346       (should (eq (markdown-point-after-unwrap 8 prefix suffix) 6))
    347       (should (eq (markdown-point-after-unwrap 9 prefix suffix) 7))
    348       (should (eq (markdown-point-after-unwrap 10 prefix suffix) 8))
    349       ;; Suffix
    350       (should (eq (markdown-point-after-unwrap 11 prefix suffix) 9))
    351       (should (eq (markdown-point-after-unwrap 12 prefix suffix) 9))
    352       ;; Immediately after
    353       (should (eq (markdown-point-after-unwrap 13 prefix suffix) 9))))
    354   (markdown-test-string "line _one_\n"
    355     (let ((prefix (cons 6 7)) (suffix (cons 10 11)))
    356       ;; Prefix
    357       (should (eq (markdown-point-after-unwrap 6 prefix suffix) 6))
    358       ;; Word
    359       (should (eq (markdown-point-after-unwrap 7 prefix suffix) 6))
    360       (should (eq (markdown-point-after-unwrap 8 prefix suffix) 7))
    361       (should (eq (markdown-point-after-unwrap 9 prefix suffix) 8))
    362       ;; Suffix
    363       (should (eq (markdown-point-after-unwrap 10 prefix suffix) 9))
    364       ;; Immediately after
    365       (should (eq (markdown-point-after-unwrap 10 prefix suffix) 9)))))
    366 
    367 (ert-deftest test-markdown-insertion/unwrap-thing-at-point-italic ()
    368   "Test function `markdown-unwrap-thing-at-point' on italics."
    369   (markdown-test-file "syntax.text"
    370     ;; Unwrap *not*
    371     (goto-char 2859)
    372     (should (thing-at-point-looking-at markdown-regex-italic))
    373     (should (equal (markdown-unwrap-thing-at-point
    374                     markdown-regex-italic 1 3)
    375                    (cons 2859 2862)))
    376     (should (= (point) 2859))
    377     ;; Unwrap *publishing*
    378     (goto-char 3064)
    379     (should (thing-at-point-looking-at markdown-regex-italic))
    380     (should (equal (markdown-unwrap-thing-at-point
    381                     markdown-regex-italic 1 3)
    382                    (cons 3060 3070)))
    383     (should (= (point) 3063))
    384     ;; Unwrap *writing*
    385     (goto-char 3101)
    386     (should (thing-at-point-looking-at markdown-regex-italic))
    387     (should (equal (markdown-unwrap-thing-at-point
    388                     markdown-regex-italic 1 3)
    389                    (cons 3093 3100)))
    390     (should (= (point) 3100))))
    391 
    392 (ert-deftest test-markdown-insertion/unwrap-things-in-region-italic ()
    393   "Test function `markdown-unwrap-things-in-region' on italics."
    394   (markdown-test-file "syntax.text"
    395     (should (equal (markdown-unwrap-things-in-region
    396                     2704 3207 markdown-regex-italic 1 3)
    397                    (cons 2704 3201)))))
    398 
    399 (ert-deftest test-markdown-insertion/unwrap-things-in-region-bound ()
    400   "Ensure that `markdown-unwrap-things-in-region' respects end bound"
    401   (markdown-test-string "**a** **b** **c** **d** **e** **f**"
    402     ;; Set region to unrwap a, b, c, and d only.  If endpoint is not
    403     ;; respected (i.e, not adjusted for character removal), the
    404     ;; function will unwrap e and f also.
    405     (should (equal (markdown-unwrap-things-in-region
    406                     1 24 markdown-regex-bold 2 4)
    407                    (cons 1 8)))
    408     (should (string-equal (buffer-string) "a b c d **e** **f**"))))
    409 
    410 (ert-deftest test-markdown-insertion/unwrap-things-in-region-links ()
    411   "Test function `markdown-unwrap-things-in-region' on inline links."
    412   (markdown-test-string "a [link](http://jblevins.org/) or [two](/).\n"
    413     (should (equal (markdown-unwrap-things-in-region
    414                     (point-min) (point-max) markdown-regex-link-inline 0 3)
    415                    (cons 1 16)))
    416     (should (string-equal (buffer-string) "a link or two.\n"))))
    417 
    418 (ert-deftest test-markdown-insertion/toggle-bold ()
    419   "Test toggling functionality of `markdown-insert-bold'."
    420   (markdown-test-string "one **two** three"
    421     (forward-word 2)
    422     (markdown-insert-bold)
    423     (should (string-equal (buffer-string) "one two three"))
    424     (should (= (point) 8))
    425     (forward-word)
    426     (markdown-insert-bold)
    427     (should (= (point) 16))
    428     (should (string-equal (buffer-string) "one two **three**"))))
    429 
    430 (ert-deftest test-markdown-insertion/toggle-bold-consecutive ()
    431   "Test toggling functionality of consecutive bolds.
    432 Detail: https://github.com/jrblevin/markdown-mode/issues/283"
    433   (markdown-test-string "one **two** **three**"
    434     (search-forward "w")
    435     (markdown-insert-bold)
    436     (should (string-equal (buffer-string) "one two **three**"))))
    437 
    438 (ert-deftest test-markdown-insertion/toggle-italic ()
    439   "Test toggling functionality of `markdown-insert-italic'."
    440   (markdown-test-string "one *two* three"
    441     (forward-word 2)
    442     (markdown-insert-italic)
    443     (should (string-equal (buffer-string) "one two three"))
    444     (should (= (point) 8))
    445     (forward-word)
    446     (markdown-insert-italic)
    447     (should (string-equal (buffer-string) "one two *three*"))
    448     (should (= (point) 15))))
    449 
    450 (ert-deftest test-markdown-insertion/toggle-italic-consecutive ()
    451   "Test toggling functionality of consecutive italics.
    452 Detail: https://github.com/jrblevin/markdown-mode/issues/283"
    453   (markdown-test-string "one *two* *three*"
    454     (search-forward "w")
    455     (markdown-insert-italic)
    456     (should (string-equal (buffer-string) "one two *three*"))))
    457 
    458 (ert-deftest test-markdown-insertion/toggle-code ()
    459   "Test toggling functionality of `markdown-insert-code'."
    460   (markdown-test-string "one `two` three"
    461     (forward-word 2)
    462     (markdown-insert-code)
    463     (should (string-equal (buffer-string) "one two three"))
    464     (should (= (point) 8))
    465     (forward-word)
    466     (markdown-insert-code)
    467     (should (string-equal (buffer-string) "one two `three`"))
    468     (should (= (point) 15))))
    469 
    470 (ert-deftest test-markdown-insertion/toggle-kbd ()
    471   "Test toggling functionality of `markdown-insert-code'."
    472   (markdown-test-string "test <kbd>C-c C-s k</kbd> toggle"
    473     (forward-word 2)
    474     (markdown-insert-kbd)
    475     (should (string-equal (buffer-string) "test C-c C-s k toggle"))
    476     (should (= (point) 6))
    477     (backward-word)
    478     (markdown-insert-kbd)
    479     (should (string-equal (buffer-string) "<kbd>test</kbd> C-c C-s k toggle"))
    480     (should (= (point) 6))))
    481 
    482 (ert-deftest test-markdown-insertion/toggle-wiki-link-alias-first ()
    483   "Test toggling of `markdown-insert-wiki-link' with alias first.
    484 Test point position upon removal and insertion."
    485   (let ((markdown-wiki-link-alias-first t))
    486     (markdown-test-string "[[text|page]]"
    487       (goto-char 5) ; point in interior of alias text, at 'x'
    488       (call-interactively 'markdown-insert-wiki-link)
    489       (should (= (point) 3)) ; leave point at, at 'x'
    490       (should (string-equal (buffer-string) "text"))
    491       (call-interactively 'markdown-insert-wiki-link)
    492       (should (= (point) 5)) ; leave point at, at 'x'
    493       (should (string-equal (buffer-string) "[[text]]")))
    494     (markdown-test-string "[[text|page]]"
    495       (goto-char 10) ; point in interior of link text, at 'g'
    496       (call-interactively 'markdown-insert-wiki-link)
    497       (should (= (point) 5)) ; leave point at end of alias text
    498       (should (string-equal (buffer-string) "text"))
    499       (call-interactively 'markdown-insert-wiki-link)
    500       (should (= (point) 7)) ; leave point at end of alias text
    501       (should (string-equal (buffer-string) "[[text]]")))))
    502 
    503 (ert-deftest test-markdown-insertion/toggle-wiki-link-alias-last ()
    504   "Test toggling of `markdown-insert-wiki-link' with alias last.
    505 Test point position upon removal and insertion."
    506   (let ((markdown-wiki-link-alias-first nil))
    507     (markdown-test-string "[[page|text]]"
    508       (goto-char 10) ; point in interior of alias text, at 'x'
    509       (call-interactively 'markdown-insert-wiki-link)
    510       (goto-char 3) ; leave point at, at 'x'
    511       (should (string-equal (buffer-string) "text"))
    512       (call-interactively 'markdown-insert-wiki-link)
    513       (should (= (point) 5)) ; leave point at, at 'x'
    514       (should (string-equal (buffer-string) "[[text]]")))
    515     (markdown-test-string "[[page|text]]"
    516       (goto-char 3) ; point in interior of link text, at 'g'
    517       (call-interactively 'markdown-insert-wiki-link)
    518       (should (= (point) 1)) ; leave point at beginning of alias text
    519       (should (string-equal (buffer-string) "text"))
    520       (call-interactively 'markdown-insert-wiki-link)
    521       (should (= (point) 3)) ; leave point at beginning of alias text
    522       (should (string-equal (buffer-string) "[[text]]")))))
    523 
    524 (ert-deftest test-markdown-insertion/bold-region ()
    525   "Test region functionality of `markdown-insert-bold'."
    526   (markdown-test-string "one two three"
    527     (push-mark (point) t t)
    528     (forward-word 2)
    529     (markdown-insert-bold)
    530     (should (string-equal (buffer-string) "**one two** three"))
    531     (should (= (point) 10))))
    532 
    533 (ert-deftest test-markdown-insertion/bold-region-begin-with-space ()
    534   "Test region functionality of `markdown-insert-bold'.
    535 When region starts/ends with spaces"
    536   (markdown-test-string "  one two three"
    537     (push-mark (point) t t)
    538     (forward-word 2)
    539     (markdown-insert-bold)
    540     (should (string-equal (buffer-string) "  **one two** three")))
    541   (markdown-test-string "  one two  three"
    542     (push-mark (point) t t)
    543     (goto-char 11)
    544     (markdown-insert-bold)
    545     (should (string-equal (buffer-string) "  **one two**  three"))))
    546 
    547 (ert-deftest test-markdown-insertion/italic-region ()
    548   "Test region functionality of `markdown-insert-italic'."
    549   (markdown-test-string "one two three"
    550     (transient-mark-mode)
    551     (push-mark (point) t t)
    552     (forward-word 2)
    553     (markdown-insert-italic)
    554     (should (string-equal (buffer-string) "*one two* three"))
    555     (should (= (point) 9))))
    556 
    557 (ert-deftest test-markdown-insertion/italic-region-begin-with-space ()
    558   "Test region functionality of `markdown-insert-italic'.
    559 When region starts/ends with spaces"
    560   (markdown-test-string "  one two  three"
    561     (transient-mark-mode)
    562     (push-mark (point) t t)
    563     (goto-char 11)
    564     (markdown-insert-italic)
    565     (should (string-equal (buffer-string) "  *one two*  three"))))
    566 
    567 (ert-deftest test-markdown-insertion/code-region ()
    568   "Test region functionality of `markdown-insert-code'."
    569   (markdown-test-string "one two three"
    570     (transient-mark-mode)
    571     (push-mark (point) t t)
    572     (forward-word 2)
    573     (markdown-insert-code)
    574     (should (string-equal (buffer-string) "`one two` three"))
    575     (should (= (point) 9))))
    576 
    577 (ert-deftest test-markdown-insertion/kbd-region ()
    578   "Test region functionality of `markdown-insert-kbd'."
    579   (markdown-test-string "one two three"
    580     (transient-mark-mode)
    581     (push-mark (point) t t)
    582     (forward-word 2)
    583     (markdown-insert-kbd)
    584     (should (string-equal (buffer-string) "<kbd>one two</kbd> three"))
    585     (should (= (point) 13))))
    586 
    587 (ert-deftest test-markdown-insertion/atx-line ()
    588   "Test ATX header insertion without region."
    589   (markdown-test-string "line one\nline two\n"
    590     (forward-word)
    591     (markdown-insert-header-atx-1)
    592     (should (= (point) 11))
    593     (should (string-equal (buffer-substring (point-min) (point-max))
    594                           "# line one #\n\nline two\n"))
    595     (forward-line 2)
    596     (markdown-insert-header-atx-2)
    597     (should (= (point) 26))
    598     (should (string-equal (buffer-substring (point-min) (point-max))
    599                           "# line one #\n\n## line two ##\n\n"))))
    600 
    601 (ert-deftest test-markdown-insertion/atx-region ()
    602   "Test ATX header insertion with region."
    603   (markdown-test-string "line one\nline two\n"
    604     (transient-mark-mode)
    605     (forward-char 5)
    606     (push-mark (point) t t)
    607     (forward-word)
    608     (should (string-equal (buffer-substring (region-beginning) (region-end))
    609                           "one"))
    610     (markdown-insert-header-atx-4)
    611     (should (= (point) 16))
    612     (should (string-equal (buffer-substring (point-min) (point-max))
    613                           "line \n\n#### one ####\n\nline two\n"))))
    614 
    615 (ert-deftest test-markdown-insertion/atx-blank ()
    616   "Test ATX header insertion on blank line."
    617   (markdown-test-string "line one\n\nline two\n"
    618     (forward-line)
    619     (markdown-insert-header-atx-3)
    620     (should (string-equal (buffer-substring (point-min) (point-max))
    621                           "line one\n\n###  ###\n\nline two\n"))
    622     (should (= (point) 15))
    623     (should (looking-at " ###\n"))))
    624 
    625 (ert-deftest test-markdown-insertion/atx-region-whitespace ()
    626   "Test ATX header insertion using a region with whitespace."
    627   (markdown-test-string "  line one\n\nline two\n  \n"
    628     (transient-mark-mode)
    629     (push-mark (point) t t)
    630     (goto-char (point-max))
    631     (markdown-insert-header-atx-2)
    632     (should (string-equal (buffer-substring (point-min) (point-max))
    633                           "## line one line two ##"))
    634     (should (= (point) 21))
    635     (should (looking-at " ##"))))
    636 
    637 (ert-deftest test-markdown-insertion/atx-line-whitespace ()
    638   "Test ATX header insertion using current line with whitespace."
    639   (markdown-test-string "  line one  \n\nline two\n"
    640     (goto-char (line-end-position))
    641     (markdown-insert-header-atx-3)
    642     (should (string-equal (buffer-substring (point-min) (point-max))
    643                           "### line one ###\n\nline two\n"))
    644     (should (= (point) 13))
    645     (should (looking-at " ###\n"))))
    646 
    647 (ert-deftest test-markdown-insertion/atx-replace-atx ()
    648   "Test ATX header insertion when replacing an existing ATX header."
    649   (markdown-test-string "## replace ##\n"
    650     (markdown-insert-header-atx-4)
    651     (should (string-equal (buffer-string) "#### replace ####\n\n"))
    652     (should (looking-at " ####\n"))))
    653 
    654 (ert-deftest test-markdown-insertion/atx-replace-setext-1 ()
    655   "Test ATX header insertion when replacing an existing setext header."
    656   (markdown-test-string "replace\n=======\n"
    657     (markdown-insert-header-atx-2)
    658     (should (string-equal (buffer-string) "## replace ##\n\n"))
    659     (should (looking-at " ##\n"))))
    660 
    661 (ert-deftest test-markdown-insertion/atx-replace-setext-2 ()
    662   "Test ATX header insertion when replacing an existing setext header."
    663   (markdown-test-string "replace\n-------\n"
    664     (markdown-insert-header-atx-5)
    665     (should (string-equal (buffer-string) "##### replace #####\n\n"))
    666     (should (looking-at " #####\n"))))
    667 
    668 (ert-deftest test-markdown-insertion/atx-asymmetric-point ()
    669   "Test point after ATX header insertion with `markdown-asymmetric-header'."
    670   (markdown-test-string
    671       "Test"
    672     (let ((markdown-asymmetric-header t))
    673       (markdown-insert-header-atx-5)
    674       (should (= (point) 11))
    675       (should (string-equal (buffer-string) "##### Test")))))
    676 
    677 (ert-deftest test-markdown-insertion/setext-line ()
    678   "Test setext header insertion without region."
    679   (markdown-test-string "line one\nline two\n"
    680     (forward-word)
    681     (markdown-insert-header-setext-1)
    682     (should (string-equal (buffer-substring (point-min) (point-max))
    683                           "line one\n========\n\nline two\n"))
    684     (forward-line 3)
    685     (markdown-insert-header-setext-2)
    686     (should (string-equal (buffer-substring (point-min) (point-max))
    687                           "line one\n========\n\nline two\n--------\n\n"))))
    688 
    689 (ert-deftest test-markdown-insertion/setext-region ()
    690   "Test setext header insertion with region."
    691   (markdown-test-string "line one\nline two\n"
    692     (transient-mark-mode)
    693     (forward-char 5)
    694     (push-mark (point) t t)
    695     (forward-word)
    696     (should (string-equal (buffer-substring (region-beginning) (region-end))
    697                           "one"))
    698     (markdown-insert-header-setext-1)
    699     (should (string-equal (buffer-substring (point-min) (point-max))
    700                           "line \n\none\n===\n\nline two\n"))))
    701 
    702 (ert-deftest test-markdown-insertion/setext-blank ()
    703   "Test setext header insertion on blank line."
    704   (markdown-test-string "line one\n\nline two\n"
    705     (forward-line)
    706     (markdown-insert-header 2 "foo" t)
    707     (should (string-equal (buffer-substring (point-min) (point-max))
    708                           "line one\n\nfoo\n---\n\nline two\n"))
    709     (should (= (point) 14))
    710     (should (looking-at "\n---"))))
    711 
    712 (ert-deftest test-markdown-insertion/setext-region-whitespace ()
    713   "Test setext header insertion using a region with whitespace."
    714   (markdown-test-string "  line one\n\nline two\n  \n"
    715     (transient-mark-mode)
    716     (push-mark (point) t t)
    717     (goto-char (point-max))
    718     (markdown-insert-header-setext-1)
    719     (should (string-equal (buffer-substring (point-min) (point-max))
    720                           "line one line two\n================="))
    721     (should (= (point) 18))
    722     (should (looking-at "\n===="))))
    723 
    724 (ert-deftest test-markdown-insertion/setext-line-whitespace ()
    725   "Test setext header insertion using current line with whitespace."
    726   (markdown-test-string "  line one  \n\nline two\n"
    727     (goto-char (line-end-position))
    728     (markdown-insert-header-setext-2)
    729     (should (string-equal (buffer-substring (point-min) (point-max))
    730                           "line one\n--------\n\nline two\n"))
    731     (should (= (point) 9))
    732     (should (looking-at "\n---"))))
    733 
    734 (ert-deftest test-markdown-insertion/setext-replace-atx ()
    735   "Test setext header insertion when replacing an existing ATX header."
    736   (markdown-test-string "## replace ##\n"
    737     (markdown-insert-header-setext-1)
    738     (should (string-equal (buffer-string) "replace\n=======\n\n"))
    739     (should (looking-at "\n==="))))
    740 
    741 (ert-deftest test-markdown-insertion/setext-replace-setext-1 ()
    742   "Test setext header insertion when replacing an existing setext title."
    743   (markdown-test-string "replace\n=======\n"
    744     (markdown-insert-header-setext-2)
    745     (should (string-equal (buffer-string) "replace\n-------\n\n"))
    746     (should (looking-at "\n---"))))
    747 
    748 (ert-deftest test-markdown-insertion/setext-replace-setext-2 ()
    749   "Test setext header insertion when replacing an existing setext section."
    750   (markdown-test-string "replace\n-------\n"
    751     (markdown-insert-header-setext-1)
    752     (should (string-equal (buffer-string) "replace\n=======\n\n"))
    753     (should (looking-at "\n==="))))
    754 
    755 (ert-deftest test-markdown-insertion/header-dwim ()
    756   "Test 'do what I mean' header insertion."
    757   (markdown-test-file "outline.text"
    758     (call-interactively 'markdown-insert-header-dwim)
    759     (should (looking-at " #$"))
    760     (end-of-defun 2)
    761     (call-interactively 'markdown-insert-header-dwim)
    762     (beginning-of-line)
    763     (should (looking-at "^#  #$"))
    764     (end-of-defun 3)
    765     (call-interactively 'markdown-insert-header-dwim)
    766     (beginning-of-line)
    767     (should (looking-at "^###  ###$"))))
    768 
    769 (ert-deftest test-markdown-insertion/header-dwim-prefix ()
    770   "Test 'do what I mean' header insertion with prefix arguments."
    771   (let ((tests (list '(nil . "## abc ##")
    772                      '(1 . "# abc #")
    773                      '(2 . "## abc ##")
    774                      '(3 . "### abc ###")
    775                      '(4 . "#### abc ####")
    776                      '(5 . "##### abc #####")
    777                      '(6 . "###### abc ######")
    778                      '((4) . "# abc #")
    779                      '((16) . "### abc ###"))))
    780     (dolist (test tests)
    781       (markdown-test-string "## atx\n\nabc"
    782         (goto-char (point-max))
    783         (let ((current-prefix-arg (car test)))
    784           (call-interactively 'markdown-insert-header-dwim)
    785           (should (string-equal
    786                    (buffer-substring (line-beginning-position) (line-end-position))
    787                    (cdr test))))))))
    788 
    789 (ert-deftest test-markdown-insertion/header-setext-dwim-prefix ()
    790   "Test 'do what I mean' header insertion with prefix arguments."
    791   (let ((tests (list '(nil . "abc\n---")
    792                      '(1 . "abc\n===")
    793                      '(2 . "abc\n---")
    794                      '(3 . "### abc ###")
    795                      '(4 . "#### abc ####")
    796                      '(5 . "##### abc #####")
    797                      '(6 . "###### abc ######")
    798                      '((4) . "abc\n===")
    799                      '((16) . "### abc ###"))))
    800     (dolist (test tests)
    801       (markdown-test-string "atx\n---\n\nabc"
    802         (goto-char (point-max))
    803         (let ((current-prefix-arg (car test)))
    804           (call-interactively 'markdown-insert-header-setext-dwim)
    805           (should (string-equal
    806                    (buffer-substring (line-beginning-position) (line-end-position 2))
    807                    (cdr test))))))))
    808 
    809 (ert-deftest test-markdown-insertion/header-setext-dwim ()
    810   "Test 'do what I mean' header insertion with setext headers."
    811   (markdown-test-string
    812       "asdfasfasfdsadfasdfasdf\n======="
    813     (goto-char 12)
    814     (call-interactively 'markdown-insert-header-dwim)
    815     (should (string-equal
    816              (buffer-string)
    817              "asdfasfasfdsadfasdfasdf\n======================="))))
    818 
    819 (ert-deftest test-markdown-insertion/remove-header ()
    820   "Test ATX and setext header."
    821   (markdown-test-string
    822       "# atx1\n\n## atx2 ##\n\nsetext1\n=======\n\nsetext2\n-------\n"
    823     (should (equal (markdown-remove-header) (cons 1 5)))
    824     (forward-line)
    825     (should (not (markdown-remove-header)))
    826     (forward-line)
    827     (should (equal (markdown-remove-header) (cons 7 11)))
    828     (forward-line)
    829     (should (not (markdown-remove-header)))
    830     (forward-line)
    831     (should (equal (markdown-remove-header) (cons 13 20)))
    832     (forward-line)
    833     (should (not (markdown-remove-header)))
    834     (forward-line)
    835     (should (equal (markdown-remove-header) (cons 22 29)))
    836     (should (string-equal (buffer-string)
    837                           "atx1\n\natx2\n\nsetext1\n\nsetext2\n"))))
    838 
    839 (ert-deftest test-markdown-insertion/italic-unwrap-region ()
    840   "A test of inserting italics with italic text in the region."
    841   (markdown-test-string "*foo* bar *baz*"
    842     (transient-mark-mode)
    843     (push-mark (point) t t)
    844     (end-of-line)
    845     (markdown-insert-italic)
    846     (should (string-equal (buffer-string) "*foo bar baz*"))))
    847 
    848 (ert-deftest test-markdown-insertion/bold-unwrap-region ()
    849   "A test of inserting bold with italic text in the region."
    850   (markdown-test-string "*foo* **bar** *baz*"
    851     (transient-mark-mode)
    852     (push-mark (point) t t)
    853     (end-of-line)
    854     (markdown-insert-bold)
    855     (should (string-equal (buffer-string) "***foo* bar *baz***"))))
    856 
    857 (ert-deftest test-markdown-insertion/code-unwrap-region ()
    858   "A test of inserting code with code already in the region."
    859   (markdown-test-string "`foo` *bar* `baz`"
    860     (transient-mark-mode)
    861     (push-mark (point) t t)
    862     (end-of-line)
    863     (markdown-insert-code)
    864     (should (string-equal (buffer-string) "`foo *bar* baz`"))))
    865 
    866 (ert-deftest test-markdown-insertion/hr-order ()
    867   "Test inserting horizontal rules."
    868   (dotimes (n (length markdown-hr-strings))
    869     (markdown-test-string ""
    870       (let ((current-prefix-arg n))
    871         (call-interactively 'markdown-insert-hr))
    872       (should (string-equal (buffer-string) (nth (1- n) markdown-hr-strings))))))
    873 
    874 (ert-deftest test-markdown-insertion/hr-prefix ()
    875   "Test inserting horizontal rule with C-u prefix."
    876   (markdown-test-string ""
    877     (let ((current-prefix-arg '(4)))
    878       (call-interactively 'markdown-insert-hr))
    879     (should (string-equal (buffer-string) (car (last markdown-hr-strings))))))
    880 
    881 (ert-deftest test-markdown-insertion/hr-bob ()
    882   "Test inserting horizontal rule at beginning of buffer."
    883   (markdown-test-string "one line\n"
    884     (call-interactively 'markdown-insert-hr)
    885     (should (string-equal (buffer-string)
    886                           (concat (car markdown-hr-strings)
    887                                   "\n\none line\n")))))
    888 
    889 (ert-deftest test-markdown-insertion/hr-eob ()
    890   "Test inserting horizontal rule at end of buffer."
    891   (markdown-test-string "one line\n"
    892     (forward-line)
    893     (call-interactively 'markdown-insert-hr)
    894     (should (string-equal (buffer-string)
    895                           (concat "one line\n\n" (car markdown-hr-strings))))))
    896 
    897 (ert-deftest test-markdown-insertion/hr-mob ()
    898   "Test inserting horizontal rule in middle of buffer."
    899   (markdown-test-string "one line\n"
    900     (forward-word)
    901     (let ((markdown-hr-strings '("----------")))
    902       (call-interactively 'markdown-insert-hr)
    903       (should (string-equal (buffer-string)
    904                             (concat "one\n\n" (car markdown-hr-strings)
    905                                     "\n\n line\n"))))))
    906 
    907 (ert-deftest test-markdown-insertion/pre-region-1 ()
    908   "Test `markdown-pre-region'."
    909   ;; Simple test as non-interactive command
    910   (markdown-test-string "line one\nline two\n"
    911     (markdown-pre-region (line-beginning-position) (line-end-position))
    912     (should (string-equal (buffer-string) "    line one\n\nline two\n")))
    913   ;; Test removal of whitespace before and after region
    914   (markdown-test-string "line one abc\nline two\n"
    915     (markdown-pre-region 6 9)
    916     (should (string-equal (buffer-string) "line\n\n    one\n\nabc\nline two\n")))
    917   ;; Simple test as interactive command
    918   (markdown-test-string "line one\nline two\n"
    919     (push-mark (point) t t)
    920     (forward-line 2)
    921     (call-interactively 'markdown-pre-region)
    922     (should (string-equal (buffer-string) "    line one\n    line two\n\n"))))
    923 
    924 (ert-deftest test-markdown-insertion/blockquote-region-1 ()
    925   "Test `markdown-blockquote-region'."
    926   ;; Simple test as non-interactive command
    927   (markdown-test-string "line one\nline two\n"
    928     (markdown-blockquote-region (line-beginning-position) (line-end-position))
    929     (should (string-equal (buffer-string) "> line one\n\nline two\n")))
    930   ;; Test removal of whitespace before and after region
    931   (markdown-test-string "line one abc\nline two\n"
    932     (markdown-blockquote-region 6 9)
    933     (should (string-equal (buffer-string) "line\n\n> one\n\nabc\nline two\n")))
    934   ;; Simple test as interactive command
    935   (markdown-test-string "line one\nline two\n"
    936     (push-mark (point) t t)
    937     (forward-line 2)
    938     (call-interactively 'markdown-blockquote-region)
    939     (should (string-equal (buffer-string) "> line one\n> line two\n\n"))))
    940 
    941 (ert-deftest test-markdown-insertion/pre-nested-lists ()
    942   "Test `markdown-pre-indentation' and `markdown-insert-pre' with nested list."
    943   (markdown-test-string "* item\n    * item\n"
    944     ;; before the first item
    945     (should (string-equal (markdown-pre-indentation (point)) "    "))
    946     (markdown-insert-pre)
    947     (beginning-of-line)
    948     (should (markdown-prev-line-blank-p))
    949     (should (looking-at "^    $"))
    950     (should (markdown-next-line-blank-p))
    951     ;; before the second item
    952     (forward-line 3)
    953     (should (string-equal (markdown-pre-indentation (point)) "        "))
    954     (markdown-insert-pre)
    955     (beginning-of-line)
    956     (should (markdown-prev-line-blank-p))
    957     (should (looking-at "^        $"))
    958     (should (markdown-next-line-blank-p))
    959     ;; after the second item
    960     (forward-line 3)
    961     (should (string-equal (markdown-pre-indentation (point)) "            "))
    962     (markdown-insert-pre)
    963     (beginning-of-line)
    964     (should (markdown-prev-line-blank-p))
    965     (should (looking-at "^            $"))
    966     (should (markdown-next-line-blank-p))))
    967 
    968 (ert-deftest test-markdown-insertion/pre-faux-list ()
    969   "Test `markdown-pre-indentation' following a list-marker in a pre block."
    970   (markdown-test-string "    * pre block, not a list item\n"
    971     (should (string-equal (markdown-pre-indentation (point-max)) "    "))))
    972 
    973 (ert-deftest test-markdown-insertion/blockquote-nested-lists ()
    974   "Test blockquote insertion in a nested list context."
    975   (markdown-test-string "* item\n    * item\n"
    976     ;; before the first item
    977     (should (string-equal (markdown-blockquote-indentation (point)) ""))
    978     (markdown-insert-blockquote)
    979     (beginning-of-line)
    980     (should (markdown-prev-line-blank-p))
    981     (should (looking-at "^> $"))
    982     (should (markdown-next-line-blank-p))
    983     ;; before the second item
    984     (forward-line 3)
    985     (should (string-equal (markdown-blockquote-indentation (point)) "    "))
    986     (markdown-insert-blockquote)
    987     (beginning-of-line)
    988     (should (markdown-prev-line-blank-p))
    989     (should (looking-at "^    > $"))
    990     (should (markdown-next-line-blank-p))
    991     ;; after the second item
    992     (forward-line 3)
    993     (should (string-equal (markdown-blockquote-indentation (point)) "        "))
    994     (markdown-insert-blockquote)
    995     (beginning-of-line)
    996     (should (markdown-prev-line-blank-p))
    997     (should (looking-at "^        > $"))
    998     (should (markdown-next-line-blank-p))))
    999 
   1000 (ert-deftest test-markdown-insertion/blockquote-region-with-newline ()
   1001   (markdown-test-string "a\n\nb\n"
   1002     (markdown-blockquote-region 1 (point-max))
   1003     (should (equal (buffer-string) "> a\n>\n> b\n\n"))))
   1004 
   1005 (ert-deftest test-markdown-insertion/empty-italic ()
   1006   "Test `markdown-insert-italic' with no word at point and no region."
   1007   (markdown-test-string ""
   1008     (call-interactively 'markdown-insert-italic)
   1009     (should (string-equal (buffer-string) "**"))
   1010     (should (= (point) 2))))
   1011 
   1012 (ert-deftest test-markdown-insertion/empty-bold ()
   1013   "Test `markdown-insert-bold' with no word at point and no region."
   1014   (markdown-test-string ""
   1015     (call-interactively 'markdown-insert-bold)
   1016     (should (string-equal (buffer-string) "****"))
   1017     (should (= (point) 3))))
   1018 
   1019 (ert-deftest test-markdown-insertion/uri ()
   1020   "Test `markdown-insert-uri'."
   1021   (markdown-test-string "http://jblevins.org/projects/markdown-mode/"
   1022     (call-interactively 'markdown-insert-uri)
   1023     (should (string-equal (buffer-string) "<http://jblevins.org/projects/markdown-mode/>"))
   1024     (should (= (point) 2))
   1025     (call-interactively 'markdown-insert-uri)
   1026     (should (string-equal (buffer-string) "http://jblevins.org/projects/markdown-mode/"))
   1027     (should (= (point) 1))
   1028     (erase-buffer)
   1029     (call-interactively 'markdown-insert-uri)
   1030     (should (string-equal (buffer-string) "<>"))
   1031     (should (= (point) 2))))
   1032 
   1033 (ert-deftest test-markdown-insertion/list-item-1 ()
   1034   "Test `markdown-insert-list-item' when there is no existing list."
   1035   (markdown-test-string "abc"
   1036     (goto-char (point-max))
   1037     (call-interactively 'markdown-insert-list-item)
   1038     (should (string-equal (buffer-string) "abc\n  * "))
   1039     (should (= (point) 9))))
   1040 
   1041 (ert-deftest test-markdown-insertion/list-item-2 ()
   1042   "Test `markdown-insert-list-item' following a list item, on the same line."
   1043   (markdown-test-string "  * foo"
   1044     (goto-char (point-max))
   1045     (call-interactively 'markdown-insert-list-item)
   1046     (should (string-equal (buffer-string) "  * foo\n  * "))))
   1047 
   1048 (ert-deftest test-markdown-insertion/list-item-3 ()
   1049   "Test `markdown-insert-list-item' following a list item, on the next line."
   1050   (markdown-test-string "- foo\n"
   1051     (goto-char (point-max))
   1052     (call-interactively 'markdown-insert-list-item)
   1053     (should (string-equal (buffer-string) "- foo\n- "))))
   1054 
   1055 (ert-deftest test-markdown-insertion/list-item-4 ()
   1056   "Test `markdown-insert-list-item' following a list item, after a blank line."
   1057   (markdown-test-string "- foo\n\n"
   1058     (goto-char (point-max))
   1059     (call-interactively 'markdown-insert-list-item)
   1060     (should (string-equal (buffer-string) "- foo\n\n- "))))
   1061 
   1062 (ert-deftest test-markdown-insertion/list-item-5 ()
   1063   "Test `markdown-insert-list-item' preceding a list item."
   1064   (markdown-test-string "- foo\n"
   1065     (goto-char (point-min))
   1066     (call-interactively 'markdown-insert-list-item)
   1067     (should (string-equal (buffer-string) "- \n- foo\n"))))
   1068 
   1069 (ert-deftest test-markdown-insertion/list-item-6 ()
   1070   "Test `markdown-insert-list-item' preceding a list item and a blank line."
   1071   (markdown-test-string "\n\n- foo\n"
   1072     (goto-char (point-min))
   1073     (call-interactively 'markdown-insert-list-item)
   1074     (should (string-equal (buffer-string) "- \n\n- foo\n"))))
   1075 
   1076 (ert-deftest test-markdown-insertion/list-item-7 ()
   1077   "Test `markdown-insert-list-item' in the middle of a list item."
   1078   (markdown-test-string "- foo bar\n"
   1079     (forward-word)
   1080     (call-interactively 'markdown-insert-list-item)
   1081     (should (string-equal (buffer-string) "- foo\n-  bar\n"))))
   1082 
   1083 (ert-deftest test-markdown-insertion/list-item-8 ()
   1084   "Test `markdown-insert-list-item' before marker, not at beginning of line."
   1085   (markdown-test-string "   - foo\n"
   1086     (forward-char 2)
   1087     (call-interactively 'markdown-insert-list-item)
   1088     (should (string-equal (buffer-string) "   - \n   - foo\n"))))
   1089 
   1090 (ert-deftest test-markdown-insertion/list-item-9 ()
   1091   "Test `markdown-insert-list-item' following an ordered list item."
   1092   (markdown-test-string "6. foo"
   1093     (goto-char (point-max))
   1094     (call-interactively 'markdown-insert-list-item)
   1095     (should (string-equal (buffer-string) "6. foo\n7. "))))
   1096 
   1097 (ert-deftest test-markdown-insertion/list-item-10 ()
   1098   "Test `markdown-insert-list-item' after fancy list item, on the next line."
   1099   (markdown-test-string "#. foo"
   1100     (goto-char (point-max))
   1101     (call-interactively 'markdown-insert-list-item)
   1102     (should (string-equal (buffer-string) "#. foo\n#. "))))
   1103 
   1104 (ert-deftest test-markdown-insertion/list-item-11 ()
   1105   "Test `markdown-insert-list-item' following a nested ordered list item."
   1106   (markdown-test-string "6. foo\n    1. bar"
   1107     (goto-char (point-max))
   1108     (call-interactively 'markdown-insert-list-item)
   1109     (should (string-equal (buffer-string) "6. foo\n    1. bar\n    2. "))))
   1110 
   1111 (ert-deftest test-markdown-insertion/list-item-12 ()
   1112   "Test `markdown-insert-list-item' preceding an ordered list item."
   1113   (markdown-test-string "\n1. foo\n2. bar"
   1114     (goto-char (point-min))
   1115     (call-interactively 'markdown-insert-list-item)
   1116     (should (string-equal (buffer-string) "1. \n1. foo\n2. bar"))))
   1117 
   1118 (ert-deftest test-markdown-insertion/list-item-13 ()
   1119   "Test `markdown-insert-list-item' preserves previous spacing in ordered list."
   1120   (markdown-test-string "1.        foo"
   1121     (goto-char (point-max))
   1122     (call-interactively 'markdown-insert-list-item)
   1123     (should (string-equal (buffer-string)  "1.        foo\n2.        "))))
   1124 
   1125 (ert-deftest test-markdown-insertion/list-item-14 ()
   1126   "Test `markdown-insert-list-item' adjusts spacing for number width changes.
   1127 For example, 9 to 10."
   1128   (markdown-test-string "9.  foo"
   1129     (goto-char (point-max))
   1130     (call-interactively 'markdown-insert-list-item)
   1131     (should (string-equal (buffer-string)  "9.  foo\n10. "))))
   1132 
   1133 (ert-deftest test-markdown-insertion/list-item-15 ()
   1134   "Test `markdown-insert-list-item' don't adjust for number width
   1135 changes if no extra whitespace."
   1136   (markdown-test-string "99. foo"
   1137     (goto-char (point-max))
   1138     (call-interactively 'markdown-insert-list-item)
   1139     (should (string-equal (buffer-string)  "99. foo\n100. "))))
   1140 
   1141 (ert-deftest test-markdown-insertion/list-item-16 ()
   1142   "Test that `markdown-insert-list-item' spacing.
   1143 Don't adjust spacing if tabs are used as whitespace."
   1144   (markdown-test-string "9.\tfoo"
   1145     (goto-char (point-max))
   1146     (call-interactively 'markdown-insert-list-item)
   1147     (should (string-equal (buffer-string)  "9.\tfoo\n10.\t"))))
   1148 
   1149 (ert-deftest test-markdown-insertion/list-item-bound-keys ()
   1150   "Test that `markdown-insert-list-item' is bound to M-RET and equivalents."
   1151   (markdown-test-string "- foo"
   1152     (goto-char (point-max))
   1153     (execute-kbd-macro (read-kbd-macro "M-RET bar C-M-m baz"))
   1154     (should (string-equal (buffer-string) "- foo\n- bar\n- baz"))
   1155     (when (display-graphic-p)
   1156       (execute-kbd-macro (read-kbd-macro "M-<return> quux"))
   1157       (should (string-equal (buffer-string) "- foo\n- bar\n- baz\n- quux")))))
   1158 
   1159 (ert-deftest test-markdown-insertion/nested-list-marker ()
   1160   "Test marker detection for `markdown-insert-list-item'."
   1161   (markdown-test-string
   1162       "1. A\n    * AA\n        1. AAA"
   1163     (goto-char (point-max))
   1164     (let ((current-prefix-arg '(4)))
   1165       (call-interactively 'markdown-insert-list-item))
   1166     (should (eq (point) 36))
   1167     (should (looking-back "\* "))
   1168     (should (string-equal
   1169              (buffer-string)
   1170              "1. A\n    * AA\n        1. AAA\n    * "))
   1171     (let ((current-prefix-arg '(4)))
   1172       (call-interactively 'markdown-insert-list-item))
   1173     (should (eq (point) 40))
   1174     (should (looking-back "2\. "))
   1175     (should (string-equal
   1176              (buffer-string)
   1177              "1. A\n    * AA\n        1. AAA\n    * \n2. "))
   1178     (let ((current-prefix-arg '(4)))
   1179       (call-interactively 'markdown-insert-list-item))
   1180     (should (eq (point) 44))
   1181     (should (looking-back "3\. "))
   1182     (should (string-equal
   1183              (buffer-string)
   1184              "1. A\n    * AA\n        1. AAA\n    * \n2. \n3. "))))
   1185 
   1186 (ert-deftest test-markdown-insertion/with-markdown-ordered-list-enumeration ()
   1187   "Test for `markdown-ordered-list-enumeration'.
   1188 Detail: https://github.com/jrblevin/markdown-mode/issues"
   1189   (markdown-test-string "1. A"
   1190     (goto-char (point-max))
   1191     (let ((markdown-ordered-list-enumeration t))
   1192       (call-interactively 'markdown-insert-list-item)
   1193       (let ((line (buffer-substring-no-properties
   1194                    (line-beginning-position) (line-end-position))))
   1195         (should (string= line "2. "))))
   1196 
   1197     (markdown-test-string "1. A"
   1198       (goto-char (point-max))
   1199       (let ((markdown-ordered-list-enumeration nil))
   1200         (call-interactively 'markdown-insert-list-item)
   1201         (let ((line (buffer-substring-no-properties
   1202                      (line-beginning-position) (line-end-position))))
   1203           (should (string= line "1. ")))))))
   1204 
   1205 (ert-deftest test-markdown-insertion/reference-link ()
   1206   "Basic tests for `markdown-insert-reference-link'."
   1207   ;; Test optional parameters (leave point after link)
   1208   (markdown-test-string ""
   1209     (markdown-insert-reference-link "abc" "1")
   1210     (should (string-equal (buffer-string) "[abc][1]"))
   1211     (should (= (point) 9)))
   1212   ;; Full link without title (leave point after link)
   1213   (markdown-test-string ""
   1214     (markdown-insert-reference-link "link" "label" "http://jblevins.org/")
   1215     (should (string-equal (buffer-string) "[link][label]\n\n[label]: http://jblevins.org/\n"))
   1216     (should (= (point) 14)))
   1217   ;; Full link without label or title (leave point after link)
   1218   (markdown-test-string ""
   1219     (markdown-insert-reference-link "link" "" "http://jblevins.org/")
   1220     (should (string-equal (buffer-string) "[link][]\n\n[link]: http://jblevins.org/\n"))
   1221     (should (= (point) 9)))
   1222   ;; Link only with no label, URL, or title (leave point after link)
   1223   (markdown-test-string ""
   1224     (markdown-insert-reference-link "link" "")
   1225     (should (string-equal (buffer-string) "[link][]"))
   1226     (should (= (point) 9))))
   1227 
   1228 (ert-deftest test-markdown-insertion/reference-link-end ()
   1229   "Basic reference link insertion test for 'end location."
   1230   (let ((markdown-reference-location 'end))
   1231     (markdown-test-string "first para\n\nsecond para\n"
   1232       (end-of-line)
   1233       (markdown-insert-reference-link "link" "" "http://jblevins.org/")
   1234       (should (= (point) 19))
   1235       (goto-char (point-min))
   1236       (forward-line 4)
   1237       (should (looking-at "\\[link\\]: http://jblevins.org/")))))
   1238 
   1239 (ert-deftest test-markdown-insertion/reference-link-immediately ()
   1240   "Basic reference link insertion test for 'immediately location."
   1241   (let ((markdown-reference-location 'immediately))
   1242     (markdown-test-string "first para\n\nsecond para\n"
   1243       (end-of-line)
   1244       (markdown-insert-reference-link "link" "" "http://jblevins.org/")
   1245       (should (= (point) 19))
   1246       (goto-char (point-min))
   1247       (forward-line 2)
   1248       (should (looking-at "\\[link\\]: http://jblevins.org/")))))
   1249 
   1250 (ert-deftest test-markdown-insertion/reference-link-header ()
   1251   "Basic reference link and definition insertion test for 'header location."
   1252   (let ((markdown-reference-location 'header))
   1253     (markdown-test-string "par one\n\npar two\n\n### header\n"
   1254       (end-of-line)
   1255       (markdown-insert-reference-link "link" "")
   1256       (markdown-insert-reference-definition "link")
   1257       (should (= (point) 35))
   1258       (should (looking-back "\\[link\\]: " nil)))))
   1259 
   1260 (ert-deftest test-markdown-insertion/reference-definition-block ()
   1261   "Test whitespace when inserting a reference definition among others"
   1262   (let ((markdown-reference-location 'header))
   1263     (markdown-test-string "text
   1264 
   1265 [1]: https://www.gnu.org/
   1266 
   1267 ### header
   1268 "
   1269       (markdown-insert-reference-definition "2")
   1270       (should (= (point) 38))
   1271       (should (looking-back "https://www.gnu.org/\n\\[2\\]: " nil)))))
   1272 
   1273 (ert-deftest test-markdown-insertion/reference-link-before-file-locals ()
   1274   "Test inserting a reference link before file-local variables."
   1275   (markdown-test-string "
   1276 
   1277 <!-- Local Variables: -->
   1278 <!-- mode: markdown -->
   1279 <!-- End: -->
   1280 "
   1281     (markdown-insert-reference-link "link" "" "http://jblevins.org/")
   1282     (should (equal (buffer-substring-no-properties 1 (point-max))
   1283                    "[link][]
   1284 
   1285 \[link]: http://jblevins.org/
   1286 
   1287 <!-- Local Variables: -->
   1288 <!-- mode: markdown -->
   1289 <!-- End: -->
   1290 "))
   1291     (should (equal (point) 9))))
   1292 
   1293 (ert-deftest test-markdown-insertion/inline-to-reference-link ()
   1294   "Inline link to reference link conversion with tab completion."
   1295   (markdown-test-string "[text](http://jblevins.org/ \"title\")"
   1296     (execute-kbd-macro (read-kbd-macro "M-x markdown-insert-link RET M-DEL M-DEL M-DEL [1] RET RET h TAB RET RET"))
   1297     (should (string-equal (buffer-string) "[text][1]\n\n[1]: http://jblevins.org/ \"title\"\n"))))
   1298 
   1299 (ert-deftest test-markdown-insertion/inline-to-reference-link-2 ()
   1300   "Inline link to reference link conversion with existing reference links."
   1301   (markdown-test-string "[text](http://jblevins.org/ \"title\")\n\n[1]: https://www.gnu.org"
   1302     (execute-kbd-macro (read-kbd-macro "M-x markdown-insert-link RET M-DEL M-DEL M-DEL [1] RET RET"))
   1303     (should (string-equal (buffer-string) "[text][1]\n\n[1]: https://www.gnu.org"))))
   1304 
   1305 (ert-deftest test-markdown-insertion/inline-link-angle-url-at-point ()
   1306   "Test `markdown-insert-link' with angle URL at point."
   1307   (markdown-test-string "<https://www.gnu.org/>"
   1308     (execute-kbd-macro (read-kbd-macro "M-x markdown-insert-link RET RET GNU RET RET"))
   1309     (should (string-equal (buffer-string) "[GNU](https://www.gnu.org/)"))))
   1310 
   1311 (ert-deftest test-markdown-insertion/inline-link-plain-url-at-point ()
   1312   "Test `markdown-insert-link' with plain URL at point."
   1313   (markdown-test-string "https://www.gnu.org/"
   1314     (execute-kbd-macro (read-kbd-macro "M-x markdown-insert-link RET RET GNU RET RET"))
   1315     (should (string-equal (buffer-string) "[GNU](https://www.gnu.org/)"))))
   1316 
   1317 (ert-deftest test-markdown-insertion/inline-link-reference-link-at-point ()
   1318   "Test `markdown-insert-link' with reference link at point."
   1319   (markdown-test-string ""
   1320     (markdown-insert-reference-link "link" "label" "http://jblevins.org/")
   1321     (execute-kbd-macro (read-kbd-macro "M-x markdown-insert-link RET DEL DEL DEL DEL DEL DEL DEL http://example.com/ RET RET RET"))
   1322     (should (string-equal (buffer-substring 1 28) "[link](http://example.com/)"))
   1323     (should (= (point) 28))))
   1324 
   1325 (ert-deftest test-markdown-insertion/inline-link-active-region ()
   1326   "Test `markdown-insert-link' with active region."
   1327   (markdown-test-string "abc def ghi"
   1328     (let ((tmm-orig transient-mark-mode))
   1329       (transient-mark-mode 1)
   1330       (push-mark (point) t t)
   1331       (forward-word 2)
   1332       (execute-kbd-macro (read-kbd-macro "M-x markdown-insert-link RET http://example.com/ RET RET RET"))
   1333       (should (string-equal (buffer-string) "[abc def](http://example.com/) ghi"))
   1334       (should (= (point) 31))
   1335       (transient-mark-mode tmm-orig))))
   1336 
   1337 (ert-deftest test-markdown-insertion/disable-tooltip-prompt ()
   1338   "Test `markdown-insert-link' with
   1339 `markdown-disable-tooltip-prompt' option t."
   1340   (markdown-test-string "<https://www.gnu.org/>"
   1341     (let ((markdown-disable-tooltip-prompt t))
   1342       (execute-kbd-macro (read-kbd-macro "M-x markdown-insert-link RET RET GNU RET"))
   1343       (should (string-equal (buffer-string) "[GNU](https://www.gnu.org/)")))))
   1344 
   1345 (ert-deftest test-markdown-insertion/link-make-text-function ()
   1346   "Test `markdown-insert-link' with custom
   1347 `markdown-link-make-text-function'."
   1348   (markdown-test-string "<https://www.gnu.org/>"
   1349     (let ((markdown-link-make-text-function (lambda (url) (ignore url) "GNU")))
   1350       (execute-kbd-macro (read-kbd-macro "M-x markdown-insert-link RET RET RET RET"))
   1351       (should (string-equal (buffer-string) "[GNU](https://www.gnu.org/)")))))
   1352 
   1353 (ert-deftest test-markdown-insertion/foldable-block ()
   1354   "Test `markdown-insert-foldable-block'."
   1355   (markdown-test-string ""
   1356     (call-interactively 'markdown-insert-foldable-block)
   1357     (should (string= (buffer-string) "<details>\n<summary> </summary>\n</details>"))
   1358     (should (looking-back "<summary>")))
   1359 
   1360   (markdown-test-string "foo"
   1361     (push-mark (point) t t)
   1362     (end-of-line)
   1363     (should (use-region-p))
   1364     (call-interactively 'markdown-insert-foldable-block)
   1365     (should (string= (buffer-string) "<details>\n<summary> </summary>\nfoo\n</details>"))
   1366     (should (looking-back "<summary>"))))
   1367 
   1368 ;;; Footnote tests:
   1369 
   1370 (ert-deftest test-markdown-footnote/basic-end ()
   1371   "Basic footnote insertion and deletion tests for 'end location."
   1372   (let ((markdown-footnote-location 'end))
   1373     (markdown-test-string "first line\nsecond line\n"
   1374       ;; new buffer with no footnotes
   1375       (should (= markdown-footnote-counter 0))
   1376       ;; footnote insertion
   1377       (end-of-line)
   1378       (markdown-insert-footnote)
   1379       (should (= (point) 35))
   1380       (should (= markdown-footnote-counter 1))
   1381       (should (looking-back "\\[^1\\]: " nil))
   1382       ;; kill with point in footnote definition
   1383       (insert "footnote text")
   1384       (let (kill-ring)
   1385         (markdown-footnote-kill))
   1386       (should (= (point) 24))
   1387       (should (bolp))
   1388       (should (string-equal (buffer-string) "first line\nsecond line\n"))
   1389       ;; insertion, counter should increment
   1390       (goto-char (point-min))
   1391       (end-of-line)
   1392       (markdown-insert-footnote)
   1393       (should (= (point) 35))
   1394       (should (= markdown-footnote-counter 2))
   1395       (should (looking-back "\\[^2\\]: " nil))
   1396       (insert "footnote text")
   1397       ;; return to marker
   1398       (markdown-footnote-return)
   1399       (should (= (point) 15))
   1400       (should (looking-back "\\[^2\\]" nil))
   1401       ;; kill with point at marker
   1402       (let (kill-ring)
   1403         (markdown-footnote-kill))
   1404       (should (= (point) 11))
   1405       (should (eolp))
   1406       (should (string-equal (buffer-string) "first line\nsecond line\n")))))
   1407 
   1408 (ert-deftest test-markdown-footnote/basic-immediately ()
   1409   "Basic footnote insertion and deletion tests for 'immediately location."
   1410   (let ((markdown-footnote-location 'immediately))
   1411     (markdown-test-string "first paragraph\n\nsecond paragraph\n"
   1412       ;; new buffer with no footnotes
   1413       (should (= markdown-footnote-counter 0))
   1414       ;; footnote insertion
   1415       (end-of-line)
   1416       (markdown-insert-footnote)
   1417       (should (= (point) 28))
   1418       (should (= markdown-footnote-counter 1))
   1419       (should (looking-back "\\[^1\\]: " nil))
   1420       ;; kill with point in footnote definition
   1421       (insert "footnote text")
   1422       (let (kill-ring)
   1423         (markdown-footnote-kill))
   1424       (should (= (point) 18))
   1425       (should (bolp))
   1426       (should (string-equal (buffer-string)
   1427                             "first paragraph\n\nsecond paragraph\n")))))
   1428 
   1429 (ert-deftest test-markdown-footnote/basic-header ()
   1430   "Basic footnote insertion and deletion tests for 'header location."
   1431   (let ((markdown-footnote-location 'header))
   1432     (markdown-test-string "par one\n\npar two\n\n### header\n"
   1433       ;; new buffer with no footnotes
   1434       (should (= markdown-footnote-counter 0))
   1435       ;; footnote insertion
   1436       (end-of-line)
   1437       (markdown-insert-footnote)
   1438       (should (= (point) 29))
   1439       (should (= markdown-footnote-counter 1))
   1440       (should (looking-back "\\[^1\\]: " nil))
   1441       ;; kill with point in footnote definition
   1442       (insert "footnote text")
   1443       (let (kill-ring)
   1444         (markdown-footnote-kill))
   1445       (should (= (point) 19))
   1446       (should (bolp))
   1447       (should (string-equal (buffer-string)
   1448                             "par one\n\npar two\n\n### header\n"))
   1449       ;; insertion, counter should increment
   1450       (goto-char (point-min))
   1451       (end-of-line)
   1452       (markdown-insert-footnote)
   1453       (should (= (point) 29))
   1454       (should (= markdown-footnote-counter 2))
   1455       (should (looking-back "\\[^2\\]: " nil))
   1456       (insert "footnote text")
   1457       ;; return to marker
   1458       (markdown-footnote-return)
   1459       (should (= (point) 12))
   1460       (should (looking-back "\\[^2\\]" nil))
   1461       ;; kill with point at marker
   1462       (let (kill-ring)
   1463         (markdown-footnote-kill))
   1464       (should (= (point) 8))
   1465       (should (eolp))
   1466       (should (string-equal (buffer-string)
   1467                             "par one\n\npar two\n\n### header\n")))))
   1468 
   1469 (ert-deftest test-markdown-footnote/basic-subtree ()
   1470   "Basic footnote insertion and deletion tests for 'subtree location."
   1471   (let ((markdown-footnote-location 'subtree))
   1472     (markdown-test-string "# h1\n\nfoo\n\n## h2\n\nbar\n"
   1473       ;; new buffer with no footnotes
   1474       (should (= markdown-footnote-counter 0))
   1475       ;; footnote insertion
   1476       (forward-line 2)
   1477       (end-of-line)
   1478       (markdown-insert-footnote)
   1479       (should (= (point) 34))
   1480       (should (= markdown-footnote-counter 1))
   1481       (should (looking-back "\\[^1\\]: " nil)))))
   1482 
   1483 (ert-deftest test-markdown-footnote/kill-empty-text ()
   1484   "Test killing a footnote with marker but no text."
   1485   (markdown-test-string "no text[^1]\n\n[^1]: \n"
   1486     (end-of-line)
   1487     (markdown-footnote-goto-text)
   1488     (should (looking-back "\\[^1\\]: " nil))
   1489     (let (kill-ring)
   1490       (markdown-footnote-kill))
   1491     (should (string-equal (buffer-string) "no text\n"))))
   1492 
   1493 (ert-deftest test-markdown-footnote/kill-empty-after ()
   1494   "Test killing an empty footnote after one with text (previously killed the
   1495 footnote with text above)."
   1496   (markdown-test-string "[^with-text][^no-text]\n\n[^with-text]: Text\n[^no-text]:"
   1497     (let (kill-ring)
   1498       (forward-line 3)
   1499       (should (looking-at "\\[\\^no-text\\]:$"))
   1500       (markdown-footnote-kill)
   1501       (should (string-equal (current-kill 0) "")))))
   1502 
   1503 (ert-deftest test-markdown-footnote/kill-hanging-paras ()
   1504   "Test killing a footnote where block text starts after the label (previously
   1505 killed the footnote above)."
   1506   (markdown-test-string "[^1][^2]\n\n[^1]: Foo\n\n[^2]:\n    Text\n\n    More text\n\n\nNot indented"
   1507     (let (kill-ring)
   1508       (forward-line 4)
   1509       (should (looking-at "\\[\\^2\\]:$"))
   1510       (markdown-footnote-kill)
   1511       ;; We want to include the leading space on hanging footnote paragraphs,
   1512       ;; even if a hanging paragraph is the first item in the footnote.
   1513       (should (string-equal (current-kill 0) "Text\n\n    More text\n")))))
   1514 
   1515 (ert-deftest test-markdown-footnote/text-positions-buffer-top ()
   1516   "Test markdown-footnote-text-positions on footnote adjacent to buffer top
   1517 (was infinite loop)."
   1518   (markdown-test-string "[^label]: text\n    more text"
   1519     (should (equal (markdown-footnote-text-positions) (list "^label" 1 29)))))
   1520 
   1521 (ert-deftest test-markdown-footnote/text-positions-buffer-top-one-line ()
   1522   "Test markdown-footnote-text-positions on one-line footnote adjacent to
   1523 buffer top (failed to find positions)."
   1524   (markdown-test-string "[^label]: text\n"
   1525     (should (equal (markdown-footnote-text-positions) (list "^label" 1 16)))))
   1526 
   1527 (ert-deftest test-markdown-footnote/text-positions-buffer-top-not-footnote ()
   1528   "Test markdown-footnote-text-positions on plain paragraph adjacent to buffer
   1529 top (was infinite loop)."
   1530   (markdown-test-string "text\n    more text\n"
   1531     (should (eq (markdown-footnote-text-positions) nil))))
   1532 
   1533 (ert-deftest test-markdown-footnote/text-positions-buffer-bottom ()
   1534   "Test markdown-footnote-text-positions on footnote adjacent to buffer bottom
   1535 (was infinite loop)."
   1536   (markdown-test-string "\n[^label]: text\n    more text"
   1537     (forward-line 1)
   1538     (should (equal (markdown-footnote-text-positions) (list "^label" 2 30)))))
   1539 
   1540 (ert-deftest test-markdown-footnote/kill-adjacent-footnote ()
   1541   "Test killing a footnote adjacent to other one-line footnotes (previously
   1542 killed the wrong one)."
   1543   (markdown-test-string "Text[^1] with[^2] footnotes[^3]\n\n[^1]: foo\n[^2]: bar\n[^3]: baz"
   1544     (let (kill-ring)
   1545       (forward-line 3)
   1546       (should (looking-at "\\[\\^2\\]: bar"))
   1547       (markdown-footnote-kill)
   1548       (should (string-equal (current-kill 0) "bar\n")))))
   1549 
   1550 (ert-deftest test-markdown-footnote/kill-adjacent-markers ()
   1551   "Test killing a footnote where the labels are adjacent (previously, the wrong
   1552 footnote would be killed because the attempt to jump to the marker would jump to
   1553 the opening bracket of [^2], and then subsequent functions would kill [^2])."
   1554   (markdown-test-string "Text with footnotes[^1][^2]\n\n[^1]: foo\n\n[^2]: bar\n"
   1555     (let (kill-ring)
   1556       (forward-line 2)
   1557       (should (looking-at "\\[\\^1\\]: foo"))
   1558       (markdown-footnote-kill)
   1559       (should (string-equal (current-kill 0) "foo\n")))))
   1560 
   1561 (ert-deftest test-markdown-do/jump-wiki-link ()
   1562   "Test `markdown-do' jumps to wiki links"
   1563   (with-current-buffer (find-file-noselect "wiki/pr666/jump_wiki_link.md")
   1564     (let ((markdown-enable-wiki-links t))
   1565       (goto-char 3)
   1566       (markdown-do)
   1567       (should (string= (buffer-name) "Foo.md")))))
   1568 
   1569 (ert-deftest test-markdown-do/jump-link ()
   1570   "Test `markdown-do' jumps to markdown links"
   1571   (markdown-test-string "[bar](https://duckduckgo.com)"
   1572     (let* ((opened-url nil)
   1573            (browse-url-browser-function
   1574             (lambda (url &rest _args) (setq opened-url url))))
   1575       (goto-char 3)
   1576       (markdown-do)
   1577       (should (string= opened-url "https://duckduckgo.com")))))
   1578 
   1579 (ert-deftest test-markdown-do/wiki-link-in-table ()
   1580   "Test `markdown-do' jumps to markdown links"
   1581   (with-current-buffer (find-file-noselect "wiki/pr666/wiki_link_in_table.md")
   1582     (let ((markdown-enable-wiki-links t))
   1583       ;; alignment
   1584       (markdown-do)
   1585       (should (string= (buffer-string) "| [[Foo]] |\n"))
   1586 
   1587       (forward-char 4)
   1588 
   1589       ;; wiki link
   1590       (markdown-do)
   1591       (should (string= (buffer-name) "Foo.md")))))
   1592 
   1593 (ert-deftest test-markdown-footnote-reference/jump ()
   1594   "Test `markdown-do' for footnotes and reference links."
   1595   (markdown-test-string
   1596       "body[^1], [link 1][ref],
   1597 [link 2][ref]
   1598 
   1599 [^1]: footnote
   1600 
   1601 [ref]: https://duckduckgo.com/"
   1602     (goto-char 5) ; start of [^1]
   1603     (markdown-do) ; markdown-footnote-goto-text
   1604     (should (looking-at "footnote"))
   1605     (markdown-do) ; markdown-footnote-return
   1606     (should (= (point) 9)) ; just after [^1]
   1607     (markdown-next-link) ; beginning of [link 1][]
   1608     (markdown-do)
   1609     (should (looking-at "https://duckduckgo.com/"))
   1610     (should (equal (markdown-reference-find-links "ref")
   1611                    (list (list "link 2" 26 2) (list "link 1" 11 1))))
   1612     (markdown-do) ; opens a reference link buffer
   1613     (should (string= (buffer-string) "Links using reference ref:\n\nlink 1 (line 1)\nlink 2 (line 2)\n"))
   1614     (should (looking-at "link 1")) ; in reference link popop buffer
   1615     (execute-kbd-macro (read-kbd-macro "RET")) ; jump to "link 1"
   1616     (should (looking-at "\\[link 1\\]")) ; back in main buffer
   1617     (should (= (point) 11))))
   1618 
   1619 ;;; Element removal tests:
   1620 
   1621 (ert-deftest test-markdown-kill/simple ()
   1622   "Simple tests for `markdown-kill-thing-at-point'."
   1623   (let ((kill-ring nil)
   1624         (tests (list '("`foo`" . "foo")
   1625                      '("## foo ##" . "foo")
   1626                      '("## foo" . "foo")
   1627                      '("foo\n---" . "foo")
   1628                      '("foo\n===" . "foo")
   1629                      '("* * * * *" . "* * * * *")
   1630                      '("[foo](http://bar.com/)" . "foo")
   1631                      '("![foo](http://bar.com/)" . "foo")
   1632                      '("[foo][bar]" . "foo")
   1633                      '("![foo][bar]" . "foo")
   1634                      '("<http://foo.com/>" . "http://foo.com/")
   1635                      '("<foo@bar.com>" . "foo@bar.com")
   1636                      '("**foo**" . "foo")
   1637                      '("__foo__" . "foo")
   1638                      '("*foo*" . "foo")
   1639                      '("_foo_" . "foo")
   1640                      '("  [foo]: http://bar.com/" . "http://bar.com/")
   1641                      '("  [foo]: http://bar.com/ \"title\"" . "http://bar.com/")
   1642                      '("foo[^bar]\n\n[^bar]: baz" . "baz")
   1643                      '("[^bar]: baz" . "baz")
   1644                      '("  * foo\n  bar" . "  * foo\n  bar"))))
   1645     (dolist (test tests)
   1646       ;; Load test string (the car), move to end of first line, kill
   1647       ;; thing at point, and then verify that the kill ring contains cdr.
   1648       (markdown-test-string (car test)
   1649         (end-of-line)
   1650         (forward-char -1)
   1651         (call-interactively 'markdown-kill-thing-at-point)
   1652         (should (string-equal (current-kill 0) (cdr test)))))))
   1653 
   1654 (ert-deftest test-markdown-kill/footnote-text ()
   1655   "Test killing a footnote with point at footnote text."
   1656   (markdown-test-string "some text[^1]\n\n[^1]: footnote\n"
   1657     (end-of-line)
   1658     (markdown-footnote-goto-text)
   1659     (let (kill-ring)
   1660       (markdown-footnote-kill))
   1661     (should (string-equal (buffer-string) "some text\n"))))
   1662 
   1663 (ert-deftest test-markdown-kill/code ()
   1664   "Test killing with code regex.."
   1665   (let ((kill-ring nil))
   1666     (markdown-test-string "Lorem `ipsum` dolor `sit` `amet`."
   1667       (goto-char 22) ; position point at s in `sit`
   1668       (call-interactively 'markdown-kill-thing-at-point)
   1669       (should (string-equal (current-kill 0) "sit")))))
   1670 
   1671 ;;; Completion:
   1672 
   1673 (ert-deftest test-markdown-complete/atx-header-incomplete ()
   1674   "Test `markdown-incomplete-atx-p'."
   1675   (markdown-test-string "###  ###"
   1676     (should (looking-at markdown-regex-header-atx))
   1677     (should-not (markdown-incomplete-atx-p)))
   1678   (markdown-test-string "###abc###"
   1679     (should-not (looking-at markdown-regex-header-atx)))
   1680   (markdown-test-string "###   ###"
   1681     (should (looking-at markdown-regex-header-atx))
   1682     (should (markdown-incomplete-atx-p))))
   1683 
   1684 (ert-deftest test-markdown-complete/atx-header ()
   1685   "Test `markdown-complete' for atx headers."
   1686   (markdown-test-string "##### test"
   1687     (call-interactively 'markdown-complete)
   1688     (should (string-equal (buffer-string) "##### test #####"))))
   1689 
   1690 (ert-deftest test-markdown-complete/setext-header-incomplete ()
   1691   "Test `markdown-incomplete-setext-p'."
   1692   (markdown-test-string "abc\n===\n"
   1693     (should (looking-at markdown-regex-header-setext))
   1694     (should-not (markdown-incomplete-setext-p)))
   1695   (markdown-test-string "abc\n==\n"
   1696     (should (looking-at markdown-regex-header-setext))
   1697     (should (markdown-incomplete-setext-p)))
   1698   (markdown-test-string "abc\n====\n"
   1699     (should (looking-at markdown-regex-header-setext))
   1700     (should (markdown-incomplete-setext-p))))
   1701 
   1702 (ert-deftest test-markdown-complete/setext-header ()
   1703   "Test `markdown-complete' for setext headers."
   1704   (markdown-test-string "test  \n=="
   1705     (call-interactively 'markdown-complete)
   1706     (should (string-equal (buffer-string) "test\n===="))))
   1707 
   1708 (ert-deftest test-markdown-complete/hr-incomplete ()
   1709   "Test `markdown-incomplete-hr-p'."
   1710   (dolist (i (number-sequence 0 (1- (length markdown-hr-strings))))
   1711     (markdown-test-string (nth i markdown-hr-strings)
   1712       (should (looking-at markdown-regex-hr))
   1713       (should-not (markdown-incomplete-hr-p))
   1714       (should-error (call-interactively 'markdown-complete)))))
   1715 
   1716 (ert-deftest test-markdown-complete/hr ()
   1717   "Test completion via `markdown-complete' for horizontal rules."
   1718   (markdown-test-string "- - - - -"
   1719     (call-interactively 'markdown-complete)
   1720     (should (string-equal (buffer-string) (car markdown-hr-strings)))))
   1721 
   1722 (ert-deftest test-markdown-complete/buffer-setext-2 ()
   1723   "Test `markdown-complete-buffer' for level two setext heading."
   1724   ;; Ensure markdown-complete-buffer doesn't mistake this for a horizontal rule
   1725   (markdown-test-string "Subheading\n--\n"
   1726     (call-interactively 'markdown-complete-buffer)
   1727     (should (string-equal (buffer-string) "Subheading\n----------\n\n")))
   1728   (markdown-test-string "Abc\n--\n\nDef\n--\n"
   1729     (call-interactively 'markdown-complete-buffer)
   1730     (should (string-equal (buffer-string) "Abc\n---\n\nDef\n---\n\n"))))
   1731 
   1732 ;;; Promotion and demotion tests:
   1733 
   1734 (ert-deftest test-markdown-promote/atx-header ()
   1735   "Test `markdown-promote' for atx headers."
   1736   (markdown-test-string "###### test ######"
   1737     (markdown-promote)
   1738     (should (string-equal (buffer-string) "##### test #####"))
   1739     (markdown-promote)
   1740     (should (string-equal (buffer-string) "#### test ####"))
   1741     (markdown-promote)
   1742     (should (string-equal (buffer-string) "### test ###"))
   1743     (markdown-promote)
   1744     (should (string-equal (buffer-string) "## test ##"))
   1745     (markdown-promote)
   1746     (should (string-equal (buffer-string) "# test #"))))
   1747 
   1748 (ert-deftest test-markdown-demote/atx-header ()
   1749   "Test `markdown-demote' for atx headers."
   1750   (markdown-test-string "# test #"
   1751     (markdown-demote)
   1752     (should (string-equal (buffer-string) "## test ##"))
   1753     (markdown-demote)
   1754     (should (string-equal (buffer-string) "### test ###"))
   1755     (markdown-demote)
   1756     (should (string-equal (buffer-string) "#### test ####"))
   1757     (markdown-demote)
   1758     (should (string-equal (buffer-string) "##### test #####"))
   1759     (markdown-demote)
   1760     (should (string-equal (buffer-string) "###### test ######"))))
   1761 
   1762 (ert-deftest test-markdown-promote/setext-header ()
   1763   "Test `markdown-promote' for setext headers."
   1764   (markdown-test-string "test\n----"
   1765     (markdown-promote)
   1766     (should (string-equal (buffer-string) "test\n===="))))
   1767 
   1768 (ert-deftest test-markdown-demote/setext-header ()
   1769   "Test `markdown-demote' for setext headers."
   1770   (markdown-test-string "test\n===="
   1771     (markdown-demote)
   1772     (should (string-equal (buffer-string) "test\n----"))
   1773     (markdown-demote)
   1774     (should (string-equal (buffer-string) "### test ###"))
   1775     (markdown-demote)
   1776     (should (string-equal (buffer-string) "#### test ####"))
   1777     (markdown-demote)
   1778     (should (string-equal (buffer-string) "##### test #####"))
   1779     (markdown-demote)
   1780     (should (string-equal (buffer-string) "###### test ######"))))
   1781 
   1782 (ert-deftest test-markdown-promote/hr ()
   1783   "Test `markdown-promote' for horizontal rules."
   1784   (markdown-test-string (car (reverse markdown-hr-strings))
   1785     (dolist (n (number-sequence 4 0 -1))
   1786       (markdown-promote)
   1787       (should (string-equal (buffer-string) (nth n markdown-hr-strings))))))
   1788 
   1789 (ert-deftest test-markdown-demote/hr ()
   1790   "Test `markdown-demote' for horizontal rules."
   1791   (markdown-test-string (car markdown-hr-strings)
   1792     (dolist (n (number-sequence 1 5))
   1793       (markdown-demote)
   1794       (should (string-equal (buffer-string) (nth n markdown-hr-strings))))))
   1795 
   1796 (ert-deftest test-markdown-promote/bold ()
   1797   "Test `markdown-promote' for bold markup."
   1798   (markdown-test-string "__bold__"
   1799     (call-interactively 'markdown-promote)
   1800     (should (string-equal (buffer-string) "**bold**"))))
   1801 
   1802 (ert-deftest test-markdown-demote/bold ()
   1803   "Test `markdown-demote' for bold markup."
   1804   (markdown-test-string "**bold**"
   1805     (call-interactively 'markdown-promote)
   1806     (should (string-equal (buffer-string) "__bold__"))))
   1807 
   1808 (ert-deftest test-markdown-promote/italic ()
   1809   "Test `markdown-promote' for italic markup."
   1810   (markdown-test-string "_italic_"
   1811     (call-interactively 'markdown-promote)
   1812     (should (string-equal (buffer-string) "*italic*"))))
   1813 
   1814 (ert-deftest test-markdown-demote/italic ()
   1815   "Test `markdown-demote' for italic markup."
   1816   (markdown-test-string "*italic*"
   1817     (call-interactively 'markdown-promote)
   1818     (should (string-equal (buffer-string) "_italic_"))))
   1819 
   1820 ;;; Subtree editing tests:
   1821 
   1822 (ert-deftest test-markdown-subtree/promote ()
   1823   "Test `markdown-promote-subtree'."
   1824   (markdown-test-string "# h1 #\n\n## h2 ##\n\n### h3 ###\n\n## h2 ##\n\n# h1 #\n"
   1825     ;; The first h1 should get promoted away.
   1826     ;; The second h1 should not be promoted.
   1827     (markdown-promote-subtree)
   1828     (should (string-equal (buffer-string) "h1\n\n# h2 #\n\n## h3 ##\n\n# h2 #\n\n# h1 #\n"))
   1829     ;; Second call should do nothing since point is no longer at a heading.
   1830     (markdown-promote-subtree)
   1831     (should (string-equal (buffer-string) "h1\n\n# h2 #\n\n## h3 ##\n\n# h2 #\n\n# h1 #\n"))
   1832     ;; Move to h2 and promote again.
   1833     (forward-line 2)
   1834     (markdown-promote-subtree)
   1835     (should (string-equal (buffer-string) "h1\n\nh2\n\n# h3 #\n\n# h2 #\n\n# h1 #\n"))))
   1836 
   1837 (ert-deftest test-markdown-subtree/promote-single-section ()
   1838   "Test `markdown-promote-subtree' on a single or last section.
   1839 Should not cause an infinite loop."
   1840   (markdown-test-string "foo\n\n## h2 ##\n\nbar\n"
   1841     ;; The h2 should get promoted to h1 away.
   1842     (markdown-test-goto-heading "h2")
   1843     (markdown-promote-subtree)
   1844     (should (string-equal (buffer-string) "foo\n\n# h2 #\n\nbar\n"))))
   1845 
   1846 (ert-deftest test-markdown-subtree/demote ()
   1847   "Test `markdown-demote-subtree'."
   1848   (markdown-test-string "# h1 #\n\n## h2 ##\n\n### h3 ###\n\n## h2 ##\n\n# h1 #\n"
   1849     ;; The second h1 should not be demoted
   1850     (markdown-demote-subtree)
   1851     (should (string-equal (buffer-string) "## h1 ##\n\n### h2 ###\n\n#### h3 ####\n\n### h2 ###\n\n# h1 #\n"))
   1852     (markdown-demote-subtree)
   1853     (should (string-equal (buffer-string) "### h1 ###\n\n#### h2 ####\n\n##### h3 #####\n\n#### h2 ####\n\n# h1 #\n"))
   1854     (markdown-demote-subtree)
   1855     (should (string-equal (buffer-string) "#### h1 ####\n\n##### h2 #####\n\n###### h3 ######\n\n##### h2 #####\n\n# h1 #\n"))
   1856     ;; Stop demoting at level six
   1857     (markdown-demote-subtree)
   1858     (should (string-equal (buffer-string) "##### h1 #####\n\n###### h2 ######\n\n###### h3 ######\n\n###### h2 ######\n\n# h1 #\n"))
   1859     (markdown-demote-subtree)
   1860     (should (string-equal (buffer-string) "###### h1 ######\n\n###### h2 ######\n\n###### h3 ######\n\n###### h2 ######\n\n# h1 #\n"))))
   1861 
   1862 (ert-deftest test-markdown-subtree/move-up ()
   1863   "Test `markdown-move-subtree-up'."
   1864   ;; Note that prior to Emacs 24.5, this does not work for the last subtree in
   1865   ;; the buffer due to Emacs bug #19102:
   1866   ;; https://debbugs.gnu.org/cgi/bugreport.cgi?bug=19102
   1867   ;; https://github.com/emacs-mirror/emacs/commit/b3910f
   1868   ;; That also corrects the type of the "Cannot move past superior level" error
   1869   ;; from 'error to 'user-error.
   1870   (markdown-test-string "# 1 #\n\n## 1.1 ##\n\n### 1.1.1 ###\n\n## 1.2 ##\n\n### 1.2.1 ###\n\n# 2 #\n# Extra\n"
   1871     (re-search-forward "^# 2")
   1872     (markdown-move-subtree-up)
   1873     (should (string-equal (buffer-string) "# 2 #\n# 1 #\n\n## 1.1 ##\n\n### 1.1.1 ###\n\n## 1.2 ##\n\n### 1.2.1 ###\n\n# Extra\n"))
   1874     ;; Second attempt should fail, leaving buffer unchanged.
   1875     ;; (This way of asserting the contents of the error
   1876     ;; message is a bit convoluted and more fragile than
   1877     ;; ideal. But prior to Emacs 24.5, the type of this
   1878     ;; error is just 'error, and a bare "should-error" is
   1879     ;; really overly broad.)
   1880     (should (string-equal
   1881              "Cannot move past superior level"
   1882              (cl-second (should-error (markdown-move-subtree-up)))))))
   1883 
   1884 (ert-deftest test-markdown-subtree/move-down ()
   1885   "Test `markdown-move-subtree-down'."
   1886   (markdown-test-string "# 1 #\n\n## 1.1 ##\n\n### 1.1.1 ###\n\n## 1.2 ##\n\n### 1.2.1 ###\n\n# 2 #\n"
   1887     (re-search-forward "^## 1\.1")
   1888     (markdown-move-subtree-down)
   1889     (should (string-equal (buffer-string) "# 1 #\n\n## 1.2 ##\n\n### 1.2.1 ###\n\n## 1.1 ##\n\n### 1.1.1 ###\n\n# 2 #\n"))))
   1890 
   1891 (ert-deftest test-markdown-subtree/mark ()
   1892   "Test `markdown-mark-subtree'."
   1893   (markdown-test-file "outline.text"
   1894     (markdown-next-visible-heading 1)
   1895     (should-not mark-active)
   1896     (markdown-mark-subtree)
   1897     (should (= (point) 19))
   1898     (should (= (mark) 349))
   1899     (should mark-active)
   1900     (deactivate-mark)
   1901     (should-not mark-active)
   1902     (markdown-forward-same-level 1)
   1903     (markdown-mark-subtree)
   1904     (should (= (point) 351))
   1905     (should (= (mark) 515))
   1906     (should mark-active)))
   1907 
   1908 (ert-deftest test-markdown-subtree/narrow ()
   1909   "Test `markdown-narrow-to-subtree'."
   1910   (markdown-test-file "outline.text"
   1911     (markdown-next-visible-heading 1)
   1912     (markdown-forward-same-level 1)
   1913     (widen)
   1914     (should (= (point-min) 1))
   1915     (should (= (point-max) 553))
   1916     (markdown-narrow-to-subtree)
   1917     (should (= (point-min) 351))
   1918     (should (= (point-max) 515))))
   1919 
   1920 ;;; Cycling:
   1921 
   1922 (ert-deftest test-markdown-cycle/atx-header ()
   1923   "Test `markdown-demote' cycling for atx headers."
   1924   (markdown-test-string "# test"
   1925     (call-interactively 'markdown-demote)
   1926     (should (string-equal (buffer-string) "## test ##"))
   1927     (call-interactively 'markdown-demote)
   1928     (should (string-equal (buffer-string) "### test ###"))
   1929     (call-interactively 'markdown-demote)
   1930     (should (string-equal (buffer-string) "#### test ####"))
   1931     (call-interactively 'markdown-demote)
   1932     (should (string-equal (buffer-string) "##### test #####"))
   1933     (call-interactively 'markdown-demote)
   1934     (should (string-equal (buffer-string) "###### test ######"))
   1935     (call-interactively 'markdown-demote)
   1936     (should (string-equal (buffer-string) "###### test ######"))))
   1937 
   1938 (ert-deftest test-markdown-cycle/setext-header ()
   1939   "Test `markdown-demote' cycling for setext headers."
   1940   (markdown-test-string "test\n===="
   1941     (call-interactively 'markdown-demote)
   1942     (should (string-equal (buffer-string) "test\n----"))
   1943     (call-interactively 'markdown-demote)
   1944     (should (string-equal (buffer-string) "### test ###"))
   1945     (call-interactively 'markdown-demote)
   1946     (should (string-equal (buffer-string) "#### test ####"))
   1947     (call-interactively 'markdown-demote)
   1948     (should (string-equal (buffer-string) "##### test #####"))
   1949     (call-interactively 'markdown-demote)
   1950     (should (string-equal (buffer-string) "###### test ######"))
   1951     (call-interactively 'markdown-demote)
   1952     (should (string-equal (buffer-string) "###### test ######"))))
   1953 
   1954 (ert-deftest test-markdown-cycle/hr ()
   1955   "Test cycling of horizontal rules."
   1956   ;; Cycle using markdown-demote
   1957   (markdown-test-string (car markdown-hr-strings)
   1958     (dolist (n (number-sequence 1 5))
   1959       (call-interactively 'markdown-demote)
   1960       (should (string-equal (buffer-string) (nth n markdown-hr-strings))))
   1961     (call-interactively 'markdown-demote)
   1962     (should (string-equal (buffer-string) (car markdown-hr-strings))))
   1963   ;; Cycle using markdown-promote
   1964   (markdown-test-string (car (reverse markdown-hr-strings))
   1965     (dolist (n (number-sequence 4 0 -1))
   1966       (call-interactively 'markdown-promote)
   1967       (should (string-equal (buffer-string) (nth n markdown-hr-strings))))
   1968     (call-interactively 'markdown-promote)
   1969     (should (string-equal (buffer-string) (car (reverse markdown-hr-strings))))))
   1970 
   1971 (ert-deftest test-markdown-cycle/bold ()
   1972   "Test cycling of bold markup."
   1973   (markdown-test-string "**bold**"
   1974     (call-interactively 'markdown-demote)
   1975     (should (string-equal (buffer-string) "__bold__"))
   1976     (call-interactively 'markdown-demote)
   1977     (should (string-equal (buffer-string) "**bold**"))))
   1978 
   1979 (ert-deftest test-markdown-cycle/italic ()
   1980   "Test cycling of italic markup."
   1981   (markdown-test-string "*italic*"
   1982     (call-interactively 'markdown-demote)
   1983     (should (string-equal (buffer-string) "_italic_"))
   1984     (call-interactively 'markdown-demote)
   1985     (should (string-equal (buffer-string) "*italic*"))))
   1986 
   1987 ;;; Indentation tests:
   1988 
   1989 (ert-deftest test-markdown-indentation/calc-indents ()
   1990   "Test `markdown-calc-indents' a nested list context."
   1991   (markdown-test-file "nested-list.text"
   1992     (goto-char (point-max))
   1993     (let ((indents (markdown-calc-indents)))
   1994       (should (= (car indents) 17)) ; indentation of previous line first
   1995       (should (equal (sort indents '<)
   1996                      (list
   1997                       0 ; beginning of line
   1998                       3 ; first-level list marker
   1999                       7 ; second-level list marker
   2000                       11 ; third-level list marker
   2001                       13 ; previous list item text
   2002                       16 ; pre-block indentation
   2003                       17 ; indentation of previous line
   2004                       21 ; previous line plus tab-width
   2005                       ))))))
   2006 
   2007 (ert-deftest test-markdown-indentation/indent-region ()
   2008   "Test `markdown-indent-region'."
   2009   ;; Basic test with multiple lines
   2010   (markdown-test-string "abc\ndef\nghi\n"
   2011     (markdown-indent-region (point-min) (point-max) nil)
   2012     (should (string-equal (buffer-string) "    abc\n    def\n    ghi\n")))
   2013   ;; Following a list item
   2014   (markdown-test-string "  * abc\ndef\n"
   2015     (forward-line)
   2016     (markdown-indent-region (line-beginning-position) (line-end-position) nil)
   2017     (should (string-equal (buffer-string) "  * abc\n  def\n"))
   2018     (markdown-indent-region (line-beginning-position) (line-end-position) nil)
   2019     (should (string-equal (buffer-string) "  * abc\n    def\n"))))
   2020 
   2021 (ert-deftest test-markdown-indentation/indent-list-hanging ()
   2022   "Test `markdown-indent-line' with hanging list item."
   2023   (markdown-test-string
   2024       "- list
   2025   - nested list with long lines which need to be
   2026     hard wrapped"
   2027     (goto-char (point-max))
   2028     (markdown-enter-key)
   2029     (should (eq (point) 78))))
   2030 
   2031 (ert-deftest test-markdown-indentation/indent-list-single ()
   2032   "Test `markdown-indent-line' with single list item."
   2033   (let ((markdown-indent-on-enter 'indent-and-new-item))
   2034     (markdown-test-string "  * item 1"
   2035       (end-of-line)
   2036       (call-interactively #'markdown-enter-key)
   2037       (should (string-equal (buffer-string) "  * item 1\n  * "))
   2038       (should (eq (point) 16))
   2039       (call-interactively #'markdown-enter-key)
   2040       (should (string-equal (buffer-string) "  * item 1\n\n"))
   2041       (should (eq (point) 13)))))
   2042 
   2043 (ert-deftest test-markdown-indentation/indent-nested-list ()
   2044   "Test `markdown-enter-key' with a nested list item."
   2045   (let ((markdown-indent-on-enter 'indent-and-new-item))
   2046     (markdown-test-string "* foo\n* bar\n  * baz"
   2047       (goto-char (point-max))
   2048       (call-interactively #'markdown-enter-key)
   2049       (should (string-equal (buffer-string) "* foo\n* bar\n  * baz\n  * "))
   2050       (should (eq (point) 25))
   2051       (call-interactively #'markdown-enter-key)
   2052       (should (string-equal (buffer-string) "* foo\n* bar\n  * baz\n\n"))
   2053       (should (eq (point) 22)))))
   2054 
   2055 (ert-deftest test-markdown-indentation/indent-pre ()
   2056   "Test `markdown-indent-line' with a pre block."
   2057   (markdown-test-string
   2058       "I'm gonna write a code block:
   2059 
   2060     my first line of code"
   2061     (goto-char (point-max))
   2062     (markdown-enter-key)
   2063     (should (eq (point) 62))
   2064     (should (looking-back "^    "))))
   2065 
   2066 (ert-deftest test-markdown-indentation/indent-region-function ()
   2067   "Test `indent-region'. Code block should not be indented.
   2068 Detail: https://github.com/jrblevin/markdown-mode/issues/228"
   2069   (markdown-test-string
   2070       "Here follows a code sample:
   2071 
   2072     #!/bin/bash
   2073     echo foobar
   2074 
   2075 Nice sample, isn't it ?"
   2076     (indent-region (point-min) (point-max))
   2077     (goto-char (point-min))
   2078     (forward-line 2)
   2079     (should (looking-at-p "    #!/bin/bash"))
   2080     (markdown-test-range-has-face (point) (line-end-position) 'markdown-pre-face)))
   2081 
   2082 (ert-deftest test-markdown-indentation/indent-hanging-line ()
   2083   "Test `markdown-indent-line' with hanging indentation.
   2084 See GH-245."
   2085   (markdown-test-string "Stuff
   2086   More"
   2087     (forward-line)
   2088     (should (looking-at "^  More"))
   2089     (should (= (current-column) 0))
   2090     (should (= (current-indentation) 2))
   2091     (let ((last-command this-command)
   2092           (this-command 'markdown-cycle))
   2093       (call-interactively #'markdown-cycle))
   2094     (should (= (current-column) 0))
   2095     (should (= (current-indentation) 0))))
   2096 
   2097 (ert-deftest test-markdown-indentation/continue-gfm-task-lists ()
   2098   (markdown-test-string "   -   [X] item"
   2099     (end-of-line)
   2100     (let ((markdown-indent-on-enter 'indent-and-new-item))
   2101       (call-interactively #'markdown-enter-key))
   2102     (should (string-equal (buffer-string) "   -   [X] item\n   -   [ ] "))
   2103     (should (= (point) 28))))
   2104 
   2105 ;;; Markup hiding tests:
   2106 
   2107 (ert-deftest test-markdown-markup-hiding/italics-1 ()
   2108   "Test hiding markup for italics."
   2109   (markdown-test-file "inline.text"
   2110     (goto-char 9)
   2111     (should (looking-at "\*italic\*"))
   2112     (markdown-test-range-has-property (point) (point) 'invisible 'markdown-markup)
   2113     (should-not (invisible-p (point)))
   2114     (should-not (invisible-p (+ 1 (point))))
   2115     (markdown-toggle-markup-hiding t)
   2116     (should (invisible-p (point)))
   2117     (should-not (invisible-p (+ 1 (point))))))
   2118 
   2119 (ert-deftest test-markdown-markup-hiding/bold-1 ()
   2120   "Test hiding markup for bold."
   2121   (markdown-test-file "inline.text"
   2122     (goto-char 27)
   2123     (should (looking-at "\*\*bold\*\*"))
   2124     (markdown-test-range-has-property (point) (1+ (point)) 'invisible 'markdown-markup)
   2125     (should-not (invisible-p (point)))
   2126     (should-not (invisible-p (+ 1 (point))))
   2127     (should-not (invisible-p (+ 2 (point))))
   2128     (markdown-toggle-markup-hiding t)
   2129     (should (invisible-p (point)))
   2130     (should (invisible-p (+ 1 (point))))
   2131     (should-not (invisible-p (+ 2 (point))))))
   2132 
   2133 (ert-deftest test-markdown-markup-hiding/code-1 ()
   2134   "Test hiding markup for inline code."
   2135   (markdown-test-file "inline.text"
   2136     (goto-char 45)
   2137     (should (looking-at "`code`"))
   2138     (markdown-test-range-has-property (point) (point) 'invisible 'markdown-markup)
   2139     (should-not (invisible-p (point)))
   2140     (should-not (invisible-p (1+ (point))))
   2141     (markdown-toggle-markup-hiding t)
   2142     (should (invisible-p (point)))
   2143     (should-not (invisible-p (1+ (point))))))
   2144 
   2145 (ert-deftest test-markdown-markup-hiding/kbd-1 ()
   2146   "Test hiding markup for <kbd> tags."
   2147   (markdown-test-string "<kbd>C-c C-x C-m</kbd>"
   2148     (markdown-test-range-has-property (point) (+ 4 (point)) 'invisible 'markdown-markup)
   2149     (should-not (invisible-p (point))) ;; part of <kbd>
   2150     (should-not (invisible-p (+ 4 (point)))) ;; part of <kbd>
   2151     (should-not (invisible-p (+ 5 (point)))) ;; inside <kbd>
   2152     (markdown-toggle-markup-hiding t)
   2153     (should (invisible-p (point))) ;; part of <kbd>
   2154     (should (invisible-p (+ 4 (point)))) ;; part of <kbd>
   2155     (should-not (invisible-p (+ 5 (point)))))) ;; inside <kbd>
   2156 
   2157 (ert-deftest test-markdown-markup-hiding/inline-links ()
   2158   "Test hiding markup for inline links."
   2159   (markdown-test-file "inline.text"
   2160     (goto-char 925)
   2161     (should (looking-at "\\[text\\](http://www.w3.org/ \"title\")"))
   2162     (markdown-test-range-has-property 925 925 'invisible 'markdown-markup) ; [
   2163     (markdown-test-range-has-property 930 958 'invisible 'markdown-markup) ; ](...)
   2164     (should-not (invisible-p 925))
   2165     (should-not (invisible-p 958))
   2166     (markdown-toggle-markup-hiding t)
   2167     (should (invisible-p 925))
   2168     (should-not (invisible-p 926))
   2169     (should (invisible-p 958))))
   2170 
   2171 (ert-deftest test-markdown-markup-hiding/reference-links ()
   2172   "Test hiding markup for reference links."
   2173   (markdown-test-string "[text][ref]"
   2174     (markdown-test-range-has-property 1 1 'invisible 'markdown-markup) ; [
   2175     (markdown-test-range-has-property 6 11 'invisible 'markdown-markup) ; ][ref]
   2176     (should-not (invisible-p 1))
   2177     (should-not (invisible-p 6))
   2178     (markdown-toggle-markup-hiding t)
   2179     (should (invisible-p 1))
   2180     (should-not (invisible-p 2))
   2181     (should (invisible-p 6))))
   2182 
   2183 (ert-deftest test-markdown-markup-hiding/angle-urls ()
   2184   "Test hiding markup for angle urls."
   2185   (markdown-test-string "<http://jblevins.org/projects/markdown-mode/>"
   2186     (markdown-test-range-has-property 1 1 'invisible 'markdown-markup) ; <
   2187     (markdown-test-range-has-property 45 45 'invisible 'markdown-markup) ; >
   2188     (should-not (invisible-p 1))
   2189     (should-not (invisible-p 2))
   2190     (should-not (invisible-p 45))
   2191     (markdown-toggle-markup-hiding t)
   2192     (should (invisible-p 1))
   2193     (should-not (invisible-p 2))
   2194     (should (invisible-p 45))))
   2195 
   2196 (ert-deftest test-markdown-markup-hiding/list-items ()
   2197   "Test hiding markup for list items."
   2198   (let ((markdown-hide-markup t))
   2199     (markdown-test-file "nested-list.text"
   2200       (markdown-test-range-has-property 4 4 'display (nth 0 markdown-list-item-bullets))
   2201       (markdown-test-range-has-property 194 194 'display (nth 0 markdown-list-item-bullets))
   2202       (markdown-test-range-has-property 224 224 'display (nth 1 markdown-list-item-bullets))
   2203       (markdown-test-range-has-property 525 525 'display (nth 2 markdown-list-item-bullets)))))
   2204 
   2205 (ert-deftest test-markdown-markup-hiding/gfm-code-blocks ()
   2206   "Test hiding markup for GFM code blocks."
   2207   (let ((markdown-hide-markup t))
   2208     (markdown-test-file "GFM.md"
   2209       (markdown-test-range-has-property 1548 1552 'invisible 'markdown-markup)
   2210       (should (invisible-p 1548))
   2211       (should (invisible-p 1552))
   2212       (markdown-test-range-has-property 1607 1609 'invisible 'markdown-markup)
   2213       (should (invisible-p 1607))
   2214       (should (invisible-p 1609)))))
   2215 
   2216 (ert-deftest test-markdown-markup-hiding/fenced-code-blocks ()
   2217   "Test hiding markup for tilde fenced code blocks."
   2218   (let ((markdown-hide-markup t))
   2219     (markdown-test-file "outline-code.text"
   2220       (markdown-test-range-has-property 83 93 'invisible 'markdown-markup)
   2221       (should (invisible-p 83))
   2222       (should (invisible-p 93))
   2223       (markdown-test-range-has-property 154 156 'invisible 'markdown-markup)
   2224       (should (invisible-p 154))
   2225       (should (invisible-p 156)))))
   2226 
   2227 ;;; Markup hiding url tests:
   2228 
   2229 (ert-deftest test-markdown-url-hiding/eldoc ()
   2230   "Test hiding URL and eldoc.
   2231 Detail: https://github.com/jrblevin/markdown-mode/pull/674"
   2232   (markdown-test-string "[This is a hidden link](http://hidden.link)"
   2233     (markdown-toggle-url-hiding +1)
   2234     (search-forward "(")
   2235     (markdown-eldoc-function)
   2236     ;; markdown-eldoc-function doesn't raise an exception
   2237     (should t)))
   2238 
   2239 ;;; Font lock tests:
   2240 
   2241 (ert-deftest test-markdown-font-lock/italics-1 ()
   2242   "A simple italics test."
   2243   (markdown-test-file "inline.text"
   2244     (goto-char 9)
   2245     (should (looking-at "\*"))
   2246     ;; Check face of char before leading asterisk
   2247     (markdown-test-range-has-face 8 8 nil)
   2248     ;; Check face of italic range
   2249     (markdown-test-range-has-face 9 9 'markdown-markup-face)
   2250     (markdown-test-range-has-face 10 16 'markdown-italic-face)
   2251     (markdown-test-range-has-face 17 17 'markdown-markup-face)
   2252     ;; Check face of point past leading asterisk
   2253     (markdown-test-range-has-face 18 18 nil)))
   2254 
   2255 (ert-deftest test-markdown-font-lock/italics-2 ()
   2256   "Test space after leading asterisk or underscore."
   2257   (markdown-test-string
   2258       "This is * not italic*, nor _ is this_."
   2259     (markdown-test-range-has-face (point-min) (point-max) nil)))
   2260 
   2261 (ert-deftest test-markdown-font-lock/italics-3 ()
   2262   "Test that slash inside asterisks is not italic."
   2263   (markdown-test-string
   2264       "not italic *\\*"
   2265     (markdown-test-range-has-face (point-min) (point-max) nil)))
   2266 
   2267 (ert-deftest test-markdown-font-lock/italics-4 ()
   2268   "Test escaped asterisk inside italics."
   2269   (markdown-test-string
   2270       "italic *\\**"
   2271     (markdown-test-range-has-face 1 7 nil)
   2272     (markdown-test-range-has-face 8 8 'markdown-markup-face)
   2273     (markdown-test-range-has-face 9 10 'markdown-italic-face)
   2274     (markdown-test-range-has-face 11 11 'markdown-markup-face)))
   2275 
   2276 (ert-deftest test-markdown-font-lock/italics-5 ()
   2277   "Test italic single letter."
   2278   (markdown-test-string
   2279       "*a*"
   2280     (markdown-test-range-has-face 1 1 'markdown-markup-face)
   2281     (markdown-test-range-has-face 2 2 'markdown-italic-face)
   2282     (markdown-test-range-has-face 3 3 'markdown-markup-face)))
   2283 
   2284 (ert-deftest test-markdown-font-lock/italics-6 ()
   2285   "Test multiline italics across list items."
   2286   (markdown-test-string
   2287       "* something about function foo_bar
   2288 * something else about foo_bar"
   2289     (markdown-test-range-has-face 31 34 nil)
   2290     (markdown-test-range-has-face 38 62 nil)))
   2291 
   2292 (ert-deftest test-markdown-font-lock/italics-8 ()
   2293   "Test multiline italics across list items."
   2294   (markdown-test-string
   2295       "* something about function
   2296   foo_bar
   2297 * something else about
   2298   foo_bar"
   2299     (markdown-test-range-has-face 30 36 nil)
   2300     (markdown-test-range-has-face 63 69 nil)))
   2301 
   2302 (ert-deftest test-markdown-font-lock/italics-9 ()
   2303   "Test multiline italics across list items."
   2304   (markdown-test-string
   2305       "foo_bar
   2306 * foo_bar"
   2307     (markdown-test-range-has-face 4 7 nil)
   2308     (markdown-test-range-has-face 11 14 nil)))
   2309 
   2310 (ert-deftest test-markdown-font-lock/italics-10 ()
   2311   "Underscores in URLs should not trigger italics."
   2312   (markdown-test-string
   2313       "<http://jblevins.org/research/centroid/cd_z_path.m>"
   2314     (markdown-test-range-face-equals 2 50 'markdown-plain-url-face)
   2315     (should-not (markdown-range-property-any 43 43 'face '(markdown-italic-face)))))
   2316 
   2317 (ert-deftest test-markdown-font-lock/italics-11 ()
   2318   "Underscores in URLs should not trigger italics."
   2319   (markdown-test-string
   2320       "[1]: http://jblevins.org/research/centroid/cd_z_path.m"
   2321     (markdown-test-range-face-equals 6 54 'markdown-url-face)))
   2322 
   2323 (ert-deftest test-markdown-font-lock/italics-12 ()
   2324   "Underscores in URLs should not trigger italics."
   2325   (markdown-test-string
   2326       "[cd\\_z\\_path.m](http://jblevins.org/research/centroid/cd_z_path.m)"
   2327     (markdown-test-range-face-equals 17 65 'markdown-url-face)))
   2328 
   2329 (ert-deftest test-markdown-font-lock/url-face-with-comma-and-parenthesis ()
   2330   "Test URL highlighting with comma and parenthesis.
   2331 Detail: https://github.com/jrblevin/markdown-mode/issues/649"
   2332   (markdown-test-string "<https://en.wikipedia.org/wiki/File:L%C3%A1szl%C3%B3_Moholy-Nagy,_nuclear_II,_1946_(milwaukee_art_museum).jpg>"
   2333     (markdown-test-range-face-equals 2 109 'markdown-plain-url-face)))
   2334 
   2335 (ert-deftest test-markdown-font-lock/italics-after-hr ()
   2336   "Test italics after a horizontal rule with asterisks."
   2337   (markdown-test-string "* * *\n\n*italic*\n"
   2338     (markdown-test-range-has-face 1 5 'markdown-hr-face)
   2339     (markdown-test-range-has-face 8 8 'markdown-markup-face)
   2340     (markdown-test-range-has-face 9 14 'markdown-italic-face)
   2341     (markdown-test-range-has-face 15 15 'markdown-markup-face)))
   2342 
   2343 (ert-deftest test-markdown-font-lock/italics-in-heading ()
   2344   "Test italic overlay in a heading."
   2345   (markdown-test-string
   2346       "# *Italics* in a Heading"
   2347     (markdown-test-range-has-face 3 3 'markdown-markup-face)
   2348     (markdown-test-range-has-face 4 10 'markdown-italic-face)
   2349     (markdown-test-range-has-face 11 11 'markdown-markup-face)))
   2350 
   2351 (ert-deftest test-markdown-font-lock/italics-link ()
   2352   "Test italic overlay in an inline link."
   2353   (markdown-test-string
   2354       "*[italic link](http://www.link.com/)*"
   2355     (markdown-test-range-has-face 1 1 'markdown-markup-face)
   2356     (markdown-test-range-has-face 2 36 'markdown-italic-face)
   2357     (markdown-test-range-has-face 37 37 'markdown-markup-face))
   2358   (markdown-test-string
   2359       "[*italic link*](http://www.link.com/)"
   2360     (markdown-test-range-has-face 2 2 'markdown-markup-face)
   2361     (markdown-test-range-has-face 3 13 'markdown-italic-face)
   2362     (markdown-test-range-has-face 14 14 'markdown-markup-face)))
   2363 
   2364 (ert-deftest test-markdown-font-lock/italics-in-blockquote ()
   2365   "Test italics overlay in a blockquote."
   2366   (markdown-test-string
   2367       "> *italics* inside a blockquote"
   2368     (markdown-test-range-has-face 3 3 'markdown-markup-face)
   2369     (markdown-test-range-has-face 4 10 'markdown-italic-face)
   2370     (markdown-test-range-has-face 11 11 'markdown-markup-face)))
   2371 
   2372 (ert-deftest test-markdown-font-lock/italics-in-pre ()
   2373   "Test italics overlay in a blockquote."
   2374   (markdown-test-string
   2375       "    *italics* inside a pre block"
   2376     (markdown-test-range-has-face (point-min) (1- (point-max))
   2377                                   'markdown-pre-face)))
   2378 
   2379 (ert-deftest test-markdown-font-lock/italics-and-code ()
   2380   "Test seeming italics mixed with code."
   2381   (markdown-test-string
   2382       "define `var_1` and `var_2` inline code"
   2383     (markdown-test-range-has-face 9 13 'markdown-inline-code-face)
   2384     (markdown-test-range-has-face 21 25 'markdown-inline-code-face))
   2385   (markdown-test-string
   2386       "`var_1` and var_2"
   2387     (markdown-test-range-has-face 2 6 'markdown-inline-code-face)
   2388     (markdown-test-range-has-face 8 17 nil))
   2389   (markdown-test-string
   2390       "var_1 and `var_2`"
   2391     (markdown-test-range-has-face 1 10 nil)
   2392     (markdown-test-range-has-face 12 16 'markdown-inline-code-face)))
   2393 
   2394 (ert-deftest test-markdown-font-lock/code-in-italics ()
   2395   "Test inline code inside italics.
   2396 See GH-275."
   2397   (markdown-test-string
   2398       "*text `code` text*"
   2399     (markdown-test-range-has-face 1 1 'markdown-markup-face)
   2400     (markdown-test-range-has-face 2 17 'markdown-italic-face)
   2401     (markdown-test-range-has-face 7 7 'markdown-markup-face)
   2402     (markdown-test-range-has-face 8 11 'markdown-inline-code-face)
   2403     (markdown-test-range-has-face 12 12 'markdown-markup-face)
   2404     (markdown-test-range-has-face 18 18 'markdown-markup-face)))
   2405 
   2406 (ert-deftest test-markdown-font-lock/italics-in-reference-definitions ()
   2407   "Test not matching italics in reference definitions across lines."
   2408   (markdown-test-string
   2409       "[lg]: twilight_sm.png\n[sm]: twilight_lg.png"
   2410     (markdown-test-range-has-face 7 21 'markdown-url-face)
   2411     (markdown-test-range-has-face 22 22 nil)
   2412     (markdown-test-range-has-face 29 43 'markdown-url-face)
   2413     (markdown-test-range-has-face 28 28 nil)))
   2414 
   2415 (ert-deftest test-markdown-font-lock/italics-in-comment ()
   2416   "Test not matching italics in comments."
   2417   (markdown-test-string
   2418       "<!-- -*- coding: utf-8 -*- -->"
   2419     (markdown-test-range-has-face 1 30 'markdown-comment-face)
   2420     (should-not (markdown-range-property-any 1 30 'face '(markdown-italic-face)))))
   2421 
   2422 (ert-deftest test-markdown-font-lock/italics-in-html-attribute ()
   2423   "Test not matching italics in HTML attributes."
   2424   (markdown-test-string
   2425       "<meta a=\"b_c\" d=\"e_f\">"
   2426     (should-not (markdown-range-property-any 12 18 'face '(markdown-italic-face)))))
   2427 
   2428 (ert-deftest test-markdown-font-lock/italics-after-bold ()
   2429   "Test bold and italics on the same line.
   2430 See GH-223."
   2431   (markdown-test-string
   2432       "**foo** is a *bar*"
   2433     (markdown-test-range-has-face 1 2 'markdown-markup-face)
   2434     (markdown-test-range-has-face 3 5 'markdown-bold-face)
   2435     (markdown-test-range-has-face 6 7 'markdown-markup-face)
   2436     (should-not
   2437      (markdown-range-property-any 8 13 'face '(markdown-italic-face)))
   2438     (markdown-test-range-has-face 14 14 'markdown-markup-face)
   2439     (markdown-test-range-has-face 15 17 'markdown-italic-face)
   2440     (markdown-test-range-has-face 18 18 'markdown-markup-face)))
   2441 
   2442 (ert-deftest test-markdown-font-lock/italics-and-bold-and-punctual ()
   2443   "Test bold and italics and punctual character.
   2444 Detail: https://github.com/jrblevin/markdown-mode/issues/359"
   2445   (markdown-test-string
   2446       "**Fat**, normal *italic*, normal **fat**"
   2447     (markdown-test-range-has-face 1 2 'markdown-markup-face)
   2448     (markdown-test-range-has-face 3 5 'markdown-bold-face)
   2449     (markdown-test-range-has-face 6 7 'markdown-markup-face)
   2450     (should-not
   2451      (markdown-range-property-any 10 15 'face '(markdown-italic-face)))
   2452     (markdown-test-range-has-face 18 23 'markdown-italic-face)
   2453     (should-not
   2454      (markdown-range-property-any 27 32 'face '(markdown-italic-face)))
   2455     (markdown-range-property-any 36 38 'face '(markdown-bold-face))))
   2456 
   2457 (ert-deftest test-markdown-font-lock/italic-after-code-block ()
   2458   "Test italic fontification after code block.
   2459 Detail: https://github.com/jrblevin/markdown-mode/issues/548"
   2460   (markdown-test-string "`(`*italic*`)` plain text
   2461 *italic*"
   2462     (markdown-test-range-has-face 4 4 'markdown-markup-face)
   2463     (markdown-test-range-has-face 5 10 'markdown-italic-face)
   2464     (markdown-test-range-has-face 11 11 'markdown-markup-face)
   2465     (markdown-test-range-has-face 16 25 nil)
   2466     (markdown-test-range-has-face 27 27 'markdown-markup-face)
   2467     (markdown-test-range-has-face 28 33 'markdown-italic-face)
   2468     (markdown-test-range-has-face 34 34 'markdown-markup-face)))
   2469 
   2470 (ert-deftest test-markdown-font-lock/bold-1 ()
   2471   "A simple bold test."
   2472   (markdown-test-file "inline.text"
   2473     (goto-char 27)
   2474     (should (looking-at "\*\*"))
   2475     ;; Check face of char before leading asterisk
   2476     (markdown-test-range-has-face 26 26 nil)
   2477     ;; Check face of opening asterisks
   2478     (markdown-test-range-has-face 27 28 'markdown-markup-face)
   2479     ;; Check face of bold range
   2480     (markdown-test-range-has-face 29 33 'markdown-bold-face)
   2481     ;; Check face of closing asterisks
   2482     (markdown-test-range-has-face 34 35 'markdown-markup-face)
   2483     ;; Check face of point past leading asterisk
   2484     (markdown-test-range-has-face 36 36 nil)))
   2485 
   2486 (ert-deftest test-markdown-font-lock/bold-2 ()
   2487   "Test space after leading asterisks or underscores."
   2488   (markdown-test-string
   2489       "This is ** not bold**, nor __ is this__."
   2490     (should-not
   2491      (markdown-range-property-any
   2492       (point-min) (point-max) 'face '(markdown-bold-face)))))
   2493 
   2494 (ert-deftest test-markdown-font-lock/bold-3 ()
   2495   "Test escaped asterisk inside bold."
   2496   (markdown-test-string
   2497       "bold **\\***"
   2498     (markdown-test-range-has-face 1 5 nil)
   2499     (markdown-test-range-has-face 6 7 'markdown-markup-face)
   2500     (markdown-test-range-has-face 8 9 'markdown-bold-face)
   2501     (markdown-test-range-has-face 10 11 'markdown-markup-face)))
   2502 
   2503 (ert-deftest test-markdown-font-lock/bold-4 ()
   2504   "Test bold single letter."
   2505   (markdown-test-string
   2506       "**a**"
   2507     (markdown-test-range-has-face 1 2 'markdown-markup-face)
   2508     (markdown-test-range-has-face 3 3 'markdown-bold-face)
   2509     (markdown-test-range-has-face 4 5 'markdown-markup-face)))
   2510 
   2511 (ert-deftest test-markdown-font-lock/bold-after-hr ()
   2512   "Test bold after a horizontal rule with asterisks."
   2513   (markdown-test-string "* * *\n\n**bold**\n"
   2514     (markdown-test-range-has-face 1 5 'markdown-hr-face)
   2515     (markdown-test-range-has-face 8 9 'markdown-markup-face)
   2516     (markdown-test-range-has-face 10 13 'markdown-bold-face)
   2517     (markdown-test-range-has-face 14 15 'markdown-markup-face)))
   2518 
   2519 (ert-deftest test-markdown-font-lock/bold-link ()
   2520   "Test bold overlay in an inline link."
   2521   (markdown-test-string
   2522       "**[bold link](http://www.link.com/)**"
   2523     (markdown-test-range-has-face 1 2 'markdown-markup-face)
   2524     (markdown-test-range-has-face 3 35 'markdown-bold-face)
   2525     (markdown-test-range-has-face 36 37 'markdown-markup-face))
   2526   (markdown-test-string
   2527       "[**bold link**](http://www.link.com/)"
   2528     (markdown-test-range-has-face 2 3 'markdown-markup-face)
   2529     (markdown-test-range-has-face 4 12 'markdown-bold-face)
   2530     (markdown-test-range-has-face 13 14 'markdown-markup-face)))
   2531 
   2532 (ert-deftest test-markdown-font-lock/bold-in-blockquote ()
   2533   "Test bold overlay in a blockquote."
   2534   (markdown-test-string
   2535       "> **bold** inside a blockquote"
   2536     (markdown-test-range-has-face 3 4 'markdown-markup-face)
   2537     (markdown-test-range-has-face 5 8 'markdown-bold-face)
   2538     (markdown-test-range-has-face 9 10 'markdown-markup-face)))
   2539 
   2540 (ert-deftest test-markdown-font-lock/bold-in-pre ()
   2541   "Test bold overlay in a blockquote."
   2542   (markdown-test-string
   2543       "    **bold** inside a pre block"
   2544     (markdown-test-range-has-face (point-min) (1- (point-max))
   2545                                   'markdown-pre-face)))
   2546 
   2547 (ert-deftest test-markdown-font-lock/no-bold-in-code ()
   2548   "Bold markers in inline code should not trigger bold."
   2549   (markdown-test-string
   2550       "`def __init__(self):`"
   2551     (markdown-test-range-has-face 8 11 'markdown-inline-code-face)
   2552     (should-not (markdown-range-property-any
   2553                  (point-min) (point-max) 'face '(markdown-bold-face))))
   2554   (markdown-test-string
   2555       "`**foo` bar `baz**`"
   2556     (markdown-test-range-has-face 2 6 'markdown-inline-code-face)
   2557     (markdown-test-range-face-equals 9 11 nil)
   2558     (markdown-test-range-has-face 14 18 'markdown-inline-code-face)
   2559     (should-not (markdown-range-property-any
   2560                  (point-min) (point-max) 'face '(markdown-bold-face)))))
   2561 
   2562 (ert-deftest test-markdown-font-lock/no-bold-asterisk-and-underscore ()
   2563   "string wrap with single asterisk and single underscore is not bold.
   2564 Detail: https://github.com/jrblevin/markdown-mode/issues/325"
   2565   (markdown-test-string
   2566       "_*bold_* *_bold*_"
   2567     (should-not (markdown-range-property-any 3 6 'face '(markdown-bold-face)))
   2568     (should-not (markdown-range-property-any 11 14 'face '(markdown-bold-face)))))
   2569 
   2570 (ert-deftest test-markdown-font-lock/code-in-bold ()
   2571   "Test inline code inside bold."
   2572   (markdown-test-string
   2573       "**text `code` text**"
   2574     (markdown-test-range-has-face 1 2 'markdown-markup-face)
   2575     (markdown-test-range-has-face 3 18 'markdown-bold-face)
   2576     (markdown-test-range-has-face 8 8 'markdown-markup-face)
   2577     (markdown-test-range-has-face 9 12 'markdown-inline-code-face)
   2578     (markdown-test-range-has-face 13 13 'markdown-markup-face)
   2579     (markdown-test-range-has-face 19 20 'markdown-markup-face)))
   2580 
   2581 (ert-deftest test-markdown-font-lock/bold-in-comment ()
   2582   "Test not matching bold in comments."
   2583   (markdown-test-string
   2584       "<!-- **not bold** -->"
   2585     (markdown-test-range-has-face 1 21 'markdown-comment-face)
   2586     (should-not
   2587      (markdown-range-property-any 1 21 'face '(markdown-bold-face)))))
   2588 
   2589 (ert-deftest test-markdown-font-lock/no-bold-in-url ()
   2590   "Test not matching bold in plain URL links."
   2591   (markdown-test-string
   2592       "<https://example.com/__not-bold__>"
   2593     (should-not (markdown-range-property-any 23 30 'face '(markdown-bold-face)))))
   2594 
   2595 (ert-deftest test-markdown-font-lock/code-1 ()
   2596   "A simple inline code test."
   2597   (markdown-test-file "inline.text"
   2598     (goto-char 45)
   2599     (should (looking-at "`"))
   2600     ;; Regular code span
   2601     (markdown-test-range-has-face 45 45 'markdown-markup-face)
   2602     (markdown-test-range-has-face 46 49 'markdown-inline-code-face)
   2603     (markdown-test-range-has-face 50 50 'markdown-markup-face)
   2604     ;; Code containing backticks
   2605     (markdown-test-range-has-face 61 62 'markdown-markup-face)
   2606     (markdown-test-range-has-face 63 87 'markdown-inline-code-face)
   2607     (markdown-test-range-has-face 88 89 'markdown-markup-face)
   2608     ;; Seven backquotes in a row
   2609     (markdown-test-range-has-face 119 125 nil)
   2610     ;; Backquotes at beginning or end
   2611     (markdown-test-range-has-face 228 229 'markdown-markup-face)
   2612     (markdown-test-range-has-face 230 237 'markdown-inline-code-face)
   2613     (markdown-test-range-has-face 238 239 'markdown-markup-face)
   2614     (markdown-test-range-has-face 341 342 'markdown-markup-face)
   2615     (markdown-test-range-has-face 343 349 'markdown-inline-code-face)
   2616     (markdown-test-range-has-face 350 351 'markdown-markup-face)
   2617     ;; Backslash as final character
   2618     (markdown-test-range-has-face 460 460 'markdown-markup-face)
   2619     (markdown-test-range-has-face 461 467 'markdown-inline-code-face)
   2620     (markdown-test-range-has-face 468 468 'markdown-markup-face)
   2621     ;; Escaping of leading backquotes
   2622     (markdown-test-range-has-face 586 592 nil)
   2623     (markdown-test-range-has-face 597 603 nil)
   2624     ;; A code span crossing lines
   2625     (markdown-test-range-has-face 652 656 nil)
   2626     (markdown-test-range-has-face 657 657 'markdown-markup-face)
   2627     (markdown-test-range-has-face 658 665 'markdown-inline-code-face)
   2628     (markdown-test-range-has-face 666 666 'markdown-markup-face)
   2629     ;; Three backquotes: same line, across lines, not across blocks
   2630     (markdown-test-range-has-face 695 748 nil)
   2631     (markdown-test-range-has-face 749 750 'markdown-markup-face)
   2632     (markdown-test-range-has-face 751 755 'markdown-inline-code-face)
   2633     (markdown-test-range-has-face 756 757 'markdown-markup-face)
   2634     (markdown-test-range-has-face 758 805 nil)
   2635     (markdown-test-range-has-face 806 807 'markdown-markup-face)
   2636     (markdown-test-range-has-face 808 812 'markdown-inline-code-face)
   2637     (markdown-test-range-has-face 813 814 'markdown-markup-face)
   2638     (markdown-test-range-has-face 815 891 nil)
   2639     ))
   2640 
   2641 (ert-deftest test-markdown-font-lock/code-2 ()
   2642   "Multiple code spans in a row and on different lines."
   2643   (markdown-test-string "`foo` `bar` `baz`"
   2644     (markdown-test-range-has-face 1 1 'markdown-markup-face)
   2645     (markdown-test-range-has-face 2 4 'markdown-inline-code-face)
   2646     (markdown-test-range-has-face 5 5 'markdown-markup-face)
   2647     (markdown-test-range-has-face 6 6 nil)
   2648     (markdown-test-range-has-face 7 7 'markdown-markup-face)
   2649     (markdown-test-range-has-face 8 10 'markdown-inline-code-face)
   2650     (markdown-test-range-has-face 11 11 'markdown-markup-face)
   2651     (markdown-test-range-has-face 12 12 nil)
   2652     (markdown-test-range-has-face 13 13 'markdown-markup-face)
   2653     (markdown-test-range-has-face 14 16 'markdown-inline-code-face)
   2654     (markdown-test-range-has-face 17 17 'markdown-markup-face))
   2655   (markdown-test-string "`a`\n`b`\n`c`\n"
   2656     (markdown-test-range-has-face 1 1 'markdown-markup-face)
   2657     (markdown-test-range-has-face 2 2 'markdown-inline-code-face)
   2658     (markdown-test-range-has-face 3 3 'markdown-markup-face)
   2659     (markdown-test-range-has-face 4 4 nil)
   2660     (markdown-test-range-has-face 5 5 'markdown-markup-face)
   2661     (markdown-test-range-has-face 6 6 'markdown-inline-code-face)
   2662     (markdown-test-range-has-face 7 7 'markdown-markup-face)
   2663     (markdown-test-range-has-face 8 8 nil)
   2664     (markdown-test-range-has-face 9 9 'markdown-markup-face)
   2665     (markdown-test-range-has-face 10 10 'markdown-inline-code-face)
   2666     (markdown-test-range-has-face 11 11 'markdown-markup-face)
   2667     (markdown-test-range-has-face 12 12 nil))
   2668   (markdown-test-string "a`foo`b`bar`c`baz`d"
   2669     (markdown-test-range-has-face 1 1 nil)
   2670     (markdown-test-range-has-face 2 2 'markdown-markup-face)
   2671     (markdown-test-range-has-face 3 5 'markdown-inline-code-face)
   2672     (markdown-test-range-has-face 6 6 'markdown-markup-face)
   2673     (markdown-test-range-has-face 7 7 nil)
   2674     (markdown-test-range-has-face 8 8 'markdown-markup-face)
   2675     (markdown-test-range-has-face 9 11 'markdown-inline-code-face)
   2676     (markdown-test-range-has-face 12 12 'markdown-markup-face)
   2677     (markdown-test-range-has-face 13 13 nil)
   2678     (markdown-test-range-has-face 14 14 'markdown-markup-face)
   2679     (markdown-test-range-has-face 15 17 'markdown-inline-code-face)
   2680     (markdown-test-range-has-face 18 18 'markdown-markup-face)
   2681     (markdown-test-range-has-face 19 19 nil)))
   2682 
   2683 (ert-deftest test-markdown-font-lock/code-3 ()
   2684   "Backslashes don't escape backticks inside of inline code strings."
   2685   (markdown-test-string
   2686       "`foo\\`bar`"
   2687     (markdown-test-range-has-face 1 1 'markdown-markup-face)
   2688     (markdown-test-range-has-face 2 5 'markdown-inline-code-face)
   2689     (markdown-test-range-has-face 6 6 'markdown-markup-face)
   2690     (markdown-test-range-has-face 7 10 nil)))
   2691 
   2692 (ert-deftest test-markdown-font-lock/code-link-precedence ()
   2693   "Test that inline code takes precedence over inline links."
   2694   (markdown-test-string
   2695       "[not a `link](/foo`)"
   2696     (markdown-test-range-has-face 1 7 nil)
   2697     (markdown-test-range-has-face 8 8 'markdown-markup-face)
   2698     (markdown-test-range-has-face 9 18 'markdown-inline-code-face)
   2699     (markdown-test-range-has-face 19 19 'markdown-markup-face)
   2700     (markdown-test-range-has-face 20 20 nil)))
   2701 
   2702 (ert-deftest test-markdown-font-lock/code-in-link-text ()
   2703   "Test that inline code in link text is fontified properly"
   2704   (markdown-test-string
   2705       "[`this is a` link](/foo)"
   2706     (markdown-test-range-has-face 1 2 'markdown-markup-face)
   2707     (markdown-test-range-has-face 3 11 'markdown-inline-code-face)
   2708     (markdown-test-range-has-face 12 12 'markdown-markup-face)
   2709     (markdown-test-range-has-face 3 17 'markdown-link-face)
   2710     (markdown-test-range-has-face 18 19 'markdown-markup-face)
   2711     (markdown-test-range-has-face 20 23 'markdown-url-face)
   2712     (markdown-test-range-has-face 24 24 'markdown-markup-face)))
   2713 
   2714 (ert-deftest test-markdown-font-lock/code-italics-precedence ()
   2715   "Test that inline code takes precedence over italics.
   2716 Test currently fails because this case isn't handled properly."
   2717   (markdown-test-string
   2718       "*text `code* text`"
   2719     (markdown-test-range-has-face 1 6 nil)
   2720     (markdown-test-range-has-face 7 7 'markdown-markup-face)
   2721     (markdown-test-range-has-face 8 17 'markdown-inline-code-face)
   2722     (markdown-test-range-has-face 18 18 'markdown-markup-face)))
   2723 
   2724 (ert-deftest test-markdown-font-lock/code-in-comment ()
   2725   "Test that inline code is not matched inside a comment."
   2726   (markdown-test-string
   2727       "<!-- `not code` -->"
   2728     (markdown-test-range-has-face 1 19 'markdown-comment-face)
   2729     (should-not (markdown-range-property-any 1 19 'face '(markdown-inline-code-face)))))
   2730 
   2731 (ert-deftest test-markdown-font-lock/consecutive-html-comments ()
   2732   "Test for consecutive HTML comments.
   2733 Detail: https://github.com/jrblevin/markdown-mode/issues/584"
   2734   (markdown-test-string
   2735       "Main text <!--a comment--><!--another comment-->."
   2736     (markdown-test-range-has-face 11 26 'markdown-comment-face)
   2737     (markdown-test-range-has-face 27 28 'markdown-comment-face)))
   2738 
   2739 (ert-deftest test-markdown-font-lock/kbd ()
   2740   "Test font lock for <kbd> tags."
   2741   (markdown-test-string "<kbd>C-c <</kbd>"
   2742     (markdown-test-range-has-face 1 5 'markdown-markup-face)
   2743     (markdown-test-range-has-face 6 10 'markdown-inline-code-face)
   2744     (markdown-test-range-has-face 11 16 'markdown-markup-face))
   2745   (markdown-test-string "To quit Emacs, press <kbd>C-x C-c</kbd>."
   2746     (markdown-test-range-has-face 1 21 nil)
   2747     (markdown-test-range-has-face 22 26 'markdown-markup-face)
   2748     (markdown-test-range-has-face 27 33 'markdown-inline-code-face)
   2749     (markdown-test-range-has-face 34 39 'markdown-markup-face)
   2750     (markdown-test-range-has-face 40 40 nil)))
   2751 
   2752 (ert-deftest test-markdown-font-lock/lists-1 ()
   2753   "A simple list marker font lock test."
   2754   (markdown-test-file "lists.text"
   2755     (dolist (loc (list 1063 1283 1659 1830 1919 2150 2393 2484
   2756                        2762 2853 3097 3188 3700 3903 4009))
   2757       (goto-char loc)
   2758       (should (looking-at "[*+-]"))
   2759       (markdown-test-range-has-face loc loc 'markdown-list-face))))
   2760 
   2761 (ert-deftest test-markdown-font-lock/lists-2 ()
   2762   "Test markdown-list-face with markdown-list-indent-width.
   2763 See https://github.com/jrblevin/markdown-mode/issues/405 ."
   2764   (let ((markdown-list-indent-width 2))
   2765     (markdown-test-string "
   2766 * level 1
   2767   * level 2
   2768     * level 3
   2769       * level 4
   2770         * level 5"
   2771       (markdown-test-range-has-face 62 62 'markdown-list-face))))
   2772 
   2773 (ert-deftest test-markdown-font-lock/lists-3 ()
   2774   "Test markdown-list-face for too intended line.
   2775 Too indented line is also treated as list rf previous line is line
   2776 in Common mark.
   2777 See https://github.com/jrblevin/markdown-mode/issues/569"
   2778   (markdown-test-string "* [ ] One
   2779   * [ ] Two
   2780     * [ ] Three
   2781       * [ ] Four
   2782         * [ ] Five
   2783           * [ ] Six"
   2784     (markdown-test-range-has-face 64 64 'markdown-list-face)
   2785     (markdown-test-range-has-face 85 85 'markdown-list-face)))
   2786 
   2787 (ert-deftest test-markdown-font-lock/lists-in-code-block ()
   2788   "Test markdown-list-face in code block like diff format.
   2789 See https://github.com/jrblevin/markdown-mode/issues/631"
   2790   (markdown-test-string "```diff
   2791 - plugins=(...)
   2792 + plugins=(... fzf-collection)
   2793 ```
   2794 "
   2795     (should-not (markdown-range-property-any 9 9 'face '(markdown-list-face)))
   2796     (should-not (markdown-range-property-any 16 16 'face '(markdown-list-face)))))
   2797 
   2798 
   2799 (ert-deftest test-markdown-font-lock/repeated-lists ()
   2800   "A simple definition list marker font lock test."
   2801   (markdown-test-file "repeated-elements.text"
   2802     (markdown-test-range-has-face 163 164 'markdown-list-face)
   2803     (markdown-test-range-has-face 190 191 'markdown-list-face)))
   2804 
   2805 (ert-deftest test-markdown-font-lock/repeated-tables ()
   2806   "A simple definition list marker font lock test."
   2807   (markdown-test-file "repeated-elements.text"
   2808     (markdown-test-range-has-face 149 155 nil)
   2809     (markdown-test-range-has-face 218 336 'markdown-table-face)))
   2810 
   2811 (ert-deftest test-markdown-font-lock/definition-list ()
   2812   "A simple definition list marker font lock test."
   2813   (markdown-test-file "definition-list.text"
   2814     (markdown-test-range-has-face 7 7 'markdown-list-face)
   2815     (markdown-test-range-has-face 29 52 'markdown-pre-face)
   2816     (markdown-test-range-has-face 55 55 'markdown-list-face)))
   2817 
   2818 (ert-deftest test-markdown-font-lock/pre-1 ()
   2819   "Nested list and pre block font lock test."
   2820   (markdown-test-file "nested-list.text"
   2821     (dolist (loc (list 4 29 194 224 491 525))
   2822       (markdown-test-range-has-face loc loc 'markdown-list-face))
   2823     (markdown-test-range-has-face 6 25 nil)
   2824     (markdown-test-range-has-face 31 83 nil)
   2825     (markdown-test-range-has-face 85 154 'markdown-pre-face)
   2826     (markdown-test-range-has-face 157 189 nil)
   2827     (markdown-test-range-has-face 196 215 nil)
   2828     (markdown-test-range-has-face 226 403 nil)
   2829     (markdown-test-range-has-face 405 481 'markdown-pre-face)
   2830     (markdown-test-range-has-face 493 512 nil)
   2831     (markdown-test-range-has-face 527 546 nil)
   2832     (markdown-test-range-has-face 548 580 'markdown-pre-face)))
   2833 
   2834 (ert-deftest test-markdown-font-lock/pre-2 ()
   2835   (markdown-test-string "* item\n\nreset baseline\n\n    pre block\n"
   2836     (markdown-test-range-has-face 1 1 'markdown-list-face)
   2837     (markdown-test-range-has-face 2 23 nil)
   2838     (markdown-test-range-has-face 29 37 'markdown-pre-face)))
   2839 
   2840 (ert-deftest test-markdown-font-lock/pre-3 ()
   2841   (markdown-test-string "It is interesting to see what happens when one queries
   2842 `social upheaval` and `protopalatial era`.
   2843 
   2844 * `social upheaval`: the following queries have been tried:
   2845 
   2846     social upheaval subClassOf"
   2847     (markdown-test-range-has-face 160 190 nil)))
   2848 
   2849 (ert-deftest test-markdown-font-lock/pre-4 ()
   2850   "Pre blocks must be preceded by a blank line"
   2851   (markdown-test-string "Paragraph
   2852     for (var i = 0; i < 10; i++) {
   2853         console.log(i);
   2854     }"
   2855     (markdown-test-range-has-face (point-min) (point-max) nil)))
   2856 
   2857 (ert-deftest test-markdown-font-lock/fenced-1 ()
   2858   "Test fenced code blocks containing four-space indents."
   2859   (markdown-test-string "Fenced code block
   2860 
   2861 ~~~
   2862 if (x)
   2863     foo();
   2864 
   2865 if (y)
   2866     bar();
   2867 ~~~
   2868 "
   2869     (markdown-test-range-has-face 1 19 nil)
   2870     (markdown-test-range-has-face 20 22 'markdown-markup-face)
   2871     (markdown-test-range-has-face 24 59 'markdown-pre-face)
   2872     (markdown-test-range-has-face 61 63 'markdown-markup-face)))
   2873 
   2874 (ert-deftest test-markdown-font-lock/gfm-fenced-1 ()
   2875   "Test GFM-style fenced code blocks (1)."
   2876   (let ((markdown-fontify-code-blocks-natively t))
   2877     (markdown-test-string "```ruby
   2878 require 'redcarpet'
   2879 markdown = Redcarpet.new('Hello World!')
   2880 puts markdown.to_html
   2881 ```"
   2882       (markdown-test-range-has-face 1 3 'markdown-markup-face) ; ```
   2883       (markdown-test-range-has-face 4 7 'markdown-language-keyword-face) ; ruby
   2884       (markdown-test-range-has-face 9 90 'markdown-code-face) ; entire code block
   2885       (markdown-test-range-has-face 9 15 'font-lock-builtin-face) ; require
   2886       (markdown-test-range-has-face 17 27 'font-lock-string-face) ; 'redcarpet'
   2887       (markdown-test-range-has-face 40 48 'font-lock-type-face) ; Redcarpet
   2888       (markdown-test-range-has-face 70 72 'font-lock-builtin-face) ; puts
   2889       (markdown-test-range-has-face 92 94 'markdown-markup-face)))) ; ```
   2890 
   2891 (ert-deftest test-markdown-font-lock/gfm-fenced-2 ()
   2892   "Test GFM-style fenced code blocks (2)."
   2893   (markdown-test-string "```{r sum}\n2+2\n```"
   2894     (markdown-test-range-has-face 1 3 'markdown-markup-face) ; ```
   2895     (markdown-test-range-has-face 4 4 'markdown-markup-face) ; {
   2896     (markdown-test-range-has-face 5 5 'markdown-language-keyword-face) ; r
   2897     (markdown-test-range-has-face 7 9 'markdown-language-info-face) ; sum
   2898     (markdown-test-range-has-face 10 10 'markdown-markup-face) ; }
   2899     (markdown-test-range-has-face 12 14 'markdown-pre-face) ; 2+2
   2900     (markdown-test-range-has-face 16 18 'markdown-markup-face))) ; ```
   2901 
   2902 (ert-deftest test-markdown-font-lock/gfm-fenced-3 ()
   2903   "GFM-style code blocks need not be preceded by a blank line."
   2904   (markdown-test-string "Paragraph
   2905 ```js
   2906 for (var i = 0; i < 10; i++) {
   2907     console.log(i);
   2908 }
   2909 ```"
   2910     (markdown-test-range-has-face 1 10 nil) ; Paragraph
   2911     (markdown-test-range-has-face 11 13 'markdown-markup-face) ; ```
   2912     (markdown-test-range-has-face 14 15 'markdown-language-keyword-face) ; js
   2913     (markdown-test-range-has-face 17 68 'markdown-pre-face)
   2914     (markdown-test-range-has-face 70 72 'markdown-markup-face)))
   2915 
   2916 (ert-deftest test-markdown-font-lock/gfm-fenced-4 ()
   2917   "Test GFM-style fenced code blocks (2)."
   2918   (markdown-test-string "```scalaFiddle libraries=\"Java8 Time-0.1.0\"\nimport java.time._\n\nval hour = LocalTime.now().getHour()\n\nprintln(hour)\n```"
   2919     (markdown-test-range-has-face 1 3 'markdown-markup-face) ; ```
   2920     (markdown-test-range-has-face 4 14 'markdown-language-keyword-face) ; scalaFiddle
   2921     (markdown-test-range-has-face 16 43 'markdown-language-info-face) ; libraries="Java8 Time-0.1.0"
   2922     (markdown-test-range-has-face 45 115 'markdown-pre-face) ; [code]
   2923     (markdown-test-range-has-face 117 119 'markdown-markup-face))) ; ```
   2924 
   2925 (ert-deftest test-markdown-font-lock/tilde-fenced-1 ()
   2926   "Test native fontification of tilde fenced code blocks."
   2927   (let ((markdown-fontify-code-blocks-natively t))
   2928     (markdown-test-string "~~~ruby
   2929 require 'redcarpet'
   2930 markdown = Redcarpet.new('Hello World!')
   2931 puts markdown.to_html
   2932 ~~~"
   2933       (markdown-test-range-has-face 1 3 'markdown-markup-face) ; ```
   2934       (markdown-test-range-has-face 4 7 'markdown-language-keyword-face) ; ruby
   2935       (markdown-test-range-has-face 9 90 'markdown-code-face) ; entire code block
   2936       (markdown-test-range-has-face 9 15 'font-lock-builtin-face) ; require
   2937       (markdown-test-range-has-face 17 27 'font-lock-string-face) ; 'redcarpet'
   2938       (markdown-test-range-has-face 40 48 'font-lock-type-face) ; Redcarpet
   2939       (markdown-test-range-has-face 70 72 'font-lock-builtin-face) ; puts
   2940       (markdown-test-range-has-face 92 94 'markdown-markup-face)))) ; ```
   2941 
   2942 (ert-deftest test-markdown-font-lock/atx-no-spaces ()
   2943   "Test font-lock for atx headers with no spaces."
   2944   (markdown-test-string "##abc##"
   2945     (markdown-test-range-has-face 1 7 nil))
   2946   (markdown-test-string "##"
   2947     (markdown-test-range-has-face 1 2 nil))
   2948   (markdown-test-string "###"
   2949     (markdown-test-range-has-face 1 3 nil)))
   2950 
   2951 (ert-deftest test-markdown-font-lock/setext-1-letter ()
   2952   "An edge case for level-one setext headers."
   2953   (markdown-test-string "a\n=\n"
   2954     (markdown-test-range-has-face 1 1 'markdown-header-face-1)
   2955     (markdown-test-range-has-face 3 3 'markdown-header-rule-face)))
   2956 
   2957 (ert-deftest test-markdown-font-lock/setext-2-letter ()
   2958   "An edge case for level-two setext headers."
   2959   (markdown-test-string "b\n-\n"
   2960     (markdown-test-range-has-face 1 1 'markdown-header-face-2)
   2961     (markdown-test-range-has-face 3 3 'markdown-header-rule-face)))
   2962 
   2963 (ert-deftest test-markdown-font-lock/inline-links ()
   2964   "Test font lock for inline links."
   2965   (let ((markdown-hide-urls nil))
   2966     (markdown-test-file "inline.text"
   2967       (markdown-test-range-has-face 925 925 'markdown-markup-face)
   2968       (markdown-test-range-has-face 926 929 'markdown-link-face)
   2969       (markdown-test-range-has-face 930 931 'markdown-markup-face)
   2970       (markdown-test-range-has-face 932 949 'markdown-url-face)
   2971       (markdown-test-range-has-face 951 957 'markdown-link-title-face)
   2972       (markdown-test-range-has-face 958 958 'markdown-markup-face))))
   2973 
   2974 (ert-deftest test-markdown-font-lock/inline-links-with-parentheses ()
   2975   "Test font lock for inline links with nested parentheses.
   2976 See <https://github.com/jrblevin/markdown-mode/issues/170>."
   2977   (let ((markdown-hide-urls nil))
   2978     (markdown-test-string "[foo](bar(baz)qux)"
   2979       (markdown-test-range-has-face 1 1 'markdown-markup-face)
   2980       (markdown-test-range-has-face 2 4 'markdown-link-face)
   2981       (markdown-test-range-has-face 5 6 'markdown-markup-face)
   2982       (markdown-test-range-has-face 7 17 'markdown-url-face)
   2983       (markdown-test-range-has-face 18 18 'markdown-markup-face))))
   2984 
   2985 (ert-deftest test-markdown-font-lock/inline-links-with-escaped-bracket ()
   2986   "Test font lock for inline links with escaped bracket.
   2987 Detail: https://github.com/jrblevin/markdown-mode/issues/409"
   2988   (markdown-test-string "[run(Class, String \\[\\])](http://foo.com)"
   2989     (markdown-test-range-has-face 1 1 'markdown-markup-face)
   2990     (markdown-test-range-has-face 2 24 'markdown-link-face)
   2991     (markdown-test-range-has-face 25 26 'markdown-markup-face)
   2992     (markdown-test-range-has-face 27 40 'markdown-url-face)
   2993     (markdown-test-range-has-face 41 41 'markdown-markup-face)))
   2994 
   2995 (ert-deftest test-markdown-font-lock/pre-comment ()
   2996   "Test comments inside of a pre block."
   2997   (markdown-test-string "    <!-- pre, not comment -->"
   2998     (markdown-test-range-has-face (point-min) (1- (point-max)) 'markdown-pre-face)))
   2999 
   3000 (ert-deftest test-markdown-font-lock/inline-code-comment ()
   3001   "Test comments inside of inline code."
   3002   (markdown-test-string "`<h1> <!-- HTML comment inside inline code -->`"
   3003     (markdown-test-range-has-face (1+ (point-min)) (- (point-max) 2) 'markdown-inline-code-face)))
   3004 
   3005 (ert-deftest test-markdown-font-lock/inline-code-link ()
   3006   "Test links inside of inline code."
   3007   (markdown-test-string "`[text](url)`"
   3008     (markdown-test-range-has-face (1+ (point-min)) (- (point-max) 2) 'markdown-inline-code-face)
   3009     (should-not (markdown-range-property-any
   3010                  (1+ (point-min)) (- (point-max) 2) 'face
   3011                  '(markdown-markup-face markdown-link-face markdown-url-face)))))
   3012 
   3013 (ert-deftest test-markdown-font-lock/comment-hanging-indent ()
   3014   "Test comments with hanging indentation."
   3015   (markdown-test-string "<!-- This comment has\n    hanging indentation -->"
   3016     (markdown-test-range-has-face (point-min) (1- (point-max)) 'markdown-comment-face)))
   3017 
   3018 (ert-deftest test-markdown-font-lock/comment-multiple ()
   3019   "Test multiple single-line comments in arow."
   3020   (markdown-test-string "<!-- This is a comment -->\n<!-- And so is this -->"
   3021     (markdown-test-range-has-face
   3022      (point-at-bol) (1- (point-at-eol)) 'markdown-comment-face)
   3023     (forward-line)
   3024     (markdown-test-range-has-face
   3025      (point-at-bol) (1- (point-at-eol)) 'markdown-comment-face)))
   3026 
   3027 (ert-deftest test-markdown-font-lock/comment-list-items ()
   3028   "Test comment with list inside."
   3029   (markdown-test-string
   3030       "<!--
   3031   - note 1;
   3032   - note 2.
   3033 -->"
   3034     (markdown-test-range-face-equals (point-min) (1- (point-max))
   3035                                      'markdown-comment-face)))
   3036 
   3037 (ert-deftest test-markdown-font-lock/comment-angle-bracket ()
   3038   "Regression test for GH-117."
   3039   (markdown-test-string "<!-- > test -->"
   3040     (markdown-test-range-face-equals (point-min) (1- (point-max))
   3041                                      'markdown-comment-face)))
   3042 
   3043 (ert-deftest test-markdown-font-lock/comment-link ()
   3044   "Test links inside of comments."
   3045   (markdown-test-string "<!-- [text](url) -->"
   3046     (markdown-test-range-has-face (+ (point-min) 5) (- (point-max) 4) 'markdown-comment-face)
   3047     (should-not (markdown-range-property-any
   3048                  (+ (point-min) 5) (- (point-max) 4) 'face
   3049                  '(markdown-markup-face markdown-link-face markdown-url-face)))))
   3050 
   3051 (ert-deftest test-markdown-font-lock/footnote-markers-links ()
   3052   "Test an edge case involving footnote markers and inline reference links."
   3053   (markdown-test-string "Harvard[^1] [tuition][]"
   3054     (markdown-test-range-has-face 1 7 nil)
   3055     (markdown-test-range-has-face 8 8 'markdown-markup-face)
   3056     (markdown-test-range-has-face 10 10 'markdown-footnote-marker-face)
   3057     (markdown-test-range-has-face 11 11 'markdown-markup-face)
   3058     (markdown-test-range-has-face 12 12 nil)
   3059     (markdown-test-range-has-face 13 13 'markdown-markup-face)
   3060     (markdown-test-range-has-face 14 20 'markdown-link-face)
   3061     (markdown-test-range-has-face 21 21 'markdown-markup-face)
   3062     (markdown-test-range-has-face 22 23 'markdown-markup-face)))
   3063 
   3064 (ert-deftest test-markdown-font-lock/mmd-metadata ()
   3065   "Basic MultMarkdown metadata tests."
   3066   (markdown-test-string "Title: peg-multimarkdown User's Guide
   3067 Author: Fletcher T. Penney
   3068 Base Header Level: 2"
   3069     (markdown-test-range-has-face 1 5 'markdown-metadata-key-face)
   3070     (markdown-test-range-has-face 6 6 'markdown-markup-face)
   3071     (markdown-test-range-has-face 8 37 'markdown-metadata-value-face)
   3072     (markdown-test-range-has-face 39 44 'markdown-metadata-key-face)
   3073     (markdown-test-range-has-face 46 46 'markdown-markup-face)
   3074     (markdown-test-range-has-face 47 64 'markdown-metadata-value-face)
   3075     (markdown-test-range-has-face 66 82 'markdown-metadata-key-face)
   3076     (markdown-test-range-has-face 83 83 'markdown-markup-face)
   3077     (markdown-test-range-has-face 85 85 'markdown-metadata-value-face))
   3078   ;; Avoid triggering when a title contains a colon (e.g., Markdown: Syntax)
   3079   (markdown-test-file "syntax.text"
   3080     (markdown-test-range-has-face 1 16 'markdown-header-face-1)))
   3081 
   3082 (ert-deftest test-markdown-font-lock/mmd-metadata-after-header ()
   3083   "Ensure that similar lines are not matched after the header."
   3084   (markdown-test-string "Title: peg-multimarkdown User's Guide
   3085 
   3086 Author: Fletcher T. Penney
   3087 Base Header Level: 2"
   3088     (markdown-test-range-has-face 1 5 'markdown-metadata-key-face)
   3089     (markdown-test-range-has-face 6 6 'markdown-markup-face)
   3090     (markdown-test-range-has-face 8 37 'markdown-metadata-value-face)
   3091     (markdown-test-range-has-face 40 65 nil)
   3092     (markdown-test-range-has-face 67 86 nil)))
   3093 
   3094 (ert-deftest test-markdown-font-lock/mmd-metadata-after-header-with-whitespace ()
   3095   "Ensure that similar lines are not matched after the header.
   3096 The blank line here has two spaces, which should not change how
   3097 it is parsed."
   3098   (markdown-test-string
   3099       "Title: peg-multimarkdown User's Guide\n  \nAuthor: Fletcher T. Penney\nBase Header Level: 2\n"
   3100     (markdown-test-range-has-face 1 5 'markdown-metadata-key-face)
   3101     (markdown-test-range-has-face 6 6 'markdown-markup-face)
   3102     (markdown-test-range-has-face 8 37 'markdown-metadata-value-face)
   3103     (markdown-test-range-has-face 42 67 nil)
   3104     (markdown-test-range-has-face 69 88 nil)))
   3105 
   3106 (ert-deftest test-markdown-font-lock/mmd-not-metadata ()
   3107   "Don't treat as metadata if its line is not in header
   3108 https://github.com/jrblevin/markdown-mode/issues/437"
   3109   (markdown-test-string "hello world
   3110 foo bar baz: one two three
   3111 "
   3112     (markdown-test-range-has-face 13 39 nil)))
   3113 
   3114 (ert-deftest test-markdown-font-lock/pandoc-metadata ()
   3115   "Basic Pandoc metadata tests."
   3116   (markdown-test-string "% title
   3117   two-line title
   3118 % first author;
   3119   second author
   3120 % date
   3121 
   3122 body"
   3123     (markdown-test-range-has-face 1 1 'markdown-markup-face)
   3124     (markdown-test-range-has-face 3 24 'markdown-metadata-value-face)
   3125     (markdown-test-range-has-face 26 26 'markdown-markup-face)
   3126     (markdown-test-range-has-face 28 56 'markdown-metadata-value-face)
   3127     (markdown-test-range-has-face 58 58 'markdown-markup-face)
   3128     (markdown-test-range-has-face 60 63 'markdown-metadata-value-face)
   3129     (markdown-test-range-has-face 64 69 nil)))
   3130 
   3131 (ert-deftest test-markdown-font-lock/yaml-metadata ()
   3132   "Basic YAML metadata tests."
   3133   (markdown-test-string
   3134       "---
   3135 layout: post
   3136 date: 2015-08-13 11:35:25 EST
   3137 ---
   3138 "
   3139     (markdown-test-range-has-face 1 3 'markdown-markup-face)
   3140     (markdown-test-range-has-face 5 10 'markdown-metadata-key-face)
   3141     (markdown-test-range-has-face 11 11 'markdown-markup-face)
   3142     (markdown-test-range-has-face 13 16 'markdown-metadata-value-face)
   3143     (markdown-test-range-has-face 18 21 'markdown-metadata-key-face)
   3144     (markdown-test-range-has-face 22 22 'markdown-markup-face)
   3145     (markdown-test-range-has-face 24 46 'markdown-metadata-value-face)
   3146     (markdown-test-range-has-face 48 50 'markdown-markup-face)))
   3147 
   3148 (ert-deftest test-markdown-font-lock/toml-metadata ()
   3149   "Basic TOML metadata tests."
   3150   (markdown-test-string
   3151       "---
   3152 layout = post
   3153 date = 2015-08-13 11:35:25 EST
   3154 ---
   3155 "
   3156     (markdown-test-range-has-face 1 3 'markdown-markup-face)
   3157     (markdown-test-range-has-face 5 10 'markdown-metadata-key-face)
   3158     (markdown-test-range-has-face 12 12 'markdown-markup-face)
   3159     (markdown-test-range-has-face 14 17 'markdown-metadata-value-face)
   3160     (markdown-test-range-has-face 19 22 'markdown-metadata-key-face)
   3161     (markdown-test-range-has-face 24 24 'markdown-markup-face)
   3162     (markdown-test-range-has-face 26 48 'markdown-metadata-value-face)
   3163     (markdown-test-range-has-face 50 52 'markdown-markup-face)))
   3164 
   3165 (ert-deftest test-markdown-font-lock/pandoc-yaml-metadata ()
   3166   "Basic yaml metadata tests, with pandoc syntax."
   3167   (let ((markdown-use-pandoc-style-yaml-metadata t))
   3168     (markdown-test-string
   3169         "some text
   3170 
   3171 ---
   3172 layout: post
   3173 date: 2015-08-13 11:35:25 EST
   3174 ...
   3175 
   3176 more text
   3177 
   3178 ---
   3179 layout: post
   3180 date: 2015-08-13 11:35:25 EST
   3181 ---
   3182 
   3183 But this is merely a code block
   3184 
   3185 ```
   3186 ---
   3187 layout: post
   3188 date: 2015-08-13 11:35:25 EST
   3189 ---
   3190 ```
   3191 "
   3192       ;; first section
   3193       (markdown-test-range-has-face 12 14 'markdown-markup-face)
   3194       (markdown-test-range-has-face 16 21 'markdown-metadata-key-face)
   3195       (markdown-test-range-has-face 22 22 'markdown-markup-face)
   3196       (markdown-test-range-has-face 24 27 'markdown-metadata-value-face)
   3197       (markdown-test-range-has-face 29 32 'markdown-metadata-key-face)
   3198       (markdown-test-range-has-face 33 33 'markdown-markup-face)
   3199       (markdown-test-range-has-face 35 57 'markdown-metadata-value-face)
   3200       (markdown-test-range-has-face 59 61 'markdown-markup-face)
   3201       ;; second section
   3202       (markdown-test-range-has-face 75 77 'markdown-markup-face)
   3203       (markdown-test-range-has-face 79 84 'markdown-metadata-key-face)
   3204       (markdown-test-range-has-face 85 85 'markdown-markup-face)
   3205       (markdown-test-range-has-face 87 90 'markdown-metadata-value-face)
   3206       (markdown-test-range-has-face 92 95 'markdown-metadata-key-face)
   3207       (markdown-test-range-has-face 96 96 'markdown-markup-face)
   3208       (markdown-test-range-has-face 98 120 'markdown-metadata-value-face)
   3209       (markdown-test-range-has-face 122 124 'markdown-markup-face)
   3210       ;; third section
   3211       (markdown-test-range-has-face 160 162 'markdown-markup-face)
   3212       (markdown-test-range-has-face 164 213 'markdown-pre-face)
   3213       (markdown-test-range-has-face 215 217 'markdown-markup-face))))
   3214 
   3215 (ert-deftest test-markdown-font-lock/yaml-metadata-nested ()
   3216   "Test font lock for metadata which has nested values
   3217 Detail: https://github.com/jrblevin/markdown-mode/issues/476"
   3218   (markdown-test-string
   3219       "---
   3220 references:
   3221 - type: article-journal
   3222   author:
   3223   - family: Watson
   3224     given: J. D.
   3225 ---
   3226 "
   3227     (markdown-test-range-has-face 5 14 'markdown-metadata-key-face)
   3228     (markdown-test-range-has-face 19 22 'markdown-metadata-key-face)
   3229     (markdown-test-range-has-face 25 39 'markdown-metadata-value-face)
   3230     (markdown-test-range-has-face 43 48 'markdown-metadata-key-face)
   3231     (markdown-test-range-has-face 55 60 'markdown-metadata-key-face)
   3232     (markdown-test-range-has-face 63 68 'markdown-metadata-value-face)
   3233     (markdown-test-range-has-face 74 78 'markdown-metadata-key-face)
   3234     (markdown-test-range-has-face 81 85 'markdown-metadata-value-face)))
   3235 
   3236 (ert-deftest test-markdown-font-lock/line-break ()
   3237   "Basic line break tests."
   3238   (markdown-test-string "    \nasdf  \n"
   3239     (markdown-test-range-has-face 1 9 nil)
   3240     (markdown-test-range-has-face 10 11 'markdown-line-break-face)))
   3241 
   3242 (ert-deftest test-markdown-font-lock/line-break-at-end-of-buffer ()
   3243   "Don't apply markdown-line-break-face at end of buffer without new line.
   3244 Details: https://github.com/jrblevin/markdown-mode/issues/621"
   3245   (markdown-test-string "    \nasdf  "
   3246     (markdown-test-range-has-face 10 11 'nil)))
   3247 
   3248 (ert-deftest test-markdown-font-lock/blockquote-bold ()
   3249   "Test font lock for bold inside of a blockquote."
   3250   (markdown-test-string
   3251       "> **bold**"
   3252     (markdown-test-range-has-face 1 10 'markdown-blockquote-face)
   3253     (markdown-test-range-has-face 5 8 'markdown-bold-face)))
   3254 
   3255 (ert-deftest test-markdown-font-lock/blockquote-italic ()
   3256   "Test font lock for italic inside of a blockquote."
   3257   (markdown-test-string
   3258       "> *italic*"
   3259     (markdown-test-range-has-face 1 10 'markdown-blockquote-face)
   3260     (markdown-test-range-has-face 4 9 'markdown-italic-face)))
   3261 
   3262 (ert-deftest test-markdown-font-lock/blockquote-code ()
   3263   "Test font lock for inline code inside of a blockquote."
   3264   (markdown-test-string
   3265       "> `code`"
   3266     (markdown-test-range-has-face 1 8 'markdown-blockquote-face)
   3267     (markdown-test-range-has-face 3 3 'markdown-markup-face)
   3268     (markdown-test-range-has-face 4 7 'markdown-inline-code-face)
   3269     (markdown-test-range-has-face 8 8 'markdown-markup-face)))
   3270 
   3271 (ert-deftest test-markdown-font-lock/blockquote-link ()
   3272   "Test font lock for links inside of a blockquote.
   3273 This test will fail until font lock for inline links inside
   3274 blockquotes is implemented (at present, the blockquote face
   3275 takes precedence)."
   3276   (markdown-test-string
   3277       "> [link](url)"
   3278     (markdown-test-range-has-face 1 1 'markdown-markup-face)
   3279     (markdown-test-range-has-face 2 13 'markdown-blockquote-face)
   3280     (markdown-test-range-has-face 3 3 'markdown-markup-face)
   3281     (markdown-test-range-has-face 4 7 'markdown-link-face)
   3282     (markdown-test-range-has-face 8 9 'markdown-markup-face)
   3283     (markdown-test-range-has-face 10 12 'markdown-url-face)
   3284     (markdown-test-range-has-face 13 13 'markdown-markup-face)))
   3285 
   3286 (ert-deftest test-markdown-font-lock/blockquote-comment ()
   3287   "Test font lock for comments inside of a blockquote."
   3288   (markdown-test-string
   3289       "> <!-- comment -->"
   3290     (markdown-test-range-has-face 1 1 'markdown-markup-face)
   3291     (markdown-test-range-has-face 3 18 'markdown-comment-face)))
   3292 
   3293 (ert-deftest test-markdown-font-lock/pre-override ()
   3294   "Test that font lock for pre blocks overrides everything else."
   3295   (markdown-test-string
   3296       "    **bold**
   3297     _italic_
   3298     <!-- comment -->
   3299     [link](url)
   3300     * list"
   3301     (markdown-test-range-has-face 1 73 'markdown-pre-face)))
   3302 
   3303 (ert-deftest test-markdown-font-lock/gfm-code-block-font-lock ()
   3304   "GFM code block font lock test. Now in base markdown-mode as well!"
   3305   (markdown-test-file "gfm.text"
   3306     (markdown-test-range-has-face 2639 2641 'markdown-markup-face) ; ```
   3307     (markdown-test-range-has-face 2642 2645 'markdown-language-keyword-face) ; lang
   3308     (markdown-test-range-has-face 2647 2728 'markdown-pre-face) ; code
   3309     (markdown-test-range-has-face 2730 2732 'markdown-markup-face))) ; ```
   3310 
   3311 (ert-deftest test-markdown-font-lock/gfm-code-block-with-one-line-block ()
   3312   "Highlighting gfm code block with one line triple quote blocks.
   3313 Detail: https://github.com/jrblevin/markdown-mode/issues/684"
   3314   (markdown-test-string-gfm "```sudo ln -s `which mkdir` /usr/bin/mkdir```
   3315 
   3316 Install Foreman. For running Rails, Sidekiq and anything else:
   3317 
   3318 ```ruby
   3319 rails db:migrate RAILS_ENV=test
   3320 ```"
   3321     (forward-line 2)
   3322     (markdown-test-range-has-face (point) (line-end-position) nil)
   3323     (re-search-forward "ruby")
   3324     (goto-char (match-beginning 0))
   3325     (markdown-test-range-has-face (point) (+ (point) 3) 'markdown-language-keyword-face)
   3326     (forward-line 1)
   3327     (markdown-test-range-has-face (point) (line-end-position) 'markdown-pre-face)))
   3328 
   3329 (ert-deftest test-markdown-font-lock/reference-definition ()
   3330   "Reference definitions should not include ]."
   3331   (let ((markdown-hide-urls nil))
   3332     (markdown-test-string "[1]: http://daringfireball.net/ \"title\""
   3333       (markdown-test-range-has-face 2 2 'markdown-reference-face) ; 1
   3334       (markdown-test-range-has-face 6 31 'markdown-url-face) ; URL
   3335       (markdown-test-range-has-face 34 38 'markdown-link-title-face)) ; title
   3336     (markdown-test-string "[foo][1] and [bar][2]: not a reference definition"
   3337       (markdown-test-range-has-face 2 4 'markdown-link-face) ; foo
   3338       (markdown-test-range-has-face 7 7 'markdown-reference-face) ; 1
   3339       (markdown-test-range-has-face 9 13 nil) ; [ ]and[ ]
   3340       (markdown-test-range-has-face 15 17 'markdown-link-face) ; bar
   3341       (markdown-test-range-has-face 20 20 'markdown-reference-face) ; 2
   3342       (markdown-test-range-has-face 22 49 nil)))) ; [ ]and[ ]
   3343 
   3344 (ert-deftest test-markdown-font-lock/subscripts ()
   3345   "Test font lock for subscripts."
   3346   (markdown-test-string "H~2~0"
   3347     (markdown-test-range-has-face 2 2 'markdown-markup-face) ; First ~
   3348     (markdown-test-range-has-face 3 3 nil) ; 2
   3349     (markdown-test-range-has-face 4 4 'markdown-markup-face))) ; Second ~
   3350 
   3351 (ert-deftest test-markdown-font-lock/superscripts ()
   3352   "Test font lock for subscripts."
   3353   (markdown-test-string "334^10^"
   3354     (markdown-test-range-has-face 1 3 nil) ; 334
   3355     (markdown-test-range-has-face 4 4 'markdown-markup-face) ; First ^
   3356     (markdown-test-range-has-face 5 6 nil) ; 10
   3357     (markdown-test-range-has-face 7 7 'markdown-markup-face)) ; Second ^
   3358   (markdown-test-string "1.0 x 10^-15^
   3359 10^+15^"
   3360     ;; -
   3361     (markdown-test-range-has-face 1 8 nil)
   3362     (markdown-test-range-has-face 9 9 'markdown-markup-face)
   3363     (markdown-test-range-has-face 10 12 nil)
   3364     (markdown-test-range-has-face 13 13 'markdown-markup-face)
   3365     ;; +
   3366     (markdown-test-range-has-face 15 16 nil)
   3367     (markdown-test-range-has-face 17 17 'markdown-markup-face)
   3368     (markdown-test-range-has-face 18 20 nil)
   3369     (markdown-test-range-has-face 21 21 'markdown-markup-face))
   3370   ;; Unicode minus sign
   3371   (markdown-test-string "10^−15^" ;; unicode minus sign U+2212
   3372     (search-forward "^")
   3373     (markdown-test-range-has-face (1- (point)) (1- (point)) 'markdown-markup-face)
   3374     (search-forward "^")
   3375     (markdown-test-range-has-face (1- (point)) (1- (point)) 'markdown-markup-face)))
   3376 
   3377 (ert-deftest test-markdown-font-lock/hidden-urls-inline ()
   3378   "Test URL hiding and toggling."
   3379   (let ((markdown-hide-urls t))
   3380     (markdown-test-file "inline.text"
   3381       (markdown-test-range-has-face 925 925 'markdown-markup-face)
   3382       (markdown-test-range-has-face 926 929 'markdown-link-face)
   3383       (markdown-test-range-has-face 930 931 'markdown-markup-face)
   3384       (markdown-test-range-has-face 932 949 'markdown-url-face)
   3385       (markdown-test-range-has-face 951 957 'markdown-link-title-face)
   3386       (markdown-test-range-has-face 958 958 'markdown-markup-face)
   3387       (should (get-text-property 932 'composition)))))
   3388 
   3389 (ert-deftest test-markdown-font-lock/hidden-urls-reference ()
   3390   "Test URL hiding and toggling."
   3391   (let ((markdown-hide-urls t))
   3392     (markdown-test-string "[link][15]"
   3393       ;; Two-character reference labels shouldn't get composed.
   3394       (markdown-test-range-has-face 1 1 'markdown-markup-face)
   3395       (markdown-test-range-has-face 2 5 'markdown-link-face)
   3396       (markdown-test-range-has-face 6 7 'markdown-markup-face)
   3397       (markdown-test-range-has-face 8 9 'markdown-reference-face)
   3398       (markdown-test-range-has-face 10 10 'markdown-markup-face)
   3399       (should-not (get-text-property 8 'composition)))
   3400     (markdown-test-string "[link][long-reference-label]"
   3401       ;; Longer reference labels should be composed
   3402       (markdown-test-range-has-face 1 1 'markdown-markup-face)
   3403       (markdown-test-range-has-face 2 5 'markdown-link-face)
   3404       (markdown-test-range-has-face 6 7 'markdown-markup-face)
   3405       (markdown-test-range-has-face 8 27 'markdown-reference-face)
   3406       (markdown-test-range-has-face 28 28 'markdown-markup-face)
   3407       (should (get-text-property 8 'composition)))))
   3408 
   3409 (ert-deftest test-markdown-font-lock/snake-case-code-in-heading ()
   3410   "Test underscores in inline code in headings."
   3411   (markdown-test-string "# Title with `snake_case_code`"
   3412     (should-not (markdown-range-property-any 21 24 'face '(markdown-italic-face)))
   3413     (markdown-test-range-has-face 15 29 'markdown-inline-code-face)))
   3414 
   3415 (ert-deftest test-markdown-font-lock/stars-in-code-in-heading ()
   3416   "Test asterisks in inline code in headings."
   3417   (markdown-test-string "# Title with `char** foo, int* bar`"
   3418     (should-not (markdown-range-property-any 20 29 'face '(markdown-italic-face)))
   3419     (markdown-test-range-has-face 15 34 'markdown-inline-code-face)))
   3420 
   3421 (ert-deftest test-markdown-font-lock/stars-in-code-in-blockquote ()
   3422   "Test asterisks in inline code in blockquote."
   3423   (markdown-test-string "> Quote with `**stars**`"
   3424     (should-not (markdown-range-property-any
   3425                  17 21 'face '(markdown-italic-face markdown-bold-face)))
   3426     (markdown-test-range-has-face 15 23 'markdown-inline-code-face)))
   3427 
   3428 (ert-deftest test-markdown-font-lock/two-bold-words-after-list ()
   3429   "Test two bold words after a list marker."
   3430   (markdown-test-string "- **foo** **bar**"
   3431     (should-not (markdown-range-property-any
   3432                  (point-min) (point-max) 'face '(markdown-italic-face)))))
   3433 
   3434 (ert-deftest test-markdown-font-lock/heading-with-italics-and-bold ()
   3435   "Test two bold words after a list marker."
   3436   (markdown-test-string "# Title with *italics* and **bold**"
   3437     (markdown-test-range-has-face 15 21 'markdown-italic-face)
   3438     (markdown-test-range-has-face 30 33 'markdown-bold-face)
   3439     (should-not (markdown-range-property-any 30 33 'face '(markdown-italic-face)))))
   3440 
   3441 (ert-deftest test-markdown-font-lock/hr-vs-level-2-setext ()
   3442   "Test that HRs are distinguished from setext H2 markup."
   3443   (markdown-test-file "outline.text"
   3444     (goto-char 485)
   3445     (should (markdown-on-heading-p))
   3446     (beginning-of-line)
   3447     (should (markdown-on-heading-p))
   3448     (should-not (markdown-range-property-any 453 484 'face '(markdown-hr-face)))))
   3449 
   3450 (ert-deftest test-markdown-font-lock/heading-code-block-no-whitespace ()
   3451   "Headings immediately before code blocks should be identified correctly.
   3452 See GH-234."
   3453   (markdown-test-string
   3454       "#### code snippet
   3455 ```javascript
   3456 const styles = require('gadgets/dist/styles.css');
   3457 ```"
   3458     (goto-char (point-min))
   3459     (forward-word)
   3460     (should (markdown-on-heading-p))
   3461     (should (markdown-match-propertized-text 'markdown-heading (point-at-eol)))
   3462     (goto-char (match-beginning 0))
   3463     (should (markdown-outline-level))
   3464     (should (= (markdown-outline-level) 4))
   3465     (markdown-test-range-has-face 6 17 'markdown-header-face-4)
   3466     (end-of-line)
   3467     (should-not (markdown-code-block-at-point-p))))
   3468 
   3469 (ert-deftest test-markdown-font-lock/hr-underscore-with-spaces ()
   3470   "Test font-lock for HR with spaced underscores."
   3471   (markdown-test-string "_ _ _ _ _ _ _\n"
   3472     (markdown-test-range-face-equals (point-min) (- (point-max) 2) 'markdown-hr-face)))
   3473 
   3474 (ert-deftest test-markdown-font-lock/hr-underscore-no-spaces ()
   3475   "Test font-lock for HR with underscores and no spaces."
   3476   (markdown-test-string "_____________\n"
   3477     (markdown-test-range-face-equals (point-min) (- (point-max) 2) 'markdown-hr-face)))
   3478 
   3479 (ert-deftest test-markdown-font-lock/inline-attributes ()
   3480   "Test inline attributes before a fenced code block."
   3481   (markdown-test-file "Leanpub.md"
   3482     ;; Inline attributes for a heading
   3483     (markdown-test-range-has-face 38 42 'markdown-markup-face)
   3484     ;; Inline attributes inside an aside block
   3485     (markdown-test-range-has-face 123 141 'markdown-markup-face)
   3486     ;; Inline attributes before a fenced code block
   3487     (markdown-test-range-has-face 632 696 'markdown-markup-face)))
   3488 
   3489 (ert-deftest test-markdown-font-lock/leanpub-sections ()
   3490   "Test Leanpub section markers."
   3491   (markdown-test-file "Leanpub.md"
   3492     ;; {frontmatter}
   3493     (markdown-test-range-has-face 12 24 'markdown-markup-face)
   3494     ;; {mainmatter}
   3495     (markdown-test-range-has-face 69 80 'markdown-markup-face)
   3496     ;; {pagebreak}
   3497     (markdown-test-range-has-face 427 437 'markdown-markup-face)))
   3498 
   3499 (ert-deftest test-markdown-font-lock/leanpub-include ()
   3500   "Test Leanpub include syntax."
   3501   (markdown-test-file "Leanpub.md"
   3502     ;; no title
   3503     (markdown-test-range-has-face 561 563 'markdown-markup-face)
   3504     (markdown-test-range-has-face 564 577 'markdown-url-face)
   3505     (markdown-test-range-has-face 578 578 'markdown-markup-face)
   3506     ;; title
   3507     (markdown-test-range-has-face 581 583 'markdown-markup-face)
   3508     (markdown-test-range-has-face 584 611 'markdown-link-title-face)
   3509     (markdown-test-range-has-face 612 613 'markdown-markup-face)
   3510     (markdown-test-range-has-face 614 628 'markdown-url-face)
   3511     (markdown-test-range-has-face 629 629 'markdown-markup-face)))
   3512 
   3513 (ert-deftest test-markdown-font-lock/curly-brace-include ()
   3514   "Test curly brace include syntax."
   3515   (markdown-test-string "<<{file}"
   3516     (markdown-test-range-has-face 1 3 'markdown-markup-face)
   3517     (markdown-test-range-has-face 4 7 'markdown-url-face)
   3518     (markdown-test-range-has-face 8 8 'markdown-markup-face)))
   3519 
   3520 (ert-deftest test-markdown-font-lock/square-bracket-include ()
   3521   "Test square bracket include syntax."
   3522   (markdown-test-string "<<[file]"
   3523     (markdown-test-range-has-face 1 3 'markdown-markup-face)
   3524     (markdown-test-range-has-face 4 7 'markdown-url-face)
   3525     (markdown-test-range-has-face 8 8 'markdown-markup-face)))
   3526 
   3527 (ert-deftest test-markdown-font-lock/pandoc-inline-footnote ()
   3528   "Test font lock for Pandoc inline footnotes."
   3529   (markdown-test-string "Here is an inline note.^[Inline notes are easier to write, since
   3530 you don't have to pick an identifier and move down to type the
   3531 note.]  And then you can close it and continue writing."
   3532     (markdown-test-range-has-face 1 23 nil)
   3533     (markdown-test-range-has-face 24 25 'markdown-markup-face)
   3534     (markdown-test-range-has-face 26 133 'markdown-footnote-text-face)
   3535     (markdown-test-range-has-face 134 134 'markdown-markup-face)))
   3536 
   3537 (ert-deftest test-markdown-font-lock/pandoc-inline-footnote-across-block ()
   3538   "Test font lock for Pandoc inline footnotes."
   3539   (markdown-test-string "Inline notes should not^[match
   3540 
   3541 across blocks]"
   3542     (markdown-test-range-has-face (point-min) (point-max) nil)))
   3543 
   3544 (ert-deftest test-markdown-font-lock/html-entity-named ()
   3545   "Test basic font-lock support for named HTML entities."
   3546   (markdown-test-string "&nbsp;"
   3547     (markdown-test-range-has-face 1 6 'markdown-html-entity-face)))
   3548 
   3549 (ert-deftest test-markdown-font-lock/html-entity-hex ()
   3550   "Test basic font-lock support for hexadecimal HTML entities."
   3551   (markdown-test-string "&#x272a;"
   3552     (markdown-test-range-has-face 1 8 'markdown-html-entity-face)))
   3553 
   3554 (ert-deftest test-markdown-font-lock/html-entity-decimal ()
   3555   "Test basic font-lock support for decimal HTML entities."
   3556   (markdown-test-string "&#9;"
   3557     (markdown-test-range-has-face 1 4 'markdown-html-entity-face)))
   3558 
   3559 (ert-deftest test-markdown-font-lock/html-entity-in-inline-code ()
   3560   "Test that HTML entities are not matched inside inline code."
   3561   (markdown-test-string "`&#9;`"
   3562     (markdown-test-range-has-face 1 1 'markdown-markup-face)
   3563     (markdown-test-range-has-face 2 5 'markdown-inline-code-face)
   3564     (markdown-test-range-has-face 6 6 'markdown-markup-face)
   3565     (should-not (markdown-range-property-any 1 6 'face '(markdown-html-entity-face)))))
   3566 
   3567 (ert-deftest test-markdown-font-lock/html-entity-in-gfm-code-block ()
   3568   "Test that HTML entities are not matched inside GFM code blocks."
   3569   (markdown-test-string "```\n&nbsp;\n&#x272a;\n&#9;\n```"
   3570     (should-not
   3571      (markdown-range-property-any
   3572       (point-min) (point-max) 'face '(markdown-html-entity-face)))))
   3573 
   3574 (ert-deftest test-markdown-font-lock/html-tags-in-syntax-file ()
   3575   "Test matching HTML tags in syntax.text."
   3576   (markdown-test-file "syntax.text"
   3577     ;; <ul id="ProjectSubmenu">
   3578     (markdown-test-range-has-face 36 36 'markdown-html-tag-delimiter-face)
   3579     (markdown-test-range-has-face 37 38 'markdown-html-tag-name-face)
   3580     (markdown-test-range-has-face 40 41 'markdown-html-attr-name-face)
   3581     (markdown-test-range-has-face 42 42 'markdown-html-tag-delimiter-face)
   3582     (markdown-test-range-has-face 43 58 'markdown-html-attr-value-face)
   3583     (markdown-test-range-has-face 59 59 'markdown-html-tag-delimiter-face)
   3584     ;; <li>
   3585     (markdown-test-range-has-face 65 65 'markdown-html-tag-delimiter-face)
   3586     (markdown-test-range-has-face 66 67 'markdown-html-tag-name-face)
   3587     (markdown-test-range-has-face 68 68 'markdown-html-tag-delimiter-face)
   3588     ;; <a href="/projects/markdown/" title="Markdown Project Page">
   3589     (markdown-test-range-has-face 69 69 'markdown-html-tag-delimiter-face)
   3590     (markdown-test-range-has-face 70 70 'markdown-html-tag-name-face)
   3591     (markdown-test-range-has-face 72 75 'markdown-html-attr-name-face)
   3592     (markdown-test-range-has-face 76 76 'markdown-html-tag-delimiter-face)
   3593     (markdown-test-range-has-face 77 97 'markdown-html-attr-value-face)
   3594     (markdown-test-range-has-face 99 103 'markdown-html-attr-name-face)
   3595     (markdown-test-range-has-face 104 104 'markdown-html-tag-delimiter-face)
   3596     (markdown-test-range-has-face 105 127 'markdown-html-attr-value-face)
   3597     (markdown-test-range-has-face 128 128 'markdown-html-tag-delimiter-face)))
   3598 
   3599 (ert-deftest test-markdown-font-lock/html-tag-in-gfm-code-block ()
   3600   "Test that HTML tags are not matched inside GFM code blocks."
   3601   (markdown-test-string "```\n<ul id=\"ProjectSubmenu\">\n```"
   3602     (should-not
   3603      (markdown-range-property-any
   3604       (point-min) (point-max) 'face
   3605       '(markdown-html-tag-name-face
   3606         markdown-html-tag-delimiter-face
   3607         markdown-html-attr-name-face
   3608         markdown-html-attr-value-face)))))
   3609 
   3610 (ert-deftest test-markdown-font-lock/html-tag-in-code-block ()
   3611   "Test that HTML tags are not matched inside code blocks."
   3612   (markdown-test-string "    <ul id=\"ProjectSubmenu\">"
   3613     (should-not
   3614      (markdown-range-property-any
   3615       (point-min) (point-max) 'face
   3616       '(markdown-html-tag-name-face
   3617         markdown-html-tag-delimiter-face
   3618         markdown-html-attr-name-face
   3619         markdown-html-attr-value-face)))))
   3620 
   3621 (ert-deftest test-markdown-font-lock/html-tag-in-inline-code ()
   3622   "Test that HTML tags are not matched inside inline code spans."
   3623   (markdown-test-string "`<ul id=\"ProjectSubmenu\">`"
   3624     (should-not
   3625      (markdown-range-property-any
   3626       (point-min) (point-max) 'face
   3627       '(markdown-html-tag-name-face
   3628         markdown-html-tag-delimiter-face
   3629         markdown-html-attr-name-face
   3630         markdown-html-attr-value-face)))))
   3631 
   3632 (ert-deftest test-markdown-font-lock/html-disabled ()
   3633   "Test disabling font-lock for HTML tags"
   3634   (let ((markdown-enable-html nil))
   3635     (markdown-test-file "syntax.text"
   3636       (should-not
   3637        (markdown-range-property-any
   3638         (point-min) (point-max) 'face
   3639         '(markdown-html-tag-name-face
   3640           markdown-html-tag-delimiter-face
   3641           markdown-html-attr-name-face
   3642           markdown-html-attr-value-face))))))
   3643 
   3644 (ert-deftest test-markdown-font-lock/html-tag-angle-bracket ()
   3645   "Test a hard to parse HTML attribute with an angle bracket."
   3646   (markdown-test-string "<img title=\"displays >\" src=\"big.gif\">"
   3647     (markdown-test-range-has-face 1 1 'markdown-html-tag-delimiter-face)
   3648     (markdown-test-range-has-face 2 4 'markdown-html-tag-name-face)
   3649     (markdown-test-range-has-face 6 10 'markdown-html-attr-name-face)
   3650     (markdown-test-range-has-face 11 11 'markdown-html-tag-delimiter-face)
   3651     (markdown-test-range-has-face 12 23 'markdown-html-attr-value-face)
   3652     (markdown-test-range-has-face 25 27 'markdown-html-attr-name-face)
   3653     (markdown-test-range-has-face 28 28 'markdown-html-tag-delimiter-face)
   3654     (markdown-test-range-has-face 29 37 'markdown-html-attr-value-face)
   3655     (markdown-test-range-has-face 38 38 'markdown-html-tag-delimiter-face)))
   3656 
   3657 (ert-deftest test-markdown-font-lock/highlighting-syntax ()
   3658   "Test highlighting syntax ==foo==."
   3659   (let ((markdown-enable-highlighting-syntax t))
   3660     (markdown-test-string "==foo=="
   3661       (markdown-test-range-has-face 1 2 'markdown-markup-face)
   3662       (markdown-test-range-has-face 3 5 'markdown-highlighting-face)
   3663       (markdown-test-range-has-face 6 7 'markdown-markup-face)))
   3664   (markdown-test-string "==foo=="
   3665     (markdown-test-range-has-face 1 7 nil)))
   3666 
   3667 ;;; Markdown Parsing Functions:
   3668 
   3669 (ert-deftest test-markdown-parsing/extend-region-function ()
   3670   "Test `markdown-syntax-propertize-extend-region'.
   3671 Should return a cons (NEW-START . NEW-END) or nil if no
   3672 adjustment should be made. Function is called repeatedly until it
   3673 returns nil."
   3674   (markdown-test-file
   3675       "inline.text"
   3676     (should (equal (markdown-syntax-propertize-extend-region 1 17)
   3677                    (cons 1 91)))
   3678     (should (equal (markdown-syntax-propertize-extend-region 2 17)
   3679                    (cons 1 91)))
   3680     (should (equal (markdown-syntax-propertize-extend-region 1 91)
   3681                    nil))
   3682     (should (equal (markdown-syntax-propertize-extend-region 93 157)
   3683                    nil))
   3684     (should (equal (markdown-syntax-propertize-extend-region 496 502)
   3685                    (cons 486 510)))
   3686     (should (equal (markdown-syntax-propertize-extend-region 486 510)
   3687                    nil))
   3688     ;; Region that begins and ends with \n\n should not be extended
   3689     (should (equal (markdown-syntax-propertize-extend-region 157 355)
   3690                    nil))))
   3691 
   3692 (defun markdown-test-check-match-limits (prop num begin end &optional pos)
   3693   (let* ((posn (or pos (point)))
   3694          (props (get-text-property posn prop)))
   3695     (save-match-data
   3696       (set-match-data props)
   3697       (should (match-beginning num))
   3698       (should (match-end num))
   3699       (should (= (match-beginning num) begin))
   3700       (should (= (match-end num) end)))))
   3701 
   3702 (ert-deftest test-markdown-parsing/syntax-with-adjacent-code-blocks ()
   3703   "Test `markdown-syntax-propertize-fenced-code-blocks' with adjacent blocks."
   3704   (markdown-test-string
   3705       "~~~ shell
   3706 #!/bin/sh
   3707 
   3708 echo \"Hello, world!\"
   3709 ~~~
   3710 
   3711 ~~~ shell
   3712 #!/bin/sh
   3713 
   3714 echo \"Hello, world v2!\"
   3715 ~~~
   3716 "
   3717     (let ((start-top-1 (make-marker)) (end-top-1 (make-marker))
   3718           (start-lang-1 (make-marker)) (end-lang-1 (make-marker))
   3719           (start-mid-1 (make-marker)) (end-mid-1 (make-marker))
   3720           (start-bottom-1 (make-marker)) (end-bottom-1 (make-marker))
   3721           (between (make-marker))
   3722           (start-top-2 (make-marker)) (end-top-2 (make-marker))
   3723           (start-lang-2 (make-marker)) (end-lang-2 (make-marker))
   3724           (start-mid-2 (make-marker)) (end-mid-2 (make-marker))
   3725           (start-bottom-2 (make-marker)) (end-bottom-2 (make-marker)))
   3726       ;; First code block
   3727       (set-marker start-top-1 1)
   3728       (set-marker end-top-1 4)
   3729       (set-marker start-lang-1 5)
   3730       (set-marker end-lang-1 10)
   3731       (set-marker start-mid-1 11)
   3732       (set-marker end-mid-1 43)
   3733       (set-marker start-bottom-1 43)
   3734       (set-marker end-bottom-1 46)
   3735       ;; check top tildes
   3736       (markdown-test-check-match-limits
   3737        'markdown-tilde-fence-begin 1 (marker-position start-top-1)
   3738        (marker-position end-top-1) (marker-position start-top-1))
   3739       ;; check top language specifier
   3740       (markdown-test-check-match-limits
   3741        'markdown-tilde-fence-begin 3 (marker-position start-lang-1)
   3742        (marker-position end-lang-1) (marker-position start-lang-1))
   3743       ;; check text in between
   3744       (markdown-test-check-match-limits
   3745        'markdown-fenced-code 0 (marker-position start-mid-1)
   3746        (marker-position end-mid-1) (marker-position start-mid-1))
   3747       ;; check bottom tildes
   3748       (markdown-test-check-match-limits
   3749        'markdown-tilde-fence-end 1 (marker-position start-bottom-1)
   3750        (marker-position end-bottom-1) (marker-position start-bottom-1))
   3751       ;; Point between code blocks
   3752       (set-marker between 47)
   3753       (should (equal (get-text-property between 'markdown-fenced-code)
   3754                      nil))
   3755       ;; Second code block
   3756       (set-marker start-top-2 48)
   3757       (set-marker end-top-2 51)
   3758       (set-marker start-lang-2 52)
   3759       (set-marker end-lang-2 57)
   3760       (set-marker start-mid-2 58)
   3761       (set-marker end-mid-2 93)
   3762       (set-marker start-bottom-2 93)
   3763       (set-marker end-bottom-2 96)
   3764       (markdown-test-check-match-limits
   3765        'markdown-tilde-fence-begin 1 (marker-position start-top-2)
   3766        (marker-position end-top-2) (marker-position start-top-2))
   3767       (markdown-test-check-match-limits
   3768        'markdown-tilde-fence-begin 3 (marker-position start-lang-2)
   3769        (marker-position end-lang-2) (marker-position start-lang-2))
   3770       (markdown-test-check-match-limits
   3771        'markdown-fenced-code 0 (marker-position start-mid-2)
   3772        (marker-position end-mid-2) (marker-position start-mid-2))
   3773       (markdown-test-check-match-limits
   3774        'markdown-tilde-fence-end 1 (marker-position start-bottom-2)
   3775        (marker-position end-bottom-2) (marker-position start-bottom-2))
   3776       ;; ;; Move point between code blocks and insert a character
   3777       (goto-char between)
   3778       (insert "x")
   3779       ;; Re-propertize region after change
   3780       (let ((range (markdown-syntax-propertize-extend-region (1- between) (point-max))))
   3781         (markdown-syntax-propertize (car range) (cdr range)))
   3782       ;; Re-check first code block
   3783       (markdown-test-check-match-limits
   3784        'markdown-tilde-fence-begin 1 (marker-position start-top-1)
   3785        (marker-position end-top-1) (marker-position start-top-1))
   3786       (markdown-test-check-match-limits
   3787        'markdown-tilde-fence-begin 3 (marker-position start-lang-1)
   3788        (marker-position end-lang-1) (marker-position start-lang-1))
   3789       (markdown-test-check-match-limits
   3790        'markdown-fenced-code 0 (marker-position start-mid-1)
   3791        (marker-position end-mid-1) (marker-position start-mid-1))
   3792       (markdown-test-check-match-limits
   3793        'markdown-tilde-fence-end 1 (marker-position start-bottom-1)
   3794        (marker-position end-bottom-1) (marker-position start-bottom-1))
   3795       ;; Re-check point between code blocks
   3796       (should (equal (get-text-property between 'markdown-fenced-code)
   3797                      nil))
   3798       ;; Re-check second code block
   3799       (markdown-test-check-match-limits
   3800        'markdown-tilde-fence-begin 1 (marker-position start-top-2)
   3801        (marker-position end-top-2) (marker-position start-top-2))
   3802       (markdown-test-check-match-limits
   3803        'markdown-tilde-fence-begin 3 (marker-position start-lang-2)
   3804        (marker-position end-lang-2) (marker-position start-lang-2))
   3805       (markdown-test-check-match-limits
   3806        'markdown-fenced-code 0 (marker-position start-mid-2)
   3807        (marker-position end-mid-2) (marker-position start-mid-2))
   3808       (markdown-test-check-match-limits
   3809        'markdown-tilde-fence-end 1 (marker-position start-bottom-2)
   3810        (marker-position end-bottom-2)
   3811        (marker-position start-bottom-2)))))
   3812 
   3813 (ert-deftest test-markdown-parsing/propertize-fenced-in-between ()
   3814   "Test whether `markdown-syntax-propertize-fenced-block-constructs' handles the
   3815 case when it can't propertize both the start and end of a fenced block within a
   3816 single pass (the end of the block is past the END argument)."
   3817   (markdown-test-string
   3818       "~~~ shell
   3819 #!/bin/sh
   3820 
   3821 echo \"Hello, world!\"
   3822 ~~~
   3823 "
   3824     (set-text-properties (point-min) (point-max) nil)
   3825     ;; syntax-propertize up to right after hashbang
   3826     (markdown-syntax-propertize-fenced-block-constructs (point-min) 21)
   3827     ;; ~~~ shell should be propertized, but nothing else
   3828     ;; check tildes
   3829     (markdown-test-check-match-limits 'markdown-tilde-fence-begin 1 1 4 1)
   3830     ;; check language
   3831     (markdown-test-check-match-limits 'markdown-tilde-fence-begin 3 5 10 5)
   3832     ;; middle should not be propertized
   3833     (should-not (get-text-property 11 'markdown-fenced-code))
   3834     ;; neither should end
   3835     (should-not (get-text-property 43 'markdown-tilde-fence-end))
   3836     (markdown-syntax-propertize-fenced-block-constructs 21 (point-max))
   3837     ;; everything should be propertized now
   3838     ;; re-check top
   3839     (markdown-test-check-match-limits 'markdown-tilde-fence-begin 1 1 4 1)
   3840     (markdown-test-check-match-limits 'markdown-tilde-fence-begin 3 5 10 5)
   3841     ;; check middle
   3842     (markdown-test-check-match-limits 'markdown-fenced-code 0 10 43 10)
   3843     ;; check ending tildes
   3844     (markdown-test-check-match-limits 'markdown-tilde-fence-end 1 43 46 43)))
   3845 
   3846 (ert-deftest test-markdown-parsing/code-block-at-pos-pre-indent ()
   3847   "Ensure `markdown-code-block-at-pos' works in a pre block."
   3848   (markdown-test-string
   3849       "    pre code
   3850     random stuff
   3851     more preformatted code"
   3852     (should (equal (markdown-code-block-at-pos 1) '(1 57)))
   3853     (should (equal (markdown-code-block-at-pos 30) '(1 57)))
   3854     (should (equal (markdown-code-block-at-pos (point-max)) '(1 57)))))
   3855 
   3856 (ert-deftest test-markdown-parsing/code-block-at-pos-tilde-fenced ()
   3857   "Ensure `markdown-code-block-at-pos' works in tilde fenced blocks."
   3858   (markdown-test-string
   3859       "~~~ ruby
   3860 some_ruby_fun()
   3861 ~~~"
   3862     (should (equal (markdown-code-block-at-pos 1) '(1 29)))
   3863     (should (equal (markdown-code-block-at-pos 10) '(1 29)))
   3864     (should (equal (markdown-code-block-at-pos 26) '(1 29)))))
   3865 
   3866 (ert-deftest test-markdown-parsing/code-block-at-pos-gfm-fenced ()
   3867   "Ensure `markdown-code-block-at-pos' works in GFM fenced blocks."
   3868   (markdown-test-string
   3869       "``` {.bash}
   3870 #!/bin/sh
   3871 echo hey
   3872 ```"
   3873     (should (equal (markdown-code-block-at-pos 1) '(1 35)))
   3874     (should (equal (markdown-code-block-at-pos 13) '(1 35)))
   3875     (should (equal (markdown-code-block-at-pos 23) '(1 35)))
   3876     (should (equal (markdown-code-block-at-pos 34) '(1 35)))
   3877     (should (equal (markdown-code-block-at-pos 35) nil))))
   3878 
   3879 (ert-deftest test-markdown-parsing/code-block-at-pos-yaml-metadata ()
   3880   "Ensure `markdown-code-block-at-pos' works in YAML metadata blocks."
   3881   (let ((markdown-use-pandoc-style-yaml-metadata t))
   3882     (markdown-test-string
   3883         "---
   3884 a: b
   3885 ---
   3886 
   3887 ---
   3888 data: pandoc
   3889 ..."
   3890       ;; First YAML block
   3891       (should (equal (markdown-code-block-at-pos 1) '(1 13)))
   3892       (should (equal (markdown-code-block-at-pos 5) '(1 13)))
   3893       (should (equal (markdown-code-block-at-pos 12) '(1 13)))
   3894       ;; Pandoc YAML block
   3895       (should (equal (markdown-code-block-at-pos 15) '(15 35)))
   3896       (should (equal (markdown-code-block-at-pos 19) '(15 35)))
   3897       (should (equal (markdown-code-block-at-pos 34) '(15 35)))
   3898       (should (equal (markdown-code-block-at-pos 35) nil)))))
   3899 
   3900 (ert-deftest test-markdown-parsing/syntax-get-fenced-blocks ()
   3901   "Test whether *-get-fenced-block-* functions work in the case where a block is
   3902 only partially propertized."
   3903   (save-match-data
   3904     (markdown-test-string
   3905         "~~~
   3906 "
   3907       (should (equal (markdown-syntax-propertize-extend-region
   3908                       (point-min) (point-max))
   3909                      nil))
   3910       (goto-char 1)
   3911       (set-match-data (markdown-text-property-at-point
   3912                        'markdown-tilde-fence-begin))
   3913       (should (equal (markdown-get-fenced-block-from-start
   3914                       'markdown-tilde-fence-begin)
   3915                      nil)))
   3916     (markdown-test-string
   3917         "~~~
   3918 ~~~"
   3919       (goto-char 1)
   3920       (set-match-data (markdown-text-property-at-point
   3921                        'markdown-tilde-fence-begin))
   3922       (should (equal (markdown-get-fenced-block-from-start
   3923                       'markdown-tilde-fence-begin)
   3924                      (list 1 8)))
   3925       (should (equal (markdown-code-block-at-pos (point)) (list 1 8)))
   3926 
   3927       ;; markdown-code-block-at-point-p should not modify match data
   3928       (set-match-data (list 1 2 3 4))
   3929       (should (markdown-code-block-at-point-p))
   3930       (should (equal (match-data) (list 1 2 3 4)))
   3931 
   3932       (goto-char 5)
   3933       (set-match-data (markdown-text-property-at-point
   3934                        'markdown-tilde-fence-end))
   3935       (should (equal (markdown-get-fenced-block-from-end
   3936                       'markdown-tilde-fence-end)
   3937                      (list 1 8)))
   3938       (should (equal (markdown-code-block-at-pos (point)) (list 1 8))))
   3939     (markdown-test-string
   3940         "~~~
   3941 
   3942 ~~~"
   3943       (goto-char 1)
   3944       (set-match-data (markdown-text-property-at-point
   3945                        'markdown-tilde-fence-begin))
   3946       (should (equal (markdown-get-fenced-block-from-start
   3947                       'markdown-tilde-fence-begin)
   3948                      (list 1 9)))
   3949       (should (equal (markdown-code-block-at-pos (point)) (list 1 9)))
   3950       (goto-char 5)
   3951       (set-match-data (markdown-text-property-at-point 'markdown-fenced-code))
   3952       (should (equal (markdown-get-fenced-block-from-middle
   3953                       'markdown-fenced-code)
   3954                      (list 1 9)))
   3955       (should (equal (markdown-code-block-at-pos (point)) (list 1 9)))
   3956       (goto-char 6)
   3957       (set-match-data (markdown-text-property-at-point
   3958                        'markdown-tilde-fence-end))
   3959       (should (equal (markdown-get-fenced-block-from-end
   3960                       'markdown-tilde-fence-end)
   3961                      (list 1 9)))
   3962       (should (equal (markdown-code-block-at-pos (point)) (list 1 9))))))
   3963 
   3964 (ert-deftest test-markdown-parsing/reference-definition-basic ()
   3965   "Test reference definition function."
   3966   (markdown-test-file "syntax.text"
   3967     ;; Test accuracy of returned text and bounds
   3968     (should (equal (markdown-reference-definition "1")
   3969                    (list "http://docutils.sourceforge.net/mirror/setext.html" 1942 1992)))
   3970     (should (equal (markdown-reference-definition "2")
   3971                    (list "http://www.aaronsw.com/2002/atx/" 2000 2032)))
   3972     ;; Test that match data remains intact
   3973     (should (string-equal (match-string 5) "http://www.aaronsw.com/2002/atx/"))
   3974     ;; Test anchor-only relative URL
   3975     (should (equal (markdown-reference-definition "bq")
   3976                    (list "#blockquote" 7536 7547)))
   3977     ;; Example references that appear in pre blocks in the text
   3978     (should (not (markdown-reference-definition "")))
   3979     (should (not (markdown-reference-definition "id")))
   3980     (should (not (markdown-reference-definition "foo")))
   3981     (should (not (markdown-reference-definition "A")))
   3982     (should (not (markdown-reference-definition "Google")))
   3983     ;; Test that we don't pick up other text in square brackets
   3984     (should (not (markdown-reference-definition "blockquoting")))
   3985     (should (not (markdown-reference-definition "square brackets")))
   3986     ;; Test case insensitivity
   3987     (should (equal (markdown-reference-definition "SRC")
   3988                    (list "/projects/markdown/syntax.text" 1245 1275)))))
   3989 
   3990 (ert-deftest test-markdown-parsing/get-defined-references ()
   3991   "Test `markdown-get-defined-references'."
   3992   (markdown-test-file "syntax.text"
   3993     (should (equal (markdown-get-defined-references)
   3994                    '(("src" . 37)
   3995                      ("1" . 55)
   3996                      ("2" . 56)
   3997                      ("3" . 57)
   3998                      ("4" . 58)
   3999                      ("5" . 59)
   4000                      ("6" . 60)
   4001                      ("bq" . 205)
   4002                      ("l" . 206)))))
   4003   (markdown-test-file "outline.text"
   4004     (should (equal (markdown-get-defined-references) nil)))
   4005   (markdown-test-file "wiki-links.text"
   4006     (should (equal (markdown-get-defined-references) nil))))
   4007 
   4008 (ert-deftest test-markdown-parsing/get-used-uris ()
   4009   "Test `markdown-get-used-uris'."
   4010   (markdown-test-file "syntax.text"
   4011     (let ((uris (markdown-get-used-uris)))
   4012       (should (equal (nth 0 uris) "#overview"))
   4013       (should (equal (nth 20 uris) "http://www.aaronsw.com/2002/atx/"))
   4014       (should-not (member "http://example.com/" uris))
   4015       (should-not (member "address@example.com" uris)))))
   4016 
   4017 (defun markdown-test-test-region (beg end)
   4018   (goto-char (1- beg))
   4019   (should-not (markdown-inline-code-at-point-p))
   4020   (goto-char (1+ end))
   4021   (should-not (markdown-inline-code-at-point-p))
   4022   (dolist (loc (number-sequence beg end))
   4023     (goto-char loc)
   4024     (should (markdown-inline-code-at-point))
   4025     (should (equal (match-beginning 0) beg))
   4026     (should (equal (match-end 0) (1+ end)))))
   4027 
   4028 (ert-deftest test-markdown-parsing/inline-code-at-point ()
   4029   "Test `markdown-inline-code-at-point'."
   4030   (markdown-test-file "inline.text"
   4031     (markdown-test-test-region 45 50) ; Regular code span
   4032     (markdown-test-test-region 61 89) ; Code containing backticks
   4033     (markdown-test-test-region 228 239) ; Backquotes at beginning
   4034     (markdown-test-test-region 341 351) ; Backquotes at end
   4035     (markdown-test-test-region 460 468) ; Backslash as final character
   4036     (markdown-test-test-region 657 666) ; A code span crossing lines
   4037     (markdown-test-test-region 749 757) ; Three backquotes on same line
   4038     (markdown-test-test-region 806 814) ; Three backquotes across lines
   4039     ))
   4040 
   4041 (ert-deftest test-markdown-parsing/inline-code-at-point-one-space ()
   4042   "Test `markdown-inline-code-at-point' with multiple code spans in a row."
   4043   (markdown-test-string "`foo` `bar` `baz`"
   4044     (dolist (loc (number-sequence 1 5)) ; `foo`
   4045       (goto-char loc)
   4046       ;; markdown-inline-code-at-point should set match data
   4047       (should (markdown-inline-code-at-point))
   4048       (should (equal (match-data) (list 1 6 1 2 2 5 5 6)))
   4049       ;; markdown-inline-code-at-point-p should not modify match data
   4050       (set-match-data (list 1 2 3 4))
   4051       (should (markdown-inline-code-at-point-p))
   4052       (should (equal (match-data) (list 1 2 3 4))))
   4053     (dolist (loc (number-sequence 7 11)) ; `bar`
   4054       (goto-char loc)
   4055       (should (markdown-inline-code-at-point))
   4056       (should (equal (match-data) (list 7 12 7 8 8 11 11 12))))
   4057     (dolist (loc (number-sequence 13 17)) ; `baz`
   4058       (goto-char loc)
   4059       (should (markdown-inline-code-at-point))
   4060       (should (equal (match-data) (list 13 18 13 14 14 17 17 18))))))
   4061 
   4062 (ert-deftest test-markdown-parsing/inline-code-at-point-no-space ()
   4063   "Test `markdown-inline-code-at-point' with multiple code spans in a row.."
   4064   (markdown-test-string "a`foo`b`bar`c`baz`d"
   4065     (goto-char 1)                       ; "a"
   4066     (should-not (markdown-inline-code-at-point-p))
   4067     (dolist (loc (number-sequence 2 6)) ; "`foo`"
   4068       (goto-char loc)
   4069       (should (markdown-inline-code-at-point))
   4070       (should (equal (match-data) (list 2 7 2 3 3 6 6 7))))
   4071     (dolist (loc (number-sequence 8 12)) ; "`bar`"
   4072       (goto-char loc)
   4073       (should (markdown-inline-code-at-point))
   4074       (should (equal (match-data) (list 8 13 8 9 9 12 12 13))))
   4075     (dolist (loc (number-sequence 14 18)) ; "`baz`"
   4076       (goto-char loc)
   4077       (should (markdown-inline-code-at-point))
   4078       (should (equal (match-data) (list 14 19 14 15 15 18 18 19))))))
   4079 
   4080 (ert-deftest test-markdown-parsing/code-at-point-blank-line ()
   4081   "Test `markdown-inline-code-at-point-p' at beginning of block."
   4082   (markdown-test-string "----------\n\n## foo\n"
   4083     (should-not (markdown-inline-code-at-point-p))
   4084     (forward-line)
   4085     (should-not (markdown-inline-code-at-point-p))
   4086     (forward-line)
   4087     (should-not (markdown-inline-code-at-point-p))))
   4088 
   4089 (ert-deftest test-markdown-parsing/in-comment-p-position ()
   4090   "Test `markdown-in-comment-p'."
   4091   (markdown-test-string
   4092       "HTML <!-- foo --> comment"
   4093     (should (eq (point) (point-min)))
   4094     (should-not (markdown-in-comment-p (point-max)))
   4095     (should (eq (point) (point-min)))))
   4096 
   4097 (ert-deftest test-markdown-parsing/match-comments ()
   4098   "Test `markdown-match-comments'."
   4099   (markdown-test-string
   4100       "HTML <!-- foo --> comment"
   4101     (should (markdown-match-comments (point-max)))
   4102     (should (eq (point) 18))
   4103     (should (equal (match-data) (list 6 18)))
   4104     (should-not (markdown-match-comments (point-max)))))
   4105 
   4106 (ert-deftest test-markdown-parsing/range-property-any ()
   4107   "Test behavior of `markdown-range-property-any'."
   4108   (markdown-test-file
   4109       "inline.text"
   4110     (should (markdown-range-property-any
   4111              (point-min) (point-at-eol)
   4112              'face '(markdown-markup-face markdown-italic-face)))
   4113     (should-not (markdown-range-property-any
   4114                  (point-min) (point-at-eol)
   4115                  'face '(markdown-bold-face)))))
   4116 
   4117 (ert-deftest test-markdown-parsing/inline-code ()
   4118   "Don't cause infinite loop for inline code just after metadata block
   4119 Detail: https://github.com/jrblevin/markdown-mode/issues/115"
   4120   (markdown-test-string "---
   4121 x: x
   4122 ---
   4123 `x`
   4124 "
   4125     (should (markdown-match-code (point-max)))
   4126     (should (= (point) 18))
   4127     (should (equal (match-data t) '(14 17 14 15 15 16 16 17)))
   4128     (should-not (markdown-match-code (point-max)))))
   4129 
   4130 (ert-deftest test-markdown-parsing/list-item-at-point ()
   4131   "Test `markdown-list-item-at-point-p'."
   4132   (markdown-test-file "lists.text"
   4133     (let ((orig-match-data '(1 2 3 4))
   4134           (not-list-points '(273 399 512 3615))
   4135           (list-points '(1063 1063 1176 1283 1659 1830 1919 2150
   4136                               2393 2484 2762 2853 3097 3188 3700
   4137                               3903 4009)))
   4138       ;; markdown-inline-code-at-point-p should not modify match data
   4139       (set-match-data orig-match-data)
   4140       ;; Not list items
   4141       (dolist (pos not-list-points)
   4142         (goto-char pos)
   4143         (should-not (markdown-list-item-at-point-p))
   4144         (should (equal (match-data) orig-match-data)))
   4145       ;; List items
   4146       (dolist (pos list-points)
   4147         (goto-char pos)
   4148         (should (markdown-list-item-at-point-p))
   4149         (should (equal (match-data) orig-match-data))))))
   4150 
   4151 (ert-deftest test-markdown-parsing/heading-at-point ()
   4152   "Test `markdown-heading-at-point'."
   4153   (save-match-data
   4154     (markdown-test-file "outline.text"
   4155       (should-not (markdown-heading-at-point))
   4156       (markdown-test-goto-heading "An underline-style header")
   4157       (forward-line -1)
   4158       (should (markdown-heading-at-point))
   4159       (should (equal (match-data t) (get-text-property (point) 'markdown-heading)))
   4160       (should (equal (match-data t) (get-text-property (point) 'markdown-heading-1-setext))))))
   4161 
   4162 (ert-deftest test-markdown-parsing/inline-link-in-code-block ()
   4163   "Test `markdown-match-generic-links'."
   4164   (markdown-test-string "    **bold**
   4165     _italic_
   4166     <!-- comment -->
   4167     [link](url)
   4168     * list"
   4169     (goto-char (point-min))
   4170     ;; The link inside the pre block should not match.
   4171     (should-not (markdown-match-generic-links (point-max) nil))
   4172     ;; Point should be left at limit.
   4173     (should (= (point) (point-max)))))
   4174 
   4175 (ert-deftest test-markdown-parsing/broken-inline-link ()
   4176   "Test `markdown-match-generic-links' with an invalid link."
   4177   (markdown-test-string "[site1](http://site1.com
   4178 [site2](http://site2.com)
   4179 [site3](http://site3.com)"
   4180     (goto-char (point-min))
   4181     (let ((limit (point-at-eol)))
   4182       ;; The first link is broken and shouldn't match.
   4183       (should-not (markdown-match-generic-links limit nil))
   4184       ;; Subsequent search shouldn't match, so point should move to limit.
   4185       (should (= (point) limit)))
   4186     ;; The second link should still match, starting from (point-min).
   4187     (let ((limit (point-at-eol 2)))
   4188       (should (markdown-match-generic-links limit nil))
   4189       (should (= (point) (match-end 0))))
   4190     ;; The third link should match when starting past the second one.
   4191     (goto-char (match-end 0))
   4192     (should (markdown-match-generic-links (point-max) nil))
   4193     (should (= (point) (match-end 0)))))
   4194 
   4195 (ert-deftest test-markdown-parsing/code-block-lang ()
   4196   "Test `markdown-code-block-lang'."
   4197   ;; Test with GFM code blocks.
   4198   (markdown-test-file "GFM.md"
   4199     ;; Test a call with the optional argument.
   4200     (should (string-equal
   4201              (markdown-code-block-lang
   4202               '(1455 . markdown-gfm-block-begin)) "js"))
   4203     ;; Test a call without the optional argument.
   4204     (goto-char 1504) ;; middle of a GFM code block
   4205     (should (string-equal (markdown-code-block-lang) "js")))
   4206   ;; Test with tilde-fenced cdoe blocks.
   4207   (markdown-test-file "outline-code.text"
   4208     (goto-char 107) ;; middle of a tilde fenced code block
   4209     (should (string-equal (markdown-code-block-lang
   4210                            '(83 . markdown-tilde-fence-begin)) "bash"))))
   4211 
   4212 (ert-deftest test-markdown-parsing/code-block-lang-period ()
   4213   "Test `markdown-code-block-lang' when language name begins with a period."
   4214   (markdown-test-string "~~~ { .ruby }
   4215 puts 'hello, world'
   4216 ~~~
   4217 "
   4218     (should (string-equal (markdown-code-block-lang) "ruby"))))
   4219 
   4220 ;;; Reference Checking:
   4221 
   4222 (ert-deftest test-markdown-references/get-unused-refs ()
   4223   "Test `markdown-get-unused-refs'."
   4224   (markdown-test-file "refs.text"
   4225     (should (equal (markdown-get-unused-refs)
   4226                    '(("logorrhea" . 8)
   4227                      ("orphan" . 11))))))
   4228 
   4229 (ert-deftest test-markdown-references/get-undefined-refs ()
   4230   "Test `markdown-get-undefined-refs'."
   4231   (markdown-test-file "refs.text"
   4232     (should (equal (markdown-get-undefined-refs)
   4233                    '(("problems" ("problems" . 3) ("controversy" . 5)))))))
   4234 
   4235 (ert-deftest test-markdown-references/goto-line-button ()
   4236   "Create and test a goto line button."
   4237   (markdown-test-string "line 1\nline 2\n"
   4238     ;; Store the temporary buffer with the text
   4239     (let ((target (current-buffer)))
   4240       ;; Create a new buffer for inserting
   4241       (with-temp-buffer
   4242         ;; Verify that point is in a different buffer
   4243         (should (not (equal (current-buffer) target)))
   4244         ;; Insert and press the button
   4245         (insert-button "goto line 2"
   4246                        :type 'markdown-goto-line-button
   4247                        'target-buffer target
   4248                        'target-line 2)
   4249         (should (string-equal (buffer-string) "goto line 2"))
   4250         (backward-button 1)
   4251         (call-interactively 'push-button)
   4252         ;; Verify that point is on line 2 of target buffer
   4253         (should (= (line-number-at-pos) 2))
   4254         (should (looking-at "line 2"))
   4255         (should (equal (current-buffer) target))))))
   4256 
   4257 (ert-deftest test-markdown-references/button-map ()
   4258   "Verify that button-buffer-map is used for check references buffer."
   4259   (markdown-test-string "[undefined][ref]\n"
   4260     (let* ((target (buffer-name))
   4261            (check (format "*Undefined references for %s*" target)))
   4262       (markdown-check-refs)
   4263       (with-current-buffer (get-buffer check)
   4264         (should (equal (local-key-binding (kbd "TAB")) 'forward-button))
   4265         (should (equal (local-key-binding (kbd "<backtab>")) 'backward-button))))))
   4266 
   4267 (ert-deftest test-markdown-references/undefined-refs-killing ()
   4268   "Test that buttons in unused references buffer delete lines when pushed."
   4269   (markdown-test-file "refs.text"
   4270     (let* ((target (buffer-name))
   4271            (check (replace-regexp-in-string
   4272                    "%buffer%" target
   4273                    markdown-unused-references-buffer))
   4274            (original-unused-refs (markdown-get-unused-refs)))
   4275       (markdown-unused-refs)
   4276       ;; Push X
   4277       (with-current-buffer (get-buffer check)
   4278         (forward-button 1)
   4279         (call-interactively 'push-button))
   4280       ;; The first orphan should now be gone with the rest of orphans
   4281       ;; moved up by one line
   4282       (should (equal (markdown-get-unused-refs)
   4283                      (mapcar (lambda (o) (cons (car o) (1- (cdr o))))
   4284                              (cdr original-unused-refs)))))))
   4285 
   4286 ;;; Lists:
   4287 
   4288 (ert-deftest test-markdown-lists/nested-list-file ()
   4289   "Test list item propertization for a nested list."
   4290   (markdown-test-file "nested-list.text"
   4291     (let ((values '(((1 25 3 5 "- " nil))
   4292                     ((26 189 3 5 "- " nil))
   4293                     ((191 581 3 5 "- " nil))
   4294                     ((217 482 7 9 "- " nil)
   4295                      (191 581 3 5 "- " nil))
   4296                     ((484 581 7 9 "- " nil)
   4297                      (191 581 3 5 "- " nil))
   4298                     ((514 581 11 13 "- " nil)
   4299                      (484 581 7 9 "- " nil)
   4300                      (191 581 3 5 "- " nil)))))
   4301       (cl-loop
   4302        for value in values
   4303        do (should
   4304            (equal (mapcar #'butlast (get-text-property (point) 'markdown-list-item)) value))
   4305        (markdown-outline-next)))))
   4306 
   4307 (ert-deftest test-markdown-lists/levels-1 ()
   4308   "Test list levels function `markdown-calculate-list-levels'."
   4309   (markdown-test-file "nested-list.text"
   4310     (let ((values '(((1 . 1) . nil) ((2 . 13) . (3)) ((14 . 23) . (7 3))
   4311                     ((24 . 26) . (11 7 3)))))
   4312       (cl-loop for (range . value) in values
   4313                do (goto-char (point-min))
   4314                (forward-line (1- (car range)))
   4315                (dotimes (_ (- (cdr range) (car range)))
   4316                  (should (equal (markdown-calculate-list-levels) value))
   4317                  (forward-line))))))
   4318 
   4319 (ert-deftest test-markdown-lists/levels-2 ()
   4320   "Test list levels function `markdown-calculate-list-levels'."
   4321   (markdown-test-file "syntax.text"
   4322     (let ((values '(((1 . 13) . nil) ((14 . 14) . (0)) ((15 . 17) . (4 0))
   4323                     ((18 . 18) . (0)) ((19 . 24) . (4 0)) ((25 . 25) . (0))
   4324                     ((26 . 29) . (4 0)) ((30 . 30) . (0)) ((31 . 33) . (4 0))
   4325                     ((34 . 588) . nil) ((589 . 595) . (0)) ((596 . 814) . nil)
   4326                     ((815 . 820) . (0)) ((821 . 898) . nil))))
   4327       (cl-loop for (range . value) in values
   4328                do (goto-char (point-min))
   4329                (forward-line (1- (car range)))
   4330                (dotimes (_ (- (cdr range) (car range)))
   4331                  (should (equal (markdown-calculate-list-levels) value))
   4332                  (forward-line))))))
   4333 
   4334 (ert-deftest test-markdown-lists/levels-interior ()
   4335   "Test `markdown-calculate-list-levels' from inside a list item."
   4336   (markdown-test-file "nested-list.text"
   4337     (goto-char 36)
   4338     (should (equal (markdown-calculate-list-levels) (list 3)))
   4339     (goto-char 267)
   4340     (should (equal (markdown-calculate-list-levels) (list 7 3)))
   4341     (goto-char 540)
   4342     (should (equal (markdown-calculate-list-levels) (list 11 7 3)))))
   4343 
   4344 (ert-deftest test-markdown-lists/bounds-1 ()
   4345   "Test list item bounds function `markdown-cur-list-item-bounds'."
   4346   (markdown-test-file "lists.text"
   4347     (markdown-test-goto-heading "Case 9")
   4348     (forward-line)
   4349     (should (eq (point) 3699))
   4350     (markdown-next-list-item 4)
   4351     (should (eq (point) 3700))
   4352     (should (equal (butlast (markdown-cur-list-item-bounds))
   4353                    (list 3700 3901 0 4 "-   " nil)))
   4354     (markdown-next-list-item 4)
   4355     (should (eq (point) 3903))
   4356     (should (equal (butlast (markdown-cur-list-item-bounds))
   4357                    (list 3903 3937 0 4 "*   " nil)))))
   4358 
   4359 (ert-deftest test-markdown-lists/bounds-2 ()
   4360   "Function `markdown-cur-list-item-bounds' should return nil outside of list items."
   4361   (markdown-test-string "line one\n\n* item\n"
   4362     (should (null (markdown-cur-list-item-bounds)))
   4363     (forward-line)
   4364     (should (null (markdown-cur-list-item-bounds)))
   4365     (forward-line)
   4366     (should (markdown-cur-list-item-bounds))))
   4367 
   4368 (ert-deftest test-markdown-lists/bounds-prev ()
   4369   "Test list item bounds function `markdown-prev-list-item-bounds'."
   4370   (markdown-test-file "lists.text"
   4371     (markdown-test-goto-heading "Case 9")
   4372     (markdown-next-list-item 4)
   4373     (markdown-next-list-item 4)
   4374     (should (eq (point) 3903))
   4375     (should (equal (butlast (markdown-prev-list-item-bounds))
   4376                    (list 3700 3901 0 4 "-   " nil)))))
   4377 
   4378 (ert-deftest test-markdown-lists/bounds-next ()
   4379   "Test list item bounds function `markdown-next-list-item-bounds'."
   4380   (markdown-test-file "lists.text"
   4381     (markdown-test-goto-heading "Case 2")
   4382     (goto-char 1283)
   4383     (should-not (markdown-next-list-item-bounds))
   4384     (markdown-test-goto-heading "Case 9")
   4385     (markdown-next-list-item 4)
   4386     (should (eq (point) 3700))
   4387     (should (equal (butlast (markdown-next-list-item-bounds))
   4388                    (list 3903 3937 0 4 "*   " nil)))))
   4389 
   4390 (ert-deftest test-markdown-lists/bounds-gfm-task-list-item ()
   4391   "Test `markdown-cur-list-item-bounds' with a GFM task list item."
   4392   (markdown-test-string "  - [ ] task name"
   4393     (should (equal (butlast (markdown-cur-list-item-bounds))
   4394                    '(1 18 2 4 "- " "[ ] ")))))
   4395 
   4396 (ert-deftest test-markdown-lists/gfm-task-list-item-at-point-1 ()
   4397   "Test `markdown-gfm-task-list-item-at-point' with regular list items."
   4398   (markdown-test-file "nested-list.text"
   4399     (dolist (pos '(1 26 36 267 514 540))
   4400       (goto-char pos)
   4401       (should-not (markdown-gfm-task-list-item-at-point)))))
   4402 
   4403 (ert-deftest test-markdown-lists/gfm-task-list-item-at-point-2 ()
   4404   "Test `markdown-gfm-task-list-item-at-point' with a task list item."
   4405   (markdown-test-string "  - [ ] task"
   4406     (should (markdown-gfm-task-list-item-at-point))))
   4407 
   4408 (ert-deftest test-markdown-insertion/insert-gfm-task-list-item ()
   4409   "Test `markdown-insert-list-item' in a GFM task list."
   4410   (markdown-test-string "  - [ ] task"
   4411     (goto-char (point-max))
   4412     (call-interactively 'markdown-insert-list-item)
   4413     (should (string-equal (buffer-string) "  - [ ] task\n  - [ ] "))))
   4414 
   4415 (ert-deftest test-markdown-lists/promotion-and-demotion-1 ()
   4416   "Test function `markdown-promote-list-item'."
   4417   (markdown-test-file "nested-list.text"
   4418     (forward-line)
   4419     (markdown-demote-list-item)
   4420     (should (looking-at-p "       - List level 1 item 2
   4421 
   4422          Second paragraph of item 2
   4423 
   4424             Nested pre block in item 2
   4425             Four spaces past the marker
   4426 
   4427          Another paragraph of item 2"))
   4428     (markdown-promote-list-item)
   4429     (should (looking-at-p "   - List level 1 item 2
   4430 
   4431      Second paragraph of item 2
   4432 
   4433         Nested pre block in item 2
   4434         Four spaces past the marker
   4435 
   4436      Another paragraph of item 2"))))
   4437 
   4438 (ert-deftest test-markdown-lists/promotion-and-demotion-2 ()
   4439   "Test function `markdown-promote-list-item'."
   4440   (markdown-test-file "nested-list.text"
   4441     (forward-line 22)
   4442     (should (looking-at-p "           - List level 3 item 1
   4443 
   4444                  Nested pre block"))
   4445     (markdown-demote-list-item)
   4446     (should (looking-at-p "               - List level 3 item 1
   4447 
   4448                      Nested pre block"))
   4449     (markdown-promote-list-item)
   4450     (should (looking-at-p "           - List level 3 item 1
   4451 
   4452                  Nested pre block"))))
   4453 
   4454 (ert-deftest test-markdown-lists/promotion-and-demotion-custom ()
   4455   "Test custom variable `markdown-list-indent-width'."
   4456   (markdown-test-file "nested-list.text"
   4457     (forward-line)
   4458     (should (looking-at "   - List level 1 item 2
   4459 
   4460      Second paragraph of item 2
   4461 
   4462         Nested pre block in item 2
   4463         Four spaces past the marker
   4464 
   4465      Another paragraph of item 2"))
   4466     (let ((markdown-list-indent-width 2))
   4467       (markdown-demote-list-item))
   4468     (should (looking-at "     - List level 1 item 2
   4469 
   4470        Second paragraph of item 2
   4471 
   4472           Nested pre block in item 2
   4473           Four spaces past the marker
   4474 
   4475        Another paragraph of item 2"))))
   4476 
   4477 (ert-deftest test-markdown-lists/add-gfm-checkbox ()
   4478   (markdown-test-file "check-items.text"
   4479     (goto-char (point-min))
   4480     (end-of-line)
   4481     (should (markdown-insert-gfm-checkbox))
   4482     (should (= (line-number-at-pos (point)) 1))
   4483     (should (eolp))
   4484     (should (string-equal (buffer-substring-no-properties (line-beginning-position) (point))
   4485                           "  * [ ] "))
   4486 
   4487     (forward-line 2)
   4488     (back-to-indentation)
   4489     (should (markdown-insert-gfm-checkbox))
   4490     (should (= (line-number-at-pos (point)) 3))
   4491     (should (string-equal (buffer-substring-no-properties (line-beginning-position) (point))
   4492                           "  * [ ] "))
   4493     (should (string-equal (buffer-substring-no-properties (point) (line-end-position))
   4494                           "item1"))
   4495 
   4496     (forward-line 2)
   4497     (back-to-indentation)
   4498     (forward-char 1)
   4499     (should (markdown-insert-gfm-checkbox))
   4500     (should (= (line-number-at-pos (point)) 5))
   4501     (should (string-equal (buffer-substring-no-properties (line-beginning-position) (point))
   4502                           "  * [ ] i"))
   4503     (should (string-equal (buffer-substring-no-properties (point) (line-end-position))
   4504                           "tem2"))
   4505 
   4506     (forward-line 2)
   4507     (back-to-indentation)
   4508     (forward-char 2)
   4509     (should (markdown-insert-gfm-checkbox))
   4510     (should (= (line-number-at-pos (point)) 7))
   4511     (should (string-equal (buffer-substring-no-properties (line-beginning-position) (point))
   4512                           "- [ ] "))
   4513     (should (string-equal (buffer-substring-no-properties (point) (line-end-position))
   4514                           "item3"))
   4515 
   4516     (forward-line 2)
   4517     (back-to-indentation)
   4518     (forward-char 3)
   4519     (should (markdown-insert-gfm-checkbox))
   4520     (should (= (line-number-at-pos (point)) 9))
   4521     (should (string-equal (buffer-substring-no-properties (line-beginning-position) (point))
   4522                           "- [ ] i"))
   4523     (should (string-equal (buffer-substring-no-properties (point) (line-end-position))
   4524                           "tem4"))
   4525 
   4526     (forward-line 2)
   4527     (end-of-line)
   4528     (should-not (markdown-insert-gfm-checkbox))
   4529     (should (= (line-number-at-pos (point)) 11))
   4530     (should (eolp))
   4531     (should (string-equal (buffer-substring-no-properties (line-beginning-position) (point))
   4532                           "*   [ ] item5"))
   4533 
   4534     (forward-line 1)
   4535     (back-to-indentation)
   4536     (should (markdown-insert-gfm-checkbox))
   4537     (should (= (line-number-at-pos (point)) 12))
   4538     (should (eolp))
   4539     (should (string-equal (buffer-substring-no-properties
   4540                            (line-beginning-position)
   4541                            (point))
   4542                           "*   [ ] "))))
   4543 
   4544 (ert-deftest test-markdown-lists/toggle-gfm-checkbox ()
   4545   (markdown-test-string "   -   [X] GFM task list item"
   4546     (should (string-equal (markdown-toggle-gfm-checkbox) "[ ]"))
   4547     (should (string-equal (buffer-string) "   -   [ ] GFM task list item"))
   4548     (should (string-equal (markdown-toggle-gfm-checkbox) "[x]"))
   4549     (should (string-equal (buffer-string) "   -   [x] GFM task list item"))))
   4550 
   4551 (ert-deftest test-markdown-lists/clean-list-numbers ()
   4552   "Test for `markdown-cleanup-list-numbers'.
   4553 Detail: https://github.com/jrblevin/markdown-mode/issues/392"
   4554   (markdown-test-string "Shortcuts
   4555 ---------
   4556   2. Horizontal rule: `C-c C-s -`
   4557   3. Underlined header `C-c C-s !`
   4558  10. Convert to HTML: `C-c C-c m`
   4559 "
   4560     (call-interactively #'markdown-cleanup-list-numbers)
   4561     (forward-line 2)
   4562     (should (looking-at-p "\\s-+1\\. Horizontal rule"))
   4563     (forward-line 1)
   4564     (should (looking-at-p "\\s-+2\\. Underlined header"))
   4565     (forward-line 1)
   4566     (should (looking-at-p "\\s-+3\\. Convert to HTML"))))
   4567 
   4568 (ert-deftest test-markdown-lists/beginning-of-list ()
   4569   "Test `markdown-beginning-of-list'."
   4570   (markdown-test-file "lists.text"
   4571     ;; Case 1: not in a list
   4572     (goto-char 399)
   4573     (should-not (markdown-beginning-of-list))
   4574     (should (= (point) 399))
   4575     ;; Case 2
   4576     (goto-char 1281)
   4577     (should (= (markdown-beginning-of-list) 1063))
   4578     (should (= (point) 1063))
   4579     (goto-char 1395)
   4580     (should (= (markdown-beginning-of-list) 1063))
   4581     (should (= (point) 1063))
   4582     ;; Case 3
   4583     (goto-char 1848)
   4584     (should (= (markdown-beginning-of-list) 1659))
   4585     (should (= (point) 1659))
   4586     ;; Case 4
   4587     (goto-char 2041)
   4588     (should (= (markdown-beginning-of-list) 1919))
   4589     (should (= (point) 1919))
   4590     ;; Case 8
   4591     (goto-char 3553)
   4592     (should (= (markdown-beginning-of-list) 3096))
   4593     (should (= (point) 3096))))
   4594 
   4595 (ert-deftest test-markdown-lists/end-of-list ()
   4596   "Test `markdown-end-of-list'."
   4597   (markdown-test-file "lists.text"
   4598     ;; Case 1: not in a list
   4599     (goto-char 399)
   4600     (should-not (markdown-end-of-list))
   4601     (should (= (point) 399))
   4602     ;; Case 2
   4603     (goto-char 1281)
   4604     (should (= (markdown-end-of-list) 1396))
   4605     (should (= (point) 1396))
   4606     (goto-char 1395)
   4607     (should (= (markdown-end-of-list) 1396))
   4608     (should (= (point) 1396))
   4609     ;; Case 3
   4610     (goto-char 1659)
   4611     (should (= (markdown-end-of-list) 1849))
   4612     (should (= (point) 1849))
   4613     ;; Case 4
   4614     (goto-char 2041)
   4615     (should (= (markdown-end-of-list) 2092))
   4616     (should (= (point) 2092))
   4617     ;; Case 8
   4618     (goto-char 3553)
   4619     (should (= (markdown-end-of-list) 3614))
   4620     (should (= (point) 3614))))
   4621 
   4622 (ert-deftest test-markdown-lists/up-list ()
   4623   "Test `markdown-up-list'."
   4624   (markdown-test-file "nested-list.text"
   4625     (goto-char 581)
   4626     (should (= (markdown-up-list) 484))
   4627     (should (= (point) 484))
   4628     (should (= (markdown-up-list) 191))
   4629     (should (= (point) 191))
   4630     ;; Return nil upon failure, but move out of list.
   4631     (should-not (markdown-up-list))
   4632     (should (= (point) (point-min)))))
   4633 
   4634 ;;; Outline minor mode tests:
   4635 
   4636 (ert-deftest test-markdown-outline/navigation ()
   4637   "Test outline navigation functions."
   4638   (markdown-test-file "outline.text"
   4639     ;; Navigate to the first visible heading
   4640     (markdown-next-visible-heading 1)
   4641     (should (eq (point) 19))
   4642     (should (looking-at "^# A top-level header"))
   4643     ;; Navigate forward at the same level
   4644     (markdown-forward-same-level 1)
   4645     (should (eq (point) 351))
   4646     (should (looking-at "^An underline-style header$"))
   4647     ;; Navigate backward by four visible headings
   4648     (markdown-previous-visible-heading 4)
   4649     (should (eq (point) 69))
   4650     (should (looking-at "^## A second-level header$"))
   4651     ;; Navigate up the hierarchy (atx)
   4652     (call-interactively #'markdown-up-heading)
   4653     (should (looking-at "^# A top-level header"))
   4654     (should (eq (mark) 69))
   4655     ;; Navigate up the hierarchy (setext)
   4656     (goto-char 516)
   4657     (call-interactively #'markdown-up-heading)
   4658     (should (looking-at "^An underline-style header$"))
   4659     (should (eq (mark) 516))
   4660     ;; Navigate back in the outline (setext to atx)
   4661     (forward-line) ;; move to setext underline
   4662     (markdown-backward-same-level 1)
   4663     (should (looking-at "^# A top-level header"))))
   4664 
   4665 (ert-deftest test-markdown-outline/navigation-with-code ()
   4666   "Test outline navigation functions with code blocks."
   4667   (markdown-test-file "outline-code.text"
   4668     ;; Navigate forward at the same level
   4669     (markdown-forward-same-level 1)
   4670     (should (eq (point) 159))
   4671     (should (looking-at "^# Level one again"))))
   4672 
   4673 (ert-deftest test-markdown-outline/back-to-heading-over-code-block ()
   4674   "Test `markdown-back-to-heading-over-code-block' over."
   4675   (markdown-test-file "outline-code.text"
   4676     ;; Initialize match data to known quantity.
   4677     (set-match-data '(1 2 3 4))
   4678     (should (equal (match-data t) '(1 2 3 4)))
   4679     ;; Function should navigate back over code blocks.
   4680     (re-search-forward "^# In a code block")
   4681     (should (= (markdown-back-to-heading-over-code-block) 69))
   4682     ;; Match data should be set for markdown-regex-header.
   4683     (should (equal (match-data t) (get-text-property (point) 'markdown-heading)))
   4684     ;; Function should return t when at a heading.
   4685     (should (equal (markdown-back-to-heading-over-code-block) t))
   4686     ;; Insert some text before the first heading.
   4687     (goto-char (point-min))
   4688     (save-excursion (insert "foo\n\n"))
   4689     ;; Function should throw an error if no previous heading.
   4690     (should-error (markdown-back-to-heading-over-code-block))
   4691     ;; Function should return nil without error if NO-ERROR is non-nil.
   4692     (should-not (markdown-back-to-heading-over-code-block t t))))
   4693 
   4694 (ert-deftest test-markdown-outline/visibility-atx ()
   4695   "Test outline visibility cycling for ATX-style headers."
   4696   (markdown-test-file "outline.text"
   4697     (let (last-command this-command)
   4698       ;; Navigate to the second visible heading
   4699       (markdown-next-visible-heading 2)
   4700       (should (eq (point) 69))
   4701       (should (looking-at "^## A second-level header$"))
   4702       ;; Cycle visibility of this subtree
   4703       (setq this-command 'markdown-cycle)
   4704       (markdown-cycle)
   4705       (setq last-command 'markdown-cycle)
   4706       (should (eq (point) 69))
   4707       (should (looking-at "^## A second-level header$"))
   4708       ;; Test that the entire subtree is invisible
   4709       (markdown-test-range-has-property 93 349 'invisible 'outline)
   4710       ;; Cycle visibility of this subtree again
   4711       (markdown-cycle)
   4712       (should (eq (point) 69))
   4713       (should (looking-at "^## A second-level header$"))
   4714       ;; Test that text is visible
   4715       (markdown-test-range-has-property 95 121 'invisible nil)
   4716       ;; Test that subheadings are visible
   4717       (markdown-test-range-has-property 123 141 'invisible nil)
   4718       ;; Cycle visibility of this subtree again
   4719       (markdown-cycle)
   4720       (should (eq (point) 69))
   4721       (should (looking-at "^## A second-level header$"))
   4722       ;; Verify that entire subtree is visible
   4723       (markdown-test-range-has-property 93 349 'invisible nil))))
   4724 
   4725 (ert-deftest test-markdown-outline/visibility-setext ()
   4726   "Test outline visibility cycling for setext-style headers."
   4727   (markdown-test-file "outline.text"
   4728     ;; Navigate to the sixth visible heading
   4729     (markdown-next-visible-heading 7)
   4730     (markdown-previous-visible-heading 1)
   4731     (should (looking-at markdown-regex-header))
   4732     (should (string-equal (match-string-no-properties 1) "An underline-style header"))
   4733     (should (string-equal (match-string-no-properties 2) "========================="))
   4734     ;; Cycle visibility subtree, test that it's invisible
   4735     (markdown-cycle)
   4736     (markdown-test-range-has-property 404 515 'invisible 'outline)
   4737     ;; Cycle visibility subtree, test that text and headers are visible
   4738     (markdown-cycle)
   4739     (markdown-test-range-has-property 404 417 'invisible nil)
   4740     (markdown-test-range-has-property 420 451 'invisible nil)))
   4741 
   4742 (ert-deftest test-markdown-outline/visibility-with-code ()
   4743   "Test outline visibility cycling with code blocks."
   4744   (markdown-test-file "outline-code.text"
   4745     (let (last-command this-command)
   4746       ;; Cycle global visibility to "overview" mode
   4747       (setq this-command 'markdown-cycle)
   4748       (markdown-cycle t)
   4749       (setq last-command 'markdown-cycle)
   4750       (should (eq (point) (point-min)))
   4751       (should (looking-at "^# Level one"))
   4752       ;; Test that the code block is invisible
   4753       (markdown-test-range-has-property 83 157 'invisible 'outline)
   4754       ;; Check subsequent headings
   4755       (outline-next-visible-heading 1)
   4756       (should (eq (point) 69))
   4757       (should (looking-at "^## Level two"))
   4758       (outline-next-visible-heading 1)
   4759       (should (eq (point) 159))
   4760       (should (looking-at "^# Level one again")))))
   4761 
   4762 (ert-deftest test-markdown-outline/visibility-with-metadata ()
   4763   "Test outline visibility cycling with metadata blocks."
   4764   (markdown-test-string
   4765       "---
   4766 layout = post
   4767 date = 2015-08-13 11:35:25 EST
   4768 ---
   4769 "
   4770     (let (last-command this-command)
   4771       ;; Cycle global visibility to "overview" mode
   4772       (setq this-command 'markdown-cycle)
   4773       (markdown-cycle t)
   4774       ;; Check that text is visible
   4775       (markdown-test-range-has-property (point-min) (point-max) 'invisible nil))
   4776 
   4777     (let (last-command this-command)
   4778       ;; Cycle global visibility to "overview" mode
   4779       (setq this-command 'markdown-cycle)
   4780       (let ((current-prefix-arg '(4)))
   4781         (markdown-cycle)
   4782         ;; Check that text is visible
   4783         (markdown-test-range-has-property (point-min) (point-max) 'invisible nil)))))
   4784 
   4785 (ert-deftest test-markdown-outline/level ()
   4786   "Test `markdown-outline-level'."
   4787   (markdown-test-file "outline.text"
   4788     (markdown-next-heading)
   4789     (should (= (markdown-outline-level) 1))
   4790     (markdown-forward-same-level 1)
   4791     (should (= (markdown-outline-level) 1))
   4792     (markdown-next-heading)
   4793     (should (= (markdown-outline-level) 2))
   4794     (markdown-next-heading)
   4795     (should (= (markdown-outline-level) 1))
   4796     (markdown-next-heading)
   4797     (should (= (markdown-outline-level) 2))))
   4798 
   4799 ;;; Movement tests:
   4800 
   4801 (ert-deftest test-markdown-movement/defun ()
   4802   "Test defun navigation."
   4803   (markdown-test-file "outline.text"
   4804     ;; end-of-defun should go to point-max
   4805     (end-of-defun 10)
   4806     (should (= (point) (point-max)))
   4807     ;; end-of-defun should stop just before the next header
   4808     (goto-char (point-min))
   4809     (end-of-defun)
   4810     (should (looking-at "\n# A top-level header"))
   4811     (end-of-defun)
   4812     (should (looking-at "\n## A second-level header"))
   4813     (end-of-defun)
   4814     (should (looking-at "\n### Third level ###"))
   4815     (end-of-defun)
   4816     (should (looking-at "\n### Third level number two ###"))
   4817     ;; beginning-of-defun should move to the start of the previous header
   4818     (beginning-of-defun)
   4819     (should (looking-at "### Third level ###"))
   4820     (beginning-of-defun)
   4821     (should (looking-at "## A second-level header"))
   4822     (beginning-of-defun)
   4823     (should (looking-at "# A top-level header"))
   4824     (beginning-of-defun)
   4825     ;; beginning-of-defun should move up to point-min
   4826     (should (= (point) (point-min)))
   4827     ;; (beginning-of-defun -1)  should move to the start of the next header
   4828     (forward-line 2)
   4829     (beginning-of-defun -1)
   4830     (should (looking-at "## A second-level header"))
   4831     (beginning-of-defun -1)
   4832     (should (looking-at "### Third level ###"))
   4833     (beginning-of-defun -1)
   4834     (should (looking-at "### Third level number two ###"))))
   4835 
   4836 (ert-deftest test-markdown-movement/beginning-of-defun-at-point-max ()
   4837   "Test beginning of defun navigation at point-max."
   4838   (markdown-test-file "outline.text"
   4839     (goto-char (point-max))
   4840     (beginning-of-defun)))
   4841 
   4842 (ert-deftest test-markdown-movement/text-block ()
   4843   "Test plain text block movement."
   4844   (markdown-test-file "outline.text"
   4845     (markdown-end-of-text-block)
   4846     (should (looking-at "\n# A top-level header"))
   4847     (markdown-end-of-text-block)
   4848     (should (looking-at "\nfollowed by some body text"))
   4849     (markdown-end-of-text-block)
   4850     (should (looking-at "\n## A second-level header"))
   4851     (markdown-end-of-text-block)
   4852     (should (looking-at "\nfollowed by some body text"))
   4853     (markdown-end-of-text-block)
   4854     (should (looking-at "\n### Third level ###"))
   4855     (markdown-end-of-text-block)
   4856     (should (looking-at "\n\\* A list item"))
   4857     (markdown-end-of-text-block)
   4858     (should (looking-at "\n### Third level number two ###"))
   4859     (markdown-end-of-text-block)
   4860     (should (looking-at "\n### Level two again"))
   4861     (markdown-end-of-text-block)
   4862     (should (looking-at "\nfollowed by some body text"))
   4863 
   4864     (markdown-test-goto-heading "Level two")
   4865     (markdown-end-of-text-block)
   4866     (should (looking-at "\nbar"))
   4867     (markdown-end-of-text-block)
   4868     (should (= (point) (point-max)))
   4869     (markdown-beginning-of-text-block)
   4870     (should (looking-at "bar"))
   4871     (markdown-beginning-of-text-block)
   4872     (should (looking-at "## Level two"))
   4873     (markdown-beginning-of-text-block)
   4874     (should (looking-at "foo"))
   4875     (markdown-beginning-of-text-block)
   4876     (should (looking-at "# Level one"))
   4877     (markdown-beginning-of-text-block)
   4878     (should (looking-at "* With"))
   4879     (markdown-beginning-of-text-block)
   4880     (should (looking-at "And a level two underline header"))
   4881 
   4882     (goto-char (point-min))
   4883     (markdown-test-goto-heading "A top-level header")
   4884     (beginning-of-line)
   4885     (markdown-beginning-of-text-block)
   4886     (should (= (point) (point-min)))))
   4887 
   4888 (ert-deftest test-markdown-movement/mark-text-block ()
   4889   "Test `markdown-mark-text-block'."
   4890   (markdown-test-file "outline.text"
   4891     ;; Start in middle of nested list with no separating whitespace.
   4892     (goto-char 193)
   4893     (markdown-mark-text-block)
   4894     (should (= (point) 143))
   4895     (should (= (mark) 269))))
   4896 
   4897 (ert-deftest test-markdown-movement/paragraph ()
   4898   "Test Markdown paragraph movement."
   4899   (markdown-test-file "outline.text"
   4900     (markdown-forward-paragraph)
   4901     (should (looking-at "\n# A top-level header"))
   4902     (markdown-forward-paragraph)
   4903     (should (looking-at "\nfollowed by some body text"))
   4904     (markdown-forward-paragraph)
   4905     (should (looking-at "\n## A second-level header"))
   4906     (markdown-forward-paragraph)
   4907     (should (looking-at "\nfollowed by some body text"))
   4908     (markdown-forward-paragraph)
   4909     (should (looking-at "\n### Third level ###"))
   4910     (markdown-forward-paragraph)
   4911     (should (looking-at "\n\\* A list item"))
   4912     (markdown-forward-paragraph)
   4913     (should (looking-at "\\* and another"))
   4914     (markdown-forward-paragraph)
   4915     (should (looking-at "   \\+ and a sublist"))
   4916     (markdown-forward-paragraph)
   4917     (should (looking-at "- And a third"))
   4918     (markdown-forward-paragraph)
   4919     (should (looking-at "\n### Third level number two ###"))
   4920     (markdown-forward-paragraph)
   4921     (should (looking-at "\n### Level two again"))
   4922     (markdown-forward-paragraph)
   4923     (should (looking-at "\nfollowed by some body text"))
   4924 
   4925     (markdown-test-goto-heading "Level two")
   4926     (markdown-forward-paragraph)
   4927     (should (looking-at "\nbar"))
   4928     (markdown-forward-paragraph)
   4929     (should (= (point) (point-max)))
   4930     (markdown-backward-paragraph)
   4931     (should (looking-at "bar"))
   4932     (markdown-backward-paragraph)
   4933     (should (looking-at "## Level two"))
   4934     (markdown-backward-paragraph)
   4935     (should (looking-at "foo"))
   4936     (markdown-backward-paragraph)
   4937     (should (looking-at "# Level one"))
   4938     (markdown-backward-paragraph)
   4939     (should (looking-at "\\* List"))
   4940     (markdown-backward-paragraph)
   4941     (should (looking-at "\\* an unordered"))
   4942     (markdown-backward-paragraph)
   4943     (should (looking-at "\\* With"))
   4944     (markdown-backward-paragraph)
   4945     (should (looking-at "And a level two underline header"))
   4946 
   4947     (goto-char (point-min))
   4948     (markdown-test-goto-heading "A top-level header")
   4949     (beginning-of-line)
   4950     (markdown-backward-paragraph)
   4951     (should (= (point) (point-min)))))
   4952 
   4953 (ert-deftest test-markdown-movement/forward-paragraph-with-whitespace ()
   4954   "Test Markdown paragraph movement."
   4955   (markdown-test-file "blocks.md"
   4956     (markdown-test-goto-heading "With Whitespace")
   4957     (dolist (pos '(58 67 78 94 109 114 123 131 135 147 157 170 184 199))
   4958       (markdown-forward-paragraph)
   4959       (should (= (point) pos)))))
   4960 
   4961 (ert-deftest test-markdown-movement/backward-paragraph-with-whitespace ()
   4962   "Test Markdown paragraph movement."
   4963   (markdown-test-file "blocks.md"
   4964     (markdown-test-goto-heading "With Whitespace")
   4965     (markdown-next-heading)
   4966     (should (= (point) 200))
   4967     (dolist (pos '(185 172 158 148 136 132 124 115 110 94 78 67 59))
   4968       (markdown-backward-paragraph)
   4969       (should (= (point) pos)))))
   4970 
   4971 (ert-deftest test-markdown-movement/forward-paragraph-without-whitespace ()
   4972   "Test Markdown paragraph movement."
   4973   (markdown-test-file "blocks.md"
   4974     (markdown-test-goto-heading "Without Whitespace")
   4975     (dolist (pos '(222 230 240 255 270 275 283 291 294 305 314 326 340 354))
   4976       (markdown-forward-paragraph)
   4977       (should (= (point) pos)))))
   4978 
   4979 (ert-deftest test-markdown-movement/backward-paragraph-without-whitespace ()
   4980   "Test Markdown paragraph movement."
   4981   (markdown-test-file "blocks.md"
   4982     (goto-char (point-max))
   4983     (dolist (pos '(340 328 314 305 294 291 284 275 271 255 240 230 223 200))
   4984       (markdown-backward-paragraph)
   4985       (should (= (point) pos)))))
   4986 
   4987 (ert-deftest test-markdown-movement/block ()
   4988   "Test Markdown block movement."
   4989   (markdown-test-file "outline.text"
   4990     (markdown-forward-block)
   4991     (should (looking-at "\n# A top-level header"))
   4992     (markdown-forward-block)
   4993     (should (looking-at "\nfollowed by some body text"))
   4994     (markdown-forward-block)
   4995     (should (looking-at "\n## A second-level header"))
   4996     (markdown-forward-block)
   4997     (should (looking-at "\nfollowed by some body text"))
   4998     (markdown-forward-block)
   4999     (should (looking-at "\n### Third level ###"))
   5000     (markdown-forward-block)
   5001     (should (looking-at "\n\\* A list item"))
   5002     (markdown-forward-block)
   5003     (should (looking-at "\n### Third level number two ###"))
   5004     (markdown-forward-block)
   5005     (should (looking-at "\n### Level two again"))
   5006     (markdown-forward-block)
   5007     (should (looking-at "\nfollowed by some body text"))
   5008 
   5009     (markdown-test-goto-heading "Level two")
   5010     (markdown-forward-block)
   5011     (should (looking-at "\nbar"))
   5012     (markdown-forward-block)
   5013     (should (= (point) (point-max)))
   5014     (markdown-backward-block)
   5015     (should (looking-at "bar"))
   5016     (markdown-backward-block)
   5017     (should (looking-at "## Level two"))
   5018     (markdown-backward-block)
   5019     (should (looking-at "foo"))
   5020     (markdown-backward-block)
   5021     (should (looking-at "# Level one"))
   5022     (markdown-backward-block)
   5023     (should (looking-at "\\* With"))
   5024     (markdown-backward-block)
   5025     (should (looking-at "And a level two underline header"))
   5026 
   5027     (goto-char (point-min))
   5028     (markdown-test-goto-heading "A top-level header")
   5029     (beginning-of-line)
   5030     (markdown-backward-block)
   5031     (should (= (point) (point-min)))))
   5032 
   5033 (ert-deftest test-markdown-movement/forward-block-with-whitespace ()
   5034   "Test Markdown block movement."
   5035   (markdown-test-file "blocks.md"
   5036     (markdown-test-goto-heading "With Whitespace")
   5037     (dolist (pos '(58 109 114 131 135 147 157 184 199))
   5038       (markdown-forward-block)
   5039       (should (= (point) pos)))))
   5040 
   5041 (ert-deftest test-markdown-movement/backward-block-with-whitespace ()
   5042   "Test Markdown block movement."
   5043   (markdown-test-file "blocks.md"
   5044     (markdown-test-goto-heading "With Whitespace")
   5045     (markdown-next-heading)
   5046     (dolist (pos '(185 158 148 136 132 115 110 59))
   5047       (markdown-backward-block)
   5048       (should (= (point) pos)))))
   5049 
   5050 (ert-deftest test-markdown-movement/forward-block-without-whitespace ()
   5051   "Test Markdown block movement."
   5052   (markdown-test-file "blocks.md"
   5053     (markdown-test-goto-heading "Without Whitespace")
   5054     (dolist (pos '(222 270 275 291 294 305 314 340 354))
   5055       (markdown-forward-block)
   5056       (should (= (point) pos)))))
   5057 
   5058 (ert-deftest test-markdown-movement/backward-block-without-whitespace ()
   5059   "Test Markdown block movement."
   5060   (markdown-test-file "blocks.md"
   5061     (goto-char (point-max))
   5062     (dolist (pos '(340 314 305 294 291 275 271 223 200))
   5063       (markdown-backward-block)
   5064       (should (= (point) pos)))))
   5065 
   5066 (ert-deftest test-markdown-movement/page ()
   5067   "Test Markdown page movement."
   5068   (markdown-test-file "outline.text"
   5069     (markdown-forward-page)
   5070     (should (looking-at "# A top-level header"))
   5071     (markdown-forward-page)
   5072     (should (looking-at "An underline-style header"))
   5073     (markdown-forward-page)
   5074     (should (looking-at "# Level one"))
   5075     (markdown-forward-page)
   5076     (should (eobp))
   5077     (markdown-backward-page)
   5078     (should (looking-at "# Level one"))
   5079     (markdown-backward-page)
   5080     (should (looking-at "An underline-style header"))
   5081     (markdown-backward-page)
   5082     (should (looking-at "# A top-level header"))
   5083     (markdown-backward-page)
   5084     (should (bobp))))
   5085 
   5086 (ert-deftest test-markdown-movement/blockquote-paragraphs ()
   5087   "Test filling of blockquotes containing multiple paragraphs."
   5088   (markdown-test-string "> Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n>\n> Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.\n"
   5089     (forward-paragraph)
   5090     (should (looking-at "^>$"))
   5091     (should (= (point) 128))
   5092     (forward-paragraph)
   5093     (should (= (point) (point-max)))))
   5094 
   5095 (ert-deftest test-markdown-movement/reference-definition ()
   5096   "Test jumping to reference definitions."
   5097   ;; Jumping to explicit reference definition
   5098   (markdown-test-string "[a][ref]\n\n[ref]: gopher://localhost/\n"
   5099     (markdown-reference-goto-definition)
   5100     (should (= (point) 18)))
   5101   ;; Jumping to implicit reference definition
   5102   (markdown-test-string "[a][]\n\n[a]: ftp://localhost/\n"
   5103     (markdown-reference-goto-definition)
   5104     (should (= (point) 13)))
   5105   ;; Creating non-existent reference definition
   5106   (markdown-test-string "[a][]\n"
   5107     (markdown-reference-goto-definition)
   5108     (should (= (point) 13))
   5109     (should (string-equal (buffer-string) "[a][]\n\n[a]: \n"))))
   5110 
   5111 (ert-deftest test-markdown-movement/back-to-same-level-over-code-block ()
   5112   "`markdown-backward-same-level' over code block which contains header
   5113 like statement. Detail: https://github.com/jrblevin/markdown-mode/issues/75"
   5114   (markdown-test-string "
   5115 ## Header 2-1
   5116 
   5117 ## Header 2-2
   5118 
   5119 ```R
   5120 # Header Like Statement
   5121 ```
   5122 
   5123 ## Header 2-3
   5124 "
   5125     (search-forward "## Header 2-3")
   5126     (let ((last-header-pos (point)))
   5127       (forward-line -1)
   5128       (call-interactively #'markdown-backward-same-level)
   5129       (should (looking-at-p "## Header 2-1"))
   5130 
   5131       (goto-char last-header-pos)
   5132       (call-interactively #'markdown-backward-same-level)
   5133       (should (looking-at-p "## Header 2-2"))
   5134 
   5135       (goto-char last-header-pos)
   5136       (markdown-backward-same-level 2)
   5137       (should (looking-at-p "## Header 2-1"))
   5138 
   5139       (search-forward "# Header Like Statement")
   5140       (call-interactively #'markdown-backward-same-level)
   5141       (should (looking-at-p "## Header 2-1")))))
   5142 
   5143 (ert-deftest test-markdown-movement/sentence ()
   5144   "Move sentencen which is wrapped markup characters.
   5145 Detail: https://github.com/jrblevin/markdown-mode/issues/517"
   5146   (markdown-test-string "*Sentence one.*  **Sentence two.**  ~Sentence three.~
   5147 _Sentence four._  `Sentence five.`  Sentence six.
   5148 Sentence seven. Sentence eight.
   5149 "
   5150     (forward-sentence 1)
   5151     (should (looking-back "one\\.\\*" (line-beginning-position)))
   5152     (forward-sentence 1)
   5153     (should (looking-back "two\\.\\*\\*" (line-beginning-position)))
   5154     (forward-sentence 1)
   5155     (should (looking-at-p "$"))
   5156     (save-excursion
   5157       (backward-sentence 2)
   5158       (should (looking-at-p "\\*\\*Sentence two")))
   5159     (forward-sentence 1)
   5160     (should (looking-back "four\\._" (line-beginning-position)))
   5161     (forward-sentence 1)
   5162     (should (looking-back "five\\.`" (line-beginning-position)))
   5163     (forward-sentence 1)
   5164     (should (looking-at-p "$"))
   5165     (forward-sentence 1)
   5166     (looking-back "seven\\." (line-beginning-position))
   5167     (forward-sentence 1)
   5168     (looking-at-p "$")))
   5169 
   5170 ;;; Link tests:
   5171 
   5172 (ert-deftest test-markdown-link/follow ()
   5173   "Test link following in a browser and in Emacs."
   5174   (markdown-test-string "[text](http://path?query=foo#id)"
   5175     (let* ((opened-url nil)
   5176            (browse-url-browser-function
   5177             (lambda (url &rest _args) (setq opened-url url))))
   5178       (markdown-follow-thing-at-point nil)
   5179       (should (equal opened-url "http://path?query=foo#id"))))
   5180   (when (featurep 'url-parse)
   5181     (markdown-test-string "[text](path?query=foo#id)"
   5182       (markdown-follow-thing-at-point nil)
   5183       (should (equal (file-name-nondirectory (buffer-file-name)) "path")))))
   5184 
   5185 (ert-deftest test-markdown-link/link-in-header ()
   5186   "Test link following even if it is in header.
   5187 Detail: https://github.com/jrblevin/markdown-mode/issues/430"
   5188   (markdown-test-string "---
   5189 [link](https://link-in-header.com)
   5190 ---"
   5191     (forward-line +1)
   5192     (let* ((opened-url nil)
   5193            (browse-url-browser-function
   5194             (lambda (url &rest _args) (setq opened-url url))))
   5195       (markdown-follow-thing-at-point nil)
   5196       (should (equal opened-url "https://link-in-header.com")))))
   5197 
   5198 (ert-deftest test-markdown-link/inline-link-at-pos ()
   5199   "Test `markdown-link-at-pos' return values with an inline link."
   5200   (markdown-test-string "[text](url \"title\")"
   5201     (should (equal (markdown-link-at-pos (point)) '(1 20 "text" "url" nil "title" nil)))))
   5202 
   5203 (ert-deftest test-markdown-link/inline-image-at-pos ()
   5204   "Test `markdown-link-at-pos' return values with an inline image."
   5205   (markdown-test-string "![text](url \"title\")"
   5206     (should (equal (markdown-link-at-pos (point)) '(1 21 "text" "url" nil "title" "!")))))
   5207 
   5208 (ert-deftest test-markdown-link/reference-link-at-pos ()
   5209   "Test `markdown-link-at-pos' return values with a reference link."
   5210   (markdown-test-string "[text][ref]"
   5211     (should (equal (markdown-link-at-pos (point)) '(1 12 "text" nil "ref" nil nil)))))
   5212 
   5213 (ert-deftest test-markdown-link/reference-image-at-pos ()
   5214   "Test `markdown-link-at-pos' return values with a reference image."
   5215   (markdown-test-string "![text][ref]"
   5216     (should (equal (markdown-link-at-pos (point)) '(1 13 "text" nil "ref" nil "!")))))
   5217 
   5218 (ert-deftest test-markdown-link/angle-uri-at-pos ()
   5219   "Test `markdown-link-at-pos' return values with an angle bracket inline link."
   5220   (markdown-test-string "<http://jblevins.org/projects/markdown-mode/>"
   5221     (should (equal (markdown-link-at-pos (point)) '(1 46 nil "http://jblevins.org/projects/markdown-mode/" nil nil nil)))))
   5222 
   5223 (ert-deftest test-markdown-link/plain-uri-at-pos ()
   5224   "Test `markdown-link-at-pos' return values with a plain URI."
   5225   (markdown-test-string "http://jblevins.org/projects/markdown-mode/"
   5226     (should (equal (markdown-link-at-pos (point)) '(1 44 nil "http://jblevins.org/projects/markdown-mode/" nil nil nil)))))
   5227 
   5228 (ert-deftest test-markdown-link/link-contains-parenthesis ()
   5229   "Test URL which contains close parenthesis.
   5230 Detail: https://github.com/jrblevin/markdown-mode/issues/408"
   5231   (let ((url "https://commons.wikimedia.org/wiki/Category:SVG_locator_maps_of_continents_(location_map_scheme)_(Winkel_3_projection)"))
   5232     (markdown-test-string (format "[foo](%s)" url)
   5233       (let ((link (markdown-link-at-pos (point))))
   5234         (should (string= (nth 3 link) url))))))
   5235 
   5236 (ert-deftest test-markdown-link/start-or-end-with-spaces ()
   5237   "Test `markdown-link-at-pos' return values with URL part starts/ends with spaces.
   5238 Detail: https://github.com/jrblevin/markdown-mode/issues/514"
   5239   (markdown-test-string "[Broken](
   5240 http://example.com  )
   5241 "
   5242     (let ((values (markdown-link-at-pos (point))))
   5243       (should (string= (nth 3 values) "http://example.com"))))
   5244 
   5245   (markdown-test-string "[Broken](
   5246 http://example.com \"title\"  )
   5247 "
   5248     (let ((values (markdown-link-at-pos (point))))
   5249       (should (string= (nth 3 values) "http://example.com"))
   5250       (should (string= (nth 5 values) "title")))))
   5251 
   5252 (ert-deftest test-markdown-link/follow-filename ()
   5253   "Test that `markdown-follow-thing-at-pos' uses
   5254 `markdown-translate-filename-function' to translate filenames."
   5255   (markdown-test-string "[text](/foo/bar/baz)"
   5256     (cl-letf* ((visited-files ())
   5257                ((symbol-function #'find-file)
   5258                 (lambda (filename)
   5259                   (push filename visited-files)))
   5260                (translated-files ())
   5261                (markdown-translate-filename-function
   5262                 (lambda (filename)
   5263                   (push filename translated-files)
   5264                   (format "/root%s.md" filename))))
   5265       (markdown-follow-thing-at-point nil)
   5266       (should (equal translated-files '("/foo/bar/baz")))
   5267       (should (equal visited-files '("/root/foo/bar/baz.md"))))))
   5268 
   5269 (ert-deftest test-markdown-link/link-p ()
   5270   "Test that `markdown-link-p' returns t if cursor is on link."
   5271   (markdown-test-string "[one][two] [three][four]"
   5272     (should (markdown-link-p))
   5273     (goto-char 2)
   5274     (should (markdown-link-p))
   5275     (goto-char 12)
   5276     (should (markdown-link-p))
   5277     (goto-char 13)
   5278     (should (markdown-link-p))))
   5279 
   5280 ;;; Wiki link tests:
   5281 
   5282 (ert-deftest test-markdown-wiki-link/file-local-variables ()
   5283   "Test enabling wiki links via file-local variables."
   5284   (markdown-test-file "wiki-links.text"
   5285     (should-not markdown-enable-wiki-links)
   5286     (hack-local-variables)
   5287     (should markdown-enable-wiki-links)))
   5288 
   5289 (ert-deftest test-markdown-wiki-link/aliasing ()
   5290   "Test filename extraction for aliased wiki links."
   5291   (let ((markdown-enable-wiki-links t))
   5292     (markdown-test-file "wiki-links.text"
   5293       ;; Confirm location of first wiki link
   5294       (should (eq (markdown-next-link) 8))
   5295       ;; Confirm location of second wiki link
   5296       (should (eq (markdown-next-link) 73))
   5297       ;; Test predicate function
   5298       (should (markdown-wiki-link-p))
   5299       ;; Test alias-first filename extraction
   5300       (setq markdown-wiki-link-alias-first t)
   5301       (should (string-equal (markdown-wiki-link-link) "second"))
   5302       ;; Test alias-second filename extraction
   5303       (setq markdown-wiki-link-alias-first nil)
   5304       (should (string-equal (markdown-wiki-link-link) "first")))))
   5305 
   5306 (ert-deftest test-markdown-wiki-link/navigation ()
   5307   "Test wiki link navigation."
   5308   (let ((markdown-enable-wiki-links t))
   5309     (markdown-test-file "wiki-links.text"
   5310       ;; Advance to first link
   5311       (should (eq (markdown-next-link) 8))
   5312       ;; Advance to second link
   5313       (should (eq (markdown-next-link) 73))
   5314       ;; Avance to final link
   5315       (should (eq (markdown-next-link) 155))
   5316       ;; Return nil and don't advance point
   5317       (should (eq (markdown-next-link) nil))
   5318       (should (eq (point) 155))
   5319       ;; Move back to second link
   5320       (should (eq (markdown-previous-link) 73))
   5321       ;; Move back to first link
   5322       (should (eq (markdown-previous-link) 8))
   5323       ;; Return nil and don't move point
   5324       (should (eq (markdown-previous-link) nil))
   5325       (should (eq (point) 8)))))
   5326 
   5327 (ert-deftest test-markdown-wiki-link/font-lock ()
   5328   "Test font lock faces for wiki links."
   5329   ;; If `temporary-file-directory' contains an inaccessible
   5330   ;; subdirectory, `markdown-fontify-buffer-wiki-links' fails because
   5331   ;; it calls `directory-files-recursively' on the directory, which
   5332   ;; fails because of
   5333   ;; <https://debbugs.gnu.org/cgi/bugreport.cgi?bug=28567>.  To fix
   5334   ;; this, we run the entire test in a new subdirectory of
   5335   ;; `temporary-file-directory', which is guaranteed to not contain
   5336   ;; any inaccessible directories.
   5337   (let ((temporary-file-directory
   5338          (file-name-as-directory (make-temp-file "markdown-test" :dir-flag))))
   5339     (markdown-test-temp-file "wiki-links.text"
   5340       (let* ((fn (concat (file-name-directory buffer-file-name)
   5341                          "inline.text"))
   5342              (markdown-enable-wiki-links t))
   5343         ;; Create inline.text in the same temp directory, refontify
   5344         (write-region "" nil fn nil 1)
   5345         (markdown-fontify-buffer-wiki-links)
   5346         ;; Confirm location of first wiki link
   5347         (should (eq (markdown-next-link) 8))
   5348         ;; First wiki link doesn't have a corresponding file
   5349         (markdown-test-range-has-property 8 20 'font-lock-face 'markdown-missing-link-face)
   5350         ;; Second wiki link doesn't have a corresponding file
   5351         (should (eq (markdown-next-link) 73))
   5352         (markdown-test-range-has-property 73 88 'font-lock-face 'markdown-missing-link-face)
   5353         ;; Move to third wiki link, and create the missing file
   5354         (should (eq (markdown-next-link) 155))
   5355         (should (string-equal (markdown-wiki-link-link) "inline"))
   5356         (markdown-test-range-has-property 155 164 'font-lock-face 'markdown-link-face)
   5357         ;; Check wiki links in code blocks
   5358         (markdown-test-range-has-face 360 395 'markdown-pre-face)
   5359         ;; Remove temporary files
   5360         (delete-file fn)))
   5361     (delete-directory temporary-file-directory)))
   5362 
   5363 (ert-deftest test-markdown-wiki-link/kill ()
   5364   "Simple tests for `markdown-kill-thing-at-point' for wiki links."
   5365   (let ((kill-ring nil)
   5366         (markdown-enable-wiki-links t)
   5367         (tests (list '("[[foo]]" . "foo")
   5368                      '("[[foo|bar]]" . "bar"))))
   5369     (dolist (test tests)
   5370       ;; Load test string (the car), move to end of first line, kill
   5371       ;; thing at point, and then verify that the kill ring contains cdr.
   5372       (markdown-test-string (car test)
   5373         (end-of-line)
   5374         (call-interactively 'markdown-kill-thing-at-point)
   5375         (should (string-equal (current-kill 0) (cdr test)))))))
   5376 
   5377 ;;; Filling tests:
   5378 
   5379 (ert-deftest test-markdown-filling/blockquote ()
   5380   "Test filling of blockquotes.
   5381 See `adaptive-fill-first-line-regexp'."
   5382   (markdown-test-string "> Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
   5383     (fill-paragraph)
   5384     (should (string-equal (buffer-string) "> Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do\n> eiusmod tempor incididunt ut labore et dolore magna aliqua."))))
   5385 
   5386 (ert-deftest test-markdown-filling/blockquote-paragraphs ()
   5387   "Test filling of blockquotes containing multiple paragraphs."
   5388   (markdown-test-string "> Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
   5389 >
   5390 > Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
   5391 "
   5392     (forward-paragraph)
   5393     (fill-paragraph)
   5394     (should (string-equal
   5395              (buffer-substring-no-properties (point-min) (point-max))
   5396              "> Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
   5397 >
   5398 > Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris
   5399 > nisi ut aliquip ex ea commodo consequat.
   5400 "))))
   5401 
   5402 (ert-deftest test-markdown-filling/nested-blockquote-paragraphs ()
   5403   "Test filling of nested blockquotes.
   5404 Detail: https://github.com/jrblevin/markdown-mode/issues/366"
   5405   (markdown-test-string "> > pursuit of Happiness.--That to secure these rights, Governments are
   5406 > > instituted among Men, deriving their just powers from the consent of
   5407 "
   5408     (fill-paragraph)
   5409     (should (string-equal
   5410              (buffer-substring-no-properties (point-min) (point-max))
   5411              "> > pursuit of Happiness.--That to secure these rights, Governments
   5412 > > are instituted among Men, deriving their just powers from the
   5413 > > consent of
   5414 "))))
   5415 
   5416 (ert-deftest test-markdown-filling/leanpub-block ()
   5417   "Test adaptive filling of Leanpub blocks."
   5418   (markdown-test-string "A> Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
   5419     (fill-paragraph)
   5420     (should (string-equal
   5421              (buffer-substring-no-properties (point-min) (point-max))
   5422              "A> Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do\nA> eiusmod tempor incididunt ut labore et dolore magna aliqua."))))
   5423 
   5424 (ert-deftest test-markdown-filling/space-after-list-marker ()
   5425   "`fill-paragraph' should preserve more than one space after a list marker,
   5426 since users may wish to indent their lists more than one space more than the
   5427 width of the marker. The examples on the Markdown Syntax page have three
   5428 spaces after the list marker for a total indentation of four."
   5429   (let ((str "\n\n*   List item indented four spaces.\n*   Also four spaces."))
   5430     (markdown-test-string str
   5431       (forward-line 2)
   5432       (fill-paragraph)
   5433       (should (string-equal (buffer-string) str)))))
   5434 
   5435 (ert-deftest test-markdown-filling/multi-line-list-with-more-space ()
   5436   "`fill-paragraph' should preserve more than one space after a list marker
   5437 (see `test-preserve-space-after-list-marker')."
   5438   (let ((str "*   This list item is continued on\n    the next line"))
   5439     (markdown-test-string str
   5440       ;; The first line is exactly 35 columns
   5441       (let ((fill-column 35))
   5442         (fill-paragraph)
   5443         (should (string-equal (buffer-string) str))))))
   5444 
   5445 (ert-deftest test-markdown-filling/definition-list-add-leading-spaces ()
   5446   "`fill-paragraph' should adapt to spaces after list marker."
   5447   (markdown-test-string
   5448       ":   This list item is continued on the next line"
   5449     (let ((fill-column 35))
   5450       (fill-paragraph)
   5451       (should (string-equal
   5452                (buffer-string)
   5453                ":   This list item is continued on\n    the next line")))))
   5454 
   5455 (ert-deftest test-markdown-filling/definition-list-preserve-leading-spaces ()
   5456   "`fill-paragraph' should preserve spaces after list marker."
   5457   (let ((str ":   This list item is continued on\n    the next line")
   5458         (fill-column 35))
   5459     (markdown-test-string
   5460         str (fill-paragraph)
   5461         (should (string-equal (buffer-string) str)))))
   5462 
   5463 (ert-deftest test-markdown-filling/list-item-plus ()
   5464   "Test filling of list items with plus sign markers.
   5465 See `adaptive-fill-regexp'."
   5466   (markdown-test-string "  + Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
   5467     (fill-paragraph)
   5468     (should (string-equal (buffer-string) "  + Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do\n    eiusmod tempor incididunt ut labore et dolore magna aliqua."))))
   5469 
   5470 (ert-deftest test-markdown-filling/list-item-plus-in-blockquote ()
   5471   "Test filling of list items with plus sign markers inside blockquote.
   5472 See `adaptive-fill-regexp'."
   5473   (markdown-test-string ">  + Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
   5474     (fill-paragraph)
   5475     (should (string-equal (buffer-string) ">  + Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do\n>    eiusmod tempor incididunt ut labore et dolore magna aliqua."))))
   5476 
   5477 (ert-deftest test-markdown-filling/line-break ()
   5478   "Test filling of paragraphs with hard line breaks.
   5479 See `paragraph-separate'."
   5480   (markdown-test-string "Lorem ipsum dolor sit amet,  \nconsectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
   5481     (let ((fill-column 70))
   5482       (fill-paragraph)
   5483       (should (string-equal (buffer-string) "Lorem ipsum dolor sit amet,  \nconsectetur adipisicing elit, sed do eiusmod tempor incididunt ut\nlabore et dolore magna aliqua.")))))
   5484 
   5485 (ert-deftest test-markdown-filling/decimal-number-at-beginning ()
   5486   "Test filling when a number with a decimal appears at the beginning of a line."
   5487   (markdown-test-string "The circumference of a circle divided by it's radius is around\n3.14."
   5488     (fill-paragraph)
   5489     (should (string-equal (buffer-string) "The circumference of a circle divided by it's radius is around 3.14."))))
   5490 
   5491 (ert-deftest test-markdown-filling/avoid-unintended-list-item ()
   5492   "Avoid breaking lines where it would result in an unintended list item."
   5493   (markdown-test-string "Lorem ipsum dolor sit 4. amet"
   5494     (let ((fill-column 22))
   5495       (fill-paragraph)
   5496       (should (string-equal (buffer-string) "Lorem ipsum dolor\nsit 4. amet")))))
   5497 
   5498 (ert-deftest test-markdown-filling/no-break-link-reference ()
   5499   "Shouldn't break line between label and url, or combine two link references."
   5500   (let ((str "[label1]: http://long-url.example.com\n[label2]: http://another-long-url.example.com/"))
   5501     (markdown-test-string str
   5502       (let ((fill-column 15)) ; after end of label, before end of URL
   5503         (fill-paragraph)
   5504         (should (string-equal (buffer-string) str))))))
   5505 
   5506 (ert-deftest test-markdown-filling/no-break-before-list-item ()
   5507   "There's no point in putting the first item of a list on the next line,
   5508 indented the same amount."
   5509   (let ((str "*   [Link](http://way-too-long.example.com)\n"))
   5510     (markdown-test-string str
   5511       (auto-fill-mode 1)
   5512       (let ((fill-column 10))
   5513         (end-of-line)
   5514         (funcall auto-fill-function)
   5515         ;; This test was known to fail in Emacs 25 and earlier.
   5516         (if (version< emacs-version "26.0")
   5517             (should-not (string-equal (buffer-string) str))
   5518           (should (string-equal (buffer-string) str)))))))
   5519 
   5520 (ert-deftest test-markdown-filling/break-within-list-item ()
   5521   "This doesn't suppress auto-fill within a multi-word list item."
   5522   :expected-result :failed
   5523   (markdown-test-string "*   [Link](http://example.com/) more text"
   5524     (auto-fill-mode 1)
   5525     (let ((fill-column 10))
   5526       (end-of-line)
   5527       (funcall auto-fill-function)
   5528       (should (string-equal
   5529                (buffer-string)
   5530                "*   [Link](http://example.com/)\n    more text")))))
   5531 
   5532 (ert-deftest test-markdown-filling/preserve-next-line-footnote ()
   5533   "Footnote block can be after label"
   5534   (let ((str "[^label1]:\n    Footnote block\n    more footnote")) ; six spaces
   5535     (markdown-test-string str
   5536       (let ((fill-column 20)) ; could fit "footnote" after label, but shouldn't
   5537         (fill-paragraph)
   5538         (should (string-equal (buffer-string) str))))))
   5539 
   5540 (ert-deftest test-markdown-filling/wrap-same-line-footnote ()
   5541   "Additional lines must be indented one level (four spaces) when wrapped."
   5542   (markdown-test-string "[^label]: Long line should be wrapped"
   5543     (let ((fill-column 25)) ; wrap before end of "should"
   5544       (fill-paragraph)
   5545       (should (string-equal (buffer-string) "[^label]: Long line\n    should be wrapped")))))
   5546 
   5547 (ert-deftest test-markdown-filling/wrap-extra-hanging-indentation ()
   5548   "Additional lines must be indented one level (four spaces) when wrapped."
   5549   (markdown-test-string "[^label]: Long line\n      should be wrapped"
   5550     (let ((fill-column 25)) ; wrap before end of "should"
   5551       (fill-paragraph)
   5552       (should (string-equal (buffer-string) "[^label]: Long line\n      should be wrapped")))))
   5553 
   5554 (ert-deftest test-markdown-filling/full-justification ()
   5555   "Test paragraph detection with lines with lots of whitespace."
   5556   (markdown-test-string "Lorem Ipsum Lorem Ipsum Lorem Ipsum Lorem Ipsum Lorem Ipsum Lorem Dolor Sit Amet Consectetur http://very-long-url.lorem.ipsum.sic.dolor.sit.amet.com"
   5557     (setq default-justification 'full)
   5558     (fill-paragraph)
   5559     (should (string-equal (buffer-string) "Lorem  Ipsum Lorem  Ipsum Lorem  Ipsum Lorem  Ipsum Lorem  Ipsum Lorem\nDolor                Sit               Amet                Consectetur\nhttp://very-long-url.lorem.ipsum.sic.dolor.sit.amet.com"))
   5560     (backward-paragraph)
   5561     (forward-paragraph)
   5562     (should (= (point) 198))))
   5563 
   5564 (ert-deftest test-markdown-filling/list-line ()
   5565   "Test fill-paragraph for list line. Don't insert bullet automatically.
   5566 Detail: https://github.com/jrblevin/markdown-mode/issues/79"
   5567   (markdown-test-string "* foo foo *foo* foo foo foo foo foo foo"
   5568     (let ((fill-column 10))
   5569       (fill-paragraph)
   5570       (fill-paragraph)
   5571       (forward-line 2)
   5572       (back-to-indentation)
   5573       (should-not (looking-at-p "\\*foo"))
   5574       (forward-line 1)
   5575       (back-to-indentation)
   5576       (should-not (looking-at-p "\\*foo")))))
   5577 
   5578 (ert-deftest test-markdown-filling/ignore-header ()
   5579   "# Test fill-paragraph for containing header line paragraph.
   5580 https://github.com/jrblevin/markdown-mode/issues/159"
   5581   (markdown-test-string "# this is header line
   5582 this is not header line
   5583 "
   5584     (let ((fill-column 10))
   5585       (fill-paragraph)
   5586       (should (string= (buffer-substring (point) (line-end-position)) "# this is header line")))))
   5587 
   5588 (ert-deftest test-markdown-filling/unclosed-square-bracket ()
   5589   "Test fill-paragraph following an unclosed square bracket."
   5590   (markdown-test-string "```\n[3\n```\n\naaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbb"
   5591     (let ((fill-column 20))
   5592       (forward-line 4)
   5593       (fill-paragraph)
   5594       (should (looking-at "aaaaaaaaaaaaaaaa\nbbbbbbbbbbbbbbbb")))))
   5595 
   5596 (ert-deftest test-markdown-filling/skip-code-blocks ()
   5597   "Test `markdown-fill-paragraph' on code blocks."
   5598   (let ((text "test\n\n```\nhello\nworld\n```"))
   5599     (markdown-test-string text
   5600       (dotimes (_ 5)
   5601         ;; Fill at each line; buffer should not change.
   5602         (fill-paragraph)
   5603         (should (string-equal (buffer-string) text))))))
   5604 
   5605 (ert-deftest test-markdown-filling/fill-region-skip-code-blocks ()
   5606   "Test `fill-region' on code blocks."
   5607   (let ((text "testing\n\n```\nhello\nworld\n```\n\n123"))
   5608     (markdown-test-string text
   5609       ;; Fill entire buffer; buffer should not change.
   5610       (fill-region (point-min) (point-max))
   5611       (should (string-equal (buffer-string) text)))))
   5612 
   5613 (ert-deftest test-markdown-filling/fill-region-skip-code-blocks-2 ()
   5614   "Test `fill-region' on a buffer with a code block with long paragraphs."
   5615   (markdown-test-string "long unwrapped paragraph 1
   5616 
   5617 ```
   5618 code
   5619 block
   5620 
   5621 foo
   5622 bar
   5623 ```
   5624 
   5625 long unwrapped paragraph 2"
   5626     ;; Test markdown-fill-forward-paragraph movement.
   5627     (should (= (markdown-fill-forward-paragraph 1) 0))
   5628     (should (= (point) 28)) ;; Point just after par. 1.
   5629     (should (= (markdown-fill-forward-paragraph 1) 0))
   5630     (should (= (point) 84)) ;; Point at end of par. 2.
   5631     ;; Test filling the entire buffer with `fill-region'.
   5632     (let ((fill-column 12))
   5633       (fill-region (point-min) (point-max))
   5634       (should (string-equal (buffer-string)
   5635                             "long
   5636 unwrapped
   5637 paragraph 1
   5638 
   5639 ```
   5640 code
   5641 block
   5642 
   5643 foo
   5644 bar
   5645 ```
   5646 
   5647 long
   5648 unwrapped
   5649 paragraph 2")))))
   5650 
   5651 (ert-deftest test-markdown-filling/fill-region-skip-code-blocks-3 ()
   5652   "Test `fill-region' on a lone code block with no surrounding text."
   5653   (let ((text "```\ncode\nblock\n```\n"))
   5654     (markdown-test-string text
   5655       ;; Fill entire buffer; buffer should not change.
   5656       (fill-region (point-min) (point-max))
   5657       (should (string-equal (buffer-string) text)))))
   5658 
   5659 (ert-deftest test-markdown-filling/long-paragraph-with-link ()
   5660   "Test `fill-paragraph' on a long paragraph with a long link.
   5661 See GH-173."
   5662   (markdown-test-string
   5663       "aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa [aaa aaa aaa aaa](aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) aaa aaa aaa aaa aaa."
   5664     (let ((fill-column 79)) (fill-paragraph))
   5665     (should (string-equal (buffer-string) "aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa
   5666 aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa [aaa aaa aaa
   5667 aaa](aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) aaa aaa aaa aaa aaa."))))
   5668 
   5669 (ert-deftest test-markdown-filling/pandoc-line-blocks ()
   5670   "Filling should leave Pandoc line blocks undisturbed.
   5671 This includes preserving whitespace after the pipe."
   5672   (let ((text "| The limerick packs laughs anatomical
   5673 | In space that is quite economical.
   5674 |    But the good ones I've seen
   5675 |    So seldom are clean
   5676 | And the clean ones so seldom are comical
   5677 
   5678 | 200 Main St.
   5679 | Berkeley, CA 94718"))
   5680     (markdown-test-string text
   5681       (fill-region (point-min) (point-max))
   5682       (should (string-equal (buffer-string) text)))))
   5683 
   5684 (ert-deftest test-markdown-filling/setext-heading ()
   5685   "Fill paragraph at setext heading.
   5686 Details: https://github.com/jrblevin/markdown-mode/issues/638"
   5687   (let ((input "Heading
   5688 =======
   5689 "))
   5690     (markdown-test-string input
   5691       (markdown-fill-paragraph)
   5692       (should (string= (buffer-string) input))))
   5693   (let ((input "Heading
   5694 -
   5695 "))
   5696     (markdown-test-string input
   5697       (markdown-fill-paragraph)
   5698       (should (string= (buffer-string) input))))
   5699   ;; leading 3 spaces and trailing spaces is ok
   5700   (let ((input "Heading
   5701    ====     \t\n"))
   5702     (markdown-test-string input
   5703       (markdown-fill-paragraph)
   5704       (should (string= (buffer-string) input))))
   5705   ;; fill-paragraph is applied for list element
   5706   (markdown-test-string "- foo
   5707 bar baz"
   5708     (markdown-fill-paragraph)
   5709     (should (string= (buffer-string) "- foo bar baz"))))
   5710 
   5711 ;;; Export tests:
   5712 
   5713 (ert-deftest test-markdown-hook/xhtml-standalone ()
   5714   "Test `markdown-xhtml-standalone-regexp' and `markdown-output-standalone-p'."
   5715   (should (string-match markdown-xhtml-standalone-regexp
   5716                         "<?xml version='1.0' encoding='UTF-8'?>"))
   5717   (should (string-match markdown-xhtml-standalone-regexp
   5718                         "<!DOCTYPE html>"))
   5719   (should (string-match markdown-xhtml-standalone-regexp
   5720                         "<html>"))
   5721   (should-not (string-match markdown-xhtml-standalone-regexp
   5722                             "<h1>title</h1>"))
   5723   (should-not (string-match markdown-xhtml-standalone-regexp
   5724                             "<div id=\"name\">")))
   5725 
   5726 (ert-deftest test-markdown-export/kill-buffer-nil ()
   5727   "Test `markdown-export-kill-buffer' equal to nil."
   5728   (markdown-test-temp-file "inline.text"
   5729     (let* ((markdown-export-kill-buffer nil)
   5730            (markdown-command #'markdown-command-identity)
   5731            (export-file (markdown-export))
   5732            (export-buffer (get-file-buffer export-file)))
   5733       ;; Output buffer should remain open.
   5734       (should (member export-buffer (buffer-list))))))
   5735 
   5736 (ert-deftest test-markdown-export/kill-buffer-t ()
   5737   "Test `markdown-export-kill-buffer' equal to t."
   5738   (markdown-test-temp-file "inline.text"
   5739     (let* ((markdown-export-kill-buffer t)
   5740            (markdown-command #'markdown-command-identity)
   5741            (export-file (markdown-export))
   5742            (export-buffer (get-file-buffer export-file)))
   5743       ;; Output buffer should be killed.
   5744       (should-not export-buffer))))
   5745 
   5746 (ert-deftest test-markdown-export/body-preamble ()
   5747   "Test `markdown-xhtml-body-preamble'."
   5748   (markdown-test-temp-file "inline.text"
   5749     (let* ((str "<!-- body preamble test -->")
   5750            (markdown-xhtml-body-preamble str)
   5751            (markdown-command #'markdown-command-identity)
   5752            (markdown-export-kill-buffer nil)
   5753            (ofile (markdown-export))
   5754            (obuffer (get-file-buffer ofile)))
   5755       (with-current-buffer obuffer
   5756         (goto-char (point-min))
   5757         (should (search-forward str)))
   5758       (kill-buffer obuffer)
   5759       (delete-file ofile))))
   5760 
   5761 (ert-deftest test-markdown-export/body-epilogue ()
   5762   "Test `markdown-xhtml-body-epilogue'."
   5763   (markdown-test-temp-file "inline.text"
   5764     (let* ((str "<!-- body epilogue test -->")
   5765            (markdown-xhtml-body-epilogue str)
   5766            (markdown-command #'markdown-command-identity)
   5767            (markdown-export-kill-buffer nil)
   5768            (ofile (markdown-export))
   5769            (obuffer (get-file-buffer ofile)))
   5770       (with-current-buffer obuffer
   5771         (goto-char (point-min))
   5772         (should (search-forward str)))
   5773       (kill-buffer obuffer)
   5774       (delete-file ofile))))
   5775 
   5776 ;;; Hook tests:
   5777 
   5778 (ert-deftest test-markdown-hook/before-export ()
   5779   "Test hook run before export XHTML."
   5780   (markdown-test-temp-file "lists.text"
   5781     (let* ((before-hook-run nil)
   5782            (orig-point (point))
   5783            (markdown-command #'markdown-command-identity)
   5784            (func (lambda ()
   5785                    ;; Change value of a variable
   5786                    (setq before-hook-run t)
   5787                    ;; Insert some text
   5788                    (goto-char (point-min))
   5789                    (insert "#")
   5790                    ;; Deliberately move the point
   5791                    (end-of-line)
   5792                    ;; Verify changes
   5793                    (should (looking-back "^## List Cases" nil))
   5794                    (should-not (= (point) orig-point))))
   5795            (ofile (progn
   5796                     ;; Register hook
   5797                     (add-hook 'markdown-before-export-hook func)
   5798                     ;; Export XHTML and return filename
   5799                     (markdown-export)))
   5800            (obuffer (get-file-buffer ofile)))
   5801       ;; Test side effects of hook
   5802       (should (eq before-hook-run t))
   5803       ;; Test position of point
   5804       (should (= (point) orig-point))
   5805       ;; Test that buffer was restored to original state
   5806       (goto-char (point-min))
   5807       (should (looking-at "^# List Cases"))
   5808       ;; Clean
   5809       (remove-hook 'markdown-before-export-hook func)
   5810       (kill-buffer obuffer)
   5811       (delete-file ofile))))
   5812 
   5813 (ert-deftest test-markdown-hook/after-export ()
   5814   "Test hook run after export XHTML."
   5815   (markdown-test-temp-file "lists.text"
   5816     (let* ((after-hook-run nil)
   5817            (markdown-command #'markdown-command-identity)
   5818            (markdown-export-kill-buffer nil)
   5819            (func (lambda ()
   5820                    ;; Change variable value
   5821                    (setq after-hook-run t)
   5822                    ;; Add comment to output buffer
   5823                    (goto-char (point-min))
   5824                    (insert "<!-- after-export-hook -->\n")))
   5825            (ofile (progn
   5826                     ;; Register hook
   5827                     (add-hook 'markdown-after-export-hook func)
   5828                     ;; Export XHTML and return filename
   5829                     (markdown-export)))
   5830            (obuffer (get-file-buffer ofile)))
   5831       (message "obuffer = %S" obuffer)
   5832       ;; Test that variable was changed
   5833       (should (eq after-hook-run t))
   5834       ;; Test that output buffer remains open
   5835       (should (get-buffer obuffer))
   5836       ;; Test that output buffer modification remains
   5837       (with-current-buffer obuffer
   5838         (goto-char (point-min))
   5839         (should (looking-at "<!-- after-export-hook -->\n")))
   5840       ;; Test that buffer modification was saved
   5841       (should-not (buffer-modified-p obuffer))
   5842       ;; Clean up
   5843       (remove-hook 'markdown-after-export-hook func)
   5844       (kill-buffer obuffer)
   5845       (delete-file ofile))))
   5846 
   5847 ;;; Extension: math support
   5848 
   5849 (ert-deftest test-markdown-math/file-local-variable ()
   5850   "Test enabling math mode via `hack-local-variables-hook'."
   5851   (markdown-test-file "math.text"
   5852     (should-not markdown-enable-math)
   5853     (hack-local-variables)
   5854     (should markdown-enable-math)))
   5855 
   5856 (ert-deftest test-markdown-math/reload ()
   5857   "Test enabling math mode via variable `markdown-enable-math'."
   5858   (let ((markdown-enable-math t))
   5859     (markdown-test-file "math.text"
   5860       ;; Flag should be set to t
   5861       (should markdown-enable-math)
   5862       ;; Font-lock keywords should be updated.
   5863       (should (member (car markdown-mode-font-lock-keywords-math)
   5864                       (cadr font-lock-keywords))))))
   5865 
   5866 (ert-deftest test-markdown-math/preserve-user-keywords ()
   5867   "Test preserving user-specified font-lock keywords."
   5868   (let ((user-keyword '("\\<\\(FIXME\\):" 1 font-lock-warning-face t)))
   5869     ;; Add user font-lock keyword using `font-lock-add-keywords'.
   5870     (font-lock-add-keywords 'markdown-mode (list user-keyword))
   5871     ;; Visit a file using `markdown-mode'.
   5872     (markdown-test-file "math.text"
   5873       ;; User keyword should be present initially.
   5874       (should (member user-keyword (cadr font-lock-keywords)))
   5875       ;; User keyword should persist after calling `markdown-reload-extensions'.
   5876       (markdown-reload-extensions)
   5877       (should (member user-keyword (cadr font-lock-keywords))))
   5878     ;; Remove the user keyword using `font-lock-remove-keywords'.
   5879     (font-lock-remove-keywords 'markdown-mode (list user-keyword))
   5880     ;; Visit a file using `markdown-mode'.
   5881     (markdown-test-file "inline.text"
   5882       ;; User keyword should not be present after removal.
   5883       (should-not (member user-keyword (cadr font-lock-keywords))))))
   5884 
   5885 (ert-deftest test-markdown-math/preserve-local-user-keywords ()
   5886   "Test preserving buffer-specific user-specified font-lock keywords."
   5887   (let ((user-keyword '("\\<\\(FIXME\\):" 1 font-lock-warning-face t)))
   5888     ;; Visit a file using `markdown-mode'.
   5889     (markdown-test-file "math.text"
   5890       ;; Add user font-lock keyword using `font-lock-add-keywords'.
   5891       (font-lock-add-keywords nil (list user-keyword))
   5892       ;; User keyword should be present initially.
   5893       (should (member user-keyword (cadr font-lock-keywords)))
   5894       ;; User keyword should persist after calling `markdown-reload-extensions'.
   5895       (markdown-reload-extensions)
   5896       (should (member user-keyword (cadr font-lock-keywords)))
   5897       ;; Remove the user keyword using `font-lock-remove-keywords'.
   5898       (font-lock-remove-keywords nil (list user-keyword))
   5899       ;; User keyword should not be present after removal.
   5900       (should-not (member user-keyword (cadr font-lock-keywords))))))
   5901 
   5902 (ert-deftest test-markdown-math/font-lock ()
   5903   "Test markdown math mode."
   5904   (let ((markdown-enable-math t))
   5905     (markdown-test-file "math.text"
   5906       (markdown-test-range-has-face 1 32 nil)
   5907       (markdown-test-range-has-face 33 33 'markdown-markup-face)
   5908       (markdown-test-range-has-face 34 45 'markdown-math-face)
   5909       (markdown-test-range-has-face 46 46 'markdown-markup-face)
   5910       (markdown-test-range-has-face 47 49 nil)
   5911       (markdown-test-range-has-face 50 51 'markdown-markup-face)
   5912       (markdown-test-range-has-face 52 63 'markdown-math-face)
   5913       (markdown-test-range-has-face 64 65 'markdown-markup-face)
   5914       (markdown-test-range-has-face 66 98 nil)
   5915       (markdown-test-range-has-face 99 100 'markdown-markup-face)
   5916       (markdown-test-range-has-face 101 112 'markdown-math-face)
   5917       (markdown-test-range-has-face 113 114 'markdown-markup-face)
   5918       (markdown-test-range-has-face 113 114 'markdown-markup-face)
   5919       (markdown-test-range-has-face 117 117 'markdown-header-delimiter-face)
   5920       (markdown-test-range-has-face 119 152 'markdown-header-face-1)
   5921       (markdown-test-range-has-face 129 129 'markdown-markup-face)
   5922       (markdown-test-range-has-face 136 136 'markdown-markup-face)
   5923 
   5924       (markdown-test-range-has-face 174 177 'markdown-markup-face)
   5925       (markdown-test-range-has-face 179 179 'markdown-markup-face)
   5926       (markdown-test-range-has-face 180 187 'markdown-language-keyword-face)
   5927       (markdown-test-range-has-face 188 188 'markdown-markup-face)
   5928       (markdown-test-range-has-face 190 210 'markdown-pre-face)
   5929       (markdown-test-range-has-face 212 215 'markdown-markup-face)
   5930 
   5931       (markdown-test-range-has-face 218 218 'markdown-markup-face)
   5932       (markdown-test-range-has-face 219 223 'markdown-math-face)
   5933       (markdown-test-range-has-face 224 224 'markdown-markup-face)
   5934       (markdown-test-range-has-face 350 351 'markdown-markup-face)
   5935       (markdown-test-range-has-face 352 356 'markdown-math-face)
   5936       (markdown-test-range-has-face 357 358 'markdown-markup-face)
   5937       (markdown-test-range-has-face 359 391 nil)
   5938       (markdown-test-range-has-face 392 393 'markdown-markup-face)
   5939       (markdown-test-range-has-face 394 398 'markdown-math-face)
   5940       (markdown-test-range-has-face 399 400 'markdown-markup-face))))
   5941 
   5942 (ert-deftest test-markdown-math/double-slash-display-math ()
   5943   "Test double slash display math font lock."
   5944   (let ((markdown-enable-math t))
   5945     (markdown-test-file "math.text"
   5946       (markdown-test-range-has-face 403 474 nil)
   5947       (markdown-test-range-has-face 475 477 'markdown-markup-face)
   5948       (markdown-test-range-has-face 478 543 'markdown-math-face)
   5949       (markdown-test-range-has-face 544 546 'markdown-markup-face))))
   5950 
   5951 (ert-deftest test-markdown-math/indented-double-slash-display-math ()
   5952   "Test font lock for indented double slash display math.
   5953 See GH-288."
   5954   (let ((markdown-enable-math t))
   5955     (markdown-test-string "- Einstein's equation:
   5956 
   5957     \\\\[ E = m c^2 \\\\]"
   5958       (markdown-test-range-has-face 29 31 'markdown-markup-face)
   5959       (markdown-test-range-has-face 32 42 'markdown-math-face)
   5960       (markdown-test-range-has-face 43 45 'markdown-markup-face))))
   5961 
   5962 (ert-deftest test-markdown-math/font-lock-italics ()
   5963   "Test markdown math mode with underscores."
   5964   (let ((markdown-enable-math t))
   5965     (markdown-test-file "math.text"
   5966       (markdown-test-range-has-face 227 227 'markdown-markup-face)
   5967       (markdown-test-range-has-face 228 233 'markdown-math-face)
   5968       (markdown-test-range-has-face 234 234 'markdown-markup-face)
   5969       (markdown-test-range-has-face 235 270 nil)
   5970       (markdown-test-range-has-face 271 271 'markdown-markup-face)
   5971       (markdown-test-range-has-face 272 274 'markdown-math-face)
   5972       (markdown-test-range-has-face 275 275 'markdown-markup-face))))
   5973 
   5974 (ert-deftest test-markdown-math/font-lock-no-bold ()
   5975   "Bold markers in math should not trigger bold."
   5976   (let ((markdown-enable-math t))
   5977     (markdown-test-file "math.text"
   5978       (markdown-test-range-has-face 279 299 'markdown-math-face)
   5979       (markdown-test-range-has-face 301 308 nil)
   5980       (markdown-test-range-has-face 310 312 'markdown-math-face))))
   5981 
   5982 (ert-deftest test-markdown-math/math-inline-single ()
   5983   "Test for math inline single.
   5984 Detail: https://github.com/jrblevin/markdown-mode/issues/352"
   5985   (let ((markdown-enable-math t))
   5986     (markdown-test-string "$a$b$c$"
   5987       (markdown-test-range-has-face 1 1 'markdown-markup-face)
   5988       (markdown-test-range-has-face 2 2 'markdown-math-face)
   5989       (markdown-test-range-has-face 3 3 'markdown-markup-face)
   5990 
   5991       (markdown-test-range-has-face 5 5 'markdown-markup-face)
   5992       (markdown-test-range-has-face 6 6 'markdown-math-face)
   5993       (markdown-test-range-has-face 7 7 'markdown-markup-face))))
   5994 
   5995 (ert-deftest test-markdown-math/math-inline-double ()
   5996   "Test for math inline double. This is similar to #352 issue."
   5997   (let ((markdown-enable-math t))
   5998     (markdown-test-string "$$a$$b$$c$$"
   5999       (markdown-test-range-has-face 1 2 'markdown-markup-face)
   6000       (markdown-test-range-has-face 3 3 'markdown-math-face)
   6001       (markdown-test-range-has-face 4 5 'markdown-markup-face)
   6002 
   6003       (markdown-test-range-has-face 7 8 'markdown-markup-face)
   6004       (markdown-test-range-has-face 9 9 'markdown-math-face)
   6005       (markdown-test-range-has-face 10 11 'markdown-markup-face))))
   6006 
   6007 (ert-deftest test-markdown-math/math-inline-small-buffer ()
   6008   "Test that font-lock parsing works with a single dollar."
   6009   (let ((markdown-enable-math t))
   6010     (markdown-test-string "$"
   6011       (should t))
   6012     (markdown-test-string "$$"
   6013       (should t))
   6014     (markdown-test-string "$$$"
   6015       (should t))))
   6016 
   6017 ;;; Extension: pipe table editing
   6018 
   6019 (ert-deftest test-markdown-table/table-begin-top-of-file ()
   6020   "Test beginning of table detection at top of file."
   6021   (markdown-test-string "| 1 | 2 |\n| 3 | 4 |\n"
   6022     (should (markdown-table-at-point-p))
   6023     (forward-line)
   6024     (should (markdown-table-at-point-p))
   6025     (should (= (markdown-table-begin) 1))))
   6026 
   6027 ;;; Extension: pipe table insertion
   6028 
   6029 (ert-deftest test-markdown-insertion/create-table-with-left-align ()
   6030   "Insert table with left column alignment."
   6031   (markdown-test-string
   6032       ""
   6033     (execute-kbd-macro (read-kbd-macro "M-x markdown-insert-table RET 3 RET 2 RET l RET"))
   6034     (should (string-equal (buffer-string) "|   |   |
   6035 |:--|:--|
   6036 |   |   |
   6037 |   |   |
   6038 "))
   6039     (should (= (point) 3))))
   6040 
   6041 (ert-deftest test-markdown-insertion/create-table-with-right-align ()
   6042   "Insert table with right column alignment."
   6043   (markdown-test-string
   6044       ""
   6045     (execute-kbd-macro (read-kbd-macro "M-x markdown-insert-table RET 3 RET 2 RET r RET"))
   6046     (should (string-equal (buffer-string) "|   |   |
   6047 |--:|--:|
   6048 |   |   |
   6049 |   |   |
   6050 "))
   6051     (should (= (point) 3))))
   6052 
   6053 (ert-deftest test-markdown-insertion/create-table-with-center-align ()
   6054   "Insert table with center column alignment."
   6055   (markdown-test-string
   6056       ""
   6057     (execute-kbd-macro (read-kbd-macro "M-x markdown-insert-table RET 3 RET 2 RET c RET"))
   6058     (should (string-equal (buffer-string) "|   |   |
   6059 |:-:|:-:|
   6060 |   |   |
   6061 |   |   |
   6062 "))
   6063     (should (= (point) 3))))
   6064 
   6065 (ert-deftest test-markdown-insertion/create-table-with-default-align ()
   6066   "Insert table with default column alignment."
   6067   (markdown-test-string
   6068       ""
   6069     (execute-kbd-macro (read-kbd-macro "M-x markdown-insert-table RET 3 RET 2 RET RET"))
   6070     (should (string-equal (buffer-string) "|   |   |
   6071 |---|---|
   6072 |   |   |
   6073 |   |   |
   6074 "))
   6075     (should (= (point) 3))))
   6076 
   6077 (ert-deftest test-markdown-table/align-with-escaped-separator ()
   6078   "Test table align if column has escaped separator.
   6079 Details: https://github.com/jrblevin/markdown-mode/issues/308"
   6080   (markdown-test-string "| Col1  | Col2  |
   6081 | :-: | :-: |
   6082 |  AAA  |  A\\|B |"
   6083     (search-forward "Col2")
   6084     (markdown-table-align)
   6085     (should (string= (buffer-substring-no-properties (point-min) (point-max))
   6086                      "| Col1 | Col2 |
   6087 |:----:|:----:|
   6088 | AAA  | A\\|B |\n"))))
   6089 
   6090 (ert-deftest test-markdown-table/align-with-wiki-link ()
   6091   "Test table align if column has wiki link.
   6092 Details: https://github.com/jrblevin/markdown-mode/issues/308"
   6093   (let ((markdown-enable-wiki-links t))
   6094     (markdown-test-string "| A | B |
   6095 |-------------|---------|
   6096 | [[Page|Address]] | Content |"
   6097       (search-forward "B")
   6098       (markdown-table-align)
   6099       (should (string= (buffer-substring-no-properties (point-min) (point-max))
   6100                        "| A                | B       |
   6101 |------------------|---------|
   6102 | [[Page|Address]] | Content |")))))
   6103 
   6104 (ert-deftest test-markdown-table/table-line-to-columns ()
   6105   "Test for splitting table line to columns."
   6106   (should (equal (markdown--table-line-to-columns "|foo|") '("foo")))
   6107   (should (equal (markdown--table-line-to-columns "foo") '("foo")))
   6108   (should (equal (markdown--table-line-to-columns "|foo|bar|") '("foo" "bar")))
   6109   (should (equal (markdown--table-line-to-columns "  |  foo  |  bar  |  ") '("foo" "bar")))
   6110   (should (equal (markdown--table-line-to-columns "foo|bar") '("foo" "bar")))
   6111   (should (equal (markdown--table-line-to-columns "foo | bar | baz") '("foo" "bar" "baz")))
   6112   (should (equal (markdown--table-line-to-columns "| x \\| |") '("x \\|"))))
   6113 
   6114 (ert-deftest test-markdown-table/blank-line ()
   6115   "Test for creating new blank line."
   6116   (should (string= (markdown-table-blank-line "|foo|")  "|   |"))
   6117   (should (string= (markdown-table-blank-line "|foo|barbaz|")  "|   |      |"))
   6118   (should (string= (markdown-table-blank-line "|a|bb|ccc|") "| |  |   |"))
   6119 
   6120   (let ((markdown-enable-wiki-links t))
   6121     (should (string= (markdown-table-blank-line "| [[Page|Address]] | Content |")
   6122                      "|                  |         |"))))
   6123 
   6124 (ert-deftest test-markdown-table/get-column ()
   6125   "Test for getting column number"
   6126   (markdown-test-string "| Col1 | Col2 |"
   6127     (search-forward "Col1")
   6128     (should (= (markdown-table-get-column) 1))
   6129     (search-forward "Col2")
   6130     (should (= (markdown-table-get-column) 2)))
   6131 
   6132   (markdown-test-string "| [[Page|Address]] | Content |"
   6133     (search-forward "Content")
   6134     (should (= (markdown-table-get-column) 3)))
   6135 
   6136   (let ((markdown-enable-wiki-links t))
   6137     (markdown-test-string "| [[Page|Address]] | Content |"
   6138       (search-forward "Content")
   6139       (should (= (markdown-table-get-column) 2)))))
   6140 
   6141 (ert-deftest test-markdown-table/goto-column ()
   6142   "Test for goto specified column."
   6143   (markdown-test-string "| Col1 | Col2 |"
   6144     (markdown-table-goto-column 1)
   6145     (should (string= (thing-at-point 'word) "Col1"))
   6146     (markdown-table-goto-column 2)
   6147     (should (string= (thing-at-point 'word) "Col2")))
   6148 
   6149   (markdown-test-string "| [[Page|Address]] | Content |"
   6150     (markdown-table-goto-column 2)
   6151     (should (string= (thing-at-point 'word) "Address")))
   6152 
   6153   (let ((markdown-enable-wiki-links t))
   6154     (markdown-test-string "| [[Page|Address]] | Content |"
   6155       (markdown-table-goto-column 2)
   6156       (should (string= (thing-at-point 'word) "Content")))))
   6157 
   6158 (ert-deftest test-markdown-table/get-column-with-escaped-vertical-bar ()
   6159   "Test for getting column number with escaped vertical bar.
   6160 Details: https://github.com/jrblevin/markdown-mode/issues/635"
   6161   (markdown-test-string "| Col1 | Col2 \\| Col2 \\| Col2 |"
   6162     (search-forward "Col2")
   6163     (should (= (markdown-table-get-column) 2))
   6164     (search-forward "Col2")
   6165     (should (= (markdown-table-get-column) 2))
   6166     (search-forward "Col2")
   6167     (should (= (markdown-table-get-column) 2))))
   6168 
   6169 (ert-deftest test-markdown-table/transpose-with-wiki-link ()
   6170   "Test for table transpose with link.
   6171 Detail: https://github.com/jrblevin/markdown-mode/commit/44a1c5bbc5d9514e97c7cc0a90a0c578130cd1dc"
   6172   (let ((markdown-enable-wiki-links t))
   6173     (markdown-test-string "| A           | B       |
   6174 | [[Page|Address]] | Content |
   6175 "
   6176       (markdown-table-transpose)
   6177       (should (string=
   6178                (buffer-substring-no-properties (point-min) (point-max))
   6179                "| A | [[Page|Address]] |
   6180 | B | Content          |
   6181 ")))))
   6182 
   6183 (ert-deftest test-markdown-table/forward-cell-with-escaped-vertical-bar ()
   6184   "Test for table forward-cell with escaped vertical bar.
   6185 Detail: https://github.com/jrblevin/markdown-mode/issues/489"
   6186   (markdown-test-string "| x \\| |
   6187 "
   6188     (forward-char 1)
   6189     (markdown-table-forward-cell)
   6190     (should (string=
   6191              (buffer-substring-no-properties (point-min) (point-max))
   6192              "| x \\| |
   6193 |      |
   6194 "))))
   6195 
   6196 (ert-deftest test-markdown-table/forward-cell-at-last-column ()
   6197   "Test for table forward-cell at last column.
   6198 Detail: https://github.com/jrblevin/markdown-mode/issues/522"
   6199   (markdown-test-string "| one  | two  |
   6200 | three | four |
   6201 "
   6202     (search-forward "two")
   6203     (markdown-table-forward-cell)
   6204     (should (string= (thing-at-point 'word) "three"))
   6205     (markdown-table-forward-cell)
   6206     (should (string= (thing-at-point 'word) "four"))
   6207     (markdown-table-forward-cell)
   6208     (should (string= (buffer-substring-no-properties (line-beginning-position) (line-end-position))
   6209                      "|       |      |"))))
   6210 
   6211 (ert-deftest test-markdown-table/backward-cell-with-escaped-vertical-bar ()
   6212   "Test for table backward-cell with escaped vertical bar."
   6213   (markdown-test-string "| x \\| |   |"
   6214     (goto-char (point-max))
   6215     (backward-char 1)
   6216     (markdown-table-backward-cell)
   6217     (should (char-equal (char-after) ?x))))
   6218 
   6219 (ert-deftest test-markdown-table/column-move-with-escaped-vertical-bar ()
   6220   "Test for column move with escaped vertical bar.
   6221 Details: https://github.com/jrblevin/markdown-mode/issues/635"
   6222   (markdown-test-string "| a \\| | b |"
   6223     (search-forward "b")
   6224     (markdown-table-move-column-left)
   6225     (should (string= (buffer-substring-no-properties (line-beginning-position) (line-end-position))
   6226                      "| b | a \\| |")))
   6227 
   6228   (markdown-test-string "| a \\| | b |"
   6229     (search-forward "a")
   6230     (markdown-table-move-column-right)
   6231     (should (string= (buffer-substring-no-properties (line-beginning-position) (line-end-position))
   6232                      "| b | a \\| |"))))
   6233 
   6234 (ert-deftest test-markdown-table/insert-column-with-escaped-vertical-bar ()
   6235   "Test for inserting column with escaped vertical bar.
   6236 Details: https://github.com/jrblevin/markdown-mode/issues/635"
   6237   (markdown-test-string "| a | b \\| bb |
   6238 | c | d |"
   6239     (search-forward "bb")
   6240     (markdown-table-insert-column)
   6241     (should (string= (buffer-string)
   6242                      "| a |   | b \\| bb |
   6243 | c |   | d       |
   6244 "))))
   6245 
   6246 (ert-deftest test-markdown-table/delete-column-with-escaped-vertical-bar ()
   6247   "Test for deleting column with escaped vertical bar.
   6248 Details: https://github.com/jrblevin/markdown-mode/issues/635"
   6249   (markdown-test-string "| a | b \\| bb |
   6250 | c | d |"
   6251     (search-forward "bb")
   6252     (markdown-table-delete-column)
   6253     (should (string= (buffer-string)
   6254                      "| a |
   6255 | c |"))))
   6256 
   6257 ;;; gfm-mode tests:
   6258 
   6259 (ert-deftest test-markdown-gfm/pre-1 ()
   6260   "GFM pre block font lock test."
   6261   (markdown-test-file-gfm "gfm.text"
   6262     (markdown-test-range-has-face 2626 2637 nil)
   6263     (markdown-test-range-has-face 2639 2641 'markdown-markup-face)
   6264     (markdown-test-range-has-face 2642 2645 'markdown-language-keyword-face)
   6265     (markdown-test-range-has-face 2647 2728 'markdown-pre-face)
   6266     (markdown-test-range-has-face 2730 2732 'markdown-markup-face)))
   6267 
   6268 (ert-deftest test-markdown-gfm/italic-1 ()
   6269   "GFM italic font lock test."
   6270   (markdown-test-file-gfm "gfm.text"
   6271     (markdown-test-range-has-face 1483 1483 'markdown-markup-face)
   6272     (markdown-test-range-has-face 1484 1487 'markdown-italic-face)
   6273     (markdown-test-range-has-face 1488 1488 'markdown-markup-face)
   6274     (markdown-test-range-has-face 1729 1790 nil)))
   6275 
   6276 (ert-deftest test-markdown-gfm/italic-underscore ()
   6277   "Test for GFM italic font lock test based on CommonMark specification.
   6278 Details: https://github.com/jrblevin/markdown-mode/issues/448"
   6279   (markdown-test-string-gfm "_no_emphasis
   6280 *emphasis*
   6281 em*pha*sis
   6282 *emph*asis
   6283 emph*asis*
   6284 em*ph as*is
   6285 _emphasis_
   6286 no_emph_asis
   6287 no_emphasis_
   6288 no_em ph_asis
   6289 "
   6290     (markdown-test-range-has-face 2 3 nil)
   6291     (markdown-test-range-has-face 15 22 'markdown-italic-face)
   6292     (markdown-test-range-has-face 28 30 'markdown-italic-face)
   6293     (markdown-test-range-has-face 37 40 'markdown-italic-face)
   6294     (markdown-test-range-has-face 52 55 'markdown-italic-face)
   6295     (markdown-test-range-has-face 61 65 'markdown-italic-face)
   6296     (markdown-test-range-has-face 71 78 'markdown-italic-face)
   6297     (markdown-test-range-has-face 84 87 nil)
   6298     (markdown-test-range-has-face 97 104 nil)
   6299     (markdown-test-range-has-face 110 114 nil)))
   6300 
   6301 (ert-deftest test-markdown-gfm/italic-underscore-one-character ()
   6302   "Test for GFM italic font lock test for one character.
   6303 Details: https://github.com/jrblevin/markdown-mode/issues/524"
   6304   (markdown-test-string-gfm "*a* other text *abc*"
   6305     (markdown-test-range-has-face 3 3 'markdown-markup-face)
   6306     (markdown-test-range-has-face 4 15 nil)
   6307     (markdown-test-range-has-face 16 16 'markdown-markup-face)
   6308     (markdown-test-range-has-face 17 19 'markdown-italic-face)
   6309     (markdown-test-range-has-face 20 20 'markdown-markup-face))
   6310 
   6311   (markdown-test-string-gfm "*a* _b_"
   6312     (markdown-test-range-has-face 1 1 'markdown-markup-face)
   6313     (markdown-test-range-has-face 2 2 'markdown-italic-face)
   6314     (markdown-test-range-has-face 3 3 'markdown-markup-face)
   6315     (markdown-test-range-has-face 4 4 nil)
   6316     (markdown-test-range-has-face 5 5 'markdown-markup-face)
   6317     (markdown-test-range-has-face 6 6 'markdown-italic-face)
   6318     (markdown-test-range-has-face 7 7 'markdown-markup-face)))
   6319 
   6320 (ert-deftest test-markdown-gfm/italic-underscore-following-functuation-character ()
   6321   "Test for GFM italic font lock with following punctuation character
   6322 Details: https://github.com/jrblevin/markdown-mode/issues/553"
   6323   (markdown-test-string-gfm "_One_, _two_, or _three_."
   6324     ;; one
   6325     (markdown-test-range-has-face 1 1 'markdown-markup-face)
   6326     (markdown-test-range-has-face 2 4 'markdown-italic-face)
   6327     (markdown-test-range-has-face 5 5 'markdown-markup-face)
   6328     ;; two
   6329     (markdown-test-range-has-face 8 8 'markdown-markup-face)
   6330     (markdown-test-range-has-face 9 11 'markdown-italic-face)
   6331     (markdown-test-range-has-face 12 12 'markdown-markup-face)
   6332     ;; or
   6333     (markdown-test-range-has-face 15 16 nil)
   6334     ;; three
   6335     (markdown-test-range-has-face 18 18 'markdown-markup-face)
   6336     (markdown-test-range-has-face 19 23 'markdown-italic-face)
   6337     (markdown-test-range-has-face 24 24 'markdown-markup-face)))
   6338 
   6339 (ert-deftest test-markdown-gfm/bold-underscore ()
   6340   "Test for GFM bold font lock test.
   6341 Details: https://github.com/jrblevin/markdown-mode/issues/525"
   6342   (markdown-test-string-gfm "**strong**
   6343 st**ro**ng
   6344 **str**ong
   6345 str**ong**
   6346 **still strong**
   6347 **still str**ong
   6348 sti**ll strong**
   6349 sti**ll str**ong
   6350 __strong__
   6351 not__str__ong
   6352 __not__strong
   6353 not__strong__
   6354 __still strong__
   6355 no__t strong__
   6356 __not str__ong
   6357 no__t str__ong
   6358 "
   6359     (markdown-test-range-has-face 3 8 'markdown-bold-face)
   6360     (markdown-test-range-has-face 16 17 'markdown-bold-face)
   6361     (markdown-test-range-has-face 27 27 'markdown-bold-face)
   6362     (markdown-test-range-has-face 39 41 'markdown-bold-face)
   6363     (markdown-test-range-has-face 47 58 'markdown-bold-face)
   6364     (markdown-test-range-has-face 64 72 'markdown-bold-face)
   6365     (markdown-test-range-has-face 84 92 'markdown-bold-face)
   6366     (markdown-test-range-has-face 101 106 'markdown-bold-face)
   6367     (markdown-test-range-has-face 115 120 'markdown-bold-face)
   6368     (markdown-test-range-has-face 129 131 nil)
   6369     (markdown-test-range-has-face 140 142 nil)
   6370     (markdown-test-range-has-face 168 179 'markdown-bold-face)
   6371     (markdown-test-range-has-face 200 206 nil)
   6372     (markdown-test-range-has-face 217 221 nil)))
   6373 
   6374 (ert-deftest test-markdown-gfm/string-between-strong-markup ()
   6375   "Test for string between strong markup.
   6376 Details: https://github.com/jrblevin/markdown-mode/issues/534"
   6377   (markdown-test-string-gfm "**foo** and **bar**"
   6378     (markdown-test-range-has-face 1 2 'markdown-markup-face)
   6379     (markdown-test-range-has-face 3 5 'markdown-bold-face)
   6380     (markdown-test-range-has-face 6 7 'markdown-markup-face)
   6381     (markdown-test-range-has-face 8 12 nil)
   6382     (markdown-test-range-has-face 13 14 'markdown-markup-face)
   6383     (markdown-test-range-has-face 15 17 'markdown-bold-face)
   6384     (markdown-test-range-has-face 18 19 'markdown-markup-face)))
   6385 
   6386 (ert-deftest test-markdown-gfm/strike-through-1 ()
   6387   "GFM strike through font lock test."
   6388   (markdown-test-string-gfm "one ~~two~~ three"
   6389     (markdown-test-range-has-face 1 4 nil)
   6390     (markdown-test-range-has-face 5 6 'markdown-markup-face)
   6391     (markdown-test-range-has-face 7 9 'markdown-strike-through-face)
   6392     (markdown-test-range-has-face 10 11 'markdown-markup-face)
   6393     (markdown-test-range-has-face 12 17 nil)))
   6394 
   6395 (ert-deftest test-markdown-gfm/insert-strike-through ()
   6396   "Test `markdown-insert-strike-through'."
   6397   (markdown-test-string-gfm "one two three"
   6398     (push-mark (point) t t)
   6399     (forward-word 2)
   6400     (markdown-insert-strike-through)
   6401     (should (string-equal (buffer-string) "~~one two~~ three")))
   6402   (markdown-test-string-gfm "  one two  three"
   6403     (push-mark (point) t t)
   6404     (goto-char 11)
   6405     (markdown-insert-strike-through)
   6406     (should (string-equal (buffer-string) "  ~~one two~~  three"))))
   6407 
   6408 (ert-deftest test-markdown-gfm/toggle-strike-through ()
   6409   "Test toggling functionality of `markdown-insert-strike-through'."
   6410   (markdown-test-string-gfm "one ~~two~~ three"
   6411     (forward-word 2)
   6412     (markdown-insert-strike-through)
   6413     (should (string-equal (buffer-string) "one two three"))
   6414     (should (= (point) 8))
   6415     (forward-word)
   6416     (markdown-insert-strike-through)
   6417     (should (= (point) 16))
   6418     (should (string-equal (buffer-string) "one two ~~three~~"))))
   6419 
   6420 (ert-deftest test-markdown-gfm/toggle-strike-through-consecutive ()
   6421   "Test toggling functionality of consecutive strike-throughs."
   6422   (markdown-test-string-gfm "one ~~two~~ ~~three~~"
   6423     (search-forward "w")
   6424     (markdown-insert-strike-through)
   6425     (should (string-equal (buffer-string) "one two ~~three~~"))))
   6426 
   6427 (ert-deftest test-markdown-gfm/insert-code-block-empty-markup ()
   6428   "Test GFM code block insertion with empty code section."
   6429   (markdown-test-string-gfm "line 1\nline 2\n"
   6430     (end-of-line)
   6431     (markdown-insert-gfm-code-block "elisp")
   6432     (should (equal (car markdown-gfm-used-languages) "elisp"))
   6433     (should (equal (car (markdown-gfm-get-corpus)) "elisp"))
   6434     (should (string-equal (buffer-string)
   6435                           "line 1\n\n``` elisp\n\n```\n\nline 2\n"))))
   6436 
   6437 (ert-deftest test-markdown-gfm/markdown-spaces-after-code-fence ()
   6438   "Test `markdown-spaces-after-code-fence'."
   6439   (markdown-test-string-gfm ""
   6440     (let ((markdown-spaces-after-code-fence 0))
   6441       (markdown-insert-gfm-code-block "elisp")
   6442       (should (equal (buffer-string) "```elisp\n\n```")))))
   6443 
   6444 (ert-deftest test-markdown-gfm/insert-code-block-active-region ()
   6445   "Test GFM code block insertion with active region."
   6446   (markdown-test-string-gfm "line 1\nline 2\nline 3\n"
   6447     (forward-line)
   6448     (transient-mark-mode)
   6449     (push-mark (point) t t)
   6450     (end-of-line)
   6451     (should (use-region-p))
   6452     (markdown-insert-gfm-code-block "elisp")
   6453     (should (string-equal (buffer-string)
   6454                           "line 1\n\n``` elisp\nline 2\n```\n\nline 3\n"))))
   6455 
   6456 (ert-deftest test-markdown-gfm/insert-code-block-indented-list-item ()
   6457   "Test GFM code block insertion with an indented list item."
   6458   (markdown-test-string-gfm "1. foo\n   "
   6459     (goto-char (point-max))
   6460     (markdown-insert-gfm-code-block "elisp")
   6461     (should (equal (buffer-substring-no-properties (point-min) (point-max))
   6462                    "1. foo\n\n   ``` elisp\n   \n   ```"))
   6463     (should (equal (buffer-substring-no-properties (point) (point-max))
   6464                    "\n   ```"))))
   6465 
   6466 (ert-deftest test-markdown-gfm/insert-code-block-indented-list-item-active-region ()
   6467   "Test GFM code block insertion with an indented list item and active region."
   6468   (markdown-test-string-gfm "1.  foo\n    bar\n"
   6469     (let ((transient-mark-mode t))
   6470       (forward-line)
   6471       (push-mark nil :nomsg :activate)
   6472       (end-of-line)
   6473       (should (use-region-p))
   6474       (markdown-insert-gfm-code-block "elisp"))
   6475     (should (equal (buffer-substring-no-properties (point-min) (point-max))
   6476                    "1.  foo\n\n    ``` elisp\n    bar\n    ```\n\n"))
   6477     (should (equal (buffer-substring-no-properties (point) (point-max))
   6478                    "\n    bar\n    ```\n\n"))))
   6479 
   6480 (ert-deftest test-markdown-gfm/markdown-code-block-braces ()
   6481   "Test `markdown-gfm-use-electric-backquote'."
   6482   (markdown-test-string-gfm ""
   6483     (let ((markdown-code-block-braces t))
   6484       (markdown-insert-gfm-code-block "elisp")
   6485       (should (equal (buffer-string) "```{elisp}\n\n```")))))
   6486 
   6487 (ert-deftest test-markdown-gfm/gfm-parse-buffer-for-languages ()
   6488   "Parse buffer for existing languages for `markdown-gfm-used-languages' test."
   6489   (markdown-test-string-gfm "``` MADEUP\n\n```\n``` LANGUAGES\n\n```\n```MaDeUp\n\n```\n```\n\n```\n``` \n\n```\n"
   6490     (markdown-gfm-parse-buffer-for-languages)
   6491     (should (equal markdown-gfm-used-languages
   6492                    (list "MaDeUp" "LANGUAGES" "MADEUP")))
   6493     (should (equal (car markdown-gfm-used-languages) "MaDeUp"))
   6494     (should (equal (car (markdown-gfm-get-corpus)) "MaDeUp"))
   6495     (goto-char (point-max))
   6496     (markdown-insert-gfm-code-block "newlang")
   6497     (should (equal markdown-gfm-used-languages
   6498                    (list "newlang" "MaDeUp" "LANGUAGES" "MADEUP")))
   6499     (should (equal (car markdown-gfm-used-languages) "newlang"))
   6500     (should (equal (car (markdown-gfm-get-corpus)) "newlang"))
   6501     (let ((markdown-gfm-downcase-languages nil))
   6502       (should
   6503        (equal (markdown-gfm-get-corpus)
   6504               (append markdown-gfm-used-languages
   6505                       markdown-gfm-additional-languages
   6506                       markdown-gfm-recognized-languages))))
   6507     (let ((markdown-gfm-downcase-languages t))
   6508       (should
   6509        (equal
   6510         (markdown-gfm-get-corpus)
   6511         (append markdown-gfm-used-languages
   6512                 (cl-mapcar #'downcase
   6513                            (append markdown-gfm-additional-languages
   6514                                    markdown-gfm-recognized-languages))))))))
   6515 
   6516 (ert-deftest test-markdown-gfm/insert-code-block-at-end-of-buffer ()
   6517   "Insert GFM code block at end of buffer.
   6518 Details: https://github.com/jrblevin/markdown-mode/issues/634"
   6519   (markdown-test-string-gfm ""
   6520     (goto-char (point-max))
   6521     (execute-kbd-macro (read-kbd-macro "C-c C-s C RET"))
   6522     ;; don't raise exception
   6523     (should t)))
   6524 
   6525 (ert-deftest test-markdown-gfm/code-block-font-lock ()
   6526   "GFM code block font lock test."
   6527   (markdown-test-file-gfm "gfm.text"
   6528     (markdown-test-range-has-face 2639 2641 'markdown-markup-face) ; ```
   6529     (markdown-test-range-has-face 2642 2645 'markdown-language-keyword-face) ; lang
   6530     (markdown-test-range-has-face 2647 2728 'markdown-pre-face)      ; code
   6531     (markdown-test-range-has-face 2730 2732 'markdown-markup-face))) ; ```
   6532 
   6533 (ert-deftest test-markdown-gfm/code-block-font-lock-2 ()
   6534   "GFM code block font lock test without language identifier."
   6535   (markdown-test-string-gfm "Plain code block:\n\n```\nfoo\n```\n"
   6536     (markdown-test-range-has-face 20 22 'markdown-markup-face)
   6537     (markdown-test-range-has-face 24 26 'markdown-pre-face)
   6538     (markdown-test-range-has-face 28 30 'markdown-markup-face)))
   6539 
   6540 (ert-deftest test-markdown-gfm/one-line-code-block ()
   6541   "Don't handle backtick as code block language.
   6542 Details: https://github.com/jrblevin/markdown-mode/issues/403"
   6543   (markdown-test-string-gfm "```three```"
   6544     (let ((face-props (get-text-property 4 'face)))
   6545       (should (memq 'markdown-inline-code-face face-props))
   6546       (should-not (memq 'markdown-language-keyword-face face-props)))))
   6547 
   6548 ;;; Extension: GFM simplified tables
   6549 
   6550 (ert-deftest test-markdown-gfm/false-table-first-line ()
   6551   "Test beginning of table detection at beginning of buffer.
   6552 Based on GH-298."
   6553   (markdown-test-string
   6554       "[|"
   6555     (should-not (gfm--table-at-point-p))))
   6556 
   6557 (ert-deftest test-markdown-gfm/true-table-first-line ()
   6558   "Test beginning of table detection at beginning of buffer."
   6559   (markdown-test-string
   6560       "[|
   6561 -|-
   6562 x|"
   6563     (dotimes (_ 3)
   6564       (should (gfm--table-at-point-p))
   6565       (forward-line))))
   6566 
   6567 (ert-deftest test-markdown-gfm/table-begin-top-of-file ()
   6568   "Test beginning of table detection at top of file."
   6569   (markdown-test-string "[|"
   6570     (should-not (gfm--table-at-point-p))))
   6571 
   6572 ;;; Tests for other extensions:
   6573 
   6574 (ert-deftest test-markdown-ext/pandoc-fancy-lists ()
   6575   "Test basic support for font lock and filling of Pandoc 'fancy lists'."
   6576   (markdown-test-string " #. abc\ndef\n"
   6577     ;; font lock
   6578     (markdown-test-range-has-face 1 1 nil)
   6579     (markdown-test-range-has-face 2 3 'markdown-list-face)
   6580     (markdown-test-range-has-face 4 11 nil)
   6581     ;; filling
   6582     (forward-line)
   6583     (markdown-indent-region (line-beginning-position) (line-end-position) nil)
   6584     (should (string-equal (buffer-string) " #. abc\n def\n"))
   6585     (markdown-indent-region (line-beginning-position) (line-end-position) nil)
   6586     (should (string-equal (buffer-string) " #. abc\n    def\n"))))
   6587 
   6588 (ert-deftest test-markdown-ext/wiki-link-rules ()
   6589   "Test wiki link search rules and font lock for missing pages."
   6590   (let ((markdown-enable-wiki-links t)
   6591         (markdown-wiki-link-fontify-missing t)
   6592         (markdown-wiki-link-search-subdirectories t)
   6593         (markdown-wiki-link-search-parent-directories t))
   6594     (progn
   6595       (find-file (expand-file-name "wiki/root" markdown-test-dir))
   6596       (unwind-protect
   6597           (progn
   6598             (markdown-mode)
   6599             ;; search rules
   6600             (should (string-match-p
   6601                      "/sub/foo$"
   6602                      (markdown-convert-wiki-link-to-filename "foo")))
   6603             (should (string-equal
   6604                      (markdown-convert-wiki-link-to-filename "doesnotexist")
   6605                      "doesnotexist"))
   6606             ;; font lock
   6607             (markdown-test-range-has-property 1 11 'font-lock-face 'markdown-link-face)
   6608             (markdown-test-range-has-property 14 33 'font-lock-face 'markdown-missing-link-face)
   6609             (markdown-test-range-has-property 36 42 'font-lock-face 'markdown-link-face)
   6610             (markdown-test-range-has-property 45 60 'font-lock-face 'markdown-missing-link-face))
   6611         (kill-buffer)))
   6612     (progn
   6613       (find-file (expand-file-name "wiki/sub/foo" markdown-test-dir))
   6614       (unwind-protect
   6615           (progn
   6616             (markdown-mode)
   6617             ;; search rules
   6618             (should (string-match-p
   6619                      "/wiki/root$"
   6620                      (markdown-convert-wiki-link-to-filename "root")))
   6621             (should (string-equal
   6622                      (markdown-convert-wiki-link-to-filename "doesnotexist")
   6623                      "doesnotexist"))
   6624             ;; font lock
   6625             (markdown-test-range-has-property 1 16 'font-lock-face 'markdown-missing-link-face)
   6626             (markdown-test-range-has-property 19 26 'font-lock-face 'markdown-link-face))
   6627         (kill-buffer)))))
   6628 
   6629 (ert-deftest test-markdown-ext/wiki-link-keep-match-data ()
   6630   "Test that markdown-wiki-link-p keeps expected match data.
   6631 Detail: https://github.com/jrblevin/markdown-mode/pull/590"
   6632   (let ((markdown-enable-wiki-links t)
   6633         (markdown-link-space-sub-char " ")
   6634         (markdown-wiki-link-search-subdirectories t))
   6635     (progn
   6636       (find-file (expand-file-name "wiki/pr590/Guide.md" markdown-test-dir))
   6637       (unwind-protect
   6638           (progn
   6639             (markdown-mode)
   6640             (re-search-forward "Zettel Markdown")
   6641             (goto-char (match-beginning 0))
   6642             (should (markdown-wiki-link-p)) ;; create match-data
   6643             (should (string= (markdown-wiki-link-link) "Zettel Markdown")))
   6644         (kill-buffer)))))
   6645 
   6646 (ert-deftest test-markdown-ext/wiki-link-search-under-project ()
   6647   "Test that searching link under project root."
   6648   (let ((markdown-enable-wiki-links t)
   6649         (markdown-link-space-sub-char " ")
   6650         (markdown-wiki-link-search-type '(project))
   6651         (expected (expand-file-name "wiki/pr590/Guide/Zettel Markdown/math.md"
   6652                                     markdown-test-dir)))
   6653     (progn
   6654       (find-file (expand-file-name "wiki/pr590/Guide/Plugin/Link.md" markdown-test-dir))
   6655       (unwind-protect
   6656           (progn
   6657             (markdown-mode)
   6658             (re-search-forward "math")
   6659             (goto-char (match-beginning 0))
   6660             (markdown-wiki-link-p) ;; create match-data
   6661             (let ((link (markdown-convert-wiki-link-to-filename (markdown-wiki-link-link))))
   6662               (should (string= (expand-file-name link) expected))))
   6663         (kill-buffer)))))
   6664 
   6665 (ert-deftest test-markdown-ext/wiki-link-major-mode ()
   6666   "Test major-mode of linked page."
   6667   (let ((markdown-enable-wiki-links t)
   6668         (auto-mode-alist (cons '("bar\\.md" . gfm-mode) auto-mode-alist)))
   6669     (find-file (expand-file-name "wiki/root" markdown-test-dir))
   6670     (unwind-protect
   6671         (progn
   6672           (markdown-mode)
   6673           (search-forward "sub/bar.md")
   6674           (markdown-follow-wiki-link-at-point)
   6675           (should (eq major-mode 'gfm-mode)))
   6676       (kill-buffer))))
   6677 
   6678 (ert-deftest test-markdown-ext/wiki-link-nonexistent-file ()
   6679   "Test following wiki link to nonexistent file visits the buffer."
   6680   (let ((markdown-enable-wiki-links t))
   6681     (find-file (expand-file-name "wiki/foo.md" markdown-test-dir))
   6682     (unwind-protect
   6683         (progn
   6684           (markdown-mode)
   6685           (search-forward "[[doesnotexist]]")
   6686           (markdown-follow-wiki-link-at-point)
   6687           (should (string= (buffer-name) "doesnotexist.md")))
   6688       (kill-buffer))))
   6689 
   6690 (defadvice markdown-live-preview-window-eww
   6691     (around markdown-test-create-fake-eww disable)
   6692   (setq ad-return-value (get-buffer-create "*eww*")))
   6693 
   6694 (defmacro markdown-test-fake-eww (&rest body)
   6695   `(progn
   6696      ,@(if (and (fboundp 'libxml-parse-html-region) (require 'eww nil t)) body
   6697          `((ad-enable-advice #'markdown-live-preview-window-eww
   6698                              'around 'markdown-test-create-fake-eww)
   6699            (ad-activate #'markdown-live-preview-window-eww)
   6700            ,@body
   6701            (ad-disable-advice #'markdown-live-preview-window-eww
   6702                               'around 'markdown-test-create-fake-eww)
   6703            (ad-activate #'markdown-live-preview-window-eww)))))
   6704 
   6705 (defmacro markdown-test-eww-or-nothing (test &rest body)
   6706   (declare (indent 1))
   6707   (if (and (fboundp 'libxml-parse-html-region) (require 'eww nil t)
   6708            (executable-find markdown-command))
   6709       `(progn ,@body)
   6710     (message "no eww, no libxml2, or no %s found: skipping %s" markdown-command test)
   6711     nil))
   6712 
   6713 (ert-deftest test-markdown-ext/live-preview-no-file ()
   6714   "Live-preview a `markdown-mode' buffer without a file."
   6715   (with-temp-buffer
   6716     (markdown-mode)
   6717 
   6718     ;; Activating `markdown-live-preview-mode' signals error
   6719     (let ((data (should-error (markdown-live-preview-mode) :type 'user-error)))
   6720       (should (string-match-p
   6721                (rx bos "Buffer " (+ nonl) " does not visit a file" eos)
   6722                (error-message-string data))))
   6723 
   6724     ;; After trying to activate live preview mode, mode is not activated
   6725     (should-not markdown-live-preview-mode)
   6726 
   6727     ;; `markdown-live-preview-export' does nothing
   6728     (should-not (markdown-live-preview-export))
   6729 
   6730     ;; `markdown-live-preview-remove' does nothing
   6731     (should-not (markdown-live-preview-remove))))
   6732 
   6733 (ert-deftest test-markdown-ext/live-preview-exports ()
   6734   (let ((markdown-command #'markdown-command-identity))
   6735     (markdown-test-temp-file "inline.text"
   6736       (unless (and (fboundp 'libxml-parse-html-region) (require 'eww nil t))
   6737         (should-error (markdown-live-preview-mode)))
   6738       (markdown-test-fake-eww
   6739        (markdown-live-preview-mode)
   6740        (should (buffer-live-p markdown-live-preview-buffer))
   6741        (should (eq (current-buffer)
   6742                    (with-current-buffer markdown-live-preview-buffer
   6743                      markdown-live-preview-source-buffer)))
   6744        (kill-buffer markdown-live-preview-buffer)
   6745        (should (null markdown-live-preview-buffer))
   6746        (set-buffer-modified-p t)
   6747        (save-buffer) ;; should create new export
   6748        (should (buffer-live-p markdown-live-preview-buffer))))))
   6749 
   6750 (ert-deftest test-markdown-ext/live-preview-delete-exports ()
   6751   (markdown-test-fake-eww
   6752    (let ((markdown-live-preview-delete-export 'delete-on-destroy)
   6753          (markdown-command #'markdown-command-identity)
   6754          file-output)
   6755      (markdown-test-temp-file "inline.text"
   6756        (markdown-live-preview-mode)
   6757        (setq file-output (markdown-export-file-name)))
   6758      (should-not (file-exists-p file-output)))
   6759    (let ((markdown-live-preview-delete-export 'delete-on-export)
   6760          (markdown-command #'markdown-command-identity)
   6761          file-output)
   6762      (markdown-test-temp-file "inline.text"
   6763        (markdown-live-preview-mode)
   6764        (setq file-output (markdown-export-file-name))
   6765        (should-not (file-exists-p file-output))))
   6766    (let ((markdown-live-preview-delete-export nil)
   6767          (markdown-command #'markdown-command-identity)
   6768          file-output)
   6769      (unwind-protect
   6770          (markdown-test-temp-file "inline.text"
   6771            (markdown-live-preview-mode)
   6772            (setq file-output (markdown-export-file-name))
   6773            (should (file-exists-p file-output)))
   6774        (delete-file file-output)))))
   6775 
   6776 (ert-deftest test-markdown-ext/live-preview-follow-min-max ()
   6777   (markdown-test-eww-or-nothing "live-preview-follow-min-max"
   6778     (markdown-test-temp-file "inline.text"
   6779       (markdown-live-preview-mode)
   6780       (should (buffer-live-p markdown-live-preview-buffer))
   6781       (should (window-live-p (get-buffer-window markdown-live-preview-buffer)))
   6782       (with-selected-window (get-buffer-window markdown-live-preview-buffer)
   6783         (goto-char (point-min)))
   6784       (goto-char (point-min))
   6785       (insert "a test ")
   6786       (markdown-live-preview-export)
   6787       (let (final-pt final-win-st-diff)
   6788         ;; test that still starts at point-min
   6789         (with-selected-window (get-buffer-window markdown-live-preview-buffer)
   6790           (should (= (window-point) 1))
   6791           (should (= (markdown-visual-lines-between-points
   6792                       (window-start) (window-point))
   6793                      0))
   6794           (set-window-point (selected-window) (point-max))
   6795           (setq final-pt (window-point)
   6796                 final-win-st-diff (markdown-visual-lines-between-points
   6797                                    (window-start) (window-point))))
   6798         (goto-char (point-min))
   6799         (insert "this is ")
   6800         (markdown-live-preview-export)
   6801         (with-selected-window (get-buffer-window markdown-live-preview-buffer)
   6802           (should (= (window-point) (+ final-pt (length "this is "))))
   6803           (should (= (markdown-visual-lines-between-points
   6804                       (window-start) (window-point))
   6805                      final-win-st-diff))
   6806           ;; test that still starts at point-max, with correct line difference
   6807           (goto-char (floor (/ (float (- (point-max) (point-min))) 2)))
   6808           (setq final-pt (window-point)
   6809                 final-win-st-diff (markdown-visual-lines-between-points
   6810                                    (window-start) final-pt)))
   6811         (markdown-live-preview-export)
   6812         ;; test that still starts at same point, with correct line difference
   6813         (with-selected-window (get-buffer-window markdown-live-preview-buffer)
   6814           (should (= (window-point) final-pt))
   6815           (should (= (markdown-visual-lines-between-points
   6816                       (window-start) (window-point))
   6817                      final-win-st-diff)))))))
   6818 
   6819 ;;; Tests for imenu
   6820 
   6821 (ert-deftest test-markdown-imenu/metadata ()
   6822   "Don't correct header like statement in metadata.
   6823 https://github.com/jrblevin/markdown-mode/issues/145"
   6824   (markdown-test-string "---
   6825 title = \"Blah\"
   6826 comments = false
   6827 ---
   6828 
   6829 # Header1
   6830 
   6831 ## Header2
   6832 "
   6833     (let ((headers (mapcar #'car (markdown-imenu-create-flat-index))))
   6834       (should (member "Header1" headers))
   6835       (should (member "Header2" headers))
   6836       (should-not (member "comments = false" headers)))))
   6837 
   6838 (ert-deftest test-markdown-imenu/include-footnotes ()
   6839   "Check that footnotes are added to the imenu.
   6840 https://github.com/jrblevin/markdown-mode/issues/235"
   6841   (markdown-test-string "# H1
   6842 
   6843 [^fn1]: footnote 1
   6844 
   6845 ## H2
   6846 
   6847 [^fn2]: footnote 2
   6848 "
   6849     (let* ((markdown-add-footnotes-to-imenu t)
   6850            (entries (mapcar #'car (markdown-imenu-create-flat-index))))
   6851       (should (member "^fn1" entries))
   6852       (should (member "^fn2" entries)))))
   6853 
   6854 (ert-deftest test-markdown-imenu/no-footnotes ()
   6855   "Check that footnotes are not added to the imenu.
   6856 https://github.com/jrblevin/markdown-mode/issues/235"
   6857   (markdown-test-string "# H1
   6858 
   6859 [^fn1]: footnote 1
   6860 
   6861 ## H2
   6862 
   6863 [^fn2]: footnote 2
   6864 "
   6865     (let* ((markdown-add-footnotes-to-imenu nil)
   6866            (entries (mapcar #'car (markdown-imenu-create-flat-index))))
   6867       (should-not (member "^fn1" entries))
   6868       (should-not (member "^fn2" entries)))))
   6869 
   6870 (ert-deftest test-markdown-imenu/no-level-one-header ()
   6871   "Create imenu entries if there is no level-1 header
   6872 https://github.com/jrblevin/markdown-mode/issues/571"
   6873   (markdown-test-string "---
   6874 title: Wat
   6875 ---
   6876 
   6877 ## Section a
   6878 
   6879 ### Sub 1
   6880 
   6881 ### Sub 11
   6882 
   6883 ## Section b
   6884 
   6885 ### Sub 2"
   6886     (let ((entries (markdown-imenu-create-nested-index)))
   6887       (should (string= (car (nth 0 entries)) "Section a"))
   6888       (should (string= (car (nth 1 entries)) "Section b")))))
   6889 
   6890 (ert-deftest test-markdown-command/function ()
   6891   "Test ‘markdown’ with ‘markdown-command’ being a function."
   6892   (markdown-test-string "foo"
   6893     (let* ((calls ())
   6894            (markdown-command (lambda (&rest args) (push args calls)))
   6895            (buffer-name (markdown))
   6896            (buffer (get-buffer buffer-name)))
   6897       (should (stringp buffer-name))
   6898       (should (buffer-live-p buffer))
   6899       (should (equal calls `((1 4 ,buffer)))))))
   6900 
   6901 (ert-deftest test-markdown-command/string-command ()
   6902   "Test `markdown-command' for string which has only command."
   6903   (skip-unless (executable-find "pandoc"))
   6904   (markdown-test-string "foo"
   6905     (let ((markdown-command "pandoc"))
   6906       ;; check exception is not thrown
   6907       (should (markdown)))))
   6908 
   6909 (ert-deftest test-markdown-command/string-command-with-options ()
   6910   "Test `markdown-command' for string which has command and options."
   6911   (skip-unless (executable-find "pandoc"))
   6912   (markdown-test-string "foo"
   6913     (let ((markdown-command "pandoc --from=markdown --to=html5"))
   6914       (should (markdown)))))
   6915 
   6916 (ert-deftest test-markdown-command/list-of-strings ()
   6917   "Test `markdown-command' for list of strings."
   6918   (skip-unless (executable-find "pandoc"))
   6919   (markdown-test-string "foo"
   6920     (let ((markdown-command '("pandoc" "--from=markdown" "--to=html5")))
   6921       (should (markdown)))))
   6922 
   6923 (ert-deftest test-markdown-command/does-not-exist ()
   6924   "Test ‘markdown’ with a non-existing ‘markdown-command’."
   6925   (skip-unless (not (file-executable-p "/does/not/exist")))
   6926   (markdown-test-string "foo"
   6927     (let* ((markdown-command "/does/not/exist")
   6928            (data (should-error (markdown) :type 'user-error)))
   6929       (should (string-prefix-p "Markdown command /does/not/exist is not found"
   6930                                (error-message-string data))))))
   6931 
   6932 (ert-deftest test-markdown-command/fails ()
   6933   "Test ‘markdown’ with a failing ‘markdown-command’."
   6934   (skip-unless (executable-find "false"))
   6935   (markdown-test-string "foo"
   6936     (let* ((markdown-command "false")
   6937            (data (should-error (markdown) :type 'user-error)))
   6938       (should (string-prefix-p "false failed with exit code "
   6939                                (error-message-string data))))))
   6940 
   6941 (ert-deftest test-markdown-open-command/function ()
   6942   "Test ‘markdown-open’ with ‘markdown-open-command’ being a function."
   6943   (markdown-test-string ""
   6944     (let* ((calls 0)
   6945            (markdown-open-command (lambda () (cl-incf calls))))
   6946       (markdown-open)
   6947       (should (equal calls 1)))))
   6948 
   6949 (ert-deftest test-markdown-open-command/does-not-exist ()
   6950   "Test ‘markdown-open’ with a non-existing ‘markdown-open-command’."
   6951   (skip-unless (not (file-executable-p "/does/not/exist")))
   6952   (markdown-test-string "foo"
   6953     (let ((buffer-file-name
   6954            (expand-file-name "bar.md" temporary-file-directory))
   6955           (markdown-open-command "/does/not/exist"))
   6956       (should-error (markdown-open) :type 'file-error))))
   6957 
   6958 (ert-deftest test-markdown-open-command/fails ()
   6959   "Test ‘markdown-open’ with a failing ‘markdown-open-command’."
   6960   (skip-unless (executable-find "false"))
   6961   (markdown-test-string "foo"
   6962     (let* ((buffer-file-name
   6963             (expand-file-name "bar.md" temporary-file-directory))
   6964            (markdown-open-command "false")
   6965            (data (should-error (markdown-open) :type 'user-error)))
   6966       (should (string-prefix-p "false failed with exit code 1"
   6967                                (error-message-string data))))))
   6968 
   6969 (ert-deftest test-markdown-open-image-command ()
   6970   "Test ‘markdown-open’ with ‘markdown-open-command’ being a function."
   6971   (markdown-test-string "![foo](./bar.jpg)"
   6972     (let ((markdown-open-image-command
   6973            (lambda (file) (should (string= file "./bar.jpg")))))
   6974       (forward-char 3)
   6975       (markdown-follow-link-at-point))))
   6976 
   6977 ;;; Tests for view mode
   6978 
   6979 (ert-deftest test-markdown-view-mode/filter-buffer-substring ()
   6980   "Test `filter-buffer-substring' of `markdown-view-mode'.
   6981 Detail: https://github.com/jrblevin/markdown-mode/pull/493"
   6982   (let ((test-string "# foo
   6983 ~~This is a dog~~
   6984 
   6985 ```python
   6986 foo(bar=None)
   6987 ```
   6988 ")
   6989         (test-func
   6990          (lambda ()
   6991            (should (string= (filter-buffer-substring (point-min) (line-end-position)) "foo"))
   6992            (forward-line +1)
   6993            (should (string= (filter-buffer-substring (point) (line-end-position)) "This is a dog"))
   6994            (forward-line +2)
   6995            (let ((code-beg (point)))
   6996              (forward-line +3)
   6997              (should (string= (filter-buffer-substring code-beg (point)) "foo(bar=None)\n"))))))
   6998     (markdown-test-string-view test-string
   6999       (funcall test-func))
   7000 
   7001     (markdown-test-string-gfm-view test-string
   7002       (funcall test-func))))
   7003 
   7004 (ert-deftest test-markdown-view-mode/buffer-read-only ()
   7005   "Test disable buffer-read-only."
   7006   (markdown-test-string "foo"
   7007     (markdown-view-mode)
   7008     (should buffer-read-only)
   7009     (markdown-mode)
   7010     (should-not buffer-read-only)))
   7011 
   7012 ;;; Tests for electric pair
   7013 
   7014 (ert-deftest test-markdown-electric-pair-mode ()
   7015   "Test insert triple backtick with `electric-pair-mode'."
   7016   (markdown-test-string-gfm ""
   7017     (let ((markdown-gfm-use-electric-backquote nil))
   7018       (electric-pair-local-mode +1)
   7019       (make-local-variable 'electric-pair-pairs)
   7020       (add-to-list 'electric-pair-pairs '(?` . ?`))
   7021       (dotimes (_ 3)
   7022         (let ((last-command-event ?`))
   7023           (call-interactively (key-binding `[,last-command-event]))))
   7024       (should (looking-back "```" (line-beginning-position)))
   7025       (should (looking-at-p "```")))))
   7026 
   7027 ;;; Tests for flyspell mode
   7028 
   7029 (defun markdown-test-flyspell-incorrect-word-p ()
   7030   (let ((bounds (bounds-of-thing-at-point 'word)))
   7031     (cl-loop for ov in (overlays-in (car bounds) (cdr bounds))
   7032              thereis (overlay-get ov 'flyspell-overlay))))
   7033 
   7034 (ert-deftest test-markdown-flyspell/check-word-p ()
   7035   "Test for `flyspell'."
   7036   (skip-unless (executable-find ispell-program-name))
   7037   (markdown-test-string "aaa
   7038 
   7039 ```
   7040 bbb
   7041 ```
   7042 
   7043 ccc
   7044 
   7045 `ddd`
   7046 
   7047 eee
   7048 
   7049 <!-- fff -->
   7050 "
   7051     (flyspell-buffer)
   7052     (search-forward "aaa")
   7053     (should (markdown-test-flyspell-incorrect-word-p))
   7054     (search-forward "bbb") ;; in code block
   7055     (should-not (markdown-test-flyspell-incorrect-word-p))
   7056     (search-forward "ccc")
   7057     (should (markdown-test-flyspell-incorrect-word-p))
   7058     (search-forward "ddd") ;; in inline code
   7059     (should-not (markdown-test-flyspell-incorrect-word-p))
   7060     (search-forward "eee")
   7061     (should (markdown-test-flyspell-incorrect-word-p))
   7062     (search-forward "fff") ;; in comment
   7063     (should-not (markdown-test-flyspell-incorrect-word-p))))
   7064 
   7065 (ert-deftest test-markdown-flyspell/remove-overlay ()
   7066   "Test non-dictionary word in code block with `flyspell-mode'.
   7067 Details: https://github.com/jrblevin/markdown-mode/issues/311"
   7068   (skip-unless (executable-find ispell-program-name))
   7069   (markdown-test-string "bbb
   7070 ```
   7071 bbb
   7072 "
   7073     (flyspell-mode +1)
   7074     (flyspell-buffer)
   7075     (goto-char (point-max))
   7076     (insert "```\n")
   7077     (forward-line -2)
   7078     (flyspell-buffer)
   7079 
   7080     ;; check 'bbb' in code block
   7081     (should-not (markdown-test-flyspell-incorrect-word-p))
   7082     ;; check 'bbb' outside block
   7083     (goto-char (point-min))
   7084     (should (markdown-test-flyspell-incorrect-word-p))))
   7085 
   7086 (ert-deftest test-markdown-flyspell/yaml-metadata ()
   7087   "Test spell check in YAML metadata with `flyspell-mode'.
   7088 Details: https://github.com/jrblevin/markdown-mode/issues/560"
   7089   (skip-unless (executable-find ispell-program-name))
   7090   (markdown-test-string "---
   7091 title: asdasdasd
   7092 ---
   7093 "
   7094     (flyspell-mode +1)
   7095     (flyspell-buffer)
   7096     (goto-char (point-min))
   7097     (search-forward "title: ")
   7098     (should (markdown-test-flyspell-incorrect-word-p))))
   7099 
   7100 (ert-deftest test-markdown-table/navigation-forward-cell ()
   7101   "Test table navigation."
   7102   (markdown-test-string "
   7103 | 1  | 2  | 3  | 4  |
   7104 |----|----|----|----|
   7105 | 5  | 6  | 7  | 8  |
   7106 | 9  | 10 | 11 | 12 |"
   7107     (search-forward "1 ")
   7108     (let ((index 2))
   7109       (while (<= index 12)
   7110         (markdown-table-forward-cell)
   7111         (should (looking-at (format "%d" index)))
   7112         (cl-incf index)))))
   7113 
   7114 (ert-deftest test-markdown-table/navigation-backward-cell ()
   7115   "Test table navigation."
   7116   (markdown-test-string "
   7117 | 1  | 2  | 3  | 4  |
   7118 |----|----|----|----|
   7119 | 5  | 6  | 7  | 8  |
   7120 | 9  | 10 | 11 | 12 |
   7121 "
   7122     (search-forward "12")
   7123     (let ((index 11))
   7124       (while (>= index 1)
   7125         (markdown-table-backward-cell)
   7126         (should (looking-at (format "%d" index)))
   7127         (cl-decf index)))))
   7128 
   7129 (ert-deftest test-markdown-table/align ()
   7130   "Test table realignment."
   7131   (markdown-test-string "
   7132 | Header 1 |Header 2|
   7133 |------|----|
   7134 | | |
   7135 | A very very very long cell| |
   7136 "
   7137     (search-forward "Header")
   7138     (markdown-table-align)
   7139     (message "\"%s\"" (buffer-string))
   7140     (should (string= (buffer-string) "
   7141 | Header 1                   | Header 2 |
   7142 |----------------------------|----------|
   7143 |                            |          |
   7144 | A very very very long cell |          |
   7145 "))))
   7146 
   7147 (ert-deftest test-markdown-table/align-with-spaces-before-delimiter ()
   7148   "Test table realignment when there are spaces before a delimiter"
   7149   (markdown-test-string "
   7150 | A | B | C | D |
   7151 | - | :- | :-: | -: |
   7152 | aaa | bbbb | ccccc | dddddd |
   7153 "
   7154     (search-forward "A")
   7155     (markdown-table-align)
   7156     (should (string= (buffer-string) "
   7157 | A   | B    | C     |      D |
   7158 |-----|:-----|:-----:|-------:|
   7159 | aaa | bbbb | ccccc | dddddd |
   7160 "))))
   7161 
   7162 (ert-deftest test-markdown-table/align-with-tabs-before-delimiter ()
   7163   "Test table realignment when there are tabs before a delimiter"
   7164   (markdown-test-string "
   7165 | A | B | C | D |
   7166 |	-	|	:-|:-:	|-:|
   7167 | aaa | bbbb | ccccc | dddddd |
   7168 "
   7169     (search-forward "A")
   7170     (markdown-table-align)
   7171     (should (string= (buffer-string) "
   7172 | A   | B    | C     |      D |
   7173 |-----|:-----|:-----:|-------:|
   7174 | aaa | bbbb | ccccc | dddddd |
   7175 "))))
   7176 
   7177 (ert-deftest test-markdown-table/disable-table-align ()
   7178   "Test disable table alignment."
   7179   (let ((input "| 12345 | 6 |
   7180 | 7 | 8 |"))
   7181     (markdown-test-string input
   7182       (save-excursion
   7183         (search-forward "1")
   7184         (let ((markdown-table-align-p nil))
   7185           (markdown-table-forward-cell)
   7186           (should (string= (buffer-string) input))))
   7187 
   7188       (search-forward "1")
   7189       (let ((expected "| 12345 | 6 |
   7190 | 7     | 8 |
   7191 "))
   7192         (markdown-table-forward-cell)
   7193         (should (string= (buffer-string) expected))))))
   7194 
   7195 (ert-deftest test-markdown-table/convert-table-region ()
   7196   "Test markdown-table-convert-region.
   7197 https://github.com/jrblevin/markdown-mode/issues/640"
   7198   (let ((markdown-table-align-p t))
   7199     (markdown-test-string "1 2 3
   7200 4 5 6"
   7201       (markdown-table-convert-region (point-min) (point-max))
   7202       (should (string= (buffer-substring-no-properties (point-min) (point-max))
   7203                        "| 1 | 2 | 3 |
   7204 | 4 | 5 | 6 |\n")))
   7205     (markdown-test-string "1 2 3 \n4 5 6 "
   7206       (markdown-table-convert-region (point-min) (point-max))
   7207       (should (string= (buffer-substring-no-properties (point-min) (point-max))
   7208                        "| 1 | 2 | 3 |\n| 4 | 5 | 6 |\n")))))
   7209 
   7210 (provide 'markdown-test)
   7211 
   7212 ;;; markdown-test.el ends here