Merge pull request #831 from jrblevin/fix-830
[markdown-mode.git] / tests / markdown-test.el
blob21c7a033d6793a42bc20d2199d9809dd4cb6a314
1 ;;;; markdown-test.el --- Tests for markdown-mode -*- lexical-binding: t; -*-
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>)
7 ;; This file is not part of GNU Emacs.
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.
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.
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/>.
22 ;;; Commentary:
24 ;; This file contains the `markdown-mode' test suite. To run the tests:
26 ;; M-x load-file RET markdown-test.el RET
27 ;; M-x markdown-test RET
29 ;;; Code:
31 (require 'markdown-mode)
32 (require 'ert)
33 (require 'cl-lib)
34 (require 'ispell)
35 (require 'eww)
37 (eval-when-compile
38 ;; This is for byte-compile warnings on older Emacs.
39 ;; eww-auto-rename-buffer is introduced at Emacs 29.1
40 (defvar eww-auto-rename-buffer)
41 ;; major-mode-remap-alist introduced at Emacs 29.1
42 (defvar major-mode-remap-alist))
44 (defvar electric-pair-pairs)
46 (defconst markdown-test-dir
47 (expand-file-name (file-name-directory
48 (or load-file-name buffer-file-name))))
50 (defmacro markdown-test-string-mode (mode string &rest body)
51 "Run BODY in a temporary buffer containing STRING in MODE."
52 (declare (indent 2))
53 `(let ((win (selected-window)))
54 (with-temp-buffer
55 (set-window-buffer win (current-buffer) t)
56 (erase-buffer)
57 (insert ,string)
58 (funcall ,mode)
59 (setq-default indent-tabs-mode nil)
60 (goto-char (point-min))
61 (font-lock-ensure)
62 ,@body)))
64 (defmacro markdown-test-file-mode (mode file &rest body)
65 "Open FILE from `markdown-test-dir' in MODE and execute BODY."
66 (declare (indent 2))
67 `(let ((fn (concat markdown-test-dir ,file)))
68 (save-window-excursion
69 (with-temp-buffer
70 (insert-file-contents fn)
71 (funcall ,mode)
72 (goto-char (point-min))
73 (font-lock-ensure)
74 ,@body))))
76 (defmacro markdown-test-string (string &rest body)
77 "Run BODY in a temporary buffer containing STRING in `markdown-mode'."
78 (declare (indent 1))
79 `(markdown-test-string-mode 'markdown-mode ,string ,@body))
80 (def-edebug-spec markdown-test-string (form body))
82 (defmacro markdown-test-string-view (string &rest body)
83 "Run BODY in a temporary buffer containing STRING in `markdown-view-mode'."
84 (declare (indent 1))
85 `(markdown-test-string-mode 'markdown-view-mode ,string ,@body))
86 (def-edebug-spec markdown-test-string-view (form body))
88 (defmacro markdown-test-file (file &rest body)
89 "Open FILE from `markdown-test-dir' in `markdown-mode' and execute BODY."
90 (declare (indent 1))
91 `(markdown-test-file-mode 'markdown-mode ,file ,@body))
92 (def-edebug-spec markdown-test-file (form body))
94 (defmacro markdown-test-string-gfm (string &rest body)
95 "Run BODY in a temporary buffer containing STRING in `gfm-mode'."
96 (declare (indent 1))
97 `(markdown-test-string-mode 'gfm-mode ,string ,@body))
98 (def-edebug-spec markdown-test-string-gfm (form body))
100 (defmacro markdown-test-string-gfm-view (string &rest body)
101 "Run BODY in a temporary buffer containing STRING in `gfm-view-mode'."
102 (declare (indent 1))
103 `(markdown-test-string-mode 'gfm-view-mode ,string ,@body))
104 (def-edebug-spec markdown-test-string-gfm-view (form body))
106 (defmacro markdown-test-file-gfm (file &rest body)
107 "Open FILE from `markdown-test-dir' in `gfm-mode' and execute BODY."
108 (declare (indent 1))
109 `(markdown-test-file-mode 'gfm-mode ,file ,@body))
110 (def-edebug-spec markdown-test-file-gfm (form body))
112 (defmacro markdown-test-temp-file (file &rest body)
113 "Open FILE from `markdown-test-dir' visiting temp file and execute BODY.
114 This file is not saved."
115 (declare (indent 1))
116 `(let ((fn (concat markdown-test-dir ,file))
117 (tmp (make-temp-file "markdown-test" nil ".text"))
118 buf)
119 (save-window-excursion
120 (unwind-protect
121 (progn
122 (setq buf (find-file tmp))
123 (insert-file-contents fn)
124 (markdown-mode)
125 (goto-char (point-min))
126 (font-lock-ensure)
127 ,@body)
128 (when (buffer-live-p buf)
129 (set-buffer-modified-p nil)
130 (kill-buffer buf))
131 (delete-file tmp)))))
132 (def-edebug-spec markdown-test-temp-file (form body))
134 (defun markdown-test-report-property-range (begin end prop)
135 "Report buffer substring and property PROP from BEGIN to END."
136 (message "Buffer substring: %s" (buffer-substring begin (1+ end)))
137 (message "Properties in range are as follows:")
138 (dolist (loc (number-sequence begin end))
139 (message "%d: %s" loc (get-char-property loc prop))))
141 (defun markdown-test-range-has-property (begin end prop value)
142 "Verify that range BEGIN to END has PROP equal to or containing VALUE."
143 (let (vals fail-loc)
144 (setq fail-loc
145 (catch 'fail
146 (dolist (loc (number-sequence begin end))
147 (setq vals (get-char-property loc prop))
148 (if (and vals (listp vals))
149 (unless (memq value vals)
150 (throw 'fail loc))
151 (unless (eq vals value)
152 (throw 'fail loc))))))
153 (when fail-loc
154 (message "Testing range (%d,%d) for property %s equal to %s."
155 begin end prop value)
156 (message "Expected value (%s) not found in property (%s) at location %d" value prop fail-loc)
157 (markdown-test-report-property-range begin end prop))
158 (should-not fail-loc)))
160 (defun markdown-test-range-property-equals (begin end prop value)
161 "Verify that range BEGIN to END has property PROP equal to VALUE."
162 (let ((fail-loc
163 (catch 'fail
164 (dolist (loc (number-sequence begin end))
165 (unless (eq (get-char-property loc prop) value)
166 (throw 'fail loc))))))
167 (when fail-loc
168 (message "Testing range (%d,%d) for property %s equal to %s."
169 begin end prop value)
170 (message "Expected value (%s) not found in property (%s) at location %d" value prop fail-loc)
171 (markdown-test-report-property-range begin end prop))
172 (should-not fail-loc)))
174 (defun markdown-test-range-has-face (begin end face)
175 "Verify that the range from BEGIN to END has face FACE."
176 (markdown-test-range-has-property begin end 'face face))
178 (defun markdown-test-range-face-equals (begin end face)
179 "Verify that the range from BEGIN to END has face equal to FACE."
180 (markdown-test-range-property-equals begin end 'face face))
182 (defun markdown-test-goto-heading (title)
183 "Move the point to section with TITLE."
184 (let ((regexp (format "\\(^#+ %s\\( #+\\)?\\|^%s\n[=-]+\n\\)" title title)))
185 (if (re-search-forward regexp nil t)
186 (goto-char (match-end 0)))))
188 (defun markdown-command-identity (begin end output-buffer)
189 "A placeholder `markdown-command' function for testing.
190 Extracts region from BEGIN to END and inserts in OUTPUT-BUFFER."
191 (let ((text (buffer-substring-no-properties begin end)))
192 (with-current-buffer output-buffer
193 (erase-buffer)
194 (insert text))))
196 (defun markdown-test ()
197 "Run all defined test cases for `markdown-mode'."
198 (interactive)
199 (ert "markdown"))
201 ;;; major-mode tests:
203 (ert-deftest test-markdown-major-mode ()
204 "Test auto-mode-alist setting."
205 (dolist (extension '(".md" ".markdown" ".mkd" ".mdown" ".mkdn" ".mdwn"))
206 (let ((file (make-temp-file "a" nil extension)))
207 (unwind-protect
208 (with-current-buffer (find-file-noselect file)
209 (should (eq major-mode 'markdown-mode)))
210 (delete-file file)))))
212 ;;; Example tests:
214 (ert-deftest test-markdown-example/string ()
215 "An example string test using the `ert' framework."
216 (markdown-test-string "foo *bar* baz"
217 (goto-char 5)
218 (delete-char 1)
219 (should (looking-at "bar"))))
221 (ert-deftest test-markdown-example/file ()
222 "An example file test using the `ert' framework."
223 (markdown-test-file "inline.text"
224 (goto-char 9)
225 (should (looking-at "\*"))))
227 ;;; Basic mode tests:
229 (ert-deftest test-markdown-mode/variables ()
230 "Test `markdown-mode' variables."
231 (markdown-test-file "inline.text"
232 (should (= tab-width 4))
233 (should (eq font-lock-multiline t))
234 (should (eq major-mode 'markdown-mode))))
236 ;;; Element insertion tests:
238 (ert-deftest test-markdown-insertion/blank-line-before-1 ()
239 "Test function `markdown-ensure-blank-line-before' at beginning of line."
240 (markdown-test-file "syntax.text"
241 (search-forward "as plain text")
242 (should (= (point) 1556))
243 (beginning-of-line)
244 (should (= (point) 1505))
245 (should (looking-back "A Markdown-formatted\n" nil))
246 (should (not (markdown-prev-line-blank-p)))
247 (markdown-ensure-blank-line-before)
248 (should (looking-back "A Markdown-formatted\n\n" nil))
249 (should (markdown-prev-line-blank-p))))
251 (ert-deftest test-markdown-insertion/blank-line-before-2 ()
252 "Test function `markdown-ensure-blank-line-before' in middle of line."
253 (markdown-test-file "syntax.text"
254 (search-forward "as plain text")
255 (should (= (point) 1556))
256 (should (looking-back "as plain text" nil))
257 (should (not (markdown-prev-line-blank-p)))
258 (markdown-ensure-blank-line-before)
259 (should (looking-back "as plain text\n\n" nil))
260 (should (markdown-prev-line-blank-p))))
262 (ert-deftest test-markdown-insertion/blank-line-before-3 ()
263 "Test function `markdown-ensure-blank-line-before' with blank line before."
264 (markdown-test-file "syntax.text"
265 (search-forward "web.\n\nMarkdown is not a replacement for HTML")
266 (beginning-of-line)
267 (should (= (point) 2704))
268 (should (looking-back "web.\n\n" nil))
269 (should (markdown-prev-line-blank-p))
270 (markdown-ensure-blank-line-before)
271 (should (= (point) 2704))
272 (should (looking-back "web.\n\n" nil))
273 (should (markdown-prev-line-blank-p))))
275 (ert-deftest test-markdown-insertion/blank-line-before-4 ()
276 "Test function `markdown-ensure-blank-line-before' at beginning of buffer."
277 (markdown-test-string "first line"
278 (beginning-of-line)
279 (should (bobp))
280 (should (= (point-max) 11))
281 (markdown-ensure-blank-line-before)
282 (should (= (point-max) 11))
283 (should (string-equal (buffer-substring (point-min) (point-max))
284 "first line"))
285 (forward-word)
286 (markdown-ensure-blank-line-before)
287 (should (string-equal (buffer-substring (point-min) (point-max))
288 "first\n\n line"))))
290 (ert-deftest test-markdown-insertion/blank-line-after-1 ()
291 "Test function `markdown-ensure-blank-line-after' at end of line."
292 (markdown-test-file "syntax.text"
293 (search-forward "as plain text")
294 (should (= (point) 1556))
295 (end-of-line)
296 (should (= (point) 1573))
297 (should (looking-at "\nlike it's been"))
298 (should (not (markdown-next-line-blank-p)))
299 (markdown-ensure-blank-line-after)
300 (should (looking-at "\n\nlike it's been"))
301 (should (markdown-next-line-blank-p))))
303 (ert-deftest test-markdown-insertion/blank-line-after-2 ()
304 "Test function `markdown-ensure-blank-line-after' in middle of line."
305 (markdown-test-file "syntax.text"
306 (search-forward "as plain text")
307 (should (= (point) 1556))
308 (should (looking-at ", without looking"))
309 (should (not (markdown-next-line-blank-p)))
310 (markdown-ensure-blank-line-after)
311 (should (looking-at "\n\n, without looking"))
312 (should (markdown-next-line-blank-p))))
314 (ert-deftest test-markdown-insertion/blank-line-after-3 ()
315 "Test function `markdown-ensure-blank-line-after' with blank line after."
316 (markdown-test-file "syntax.text"
317 (search-forward "*writing* for the web.")
318 (should (= (point) 2702))
319 (should (looking-at "\n\nMarkdown is not a replacement for HTML"))
320 (should (markdown-next-line-blank-p))
321 (markdown-ensure-blank-line-after)
322 (should (= (point) 2702))
323 (should (looking-at "\n\nMarkdown is not a replacement for HTML"))
324 (should (markdown-next-line-blank-p))))
326 (ert-deftest test-markdown-insertion/blank-line-after-4 ()
327 "Test function `markdown-ensure-blank-line-after' at end of buffer."
328 (markdown-test-string "last line"
329 (end-of-line)
330 (should (eobp))
331 (should (= (point-max) 10))
332 (markdown-ensure-blank-line-after)
333 (should (= (point-max) 10))
334 (should (string-equal (buffer-substring (point-min) (point-max))
335 "last line"))
336 (backward-word)
337 (markdown-ensure-blank-line-after)
338 (should (string-equal (buffer-substring (point-min) (point-max))
339 "last \n\nline"))))
341 (ert-deftest test-markdown-insertion/point-after-unwrap ()
342 "Test new point position calculations after unwrap operations."
343 (markdown-test-string "line **one**\n"
344 (let ((prefix (cons 6 8)) (suffix (cons 11 13)))
345 ;; Prefix
346 (should (eq (markdown-point-after-unwrap 6 prefix suffix) 6))
347 (should (eq (markdown-point-after-unwrap 7 prefix suffix) 6))
348 ;; Word
349 (should (eq (markdown-point-after-unwrap 8 prefix suffix) 6))
350 (should (eq (markdown-point-after-unwrap 9 prefix suffix) 7))
351 (should (eq (markdown-point-after-unwrap 10 prefix suffix) 8))
352 ;; Suffix
353 (should (eq (markdown-point-after-unwrap 11 prefix suffix) 9))
354 (should (eq (markdown-point-after-unwrap 12 prefix suffix) 9))
355 ;; Immediately after
356 (should (eq (markdown-point-after-unwrap 13 prefix suffix) 9))))
357 (markdown-test-string "line _one_\n"
358 (let ((prefix (cons 6 7)) (suffix (cons 10 11)))
359 ;; Prefix
360 (should (eq (markdown-point-after-unwrap 6 prefix suffix) 6))
361 ;; Word
362 (should (eq (markdown-point-after-unwrap 7 prefix suffix) 6))
363 (should (eq (markdown-point-after-unwrap 8 prefix suffix) 7))
364 (should (eq (markdown-point-after-unwrap 9 prefix suffix) 8))
365 ;; Suffix
366 (should (eq (markdown-point-after-unwrap 10 prefix suffix) 9))
367 ;; Immediately after
368 (should (eq (markdown-point-after-unwrap 10 prefix suffix) 9)))))
370 (ert-deftest test-markdown-insertion/unwrap-thing-at-point-italic ()
371 "Test function `markdown-unwrap-thing-at-point' on italics."
372 (markdown-test-file "syntax.text"
373 ;; Unwrap *not*
374 (goto-char 2859)
375 (should (thing-at-point-looking-at markdown-regex-italic))
376 (should (equal (markdown-unwrap-thing-at-point
377 markdown-regex-italic 1 3)
378 (cons 2859 2862)))
379 (should (= (point) 2859))
380 ;; Unwrap *publishing*
381 (goto-char 3064)
382 (should (thing-at-point-looking-at markdown-regex-italic))
383 (should (equal (markdown-unwrap-thing-at-point
384 markdown-regex-italic 1 3)
385 (cons 3060 3070)))
386 (should (= (point) 3063))
387 ;; Unwrap *writing*
388 (goto-char 3101)
389 (should (thing-at-point-looking-at markdown-regex-italic))
390 (should (equal (markdown-unwrap-thing-at-point
391 markdown-regex-italic 1 3)
392 (cons 3093 3100)))
393 (should (= (point) 3100))))
395 (ert-deftest test-markdown-insertion/unwrap-things-in-region-italic ()
396 "Test function `markdown-unwrap-things-in-region' on italics."
397 (markdown-test-file "syntax.text"
398 (should (equal (markdown-unwrap-things-in-region
399 2704 3207 markdown-regex-italic 1 3)
400 (cons 2704 3201)))))
402 (ert-deftest test-markdown-insertion/unwrap-things-in-region-bound ()
403 "Ensure that `markdown-unwrap-things-in-region' respects end bound"
404 (markdown-test-string "**a** **b** **c** **d** **e** **f**"
405 ;; Set region to unrwap a, b, c, and d only. If endpoint is not
406 ;; respected (i.e, not adjusted for character removal), the
407 ;; function will unwrap e and f also.
408 (should (equal (markdown-unwrap-things-in-region
409 1 24 markdown-regex-bold 2 4)
410 (cons 1 8)))
411 (should (string-equal (buffer-string) "a b c d **e** **f**"))))
413 (ert-deftest test-markdown-insertion/unwrap-things-in-region-links ()
414 "Test function `markdown-unwrap-things-in-region' on inline links."
415 (markdown-test-string "a [link](http://jblevins.org/) or [two](/).\n"
416 (should (equal (markdown-unwrap-things-in-region
417 (point-min) (point-max) markdown-regex-link-inline 0 3)
418 (cons 1 16)))
419 (should (string-equal (buffer-string) "a link or two.\n"))))
421 (ert-deftest test-markdown-insertion/toggle-bold ()
422 "Test toggling functionality of `markdown-insert-bold'."
423 (markdown-test-string "one **two** three"
424 (forward-word 2)
425 (markdown-insert-bold)
426 (should (string-equal (buffer-string) "one two three"))
427 (should (= (point) 8))
428 (forward-word)
429 (markdown-insert-bold)
430 (should (= (point) 16))
431 (should (string-equal (buffer-string) "one two **three**"))))
433 (ert-deftest test-markdown-insertion/toggle-bold-consecutive ()
434 "Test toggling functionality of consecutive bolds.
435 Detail: https://github.com/jrblevin/markdown-mode/issues/283"
436 (markdown-test-string "one **two** **three**"
437 (search-forward "w")
438 (markdown-insert-bold)
439 (should (string-equal (buffer-string) "one two **three**"))))
441 (ert-deftest test-markdown-insertion/toggle-italic ()
442 "Test toggling functionality of `markdown-insert-italic'."
443 (markdown-test-string "one *two* three"
444 (forward-word 2)
445 (markdown-insert-italic)
446 (should (string-equal (buffer-string) "one two three"))
447 (should (= (point) 8))
448 (forward-word)
449 (markdown-insert-italic)
450 (should (string-equal (buffer-string) "one two *three*"))
451 (should (= (point) 15))))
453 (ert-deftest test-markdown-insertion/toggle-italic-consecutive ()
454 "Test toggling functionality of consecutive italics.
455 Detail: https://github.com/jrblevin/markdown-mode/issues/283"
456 (markdown-test-string "one *two* *three*"
457 (search-forward "w")
458 (markdown-insert-italic)
459 (should (string-equal (buffer-string) "one two *three*"))))
461 (ert-deftest test-markdown-insertion/toggle-code ()
462 "Test toggling functionality of `markdown-insert-code'."
463 (markdown-test-string "one `two` three"
464 (forward-word 2)
465 (markdown-insert-code)
466 (should (string-equal (buffer-string) "one two three"))
467 (should (= (point) 8))
468 (forward-word)
469 (markdown-insert-code)
470 (should (string-equal (buffer-string) "one two `three`"))
471 (should (= (point) 15))))
473 (ert-deftest test-markdown-insertion/toggle-kbd ()
474 "Test toggling functionality of `markdown-insert-code'."
475 (markdown-test-string "test <kbd>C-c C-s k</kbd> toggle"
476 (forward-word 2)
477 (markdown-insert-kbd)
478 (should (string-equal (buffer-string) "test C-c C-s k toggle"))
479 (should (= (point) 6))
480 (backward-word)
481 (markdown-insert-kbd)
482 (should (string-equal (buffer-string) "<kbd>test</kbd> C-c C-s k toggle"))
483 (should (= (point) 6))))
485 (ert-deftest test-markdown-insertion/toggle-wiki-link-alias-first ()
486 "Test toggling of `markdown-insert-wiki-link' with alias first.
487 Test point position upon removal and insertion."
488 (let ((markdown-wiki-link-alias-first t))
489 (markdown-test-string "[[text|page]]"
490 (goto-char 5) ; point in interior of alias text, at 'x'
491 (call-interactively 'markdown-insert-wiki-link)
492 (should (= (point) 3)) ; leave point at, at 'x'
493 (should (string-equal (buffer-string) "text"))
494 (call-interactively 'markdown-insert-wiki-link)
495 (should (= (point) 5)) ; leave point at, at 'x'
496 (should (string-equal (buffer-string) "[[text]]")))
497 (markdown-test-string "[[text|page]]"
498 (goto-char 10) ; point in interior of link text, at 'g'
499 (call-interactively 'markdown-insert-wiki-link)
500 (should (= (point) 5)) ; leave point at end of alias text
501 (should (string-equal (buffer-string) "text"))
502 (call-interactively 'markdown-insert-wiki-link)
503 (should (= (point) 7)) ; leave point at end of alias text
504 (should (string-equal (buffer-string) "[[text]]")))))
506 (ert-deftest test-markdown-insertion/toggle-wiki-link-alias-last ()
507 "Test toggling of `markdown-insert-wiki-link' with alias last.
508 Test point position upon removal and insertion."
509 (let ((markdown-wiki-link-alias-first nil))
510 (markdown-test-string "[[page|text]]"
511 (goto-char 10) ; point in interior of alias text, at 'x'
512 (call-interactively 'markdown-insert-wiki-link)
513 (goto-char 3) ; leave point at, at 'x'
514 (should (string-equal (buffer-string) "text"))
515 (call-interactively 'markdown-insert-wiki-link)
516 (should (= (point) 5)) ; leave point at, at 'x'
517 (should (string-equal (buffer-string) "[[text]]")))
518 (markdown-test-string "[[page|text]]"
519 (goto-char 3) ; point in interior of link text, at 'g'
520 (call-interactively 'markdown-insert-wiki-link)
521 (should (= (point) 1)) ; leave point at beginning of alias text
522 (should (string-equal (buffer-string) "text"))
523 (call-interactively 'markdown-insert-wiki-link)
524 (should (= (point) 3)) ; leave point at beginning of alias text
525 (should (string-equal (buffer-string) "[[text]]")))))
527 (ert-deftest test-markdown-insertion/bold-region ()
528 "Test region functionality of `markdown-insert-bold'."
529 (markdown-test-string "one two three"
530 (push-mark (point) t t)
531 (forward-word 2)
532 (markdown-insert-bold)
533 (should (string-equal (buffer-string) "**one two** three"))
534 (should (= (point) 10))))
536 (ert-deftest test-markdown-insertion/bold-region-begin-with-space ()
537 "Test region functionality of `markdown-insert-bold'.
538 When region starts/ends with spaces"
539 (markdown-test-string " one two three"
540 (push-mark (point) t t)
541 (forward-word 2)
542 (markdown-insert-bold)
543 (should (string-equal (buffer-string) " **one two** three")))
544 (markdown-test-string " one two three"
545 (push-mark (point) t t)
546 (goto-char 11)
547 (markdown-insert-bold)
548 (should (string-equal (buffer-string) " **one two** three"))))
550 (ert-deftest test-markdown-insertion/italic-region ()
551 "Test region functionality of `markdown-insert-italic'."
552 (markdown-test-string "one two three"
553 (transient-mark-mode)
554 (push-mark (point) t t)
555 (forward-word 2)
556 (markdown-insert-italic)
557 (should (string-equal (buffer-string) "*one two* three"))
558 (should (= (point) 9))))
560 (ert-deftest test-markdown-insertion/italic-region-begin-with-space ()
561 "Test region functionality of `markdown-insert-italic'.
562 When region starts/ends with spaces"
563 (markdown-test-string " one two three"
564 (transient-mark-mode)
565 (push-mark (point) t t)
566 (goto-char 11)
567 (markdown-insert-italic)
568 (should (string-equal (buffer-string) " *one two* three"))))
570 (ert-deftest test-markdown-insertion/code-region ()
571 "Test region functionality of `markdown-insert-code'."
572 (markdown-test-string "one two three"
573 (transient-mark-mode)
574 (push-mark (point) t t)
575 (forward-word 2)
576 (markdown-insert-code)
577 (should (string-equal (buffer-string) "`one two` three"))
578 (should (= (point) 9))))
580 (ert-deftest test-markdown-insertion/kbd-region ()
581 "Test region functionality of `markdown-insert-kbd'."
582 (markdown-test-string "one two three"
583 (transient-mark-mode)
584 (push-mark (point) t t)
585 (forward-word 2)
586 (markdown-insert-kbd)
587 (should (string-equal (buffer-string) "<kbd>one two</kbd> three"))
588 (should (= (point) 13))))
590 (ert-deftest test-markdown-insertion/atx-line ()
591 "Test ATX header insertion without region."
592 (markdown-test-string "line one\nline two\n"
593 (forward-word)
594 (markdown-insert-header-atx-1)
595 (should (= (point) 11))
596 (should (string-equal (buffer-substring (point-min) (point-max))
597 "# line one #\n\nline two\n"))
598 (forward-line 2)
599 (markdown-insert-header-atx-2)
600 (should (= (point) 26))
601 (should (string-equal (buffer-substring (point-min) (point-max))
602 "# line one #\n\n## line two ##\n\n"))))
604 (ert-deftest test-markdown-insertion/atx-region ()
605 "Test ATX header insertion with region."
606 (markdown-test-string "line one\nline two\n"
607 (transient-mark-mode)
608 (forward-char 5)
609 (push-mark (point) t t)
610 (forward-word)
611 (should (string-equal (buffer-substring (region-beginning) (region-end))
612 "one"))
613 (markdown-insert-header-atx-4)
614 (should (= (point) 16))
615 (should (string-equal (buffer-substring (point-min) (point-max))
616 "line \n\n#### one ####\n\nline two\n"))))
618 (ert-deftest test-markdown-insertion/atx-blank ()
619 "Test ATX header insertion on blank line."
620 (markdown-test-string "line one\n\nline two\n"
621 (forward-line)
622 (markdown-insert-header-atx-3)
623 (should (string-equal (buffer-substring (point-min) (point-max))
624 "line one\n\n### ###\n\nline two\n"))
625 (should (= (point) 15))
626 (should (looking-at " ###\n"))))
628 (ert-deftest test-markdown-insertion/atx-region-whitespace ()
629 "Test ATX header insertion using a region with whitespace."
630 (markdown-test-string " line one\n\nline two\n \n"
631 (transient-mark-mode)
632 (push-mark (point) t t)
633 (goto-char (point-max))
634 (markdown-insert-header-atx-2)
635 (should (string-equal (buffer-substring (point-min) (point-max))
636 "## line one line two ##"))
637 (should (= (point) 21))
638 (should (looking-at " ##"))))
640 (ert-deftest test-markdown-insertion/atx-line-whitespace ()
641 "Test ATX header insertion using current line with whitespace."
642 (markdown-test-string " line one \n\nline two\n"
643 (goto-char (line-end-position))
644 (markdown-insert-header-atx-3)
645 (should (string-equal (buffer-substring (point-min) (point-max))
646 "### line one ###\n\nline two\n"))
647 (should (= (point) 13))
648 (should (looking-at " ###\n"))))
650 (ert-deftest test-markdown-insertion/atx-replace-atx ()
651 "Test ATX header insertion when replacing an existing ATX header."
652 (markdown-test-string "## replace ##\n"
653 (markdown-insert-header-atx-4)
654 (should (string-equal (buffer-string) "#### replace ####\n\n"))
655 (should (looking-at " ####\n"))))
657 (ert-deftest test-markdown-insertion/atx-replace-setext-1 ()
658 "Test ATX header insertion when replacing an existing setext header."
659 (markdown-test-string "replace\n=======\n"
660 (markdown-insert-header-atx-2)
661 (should (string-equal (buffer-string) "## replace ##\n\n"))
662 (should (looking-at " ##\n"))))
664 (ert-deftest test-markdown-insertion/atx-replace-setext-2 ()
665 "Test ATX header insertion when replacing an existing setext header."
666 (markdown-test-string "replace\n-------\n"
667 (markdown-insert-header-atx-5)
668 (should (string-equal (buffer-string) "##### replace #####\n\n"))
669 (should (looking-at " #####\n"))))
671 (ert-deftest test-markdown-insertion/atx-asymmetric-point ()
672 "Test point after ATX header insertion with `markdown-asymmetric-header'."
673 (markdown-test-string
674 "Test"
675 (let ((markdown-asymmetric-header t))
676 (markdown-insert-header-atx-5)
677 (should (= (point) 11))
678 (should (string-equal (buffer-string) "##### Test")))))
680 (ert-deftest test-markdown-insertion/setext-line ()
681 "Test setext header insertion without region."
682 (markdown-test-string "line one\nline two\n"
683 (forward-word)
684 (markdown-insert-header-setext-1)
685 (should (string-equal (buffer-substring (point-min) (point-max))
686 "line one\n========\n\nline two\n"))
687 (forward-line 3)
688 (markdown-insert-header-setext-2)
689 (should (string-equal (buffer-substring (point-min) (point-max))
690 "line one\n========\n\nline two\n--------\n\n"))))
692 (ert-deftest test-markdown-insertion/setext-region ()
693 "Test setext header insertion with region."
694 (markdown-test-string "line one\nline two\n"
695 (transient-mark-mode)
696 (forward-char 5)
697 (push-mark (point) t t)
698 (forward-word)
699 (should (string-equal (buffer-substring (region-beginning) (region-end))
700 "one"))
701 (markdown-insert-header-setext-1)
702 (should (string-equal (buffer-substring (point-min) (point-max))
703 "line \n\none\n===\n\nline two\n"))))
705 (ert-deftest test-markdown-insertion/setext-blank ()
706 "Test setext header insertion on blank line."
707 (markdown-test-string "line one\n\nline two\n"
708 (forward-line)
709 (markdown-insert-header 2 "foo" t)
710 (should (string-equal (buffer-substring (point-min) (point-max))
711 "line one\n\nfoo\n---\n\nline two\n"))
712 (should (= (point) 14))
713 (should (looking-at "\n---"))))
715 (ert-deftest test-markdown-insertion/setext-region-whitespace ()
716 "Test setext header insertion using a region with whitespace."
717 (markdown-test-string " line one\n\nline two\n \n"
718 (transient-mark-mode)
719 (push-mark (point) t t)
720 (goto-char (point-max))
721 (markdown-insert-header-setext-1)
722 (should (string-equal (buffer-substring (point-min) (point-max))
723 "line one line two\n================="))
724 (should (= (point) 18))
725 (should (looking-at "\n===="))))
727 (ert-deftest test-markdown-insertion/setext-line-whitespace ()
728 "Test setext header insertion using current line with whitespace."
729 (markdown-test-string " line one \n\nline two\n"
730 (goto-char (line-end-position))
731 (markdown-insert-header-setext-2)
732 (should (string-equal (buffer-substring (point-min) (point-max))
733 "line one\n--------\n\nline two\n"))
734 (should (= (point) 9))
735 (should (looking-at "\n---"))))
737 (ert-deftest test-markdown-insertion/setext-replace-atx ()
738 "Test setext header insertion when replacing an existing ATX header."
739 (markdown-test-string "## replace ##\n"
740 (markdown-insert-header-setext-1)
741 (should (string-equal (buffer-string) "replace\n=======\n\n"))
742 (should (looking-at "\n==="))))
744 (ert-deftest test-markdown-insertion/setext-replace-setext-1 ()
745 "Test setext header insertion when replacing an existing setext title."
746 (markdown-test-string "replace\n=======\n"
747 (markdown-insert-header-setext-2)
748 (should (string-equal (buffer-string) "replace\n-------\n\n"))
749 (should (looking-at "\n---"))))
751 (ert-deftest test-markdown-insertion/setext-replace-setext-2 ()
752 "Test setext header insertion when replacing an existing setext section."
753 (markdown-test-string "replace\n-------\n"
754 (markdown-insert-header-setext-1)
755 (should (string-equal (buffer-string) "replace\n=======\n\n"))
756 (should (looking-at "\n==="))))
758 (ert-deftest test-markdown-insertion/header-dwim ()
759 "Test 'do what I mean' header insertion."
760 (markdown-test-file "outline.text"
761 (call-interactively 'markdown-insert-header-dwim)
762 (should (looking-at " #$"))
763 (end-of-defun 2)
764 (call-interactively 'markdown-insert-header-dwim)
765 (beginning-of-line)
766 (should (looking-at "^# #$"))
767 (end-of-defun 3)
768 (call-interactively 'markdown-insert-header-dwim)
769 (beginning-of-line)
770 (should (looking-at "^### ###$"))))
772 (ert-deftest test-markdown-insertion/header-dwim-prefix ()
773 "Test 'do what I mean' header insertion with prefix arguments."
774 (let ((tests (list '(nil . "## abc ##")
775 '(1 . "# abc #")
776 '(2 . "## abc ##")
777 '(3 . "### abc ###")
778 '(4 . "#### abc ####")
779 '(5 . "##### abc #####")
780 '(6 . "###### abc ######")
781 '((4) . "# abc #")
782 '((16) . "### abc ###"))))
783 (dolist (test tests)
784 (markdown-test-string "## atx\n\nabc"
785 (goto-char (point-max))
786 (let ((current-prefix-arg (car test)))
787 (call-interactively 'markdown-insert-header-dwim)
788 (should (string-equal
789 (buffer-substring (line-beginning-position) (line-end-position))
790 (cdr test))))))))
792 (ert-deftest test-markdown-insertion/header-setext-dwim-prefix ()
793 "Test 'do what I mean' header insertion with prefix arguments."
794 (let ((tests (list '(nil . "abc\n---")
795 '(1 . "abc\n===")
796 '(2 . "abc\n---")
797 '(3 . "### abc ###")
798 '(4 . "#### abc ####")
799 '(5 . "##### abc #####")
800 '(6 . "###### abc ######")
801 '((4) . "abc\n===")
802 '((16) . "### abc ###"))))
803 (dolist (test tests)
804 (markdown-test-string "atx\n---\n\nabc"
805 (goto-char (point-max))
806 (let ((current-prefix-arg (car test)))
807 (call-interactively 'markdown-insert-header-setext-dwim)
808 (should (string-equal
809 (buffer-substring (line-beginning-position) (line-end-position 2))
810 (cdr test))))))))
812 (ert-deftest test-markdown-insertion/header-setext-dwim ()
813 "Test 'do what I mean' header insertion with setext headers."
814 (markdown-test-string
815 "asdfasfasfdsadfasdfasdf\n======="
816 (goto-char 12)
817 (call-interactively 'markdown-insert-header-dwim)
818 (should (string-equal
819 (buffer-string)
820 "asdfasfasfdsadfasdfasdf\n======================="))))
822 (ert-deftest test-markdown-insertion/remove-header ()
823 "Test ATX and setext header."
824 (markdown-test-string
825 "# atx1\n\n## atx2 ##\n\nsetext1\n=======\n\nsetext2\n-------\n"
826 (should (equal (markdown-remove-header) (cons 1 5)))
827 (forward-line)
828 (should (not (markdown-remove-header)))
829 (forward-line)
830 (should (equal (markdown-remove-header) (cons 7 11)))
831 (forward-line)
832 (should (not (markdown-remove-header)))
833 (forward-line)
834 (should (equal (markdown-remove-header) (cons 13 20)))
835 (forward-line)
836 (should (not (markdown-remove-header)))
837 (forward-line)
838 (should (equal (markdown-remove-header) (cons 22 29)))
839 (should (string-equal (buffer-string)
840 "atx1\n\natx2\n\nsetext1\n\nsetext2\n"))))
842 (ert-deftest test-markdown-insertion/italic-unwrap-region ()
843 "A test of inserting italics with italic text in the region."
844 (markdown-test-string "*foo* bar *baz*"
845 (transient-mark-mode)
846 (push-mark (point) t t)
847 (end-of-line)
848 (markdown-insert-italic)
849 (should (string-equal (buffer-string) "*foo bar baz*"))))
851 (ert-deftest test-markdown-insertion/bold-unwrap-region ()
852 "A test of inserting bold with italic text in the region."
853 (markdown-test-string "*foo* **bar** *baz*"
854 (transient-mark-mode)
855 (push-mark (point) t t)
856 (end-of-line)
857 (markdown-insert-bold)
858 (should (string-equal (buffer-string) "***foo* bar *baz***"))))
860 (ert-deftest test-markdown-insertion/code-unwrap-region ()
861 "A test of inserting code with code already in the region."
862 (markdown-test-string "`foo` *bar* `baz`"
863 (transient-mark-mode)
864 (push-mark (point) t t)
865 (end-of-line)
866 (markdown-insert-code)
867 (should (string-equal (buffer-string) "`foo *bar* baz`"))))
869 (ert-deftest test-markdown-insertion/hr-order ()
870 "Test inserting horizontal rules."
871 (dotimes (n (length markdown-hr-strings))
872 (markdown-test-string ""
873 (let ((current-prefix-arg n))
874 (call-interactively 'markdown-insert-hr))
875 (should (string-equal (buffer-string) (nth (1- n) markdown-hr-strings))))))
877 (ert-deftest test-markdown-insertion/hr-prefix ()
878 "Test inserting horizontal rule with C-u prefix."
879 (markdown-test-string ""
880 (let ((current-prefix-arg '(4)))
881 (call-interactively 'markdown-insert-hr))
882 (should (string-equal (buffer-string) (car (last markdown-hr-strings))))))
884 (ert-deftest test-markdown-insertion/hr-bob ()
885 "Test inserting horizontal rule at beginning of buffer."
886 (markdown-test-string "one line\n"
887 (call-interactively 'markdown-insert-hr)
888 (should (string-equal (buffer-string)
889 (concat (car markdown-hr-strings)
890 "\n\none line\n")))))
892 (ert-deftest test-markdown-insertion/hr-eob ()
893 "Test inserting horizontal rule at end of buffer."
894 (markdown-test-string "one line\n"
895 (forward-line)
896 (call-interactively 'markdown-insert-hr)
897 (should (string-equal (buffer-string)
898 (concat "one line\n\n" (car markdown-hr-strings))))))
900 (ert-deftest test-markdown-insertion/hr-mob ()
901 "Test inserting horizontal rule in middle of buffer."
902 (markdown-test-string "one line\n"
903 (forward-word)
904 (let ((markdown-hr-strings '("----------")))
905 (call-interactively 'markdown-insert-hr)
906 (should (string-equal (buffer-string)
907 (concat "one\n\n" (car markdown-hr-strings)
908 "\n\n line\n"))))))
910 (ert-deftest test-markdown-insertion/pre-region-1 ()
911 "Test `markdown-pre-region'."
912 ;; Simple test as non-interactive command
913 (markdown-test-string "line one\nline two\n"
914 (markdown-pre-region (line-beginning-position) (line-end-position))
915 (should (string-equal (buffer-string) " line one\n\nline two\n")))
916 ;; Test removal of whitespace before and after region
917 (markdown-test-string "line one abc\nline two\n"
918 (markdown-pre-region 6 9)
919 (should (string-equal (buffer-string) "line\n\n one\n\nabc\nline two\n")))
920 ;; Simple test as interactive command
921 (markdown-test-string "line one\nline two\n"
922 (push-mark (point) t t)
923 (forward-line 2)
924 (call-interactively 'markdown-pre-region)
925 (should (string-equal (buffer-string) " line one\n line two\n\n"))))
927 (ert-deftest test-markdown-insertion/blockquote-region-1 ()
928 "Test `markdown-blockquote-region'."
929 ;; Simple test as non-interactive command
930 (markdown-test-string "line one\nline two\n"
931 (markdown-blockquote-region (line-beginning-position) (line-end-position))
932 (should (string-equal (buffer-string) "> line one\n\nline two\n")))
933 ;; Test removal of whitespace before and after region
934 (markdown-test-string "line one abc\nline two\n"
935 (markdown-blockquote-region 6 9)
936 (should (string-equal (buffer-string) "line\n\n> one\n\nabc\nline two\n")))
937 ;; Simple test as interactive command
938 (markdown-test-string "line one\nline two\n"
939 (push-mark (point) t t)
940 (forward-line 2)
941 (call-interactively 'markdown-blockquote-region)
942 (should (string-equal (buffer-string) "> line one\n> line two\n\n"))))
944 (ert-deftest test-markdown-insertion/pre-nested-lists ()
945 "Test `markdown-pre-indentation' and `markdown-insert-pre' with nested list."
946 (markdown-test-string "* item\n * item\n"
947 ;; before the first item
948 (should (string-equal (markdown-pre-indentation (point)) " "))
949 (markdown-insert-pre)
950 (beginning-of-line)
951 (should (markdown-prev-line-blank-p))
952 (should (looking-at "^ $"))
953 (should (markdown-next-line-blank-p))
954 ;; before the second item
955 (forward-line 3)
956 (should (string-equal (markdown-pre-indentation (point)) " "))
957 (markdown-insert-pre)
958 (beginning-of-line)
959 (should (markdown-prev-line-blank-p))
960 (should (looking-at "^ $"))
961 (should (markdown-next-line-blank-p))
962 ;; after the second item
963 (forward-line 3)
964 (should (string-equal (markdown-pre-indentation (point)) " "))
965 (markdown-insert-pre)
966 (beginning-of-line)
967 (should (markdown-prev-line-blank-p))
968 (should (looking-at "^ $"))
969 (should (markdown-next-line-blank-p))))
971 (ert-deftest test-markdown-insertion/pre-faux-list ()
972 "Test `markdown-pre-indentation' following a list-marker in a pre block."
973 (markdown-test-string " * pre block, not a list item\n"
974 (should (string-equal (markdown-pre-indentation (point-max)) " "))))
976 (ert-deftest test-markdown-insertion/blockquote-nested-lists ()
977 "Test blockquote insertion in a nested list context."
978 (markdown-test-string "* item\n * item\n"
979 ;; before the first item
980 (should (string-equal (markdown-blockquote-indentation (point)) ""))
981 (markdown-insert-blockquote)
982 (beginning-of-line)
983 (should (markdown-prev-line-blank-p))
984 (should (looking-at "^> $"))
985 (should (markdown-next-line-blank-p))
986 ;; before the second item
987 (forward-line 3)
988 (should (string-equal (markdown-blockquote-indentation (point)) " "))
989 (markdown-insert-blockquote)
990 (beginning-of-line)
991 (should (markdown-prev-line-blank-p))
992 (should (looking-at "^ > $"))
993 (should (markdown-next-line-blank-p))
994 ;; after the second item
995 (forward-line 3)
996 (should (string-equal (markdown-blockquote-indentation (point)) " "))
997 (markdown-insert-blockquote)
998 (beginning-of-line)
999 (should (markdown-prev-line-blank-p))
1000 (should (looking-at "^ > $"))
1001 (should (markdown-next-line-blank-p))))
1003 (ert-deftest test-markdown-insertion/blockquote-region-with-newline ()
1004 (markdown-test-string "a\n\nb\n"
1005 (markdown-blockquote-region 1 (point-max))
1006 (should (equal (buffer-string) "> a\n>\n> b\n\n"))))
1008 (ert-deftest test-markdown-insertion/empty-italic ()
1009 "Test `markdown-insert-italic' with no word at point and no region."
1010 (markdown-test-string ""
1011 (call-interactively 'markdown-insert-italic)
1012 (should (string-equal (buffer-string) "**"))
1013 (should (= (point) 2))))
1015 (ert-deftest test-markdown-insertion/empty-bold ()
1016 "Test `markdown-insert-bold' with no word at point and no region."
1017 (markdown-test-string ""
1018 (call-interactively 'markdown-insert-bold)
1019 (should (string-equal (buffer-string) "****"))
1020 (should (= (point) 3))))
1022 (ert-deftest test-markdown-insertion/uri ()
1023 "Test `markdown-insert-uri'."
1024 (markdown-test-string "http://jblevins.org/projects/markdown-mode/"
1025 (call-interactively 'markdown-insert-uri)
1026 (should (string-equal (buffer-string) "<http://jblevins.org/projects/markdown-mode/>"))
1027 (should (= (point) 2))
1028 (call-interactively 'markdown-insert-uri)
1029 (should (string-equal (buffer-string) "http://jblevins.org/projects/markdown-mode/"))
1030 (should (= (point) 1))
1031 (erase-buffer)
1032 (call-interactively 'markdown-insert-uri)
1033 (should (string-equal (buffer-string) "<>"))
1034 (should (= (point) 2))))
1036 (ert-deftest test-markdown-insertion/list-item-1 ()
1037 "Test `markdown-insert-list-item' when there is no existing list."
1038 (markdown-test-string "abc"
1039 (goto-char (point-max))
1040 (call-interactively 'markdown-insert-list-item)
1041 (should (string-equal (buffer-string) "abc\n * "))
1042 (should (= (point) 9))))
1044 (ert-deftest test-markdown-insertion/list-item-2 ()
1045 "Test `markdown-insert-list-item' following a list item, on the same line."
1046 (markdown-test-string " * foo"
1047 (goto-char (point-max))
1048 (call-interactively 'markdown-insert-list-item)
1049 (should (string-equal (buffer-string) " * foo\n * "))))
1051 (ert-deftest test-markdown-insertion/list-item-3 ()
1052 "Test `markdown-insert-list-item' following a list item, on the next line."
1053 (markdown-test-string "- foo\n"
1054 (goto-char (point-max))
1055 (call-interactively 'markdown-insert-list-item)
1056 (should (string-equal (buffer-string) "- foo\n- "))))
1058 (ert-deftest test-markdown-insertion/list-item-4 ()
1059 "Test `markdown-insert-list-item' following a list item, after a blank line."
1060 (markdown-test-string "- foo\n\n"
1061 (goto-char (point-max))
1062 (call-interactively 'markdown-insert-list-item)
1063 (should (string-equal (buffer-string) "- foo\n\n- "))))
1065 (ert-deftest test-markdown-insertion/list-item-5 ()
1066 "Test `markdown-insert-list-item' preceding a list item."
1067 (markdown-test-string "- foo\n"
1068 (goto-char (point-min))
1069 (call-interactively 'markdown-insert-list-item)
1070 (should (string-equal (buffer-string) "- \n- foo\n"))))
1072 (ert-deftest test-markdown-insertion/list-item-6 ()
1073 "Test `markdown-insert-list-item' preceding a list item and a blank line."
1074 (markdown-test-string "\n\n- foo\n"
1075 (goto-char (point-min))
1076 (call-interactively 'markdown-insert-list-item)
1077 (should (string-equal (buffer-string) "- \n\n- foo\n"))))
1079 (ert-deftest test-markdown-insertion/list-item-7 ()
1080 "Test `markdown-insert-list-item' in the middle of a list item."
1081 (markdown-test-string "- foo bar\n"
1082 (forward-word)
1083 (call-interactively 'markdown-insert-list-item)
1084 (should (string-equal (buffer-string) "- foo\n- bar\n"))))
1086 (ert-deftest test-markdown-insertion/list-item-8 ()
1087 "Test `markdown-insert-list-item' before marker, not at beginning of line."
1088 (markdown-test-string " - foo\n"
1089 (forward-char 2)
1090 (call-interactively 'markdown-insert-list-item)
1091 (should (string-equal (buffer-string) " - \n - foo\n"))))
1093 (ert-deftest test-markdown-insertion/list-item-9 ()
1094 "Test `markdown-insert-list-item' following an ordered list item."
1095 (markdown-test-string "6. foo"
1096 (goto-char (point-max))
1097 (call-interactively 'markdown-insert-list-item)
1098 (should (string-equal (buffer-string) "6. foo\n7. "))))
1100 (ert-deftest test-markdown-insertion/list-item-10 ()
1101 "Test `markdown-insert-list-item' after fancy list item, on the next line."
1102 (markdown-test-string "#. foo"
1103 (goto-char (point-max))
1104 (call-interactively 'markdown-insert-list-item)
1105 (should (string-equal (buffer-string) "#. foo\n#. "))))
1107 (ert-deftest test-markdown-insertion/list-item-11 ()
1108 "Test `markdown-insert-list-item' following a nested ordered list item."
1109 (markdown-test-string "6. foo\n 1. bar"
1110 (goto-char (point-max))
1111 (call-interactively 'markdown-insert-list-item)
1112 (should (string-equal (buffer-string) "6. foo\n 1. bar\n 2. "))))
1114 (ert-deftest test-markdown-insertion/list-item-12 ()
1115 "Test `markdown-insert-list-item' preceding an ordered list item."
1116 (markdown-test-string "\n1. foo\n2. bar"
1117 (goto-char (point-min))
1118 (call-interactively 'markdown-insert-list-item)
1119 (should (string-equal (buffer-string) "1. \n1. foo\n2. bar"))))
1121 (ert-deftest test-markdown-insertion/list-item-13 ()
1122 "Test `markdown-insert-list-item' preserves previous spacing in ordered list."
1123 (markdown-test-string "1. foo"
1124 (goto-char (point-max))
1125 (call-interactively 'markdown-insert-list-item)
1126 (should (string-equal (buffer-string) "1. foo\n2. "))))
1128 (ert-deftest test-markdown-insertion/list-item-14 ()
1129 "Test `markdown-insert-list-item' adjusts spacing for number width changes.
1130 For example, 9 to 10."
1131 (markdown-test-string "9. foo"
1132 (goto-char (point-max))
1133 (call-interactively 'markdown-insert-list-item)
1134 (should (string-equal (buffer-string) "9. foo\n10. "))))
1136 (ert-deftest test-markdown-insertion/list-item-15 ()
1137 "Test `markdown-insert-list-item' don't adjust for number width
1138 changes if no extra whitespace."
1139 (markdown-test-string "99. foo"
1140 (goto-char (point-max))
1141 (call-interactively 'markdown-insert-list-item)
1142 (should (string-equal (buffer-string) "99. foo\n100. "))))
1144 (ert-deftest test-markdown-insertion/list-item-16 ()
1145 "Test that `markdown-insert-list-item' spacing.
1146 Don't adjust spacing if tabs are used as whitespace."
1147 (markdown-test-string "9.\tfoo"
1148 (goto-char (point-max))
1149 (call-interactively 'markdown-insert-list-item)
1150 (should (string-equal (buffer-string) "9.\tfoo\n10.\t"))))
1152 (ert-deftest test-markdown-insertion/list-item-bound-keys ()
1153 "Test that `markdown-insert-list-item' is bound to M-RET and equivalents."
1154 (markdown-test-string "- foo"
1155 (goto-char (point-max))
1156 (execute-kbd-macro (read-kbd-macro "M-RET bar C-M-m baz"))
1157 (should (string-equal (buffer-string) "- foo\n- bar\n- baz"))
1158 (when (display-graphic-p)
1159 (execute-kbd-macro (read-kbd-macro "M-<return> quux"))
1160 (should (string-equal (buffer-string) "- foo\n- bar\n- baz\n- quux")))))
1162 (ert-deftest test-markdown-insertion/nested-list-marker ()
1163 "Test marker detection for `markdown-insert-list-item'."
1164 (markdown-test-string
1165 "1. A\n * AA\n 1. AAA"
1166 (goto-char (point-max))
1167 (let ((current-prefix-arg '(4)))
1168 (call-interactively 'markdown-insert-list-item))
1169 (should (eq (point) 36))
1170 (should (looking-back "\* "))
1171 (should (string-equal
1172 (buffer-string)
1173 "1. A\n * AA\n 1. AAA\n * "))
1174 (let ((current-prefix-arg '(4)))
1175 (call-interactively 'markdown-insert-list-item))
1176 (should (eq (point) 40))
1177 (should (looking-back "2\. "))
1178 (should (string-equal
1179 (buffer-string)
1180 "1. A\n * AA\n 1. AAA\n * \n2. "))
1181 (let ((current-prefix-arg '(4)))
1182 (call-interactively 'markdown-insert-list-item))
1183 (should (eq (point) 44))
1184 (should (looking-back "3\. "))
1185 (should (string-equal
1186 (buffer-string)
1187 "1. A\n * AA\n 1. AAA\n * \n2. \n3. "))))
1189 (ert-deftest test-markdown-insertion/with-markdown-ordered-list-enumeration ()
1190 "Test for `markdown-ordered-list-enumeration'.
1191 Detail: https://github.com/jrblevin/markdown-mode/issues"
1192 (markdown-test-string "1. A"
1193 (goto-char (point-max))
1194 (let ((markdown-ordered-list-enumeration t))
1195 (call-interactively 'markdown-insert-list-item)
1196 (let ((line (buffer-substring-no-properties
1197 (line-beginning-position) (line-end-position))))
1198 (should (string= line "2. "))))
1200 (markdown-test-string "1. A"
1201 (goto-char (point-max))
1202 (let ((markdown-ordered-list-enumeration nil))
1203 (call-interactively 'markdown-insert-list-item)
1204 (let ((line (buffer-substring-no-properties
1205 (line-beginning-position) (line-end-position))))
1206 (should (string= line "1. ")))))))
1208 (ert-deftest test-markdown-insertion/reference-link ()
1209 "Basic tests for `markdown-insert-reference-link'."
1210 ;; Test optional parameters (leave point after link)
1211 (markdown-test-string ""
1212 (markdown-insert-reference-link "abc" "1")
1213 (should (string-equal (buffer-string) "[abc][1]"))
1214 (should (= (point) 9)))
1215 ;; Full link without title (leave point after link)
1216 (markdown-test-string ""
1217 (markdown-insert-reference-link "link" "label" "http://jblevins.org/")
1218 (should (string-equal (buffer-string) "[link][label]\n\n[label]: http://jblevins.org/\n"))
1219 (should (= (point) 14)))
1220 ;; Full link without label or title (leave point after link)
1221 (markdown-test-string ""
1222 (markdown-insert-reference-link "link" "" "http://jblevins.org/")
1223 (should (string-equal (buffer-string) "[link][]\n\n[link]: http://jblevins.org/\n"))
1224 (should (= (point) 9)))
1225 ;; Link only with no label, URL, or title (leave point after link)
1226 (markdown-test-string ""
1227 (markdown-insert-reference-link "link" "")
1228 (should (string-equal (buffer-string) "[link][]"))
1229 (should (= (point) 9))))
1231 (ert-deftest test-markdown-insertion/reference-link-end ()
1232 "Basic reference link insertion test for 'end location."
1233 (let ((markdown-reference-location 'end))
1234 (markdown-test-string "first para\n\nsecond para\n"
1235 (end-of-line)
1236 (markdown-insert-reference-link "link" "" "http://jblevins.org/")
1237 (should (= (point) 19))
1238 (goto-char (point-min))
1239 (forward-line 4)
1240 (should (looking-at "\\[link\\]: http://jblevins.org/")))))
1242 (ert-deftest test-markdown-insertion/reference-link-immediately ()
1243 "Basic reference link insertion test for 'immediately location."
1244 (let ((markdown-reference-location 'immediately))
1245 (markdown-test-string "first para\n\nsecond para\n"
1246 (end-of-line)
1247 (markdown-insert-reference-link "link" "" "http://jblevins.org/")
1248 (should (= (point) 19))
1249 (goto-char (point-min))
1250 (forward-line 2)
1251 (should (looking-at "\\[link\\]: http://jblevins.org/")))))
1253 (ert-deftest test-markdown-insertion/reference-link-header ()
1254 "Basic reference link and definition insertion test for 'header location."
1255 (let ((markdown-reference-location 'header))
1256 (markdown-test-string "par one\n\npar two\n\n### header\n"
1257 (end-of-line)
1258 (markdown-insert-reference-link "link" "")
1259 (markdown-insert-reference-definition "link")
1260 (should (= (point) 35))
1261 (should (looking-back "\\[link\\]: " nil)))))
1263 (ert-deftest test-markdown-insertion/reference-definition-block ()
1264 "Test whitespace when inserting a reference definition among others"
1265 (let ((markdown-reference-location 'header))
1266 (markdown-test-string "text
1268 [1]: https://www.gnu.org/
1270 ### header
1272 (markdown-insert-reference-definition "2")
1273 (should (= (point) 38))
1274 (should (looking-back "https://www.gnu.org/\n\\[2\\]: " nil)))))
1276 (ert-deftest test-markdown-insertion/reference-link-before-file-locals ()
1277 "Test inserting a reference link before file-local variables."
1278 (markdown-test-string "
1280 <!-- Local Variables: -->
1281 <!-- mode: markdown -->
1282 <!-- End: -->
1284 (markdown-insert-reference-link "link" "" "http://jblevins.org/")
1285 (should (equal (buffer-substring-no-properties 1 (point-max))
1286 "[link][]
1288 \[link]: http://jblevins.org/
1290 <!-- Local Variables: -->
1291 <!-- mode: markdown -->
1292 <!-- End: -->
1294 (should (equal (point) 9))))
1296 (ert-deftest test-markdown-insertion/inline-to-reference-link ()
1297 "Inline link to reference link conversion with tab completion."
1298 (markdown-test-string "[text](http://jblevins.org/ \"title\")"
1299 (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"))
1300 (should (string-equal (buffer-string) "[text][1]\n\n[1]: http://jblevins.org/ \"title\"\n"))))
1302 (ert-deftest test-markdown-insertion/inline-to-reference-link-2 ()
1303 "Inline link to reference link conversion with existing reference links."
1304 (markdown-test-string "[text](http://jblevins.org/ \"title\")\n\n[1]: https://www.gnu.org"
1305 (execute-kbd-macro (read-kbd-macro "M-x markdown-insert-link RET M-DEL M-DEL M-DEL [1] RET RET"))
1306 (should (string-equal (buffer-string) "[text][1]\n\n[1]: https://www.gnu.org"))))
1308 (ert-deftest test-markdown-insertion/inline-link-angle-url-at-point ()
1309 "Test `markdown-insert-link' with angle URL at point."
1310 (markdown-test-string "<https://www.gnu.org/>"
1311 (execute-kbd-macro (read-kbd-macro "M-x markdown-insert-link RET RET GNU RET RET"))
1312 (should (string-equal (buffer-string) "[GNU](https://www.gnu.org/)"))))
1314 (ert-deftest test-markdown-insertion/inline-link-plain-url-at-point ()
1315 "Test `markdown-insert-link' with plain URL at point."
1316 (markdown-test-string "https://www.gnu.org/"
1317 (execute-kbd-macro (read-kbd-macro "M-x markdown-insert-link RET RET GNU RET RET"))
1318 (should (string-equal (buffer-string) "[GNU](https://www.gnu.org/)"))))
1320 (ert-deftest test-markdown-insertion/inline-link-reference-link-at-point ()
1321 "Test `markdown-insert-link' with reference link at point."
1322 (markdown-test-string ""
1323 (markdown-insert-reference-link "link" "label" "http://jblevins.org/")
1324 (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"))
1325 (should (string-equal (buffer-substring 1 28) "[link](http://example.com/)"))
1326 (should (= (point) 28))))
1328 (ert-deftest test-markdown-insertion/inline-link-active-region ()
1329 "Test `markdown-insert-link' with active region."
1330 (markdown-test-string "abc def ghi"
1331 (let ((tmm-orig transient-mark-mode))
1332 (transient-mark-mode 1)
1333 (push-mark (point) t t)
1334 (forward-word 2)
1335 (execute-kbd-macro (read-kbd-macro "M-x markdown-insert-link RET http://example.com/ RET RET RET"))
1336 (should (string-equal (buffer-string) "[abc def](http://example.com/) ghi"))
1337 (should (= (point) 31))
1338 (transient-mark-mode tmm-orig))))
1340 (ert-deftest test-markdown-insertion/disable-tooltip-prompt ()
1341 "Test `markdown-insert-link' with
1342 `markdown-disable-tooltip-prompt' option t."
1343 (markdown-test-string "<https://www.gnu.org/>"
1344 (let ((markdown-disable-tooltip-prompt t))
1345 (execute-kbd-macro (read-kbd-macro "M-x markdown-insert-link RET RET GNU RET"))
1346 (should (string-equal (buffer-string) "[GNU](https://www.gnu.org/)")))))
1348 (ert-deftest test-markdown-insertion/link-make-text-function ()
1349 "Test `markdown-insert-link' with custom
1350 `markdown-link-make-text-function'."
1351 (markdown-test-string "<https://www.gnu.org/>"
1352 (let ((markdown-link-make-text-function (lambda (url) (ignore url) "GNU")))
1353 (execute-kbd-macro (read-kbd-macro "M-x markdown-insert-link RET RET RET RET"))
1354 (should (string-equal (buffer-string) "[GNU](https://www.gnu.org/)")))))
1356 (ert-deftest test-markdown-insertion/foldable-block ()
1357 "Test `markdown-insert-foldable-block'."
1358 (markdown-test-string ""
1359 (call-interactively 'markdown-insert-foldable-block)
1360 (should (string= (buffer-string) "<details>\n<summary> </summary>\n</details>"))
1361 (should (looking-back "<summary>")))
1363 (markdown-test-string "foo"
1364 (push-mark (point) t t)
1365 (end-of-line)
1366 (should (use-region-p))
1367 (call-interactively 'markdown-insert-foldable-block)
1368 (should (string= (buffer-string) "<details>\n<summary> </summary>\nfoo\n</details>"))
1369 (should (looking-back "<summary>"))))
1371 ;;; Footnote tests:
1373 (ert-deftest test-markdown-footnote/basic-end ()
1374 "Basic footnote insertion and deletion tests for 'end location."
1375 (let ((markdown-footnote-location 'end))
1376 (markdown-test-string "first line\nsecond line\n"
1377 ;; new buffer with no footnotes
1378 (should (= markdown-footnote-counter 0))
1379 ;; footnote insertion
1380 (end-of-line)
1381 (markdown-insert-footnote)
1382 (should (= (point) 35))
1383 (should (= markdown-footnote-counter 1))
1384 (should (looking-back "\\[^1\\]: " nil))
1385 ;; kill with point in footnote definition
1386 (insert "footnote text")
1387 (let (kill-ring)
1388 (markdown-footnote-kill))
1389 (should (= (point) 24))
1390 (should (bolp))
1391 (should (string-equal (buffer-string) "first line\nsecond line\n"))
1392 ;; insertion, counter should increment
1393 (goto-char (point-min))
1394 (end-of-line)
1395 (markdown-insert-footnote)
1396 (should (= (point) 35))
1397 (should (= markdown-footnote-counter 2))
1398 (should (looking-back "\\[^2\\]: " nil))
1399 (insert "footnote text")
1400 ;; return to marker
1401 (markdown-footnote-return)
1402 (should (= (point) 15))
1403 (should (looking-back "\\[^2\\]" nil))
1404 ;; kill with point at marker
1405 (let (kill-ring)
1406 (markdown-footnote-kill))
1407 (should (= (point) 11))
1408 (should (eolp))
1409 (should (string-equal (buffer-string) "first line\nsecond line\n")))))
1411 (ert-deftest test-markdown-footnote/basic-immediately ()
1412 "Basic footnote insertion and deletion tests for 'immediately location."
1413 (let ((markdown-footnote-location 'immediately))
1414 (markdown-test-string "first paragraph\n\nsecond paragraph\n"
1415 ;; new buffer with no footnotes
1416 (should (= markdown-footnote-counter 0))
1417 ;; footnote insertion
1418 (end-of-line)
1419 (markdown-insert-footnote)
1420 (should (= (point) 28))
1421 (should (= markdown-footnote-counter 1))
1422 (should (looking-back "\\[^1\\]: " nil))
1423 ;; kill with point in footnote definition
1424 (insert "footnote text")
1425 (let (kill-ring)
1426 (markdown-footnote-kill))
1427 (should (= (point) 18))
1428 (should (bolp))
1429 (should (string-equal (buffer-string)
1430 "first paragraph\n\nsecond paragraph\n")))))
1432 (ert-deftest test-markdown-footnote/basic-header ()
1433 "Basic footnote insertion and deletion tests for 'header location."
1434 (let ((markdown-footnote-location 'header))
1435 (markdown-test-string "par one\n\npar two\n\n### header\n"
1436 ;; new buffer with no footnotes
1437 (should (= markdown-footnote-counter 0))
1438 ;; footnote insertion
1439 (end-of-line)
1440 (markdown-insert-footnote)
1441 (should (= (point) 29))
1442 (should (= markdown-footnote-counter 1))
1443 (should (looking-back "\\[^1\\]: " nil))
1444 ;; kill with point in footnote definition
1445 (insert "footnote text")
1446 (let (kill-ring)
1447 (markdown-footnote-kill))
1448 (should (= (point) 19))
1449 (should (bolp))
1450 (should (string-equal (buffer-string)
1451 "par one\n\npar two\n\n### header\n"))
1452 ;; insertion, counter should increment
1453 (goto-char (point-min))
1454 (end-of-line)
1455 (markdown-insert-footnote)
1456 (should (= (point) 29))
1457 (should (= markdown-footnote-counter 2))
1458 (should (looking-back "\\[^2\\]: " nil))
1459 (insert "footnote text")
1460 ;; return to marker
1461 (markdown-footnote-return)
1462 (should (= (point) 12))
1463 (should (looking-back "\\[^2\\]" nil))
1464 ;; kill with point at marker
1465 (let (kill-ring)
1466 (markdown-footnote-kill))
1467 (should (= (point) 8))
1468 (should (eolp))
1469 (should (string-equal (buffer-string)
1470 "par one\n\npar two\n\n### header\n")))))
1472 (ert-deftest test-markdown-footnote/basic-subtree ()
1473 "Basic footnote insertion and deletion tests for 'subtree location."
1474 (let ((markdown-footnote-location 'subtree))
1475 (markdown-test-string "# h1\n\nfoo\n\n## h2\n\nbar\n"
1476 ;; new buffer with no footnotes
1477 (should (= markdown-footnote-counter 0))
1478 ;; footnote insertion
1479 (forward-line 2)
1480 (end-of-line)
1481 (markdown-insert-footnote)
1482 (should (= (point) 34))
1483 (should (= markdown-footnote-counter 1))
1484 (should (looking-back "\\[^1\\]: " nil)))))
1486 (ert-deftest test-markdown-footnote/kill-empty-text ()
1487 "Test killing a footnote with marker but no text."
1488 (markdown-test-string "no text[^1]\n\n[^1]: \n"
1489 (end-of-line)
1490 (markdown-footnote-goto-text)
1491 (should (looking-back "\\[^1\\]: " nil))
1492 (let (kill-ring)
1493 (markdown-footnote-kill))
1494 (should (string-equal (buffer-string) "no text\n"))))
1496 (ert-deftest test-markdown-footnote/kill-empty-after ()
1497 "Test killing an empty footnote after one with text (previously killed the
1498 footnote with text above)."
1499 (markdown-test-string "[^with-text][^no-text]\n\n[^with-text]: Text\n[^no-text]:"
1500 (let (kill-ring)
1501 (forward-line 3)
1502 (should (looking-at "\\[\\^no-text\\]:$"))
1503 (markdown-footnote-kill)
1504 (should (string-equal (current-kill 0) "")))))
1506 (ert-deftest test-markdown-footnote/kill-hanging-paras ()
1507 "Test killing a footnote where block text starts after the label (previously
1508 killed the footnote above)."
1509 (markdown-test-string "[^1][^2]\n\n[^1]: Foo\n\n[^2]:\n Text\n\n More text\n\n\nNot indented"
1510 (let (kill-ring)
1511 (forward-line 4)
1512 (should (looking-at "\\[\\^2\\]:$"))
1513 (markdown-footnote-kill)
1514 ;; We want to include the leading space on hanging footnote paragraphs,
1515 ;; even if a hanging paragraph is the first item in the footnote.
1516 (should (string-equal (current-kill 0) "Text\n\n More text\n")))))
1518 (ert-deftest test-markdown-footnote/text-positions-buffer-top ()
1519 "Test markdown-footnote-text-positions on footnote adjacent to buffer top
1520 (was infinite loop)."
1521 (markdown-test-string "[^label]: text\n more text"
1522 (should (equal (markdown-footnote-text-positions) (list "^label" 1 29)))))
1524 (ert-deftest test-markdown-footnote/text-positions-buffer-top-one-line ()
1525 "Test markdown-footnote-text-positions on one-line footnote adjacent to
1526 buffer top (failed to find positions)."
1527 (markdown-test-string "[^label]: text\n"
1528 (should (equal (markdown-footnote-text-positions) (list "^label" 1 16)))))
1530 (ert-deftest test-markdown-footnote/text-positions-buffer-top-not-footnote ()
1531 "Test markdown-footnote-text-positions on plain paragraph adjacent to buffer
1532 top (was infinite loop)."
1533 (markdown-test-string "text\n more text\n"
1534 (should (eq (markdown-footnote-text-positions) nil))))
1536 (ert-deftest test-markdown-footnote/text-positions-buffer-bottom ()
1537 "Test markdown-footnote-text-positions on footnote adjacent to buffer bottom
1538 (was infinite loop)."
1539 (markdown-test-string "\n[^label]: text\n more text"
1540 (forward-line 1)
1541 (should (equal (markdown-footnote-text-positions) (list "^label" 2 30)))))
1543 (ert-deftest test-markdown-footnote/kill-adjacent-footnote ()
1544 "Test killing a footnote adjacent to other one-line footnotes (previously
1545 killed the wrong one)."
1546 (markdown-test-string "Text[^1] with[^2] footnotes[^3]\n\n[^1]: foo\n[^2]: bar\n[^3]: baz"
1547 (let (kill-ring)
1548 (forward-line 3)
1549 (should (looking-at "\\[\\^2\\]: bar"))
1550 (markdown-footnote-kill)
1551 (should (string-equal (current-kill 0) "bar\n")))))
1553 (ert-deftest test-markdown-footnote/kill-adjacent-markers ()
1554 "Test killing a footnote where the labels are adjacent (previously, the wrong
1555 footnote would be killed because the attempt to jump to the marker would jump to
1556 the opening bracket of [^2], and then subsequent functions would kill [^2])."
1557 (markdown-test-string "Text with footnotes[^1][^2]\n\n[^1]: foo\n\n[^2]: bar\n"
1558 (let (kill-ring)
1559 (forward-line 2)
1560 (should (looking-at "\\[\\^1\\]: foo"))
1561 (markdown-footnote-kill)
1562 (should (string-equal (current-kill 0) "foo\n")))))
1564 (ert-deftest test-markdown-do/jump-wiki-link ()
1565 "Test `markdown-do' jumps to wiki links"
1566 (with-current-buffer (find-file-noselect "wiki/pr666/jump_wiki_link.md")
1567 (let ((markdown-enable-wiki-links t))
1568 (goto-char 3)
1569 (markdown-do)
1570 (should (string= (buffer-name) "Foo.md")))))
1572 (ert-deftest test-markdown-do/jump-link ()
1573 "Test `markdown-do' jumps to markdown links"
1574 (markdown-test-string "[bar](https://duckduckgo.com)"
1575 (let* ((opened-url nil)
1576 (browse-url-browser-function
1577 (lambda (url &rest _args) (setq opened-url url))))
1578 (goto-char 3)
1579 (markdown-do)
1580 (should (string= opened-url "https://duckduckgo.com")))))
1582 (ert-deftest test-markdown-do/wiki-link-in-table ()
1583 "Test `markdown-do' jumps to markdown links"
1584 (with-current-buffer (find-file-noselect "wiki/pr666/wiki_link_in_table.md")
1585 (let ((markdown-enable-wiki-links t))
1586 ;; alignment
1587 (markdown-do)
1588 (should (string= (buffer-string) "| [[Foo]] |\n"))
1590 (forward-char 4)
1592 ;; wiki link
1593 (markdown-do)
1594 (should (string= (buffer-name) "Foo.md")))))
1596 (ert-deftest test-markdown-footnote-reference/jump ()
1597 "Test `markdown-do' for footnotes and reference links."
1598 (markdown-test-string
1599 "body[^1], [link 1][ref],
1600 [link 2][ref]
1602 [^1]: footnote
1604 [ref]: https://duckduckgo.com/"
1605 (goto-char 5) ; start of [^1]
1606 (markdown-do) ; markdown-footnote-goto-text
1607 (should (looking-at "footnote"))
1608 (markdown-do) ; markdown-footnote-return
1609 (should (= (point) 9)) ; just after [^1]
1610 (markdown-next-link) ; beginning of [link 1][]
1611 (markdown-do)
1612 (should (looking-at "https://duckduckgo.com/"))
1613 (should (equal (markdown-reference-find-links "ref")
1614 (list (list "link 2" 26 2) (list "link 1" 11 1))))
1615 (markdown-do) ; opens a reference link buffer
1616 (should (string= (buffer-string) "Links using reference ref:\n\nlink 1 (line 1)\nlink 2 (line 2)\n"))
1617 (should (looking-at "link 1")) ; in reference link popop buffer
1618 (execute-kbd-macro (read-kbd-macro "RET")) ; jump to "link 1"
1619 (should (looking-at "\\[link 1\\]")) ; back in main buffer
1620 (should (= (point) 11))))
1622 ;;; Element removal tests:
1624 (ert-deftest test-markdown-kill/simple ()
1625 "Simple tests for `markdown-kill-thing-at-point'."
1626 (let ((kill-ring nil)
1627 (tests (list '("`foo`" . "foo")
1628 '("## foo ##" . "foo")
1629 '("## foo" . "foo")
1630 '("foo\n---" . "foo")
1631 '("foo\n===" . "foo")
1632 '("* * * * *" . "* * * * *")
1633 '("[foo](http://bar.com/)" . "foo")
1634 '("![foo](http://bar.com/)" . "foo")
1635 '("[foo][bar]" . "foo")
1636 '("![foo][bar]" . "foo")
1637 '("<http://foo.com/>" . "http://foo.com/")
1638 '("<foo@bar.com>" . "foo@bar.com")
1639 '("**foo**" . "foo")
1640 '("__foo__" . "foo")
1641 '("*foo*" . "foo")
1642 '("_foo_" . "foo")
1643 '(" [foo]: http://bar.com/" . "http://bar.com/")
1644 '(" [foo]: http://bar.com/ \"title\"" . "http://bar.com/")
1645 '("foo[^bar]\n\n[^bar]: baz" . "baz")
1646 '("[^bar]: baz" . "baz")
1647 '(" * foo\n bar" . " * foo\n bar"))))
1648 (dolist (test tests)
1649 ;; Load test string (the car), move to end of first line, kill
1650 ;; thing at point, and then verify that the kill ring contains cdr.
1651 (markdown-test-string (car test)
1652 (end-of-line)
1653 (forward-char -1)
1654 (call-interactively 'markdown-kill-thing-at-point)
1655 (should (string-equal (current-kill 0) (cdr test)))))))
1657 (ert-deftest test-markdown-kill/footnote-text ()
1658 "Test killing a footnote with point at footnote text."
1659 (markdown-test-string "some text[^1]\n\n[^1]: footnote\n"
1660 (end-of-line)
1661 (markdown-footnote-goto-text)
1662 (let (kill-ring)
1663 (markdown-footnote-kill))
1664 (should (string-equal (buffer-string) "some text\n"))))
1666 (ert-deftest test-markdown-kill/code ()
1667 "Test killing with code regex.."
1668 (let ((kill-ring nil))
1669 (markdown-test-string "Lorem `ipsum` dolor `sit` `amet`."
1670 (goto-char 22) ; position point at s in `sit`
1671 (call-interactively 'markdown-kill-thing-at-point)
1672 (should (string-equal (current-kill 0) "sit")))))
1674 ;;; Completion:
1676 (ert-deftest test-markdown-complete/atx-header-incomplete ()
1677 "Test `markdown-incomplete-atx-p'."
1678 (markdown-test-string "### ###"
1679 (should (looking-at markdown-regex-header-atx))
1680 (should-not (markdown-incomplete-atx-p)))
1681 (markdown-test-string "###abc###"
1682 (should-not (looking-at markdown-regex-header-atx)))
1683 (markdown-test-string "### ###"
1684 (should (looking-at markdown-regex-header-atx))
1685 (should (markdown-incomplete-atx-p))))
1687 (ert-deftest test-markdown-complete/atx-header ()
1688 "Test `markdown-complete' for atx headers."
1689 (markdown-test-string "##### test"
1690 (call-interactively 'markdown-complete)
1691 (should (string-equal (buffer-string) "##### test #####"))))
1693 (ert-deftest test-markdown-complete/setext-header-incomplete ()
1694 "Test `markdown-incomplete-setext-p'."
1695 (markdown-test-string "abc\n===\n"
1696 (should (looking-at markdown-regex-header-setext))
1697 (should-not (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 (markdown-test-string "abc\n====\n"
1702 (should (looking-at markdown-regex-header-setext))
1703 (should (markdown-incomplete-setext-p))))
1705 (ert-deftest test-markdown-complete/setext-header ()
1706 "Test `markdown-complete' for setext headers."
1707 (markdown-test-string "test \n=="
1708 (call-interactively 'markdown-complete)
1709 (should (string-equal (buffer-string) "test\n===="))))
1711 (ert-deftest test-markdown-complete/hr-incomplete ()
1712 "Test `markdown-incomplete-hr-p'."
1713 (dolist (i (number-sequence 0 (1- (length markdown-hr-strings))))
1714 (markdown-test-string (nth i markdown-hr-strings)
1715 (should (looking-at markdown-regex-hr))
1716 (should-not (markdown-incomplete-hr-p))
1717 (should-error (call-interactively 'markdown-complete)))))
1719 (ert-deftest test-markdown-complete/hr ()
1720 "Test completion via `markdown-complete' for horizontal rules."
1721 (markdown-test-string "- - - - -"
1722 (call-interactively 'markdown-complete)
1723 (should (string-equal (buffer-string) (car markdown-hr-strings)))))
1725 (ert-deftest test-markdown-complete/buffer-setext-2 ()
1726 "Test `markdown-complete-buffer' for level two setext heading."
1727 ;; Ensure markdown-complete-buffer doesn't mistake this for a horizontal rule
1728 (markdown-test-string "Subheading\n--\n"
1729 (call-interactively 'markdown-complete-buffer)
1730 (should (string-equal (buffer-string) "Subheading\n----------\n\n")))
1731 (markdown-test-string "Abc\n--\n\nDef\n--\n"
1732 (call-interactively 'markdown-complete-buffer)
1733 (should (string-equal (buffer-string) "Abc\n---\n\nDef\n---\n\n"))))
1735 ;;; Promotion and demotion tests:
1737 (ert-deftest test-markdown-promote/atx-header ()
1738 "Test `markdown-promote' for atx headers."
1739 (markdown-test-string "###### test ######"
1740 (markdown-promote)
1741 (should (string-equal (buffer-string) "##### test #####"))
1742 (markdown-promote)
1743 (should (string-equal (buffer-string) "#### test ####"))
1744 (markdown-promote)
1745 (should (string-equal (buffer-string) "### test ###"))
1746 (markdown-promote)
1747 (should (string-equal (buffer-string) "## test ##"))
1748 (markdown-promote)
1749 (should (string-equal (buffer-string) "# test #"))))
1751 (ert-deftest test-markdown-demote/atx-header ()
1752 "Test `markdown-demote' for atx headers."
1753 (markdown-test-string "# test #"
1754 (markdown-demote)
1755 (should (string-equal (buffer-string) "## test ##"))
1756 (markdown-demote)
1757 (should (string-equal (buffer-string) "### test ###"))
1758 (markdown-demote)
1759 (should (string-equal (buffer-string) "#### test ####"))
1760 (markdown-demote)
1761 (should (string-equal (buffer-string) "##### test #####"))
1762 (markdown-demote)
1763 (should (string-equal (buffer-string) "###### test ######"))))
1765 (ert-deftest test-markdown-promote/setext-header ()
1766 "Test `markdown-promote' for setext headers."
1767 (markdown-test-string "test\n----"
1768 (markdown-promote)
1769 (should (string-equal (buffer-string) "test\n===="))))
1771 (ert-deftest test-markdown-demote/setext-header ()
1772 "Test `markdown-demote' for setext headers."
1773 (markdown-test-string "test\n===="
1774 (markdown-demote)
1775 (should (string-equal (buffer-string) "test\n----"))
1776 (markdown-demote)
1777 (should (string-equal (buffer-string) "### test ###"))
1778 (markdown-demote)
1779 (should (string-equal (buffer-string) "#### test ####"))
1780 (markdown-demote)
1781 (should (string-equal (buffer-string) "##### test #####"))
1782 (markdown-demote)
1783 (should (string-equal (buffer-string) "###### test ######"))))
1785 (ert-deftest test-markdown-promote/hr ()
1786 "Test `markdown-promote' for horizontal rules."
1787 (markdown-test-string (car (reverse markdown-hr-strings))
1788 (dolist (n (number-sequence 4 0 -1))
1789 (markdown-promote)
1790 (should (string-equal (buffer-string) (nth n markdown-hr-strings))))))
1792 (ert-deftest test-markdown-demote/hr ()
1793 "Test `markdown-demote' for horizontal rules."
1794 (markdown-test-string (car markdown-hr-strings)
1795 (dolist (n (number-sequence 1 5))
1796 (markdown-demote)
1797 (should (string-equal (buffer-string) (nth n markdown-hr-strings))))))
1799 (ert-deftest test-markdown-promote/bold ()
1800 "Test `markdown-promote' for bold markup."
1801 (markdown-test-string "__bold__"
1802 (call-interactively 'markdown-promote)
1803 (should (string-equal (buffer-string) "**bold**"))))
1805 (ert-deftest test-markdown-demote/bold ()
1806 "Test `markdown-demote' for bold markup."
1807 (markdown-test-string "**bold**"
1808 (call-interactively 'markdown-promote)
1809 (should (string-equal (buffer-string) "__bold__"))))
1811 (ert-deftest test-markdown-promote/italic ()
1812 "Test `markdown-promote' for italic markup."
1813 (markdown-test-string "_italic_"
1814 (call-interactively 'markdown-promote)
1815 (should (string-equal (buffer-string) "*italic*"))))
1817 (ert-deftest test-markdown-demote/italic ()
1818 "Test `markdown-demote' for italic markup."
1819 (markdown-test-string "*italic*"
1820 (call-interactively 'markdown-promote)
1821 (should (string-equal (buffer-string) "_italic_"))))
1823 ;;; Subtree editing tests:
1825 (ert-deftest test-markdown-subtree/promote ()
1826 "Test `markdown-promote-subtree'."
1827 (markdown-test-string "# h1 #\n\n## h2 ##\n\n### h3 ###\n\n## h2 ##\n\n# h1 #\n"
1828 ;; The first h1 should get promoted away.
1829 ;; The second h1 should not be promoted.
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 ;; Second call should do nothing since point is no longer at a heading.
1833 (markdown-promote-subtree)
1834 (should (string-equal (buffer-string) "h1\n\n# h2 #\n\n## h3 ##\n\n# h2 #\n\n# h1 #\n"))
1835 ;; Move to h2 and promote again.
1836 (forward-line 2)
1837 (markdown-promote-subtree)
1838 (should (string-equal (buffer-string) "h1\n\nh2\n\n# h3 #\n\n# h2 #\n\n# h1 #\n"))))
1840 (ert-deftest test-markdown-subtree/promote-single-section ()
1841 "Test `markdown-promote-subtree' on a single or last section.
1842 Should not cause an infinite loop."
1843 (markdown-test-string "foo\n\n## h2 ##\n\nbar\n"
1844 ;; The h2 should get promoted to h1 away.
1845 (markdown-test-goto-heading "h2")
1846 (markdown-promote-subtree)
1847 (should (string-equal (buffer-string) "foo\n\n# h2 #\n\nbar\n"))))
1849 (ert-deftest test-markdown-subtree/demote ()
1850 "Test `markdown-demote-subtree'."
1851 (markdown-test-string "# h1 #\n\n## h2 ##\n\n### h3 ###\n\n## h2 ##\n\n# h1 #\n"
1852 ;; The second h1 should not be demoted
1853 (markdown-demote-subtree)
1854 (should (string-equal (buffer-string) "## h1 ##\n\n### h2 ###\n\n#### h3 ####\n\n### h2 ###\n\n# h1 #\n"))
1855 (markdown-demote-subtree)
1856 (should (string-equal (buffer-string) "### h1 ###\n\n#### h2 ####\n\n##### h3 #####\n\n#### h2 ####\n\n# h1 #\n"))
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 ;; Stop demoting at level six
1860 (markdown-demote-subtree)
1861 (should (string-equal (buffer-string) "##### h1 #####\n\n###### h2 ######\n\n###### h3 ######\n\n###### h2 ######\n\n# h1 #\n"))
1862 (markdown-demote-subtree)
1863 (should (string-equal (buffer-string) "###### h1 ######\n\n###### h2 ######\n\n###### h3 ######\n\n###### h2 ######\n\n# h1 #\n"))))
1865 (ert-deftest test-markdown-subtree/move-up ()
1866 "Test `markdown-move-subtree-up'."
1867 ;; Note that prior to Emacs 24.5, this does not work for the last subtree in
1868 ;; the buffer due to Emacs bug #19102:
1869 ;; https://debbugs.gnu.org/cgi/bugreport.cgi?bug=19102
1870 ;; https://github.com/emacs-mirror/emacs/commit/b3910f
1871 ;; That also corrects the type of the "Cannot move past superior level" error
1872 ;; from 'error to 'user-error.
1873 (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"
1874 (re-search-forward "^# 2")
1875 (markdown-move-subtree-up)
1876 (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"))
1877 ;; Second attempt should fail, leaving buffer unchanged.
1878 ;; (This way of asserting the contents of the error
1879 ;; message is a bit convoluted and more fragile than
1880 ;; ideal. But prior to Emacs 24.5, the type of this
1881 ;; error is just 'error, and a bare "should-error" is
1882 ;; really overly broad.)
1883 (should (string-equal
1884 "Cannot move past superior level"
1885 (cl-second (should-error (markdown-move-subtree-up)))))))
1887 (ert-deftest test-markdown-subtree/move-down ()
1888 "Test `markdown-move-subtree-down'."
1889 (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"
1890 (re-search-forward "^## 1\.1")
1891 (markdown-move-subtree-down)
1892 (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"))))
1894 (ert-deftest test-markdown-subtree/mark ()
1895 "Test `markdown-mark-subtree'."
1896 (markdown-test-file "outline.text"
1897 (markdown-next-visible-heading 1)
1898 (should-not mark-active)
1899 (markdown-mark-subtree)
1900 (should (= (point) 19))
1901 (should (= (mark) 349))
1902 (should mark-active)
1903 (deactivate-mark)
1904 (should-not mark-active)
1905 (markdown-forward-same-level 1)
1906 (markdown-mark-subtree)
1907 (should (= (point) 351))
1908 (should (= (mark) 515))
1909 (should mark-active)))
1911 (ert-deftest test-markdown-subtree/narrow ()
1912 "Test `markdown-narrow-to-subtree'."
1913 (markdown-test-file "outline.text"
1914 (markdown-next-visible-heading 1)
1915 (markdown-forward-same-level 1)
1916 (widen)
1917 (should (= (point-min) 1))
1918 (should (= (point-max) 553))
1919 (markdown-narrow-to-subtree)
1920 (should (= (point-min) 351))
1921 (should (= (point-max) 515))))
1923 ;;; Cycling:
1925 (ert-deftest test-markdown-cycle/atx-header ()
1926 "Test `markdown-demote' cycling for atx headers."
1927 (markdown-test-string "# test"
1928 (call-interactively 'markdown-demote)
1929 (should (string-equal (buffer-string) "## test ##"))
1930 (call-interactively 'markdown-demote)
1931 (should (string-equal (buffer-string) "### test ###"))
1932 (call-interactively 'markdown-demote)
1933 (should (string-equal (buffer-string) "#### test ####"))
1934 (call-interactively 'markdown-demote)
1935 (should (string-equal (buffer-string) "##### test #####"))
1936 (call-interactively 'markdown-demote)
1937 (should (string-equal (buffer-string) "###### test ######"))
1938 (call-interactively 'markdown-demote)
1939 (should (string-equal (buffer-string) "###### test ######"))))
1941 (ert-deftest test-markdown-cycle/setext-header ()
1942 "Test `markdown-demote' cycling for setext headers."
1943 (markdown-test-string "test\n===="
1944 (call-interactively 'markdown-demote)
1945 (should (string-equal (buffer-string) "test\n----"))
1946 (call-interactively 'markdown-demote)
1947 (should (string-equal (buffer-string) "### test ###"))
1948 (call-interactively 'markdown-demote)
1949 (should (string-equal (buffer-string) "#### test ####"))
1950 (call-interactively 'markdown-demote)
1951 (should (string-equal (buffer-string) "##### test #####"))
1952 (call-interactively 'markdown-demote)
1953 (should (string-equal (buffer-string) "###### test ######"))
1954 (call-interactively 'markdown-demote)
1955 (should (string-equal (buffer-string) "###### test ######"))))
1957 (ert-deftest test-markdown-cycle/hr ()
1958 "Test cycling of horizontal rules."
1959 ;; Cycle using markdown-demote
1960 (markdown-test-string (car markdown-hr-strings)
1961 (dolist (n (number-sequence 1 5))
1962 (call-interactively 'markdown-demote)
1963 (should (string-equal (buffer-string) (nth n markdown-hr-strings))))
1964 (call-interactively 'markdown-demote)
1965 (should (string-equal (buffer-string) (car markdown-hr-strings))))
1966 ;; Cycle using markdown-promote
1967 (markdown-test-string (car (reverse markdown-hr-strings))
1968 (dolist (n (number-sequence 4 0 -1))
1969 (call-interactively 'markdown-promote)
1970 (should (string-equal (buffer-string) (nth n markdown-hr-strings))))
1971 (call-interactively 'markdown-promote)
1972 (should (string-equal (buffer-string) (car (reverse markdown-hr-strings))))))
1974 (ert-deftest test-markdown-cycle/bold ()
1975 "Test cycling of bold markup."
1976 (markdown-test-string "**bold**"
1977 (call-interactively 'markdown-demote)
1978 (should (string-equal (buffer-string) "__bold__"))
1979 (call-interactively 'markdown-demote)
1980 (should (string-equal (buffer-string) "**bold**"))))
1982 (ert-deftest test-markdown-cycle/italic ()
1983 "Test cycling of italic markup."
1984 (markdown-test-string "*italic*"
1985 (call-interactively 'markdown-demote)
1986 (should (string-equal (buffer-string) "_italic_"))
1987 (call-interactively 'markdown-demote)
1988 (should (string-equal (buffer-string) "*italic*"))))
1990 ;;; Indentation tests:
1992 (ert-deftest test-markdown-indentation/calc-indents ()
1993 "Test `markdown-calc-indents' a nested list context."
1994 (markdown-test-file "nested-list.text"
1995 (goto-char (point-max))
1996 (let ((indents (markdown-calc-indents)))
1997 (should (= (car indents) 17)) ; indentation of previous line first
1998 (should (equal (sort indents '<)
1999 (list
2000 0 ; beginning of line
2001 3 ; first-level list marker
2002 7 ; second-level list marker
2003 11 ; third-level list marker
2004 13 ; previous list item text
2005 16 ; pre-block indentation
2006 17 ; indentation of previous line
2007 21 ; previous line plus tab-width
2008 ))))))
2010 (ert-deftest test-markdown-indentation/indent-region ()
2011 "Test `markdown-indent-region'."
2012 ;; Basic test with multiple lines
2013 (markdown-test-string "abc\ndef\nghi\n"
2014 (markdown-indent-region (point-min) (point-max) nil)
2015 (should (string-equal (buffer-string) " abc\n def\n ghi\n")))
2016 ;; Following a list item
2017 (markdown-test-string " * abc\ndef\n"
2018 (forward-line)
2019 (markdown-indent-region (line-beginning-position) (line-end-position) nil)
2020 (should (string-equal (buffer-string) " * abc\n def\n"))
2021 (markdown-indent-region (line-beginning-position) (line-end-position) nil)
2022 (should (string-equal (buffer-string) " * abc\n def\n"))))
2024 (ert-deftest test-markdown-indentation/indent-list-hanging ()
2025 "Test `markdown-indent-line' with hanging list item."
2026 (markdown-test-string
2027 "- list
2028 - nested list with long lines which need to be
2029 hard wrapped"
2030 (goto-char (point-max))
2031 (markdown-enter-key)
2032 (should (eq (point) 78))))
2034 (ert-deftest test-markdown-indentation/indent-list-single ()
2035 "Test `markdown-indent-line' with single list item."
2036 (let ((markdown-indent-on-enter 'indent-and-new-item))
2037 (markdown-test-string " * item 1"
2038 (end-of-line)
2039 (call-interactively #'markdown-enter-key)
2040 (should (string-equal (buffer-string) " * item 1\n * "))
2041 (should (eq (point) 16))
2042 (call-interactively #'markdown-enter-key)
2043 (should (string-equal (buffer-string) " * item 1\n\n"))
2044 (should (eq (point) 13)))))
2046 (ert-deftest test-markdown-indentation/indent-nested-list ()
2047 "Test `markdown-enter-key' with a nested list item."
2048 (let ((markdown-indent-on-enter 'indent-and-new-item))
2049 (markdown-test-string "* foo\n* bar\n * baz"
2050 (goto-char (point-max))
2051 (call-interactively #'markdown-enter-key)
2052 (should (string-equal (buffer-string) "* foo\n* bar\n * baz\n * "))
2053 (should (eq (point) 25))
2054 (call-interactively #'markdown-enter-key)
2055 (should (string-equal (buffer-string) "* foo\n* bar\n * baz\n\n"))
2056 (should (eq (point) 22)))))
2058 (ert-deftest test-markdown-indentation/indent-pre ()
2059 "Test `markdown-indent-line' with a pre block."
2060 (markdown-test-string
2061 "I'm gonna write a code block:
2063 my first line of code"
2064 (goto-char (point-max))
2065 (markdown-enter-key)
2066 (should (eq (point) 62))
2067 (should (looking-back "^ "))))
2069 (ert-deftest test-markdown-indentation/indent-region-function ()
2070 "Test `indent-region'. Code block should not be indented.
2071 Detail: https://github.com/jrblevin/markdown-mode/issues/228"
2072 (markdown-test-string
2073 "Here follows a code sample:
2075 #!/bin/bash
2076 echo foobar
2078 Nice sample, isn't it ?"
2079 (indent-region (point-min) (point-max))
2080 (goto-char (point-min))
2081 (forward-line 2)
2082 (should (looking-at-p " #!/bin/bash"))
2083 (markdown-test-range-has-face (point) (line-end-position) 'markdown-pre-face)))
2085 (ert-deftest test-markdown-indentation/indent-hanging-line ()
2086 "Test `markdown-indent-line' with hanging indentation.
2087 See GH-245."
2088 (markdown-test-string "Stuff
2089 More"
2090 (forward-line)
2091 (should (looking-at "^ More"))
2092 (should (= (current-column) 0))
2093 (should (= (current-indentation) 2))
2094 (let ((last-command this-command)
2095 (this-command 'markdown-cycle))
2096 (call-interactively #'markdown-cycle))
2097 (should (= (current-column) 0))
2098 (should (= (current-indentation) 0))))
2100 (ert-deftest test-markdown-indentation/continue-gfm-task-lists ()
2101 "Test `markdown-enter-key' with a gfm task list item."
2102 (let ((markdown-indent-on-enter 'indent-and-new-item))
2103 (markdown-test-string " - [X] item"
2104 (end-of-line)
2105 (call-interactively #'markdown-enter-key)
2106 (should (string-equal (buffer-string) " - [X] item\n - [ ] "))
2107 (should (= (point) 28))
2108 (call-interactively #'markdown-enter-key)
2109 (should (string-equal (buffer-string) " - [X] item\n\n"))
2110 (should (= (point) 18)))))
2112 ;;; Markup hiding tests:
2114 (ert-deftest test-markdown-markup-hiding/italics-1 ()
2115 "Test hiding markup for italics."
2116 (markdown-test-file "inline.text"
2117 (goto-char 9)
2118 (should (looking-at "\*italic\*"))
2119 (markdown-test-range-has-property (point) (point) 'invisible 'markdown-markup)
2120 (should-not (invisible-p (point)))
2121 (should-not (invisible-p (+ 1 (point))))
2122 (markdown-toggle-markup-hiding t)
2123 (should (invisible-p (point)))
2124 (should-not (invisible-p (+ 1 (point))))))
2126 (ert-deftest test-markdown-markup-hiding/bold-1 ()
2127 "Test hiding markup for bold."
2128 (markdown-test-file "inline.text"
2129 (goto-char 27)
2130 (should (looking-at "\*\*bold\*\*"))
2131 (markdown-test-range-has-property (point) (1+ (point)) 'invisible 'markdown-markup)
2132 (should-not (invisible-p (point)))
2133 (should-not (invisible-p (+ 1 (point))))
2134 (should-not (invisible-p (+ 2 (point))))
2135 (markdown-toggle-markup-hiding t)
2136 (should (invisible-p (point)))
2137 (should (invisible-p (+ 1 (point))))
2138 (should-not (invisible-p (+ 2 (point))))))
2140 (ert-deftest test-markdown-markup-hiding/code-1 ()
2141 "Test hiding markup for inline code."
2142 (markdown-test-file "inline.text"
2143 (goto-char 45)
2144 (should (looking-at "`code`"))
2145 (markdown-test-range-has-property (point) (point) 'invisible 'markdown-markup)
2146 (should-not (invisible-p (point)))
2147 (should-not (invisible-p (1+ (point))))
2148 (markdown-toggle-markup-hiding t)
2149 (should (invisible-p (point)))
2150 (should-not (invisible-p (1+ (point))))))
2152 (ert-deftest test-markdown-markup-hiding/code-2 ()
2153 "Test hiding markup for inline code with backslashes."
2154 (markdown-test-file "inline.text"
2155 (goto-char 460)
2156 (should (looking-at "`C-h C-\\\\`"))
2157 (markdown-test-range-has-property (point) (point) 'invisible 'markdown-markup)
2158 (should-not (invisible-p (point)))
2159 (should-not (invisible-p (+ 1 (point))))
2160 (should-not (invisible-p (+ 7 (point))))
2161 (should-not (invisible-p (+ 8 (point))))
2162 (markdown-toggle-markup-hiding t)
2163 (should (invisible-p (point)))
2164 (should-not (invisible-p (+ 1 (point))))
2165 (should-not (invisible-p (+ 7 (point))))
2166 (should (invisible-p (+ 8 (point))))))
2168 (ert-deftest test-markdown-markup-hiding/kbd-1 ()
2169 "Test hiding markup for <kbd> tags."
2170 (markdown-test-string "<kbd>C-c C-x C-m</kbd>"
2171 (markdown-test-range-has-property (point) (+ 4 (point)) 'invisible 'markdown-markup)
2172 (should-not (invisible-p (point))) ;; part of <kbd>
2173 (should-not (invisible-p (+ 4 (point)))) ;; part of <kbd>
2174 (should-not (invisible-p (+ 5 (point)))) ;; inside <kbd>
2175 (markdown-toggle-markup-hiding t)
2176 (should (invisible-p (point))) ;; part of <kbd>
2177 (should (invisible-p (+ 4 (point)))) ;; part of <kbd>
2178 (should-not (invisible-p (+ 5 (point)))))) ;; inside <kbd>
2180 (ert-deftest test-markdown-markup-hiding/inline-links ()
2181 "Test hiding markup for inline links."
2182 (markdown-test-file "inline.text"
2183 (goto-char 925)
2184 (should (looking-at "\\[text\\](http://www.w3.org/ \"title\")"))
2185 (markdown-test-range-has-property 925 925 'invisible 'markdown-markup) ; [
2186 (markdown-test-range-has-property 930 958 'invisible 'markdown-markup) ; ](...)
2187 (should-not (invisible-p 925))
2188 (should-not (invisible-p 958))
2189 (markdown-toggle-markup-hiding t)
2190 (should (invisible-p 925))
2191 (should-not (invisible-p 926))
2192 (should (invisible-p 958))))
2194 (ert-deftest test-markdown-markup-hiding/reference-links ()
2195 "Test hiding markup for reference links."
2196 (markdown-test-string "[text][ref]"
2197 (markdown-test-range-has-property 1 1 'invisible 'markdown-markup) ; [
2198 (markdown-test-range-has-property 6 11 'invisible 'markdown-markup) ; ][ref]
2199 (should-not (invisible-p 1))
2200 (should-not (invisible-p 6))
2201 (markdown-toggle-markup-hiding t)
2202 (should (invisible-p 1))
2203 (should-not (invisible-p 2))
2204 (should (invisible-p 6))))
2206 (ert-deftest test-markdown-markup-hiding/angle-urls ()
2207 "Test hiding markup for angle urls."
2208 (markdown-test-string "<http://jblevins.org/projects/markdown-mode/>"
2209 (markdown-test-range-has-property 1 1 'invisible 'markdown-markup) ; <
2210 (markdown-test-range-has-property 45 45 'invisible 'markdown-markup) ; >
2211 (should-not (invisible-p 1))
2212 (should-not (invisible-p 2))
2213 (should-not (invisible-p 45))
2214 (markdown-toggle-markup-hiding t)
2215 (should (invisible-p 1))
2216 (should-not (invisible-p 2))
2217 (should (invisible-p 45))))
2219 (ert-deftest test-markdown-markup-hiding/list-items ()
2220 "Test hiding markup for list items."
2221 (let ((markdown-hide-markup t))
2222 (markdown-test-file "nested-list.text"
2223 (markdown-test-range-has-property 4 4 'display (nth 0 markdown-list-item-bullets))
2224 (markdown-test-range-has-property 194 194 'display (nth 0 markdown-list-item-bullets))
2225 (markdown-test-range-has-property 224 224 'display (nth 1 markdown-list-item-bullets))
2226 (markdown-test-range-has-property 525 525 'display (nth 2 markdown-list-item-bullets)))))
2228 (ert-deftest test-markdown-markup-hiding/gfm-code-blocks ()
2229 "Test hiding markup for GFM code blocks."
2230 (let ((markdown-hide-markup t))
2231 (markdown-test-file "GFM.md"
2232 (markdown-test-range-has-property 1548 1552 'invisible 'markdown-markup)
2233 (should (invisible-p 1548))
2234 (should (invisible-p 1552))
2235 (markdown-test-range-has-property 1607 1609 'invisible 'markdown-markup)
2236 (should (invisible-p 1607))
2237 (should (invisible-p 1609)))))
2239 (ert-deftest test-markdown-markup-hiding/fenced-code-blocks ()
2240 "Test hiding markup for tilde fenced code blocks."
2241 (let ((markdown-hide-markup t))
2242 (markdown-test-file "outline-code.text"
2243 (markdown-test-range-has-property 83 93 'invisible 'markdown-markup)
2244 (should (invisible-p 83))
2245 (should (invisible-p 93))
2246 (markdown-test-range-has-property 154 156 'invisible 'markdown-markup)
2247 (should (invisible-p 154))
2248 (should (invisible-p 156)))))
2250 (ert-deftest test-markdown-markup-hiding/escape ()
2251 "Test hiding markup for backslash escapes."
2252 (markdown-test-string "\\#"
2253 (markdown-test-range-has-property (point) (point) 'invisible 'markdown-markup)
2254 (should-not (invisible-p (point)))
2255 (should-not (invisible-p (1+ (point))))
2256 (markdown-toggle-markup-hiding t)
2257 (should (invisible-p (point)))
2258 (should-not (invisible-p (1+ (point))))))
2260 (ert-deftest test-markdown-markup-hiding/line-break ()
2261 "Test hiding markup for line break markup."
2262 (markdown-test-string "hello \nworld"
2263 (markdown-test-range-has-property (+ 5 (point)) (+ 6 (point)) 'invisible 'markdown-markup)
2264 (should-not (invisible-p (point))) ;; part of "hello"
2265 (should-not (invisible-p (+ 5 (point)))) ;; part of line break
2266 (should-not (invisible-p (+ 7 (point)))) ;; part of "world"
2267 (markdown-toggle-markup-hiding t)
2268 (should-not (invisible-p (point))) ;; part of "hello"
2269 (should (invisible-p (+ 5 (point)))) ;; part of line break
2270 (should-not (invisible-p (+ 7 (point)))))) ;; inside "world"
2272 ;;; Markup hiding url tests:
2274 (ert-deftest test-markdown-url-hiding/eldoc ()
2275 "Test hiding URL and eldoc.
2276 Detail: https://github.com/jrblevin/markdown-mode/pull/674"
2277 (markdown-test-string "[This is a hidden link](http://hidden.link)"
2278 (markdown-toggle-url-hiding +1)
2279 (search-forward "(")
2280 (markdown-eldoc-function)
2281 ;; markdown-eldoc-function doesn't raise an exception
2282 (should t)))
2284 ;;; Font lock tests:
2286 (ert-deftest test-markdown-font-lock/italics-1 ()
2287 "A simple italics test."
2288 (markdown-test-file "inline.text"
2289 (goto-char 9)
2290 (should (looking-at "\*"))
2291 ;; Check face of char before leading asterisk
2292 (markdown-test-range-has-face 8 8 nil)
2293 ;; Check face of italic range
2294 (markdown-test-range-has-face 9 9 'markdown-markup-face)
2295 (markdown-test-range-has-face 10 16 'markdown-italic-face)
2296 (markdown-test-range-has-face 17 17 'markdown-markup-face)
2297 ;; Check face of point past leading asterisk
2298 (markdown-test-range-has-face 18 18 nil)))
2300 (ert-deftest test-markdown-font-lock/italics-2 ()
2301 "Test space after leading asterisk or underscore."
2302 (markdown-test-string
2303 "This is * not italic*, nor _ is this_."
2304 (markdown-test-range-has-face (point-min) (point-max) nil)))
2306 (ert-deftest test-markdown-font-lock/italics-3 ()
2307 "Test that slash inside asterisks is not italic."
2308 (markdown-test-string
2309 "not italic *\\*"
2310 (markdown-test-range-has-face 1 12 nil)
2311 ;; Check face of the backslash
2312 (markdown-test-range-has-face 13 13 'markdown-markup-face)
2313 (markdown-test-range-has-face 14 14 nil)))
2315 (ert-deftest test-markdown-font-lock/italics-4 ()
2316 "Test escaped asterisk inside italics."
2317 (markdown-test-string
2318 "italic *\\**"
2319 (markdown-test-range-has-face 1 7 nil)
2320 (markdown-test-range-has-face 8 8 'markdown-markup-face)
2321 (markdown-test-range-has-face 9 10 'markdown-italic-face)
2322 (markdown-test-range-has-face 11 11 'markdown-markup-face)))
2324 (ert-deftest test-markdown-font-lock/italics-5 ()
2325 "Test italic single letter."
2326 (markdown-test-string
2327 "*a*"
2328 (markdown-test-range-has-face 1 1 'markdown-markup-face)
2329 (markdown-test-range-has-face 2 2 'markdown-italic-face)
2330 (markdown-test-range-has-face 3 3 'markdown-markup-face)))
2332 (ert-deftest test-markdown-font-lock/italics-6 ()
2333 "Test multiline italics across list items."
2334 (markdown-test-string
2335 "* something about function foo_bar
2336 * something else about foo_bar"
2337 (markdown-test-range-has-face 31 34 nil)
2338 (markdown-test-range-has-face 38 62 nil)))
2340 (ert-deftest test-markdown-font-lock/italics-8 ()
2341 "Test multiline italics across list items."
2342 (markdown-test-string
2343 "* something about function
2344 foo_bar
2345 * something else about
2346 foo_bar"
2347 (markdown-test-range-has-face 30 36 nil)
2348 (markdown-test-range-has-face 63 69 nil)))
2350 (ert-deftest test-markdown-font-lock/italics-9 ()
2351 "Test multiline italics across list items."
2352 (markdown-test-string
2353 "foo_bar
2354 * foo_bar"
2355 (markdown-test-range-has-face 4 7 nil)
2356 (markdown-test-range-has-face 11 14 nil)))
2358 (ert-deftest test-markdown-font-lock/italics-10 ()
2359 "Underscores in URLs should not trigger italics."
2360 (markdown-test-string
2361 "<http://jblevins.org/research/centroid/cd_z_path.m>"
2362 (markdown-test-range-face-equals 2 50 'markdown-plain-url-face)
2363 (should-not (markdown-range-property-any 43 43 'face '(markdown-italic-face)))))
2365 (ert-deftest test-markdown-font-lock/italics-11 ()
2366 "Underscores in URLs should not trigger italics."
2367 (markdown-test-string
2368 "[1]: http://jblevins.org/research/centroid/cd_z_path.m"
2369 (markdown-test-range-face-equals 6 54 'markdown-url-face)))
2371 (ert-deftest test-markdown-font-lock/italics-12 ()
2372 "Underscores in URLs should not trigger italics."
2373 (markdown-test-string
2374 "[cd\\_z\\_path.m](http://jblevins.org/research/centroid/cd_z_path.m)"
2375 (markdown-test-range-face-equals 17 65 'markdown-url-face)))
2377 (ert-deftest test-markdown-font-lock/url-face-with-comma-and-parenthesis ()
2378 "Test URL highlighting with comma and parenthesis.
2379 Detail: https://github.com/jrblevin/markdown-mode/issues/649"
2380 (markdown-test-string "<https://en.wikipedia.org/wiki/File:L%C3%A1szl%C3%B3_Moholy-Nagy,_nuclear_II,_1946_(milwaukee_art_museum).jpg>"
2381 (markdown-test-range-face-equals 2 109 'markdown-plain-url-face)))
2383 (ert-deftest test-markdown-font-lock/italics-after-hr ()
2384 "Test italics after a horizontal rule with asterisks."
2385 (markdown-test-string "* * *\n\n*italic*\n"
2386 (markdown-test-range-has-face 1 5 'markdown-hr-face)
2387 (markdown-test-range-has-face 8 8 'markdown-markup-face)
2388 (markdown-test-range-has-face 9 14 'markdown-italic-face)
2389 (markdown-test-range-has-face 15 15 'markdown-markup-face)))
2391 (ert-deftest test-markdown-font-lock/italics-in-heading ()
2392 "Test italic overlay in a heading."
2393 (markdown-test-string
2394 "# *Italics* in a Heading"
2395 (markdown-test-range-has-face 3 3 'markdown-markup-face)
2396 (markdown-test-range-has-face 4 10 'markdown-italic-face)
2397 (markdown-test-range-has-face 11 11 'markdown-markup-face)))
2399 (ert-deftest test-markdown-font-lock/italics-link ()
2400 "Test italic overlay in an inline link."
2401 (markdown-test-string
2402 "*[italic link](http://www.link.com/)*"
2403 (markdown-test-range-has-face 1 1 'markdown-markup-face)
2404 (markdown-test-range-has-face 2 36 'markdown-italic-face)
2405 (markdown-test-range-has-face 37 37 'markdown-markup-face))
2406 (markdown-test-string
2407 "[*italic link*](http://www.link.com/)"
2408 (markdown-test-range-has-face 2 2 'markdown-markup-face)
2409 (markdown-test-range-has-face 3 13 'markdown-italic-face)
2410 (markdown-test-range-has-face 14 14 'markdown-markup-face)))
2412 (ert-deftest test-markdown-font-lock/italics-in-blockquote ()
2413 "Test italics overlay in a blockquote."
2414 (markdown-test-string
2415 "> *italics* inside a blockquote"
2416 (markdown-test-range-has-face 3 3 'markdown-markup-face)
2417 (markdown-test-range-has-face 4 10 'markdown-italic-face)
2418 (markdown-test-range-has-face 11 11 'markdown-markup-face)))
2420 (ert-deftest test-markdown-font-lock/italics-in-pre ()
2421 "Test italics overlay in a blockquote."
2422 (markdown-test-string
2423 " *italics* inside a pre block"
2424 (markdown-test-range-has-face (point-min) (1- (point-max))
2425 'markdown-pre-face)))
2427 (ert-deftest test-markdown-font-lock/italics-and-code ()
2428 "Test seeming italics mixed with code."
2429 (markdown-test-string
2430 "define `var_1` and `var_2` inline code"
2431 (markdown-test-range-has-face 9 13 'markdown-inline-code-face)
2432 (markdown-test-range-has-face 21 25 'markdown-inline-code-face))
2433 (markdown-test-string
2434 "`var_1` and var_2"
2435 (markdown-test-range-has-face 2 6 'markdown-inline-code-face)
2436 (markdown-test-range-has-face 8 17 nil))
2437 (markdown-test-string
2438 "var_1 and `var_2`"
2439 (markdown-test-range-has-face 1 10 nil)
2440 (markdown-test-range-has-face 12 16 'markdown-inline-code-face)))
2442 (ert-deftest test-markdown-font-lock/code-in-italics ()
2443 "Test inline code inside italics.
2444 See GH-275."
2445 (markdown-test-string
2446 "*text `code` text*"
2447 (markdown-test-range-has-face 1 1 'markdown-markup-face)
2448 (markdown-test-range-has-face 2 17 'markdown-italic-face)
2449 (markdown-test-range-has-face 7 7 'markdown-markup-face)
2450 (markdown-test-range-has-face 8 11 'markdown-inline-code-face)
2451 (markdown-test-range-has-face 12 12 'markdown-markup-face)
2452 (markdown-test-range-has-face 18 18 'markdown-markup-face)))
2454 (ert-deftest test-markdown-font-lock/italics-in-reference-definitions ()
2455 "Test not matching italics in reference definitions across lines."
2456 (markdown-test-string
2457 "[lg]: twilight_sm.png\n[sm]: twilight_lg.png"
2458 (markdown-test-range-has-face 7 21 'markdown-url-face)
2459 (markdown-test-range-has-face 22 22 nil)
2460 (markdown-test-range-has-face 29 43 'markdown-url-face)
2461 (markdown-test-range-has-face 28 28 nil)))
2463 (ert-deftest test-markdown-font-lock/italics-in-comment ()
2464 "Test not matching italics in comments."
2465 (markdown-test-string
2466 "<!-- -*- coding: utf-8 -*- -->"
2467 (markdown-test-range-has-face 1 30 'markdown-comment-face)
2468 (should-not (markdown-range-property-any 1 30 'face '(markdown-italic-face)))))
2470 (ert-deftest test-markdown-font-lock/italics-in-html-attribute ()
2471 "Test not matching italics in HTML attributes."
2472 (markdown-test-string
2473 "<meta a=\"b_c\" d=\"e_f\">"
2474 (should-not (markdown-range-property-any 12 18 'face '(markdown-italic-face)))))
2476 (ert-deftest test-markdown-font-lock/italics-after-bold ()
2477 "Test bold and italics on the same line.
2478 See GH-223."
2479 (markdown-test-string
2480 "**foo** is a *bar*"
2481 (markdown-test-range-has-face 1 2 'markdown-markup-face)
2482 (markdown-test-range-has-face 3 5 'markdown-bold-face)
2483 (markdown-test-range-has-face 6 7 'markdown-markup-face)
2484 (should-not
2485 (markdown-range-property-any 8 13 'face '(markdown-italic-face)))
2486 (markdown-test-range-has-face 14 14 'markdown-markup-face)
2487 (markdown-test-range-has-face 15 17 'markdown-italic-face)
2488 (markdown-test-range-has-face 18 18 'markdown-markup-face)))
2490 (ert-deftest test-markdown-font-lock/italics-and-bold-and-punctual ()
2491 "Test bold and italics and punctual character.
2492 Detail: https://github.com/jrblevin/markdown-mode/issues/359"
2493 (markdown-test-string
2494 "**Fat**, normal *italic*, normal **fat**"
2495 (markdown-test-range-has-face 1 2 'markdown-markup-face)
2496 (markdown-test-range-has-face 3 5 'markdown-bold-face)
2497 (markdown-test-range-has-face 6 7 'markdown-markup-face)
2498 (should-not
2499 (markdown-range-property-any 10 15 'face '(markdown-italic-face)))
2500 (markdown-test-range-has-face 18 23 'markdown-italic-face)
2501 (should-not
2502 (markdown-range-property-any 27 32 'face '(markdown-italic-face)))
2503 (markdown-range-property-any 36 38 'face '(markdown-bold-face))))
2505 (ert-deftest test-markdown-font-lock/italic-after-code-block ()
2506 "Test italic fontification after code block.
2507 Detail: https://github.com/jrblevin/markdown-mode/issues/548"
2508 (markdown-test-string "`(`*italic*`)` plain text
2509 *italic*"
2510 (markdown-test-range-has-face 4 4 'markdown-markup-face)
2511 (markdown-test-range-has-face 5 10 'markdown-italic-face)
2512 (markdown-test-range-has-face 11 11 'markdown-markup-face)
2513 (markdown-test-range-has-face 16 25 nil)
2514 (markdown-test-range-has-face 27 27 'markdown-markup-face)
2515 (markdown-test-range-has-face 28 33 'markdown-italic-face)
2516 (markdown-test-range-has-face 34 34 'markdown-markup-face)))
2518 (ert-deftest test-markdown-font-lock/italic-after-bold ()
2519 "Test italic fontification after after.
2520 Detail: https://github.com/jrblevin/markdown-mode/issues/731"
2521 (markdown-test-string "__ONE__ TWO _THREE_"
2522 (markdown-test-range-has-face 1 2 'markdown-markup-face)
2523 (markdown-test-range-has-face 3 5 'markdown-bold-face)
2524 (markdown-test-range-has-face 6 7 'markdown-markup-face)
2525 (markdown-test-range-has-face 8 12 nil)
2526 (markdown-test-range-has-face 13 13 'markdown-markup-face)
2527 (markdown-test-range-has-face 14 18 'markdown-italic-face)
2528 (markdown-test-range-has-face 19 19 'markdown-markup-face)))
2530 (ert-deftest test-markdown-font-lock/bold-1 ()
2531 "A simple bold test."
2532 (markdown-test-file "inline.text"
2533 (goto-char 27)
2534 (should (looking-at "\*\*"))
2535 ;; Check face of char before leading asterisk
2536 (markdown-test-range-has-face 26 26 nil)
2537 ;; Check face of opening asterisks
2538 (markdown-test-range-has-face 27 28 'markdown-markup-face)
2539 ;; Check face of bold range
2540 (markdown-test-range-has-face 29 33 'markdown-bold-face)
2541 ;; Check face of closing asterisks
2542 (markdown-test-range-has-face 34 35 'markdown-markup-face)
2543 ;; Check face of point past leading asterisk
2544 (markdown-test-range-has-face 36 36 nil)))
2546 (ert-deftest test-markdown-font-lock/bold-2 ()
2547 "Test space after leading asterisks or underscores."
2548 (markdown-test-string
2549 "This is ** not bold**, nor __ is this__."
2550 (should-not
2551 (markdown-range-property-any
2552 (point-min) (point-max) 'face '(markdown-bold-face)))))
2554 (ert-deftest test-markdown-font-lock/bold-3 ()
2555 "Test escaped asterisk inside bold."
2556 (markdown-test-string
2557 "bold **\\***"
2558 (markdown-test-range-has-face 1 5 nil)
2559 (markdown-test-range-has-face 6 7 'markdown-markup-face)
2560 (markdown-test-range-has-face 8 9 'markdown-bold-face)
2561 (markdown-test-range-has-face 10 11 'markdown-markup-face)))
2563 (ert-deftest test-markdown-font-lock/bold-4 ()
2564 "Test bold single letter."
2565 (markdown-test-string
2566 "**a**"
2567 (markdown-test-range-has-face 1 2 'markdown-markup-face)
2568 (markdown-test-range-has-face 3 3 'markdown-bold-face)
2569 (markdown-test-range-has-face 4 5 'markdown-markup-face)))
2571 (ert-deftest test-markdown-font-lock/bold-after-hr ()
2572 "Test bold after a horizontal rule with asterisks."
2573 (markdown-test-string "* * *\n\n**bold**\n"
2574 (markdown-test-range-has-face 1 5 'markdown-hr-face)
2575 (markdown-test-range-has-face 8 9 'markdown-markup-face)
2576 (markdown-test-range-has-face 10 13 'markdown-bold-face)
2577 (markdown-test-range-has-face 14 15 'markdown-markup-face)))
2579 (ert-deftest test-markdown-font-lock/bold-link ()
2580 "Test bold overlay in an inline link."
2581 (markdown-test-string
2582 "**[bold link](http://www.link.com/)**"
2583 (markdown-test-range-has-face 1 2 'markdown-markup-face)
2584 (markdown-test-range-has-face 3 35 'markdown-bold-face)
2585 (markdown-test-range-has-face 36 37 'markdown-markup-face))
2586 (markdown-test-string
2587 "[**bold link**](http://www.link.com/)"
2588 (markdown-test-range-has-face 2 3 'markdown-markup-face)
2589 (markdown-test-range-has-face 4 12 'markdown-bold-face)
2590 (markdown-test-range-has-face 13 14 'markdown-markup-face)))
2592 (ert-deftest test-markdown-font-lock/bold-in-blockquote ()
2593 "Test bold overlay in a blockquote."
2594 (markdown-test-string
2595 "> **bold** inside a blockquote"
2596 (markdown-test-range-has-face 3 4 'markdown-markup-face)
2597 (markdown-test-range-has-face 5 8 'markdown-bold-face)
2598 (markdown-test-range-has-face 9 10 'markdown-markup-face)))
2600 (ert-deftest test-markdown-font-lock/bold-in-pre ()
2601 "Test bold overlay in a blockquote."
2602 (markdown-test-string
2603 " **bold** inside a pre block"
2604 (markdown-test-range-has-face (point-min) (1- (point-max))
2605 'markdown-pre-face)))
2607 (ert-deftest test-markdown-font-lock/no-bold-in-code ()
2608 "Bold markers in inline code should not trigger bold."
2609 (markdown-test-string
2610 "`def __init__(self):`"
2611 (markdown-test-range-has-face 8 11 'markdown-inline-code-face)
2612 (should-not (markdown-range-property-any
2613 (point-min) (point-max) 'face '(markdown-bold-face))))
2614 (markdown-test-string
2615 "`**foo` bar `baz**`"
2616 (markdown-test-range-has-face 2 6 'markdown-inline-code-face)
2617 (markdown-test-range-face-equals 9 11 nil)
2618 (markdown-test-range-has-face 14 18 'markdown-inline-code-face)
2619 (should-not (markdown-range-property-any
2620 (point-min) (point-max) 'face '(markdown-bold-face)))))
2622 (ert-deftest test-markdown-font-lock/no-bold-asterisk-and-underscore ()
2623 "string wrap with single asterisk and single underscore is not bold.
2624 Detail: https://github.com/jrblevin/markdown-mode/issues/325"
2625 (markdown-test-string
2626 "_*bold_* *_bold*_"
2627 (should-not (markdown-range-property-any 3 6 'face '(markdown-bold-face)))
2628 (should-not (markdown-range-property-any 11 14 'face '(markdown-bold-face)))))
2630 (ert-deftest test-markdown-font-lock/code-in-bold ()
2631 "Test inline code inside bold."
2632 (markdown-test-string
2633 "**text `code` text**"
2634 (markdown-test-range-has-face 1 2 'markdown-markup-face)
2635 (markdown-test-range-has-face 3 18 'markdown-bold-face)
2636 (markdown-test-range-has-face 8 8 'markdown-markup-face)
2637 (markdown-test-range-has-face 9 12 'markdown-inline-code-face)
2638 (markdown-test-range-has-face 13 13 'markdown-markup-face)
2639 (markdown-test-range-has-face 19 20 'markdown-markup-face)))
2641 (ert-deftest test-markdown-font-lock/bold-in-comment ()
2642 "Test not matching bold in comments."
2643 (markdown-test-string
2644 "<!-- **not bold** -->"
2645 (markdown-test-range-has-face 1 21 'markdown-comment-face)
2646 (should-not
2647 (markdown-range-property-any 1 21 'face '(markdown-bold-face)))))
2649 (ert-deftest test-markdown-font-lock/no-bold-in-url ()
2650 "Test not matching bold in plain URL links."
2651 (markdown-test-string
2652 "<https://example.com/__not-bold__>"
2653 (should-not (markdown-range-property-any 23 30 'face '(markdown-bold-face)))))
2655 (ert-deftest test-markdown-font-lock/autolinks ()
2656 "Test highlighting inside brackets if it looks like URI.
2657 Detail: https://github.com/jrblevin/markdown-mode/issues/743"
2658 (markdown-test-string "<https://example.com/>
2659 <mailto:nobody@example.com>
2660 <MAILTO:nobody@example.com>
2661 <uri://example.com>
2662 <tel:+555>
2663 <geo:59.5,11.0>
2664 <irc://example.com/channel>
2665 <x-web-search://>
2666 <x-apple-reminder://>
2668 (while (re-search-forward "<\\([^>]+\\)>" nil t)
2669 (markdown-test-range-face-equals (match-beginning 1) (1- (match-end 1)) 'markdown-plain-url-face)))
2671 ;; valid scheme length is 2..32 characters
2672 (markdown-test-string "<a:abcde>
2673 <this-is-very-very-very-very-long-scheme://example.com>
2675 (while (re-search-forward "<\\([^>]+\\)>" nil t)
2676 (should-not
2677 (markdown-range-property-any (match-beginning 1) (1- (match-end 1)) 'face '(markdown-plain-url-face))))))
2679 (ert-deftest test-markdown-font-lock/code-1 ()
2680 "A simple inline code test."
2681 (markdown-test-file "inline.text"
2682 (goto-char 45)
2683 (should (looking-at "`"))
2684 ;; Regular code span
2685 (markdown-test-range-has-face 45 45 'markdown-markup-face)
2686 (markdown-test-range-has-face 46 49 'markdown-inline-code-face)
2687 (markdown-test-range-has-face 50 50 'markdown-markup-face)
2688 ;; Code containing backticks
2689 (markdown-test-range-has-face 61 62 'markdown-markup-face)
2690 (markdown-test-range-has-face 63 87 'markdown-inline-code-face)
2691 (markdown-test-range-has-face 88 89 'markdown-markup-face)
2692 ;; Seven backquotes in a row
2693 (markdown-test-range-has-face 119 125 nil)
2694 ;; Backquotes at beginning or end
2695 (markdown-test-range-has-face 228 229 'markdown-markup-face)
2696 (markdown-test-range-has-face 230 237 'markdown-inline-code-face)
2697 (markdown-test-range-has-face 238 239 'markdown-markup-face)
2698 (markdown-test-range-has-face 341 342 'markdown-markup-face)
2699 (markdown-test-range-has-face 343 349 'markdown-inline-code-face)
2700 (markdown-test-range-has-face 350 351 'markdown-markup-face)
2701 ;; Backslash as final character
2702 (markdown-test-range-has-face 460 460 'markdown-markup-face)
2703 (markdown-test-range-has-face 461 467 'markdown-inline-code-face)
2704 (markdown-test-range-has-face 468 468 'markdown-markup-face)
2705 ;; Escaping of leading backquotes
2706 (markdown-test-range-has-face 586 586 'markdown-markup-face)
2707 (markdown-test-range-has-face 587 590 nil)
2708 (markdown-test-range-has-face 591 591 'markdown-markup-face)
2709 (markdown-test-range-has-face 592 592 nil)
2710 (markdown-test-range-has-face 597 597 'markdown-markup-face)
2711 (markdown-test-range-has-face 598 601 nil)
2712 (markdown-test-range-has-face 602 602 'markdown-markup-face)
2713 (markdown-test-range-has-face 603 603 nil)
2714 ;; A code span crossing lines
2715 (markdown-test-range-has-face 652 652 'markdown-markup-face)
2716 (markdown-test-range-has-face 653 656 nil)
2717 (markdown-test-range-has-face 657 657 'markdown-markup-face)
2718 (markdown-test-range-has-face 658 665 'markdown-inline-code-face)
2719 (markdown-test-range-has-face 666 666 'markdown-markup-face)
2720 ;; Three backquotes: same line, across lines, not across blocks
2721 (markdown-test-range-has-face 695 748 nil)
2722 (markdown-test-range-has-face 749 750 'markdown-markup-face)
2723 (markdown-test-range-has-face 751 755 'markdown-inline-code-face)
2724 (markdown-test-range-has-face 756 757 'markdown-markup-face)
2725 (markdown-test-range-has-face 758 805 nil)
2726 (markdown-test-range-has-face 806 807 'markdown-markup-face)
2727 (markdown-test-range-has-face 808 812 'markdown-inline-code-face)
2728 (markdown-test-range-has-face 813 814 'markdown-markup-face)
2729 (markdown-test-range-has-face 815 891 nil)
2732 (ert-deftest test-markdown-font-lock/code-2 ()
2733 "Multiple code spans in a row and on different lines."
2734 (markdown-test-string "`foo` `bar` `baz`"
2735 (markdown-test-range-has-face 1 1 'markdown-markup-face)
2736 (markdown-test-range-has-face 2 4 'markdown-inline-code-face)
2737 (markdown-test-range-has-face 5 5 'markdown-markup-face)
2738 (markdown-test-range-has-face 6 6 nil)
2739 (markdown-test-range-has-face 7 7 'markdown-markup-face)
2740 (markdown-test-range-has-face 8 10 'markdown-inline-code-face)
2741 (markdown-test-range-has-face 11 11 'markdown-markup-face)
2742 (markdown-test-range-has-face 12 12 nil)
2743 (markdown-test-range-has-face 13 13 'markdown-markup-face)
2744 (markdown-test-range-has-face 14 16 'markdown-inline-code-face)
2745 (markdown-test-range-has-face 17 17 'markdown-markup-face))
2746 (markdown-test-string "`a`\n`b`\n`c`\n"
2747 (markdown-test-range-has-face 1 1 'markdown-markup-face)
2748 (markdown-test-range-has-face 2 2 'markdown-inline-code-face)
2749 (markdown-test-range-has-face 3 3 'markdown-markup-face)
2750 (markdown-test-range-has-face 4 4 nil)
2751 (markdown-test-range-has-face 5 5 'markdown-markup-face)
2752 (markdown-test-range-has-face 6 6 'markdown-inline-code-face)
2753 (markdown-test-range-has-face 7 7 'markdown-markup-face)
2754 (markdown-test-range-has-face 8 8 nil)
2755 (markdown-test-range-has-face 9 9 'markdown-markup-face)
2756 (markdown-test-range-has-face 10 10 'markdown-inline-code-face)
2757 (markdown-test-range-has-face 11 11 'markdown-markup-face)
2758 (markdown-test-range-has-face 12 12 nil))
2759 (markdown-test-string "a`foo`b`bar`c`baz`d"
2760 (markdown-test-range-has-face 1 1 nil)
2761 (markdown-test-range-has-face 2 2 'markdown-markup-face)
2762 (markdown-test-range-has-face 3 5 'markdown-inline-code-face)
2763 (markdown-test-range-has-face 6 6 'markdown-markup-face)
2764 (markdown-test-range-has-face 7 7 nil)
2765 (markdown-test-range-has-face 8 8 'markdown-markup-face)
2766 (markdown-test-range-has-face 9 11 'markdown-inline-code-face)
2767 (markdown-test-range-has-face 12 12 'markdown-markup-face)
2768 (markdown-test-range-has-face 13 13 nil)
2769 (markdown-test-range-has-face 14 14 'markdown-markup-face)
2770 (markdown-test-range-has-face 15 17 'markdown-inline-code-face)
2771 (markdown-test-range-has-face 18 18 'markdown-markup-face)
2772 (markdown-test-range-has-face 19 19 nil)))
2774 (ert-deftest test-markdown-font-lock/code-3 ()
2775 "Backslashes don't escape backticks inside of inline code strings."
2776 (markdown-test-string
2777 "`foo\\`bar`"
2778 (markdown-test-range-has-face 1 1 'markdown-markup-face)
2779 (markdown-test-range-has-face 2 5 'markdown-inline-code-face)
2780 (markdown-test-range-has-face 6 6 'markdown-markup-face)
2781 (markdown-test-range-has-face 7 10 nil)))
2783 (ert-deftest test-markdown-font-lock/code-link-precedence ()
2784 "Test that inline code takes precedence over inline links."
2785 (markdown-test-string
2786 "[not a `link](/foo`)"
2787 (markdown-test-range-has-face 1 7 nil)
2788 (markdown-test-range-has-face 8 8 'markdown-markup-face)
2789 (markdown-test-range-has-face 9 18 'markdown-inline-code-face)
2790 (markdown-test-range-has-face 19 19 'markdown-markup-face)
2791 (markdown-test-range-has-face 20 20 nil)))
2793 (ert-deftest test-markdown-font-lock/code-in-link-text ()
2794 "Test that inline code in link text is fontified properly"
2795 (markdown-test-string
2796 "[`this is a` link](/foo)"
2797 (markdown-test-range-has-face 1 2 'markdown-markup-face)
2798 (markdown-test-range-has-face 3 11 'markdown-inline-code-face)
2799 (markdown-test-range-has-face 12 12 'markdown-markup-face)
2800 (markdown-test-range-has-face 3 17 'markdown-link-face)
2801 (markdown-test-range-has-face 18 19 'markdown-markup-face)
2802 (markdown-test-range-has-face 20 23 'markdown-url-face)
2803 (markdown-test-range-has-face 24 24 'markdown-markup-face)))
2805 (ert-deftest test-markdown-font-lock/code-italics-precedence ()
2806 "Test that inline code takes precedence over italics.
2807 Test currently fails because this case isn't handled properly."
2808 (markdown-test-string
2809 "*text `code* text`"
2810 (markdown-test-range-has-face 1 6 nil)
2811 (markdown-test-range-has-face 7 7 'markdown-markup-face)
2812 (markdown-test-range-has-face 8 17 'markdown-inline-code-face)
2813 (markdown-test-range-has-face 18 18 'markdown-markup-face)))
2815 (ert-deftest test-markdown-font-lock/code-in-comment ()
2816 "Test that inline code is not matched inside a comment."
2817 (markdown-test-string
2818 "<!-- `not code` -->"
2819 (markdown-test-range-has-face 1 19 'markdown-comment-face)
2820 (should-not (markdown-range-property-any 1 19 'face '(markdown-inline-code-face)))))
2822 (ert-deftest test-markdown-font-lock/consecutive-html-comments ()
2823 "Test for consecutive HTML comments.
2824 Detail: https://github.com/jrblevin/markdown-mode/issues/584"
2825 (markdown-test-string
2826 "Main text <!--a comment--><!--another comment-->."
2827 (markdown-test-range-has-face 11 26 'markdown-comment-face)
2828 (markdown-test-range-has-face 27 28 'markdown-comment-face)))
2830 (ert-deftest test-markdown-font-lock/kbd ()
2831 "Test font lock for <kbd> tags."
2832 (markdown-test-string "<kbd>C-c <</kbd>"
2833 (markdown-test-range-has-face 1 5 'markdown-markup-face)
2834 (markdown-test-range-has-face 6 10 'markdown-inline-code-face)
2835 (markdown-test-range-has-face 11 16 'markdown-markup-face))
2836 (markdown-test-string "To quit Emacs, press <kbd>C-x C-c</kbd>."
2837 (markdown-test-range-has-face 1 21 nil)
2838 (markdown-test-range-has-face 22 26 'markdown-markup-face)
2839 (markdown-test-range-has-face 27 33 'markdown-inline-code-face)
2840 (markdown-test-range-has-face 34 39 'markdown-markup-face)
2841 (markdown-test-range-has-face 40 40 nil)))
2843 (ert-deftest test-markdown-font-lock/lists-1 ()
2844 "A simple list marker font lock test."
2845 (markdown-test-file "lists.text"
2846 (dolist (loc (list 1063 1283 1659 1830 1919 2150 2393 2484
2847 2762 2853 3097 3188 3700 3903 4009))
2848 (goto-char loc)
2849 (should (looking-at "[*+-]"))
2850 (markdown-test-range-has-face loc loc 'markdown-list-face))))
2852 (ert-deftest test-markdown-font-lock/lists-2 ()
2853 "Test markdown-list-face with markdown-list-indent-width.
2854 See https://github.com/jrblevin/markdown-mode/issues/405 ."
2855 (let ((markdown-list-indent-width 2))
2856 (markdown-test-string "
2857 * level 1
2858 * level 2
2859 * level 3
2860 * level 4
2861 * level 5"
2862 (markdown-test-range-has-face 62 62 'markdown-list-face))))
2864 (ert-deftest test-markdown-font-lock/lists-3 ()
2865 "Test markdown-list-face for too intended line.
2866 Too indented line is also treated as list rf previous line is line
2867 in Common mark.
2868 See https://github.com/jrblevin/markdown-mode/issues/569"
2869 (markdown-test-string "* [ ] One
2870 * [ ] Two
2871 * [ ] Three
2872 * [ ] Four
2873 * [ ] Five
2874 * [ ] Six"
2875 (markdown-test-range-has-face 64 64 'markdown-list-face)
2876 (markdown-test-range-has-face 85 85 'markdown-list-face)))
2878 (ert-deftest test-markdown-font-lock/lists-in-code-block ()
2879 "Test markdown-list-face in code block like diff format.
2880 See https://github.com/jrblevin/markdown-mode/issues/631"
2881 (markdown-test-string "```diff
2882 - plugins=(...)
2883 + plugins=(... fzf-collection)
2886 (should-not (markdown-range-property-any 9 9 'face '(markdown-list-face)))
2887 (should-not (markdown-range-property-any 16 16 'face '(markdown-list-face)))))
2890 (ert-deftest test-markdown-font-lock/repeated-lists ()
2891 "A simple definition list marker font lock test."
2892 (markdown-test-file "repeated-elements.text"
2893 (markdown-test-range-has-face 163 164 'markdown-list-face)
2894 (markdown-test-range-has-face 190 191 'markdown-list-face)))
2896 (ert-deftest test-markdown-font-lock/repeated-tables ()
2897 "A simple definition list marker font lock test."
2898 (markdown-test-file "repeated-elements.text"
2899 (markdown-test-range-has-face 149 155 nil)
2900 (markdown-test-range-has-face 218 336 'markdown-table-face)))
2902 (ert-deftest test-markdown-font-lock/definition-list ()
2903 "A simple definition list marker font lock test."
2904 (markdown-test-file "definition-list.text"
2905 (markdown-test-range-has-face 7 7 'markdown-list-face)
2906 (markdown-test-range-has-face 29 52 'markdown-pre-face)
2907 (markdown-test-range-has-face 55 55 'markdown-list-face)))
2909 (ert-deftest test-markdown-font-lock/pre-1 ()
2910 "Nested list and pre block font lock test."
2911 (markdown-test-file "nested-list.text"
2912 (dolist (loc (list 4 29 194 224 491 525))
2913 (markdown-test-range-has-face loc loc 'markdown-list-face))
2914 (markdown-test-range-has-face 6 25 nil)
2915 (markdown-test-range-has-face 31 83 nil)
2916 (markdown-test-range-has-face 85 154 'markdown-pre-face)
2917 (markdown-test-range-has-face 157 189 nil)
2918 (markdown-test-range-has-face 196 215 nil)
2919 (markdown-test-range-has-face 226 403 nil)
2920 (markdown-test-range-has-face 405 481 'markdown-pre-face)
2921 (markdown-test-range-has-face 493 512 nil)
2922 (markdown-test-range-has-face 527 546 nil)
2923 (markdown-test-range-has-face 548 580 'markdown-pre-face)))
2925 (ert-deftest test-markdown-font-lock/pre-2 ()
2926 (markdown-test-string "* item\n\nreset baseline\n\n pre block\n"
2927 (markdown-test-range-has-face 1 1 'markdown-list-face)
2928 (markdown-test-range-has-face 2 23 nil)
2929 (markdown-test-range-has-face 29 37 'markdown-pre-face)))
2931 (ert-deftest test-markdown-font-lock/pre-3 ()
2932 (markdown-test-string "It is interesting to see what happens when one queries
2933 `social upheaval` and `protopalatial era`.
2935 * `social upheaval`: the following queries have been tried:
2937 social upheaval subClassOf"
2938 (markdown-test-range-has-face 160 190 nil)))
2940 (ert-deftest test-markdown-font-lock/pre-4 ()
2941 "Pre blocks must be preceded by a blank line"
2942 (markdown-test-string "Paragraph
2943 for (var i = 0; i < 10; i++) {
2944 console.log(i);
2946 (markdown-test-range-has-face (point-min) (point-max) nil)))
2948 (ert-deftest test-markdown-font-lock/fenced-1 ()
2949 "Test fenced code blocks containing four-space indents."
2950 (markdown-test-string "Fenced code block
2953 if (x)
2954 foo();
2956 if (y)
2957 bar();
2960 (markdown-test-range-has-face 1 19 nil)
2961 (markdown-test-range-has-face 20 22 'markdown-markup-face)
2962 (markdown-test-range-has-face 24 59 'markdown-pre-face)
2963 (markdown-test-range-has-face 61 63 'markdown-markup-face)))
2965 (ert-deftest test-markdown-font-lock/gfm-fenced-1 ()
2966 "Test GFM-style fenced code blocks (1)."
2967 (let ((markdown-fontify-code-blocks-natively t))
2968 (markdown-test-string "```ruby
2969 require 'redcarpet'
2970 markdown = Redcarpet.new('Hello World!')
2971 puts markdown.to_html
2972 ```"
2973 (markdown-test-range-has-face 1 3 'markdown-markup-face) ; ```
2974 (markdown-test-range-has-face 4 7 'markdown-language-keyword-face) ; ruby
2975 (markdown-test-range-has-face 9 90 'markdown-code-face) ; entire code block
2976 (markdown-test-range-has-face 9 15 'font-lock-builtin-face) ; require
2977 (markdown-test-range-has-face 17 27 'font-lock-string-face) ; 'redcarpet'
2978 (markdown-test-range-has-face 40 48 'font-lock-type-face) ; Redcarpet
2979 (markdown-test-range-has-face 70 72 'font-lock-builtin-face) ; puts
2980 (markdown-test-range-has-face 92 94 'markdown-markup-face)))) ; ```
2982 (ert-deftest test-markdown-font-lock/gfm-fenced-2 ()
2983 "Test GFM-style fenced code blocks (2)."
2984 (markdown-test-string "```{r sum}\n2+2\n```"
2985 (markdown-test-range-has-face 1 3 'markdown-markup-face) ; ```
2986 (markdown-test-range-has-face 4 4 'markdown-markup-face) ; {
2987 (markdown-test-range-has-face 5 5 'markdown-language-keyword-face) ; r
2988 (markdown-test-range-has-face 7 9 'markdown-language-info-face) ; sum
2989 (markdown-test-range-has-face 10 10 'markdown-markup-face) ; }
2990 (markdown-test-range-has-face 12 14 'markdown-pre-face) ; 2+2
2991 (markdown-test-range-has-face 16 18 'markdown-markup-face))) ; ```
2993 (ert-deftest test-markdown-font-lock/gfm-fenced-3 ()
2994 "GFM-style code blocks need not be preceded by a blank line."
2995 (markdown-test-string "Paragraph
2996 ```js
2997 for (var i = 0; i < 10; i++) {
2998 console.log(i);
3000 ```"
3001 (markdown-test-range-has-face 1 10 nil) ; Paragraph
3002 (markdown-test-range-has-face 11 13 'markdown-markup-face) ; ```
3003 (markdown-test-range-has-face 14 15 'markdown-language-keyword-face) ; js
3004 (markdown-test-range-has-face 17 68 'markdown-pre-face)
3005 (markdown-test-range-has-face 70 72 'markdown-markup-face)))
3007 (ert-deftest test-markdown-font-lock/gfm-fenced-4 ()
3008 "Test GFM-style fenced code blocks (2)."
3009 (markdown-test-string "```scalaFiddle libraries=\"Java8 Time-0.1.0\"\nimport java.time._\n\nval hour = LocalTime.now().getHour()\n\nprintln(hour)\n```"
3010 (markdown-test-range-has-face 1 3 'markdown-markup-face) ; ```
3011 (markdown-test-range-has-face 4 14 'markdown-language-keyword-face) ; scalaFiddle
3012 (markdown-test-range-has-face 16 43 'markdown-language-info-face) ; libraries="Java8 Time-0.1.0"
3013 (markdown-test-range-has-face 45 115 'markdown-pre-face) ; [code]
3014 (markdown-test-range-has-face 117 119 'markdown-markup-face))) ; ```
3016 (ert-deftest test-markdown-font-lock/tilde-fenced-1 ()
3017 "Test native fontification of tilde fenced code blocks."
3018 (let ((markdown-fontify-code-blocks-natively t))
3019 (markdown-test-string "~~~ruby
3020 require 'redcarpet'
3021 markdown = Redcarpet.new('Hello World!')
3022 puts markdown.to_html
3023 ~~~"
3024 (markdown-test-range-has-face 1 3 'markdown-markup-face) ; ```
3025 (markdown-test-range-has-face 4 7 'markdown-language-keyword-face) ; ruby
3026 (markdown-test-range-has-face 9 90 'markdown-code-face) ; entire code block
3027 (markdown-test-range-has-face 9 15 'font-lock-builtin-face) ; require
3028 (markdown-test-range-has-face 17 27 'font-lock-string-face) ; 'redcarpet'
3029 (markdown-test-range-has-face 40 48 'font-lock-type-face) ; Redcarpet
3030 (markdown-test-range-has-face 70 72 'font-lock-builtin-face) ; puts
3031 (markdown-test-range-has-face 92 94 'markdown-markup-face)))) ; ```
3033 (ert-deftest test-markdown-font-lock/atx-headers ()
3034 "Test font-lock for atx headers"
3035 (markdown-test-string "## abc "
3036 (markdown-test-range-has-face 1 3 'markdown-header-delimiter-face)
3037 (markdown-test-range-has-face 4 8 'markdown-header-face-2))
3038 (markdown-test-string "## abc ##"
3039 (markdown-test-range-has-face 1 3 'markdown-header-delimiter-face)
3040 (markdown-test-range-has-face 4 6 'markdown-header-face-2)
3041 (markdown-test-range-has-face 7 9 'markdown-header-delimiter-face)))
3043 (ert-deftest test-markdown-font-lock/atx-no-spaces ()
3044 "Test font-lock for atx headers with no spaces."
3045 (markdown-test-string "##abc##"
3046 (markdown-test-range-has-face 1 7 nil))
3047 (markdown-test-string "##"
3048 (markdown-test-range-has-face 1 2 nil))
3049 (markdown-test-string "###"
3050 (markdown-test-range-has-face 1 3 nil))
3051 (markdown-test-string "## abc##"
3052 (markdown-test-range-has-face 1 3 'markdown-header-delimiter-face)
3053 (markdown-test-range-has-face 4 8 'markdown-header-face-2)))
3055 (ert-deftest test-markdown-font-lock/atx-whole-line ()
3056 "Test font-lock for atx headers with whole line flag."
3057 (let ((markdown-fontify-whole-heading-line t))
3058 (let ((markdown-hide-markup nil))
3059 (markdown-test-string "## abc \n"
3060 (markdown-test-range-has-face 4 9 'markdown-header-face-2))
3061 (markdown-test-string "## abc ##\n"
3062 (markdown-test-range-has-face 4 6 'markdown-header-face-2)
3063 (markdown-test-range-has-face 7 10 'markdown-header-delimiter-face)))
3065 (let ((markdown-hide-markup t))
3066 (markdown-test-string "## abc \n"
3067 (markdown-test-range-has-face 4 9 'markdown-header-face-2))
3068 (markdown-test-string "## abc ##\n"
3069 (markdown-test-range-has-face 4 6 'markdown-header-face-2)
3070 (markdown-test-range-has-face 7 9 'markdown-header-delimiter-face)
3071 (markdown-test-range-has-face 10 10 'markdown-header-face-2))
3074 (ert-deftest test-markdown-font-lock/setext-1-letter ()
3075 "An edge case for level-one setext headers."
3076 (markdown-test-string "a\n=\n"
3077 (markdown-test-range-has-face 1 1 'markdown-header-face-1)
3078 (markdown-test-range-has-face 3 3 'markdown-header-rule-face)))
3080 (ert-deftest test-markdown-font-lock/setext-2-letter ()
3081 "An edge case for level-two setext headers."
3082 (markdown-test-string "b\n-\n"
3083 (markdown-test-range-has-face 1 1 'markdown-header-face-2)
3084 (markdown-test-range-has-face 3 3 'markdown-header-rule-face)))
3086 (ert-deftest test-markdown-font-lock/inline-links ()
3087 "Test font lock for inline links."
3088 (let ((markdown-hide-urls nil))
3089 (markdown-test-file "inline.text"
3090 (markdown-test-range-has-face 925 925 'markdown-markup-face)
3091 (markdown-test-range-has-face 926 929 'markdown-link-face)
3092 (markdown-test-range-has-face 930 931 'markdown-markup-face)
3093 (markdown-test-range-has-face 932 949 'markdown-url-face)
3094 (markdown-test-range-has-face 951 957 'markdown-link-title-face)
3095 (markdown-test-range-has-face 958 958 'markdown-markup-face))))
3097 (ert-deftest test-markdown-font-lock/inline-links-with-parentheses ()
3098 "Test font lock for inline links with nested parentheses.
3099 See <https://github.com/jrblevin/markdown-mode/issues/170>."
3100 (let ((markdown-hide-urls nil))
3101 (markdown-test-string "[foo](bar(baz)qux)"
3102 (markdown-test-range-has-face 1 1 'markdown-markup-face)
3103 (markdown-test-range-has-face 2 4 'markdown-link-face)
3104 (markdown-test-range-has-face 5 6 'markdown-markup-face)
3105 (markdown-test-range-has-face 7 17 'markdown-url-face)
3106 (markdown-test-range-has-face 18 18 'markdown-markup-face))))
3108 (ert-deftest test-markdown-font-lock/inline-links-with-escaped-bracket ()
3109 "Test font lock for inline links with escaped bracket.
3110 Detail: https://github.com/jrblevin/markdown-mode/issues/409"
3111 (markdown-test-string "[run(Class, String \\[\\])](http://foo.com)"
3112 (markdown-test-range-has-face 1 1 'markdown-markup-face)
3113 (markdown-test-range-has-face 2 24 'markdown-link-face)
3114 (markdown-test-range-has-face 25 26 'markdown-markup-face)
3115 (markdown-test-range-has-face 27 40 'markdown-url-face)
3116 (markdown-test-range-has-face 41 41 'markdown-markup-face)))
3118 (ert-deftest test-markdown-font-lock/pre-comment ()
3119 "Test comments inside of a pre block."
3120 (markdown-test-string " <!-- pre, not comment -->"
3121 (markdown-test-range-has-face (point-min) (1- (point-max)) 'markdown-pre-face)))
3123 (ert-deftest test-markdown-font-lock/inline-code-comment ()
3124 "Test comments inside of inline code."
3125 (markdown-test-string "`<h1> <!-- HTML comment inside inline code -->`"
3126 (markdown-test-range-has-face (1+ (point-min)) (- (point-max) 2) 'markdown-inline-code-face)))
3128 (ert-deftest test-markdown-font-lock/inline-code-link ()
3129 "Test links inside of inline code."
3130 (markdown-test-string "`[text](url)`"
3131 (markdown-test-range-has-face (1+ (point-min)) (- (point-max) 2) 'markdown-inline-code-face)
3132 (should-not (markdown-range-property-any
3133 (1+ (point-min)) (- (point-max) 2) 'face
3134 '(markdown-markup-face markdown-link-face markdown-url-face)))))
3136 (ert-deftest test-markdown-font-lock/do-not-overwrite-by-link-face ()
3137 "Test links inside of table.
3138 Don't override table faces by link faces.
3139 Detail: https://github.com/jrblevin/markdown-mode/issues/716"
3140 (markdown-test-string "| Links |
3141 |------------------------------|
3142 | [Link 1](https://github.com) |
3143 | [Link 2][link-reference] |
3145 (search-forward "Link 1")
3146 (markdown-test-range-has-face (match-beginning 0) (1- (match-end 0)) 'markdown-link-face)
3147 (markdown-test-range-has-face (match-beginning 0) (1- (match-end 0)) 'markdown-table-face)
3149 (search-forward "https://github.com")
3150 (markdown-test-range-has-face (match-beginning 0) (1- (match-end 0)) 'markdown-url-face)
3151 (markdown-test-range-has-face (match-beginning 0) (1- (match-end 0)) 'markdown-table-face)
3153 (search-forward "Link 2")
3154 (markdown-test-range-has-face (match-beginning 0) (1- (match-end 0)) 'markdown-link-face)
3155 (markdown-test-range-has-face (match-beginning 0) (1- (match-end 0)) 'markdown-table-face)
3157 (search-forward "link-reference")
3158 (markdown-test-range-has-face (match-beginning 0) (1- (match-end 0)) 'markdown-reference-face)
3159 (markdown-test-range-has-face (match-beginning 0) (1- (match-end 0)) 'markdown-table-face)
3161 ;; check [] and ()
3162 (goto-char (point-min))
3163 (while (re-search-forward "[][()]" nil t)
3164 (markdown-test-range-has-face (match-beginning 0) (1- (match-end 0)) 'markdown-markup-face)
3165 (markdown-test-range-has-face (match-beginning 0) (1- (match-end 0)) 'markdown-table-face))))
3167 (ert-deftest test-markdown-font-lock/comment-hanging-indent ()
3168 "Test comments with hanging indentation."
3169 (markdown-test-string "<!-- This comment has\n hanging indentation -->"
3170 (markdown-test-range-has-face (point-min) (1- (point-max)) 'markdown-comment-face)))
3172 (ert-deftest test-markdown-font-lock/comment-multiple ()
3173 "Test multiple single-line comments in arow."
3174 (markdown-test-string "<!-- This is a comment -->\n<!-- And so is this -->"
3175 (markdown-test-range-has-face
3176 (line-beginning-position) (1- (line-end-position)) 'markdown-comment-face)
3177 (forward-line)
3178 (markdown-test-range-has-face
3179 (line-beginning-position) (1- (line-end-position)) 'markdown-comment-face)))
3181 (ert-deftest test-markdown-font-lock/comment-list-items ()
3182 "Test comment with list inside."
3183 (markdown-test-string
3184 "<!--
3185 - note 1;
3186 - note 2.
3187 -->"
3188 (markdown-test-range-face-equals (point-min) (1- (point-max))
3189 'markdown-comment-face)))
3191 (ert-deftest test-markdown-font-lock/comment-angle-bracket ()
3192 "Regression test for GH-117."
3193 (markdown-test-string "<!-- > test -->"
3194 (markdown-test-range-face-equals (point-min) (1- (point-max))
3195 'markdown-comment-face)))
3197 (ert-deftest test-markdown-font-lock/comment-link ()
3198 "Test links inside of comments."
3199 (markdown-test-string "<!-- [text](url) -->"
3200 (markdown-test-range-has-face (+ (point-min) 5) (- (point-max) 4) 'markdown-comment-face)
3201 (should-not (markdown-range-property-any
3202 (+ (point-min) 5) (- (point-max) 4) 'face
3203 '(markdown-markup-face markdown-link-face markdown-url-face)))))
3205 (ert-deftest test-markdown-font-lock/footnote-markers-links ()
3206 "Test an edge case involving footnote markers and inline reference links."
3207 (markdown-test-string "Harvard[^1] [tuition][]"
3208 (markdown-test-range-has-face 1 7 nil)
3209 (markdown-test-range-has-face 8 8 'markdown-markup-face)
3210 (markdown-test-range-has-face 10 10 'markdown-footnote-marker-face)
3211 (markdown-test-range-has-face 11 11 'markdown-markup-face)
3212 (markdown-test-range-has-face 12 12 nil)
3213 (markdown-test-range-has-face 13 13 'markdown-markup-face)
3214 (markdown-test-range-has-face 14 20 'markdown-link-face)
3215 (markdown-test-range-has-face 21 21 'markdown-markup-face)
3216 (markdown-test-range-has-face 22 23 'markdown-markup-face)))
3218 (ert-deftest test-markdown-font-lock/mmd-metadata ()
3219 "Basic MultMarkdown metadata tests."
3220 (markdown-test-string "Title: peg-multimarkdown User's Guide
3221 Author: Fletcher T. Penney
3222 Base Header Level: 2"
3223 (markdown-test-range-has-face 1 5 'markdown-metadata-key-face)
3224 (markdown-test-range-has-face 6 6 'markdown-markup-face)
3225 (markdown-test-range-has-face 8 37 'markdown-metadata-value-face)
3226 (markdown-test-range-has-face 39 44 'markdown-metadata-key-face)
3227 (markdown-test-range-has-face 46 46 'markdown-markup-face)
3228 (markdown-test-range-has-face 47 64 'markdown-metadata-value-face)
3229 (markdown-test-range-has-face 66 82 'markdown-metadata-key-face)
3230 (markdown-test-range-has-face 83 83 'markdown-markup-face)
3231 (markdown-test-range-has-face 85 85 'markdown-metadata-value-face))
3232 ;; Avoid triggering when a title contains a colon (e.g., Markdown: Syntax)
3233 (markdown-test-file "syntax.text"
3234 (markdown-test-range-has-face 1 16 'markdown-header-face-1)))
3236 (ert-deftest test-markdown-font-lock/mmd-metadata-after-header ()
3237 "Ensure that similar lines are not matched after the header."
3238 (markdown-test-string "Title: peg-multimarkdown User's Guide
3240 Author: Fletcher T. Penney
3241 Base Header Level: 2"
3242 (markdown-test-range-has-face 1 5 'markdown-metadata-key-face)
3243 (markdown-test-range-has-face 6 6 'markdown-markup-face)
3244 (markdown-test-range-has-face 8 37 'markdown-metadata-value-face)
3245 (markdown-test-range-has-face 40 65 nil)
3246 (markdown-test-range-has-face 67 86 nil)))
3248 (ert-deftest test-markdown-font-lock/mmd-metadata-after-header-with-whitespace ()
3249 "Ensure that similar lines are not matched after the header.
3250 The blank line here has two spaces, which should not change how
3251 it is parsed."
3252 (markdown-test-string
3253 "Title: peg-multimarkdown User's Guide\n \nAuthor: Fletcher T. Penney\nBase Header Level: 2\n"
3254 (markdown-test-range-has-face 1 5 'markdown-metadata-key-face)
3255 (markdown-test-range-has-face 6 6 'markdown-markup-face)
3256 (markdown-test-range-has-face 8 37 'markdown-metadata-value-face)
3257 (markdown-test-range-has-face 42 67 nil)
3258 (markdown-test-range-has-face 69 88 nil)))
3260 (ert-deftest test-markdown-font-lock/mmd-not-metadata ()
3261 "Don't treat as metadata if its line is not in header
3262 https://github.com/jrblevin/markdown-mode/issues/437"
3263 (markdown-test-string "hello world
3264 foo bar baz: one two three
3266 (markdown-test-range-has-face 13 39 nil)))
3268 (ert-deftest test-markdown-font-lock/pandoc-metadata ()
3269 "Basic Pandoc metadata tests."
3270 (markdown-test-string "% title
3271 two-line title
3272 % first author;
3273 second author
3274 % date
3276 body"
3277 (markdown-test-range-has-face 1 1 'markdown-markup-face)
3278 (markdown-test-range-has-face 3 24 'markdown-metadata-value-face)
3279 (markdown-test-range-has-face 26 26 'markdown-markup-face)
3280 (markdown-test-range-has-face 28 56 'markdown-metadata-value-face)
3281 (markdown-test-range-has-face 58 58 'markdown-markup-face)
3282 (markdown-test-range-has-face 60 63 'markdown-metadata-value-face)
3283 (markdown-test-range-has-face 64 69 nil)))
3285 (ert-deftest test-markdown-font-lock/yaml-metadata ()
3286 "Basic YAML metadata tests."
3287 (markdown-test-string
3288 "---
3289 layout: post
3290 date: 2015-08-13 11:35:25 EST
3293 (markdown-test-range-has-face 1 3 'markdown-markup-face)
3294 (markdown-test-range-has-face 5 10 'markdown-metadata-key-face)
3295 (markdown-test-range-has-face 11 11 'markdown-markup-face)
3296 (markdown-test-range-has-face 13 16 'markdown-metadata-value-face)
3297 (markdown-test-range-has-face 18 21 'markdown-metadata-key-face)
3298 (markdown-test-range-has-face 22 22 'markdown-markup-face)
3299 (markdown-test-range-has-face 24 46 'markdown-metadata-value-face)
3300 (markdown-test-range-has-face 48 50 'markdown-markup-face)))
3302 (ert-deftest test-markdown-font-lock/toml-metadata ()
3303 "Basic TOML metadata tests."
3304 (markdown-test-string
3305 "---
3306 layout = post
3307 date = 2015-08-13 11:35:25 EST
3310 (markdown-test-range-has-face 1 3 'markdown-markup-face)
3311 (markdown-test-range-has-face 5 10 'markdown-metadata-key-face)
3312 (markdown-test-range-has-face 12 12 'markdown-markup-face)
3313 (markdown-test-range-has-face 14 17 'markdown-metadata-value-face)
3314 (markdown-test-range-has-face 19 22 'markdown-metadata-key-face)
3315 (markdown-test-range-has-face 24 24 'markdown-markup-face)
3316 (markdown-test-range-has-face 26 48 'markdown-metadata-value-face)
3317 (markdown-test-range-has-face 50 52 'markdown-markup-face)))
3319 (ert-deftest test-markdown-font-lock/pandoc-yaml-metadata ()
3320 "Basic yaml metadata tests, with pandoc syntax."
3321 (let ((markdown-use-pandoc-style-yaml-metadata t))
3322 (markdown-test-string
3323 "some text
3326 layout: post
3327 date: 2015-08-13 11:35:25 EST
3330 more text
3333 layout: post
3334 date: 2015-08-13 11:35:25 EST
3337 But this is merely a code block
3341 layout: post
3342 date: 2015-08-13 11:35:25 EST
3346 ;; first section
3347 (markdown-test-range-has-face 12 14 'markdown-markup-face)
3348 (markdown-test-range-has-face 16 21 'markdown-metadata-key-face)
3349 (markdown-test-range-has-face 22 22 'markdown-markup-face)
3350 (markdown-test-range-has-face 24 27 'markdown-metadata-value-face)
3351 (markdown-test-range-has-face 29 32 'markdown-metadata-key-face)
3352 (markdown-test-range-has-face 33 33 'markdown-markup-face)
3353 (markdown-test-range-has-face 35 57 'markdown-metadata-value-face)
3354 (markdown-test-range-has-face 59 61 'markdown-markup-face)
3355 ;; second section
3356 (markdown-test-range-has-face 75 77 'markdown-markup-face)
3357 (markdown-test-range-has-face 79 84 'markdown-metadata-key-face)
3358 (markdown-test-range-has-face 85 85 'markdown-markup-face)
3359 (markdown-test-range-has-face 87 90 'markdown-metadata-value-face)
3360 (markdown-test-range-has-face 92 95 'markdown-metadata-key-face)
3361 (markdown-test-range-has-face 96 96 'markdown-markup-face)
3362 (markdown-test-range-has-face 98 120 'markdown-metadata-value-face)
3363 (markdown-test-range-has-face 122 124 'markdown-markup-face)
3364 ;; third section
3365 (markdown-test-range-has-face 160 162 'markdown-markup-face)
3366 (markdown-test-range-has-face 164 213 'markdown-pre-face)
3367 (markdown-test-range-has-face 215 217 'markdown-markup-face))))
3369 (ert-deftest test-markdown-font-lock/yaml-metadata-nested ()
3370 "Test font lock for metadata which has nested values
3371 Detail: https://github.com/jrblevin/markdown-mode/issues/476"
3372 (markdown-test-string
3373 "---
3374 references:
3375 - type: article-journal
3376 author:
3377 - family: Watson
3378 given: J. D.
3381 (markdown-test-range-has-face 5 14 'markdown-metadata-key-face)
3382 (markdown-test-range-has-face 19 22 'markdown-metadata-key-face)
3383 (markdown-test-range-has-face 25 39 'markdown-metadata-value-face)
3384 (markdown-test-range-has-face 43 48 'markdown-metadata-key-face)
3385 (markdown-test-range-has-face 55 60 'markdown-metadata-key-face)
3386 (markdown-test-range-has-face 63 68 'markdown-metadata-value-face)
3387 (markdown-test-range-has-face 74 78 'markdown-metadata-key-face)
3388 (markdown-test-range-has-face 81 85 'markdown-metadata-value-face)))
3390 (ert-deftest test-markdown-font-lock/line-break ()
3391 "Basic line break tests."
3392 (markdown-test-string " \nasdf \n"
3393 (markdown-test-range-has-face 1 9 nil)
3394 (markdown-test-range-has-face 10 11 'markdown-line-break-face)))
3396 (ert-deftest test-markdown-font-lock/line-break-at-end-of-buffer ()
3397 "Don't apply markdown-line-break-face at end of buffer without new line.
3398 Details: https://github.com/jrblevin/markdown-mode/issues/621"
3399 (markdown-test-string " \nasdf "
3400 (markdown-test-range-has-face 10 11 'nil)))
3402 (ert-deftest test-markdown-font-lock/blockquote-bold ()
3403 "Test font lock for bold inside of a blockquote."
3404 (markdown-test-string
3405 "> **bold**"
3406 (markdown-test-range-has-face 1 10 'markdown-blockquote-face)
3407 (markdown-test-range-has-face 5 8 'markdown-bold-face)))
3409 (ert-deftest test-markdown-font-lock/blockquote-italic ()
3410 "Test font lock for italic inside of a blockquote."
3411 (markdown-test-string
3412 "> *italic*"
3413 (markdown-test-range-has-face 1 10 'markdown-blockquote-face)
3414 (markdown-test-range-has-face 4 9 'markdown-italic-face)))
3416 (ert-deftest test-markdown-font-lock/blockquote-code ()
3417 "Test font lock for inline code inside of a blockquote."
3418 (markdown-test-string
3419 "> `code`"
3420 (markdown-test-range-has-face 1 8 'markdown-blockquote-face)
3421 (markdown-test-range-has-face 3 3 'markdown-markup-face)
3422 (markdown-test-range-has-face 4 7 'markdown-inline-code-face)
3423 (markdown-test-range-has-face 8 8 'markdown-markup-face)))
3425 (ert-deftest test-markdown-font-lock/blockquote-link ()
3426 "Test font lock for links inside of a blockquote.
3427 This test will fail until font lock for inline links inside
3428 blockquotes is implemented (at present, the blockquote face
3429 takes precedence)."
3430 (markdown-test-string
3431 "> [link](url)"
3432 (markdown-test-range-has-face 1 1 'markdown-markup-face)
3433 (markdown-test-range-has-face 2 13 'markdown-blockquote-face)
3434 (markdown-test-range-has-face 3 3 'markdown-markup-face)
3435 (markdown-test-range-has-face 4 7 'markdown-link-face)
3436 (markdown-test-range-has-face 8 9 'markdown-markup-face)
3437 (markdown-test-range-has-face 10 12 'markdown-url-face)
3438 (markdown-test-range-has-face 13 13 'markdown-markup-face)))
3440 (ert-deftest test-markdown-font-lock/blockquote-comment ()
3441 "Test font lock for comments inside of a blockquote."
3442 (markdown-test-string
3443 "> <!-- comment -->"
3444 (markdown-test-range-has-face 1 1 'markdown-markup-face)
3445 (markdown-test-range-has-face 3 18 'markdown-comment-face)))
3447 (ert-deftest test-markdown-font-lock/pre-override ()
3448 "Test that font lock for pre blocks overrides everything else."
3449 (markdown-test-string
3450 " **bold**
3451 _italic_
3452 <!-- comment -->
3453 [link](url)
3454 * list"
3455 (markdown-test-range-has-face 1 73 'markdown-pre-face)))
3457 (ert-deftest test-markdown-font-lock/gfm-code-block-font-lock ()
3458 "GFM code block font lock test. Now in base markdown-mode as well!"
3459 (markdown-test-file "gfm.text"
3460 (markdown-test-range-has-face 2639 2641 'markdown-markup-face) ; ```
3461 (markdown-test-range-has-face 2642 2645 'markdown-language-keyword-face) ; lang
3462 (markdown-test-range-has-face 2647 2728 'markdown-pre-face) ; code
3463 (markdown-test-range-has-face 2730 2732 'markdown-markup-face))) ; ```
3465 (ert-deftest test-markdown-font-lock/gfm-code-block-with-one-line-block ()
3466 "Highlighting gfm code block with one line triple quote blocks.
3467 Detail: https://github.com/jrblevin/markdown-mode/issues/684"
3468 (markdown-test-string-gfm "```sudo ln -s `which mkdir` /usr/bin/mkdir```
3470 Install Foreman. For running Rails, Sidekiq and anything else:
3472 ```ruby
3473 rails db:migrate RAILS_ENV=test
3474 ```"
3475 (forward-line 2)
3476 (markdown-test-range-has-face (point) (line-end-position) nil)
3477 (re-search-forward "ruby")
3478 (goto-char (match-beginning 0))
3479 (markdown-test-range-has-face (point) (+ (point) 3) 'markdown-language-keyword-face)
3480 (forward-line 1)
3481 (markdown-test-range-has-face (point) (line-end-position) 'markdown-pre-face)))
3483 (ert-deftest test-markdown-font-lock/reference-definition ()
3484 "Reference definitions should not include ]."
3485 (let ((markdown-hide-urls nil))
3486 (markdown-test-string "[1]: http://daringfireball.net/ \"title\""
3487 (markdown-test-range-has-face 2 2 'markdown-reference-face) ; 1
3488 (markdown-test-range-has-face 6 31 'markdown-url-face) ; URL
3489 (markdown-test-range-has-face 34 38 'markdown-link-title-face)) ; title
3490 (markdown-test-string "[foo][1] and [bar][2]: not a reference definition"
3491 (markdown-test-range-has-face 2 4 'markdown-link-face) ; foo
3492 (markdown-test-range-has-face 7 7 'markdown-reference-face) ; 1
3493 (markdown-test-range-has-face 9 13 nil) ; [ ]and[ ]
3494 (markdown-test-range-has-face 15 17 'markdown-link-face) ; bar
3495 (markdown-test-range-has-face 20 20 'markdown-reference-face) ; 2
3496 (markdown-test-range-has-face 22 49 nil)))) ; [ ]and[ ]
3498 (ert-deftest test-markdown-font-lock/subscripts ()
3499 "Test font lock for subscripts."
3500 (markdown-test-string "H~2~0"
3501 (markdown-test-range-has-face 2 2 'markdown-markup-face) ; First ~
3502 (markdown-test-range-has-face 3 3 nil) ; 2
3503 (markdown-test-range-has-face 4 4 'markdown-markup-face))) ; Second ~
3505 (ert-deftest test-markdown-font-lock/superscripts ()
3506 "Test font lock for subscripts."
3507 (markdown-test-string "334^10^"
3508 (markdown-test-range-has-face 1 3 nil) ; 334
3509 (markdown-test-range-has-face 4 4 'markdown-markup-face) ; First ^
3510 (markdown-test-range-has-face 5 6 nil) ; 10
3511 (markdown-test-range-has-face 7 7 'markdown-markup-face)) ; Second ^
3512 (markdown-test-string "1.0 x 10^-15^
3513 10^+15^"
3514 ;; -
3515 (markdown-test-range-has-face 1 8 nil)
3516 (markdown-test-range-has-face 9 9 'markdown-markup-face)
3517 (markdown-test-range-has-face 10 12 nil)
3518 (markdown-test-range-has-face 13 13 'markdown-markup-face)
3519 ;; +
3520 (markdown-test-range-has-face 15 16 nil)
3521 (markdown-test-range-has-face 17 17 'markdown-markup-face)
3522 (markdown-test-range-has-face 18 20 nil)
3523 (markdown-test-range-has-face 21 21 'markdown-markup-face))
3524 ;; Unicode minus sign
3525 (markdown-test-string "10^−15^" ;; unicode minus sign U+2212
3526 (search-forward "^")
3527 (markdown-test-range-has-face (1- (point)) (1- (point)) 'markdown-markup-face)
3528 (search-forward "^")
3529 (markdown-test-range-has-face (1- (point)) (1- (point)) 'markdown-markup-face)))
3531 (ert-deftest test-markdown-font-lock/hidden-urls-inline ()
3532 "Test URL hiding and toggling."
3533 (let ((markdown-hide-urls t))
3534 (markdown-test-file "inline.text"
3535 (markdown-test-range-has-face 925 925 'markdown-markup-face)
3536 (markdown-test-range-has-face 926 929 'markdown-link-face)
3537 (markdown-test-range-has-face 930 931 'markdown-markup-face)
3538 (markdown-test-range-has-face 932 949 'markdown-url-face)
3539 (markdown-test-range-has-face 951 957 'markdown-link-title-face)
3540 (markdown-test-range-has-face 958 958 'markdown-markup-face)
3541 (should (get-text-property 932 'composition)))))
3543 (ert-deftest test-markdown-font-lock/hidden-urls-reference ()
3544 "Test URL hiding and toggling."
3545 (let ((markdown-hide-urls t))
3546 (markdown-test-string "[link][15]"
3547 ;; Two-character reference labels shouldn't get composed.
3548 (markdown-test-range-has-face 1 1 'markdown-markup-face)
3549 (markdown-test-range-has-face 2 5 'markdown-link-face)
3550 (markdown-test-range-has-face 6 7 'markdown-markup-face)
3551 (markdown-test-range-has-face 8 9 'markdown-reference-face)
3552 (markdown-test-range-has-face 10 10 'markdown-markup-face)
3553 (should-not (get-text-property 8 'composition)))
3554 (markdown-test-string "[link][long-reference-label]"
3555 ;; Longer reference labels should be composed
3556 (markdown-test-range-has-face 1 1 'markdown-markup-face)
3557 (markdown-test-range-has-face 2 5 'markdown-link-face)
3558 (markdown-test-range-has-face 6 7 'markdown-markup-face)
3559 (markdown-test-range-has-face 8 27 'markdown-reference-face)
3560 (markdown-test-range-has-face 28 28 'markdown-markup-face)
3561 (should (get-text-property 8 'composition)))))
3563 (ert-deftest test-markdown-font-lock/snake-case-code-in-heading ()
3564 "Test underscores in inline code in headings."
3565 (markdown-test-string "# Title with `snake_case_code`"
3566 (should-not (markdown-range-property-any 21 24 'face '(markdown-italic-face)))
3567 (markdown-test-range-has-face 15 29 'markdown-inline-code-face)))
3569 (ert-deftest test-markdown-font-lock/stars-in-code-in-heading ()
3570 "Test asterisks in inline code in headings."
3571 (markdown-test-string "# Title with `char** foo, int* bar`"
3572 (should-not (markdown-range-property-any 20 29 'face '(markdown-italic-face)))
3573 (markdown-test-range-has-face 15 34 'markdown-inline-code-face)))
3575 (ert-deftest test-markdown-font-lock/stars-in-code-in-blockquote ()
3576 "Test asterisks in inline code in blockquote."
3577 (markdown-test-string "> Quote with `**stars**`"
3578 (should-not (markdown-range-property-any
3579 17 21 'face '(markdown-italic-face markdown-bold-face)))
3580 (markdown-test-range-has-face 15 23 'markdown-inline-code-face)))
3582 (ert-deftest test-markdown-font-lock/two-bold-words-after-list ()
3583 "Test two bold words after a list marker."
3584 (markdown-test-string "- **foo** **bar**"
3585 (should-not (markdown-range-property-any
3586 (point-min) (point-max) 'face '(markdown-italic-face)))))
3588 (ert-deftest test-markdown-font-lock/heading-with-italics-and-bold ()
3589 "Test two bold words after a list marker."
3590 (markdown-test-string "# Title with *italics* and **bold**"
3591 (markdown-test-range-has-face 15 21 'markdown-italic-face)
3592 (markdown-test-range-has-face 30 33 'markdown-bold-face)
3593 (should-not (markdown-range-property-any 30 33 'face '(markdown-italic-face)))))
3595 (ert-deftest test-markdown-font-lock/hr-vs-level-2-setext ()
3596 "Test that HRs are distinguished from setext H2 markup."
3597 (markdown-test-file "outline.text"
3598 (goto-char 485)
3599 (should (markdown-on-heading-p))
3600 (beginning-of-line)
3601 (should (markdown-on-heading-p))
3602 (should-not (markdown-range-property-any 453 484 'face '(markdown-hr-face)))))
3604 (ert-deftest test-markdown-font-lock/heading-code-block-no-whitespace ()
3605 "Headings immediately before code blocks should be identified correctly.
3606 See GH-234."
3607 (markdown-test-string
3608 "#### code snippet
3609 ```javascript
3610 const styles = require('gadgets/dist/styles.css');
3611 ```"
3612 (goto-char (point-min))
3613 (forward-word)
3614 (should (markdown-on-heading-p))
3615 (should (markdown-match-propertized-text 'markdown-heading (line-end-position)))
3616 (goto-char (match-beginning 0))
3617 (should (markdown-outline-level))
3618 (should (= (markdown-outline-level) 4))
3619 (markdown-test-range-has-face 6 17 'markdown-header-face-4)
3620 (end-of-line)
3621 (should-not (markdown-code-block-at-point-p))))
3623 (ert-deftest test-markdown-font-lock/hr-underscore-with-spaces ()
3624 "Test font-lock for HR with spaced underscores."
3625 (markdown-test-string "_ _ _ _ _ _ _\n"
3626 (markdown-test-range-face-equals (point-min) (- (point-max) 2) 'markdown-hr-face)))
3628 (ert-deftest test-markdown-font-lock/hr-underscore-no-spaces ()
3629 "Test font-lock for HR with underscores and no spaces."
3630 (markdown-test-string "_____________\n"
3631 (markdown-test-range-face-equals (point-min) (- (point-max) 2) 'markdown-hr-face)))
3633 (ert-deftest test-markdown-font-lock/inline-attributes ()
3634 "Test inline attributes before a fenced code block."
3635 (markdown-test-file "Leanpub.md"
3636 ;; Inline attributes for a heading
3637 (markdown-test-range-has-face 38 42 'markdown-markup-face)
3638 ;; Inline attributes inside an aside block
3639 (markdown-test-range-has-face 123 141 'markdown-markup-face)
3640 ;; Inline attributes before a fenced code block
3641 (markdown-test-range-has-face 632 696 'markdown-markup-face)))
3643 (ert-deftest test-markdown-font-lock/leanpub-sections ()
3644 "Test Leanpub section markers."
3645 (markdown-test-file "Leanpub.md"
3646 ;; {frontmatter}
3647 (markdown-test-range-has-face 12 24 'markdown-markup-face)
3648 ;; {mainmatter}
3649 (markdown-test-range-has-face 69 80 'markdown-markup-face)
3650 ;; {pagebreak}
3651 (markdown-test-range-has-face 427 437 'markdown-markup-face)))
3653 (ert-deftest test-markdown-font-lock/leanpub-include ()
3654 "Test Leanpub include syntax."
3655 (markdown-test-file "Leanpub.md"
3656 ;; no title
3657 (markdown-test-range-has-face 561 563 'markdown-markup-face)
3658 (markdown-test-range-has-face 564 577 'markdown-url-face)
3659 (markdown-test-range-has-face 578 578 'markdown-markup-face)
3660 ;; title
3661 (markdown-test-range-has-face 581 583 'markdown-markup-face)
3662 (markdown-test-range-has-face 584 611 'markdown-link-title-face)
3663 (markdown-test-range-has-face 612 613 'markdown-markup-face)
3664 (markdown-test-range-has-face 614 628 'markdown-url-face)
3665 (markdown-test-range-has-face 629 629 'markdown-markup-face)))
3667 (ert-deftest test-markdown-font-lock/curly-brace-include ()
3668 "Test curly brace include syntax."
3669 (markdown-test-string "<<{file}"
3670 (markdown-test-range-has-face 1 3 'markdown-markup-face)
3671 (markdown-test-range-has-face 4 7 'markdown-url-face)
3672 (markdown-test-range-has-face 8 8 'markdown-markup-face)))
3674 (ert-deftest test-markdown-font-lock/square-bracket-include ()
3675 "Test square bracket include syntax."
3676 (markdown-test-string "<<[file]"
3677 (markdown-test-range-has-face 1 3 'markdown-markup-face)
3678 (markdown-test-range-has-face 4 7 'markdown-url-face)
3679 (markdown-test-range-has-face 8 8 'markdown-markup-face)))
3681 (ert-deftest test-markdown-font-lock/pandoc-inline-footnote ()
3682 "Test font lock for Pandoc inline footnotes."
3683 (markdown-test-string "Here is an inline note.^[Inline notes are easier to write, since
3684 you don't have to pick an identifier and move down to type the
3685 note.] And then you can close it and continue writing."
3686 (markdown-test-range-has-face 1 23 nil)
3687 (markdown-test-range-has-face 24 25 'markdown-markup-face)
3688 (markdown-test-range-has-face 26 133 'markdown-footnote-text-face)
3689 (markdown-test-range-has-face 134 134 'markdown-markup-face)))
3691 (ert-deftest test-markdown-font-lock/pandoc-inline-footnote-across-block ()
3692 "Test font lock for Pandoc inline footnotes."
3693 (markdown-test-string "Inline notes should not^[match
3695 across blocks]"
3696 (markdown-test-range-has-face (point-min) (point-max) nil)))
3698 (ert-deftest test-markdown-font-lock/html-entity-named ()
3699 "Test basic font-lock support for named HTML entities."
3700 (markdown-test-string "&nbsp;"
3701 (markdown-test-range-has-face 1 6 'markdown-html-entity-face)))
3703 (ert-deftest test-markdown-font-lock/html-entity-hex ()
3704 "Test basic font-lock support for hexadecimal HTML entities."
3705 (markdown-test-string "&#x272a;"
3706 (markdown-test-range-has-face 1 8 'markdown-html-entity-face)))
3708 (ert-deftest test-markdown-font-lock/html-entity-decimal ()
3709 "Test basic font-lock support for decimal HTML entities."
3710 (markdown-test-string "&#9;"
3711 (markdown-test-range-has-face 1 4 'markdown-html-entity-face)))
3713 (ert-deftest test-markdown-font-lock/html-entity-in-inline-code ()
3714 "Test that HTML entities are not matched inside inline code."
3715 (markdown-test-string "`&#9;`"
3716 (markdown-test-range-has-face 1 1 'markdown-markup-face)
3717 (markdown-test-range-has-face 2 5 'markdown-inline-code-face)
3718 (markdown-test-range-has-face 6 6 'markdown-markup-face)
3719 (should-not (markdown-range-property-any 1 6 'face '(markdown-html-entity-face)))))
3721 (ert-deftest test-markdown-font-lock/html-entity-in-gfm-code-block ()
3722 "Test that HTML entities are not matched inside GFM code blocks."
3723 (markdown-test-string "```\n&nbsp;\n&#x272a;\n&#9;\n```"
3724 (should-not
3725 (markdown-range-property-any
3726 (point-min) (point-max) 'face '(markdown-html-entity-face)))))
3728 (ert-deftest test-markdown-font-lock/html-tags-in-syntax-file ()
3729 "Test matching HTML tags in syntax.text."
3730 (markdown-test-file "syntax.text"
3731 ;; <ul id="ProjectSubmenu">
3732 (markdown-test-range-has-face 36 36 'markdown-html-tag-delimiter-face)
3733 (markdown-test-range-has-face 37 38 'markdown-html-tag-name-face)
3734 (markdown-test-range-has-face 40 41 'markdown-html-attr-name-face)
3735 (markdown-test-range-has-face 42 42 'markdown-html-tag-delimiter-face)
3736 (markdown-test-range-has-face 43 58 'markdown-html-attr-value-face)
3737 (markdown-test-range-has-face 59 59 'markdown-html-tag-delimiter-face)
3738 ;; <li>
3739 (markdown-test-range-has-face 65 65 'markdown-html-tag-delimiter-face)
3740 (markdown-test-range-has-face 66 67 'markdown-html-tag-name-face)
3741 (markdown-test-range-has-face 68 68 'markdown-html-tag-delimiter-face)
3742 ;; <a href="/projects/markdown/" title="Markdown Project Page">
3743 (markdown-test-range-has-face 69 69 'markdown-html-tag-delimiter-face)
3744 (markdown-test-range-has-face 70 70 'markdown-html-tag-name-face)
3745 (markdown-test-range-has-face 72 75 'markdown-html-attr-name-face)
3746 (markdown-test-range-has-face 76 76 'markdown-html-tag-delimiter-face)
3747 (markdown-test-range-has-face 77 97 'markdown-html-attr-value-face)
3748 (markdown-test-range-has-face 99 103 'markdown-html-attr-name-face)
3749 (markdown-test-range-has-face 104 104 'markdown-html-tag-delimiter-face)
3750 (markdown-test-range-has-face 105 127 'markdown-html-attr-value-face)
3751 (markdown-test-range-has-face 128 128 'markdown-html-tag-delimiter-face)))
3753 (ert-deftest test-markdown-font-lock/html-tag-in-gfm-code-block ()
3754 "Test that HTML tags are not matched inside GFM code blocks."
3755 (markdown-test-string "```\n<ul id=\"ProjectSubmenu\">\n```"
3756 (should-not
3757 (markdown-range-property-any
3758 (point-min) (point-max) 'face
3759 '(markdown-html-tag-name-face
3760 markdown-html-tag-delimiter-face
3761 markdown-html-attr-name-face
3762 markdown-html-attr-value-face)))))
3764 (ert-deftest test-markdown-font-lock/html-tag-in-code-block ()
3765 "Test that HTML tags are not matched inside code blocks."
3766 (markdown-test-string " <ul id=\"ProjectSubmenu\">"
3767 (should-not
3768 (markdown-range-property-any
3769 (point-min) (point-max) 'face
3770 '(markdown-html-tag-name-face
3771 markdown-html-tag-delimiter-face
3772 markdown-html-attr-name-face
3773 markdown-html-attr-value-face)))))
3775 (ert-deftest test-markdown-font-lock/html-tag-in-inline-code ()
3776 "Test that HTML tags are not matched inside inline code spans."
3777 (markdown-test-string "`<ul id=\"ProjectSubmenu\">`"
3778 (should-not
3779 (markdown-range-property-any
3780 (point-min) (point-max) 'face
3781 '(markdown-html-tag-name-face
3782 markdown-html-tag-delimiter-face
3783 markdown-html-attr-name-face
3784 markdown-html-attr-value-face)))))
3786 (ert-deftest test-markdown-font-lock/html-disabled ()
3787 "Test disabling font-lock for HTML tags"
3788 (let ((markdown-enable-html nil))
3789 (markdown-test-file "syntax.text"
3790 (should-not
3791 (markdown-range-property-any
3792 (point-min) (point-max) 'face
3793 '(markdown-html-tag-name-face
3794 markdown-html-tag-delimiter-face
3795 markdown-html-attr-name-face
3796 markdown-html-attr-value-face))))))
3798 (ert-deftest test-markdown-font-lock/html-tag-angle-bracket ()
3799 "Test a hard to parse HTML attribute with an angle bracket."
3800 (markdown-test-string "<img title=\"displays >\" src=\"big.gif\">"
3801 (markdown-test-range-has-face 1 1 'markdown-html-tag-delimiter-face)
3802 (markdown-test-range-has-face 2 4 'markdown-html-tag-name-face)
3803 (markdown-test-range-has-face 6 10 'markdown-html-attr-name-face)
3804 (markdown-test-range-has-face 11 11 'markdown-html-tag-delimiter-face)
3805 (markdown-test-range-has-face 12 23 'markdown-html-attr-value-face)
3806 (markdown-test-range-has-face 25 27 'markdown-html-attr-name-face)
3807 (markdown-test-range-has-face 28 28 'markdown-html-tag-delimiter-face)
3808 (markdown-test-range-has-face 29 37 'markdown-html-attr-value-face)
3809 (markdown-test-range-has-face 38 38 'markdown-html-tag-delimiter-face)))
3811 (ert-deftest test-markdown-font-lock/highlighting-syntax ()
3812 "Test highlighting syntax ==foo==."
3813 (let ((markdown-enable-highlighting-syntax t))
3814 (markdown-test-string "==foo=="
3815 (markdown-test-range-has-face 1 2 'markdown-markup-face)
3816 (markdown-test-range-has-face 3 5 'markdown-highlighting-face)
3817 (markdown-test-range-has-face 6 7 'markdown-markup-face)))
3818 (markdown-test-string "==foo=="
3819 (markdown-test-range-has-face 1 7 nil)))
3821 ;;; Markdown Parsing Functions:
3823 (ert-deftest test-markdown-parsing/extend-region-function ()
3824 "Test `markdown-syntax-propertize-extend-region'.
3825 Should return a cons (NEW-START . NEW-END) or nil if no
3826 adjustment should be made. Function is called repeatedly until it
3827 returns nil."
3828 (markdown-test-file
3829 "inline.text"
3830 (should (equal (markdown-syntax-propertize-extend-region 1 17)
3831 (cons 1 91)))
3832 (should (equal (markdown-syntax-propertize-extend-region 2 17)
3833 (cons 1 91)))
3834 (should (equal (markdown-syntax-propertize-extend-region 1 91)
3835 nil))
3836 (should (equal (markdown-syntax-propertize-extend-region 93 157)
3837 nil))
3838 (should (equal (markdown-syntax-propertize-extend-region 496 502)
3839 (cons 486 511)))
3840 (should (equal (markdown-syntax-propertize-extend-region 486 511)
3841 nil))
3842 ;; Region that begins and ends with \n\n should not be extended
3843 (should (equal (markdown-syntax-propertize-extend-region 157 355)
3844 nil))))
3846 (defun markdown-test-check-match-limits (prop num begin end &optional pos)
3847 (let* ((posn (or pos (point)))
3848 (props (get-text-property posn prop)))
3849 (save-match-data
3850 (set-match-data props)
3851 (should (match-beginning num))
3852 (should (match-end num))
3853 (should (= (match-beginning num) begin))
3854 (should (= (match-end num) end)))))
3856 (ert-deftest test-markdown-parsing/syntax-with-adjacent-code-blocks ()
3857 "Test `markdown-syntax-propertize-fenced-code-blocks' with adjacent blocks."
3858 (markdown-test-string
3859 "~~~ shell
3860 #!/bin/sh
3862 echo \"Hello, world!\"
3865 ~~~ shell
3866 #!/bin/sh
3868 echo \"Hello, world v2!\"
3871 (let ((start-top-1 (make-marker)) (end-top-1 (make-marker))
3872 (start-lang-1 (make-marker)) (end-lang-1 (make-marker))
3873 (start-mid-1 (make-marker)) (end-mid-1 (make-marker))
3874 (start-bottom-1 (make-marker)) (end-bottom-1 (make-marker))
3875 (between (make-marker))
3876 (start-top-2 (make-marker)) (end-top-2 (make-marker))
3877 (start-lang-2 (make-marker)) (end-lang-2 (make-marker))
3878 (start-mid-2 (make-marker)) (end-mid-2 (make-marker))
3879 (start-bottom-2 (make-marker)) (end-bottom-2 (make-marker)))
3880 ;; First code block
3881 (set-marker start-top-1 1)
3882 (set-marker end-top-1 4)
3883 (set-marker start-lang-1 5)
3884 (set-marker end-lang-1 10)
3885 (set-marker start-mid-1 11)
3886 (set-marker end-mid-1 43)
3887 (set-marker start-bottom-1 43)
3888 (set-marker end-bottom-1 46)
3889 ;; check top tildes
3890 (markdown-test-check-match-limits
3891 'markdown-tilde-fence-begin 1 (marker-position start-top-1)
3892 (marker-position end-top-1) (marker-position start-top-1))
3893 ;; check top language specifier
3894 (markdown-test-check-match-limits
3895 'markdown-tilde-fence-begin 3 (marker-position start-lang-1)
3896 (marker-position end-lang-1) (marker-position start-lang-1))
3897 ;; check text in between
3898 (markdown-test-check-match-limits
3899 'markdown-fenced-code 0 (marker-position start-mid-1)
3900 (marker-position end-mid-1) (marker-position start-mid-1))
3901 ;; check bottom tildes
3902 (markdown-test-check-match-limits
3903 'markdown-tilde-fence-end 1 (marker-position start-bottom-1)
3904 (marker-position end-bottom-1) (marker-position start-bottom-1))
3905 ;; Point between code blocks
3906 (set-marker between 47)
3907 (should (equal (get-text-property between 'markdown-fenced-code)
3908 nil))
3909 ;; Second code block
3910 (set-marker start-top-2 48)
3911 (set-marker end-top-2 51)
3912 (set-marker start-lang-2 52)
3913 (set-marker end-lang-2 57)
3914 (set-marker start-mid-2 58)
3915 (set-marker end-mid-2 93)
3916 (set-marker start-bottom-2 93)
3917 (set-marker end-bottom-2 96)
3918 (markdown-test-check-match-limits
3919 'markdown-tilde-fence-begin 1 (marker-position start-top-2)
3920 (marker-position end-top-2) (marker-position start-top-2))
3921 (markdown-test-check-match-limits
3922 'markdown-tilde-fence-begin 3 (marker-position start-lang-2)
3923 (marker-position end-lang-2) (marker-position start-lang-2))
3924 (markdown-test-check-match-limits
3925 'markdown-fenced-code 0 (marker-position start-mid-2)
3926 (marker-position end-mid-2) (marker-position start-mid-2))
3927 (markdown-test-check-match-limits
3928 'markdown-tilde-fence-end 1 (marker-position start-bottom-2)
3929 (marker-position end-bottom-2) (marker-position start-bottom-2))
3930 ;; ;; Move point between code blocks and insert a character
3931 (goto-char between)
3932 (insert "x")
3933 ;; Re-propertize region after change
3934 (let ((range (markdown-syntax-propertize-extend-region (1- between) (point-max))))
3935 (markdown-syntax-propertize (car range) (cdr range)))
3936 ;; Re-check first code block
3937 (markdown-test-check-match-limits
3938 'markdown-tilde-fence-begin 1 (marker-position start-top-1)
3939 (marker-position end-top-1) (marker-position start-top-1))
3940 (markdown-test-check-match-limits
3941 'markdown-tilde-fence-begin 3 (marker-position start-lang-1)
3942 (marker-position end-lang-1) (marker-position start-lang-1))
3943 (markdown-test-check-match-limits
3944 'markdown-fenced-code 0 (marker-position start-mid-1)
3945 (marker-position end-mid-1) (marker-position start-mid-1))
3946 (markdown-test-check-match-limits
3947 'markdown-tilde-fence-end 1 (marker-position start-bottom-1)
3948 (marker-position end-bottom-1) (marker-position start-bottom-1))
3949 ;; Re-check point between code blocks
3950 (should (equal (get-text-property between 'markdown-fenced-code)
3951 nil))
3952 ;; Re-check second code block
3953 (markdown-test-check-match-limits
3954 'markdown-tilde-fence-begin 1 (marker-position start-top-2)
3955 (marker-position end-top-2) (marker-position start-top-2))
3956 (markdown-test-check-match-limits
3957 'markdown-tilde-fence-begin 3 (marker-position start-lang-2)
3958 (marker-position end-lang-2) (marker-position start-lang-2))
3959 (markdown-test-check-match-limits
3960 'markdown-fenced-code 0 (marker-position start-mid-2)
3961 (marker-position end-mid-2) (marker-position start-mid-2))
3962 (markdown-test-check-match-limits
3963 'markdown-tilde-fence-end 1 (marker-position start-bottom-2)
3964 (marker-position end-bottom-2)
3965 (marker-position start-bottom-2)))))
3967 (ert-deftest test-markdown-parsing/propertize-fenced-in-between ()
3968 "Test whether `markdown-syntax-propertize-fenced-block-constructs' handles the
3969 case when it can't propertize both the start and end of a fenced block within a
3970 single pass (the end of the block is past the END argument)."
3971 (markdown-test-string
3972 "~~~ shell
3973 #!/bin/sh
3975 echo \"Hello, world!\"
3978 (set-text-properties (point-min) (point-max) nil)
3979 ;; syntax-propertize up to right after hashbang
3980 (markdown-syntax-propertize-fenced-block-constructs (point-min) 21)
3981 ;; ~~~ shell should be propertized, but nothing else
3982 ;; check tildes
3983 (markdown-test-check-match-limits 'markdown-tilde-fence-begin 1 1 4 1)
3984 ;; check language
3985 (markdown-test-check-match-limits 'markdown-tilde-fence-begin 3 5 10 5)
3986 ;; middle should not be propertized
3987 (should-not (get-text-property 11 'markdown-fenced-code))
3988 ;; neither should end
3989 (should-not (get-text-property 43 'markdown-tilde-fence-end))
3990 (markdown-syntax-propertize-fenced-block-constructs 21 (point-max))
3991 ;; everything should be propertized now
3992 ;; re-check top
3993 (markdown-test-check-match-limits 'markdown-tilde-fence-begin 1 1 4 1)
3994 (markdown-test-check-match-limits 'markdown-tilde-fence-begin 3 5 10 5)
3995 ;; check middle
3996 (markdown-test-check-match-limits 'markdown-fenced-code 0 10 43 10)
3997 ;; check ending tildes
3998 (markdown-test-check-match-limits 'markdown-tilde-fence-end 1 43 46 43)))
4000 (ert-deftest test-markdown-parsing/code-block-at-pos-pre-indent ()
4001 "Ensure `markdown-code-block-at-pos' works in a pre block."
4002 (markdown-test-string
4003 " pre code
4004 random stuff
4005 more preformatted code"
4006 (should (equal (markdown-code-block-at-pos 1) '(1 57)))
4007 (should (equal (markdown-code-block-at-pos 30) '(1 57)))
4008 (should (equal (markdown-code-block-at-pos (point-max)) '(1 57)))))
4010 (ert-deftest test-markdown-parsing/code-block-at-pos-tilde-fenced ()
4011 "Ensure `markdown-code-block-at-pos' works in tilde fenced blocks."
4012 (markdown-test-string
4013 "~~~ ruby
4014 some_ruby_fun()
4015 ~~~"
4016 (should (equal (markdown-code-block-at-pos 1) '(1 29)))
4017 (should (equal (markdown-code-block-at-pos 10) '(1 29)))
4018 (should (equal (markdown-code-block-at-pos 26) '(1 29)))))
4020 (ert-deftest test-markdown-parsing/code-block-at-pos-gfm-fenced ()
4021 "Ensure `markdown-code-block-at-pos' works in GFM fenced blocks."
4022 (markdown-test-string
4023 "``` {.bash}
4024 #!/bin/sh
4025 echo hey
4026 ```"
4027 (should (equal (markdown-code-block-at-pos 1) '(1 35)))
4028 (should (equal (markdown-code-block-at-pos 13) '(1 35)))
4029 (should (equal (markdown-code-block-at-pos 23) '(1 35)))
4030 (should (equal (markdown-code-block-at-pos 34) '(1 35)))
4031 (should (equal (markdown-code-block-at-pos 35) nil))))
4033 (ert-deftest test-markdown-parsing/code-block-at-pos-yaml-metadata ()
4034 "Ensure `markdown-code-block-at-pos' works in YAML metadata blocks."
4035 (let ((markdown-use-pandoc-style-yaml-metadata t))
4036 (markdown-test-string
4037 "---
4038 a: b
4042 data: pandoc
4043 ..."
4044 ;; First YAML block
4045 (should (equal (markdown-code-block-at-pos 1) '(1 13)))
4046 (should (equal (markdown-code-block-at-pos 5) '(1 13)))
4047 (should (equal (markdown-code-block-at-pos 12) '(1 13)))
4048 ;; Pandoc YAML block
4049 (should (equal (markdown-code-block-at-pos 15) '(15 35)))
4050 (should (equal (markdown-code-block-at-pos 19) '(15 35)))
4051 (should (equal (markdown-code-block-at-pos 34) '(15 35)))
4052 (should (equal (markdown-code-block-at-pos 35) nil)))))
4054 (ert-deftest test-markdown-parsing/syntax-get-fenced-blocks ()
4055 "Test whether *-get-fenced-block-* functions work in the case where a block is
4056 only partially propertized."
4057 (save-match-data
4058 (markdown-test-string
4059 "~~~
4061 (should (equal (markdown-syntax-propertize-extend-region
4062 (point-min) (point-max))
4063 nil))
4064 (goto-char 1)
4065 (set-match-data (markdown-text-property-at-point
4066 'markdown-tilde-fence-begin))
4067 (should (equal (markdown-get-fenced-block-from-start
4068 'markdown-tilde-fence-begin)
4069 nil)))
4070 (markdown-test-string
4071 "~~~
4072 ~~~"
4073 (goto-char 1)
4074 (set-match-data (markdown-text-property-at-point
4075 'markdown-tilde-fence-begin))
4076 (should (equal (markdown-get-fenced-block-from-start
4077 'markdown-tilde-fence-begin)
4078 (list 1 8)))
4079 (should (equal (markdown-code-block-at-pos (point)) (list 1 8)))
4081 ;; markdown-code-block-at-point-p should not modify match data
4082 (set-match-data (list 1 2 3 4))
4083 (should (markdown-code-block-at-point-p))
4084 (should (equal (match-data) (list 1 2 3 4)))
4086 (goto-char 5)
4087 (set-match-data (markdown-text-property-at-point
4088 'markdown-tilde-fence-end))
4089 (should (equal (markdown-get-fenced-block-from-end
4090 'markdown-tilde-fence-end)
4091 (list 1 8)))
4092 (should (equal (markdown-code-block-at-pos (point)) (list 1 8))))
4093 (markdown-test-string
4094 "~~~
4096 ~~~"
4097 (goto-char 1)
4098 (set-match-data (markdown-text-property-at-point
4099 'markdown-tilde-fence-begin))
4100 (should (equal (markdown-get-fenced-block-from-start
4101 'markdown-tilde-fence-begin)
4102 (list 1 9)))
4103 (should (equal (markdown-code-block-at-pos (point)) (list 1 9)))
4104 (goto-char 5)
4105 (set-match-data (markdown-text-property-at-point 'markdown-fenced-code))
4106 (should (equal (markdown-get-fenced-block-from-middle
4107 'markdown-fenced-code)
4108 (list 1 9)))
4109 (should (equal (markdown-code-block-at-pos (point)) (list 1 9)))
4110 (goto-char 6)
4111 (set-match-data (markdown-text-property-at-point
4112 'markdown-tilde-fence-end))
4113 (should (equal (markdown-get-fenced-block-from-end
4114 'markdown-tilde-fence-end)
4115 (list 1 9)))
4116 (should (equal (markdown-code-block-at-pos (point)) (list 1 9))))))
4118 (ert-deftest test-markdown-parsing/reference-definition-basic ()
4119 "Test reference definition function."
4120 (markdown-test-file "syntax.text"
4121 ;; Test accuracy of returned text and bounds
4122 (should (equal (markdown-reference-definition "1")
4123 (list "http://docutils.sourceforge.net/mirror/setext.html" 1942 1992)))
4124 (should (equal (markdown-reference-definition "2")
4125 (list "http://www.aaronsw.com/2002/atx/" 2000 2032)))
4126 ;; Test that match data remains intact
4127 (should (string-equal (match-string 5) "http://www.aaronsw.com/2002/atx/"))
4128 ;; Test anchor-only relative URL
4129 (should (equal (markdown-reference-definition "bq")
4130 (list "#blockquote" 7536 7547)))
4131 ;; Example references that appear in pre blocks in the text
4132 (should (not (markdown-reference-definition "")))
4133 (should (not (markdown-reference-definition "id")))
4134 (should (not (markdown-reference-definition "foo")))
4135 (should (not (markdown-reference-definition "A")))
4136 (should (not (markdown-reference-definition "Google")))
4137 ;; Test that we don't pick up other text in square brackets
4138 (should (not (markdown-reference-definition "blockquoting")))
4139 (should (not (markdown-reference-definition "square brackets")))
4140 ;; Test case insensitivity
4141 (should (equal (markdown-reference-definition "SRC")
4142 (list "/projects/markdown/syntax.text" 1245 1275)))))
4144 (ert-deftest test-markdown-parsing/get-defined-references ()
4145 "Test `markdown-get-defined-references'."
4146 (markdown-test-file "syntax.text"
4147 (should (equal (markdown-get-defined-references)
4148 '(("src" . 37)
4149 ("1" . 55)
4150 ("2" . 56)
4151 ("3" . 57)
4152 ("4" . 58)
4153 ("5" . 59)
4154 ("6" . 60)
4155 ("bq" . 205)
4156 ("l" . 206)))))
4157 (markdown-test-file "outline.text"
4158 (should (equal (markdown-get-defined-references) nil)))
4159 (markdown-test-file "wiki-links.text"
4160 (should (equal (markdown-get-defined-references) nil))))
4162 (ert-deftest test-markdown-parsing/get-used-uris ()
4163 "Test `markdown-get-used-uris'."
4164 (markdown-test-file "syntax.text"
4165 (let ((uris (markdown-get-used-uris)))
4166 (should (equal (nth 0 uris) "#overview"))
4167 (should (equal (nth 20 uris) "http://www.aaronsw.com/2002/atx/"))
4168 (should-not (member "http://example.com/" uris))
4169 (should-not (member "address@example.com" uris)))))
4171 (defun markdown-test-test-region (beg end)
4172 (goto-char (1- beg))
4173 (should-not (markdown-inline-code-at-point-p))
4174 (goto-char (1+ end))
4175 (should-not (markdown-inline-code-at-point-p))
4176 (dolist (loc (number-sequence beg end))
4177 (goto-char loc)
4178 (should (markdown-inline-code-at-point))
4179 (should (equal (match-beginning 0) beg))
4180 (should (equal (match-end 0) (1+ end)))))
4182 (ert-deftest test-markdown-parsing/inline-code-at-point ()
4183 "Test `markdown-inline-code-at-point'."
4184 (markdown-test-file "inline.text"
4185 (markdown-test-test-region 45 50) ; Regular code span
4186 (markdown-test-test-region 61 89) ; Code containing backticks
4187 (markdown-test-test-region 228 239) ; Backquotes at beginning
4188 (markdown-test-test-region 341 351) ; Backquotes at end
4189 (markdown-test-test-region 460 468) ; Backslash as final character
4190 (markdown-test-test-region 657 666) ; A code span crossing lines
4191 (markdown-test-test-region 749 757) ; Three backquotes on same line
4192 (markdown-test-test-region 806 814) ; Three backquotes across lines
4195 (ert-deftest test-markdown-parsing/inline-code-at-point-one-space ()
4196 "Test `markdown-inline-code-at-point' with multiple code spans in a row."
4197 (markdown-test-string "`foo` `bar` `baz`"
4198 (dolist (loc (number-sequence 1 5)) ; `foo`
4199 (goto-char loc)
4200 ;; markdown-inline-code-at-point should set match data
4201 (should (markdown-inline-code-at-point))
4202 (should (equal (match-data) (list 1 6 1 2 2 5 5 6)))
4203 ;; markdown-inline-code-at-point-p should not modify match data
4204 (set-match-data (list 1 2 3 4))
4205 (should (markdown-inline-code-at-point-p))
4206 (should (equal (match-data) (list 1 2 3 4))))
4207 (dolist (loc (number-sequence 7 11)) ; `bar`
4208 (goto-char loc)
4209 (should (markdown-inline-code-at-point))
4210 (should (equal (match-data) (list 7 12 7 8 8 11 11 12))))
4211 (dolist (loc (number-sequence 13 17)) ; `baz`
4212 (goto-char loc)
4213 (should (markdown-inline-code-at-point))
4214 (should (equal (match-data) (list 13 18 13 14 14 17 17 18))))))
4216 (ert-deftest test-markdown-parsing/inline-code-at-point-no-space ()
4217 "Test `markdown-inline-code-at-point' with multiple code spans in a row.."
4218 (markdown-test-string "a`foo`b`bar`c`baz`d"
4219 (goto-char 1) ; "a"
4220 (should-not (markdown-inline-code-at-point-p))
4221 (dolist (loc (number-sequence 2 6)) ; "`foo`"
4222 (goto-char loc)
4223 (should (markdown-inline-code-at-point))
4224 (should (equal (match-data) (list 2 7 2 3 3 6 6 7))))
4225 (dolist (loc (number-sequence 8 12)) ; "`bar`"
4226 (goto-char loc)
4227 (should (markdown-inline-code-at-point))
4228 (should (equal (match-data) (list 8 13 8 9 9 12 12 13))))
4229 (dolist (loc (number-sequence 14 18)) ; "`baz`"
4230 (goto-char loc)
4231 (should (markdown-inline-code-at-point))
4232 (should (equal (match-data) (list 14 19 14 15 15 18 18 19))))))
4234 (ert-deftest test-markdown-parsing/code-at-point-blank-line ()
4235 "Test `markdown-inline-code-at-point-p' at beginning of block."
4236 (markdown-test-string "----------\n\n## foo\n"
4237 (should-not (markdown-inline-code-at-point-p))
4238 (forward-line)
4239 (should-not (markdown-inline-code-at-point-p))
4240 (forward-line)
4241 (should-not (markdown-inline-code-at-point-p))))
4243 (ert-deftest test-markdown-parsing/in-comment-p-position ()
4244 "Test `markdown-in-comment-p'."
4245 (markdown-test-string
4246 "HTML <!-- foo --> comment"
4247 (should (eq (point) (point-min)))
4248 (should-not (markdown-in-comment-p (point-max)))
4249 (should (eq (point) (point-min)))))
4251 (ert-deftest test-markdown-parsing/match-comments ()
4252 "Test `markdown-match-comments'."
4253 (markdown-test-string
4254 "HTML <!-- foo --> comment"
4255 (should (markdown-match-comments (point-max)))
4256 (should (eq (point) 18))
4257 (should (equal (match-data) (list 6 18)))
4258 (should-not (markdown-match-comments (point-max)))))
4260 (ert-deftest test-markdown-parsing/range-property-any ()
4261 "Test behavior of `markdown-range-property-any'."
4262 (markdown-test-file
4263 "inline.text"
4264 (should (markdown-range-property-any
4265 (point-min) (line-end-position)
4266 'face '(markdown-markup-face markdown-italic-face)))
4267 (should-not (markdown-range-property-any
4268 (point-min) (line-end-position)
4269 'face '(markdown-bold-face)))))
4271 (ert-deftest test-markdown-parsing/inline-code ()
4272 "Don't cause infinite loop for inline code just after metadata block
4273 Detail: https://github.com/jrblevin/markdown-mode/issues/115"
4274 (markdown-test-string "---
4275 x: x
4279 (should (markdown-match-code (point-max)))
4280 (should (= (point) 18))
4281 (should (equal (match-data t) '(14 17 14 15 15 16 16 17)))
4282 (should-not (markdown-match-code (point-max)))))
4284 (ert-deftest test-markdown-parsing/list-item-at-point ()
4285 "Test `markdown-list-item-at-point-p'."
4286 (markdown-test-file "lists.text"
4287 (let ((orig-match-data '(1 2 3 4))
4288 (not-list-points '(273 399 512 3615))
4289 (list-points '(1063 1063 1176 1283 1659 1830 1919 2150
4290 2393 2484 2762 2853 3097 3188 3700
4291 3903 4009)))
4292 ;; markdown-inline-code-at-point-p should not modify match data
4293 (set-match-data orig-match-data)
4294 ;; Not list items
4295 (dolist (pos not-list-points)
4296 (goto-char pos)
4297 (should-not (markdown-list-item-at-point-p))
4298 (should (equal (match-data) orig-match-data)))
4299 ;; List items
4300 (dolist (pos list-points)
4301 (goto-char pos)
4302 (should (markdown-list-item-at-point-p))
4303 (should (equal (match-data) orig-match-data))))))
4305 (ert-deftest test-markdown-parsing/heading-at-point ()
4306 "Test `markdown-heading-at-point'."
4307 (save-match-data
4308 (markdown-test-file "outline.text"
4309 (should-not (markdown-heading-at-point))
4310 (markdown-test-goto-heading "An underline-style header")
4311 (forward-line -1)
4312 (should (markdown-heading-at-point))
4313 (should (equal (match-data t) (get-text-property (point) 'markdown-heading)))
4314 (should (equal (match-data t) (get-text-property (point) 'markdown-heading-1-setext))))))
4316 (ert-deftest test-markdown-parsing/inline-link-in-code-block ()
4317 "Test `markdown-match-generic-links'."
4318 (markdown-test-string " **bold**
4319 _italic_
4320 <!-- comment -->
4321 [link](url)
4322 * list"
4323 (goto-char (point-min))
4324 ;; The link inside the pre block should not match.
4325 (should-not (markdown-match-generic-links (point-max) nil))
4326 ;; Point should be left at limit.
4327 (should (= (point) (point-max)))))
4329 (ert-deftest test-markdown-parsing/broken-inline-link ()
4330 "Test `markdown-match-generic-links' with an invalid link."
4331 (markdown-test-string "[site1](http://site1.com
4332 [site2](http://site2.com)
4333 [site3](http://site3.com)"
4334 (goto-char (point-min))
4335 (let ((limit (line-end-position)))
4336 ;; The first link is broken and shouldn't match.
4337 (should-not (markdown-match-generic-links limit nil))
4338 ;; Subsequent search shouldn't match, so point should move to limit.
4339 (should (= (point) limit)))
4340 ;; The second link should still match, starting from (point-min).
4341 (let ((limit (line-end-position 2)))
4342 (should (markdown-match-generic-links limit nil))
4343 (should (= (point) (match-end 0))))
4344 ;; The third link should match when starting past the second one.
4345 (goto-char (match-end 0))
4346 (should (markdown-match-generic-links (point-max) nil))
4347 (should (= (point) (match-end 0)))))
4349 (ert-deftest test-markdown-parsing/code-block-lang ()
4350 "Test `markdown-code-block-lang'."
4351 ;; Test with GFM code blocks.
4352 (markdown-test-file "GFM.md"
4353 ;; Test a call with the optional argument.
4354 (should (string-equal
4355 (markdown-code-block-lang
4356 '(1455 . markdown-gfm-block-begin)) "js"))
4357 ;; Test a call without the optional argument.
4358 (goto-char 1504) ;; middle of a GFM code block
4359 (should (string-equal (markdown-code-block-lang) "js")))
4360 ;; Test with tilde-fenced cdoe blocks.
4361 (markdown-test-file "outline-code.text"
4362 (goto-char 107) ;; middle of a tilde fenced code block
4363 (should (string-equal (markdown-code-block-lang
4364 '(83 . markdown-tilde-fence-begin)) "bash"))))
4366 (ert-deftest test-markdown-parsing/get-lang-mode ()
4367 "Test `markdown-get-lang-mode'.
4368 Do not load major-mode function if it isn't in auto-mode-alist.
4369 Details: https://github.com/jrblevin/markdown-mode/issues/761"
4370 (should (eq (markdown-get-lang-mode "emacs-lisp") 'emacs-lisp-mode))
4372 (let ((auto-mode-alist nil))
4373 (should (null (markdown-get-lang-mode "emacs-lisp")))))
4375 (ert-deftest test-markdown-parsing/get-lang-mode-from-remap-alist ()
4376 "Test `markdown-get-lang-mode' from major-mode-remap-alist.
4377 Details: https://github.com/jrblevin/markdown-mode/issues/787"
4378 (when (and (fboundp 'treesit-language-available-p)
4379 (funcall 'treesit-language-available-p 'python))
4380 (let ((major-mode-remap-alist '((python-mode . python-ts-mode))))
4381 (should (eq (markdown-get-lang-mode "python") 'python-ts-mode)))))
4383 (ert-deftest test-markdown-parsing/code-block-lang-period ()
4384 "Test `markdown-code-block-lang' when language name begins with a period."
4385 (markdown-test-string "~~~ { .ruby }
4386 puts 'hello, world'
4389 (should (string-equal (markdown-code-block-lang) "ruby"))))
4391 ;;; Reference Checking:
4393 (ert-deftest test-markdown-references/get-unused-refs ()
4394 "Test `markdown-get-unused-refs'."
4395 (markdown-test-file "refs.text"
4396 (should (equal (markdown-get-unused-refs)
4397 '(("logorrhea" . 8)
4398 ("orphan" . 11))))))
4400 (ert-deftest test-markdown-references/get-undefined-refs ()
4401 "Test `markdown-get-undefined-refs'."
4402 (markdown-test-file "refs.text"
4403 (should (equal (markdown-get-undefined-refs)
4404 '(("problems" ("problems" . 3) ("controversy" . 5)))))))
4406 (ert-deftest test-markdown-references/goto-line-button ()
4407 "Create and test a goto line button."
4408 (markdown-test-string "line 1\nline 2\n"
4409 ;; Store the temporary buffer with the text
4410 (let ((target (current-buffer)))
4411 ;; Create a new buffer for inserting
4412 (with-temp-buffer
4413 ;; Verify that point is in a different buffer
4414 (should (not (equal (current-buffer) target)))
4415 ;; Insert and press the button
4416 (insert-button "goto line 2"
4417 :type 'markdown-goto-line-button
4418 'target-buffer target
4419 'target-line 2)
4420 (should (string-equal (buffer-string) "goto line 2"))
4421 (backward-button 1)
4422 (call-interactively 'push-button)
4423 ;; Verify that point is on line 2 of target buffer
4424 (should (= (line-number-at-pos) 2))
4425 (should (looking-at "line 2"))
4426 (should (equal (current-buffer) target))))))
4428 (ert-deftest test-markdown-references/button-map ()
4429 "Verify that button-buffer-map is used for check references buffer."
4430 (markdown-test-string "[undefined][ref]\n"
4431 (let* ((target (buffer-name))
4432 (check (format "*Undefined references for %s*" target)))
4433 (markdown-check-refs)
4434 (with-current-buffer (get-buffer check)
4435 (should (equal (local-key-binding (kbd "TAB")) 'forward-button))
4436 (should (equal (local-key-binding (kbd "<backtab>")) 'backward-button))))))
4438 (ert-deftest test-markdown-references/undefined-refs-killing ()
4439 "Test that buttons in unused references buffer delete lines when pushed."
4440 (markdown-test-file "refs.text"
4441 (let* ((target (buffer-name))
4442 (check (replace-regexp-in-string
4443 "%buffer%" target
4444 markdown-unused-references-buffer))
4445 (original-unused-refs (markdown-get-unused-refs)))
4446 (markdown-unused-refs)
4447 ;; Push X
4448 (with-current-buffer (get-buffer check)
4449 (forward-button 1)
4450 (call-interactively 'push-button))
4451 ;; The first orphan should now be gone with the rest of orphans
4452 ;; moved up by one line
4453 (should (equal (markdown-get-unused-refs)
4454 (mapcar (lambda (o) (cons (car o) (1- (cdr o))))
4455 (cdr original-unused-refs)))))))
4457 ;;; Lists:
4459 (ert-deftest test-markdown-lists/nested-list-file ()
4460 "Test list item propertization for a nested list."
4461 (markdown-test-file "nested-list.text"
4462 (let ((values '(((1 25 3 5 "- " nil))
4463 ((26 189 3 5 "- " nil))
4464 ((191 581 3 5 "- " nil))
4465 ((217 482 7 9 "- " nil)
4466 (191 581 3 5 "- " nil))
4467 ((484 581 7 9 "- " nil)
4468 (191 581 3 5 "- " nil))
4469 ((514 581 11 13 "- " nil)
4470 (484 581 7 9 "- " nil)
4471 (191 581 3 5 "- " nil)))))
4472 (cl-loop
4473 for value in values
4474 do (should
4475 (equal (mapcar #'butlast (get-text-property (point) 'markdown-list-item)) value))
4476 (markdown-outline-next)))))
4478 (ert-deftest test-markdown-lists/levels-1 ()
4479 "Test list levels function `markdown-calculate-list-levels'."
4480 (markdown-test-file "nested-list.text"
4481 (let ((values '(((1 . 1) . nil) ((2 . 13) . (3)) ((14 . 23) . (7 3))
4482 ((24 . 26) . (11 7 3)))))
4483 (cl-loop for (range . value) in values
4484 do (goto-char (point-min))
4485 (forward-line (1- (car range)))
4486 (dotimes (_ (- (cdr range) (car range)))
4487 (should (equal (markdown-calculate-list-levels) value))
4488 (forward-line))))))
4490 (ert-deftest test-markdown-lists/levels-2 ()
4491 "Test list levels function `markdown-calculate-list-levels'."
4492 (markdown-test-file "syntax.text"
4493 (let ((values '(((1 . 13) . nil) ((14 . 14) . (0)) ((15 . 17) . (4 0))
4494 ((18 . 18) . (0)) ((19 . 24) . (4 0)) ((25 . 25) . (0))
4495 ((26 . 29) . (4 0)) ((30 . 30) . (0)) ((31 . 33) . (4 0))
4496 ((34 . 588) . nil) ((589 . 595) . (0)) ((596 . 814) . nil)
4497 ((815 . 820) . (0)) ((821 . 898) . nil))))
4498 (cl-loop for (range . value) in values
4499 do (goto-char (point-min))
4500 (forward-line (1- (car range)))
4501 (dotimes (_ (- (cdr range) (car range)))
4502 (should (equal (markdown-calculate-list-levels) value))
4503 (forward-line))))))
4505 (ert-deftest test-markdown-lists/levels-interior ()
4506 "Test `markdown-calculate-list-levels' from inside a list item."
4507 (markdown-test-file "nested-list.text"
4508 (goto-char 36)
4509 (should (equal (markdown-calculate-list-levels) (list 3)))
4510 (goto-char 267)
4511 (should (equal (markdown-calculate-list-levels) (list 7 3)))
4512 (goto-char 540)
4513 (should (equal (markdown-calculate-list-levels) (list 11 7 3)))))
4515 (ert-deftest test-markdown-lists/bounds-1 ()
4516 "Test list item bounds function `markdown-cur-list-item-bounds'."
4517 (markdown-test-file "lists.text"
4518 (markdown-test-goto-heading "Case 9")
4519 (forward-line)
4520 (should (eq (point) 3699))
4521 (markdown-next-list-item 4)
4522 (should (eq (point) 3700))
4523 (should (equal (butlast (markdown-cur-list-item-bounds))
4524 (list 3700 3901 0 4 "- " nil)))
4525 (markdown-next-list-item 4)
4526 (should (eq (point) 3903))
4527 (should (equal (butlast (markdown-cur-list-item-bounds))
4528 (list 3903 3937 0 4 "* " nil)))))
4530 (ert-deftest test-markdown-lists/bounds-2 ()
4531 "Function `markdown-cur-list-item-bounds' should return nil outside of list items."
4532 (markdown-test-string "line one\n\n* item\n"
4533 (should (null (markdown-cur-list-item-bounds)))
4534 (forward-line)
4535 (should (null (markdown-cur-list-item-bounds)))
4536 (forward-line)
4537 (should (markdown-cur-list-item-bounds))))
4539 (ert-deftest test-markdown-lists/bounds-prev ()
4540 "Test list item bounds function `markdown-prev-list-item-bounds'."
4541 (markdown-test-file "lists.text"
4542 (markdown-test-goto-heading "Case 9")
4543 (markdown-next-list-item 4)
4544 (markdown-next-list-item 4)
4545 (should (eq (point) 3903))
4546 (should (equal (butlast (markdown-prev-list-item-bounds))
4547 (list 3700 3901 0 4 "- " nil)))))
4549 (ert-deftest test-markdown-lists/bounds-next ()
4550 "Test list item bounds function `markdown-next-list-item-bounds'."
4551 (markdown-test-file "lists.text"
4552 (markdown-test-goto-heading "Case 2")
4553 (goto-char 1283)
4554 (should-not (markdown-next-list-item-bounds))
4555 (markdown-test-goto-heading "Case 9")
4556 (markdown-next-list-item 4)
4557 (should (eq (point) 3700))
4558 (should (equal (butlast (markdown-next-list-item-bounds))
4559 (list 3903 3937 0 4 "* " nil)))))
4561 (ert-deftest test-markdown-lists/bounds-gfm-task-list-item ()
4562 "Test `markdown-cur-list-item-bounds' with a GFM task list item."
4563 (markdown-test-string " - [ ] task name"
4564 (should (equal (butlast (markdown-cur-list-item-bounds))
4565 '(1 18 2 4 "- " "[ ] ")))))
4567 (ert-deftest test-markdown-lists/gfm-task-list-item-at-point-1 ()
4568 "Test `markdown-gfm-task-list-item-at-point' with regular list items."
4569 (markdown-test-file "nested-list.text"
4570 (dolist (pos '(1 26 36 267 514 540))
4571 (goto-char pos)
4572 (should-not (markdown-gfm-task-list-item-at-point)))))
4574 (ert-deftest test-markdown-lists/gfm-task-list-item-at-point-2 ()
4575 "Test `markdown-gfm-task-list-item-at-point' with a task list item."
4576 (markdown-test-string " - [ ] task"
4577 (should (markdown-gfm-task-list-item-at-point))))
4579 (ert-deftest test-markdown-insertion/insert-gfm-task-list-item ()
4580 "Test `markdown-insert-list-item' in a GFM task list."
4581 (markdown-test-string " - [ ] task"
4582 (goto-char (point-max))
4583 (call-interactively 'markdown-insert-list-item)
4584 (should (string-equal (buffer-string) " - [ ] task\n - [ ] "))))
4586 (ert-deftest test-markdown-lists/promotion-and-demotion-1 ()
4587 "Test function `markdown-promote-list-item'."
4588 (markdown-test-file "nested-list.text"
4589 (forward-line)
4590 (markdown-demote-list-item)
4591 (should (looking-at-p " - List level 1 item 2
4593 Second paragraph of item 2
4595 Nested pre block in item 2
4596 Four spaces past the marker
4598 Another paragraph of item 2"))
4599 (markdown-promote-list-item)
4600 (should (looking-at-p " - List level 1 item 2
4602 Second paragraph of item 2
4604 Nested pre block in item 2
4605 Four spaces past the marker
4607 Another paragraph of item 2"))))
4609 (ert-deftest test-markdown-lists/promotion-and-demotion-2 ()
4610 "Test function `markdown-promote-list-item'."
4611 (markdown-test-file "nested-list.text"
4612 (forward-line 22)
4613 (should (looking-at-p " - List level 3 item 1
4615 Nested pre block"))
4616 (markdown-demote-list-item)
4617 (should (looking-at-p " - List level 3 item 1
4619 Nested pre block"))
4620 (markdown-promote-list-item)
4621 (should (looking-at-p " - List level 3 item 1
4623 Nested pre block"))))
4625 (ert-deftest test-markdown-lists/promotion-and-demotion-custom ()
4626 "Test custom variable `markdown-list-indent-width'."
4627 (markdown-test-file "nested-list.text"
4628 (forward-line)
4629 (should (looking-at " - List level 1 item 2
4631 Second paragraph of item 2
4633 Nested pre block in item 2
4634 Four spaces past the marker
4636 Another paragraph of item 2"))
4637 (let ((markdown-list-indent-width 2))
4638 (markdown-demote-list-item))
4639 (should (looking-at " - List level 1 item 2
4641 Second paragraph of item 2
4643 Nested pre block in item 2
4644 Four spaces past the marker
4646 Another paragraph of item 2"))))
4648 (ert-deftest test-markdown-lists/add-gfm-checkbox ()
4649 (markdown-test-file "check-items.text"
4650 (goto-char (point-min))
4651 (end-of-line)
4652 (should (markdown-insert-gfm-checkbox))
4653 (should (= (line-number-at-pos (point)) 1))
4654 (should (eolp))
4655 (should (string-equal (buffer-substring-no-properties (line-beginning-position) (point))
4656 " * [ ] "))
4658 (forward-line 2)
4659 (back-to-indentation)
4660 (should (markdown-insert-gfm-checkbox))
4661 (should (= (line-number-at-pos (point)) 3))
4662 (should (string-equal (buffer-substring-no-properties (line-beginning-position) (point))
4663 " * [ ] "))
4664 (should (string-equal (buffer-substring-no-properties (point) (line-end-position))
4665 "item1"))
4667 (forward-line 2)
4668 (back-to-indentation)
4669 (forward-char 1)
4670 (should (markdown-insert-gfm-checkbox))
4671 (should (= (line-number-at-pos (point)) 5))
4672 (should (string-equal (buffer-substring-no-properties (line-beginning-position) (point))
4673 " * [ ] i"))
4674 (should (string-equal (buffer-substring-no-properties (point) (line-end-position))
4675 "tem2"))
4677 (forward-line 2)
4678 (back-to-indentation)
4679 (forward-char 2)
4680 (should (markdown-insert-gfm-checkbox))
4681 (should (= (line-number-at-pos (point)) 7))
4682 (should (string-equal (buffer-substring-no-properties (line-beginning-position) (point))
4683 "- [ ] "))
4684 (should (string-equal (buffer-substring-no-properties (point) (line-end-position))
4685 "item3"))
4687 (forward-line 2)
4688 (back-to-indentation)
4689 (forward-char 3)
4690 (should (markdown-insert-gfm-checkbox))
4691 (should (= (line-number-at-pos (point)) 9))
4692 (should (string-equal (buffer-substring-no-properties (line-beginning-position) (point))
4693 "- [ ] i"))
4694 (should (string-equal (buffer-substring-no-properties (point) (line-end-position))
4695 "tem4"))
4697 (forward-line 2)
4698 (end-of-line)
4699 (should-not (markdown-insert-gfm-checkbox))
4700 (should (= (line-number-at-pos (point)) 11))
4701 (should (eolp))
4702 (should (string-equal (buffer-substring-no-properties (line-beginning-position) (point))
4703 "* [ ] item5"))
4705 (forward-line 1)
4706 (back-to-indentation)
4707 (should (markdown-insert-gfm-checkbox))
4708 (should (= (line-number-at-pos (point)) 12))
4709 (should (eolp))
4710 (should (string-equal (buffer-substring-no-properties
4711 (line-beginning-position)
4712 (point))
4713 "* [ ] "))))
4715 (ert-deftest test-markdown-lists/toggle-gfm-checkbox ()
4716 (markdown-test-string " - [X] GFM task list item"
4717 (should (string-equal (markdown-toggle-gfm-checkbox) "[ ]"))
4718 (should (string-equal (buffer-string) " - [ ] GFM task list item"))
4719 (should (string-equal (markdown-toggle-gfm-checkbox) "[x]"))
4720 (should (string-equal (buffer-string) " - [x] GFM task list item"))))
4722 (ert-deftest test-markdown-lists/clean-list-numbers ()
4723 "Test for `markdown-cleanup-list-numbers'.
4724 Detail: https://github.com/jrblevin/markdown-mode/issues/392"
4725 (markdown-test-string "Shortcuts
4726 ---------
4727 2. Horizontal rule: `C-c C-s -`
4728 3. Underlined header `C-c C-s !`
4729 10. Convert to HTML: `C-c C-c m`
4731 (call-interactively #'markdown-cleanup-list-numbers)
4732 (forward-line 2)
4733 (should (looking-at-p "\\s-+1\\. Horizontal rule"))
4734 (forward-line 1)
4735 (should (looking-at-p "\\s-+2\\. Underlined header"))
4736 (forward-line 1)
4737 (should (looking-at-p "\\s-+3\\. Convert to HTML"))))
4739 (ert-deftest test-markdown-lists/beginning-of-list ()
4740 "Test `markdown-beginning-of-list'."
4741 (markdown-test-file "lists.text"
4742 ;; Case 1: not in a list
4743 (goto-char 399)
4744 (should-not (markdown-beginning-of-list))
4745 (should (= (point) 399))
4746 ;; Case 2
4747 (goto-char 1281)
4748 (should (= (markdown-beginning-of-list) 1063))
4749 (should (= (point) 1063))
4750 (goto-char 1395)
4751 (should (= (markdown-beginning-of-list) 1063))
4752 (should (= (point) 1063))
4753 ;; Case 3
4754 (goto-char 1848)
4755 (should (= (markdown-beginning-of-list) 1659))
4756 (should (= (point) 1659))
4757 ;; Case 4
4758 (goto-char 2041)
4759 (should (= (markdown-beginning-of-list) 1919))
4760 (should (= (point) 1919))
4761 ;; Case 8
4762 (goto-char 3553)
4763 (should (= (markdown-beginning-of-list) 3096))
4764 (should (= (point) 3096))))
4766 (ert-deftest test-markdown-lists/end-of-list ()
4767 "Test `markdown-end-of-list'."
4768 (markdown-test-file "lists.text"
4769 ;; Case 1: not in a list
4770 (goto-char 399)
4771 (should-not (markdown-end-of-list))
4772 (should (= (point) 399))
4773 ;; Case 2
4774 (goto-char 1281)
4775 (should (= (markdown-end-of-list) 1396))
4776 (should (= (point) 1396))
4777 (goto-char 1395)
4778 (should (= (markdown-end-of-list) 1396))
4779 (should (= (point) 1396))
4780 ;; Case 3
4781 (goto-char 1659)
4782 (should (= (markdown-end-of-list) 1849))
4783 (should (= (point) 1849))
4784 ;; Case 4
4785 (goto-char 2041)
4786 (should (= (markdown-end-of-list) 2092))
4787 (should (= (point) 2092))
4788 ;; Case 8
4789 (goto-char 3553)
4790 (should (= (markdown-end-of-list) 3614))
4791 (should (= (point) 3614))))
4793 (ert-deftest test-markdown-lists/up-list ()
4794 "Test `markdown-up-list'."
4795 (markdown-test-file "nested-list.text"
4796 (goto-char 581)
4797 (should (= (markdown-up-list) 484))
4798 (should (= (point) 484))
4799 (should (= (markdown-up-list) 191))
4800 (should (= (point) 191))
4801 ;; Return nil upon failure, but move out of list.
4802 (should-not (markdown-up-list))
4803 (should (= (point) (point-min)))))
4805 ;;; Outline minor mode tests:
4807 (ert-deftest test-markdown-outline/navigation ()
4808 "Test outline navigation functions."
4809 (markdown-test-file "outline.text"
4810 ;; Navigate to the first visible heading
4811 (markdown-next-visible-heading 1)
4812 (should (eq (point) 19))
4813 (should (looking-at "^# A top-level header"))
4814 ;; Navigate forward at the same level
4815 (markdown-forward-same-level 1)
4816 (should (eq (point) 351))
4817 (should (looking-at "^An underline-style header$"))
4818 ;; Navigate backward by four visible headings
4819 (markdown-previous-visible-heading 4)
4820 (should (eq (point) 69))
4821 (should (looking-at "^## A second-level header$"))
4822 ;; Navigate up the hierarchy (atx)
4823 (call-interactively #'markdown-up-heading)
4824 (should (looking-at "^# A top-level header"))
4825 (should (eq (mark) 69))
4826 ;; Navigate up the hierarchy (setext)
4827 (goto-char 516)
4828 (call-interactively #'markdown-up-heading)
4829 (should (looking-at "^An underline-style header$"))
4830 (should (eq (mark) 516))
4831 ;; Navigate back in the outline (setext to atx)
4832 (forward-line) ;; move to setext underline
4833 (markdown-backward-same-level 1)
4834 (should (looking-at "^# A top-level header"))))
4836 (ert-deftest test-markdown-outline/navigation-with-code ()
4837 "Test outline navigation functions with code blocks."
4838 (markdown-test-file "outline-code.text"
4839 ;; Navigate forward at the same level
4840 (markdown-forward-same-level 1)
4841 (should (eq (point) 159))
4842 (should (looking-at "^# Level one again"))))
4844 (ert-deftest test-markdown-outline/back-to-heading-over-code-block ()
4845 "Test `markdown-back-to-heading-over-code-block' over."
4846 (markdown-test-file "outline-code.text"
4847 ;; Initialize match data to known quantity.
4848 (set-match-data '(1 2 3 4))
4849 (should (equal (match-data t) '(1 2 3 4)))
4850 ;; Function should navigate back over code blocks.
4851 (re-search-forward "^# In a code block")
4852 (should (= (markdown-back-to-heading-over-code-block) 69))
4853 ;; Match data should be set for markdown-regex-header.
4854 (should (equal (match-data t) (get-text-property (point) 'markdown-heading)))
4855 ;; Function should return t when at a heading.
4856 (should (equal (markdown-back-to-heading-over-code-block) t))
4857 ;; Insert some text before the first heading.
4858 (goto-char (point-min))
4859 (save-excursion (insert "foo\n\n"))
4860 ;; Function should throw an error if no previous heading.
4861 (should-error (markdown-back-to-heading-over-code-block))
4862 ;; Function should return nil without error if NO-ERROR is non-nil.
4863 (should-not (markdown-back-to-heading-over-code-block t t))))
4865 (ert-deftest test-markdown-outline/visibility-atx ()
4866 "Test outline visibility cycling for ATX-style headers."
4867 (markdown-test-file "outline.text"
4868 (let (last-command this-command)
4869 ;; Navigate to the second visible heading
4870 (markdown-next-visible-heading 2)
4871 (should (eq (point) 69))
4872 (should (looking-at "^## A second-level header$"))
4873 ;; Cycle visibility of this subtree
4874 (setq this-command 'markdown-cycle)
4875 (markdown-cycle)
4876 (setq last-command 'markdown-cycle)
4877 (should (eq (point) 69))
4878 (should (looking-at "^## A second-level header$"))
4879 ;; Test that the entire subtree is invisible
4880 (markdown-test-range-has-property 93 349 'invisible 'outline)
4881 ;; Cycle visibility of this subtree again
4882 (markdown-cycle)
4883 (should (eq (point) 69))
4884 (should (looking-at "^## A second-level header$"))
4885 ;; Test that text is visible
4886 (markdown-test-range-has-property 95 121 'invisible nil)
4887 ;; Test that subheadings are visible
4888 (markdown-test-range-has-property 123 141 'invisible nil)
4889 ;; Cycle visibility of this subtree again
4890 (markdown-cycle)
4891 (should (eq (point) 69))
4892 (should (looking-at "^## A second-level header$"))
4893 ;; Verify that entire subtree is visible
4894 (markdown-test-range-has-property 93 349 'invisible nil))))
4896 (ert-deftest test-markdown-outline/visibility-setext ()
4897 "Test outline visibility cycling for setext-style headers."
4898 (markdown-test-file "outline.text"
4899 ;; Navigate to the sixth visible heading
4900 (markdown-next-visible-heading 7)
4901 (markdown-previous-visible-heading 1)
4902 (should (looking-at markdown-regex-header))
4903 (should (string-equal (match-string-no-properties 1) "An underline-style header"))
4904 (should (string-equal (match-string-no-properties 2) "========================="))
4905 ;; Cycle visibility subtree, test that it's invisible
4906 (markdown-cycle)
4907 (markdown-test-range-has-property 404 515 'invisible 'outline)
4908 ;; Cycle visibility subtree, test that text and headers are visible
4909 (markdown-cycle)
4910 (markdown-test-range-has-property 404 417 'invisible nil)
4911 (markdown-test-range-has-property 420 451 'invisible nil)))
4913 (ert-deftest test-markdown-outline/visibility-with-code ()
4914 "Test outline visibility cycling with code blocks."
4915 (markdown-test-file "outline-code.text"
4916 (let (last-command this-command)
4917 ;; Cycle global visibility to "overview" mode
4918 (setq this-command 'markdown-cycle)
4919 (markdown-cycle t)
4920 (setq last-command 'markdown-cycle)
4921 (should (eq (point) (point-min)))
4922 (should (looking-at "^# Level one"))
4923 ;; Test that the code block is invisible
4924 (markdown-test-range-has-property 83 157 'invisible 'outline)
4925 ;; Check subsequent headings
4926 (outline-next-visible-heading 1)
4927 (should (eq (point) 69))
4928 (should (looking-at "^## Level two"))
4929 (outline-next-visible-heading 1)
4930 (should (eq (point) 159))
4931 (should (looking-at "^# Level one again")))))
4933 (ert-deftest test-markdown-outline/visibility-with-metadata ()
4934 "Test outline visibility cycling with metadata blocks."
4935 (markdown-test-string
4936 "---
4937 layout = post
4938 date = 2015-08-13 11:35:25 EST
4941 (let (last-command this-command)
4942 ;; Cycle global visibility to "overview" mode
4943 (setq this-command 'markdown-cycle)
4944 (markdown-cycle t)
4945 ;; Check that text is visible
4946 (markdown-test-range-has-property (point-min) (point-max) 'invisible nil))
4948 (let (last-command this-command)
4949 ;; Cycle global visibility to "overview" mode
4950 (setq this-command 'markdown-cycle)
4951 (let ((current-prefix-arg '(4)))
4952 (markdown-cycle)
4953 ;; Check that text is visible
4954 (markdown-test-range-has-property (point-min) (point-max) 'invisible nil)))))
4956 (ert-deftest test-markdown-outline/level ()
4957 "Test `markdown-outline-level'."
4958 (markdown-test-file "outline.text"
4959 (markdown-next-heading)
4960 (should (= (markdown-outline-level) 1))
4961 (markdown-forward-same-level 1)
4962 (should (= (markdown-outline-level) 1))
4963 (markdown-next-heading)
4964 (should (= (markdown-outline-level) 2))
4965 (markdown-next-heading)
4966 (should (= (markdown-outline-level) 1))
4967 (markdown-next-heading)
4968 (should (= (markdown-outline-level) 2))))
4970 ;;; Movement tests:
4972 (ert-deftest test-markdown-movement/beginning-of-line ()
4973 "Test beginning of line movement"
4974 (markdown-test-string "Some text\nSome other text"
4975 (goto-char (point-max))
4976 (markdown-beginning-of-line)
4977 (should (bolp)))
4978 (markdown-test-string "## Headline\n### Sub"
4979 (goto-char (point-max))
4980 (outline-hide-sublevels 2)
4981 (markdown-beginning-of-line)
4982 (should (= (line-beginning-position) 1)))
4984 ;; With `visual-line-mode' active, move to beginning of visual line.
4985 (markdown-test-string "Text "
4986 (visual-line-mode)
4987 (dotimes (_ 1000) (insert "Text "))
4988 (goto-char (point-max))
4989 (markdown-beginning-of-line)
4990 (should-not (bolp)))
4992 ;; In a wide headline, with `visual-line-mode', prefer going to the
4993 ;; beginning of a visual line than to the logical beginning of line,
4994 ;; even if special movement is active.
4995 (markdown-test-string "## Headline"
4996 (visual-line-mode)
4997 (goto-char (point-max))
4998 (dotimes (_ 1000) (insert "Text "))
4999 (markdown-beginning-of-line)
5000 (should-not (bolp)))
5001 (markdown-test-string "## Headline"
5002 (visual-line-mode)
5003 (goto-char (point-max))
5004 (dotimes (_ 1000) (insert "Text "))
5005 (let ((markdown-special-ctrl-a/e t))
5006 (markdown-beginning-of-line))
5007 (should-not (bolp)))
5009 ;; At an headline with special movement, first move at beginning of
5010 ;; title, then at the beginning of line, rinse, repeat.
5011 (markdown-test-string "## Headline"
5012 (let ((markdown-special-ctrl-a/e t))
5013 (goto-char (point-max))
5014 (markdown-beginning-of-line)
5015 (should (looking-at "Headline"))
5016 (markdown-beginning-of-line)
5017 (should (bolp))
5018 (markdown-beginning-of-line)
5019 (should (looking-at "Headline"))))
5020 (markdown-test-string "## Headline"
5021 (let ((markdown-special-ctrl-a/e nil))
5022 (goto-char (point-max))
5023 (markdown-beginning-of-line)
5024 (should (bolp))))
5026 ;; At an headline with reversed movement, first move to beginning of
5027 ;; line, then to the beginning of title.
5028 (markdown-test-string "## Headline"
5029 (let ((markdown-special-ctrl-a/e 'reversed)
5030 (this-command last-command))
5031 (goto-char (point-max))
5032 (markdown-beginning-of-line)
5033 (should (bolp))
5034 (markdown-beginning-of-line)
5035 (should (looking-at "Headline"))))
5037 ;; At an item with special movement, first move after to beginning
5038 ;; of title, then to the beginning of line, rinse, repeat.
5039 (markdown-test-string "- [ ] Item"
5040 (let ((markdown-special-ctrl-a/e nil))
5041 (goto-char (point-max))
5042 (markdown-beginning-of-line)
5043 (should (bolp))))
5044 (markdown-test-string "- [ ] Item"
5045 (let ((markdown-special-ctrl-a/e t))
5046 (goto-char (point-max))
5047 (markdown-beginning-of-line)
5048 (should (looking-at "Item"))
5049 (markdown-beginning-of-line)
5050 (should (bolp))
5051 (markdown-beginning-of-line)
5052 (should (looking-at "Item"))))
5053 (markdown-test-string "- [ ] Item"
5054 (let ((markdown-special-ctrl-a/e 'reversed)
5055 (this-command last-command))
5056 (goto-char (point-max))
5057 (markdown-beginning-of-line)
5058 (should (bolp))
5059 (markdown-beginning-of-line)
5060 (should (looking-at "Item")))))
5062 (ert-deftest test-markdown-movement/end-of-line ()
5063 "Test end of line movement"
5064 (markdown-test-string
5065 "Some text\nSome other text"
5066 (markdown-end-of-line)
5067 (should (eolp)))
5069 ;; With `visual-line-mode' active, move to end of visual line.
5070 ;; However, never go past ellipsis.
5071 (markdown-test-string
5072 "Some Text"
5073 (visual-line-mode)
5074 (goto-char (point-max))
5075 (dotimes (_ 1000) (insert "Text "))
5076 (markdown-end-of-line)
5077 (should-not (eolp)))
5079 ;; In a wide headline, with `visual-line-mode', prefer going to end
5080 ;; of visible line if tags, or end of line, are farther.
5081 (markdown-test-string "Text "
5082 (visual-line-mode)
5083 (goto-char (point-max))
5084 (dotimes (_ 1000) (insert "Text "))
5085 (goto-char (point-min))
5086 (markdown-end-of-line)
5087 (should-not (eolp)))
5088 (markdown-test-string "## Heading\nSome contents"
5089 (goto-char (point-max))
5090 (outline-hide-sublevels 2)
5091 (markdown-end-of-line)
5092 (should (= (line-beginning-position) 1)))
5094 ;; In a wide headline, with `visual-line-mode', prefer going to end
5095 ;; of visible line if tags, or end of line, are farther.
5096 (markdown-test-string "## Heading "
5097 (visual-line-mode)
5098 (goto-char (point-max))
5099 (dotimes (_ 1000) (insert "Text "))
5100 (goto-char (point-min))
5101 (markdown-end-of-line)
5102 (should-not (eolp)))
5103 (markdown-test-string "## Heading ##"
5104 (visual-line-mode)
5105 (re-search-forward "## Heading ")
5106 (dotimes (_ 1000) (insert "Text "))
5107 (goto-char (point-min))
5108 (markdown-end-of-line)
5109 (should-not (eolp)))
5110 ;; At an headline without special movement, go to end of line.
5111 ;; However, never go past ellipsis.
5112 (markdown-test-string "## Headline ##"
5113 (let ((markdown-special-ctrl-a/e nil))
5114 (markdown-end-of-line)
5115 (should (eolp))))
5116 (markdown-test-string "## Headline ##\n### Sub"
5117 (let ((markdown-special-ctrl-a/e nil))
5118 (goto-char (point-max))
5119 (outline-hide-sublevels 2)
5120 (markdown-end-of-line)
5121 (should (= (line-beginning-position) 1))))
5123 ;; At an headline with special movement, first move before close tag,
5124 ;; then at the end of line, rinse, repeat. However, never go past
5125 ;; ellipsis.
5126 (markdown-test-string "## Headline ##"
5127 (let ((markdown-special-ctrl-a/e t))
5128 (markdown-end-of-line)
5129 (should (looking-at " ##"))
5130 (markdown-end-of-line)
5131 (should (eolp))
5132 (markdown-end-of-line)
5133 (should (looking-at " ##"))))
5134 (markdown-test-string "## Headline ##\n### Sub"
5135 (let ((markdown-special-ctrl-a/e t))
5136 (goto-char (point-max))
5137 (outline-hide-sublevels 2)
5138 (markdown-end-of-line)
5139 (should (= (line-beginning-position) 1))))
5141 ;; At an headline, with reversed movement, first go to end of line,
5142 ;; then before tags. However, never go past ellipsis.
5143 (markdown-test-string "## Headline ##"
5144 (let ((markdown-special-ctrl-a/e 'reversed)
5145 (this-command last-command))
5146 (markdown-end-of-line)
5147 (should (eolp))
5148 (markdown-end-of-line)
5149 (should (looking-at " ##"))))
5150 (markdown-test-string "## Headline ##\n### Sub"
5151 (let ((markdown-special-ctrl-a/e 'reversed)
5152 (this-command last-command))
5153 (goto-char (point-max))
5154 (outline-hide-sublevels 2)
5155 (markdown-end-of-line)
5156 (should (= (line-beginning-position) 1)))))
5158 (ert-deftest test-markdown-movement/defun ()
5159 "Test defun navigation."
5160 (markdown-test-file "outline.text"
5161 ;; end-of-defun should go to point-max
5162 (end-of-defun 10)
5163 (should (= (point) (point-max)))
5164 ;; end-of-defun should stop just before the next header
5165 (goto-char (point-min))
5166 (end-of-defun)
5167 (should (looking-at "\n# A top-level header"))
5168 (end-of-defun)
5169 (should (looking-at "\n## A second-level header"))
5170 (end-of-defun)
5171 (should (looking-at "\n### Third level ###"))
5172 (end-of-defun)
5173 (should (looking-at "\n### Third level number two ###"))
5174 ;; beginning-of-defun should move to the start of the previous header
5175 (beginning-of-defun)
5176 (should (looking-at "### Third level ###"))
5177 (beginning-of-defun)
5178 (should (looking-at "## A second-level header"))
5179 (beginning-of-defun)
5180 (should (looking-at "# A top-level header"))
5181 (beginning-of-defun)
5182 ;; beginning-of-defun should move up to point-min
5183 (should (= (point) (point-min)))
5184 ;; (beginning-of-defun -1) should move to the start of the next header
5185 (forward-line 2)
5186 (beginning-of-defun -1)
5187 (should (looking-at "## A second-level header"))
5188 (beginning-of-defun -1)
5189 (should (looking-at "### Third level ###"))
5190 (beginning-of-defun -1)
5191 (should (looking-at "### Third level number two ###"))))
5193 (ert-deftest test-markdown-movement/beginning-of-defun-at-point-max ()
5194 "Test beginning of defun navigation at point-max."
5195 (markdown-test-file "outline.text"
5196 (goto-char (point-max))
5197 (beginning-of-defun)))
5199 (ert-deftest test-markdown-movement/text-block ()
5200 "Test plain text block movement."
5201 (markdown-test-file "outline.text"
5202 (markdown-end-of-text-block)
5203 (should (looking-at "\n# A top-level header"))
5204 (markdown-end-of-text-block)
5205 (should (looking-at "\nfollowed by some body text"))
5206 (markdown-end-of-text-block)
5207 (should (looking-at "\n## A second-level header"))
5208 (markdown-end-of-text-block)
5209 (should (looking-at "\nfollowed by some body text"))
5210 (markdown-end-of-text-block)
5211 (should (looking-at "\n### Third level ###"))
5212 (markdown-end-of-text-block)
5213 (should (looking-at "\n\\* A list item"))
5214 (markdown-end-of-text-block)
5215 (should (looking-at "\n### Third level number two ###"))
5216 (markdown-end-of-text-block)
5217 (should (looking-at "\n### Level two again"))
5218 (markdown-end-of-text-block)
5219 (should (looking-at "\nfollowed by some body text"))
5221 (markdown-test-goto-heading "Level two")
5222 (markdown-end-of-text-block)
5223 (should (looking-at "\nbar"))
5224 (markdown-end-of-text-block)
5225 (should (= (point) (point-max)))
5226 (markdown-beginning-of-text-block)
5227 (should (looking-at "bar"))
5228 (markdown-beginning-of-text-block)
5229 (should (looking-at "## Level two"))
5230 (markdown-beginning-of-text-block)
5231 (should (looking-at "foo"))
5232 (markdown-beginning-of-text-block)
5233 (should (looking-at "# Level one"))
5234 (markdown-beginning-of-text-block)
5235 (should (looking-at "* With"))
5236 (markdown-beginning-of-text-block)
5237 (should (looking-at "And a level two underline header"))
5239 (goto-char (point-min))
5240 (markdown-test-goto-heading "A top-level header")
5241 (beginning-of-line)
5242 (markdown-beginning-of-text-block)
5243 (should (= (point) (point-min)))))
5245 (ert-deftest test-markdown-movement/mark-text-block ()
5246 "Test `markdown-mark-text-block'."
5247 (markdown-test-file "outline.text"
5248 ;; Start in middle of nested list with no separating whitespace.
5249 (goto-char 193)
5250 (markdown-mark-text-block)
5251 (should (= (point) 143))
5252 (should (= (mark) 269))))
5254 (ert-deftest test-markdown-movement/paragraph ()
5255 "Test Markdown paragraph movement."
5256 (markdown-test-file "outline.text"
5257 (markdown-forward-paragraph)
5258 (should (looking-at "\n# A top-level header"))
5259 (markdown-forward-paragraph)
5260 (should (looking-at "\nfollowed by some body text"))
5261 (markdown-forward-paragraph)
5262 (should (looking-at "\n## A second-level header"))
5263 (markdown-forward-paragraph)
5264 (should (looking-at "\nfollowed by some body text"))
5265 (markdown-forward-paragraph)
5266 (should (looking-at "\n### Third level ###"))
5267 (markdown-forward-paragraph)
5268 (should (looking-at "\n\\* A list item"))
5269 (markdown-forward-paragraph)
5270 (should (looking-at "\\* and another"))
5271 (markdown-forward-paragraph)
5272 (should (looking-at " \\+ and a sublist"))
5273 (markdown-forward-paragraph)
5274 (should (looking-at "- And a third"))
5275 (markdown-forward-paragraph)
5276 (should (looking-at "\n### Third level number two ###"))
5277 (markdown-forward-paragraph)
5278 (should (looking-at "\n### Level two again"))
5279 (markdown-forward-paragraph)
5280 (should (looking-at "\nfollowed by some body text"))
5282 (markdown-test-goto-heading "Level two")
5283 (markdown-forward-paragraph)
5284 (should (looking-at "\nbar"))
5285 (markdown-forward-paragraph)
5286 (should (= (point) (point-max)))
5287 (markdown-backward-paragraph)
5288 (should (looking-at "bar"))
5289 (markdown-backward-paragraph)
5290 (should (looking-at "## Level two"))
5291 (markdown-backward-paragraph)
5292 (should (looking-at "foo"))
5293 (markdown-backward-paragraph)
5294 (should (looking-at "# Level one"))
5295 (markdown-backward-paragraph)
5296 (should (looking-at "\\* List"))
5297 (markdown-backward-paragraph)
5298 (should (looking-at "\\* an unordered"))
5299 (markdown-backward-paragraph)
5300 (should (looking-at "\\* With"))
5301 (markdown-backward-paragraph)
5302 (should (looking-at "And a level two underline header"))
5304 (goto-char (point-min))
5305 (markdown-test-goto-heading "A top-level header")
5306 (beginning-of-line)
5307 (markdown-backward-paragraph)
5308 (should (= (point) (point-min)))))
5310 (ert-deftest test-markdown-movement/forward-paragraph-with-whitespace ()
5311 "Test Markdown paragraph movement."
5312 (markdown-test-file "blocks.md"
5313 (markdown-test-goto-heading "With Whitespace")
5314 (dolist (pos '(58 67 78 94 109 114 123 131 135 147 157 170 184 199))
5315 (markdown-forward-paragraph)
5316 (should (= (point) pos)))))
5318 (ert-deftest test-markdown-movement/backward-paragraph-with-whitespace ()
5319 "Test Markdown paragraph movement."
5320 (markdown-test-file "blocks.md"
5321 (markdown-test-goto-heading "With Whitespace")
5322 (markdown-next-heading)
5323 (should (= (point) 200))
5324 (dolist (pos '(185 172 158 148 136 132 124 115 110 94 78 67 59))
5325 (markdown-backward-paragraph)
5326 (should (= (point) pos)))))
5328 (ert-deftest test-markdown-movement/forward-paragraph-without-whitespace ()
5329 "Test Markdown paragraph movement."
5330 (markdown-test-file "blocks.md"
5331 (markdown-test-goto-heading "Without Whitespace")
5332 (dolist (pos '(222 230 240 255 270 275 283 291 294 305 314 326 340 354))
5333 (markdown-forward-paragraph)
5334 (should (= (point) pos)))))
5336 (ert-deftest test-markdown-movement/backward-paragraph-without-whitespace ()
5337 "Test Markdown paragraph movement."
5338 (markdown-test-file "blocks.md"
5339 (goto-char (point-max))
5340 (dolist (pos '(340 328 314 305 294 291 284 275 271 255 240 230 223 200))
5341 (markdown-backward-paragraph)
5342 (should (= (point) pos)))))
5344 (ert-deftest test-markdown-movement/block ()
5345 "Test Markdown block movement."
5346 (markdown-test-file "outline.text"
5347 (markdown-forward-block)
5348 (should (looking-at "\n# A top-level header"))
5349 (markdown-forward-block)
5350 (should (looking-at "\nfollowed by some body text"))
5351 (markdown-forward-block)
5352 (should (looking-at "\n## A second-level header"))
5353 (markdown-forward-block)
5354 (should (looking-at "\nfollowed by some body text"))
5355 (markdown-forward-block)
5356 (should (looking-at "\n### Third level ###"))
5357 (markdown-forward-block)
5358 (should (looking-at "\n\\* A list item"))
5359 (markdown-forward-block)
5360 (should (looking-at "\n### Third level number two ###"))
5361 (markdown-forward-block)
5362 (should (looking-at "\n### Level two again"))
5363 (markdown-forward-block)
5364 (should (looking-at "\nfollowed by some body text"))
5366 (markdown-test-goto-heading "Level two")
5367 (markdown-forward-block)
5368 (should (looking-at "\nbar"))
5369 (markdown-forward-block)
5370 (should (= (point) (point-max)))
5371 (markdown-backward-block)
5372 (should (looking-at "bar"))
5373 (markdown-backward-block)
5374 (should (looking-at "## Level two"))
5375 (markdown-backward-block)
5376 (should (looking-at "foo"))
5377 (markdown-backward-block)
5378 (should (looking-at "# Level one"))
5379 (markdown-backward-block)
5380 (should (looking-at "\\* With"))
5381 (markdown-backward-block)
5382 (should (looking-at "And a level two underline header"))
5384 (goto-char (point-min))
5385 (markdown-test-goto-heading "A top-level header")
5386 (beginning-of-line)
5387 (markdown-backward-block)
5388 (should (= (point) (point-min)))))
5390 (ert-deftest test-markdown-movement/forward-block-with-whitespace ()
5391 "Test Markdown block movement."
5392 (markdown-test-file "blocks.md"
5393 (markdown-test-goto-heading "With Whitespace")
5394 (dolist (pos '(58 109 114 131 135 147 157 184 199))
5395 (markdown-forward-block)
5396 (should (= (point) pos)))))
5398 (ert-deftest test-markdown-movement/backward-block-with-whitespace ()
5399 "Test Markdown block movement."
5400 (markdown-test-file "blocks.md"
5401 (markdown-test-goto-heading "With Whitespace")
5402 (markdown-next-heading)
5403 (dolist (pos '(185 158 148 136 132 115 110 59))
5404 (markdown-backward-block)
5405 (should (= (point) pos)))))
5407 (ert-deftest test-markdown-movement/forward-block-without-whitespace ()
5408 "Test Markdown block movement."
5409 (markdown-test-file "blocks.md"
5410 (markdown-test-goto-heading "Without Whitespace")
5411 (dolist (pos '(222 270 275 291 294 305 314 340 354))
5412 (markdown-forward-block)
5413 (should (= (point) pos)))))
5415 (ert-deftest test-markdown-movement/backward-block-without-whitespace ()
5416 "Test Markdown block movement."
5417 (markdown-test-file "blocks.md"
5418 (goto-char (point-max))
5419 (dolist (pos '(340 314 305 294 291 275 271 223 200))
5420 (markdown-backward-block)
5421 (should (= (point) pos)))))
5423 (ert-deftest test-markdown-movement/page ()
5424 "Test Markdown page movement."
5425 (markdown-test-file "outline.text"
5426 (markdown-forward-page)
5427 (should (looking-at "# A top-level header"))
5428 (markdown-forward-page)
5429 (should (looking-at "An underline-style header"))
5430 (markdown-forward-page)
5431 (should (looking-at "# Level one"))
5432 (markdown-forward-page)
5433 (should (eobp))
5434 (markdown-backward-page)
5435 (should (looking-at "# Level one"))
5436 (markdown-backward-page)
5437 (should (looking-at "An underline-style header"))
5438 (markdown-backward-page)
5439 (should (looking-at "# A top-level header"))
5440 (markdown-backward-page)
5441 (should (bobp))))
5443 (ert-deftest test-markdown-movement/blockquote-paragraphs ()
5444 "Test filling of blockquotes containing multiple paragraphs."
5445 (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"
5446 (forward-paragraph)
5447 (should (looking-at "^>$"))
5448 (should (= (point) 128))
5449 (forward-paragraph)
5450 (should (= (point) (point-max)))))
5452 (ert-deftest test-markdown-movement/reference-definition ()
5453 "Test jumping to reference definitions."
5454 ;; Jumping to explicit reference definition
5455 (markdown-test-string "[a][ref]\n\n[ref]: gopher://localhost/\n"
5456 (markdown-reference-goto-definition)
5457 (should (= (point) 18)))
5458 ;; Jumping to implicit reference definition
5459 (markdown-test-string "[a][]\n\n[a]: ftp://localhost/\n"
5460 (markdown-reference-goto-definition)
5461 (should (= (point) 13)))
5462 ;; Creating non-existent reference definition
5463 (markdown-test-string "[a][]\n"
5464 (markdown-reference-goto-definition)
5465 (should (= (point) 13))
5466 (should (string-equal (buffer-string) "[a][]\n\n[a]: \n"))))
5468 (ert-deftest test-markdown-movement/back-to-same-level-over-code-block ()
5469 "`markdown-backward-same-level' over code block which contains header
5470 like statement. Detail: https://github.com/jrblevin/markdown-mode/issues/75"
5471 (markdown-test-string "
5472 ## Header 2-1
5474 ## Header 2-2
5476 ```R
5477 # Header Like Statement
5480 ## Header 2-3
5482 (search-forward "## Header 2-3")
5483 (let ((last-header-pos (point)))
5484 (forward-line -1)
5485 (call-interactively #'markdown-backward-same-level)
5486 (should (looking-at-p "## Header 2-1"))
5488 (goto-char last-header-pos)
5489 (call-interactively #'markdown-backward-same-level)
5490 (should (looking-at-p "## Header 2-2"))
5492 (goto-char last-header-pos)
5493 (markdown-backward-same-level 2)
5494 (should (looking-at-p "## Header 2-1"))
5496 (search-forward "# Header Like Statement")
5497 (call-interactively #'markdown-backward-same-level)
5498 (should (looking-at-p "## Header 2-1")))))
5500 (ert-deftest test-markdown-movement/sentence ()
5501 "Move sentencen which is wrapped markup characters.
5502 Detail: https://github.com/jrblevin/markdown-mode/issues/517"
5503 (markdown-test-string "*Sentence one.* **Sentence two.** ~Sentence three.~
5504 _Sentence four._ `Sentence five.` Sentence six.
5505 Sentence seven. Sentence eight.
5507 (forward-sentence 1)
5508 (should (looking-back "one\\.\\*" (line-beginning-position)))
5509 (forward-sentence 1)
5510 (should (looking-back "two\\.\\*\\*" (line-beginning-position)))
5511 (forward-sentence 1)
5512 (should (looking-at-p "$"))
5513 (save-excursion
5514 (backward-sentence 2)
5515 (should (looking-at-p "\\*\\*Sentence two")))
5516 (forward-sentence 1)
5517 (should (looking-back "four\\._" (line-beginning-position)))
5518 (forward-sentence 1)
5519 (should (looking-back "five\\.`" (line-beginning-position)))
5520 (forward-sentence 1)
5521 (should (looking-at-p "$"))
5522 (forward-sentence 1)
5523 (looking-back "seven\\." (line-beginning-position))
5524 (forward-sentence 1)
5525 (should (looking-at-p "$"))))
5527 ;;; Link tests:
5529 (ert-deftest test-markdown-link/follow ()
5530 "Test link following in a browser and in Emacs."
5531 (markdown-test-string "[text](http://path?query=foo#id)"
5532 (let* ((opened-url nil)
5533 (browse-url-browser-function
5534 (lambda (url &rest _args) (setq opened-url url))))
5535 (markdown-follow-thing-at-point nil)
5536 (should (equal opened-url "http://path?query=foo#id"))))
5537 (when (featurep 'url-parse)
5538 (markdown-test-string "[text](path?query=foo#id)"
5539 (markdown-follow-thing-at-point nil)
5540 (should (equal (file-name-nondirectory (buffer-file-name)) "path")))))
5542 (ert-deftest test-markdown-link/link-in-header ()
5543 "Test link following even if it is in header.
5544 Detail: https://github.com/jrblevin/markdown-mode/issues/430"
5545 (markdown-test-string "---
5546 [link](https://link-in-header.com)
5547 ---"
5548 (forward-line +1)
5549 (let* ((opened-url nil)
5550 (browse-url-browser-function
5551 (lambda (url &rest _args) (setq opened-url url))))
5552 (markdown-follow-thing-at-point nil)
5553 (should (equal opened-url "https://link-in-header.com")))))
5555 (ert-deftest test-markdown-link/inline-link-at-pos ()
5556 "Test `markdown-link-at-pos' return values with an inline link."
5557 (markdown-test-string "[text](url \"title\")"
5558 (should (equal (markdown-link-at-pos (point)) '(1 20 "text" "url" nil "title" nil)))))
5560 (ert-deftest test-markdown-link/inline-image-at-pos ()
5561 "Test `markdown-link-at-pos' return values with an inline image."
5562 (markdown-test-string "![text](url \"title\")"
5563 (should (equal (markdown-link-at-pos (point)) '(1 21 "text" "url" nil "title" "!")))))
5565 (ert-deftest test-markdown-link/inline-link-with-brackets ()
5566 "Test `markdown-link-at-pos' return values with a link with backets.
5567 Details: https://github.com/jrblevin/markdown-mode/issues/800
5569 A link can contain spaces if it is wrapped with angle brackets"
5570 (markdown-test-string "[text](<file name has space>)"
5571 (should (equal (markdown-link-at-pos (point)) '(1 30 "text" "file name has space" nil nil nil)))))
5573 (ert-deftest test-markdown-link/inline-link-with-url-escape ()
5574 "Test `markdown-link-at-pos' return values with a link with url escapes.
5575 Details: https://github.com/jrblevin/markdown-mode/issues/805
5577 A link can contain spaces if it is wrapped with angle brackets"
5578 (markdown-test-string "[text](bar%20baz.md)"
5579 (should (equal (nth 3 (markdown-link-at-pos (point))) "bar baz.md")))
5580 (markdown-test-string "[text](<bar%20baz.md>)"
5581 (should (equal (nth 3 (markdown-link-at-pos (point))) "bar baz.md"))))
5583 (ert-deftest test-markdown-link/reference-link-at-pos ()
5584 "Test `markdown-link-at-pos' return values with a reference link."
5585 (markdown-test-string "[text][ref]"
5586 (should (equal (markdown-link-at-pos (point)) '(1 12 "text" nil "ref" nil nil)))))
5588 (ert-deftest test-markdown-link/reference-image-at-pos ()
5589 "Test `markdown-link-at-pos' return values with a reference image."
5590 (markdown-test-string "![text][ref]"
5591 (should (equal (markdown-link-at-pos (point)) '(1 13 "text" nil "ref" nil "!")))))
5593 (ert-deftest test-markdown-link/angle-uri-at-pos ()
5594 "Test `markdown-link-at-pos' return values with an angle bracket inline link."
5595 (markdown-test-string "<http://jblevins.org/projects/markdown-mode/>"
5596 (should (equal (markdown-link-at-pos (point)) '(1 46 nil "http://jblevins.org/projects/markdown-mode/" nil nil nil)))))
5598 (ert-deftest test-markdown-link/plain-uri-at-pos ()
5599 "Test `markdown-link-at-pos' return values with a plain URI."
5600 (markdown-test-string "http://jblevins.org/projects/markdown-mode/"
5601 (should (equal (markdown-link-at-pos (point)) '(1 44 nil "http://jblevins.org/projects/markdown-mode/" nil nil nil)))))
5603 (ert-deftest test-markdown-link/link-contains-parenthesis ()
5604 "Test URL which contains close parenthesis.
5605 Detail: https://github.com/jrblevin/markdown-mode/issues/408"
5606 (let ((url "https://commons.wikimedia.org/wiki/Category:SVG_locator_maps_of_continents_(location_map_scheme)_(Winkel_3_projection)"))
5607 (markdown-test-string (format "[foo](%s)" url)
5608 (let ((link (markdown-link-at-pos (point))))
5609 (should (string= (nth 3 link) url))))))
5611 (ert-deftest test-markdown-link/link-contains-parenthesis-and-label ()
5612 "Test URL which contains close parenthesis.
5613 Detail: https://github.com/jrblevin/markdown-mode/issues/762"
5614 (markdown-test-string "![Text](url(par).png \"label\")"
5615 (let ((link (markdown-link-at-pos (point))))
5616 (should (string= (nth 3 link) "url(par).png"))
5617 (should (string= (nth 5 link) "label")))))
5619 (ert-deftest test-markdown-link/start-or-end-with-spaces ()
5620 "Test `markdown-link-at-pos' return values with URL part starts/ends with spaces.
5621 Detail: https://github.com/jrblevin/markdown-mode/issues/514"
5622 (markdown-test-string "[Broken](
5623 http://example.com )
5625 (let ((values (markdown-link-at-pos (point))))
5626 (should (string= (nth 3 values) "http://example.com"))))
5628 (markdown-test-string "[Broken](
5629 http://example.com \"title\" )
5631 (let ((values (markdown-link-at-pos (point))))
5632 (should (string= (nth 3 values) "http://example.com"))
5633 (should (string= (nth 5 values) "title")))))
5635 (ert-deftest test-markdown-link/follow-filename ()
5636 "Test that `markdown-follow-thing-at-pos' uses
5637 `markdown-translate-filename-function' to translate filenames."
5638 (markdown-test-string "[text](/foo/bar/baz)"
5639 (cl-letf* ((visited-files ())
5640 ((symbol-function #'find-file)
5641 (lambda (filename)
5642 (push filename visited-files)))
5643 (translated-files ())
5644 (markdown-translate-filename-function
5645 (lambda (filename)
5646 (push filename translated-files)
5647 (format "/root%s.md" filename))))
5648 (markdown-follow-thing-at-point nil)
5649 (should (equal translated-files '("/foo/bar/baz")))
5650 (should (equal visited-files '("/root/foo/bar/baz.md"))))))
5652 (ert-deftest test-markdown-link/link-p ()
5653 "Test that `markdown-link-p' returns t if cursor is on link."
5654 (markdown-test-string "[one][two] [three][four]"
5655 (should (markdown-link-p))
5656 (goto-char 2)
5657 (should (markdown-link-p))
5658 (goto-char 12)
5659 (should (markdown-link-p))
5660 (goto-char 13)
5661 (should (markdown-link-p))))
5663 (ert-deftest test-markdown-link/link-p-2 ()
5664 "Don't allow space between label and text in reference link."
5665 (markdown-test-string "[one] [two]"
5666 (should-not (markdown-link-p))))
5668 ;;; Wiki link tests:
5670 (ert-deftest test-markdown-wiki-link/file-local-variables ()
5671 "Test enabling wiki links via file-local variables."
5672 (markdown-test-file "wiki-links.text"
5673 (should-not markdown-enable-wiki-links)
5674 (hack-local-variables)
5675 (should markdown-enable-wiki-links)))
5677 (ert-deftest test-markdown-wiki-link/aliasing ()
5678 "Test filename extraction for aliased wiki links."
5679 (let ((markdown-enable-wiki-links t))
5680 (markdown-test-file "wiki-links.text"
5681 ;; Confirm location of first wiki link
5682 (should (eq (markdown-next-link) 8))
5683 ;; Confirm location of second wiki link
5684 (should (eq (markdown-next-link) 73))
5685 ;; Test predicate function
5686 (should (markdown-wiki-link-p))
5687 ;; Test alias-first filename extraction
5688 (setq markdown-wiki-link-alias-first t)
5689 (should (string-equal (markdown-wiki-link-link) "second"))
5690 ;; Test alias-second filename extraction
5691 (setq markdown-wiki-link-alias-first nil)
5692 (should (string-equal (markdown-wiki-link-link) "first")))))
5694 (ert-deftest test-markdown-wiki-link/navigation ()
5695 "Test wiki link navigation."
5696 (let ((markdown-enable-wiki-links t))
5697 (markdown-test-file "wiki-links.text"
5698 ;; Advance to first link
5699 (should (eq (markdown-next-link) 8))
5700 ;; Advance to second link
5701 (should (eq (markdown-next-link) 73))
5702 ;; Advance to final link
5703 (should (eq (markdown-next-link) 155))
5704 ;; Return nil and don't advance point
5705 (should (eq (markdown-next-link) nil))
5706 (should (eq (point) 155))
5707 ;; Move back to second link
5708 (should (eq (markdown-previous-link) 73))
5709 ;; Move back to first link
5710 (should (eq (markdown-previous-link) 8))
5711 ;; Return nil and don't move point
5712 (should (eq (markdown-previous-link) nil))
5713 (should (eq (point) 8)))))
5715 (ert-deftest test-markdown-wiki-link/font-lock ()
5716 "Test font lock faces for wiki links."
5717 ;; If `temporary-file-directory' contains an inaccessible
5718 ;; subdirectory, `markdown-fontify-buffer-wiki-links' fails because
5719 ;; it calls `directory-files-recursively' on the directory, which
5720 ;; fails because of
5721 ;; <https://debbugs.gnu.org/cgi/bugreport.cgi?bug=28567>. To fix
5722 ;; this, we run the entire test in a new subdirectory of
5723 ;; `temporary-file-directory', which is guaranteed to not contain
5724 ;; any inaccessible directories.
5725 (let ((temporary-file-directory
5726 (file-name-as-directory (make-temp-file "markdown-test" :dir-flag))))
5727 (markdown-test-temp-file "wiki-links.text"
5728 (let* ((fn (concat (file-name-directory buffer-file-name)
5729 "inline.text"))
5730 (markdown-enable-wiki-links t))
5731 ;; Create inline.text in the same temp directory, refontify
5732 (write-region "" nil fn nil 1)
5733 (markdown-fontify-buffer-wiki-links)
5734 ;; Confirm location of first wiki link
5735 (should (eq (markdown-next-link) 8))
5736 ;; First wiki link doesn't have a corresponding file
5737 (markdown-test-range-has-property 8 20 'font-lock-face 'markdown-missing-link-face)
5738 ;; Second wiki link doesn't have a corresponding file
5739 (should (eq (markdown-next-link) 73))
5740 (markdown-test-range-has-property 73 88 'font-lock-face 'markdown-missing-link-face)
5741 ;; Move to third wiki link, and create the missing file
5742 (should (eq (markdown-next-link) 155))
5743 (should (string-equal (markdown-wiki-link-link) "inline"))
5744 (markdown-test-range-has-property 155 164 'font-lock-face 'markdown-link-face)
5745 ;; Check wiki links in code blocks
5746 (markdown-test-range-has-face 360 395 'markdown-pre-face)
5747 ;; Remove temporary files
5748 (delete-file fn)))
5749 (delete-directory temporary-file-directory)))
5751 (ert-deftest test-markdown-wiki-link/kill ()
5752 "Simple tests for `markdown-kill-thing-at-point' for wiki links."
5753 (let ((kill-ring nil)
5754 (markdown-enable-wiki-links t)
5755 (tests (list '("[[foo]]" . "foo")
5756 '("[[foo|bar]]" . "bar"))))
5757 (dolist (test tests)
5758 ;; Load test string (the car), move to end of first line, kill
5759 ;; thing at point, and then verify that the kill ring contains cdr.
5760 (markdown-test-string (car test)
5761 (end-of-line)
5762 (call-interactively 'markdown-kill-thing-at-point)
5763 (should (string-equal (current-kill 0) (cdr test)))))))
5765 ;;; Filling tests:
5767 (ert-deftest test-markdown-filling/blockquote ()
5768 "Test filling of blockquotes.
5769 See `adaptive-fill-first-line-regexp'."
5770 (markdown-test-string "> Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
5771 (fill-paragraph)
5772 (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."))))
5774 (ert-deftest test-markdown-filling/blockquote-paragraphs ()
5775 "Test filling of blockquotes containing multiple paragraphs."
5776 (markdown-test-string "> Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
5778 > Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
5780 (forward-paragraph)
5781 (fill-paragraph)
5782 (should (string-equal
5783 (buffer-substring-no-properties (point-min) (point-max))
5784 "> Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
5786 > Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris
5787 > nisi ut aliquip ex ea commodo consequat.
5788 "))))
5790 (ert-deftest test-markdown-filling/nested-blockquote-paragraphs ()
5791 "Test filling of nested blockquotes.
5792 Detail: https://github.com/jrblevin/markdown-mode/issues/366"
5793 (markdown-test-string "> > pursuit of Happiness.--That to secure these rights, Governments are
5794 > > instituted among Men, deriving their just powers from the consent of
5796 (fill-paragraph)
5797 (should (string-equal
5798 (buffer-substring-no-properties (point-min) (point-max))
5799 "> > pursuit of Happiness.--That to secure these rights, Governments
5800 > > are instituted among Men, deriving their just powers from the
5801 > > consent of
5802 "))))
5804 (ert-deftest test-markdown-filling/leanpub-block ()
5805 "Test adaptive filling of Leanpub blocks."
5806 (markdown-test-string "A> Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
5807 (fill-paragraph)
5808 (should (string-equal
5809 (buffer-substring-no-properties (point-min) (point-max))
5810 "A> Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do\nA> eiusmod tempor incididunt ut labore et dolore magna aliqua."))))
5812 (ert-deftest test-markdown-filling/space-after-list-marker ()
5813 "`fill-paragraph' should preserve more than one space after a list marker,
5814 since users may wish to indent their lists more than one space more than the
5815 width of the marker. The examples on the Markdown Syntax page have three
5816 spaces after the list marker for a total indentation of four."
5817 (let ((str "\n\n* List item indented four spaces.\n* Also four spaces."))
5818 (markdown-test-string str
5819 (forward-line 2)
5820 (fill-paragraph)
5821 (should (string-equal (buffer-string) str)))))
5823 (ert-deftest test-markdown-filling/multi-line-list-with-more-space ()
5824 "`fill-paragraph' should preserve more than one space after a list marker
5825 (see `test-preserve-space-after-list-marker')."
5826 (let ((str "* This list item is continued on\n the next line"))
5827 (markdown-test-string str
5828 ;; The first line is exactly 35 columns
5829 (let ((fill-column 35))
5830 (fill-paragraph)
5831 (should (string-equal (buffer-string) str))))))
5833 (ert-deftest test-markdown-filling/definition-list-add-leading-spaces ()
5834 "`fill-paragraph' should adapt to spaces after list marker."
5835 (markdown-test-string
5836 ": This list item is continued on the next line"
5837 (let ((fill-column 35))
5838 (fill-paragraph)
5839 (should (string-equal
5840 (buffer-string)
5841 ": This list item is continued on\n the next line")))))
5843 (ert-deftest test-markdown-filling/definition-list-preserve-leading-spaces ()
5844 "`fill-paragraph' should preserve spaces after list marker."
5845 (let ((str ": This list item is continued on\n the next line")
5846 (fill-column 35))
5847 (markdown-test-string
5848 str (fill-paragraph)
5849 (should (string-equal (buffer-string) str)))))
5851 (ert-deftest test-markdown-filling/list-item-plus ()
5852 "Test filling of list items with plus sign markers.
5853 See `adaptive-fill-regexp'."
5854 (markdown-test-string " + Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
5855 (fill-paragraph)
5856 (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."))))
5858 (ert-deftest test-markdown-filling/list-item-plus-in-blockquote ()
5859 "Test filling of list items with plus sign markers inside blockquote.
5860 See `adaptive-fill-regexp'."
5861 (markdown-test-string "> + Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
5862 (fill-paragraph)
5863 (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."))))
5865 (ert-deftest test-markdown-filling/line-break ()
5866 "Test filling of paragraphs with hard line breaks.
5867 See `paragraph-separate'."
5868 (markdown-test-string "Lorem ipsum dolor sit amet, \nconsectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
5869 (let ((fill-column 70))
5870 (fill-paragraph)
5871 (should (string-equal (buffer-string) "Lorem ipsum dolor sit amet, \nconsectetur adipisicing elit, sed do eiusmod tempor incididunt ut\nlabore et dolore magna aliqua.")))))
5873 (ert-deftest test-markdown-filling/decimal-number-at-beginning ()
5874 "Test filling when a number with a decimal appears at the beginning of a line."
5875 (markdown-test-string "The circumference of a circle divided by it's radius is around\n3.14."
5876 (fill-paragraph)
5877 (should (string-equal (buffer-string) "The circumference of a circle divided by it's radius is around 3.14."))))
5879 (ert-deftest test-markdown-filling/avoid-unintended-list-item ()
5880 "Avoid breaking lines where it would result in an unintended list item."
5881 (markdown-test-string "Lorem ipsum dolor sit 4. amet"
5882 (let ((fill-column 22))
5883 (fill-paragraph)
5884 (should (string-equal (buffer-string) "Lorem ipsum dolor\nsit 4. amet")))))
5886 (ert-deftest test-markdown-filling/no-break-link-reference ()
5887 "Shouldn't break line between label and url, or combine two link references."
5888 (let ((str "[label1]: http://long-url.example.com\n[label2]: http://another-long-url.example.com/"))
5889 (markdown-test-string str
5890 (let ((fill-column 15)) ; after end of label, before end of URL
5891 (fill-paragraph)
5892 (should (string-equal (buffer-string) str))))))
5894 (ert-deftest test-markdown-filling/no-break-before-list-item ()
5895 "There's no point in putting the first item of a list on the next line,
5896 indented the same amount."
5897 (let ((str "* [Link](http://way-too-long.example.com)\n"))
5898 (markdown-test-string str
5899 (auto-fill-mode 1)
5900 (let ((fill-column 10))
5901 (end-of-line)
5902 (funcall auto-fill-function)
5903 (should (string-equal (buffer-string) str))))))
5905 (ert-deftest test-markdown-filling/break-within-list-item ()
5906 "This doesn't suppress auto-fill within a multi-word list item."
5907 :expected-result :failed
5908 (markdown-test-string "* [Link](http://example.com/) more text"
5909 (auto-fill-mode 1)
5910 (let ((fill-column 10))
5911 (end-of-line)
5912 (funcall auto-fill-function)
5913 (should (string-equal
5914 (buffer-string)
5915 "* [Link](http://example.com/)\n more text")))))
5917 (ert-deftest test-markdown-filling/preserve-next-line-footnote ()
5918 "Footnote block can be after label"
5919 (let ((str "[^label1]:\n Footnote block\n more footnote")) ; six spaces
5920 (markdown-test-string str
5921 (let ((fill-column 20)) ; could fit "footnote" after label, but shouldn't
5922 (fill-paragraph)
5923 (should (string-equal (buffer-string) str))))))
5925 (ert-deftest test-markdown-filling/wrap-same-line-footnote ()
5926 "Additional lines must be indented one level (four spaces) when wrapped."
5927 (markdown-test-string "[^label]: Long line should be wrapped"
5928 (let ((fill-column 25)) ; wrap before end of "should"
5929 (fill-paragraph)
5930 (should (string-equal (buffer-string) "[^label]: Long line\n should be wrapped")))))
5932 (ert-deftest test-markdown-filling/wrap-extra-hanging-indentation ()
5933 "Additional lines must be indented one level (four spaces) when wrapped."
5934 (markdown-test-string "[^label]: Long line\n should be wrapped"
5935 (let ((fill-column 25)) ; wrap before end of "should"
5936 (fill-paragraph)
5937 (should (string-equal (buffer-string) "[^label]: Long line\n should be wrapped")))))
5939 (ert-deftest test-markdown-filling/full-justification ()
5940 "Test paragraph detection with lines with lots of whitespace."
5941 (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"
5942 (setq default-justification 'full)
5943 (fill-paragraph)
5944 (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"))
5945 (backward-paragraph)
5946 (forward-paragraph)
5947 (should (= (point) 198))))
5949 (ert-deftest test-markdown-filling/list-line ()
5950 "Test fill-paragraph for list line. Don't insert bullet automatically.
5951 Detail: https://github.com/jrblevin/markdown-mode/issues/79"
5952 (markdown-test-string "* foo foo *foo* foo foo foo foo foo foo"
5953 (let ((fill-column 10))
5954 (fill-paragraph)
5955 (fill-paragraph)
5956 (forward-line 2)
5957 (back-to-indentation)
5958 (should-not (looking-at-p "\\*foo"))
5959 (forward-line 1)
5960 (back-to-indentation)
5961 (should-not (looking-at-p "\\*foo")))))
5963 (ert-deftest test-markdown-filling/ignore-header ()
5964 "# Test fill-paragraph for containing header line paragraph.
5965 https://github.com/jrblevin/markdown-mode/issues/159"
5966 (markdown-test-string "# this is header line
5967 this is not header line
5969 (let ((fill-column 10))
5970 (fill-paragraph)
5971 (should (string= (buffer-substring (point) (line-end-position)) "# this is header line")))))
5973 (ert-deftest test-markdown-filling/unclosed-square-bracket ()
5974 "Test fill-paragraph following an unclosed square bracket."
5975 (markdown-test-string "```\n[3\n```\n\naaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbb"
5976 (let ((fill-column 20))
5977 (forward-line 4)
5978 (fill-paragraph)
5979 (should (looking-at "aaaaaaaaaaaaaaaa\nbbbbbbbbbbbbbbbb")))))
5981 (ert-deftest test-markdown-filling/skip-code-blocks ()
5982 "Test `markdown-fill-paragraph' on code blocks."
5983 (let ((text "test\n\n```\nhello\nworld\n```"))
5984 (markdown-test-string text
5985 (dotimes (_ 5)
5986 ;; Fill at each line; buffer should not change.
5987 (fill-paragraph)
5988 (should (string-equal (buffer-string) text))))))
5990 (ert-deftest test-markdown-filling/fill-region-skip-code-blocks ()
5991 "Test `fill-region' on code blocks."
5992 (let ((text "testing\n\n```\nhello\nworld\n```\n\n123"))
5993 (markdown-test-string text
5994 ;; Fill entire buffer; buffer should not change.
5995 (fill-region (point-min) (point-max))
5996 (should (string-equal (buffer-string) text)))))
5998 (ert-deftest test-markdown-filling/fill-region-skip-code-blocks-2 ()
5999 "Test `fill-region' on a buffer with a code block with long paragraphs."
6000 (markdown-test-string "long unwrapped paragraph 1
6003 code
6004 block
6010 long unwrapped paragraph 2"
6011 ;; Test markdown-fill-forward-paragraph movement.
6012 (should (= (markdown-fill-forward-paragraph 1) 0))
6013 (should (= (point) 28)) ;; Point just after par. 1.
6014 (should (= (markdown-fill-forward-paragraph 1) 0))
6015 (should (= (point) 84)) ;; Point at end of par. 2.
6016 ;; Test filling the entire buffer with `fill-region'.
6017 (let ((fill-column 12))
6018 (fill-region (point-min) (point-max))
6019 (should (string-equal (buffer-string)
6020 "long
6021 unwrapped
6022 paragraph 1
6025 code
6026 block
6032 long
6033 unwrapped
6034 paragraph 2")))))
6036 (ert-deftest test-markdown-filling/fill-region-skip-code-blocks-3 ()
6037 "Test `fill-region' on a lone code block with no surrounding text."
6038 (let ((text "```\ncode\nblock\n```\n"))
6039 (markdown-test-string text
6040 ;; Fill entire buffer; buffer should not change.
6041 (fill-region (point-min) (point-max))
6042 (should (string-equal (buffer-string) text)))))
6044 (ert-deftest test-markdown-filling/long-paragraph-with-link ()
6045 "Test `fill-paragraph' on a long paragraph with a long link.
6046 See GH-173."
6047 (markdown-test-string
6048 "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."
6049 (let ((fill-column 79)) (fill-paragraph))
6050 (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
6051 aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa [aaa aaa aaa
6052 aaa](aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) aaa aaa aaa aaa aaa."))))
6054 (ert-deftest test-markdown-filling/pandoc-line-blocks ()
6055 "Filling should leave Pandoc line blocks undisturbed.
6056 This includes preserving whitespace after the pipe."
6057 (let ((text "| The limerick packs laughs anatomical
6058 | In space that is quite economical.
6059 | But the good ones I've seen
6060 | So seldom are clean
6061 | And the clean ones so seldom are comical
6063 | 200 Main St.
6064 | Berkeley, CA 94718"))
6065 (markdown-test-string text
6066 (fill-region (point-min) (point-max))
6067 (should (string-equal (buffer-string) text)))))
6069 (ert-deftest test-markdown-filling/setext-heading ()
6070 "Fill paragraph at setext heading.
6071 Details: https://github.com/jrblevin/markdown-mode/issues/638"
6072 (let ((input "Heading
6073 =======
6075 (markdown-test-string input
6076 (markdown-fill-paragraph)
6077 (should (string= (buffer-string) input))))
6078 (let ((input "Heading
6081 (markdown-test-string input
6082 (markdown-fill-paragraph)
6083 (should (string= (buffer-string) input))))
6084 ;; leading 3 spaces and trailing spaces is ok
6085 (let ((input "Heading
6086 ==== \t\n"))
6087 (markdown-test-string input
6088 (markdown-fill-paragraph)
6089 (should (string= (buffer-string) input))))
6090 ;; fill-paragraph is applied for list element
6091 (markdown-test-string "- foo
6092 bar baz"
6093 (markdown-fill-paragraph)
6094 (should (string= (buffer-string) "- foo bar baz"))))
6096 ;;; Export tests:
6098 (ert-deftest test-markdown-hook/xhtml-standalone ()
6099 "Test `markdown-xhtml-standalone-regexp' and `markdown-output-standalone-p'."
6100 (should (string-match markdown-xhtml-standalone-regexp
6101 "<?xml version='1.0' encoding='UTF-8'?>"))
6102 (should (string-match markdown-xhtml-standalone-regexp
6103 "<!DOCTYPE html>"))
6104 (should (string-match markdown-xhtml-standalone-regexp
6105 "<html>"))
6106 (should-not (string-match markdown-xhtml-standalone-regexp
6107 "<h1>title</h1>"))
6108 (should-not (string-match markdown-xhtml-standalone-regexp
6109 "<div id=\"name\">")))
6111 (ert-deftest test-markdown-export/kill-buffer-nil ()
6112 "Test `markdown-export-kill-buffer' equal to nil."
6113 (markdown-test-temp-file "inline.text"
6114 (let* ((markdown-export-kill-buffer nil)
6115 (markdown-command #'markdown-command-identity)
6116 (export-file (markdown-export))
6117 (export-buffer (get-file-buffer export-file)))
6118 ;; Output buffer should remain open.
6119 (should (member export-buffer (buffer-list))))))
6121 (ert-deftest test-markdown-export/kill-buffer-t ()
6122 "Test `markdown-export-kill-buffer' equal to t."
6123 (markdown-test-temp-file "inline.text"
6124 (let* ((markdown-export-kill-buffer t)
6125 (markdown-command #'markdown-command-identity)
6126 (export-file (markdown-export))
6127 (export-buffer (get-file-buffer export-file)))
6128 ;; Output buffer should be killed.
6129 (should-not export-buffer))))
6131 (ert-deftest test-markdown-export/body-preamble ()
6132 "Test `markdown-xhtml-body-preamble'."
6133 (markdown-test-temp-file "inline.text"
6134 (let* ((str "<!-- body preamble test -->")
6135 (markdown-xhtml-body-preamble str)
6136 (markdown-command #'markdown-command-identity)
6137 (markdown-export-kill-buffer nil)
6138 (ofile (markdown-export))
6139 (obuffer (get-file-buffer ofile)))
6140 (with-current-buffer obuffer
6141 (goto-char (point-min))
6142 (should (search-forward str)))
6143 (kill-buffer obuffer)
6144 (delete-file ofile))))
6146 (ert-deftest test-markdown-export/body-epilogue ()
6147 "Test `markdown-xhtml-body-epilogue'."
6148 (markdown-test-temp-file "inline.text"
6149 (let* ((str "<!-- body epilogue test -->")
6150 (markdown-xhtml-body-epilogue str)
6151 (markdown-command #'markdown-command-identity)
6152 (markdown-export-kill-buffer nil)
6153 (ofile (markdown-export))
6154 (obuffer (get-file-buffer ofile)))
6155 (with-current-buffer obuffer
6156 (goto-char (point-min))
6157 (should (search-forward str)))
6158 (kill-buffer obuffer)
6159 (delete-file ofile))))
6161 ;;; Hook tests:
6163 (ert-deftest test-markdown-hook/before-export ()
6164 "Test hook run before export XHTML."
6165 (markdown-test-temp-file "lists.text"
6166 (let* ((before-hook-run nil)
6167 (orig-point (point))
6168 (markdown-command #'markdown-command-identity)
6169 (func (lambda ()
6170 ;; Change value of a variable
6171 (setq before-hook-run t)
6172 ;; Insert some text
6173 (goto-char (point-min))
6174 (insert "#")
6175 ;; Deliberately move the point
6176 (end-of-line)
6177 ;; Verify changes
6178 (should (looking-back "^## List Cases" nil))
6179 (should-not (= (point) orig-point))))
6180 (ofile (progn
6181 ;; Register hook
6182 (add-hook 'markdown-before-export-hook func)
6183 ;; Export XHTML and return filename
6184 (markdown-export)))
6185 (obuffer (get-file-buffer ofile)))
6186 ;; Test side effects of hook
6187 (should (eq before-hook-run t))
6188 ;; Test position of point
6189 (should (= (point) orig-point))
6190 ;; Test that buffer was restored to original state
6191 (goto-char (point-min))
6192 (should (looking-at "^# List Cases"))
6193 ;; Clean
6194 (remove-hook 'markdown-before-export-hook func)
6195 (kill-buffer obuffer)
6196 (delete-file ofile))))
6198 (ert-deftest test-markdown-hook/after-export ()
6199 "Test hook run after export XHTML."
6200 (markdown-test-temp-file "lists.text"
6201 (let* ((after-hook-run nil)
6202 (markdown-command #'markdown-command-identity)
6203 (markdown-export-kill-buffer nil)
6204 (func (lambda ()
6205 ;; Change variable value
6206 (setq after-hook-run t)
6207 ;; Add comment to output buffer
6208 (goto-char (point-min))
6209 (insert "<!-- after-export-hook -->\n")))
6210 (ofile (progn
6211 ;; Register hook
6212 (add-hook 'markdown-after-export-hook func)
6213 ;; Export XHTML and return filename
6214 (markdown-export)))
6215 (obuffer (get-file-buffer ofile)))
6216 (message "obuffer = %S" obuffer)
6217 ;; Test that variable was changed
6218 (should (eq after-hook-run t))
6219 ;; Test that output buffer remains open
6220 (should (get-buffer obuffer))
6221 ;; Test that output buffer modification remains
6222 (with-current-buffer obuffer
6223 (goto-char (point-min))
6224 (should (looking-at "<!-- after-export-hook -->\n")))
6225 ;; Test that buffer modification was saved
6226 (should-not (buffer-modified-p obuffer))
6227 ;; Clean up
6228 (remove-hook 'markdown-after-export-hook func)
6229 (kill-buffer obuffer)
6230 (delete-file ofile))))
6232 ;;; Extension: math support
6234 (ert-deftest test-markdown-math/file-local-variable ()
6235 "Test enabling math mode via `hack-local-variables-hook'."
6236 (markdown-test-file "math.text"
6237 (should-not markdown-enable-math)
6238 (hack-local-variables)
6239 (should markdown-enable-math)))
6241 (ert-deftest test-markdown-math/reload ()
6242 "Test enabling math mode via variable `markdown-enable-math'."
6243 (let ((markdown-enable-math t))
6244 (markdown-test-file "math.text"
6245 ;; Flag should be set to t
6246 (should markdown-enable-math)
6247 ;; Font-lock keywords should be updated.
6248 (should (member (car markdown-mode-font-lock-keywords-math)
6249 (cadr font-lock-keywords))))))
6251 (ert-deftest test-markdown-math/preserve-user-keywords ()
6252 "Test preserving user-specified font-lock keywords."
6253 (let ((user-keyword '("\\<\\(FIXME\\):" 1 font-lock-warning-face t)))
6254 ;; Add user font-lock keyword using `font-lock-add-keywords'.
6255 (font-lock-add-keywords 'markdown-mode (list user-keyword))
6256 ;; Visit a file using `markdown-mode'.
6257 (markdown-test-file "math.text"
6258 ;; User keyword should be present initially.
6259 (should (member user-keyword (cadr font-lock-keywords)))
6260 ;; User keyword should persist after calling `markdown-reload-extensions'.
6261 (markdown-reload-extensions)
6262 (should (member user-keyword (cadr font-lock-keywords))))
6263 ;; Remove the user keyword using `font-lock-remove-keywords'.
6264 (font-lock-remove-keywords 'markdown-mode (list user-keyword))
6265 ;; Visit a file using `markdown-mode'.
6266 (markdown-test-file "inline.text"
6267 ;; User keyword should not be present after removal.
6268 (should-not (member user-keyword (cadr font-lock-keywords))))))
6270 (ert-deftest test-markdown-math/preserve-local-user-keywords ()
6271 "Test preserving buffer-specific user-specified font-lock keywords."
6272 (let ((user-keyword '("\\<\\(FIXME\\):" 1 font-lock-warning-face t)))
6273 ;; Visit a file using `markdown-mode'.
6274 (markdown-test-file "math.text"
6275 ;; Add user font-lock keyword using `font-lock-add-keywords'.
6276 (font-lock-add-keywords nil (list user-keyword))
6277 ;; User keyword should be present initially.
6278 (should (member user-keyword (cadr font-lock-keywords)))
6279 ;; User keyword should persist after calling `markdown-reload-extensions'.
6280 (markdown-reload-extensions)
6281 (should (member user-keyword (cadr font-lock-keywords)))
6282 ;; Remove the user keyword using `font-lock-remove-keywords'.
6283 (font-lock-remove-keywords nil (list user-keyword))
6284 ;; User keyword should not be present after removal.
6285 (should-not (member user-keyword (cadr font-lock-keywords))))))
6287 (ert-deftest test-markdown-math/font-lock ()
6288 "Test markdown math mode."
6289 (let ((markdown-enable-math t))
6290 (markdown-test-file "math.text"
6291 (markdown-test-range-has-face 1 32 nil)
6292 (markdown-test-range-has-face 33 33 'markdown-markup-face)
6293 (markdown-test-range-has-face 34 45 'markdown-math-face)
6294 (markdown-test-range-has-face 46 46 'markdown-markup-face)
6295 (markdown-test-range-has-face 47 49 nil)
6296 (markdown-test-range-has-face 50 51 'markdown-markup-face)
6297 (markdown-test-range-has-face 52 63 'markdown-math-face)
6298 (markdown-test-range-has-face 64 65 'markdown-markup-face)
6299 (markdown-test-range-has-face 66 98 nil)
6300 (markdown-test-range-has-face 99 100 'markdown-markup-face)
6301 (markdown-test-range-has-face 101 112 'markdown-math-face)
6302 (markdown-test-range-has-face 113 114 'markdown-markup-face)
6303 (markdown-test-range-has-face 113 114 'markdown-markup-face)
6304 (markdown-test-range-has-face 117 117 'markdown-header-delimiter-face)
6305 (markdown-test-range-has-face 119 152 'markdown-header-face-1)
6306 (markdown-test-range-has-face 129 129 'markdown-markup-face)
6307 (markdown-test-range-has-face 136 136 'markdown-markup-face)
6309 (markdown-test-range-has-face 174 177 'markdown-markup-face)
6310 (markdown-test-range-has-face 179 179 'markdown-markup-face)
6311 (markdown-test-range-has-face 180 187 'markdown-language-keyword-face)
6312 (markdown-test-range-has-face 188 188 'markdown-markup-face)
6313 (markdown-test-range-has-face 190 210 'markdown-pre-face)
6314 (markdown-test-range-has-face 212 215 'markdown-markup-face)
6316 (markdown-test-range-has-face 218 218 'markdown-markup-face)
6317 (markdown-test-range-has-face 219 223 'markdown-math-face)
6318 (markdown-test-range-has-face 224 224 'markdown-markup-face)
6319 (markdown-test-range-has-face 350 351 'markdown-markup-face)
6320 (markdown-test-range-has-face 352 356 'markdown-math-face)
6321 (markdown-test-range-has-face 357 358 'markdown-markup-face)
6322 (markdown-test-range-has-face 359 391 nil)
6323 (markdown-test-range-has-face 392 393 'markdown-markup-face)
6324 (markdown-test-range-has-face 394 398 'markdown-math-face)
6325 (markdown-test-range-has-face 399 400 'markdown-markup-face))))
6327 (ert-deftest test-markdown-math/double-slash-display-math ()
6328 "Test double slash display math font lock."
6329 (let ((markdown-enable-math t))
6330 (markdown-test-file "math.text"
6331 (markdown-test-range-has-face 403 474 nil)
6332 (markdown-test-range-has-face 475 477 'markdown-markup-face)
6333 (markdown-test-range-has-face 478 543 'markdown-math-face)
6334 (markdown-test-range-has-face 544 546 'markdown-markup-face))))
6336 (ert-deftest test-markdown-math/indented-double-slash-display-math ()
6337 "Test font lock for indented double slash display math.
6338 See GH-288."
6339 (let ((markdown-enable-math t))
6340 (markdown-test-string "- Einstein's equation:
6342 \\\\[ E = m c^2 \\\\]"
6343 (markdown-test-range-has-face 29 31 'markdown-markup-face)
6344 (markdown-test-range-has-face 32 42 'markdown-math-face)
6345 (markdown-test-range-has-face 43 45 'markdown-markup-face))))
6347 (ert-deftest test-markdown-math/font-lock-italics ()
6348 "Test markdown math mode with underscores."
6349 (let ((markdown-enable-math t))
6350 (markdown-test-file "math.text"
6351 (markdown-test-range-has-face 227 227 'markdown-markup-face)
6352 (markdown-test-range-has-face 228 233 'markdown-math-face)
6353 (markdown-test-range-has-face 234 234 'markdown-markup-face)
6354 (markdown-test-range-has-face 235 270 nil)
6355 (markdown-test-range-has-face 271 271 'markdown-markup-face)
6356 (markdown-test-range-has-face 272 274 'markdown-math-face)
6357 (markdown-test-range-has-face 275 275 'markdown-markup-face))))
6359 (ert-deftest test-markdown-math/font-lock-no-bold ()
6360 "Bold markers in math should not trigger bold."
6361 (let ((markdown-enable-math t))
6362 (markdown-test-file "math.text"
6363 (markdown-test-range-has-face 279 299 'markdown-math-face)
6364 (markdown-test-range-has-face 301 308 nil)
6365 (markdown-test-range-has-face 310 312 'markdown-math-face))))
6367 (ert-deftest test-markdown-math/math-inline-single ()
6368 "Test for math inline single.
6369 Detail: https://github.com/jrblevin/markdown-mode/issues/352"
6370 (let ((markdown-enable-math t))
6371 (markdown-test-string "$a$b$c$"
6372 (markdown-test-range-has-face 1 1 'markdown-markup-face)
6373 (markdown-test-range-has-face 2 2 'markdown-math-face)
6374 (markdown-test-range-has-face 3 3 'markdown-markup-face)
6376 (markdown-test-range-has-face 5 5 'markdown-markup-face)
6377 (markdown-test-range-has-face 6 6 'markdown-math-face)
6378 (markdown-test-range-has-face 7 7 'markdown-markup-face))))
6380 (ert-deftest test-markdown-math/math-inline-double ()
6381 "Test for math inline double. This is similar to #352 issue."
6382 (let ((markdown-enable-math t))
6383 (markdown-test-string "$$a$$b$$c$$"
6384 (markdown-test-range-has-face 1 2 'markdown-markup-face)
6385 (markdown-test-range-has-face 3 3 'markdown-math-face)
6386 (markdown-test-range-has-face 4 5 'markdown-markup-face)
6388 (markdown-test-range-has-face 7 8 'markdown-markup-face)
6389 (markdown-test-range-has-face 9 9 'markdown-math-face)
6390 (markdown-test-range-has-face 10 11 'markdown-markup-face))))
6392 (ert-deftest test-markdown-math/caret-in-math-inline ()
6393 "Test for carets in math inline.
6394 Details: https://github.com/jrblevin/markdown-mode/issues/802"
6395 (let ((markdown-enable-math t))
6396 (markdown-test-string "$a^b^c$"
6397 (markdown-test-range-has-face 3 3 'markdown-math-face)
6398 (markdown-test-range-has-face 5 5 'markdown-math-face))
6400 (markdown-test-string "$$a^b^c$$"
6401 (markdown-test-range-has-face 4 4 'markdown-math-face)
6402 (markdown-test-range-has-face 6 6 'markdown-math-face))))
6404 (ert-deftest test-markdown-math/math-inline-small-buffer ()
6405 "Test that font-lock parsing works with a single dollar."
6406 (let ((markdown-enable-math t))
6407 (markdown-test-string "$"
6408 (should t))
6409 (markdown-test-string "$$"
6410 (should t))
6411 (markdown-test-string "$$$"
6412 (should t))))
6414 ;;; Extension: pipe table editing
6416 (ert-deftest test-markdown-table/table-begin-top-of-file ()
6417 "Test beginning of table detection at top of file."
6418 (markdown-test-string "| 1 | 2 |\n| 3 | 4 |\n"
6419 (should (markdown-table-at-point-p))
6420 (forward-line)
6421 (should (markdown-table-at-point-p))
6422 (should (= (markdown-table-begin) 1))))
6424 ;;; Extension: pipe table insertion
6426 (ert-deftest test-markdown-insertion/create-table-with-left-align ()
6427 "Insert table with left column alignment."
6428 (markdown-test-string
6430 (execute-kbd-macro (read-kbd-macro "M-x markdown-insert-table RET 3 RET 2 RET l RET"))
6431 (should (string-equal (buffer-string) "| | |
6432 |:--|:--|
6433 | | |
6434 | | |
6436 (should (= (point) 3))))
6438 (ert-deftest test-markdown-insertion/create-table-with-right-align ()
6439 "Insert table with right column alignment."
6440 (markdown-test-string
6442 (execute-kbd-macro (read-kbd-macro "M-x markdown-insert-table RET 3 RET 2 RET r RET"))
6443 (should (string-equal (buffer-string) "| | |
6444 |--:|--:|
6445 | | |
6446 | | |
6448 (should (= (point) 3))))
6450 (ert-deftest test-markdown-insertion/create-table-with-center-align ()
6451 "Insert table with center column alignment."
6452 (markdown-test-string
6454 (execute-kbd-macro (read-kbd-macro "M-x markdown-insert-table RET 3 RET 2 RET c RET"))
6455 (should (string-equal (buffer-string) "| | |
6456 |:-:|:-:|
6457 | | |
6458 | | |
6460 (should (= (point) 3))))
6462 (ert-deftest test-markdown-insertion/create-table-with-default-align ()
6463 "Insert table with default column alignment."
6464 (markdown-test-string
6466 (execute-kbd-macro (read-kbd-macro "M-x markdown-insert-table RET 3 RET 2 RET RET"))
6467 (should (string-equal (buffer-string) "| | |
6468 |---|---|
6469 | | |
6470 | | |
6472 (should (= (point) 3))))
6474 (ert-deftest test-markdown-table/align-with-escaped-separator ()
6475 "Test table align if column has escaped separator.
6476 Details: https://github.com/jrblevin/markdown-mode/issues/308"
6477 (markdown-test-string "| Col1 | Col2 |
6478 | :-: | :-: |
6479 | AAA | A\\|B |"
6480 (search-forward "Col2")
6481 (markdown-table-align)
6482 (should (string= (buffer-substring-no-properties (point-min) (point-max))
6483 "| Col1 | Col2 |
6484 |:----:|:----:|
6485 | AAA | A\\|B |\n"))))
6487 (ert-deftest test-markdown-table/align-with-wiki-link ()
6488 "Test table align if column has wiki link.
6489 Details: https://github.com/jrblevin/markdown-mode/issues/308"
6490 (let ((markdown-enable-wiki-links t))
6491 (markdown-test-string "| A | B |
6492 |-------------|---------|
6493 | [[Page|Address]] | Content |"
6494 (search-forward "B")
6495 (markdown-table-align)
6496 (should (string= (buffer-substring-no-properties (point-min) (point-max))
6497 "| A | B |
6498 |------------------|---------|
6499 | [[Page|Address]] | Content |")))))
6501 (ert-deftest test-markdown-table/table-line-to-columns ()
6502 "Test for splitting table line to columns."
6503 (should (equal (markdown--table-line-to-columns "|foo|") '("foo")))
6504 (should (equal (markdown--table-line-to-columns "foo") '("foo")))
6505 (should (equal (markdown--table-line-to-columns "|foo|bar|") '("foo" "bar")))
6506 (should (equal (markdown--table-line-to-columns " | foo | bar | ") '("foo" "bar")))
6507 (should (equal (markdown--table-line-to-columns "foo|bar") '("foo" "bar")))
6508 (should (equal (markdown--table-line-to-columns "foo | bar | baz") '("foo" "bar" "baz")))
6509 (should (equal (markdown--table-line-to-columns "| x \\| |") '("x \\|"))))
6511 (ert-deftest test-markdown-table/blank-line ()
6512 "Test for creating new blank line."
6513 (should (string= (markdown-table-blank-line "|foo|") "| |"))
6514 (should (string= (markdown-table-blank-line "|foo|barbaz|") "| | |"))
6515 (should (string= (markdown-table-blank-line "|a|bb|ccc|") "| | | |"))
6517 (let ((markdown-enable-wiki-links t))
6518 (should (string= (markdown-table-blank-line "| [[Page|Address]] | Content |")
6519 "| | |"))))
6521 (ert-deftest test-markdown-table/get-column ()
6522 "Test for getting column number"
6523 (markdown-test-string "| Col1 | Col2 |"
6524 (search-forward "Col1")
6525 (should (= (markdown-table-get-column) 1))
6526 (search-forward "Col2")
6527 (should (= (markdown-table-get-column) 2)))
6529 (markdown-test-string "| [[Page|Address]] | Content |"
6530 (search-forward "Content")
6531 (should (= (markdown-table-get-column) 3)))
6533 (let ((markdown-enable-wiki-links t))
6534 (markdown-test-string "| [[Page|Address]] | Content |"
6535 (search-forward "Content")
6536 (should (= (markdown-table-get-column) 2)))))
6538 (ert-deftest test-markdown-table/goto-column ()
6539 "Test for goto specified column."
6540 (markdown-test-string "| Col1 | Col2 |"
6541 (markdown-table-goto-column 1)
6542 (should (string= (thing-at-point 'word) "Col1"))
6543 (markdown-table-goto-column 2)
6544 (should (string= (thing-at-point 'word) "Col2")))
6546 (markdown-test-string "| [[Page|Address]] | Content |"
6547 (markdown-table-goto-column 2)
6548 (should (string= (thing-at-point 'word) "Address")))
6550 (let ((markdown-enable-wiki-links t))
6551 (markdown-test-string "| [[Page|Address]] | Content |"
6552 (markdown-table-goto-column 2)
6553 (should (string= (thing-at-point 'word) "Content")))))
6555 (ert-deftest test-markdown-table/get-column-with-escaped-vertical-bar ()
6556 "Test for getting column number with escaped vertical bar.
6557 Details: https://github.com/jrblevin/markdown-mode/issues/635"
6558 (markdown-test-string "| Col1 | Col2 \\| Col2 \\| Col2 |"
6559 (search-forward "Col2")
6560 (should (= (markdown-table-get-column) 2))
6561 (search-forward "Col2")
6562 (should (= (markdown-table-get-column) 2))
6563 (search-forward "Col2")
6564 (should (= (markdown-table-get-column) 2))))
6566 (ert-deftest test-markdown-table/transpose-with-wiki-link ()
6567 "Test for table transpose with link.
6568 Detail: https://github.com/jrblevin/markdown-mode/commit/44a1c5bbc5d9514e97c7cc0a90a0c578130cd1dc"
6569 (let ((markdown-enable-wiki-links t))
6570 (markdown-test-string "| A | B |
6571 | [[Page|Address]] | Content |
6573 (markdown-table-transpose)
6574 (should (string=
6575 (buffer-substring-no-properties (point-min) (point-max))
6576 "| A | [[Page|Address]] |
6577 | B | Content |
6578 ")))))
6580 (ert-deftest test-markdown-table/forward-cell-with-escaped-vertical-bar ()
6581 "Test for table forward-cell with escaped vertical bar.
6582 Detail: https://github.com/jrblevin/markdown-mode/issues/489"
6583 (markdown-test-string "| x \\| |
6585 (forward-char 1)
6586 (markdown-table-forward-cell)
6587 (should (string=
6588 (buffer-substring-no-properties (point-min) (point-max))
6589 "| x \\| |
6591 "))))
6593 (ert-deftest test-markdown-table/forward-cell-at-last-column ()
6594 "Test for table forward-cell at last column.
6595 Detail: https://github.com/jrblevin/markdown-mode/issues/522"
6596 (markdown-test-string "| one | two |
6597 | three | four |
6599 (search-forward "two")
6600 (markdown-table-forward-cell)
6601 (should (string= (thing-at-point 'word) "three"))
6602 (markdown-table-forward-cell)
6603 (should (string= (thing-at-point 'word) "four"))
6604 (markdown-table-forward-cell)
6605 (should (string= (buffer-substring-no-properties (line-beginning-position) (line-end-position))
6606 "| | |"))))
6608 (ert-deftest test-markdown-table/backward-cell-with-escaped-vertical-bar ()
6609 "Test for table backward-cell with escaped vertical bar."
6610 (markdown-test-string "| x \\| | |"
6611 (goto-char (point-max))
6612 (backward-char 1)
6613 (markdown-table-backward-cell)
6614 (should (char-equal (char-after) ?x))))
6616 (ert-deftest test-markdown-table/column-move-with-escaped-vertical-bar ()
6617 "Test for column move with escaped vertical bar.
6618 Details: https://github.com/jrblevin/markdown-mode/issues/635"
6619 (markdown-test-string "| a \\| | b |"
6620 (search-forward "b")
6621 (markdown-table-move-column-left)
6622 (should (string= (buffer-substring-no-properties (line-beginning-position) (line-end-position))
6623 "| b | a \\| |")))
6625 (markdown-test-string "| a \\| | b |"
6626 (search-forward "a")
6627 (markdown-table-move-column-right)
6628 (should (string= (buffer-substring-no-properties (line-beginning-position) (line-end-position))
6629 "| b | a \\| |"))))
6631 (ert-deftest test-markdown-table/insert-column-with-escaped-vertical-bar ()
6632 "Test for inserting column with escaped vertical bar.
6633 Details: https://github.com/jrblevin/markdown-mode/issues/635"
6634 (markdown-test-string "| a | b \\| bb |
6635 | c | d |"
6636 (search-forward "bb")
6637 (markdown-table-insert-column)
6638 (should (string= (buffer-string)
6639 "| a | | b \\| bb |
6640 | c | | d |
6641 "))))
6643 (ert-deftest test-markdown-table/delete-column-with-escaped-vertical-bar ()
6644 "Test for deleting column with escaped vertical bar.
6645 Details: https://github.com/jrblevin/markdown-mode/issues/635"
6646 (markdown-test-string "| a | b \\| bb |
6647 | c | d |"
6648 (search-forward "bb")
6649 (markdown-table-delete-column)
6650 (should (string= (buffer-string)
6651 "| a |
6652 | c |"))))
6654 ;;; gfm-mode tests:
6656 (ert-deftest test-markdown-gfm/pre-1 ()
6657 "GFM pre block font lock test."
6658 (markdown-test-file-gfm "gfm.text"
6659 (markdown-test-range-has-face 2626 2637 nil)
6660 (markdown-test-range-has-face 2639 2641 'markdown-markup-face)
6661 (markdown-test-range-has-face 2642 2645 'markdown-language-keyword-face)
6662 (markdown-test-range-has-face 2647 2728 'markdown-pre-face)
6663 (markdown-test-range-has-face 2730 2732 'markdown-markup-face)))
6665 (ert-deftest test-markdown-gfm/italic-1 ()
6666 "GFM italic font lock test."
6667 (markdown-test-file-gfm "gfm.text"
6668 (markdown-test-range-has-face 1483 1483 'markdown-markup-face)
6669 (markdown-test-range-has-face 1484 1487 'markdown-italic-face)
6670 (markdown-test-range-has-face 1488 1488 'markdown-markup-face)
6671 (markdown-test-range-has-face 1729 1790 nil)))
6673 (ert-deftest test-markdown-gfm/italic-underscore ()
6674 "Test for GFM italic font lock test based on CommonMark specification.
6675 Details: https://github.com/jrblevin/markdown-mode/issues/448"
6676 (markdown-test-string-gfm "_no_emphasis
6677 *emphasis*
6678 em*pha*sis
6679 *emph*asis
6680 emph*asis*
6681 em*ph as*is
6682 _emphasis_
6683 no_emph_asis
6684 no_emphasis_
6685 no_em ph_asis
6687 (markdown-test-range-has-face 2 3 nil)
6688 (markdown-test-range-has-face 15 22 'markdown-italic-face)
6689 (markdown-test-range-has-face 28 30 'markdown-italic-face)
6690 (markdown-test-range-has-face 37 40 'markdown-italic-face)
6691 (markdown-test-range-has-face 52 55 'markdown-italic-face)
6692 (markdown-test-range-has-face 61 65 'markdown-italic-face)
6693 (markdown-test-range-has-face 71 78 'markdown-italic-face)
6694 (markdown-test-range-has-face 84 87 nil)
6695 (markdown-test-range-has-face 97 104 nil)
6696 (markdown-test-range-has-face 110 114 nil)))
6698 (ert-deftest test-markdown-gfm/italic-underscore-one-character ()
6699 "Test for GFM italic font lock test for one character.
6700 Details: https://github.com/jrblevin/markdown-mode/issues/524"
6701 (markdown-test-string-gfm "*a* other text *abc*"
6702 (markdown-test-range-has-face 3 3 'markdown-markup-face)
6703 (markdown-test-range-has-face 4 15 nil)
6704 (markdown-test-range-has-face 16 16 'markdown-markup-face)
6705 (markdown-test-range-has-face 17 19 'markdown-italic-face)
6706 (markdown-test-range-has-face 20 20 'markdown-markup-face))
6708 (markdown-test-string-gfm "*a* _b_"
6709 (markdown-test-range-has-face 1 1 'markdown-markup-face)
6710 (markdown-test-range-has-face 2 2 'markdown-italic-face)
6711 (markdown-test-range-has-face 3 3 'markdown-markup-face)
6712 (markdown-test-range-has-face 4 4 nil)
6713 (markdown-test-range-has-face 5 5 'markdown-markup-face)
6714 (markdown-test-range-has-face 6 6 'markdown-italic-face)
6715 (markdown-test-range-has-face 7 7 'markdown-markup-face)))
6717 (ert-deftest test-markdown-gfm/italic-underscore-following-functuation-character ()
6718 "Test for GFM italic font lock with following punctuation character
6719 Details: https://github.com/jrblevin/markdown-mode/issues/553"
6720 (markdown-test-string-gfm "_One_, _two_, or _three_."
6721 ;; one
6722 (markdown-test-range-has-face 1 1 'markdown-markup-face)
6723 (markdown-test-range-has-face 2 4 'markdown-italic-face)
6724 (markdown-test-range-has-face 5 5 'markdown-markup-face)
6725 ;; two
6726 (markdown-test-range-has-face 8 8 'markdown-markup-face)
6727 (markdown-test-range-has-face 9 11 'markdown-italic-face)
6728 (markdown-test-range-has-face 12 12 'markdown-markup-face)
6729 ;; or
6730 (markdown-test-range-has-face 15 16 nil)
6731 ;; three
6732 (markdown-test-range-has-face 18 18 'markdown-markup-face)
6733 (markdown-test-range-has-face 19 23 'markdown-italic-face)
6734 (markdown-test-range-has-face 24 24 'markdown-markup-face)))
6736 (ert-deftest test-markdown-gfm/bold-underscore ()
6737 "Test for GFM bold font lock test.
6738 Details: https://github.com/jrblevin/markdown-mode/issues/525"
6739 (markdown-test-string-gfm "**strong**
6740 st**ro**ng
6741 **str**ong
6742 str**ong**
6743 **still strong**
6744 **still str**ong
6745 sti**ll strong**
6746 sti**ll str**ong
6747 __strong__
6748 not__str__ong
6749 __not__strong
6750 not__strong__
6751 __still strong__
6752 no__t strong__
6753 __not str__ong
6754 no__t str__ong
6756 (markdown-test-range-has-face 3 8 'markdown-bold-face)
6757 (markdown-test-range-has-face 16 17 'markdown-bold-face)
6758 (markdown-test-range-has-face 27 27 'markdown-bold-face)
6759 (markdown-test-range-has-face 39 41 'markdown-bold-face)
6760 (markdown-test-range-has-face 47 58 'markdown-bold-face)
6761 (markdown-test-range-has-face 64 72 'markdown-bold-face)
6762 (markdown-test-range-has-face 84 92 'markdown-bold-face)
6763 (markdown-test-range-has-face 101 106 'markdown-bold-face)
6764 (markdown-test-range-has-face 115 120 'markdown-bold-face)
6765 (markdown-test-range-has-face 129 131 nil)
6766 (markdown-test-range-has-face 140 142 nil)
6767 (markdown-test-range-has-face 168 179 'markdown-bold-face)
6768 (markdown-test-range-has-face 200 206 nil)
6769 (markdown-test-range-has-face 217 221 nil)))
6771 (ert-deftest test-markdown-gfm/string-between-strong-markup ()
6772 "Test for string between strong markup.
6773 Details: https://github.com/jrblevin/markdown-mode/issues/534"
6774 (markdown-test-string-gfm "**foo** and **bar**"
6775 (markdown-test-range-has-face 1 2 'markdown-markup-face)
6776 (markdown-test-range-has-face 3 5 'markdown-bold-face)
6777 (markdown-test-range-has-face 6 7 'markdown-markup-face)
6778 (markdown-test-range-has-face 8 12 nil)
6779 (markdown-test-range-has-face 13 14 'markdown-markup-face)
6780 (markdown-test-range-has-face 15 17 'markdown-bold-face)
6781 (markdown-test-range-has-face 18 19 'markdown-markup-face)))
6783 (ert-deftest test-markdown-gfm/strike-through-1 ()
6784 "GFM strike through font lock test."
6785 (markdown-test-string-gfm "one ~~two~~ three"
6786 (markdown-test-range-has-face 1 4 nil)
6787 (markdown-test-range-has-face 5 6 'markdown-markup-face)
6788 (markdown-test-range-has-face 7 9 'markdown-strike-through-face)
6789 (markdown-test-range-has-face 10 11 'markdown-markup-face)
6790 (markdown-test-range-has-face 12 17 nil)))
6792 (ert-deftest test-markdown-gfm/insert-strike-through ()
6793 "Test `markdown-insert-strike-through'."
6794 (markdown-test-string-gfm "one two three"
6795 (push-mark (point) t t)
6796 (forward-word 2)
6797 (markdown-insert-strike-through)
6798 (should (string-equal (buffer-string) "~~one two~~ three")))
6799 (markdown-test-string-gfm " one two three"
6800 (push-mark (point) t t)
6801 (goto-char 11)
6802 (markdown-insert-strike-through)
6803 (should (string-equal (buffer-string) " ~~one two~~ three"))))
6805 (ert-deftest test-markdown-gfm/toggle-strike-through ()
6806 "Test toggling functionality of `markdown-insert-strike-through'."
6807 (markdown-test-string-gfm "one ~~two~~ three"
6808 (forward-word 2)
6809 (markdown-insert-strike-through)
6810 (should (string-equal (buffer-string) "one two three"))
6811 (should (= (point) 8))
6812 (forward-word)
6813 (markdown-insert-strike-through)
6814 (should (= (point) 16))
6815 (should (string-equal (buffer-string) "one two ~~three~~"))))
6817 (ert-deftest test-markdown-gfm/toggle-strike-through-consecutive ()
6818 "Test toggling functionality of consecutive strike-throughs."
6819 (markdown-test-string-gfm "one ~~two~~ ~~three~~"
6820 (search-forward "w")
6821 (markdown-insert-strike-through)
6822 (should (string-equal (buffer-string) "one two ~~three~~"))))
6824 (ert-deftest test-markdown-gfm/insert-code-block-empty-markup ()
6825 "Test GFM code block insertion with empty code section."
6826 (markdown-test-string-gfm "line 1\nline 2\n"
6827 (end-of-line)
6828 (markdown-insert-gfm-code-block "elisp")
6829 (should (equal (car markdown-gfm-used-languages) "elisp"))
6830 (should (equal (car (markdown-gfm-get-corpus)) "elisp"))
6831 (should (string-equal (buffer-string)
6832 "line 1\n\n``` elisp\n\n```\n\nline 2\n"))))
6834 (ert-deftest test-markdown-gfm/markdown-spaces-after-code-fence ()
6835 "Test `markdown-spaces-after-code-fence'."
6836 (markdown-test-string-gfm ""
6837 (let ((markdown-spaces-after-code-fence 0))
6838 (markdown-insert-gfm-code-block "elisp")
6839 (should (equal (buffer-string) "```elisp\n\n```")))))
6841 (ert-deftest test-markdown-gfm/insert-code-block-active-region ()
6842 "Test GFM code block insertion with active region."
6843 (markdown-test-string-gfm "line 1\nline 2\nline 3\n"
6844 (forward-line)
6845 (transient-mark-mode)
6846 (push-mark (point) t t)
6847 (end-of-line)
6848 (should (use-region-p))
6849 (markdown-insert-gfm-code-block "elisp")
6850 (should (string-equal (buffer-string)
6851 "line 1\n\n``` elisp\nline 2\n```\n\nline 3\n"))))
6853 (ert-deftest test-markdown-gfm/insert-code-block-indented-list-item ()
6854 "Test GFM code block insertion with an indented list item."
6855 (markdown-test-string-gfm "1. foo\n "
6856 (goto-char (point-max))
6857 (markdown-insert-gfm-code-block "elisp")
6858 (should (equal (buffer-substring-no-properties (point-min) (point-max))
6859 "1. foo\n\n ``` elisp\n \n ```"))
6860 (should (equal (buffer-substring-no-properties (point) (point-max))
6861 "\n ```"))))
6863 (ert-deftest test-markdown-gfm/insert-code-block-indented-list-item-active-region ()
6864 "Test GFM code block insertion with an indented list item and active region."
6865 (markdown-test-string-gfm "1. foo\n bar\n"
6866 (let ((transient-mark-mode t))
6867 (forward-line)
6868 (push-mark nil :nomsg :activate)
6869 (end-of-line)
6870 (should (use-region-p))
6871 (markdown-insert-gfm-code-block "elisp"))
6872 (should (equal (buffer-substring-no-properties (point-min) (point-max))
6873 "1. foo\n\n ``` elisp\n bar\n ```\n\n"))
6874 (should (equal (buffer-substring-no-properties (point) (point-max))
6875 "\n bar\n ```\n\n"))))
6877 (ert-deftest test-markdown-gfm/markdown-code-block-braces ()
6878 "Test `markdown-gfm-use-electric-backquote'."
6879 (markdown-test-string-gfm ""
6880 (let ((markdown-code-block-braces t))
6881 (markdown-insert-gfm-code-block "elisp")
6882 (should (equal (buffer-string) "```{elisp}\n\n```")))))
6884 (ert-deftest test-markdown-gfm/gfm-parse-buffer-for-languages ()
6885 "Parse buffer for existing languages for `markdown-gfm-used-languages' test."
6886 (markdown-test-string-gfm "``` MADEUP\n\n```\n``` LANGUAGES\n\n```\n```MaDeUp\n\n```\n```\n\n```\n``` \n\n```\n"
6887 (markdown-gfm-parse-buffer-for-languages)
6888 (should (equal markdown-gfm-used-languages
6889 (list "MaDeUp" "LANGUAGES" "MADEUP")))
6890 (should (equal (car markdown-gfm-used-languages) "MaDeUp"))
6891 (should (equal (car (markdown-gfm-get-corpus)) "MaDeUp"))
6892 (goto-char (point-max))
6893 (markdown-insert-gfm-code-block "newlang")
6894 (should (equal markdown-gfm-used-languages
6895 (list "newlang" "MaDeUp" "LANGUAGES" "MADEUP")))
6896 (should (equal (car markdown-gfm-used-languages) "newlang"))
6897 (should (equal (car (markdown-gfm-get-corpus)) "newlang"))
6898 (let ((markdown-gfm-downcase-languages nil))
6899 (should
6900 (equal (markdown-gfm-get-corpus)
6901 (append markdown-gfm-used-languages
6902 markdown-gfm-additional-languages
6903 markdown-gfm-recognized-languages))))
6904 (let ((markdown-gfm-downcase-languages t))
6905 (should
6906 (equal
6907 (markdown-gfm-get-corpus)
6908 (append markdown-gfm-used-languages
6909 (cl-mapcar #'downcase
6910 (append markdown-gfm-additional-languages
6911 markdown-gfm-recognized-languages))))))))
6913 (ert-deftest test-markdown-gfm/insert-code-block-at-end-of-buffer ()
6914 "Insert GFM code block at end of buffer.
6915 Details: https://github.com/jrblevin/markdown-mode/issues/634"
6916 (markdown-test-string-gfm ""
6917 (goto-char (point-max))
6918 (execute-kbd-macro (read-kbd-macro "C-c C-s C RET"))
6919 ;; don't raise exception
6920 (should t)))
6922 (ert-deftest test-markdown-gfm/code-block-font-lock ()
6923 "GFM code block font lock test."
6924 (markdown-test-file-gfm "gfm.text"
6925 (markdown-test-range-has-face 2639 2641 'markdown-markup-face) ; ```
6926 (markdown-test-range-has-face 2642 2645 'markdown-language-keyword-face) ; lang
6927 (markdown-test-range-has-face 2647 2728 'markdown-pre-face) ; code
6928 (markdown-test-range-has-face 2730 2732 'markdown-markup-face))) ; ```
6930 (ert-deftest test-markdown-gfm/code-block-font-lock-2 ()
6931 "GFM code block font lock test without language identifier."
6932 (markdown-test-string-gfm "Plain code block:\n\n```\nfoo\n```\n"
6933 (markdown-test-range-has-face 20 22 'markdown-markup-face)
6934 (markdown-test-range-has-face 24 26 'markdown-pre-face)
6935 (markdown-test-range-has-face 28 30 'markdown-markup-face)))
6937 (ert-deftest test-markdown-gfm/one-line-code-block ()
6938 "Don't handle backtick as code block language.
6939 Details: https://github.com/jrblevin/markdown-mode/issues/403"
6940 (markdown-test-string-gfm "```three```"
6941 (let ((face-props (get-text-property 4 'face)))
6942 (should (memq 'markdown-inline-code-face face-props))
6943 (should-not (memq 'markdown-language-keyword-face face-props)))))
6945 ;;; Extension: GFM simplified tables
6947 (ert-deftest test-markdown-gfm/false-table-first-line ()
6948 "Test beginning of table detection at beginning of buffer.
6949 Based on GH-298."
6950 (markdown-test-string
6951 "[|"
6952 (should-not (gfm--table-at-point-p))))
6954 (ert-deftest test-markdown-gfm/true-table-first-line ()
6955 "Test beginning of table detection at beginning of buffer."
6956 (markdown-test-string
6960 (dotimes (_ 3)
6961 (should (gfm--table-at-point-p))
6962 (forward-line))))
6964 (ert-deftest test-markdown-gfm/table-begin-top-of-file ()
6965 "Test beginning of table detection at top of file."
6966 (markdown-test-string "[|"
6967 (should-not (gfm--table-at-point-p))))
6969 ;;; Tests for other extensions:
6971 (ert-deftest test-markdown-ext/pandoc-fancy-lists ()
6972 "Test basic support for font lock and filling of Pandoc 'fancy lists'."
6973 (markdown-test-string " #. abc\ndef\n"
6974 ;; font lock
6975 (markdown-test-range-has-face 1 1 nil)
6976 (markdown-test-range-has-face 2 3 'markdown-list-face)
6977 (markdown-test-range-has-face 4 11 nil)
6978 ;; filling
6979 (forward-line)
6980 (markdown-indent-region (line-beginning-position) (line-end-position) nil)
6981 (should (string-equal (buffer-string) " #. abc\n def\n"))
6982 (markdown-indent-region (line-beginning-position) (line-end-position) nil)
6983 (should (string-equal (buffer-string) " #. abc\n def\n"))))
6985 (ert-deftest test-markdown-ext/wiki-link-rules ()
6986 "Test wiki link search rules and font lock for missing pages."
6987 (let ((markdown-enable-wiki-links t)
6988 (markdown-wiki-link-fontify-missing t)
6989 (markdown-wiki-link-search-type '(project)))
6990 (progn
6991 (find-file (expand-file-name "wiki/root" markdown-test-dir))
6992 (unwind-protect
6993 (progn
6994 (markdown-mode)
6995 ;; search rules
6996 (should (string-match-p
6997 "/sub/foo$"
6998 (markdown-convert-wiki-link-to-filename "foo")))
6999 (should (string-equal
7000 (markdown-convert-wiki-link-to-filename "doesnotexist")
7001 "doesnotexist"))
7002 ;; font lock
7003 (markdown-test-range-has-property 1 11 'font-lock-face 'markdown-link-face)
7004 (markdown-test-range-has-property 14 33 'font-lock-face 'markdown-missing-link-face)
7005 (markdown-test-range-has-property 36 42 'font-lock-face 'markdown-link-face)
7006 (markdown-test-range-has-property 45 60 'font-lock-face 'markdown-missing-link-face))
7007 (kill-buffer)))
7008 (progn
7009 (find-file (expand-file-name "wiki/sub/foo" markdown-test-dir))
7010 (unwind-protect
7011 (progn
7012 (markdown-mode)
7013 ;; search rules
7014 (should (string-match-p
7015 "/wiki/root$"
7016 (markdown-convert-wiki-link-to-filename "root")))
7017 (should (string-equal
7018 (markdown-convert-wiki-link-to-filename "doesnotexist")
7019 "doesnotexist"))
7020 ;; font lock
7021 (markdown-test-range-has-property 1 16 'font-lock-face 'markdown-missing-link-face)
7022 (markdown-test-range-has-property 19 26 'font-lock-face 'markdown-link-face))
7023 (kill-buffer)))))
7025 (ert-deftest test-markdown-ext/wiki-link-keep-match-data ()
7026 "Test that markdown-wiki-link-p keeps expected match data.
7027 Detail: https://github.com/jrblevin/markdown-mode/pull/590"
7028 (let ((markdown-enable-wiki-links t)
7029 (markdown-link-space-sub-char " ")
7030 (markdown-wiki-link-search-type '(sub-directories)))
7031 (progn
7032 (find-file (expand-file-name "wiki/pr590/Guide.md" markdown-test-dir))
7033 (unwind-protect
7034 (progn
7035 (markdown-mode)
7036 (re-search-forward "Zettel Markdown")
7037 (goto-char (match-beginning 0))
7038 (should (markdown-wiki-link-p)) ;; create match-data
7039 (should (string= (markdown-wiki-link-link) "Zettel Markdown")))
7040 (kill-buffer)))))
7042 (ert-deftest test-markdown-ext/wiki-link-search-under-project ()
7043 "Test that searching link under project root."
7044 (let ((markdown-enable-wiki-links t)
7045 (markdown-link-space-sub-char " ")
7046 (markdown-wiki-link-search-type '(project))
7047 (expected (expand-file-name "wiki/pr590/Guide/Zettel Markdown/math.md"
7048 markdown-test-dir)))
7049 (progn
7050 (find-file (expand-file-name "wiki/pr590/Guide/Plugin/Link.md" markdown-test-dir))
7051 (unwind-protect
7052 (progn
7053 (markdown-mode)
7054 (re-search-forward "math")
7055 (goto-char (match-beginning 0))
7056 (markdown-wiki-link-p) ;; create match-data
7057 (let ((link (markdown-convert-wiki-link-to-filename (markdown-wiki-link-link))))
7058 (should (string= (expand-file-name link) expected))))
7059 (kill-buffer)))))
7061 (ert-deftest test-markdown-ext/wiki-link-major-mode ()
7062 "Test major-mode of linked page."
7063 (let ((markdown-enable-wiki-links t)
7064 (auto-mode-alist (cons '("bar\\.md" . gfm-mode) auto-mode-alist)))
7065 (find-file (expand-file-name "wiki/root" markdown-test-dir))
7066 (unwind-protect
7067 (progn
7068 (markdown-mode)
7069 (search-forward "sub/bar.md")
7070 (markdown-follow-wiki-link-at-point)
7071 (should (eq major-mode 'gfm-mode)))
7072 (kill-buffer))))
7074 (ert-deftest test-markdown-ext/wiki-link-nonexistent-file ()
7075 "Test following wiki link to nonexistent file visits the buffer."
7076 (let ((markdown-enable-wiki-links t))
7077 (find-file (expand-file-name "wiki/foo.md" markdown-test-dir))
7078 (unwind-protect
7079 (progn
7080 (markdown-mode)
7081 (search-forward "[[doesnotexist]]")
7082 (markdown-follow-wiki-link-at-point)
7083 (should (string= (buffer-name) "doesnotexist.md")))
7084 (kill-buffer))))
7086 (defun markdown-test-live-preview-window-eww (_orig-fun &rest _args)
7087 (get-buffer-create "*eww*"))
7089 (defmacro markdown-test-fake-eww (&rest body)
7090 `(progn
7091 ,@(if (fboundp 'libxml-parse-html-region)
7092 body
7093 `((advice-add 'markdown-live-preview-window-eww :around #'markdown-test-live-preview-window-eww)
7094 ,@body
7095 (advice-remove 'markdown-live-preview-window-eww #'markdown-test-live-preview-window-eww)))))
7097 (defmacro markdown-test-eww-or-nothing (test &rest body)
7098 (declare (indent 1))
7099 (if (and (fboundp 'libxml-parse-html-region) (executable-find markdown-command))
7100 `(progn ,@body)
7101 (message "no eww, no libxml2, or no %s found: skipping %s" markdown-command test)
7102 nil))
7104 (ert-deftest test-markdown-ext/live-preview-no-file ()
7105 "Live-preview a `markdown-mode' buffer without a file."
7106 (with-temp-buffer
7107 (markdown-mode)
7109 ;; Activating `markdown-live-preview-mode' signals error
7110 (let ((data (should-error (markdown-live-preview-mode) :type 'user-error)))
7111 (should (string-match-p
7112 (rx bos "Buffer " (+ nonl) " does not visit a file" eos)
7113 (error-message-string data))))
7115 ;; After trying to activate live preview mode, mode is not activated
7116 (should-not markdown-live-preview-mode)
7118 ;; `markdown-live-preview-export' does nothing
7119 (should-not (markdown-live-preview-export))
7121 ;; `markdown-live-preview-remove' does nothing
7122 (should-not (markdown-live-preview-remove))))
7124 (ert-deftest test-markdown-ext/live-preview-exports ()
7125 (let ((markdown-command #'markdown-command-identity))
7126 (markdown-test-temp-file "inline.text"
7127 (unless (and (fboundp 'libxml-parse-html-region) (require 'eww nil t))
7128 (should-error (markdown-live-preview-mode)))
7129 (markdown-test-fake-eww
7130 (markdown-live-preview-mode)
7131 (should (buffer-live-p markdown-live-preview-buffer))
7132 (should (eq (current-buffer)
7133 (with-current-buffer markdown-live-preview-buffer
7134 markdown-live-preview-source-buffer)))
7135 (kill-buffer markdown-live-preview-buffer)
7136 (should (null markdown-live-preview-buffer))
7137 (set-buffer-modified-p t)
7138 (save-buffer) ;; should create new export
7139 (should (buffer-live-p markdown-live-preview-buffer))))))
7141 (ert-deftest test-markdown-ext/live-preview-delete-exports ()
7142 (markdown-test-fake-eww
7143 (let ((markdown-live-preview-delete-export 'delete-on-destroy)
7144 (markdown-command #'markdown-command-identity)
7145 file-output)
7146 (markdown-test-temp-file "inline.text"
7147 (markdown-live-preview-mode)
7148 (setq file-output (markdown-export-file-name)))
7149 (should-not (file-exists-p file-output)))
7150 (let ((markdown-live-preview-delete-export 'delete-on-export)
7151 (markdown-command #'markdown-command-identity)
7152 file-output)
7153 (markdown-test-temp-file "inline.text"
7154 (markdown-live-preview-mode)
7155 (setq file-output (markdown-export-file-name))
7156 (should-not (file-exists-p file-output))))
7157 (let ((markdown-live-preview-delete-export nil)
7158 (markdown-command #'markdown-command-identity)
7159 file-output)
7160 (unwind-protect
7161 (markdown-test-temp-file "inline.text"
7162 (markdown-live-preview-mode)
7163 (setq file-output (markdown-export-file-name))
7164 (should (file-exists-p file-output)))
7165 (delete-file file-output)))))
7167 (ert-deftest test-markdown-ext/live-preview-follow-min-max ()
7168 (markdown-test-eww-or-nothing "live-preview-follow-min-max"
7169 (markdown-test-temp-file "inline.text"
7170 (markdown-live-preview-mode)
7171 (should (buffer-live-p markdown-live-preview-buffer))
7172 (should (window-live-p (get-buffer-window markdown-live-preview-buffer)))
7173 (with-selected-window (get-buffer-window markdown-live-preview-buffer)
7174 (goto-char (point-min)))
7175 (goto-char (point-min))
7176 (insert "a test ")
7177 (markdown-live-preview-export)
7178 (let (final-pt final-win-st-diff)
7179 ;; test that still starts at point-min
7180 (with-selected-window (get-buffer-window markdown-live-preview-buffer)
7181 (should (= (window-point) 1))
7182 (should (= (markdown-visual-lines-between-points
7183 (window-start) (window-point))
7185 (set-window-point (selected-window) (point-max))
7186 (setq final-pt (window-point)
7187 final-win-st-diff (markdown-visual-lines-between-points
7188 (window-start) (window-point))))
7189 (goto-char (point-min))
7190 (insert "this is ")
7191 (markdown-live-preview-export)
7192 (with-selected-window (get-buffer-window markdown-live-preview-buffer)
7193 (should (= (window-point) (+ final-pt (length "this is "))))
7194 (should (= (markdown-visual-lines-between-points
7195 (window-start) (window-point))
7196 final-win-st-diff))
7197 ;; test that still starts at point-max, with correct line difference
7198 (goto-char (floor (/ (float (- (point-max) (point-min))) 2)))
7199 (setq final-pt (window-point)
7200 final-win-st-diff (markdown-visual-lines-between-points
7201 (window-start) final-pt)))
7202 (markdown-live-preview-export)
7203 ;; test that still starts at same point, with correct line difference
7204 (with-selected-window (get-buffer-window markdown-live-preview-buffer)
7205 (should (= (window-point) final-pt))
7206 (should (= (markdown-visual-lines-between-points
7207 (window-start) (window-point))
7208 final-win-st-diff)))))))
7210 (when (version< "29" emacs-version)
7211 (ert-deftest test-markdown-live-preview/eww-auto-rename-buffer ()
7212 "Test `eww-auto-rename-buffer' is non-nil.
7213 Detail: https://github.com/jrblevin/markdown-mode/issues/737"
7214 (let ((markdown-command #'markdown-command-identity))
7215 (let ((eww-auto-rename-buffer 'title))
7216 (should (markdown-live-preview-window-eww "Markdown.md"))))))
7218 ;;; Tests for imenu
7220 (ert-deftest test-markdown-imenu/metadata ()
7221 "Don't correct header like statement in metadata.
7222 https://github.com/jrblevin/markdown-mode/issues/145"
7223 (markdown-test-string "---
7224 title = \"Blah\"
7225 comments = false
7228 # Header1
7230 ## Header2
7232 (let ((headers (mapcar #'car (markdown-imenu-create-flat-index))))
7233 (should (member "Header1" headers))
7234 (should (member "Header2" headers))
7235 (should-not (member "comments = false" headers)))))
7237 (ert-deftest test-markdown-imenu/include-footnotes ()
7238 "Check that footnotes are added to the imenu.
7239 https://github.com/jrblevin/markdown-mode/issues/235"
7240 (markdown-test-string "# H1
7242 [^fn1]: footnote 1
7244 ## H2
7246 [^fn2]: footnote 2
7248 (let* ((markdown-add-footnotes-to-imenu t)
7249 (entries (mapcar #'car (markdown-imenu-create-flat-index))))
7250 (should (member "^fn1" entries))
7251 (should (member "^fn2" entries)))))
7253 (ert-deftest test-markdown-imenu/no-footnotes ()
7254 "Check that footnotes are not added to the imenu.
7255 https://github.com/jrblevin/markdown-mode/issues/235"
7256 (markdown-test-string "# H1
7258 [^fn1]: footnote 1
7260 ## H2
7262 [^fn2]: footnote 2
7264 (let* ((markdown-add-footnotes-to-imenu nil)
7265 (entries (mapcar #'car (markdown-imenu-create-flat-index))))
7266 (should-not (member "^fn1" entries))
7267 (should-not (member "^fn2" entries)))))
7269 (ert-deftest test-markdown-imenu/no-level-one-header ()
7270 "Create imenu entries if there is no level-1 header
7271 https://github.com/jrblevin/markdown-mode/issues/571"
7272 (markdown-test-string "---
7273 title: Wat
7276 ## Section a
7278 ### Sub 1
7280 ### Sub 11
7282 ## Section b
7284 ### Sub 2"
7285 (let ((entries (markdown-imenu-create-nested-index)))
7286 (should (string= (car (nth 0 entries)) "Section a"))
7287 (should (string= (car (nth 1 entries)) "Section b")))))
7289 (ert-deftest test-markdown-command/function ()
7290 "Test ‘markdown’ with ‘markdown-command’ being a function."
7291 (markdown-test-string "foo"
7292 (let* ((calls ())
7293 (markdown-command (lambda (&rest args) (push args calls)))
7294 (buffer-name (markdown))
7295 (buffer (get-buffer buffer-name)))
7296 (should (stringp buffer-name))
7297 (should (buffer-live-p buffer))
7298 (should (equal calls `((1 4 ,buffer)))))))
7300 (ert-deftest test-markdown-command/string-command ()
7301 "Test `markdown-command' for string which has only command."
7302 (skip-unless (executable-find "pandoc"))
7303 (markdown-test-string "foo"
7304 (let ((markdown-command "pandoc"))
7305 ;; check exception is not thrown
7306 (should (markdown)))))
7308 (ert-deftest test-markdown-command/string-command-with-options ()
7309 "Test `markdown-command' for string which has command and options."
7310 (skip-unless (executable-find "pandoc"))
7311 (markdown-test-string "foo"
7312 (let ((markdown-command "pandoc --from=markdown --to=html5"))
7313 (should (markdown)))))
7315 (ert-deftest test-markdown-command/list-of-strings ()
7316 "Test `markdown-command' for list of strings."
7317 (skip-unless (executable-find "pandoc"))
7318 (markdown-test-string "foo"
7319 (let ((markdown-command '("pandoc" "--from=markdown" "--to=html5")))
7320 (should (markdown)))))
7322 (ert-deftest test-markdown-command/does-not-exist ()
7323 "Test ‘markdown’ with a non-existing ‘markdown-command’."
7324 (skip-unless (not (file-executable-p "/does/not/exist")))
7325 (markdown-test-string "foo"
7326 (let* ((markdown-command "/does/not/exist")
7327 (data (should-error (markdown) :type 'user-error)))
7328 (should (string-prefix-p "Markdown command /does/not/exist is not found"
7329 (error-message-string data))))))
7331 (ert-deftest test-markdown-command/fails ()
7332 "Test ‘markdown’ with a failing ‘markdown-command’."
7333 (skip-unless (executable-find "false"))
7334 (markdown-test-string "foo"
7335 (let* ((markdown-command "false")
7336 (data (should-error (markdown) :type 'user-error)))
7337 (should (string-prefix-p "false failed with exit code "
7338 (error-message-string data))))))
7340 (ert-deftest test-markdown-open-command/function ()
7341 "Test ‘markdown-open’ with ‘markdown-open-command’ being a function."
7342 (markdown-test-string ""
7343 (let* ((calls 0)
7344 (markdown-open-command (lambda () (cl-incf calls))))
7345 (markdown-open)
7346 (should (equal calls 1)))))
7348 (ert-deftest test-markdown-open-command/does-not-exist ()
7349 "Test ‘markdown-open’ with a non-existing ‘markdown-open-command’."
7350 (skip-unless (not (file-executable-p "/does/not/exist")))
7351 (markdown-test-string "foo"
7352 (let ((buffer-file-name
7353 (expand-file-name "bar.md" temporary-file-directory))
7354 (markdown-open-command "/does/not/exist"))
7355 (should-error (markdown-open) :type 'file-error))))
7357 (ert-deftest test-markdown-open-command/fails ()
7358 "Test ‘markdown-open’ with a failing ‘markdown-open-command’."
7359 (skip-unless (executable-find "false"))
7360 (markdown-test-string "foo"
7361 (let* ((buffer-file-name
7362 (expand-file-name "bar.md" temporary-file-directory))
7363 (markdown-open-command "false")
7364 (data (should-error (markdown-open) :type 'user-error)))
7365 (should (string-prefix-p "false failed with exit code 1"
7366 (error-message-string data))))))
7368 (ert-deftest test-markdown-open-image-command ()
7369 "Test ‘markdown-open’ with ‘markdown-open-command’ being a function."
7370 (markdown-test-string "![foo](./bar.jpg)"
7371 (let ((markdown-open-image-command
7372 (lambda (file) (should (string= file "./bar.jpg")))))
7373 (forward-char 3)
7374 (markdown-follow-link-at-point))))
7376 ;;; Tests for view mode
7378 (ert-deftest test-markdown-view-mode/filter-buffer-substring ()
7379 "Test `filter-buffer-substring' of `markdown-view-mode'.
7380 Detail: https://github.com/jrblevin/markdown-mode/pull/493"
7381 (let ((test-string "# foo
7382 ~~This is a dog~~
7384 ```python
7385 foo(bar=None)
7388 (test-func
7389 (lambda ()
7390 (should (string= (filter-buffer-substring (point-min) (line-end-position)) "foo"))
7391 (forward-line +1)
7392 (should (string= (filter-buffer-substring (point) (line-end-position)) "This is a dog"))
7393 (forward-line +2)
7394 (let ((code-beg (point)))
7395 (forward-line +3)
7396 (should (string= (filter-buffer-substring code-beg (point)) "foo(bar=None)\n"))))))
7397 (markdown-test-string-view test-string
7398 (funcall test-func))
7400 (markdown-test-string-gfm-view test-string
7401 (funcall test-func))))
7403 (ert-deftest test-markdown-view-mode/buffer-read-only ()
7404 "Test disable buffer-read-only."
7405 (markdown-test-string "foo"
7406 (markdown-view-mode)
7407 (should buffer-read-only)
7408 (markdown-mode)
7409 (should-not buffer-read-only)))
7411 ;;; Tests for electric pair
7413 (ert-deftest test-markdown-electric-pair-mode ()
7414 "Test insert triple backtick with `electric-pair-mode'."
7415 (markdown-test-string-gfm ""
7416 (let ((markdown-gfm-use-electric-backquote nil))
7417 (electric-pair-local-mode +1)
7418 (make-local-variable 'electric-pair-pairs)
7419 (add-to-list 'electric-pair-pairs '(?` . ?`))
7420 (dotimes (_ 3)
7421 (let ((last-command-event ?`))
7422 (call-interactively (key-binding `[,last-command-event]))))
7423 (should (looking-back "```" (line-beginning-position)))
7424 (should (looking-at-p "```")))))
7426 ;;; Tests for flyspell mode
7428 (defun markdown-test-flyspell-incorrect-word-p ()
7429 (let ((bounds (bounds-of-thing-at-point 'word)))
7430 (cl-loop for ov in (overlays-in (car bounds) (cdr bounds))
7431 thereis (overlay-get ov 'flyspell-overlay))))
7433 (ert-deftest test-markdown-flyspell/check-word-p ()
7434 "Test for `flyspell'."
7435 (skip-unless (executable-find ispell-program-name))
7436 (markdown-test-string "aaa
7444 `ddd`
7448 <!-- fff -->
7450 @ref9999
7452 (flyspell-buffer)
7453 (search-forward "aaa")
7454 (should (markdown-test-flyspell-incorrect-word-p))
7455 (search-forward "bbb") ;; in code block
7456 (should-not (markdown-test-flyspell-incorrect-word-p))
7457 (search-forward "ccc")
7458 (should (markdown-test-flyspell-incorrect-word-p))
7459 (search-forward "ddd") ;; in inline code
7460 (should-not (markdown-test-flyspell-incorrect-word-p))
7461 (search-forward "eee")
7462 (should (markdown-test-flyspell-incorrect-word-p))
7463 (search-forward "fff") ;; in comment
7464 (should-not (markdown-test-flyspell-incorrect-word-p))
7465 (search-forward "@ref") ;; pandoc reference
7466 (should-not (markdown-test-flyspell-incorrect-word-p))))
7468 (ert-deftest test-markdown-flyspell/remove-overlay ()
7469 "Test non-dictionary word in code block with `flyspell-mode'.
7470 Details: https://github.com/jrblevin/markdown-mode/issues/311"
7471 (skip-unless (executable-find ispell-program-name))
7472 (markdown-test-string "bbb
7476 (flyspell-mode +1)
7477 (flyspell-buffer)
7478 (goto-char (point-max))
7479 (insert "```\n")
7480 (forward-line -2)
7481 (flyspell-buffer)
7483 ;; check 'bbb' in code block
7484 (should-not (markdown-test-flyspell-incorrect-word-p))
7485 ;; check 'bbb' outside block
7486 (goto-char (point-min))
7487 (should (markdown-test-flyspell-incorrect-word-p))))
7489 (ert-deftest test-markdown-flyspell/yaml-metadata ()
7490 "Test spell check in YAML metadata with `flyspell-mode'.
7491 Details: https://github.com/jrblevin/markdown-mode/issues/560"
7492 (skip-unless (executable-find ispell-program-name))
7493 (markdown-test-string "---
7494 title: asdasdasd
7497 (flyspell-mode +1)
7498 (flyspell-buffer)
7499 (goto-char (point-min))
7500 (search-forward "title: ")
7501 (should (markdown-test-flyspell-incorrect-word-p))))
7503 (ert-deftest test-markdown-table/navigation-forward-cell ()
7504 "Test table navigation."
7505 (markdown-test-string "
7506 | 1 | 2 | 3 | 4 |
7507 |----|----|----|----|
7508 | 5 | 6 | 7 | 8 |
7509 | 9 | 10 | 11 | 12 |"
7510 (search-forward "1 ")
7511 (let ((index 2))
7512 (while (<= index 12)
7513 (markdown-table-forward-cell)
7514 (should (looking-at (format "%d" index)))
7515 (cl-incf index)))))
7517 (ert-deftest test-markdown-table/navigation-backward-cell ()
7518 "Test table navigation."
7519 (markdown-test-string "
7520 | 1 | 2 | 3 | 4 |
7521 |----|----|----|----|
7522 | 5 | 6 | 7 | 8 |
7523 | 9 | 10 | 11 | 12 |
7525 (search-forward "12")
7526 (let ((index 11))
7527 (while (>= index 1)
7528 (markdown-table-backward-cell)
7529 (should (looking-at (format "%d" index)))
7530 (cl-decf index)))))
7532 (ert-deftest test-markdown-table/align ()
7533 "Test table realignment."
7534 (markdown-test-string "
7535 | Header 1 |Header 2|
7536 |------|----|
7537 | | |
7538 | A very very very long cell| |
7540 (search-forward "Header")
7541 (markdown-table-align)
7542 (message "\"%s\"" (buffer-string))
7543 (should (string= (buffer-string) "
7544 | Header 1 | Header 2 |
7545 |----------------------------|----------|
7546 | | |
7547 | A very very very long cell | |
7548 "))))
7550 (ert-deftest test-markdown-table/align-with-spaces-before-delimiter ()
7551 "Test table realignment when there are spaces before a delimiter"
7552 (markdown-test-string "
7553 | A | B | C | D |
7554 | - | :- | :-: | -: |
7555 | aaa | bbbb | ccccc | dddddd |
7557 (search-forward "A")
7558 (markdown-table-align)
7559 (should (string= (buffer-string) "
7560 | A | B | C | D |
7561 |-----|:-----|:-----:|-------:|
7562 | aaa | bbbb | ccccc | dddddd |
7563 "))))
7565 (ert-deftest test-markdown-table/align-with-tabs-before-delimiter ()
7566 "Test table realignment when there are tabs before a delimiter"
7567 (markdown-test-string "
7568 | A | B | C | D |
7569 | - | :-|:-: |-:|
7570 | aaa | bbbb | ccccc | dddddd |
7572 (search-forward "A")
7573 (markdown-table-align)
7574 (should (string= (buffer-string) "
7575 | A | B | C | D |
7576 |-----|:-----|:-----:|-------:|
7577 | aaa | bbbb | ccccc | dddddd |
7578 "))))
7580 (ert-deftest test-markdown-table/align-with-seperator-in-inline-code ()
7581 "Test table realignment when separator is in inline code.
7582 Detail: https://github.com/jrblevin/markdown-mode/issues/817"
7583 (markdown-test-string "| `<|--` | Inheritance |
7584 | `..|>` | Realization |
7586 (let ((columns (markdown--table-line-to-columns
7587 (buffer-substring (line-beginning-position) (line-end-position)))))
7588 (should (equal columns '("`<|--`" "Inheritance"))))
7590 (forward-line)
7591 (let ((columns (markdown--table-line-to-columns
7592 (buffer-substring (line-beginning-position) (line-end-position)))))
7593 (should (equal columns '("`..|>`" "Realization"))))))
7595 (ert-deftest test-markdown-table/disable-table-align ()
7596 "Test disable table alignment."
7597 (let ((input "| 12345 | 6 |
7598 | 7 | 8 |"))
7599 (markdown-test-string input
7600 (save-excursion
7601 (search-forward "1")
7602 (let ((markdown-table-align-p nil))
7603 (markdown-table-forward-cell)
7604 (should (string= (buffer-string) input))))
7606 (search-forward "1")
7607 (let ((expected "| 12345 | 6 |
7608 | 7 | 8 |
7610 (markdown-table-forward-cell)
7611 (should (string= (buffer-string) expected))))))
7613 (ert-deftest test-markdown-table/convert-table-region ()
7614 "Test markdown-table-convert-region.
7615 https://github.com/jrblevin/markdown-mode/issues/640"
7616 (let ((markdown-table-align-p t))
7617 (markdown-test-string "1 2 3
7618 4 5 6"
7619 (markdown-table-convert-region (point-min) (point-max))
7620 (should (string= (buffer-substring-no-properties (point-min) (point-max))
7621 "| 1 | 2 | 3 |
7622 | 4 | 5 | 6 |\n")))
7623 (markdown-test-string "1 2 3 \n4 5 6 "
7624 (markdown-table-convert-region (point-min) (point-max))
7625 (should (string= (buffer-substring-no-properties (point-min) (point-max))
7626 "| 1 | 2 | 3 |\n| 4 | 5 | 6 |\n")))))
7628 (ert-deftest test-markdown-table/decide-delimiter-line ()
7629 "Test `markdown-table-aligh' for the line which starts with dash.
7630 Detail: https://github.com/jrblevin/markdown-mode/issues/747"
7631 (let ((markdown-table-align-p t))
7632 (markdown-test-string "| -c | some text |\n"
7633 (search-forward "some")
7634 (call-interactively 'markdown-table-next-row)
7635 (should (string= (buffer-substring-no-properties (point-min) (point-max))
7636 "| -c | some text |\n| | |\n")))))
7638 (ert-deftest test-markdown-table/ensure-valid-html-title ()
7639 "Test `markdown-table-aligh' for the line which starts with dash.
7640 Detail: https://github.com/jrblevin/markdown-mode/issues/747"
7641 (markdown-test-string "simple"
7642 (markdown-add-xhtml-header-and-footer "test<&>")
7643 (goto-char (point-min))
7644 (should (search-forward "test&lt;&amp;&gt;"))))
7646 (provide 'markdown-test)
7648 ;;; markdown-test.el ends here