Handle unspecified or unknown languages when editing code blocks
[markdown-mode.git] / tests / markdown-test.el
blob66b506e573dca74c5a098d664b39ab925b123a3c
1 ;;;; markdown-test.el --- Tests for markdown-mode
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)
35 (defconst markdown-test-dir
36 (expand-file-name (file-name-directory
37 (or load-file-name buffer-file-name))))
39 (defconst markdown-test-font-lock-function
40 (if (and noninteractive (fboundp 'font-lock-ensure))
41 #'font-lock-ensure #'font-lock-fontify-buffer))
43 (defmacro markdown-test-string-mode (mode string &rest body)
44 "Run BODY in a temporary buffer containing STRING in MODE."
45 (declare (indent 2))
46 `(let ((win (selected-window)))
47 (unwind-protect
48 (with-temp-buffer
49 (set-window-buffer win (current-buffer) t)
50 (erase-buffer)
51 (funcall ,mode)
52 (setq-default indent-tabs-mode nil)
53 (insert ,string)
54 (goto-char (point-min))
55 (funcall markdown-test-font-lock-function)
56 (prog1 ,@body (kill-buffer))))))
58 (defmacro markdown-test-file-mode (mode file &rest body)
59 "Open FILE from `markdown-test-dir' in MODE and execute BODY."
60 (declare (indent 2))
61 `(let ((fn (concat markdown-test-dir ,file)))
62 (save-window-excursion
63 (with-temp-buffer
64 (insert-file-contents fn)
65 (funcall ,mode)
66 (goto-char (point-min))
67 (funcall markdown-test-font-lock-function)
68 ,@body))))
70 (defmacro markdown-test-string (string &rest body)
71 "Run BODY in a temporary buffer containing STRING in `markdown-mode'."
72 (declare (indent 1))
73 `(markdown-test-string-mode 'markdown-mode ,string ,@body))
74 (def-edebug-spec markdown-test-string (form body))
76 (defmacro markdown-test-file (file &rest body)
77 "Open FILE from `markdown-test-dir' in `markdown-mode' and execute BODY."
78 (declare (indent 1))
79 `(markdown-test-file-mode 'markdown-mode ,file ,@body))
80 (def-edebug-spec markdown-test-file (form body))
82 (defmacro markdown-test-string-gfm (string &rest body)
83 "Run BODY in a temporary buffer containing STRING in `gfm-mode'."
84 (declare (indent 1))
85 `(markdown-test-string-mode 'gfm-mode ,string ,@body))
86 (def-edebug-spec markdown-test-string-gfm (form body))
88 (defmacro markdown-test-file-gfm (file &rest body)
89 "Open FILE from `markdown-test-dir' in `gfm-mode' and execute BODY."
90 (declare (indent 1))
91 `(markdown-test-file-mode 'gfm-mode ,file ,@body))
92 (def-edebug-spec markdown-test-file-gfm (form body))
94 (defmacro markdown-test-temp-file (file &rest body)
95 "Open FILE from `markdown-test-dir' visiting temp file and execute BODY.
96 This file is not saved."
97 (declare (indent 1))
98 `(let ((fn (concat markdown-test-dir ,file))
99 (tmp (make-temp-file "markdown-test" nil ".text"))
100 buf)
101 (save-window-excursion
102 (unwind-protect
103 (progn
104 (setq buf (find-file tmp))
105 (insert-file-contents fn)
106 (markdown-mode)
107 (goto-char (point-min))
108 (funcall markdown-test-font-lock-function)
109 ,@body
110 (set-buffer-modified-p nil))
111 (when (buffer-live-p buf) (kill-buffer buf))
112 (delete-file tmp)))))
113 (def-edebug-spec markdown-test-temp-file (form body))
115 (defun markdown-test-report-property-range (begin end prop)
116 "Report buffer substring and property PROP from BEGIN to END."
117 (message "Buffer substring: %s" (buffer-substring begin (1+ end)))
118 (message "Properties in range are as follows:")
119 (dolist (loc (number-sequence begin end))
120 (message "%d: %s" loc (get-char-property loc prop))))
122 (defun markdown-test-range-has-property (begin end prop value)
123 "Verify that range BEGIN to END has PROP equal to or containing VALUE."
124 (let (vals fail-loc)
125 (setq fail-loc
126 (catch 'fail
127 (dolist (loc (number-sequence begin end))
128 (setq vals (get-char-property loc prop))
129 (if (and vals (listp vals))
130 (unless (memq value vals)
131 (throw 'fail loc))
132 (unless (eq vals value)
133 (throw 'fail loc))))))
134 (when fail-loc
135 (message "Testing range (%d,%d) for property %s equal to %s."
136 begin end prop value)
137 (message "Expected value (%s) not found in property (%s) at location %d" value prop fail-loc)
138 (markdown-test-report-property-range begin end prop))
139 (should-not fail-loc)))
141 (defun markdown-test-range-property-equals (begin end prop value)
142 "Verify that range BEGIN to END has property PROP equal to VALUE."
143 (let ((fail-loc
144 (catch 'fail
145 (dolist (loc (number-sequence begin end))
146 (unless (eq (get-char-property loc prop) value)
147 (throw 'fail loc))))))
148 (when fail-loc
149 (message "Testing range (%d,%d) for property %s equal to %s."
150 begin end prop value)
151 (message "Expected value (%s) not found in property (%s) at location %d" value prop fail-loc)
152 (markdown-test-report-property-range begin end prop))
153 (should-not fail-loc)))
155 (defun markdown-test-range-has-face (begin end face)
156 "Verify that the range from BEGIN to END has face FACE."
157 (markdown-test-range-has-property begin end 'face face))
159 (defun markdown-test-range-face-equals (begin end face)
160 "Verify that the range from BEGIN to END has face equal to FACE."
161 (markdown-test-range-property-equals begin end 'face face))
163 (defun markdown-test-goto-heading (title)
164 "Move the point to section with TITLE."
165 (let ((regexp (format "\\(^#+ %s\\( #+\\)?\\|^%s\n[=-]+\n\\)" title title)))
166 (if (re-search-forward regexp nil t)
167 (goto-char (match-end 0)))))
169 (defun markdown-test ()
170 "Run all defined test cases for `markdown-mode'."
171 (interactive)
172 (ert "markdown"))
174 ;;; Example tests:
176 (ert-deftest test-markdown-example/string ()
177 "An example string test using the `ert' framework."
178 (markdown-test-string "foo *bar* baz"
179 (goto-char 5)
180 (delete-char 1)
181 (should (looking-at "bar"))))
183 (ert-deftest test-markdown-example/file ()
184 "An example file test using the `ert' framework."
185 (markdown-test-file "inline.text"
186 (goto-char 9)
187 (should (looking-at "\*"))))
189 ;;; Basic mode tests:
191 (ert-deftest test-markdown-mode/variables ()
192 "Test `markdown-mode' variables."
193 (markdown-test-file "inline.text"
194 (should (= tab-width 4))
195 (should (eq font-lock-multiline t))
196 (should (eq major-mode 'markdown-mode))))
198 ;;; Element insertion tests:
200 (ert-deftest test-markdown-insertion/blank-line-before-1 ()
201 "Test function `markdown-ensure-blank-line-before' at beginning of line."
202 (markdown-test-file "syntax.text"
203 (search-forward "as plain text")
204 (should (= (point) 1556))
205 (beginning-of-line)
206 (should (= (point) 1505))
207 (should (looking-back "A Markdown-formatted\n" nil))
208 (should (not (markdown-prev-line-blank-p)))
209 (markdown-ensure-blank-line-before)
210 (should (looking-back "A Markdown-formatted\n\n" nil))
211 (should (markdown-prev-line-blank-p))))
213 (ert-deftest test-markdown-insertion/blank-line-before-2 ()
214 "Test function `markdown-ensure-blank-line-before' in middle of line."
215 (markdown-test-file "syntax.text"
216 (search-forward "as plain text")
217 (should (= (point) 1556))
218 (should (looking-back "as plain text" nil))
219 (should (not (markdown-prev-line-blank-p)))
220 (markdown-ensure-blank-line-before)
221 (should (looking-back "as plain text\n\n" nil))
222 (should (markdown-prev-line-blank-p))))
224 (ert-deftest test-markdown-insertion/blank-line-before-3 ()
225 "Test function `markdown-ensure-blank-line-before' with blank line before."
226 (markdown-test-file "syntax.text"
227 (search-forward "web.\n\nMarkdown is not a replacement for HTML")
228 (beginning-of-line)
229 (should (= (point) 2704))
230 (should (looking-back "web.\n\n" nil))
231 (should (markdown-prev-line-blank-p))
232 (markdown-ensure-blank-line-before)
233 (should (= (point) 2704))
234 (should (looking-back "web.\n\n" nil))
235 (should (markdown-prev-line-blank-p))))
237 (ert-deftest test-markdown-insertion/blank-line-before-4 ()
238 "Test function `markdown-ensure-blank-line-before' at beginning of buffer."
239 (markdown-test-string "first line"
240 (beginning-of-line)
241 (should (bobp))
242 (should (= (point-max) 11))
243 (markdown-ensure-blank-line-before)
244 (should (= (point-max) 11))
245 (should (string-equal (buffer-substring (point-min) (point-max))
246 "first line"))
247 (forward-word)
248 (markdown-ensure-blank-line-before)
249 (should (string-equal (buffer-substring (point-min) (point-max))
250 "first\n\n line"))))
252 (ert-deftest test-markdown-insertion/blank-line-after-1 ()
253 "Test function `markdown-ensure-blank-line-after' at end of line."
254 (markdown-test-file "syntax.text"
255 (search-forward "as plain text")
256 (should (= (point) 1556))
257 (end-of-line)
258 (should (= (point) 1573))
259 (should (looking-at "\nlike it's been"))
260 (should (not (markdown-next-line-blank-p)))
261 (markdown-ensure-blank-line-after)
262 (should (looking-at "\n\nlike it's been"))
263 (should (markdown-next-line-blank-p))))
265 (ert-deftest test-markdown-insertion/blank-line-after-2 ()
266 "Test function `markdown-ensure-blank-line-after' in middle of line."
267 (markdown-test-file "syntax.text"
268 (search-forward "as plain text")
269 (should (= (point) 1556))
270 (should (looking-at ", without looking"))
271 (should (not (markdown-next-line-blank-p)))
272 (markdown-ensure-blank-line-after)
273 (should (looking-at "\n\n, without looking"))
274 (should (markdown-next-line-blank-p))))
276 (ert-deftest test-markdown-insertion/blank-line-after-3 ()
277 "Test function `markdown-ensure-blank-line-after' with blank line after."
278 (markdown-test-file "syntax.text"
279 (search-forward "*writing* for the web.")
280 (should (= (point) 2702))
281 (should (looking-at "\n\nMarkdown is not a replacement for HTML"))
282 (should (markdown-next-line-blank-p))
283 (markdown-ensure-blank-line-after)
284 (should (= (point) 2702))
285 (should (looking-at "\n\nMarkdown is not a replacement for HTML"))
286 (should (markdown-next-line-blank-p))))
288 (ert-deftest test-markdown-insertion/blank-line-after-4 ()
289 "Test function `markdown-ensure-blank-line-after' at end of buffer."
290 (markdown-test-string "last line"
291 (end-of-line)
292 (should (eobp))
293 (should (= (point-max) 10))
294 (markdown-ensure-blank-line-after)
295 (should (= (point-max) 10))
296 (should (string-equal (buffer-substring (point-min) (point-max))
297 "last line"))
298 (backward-word)
299 (markdown-ensure-blank-line-after)
300 (should (string-equal (buffer-substring (point-min) (point-max))
301 "last \n\nline"))))
303 (ert-deftest test-markdown-insertion/point-after-unwrap ()
304 "Test new point position calculations after unwrap operations."
305 (markdown-test-string "line **one**\n"
306 (let ((prefix (cons 6 8)) (suffix (cons 11 13)))
307 ;; Prefix
308 (should (eq (markdown-point-after-unwrap 6 prefix suffix) 6))
309 (should (eq (markdown-point-after-unwrap 7 prefix suffix) 6))
310 ;; Word
311 (should (eq (markdown-point-after-unwrap 8 prefix suffix) 6))
312 (should (eq (markdown-point-after-unwrap 9 prefix suffix) 7))
313 (should (eq (markdown-point-after-unwrap 10 prefix suffix) 8))
314 ;; Suffix
315 (should (eq (markdown-point-after-unwrap 11 prefix suffix) 9))
316 (should (eq (markdown-point-after-unwrap 12 prefix suffix) 9))
317 ;; Immediately after
318 (should (eq (markdown-point-after-unwrap 13 prefix suffix) 9))))
319 (markdown-test-string "line _one_\n"
320 (let ((prefix (cons 6 7)) (suffix (cons 10 11)))
321 ;; Prefix
322 (should (eq (markdown-point-after-unwrap 6 prefix suffix) 6))
323 ;; Word
324 (should (eq (markdown-point-after-unwrap 7 prefix suffix) 6))
325 (should (eq (markdown-point-after-unwrap 8 prefix suffix) 7))
326 (should (eq (markdown-point-after-unwrap 9 prefix suffix) 8))
327 ;; Suffix
328 (should (eq (markdown-point-after-unwrap 10 prefix suffix) 9))
329 ;; Immediately after
330 (should (eq (markdown-point-after-unwrap 10 prefix suffix) 9)))))
332 (ert-deftest test-markdown-insertion/unwrap-thing-at-point-italic ()
333 "Test function `markdown-unwrap-thing-at-point' on italics."
334 (markdown-test-file "syntax.text"
335 ;; Unwrap *not*
336 (goto-char 2859)
337 (should (thing-at-point-looking-at markdown-regex-italic))
338 (should (equal (markdown-unwrap-thing-at-point
339 markdown-regex-italic 1 3)
340 (cons 2859 2862)))
341 (should (= (point) 2859))
342 ;; Unwrap *publishing*
343 (goto-char 3064)
344 (should (thing-at-point-looking-at markdown-regex-italic))
345 (should (equal (markdown-unwrap-thing-at-point
346 markdown-regex-italic 1 3)
347 (cons 3060 3070)))
348 (should (= (point) 3063))
349 ;; Unwrap *writing*
350 (goto-char 3101)
351 (should (thing-at-point-looking-at markdown-regex-italic))
352 (should (equal (markdown-unwrap-thing-at-point
353 markdown-regex-italic 1 3)
354 (cons 3093 3100)))
355 (should (= (point) 3100))))
357 (ert-deftest test-markdown-insertion/unwrap-things-in-region-italic ()
358 "Test function `markdown-unwrap-things-in-region' on italics."
359 (markdown-test-file "syntax.text"
360 (should (equal (markdown-unwrap-things-in-region
361 2704 3207 markdown-regex-italic 1 3)
362 (cons 2704 3201)))))
364 (ert-deftest test-markdown-insertion/unwrap-things-in-region-bound ()
365 "Ensure that `markdown-unwrap-things-in-region' respects end bound"
366 (markdown-test-string "**a** **b** **c** **d** **e** **f**"
367 ;; Set region to unrwap a, b, c, and d only. If endpoint is not
368 ;; respected (i.e, not adjusted for character removal), the
369 ;; function will unwrap e and f also.
370 (should (equal (markdown-unwrap-things-in-region
371 1 24 markdown-regex-bold 2 4)
372 (cons 1 8)))
373 (should (string-equal (buffer-string) "a b c d **e** **f**"))))
375 (ert-deftest test-markdown-insertion/unwrap-things-in-region-links ()
376 "Test function `markdown-unwrap-things-in-region' on inline links."
377 (markdown-test-string "a [link](http://jblevins.org/) or [two](/).\n"
378 (should (equal (markdown-unwrap-things-in-region
379 (point-min) (point-max) markdown-regex-link-inline 0 3)
380 (cons 1 16)))
381 (should (string-equal (buffer-string) "a link or two.\n"))))
383 (ert-deftest test-markdown-insertion/toggle-bold ()
384 "Test toggling functionality of `markdown-insert-bold'."
385 (markdown-test-string "one **two** three"
386 (forward-word 2)
387 (markdown-insert-bold)
388 (should (string-equal (buffer-string) "one two three"))
389 (should (= (point) 8))
390 (forward-word)
391 (markdown-insert-bold)
392 (should (= (point) 16))
393 (should (string-equal (buffer-string) "one two **three**"))))
395 (ert-deftest test-markdown-insertion/toggle-italic ()
396 "Test toggling functionality of `markdown-insert-italic'."
397 (markdown-test-string "one *two* three"
398 (forward-word 2)
399 (markdown-insert-italic)
400 (should (string-equal (buffer-string) "one two three"))
401 (should (= (point) 8))
402 (forward-word)
403 (markdown-insert-italic)
404 (should (string-equal (buffer-string) "one two *three*"))
405 (should (= (point) 15))))
407 (ert-deftest test-markdown-insertion/toggle-code ()
408 "Test toggling functionality of `markdown-insert-code'."
409 (markdown-test-string "one `two` three"
410 (forward-word 2)
411 (markdown-insert-code)
412 (should (string-equal (buffer-string) "one two three"))
413 (should (= (point) 8))
414 (forward-word)
415 (markdown-insert-code)
416 (should (string-equal (buffer-string) "one two `three`"))
417 (should (= (point) 15))))
419 (ert-deftest test-markdown-insertion/toggle-kbd ()
420 "Test toggling functionality of `markdown-insert-code'."
421 (markdown-test-string "test <kbd>C-c C-s k</kbd> toggle"
422 (forward-word 2)
423 (markdown-insert-kbd)
424 (should (string-equal (buffer-string) "test C-c C-s k toggle"))
425 (should (= (point) 6))
426 (backward-word)
427 (markdown-insert-kbd)
428 (should (string-equal (buffer-string) "<kbd>test</kbd> C-c C-s k toggle"))
429 (should (= (point) 6))))
431 (ert-deftest test-markdown-insertion/toggle-wiki-link-alias-first ()
432 "Test toggling of `markdown-insert-wiki-link' with alias first.
433 Test point position upon removal and insertion."
434 (let ((markdown-wiki-link-alias-first t))
435 (markdown-test-string "[[text|page]]"
436 (goto-char 5) ; point in interior of alias text, at 'x'
437 (call-interactively 'markdown-insert-wiki-link)
438 (should (= (point) 3)) ; leave point at, at 'x'
439 (should (string-equal (buffer-string) "text"))
440 (call-interactively 'markdown-insert-wiki-link)
441 (should (= (point) 5)) ; leave point at, at 'x'
442 (should (string-equal (buffer-string) "[[text]]")))
443 (markdown-test-string "[[text|page]]"
444 (goto-char 10) ; point in interior of link text, at 'g'
445 (call-interactively 'markdown-insert-wiki-link)
446 (should (= (point) 5)) ; leave point at end of alias text
447 (should (string-equal (buffer-string) "text"))
448 (call-interactively 'markdown-insert-wiki-link)
449 (should (= (point) 7)) ; leave point at end of alias text
450 (should (string-equal (buffer-string) "[[text]]")))))
452 (ert-deftest test-markdown-insertion/toggle-wiki-link-alias-last ()
453 "Test toggling of `markdown-insert-wiki-link' with alias last.
454 Test point position upon removal and insertion."
455 (let ((markdown-wiki-link-alias-first nil))
456 (markdown-test-string "[[page|text]]"
457 (goto-char 10) ; point in interior of alias text, at 'x'
458 (call-interactively 'markdown-insert-wiki-link)
459 (goto-char 3) ; leave point at, at 'x'
460 (should (string-equal (buffer-string) "text"))
461 (call-interactively 'markdown-insert-wiki-link)
462 (should (= (point) 5)) ; leave point at, at 'x'
463 (should (string-equal (buffer-string) "[[text]]")))
464 (markdown-test-string "[[page|text]]"
465 (goto-char 3) ; point in interior of link text, at 'g'
466 (call-interactively 'markdown-insert-wiki-link)
467 (should (= (point) 1)) ; leave point at beginning of alias text
468 (should (string-equal (buffer-string) "text"))
469 (call-interactively 'markdown-insert-wiki-link)
470 (should (= (point) 3)) ; leave point at beginning of alias text
471 (should (string-equal (buffer-string) "[[text]]")))))
473 (ert-deftest test-markdown-insertion/bold-region ()
474 "Test region functionality of `markdown-insert-bold'."
475 (markdown-test-string "one two three"
476 (push-mark (point) t t)
477 (forward-word 2)
478 (markdown-insert-bold)
479 (should (string-equal (buffer-string) "**one two** three"))
480 (should (= (point) 10))))
482 (ert-deftest test-markdown-insertion/italic-region ()
483 "Test region functionality of `markdown-insert-italic'."
484 (markdown-test-string "one two three"
485 (transient-mark-mode)
486 (push-mark (point) t t)
487 (forward-word 2)
488 (markdown-insert-italic)
489 (should (string-equal (buffer-string) "*one two* three"))
490 (should (= (point) 9))))
492 (ert-deftest test-markdown-insertion/code-region ()
493 "Test region functionality of `markdown-insert-code'."
494 (markdown-test-string "one two three"
495 (transient-mark-mode)
496 (push-mark (point) t t)
497 (forward-word 2)
498 (markdown-insert-code)
499 (should (string-equal (buffer-string) "`one two` three"))
500 (should (= (point) 9))))
502 (ert-deftest test-markdown-insertion/kbd-region ()
503 "Test region functionality of `markdown-insert-kbd'."
504 (markdown-test-string "one two three"
505 (transient-mark-mode)
506 (push-mark (point) t t)
507 (forward-word 2)
508 (markdown-insert-kbd)
509 (should (string-equal (buffer-string) "<kbd>one two</kbd> three"))
510 (should (= (point) 13))))
512 (ert-deftest test-markdown-insertion/atx-line ()
513 "Test ATX header insertion without region."
514 (markdown-test-string "line one\nline two\n"
515 (forward-word)
516 (markdown-insert-header-atx-1)
517 (should (= (point) 11))
518 (should (string-equal (buffer-substring (point-min) (point-max))
519 "# line one #\n\nline two\n"))
520 (forward-line 2)
521 (markdown-insert-header-atx-2)
522 (should (= (point) 26))
523 (should (string-equal (buffer-substring (point-min) (point-max))
524 "# line one #\n\n## line two ##\n\n"))))
526 (ert-deftest test-markdown-insertion/atx-region ()
527 "Test ATX header insertion with region."
528 (markdown-test-string "line one\nline two\n"
529 (transient-mark-mode)
530 (forward-char 5)
531 (push-mark (point) t t)
532 (forward-word)
533 (should (string-equal (buffer-substring (region-beginning) (region-end))
534 "one"))
535 (markdown-insert-header-atx-4)
536 (should (= (point) 16))
537 (should (string-equal (buffer-substring (point-min) (point-max))
538 "line \n\n#### one ####\n\nline two\n"))))
540 (ert-deftest test-markdown-insertion/atx-blank ()
541 "Test ATX header insertion on blank line."
542 (markdown-test-string "line one\n\nline two\n"
543 (forward-line)
544 (markdown-insert-header-atx-3)
545 (should (string-equal (buffer-substring (point-min) (point-max))
546 "line one\n\n### ###\n\nline two\n"))
547 (should (= (point) 15))
548 (should (looking-at " ###\n"))))
550 (ert-deftest test-markdown-insertion/atx-region-whitespace ()
551 "Test ATX header insertion using a region with whitespace."
552 (markdown-test-string " line one\n\nline two\n \n"
553 (transient-mark-mode)
554 (push-mark (point) t t)
555 (goto-char (point-max))
556 (markdown-insert-header-atx-2)
557 (should (string-equal (buffer-substring (point-min) (point-max))
558 "## line one line two ##"))
559 (should (= (point) 21))
560 (should (looking-at " ##"))))
562 (ert-deftest test-markdown-insertion/atx-line-whitespace ()
563 "Test ATX header insertion using current line with whitespace."
564 (markdown-test-string " line one \n\nline two\n"
565 (goto-char (line-end-position))
566 (markdown-insert-header-atx-3)
567 (should (string-equal (buffer-substring (point-min) (point-max))
568 "### line one ###\n\nline two\n"))
569 (should (= (point) 13))
570 (should (looking-at " ###\n"))))
572 (ert-deftest test-markdown-insertion/atx-replace-atx ()
573 "Test ATX header insertion when replacing an existing ATX header."
574 (markdown-test-string "## replace ##\n"
575 (markdown-insert-header-atx-4)
576 (should (string-equal (buffer-string) "#### replace ####\n\n"))
577 (should (looking-at " ####\n"))))
579 (ert-deftest test-markdown-insertion/atx-replace-setext-1 ()
580 "Test ATX header insertion when replacing an existing setext header."
581 (markdown-test-string "replace\n=======\n"
582 (markdown-insert-header-atx-2)
583 (should (string-equal (buffer-string) "## replace ##\n\n"))
584 (should (looking-at " ##\n"))))
586 (ert-deftest test-markdown-insertion/atx-replace-setext-2 ()
587 "Test ATX header insertion when replacing an existing setext header."
588 (markdown-test-string "replace\n-------\n"
589 (markdown-insert-header-atx-5)
590 (should (string-equal (buffer-string) "##### replace #####\n\n"))
591 (should (looking-at " #####\n"))))
593 (ert-deftest test-markdown-insertion/atx-asymmetric-point ()
594 "Test point after ATX header insertion with `markdown-asymmetric-header'."
595 (markdown-test-string
596 "Test"
597 (let ((markdown-asymmetric-header t))
598 (markdown-insert-header-atx-5)
599 (should (= (point) 11))
600 (should (string-equal (buffer-string) "##### Test")))))
602 (ert-deftest test-markdown-insertion/setext-line ()
603 "Test setext header insertion without region."
604 (markdown-test-string "line one\nline two\n"
605 (forward-word)
606 (markdown-insert-header-setext-1)
607 (should (string-equal (buffer-substring (point-min) (point-max))
608 "line one\n========\n\nline two\n"))
609 (forward-line 3)
610 (markdown-insert-header-setext-2)
611 (should (string-equal (buffer-substring (point-min) (point-max))
612 "line one\n========\n\nline two\n--------\n\n"))))
614 (ert-deftest test-markdown-insertion/setext-region ()
615 "Test setext header insertion with region."
616 (markdown-test-string "line one\nline two\n"
617 (transient-mark-mode)
618 (forward-char 5)
619 (push-mark (point) t t)
620 (forward-word)
621 (should (string-equal (buffer-substring (region-beginning) (region-end))
622 "one"))
623 (markdown-insert-header-setext-1)
624 (should (string-equal (buffer-substring (point-min) (point-max))
625 "line \n\none\n===\n\nline two\n"))))
627 (ert-deftest test-markdown-insertion/setext-blank ()
628 "Test setext header insertion on blank line."
629 (markdown-test-string "line one\n\nline two\n"
630 (forward-line)
631 (markdown-insert-header 2 "foo" t)
632 (should (string-equal (buffer-substring (point-min) (point-max))
633 "line one\n\nfoo\n---\n\nline two\n"))
634 (should (= (point) 14))
635 (should (looking-at "\n---"))))
637 (ert-deftest test-markdown-insertion/setext-region-whitespace ()
638 "Test setext header insertion using a region with whitespace."
639 (markdown-test-string " line one\n\nline two\n \n"
640 (transient-mark-mode)
641 (push-mark (point) t t)
642 (goto-char (point-max))
643 (markdown-insert-header-setext-1)
644 (should (string-equal (buffer-substring (point-min) (point-max))
645 "line one line two\n================="))
646 (should (= (point) 18))
647 (should (looking-at "\n===="))))
649 (ert-deftest test-markdown-insertion/setext-line-whitespace ()
650 "Test setext header insertion using current line with whitespace."
651 (markdown-test-string " line one \n\nline two\n"
652 (goto-char (line-end-position))
653 (markdown-insert-header-setext-2)
654 (should (string-equal (buffer-substring (point-min) (point-max))
655 "line one\n--------\n\nline two\n"))
656 (should (= (point) 9))
657 (should (looking-at "\n---"))))
659 (ert-deftest test-markdown-insertion/setext-replace-atx ()
660 "Test setext header insertion when replacing an existing ATX header."
661 (markdown-test-string "## replace ##\n"
662 (markdown-insert-header-setext-1)
663 (should (string-equal (buffer-string) "replace\n=======\n\n"))
664 (should (looking-at "\n==="))))
666 (ert-deftest test-markdown-insertion/setext-replace-setext-1 ()
667 "Test setext header insertion when replacing an existing setext title."
668 (markdown-test-string "replace\n=======\n"
669 (markdown-insert-header-setext-2)
670 (should (string-equal (buffer-string) "replace\n-------\n\n"))
671 (should (looking-at "\n---"))))
673 (ert-deftest test-markdown-insertion/setext-replace-setext-2 ()
674 "Test setext header insertion when replacing an existing setext section."
675 (markdown-test-string "replace\n-------\n"
676 (markdown-insert-header-setext-1)
677 (should (string-equal (buffer-string) "replace\n=======\n\n"))
678 (should (looking-at "\n==="))))
680 (ert-deftest test-markdown-insertion/header-dwim ()
681 "Test 'do what I mean' header insertion."
682 (markdown-test-file "outline.text"
683 (call-interactively 'markdown-insert-header-dwim)
684 (should (looking-at " #$"))
685 (end-of-defun 2)
686 (call-interactively 'markdown-insert-header-dwim)
687 (beginning-of-line)
688 (should (looking-at "^# #$"))
689 (end-of-defun 3)
690 (call-interactively 'markdown-insert-header-dwim)
691 (beginning-of-line)
692 (should (looking-at "^### ###$"))))
694 (ert-deftest test-markdown-insertion/header-dwim-prefix ()
695 "Test 'do what I mean' header insertion with prefix arguments."
696 (let ((tests (list '(nil . "## abc ##")
697 '(1 . "# abc #")
698 '(2 . "## abc ##")
699 '(3 . "### abc ###")
700 '(4 . "#### abc ####")
701 '(5 . "##### abc #####")
702 '(6 . "###### abc ######")
703 '((4) . "# abc #")
704 '((16) . "### abc ###"))))
705 (dolist (test tests)
706 (markdown-test-string "## atx\n\nabc"
707 (goto-char (point-max))
708 (let ((current-prefix-arg (car test)))
709 (call-interactively 'markdown-insert-header-dwim)
710 (should (string-equal
711 (buffer-substring (line-beginning-position) (line-end-position))
712 (cdr test))))))))
714 (ert-deftest test-markdown-insertion/header-setext-dwim-prefix ()
715 "Test 'do what I mean' header insertion with prefix arguments."
716 (let ((tests (list '(nil . "abc\n---")
717 '(1 . "abc\n===")
718 '(2 . "abc\n---")
719 '(3 . "### abc ###")
720 '(4 . "#### abc ####")
721 '(5 . "##### abc #####")
722 '(6 . "###### abc ######")
723 '((4) . "abc\n===")
724 '((16) . "### abc ###"))))
725 (dolist (test tests)
726 (markdown-test-string "atx\n---\n\nabc"
727 (goto-char (point-max))
728 (let ((current-prefix-arg (car test)))
729 (call-interactively 'markdown-insert-header-setext-dwim)
730 (should (string-equal
731 (buffer-substring (line-beginning-position) (line-end-position 2))
732 (cdr test))))))))
734 (ert-deftest test-markdown-insertion/header-setext-dwim ()
735 "Test 'do what I mean' header insertion with setext headers."
736 (markdown-test-string
737 "asdfasfasfdsadfasdfasdf\n======="
738 (goto-char 12)
739 (call-interactively 'markdown-insert-header-dwim)
740 (should (string-equal
741 (buffer-string)
742 "asdfasfasfdsadfasdfasdf\n======================="))))
744 (ert-deftest test-markdown-insertion/remove-header ()
745 "Test ATX and setext header."
746 (markdown-test-string
747 "# atx1\n\n## atx2 ##\n\nsetext1\n=======\n\nsetext2\n-------\n"
748 (should (equal (markdown-remove-header) (cons 1 5)))
749 (forward-line)
750 (should (not (markdown-remove-header)))
751 (forward-line)
752 (should (equal (markdown-remove-header) (cons 7 11)))
753 (forward-line)
754 (should (not (markdown-remove-header)))
755 (forward-line)
756 (should (equal (markdown-remove-header) (cons 13 20)))
757 (forward-line)
758 (should (not (markdown-remove-header)))
759 (forward-line)
760 (should (equal (markdown-remove-header) (cons 22 29)))
761 (should (string-equal (buffer-string)
762 "atx1\n\natx2\n\nsetext1\n\nsetext2\n"))))
764 (ert-deftest test-markdown-insertion/italic-unwrap-region ()
765 "A test of inserting italics with italic text in the region."
766 (markdown-test-string "*foo* bar *baz*"
767 (transient-mark-mode)
768 (push-mark (point) t t)
769 (end-of-line)
770 (markdown-insert-italic)
771 (should (string-equal (buffer-string) "*foo bar baz*"))))
773 (ert-deftest test-markdown-insertion/bold-unwrap-region ()
774 "A test of inserting bold with italic text in the region."
775 (markdown-test-string "*foo* **bar** *baz*"
776 (transient-mark-mode)
777 (push-mark (point) t t)
778 (end-of-line)
779 (markdown-insert-bold)
780 (should (string-equal (buffer-string) "***foo* bar *baz***"))))
782 (ert-deftest test-markdown-insertion/code-unwrap-region ()
783 "A test of inserting code with code already in the region."
784 (markdown-test-string "`foo` *bar* `baz`"
785 (transient-mark-mode)
786 (push-mark (point) t t)
787 (end-of-line)
788 (markdown-insert-code)
789 (should (string-equal (buffer-string) "`foo *bar* baz`"))))
791 (ert-deftest test-markdown-insertion/hr-order ()
792 "Test inserting horizontal rules."
793 (dotimes (n (length markdown-hr-strings))
794 (markdown-test-string ""
795 (let ((current-prefix-arg n))
796 (call-interactively 'markdown-insert-hr))
797 (should (string-equal (buffer-string) (nth (1- n) markdown-hr-strings))))))
799 (ert-deftest test-markdown-insertion/hr-prefix ()
800 "Test inserting horizontal rule with C-u prefix."
801 (markdown-test-string ""
802 (let ((current-prefix-arg '(4)))
803 (call-interactively 'markdown-insert-hr))
804 (should (string-equal (buffer-string) (car (last markdown-hr-strings))))))
806 (ert-deftest test-markdown-insertion/hr-bob ()
807 "Test inserting horizontal rule at beginning of buffer."
808 (markdown-test-string "one line\n"
809 (call-interactively 'markdown-insert-hr)
810 (should (string-equal (buffer-string)
811 (concat (car markdown-hr-strings)
812 "\n\none line\n")))))
814 (ert-deftest test-markdown-insertion/hr-eob ()
815 "Test inserting horizontal rule at end of buffer."
816 (markdown-test-string "one line\n"
817 (forward-line)
818 (call-interactively 'markdown-insert-hr)
819 (should (string-equal (buffer-string)
820 (concat "one line\n\n" (car markdown-hr-strings))))))
822 (ert-deftest test-markdown-insertion/hr-mob ()
823 "Test inserting horizontal rule in middle of buffer."
824 (markdown-test-string "one line\n"
825 (forward-word)
826 (let ((markdown-hr-strings '("----------")))
827 (call-interactively 'markdown-insert-hr)
828 (should (string-equal (buffer-string)
829 (concat "one\n\n" (car markdown-hr-strings)
830 "\n\n line\n"))))))
832 (ert-deftest test-markdown-insertion/pre-region-1 ()
833 "Test `markdown-pre-region'."
834 ;; Simple test as non-interactive command
835 (markdown-test-string "line one\nline two\n"
836 (markdown-pre-region (line-beginning-position) (line-end-position))
837 (should (string-equal (buffer-string) " line one\n\nline two\n")))
838 ;; Test removal of whitespace before and after region
839 (markdown-test-string "line one abc\nline two\n"
840 (markdown-pre-region 6 9)
841 (should (string-equal (buffer-string) "line\n\n one\n\nabc\nline two\n")))
842 ;; Simple test as interactive command
843 (markdown-test-string "line one\nline two\n"
844 (push-mark (point) t t)
845 (forward-line 2)
846 (call-interactively 'markdown-pre-region)
847 (should (string-equal (buffer-string) " line one\n line two\n\n"))))
849 (ert-deftest test-markdown-insertion/blockquote-region-1 ()
850 "Test `markdown-blockquote-region'."
851 ;; Simple test as non-interactive command
852 (markdown-test-string "line one\nline two\n"
853 (markdown-blockquote-region (line-beginning-position) (line-end-position))
854 (should (string-equal (buffer-string) "> line one\n\nline two\n")))
855 ;; Test removal of whitespace before and after region
856 (markdown-test-string "line one abc\nline two\n"
857 (markdown-blockquote-region 6 9)
858 (should (string-equal (buffer-string) "line\n\n> one\n\nabc\nline two\n")))
859 ;; Simple test as interactive command
860 (markdown-test-string "line one\nline two\n"
861 (push-mark (point) t t)
862 (forward-line 2)
863 (call-interactively 'markdown-blockquote-region)
864 (should (string-equal (buffer-string) "> line one\n> line two\n\n"))))
866 (ert-deftest test-markdown-insertion/pre-nested-lists ()
867 "Test `markdown-pre-indentation' and `markdown-insert-pre' with nested list."
868 (markdown-test-string "* item\n * item\n"
869 ;; before the first item
870 (should (string-equal (markdown-pre-indentation (point)) " "))
871 (markdown-insert-pre)
872 (beginning-of-line)
873 (should (markdown-prev-line-blank-p))
874 (should (looking-at "^ $"))
875 (should (markdown-next-line-blank-p))
876 ;; before the second item
877 (forward-line 3)
878 (should (string-equal (markdown-pre-indentation (point)) " "))
879 (markdown-insert-pre)
880 (beginning-of-line)
881 (should (markdown-prev-line-blank-p))
882 (should (looking-at "^ $"))
883 (should (markdown-next-line-blank-p))
884 ;; after the second item
885 (forward-line 3)
886 (should (string-equal (markdown-pre-indentation (point)) " "))
887 (markdown-insert-pre)
888 (beginning-of-line)
889 (should (markdown-prev-line-blank-p))
890 (should (looking-at "^ $"))
891 (should (markdown-next-line-blank-p))))
893 (ert-deftest test-markdown-insertion/pre-faux-list ()
894 "Test `markdown-pre-indentation' following a list-marker in a pre block."
895 (markdown-test-string " * pre block, not a list item\n"
896 (should (string-equal (markdown-pre-indentation (point-max)) " "))))
898 (ert-deftest test-markdown-insertion/blockquote-nested-lists ()
899 "Test blockquote insertion in a nested list context."
900 (markdown-test-string "* item\n * item\n"
901 ;; before the first item
902 (should (string-equal (markdown-blockquote-indentation (point)) ""))
903 (markdown-insert-blockquote)
904 (beginning-of-line)
905 (should (markdown-prev-line-blank-p))
906 (should (looking-at "^> $"))
907 (should (markdown-next-line-blank-p))
908 ;; before the second item
909 (forward-line 3)
910 (should (string-equal (markdown-blockquote-indentation (point)) " "))
911 (markdown-insert-blockquote)
912 (beginning-of-line)
913 (should (markdown-prev-line-blank-p))
914 (should (looking-at "^ > $"))
915 (should (markdown-next-line-blank-p))
916 ;; after the second item
917 (forward-line 3)
918 (should (string-equal (markdown-blockquote-indentation (point)) " "))
919 (markdown-insert-blockquote)
920 (beginning-of-line)
921 (should (markdown-prev-line-blank-p))
922 (should (looking-at "^ > $"))
923 (should (markdown-next-line-blank-p))))
925 (ert-deftest test-markdown-insertion/blockquote-region-with-newline ()
926 (markdown-test-string "a\n\nb\n"
927 (markdown-blockquote-region 1 (point-max))
928 (should (equal (buffer-string) "> a\n>\n> b\n\n"))))
930 (ert-deftest test-markdown-insertion/empty-italic ()
931 "Test `markdown-insert-italic' with no word at point and no region."
932 (markdown-test-string ""
933 (call-interactively 'markdown-insert-italic)
934 (should (string-equal (buffer-string) "**"))
935 (should (= (point) 2))))
937 (ert-deftest test-markdown-insertion/empty-bold ()
938 "Test `markdown-insert-bold' with no word at point and no region."
939 (markdown-test-string ""
940 (call-interactively 'markdown-insert-bold)
941 (should (string-equal (buffer-string) "****"))
942 (should (= (point) 3))))
944 (ert-deftest test-markdown-insertion/uri ()
945 "Test `markdown-insert-uri'."
946 (markdown-test-string "http://jblevins.org/projects/markdown-mode/"
947 (call-interactively 'markdown-insert-uri)
948 (should (string-equal (buffer-string) "<http://jblevins.org/projects/markdown-mode/>"))
949 (should (= (point) 2))
950 (call-interactively 'markdown-insert-uri)
951 (should (string-equal (buffer-string) "http://jblevins.org/projects/markdown-mode/"))
952 (should (= (point) 1))
953 (erase-buffer)
954 (call-interactively 'markdown-insert-uri)
955 (should (string-equal (buffer-string) "<>"))
956 (should (= (point) 2))))
958 (ert-deftest test-markdown-insertion/list-item ()
959 "Test `markdown-insert-list-item' on several lists."
960 ;; No existing list
961 (markdown-test-string "abc"
962 (goto-char (point-max))
963 (call-interactively 'markdown-insert-list-item)
964 (should (string-equal (buffer-string) "abc\n * "))
965 (should (= (point) 9)))
966 ;; Following a list item, on the same line
967 (markdown-test-string " * foo"
968 (goto-char (point-max))
969 (call-interactively 'markdown-insert-list-item)
970 (should (string-equal (buffer-string) " * foo\n * ")))
971 ;; Following a list item, on the next line
972 (markdown-test-string "- foo\n"
973 (goto-char (point-max))
974 (call-interactively 'markdown-insert-list-item)
975 (should (string-equal (buffer-string) "- foo\n- ")))
976 ;; Following a list item, after a blank line
977 (markdown-test-string "- foo\n\n"
978 (goto-char (point-max))
979 (call-interactively 'markdown-insert-list-item)
980 (should (string-equal (buffer-string) "- foo\n\n- ")))
981 ;; Preceding a list item
982 (markdown-test-string "- foo\n"
983 (goto-char (point-min))
984 (call-interactively 'markdown-insert-list-item)
985 (should (string-equal (buffer-string) "- \n- foo\n")))
986 ;; Preceding a list item and a blank line
987 (markdown-test-string "\n\n- foo\n"
988 (goto-char (point-min))
989 (call-interactively 'markdown-insert-list-item)
990 (should (string-equal (buffer-string) "- \n\n- foo\n")))
991 ;; In the middle of a list item
992 (markdown-test-string "- foo bar\n"
993 (forward-word)
994 (call-interactively 'markdown-insert-list-item)
995 (should (string-equal (buffer-string) "- foo\n- bar\n")))
996 ;; Before a list marker, but not at beginning of line
997 (markdown-test-string " - foo\n"
998 (forward-char 2)
999 (call-interactively 'markdown-insert-list-item)
1000 (should (string-equal (buffer-string) " - \n - foo\n")))
1001 ;; Following an ordered list item
1002 (markdown-test-string "6. foo"
1003 (goto-char (point-max))
1004 (call-interactively 'markdown-insert-list-item)
1005 (should (string-equal (buffer-string) "6. foo\n7. ")))
1006 ;; Following a fancy list item, on the next line
1007 (markdown-test-string "#. foo"
1008 (goto-char (point-max))
1009 (call-interactively 'markdown-insert-list-item)
1010 (should (string-equal (buffer-string) "#. foo\n#. ")))
1011 ;; Following a nested ordered list item
1012 (markdown-test-string "6. foo\n 1. bar"
1013 (goto-char (point-max))
1014 (call-interactively 'markdown-insert-list-item)
1015 (should (string-equal (buffer-string) "6. foo\n 1. bar\n 2. ")))
1016 ;; Preceding an ordered list item
1017 (markdown-test-string "\n1. foo\n2. bar"
1018 (goto-char (point-min))
1019 (call-interactively 'markdown-insert-list-item)
1020 (should (string-equal (buffer-string) "1. \n1. foo\n2. bar")))
1021 ;; Preserve previous spacing in ordered list
1022 (markdown-test-string "1. foo"
1023 (goto-char (point-max))
1024 (call-interactively 'markdown-insert-list-item)
1025 (should (string-equal (buffer-string) "1. foo\n2. ")))
1026 ;; Adjust spacing for number width changes (e.g., 9 -> 10)
1027 (markdown-test-string "9. foo"
1028 (goto-char (point-max))
1029 (call-interactively 'markdown-insert-list-item)
1030 (should (string-equal (buffer-string) "9. foo\n10. ")))
1031 ;; Don't adjust spacing for number width changes if no extra whitespace
1032 (markdown-test-string "99. foo"
1033 (goto-char (point-max))
1034 (call-interactively 'markdown-insert-list-item)
1035 (should (string-equal (buffer-string) "99. foo\n100. ")))
1036 ;; Don't adjust spacing if tabs are used as whitespace
1037 (markdown-test-string "9.\tfoo"
1038 (goto-char (point-max))
1039 (call-interactively 'markdown-insert-list-item)
1040 (should (string-equal (buffer-string) "9.\tfoo\n10.\t"))))
1042 (ert-deftest test-markdown-insertion/nested-list-marker ()
1043 "Test marker detection for `markdown-insert-list-item'."
1044 (markdown-test-string
1045 "1. A\n * AA\n 1. AAA"
1046 (goto-char (point-max))
1047 (let ((current-prefix-arg '(4)))
1048 (call-interactively 'markdown-insert-list-item))
1049 (should (eq (point) 36))
1050 (should (looking-back "\* "))
1051 (should (string-equal
1052 (buffer-string)
1053 "1. A\n * AA\n 1. AAA\n * "))
1054 (let ((current-prefix-arg '(4)))
1055 (call-interactively 'markdown-insert-list-item))
1056 (should (eq (point) 40))
1057 (should (looking-back "2\. "))
1058 (should (string-equal
1059 (buffer-string)
1060 "1. A\n * AA\n 1. AAA\n * \n2. "))
1061 (let ((current-prefix-arg '(4)))
1062 (call-interactively 'markdown-insert-list-item))
1063 (should (eq (point) 44))
1064 (should (looking-back "3\. "))
1065 (should (string-equal
1066 (buffer-string)
1067 "1. A\n * AA\n 1. AAA\n * \n2. \n3. "))))
1069 (ert-deftest test-markdown-insertion/reference-link ()
1070 "Basic tests for `markdown-insert-reference-link'."
1071 ;; Test optional parameters (leave point after link)
1072 (markdown-test-string ""
1073 (markdown-insert-reference-link "abc" "1")
1074 (should (string-equal (buffer-string) "[abc][1]"))
1075 (should (= (point) 9)))
1076 ;; Full link without title (leave point after link)
1077 (markdown-test-string ""
1078 (markdown-insert-reference-link "link" "label" "http://jblevins.org/")
1079 (should (string-equal (buffer-string) "[link][label]\n\n[label]: http://jblevins.org/\n"))
1080 (should (= (point) 14)))
1081 ;; Full link without label or title (leave point after link)
1082 (markdown-test-string ""
1083 (markdown-insert-reference-link "link" "" "http://jblevins.org/")
1084 (should (string-equal (buffer-string) "[link][]\n\n[link]: http://jblevins.org/\n"))
1085 (should (= (point) 9)))
1086 ;; Link only with no label, URL, or title (leave point after link)
1087 (markdown-test-string ""
1088 (markdown-insert-reference-link "link" "")
1089 (should (string-equal (buffer-string) "[link][]"))
1090 (should (= (point) 9))))
1092 (ert-deftest test-markdown-insertion/reference-link-end ()
1093 "Basic reference link insertion test for 'end location."
1094 (let ((markdown-reference-location 'end))
1095 (markdown-test-string "first para\n\nsecond para\n"
1096 (end-of-line)
1097 (markdown-insert-reference-link "link" "" "http://jblevins.org/")
1098 (should (= (point) 19))
1099 (goto-char (point-min))
1100 (forward-line 4)
1101 (should (looking-at "\\[link\\]: http://jblevins.org/")))))
1103 (ert-deftest test-markdown-insertion/reference-link-immediately ()
1104 "Basic reference link insertion test for 'immediately location."
1105 (let ((markdown-reference-location 'immediately))
1106 (markdown-test-string "first para\n\nsecond para\n"
1107 (end-of-line)
1108 (markdown-insert-reference-link "link" "" "http://jblevins.org/")
1109 (should (= (point) 19))
1110 (goto-char (point-min))
1111 (forward-line 2)
1112 (should (looking-at "\\[link\\]: http://jblevins.org/")))))
1114 (ert-deftest test-markdown-insertion/reference-link-header ()
1115 "Basic reference link and definition insertion test for 'header location."
1116 (let ((markdown-reference-location 'header))
1117 (markdown-test-string "par one\n\npar two\n\n### header\n"
1118 (end-of-line)
1119 (markdown-insert-reference-link "link" "")
1120 (markdown-insert-reference-definition "link")
1121 (should (= (point) 35))
1122 (should (looking-back "\\[link\\]: " nil)))))
1124 (ert-deftest test-markdown-insertion/reference-definition-block ()
1125 "Test whitespace when inserting a reference definition among others"
1126 (let ((markdown-reference-location 'header))
1127 (markdown-test-string "text
1129 [1]: https://www.gnu.org/
1131 ### header
1133 (markdown-insert-reference-definition "2")
1134 (should (= (point) 38))
1135 (should (looking-back "https://www.gnu.org/\n\\[2\\]: " nil)))))
1137 (ert-deftest test-markdown-insertion/reference-link-before-file-locals ()
1138 "Test inserting a reference link before file-local variables."
1139 (markdown-test-string "
1141 <!-- Local Variables: -->
1142 <!-- mode: markdown -->
1143 <!-- End: -->
1145 (markdown-insert-reference-link "link" "" "http://jblevins.org/")
1146 (should (equal (buffer-substring-no-properties 1 (point-max))
1147 "[link][]
1149 \[link]: http://jblevins.org/
1151 <!-- Local Variables: -->
1152 <!-- mode: markdown -->
1153 <!-- End: -->
1155 (should (equal (point) 9))))
1157 (ert-deftest test-markdown-insertion/inline-to-reference-link ()
1158 "Inline link to reference link conversion with tab completion."
1159 (markdown-test-string "[text](http://jblevins.org/ \"title\")"
1160 (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"))
1161 (should (string-equal (buffer-string) "[text][1]\n\n[1]: http://jblevins.org/ \"title\"\n"))))
1163 (ert-deftest test-markdown-insertion/inline-to-reference-link-2 ()
1164 "Inline link to reference link conversion with existing reference links."
1165 (markdown-test-string "[text](http://jblevins.org/ \"title\")\n\n[1]: https://www.gnu.org"
1166 (execute-kbd-macro (read-kbd-macro "M-x markdown-insert-link RET M-DEL M-DEL M-DEL [1] RET RET"))
1167 (should (string-equal (buffer-string) "[text][1]\n\n[1]: https://www.gnu.org"))))
1169 (ert-deftest test-markdown-insertion/inline-link-angle-url-at-point ()
1170 "Test `markdown-insert-link' with angle URL at point."
1171 (markdown-test-string "<https://www.gnu.org/>"
1172 (execute-kbd-macro (read-kbd-macro "M-x markdown-insert-link RET RET GNU RET RET"))
1173 (should (string-equal (buffer-string) "[GNU](https://www.gnu.org/)"))))
1175 (ert-deftest test-markdown-insertion/inline-link-plain-url-at-point ()
1176 "Test `markdown-insert-link' with plain URL at point."
1177 (markdown-test-string "https://www.gnu.org/"
1178 (execute-kbd-macro (read-kbd-macro "M-x markdown-insert-link RET RET GNU RET RET"))
1179 (should (string-equal (buffer-string) "[GNU](https://www.gnu.org/)"))))
1181 (ert-deftest test-markdown-insertion/inline-link-reference-link-at-point ()
1182 "Test `markdown-insert-link' with reference link at point."
1183 (markdown-test-string ""
1184 (markdown-insert-reference-link "link" "label" "http://jblevins.org/")
1185 (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"))
1186 (should (string-equal (buffer-substring 1 28) "[link](http://example.com/)"))
1187 (should (= (point) 28))))
1189 (ert-deftest test-markdown-insertion/inline-link-active-region ()
1190 "Test `markdown-insert-link' with active region."
1191 (markdown-test-string "abc def ghi"
1192 (let ((tmm-orig transient-mark-mode))
1193 (transient-mark-mode 1)
1194 (push-mark (point) t t)
1195 (forward-word 2)
1196 (execute-kbd-macro (read-kbd-macro "M-x markdown-insert-link RET http://example.com/ RET RET RET"))
1197 (should (string-equal (buffer-string) "[abc def](http://example.com/) ghi"))
1198 (should (= (point) 31))
1199 (transient-mark-mode tmm-orig))))
1201 ;;; Footnote tests:
1203 (ert-deftest test-markdown-footnote/basic-end ()
1204 "Basic footnote insertion and deletion tests for 'end location."
1205 (let ((markdown-footnote-location 'end))
1206 (markdown-test-string "first line\nsecond line\n"
1207 ;; new buffer with no footnotes
1208 (should (= markdown-footnote-counter 0))
1209 ;; footnote insertion
1210 (end-of-line)
1211 (markdown-insert-footnote)
1212 (should (= (point) 35))
1213 (should (= markdown-footnote-counter 1))
1214 (should (looking-back "\\[^1\\]: " nil))
1215 ;; kill with point in footnote definition
1216 (insert "footnote text")
1217 (let (kill-ring)
1218 (markdown-footnote-kill))
1219 (should (= (point) 24))
1220 (should (bolp))
1221 (should (string-equal (buffer-string) "first line\nsecond line\n"))
1222 ;; insertion, counter should increment
1223 (goto-char (point-min))
1224 (end-of-line)
1225 (markdown-insert-footnote)
1226 (should (= (point) 35))
1227 (should (= markdown-footnote-counter 2))
1228 (should (looking-back "\\[^2\\]: " nil))
1229 (insert "footnote text")
1230 ;; return to marker
1231 (markdown-footnote-return)
1232 (should (= (point) 15))
1233 (should (looking-back "\\[^2\\]" nil))
1234 ;; kill with point at marker
1235 (let (kill-ring)
1236 (markdown-footnote-kill))
1237 (should (= (point) 11))
1238 (should (eolp))
1239 (should (string-equal (buffer-string) "first line\nsecond line\n")))))
1241 (ert-deftest test-markdown-footnote/basic-immediately ()
1242 "Basic footnote insertion and deletion tests for 'immediately location."
1243 (let ((markdown-footnote-location 'immediately))
1244 (markdown-test-string "first paragraph\n\nsecond paragraph\n"
1245 ;; new buffer with no footnotes
1246 (should (= markdown-footnote-counter 0))
1247 ;; footnote insertion
1248 (end-of-line)
1249 (markdown-insert-footnote)
1250 (should (= (point) 28))
1251 (should (= markdown-footnote-counter 1))
1252 (should (looking-back "\\[^1\\]: " nil))
1253 ;; kill with point in footnote definition
1254 (insert "footnote text")
1255 (let (kill-ring)
1256 (markdown-footnote-kill))
1257 (should (= (point) 18))
1258 (should (bolp))
1259 (should (string-equal (buffer-string)
1260 "first paragraph\n\nsecond paragraph\n")))))
1262 (ert-deftest test-markdown-footnote/basic-header ()
1263 "Basic footnote insertion and deletion tests for 'header location."
1264 (let ((markdown-footnote-location 'header))
1265 (markdown-test-string "par one\n\npar two\n\n### header\n"
1266 ;; new buffer with no footnotes
1267 (should (= markdown-footnote-counter 0))
1268 ;; footnote insertion
1269 (end-of-line)
1270 (markdown-insert-footnote)
1271 (should (= (point) 29))
1272 (should (= markdown-footnote-counter 1))
1273 (should (looking-back "\\[^1\\]: " nil))
1274 ;; kill with point in footnote definition
1275 (insert "footnote text")
1276 (let (kill-ring)
1277 (markdown-footnote-kill))
1278 (should (= (point) 19))
1279 (should (bolp))
1280 (should (string-equal (buffer-string)
1281 "par one\n\npar two\n\n### header\n"))
1282 ;; insertion, counter should increment
1283 (goto-char (point-min))
1284 (end-of-line)
1285 (markdown-insert-footnote)
1286 (should (= (point) 29))
1287 (should (= markdown-footnote-counter 2))
1288 (should (looking-back "\\[^2\\]: " nil))
1289 (insert "footnote text")
1290 ;; return to marker
1291 (markdown-footnote-return)
1292 (should (= (point) 12))
1293 (should (looking-back "\\[^2\\]" nil))
1294 ;; kill with point at marker
1295 (let (kill-ring)
1296 (markdown-footnote-kill))
1297 (should (= (point) 8))
1298 (should (eolp))
1299 (should (string-equal (buffer-string)
1300 "par one\n\npar two\n\n### header\n")))))
1302 (ert-deftest test-markdown-footnote/basic-subtree ()
1303 "Basic footnote insertion and deletion tests for 'subtree location."
1304 (let ((markdown-footnote-location 'subtree))
1305 (markdown-test-string "# h1\n\nfoo\n\n## h2\n\nbar\n"
1306 ;; new buffer with no footnotes
1307 (should (= markdown-footnote-counter 0))
1308 ;; footnote insertion
1309 (forward-line 2)
1310 (end-of-line)
1311 (markdown-insert-footnote)
1312 (should (= (point) 34))
1313 (should (= markdown-footnote-counter 1))
1314 (should (looking-back "\\[^1\\]: " nil)))))
1316 (ert-deftest test-markdown-footnote/kill-empty-text ()
1317 "Test killing a footnote with marker but no text."
1318 (markdown-test-string "no text[^1]\n\n[^1]: \n"
1319 (end-of-line)
1320 (markdown-footnote-goto-text)
1321 (should (looking-back "\\[^1\\]: " nil))
1322 (let (kill-ring)
1323 (markdown-footnote-kill))
1324 (should (string-equal (buffer-string) "no text\n"))))
1326 (ert-deftest test-markdown-footnote/kill-empty-after ()
1327 "Test killing an empty footnote after one with text (previously killed the
1328 footnote with text above)."
1329 (markdown-test-string "[^with-text][^no-text]\n\n[^with-text]: Text\n[^no-text]:"
1330 (let (kill-ring)
1331 (forward-line 3)
1332 (should (looking-at "\\[\\^no-text\\]:$"))
1333 (markdown-footnote-kill)
1334 (should (string-equal (current-kill 0) "")))))
1336 (ert-deftest test-markdown-footnote/kill-hanging-paras ()
1337 "Test killing a footnote where block text starts after the label (previously
1338 killed the footnote above)."
1339 (markdown-test-string "[^1][^2]\n\n[^1]: Foo\n\n[^2]:\n Text\n\n More text\n\n\nNot indented"
1340 (let (kill-ring)
1341 (forward-line 4)
1342 (should (looking-at "\\[\\^2\\]:$"))
1343 (markdown-footnote-kill)
1344 ;; We want to include the leading space on hanging footnote paragraphs,
1345 ;; even if a hanging paragraph is the first item in the footnote.
1346 (should (string-equal (current-kill 0) "Text\n\n More text\n")))))
1348 (ert-deftest test-markdown-footnote/text-positions-buffer-top ()
1349 "Test markdown-footnote-text-positions on footnote adjacent to buffer top
1350 (was infinite loop)."
1351 (markdown-test-string "[^label]: text\n more text"
1352 (should (equal (markdown-footnote-text-positions) (list "^label" 1 29)))))
1354 (ert-deftest test-markdown-footnote/text-positions-buffer-top-one-line ()
1355 "Test markdown-footnote-text-positions on one-line footnote adjacent to
1356 buffer top (failed to find positions)."
1357 (markdown-test-string "[^label]: text\n"
1358 (should (equal (markdown-footnote-text-positions) (list "^label" 1 16)))))
1360 (ert-deftest test-markdown-footnote/text-positions-buffer-top-not-footnote ()
1361 "Test markdown-footnote-text-positions on plain paragraph adjacent to buffer
1362 top (was infinite loop)."
1363 (markdown-test-string "text\n more text\n"
1364 (should (eq (markdown-footnote-text-positions) nil))))
1366 (ert-deftest test-markdown-footnote/text-positions-buffer-bottom ()
1367 "Test markdown-footnote-text-positions on footnote adjacent to buffer bottom
1368 (was infinite loop)."
1369 (markdown-test-string "\n[^label]: text\n more text"
1370 (forward-line 1)
1371 (should (equal (markdown-footnote-text-positions) (list "^label" 2 30)))))
1373 (ert-deftest test-markdown-footnote/kill-adjacent-footnote ()
1374 "Test killing a footnote adjacent to other one-line footnotes (previously
1375 killed the wrong one)."
1376 (markdown-test-string "Text[^1] with[^2] footnotes[^3]\n\n[^1]: foo\n[^2]: bar\n[^3]: baz"
1377 (let (kill-ring)
1378 (forward-line 3)
1379 (should (looking-at "\\[\\^2\\]: bar"))
1380 (markdown-footnote-kill)
1381 (should (string-equal (current-kill 0) "bar\n")))))
1383 (ert-deftest test-markdown-footnote/kill-adjacent-markers ()
1384 "Test killing a footnote where the labels are adjacent (previously, the wrong
1385 footnote would be killed because the attempt to jump to the marker would jump to
1386 the opening bracket of [^2], and then subsequent functions would kill [^2])."
1387 (markdown-test-string "Text with footnotes[^1][^2]\n\n[^1]: foo\n\n[^2]: bar\n"
1388 (let (kill-ring)
1389 (forward-line 2)
1390 (should (looking-at "\\[\\^1\\]: foo"))
1391 (markdown-footnote-kill)
1392 (should (string-equal (current-kill 0) "foo\n")))))
1394 (when (version< emacs-version "24.2")
1395 ;; fix segfault on 24.1 with the normal implementation of this function. isn't
1396 ;; exactly correct, but should make tests work the same
1397 (defadvice kill-buffer-and-window (around markdown-test-fix-segfault activate)
1398 (kill-buffer)
1399 (select-window (previous-window))))
1401 (ert-deftest test-markdown-footnote-reference/jump ()
1402 "Test `markdown-do' for footnotes and reference links."
1403 (markdown-test-string
1404 "body[^1], [link 1][ref],
1405 [link 2][ref]
1407 [^1]: footnote
1409 [ref]: https://duckduckgo.com/"
1410 (goto-char 5) ; start of [^1]
1411 (markdown-do) ; markdown-footnote-goto-text
1412 (should (looking-at "footnote"))
1413 (markdown-do) ; markdown-footnote-return
1414 (should (= (point) 9)) ; just after [^1]
1415 (markdown-next-link) ; beginning of [link 1][]
1416 (markdown-do)
1417 (should (looking-at "https://duckduckgo.com/"))
1418 (should (equal (markdown-reference-find-links "ref")
1419 (list (list "link 2" 26 2) (list "link 1" 11 1))))
1420 (markdown-do) ; opens a reference link buffer
1421 (should (string= (buffer-string) "Links using reference ref:\n\nlink 1 (line 1)\nlink 2 (line 2)\n"))
1422 (should (looking-at "link 1")) ; in reference link popop buffer
1423 (execute-kbd-macro (read-kbd-macro "RET")) ; jump to "link 1"
1424 (should (looking-at "\\[link 1\\]")) ; back in main buffer
1425 (should (= (point) 11))))
1427 ;;; Element removal tests:
1429 (ert-deftest test-markdown-kill/simple ()
1430 "Simple tests for `markdown-kill-thing-at-point'."
1431 (let ((kill-ring nil)
1432 (tests (list '("`foo`" . "foo")
1433 '("## foo ##" . "foo")
1434 '("## foo" . "foo")
1435 '("foo\n---" . "foo")
1436 '("foo\n===" . "foo")
1437 '("* * * * *" . "* * * * *")
1438 '("[foo](http://bar.com/)" . "foo")
1439 '("![foo](http://bar.com/)" . "foo")
1440 '("[foo][bar]" . "foo")
1441 '("![foo][bar]" . "foo")
1442 '("<http://foo.com/>" . "http://foo.com/")
1443 '("<foo@bar.com>" . "foo@bar.com")
1444 '("**foo**" . "foo")
1445 '("__foo__" . "foo")
1446 '("*foo*" . "foo")
1447 '("_foo_" . "foo")
1448 '(" [foo]: http://bar.com/" . "http://bar.com/")
1449 '(" [foo]: http://bar.com/ \"title\"" . "http://bar.com/")
1450 '("foo[^bar]\n\n[^bar]: baz" . "baz")
1451 '("[^bar]: baz" . "baz")
1452 '(" * foo\n bar" . " * foo\n bar"))))
1453 (dolist (test tests)
1454 ;; Load test string (the car), move to end of first line, kill
1455 ;; thing at point, and then verify that the kill ring contains cdr.
1456 (markdown-test-string (car test)
1457 (end-of-line)
1458 (call-interactively 'markdown-kill-thing-at-point)
1459 (should (string-equal (current-kill 0) (cdr test)))))))
1461 (ert-deftest test-markdown-kill/footnote-text ()
1462 "Test killing a footnote with point at footnote text."
1463 (markdown-test-string "some text[^1]\n\n[^1]: footnote\n"
1464 (end-of-line)
1465 (markdown-footnote-goto-text)
1466 (let (kill-ring)
1467 (markdown-footnote-kill))
1468 (should (string-equal (buffer-string) "some text\n"))))
1470 (ert-deftest test-markdown-kill/code ()
1471 "Test killing with code regex.."
1472 (let ((kill-ring nil))
1473 (markdown-test-string "Lorem `ipsum` dolor `sit` `amet`."
1474 (goto-char 22) ; position point at s in `sit`
1475 (call-interactively 'markdown-kill-thing-at-point)
1476 (should (string-equal (current-kill 0) "sit")))))
1478 ;;; Completion:
1480 (ert-deftest test-markdown-complete/atx-header-incomplete ()
1481 "Test `markdown-incomplete-atx-p'."
1482 (markdown-test-string "### ###"
1483 (should (looking-at markdown-regex-header-atx))
1484 (should-not (markdown-incomplete-atx-p)))
1485 (markdown-test-string "###abc###"
1486 (should-not (looking-at markdown-regex-header-atx)))
1487 (markdown-test-string "### ###"
1488 (should (looking-at markdown-regex-header-atx))
1489 (should (markdown-incomplete-atx-p))))
1491 (ert-deftest test-markdown-complete/atx-header ()
1492 "Test `markdown-complete' for atx headers."
1493 (markdown-test-string "##### test"
1494 (call-interactively 'markdown-complete)
1495 (should (string-equal (buffer-string) "##### test #####"))))
1497 (ert-deftest test-markdown-complete/setext-header-incomplete ()
1498 "Test `markdown-incomplete-setext-p'."
1499 (markdown-test-string "abc\n===\n"
1500 (should (looking-at markdown-regex-header-setext))
1501 (should-not (markdown-incomplete-setext-p)))
1502 (markdown-test-string "abc\n==\n"
1503 (should (looking-at markdown-regex-header-setext))
1504 (should (markdown-incomplete-setext-p)))
1505 (markdown-test-string "abc\n====\n"
1506 (should (looking-at markdown-regex-header-setext))
1507 (should (markdown-incomplete-setext-p))))
1509 (ert-deftest test-markdown-complete/setext-header ()
1510 "Test `markdown-complete' for setext headers."
1511 (markdown-test-string "test \n=="
1512 (call-interactively 'markdown-complete)
1513 (should (string-equal (buffer-string) "test\n===="))))
1515 (ert-deftest test-markdown-complete/hr-incomplete ()
1516 "Test `markdown-incomplete-hr-p'."
1517 (dolist (i (number-sequence 0 (1- (length markdown-hr-strings))))
1518 (markdown-test-string (nth i markdown-hr-strings)
1519 (should (looking-at markdown-regex-hr))
1520 (should-not (markdown-incomplete-hr-p))
1521 (should-error (call-interactively 'markdown-complete)))))
1523 (ert-deftest test-markdown-complete/hr ()
1524 "Test completion via `markdown-complete' for horizontal rules."
1525 (markdown-test-string "- - - - -"
1526 (call-interactively 'markdown-complete)
1527 (should (string-equal (buffer-string) (car markdown-hr-strings)))))
1529 (ert-deftest test-markdown-complete/buffer-setext-2 ()
1530 "Test `markdown-complete-buffer' for level two setext heading."
1531 ;; Ensure markdown-complete-buffer doesn't mistake this for a horizontal rule
1532 (markdown-test-string "Subheading\n--\n"
1533 (call-interactively 'markdown-complete-buffer)
1534 (should (string-equal (buffer-string) "Subheading\n----------\n\n")))
1535 (markdown-test-string "Abc\n--\n\nDef\n--\n"
1536 (call-interactively 'markdown-complete-buffer)
1537 (should (string-equal (buffer-string) "Abc\n---\n\nDef\n---\n\n"))))
1539 ;;; Promotion and demotion tests:
1541 (ert-deftest test-markdown-promote/atx-header ()
1542 "Test `markdown-promote' for atx headers."
1543 (markdown-test-string "###### test ######"
1544 (markdown-promote)
1545 (should (string-equal (buffer-string) "##### test #####"))
1546 (markdown-promote)
1547 (should (string-equal (buffer-string) "#### test ####"))
1548 (markdown-promote)
1549 (should (string-equal (buffer-string) "### test ###"))
1550 (markdown-promote)
1551 (should (string-equal (buffer-string) "## test ##"))
1552 (markdown-promote)
1553 (should (string-equal (buffer-string) "# test #"))))
1555 (ert-deftest test-markdown-demote/atx-header ()
1556 "Test `markdown-demote' for atx headers."
1557 (markdown-test-string "# test #"
1558 (markdown-demote)
1559 (should (string-equal (buffer-string) "## test ##"))
1560 (markdown-demote)
1561 (should (string-equal (buffer-string) "### test ###"))
1562 (markdown-demote)
1563 (should (string-equal (buffer-string) "#### test ####"))
1564 (markdown-demote)
1565 (should (string-equal (buffer-string) "##### test #####"))
1566 (markdown-demote)
1567 (should (string-equal (buffer-string) "###### test ######"))))
1569 (ert-deftest test-markdown-promote/setext-header ()
1570 "Test `markdown-promote' for setext headers."
1571 (markdown-test-string "test\n----"
1572 (markdown-promote)
1573 (should (string-equal (buffer-string) "test\n===="))))
1575 (ert-deftest test-markdown-demote/setext-header ()
1576 "Test `markdown-demote' for setext headers."
1577 (markdown-test-string "test\n===="
1578 (markdown-demote)
1579 (should (string-equal (buffer-string) "test\n----"))
1580 (markdown-demote)
1581 (should (string-equal (buffer-string) "### test ###"))
1582 (markdown-demote)
1583 (should (string-equal (buffer-string) "#### test ####"))
1584 (markdown-demote)
1585 (should (string-equal (buffer-string) "##### test #####"))
1586 (markdown-demote)
1587 (should (string-equal (buffer-string) "###### test ######"))))
1589 (ert-deftest test-markdown-promote/hr ()
1590 "Test `markdown-promote' for horizontal rules."
1591 (markdown-test-string (car (reverse markdown-hr-strings))
1592 (dolist (n (number-sequence 4 0 -1))
1593 (markdown-promote)
1594 (should (string-equal (buffer-string) (nth n markdown-hr-strings))))))
1596 (ert-deftest test-markdown-demote/hr ()
1597 "Test `markdown-demote' for horizontal rules."
1598 (markdown-test-string (car markdown-hr-strings)
1599 (dolist (n (number-sequence 1 5))
1600 (markdown-demote)
1601 (should (string-equal (buffer-string) (nth n markdown-hr-strings))))))
1603 (ert-deftest test-markdown-promote/bold ()
1604 "Test `markdown-promote' for bold markup."
1605 (markdown-test-string "__bold__"
1606 (call-interactively 'markdown-promote)
1607 (should (string-equal (buffer-string) "**bold**"))))
1609 (ert-deftest test-markdown-demote/bold ()
1610 "Test `markdown-demote' for bold markup."
1611 (markdown-test-string "**bold**"
1612 (call-interactively 'markdown-promote)
1613 (should (string-equal (buffer-string) "__bold__"))))
1615 (ert-deftest test-markdown-promote/italic ()
1616 "Test `markdown-promote' for italic markup."
1617 (markdown-test-string "_italic_"
1618 (call-interactively 'markdown-promote)
1619 (should (string-equal (buffer-string) "*italic*"))))
1621 (ert-deftest test-markdown-demote/italic ()
1622 "Test `markdown-demote' for italic markup."
1623 (markdown-test-string "*italic*"
1624 (call-interactively 'markdown-promote)
1625 (should (string-equal (buffer-string) "_italic_"))))
1627 ;;; Subtree editing tests:
1629 (ert-deftest test-markdown-subtree/promote ()
1630 "Test `markdown-promote-subtree'."
1631 (markdown-test-string "# h1 #\n\n## h2 ##\n\n### h3 ###\n\n## h2 ##\n\n# h1 #\n"
1632 ;; The first h1 should get promoted away.
1633 ;; The second h1 should not be promoted.
1634 (markdown-promote-subtree)
1635 (should (string-equal (buffer-string) "h1\n\n# h2 #\n\n## h3 ##\n\n# h2 #\n\n# h1 #\n"))
1636 ;; Second call should do nothing since point is no longer at a heading.
1637 (markdown-promote-subtree)
1638 (should (string-equal (buffer-string) "h1\n\n# h2 #\n\n## h3 ##\n\n# h2 #\n\n# h1 #\n"))
1639 ;; Move to h2 and promote again.
1640 (forward-line 2)
1641 (markdown-promote-subtree)
1642 (should (string-equal (buffer-string) "h1\n\nh2\n\n# h3 #\n\n# h2 #\n\n# h1 #\n"))))
1644 (ert-deftest test-markdown-subtree/promote-single-section ()
1645 "Test `markdown-promote-subtree' on a single or last section.
1646 Should not cause an infinite loop."
1647 (markdown-test-string "foo\n\n## h2 ##\n\nbar\n"
1648 ;; The h2 should get promoted to h1 away.
1649 (markdown-test-goto-heading "h2")
1650 (markdown-promote-subtree)
1651 (should (string-equal (buffer-string) "foo\n\n# h2 #\n\nbar\n"))))
1653 (ert-deftest test-markdown-subtree/demote ()
1654 "Test `markdown-demote-subtree'."
1655 (markdown-test-string "# h1 #\n\n## h2 ##\n\n### h3 ###\n\n## h2 ##\n\n# h1 #\n"
1656 ;; The second h1 should not be demoted
1657 (markdown-demote-subtree)
1658 (should (string-equal (buffer-string) "## h1 ##\n\n### h2 ###\n\n#### h3 ####\n\n### h2 ###\n\n# h1 #\n"))
1659 (markdown-demote-subtree)
1660 (should (string-equal (buffer-string) "### h1 ###\n\n#### h2 ####\n\n##### h3 #####\n\n#### h2 ####\n\n# h1 #\n"))
1661 (markdown-demote-subtree)
1662 (should (string-equal (buffer-string) "#### h1 ####\n\n##### h2 #####\n\n###### h3 ######\n\n##### h2 #####\n\n# h1 #\n"))
1663 ;; Stop demoting at level six
1664 (markdown-demote-subtree)
1665 (should (string-equal (buffer-string) "##### h1 #####\n\n###### h2 ######\n\n###### h3 ######\n\n###### h2 ######\n\n# h1 #\n"))
1666 (markdown-demote-subtree)
1667 (should (string-equal (buffer-string) "###### h1 ######\n\n###### h2 ######\n\n###### h3 ######\n\n###### h2 ######\n\n# h1 #\n"))))
1669 (ert-deftest test-markdown-subtree/move-up ()
1670 "Test `markdown-move-subtree-up'."
1671 ;; Note that prior to Emacs 24.5, this does not work for the last subtree in
1672 ;; the buffer due to Emacs bug #19102:
1673 ;; https://debbugs.gnu.org/cgi/bugreport.cgi?bug=19102
1674 ;; https://github.com/emacs-mirror/emacs/commit/b3910f
1675 ;; That also corrects the type of the "Cannot move pase superior level" error
1676 ;; from 'error to 'user-error.
1677 (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"
1678 (re-search-forward "^# 2")
1679 (markdown-move-subtree-up)
1680 (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"))
1681 ;; Second attempt should fail, leaving buffer unchanged.
1682 ;; (This way of asserting the contents of the error
1683 ;; message is a bit convoluted and more fragile than
1684 ;; ideal. But prior to Emacs 24.5, the type of this
1685 ;; error is just 'error, and a bare "should-error" is
1686 ;; really overly broad.)
1687 (should (string-equal
1688 "Cannot move past superior level"
1689 (cl-second (should-error (markdown-move-subtree-up)))))))
1691 (ert-deftest test-markdown-subtree/move-down ()
1692 "Test `markdown-move-subtree-down'."
1693 (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"
1694 (re-search-forward "^## 1\.1")
1695 (markdown-move-subtree-down)
1696 (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"))))
1698 (ert-deftest test-markdown-subtree/mark ()
1699 "Test `markdown-mark-subtree'."
1700 (markdown-test-file "outline.text"
1701 (markdown-next-visible-heading 1)
1702 (should-not mark-active)
1703 (markdown-mark-subtree)
1704 (should (= (point) 19))
1705 (should (= (mark) 349))
1706 (should mark-active)
1707 (deactivate-mark)
1708 (should-not mark-active)
1709 (markdown-forward-same-level 1)
1710 (markdown-mark-subtree)
1711 (should (= (point) 351))
1712 (should (= (mark) 515))
1713 (should mark-active)))
1715 (ert-deftest test-markdown-subtree/narrow ()
1716 "Test `markdown-narrow-to-subtree'."
1717 (markdown-test-file "outline.text"
1718 (markdown-next-visible-heading 1)
1719 (markdown-forward-same-level 1)
1720 (widen)
1721 (should (= (point-min) 1))
1722 (should (= (point-max) 553))
1723 (markdown-narrow-to-subtree)
1724 (should (= (point-min) 351))
1725 (should (= (point-max) 515))))
1727 ;;; Cycling:
1729 (ert-deftest test-markdown-cycle/atx-header ()
1730 "Test `markdown-demote' cycling for atx headers."
1731 (markdown-test-string "# test"
1732 (call-interactively 'markdown-demote)
1733 (should (string-equal (buffer-string) "## test ##"))
1734 (call-interactively 'markdown-demote)
1735 (should (string-equal (buffer-string) "### test ###"))
1736 (call-interactively 'markdown-demote)
1737 (should (string-equal (buffer-string) "#### test ####"))
1738 (call-interactively 'markdown-demote)
1739 (should (string-equal (buffer-string) "##### test #####"))
1740 (call-interactively 'markdown-demote)
1741 (should (string-equal (buffer-string) "###### test ######"))
1742 (call-interactively 'markdown-demote)
1743 (should (string-equal (buffer-string) "###### test ######"))))
1745 (ert-deftest test-markdown-cycle/setext-header ()
1746 "Test `markdown-demote' cycling for setext headers."
1747 (markdown-test-string "test\n===="
1748 (call-interactively 'markdown-demote)
1749 (should (string-equal (buffer-string) "test\n----"))
1750 (call-interactively 'markdown-demote)
1751 (should (string-equal (buffer-string) "### test ###"))
1752 (call-interactively 'markdown-demote)
1753 (should (string-equal (buffer-string) "#### test ####"))
1754 (call-interactively 'markdown-demote)
1755 (should (string-equal (buffer-string) "##### test #####"))
1756 (call-interactively 'markdown-demote)
1757 (should (string-equal (buffer-string) "###### test ######"))
1758 (call-interactively 'markdown-demote)
1759 (should (string-equal (buffer-string) "###### test ######"))))
1761 (ert-deftest test-markdown-cycle/hr ()
1762 "Test cycling of horizontal rules."
1763 ;; Cycle using markdown-demote
1764 (markdown-test-string (car markdown-hr-strings)
1765 (dolist (n (number-sequence 1 5))
1766 (call-interactively 'markdown-demote)
1767 (should (string-equal (buffer-string) (nth n markdown-hr-strings))))
1768 (call-interactively 'markdown-demote)
1769 (should (string-equal (buffer-string) (car markdown-hr-strings))))
1770 ;; Cycle using markdown-promote
1771 (markdown-test-string (car (reverse markdown-hr-strings))
1772 (dolist (n (number-sequence 4 0 -1))
1773 (call-interactively 'markdown-promote)
1774 (should (string-equal (buffer-string) (nth n markdown-hr-strings))))
1775 (call-interactively 'markdown-promote)
1776 (should (string-equal (buffer-string) (car (reverse markdown-hr-strings))))))
1778 (ert-deftest test-markdown-cycle/bold ()
1779 "Test cycling of bold markup."
1780 (markdown-test-string "**bold**"
1781 (call-interactively 'markdown-demote)
1782 (should (string-equal (buffer-string) "__bold__"))
1783 (call-interactively 'markdown-demote)
1784 (should (string-equal (buffer-string) "**bold**"))))
1786 (ert-deftest test-markdown-cycle/italic ()
1787 "Test cycling of italic markup."
1788 (markdown-test-string "*italic*"
1789 (call-interactively 'markdown-demote)
1790 (should (string-equal (buffer-string) "_italic_"))
1791 (call-interactively 'markdown-demote)
1792 (should (string-equal (buffer-string) "*italic*"))))
1794 ;;; Indentation tests:
1796 (ert-deftest test-markdown-indentation/calc-indents ()
1797 "Test `markdown-calc-indents' a nested list context."
1798 (markdown-test-file "nested-list.text"
1799 (goto-char (point-max))
1800 (let ((indents (markdown-calc-indents)))
1801 (should (= (car indents) 17)) ; indentation of previous line first
1802 (should (equal (sort indents '<)
1803 (list
1804 0 ; beginning of line
1805 3 ; first-level list marker
1806 7 ; second-level list marker
1807 11 ; third-level list marker
1808 13 ; previous list item text
1809 16 ; pre-block indentation
1810 17 ; indentation of previous line
1811 21 ; previous line plus tab-width
1812 ))))))
1814 (ert-deftest test-markdown-indentation/indent-region ()
1815 "Test `markdown-indent-region'."
1816 ;; Basic test with multiple lines
1817 (markdown-test-string "abc\ndef\nghi\n"
1818 (markdown-indent-region (point-min) (point-max) nil)
1819 (should (string-equal (buffer-string) " abc\n def\n ghi\n")))
1820 ;; Following a list item
1821 (markdown-test-string " * abc\ndef\n"
1822 (forward-line)
1823 (markdown-indent-region (line-beginning-position) (line-end-position) nil)
1824 (should (string-equal (buffer-string) " * abc\n def\n"))
1825 (markdown-indent-region (line-beginning-position) (line-end-position) nil)
1826 (should (string-equal (buffer-string) " * abc\n def\n"))))
1828 (ert-deftest test-markdown-indentation/indent-list-hanging ()
1829 "Test `markdown-indent-line' with hanging list item."
1830 (markdown-test-string
1831 "- list
1832 - nested list with long lines which need to be
1833 hard wrapped"
1834 (goto-char (point-max))
1835 (markdown-enter-key)
1836 (should (eq (point) 78))))
1838 (ert-deftest test-markdown-indentation/indent-list-single ()
1839 "Test `markdown-indent-line' with single list item."
1840 (let ((markdown-indent-on-enter 'indent-and-new-item))
1841 (markdown-test-string " * item 1"
1842 (end-of-line)
1843 (call-interactively #'markdown-enter-key)
1844 (should (string-equal (buffer-string) " * item 1\n * "))
1845 (should (eq (point) 16))
1846 (call-interactively #'markdown-enter-key)
1847 (should (string-equal (buffer-string) " * item 1\n\n"))
1848 (should (eq (point) 13)))))
1850 (ert-deftest test-markdown-indentation/indent-nested-list ()
1851 "Test `markdown-enter-key' with a nested list item."
1852 (let ((markdown-indent-on-enter 'indent-and-new-item))
1853 (markdown-test-string "* foo\n* bar\n * baz"
1854 (goto-char (point-max))
1855 (call-interactively #'markdown-enter-key)
1856 (should (string-equal (buffer-string) "* foo\n* bar\n * baz\n * "))
1857 (should (eq (point) 25))
1858 (call-interactively #'markdown-enter-key)
1859 (should (string-equal (buffer-string) "* foo\n* bar\n * baz\n\n"))
1860 (should (eq (point) 22)))))
1862 (ert-deftest test-markdown-indentation/indent-pre ()
1863 "Test `markdown-indent-line' with a pre block."
1864 (markdown-test-string
1865 "I'm gonna write a code block:
1867 my first line of code"
1868 (goto-char (point-max))
1869 (markdown-enter-key)
1870 (should (eq (point) 62))
1871 (should (looking-back "^ "))))
1873 (ert-deftest test-markdown-indentation/indent-hanging-line ()
1874 "Test `markdown-indent-line' with hanging indentation.
1875 See GH-245."
1876 (markdown-test-string "Stuff
1877 More"
1878 (forward-line)
1879 (should (looking-at "^ More"))
1880 (should (= (current-column) 0))
1881 (should (= (current-indentation) 2))
1882 (let ((last-command this-command)
1883 (this-command 'markdown-cycle))
1884 (call-interactively #'markdown-cycle))
1885 (should (= (current-column) 0))
1886 (should (= (current-indentation) 0))))
1888 (ert-deftest test-markdown-indentation/continue-gfm-task-lists ()
1889 (markdown-test-string " - [X] item"
1890 (end-of-line)
1891 (let ((markdown-indent-on-enter 'indent-and-new-item))
1892 (call-interactively #'markdown-enter-key))
1893 (should (string-equal (buffer-string) " - [X] item\n - [ ] "))
1894 (should (= (point) 28))))
1896 ;;; Markup hiding tests:
1898 (ert-deftest test-markdown-markup-hiding/italics-1 ()
1899 "Test hiding markup for italics."
1900 (markdown-test-file "inline.text"
1901 (goto-char 9)
1902 (should (looking-at "\*italic\*"))
1903 (markdown-test-range-has-property (point) (point) 'invisible 'markdown-markup)
1904 (should-not (invisible-p (point)))
1905 (should-not (invisible-p (+ 1 (point))))
1906 (markdown-toggle-markup-hiding t)
1907 (should (invisible-p (point)))
1908 (should-not (invisible-p (+ 1 (point))))))
1910 (ert-deftest test-markdown-markup-hiding/bold-1 ()
1911 "Test hiding markup for bold."
1912 (markdown-test-file "inline.text"
1913 (goto-char 27)
1914 (should (looking-at "\*\*bold\*\*"))
1915 (markdown-test-range-has-property (point) (1+ (point)) 'invisible 'markdown-markup)
1916 (should-not (invisible-p (point)))
1917 (should-not (invisible-p (+ 1 (point))))
1918 (should-not (invisible-p (+ 2 (point))))
1919 (markdown-toggle-markup-hiding t)
1920 (should (invisible-p (point)))
1921 (should (invisible-p (+ 1 (point))))
1922 (should-not (invisible-p (+ 2 (point))))))
1924 (ert-deftest test-markdown-markup-hiding/code-1 ()
1925 "Test hiding markup for inline code."
1926 (markdown-test-file "inline.text"
1927 (goto-char 45)
1928 (should (looking-at "`code`"))
1929 (markdown-test-range-has-property (point) (point) 'invisible 'markdown-markup)
1930 (should-not (invisible-p (point)))
1931 (should-not (invisible-p (1+ (point))))
1932 (markdown-toggle-markup-hiding t)
1933 (should (invisible-p (point)))
1934 (should-not (invisible-p (1+ (point))))))
1936 (ert-deftest test-markdown-markup-hiding/kbd-1 ()
1937 "Test hiding markup for <kbd> tags."
1938 (markdown-test-string "<kbd>C-c C-x C-m</kbd>"
1939 (markdown-test-range-has-property (point) (+ 4 (point)) 'invisible 'markdown-markup)
1940 (should-not (invisible-p (point))) ;; part of <kbd>
1941 (should-not (invisible-p (+ 4 (point)))) ;; part of <kbd>
1942 (should-not (invisible-p (+ 5 (point)))) ;; inside <kbd>
1943 (markdown-toggle-markup-hiding t)
1944 (should (invisible-p (point))) ;; part of <kbd>
1945 (should (invisible-p (+ 4 (point)))) ;; part of <kbd>
1946 (should-not (invisible-p (+ 5 (point)))))) ;; inside <kbd>
1948 (ert-deftest test-markdown-markup-hiding/inline-links ()
1949 "Test hiding markup for inline links."
1950 (markdown-test-file "inline.text"
1951 (goto-char 925)
1952 (should (looking-at "\\[text\\](http://www.w3.org/ \"title\")"))
1953 (markdown-test-range-has-property 925 925 'invisible 'markdown-markup) ; [
1954 (markdown-test-range-has-property 930 958 'invisible 'markdown-markup) ; ](...)
1955 (should-not (invisible-p 925))
1956 (should-not (invisible-p 958))
1957 (markdown-toggle-markup-hiding t)
1958 (should (invisible-p 925))
1959 (should-not (invisible-p 926))
1960 (should (invisible-p 958))))
1962 (ert-deftest test-markdown-markup-hiding/reference-links ()
1963 "Test hiding markup for reference links."
1964 (markdown-test-string "[text][ref]"
1965 (markdown-test-range-has-property 1 1 'invisible 'markdown-markup) ; [
1966 (markdown-test-range-has-property 6 11 'invisible 'markdown-markup) ; ][ref]
1967 (should-not (invisible-p 1))
1968 (should-not (invisible-p 6))
1969 (markdown-toggle-markup-hiding t)
1970 (should (invisible-p 1))
1971 (should-not (invisible-p 2))
1972 (should (invisible-p 6))))
1974 (ert-deftest test-markdown-markup-hiding/angle-urls ()
1975 "Test hiding markup for angle urls."
1976 (markdown-test-string "<http://jblevins.org/projects/markdown-mode/>"
1977 (markdown-test-range-has-property 1 1 'invisible 'markdown-markup) ; <
1978 (markdown-test-range-has-property 45 45 'invisible 'markdown-markup) ; >
1979 (should-not (invisible-p 1))
1980 (should-not (invisible-p 2))
1981 (should-not (invisible-p 45))
1982 (markdown-toggle-markup-hiding t)
1983 (should (invisible-p 1))
1984 (should-not (invisible-p 2))
1985 (should (invisible-p 45))))
1987 (ert-deftest test-markdown-markup-hiding/list-items ()
1988 "Test hiding markup for list items."
1989 (let ((markdown-hide-markup t))
1990 (markdown-test-file "nested-list.text"
1991 (markdown-test-range-has-property 4 4 'display (nth 0 markdown-list-item-bullets))
1992 (markdown-test-range-has-property 194 194 'display (nth 0 markdown-list-item-bullets))
1993 (markdown-test-range-has-property 224 224 'display (nth 1 markdown-list-item-bullets))
1994 (markdown-test-range-has-property 525 525 'display (nth 2 markdown-list-item-bullets)))))
1996 (ert-deftest test-markdown-markup-hiding/gfm-code-blocks ()
1997 "Test hiding markup for GFM code blocks."
1998 (let ((markdown-hide-markup t))
1999 (markdown-test-file "GFM.md"
2000 (markdown-test-range-has-property 1548 1552 'invisible 'markdown-markup)
2001 (should (invisible-p 1548))
2002 (should (invisible-p 1552))
2003 (markdown-test-range-has-property 1607 1609 'invisible 'markdown-markup)
2004 (should (invisible-p 1607))
2005 (should (invisible-p 1609)))))
2007 (ert-deftest test-markdown-markup-hiding/fenced-code-blocks ()
2008 "Test hiding markup for tilde fenced code blocks."
2009 (let ((markdown-hide-markup t))
2010 (markdown-test-file "outline-code.text"
2011 (markdown-test-range-has-property 83 93 'invisible 'markdown-markup)
2012 (should (invisible-p 83))
2013 (should (invisible-p 93))
2014 (markdown-test-range-has-property 154 156 'invisible 'markdown-markup)
2015 (should (invisible-p 154))
2016 (should (invisible-p 156)))))
2018 ;;; Font lock tests:
2020 (ert-deftest test-markdown-font-lock/italics-1 ()
2021 "A simple italics test."
2022 (markdown-test-file "inline.text"
2023 (goto-char 9)
2024 (should (looking-at "\*"))
2025 ;; Check face of char before leading asterisk
2026 (markdown-test-range-has-face 8 8 nil)
2027 ;; Check face of italic range
2028 (markdown-test-range-has-face 9 9 markdown-markup-face)
2029 (markdown-test-range-has-face 10 16 markdown-italic-face)
2030 (markdown-test-range-has-face 17 17 markdown-markup-face)
2031 ;; Check face of point past leading asterisk
2032 (markdown-test-range-has-face 18 18 nil)))
2034 (ert-deftest test-markdown-font-lock/italics-2 ()
2035 "Test space after leading asterisk or underscore."
2036 (markdown-test-string
2037 "This is * not italic*, nor _ is this_."
2038 (markdown-test-range-has-face (point-min) (point-max) nil)))
2040 (ert-deftest test-markdown-font-lock/italics-3 ()
2041 "Test that slash inside asterisks is not italic."
2042 (markdown-test-string
2043 "not italic *\\*"
2044 (markdown-test-range-has-face (point-min) (point-max) nil)))
2046 (ert-deftest test-markdown-font-lock/italics-4 ()
2047 "Test escaped asterisk inside italics."
2048 (markdown-test-string
2049 "italic *\\**"
2050 (markdown-test-range-has-face 1 7 nil)
2051 (markdown-test-range-has-face 8 8 markdown-markup-face)
2052 (markdown-test-range-has-face 9 10 markdown-italic-face)
2053 (markdown-test-range-has-face 11 11 markdown-markup-face)))
2055 (ert-deftest test-markdown-font-lock/italics-5 ()
2056 "Test italic single letter."
2057 (markdown-test-string
2058 "*a*"
2059 (markdown-test-range-has-face 1 1 markdown-markup-face)
2060 (markdown-test-range-has-face 2 2 markdown-italic-face)
2061 (markdown-test-range-has-face 3 3 markdown-markup-face)))
2063 (ert-deftest test-markdown-font-lock/italics-6 ()
2064 "Test multiline italics across list items."
2065 (markdown-test-string
2066 "* something about function foo_bar
2067 * something else about foo_bar"
2068 (markdown-test-range-has-face 31 34 nil)
2069 (markdown-test-range-has-face 38 62 nil)))
2071 (ert-deftest test-markdown-font-lock/italics-8 ()
2072 "Test multiline italics across list items."
2073 (markdown-test-string
2074 "* something about function
2075 foo_bar
2076 * something else about
2077 foo_bar"
2078 (markdown-test-range-has-face 30 36 nil)
2079 (markdown-test-range-has-face 63 69 nil)))
2081 (ert-deftest test-markdown-font-lock/italics-9 ()
2082 "Test multiline italics across list items."
2083 (markdown-test-string
2084 "foo_bar
2085 * foo_bar"
2086 (markdown-test-range-has-face 4 7 nil)
2087 (markdown-test-range-has-face 11 14 nil)))
2089 (ert-deftest test-markdown-font-lock/italics-10 ()
2090 "Underscores in URLs should not trigger italics."
2091 (markdown-test-string
2092 "<http://jblevins.org/research/centroid/cd_z_path.m>"
2093 (markdown-test-range-face-equals 2 50 'markdown-plain-url-face)
2094 (should-not (markdown-range-property-any 43 43 'face '(markdown-italic-face)))))
2096 (ert-deftest test-markdown-font-lock/italics-11 ()
2097 "Underscores in URLs should not trigger italics."
2098 (markdown-test-string
2099 "[1]: http://jblevins.org/research/centroid/cd_z_path.m"
2100 (markdown-test-range-face-equals 6 54 markdown-url-face)))
2102 (ert-deftest test-markdown-font-lock/italics-12 ()
2103 "Underscores in URLs should not trigger italics."
2104 (markdown-test-string
2105 "[cd\\_z\\_path.m](http://jblevins.org/research/centroid/cd_z_path.m)"
2106 (markdown-test-range-face-equals 17 65 markdown-url-face)))
2108 (ert-deftest test-markdown-font-lock/italics-after-hr ()
2109 "Test italics after a horizontal rule with asterisks."
2110 (markdown-test-string "* * *\n\n*italic*\n"
2111 (markdown-test-range-has-face 1 5 'markdown-hr-face)
2112 (markdown-test-range-has-face 8 8 markdown-markup-face)
2113 (markdown-test-range-has-face 9 14 markdown-italic-face)
2114 (markdown-test-range-has-face 15 15 markdown-markup-face)))
2116 (ert-deftest test-markdown-font-lock/italics-in-heading ()
2117 "Test italic overlay in a heading."
2118 (markdown-test-string
2119 "# *Italics* in a Heading"
2120 (markdown-test-range-has-face 3 3 markdown-markup-face)
2121 (markdown-test-range-has-face 4 10 markdown-italic-face)
2122 (markdown-test-range-has-face 11 11 markdown-markup-face)))
2124 (ert-deftest test-markdown-font-lock/italics-link ()
2125 "Test italic overlay in an inline link."
2126 (markdown-test-string
2127 "*[italic link](http://www.link.com/)*"
2128 (markdown-test-range-has-face 1 1 markdown-markup-face)
2129 (markdown-test-range-has-face 2 36 markdown-italic-face)
2130 (markdown-test-range-has-face 37 37 markdown-markup-face))
2131 (markdown-test-string
2132 "[*italic link*](http://www.link.com/)"
2133 (markdown-test-range-has-face 2 2 markdown-markup-face)
2134 (markdown-test-range-has-face 3 13 markdown-italic-face)
2135 (markdown-test-range-has-face 14 14 markdown-markup-face)))
2137 (ert-deftest test-markdown-font-lock/italics-in-blockquote ()
2138 "Test italics overlay in a blockquote."
2139 (markdown-test-string
2140 "> *italics* inside a blockquote"
2141 (markdown-test-range-has-face 3 3 markdown-markup-face)
2142 (markdown-test-range-has-face 4 10 markdown-italic-face)
2143 (markdown-test-range-has-face 11 11 markdown-markup-face)))
2145 (ert-deftest test-markdown-font-lock/italics-in-pre ()
2146 "Test italics overlay in a blockquote."
2147 (markdown-test-string
2148 " *italics* inside a pre block"
2149 (markdown-test-range-has-face (point-min) (1- (point-max))
2150 markdown-pre-face)))
2152 (ert-deftest test-markdown-font-lock/italics-and-code ()
2153 "Test seeming italics mixed with code."
2154 (markdown-test-string
2155 "define `var_1` and `var_2` inline code"
2156 (markdown-test-range-has-face 9 13 markdown-inline-code-face)
2157 (markdown-test-range-has-face 21 25 markdown-inline-code-face))
2158 (markdown-test-string
2159 "`var_1` and var_2"
2160 (markdown-test-range-has-face 2 6 markdown-inline-code-face)
2161 (markdown-test-range-has-face 8 17 nil))
2162 (markdown-test-string
2163 "var_1 and `var_2`"
2164 (markdown-test-range-has-face 1 10 nil)
2165 (markdown-test-range-has-face 12 16 markdown-inline-code-face)))
2167 (ert-deftest test-markdown-font-lock/code-in-italics ()
2168 "Test inline code inside italics.
2169 See GH-275."
2170 (markdown-test-string
2171 "*text `code` text*"
2172 (markdown-test-range-has-face 1 1 markdown-markup-face)
2173 (markdown-test-range-has-face 2 17 markdown-italic-face)
2174 (markdown-test-range-has-face 7 7 markdown-markup-face)
2175 (markdown-test-range-has-face 8 11 markdown-inline-code-face)
2176 (markdown-test-range-has-face 12 12 markdown-markup-face)
2177 (markdown-test-range-has-face 18 18 markdown-markup-face)))
2179 (ert-deftest test-markdown-font-lock/italics-in-reference-definitions ()
2180 "Test not matching italics in reference definitions across lines."
2181 (markdown-test-string
2182 "[lg]: twilight_sm.png\n[sm]: twilight_lg.png"
2183 (markdown-test-range-has-face 7 21 markdown-url-face)
2184 (markdown-test-range-has-face 22 22 nil)
2185 (markdown-test-range-has-face 29 43 markdown-url-face)
2186 (markdown-test-range-has-face 28 28 nil)))
2188 (ert-deftest test-markdown-font-lock/italics-in-comment ()
2189 "Test not matching italics in comments."
2190 (markdown-test-string
2191 "<!-- -*- coding: utf-8 -*- -->"
2192 (markdown-test-range-has-face 1 30 'markdown-comment-face)
2193 (should-not (markdown-range-property-any 1 30 'face '(markdown-italic-face)))))
2195 (ert-deftest test-markdown-font-lock/italics-after-bold ()
2196 "Test bold and italics on the same line.
2197 See GH-223."
2198 (markdown-test-string
2199 "**foo** is a *bar*"
2200 (markdown-test-range-has-face 1 2 'markdown-markup-face)
2201 (markdown-test-range-has-face 3 5 'markdown-bold-face)
2202 (markdown-test-range-has-face 6 7 'markdown-markup-face)
2203 (should-not
2204 (markdown-range-property-any 8 13 'face '(markdown-italic-face)))
2205 (markdown-test-range-has-face 14 14 'markdown-markup-face)
2206 (markdown-test-range-has-face 15 17 'markdown-italic-face)
2207 (markdown-test-range-has-face 18 18 'markdown-markup-face)))
2209 (ert-deftest test-markdown-font-lock/bold-1 ()
2210 "A simple bold test."
2211 (markdown-test-file "inline.text"
2212 (goto-char 27)
2213 (should (looking-at "\*\*"))
2214 ;; Check face of char before leading asterisk
2215 (markdown-test-range-has-face 26 26 nil)
2216 ;; Check face of opening asterisks
2217 (markdown-test-range-has-face 27 28 markdown-markup-face)
2218 ;; Check face of bold range
2219 (markdown-test-range-has-face 29 33 markdown-bold-face)
2220 ;; Check face of closing asterisks
2221 (markdown-test-range-has-face 34 35 markdown-markup-face)
2222 ;; Check face of point past leading asterisk
2223 (markdown-test-range-has-face 36 36 nil)))
2225 (ert-deftest test-markdown-font-lock/bold-2 ()
2226 "Test space after leading asterisks or underscores."
2227 (markdown-test-string
2228 "This is ** not bold**, nor __ is this__."
2229 (should-not
2230 (markdown-range-property-any
2231 (point-min) (point-max) 'face '(markdown-bold-face)))))
2233 (ert-deftest test-markdown-font-lock/bold-3 ()
2234 "Test escaped asterisk inside bold."
2235 (markdown-test-string
2236 "bold **\\***"
2237 (markdown-test-range-has-face 1 5 nil)
2238 (markdown-test-range-has-face 6 7 markdown-markup-face)
2239 (markdown-test-range-has-face 8 9 markdown-bold-face)
2240 (markdown-test-range-has-face 10 11 markdown-markup-face)))
2242 (ert-deftest test-markdown-font-lock/bold-4 ()
2243 "Test bold single letter."
2244 (markdown-test-string
2245 "**a**"
2246 (markdown-test-range-has-face 1 2 markdown-markup-face)
2247 (markdown-test-range-has-face 3 3 markdown-bold-face)
2248 (markdown-test-range-has-face 4 5 markdown-markup-face)))
2250 (ert-deftest test-markdown-font-lock/bold-after-hr ()
2251 "Test bold after a horizontal rule with asterisks."
2252 (markdown-test-string "* * *\n\n**bold**\n"
2253 (markdown-test-range-has-face 1 5 'markdown-hr-face)
2254 (markdown-test-range-has-face 8 9 markdown-markup-face)
2255 (markdown-test-range-has-face 10 13 markdown-bold-face)
2256 (markdown-test-range-has-face 14 15 markdown-markup-face)))
2258 (ert-deftest test-markdown-font-lock/bold-link ()
2259 "Test bold overlay in an inline link."
2260 (markdown-test-string
2261 "**[bold link](http://www.link.com/)**"
2262 (markdown-test-range-has-face 1 2 markdown-markup-face)
2263 (markdown-test-range-has-face 3 35 markdown-bold-face)
2264 (markdown-test-range-has-face 36 37 markdown-markup-face))
2265 (markdown-test-string
2266 "[**bold link**](http://www.link.com/)"
2267 (markdown-test-range-has-face 2 3 markdown-markup-face)
2268 (markdown-test-range-has-face 4 12 markdown-bold-face)
2269 (markdown-test-range-has-face 13 14 markdown-markup-face)))
2271 (ert-deftest test-markdown-font-lock/bold-in-blockquote ()
2272 "Test bold overlay in a blockquote."
2273 (markdown-test-string
2274 "> **bold** inside a blockquote"
2275 (markdown-test-range-has-face 3 4 markdown-markup-face)
2276 (markdown-test-range-has-face 5 8 markdown-bold-face)
2277 (markdown-test-range-has-face 9 10 markdown-markup-face)))
2279 (ert-deftest test-markdown-font-lock/bold-in-pre ()
2280 "Test bold overlay in a blockquote."
2281 (markdown-test-string
2282 " **bold** inside a pre block"
2283 (markdown-test-range-has-face (point-min) (1- (point-max))
2284 markdown-pre-face)))
2286 (ert-deftest test-markdown-font-lock/no-bold-in-code ()
2287 "Bold markers in inline code should not trigger bold."
2288 (markdown-test-string
2289 "`def __init__(self):`"
2290 (markdown-test-range-has-face 8 11 'markdown-inline-code-face)
2291 (should-not (markdown-range-property-any
2292 (point-min) (point-max) 'face '(markdown-bold-face))))
2293 (markdown-test-string
2294 "`**foo` bar `baz**`"
2295 (markdown-test-range-has-face 2 6 'markdown-inline-code-face)
2296 (markdown-test-range-face-equals 9 11 nil)
2297 (markdown-test-range-has-face 14 18 'markdown-inline-code-face)
2298 (should-not (markdown-range-property-any
2299 (point-min) (point-max) 'face '(markdown-bold-face)))))
2301 (ert-deftest test-markdown-font-lock/code-in-bold ()
2302 "Test inline code inside bold."
2303 (markdown-test-string
2304 "**text `code` text**"
2305 (markdown-test-range-has-face 1 2 markdown-markup-face)
2306 (markdown-test-range-has-face 3 18 markdown-bold-face)
2307 (markdown-test-range-has-face 8 8 markdown-markup-face)
2308 (markdown-test-range-has-face 9 12 markdown-inline-code-face)
2309 (markdown-test-range-has-face 13 13 markdown-markup-face)
2310 (markdown-test-range-has-face 19 20 markdown-markup-face)))
2312 (ert-deftest test-markdown-font-lock/bold-in-comment ()
2313 "Test not matching bold in comments."
2314 (markdown-test-string
2315 "<!-- **not bold** -->"
2316 (markdown-test-range-has-face 1 21 'markdown-comment-face)
2317 (should-not
2318 (markdown-range-property-any 1 21 'face '(markdown-bold-face)))))
2320 (ert-deftest test-markdown-font-lock/no-bold-in-url ()
2321 "Test not matching bold in plain URL links."
2322 (markdown-test-string
2323 "<https://example.com/__not-bold__>"
2324 (should-not (markdown-range-property-any 23 30 'face '(markdown-bold-face)))))
2326 (ert-deftest test-markdown-font-lock/code-1 ()
2327 "A simple inline code test."
2328 (markdown-test-file "inline.text"
2329 (goto-char 45)
2330 (should (looking-at "`"))
2331 ;; Regular code span
2332 (markdown-test-range-has-face 45 45 markdown-markup-face)
2333 (markdown-test-range-has-face 46 49 markdown-inline-code-face)
2334 (markdown-test-range-has-face 50 50 markdown-markup-face)
2335 ;; Code containing backticks
2336 (markdown-test-range-has-face 61 62 markdown-markup-face)
2337 (markdown-test-range-has-face 63 87 markdown-inline-code-face)
2338 (markdown-test-range-has-face 88 89 markdown-markup-face)
2339 ;; Seven backquotes in a row
2340 (markdown-test-range-has-face 119 125 nil)
2341 ;; Backquotes at beginning or end
2342 (markdown-test-range-has-face 228 229 markdown-markup-face)
2343 (markdown-test-range-has-face 230 237 markdown-inline-code-face)
2344 (markdown-test-range-has-face 238 239 markdown-markup-face)
2345 (markdown-test-range-has-face 341 342 markdown-markup-face)
2346 (markdown-test-range-has-face 343 349 markdown-inline-code-face)
2347 (markdown-test-range-has-face 350 351 markdown-markup-face)
2348 ;; Backslash as final character
2349 (markdown-test-range-has-face 460 460 markdown-markup-face)
2350 (markdown-test-range-has-face 461 467 markdown-inline-code-face)
2351 (markdown-test-range-has-face 468 468 markdown-markup-face)
2352 ;; Escaping of leading backquotes
2353 (markdown-test-range-has-face 586 592 nil)
2354 (markdown-test-range-has-face 597 603 nil)
2355 ;; A code span crossing lines
2356 (markdown-test-range-has-face 652 656 nil)
2357 (markdown-test-range-has-face 657 657 markdown-markup-face)
2358 (markdown-test-range-has-face 658 665 markdown-inline-code-face)
2359 (markdown-test-range-has-face 666 666 markdown-markup-face)
2360 ;; Three backquotes: same line, across lines, not across blocks
2361 (markdown-test-range-has-face 695 748 nil)
2362 (markdown-test-range-has-face 749 750 markdown-markup-face)
2363 (markdown-test-range-has-face 751 755 markdown-inline-code-face)
2364 (markdown-test-range-has-face 756 757 markdown-markup-face)
2365 (markdown-test-range-has-face 758 805 nil)
2366 (markdown-test-range-has-face 806 807 markdown-markup-face)
2367 (markdown-test-range-has-face 808 812 markdown-inline-code-face)
2368 (markdown-test-range-has-face 813 814 markdown-markup-face)
2369 (markdown-test-range-has-face 815 891 nil)
2372 (ert-deftest test-markdown-font-lock/code-2 ()
2373 "Multiple code spans in a row and on different lines."
2374 (markdown-test-string "`foo` `bar` `baz`"
2375 (markdown-test-range-has-face 1 1 markdown-markup-face)
2376 (markdown-test-range-has-face 2 4 markdown-inline-code-face)
2377 (markdown-test-range-has-face 5 5 markdown-markup-face)
2378 (markdown-test-range-has-face 6 6 nil)
2379 (markdown-test-range-has-face 7 7 markdown-markup-face)
2380 (markdown-test-range-has-face 8 10 markdown-inline-code-face)
2381 (markdown-test-range-has-face 11 11 markdown-markup-face)
2382 (markdown-test-range-has-face 12 12 nil)
2383 (markdown-test-range-has-face 13 13 markdown-markup-face)
2384 (markdown-test-range-has-face 14 16 markdown-inline-code-face)
2385 (markdown-test-range-has-face 17 17 markdown-markup-face))
2386 (markdown-test-string "`a`\n`b`\n`c`\n"
2387 (markdown-test-range-has-face 1 1 markdown-markup-face)
2388 (markdown-test-range-has-face 2 2 markdown-inline-code-face)
2389 (markdown-test-range-has-face 3 3 markdown-markup-face)
2390 (markdown-test-range-has-face 4 4 nil)
2391 (markdown-test-range-has-face 5 5 markdown-markup-face)
2392 (markdown-test-range-has-face 6 6 markdown-inline-code-face)
2393 (markdown-test-range-has-face 7 7 markdown-markup-face)
2394 (markdown-test-range-has-face 8 8 nil)
2395 (markdown-test-range-has-face 9 9 markdown-markup-face)
2396 (markdown-test-range-has-face 10 10 markdown-inline-code-face)
2397 (markdown-test-range-has-face 11 11 markdown-markup-face)
2398 (markdown-test-range-has-face 12 12 nil))
2399 (markdown-test-string "a`foo`b`bar`c`baz`d"
2400 (markdown-test-range-has-face 1 1 nil)
2401 (markdown-test-range-has-face 2 2 markdown-markup-face)
2402 (markdown-test-range-has-face 3 5 markdown-inline-code-face)
2403 (markdown-test-range-has-face 6 6 markdown-markup-face)
2404 (markdown-test-range-has-face 7 7 nil)
2405 (markdown-test-range-has-face 8 8 markdown-markup-face)
2406 (markdown-test-range-has-face 9 11 markdown-inline-code-face)
2407 (markdown-test-range-has-face 12 12 markdown-markup-face)
2408 (markdown-test-range-has-face 13 13 nil)
2409 (markdown-test-range-has-face 14 14 markdown-markup-face)
2410 (markdown-test-range-has-face 15 17 markdown-inline-code-face)
2411 (markdown-test-range-has-face 18 18 markdown-markup-face)
2412 (markdown-test-range-has-face 19 19 nil)))
2414 (ert-deftest test-markdown-font-lock/code-3 ()
2415 "Backslashes don't escape backticks inside of inline code strings."
2416 (markdown-test-string
2417 "`foo\\`bar`"
2418 (markdown-test-range-has-face 1 1 markdown-markup-face)
2419 (markdown-test-range-has-face 2 5 markdown-inline-code-face)
2420 (markdown-test-range-has-face 6 6 markdown-markup-face)
2421 (markdown-test-range-has-face 7 10 nil)))
2423 (ert-deftest test-markdown-font-lock/code-link-precedence ()
2424 "Test that inline code takes precedence over inline links.
2425 Test currently fails because this case isn't handled properly."
2426 :expected-result :failed
2427 (markdown-test-string
2428 "[not a `link](/foo`)"
2429 (markdown-test-range-has-face 1 7 nil)
2430 (markdown-test-range-has-face 8 8 markdown-markup-face)
2431 (markdown-test-range-has-face 9 18 markdown-inline-code-face)
2432 (markdown-test-range-has-face 19 19 markdown-markup-face)
2433 (markdown-test-range-has-face 20 20 nil)))
2435 (ert-deftest test-markdown-font-lock/code-in-comment ()
2436 "Test that inline code is not matched inside a comment."
2437 (markdown-test-string
2438 "<!-- `not code` -->"
2439 (markdown-test-range-has-face 1 19 'markdown-comment-face)
2440 (should-not (markdown-range-property-any 1 19 'face '(markdown-inline-code-face)))))
2442 (ert-deftest test-markdown-font-lock/kbd ()
2443 "Test font lock for <kbd> tags."
2444 (markdown-test-string "<kbd>C-c <</kbd>"
2445 (markdown-test-range-has-face 1 5 markdown-markup-face)
2446 (markdown-test-range-has-face 6 10 markdown-inline-code-face)
2447 (markdown-test-range-has-face 11 16 markdown-markup-face))
2448 (markdown-test-string "To quit Emacs, press <kbd>C-x C-c</kbd>."
2449 (markdown-test-range-has-face 1 21 nil)
2450 (markdown-test-range-has-face 22 26 markdown-markup-face)
2451 (markdown-test-range-has-face 27 33 markdown-inline-code-face)
2452 (markdown-test-range-has-face 34 39 markdown-markup-face)
2453 (markdown-test-range-has-face 40 40 nil)))
2455 (ert-deftest test-markdown-font-lock/lists-1 ()
2456 "A simple list marker font lock test."
2457 (markdown-test-file "lists.text"
2458 (dolist (loc (list 1063 1283 1659 1830 1919 2150 2393 2484
2459 2762 2853 3097 3188 3700 3903 4009))
2460 (goto-char loc)
2461 (should (looking-at "[*+-]"))
2462 (markdown-test-range-has-face loc loc markdown-list-face))))
2464 (ert-deftest test-markdown-font-lock/definition-list ()
2465 "A simple definition list marker font lock test."
2466 (markdown-test-file "definition-list.text"
2467 (markdown-test-range-has-face 7 7 'markdown-list-face)
2468 (markdown-test-range-has-face 29 52 'markdown-pre-face)
2469 (markdown-test-range-has-face 55 55 'markdown-list-face)))
2471 (ert-deftest test-markdown-font-lock/pre-1 ()
2472 "Nested list and pre block font lock test."
2473 (markdown-test-file "nested-list.text"
2474 (dolist (loc (list 4 29 194 224 491 525))
2475 (markdown-test-range-has-face loc loc markdown-list-face))
2476 (markdown-test-range-has-face 6 25 nil)
2477 (markdown-test-range-has-face 31 83 nil)
2478 (markdown-test-range-has-face 85 154 markdown-pre-face)
2479 (markdown-test-range-has-face 157 189 nil)
2480 (markdown-test-range-has-face 196 215 nil)
2481 (markdown-test-range-has-face 226 403 nil)
2482 (markdown-test-range-has-face 405 481 markdown-pre-face)
2483 (markdown-test-range-has-face 493 512 nil)
2484 (markdown-test-range-has-face 527 546 nil)
2485 (markdown-test-range-has-face 548 580 markdown-pre-face)))
2487 (ert-deftest test-markdown-font-lock/pre-2 ()
2488 (markdown-test-string "* item\n\nreset baseline\n\n pre block\n"
2489 (markdown-test-range-has-face 1 1 markdown-list-face)
2490 (markdown-test-range-has-face 2 23 nil)
2491 (markdown-test-range-has-face 29 37 markdown-pre-face)))
2493 (ert-deftest test-markdown-font-lock/pre-3 ()
2494 (markdown-test-string "It is interesting to see what happens when one queries
2495 `social upheaval` and `protopalatial era`.
2497 * `social upheaval`: the follwing queries have been tried:
2499 social upheaval subClassOf"
2500 (markdown-test-range-has-face 160 190 nil)))
2502 (ert-deftest test-markdown-font-lock/pre-4 ()
2503 "Pre blocks must be preceded by a blank line"
2504 (markdown-test-string "Paragraph
2505 for (var i = 0; i < 10; i++) {
2506 console.log(i);
2508 (markdown-test-range-has-face (point-min) (point-max) nil)))
2510 (ert-deftest test-markdown-font-lock/fenced-1 ()
2511 "Test fenced code blocks containing four-space indents."
2512 (markdown-test-string "Fenced code block
2515 if (x)
2516 foo();
2518 if (y)
2519 bar();
2522 (markdown-test-range-has-face 1 19 nil)
2523 (markdown-test-range-has-face 20 22 markdown-markup-face)
2524 (markdown-test-range-has-face 24 60 markdown-pre-face)
2525 (markdown-test-range-has-face 61 63 markdown-markup-face)))
2527 (ert-deftest test-markdown-font-lock/gfm-fenced-1 ()
2528 "Test GFM-style fenced code blocks (1)."
2529 (let ((markdown-fontify-code-blocks-natively t))
2530 (markdown-test-string "```ruby
2531 require 'redcarpet'
2532 markdown = Redcarpet.new('Hello World!')
2533 puts markdown.to_html
2534 ```"
2535 (markdown-test-range-has-face 1 3 markdown-markup-face) ; ```
2536 (markdown-test-range-has-face 4 7 markdown-language-keyword-face) ; ruby
2537 (markdown-test-range-has-face 9 90 'markdown-code-face) ; entire code block
2538 (unless (version< emacs-version "24.4")
2539 (markdown-test-range-has-face 9 15 'font-lock-builtin-face)) ; require
2540 (markdown-test-range-has-face 17 27 'font-lock-string-face) ; 'redcarpet'
2541 (markdown-test-range-has-face 40 48 'font-lock-type-face) ; Redcarpet
2542 (unless (version< emacs-version "24.4")
2543 (markdown-test-range-has-face 70 72 'font-lock-builtin-face)) ; puts
2544 (markdown-test-range-has-face 92 94 markdown-markup-face)))) ; ```
2546 (ert-deftest test-markdown-font-lock/gfm-fenced-2 ()
2547 "Test GFM-style fenced code blocks (2)."
2548 (markdown-test-string "```{r sum}\n2+2\n```"
2549 (markdown-test-range-has-face 1 3 markdown-markup-face) ; ```
2550 (markdown-test-range-has-face 4 4 markdown-markup-face) ; {
2551 (markdown-test-range-has-face 5 5 markdown-language-keyword-face) ; r
2552 (markdown-test-range-has-face 7 9 markdown-language-info-face) ; sum
2553 (markdown-test-range-has-face 10 10 markdown-markup-face) ; }
2554 (markdown-test-range-has-face 12 14 markdown-pre-face) ; 2+2
2555 (markdown-test-range-has-face 16 18 markdown-markup-face))) ; ```
2557 (ert-deftest test-markdown-font-lock/gfm-fenced-3 ()
2558 "GFM-style code blocks need not be preceded by a blank line."
2559 (markdown-test-string "Paragraph
2560 ```js
2561 for (var i = 0; i < 10; i++) {
2562 console.log(i);
2564 ```"
2565 (markdown-test-range-has-face 1 10 nil) ; Paragraph
2566 (markdown-test-range-has-face 11 13 markdown-markup-face) ; ```
2567 (markdown-test-range-has-face 14 15 markdown-language-keyword-face) ; js
2568 (markdown-test-range-has-face 17 68 markdown-pre-face)
2569 (markdown-test-range-has-face 70 72 markdown-markup-face)))
2571 (ert-deftest test-markdown-font-lock/gfm-fenced-4 ()
2572 "Test GFM-style fenced code blocks (2)."
2573 (markdown-test-string "```scalaFiddle libraries=\"Java8 Time-0.1.0\"\nimport java.time._\n\nval hour = LocalTime.now().getHour()\n\nprintln(hour)\n```"
2574 (markdown-test-range-has-face 1 3 markdown-markup-face) ; ```
2575 (markdown-test-range-has-face 4 14 markdown-language-keyword-face) ; scalaFiddle
2576 (markdown-test-range-has-face 16 43 markdown-language-info-face) ; libraries="Java8 Time-0.1.0"
2577 (markdown-test-range-has-face 45 115 markdown-pre-face) ; [code]
2578 (markdown-test-range-has-face 117 119 markdown-markup-face))) ; ```
2580 (ert-deftest test-markdown-font-lock/tilde-fenced-1 ()
2581 "Test native fontification of tilde fenced code blocks."
2582 (let ((markdown-fontify-code-blocks-natively t))
2583 (markdown-test-string "~~~ruby
2584 require 'redcarpet'
2585 markdown = Redcarpet.new('Hello World!')
2586 puts markdown.to_html
2587 ~~~"
2588 (markdown-test-range-has-face 1 3 markdown-markup-face) ; ```
2589 (markdown-test-range-has-face 4 7 markdown-language-keyword-face) ; ruby
2590 (markdown-test-range-has-face 9 90 'markdown-code-face) ; entire code block
2591 (unless (version< emacs-version "24.4")
2592 (markdown-test-range-has-face 9 15 'font-lock-builtin-face)) ; require
2593 (markdown-test-range-has-face 17 27 'font-lock-string-face) ; 'redcarpet'
2594 (markdown-test-range-has-face 40 48 'font-lock-type-face) ; Redcarpet
2595 (unless (version< emacs-version "24.4")
2596 (markdown-test-range-has-face 70 72 'font-lock-builtin-face)) ; puts
2597 (markdown-test-range-has-face 92 94 markdown-markup-face)))) ; ```
2599 (ert-deftest test-markdown-font-lock/atx-no-spaces ()
2600 "Test font-lock for atx headers with no spaces."
2601 (markdown-test-string "##abc##"
2602 (markdown-test-range-has-face 1 7 nil))
2603 (markdown-test-string "##"
2604 (markdown-test-range-has-face 1 2 nil))
2605 (markdown-test-string "###"
2606 (markdown-test-range-has-face 1 3 nil)))
2608 (ert-deftest test-markdown-font-lock/setext-1-letter ()
2609 "An edge case for level-one setext headers."
2610 (markdown-test-string "a\n=\n"
2611 (markdown-test-range-has-face 1 1 markdown-header-face-1)
2612 (markdown-test-range-has-face 3 3 markdown-header-rule-face)))
2614 (ert-deftest test-markdown-font-lock/setext-2-letter ()
2615 "An edge case for level-two setext headers."
2616 (markdown-test-string "b\n-\n"
2617 (markdown-test-range-has-face 1 1 markdown-header-face-2)
2618 (markdown-test-range-has-face 3 3 markdown-header-rule-face)))
2620 (ert-deftest test-markdown-font-lock/inline-links ()
2621 "Test font lock for inline links."
2622 (let ((markdown-hide-urls nil))
2623 (markdown-test-file "inline.text"
2624 (markdown-test-range-has-face 925 925 markdown-markup-face)
2625 (markdown-test-range-has-face 926 929 markdown-link-face)
2626 (markdown-test-range-has-face 930 931 markdown-markup-face)
2627 (markdown-test-range-has-face 932 949 markdown-url-face)
2628 (markdown-test-range-has-face 951 957 markdown-link-title-face)
2629 (markdown-test-range-has-face 958 958 markdown-markup-face))))
2631 (ert-deftest test-markdown-font-lock/inline-links-with-parentheses ()
2632 "Test font lock for inline links with nested parentheses.
2633 See <https://github.com/jrblevin/markdown-mode/issues/170>."
2634 (let ((markdown-hide-urls nil))
2635 (markdown-test-string "[foo](bar(baz)qux)"
2636 (markdown-test-range-has-face 1 1 markdown-markup-face)
2637 (markdown-test-range-has-face 2 4 markdown-link-face)
2638 (markdown-test-range-has-face 5 6 markdown-markup-face)
2639 (markdown-test-range-has-face 7 17 markdown-url-face)
2640 (markdown-test-range-has-face 18 18 markdown-markup-face))))
2642 (ert-deftest test-markdown-font-lock/pre-comment ()
2643 "Test comments inside of a pre block."
2644 (markdown-test-string " <!-- pre, not comment -->"
2645 (markdown-test-range-has-face (point-min) (1- (point-max)) markdown-pre-face)))
2647 (ert-deftest test-markdown-font-lock/inline-code-comment ()
2648 "Test comments inside of inline code."
2649 (markdown-test-string "`<h1> <!-- HTML comment inside inline code -->`"
2650 (markdown-test-range-has-face (1+ (point-min)) (- (point-max) 2) markdown-inline-code-face)))
2652 (ert-deftest test-markdown-font-lock/inline-code-link ()
2653 "Test links inside of inline code."
2654 (markdown-test-string "`[text](url)`"
2655 (markdown-test-range-has-face (1+ (point-min)) (- (point-max) 2) 'markdown-inline-code-face)
2656 (should-not (markdown-range-property-any
2657 (1+ (point-min)) (- (point-max) 2) 'face
2658 '(markdown-markup-face markdown-link-face markdown-url-face)))))
2660 (ert-deftest test-markdown-font-lock/comment-hanging-indent ()
2661 "Test comments with hanging indentation."
2662 (markdown-test-string "<!-- This comment has\n hanging indentation -->"
2663 (markdown-test-range-has-face (point-min) (1- (point-max)) markdown-comment-face)))
2665 (ert-deftest test-markdown-font-lock/comment-multiple ()
2666 "Test multiple single-line comments in arow."
2667 (markdown-test-string "<!-- This is a comment -->\n<!-- And so is this -->"
2668 (markdown-test-range-has-face
2669 (point-at-bol) (1- (point-at-eol)) markdown-comment-face)
2670 (forward-line)
2671 (markdown-test-range-has-face
2672 (point-at-bol) (1- (point-at-eol)) markdown-comment-face)))
2674 (ert-deftest test-markdown-font-lock/comment-list-items ()
2675 "Test comment with list inside."
2676 (markdown-test-string
2677 "<!--
2678 - note 1;
2679 - note 2.
2680 -->"
2681 (markdown-test-range-face-equals (point-min) (1- (point-max))
2682 markdown-comment-face)))
2684 (ert-deftest test-markdown-font-lock/comment-angle-bracket ()
2685 "Regression test for GH-117."
2686 (markdown-test-string "<!-- > test -->"
2687 (markdown-test-range-face-equals (point-min) (1- (point-max))
2688 markdown-comment-face)))
2690 (ert-deftest test-markdown-font-lock/comment-link ()
2691 "Test links inside of comments."
2692 (markdown-test-string "<!-- [text](url) -->"
2693 (markdown-test-range-has-face (+ (point-min) 5) (- (point-max) 4) 'markdown-comment-face)
2694 (should-not (markdown-range-property-any
2695 (+ (point-min) 5) (- (point-max) 4) 'face
2696 '(markdown-markup-face markdown-link-face markdown-url-face)))))
2698 (ert-deftest test-markdown-font-lock/footnote-markers-links ()
2699 "Test an edge case involving footnote markers and inline reference links."
2700 (markdown-test-string "Harvard[^1] [tuition][]"
2701 (markdown-test-range-has-face 1 7 nil)
2702 (markdown-test-range-has-face 8 8 markdown-markup-face)
2703 (markdown-test-range-has-face 10 10 markdown-footnote-marker-face)
2704 (markdown-test-range-has-face 11 11 markdown-markup-face)
2705 (markdown-test-range-has-face 12 12 nil)
2706 (markdown-test-range-has-face 13 13 markdown-markup-face)
2707 (markdown-test-range-has-face 14 20 markdown-link-face)
2708 (markdown-test-range-has-face 21 21 markdown-markup-face)
2709 (markdown-test-range-has-face 22 23 markdown-markup-face)))
2711 (ert-deftest test-markdown-font-lock/mmd-metadata ()
2712 "Basic MultMarkdown metadata tests."
2713 (markdown-test-string "Title: peg-multimarkdown User's Guide
2714 Author: Fletcher T. Penney
2715 Base Header Level: 2"
2716 (markdown-test-range-has-face 1 5 markdown-metadata-key-face)
2717 (markdown-test-range-has-face 6 6 markdown-markup-face)
2718 (markdown-test-range-has-face 8 37 markdown-metadata-value-face)
2719 (markdown-test-range-has-face 39 44 markdown-metadata-key-face)
2720 (markdown-test-range-has-face 46 46 markdown-markup-face)
2721 (markdown-test-range-has-face 47 64 markdown-metadata-value-face)
2722 (markdown-test-range-has-face 66 82 markdown-metadata-key-face)
2723 (markdown-test-range-has-face 83 83 markdown-markup-face)
2724 (markdown-test-range-has-face 85 85 markdown-metadata-value-face))
2725 ;; Avoid triggering when a title contains a colon (e.g., Markdown: Syntax)
2726 (markdown-test-file "syntax.text"
2727 (markdown-test-range-has-face 1 16 markdown-header-face-1)))
2729 (ert-deftest test-markdown-font-lock/mmd-metadata-after-header ()
2730 "Ensure that similar lines are not matched after the header."
2731 (markdown-test-string "Title: peg-multimarkdown User's Guide
2733 Author: Fletcher T. Penney
2734 Base Header Level: 2"
2735 (markdown-test-range-has-face 1 5 markdown-metadata-key-face)
2736 (markdown-test-range-has-face 6 6 markdown-markup-face)
2737 (markdown-test-range-has-face 8 37 markdown-metadata-value-face)
2738 (markdown-test-range-has-face 40 65 nil)
2739 (markdown-test-range-has-face 67 86 nil)))
2741 (ert-deftest test-markdown-font-lock/mmd-metadata-after-header-with-whitespace ()
2742 "Ensure that similar lines are not matched after the header.
2743 The blank line here has two spaces, which should not change how
2744 it is parsed."
2745 (markdown-test-string
2746 "Title: peg-multimarkdown User's Guide\n \nAuthor: Fletcher T. Penney\nBase Header Level: 2\n"
2747 (markdown-test-range-has-face 1 5 markdown-metadata-key-face)
2748 (markdown-test-range-has-face 6 6 markdown-markup-face)
2749 (markdown-test-range-has-face 8 37 markdown-metadata-value-face)
2750 (markdown-test-range-has-face 42 67 nil)
2751 (markdown-test-range-has-face 69 88 nil)))
2753 (ert-deftest test-markdown-font-lock/pandoc-metadata ()
2754 "Basic Pandoc metadata tests."
2755 (markdown-test-string "% title
2756 two-line title
2757 % first author;
2758 second author
2759 % date
2761 body"
2762 (markdown-test-range-has-face 1 1 markdown-markup-face)
2763 (markdown-test-range-has-face 3 24 markdown-metadata-value-face)
2764 (markdown-test-range-has-face 26 26 markdown-markup-face)
2765 (markdown-test-range-has-face 28 56 markdown-metadata-value-face)
2766 (markdown-test-range-has-face 58 58 markdown-markup-face)
2767 (markdown-test-range-has-face 60 63 markdown-metadata-value-face)
2768 (markdown-test-range-has-face 64 69 nil)))
2770 (ert-deftest test-markdown-font-lock/yaml-metadata ()
2771 "Basic YAML metadata tests."
2772 (markdown-test-string
2773 "---
2774 layout: post
2775 date: 2015-08-13 11:35:25 EST
2778 (markdown-test-range-has-face 1 3 markdown-markup-face)
2779 (markdown-test-range-has-face 5 10 markdown-metadata-key-face)
2780 (markdown-test-range-has-face 11 11 markdown-markup-face)
2781 (markdown-test-range-has-face 13 16 markdown-metadata-value-face)
2782 (markdown-test-range-has-face 18 21 markdown-metadata-key-face)
2783 (markdown-test-range-has-face 22 22 markdown-markup-face)
2784 (markdown-test-range-has-face 24 46 markdown-metadata-value-face)
2785 (markdown-test-range-has-face 48 50 markdown-markup-face)))
2787 (ert-deftest test-markdown-font-lock/toml-metadata ()
2788 "Basic TOML metadata tests."
2789 (markdown-test-string
2790 "---
2791 layout = post
2792 date = 2015-08-13 11:35:25 EST
2795 (markdown-test-range-has-face 1 3 markdown-markup-face)
2796 (markdown-test-range-has-face 5 10 markdown-metadata-key-face)
2797 (markdown-test-range-has-face 12 12 markdown-markup-face)
2798 (markdown-test-range-has-face 14 17 markdown-metadata-value-face)
2799 (markdown-test-range-has-face 19 22 markdown-metadata-key-face)
2800 (markdown-test-range-has-face 24 24 markdown-markup-face)
2801 (markdown-test-range-has-face 26 48 markdown-metadata-value-face)
2802 (markdown-test-range-has-face 50 52 markdown-markup-face)))
2804 (ert-deftest test-markdown-font-lock/pandoc-yaml-metadata ()
2805 "Basic yaml metadata tests, with pandoc syntax."
2806 (let ((markdown-use-pandoc-style-yaml-metadata t))
2807 (markdown-test-string
2808 "some text
2811 layout: post
2812 date: 2015-08-13 11:35:25 EST
2815 more text
2818 layout: post
2819 date: 2015-08-13 11:35:25 EST
2822 But this is merely a code block
2826 layout: post
2827 date: 2015-08-13 11:35:25 EST
2831 ;; first section
2832 (markdown-test-range-has-face 12 14 markdown-markup-face)
2833 (markdown-test-range-has-face 16 21 markdown-metadata-key-face)
2834 (markdown-test-range-has-face 22 22 markdown-markup-face)
2835 (markdown-test-range-has-face 24 27 markdown-metadata-value-face)
2836 (markdown-test-range-has-face 29 32 markdown-metadata-key-face)
2837 (markdown-test-range-has-face 33 33 markdown-markup-face)
2838 (markdown-test-range-has-face 35 57 markdown-metadata-value-face)
2839 (markdown-test-range-has-face 59 61 markdown-markup-face)
2840 ;; second section
2841 (markdown-test-range-has-face 75 77 markdown-markup-face)
2842 (markdown-test-range-has-face 79 84 markdown-metadata-key-face)
2843 (markdown-test-range-has-face 85 85 markdown-markup-face)
2844 (markdown-test-range-has-face 87 90 markdown-metadata-value-face)
2845 (markdown-test-range-has-face 92 95 markdown-metadata-key-face)
2846 (markdown-test-range-has-face 96 96 markdown-markup-face)
2847 (markdown-test-range-has-face 98 120 markdown-metadata-value-face)
2848 (markdown-test-range-has-face 122 124 markdown-markup-face)
2849 ;; third section
2850 (markdown-test-range-has-face 160 162 markdown-markup-face)
2851 (markdown-test-range-has-face 164 213 markdown-pre-face)
2852 (markdown-test-range-has-face 215 217 markdown-markup-face))))
2854 (ert-deftest test-markdown-font-lock/line-break ()
2855 "Basic line break tests."
2856 (markdown-test-string " \nasdf \n"
2857 (markdown-test-range-has-face 1 9 nil)
2858 (markdown-test-range-has-face 10 11 markdown-line-break-face)))
2860 (ert-deftest test-markdown-font-lock/blockquote-bold ()
2861 "Test font lock for bold inside of a blockquote."
2862 (markdown-test-string
2863 "> **bold**"
2864 (markdown-test-range-has-face 1 10 markdown-blockquote-face)
2865 (markdown-test-range-has-face 5 8 markdown-bold-face)))
2867 (ert-deftest test-markdown-font-lock/blockquote-italic ()
2868 "Test font lock for italic inside of a blockquote."
2869 (markdown-test-string
2870 "> *italic*"
2871 (markdown-test-range-has-face 1 10 markdown-blockquote-face)
2872 (markdown-test-range-has-face 4 9 markdown-italic-face)))
2874 (ert-deftest test-markdown-font-lock/blockquote-code ()
2875 "Test font lock for inline code inside of a blockquote."
2876 (markdown-test-string
2877 "> `code`"
2878 (markdown-test-range-has-face 1 8 'markdown-blockquote-face)
2879 (markdown-test-range-has-face 3 3 'markdown-markup-face)
2880 (markdown-test-range-has-face 4 7 'markdown-inline-code-face)
2881 (markdown-test-range-has-face 8 8 'markdown-markup-face)))
2883 (ert-deftest test-markdown-font-lock/blockquote-link ()
2884 "Test font lock for links inside of a blockquote.
2885 This test will fail until font lock for inline links inside
2886 blockquotes is implemented (at present, the blockquote face
2887 takes precedence)."
2888 (markdown-test-string
2889 "> [link](url)"
2890 (markdown-test-range-has-face 1 1 markdown-markup-face)
2891 (markdown-test-range-has-face 2 13 markdown-blockquote-face)
2892 (markdown-test-range-has-face 3 3 markdown-markup-face)
2893 (markdown-test-range-has-face 4 7 markdown-link-face)
2894 (markdown-test-range-has-face 8 9 markdown-markup-face)
2895 (markdown-test-range-has-face 10 12 markdown-url-face)
2896 (markdown-test-range-has-face 13 13 markdown-markup-face)))
2898 (ert-deftest test-markdown-font-lock/blockquote-comment ()
2899 "Test font lock for comments inside of a blockquote."
2900 (markdown-test-string
2901 "> <!-- comment -->"
2902 (markdown-test-range-has-face 1 1 markdown-markup-face)
2903 (markdown-test-range-has-face 3 18 markdown-comment-face)))
2905 (ert-deftest test-markdown-font-lock/pre-override ()
2906 "Test that font lock for pre blocks overrides everything else."
2907 (markdown-test-string
2908 " **bold**
2909 _italic_
2910 <!-- comment -->
2911 [link](url)
2912 * list"
2913 (markdown-test-range-has-face 1 73 markdown-pre-face)))
2915 (ert-deftest test-markdown-font-lock/gfm-code-block-font-lock ()
2916 "GFM code block font lock test. Now in base markdown-mode as well!"
2917 (markdown-test-file "gfm.text"
2918 (markdown-test-range-has-face 2639 2641 markdown-markup-face) ; ```
2919 (markdown-test-range-has-face 2642 2645 markdown-language-keyword-face) ; lang
2920 (markdown-test-range-has-face 2647 2728 markdown-pre-face) ; code
2921 (markdown-test-range-has-face 2730 2732 markdown-markup-face))) ; ```
2923 (ert-deftest test-markdown-font-lock/reference-definition ()
2924 "Reference definitions should not include ]."
2925 (let ((markdown-hide-urls nil))
2926 (markdown-test-string "[1]: http://daringfireball.net/ \"title\""
2927 (markdown-test-range-has-face 2 2 markdown-reference-face) ; 1
2928 (markdown-test-range-has-face 6 31 markdown-url-face) ; URL
2929 (markdown-test-range-has-face 34 38 markdown-link-title-face)) ; title
2930 (markdown-test-string "[foo][1] and [bar][2]: not a reference definition"
2931 (markdown-test-range-has-face 2 4 markdown-link-face) ; foo
2932 (markdown-test-range-has-face 7 7 markdown-reference-face) ; 1
2933 (markdown-test-range-has-face 9 13 nil) ; [ ]and[ ]
2934 (markdown-test-range-has-face 15 17 markdown-link-face) ; bar
2935 (markdown-test-range-has-face 20 20 markdown-reference-face) ; 2
2936 (markdown-test-range-has-face 22 49 nil)))) ; [ ]and[ ]
2938 (ert-deftest test-markdown-font-lock/subscripts ()
2939 "Test font lock for subscripts."
2940 (markdown-test-string "H~2~0"
2941 (markdown-test-range-has-face 2 2 'markdown-markup-face) ; First ~
2942 (markdown-test-range-has-face 3 3 nil) ; 2
2943 (markdown-test-range-has-face 4 4 'markdown-markup-face))) ; Second ~
2945 (ert-deftest test-markdown-font-lock/superscripts ()
2946 "Test font lock for subscripts."
2947 (markdown-test-string "334^10^"
2948 (markdown-test-range-has-face 1 3 nil) ; 334
2949 (markdown-test-range-has-face 4 4 'markdown-markup-face) ; First ^
2950 (markdown-test-range-has-face 5 6 nil) ; 10
2951 (markdown-test-range-has-face 7 7 'markdown-markup-face))) ; Second ^
2953 (ert-deftest test-markdown-font-lock/hidden-urls-inline ()
2954 "Test URL hiding and toggling."
2955 (let ((markdown-hide-urls t))
2956 (markdown-test-file "inline.text"
2957 (markdown-test-range-has-face 925 925 markdown-markup-face)
2958 (markdown-test-range-has-face 926 929 markdown-link-face)
2959 (markdown-test-range-has-face 930 931 markdown-markup-face)
2960 (markdown-test-range-has-face 932 949 markdown-url-face)
2961 (markdown-test-range-has-face 951 957 markdown-link-title-face)
2962 (markdown-test-range-has-face 958 958 markdown-markup-face)
2963 (should (get-text-property 932 'composition)))))
2965 (ert-deftest test-markdown-font-lock/hidden-urls-reference ()
2966 "Test URL hiding and toggling."
2967 (let ((markdown-hide-urls t))
2968 (markdown-test-string "[link][15]"
2969 ;; Two-character reference labels shouldn't get composed.
2970 (markdown-test-range-has-face 1 1 markdown-markup-face)
2971 (markdown-test-range-has-face 2 5 markdown-link-face)
2972 (markdown-test-range-has-face 6 7 markdown-markup-face)
2973 (markdown-test-range-has-face 8 9 markdown-reference-face)
2974 (markdown-test-range-has-face 10 10 markdown-markup-face)
2975 (should-not (get-text-property 8 'composition)))
2976 (markdown-test-string "[link][long-reference-label]"
2977 ;; Longer reference labels should be composed
2978 (markdown-test-range-has-face 1 1 markdown-markup-face)
2979 (markdown-test-range-has-face 2 5 markdown-link-face)
2980 (markdown-test-range-has-face 6 7 markdown-markup-face)
2981 (markdown-test-range-has-face 8 27 markdown-reference-face)
2982 (markdown-test-range-has-face 28 28 markdown-markup-face)
2983 (should (get-text-property 8 'composition)))))
2985 (ert-deftest test-markdown-font-lock/snake-case-code-in-heading ()
2986 "Test underscores in inline code in headings."
2987 (markdown-test-string "# Title with `snake_case_code`"
2988 (should-not (markdown-range-property-any 21 24 'face '(markdown-italic-face)))
2989 (markdown-test-range-has-face 15 29 'markdown-inline-code-face)))
2991 (ert-deftest test-markdown-font-lock/stars-in-code-in-heading ()
2992 "Test asterisks in inline code in headings."
2993 (markdown-test-string "# Title with `char** foo, int* bar`"
2994 (should-not (markdown-range-property-any 20 29 'face '(markdown-italic-face)))
2995 (markdown-test-range-has-face 15 34 'markdown-inline-code-face)))
2997 (ert-deftest test-markdown-font-lock/stars-in-code-in-blockquote ()
2998 "Test asterisks in inline code in blockquote."
2999 (markdown-test-string "> Quote with `**stars**`"
3000 (should-not (markdown-range-property-any
3001 17 21 'face '(markdown-italic-face markdown-bold-face)))
3002 (markdown-test-range-has-face 15 23 'markdown-inline-code-face)))
3004 (ert-deftest test-markdown-font-lock/two-bold-words-after-list ()
3005 "Test two bold words after a list marker."
3006 (markdown-test-string "- **foo** **bar**"
3007 (should-not (markdown-range-property-any
3008 (point-min) (point-max) 'face '(markdown-italic-face)))))
3010 (ert-deftest test-markdown-font-lock/heading-with-italics-and-bold ()
3011 "Test two bold words after a list marker."
3012 (markdown-test-string "# Title with *italics* and **bold**"
3013 (markdown-test-range-has-face 15 21 'markdown-italic-face)
3014 (markdown-test-range-has-face 30 33 'markdown-bold-face)
3015 (should-not (markdown-range-property-any 30 33 'face '(markdown-italic-face)))))
3017 (ert-deftest test-markdown-font-lock/heading-with-italics-and-bold ()
3018 "Test that HRs are distinguished from setext H2 markup."
3019 (markdown-test-file "outline.text"
3020 (goto-char 485)
3021 (should (markdown-on-heading-p))
3022 (beginning-of-line)
3023 (should (markdown-on-heading-p))
3024 (should-not (markdown-range-property-any 453 484 'face '(markdown-hr-face)))))
3026 (ert-deftest test-markdown-font-lock/heading-code-block-no-whitespace ()
3027 "Headings immediately before code blocks should be identified correctly.
3028 See GH-234."
3029 (markdown-test-string
3030 "#### code snippet
3031 ```javascript
3032 const styles = require('gadgets/dist/styles.css');
3033 ```"
3034 (goto-char (point-min))
3035 (forward-word)
3036 (should (markdown-on-heading-p))
3037 (should (markdown-match-propertized-text 'markdown-heading (point-at-eol)))
3038 (goto-char (match-beginning 0))
3039 (should (markdown-outline-level))
3040 (should (= (markdown-outline-level) 4))
3041 (markdown-test-range-has-face 6 17 'markdown-header-face-4)
3042 (end-of-line)
3043 (should-not (markdown-code-block-at-point-p))))
3045 (ert-deftest test-markdown-font-lock/inline-attributes ()
3046 "Test inline attributes before a fenced code block."
3047 (markdown-test-file "Leanpub.md"
3048 ;; Inline attributes for a heading
3049 (markdown-test-range-has-face 38 42 'markdown-markup-face)
3050 ;; Inline attributes inside an aside block
3051 (markdown-test-range-has-face 123 141 'markdown-markup-face)
3052 ;; Inline attributes before a fenced code block
3053 (markdown-test-range-has-face 632 696 'markdown-markup-face)))
3055 (ert-deftest test-markdown-font-lock/leanpub-sections ()
3056 "Test Leanpub section markers."
3057 (markdown-test-file "Leanpub.md"
3058 ;; {frontmatter}
3059 (markdown-test-range-has-face 12 24 'markdown-markup-face)
3060 ;; {mainmatter}
3061 (markdown-test-range-has-face 69 80 'markdown-markup-face)
3062 ;; {pagebreak}
3063 (markdown-test-range-has-face 427 437 'markdown-markup-face)))
3065 (ert-deftest test-markdown-font-lock/leanpub-include ()
3066 "Test Leanpub include syntax."
3067 (markdown-test-file "Leanpub.md"
3068 ;; no title
3069 (markdown-test-range-has-face 561 563 'markdown-markup-face)
3070 (markdown-test-range-has-face 564 577 'markdown-url-face)
3071 (markdown-test-range-has-face 578 578 'markdown-markup-face)
3072 ;; title
3073 (markdown-test-range-has-face 581 583 'markdown-markup-face)
3074 (markdown-test-range-has-face 584 611 'markdown-link-title-face)
3075 (markdown-test-range-has-face 612 613 'markdown-markup-face)
3076 (markdown-test-range-has-face 614 628 'markdown-url-face)
3077 (markdown-test-range-has-face 629 629 'markdown-markup-face)))
3079 (ert-deftest test-markdown-font-lock/curly-brace-include ()
3080 "Test curly brace include syntax."
3081 (markdown-test-string "<<{file}"
3082 (markdown-test-range-has-face 1 3 'markdown-markup-face)
3083 (markdown-test-range-has-face 4 7 'markdown-url-face)
3084 (markdown-test-range-has-face 8 8 'markdown-markup-face)))
3086 (ert-deftest test-markdown-font-lock/square-bracket-include ()
3087 "Test square bracket include syntax."
3088 (markdown-test-string "<<[file]"
3089 (markdown-test-range-has-face 1 3 'markdown-markup-face)
3090 (markdown-test-range-has-face 4 7 'markdown-url-face)
3091 (markdown-test-range-has-face 8 8 'markdown-markup-face)))
3093 (ert-deftest test-markdown-font-lock/pandoc-inline-footnote ()
3094 "Test font lock for Pandoc inline footnotes."
3095 (markdown-test-string "Here is an inline note.^[Inline notes are easier to write, since
3096 you don't have to pick an identifier and move down to type the
3097 note.] And then you can close it and continue writing."
3098 (markdown-test-range-has-face 1 23 nil)
3099 (markdown-test-range-has-face 24 25 'markdown-markup-face)
3100 (markdown-test-range-has-face 26 133 'markdown-footnote-text-face)
3101 (markdown-test-range-has-face 134 134 'markdown-markup-face)))
3103 (ert-deftest test-markdown-font-lock/pandoc-inline-footnote-across-block ()
3104 "Test font lock for Pandoc inline footnotes."
3105 (markdown-test-string "Inline notes should not^[match
3107 across blocks]"
3108 (markdown-test-range-has-face (point-min) (point-max) nil)))
3110 (ert-deftest test-markdown-font-lock/html-entity-named ()
3111 "Test basic font-lock support for named HTML entities."
3112 (markdown-test-string "&nbsp;"
3113 (markdown-test-range-has-face 1 6 'markdown-html-entity-face)))
3115 (ert-deftest test-markdown-font-lock/html-entity-hex ()
3116 "Test basic font-lock support for hexadecimal HTML entities."
3117 (markdown-test-string "&#x272a;"
3118 (markdown-test-range-has-face 1 8 'markdown-html-entity-face)))
3120 (ert-deftest test-markdown-font-lock/html-entity-decimal ()
3121 "Test basic font-lock support for decimal HTML entities."
3122 (markdown-test-string "&#9;"
3123 (markdown-test-range-has-face 1 4 'markdown-html-entity-face)))
3125 (ert-deftest test-markdown-font-lock/html-entity-in-inline-code ()
3126 "Test that HTML entities are not matched inside inline code."
3127 (markdown-test-string "`&#9;`"
3128 (markdown-test-range-has-face 1 1 'markdown-markup-face)
3129 (markdown-test-range-has-face 2 5 'markdown-inline-code-face)
3130 (markdown-test-range-has-face 6 6 'markdown-markup-face)
3131 (should-not (markdown-range-property-any 1 6 'face '(markdown-html-entity-face)))))
3133 (ert-deftest test-markdown-font-lock/html-entity-in-gfm-code-block ()
3134 "Test that HTML entities are not matched inside GFM code blocks."
3135 (markdown-test-string "```\n&nbsp;\n&#x272a;\n&#9;\n```"
3136 (should-not
3137 (markdown-range-property-any
3138 (point-min) (point-max) 'face '(markdown-html-entity-face)))))
3140 (ert-deftest test-markdown-font-lock/html-tags-in-syntax-file ()
3141 "Test matching HTML tags in syntax.text."
3142 (markdown-test-file "syntax.text"
3143 ;; <ul id="ProjectSubmenu">
3144 (markdown-test-range-has-face 36 36 'markdown-html-tag-delimiter-face)
3145 (markdown-test-range-has-face 37 38 'markdown-html-tag-name-face)
3146 (markdown-test-range-has-face 40 41 'markdown-html-attr-name-face)
3147 (markdown-test-range-has-face 42 42 'markdown-html-tag-delimiter-face)
3148 (markdown-test-range-has-face 43 58 'markdown-html-attr-value-face)
3149 (markdown-test-range-has-face 59 59 'markdown-html-tag-delimiter-face)
3150 ;; <li>
3151 (markdown-test-range-has-face 65 65 'markdown-html-tag-delimiter-face)
3152 (markdown-test-range-has-face 66 67 'markdown-html-tag-name-face)
3153 (markdown-test-range-has-face 68 68 'markdown-html-tag-delimiter-face)
3154 ;; <a href="/projects/markdown/" title="Markdown Project Page">
3155 (markdown-test-range-has-face 69 69 'markdown-html-tag-delimiter-face)
3156 (markdown-test-range-has-face 70 70 'markdown-html-tag-name-face)
3157 (markdown-test-range-has-face 72 75 'markdown-html-attr-name-face)
3158 (markdown-test-range-has-face 76 76 'markdown-html-tag-delimiter-face)
3159 (markdown-test-range-has-face 77 97 'markdown-html-attr-value-face)
3160 (markdown-test-range-has-face 99 103 'markdown-html-attr-name-face)
3161 (markdown-test-range-has-face 104 104 'markdown-html-tag-delimiter-face)
3162 (markdown-test-range-has-face 105 127 'markdown-html-attr-value-face)
3163 (markdown-test-range-has-face 128 128 'markdown-html-tag-delimiter-face)))
3165 (ert-deftest test-markdown-font-lock/html-tag-in-gfm-code-block ()
3166 "Test that HTML tags are not matched inside GFM code blocks."
3167 (markdown-test-string "```\n<ul id=\"ProjectSubmenu\">\n```"
3168 (should-not
3169 (markdown-range-property-any
3170 (point-min) (point-max) 'face
3171 '(markdown-html-tag-name-face
3172 markdown-html-tag-delimiter-face
3173 markdown-html-attr-name-face
3174 markdown-html-attr-value-face)))))
3176 (ert-deftest test-markdown-font-lock/html-tag-in-code-block ()
3177 "Test that HTML tags are not matched inside code blocks."
3178 (markdown-test-string " <ul id=\"ProjectSubmenu\">"
3179 (should-not
3180 (markdown-range-property-any
3181 (point-min) (point-max) 'face
3182 '(markdown-html-tag-name-face
3183 markdown-html-tag-delimiter-face
3184 markdown-html-attr-name-face
3185 markdown-html-attr-value-face)))))
3187 (ert-deftest test-markdown-font-lock/html-tag-in-inline-code ()
3188 "Test that HTML tags are not matched inside inline code spans."
3189 (markdown-test-string "`<ul id=\"ProjectSubmenu\">`"
3190 (should-not
3191 (markdown-range-property-any
3192 (point-min) (point-max) 'face
3193 '(markdown-html-tag-name-face
3194 markdown-html-tag-delimiter-face
3195 markdown-html-attr-name-face
3196 markdown-html-attr-value-face)))))
3198 (ert-deftest test-markdown-font-lock/html-disabled ()
3199 "Test disabling font-lock for HTML tags"
3200 (let ((markdown-enable-html nil))
3201 (markdown-test-file "syntax.text"
3202 (should-not
3203 (markdown-range-property-any
3204 (point-min) (point-max) 'face
3205 '(markdown-html-tag-name-face
3206 markdown-html-tag-delimiter-face
3207 markdown-html-attr-name-face
3208 markdown-html-attr-value-face))))))
3210 ;;; Markdown Parsing Functions:
3212 (ert-deftest test-markdown-parsing/extend-region-function ()
3213 "Test `markdown-syntax-propertize-extend-region'.
3214 Should return a cons (NEW-START . NEW-END) or nil if no
3215 adjustment should be made. Function is called repeatedly until it
3216 returns nil."
3217 (markdown-test-file
3218 "inline.text"
3219 (should (equal (markdown-syntax-propertize-extend-region 1 17)
3220 (cons 1 91)))
3221 (should (equal (markdown-syntax-propertize-extend-region 2 17)
3222 (cons 1 91)))
3223 (should (equal (markdown-syntax-propertize-extend-region 1 91)
3224 nil))
3225 (should (equal (markdown-syntax-propertize-extend-region 93 157)
3226 nil))
3227 (should (equal (markdown-syntax-propertize-extend-region 496 502)
3228 (cons 486 510)))
3229 (should (equal (markdown-syntax-propertize-extend-region 486 510)
3230 nil))
3231 ;; Region that begins and ends with \n\n should not be extended
3232 (should (equal (markdown-syntax-propertize-extend-region 157 355)
3233 nil))))
3235 (defun markdown-test-check-match-limits (prop num begin end &optional pos)
3236 (let* ((posn (or pos (point)))
3237 (props (get-text-property posn prop)))
3238 (save-match-data
3239 (set-match-data props)
3240 (and (match-beginning num) (match-end num)
3241 (= (match-beginning num) begin)
3242 (= (match-end num) end)))))
3244 (ert-deftest test-markdown-parsing/syntax-with-adjacent-code-blocks ()
3245 "Test `markdown-syntax-propertize-fenced-code-blocks' with adjacent blocks."
3246 (markdown-test-string
3247 "~~~ shell
3248 #!/bin/sh
3250 echo \"Hello, world!\"
3253 ~~~ shell
3254 #!/bin/sh
3256 echo \"Hello, world v2!\"
3259 (let ((start-top-1 (make-marker)) (end-top-1 (make-marker))
3260 (start-lang-1 (make-marker)) (end-lang-1 (make-marker))
3261 (start-mid-1 (make-marker)) (end-mid-1 (make-marker))
3262 (start-bottom-1 (make-marker)) (end-bottom-1 (make-marker))
3263 (between (make-marker))
3264 (start-top-2 (make-marker)) (end-top-2 (make-marker))
3265 (start-lang-2 (make-marker)) (end-lang-2 (make-marker))
3266 (start-mid-2 (make-marker)) (end-mid-2 (make-marker))
3267 (start-bottom-2 (make-marker)) (end-bottom-2 (make-marker)))
3268 ;; First code block
3269 (set-marker start-top-1 1)
3270 (set-marker end-top-1 4)
3271 (set-marker start-lang-1 5)
3272 (set-marker end-lang-1 10)
3273 (set-marker start-mid-1 11)
3274 (set-marker end-mid-1 43)
3275 (set-marker start-bottom-1 43)
3276 (set-marker end-bottom-1 46)
3277 ;; check top tildes
3278 (should (markdown-test-check-match-limits
3279 'markdown-tilde-fence-begin 1 (marker-position start-top-1)
3280 (marker-position end-top-1) (marker-position start-top-1)))
3281 ;; check top language specifier
3282 (should (markdown-test-check-match-limits
3283 'markdown-tilde-fence-begin 3 (marker-position start-lang-1)
3284 (marker-position end-lang-1) (marker-position start-lang-1)))
3285 ;; check text in between
3286 (should (markdown-test-check-match-limits
3287 'markdown-fenced-code 0 (marker-position start-mid-1)
3288 (marker-position end-mid-1) (marker-position start-mid-1)))
3289 ;; check bottom tildes
3290 (should (markdown-test-check-match-limits
3291 'markdown-tilde-fence-end 1 (marker-position start-bottom-1)
3292 (marker-position end-bottom-1) (marker-position start-bottom-1)))
3293 ;; Point between code blocks
3294 (set-marker between 47)
3295 (should (equal (get-text-property between 'markdown-fenced-code)
3296 nil))
3297 ;; Second code block
3298 (set-marker start-top-2 48)
3299 (set-marker end-top-2 51)
3300 (set-marker start-lang-2 52)
3301 (set-marker end-lang-2 57)
3302 (set-marker start-mid-2 58)
3303 (set-marker end-mid-2 93)
3304 (set-marker start-bottom-2 93)
3305 (set-marker end-bottom-2 96)
3306 (should (markdown-test-check-match-limits
3307 'markdown-tilde-fence-begin 1 (marker-position start-top-2)
3308 (marker-position end-top-2) (marker-position start-top-2)))
3309 (should (markdown-test-check-match-limits
3310 'markdown-tilde-fence-begin 3 (marker-position start-lang-2)
3311 (marker-position end-lang-2) (marker-position start-lang-2)))
3312 (should (markdown-test-check-match-limits
3313 'markdown-fenced-code 0 (marker-position start-mid-2)
3314 (marker-position end-mid-2) (marker-position start-mid-2)))
3315 (should (markdown-test-check-match-limits
3316 'markdown-tilde-fence-end 1 (marker-position start-bottom-2)
3317 (marker-position end-bottom-2) (marker-position start-bottom-2)))
3318 ;; ;; Move point between code blocks and insert a character
3319 (goto-char between)
3320 (insert "x")
3321 ;; Re-propertize region after change
3322 (let ((range (markdown-syntax-propertize-extend-region (1- between) (point-max))))
3323 (markdown-syntax-propertize (car range) (cdr range)))
3324 ;; Re-check first code block
3325 (should (markdown-test-check-match-limits
3326 'markdown-tilde-fence-begin 1 (marker-position start-top-1)
3327 (marker-position end-top-1) (marker-position start-top-1)))
3328 (should (markdown-test-check-match-limits
3329 'markdown-tilde-fence-begin 3 (marker-position start-lang-1)
3330 (marker-position end-lang-1) (marker-position start-lang-1)))
3331 (should (markdown-test-check-match-limits
3332 'markdown-fenced-code 0 (marker-position start-mid-1)
3333 (marker-position end-mid-1) (marker-position start-mid-1)))
3334 (should (markdown-test-check-match-limits
3335 'markdown-tilde-fence-end 1 (marker-position start-bottom-1)
3336 (marker-position end-bottom-1) (marker-position start-bottom-1)))
3337 ;; Re-check point between code blocks
3338 (should (equal (get-text-property between 'markdown-fenced-code)
3339 nil))
3340 ;; Re-check second code block
3341 (should (markdown-test-check-match-limits
3342 'markdown-tilde-fence-begin 1 (marker-position start-top-2)
3343 (marker-position end-top-2) (marker-position start-top-2)))
3344 (should (markdown-test-check-match-limits
3345 'markdown-tilde-fence-begin 3 (marker-position start-lang-2)
3346 (marker-position end-lang-2) (marker-position start-lang-2)))
3347 (should (markdown-test-check-match-limits
3348 'markdown-fenced-code 0 (marker-position start-mid-2)
3349 (marker-position end-mid-2) (marker-position start-mid-2)))
3350 (should (markdown-test-check-match-limits
3351 'markdown-tilde-fence-end 1 (marker-position start-bottom-2)
3352 (marker-position end-bottom-2)
3353 (marker-position start-bottom-2))))))
3355 (ert-deftest test-markdown-parsing/propertize-fenced-in-between ()
3356 "Test whether `markdown-syntax-propertize-fenced-block-constructs' handles the
3357 case when it can't propertize both the start and end of a fenced block within a
3358 single pass (the end of the block is past the END argument)."
3359 (markdown-test-string
3360 "~~~ shell
3361 #!/bin/sh
3363 echo \"Hello, world!\"
3366 (set-text-properties (point-min) (point-max) nil)
3367 ;; syntax-propertize up to right after hashbang
3368 (markdown-syntax-propertize-fenced-block-constructs (point-min) 21)
3369 ;; ~~~ shell should be propertized, but nothing else
3370 ;; check tildes
3371 (should (markdown-test-check-match-limits
3372 'markdown-tilde-fence-begin 1 1 4 1))
3373 ;; check language
3374 (should (markdown-test-check-match-limits
3375 'markdown-tilde-fence-begin 3 5 10 5))
3376 ;; middle should not be propertized
3377 (should-not (get-text-property 11 'markdown-fenced-code))
3378 ;; neither should end
3379 (should-not (get-text-property 43 'markdown-tilde-fence-end))
3380 (markdown-syntax-propertize-fenced-block-constructs 21 (point-max))
3381 ;; everything should be propertized now
3382 ;; re-check top
3383 (should (markdown-test-check-match-limits
3384 'markdown-tilde-fence-begin 1 1 4 1))
3385 (should (markdown-test-check-match-limits
3386 'markdown-tilde-fence-begin 3 5 10 5))
3387 ;; check middle
3388 (should (markdown-test-check-match-limits 'markdown-fenced-code 0 10 43 10))
3389 ;; check ending tildes
3390 (should (markdown-test-check-match-limits
3391 'markdown-tilde-fence-end 1 43 46 43))))
3393 (ert-deftest test-markdown-parsing/get-code-block-at-pos ()
3394 "Test whether `markdown-code-block-at-pos' works in all situations. All
3395 situations are:
3396 1. pre block
3397 2. tilde block
3398 3. gfm block
3399 4. yaml metadata block"
3400 (let ((markdown-use-pandoc-style-yaml-metadata t))
3401 (markdown-test-string
3403 ~~~ ruby
3404 some_ruby_fun()
3408 a: b
3411 ``` {.bash}
3412 #!/bin/sh
3413 echo hey
3416 pre code
3417 random stuff
3418 more preformatted code
3421 data: pandoc
3424 ;; start/mid/end at tilde block
3425 (should (equal (markdown-code-block-at-pos 2) (list 2 30)))
3426 (should (equal (markdown-code-block-at-pos 11) (list 2 30)))
3427 (should (equal (markdown-code-block-at-pos 27) (list 2 30)))
3428 ;; yaml metadata block
3429 (should (equal (markdown-code-block-at-pos 32) (list 32 44)))
3430 (should (equal (markdown-code-block-at-pos 36) (list 32 44)))
3431 (should (equal (markdown-code-block-at-pos 41) (list 32 44)))
3432 ;; gfm block
3433 (should (equal (markdown-code-block-at-pos 46) (list 46 80)))
3434 (should (equal (markdown-code-block-at-pos 58) (list 46 80)))
3435 (should (equal (markdown-code-block-at-pos 77) (list 46 80)))
3436 ;; pre block
3437 (should (equal (markdown-code-block-at-pos 82) (list 82 138)))
3438 (should (equal (markdown-code-block-at-pos 99) (list 82 138)))
3439 (should (equal (markdown-code-block-at-pos 137) (list 82 138)))
3440 ;; pandoc yaml metadata block (should work if yaml above works)
3441 (should (equal (markdown-code-block-at-pos 140) (list 140 160)))
3442 (should (equal (markdown-code-block-at-pos 142) (list 140 160)))
3443 (should (equal (markdown-code-block-at-pos 144) (list 140 160)))
3444 (should (equal (markdown-code-block-at-pos 157) (list 140 160)))
3445 (should (equal (markdown-code-block-at-pos 159) (list 140 160))))))
3447 (ert-deftest test-markdown-parsing/syntax-get-fenced-blocks ()
3448 "Test whether *-get-fenced-block-* functions work in the case where a block is
3449 only partially propertized."
3450 (save-match-data
3451 (markdown-test-string
3452 "~~~
3454 (should (equal (markdown-syntax-propertize-extend-region
3455 (point-min) (point-max))
3456 nil))
3457 (goto-char 1)
3458 (set-match-data (markdown-text-property-at-point
3459 'markdown-tilde-fence-begin))
3460 (should (equal (markdown-get-fenced-block-from-start
3461 'markdown-tilde-fence-begin)
3462 nil)))
3463 (markdown-test-string
3464 "~~~
3465 ~~~"
3466 (goto-char 1)
3467 (set-match-data (markdown-text-property-at-point
3468 'markdown-tilde-fence-begin))
3469 (should (equal (markdown-get-fenced-block-from-start
3470 'markdown-tilde-fence-begin)
3471 (list 1 8)))
3472 (should (equal (markdown-code-block-at-pos (point)) (list 1 8)))
3474 ;; markdown-code-block-at-point-p should not modify match data
3475 (set-match-data (list 1 2 3 4))
3476 (should (markdown-code-block-at-point-p))
3477 (should (equal (match-data) (list 1 2 3 4)))
3479 (goto-char 5)
3480 (set-match-data (markdown-text-property-at-point
3481 'markdown-tilde-fence-end))
3482 (should (equal (markdown-get-fenced-block-from-end
3483 'markdown-tilde-fence-end)
3484 (list 1 8)))
3485 (should (equal (markdown-code-block-at-pos (point)) (list 1 8))))
3486 (markdown-test-string
3487 "~~~
3489 ~~~"
3490 (goto-char 1)
3491 (set-match-data (markdown-text-property-at-point
3492 'markdown-tilde-fence-begin))
3493 (should (equal (markdown-get-fenced-block-from-start
3494 'markdown-tilde-fence-begin)
3495 (list 1 9)))
3496 (should (equal (markdown-code-block-at-pos (point)) (list 1 9)))
3497 (goto-char 5)
3498 (set-match-data (markdown-text-property-at-point 'markdown-fenced-code))
3499 (should (equal (markdown-get-fenced-block-from-middle
3500 'markdown-fenced-code)
3501 (list 1 9)))
3502 (should (equal (markdown-code-block-at-pos (point)) (list 1 9)))
3503 (goto-char 6)
3504 (set-match-data (markdown-text-property-at-point
3505 'markdown-tilde-fence-end))
3506 (should (equal (markdown-get-fenced-block-from-end
3507 'markdown-tilde-fence-end)
3508 (list 1 9)))
3509 (should (equal (markdown-code-block-at-pos (point)) (list 1 9))))))
3511 (ert-deftest test-markdown-parsing/reference-definition-basic ()
3512 "Test reference definition function."
3513 (markdown-test-file "syntax.text"
3514 ;; Test accuracy of returned text and bounds
3515 (should (equal (markdown-reference-definition "1")
3516 (list "http://docutils.sourceforge.net/mirror/setext.html" 1942 1992)))
3517 (should (equal (markdown-reference-definition "2")
3518 (list "http://www.aaronsw.com/2002/atx/" 2000 2032)))
3519 ;; Test that match data remains intact
3520 (should (string-equal (match-string 5) "http://www.aaronsw.com/2002/atx/"))
3521 ;; Test anchor-only relative URL
3522 (should (equal (markdown-reference-definition "bq")
3523 (list "#blockquote" 7536 7547)))
3524 ;; Example references that appear in pre blocks in the text
3525 (should (not (markdown-reference-definition "")))
3526 (should (not (markdown-reference-definition "id")))
3527 (should (not (markdown-reference-definition "foo")))
3528 (should (not (markdown-reference-definition "A")))
3529 (should (not (markdown-reference-definition "Google")))
3530 ;; Test that we don't pick up other text in square brackets
3531 (should (not (markdown-reference-definition "blockquoting")))
3532 (should (not (markdown-reference-definition "square brackets")))
3533 ;; Test case insensitivity
3534 (should (equal (markdown-reference-definition "SRC")
3535 (list "/projects/markdown/syntax.text" 1245 1275)))))
3537 (ert-deftest test-markdown-parsing/get-defined-references ()
3538 "Test `markdown-get-defined-references'."
3539 (markdown-test-file "syntax.text"
3540 (should (equal (markdown-get-defined-references)
3541 '("src" "1" "2" "3" "4" "5" "6" "bq" "l"))))
3542 (markdown-test-file "outline.text"
3543 (should (equal (markdown-get-defined-references) nil)))
3544 (markdown-test-file "wiki-links.text"
3545 (should (equal (markdown-get-defined-references) nil))))
3547 (ert-deftest test-markdown-parsing/get-used-uris ()
3548 "Test `markdown-get-used-uris'."
3549 (markdown-test-file "syntax.text"
3550 (let ((uris (markdown-get-used-uris)))
3551 (should (equal (nth 0 uris) "#overview"))
3552 (should (equal (nth 20 uris) "http://www.aaronsw.com/2002/atx/"))
3553 (should-not (member "http://example.com/" uris))
3554 (should-not (member "address@example.com" uris)))))
3556 (defun markdown-test-test-region (beg end)
3557 (goto-char (1- beg))
3558 (should-not (markdown-inline-code-at-point-p))
3559 (goto-char (1+ end))
3560 (should-not (markdown-inline-code-at-point-p))
3561 (dolist (loc (number-sequence beg end))
3562 (goto-char loc)
3563 (should (markdown-inline-code-at-point))
3564 (should (equal (match-beginning 0) beg))
3565 (should (equal (match-end 0) end))))
3567 (ert-deftest test-markdown-parsing/inline-code-at-point ()
3568 "Test `markdown-inline-code-at-point'."
3569 (markdown-test-file "inline.text"
3570 (markdown-test-test-region 45 51) ; Regular code span
3571 (markdown-test-test-region 61 90) ; Code containing backticks
3572 (markdown-test-test-region 228 240) ; Backquotes at beginning
3573 (markdown-test-test-region 341 352) ; Backquotes at end
3574 (markdown-test-test-region 460 469) ; Backslash as final character
3575 (markdown-test-test-region 657 667) ; A code span crossing lines
3576 (markdown-test-test-region 749 758) ; Three backquotes on same line
3577 (markdown-test-test-region 806 815) ; Three backquotes across lines
3580 (ert-deftest test-markdown-parsing/inline-code-at-point-one-space ()
3581 "Test `markdown-inline-code-at-point' with multiple code spans in a row."
3582 (markdown-test-string "`foo` `bar` `baz`"
3583 (dolist (loc (number-sequence 1 6))
3584 (goto-char loc)
3585 ;; markdown-inline-code-at-point should set match data
3586 (should (markdown-inline-code-at-point))
3587 (should (equal (match-data) (list 1 6 1 2 2 5 5 6)))
3588 ;; markdown-inline-code-at-point-p should not modify match data
3589 (set-match-data (list 1 2 3 4))
3590 (should (markdown-inline-code-at-point-p))
3591 (should (equal (match-data) (list 1 2 3 4))))
3592 (dolist (loc (number-sequence 7 12))
3593 (goto-char loc)
3594 (should (markdown-inline-code-at-point))
3595 (should (equal (match-data) (list 7 12 7 8 8 11 11 12))))
3596 (dolist (loc (number-sequence 13 18))
3597 (goto-char loc)
3598 (should (markdown-inline-code-at-point))
3599 (should (equal (match-data) (list 13 18 13 14 14 17 17 18))))))
3601 (ert-deftest test-markdown-parsing/inline-code-at-point-no-space ()
3602 "Test `markdown-inline-code-at-point' with multiple code spans in a row.."
3603 (markdown-test-string "a`foo`b`bar`c`baz`d"
3604 (goto-char 1) ; "a"
3605 (should-not (markdown-inline-code-at-point-p))
3606 (dolist (loc (number-sequence 2 7)) ; "`foo`b"
3607 (goto-char loc)
3608 (should (markdown-inline-code-at-point))
3609 (should (equal (match-data) (list 2 7 2 3 3 6 6 7))))
3610 (dolist (loc (number-sequence 8 13)) ; "`bar`c"
3611 (goto-char loc)
3612 (should (markdown-inline-code-at-point))
3613 (should (equal (match-data) (list 8 13 8 9 9 12 12 13))))
3614 (dolist (loc (number-sequence 14 19)) ; "`baz`d"
3615 (goto-char loc)
3616 (should (markdown-inline-code-at-point))
3617 (should (equal (match-data) (list 14 19 14 15 15 18 18 19))))))
3619 (ert-deftest test-markdown-parsing/code-at-point-blank-line ()
3620 "Test `markdown-inline-code-at-point-p' at beginning of block."
3621 (markdown-test-string "----------\n\n## foo\n"
3622 (should-not (markdown-inline-code-at-point-p))
3623 (forward-line)
3624 (should-not (markdown-inline-code-at-point-p))
3625 (forward-line)
3626 (should-not (markdown-inline-code-at-point-p))))
3628 (ert-deftest test-markdown-parsing/match-comments ()
3629 "Test `markdown-match-comments'."
3630 (markdown-test-string
3631 "HTML <!-- foo --> comment"
3632 (should (markdown-match-comments (point-max)))
3633 (should (eq (point) 18))
3634 (should (equal (match-data) (list 6 18)))
3635 (should-not (markdown-match-comments (point-max)))))
3637 (ert-deftest test-markdown-parsing/range-property-any ()
3638 "Test behavior of `markdown-range-property-any'."
3639 (markdown-test-file
3640 "inline.text"
3641 (should (markdown-range-property-any
3642 (point-min) (point-at-eol)
3643 'face (list markdown-markup-face
3644 markdown-italic-face)))
3645 (should-not (markdown-range-property-any
3646 (point-min) (point-at-eol)
3647 'face (list markdown-bold-face)))))
3649 (ert-deftest test-markdown-parsing/inline-code ()
3650 "Don't cause infinite loop for inline code just after metadata block
3651 Detail: https://github.com/jrblevin/markdown-mode/issues/115"
3652 (markdown-test-string "---
3653 x: x
3657 (should (markdown-match-code (point-max)))
3658 (should (= (point) 17))
3659 (should (equal (match-data t) '(14 17 14 15 15 16 16 17)))
3660 (should-not (markdown-match-code (point-max)))))
3662 (ert-deftest test-markdown-parsing/list-item-at-point ()
3663 "Test `markdown-list-item-at-point-p'."
3664 (markdown-test-file "lists.text"
3665 (let ((orig-match-data '(1 2 3 4))
3666 (not-list-points '(273 399 512 3615))
3667 (list-points '(1063 1063 1176 1283 1659 1830 1919 2150
3668 2393 2484 2762 2853 3097 3188 3700
3669 3903 4009)))
3670 ;; markdown-inline-code-at-point-p should not modify match data
3671 (set-match-data orig-match-data)
3672 ;; Not list items
3673 (dolist (pos not-list-points)
3674 (goto-char pos)
3675 (should-not (markdown-list-item-at-point-p))
3676 (should (equal (match-data) orig-match-data)))
3677 ;; List items
3678 (dolist (pos list-points)
3679 (goto-char pos)
3680 (should (markdown-list-item-at-point-p))
3681 (should (equal (match-data) orig-match-data))))))
3683 (ert-deftest test-markdown-parsing/heading-at-point ()
3684 "Test `markdown-heading-at-point'."
3685 (save-match-data
3686 (markdown-test-file "outline.text"
3687 (should-not (markdown-heading-at-point))
3688 (markdown-test-goto-heading "An underline-style header")
3689 (forward-line -1)
3690 (should (markdown-heading-at-point))
3691 (should (equal (match-data t) (get-text-property (point) 'markdown-heading)))
3692 (should (equal (match-data t) (get-text-property (point) 'markdown-heading-1-setext))))))
3694 (ert-deftest test-markdown-parsing/inline-link-in-code-block ()
3695 "Test `markdown-match-generic-links'."
3696 (markdown-test-string " **bold**
3697 _italic_
3698 <!-- comment -->
3699 [link](url)
3700 * list"
3701 (goto-char (point-min))
3702 ;; The link inside the pre block should not match.
3703 (should-not (markdown-match-generic-links (point-max) nil))
3704 ;; Point should be left at limit.
3705 (should (= (point) (point-max)))))
3707 (ert-deftest test-markdown-parsing/broken-inline-link ()
3708 "Test `markdown-match-generic-links' with an invalid link."
3709 (markdown-test-string "[site1](http://site1.com
3710 [site2](http://site2.com)
3711 [site3](http://site3.com)"
3712 (goto-char (point-min))
3713 (let ((limit (point-at-eol)))
3714 ;; The first link is broken and shouldn't match.
3715 (should-not (markdown-match-generic-links limit nil))
3716 ;; Subsequent search shouldn't match, so point should move to limit.
3717 (should (= (point) limit)))
3718 ;; The second link should still match, starting from (point-min).
3719 (let ((limit (point-at-eol 2)))
3720 (should (markdown-match-generic-links limit nil))
3721 (should (= (point) (match-end 0))))
3722 ;; The third link should match when starting past the second one.
3723 (goto-char (match-end 0))
3724 (should (markdown-match-generic-links (point-max) nil))
3725 (should (= (point) (match-end 0)))))
3727 (ert-deftest test-markdown-parsing/code-block-lang ()
3728 "Test `markdown-code-block-lang'."
3729 ;; Test with GFM code blocks.
3730 (markdown-test-file "GFM.md"
3731 ;; Test a call with the optional argument.
3732 (should (string-equal
3733 (markdown-code-block-lang
3734 '(1455 . markdown-gfm-block-begin)) "js"))
3735 ;; Test a call without the optional argument.
3736 (goto-char 1504) ;; middle of a GFM code block
3737 (should (string-equal (markdown-code-block-lang) "js")))
3738 ;; Test with tilde-fenced cdoe blocks.
3739 (markdown-test-file "outline-code.text"
3740 (goto-char 107) ;; middle of a tilde fenced code block
3741 (should (string-equal (markdown-code-block-lang
3742 '(83 . markdown-tilde-fence-begin)) "bash"))))
3744 (ert-deftest test-markdown-parsing/code-block-lang-period ()
3745 "Test `markdown-code-block-lang' when language name begins with a period."
3746 (markdown-test-string "~~~ { .ruby }
3747 puts 'hello, world'
3750 (should (string-equal (markdown-code-block-lang) "ruby"))))
3752 ;;; Reference Checking:
3754 (ert-deftest test-markdown-references/goto-line-button ()
3755 "Create and test a goto line button."
3756 (markdown-test-string "line 1\nline 2\n"
3757 ;; Store the temporary buffer with the text
3758 (let ((target (current-buffer)))
3759 ;; Create a new buffer for inserting
3760 (with-temp-buffer
3761 ;; Verify that point is in a different buffer
3762 (should (not (equal (current-buffer) target)))
3763 ;; Insert and press the button
3764 (insert-button "goto line 2"
3765 :type 'markdown-goto-line-button
3766 'target-buffer target
3767 'target-line 2)
3768 (should (string-equal (buffer-string) "goto line 2"))
3769 (backward-button 1)
3770 (call-interactively 'push-button)
3771 ;; Verify that point is on line 2 of target buffer
3772 (should (= (line-number-at-pos) 2))
3773 (should (looking-at "line 2"))
3774 (should (equal (current-buffer) target))))))
3776 (ert-deftest test-markdown-references/button-map ()
3777 "Verify that button-buffer-map is used for check references buffer."
3778 (markdown-test-string "[undefined][ref]\n"
3779 (let* ((target (buffer-name))
3780 (check (format "*Undefined references for %s*" target)))
3781 (markdown-check-refs)
3782 (with-current-buffer (get-buffer check)
3783 (should (equal (local-key-binding (kbd "TAB")) 'forward-button))
3784 (should (equal (local-key-binding (kbd "<backtab>")) 'backward-button))))))
3786 ;;; Lists:
3788 (ert-deftest test-markdown-lists/levels-1 ()
3789 "Test list levels function `markdown-calculate-list-levels'."
3790 (markdown-test-file "nested-list.text"
3791 (let ((values '(((1 . 1) . nil) ((2 . 13) . (3)) ((14 . 23) . (7 3))
3792 ((24 . 26) . (11 7 3)))))
3793 (cl-loop for (range . value) in values
3794 do (goto-char (point-min))
3795 (forward-line (1- (car range)))
3796 (dotimes (n (- (cdr range) (car range)))
3797 (should (equal (markdown-calculate-list-levels) value))
3798 (forward-line))))))
3800 (ert-deftest test-markdown-lists/levels-2 ()
3801 "Test list levels function `markdown-calculate-list-levels'."
3802 (markdown-test-file "syntax.text"
3803 (let ((values '(((1 . 13) . nil) ((14 . 14) . (0)) ((15 . 17) . (4 0))
3804 ((18 . 18) . (0)) ((19 . 24) . (4 0)) ((25 . 25) . (0))
3805 ((26 . 29) . (4 0)) ((30 . 30) . (0)) ((31 . 33) . (4 0))
3806 ((34 . 588) . nil) ((589 . 595) . (0)) ((596 . 814) . nil)
3807 ((815 . 820) . (0)) ((821 . 898) . nil))))
3808 (cl-loop for (range . value) in values
3809 do (goto-char (point-min))
3810 (forward-line (1- (car range)))
3811 (dotimes (n (- (cdr range) (car range)))
3812 (should (equal (markdown-calculate-list-levels) value))
3813 (forward-line))))))
3815 (ert-deftest test-markdown-lists/levels-interior ()
3816 "Test `markdown-calculate-list-levels' from inside a list item."
3817 (markdown-test-file "nested-list.text"
3818 (goto-char 36)
3819 (should (equal (markdown-calculate-list-levels) (list 3)))
3820 (goto-char 267)
3821 (should (equal (markdown-calculate-list-levels) (list 7 3)))
3822 (goto-char 540)
3823 (should (equal (markdown-calculate-list-levels) (list 11 7 3)))))
3825 (ert-deftest test-markdown-lists/bounds-1 ()
3826 "Test list item bounds function `markdown-cur-list-item-bounds'."
3827 (markdown-test-file "lists.text"
3828 (markdown-test-goto-heading "Case 9")
3829 (forward-line)
3830 (should (eq (point) 3699))
3831 (markdown-next-list-item 4)
3832 (should (eq (point) 3700))
3833 (should (equal (markdown-cur-list-item-bounds)
3834 (list 3700 3901 0 4 "- " nil)))
3835 (markdown-next-list-item 4)
3836 (should (eq (point) 3903))
3837 (should (equal (markdown-cur-list-item-bounds)
3838 (list 3903 3937 0 4 "* " nil)))))
3840 (ert-deftest test-markdown-lists/bounds-2 ()
3841 "Function `markdown-cur-list-item-bounds' should return nil outside of list items."
3842 (markdown-test-string "line one\n\n* item\n"
3843 (should (null (markdown-cur-list-item-bounds)))
3844 (forward-line)
3845 (should (null (markdown-cur-list-item-bounds)))
3846 (forward-line)
3847 (should (markdown-cur-list-item-bounds))))
3849 (ert-deftest test-markdown-lists/bounds-prev ()
3850 "Test list item bounds function `markdown-prev-list-item-bounds'."
3851 (markdown-test-file "lists.text"
3852 (markdown-test-goto-heading "Case 9")
3853 (markdown-next-list-item 4)
3854 (markdown-next-list-item 4)
3855 (should (eq (point) 3903))
3856 (should (equal (markdown-prev-list-item-bounds)
3857 (list 3700 3901 0 4 "- " nil)))))
3859 (ert-deftest test-markdown-lists/bounds-next ()
3860 "Test list item bounds function `markdown-next-list-item-bounds'."
3861 (markdown-test-file "lists.text"
3862 (markdown-test-goto-heading "Case 2")
3863 (goto-char 1283)
3864 (should-not (markdown-next-list-item-bounds))
3865 (markdown-test-goto-heading "Case 9")
3866 (markdown-next-list-item 4)
3867 (should (eq (point) 3700))
3868 (should (equal (markdown-next-list-item-bounds)
3869 (list 3903 3937 0 4 "* " nil)))))
3871 (ert-deftest test-markdown-lists/bounds-gfm-task-list-item ()
3872 "Test `markdown-cur-list-item-bounds' with a GFM task list item."
3873 (markdown-test-string " - [ ] task name"
3874 (should (equal (markdown-cur-list-item-bounds)
3875 '(1 18 2 4 "- " "[ ] ")))))
3877 (ert-deftest test-markdown-lists/gfm-task-list-item-at-point-1 ()
3878 "Test `markdown-gfm-task-list-item-at-point' with regular list items."
3879 (markdown-test-file "nested-list.text"
3880 (dolist (pos '(1 26 36 267 514 540))
3881 (goto-char pos)
3882 (should-not (markdown-gfm-task-list-item-at-point)))))
3884 (ert-deftest test-markdown-lists/gfm-task-list-item-at-point-2 ()
3885 "Test `markdown-gfm-task-list-item-at-point' with a task list item."
3886 (markdown-test-string " - [ ] task"
3887 (should (markdown-gfm-task-list-item-at-point))))
3889 (ert-deftest test-markdown-insertion/insert-gfm-task-list-item ()
3890 "Test `markdown-insert-list-item' in a GFM task list."
3891 (markdown-test-string " - [ ] task"
3892 (goto-char (point-max))
3893 (call-interactively 'markdown-insert-list-item)
3894 (should (string-equal (buffer-string) " - [ ] task\n - [ ] "))))
3896 (ert-deftest test-markdown-lists/promotion-and-demotion ()
3897 "Test function `markdown-promote-list-item'."
3898 (markdown-test-file "nested-list.text"
3899 (forward-line)
3900 (should (looking-at " - List level 1 item 2
3902 Second paragraph of item 2
3904 Nested pre block in item 2
3905 Four spaces past the marker
3907 Another paragraph of item 2"))
3908 (markdown-demote-list-item)
3909 (should (looking-at " - List level 1 item 2
3911 Second paragraph of item 2
3913 Nested pre block in item 2
3914 Four spaces past the marker
3916 Another paragraph of item 2"))
3917 (markdown-promote-list-item)
3918 (should (looking-at " - List level 1 item 2
3920 Second paragraph of item 2
3922 Nested pre block in item 2
3923 Four spaces past the marker
3925 Another paragraph of item 2"))
3926 (goto-char (point-min))
3927 (forward-line 22)
3928 (should (looking-at " - List level 3 item 1
3930 Nested pre block"))
3931 (markdown-demote-list-item)
3932 (should (looking-at " - List level 3 item 1
3934 Nested pre block"))
3935 (markdown-promote-list-item)
3936 (should (looking-at " - List level 3 item 1
3938 Nested pre block"))))
3940 (ert-deftest test-markdown-lists/promotion-and-demotion-custom ()
3941 "Test custom variable `markdown-list-indent-width'."
3942 (markdown-test-file "nested-list.text"
3943 (forward-line)
3944 (should (looking-at " - List level 1 item 2
3946 Second paragraph of item 2
3948 Nested pre block in item 2
3949 Four spaces past the marker
3951 Another paragraph of item 2"))
3952 (let ((markdown-list-indent-width 2))
3953 (markdown-demote-list-item))
3954 (should (looking-at " - List level 1 item 2
3956 Second paragraph of item 2
3958 Nested pre block in item 2
3959 Four spaces past the marker
3961 Another paragraph of item 2"))))
3963 (ert-deftest test-markdown-lists/add-gfm-checkbox ()
3964 (markdown-test-file "check-items.text"
3965 (goto-char (point-min))
3966 (end-of-line)
3967 (should (markdown-insert-gfm-checkbox))
3968 (should (= (line-number-at-pos (point)) 1))
3969 (should (eolp))
3970 (should (string-equal (buffer-substring-no-properties (line-beginning-position) (point))
3971 " * [ ] "))
3973 (forward-line 2)
3974 (back-to-indentation)
3975 (should (markdown-insert-gfm-checkbox))
3976 (should (= (line-number-at-pos (point)) 3))
3977 (should (string-equal (buffer-substring-no-properties (line-beginning-position) (point))
3978 " * [ ] "))
3979 (should (string-equal (buffer-substring-no-properties (point) (line-end-position))
3980 "item1"))
3982 (forward-line 2)
3983 (back-to-indentation)
3984 (forward-char 1)
3985 (should (markdown-insert-gfm-checkbox))
3986 (should (= (line-number-at-pos (point)) 5))
3987 (should (string-equal (buffer-substring-no-properties (line-beginning-position) (point))
3988 " * [ ] i"))
3989 (should (string-equal (buffer-substring-no-properties (point) (line-end-position))
3990 "tem2"))
3992 (forward-line 2)
3993 (back-to-indentation)
3994 (forward-char 2)
3995 (should (markdown-insert-gfm-checkbox))
3996 (should (= (line-number-at-pos (point)) 7))
3997 (should (string-equal (buffer-substring-no-properties (line-beginning-position) (point))
3998 "- [ ] "))
3999 (should (string-equal (buffer-substring-no-properties (point) (line-end-position))
4000 "item3"))
4002 (forward-line 2)
4003 (back-to-indentation)
4004 (forward-char 3)
4005 (should (markdown-insert-gfm-checkbox))
4006 (should (= (line-number-at-pos (point)) 9))
4007 (should (string-equal (buffer-substring-no-properties (line-beginning-position) (point))
4008 "- [ ] i"))
4009 (should (string-equal (buffer-substring-no-properties (point) (line-end-position))
4010 "tem4"))
4012 (forward-line 2)
4013 (end-of-line)
4014 (should-not (markdown-insert-gfm-checkbox))
4015 (should (= (line-number-at-pos (point)) 11))
4016 (should (eolp))
4017 (should (string-equal (buffer-substring-no-properties (line-beginning-position) (point))
4018 "* [ ] item5"))
4020 (forward-line 1)
4021 (back-to-indentation)
4022 (should (markdown-insert-gfm-checkbox))
4023 (should (= (line-number-at-pos (point)) 12))
4024 (should (eolp))
4025 (should (string-equal (buffer-substring-no-properties
4026 (line-beginning-position)
4027 (point))
4028 "* [ ] "))))
4030 (ert-deftest test-markdown-lists/toggle-gfm-checkbox ()
4031 (markdown-test-string " - [X] GFM task list item"
4032 (should (string-equal (markdown-toggle-gfm-checkbox) "[ ]"))
4033 (should (string-equal (buffer-string) " - [ ] GFM task list item"))
4034 (should (string-equal (markdown-toggle-gfm-checkbox) "[x]"))
4035 (should (string-equal (buffer-string) " - [x] GFM task list item"))))
4037 (ert-deftest test-markdown-lists/beginning-of-list ()
4038 "Test `markdown-beginning-of-list'."
4039 (markdown-test-file "lists.text"
4040 ;; Case 1: not in a list
4041 (goto-char 399)
4042 (should-not (markdown-beginning-of-list))
4043 (should (= (point) 399))
4044 ;; Case 2
4045 (goto-char 1281)
4046 (should (= (markdown-beginning-of-list) 1063))
4047 (should (= (point) 1063))
4048 (goto-char 1395)
4049 (should (= (markdown-beginning-of-list) 1063))
4050 (should (= (point) 1063))
4051 ;; Case 3
4052 (goto-char 1848)
4053 (should (= (markdown-beginning-of-list) 1659))
4054 (should (= (point) 1659))
4055 ;; Case 4
4056 (goto-char 2041)
4057 (should (= (markdown-beginning-of-list) 1919))
4058 (should (= (point) 1919))
4059 ;; Case 8
4060 (goto-char 3553)
4061 (should (= (markdown-beginning-of-list) 3096))
4062 (should (= (point) 3096))))
4064 (ert-deftest test-markdown-lists/end-of-list ()
4065 "Test `markdown-end-of-list'."
4066 (markdown-test-file "lists.text"
4067 ;; Case 1: not in a list
4068 (goto-char 399)
4069 (should-not (markdown-end-of-list))
4070 (should (= (point) 399))
4071 ;; Case 2
4072 (goto-char 1281)
4073 (should (= (markdown-end-of-list) 1396))
4074 (should (= (point) 1396))
4075 (goto-char 1395)
4076 (should (= (markdown-end-of-list) 1396))
4077 (should (= (point) 1396))
4078 ;; Case 3
4079 (goto-char 1659)
4080 (should (= (markdown-end-of-list) 1849))
4081 (should (= (point) 1849))
4082 ;; Case 4
4083 (goto-char 2041)
4084 (should (= (markdown-end-of-list) 2092))
4085 (should (= (point) 2092))
4086 ;; Case 8
4087 (goto-char 3553)
4088 (should (= (markdown-end-of-list) 3614))
4089 (should (= (point) 3614))))
4091 (ert-deftest test-markdown-lists/up-list ()
4092 "Test `markdown-up-list'."
4093 (markdown-test-file "nested-list.text"
4094 (goto-char 581)
4095 (should (= (markdown-up-list) 484))
4096 (should (= (point) 484))
4097 (should (= (markdown-up-list) 191))
4098 (should (= (point) 191))
4099 ;; Return nil upon failure, but move out of list.
4100 (should-not (markdown-up-list))
4101 (should (= (point) (point-min)))))
4103 ;;; Outline minor mode tests:
4105 (ert-deftest test-markdown-outline/navigation ()
4106 "Test outline navigation functions."
4107 (markdown-test-file "outline.text"
4108 ;; Navigate to the first visible heading
4109 (markdown-next-visible-heading 1)
4110 (should (eq (point) 19))
4111 (should (looking-at "^# A top-level header"))
4112 ;; Navigate forward at the same level
4113 (markdown-forward-same-level 1)
4114 (should (eq (point) 351))
4115 (should (looking-at "^An underline-style header$"))
4116 ;; Navigate backward by four visible headings
4117 (markdown-previous-visible-heading 4)
4118 (should (eq (point) 69))
4119 (should (looking-at "^## A second-level header$"))
4120 ;; Navigate up the hierarchy (atx)
4121 (call-interactively #'markdown-up-heading)
4122 (should (looking-at "^# A top-level header"))
4123 (should (eq (mark) 69))
4124 ;; Navigate up the hierarchy (setext)
4125 (goto-char 516)
4126 (call-interactively #'markdown-up-heading)
4127 (should (looking-at "^An underline-style header$"))
4128 (should (eq (mark) 516))
4129 ;; Navigate back in the outline (setext to atx)
4130 (forward-line) ;; move to setext underline
4131 (markdown-backward-same-level 1)
4132 (should (looking-at "^# A top-level header"))))
4134 (ert-deftest test-markdown-outline/navigation-with-code ()
4135 "Test outline navigation functions with code blocks."
4136 (markdown-test-file "outline-code.text"
4137 ;; Navigate forward at the same level
4138 (markdown-forward-same-level 1)
4139 (should (eq (point) 159))
4140 (should (looking-at "^# Level one again"))))
4142 (ert-deftest test-markdown-outline/back-to-heading-over-code-block ()
4143 "Test `markdown-back-to-heading-over-code-block' over."
4144 (markdown-test-file "outline-code.text"
4145 ;; Initialize match data to known quantity.
4146 (set-match-data '(1 2 3 4))
4147 (should (equal (match-data t) '(1 2 3 4)))
4148 ;; Function should navigate back over code blocks.
4149 (re-search-forward "^# In a code block")
4150 (should (= (markdown-back-to-heading-over-code-block) 69))
4151 ;; Match data should be set for markdown-regex-header.
4152 (should (equal (match-data t) (get-text-property (point) 'markdown-heading)))
4153 ;; Function should return t when at a heading.
4154 (should (equal (markdown-back-to-heading-over-code-block) t))
4155 ;; Insert some text before the first heading.
4156 (goto-char (point-min))
4157 (save-excursion (insert "foo\n\n"))
4158 ;; Function should throw an error if no previous heading.
4159 (should-error (markdown-back-to-heading-over-code-block))
4160 ;; Function should return nil without error if NO-ERROR is non-nil.
4161 (should-not (markdown-back-to-heading-over-code-block t t))))
4163 (ert-deftest test-markdown-outline/visibility-atx ()
4164 "Test outline visibility cycling for ATX-style headers."
4165 (markdown-test-file "outline.text"
4166 (let (last-command this-command)
4167 ;; Navigate to the second visible heading
4168 (markdown-next-visible-heading 2)
4169 (should (eq (point) 69))
4170 (should (looking-at "^## A second-level header$"))
4171 ;; Cycle visibility of this subtree
4172 (setq this-command 'markdown-cycle)
4173 (markdown-cycle)
4174 (setq last-command 'markdown-cycle)
4175 (should (eq (point) 69))
4176 (should (looking-at "^## A second-level header$"))
4177 ;; Test that the entire subtree is invisible
4178 (markdown-test-range-has-property 93 349 'invisible 'outline)
4179 ;; Cycle visibility of this subtree again
4180 (markdown-cycle)
4181 (should (eq (point) 69))
4182 (should (looking-at "^## A second-level header$"))
4183 ;; Test that text is visible
4184 (markdown-test-range-has-property 95 121 'invisible nil)
4185 ;; Test that subheadings are visible
4186 (markdown-test-range-has-property 123 141 'invisible nil)
4187 ;; Cycle visibility of this subtree again
4188 (markdown-cycle)
4189 (should (eq (point) 69))
4190 (should (looking-at "^## A second-level header$"))
4191 ;; Verify that entire subtree is visible
4192 (markdown-test-range-has-property 93 349 'invisible nil))))
4194 (ert-deftest test-markdown-outline/visibility-setext ()
4195 "Test outline visibility cycling for setext-style headers."
4196 (markdown-test-file "outline.text"
4197 ;; Navigate to the sixth visible heading
4198 (markdown-next-visible-heading 7)
4199 (markdown-previous-visible-heading 1)
4200 (should (looking-at markdown-regex-header))
4201 (should (string-equal (match-string-no-properties 1) "An underline-style header"))
4202 (should (string-equal (match-string-no-properties 2) "========================="))
4203 ;; Cycle visibility subtree, test that it's invisible
4204 (markdown-cycle)
4205 (markdown-test-range-has-property 404 515 'invisible 'outline)
4206 ;; Cycle visibility subtree, test that text and headers are visible
4207 (markdown-cycle)
4208 (markdown-test-range-has-property 404 417 'invisible nil)
4209 (markdown-test-range-has-property 420 451 'invisible nil)))
4211 (ert-deftest test-markdown-outline/visibility-with-code ()
4212 "Test outline visibility cycling with code blocks."
4213 (markdown-test-file "outline-code.text"
4214 (let (last-command this-command)
4215 ;; Cycle global visibility to "overview" mode
4216 (setq this-command 'markdown-cycle)
4217 (markdown-cycle t)
4218 (setq last-command 'markdown-cycle)
4219 (should (eq (point) (point-min)))
4220 (should (looking-at "^# Level one"))
4221 ;; Test that the code block is invisible
4222 (markdown-test-range-has-property 83 157 'invisible 'outline)
4223 ;; Check subsequent headings
4224 (outline-next-visible-heading 1)
4225 (should (eq (point) 69))
4226 (should (looking-at "^## Level two"))
4227 (outline-next-visible-heading 1)
4228 (should (eq (point) 159))
4229 (should (looking-at "^# Level one again")))))
4231 (ert-deftest test-markdown-outline/visibility-with-metadata ()
4232 "Test outline visibility cycling with metadata blocks."
4233 (markdown-test-string
4234 "---
4235 layout = post
4236 date = 2015-08-13 11:35:25 EST
4239 (let (last-command this-command)
4240 ;; Cycle global visibility to "overview" mode
4241 (setq this-command 'markdown-cycle)
4242 (markdown-cycle t)
4243 ;; Check that text is visible
4244 (markdown-test-range-has-property (point-min) (point-max) 'invisible nil))))
4246 (ert-deftest test-markdown-outline/level ()
4247 "Test `markdown-outline-level'."
4248 (markdown-test-file "outline.text"
4249 (markdown-next-heading)
4250 (should (= (markdown-outline-level) 1))
4251 (markdown-forward-same-level 1)
4252 (should (= (markdown-outline-level) 1))
4253 (markdown-next-heading)
4254 (should (= (markdown-outline-level) 2))
4255 (markdown-next-heading)
4256 (should (= (markdown-outline-level) 1))
4257 (markdown-next-heading)
4258 (should (= (markdown-outline-level) 2))))
4260 ;;; Movement tests:
4262 (ert-deftest test-markdown-movement/defun ()
4263 "Test defun navigation."
4264 (markdown-test-file "outline.text"
4265 ;; end-of-defun should go to point-max
4266 (end-of-defun 10)
4267 (should (= (point) (point-max)))
4268 ;; end-of-defun should stop just before the next header
4269 (goto-char (point-min))
4270 (end-of-defun)
4271 (should (looking-at "\n# A top-level header"))
4272 (end-of-defun)
4273 (should (looking-at "\n## A second-level header"))
4274 (end-of-defun)
4275 (should (looking-at "\n### Third level ###"))
4276 (end-of-defun)
4277 (should (looking-at "\n### Third level number two ###"))
4278 ;; beginning-of-defun should move to the start of the previous header
4279 (beginning-of-defun)
4280 (should (looking-at "### Third level ###"))
4281 (beginning-of-defun)
4282 (should (looking-at "## A second-level header"))
4283 (beginning-of-defun)
4284 (should (looking-at "# A top-level header"))
4285 (beginning-of-defun)
4286 ;; beginning-of-defun should move up to point-min
4287 (should (= (point) (point-min)))
4288 ;; (beginning-of-defun -1) should move to the start of the next header
4289 (forward-line 2)
4290 (beginning-of-defun -1)
4291 (should (looking-at "## A second-level header"))
4292 (beginning-of-defun -1)
4293 (should (looking-at "### Third level ###"))
4294 (beginning-of-defun -1)
4295 (should (looking-at "### Third level number two ###"))))
4297 (ert-deftest test-markdown-movement/beginning-of-defun-at-point-max ()
4298 "Test beginning of defun navigation at point-max."
4299 (markdown-test-file "outline.text"
4300 (goto-char (point-max))
4301 (beginning-of-defun)))
4303 (ert-deftest test-markdown-movement/text-block ()
4304 "Test plain text block movement."
4305 (markdown-test-file "outline.text"
4306 (markdown-end-of-text-block)
4307 (should (looking-at "\n# A top-level header"))
4308 (markdown-end-of-text-block)
4309 (should (looking-at "\nfollowed by some body text"))
4310 (markdown-end-of-text-block)
4311 (should (looking-at "\n## A second-level header"))
4312 (markdown-end-of-text-block)
4313 (should (looking-at "\nfollowed by some body text"))
4314 (markdown-end-of-text-block)
4315 (should (looking-at "\n### Third level ###"))
4316 (markdown-end-of-text-block)
4317 (should (looking-at "\n\\* A list item"))
4318 (markdown-end-of-text-block)
4319 (should (looking-at "\n### Third level number two ###"))
4320 (markdown-end-of-text-block)
4321 (should (looking-at "\n### Level two again"))
4322 (markdown-end-of-text-block)
4323 (should (looking-at "\nfollowed by some body text"))
4325 (markdown-test-goto-heading "Level two")
4326 (markdown-end-of-text-block)
4327 (should (looking-at "\nbar"))
4328 (markdown-end-of-text-block)
4329 (should (= (point) (point-max)))
4330 (markdown-beginning-of-text-block)
4331 (should (looking-at "bar"))
4332 (markdown-beginning-of-text-block)
4333 (should (looking-at "## Level two"))
4334 (markdown-beginning-of-text-block)
4335 (should (looking-at "foo"))
4336 (markdown-beginning-of-text-block)
4337 (should (looking-at "# Level one"))
4338 (markdown-beginning-of-text-block)
4339 (should (looking-at "* With"))
4340 (markdown-beginning-of-text-block)
4341 (should (looking-at "And a level two underline header"))
4343 (goto-char (point-min))
4344 (markdown-test-goto-heading "A top-level header")
4345 (beginning-of-line)
4346 (markdown-beginning-of-text-block)
4347 (should (= (point) (point-min)))))
4349 (ert-deftest test-markdown-movement/mark-text-block ()
4350 "Test `markdown-mark-text-block'."
4351 (markdown-test-file "outline.text"
4352 ;; Start in middle of nested list with no separating whitespace.
4353 (goto-char 193)
4354 (markdown-mark-text-block)
4355 (should (= (point) 143))
4356 (should (= (mark) 269))))
4358 (ert-deftest test-markdown-movement/paragraph ()
4359 "Test Markdown paragraph movement."
4360 (markdown-test-file "outline.text"
4361 (markdown-forward-paragraph)
4362 (should (looking-at "\n# A top-level header"))
4363 (markdown-forward-paragraph)
4364 (should (looking-at "\nfollowed by some body text"))
4365 (markdown-forward-paragraph)
4366 (should (looking-at "\n## A second-level header"))
4367 (markdown-forward-paragraph)
4368 (should (looking-at "\nfollowed by some body text"))
4369 (markdown-forward-paragraph)
4370 (should (looking-at "\n### Third level ###"))
4371 (markdown-forward-paragraph)
4372 (should (looking-at "\n\\* A list item"))
4373 (markdown-forward-paragraph)
4374 (should (looking-at "\\* and another"))
4375 (markdown-forward-paragraph)
4376 (should (looking-at " \\+ and a sublist"))
4377 (markdown-forward-paragraph)
4378 (should (looking-at "- And a third"))
4379 (markdown-forward-paragraph)
4380 (should (looking-at "\n### Third level number two ###"))
4381 (markdown-forward-paragraph)
4382 (should (looking-at "\n### Level two again"))
4383 (markdown-forward-paragraph)
4384 (should (looking-at "\nfollowed by some body text"))
4386 (markdown-test-goto-heading "Level two")
4387 (markdown-forward-paragraph)
4388 (should (looking-at "\nbar"))
4389 (markdown-forward-paragraph)
4390 (should (= (point) (point-max)))
4391 (markdown-backward-paragraph)
4392 (should (looking-at "bar"))
4393 (markdown-backward-paragraph)
4394 (should (looking-at "## Level two"))
4395 (markdown-backward-paragraph)
4396 (should (looking-at "foo"))
4397 (markdown-backward-paragraph)
4398 (should (looking-at "# Level one"))
4399 (markdown-backward-paragraph)
4400 (should (looking-at "\\* List"))
4401 (markdown-backward-paragraph)
4402 (should (looking-at "\\* an unordered"))
4403 (markdown-backward-paragraph)
4404 (should (looking-at "\\* With"))
4405 (markdown-backward-paragraph)
4406 (should (looking-at "And a level two underline header"))
4408 (goto-char (point-min))
4409 (markdown-test-goto-heading "A top-level header")
4410 (beginning-of-line)
4411 (markdown-backward-paragraph)
4412 (should (= (point) (point-min)))))
4414 (ert-deftest test-markdown-movement/forward-paragraph-with-whitespace ()
4415 "Test Markdown paragraph movement."
4416 (markdown-test-file "blocks.md"
4417 (markdown-test-goto-heading "With Whitespace")
4418 (dolist (pos '(58 67 78 94 109 114 123 131 135 147 157 170 184 199))
4419 (markdown-forward-paragraph)
4420 (should (= (point) pos)))))
4422 (ert-deftest test-markdown-movement/backward-paragraph-with-whitespace ()
4423 "Test Markdown paragraph movement."
4424 (markdown-test-file "blocks.md"
4425 (markdown-test-goto-heading "With Whitespace")
4426 (markdown-next-heading)
4427 (should (= (point) 200))
4428 (dolist (pos '(185 172 158 148 136 132 124 115 110 94 78 67 59))
4429 (markdown-backward-paragraph)
4430 (should (= (point) pos)))))
4432 (ert-deftest test-markdown-movement/forward-paragraph-without-whitespace ()
4433 "Test Markdown paragraph movement."
4434 (markdown-test-file "blocks.md"
4435 (markdown-test-goto-heading "Without Whitespace")
4436 (dolist (pos '(222 230 240 255 270 275 283 291 294 305 314 326 340 354))
4437 (markdown-forward-paragraph)
4438 (should (= (point) pos)))))
4440 (ert-deftest test-markdown-movement/backward-paragraph-without-whitespace ()
4441 "Test Markdown paragraph movement."
4442 (markdown-test-file "blocks.md"
4443 (goto-char (point-max))
4444 (dolist (pos '(340 328 314 305 294 291 284 275 271 255 240 230 223 200))
4445 (markdown-backward-paragraph)
4446 (should (= (point) pos)))))
4448 (ert-deftest test-markdown-movement/block ()
4449 "Test Markdown block movement."
4450 (markdown-test-file "outline.text"
4451 (markdown-forward-block)
4452 (should (looking-at "\n# A top-level header"))
4453 (markdown-forward-block)
4454 (should (looking-at "\nfollowed by some body text"))
4455 (markdown-forward-block)
4456 (should (looking-at "\n## A second-level header"))
4457 (markdown-forward-block)
4458 (should (looking-at "\nfollowed by some body text"))
4459 (markdown-forward-block)
4460 (should (looking-at "\n### Third level ###"))
4461 (markdown-forward-block)
4462 (should (looking-at "\n\\* A list item"))
4463 (markdown-forward-block)
4464 (should (looking-at "\n### Third level number two ###"))
4465 (markdown-forward-block)
4466 (should (looking-at "\n### Level two again"))
4467 (markdown-forward-block)
4468 (should (looking-at "\nfollowed by some body text"))
4470 (markdown-test-goto-heading "Level two")
4471 (markdown-forward-block)
4472 (should (looking-at "\nbar"))
4473 (markdown-forward-block)
4474 (should (= (point) (point-max)))
4475 (markdown-backward-block)
4476 (should (looking-at "bar"))
4477 (markdown-backward-block)
4478 (should (looking-at "## Level two"))
4479 (markdown-backward-block)
4480 (should (looking-at "foo"))
4481 (markdown-backward-block)
4482 (should (looking-at "# Level one"))
4483 (markdown-backward-block)
4484 (should (looking-at "\\* With"))
4485 (markdown-backward-block)
4486 (should (looking-at "And a level two underline header"))
4488 (goto-char (point-min))
4489 (markdown-test-goto-heading "A top-level header")
4490 (beginning-of-line)
4491 (markdown-backward-block)
4492 (should (= (point) (point-min)))))
4494 (ert-deftest test-markdown-movement/forward-block-with-whitespace ()
4495 "Test Markdown block movement."
4496 (markdown-test-file "blocks.md"
4497 (markdown-test-goto-heading "With Whitespace")
4498 (dolist (pos '(58 109 114 131 135 147 157 184 199))
4499 (markdown-forward-block)
4500 (should (= (point) pos)))))
4502 (ert-deftest test-markdown-movement/backward-block-with-whitespace ()
4503 "Test Markdown block movement."
4504 (markdown-test-file "blocks.md"
4505 (markdown-test-goto-heading "With Whitespace")
4506 (markdown-next-heading)
4507 (dolist (pos '(185 158 148 136 132 115 110 59))
4508 (markdown-backward-block)
4509 (should (= (point) pos)))))
4511 (ert-deftest test-markdown-movement/forward-block-without-whitespace ()
4512 "Test Markdown block movement."
4513 (markdown-test-file "blocks.md"
4514 (markdown-test-goto-heading "Without Whitespace")
4515 (dolist (pos '(222 270 275 291 294 305 314 340 354))
4516 (markdown-forward-block)
4517 (should (= (point) pos)))))
4519 (ert-deftest test-markdown-movement/backward-block-without-whitespace ()
4520 "Test Markdown block movement."
4521 (markdown-test-file "blocks.md"
4522 (goto-char (point-max))
4523 (dolist (pos '(340 314 305 294 291 275 271 223 200))
4524 (markdown-backward-block)
4525 (should (= (point) pos)))))
4527 (ert-deftest test-markdown-movement/page ()
4528 "Test Markdown page movement."
4529 (markdown-test-file "outline.text"
4530 (markdown-forward-page)
4531 (should (looking-at "# A top-level header"))
4532 (markdown-forward-page)
4533 (should (looking-at "An underline-style header"))
4534 (markdown-forward-page)
4535 (should (looking-at "# Level one"))
4536 (markdown-forward-page)
4537 (should (eobp))
4538 (markdown-backward-page)
4539 (should (looking-at "# Level one"))
4540 (markdown-backward-page)
4541 (should (looking-at "An underline-style header"))
4542 (markdown-backward-page)
4543 (should (looking-at "# A top-level header"))
4544 (markdown-backward-page)
4545 (should (bobp))))
4547 (ert-deftest test-markdown-movement/blockquote-paragraphs ()
4548 "Test filling of blockquotes containing multiple paragraphs."
4549 (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"
4550 (forward-paragraph)
4551 (should (looking-at "^>$"))
4552 (should (= (point) 128))
4553 (forward-paragraph)
4554 (should (= (point) (point-max)))))
4556 (ert-deftest test-markdown-movement/reference-definition ()
4557 "Test jumping to reference definitions."
4558 ;; Jumping to explicit reference definition
4559 (markdown-test-string "[a][ref]\n\n[ref]: gopher://localhost/\n"
4560 (markdown-reference-goto-definition)
4561 (should (= (point) 18)))
4562 ;; Jumping to implicit reference definition
4563 (markdown-test-string "[a][]\n\n[a]: ftp://localhost/\n"
4564 (markdown-reference-goto-definition)
4565 (should (= (point) 13)))
4566 ;; Creating non-existent reference definition
4567 (markdown-test-string "[a][]\n"
4568 (markdown-reference-goto-definition)
4569 (should (= (point) 13))
4570 (should (string-equal (buffer-string) "[a][]\n\n[a]: \n"))))
4572 (ert-deftest test-markdown-movement/back-to-same-level-over-code-block ()
4573 "`markdown-backward-same-level' over code block which contains header
4574 like statement. Detail: https://github.com/jrblevin/markdown-mode/issues/75"
4575 (markdown-test-string "
4576 ## Header 2-1
4578 ## Header 2-2
4580 ```R
4581 # Header Like Statement
4584 ## Header 2-3
4586 (search-forward "## Header 2-3")
4587 (let ((last-header-pos (point)))
4588 (forward-line -1)
4589 (call-interactively #'markdown-backward-same-level)
4590 (should (looking-at-p "## Header 2-1"))
4592 (goto-char last-header-pos)
4593 (call-interactively #'markdown-backward-same-level)
4594 (should (looking-at-p "## Header 2-2"))
4596 (goto-char last-header-pos)
4597 (markdown-backward-same-level 2)
4598 (should (looking-at-p "## Header 2-1"))
4600 (search-forward "# Header Like Statement")
4601 (call-interactively #'markdown-backward-same-level)
4602 (should (looking-at-p "## Header 2-1")))))
4604 ;;; Link tests:
4606 (ert-deftest test-markdown-link/follow ()
4607 "Test link following in a browser and in Emacs."
4608 (markdown-test-string "[text](http://path?query=foo#id)"
4609 (let* ((opened-url nil)
4610 (browse-url-browser-function
4611 (lambda (url &rest args) (setq opened-url url))))
4612 (markdown-follow-thing-at-point nil)
4613 (should (equal opened-url "http://path?query=foo#id"))))
4614 (when (featurep 'url-parse)
4615 (markdown-test-string "[text](path?query=foo#id)"
4616 (markdown-follow-thing-at-point nil)
4617 (should (equal (file-name-nondirectory (buffer-file-name)) "path"))
4618 (kill-buffer))))
4620 (ert-deftest test-markdown-link/inline-link-at-pos ()
4621 "Test `markdown-link-at-pos' return values with an inline link."
4622 (markdown-test-string "[text](url \"title\")"
4623 (should (equal (markdown-link-at-pos (point)) '(1 20 "text" "url" nil "title" nil)))))
4625 (ert-deftest test-markdown-link/inline-image-at-pos ()
4626 "Test `markdown-link-at-pos' return values with an inline image."
4627 (markdown-test-string "![text](url \"title\")"
4628 (should (equal (markdown-link-at-pos (point)) '(1 21 "text" "url" nil "title" "!")))))
4630 (ert-deftest test-markdown-link/reference-link-at-pos ()
4631 "Test `markdown-link-at-pos' return values with a reference link."
4632 (markdown-test-string "[text][ref]"
4633 (should (equal (markdown-link-at-pos (point)) '(1 12 "text" nil "ref" nil nil)))))
4635 (ert-deftest test-markdown-link/reference-image-at-pos ()
4636 "Test `markdown-link-at-pos' return values with a reference image."
4637 (markdown-test-string "![text][ref]"
4638 (should (equal (markdown-link-at-pos (point)) '(1 13 "text" nil "ref" nil "!")))))
4640 (ert-deftest test-markdown-link/angle-uri-at-pos ()
4641 "Test `markdown-link-at-pos' return values with an angle bracket inline link."
4642 (markdown-test-string "<http://jblevins.org/projects/markdown-mode/>"
4643 (should (equal (markdown-link-at-pos (point)) '(1 46 nil "http://jblevins.org/projects/markdown-mode/" nil nil nil)))))
4645 (ert-deftest test-markdown-link/plain-uri-at-pos ()
4646 "Test `markdown-link-at-pos' return values with a plain URI."
4647 (markdown-test-string "http://jblevins.org/projects/markdown-mode/"
4648 (should (equal (markdown-link-at-pos (point)) '(1 44 nil "http://jblevins.org/projects/markdown-mode/" nil nil nil)))))
4650 (ert-deftest test-markdown-link/follow-filename ()
4651 "Test that `markdown-follow-thing-at-pos' uses
4652 `markdown-translate-filename-function' to translate filenames."
4653 (markdown-test-string "[text](/foo/bar/baz)"
4654 (cl-letf* ((visited-files ())
4655 ((symbol-function #'find-file)
4656 (lambda (filename)
4657 (push filename visited-files)))
4658 (translated-files ())
4659 (markdown-translate-filename-function
4660 (lambda (filename)
4661 (push filename translated-files)
4662 (format "/root%s.md" filename))))
4663 (markdown-follow-thing-at-point nil)
4664 (should (equal translated-files '("/foo/bar/baz")))
4665 (should (equal visited-files '("/root/foo/bar/baz.md"))))))
4667 ;;; Wiki link tests:
4669 (ert-deftest test-markdown-wiki-link/file-local-variables ()
4670 "Test enabling wiki links via file-local variables."
4671 (markdown-test-file "wiki-links.text"
4672 (should-not markdown-enable-wiki-links)
4673 (hack-local-variables)
4674 (should markdown-enable-wiki-links)))
4676 (ert-deftest test-markdown-wiki-link/aliasing ()
4677 "Test filename extraction for aliased wiki links."
4678 (let ((markdown-enable-wiki-links t))
4679 (markdown-test-file "wiki-links.text"
4680 ;; Confirm location of first wiki link
4681 (should (eq (markdown-next-link) 8))
4682 ;; Confirm location of second wiki link
4683 (should (eq (markdown-next-link) 73))
4684 ;; Test predicate function
4685 (should (markdown-wiki-link-p))
4686 ;; Test alias-first filename extraction
4687 (setq markdown-wiki-link-alias-first t)
4688 (should (string-equal (markdown-wiki-link-link) "second"))
4689 ;; Test alias-second filename extraction
4690 (setq markdown-wiki-link-alias-first nil)
4691 (should (string-equal (markdown-wiki-link-link) "first")))))
4693 (ert-deftest test-markdown-wiki-link/navigation ()
4694 "Test wiki link navigation."
4695 (let ((markdown-enable-wiki-links t))
4696 (markdown-test-file "wiki-links.text"
4697 ;; Advance to first link
4698 (should (eq (markdown-next-link) 8))
4699 ;; Advance to second link
4700 (should (eq (markdown-next-link) 73))
4701 ;; Avance to final link
4702 (should (eq (markdown-next-link) 155))
4703 ;; Return nil and don't advance point
4704 (should (eq (markdown-next-link) nil))
4705 (should (eq (point) 155))
4706 ;; Move back to second link
4707 (should (eq (markdown-previous-link) 73))
4708 ;; Move back to first link
4709 (should (eq (markdown-previous-link) 8))
4710 ;; Return nil and don't move point
4711 (should (eq (markdown-previous-link) nil))
4712 (should (eq (point) 8)))))
4714 (ert-deftest test-markdown-wiki-link/font-lock ()
4715 "Test font lock faces for wiki links."
4716 ;; If `temporary-file-directory' contains an inaccessible
4717 ;; subdirectory, `markdown-fontify-buffer-wiki-links' fails because
4718 ;; it calls `directory-files-recursively' on the directory, which
4719 ;; fails because of
4720 ;; <https://debbugs.gnu.org/cgi/bugreport.cgi?bug=28567>. To fix
4721 ;; this, we run the entire test in a new subdirectory of
4722 ;; `temporary-file-directory', which is guaranteed to not contain
4723 ;; any inaccessible directories.
4724 (let ((temporary-file-directory
4725 (file-name-as-directory (make-temp-file "markdown-test" :dir-flag))))
4726 (markdown-test-temp-file "wiki-links.text"
4727 (let* ((fn (concat (file-name-directory buffer-file-name)
4728 "inline.text"))
4729 (markdown-enable-wiki-links t))
4730 ;; Create inline.text in the same temp directory, refontify
4731 (write-region "" nil fn nil 1)
4732 (markdown-fontify-buffer-wiki-links)
4733 ;; Confirm location of first wiki link
4734 (should (eq (markdown-next-link) 8))
4735 ;; First wiki link doesn't have a corresponding file
4736 (markdown-test-range-has-property 8 20 'font-lock-face markdown-missing-link-face)
4737 ;; Second wiki link doesn't have a corresponding file
4738 (should (eq (markdown-next-link) 73))
4739 (markdown-test-range-has-property 73 88 'font-lock-face markdown-missing-link-face)
4740 ;; Move to third wiki link, and create the missing file
4741 (should (eq (markdown-next-link) 155))
4742 (should (string-equal (markdown-wiki-link-link) "inline"))
4743 (markdown-test-range-has-property 155 164 'font-lock-face markdown-link-face)
4744 ;; Check wiki links in code blocks
4745 (markdown-test-range-has-face 360 395 markdown-pre-face)
4746 ;; Remove temporary files
4747 (delete-file fn)))
4748 (delete-directory temporary-file-directory)))
4750 (ert-deftest test-markdown-wiki-link/kill ()
4751 "Simple tests for `markdown-kill-thing-at-point' for wiki links."
4752 (let ((kill-ring nil)
4753 (markdown-enable-wiki-links t)
4754 (tests (list '("[[foo]]" . "foo")
4755 '("[[foo|bar]]" . "bar"))))
4756 (dolist (test tests)
4757 ;; Load test string (the car), move to end of first line, kill
4758 ;; thing at point, and then verify that the kill ring contains cdr.
4759 (markdown-test-string (car test)
4760 (end-of-line)
4761 (call-interactively 'markdown-kill-thing-at-point)
4762 (should (string-equal (current-kill 0) (cdr test)))))))
4764 ;;; Filling tests:
4766 (ert-deftest test-markdown-filling/blockquote ()
4767 "Test filling of blockquotes.
4768 See `adaptive-fill-first-line-regexp'."
4769 (markdown-test-string "> Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
4770 (fill-paragraph)
4771 (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."))))
4773 (ert-deftest test-markdown-filling/blockquote-paragraphs ()
4774 "Test filling of blockquotes containing multiple paragraphs."
4775 (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"
4776 (forward-paragraph)
4777 (fill-paragraph)
4778 (should (string-equal (buffer-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\n> nisi ut aliquip ex ea commodo consequat.\n"))))
4780 (ert-deftest test-markdown-filling/leanpub-block ()
4781 "Test adaptive filling of Leanpub blocks."
4782 (markdown-test-string "A> Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
4783 (fill-paragraph)
4784 (should (string-equal (buffer-string) "A> Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do\nA> eiusmod tempor incididunt ut labore et dolore magna aliqua."))))
4786 (ert-deftest test-markdown-filling/space-after-list-marker ()
4787 "`fill-paragraph' should preserve more than one space after a list marker,
4788 since users may wish to indent their lists more than one space more than the
4789 width of the marker. The examples on the Markdown Syntax page have three
4790 spaces after the list marker for a total indentation of four."
4791 (let ((str "\n\n* List item indented four spaces.\n* Also four spaces."))
4792 (markdown-test-string str
4793 (forward-line 2)
4794 (fill-paragraph)
4795 (should (string-equal (buffer-string) str)))))
4797 (ert-deftest test-markdown-filling/multi-line-list-with-more-space ()
4798 "`fill-paragraph' should preserve more than one space after a list marker
4799 (see `test-preserve-space-after-list-marker')."
4800 (let ((str "* This list item is continued on\n the next line"))
4801 (markdown-test-string str
4802 ;; The first line is exactly 35 columns
4803 (let ((fill-column 35))
4804 (fill-paragraph)
4805 (should (string-equal (buffer-string) str))))))
4807 (ert-deftest test-markdown-filling/definition-list-add-leading-spaces ()
4808 "`fill-paragraph' should adapt to spaces after list marker."
4809 (markdown-test-string
4810 ": This list item is continued on the next line"
4811 (let ((fill-column 35))
4812 (fill-paragraph)
4813 (should (string-equal
4814 (buffer-string)
4815 ": This list item is continued on\n the next line")))))
4817 (ert-deftest test-markdown-filling/definition-list-preserve-leading-spaces ()
4818 "`fill-paragraph' should preserve spaces after list marker."
4819 (let ((str ": This list item is continued on\n the next line")
4820 (fill-column 35))
4821 (markdown-test-string
4822 str (fill-paragraph)
4823 (should (string-equal (buffer-string) str)))))
4825 (ert-deftest test-markdown-filling/list-item-plus ()
4826 "Test filling of list items with plus sign markers.
4827 See `adaptive-fill-regexp'."
4828 (markdown-test-string " + Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
4829 (fill-paragraph)
4830 (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."))))
4832 (ert-deftest test-markdown-filling/list-item-plus-in-blockquote ()
4833 "Test filling of list items with plus sign markers inside blockquote.
4834 See `adaptive-fill-regexp'."
4835 (markdown-test-string "> + Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
4836 (fill-paragraph)
4837 (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."))))
4839 (ert-deftest test-markdown-filling/line-break ()
4840 "Test filling of paragraphs with hard line breaks.
4841 See `paragraph-separate'."
4842 (markdown-test-string "Lorem ipsum dolor sit amet, \nconsectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
4843 (let ((fill-column 70))
4844 (fill-paragraph)
4845 (should (string-equal (buffer-string) "Lorem ipsum dolor sit amet, \nconsectetur adipisicing elit, sed do eiusmod tempor incididunt ut\nlabore et dolore magna aliqua.")))))
4847 (ert-deftest test-markdown-filling/decimal-number-at-beginning ()
4848 "Test filling when a number with a decimal appears at the beginning of a line."
4849 (markdown-test-string "The circumference of a circle divided by it's radius is around\n3.14."
4850 (fill-paragraph)
4851 (should (string-equal (buffer-string) "The circumference of a circle divided by it's radius is around 3.14."))))
4853 (ert-deftest test-markdown-filling/avoid-unintended-list-item ()
4854 "Avoid breaking lines where it would result in an unintended list item."
4855 (markdown-test-string "Lorem ipsum dolor sit 4. amet"
4856 (let ((fill-column 22))
4857 (fill-paragraph)
4858 (should (string-equal (buffer-string) "Lorem ipsum dolor\nsit 4. amet")))))
4860 (ert-deftest test-markdown-filling/no-break-link-reference ()
4861 "Shouldn't break line between label and url, or combine two link references."
4862 (let ((str "[label1]: http://long-url.example.com\n[label2]: http://another-long-url.example.com/"))
4863 (markdown-test-string str
4864 (let ((fill-column 15)) ; after end of label, before end of URL
4865 (fill-paragraph)
4866 (should (string-equal (buffer-string) str))))))
4868 (ert-deftest test-markdown-filling/no-break-before-list-item ()
4869 "There's no point in putting the first item of a list on the next line,
4870 indented the same amount."
4871 (let ((str "* [Link](http://way-too-long.example.com)\n"))
4872 (markdown-test-string str
4873 (auto-fill-mode 1)
4874 (let ((fill-column 10))
4875 (end-of-line)
4876 (funcall auto-fill-function)
4877 ;; This test was known to fail in Emacs 25 and earlier.
4878 (if (version< emacs-version "26.0")
4879 (should-not (string-equal (buffer-string) str))
4880 (should (string-equal (buffer-string) str)))))))
4882 (ert-deftest test-markdown-filling/break-within-list-item ()
4883 "This doesn't suppress auto-fill within a multi-word list item."
4884 :expected-result :failed
4885 (markdown-test-string "* [Link](http://example.com/) more text"
4886 (auto-fill-mode 1)
4887 (let ((fill-column 10))
4888 (end-of-line)
4889 (funcall auto-fill-function)
4890 (should (string-equal
4891 (buffer-string)
4892 "* [Link](http://example.com/)\n more text")))))
4894 (ert-deftest test-markdown-filling/preserve-next-line-footnote ()
4895 "Footnote block can be after label"
4896 (let ((str "[^label1]:\n Footnote block\n more footnote")) ; six spaces
4897 (markdown-test-string str
4898 (let ((fill-column 20)) ; could fit "footnote" after label, but shouldn't
4899 (fill-paragraph)
4900 (should (string-equal (buffer-string) str))))))
4902 (ert-deftest test-markdown-filling/wrap-same-line-footnote ()
4903 "Additional lines must be indented one level (four spaces) when wrapped."
4904 (markdown-test-string "[^label]: Long line should be wrapped"
4905 (let ((fill-column 25)) ; wrap before end of "should"
4906 (fill-paragraph)
4907 (should (string-equal (buffer-string) "[^label]: Long line\n should be wrapped")))))
4909 (ert-deftest test-markdown-filling/wrap-extra-hanging-indentation ()
4910 "Additional lines must be indented one level (four spaces) when wrapped."
4911 (markdown-test-string "[^label]: Long line\n should be wrapped"
4912 (let ((fill-column 25)) ; wrap before end of "should"
4913 (fill-paragraph)
4914 (should (string-equal (buffer-string) "[^label]: Long line\n should be wrapped")))))
4916 (ert-deftest test-markdown-filling/full-justification ()
4917 "Test paragraph detection with lines with lots of whitespace."
4918 (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"
4919 (setq default-justification 'full)
4920 (fill-paragraph)
4921 (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"))
4922 (backward-paragraph)
4923 (forward-paragraph)
4924 (should (= (point) 198))))
4926 (ert-deftest test-markdown-filling/list-line ()
4927 "Test fill-paragraph for list line. Don't insert bullet automatically.
4928 Detail: https://github.com/jrblevin/markdown-mode/issues/79"
4929 (markdown-test-string "* foo foo *foo* foo foo foo foo foo foo"
4930 (let ((fill-column 10))
4931 (fill-paragraph)
4932 (fill-paragraph)
4933 (forward-line 2)
4934 (back-to-indentation)
4935 (should-not (looking-at-p "\\*foo"))
4936 (forward-line 1)
4937 (back-to-indentation)
4938 (should-not (looking-at-p "\\*foo")))))
4940 (ert-deftest test-markdown-filling/ignore-header ()
4941 "# Test fill-paragraph for containing header line paragraph.
4942 https://github.com/jrblevin/markdown-mode/issues/159"
4943 (markdown-test-string "# this is header line
4944 this is not header line
4946 (let ((fill-column 10))
4947 (fill-paragraph)
4948 (should (string= (buffer-substring (point) (line-end-position)) "# this is header line")))))
4950 (ert-deftest test-markdown-filling/unclosed-square-bracket ()
4951 "Test fill-paragraph following an unclosed square bracket."
4952 (markdown-test-string "```\n[3\n```\n\naaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbb"
4953 (let ((fill-column 20))
4954 (forward-line 4)
4955 (fill-paragraph)
4956 (should (looking-at "aaaaaaaaaaaaaaaa\nbbbbbbbbbbbbbbbb")))))
4958 (ert-deftest test-markdown-filling/skip-code-blocks ()
4959 "Test `markdown-fill-paragraph' on code blocks."
4960 (let ((text "test\n\n```\nhello\nworld\n```"))
4961 (markdown-test-string text
4962 (dotimes (n 5)
4963 ;; Fill at each line; buffer should not change.
4964 (fill-paragraph)
4965 (should (string-equal (buffer-string) text))))))
4967 (ert-deftest test-markdown-filling/fill-region-skip-code-blocks ()
4968 "Test `fill-region' on code blocks."
4969 (let ((text "testing\n\n```\nhello\nworld\n```\n\n123"))
4970 (markdown-test-string text
4971 ;; Fill entire buffer; buffer should not change.
4972 (fill-region (point-min) (point-max))
4973 (should (string-equal (buffer-string) text)))))
4975 (ert-deftest test-markdown-filling/fill-region-skip-code-blocks-2 ()
4976 "Test `fill-region' on a buffer with a code block with long paragraphs."
4977 (markdown-test-string "long unwrapped paragraph 1
4980 code
4981 block
4987 long unwrapped paragraph 2"
4988 ;; Test markdown-fill-forward-paragraph movement.
4989 (should (= (markdown-fill-forward-paragraph 1) 0))
4990 (should (= (point) 28)) ;; Point just after par. 1.
4991 (should (= (markdown-fill-forward-paragraph 1) 0))
4992 (should (= (point) 84)) ;; Point at end of par. 2.
4993 ;; Test filling the entire buffer with `fill-region'.
4994 (let ((fill-column 12))
4995 (fill-region (point-min) (point-max))
4996 (should (string-equal (buffer-string)
4997 "long
4998 unwrapped
4999 paragraph 1
5002 code
5003 block
5009 long
5010 unwrapped
5011 paragraph 2")))))
5013 (ert-deftest test-markdown-filling/fill-region-skip-code-blocks-3 ()
5014 "Test `fill-region' on a lone code block with no surrounding text."
5015 (let ((text "```\ncode\nblock\n```\n"))
5016 (markdown-test-string text
5017 ;; Fill entire buffer; buffer should not change.
5018 (fill-region (point-min) (point-max))
5019 (should (string-equal (buffer-string) text)))))
5021 (ert-deftest test-markdown-filling/long-paragraph-with-link ()
5022 "Test `fill-paragraph' on a long paragraph with a long link.
5023 See GH-173."
5024 (markdown-test-string
5025 "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."
5026 (let ((fill-column 79)) (fill-paragraph))
5027 (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
5028 aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa aaa [aaa aaa aaa
5029 aaa](aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) aaa aaa aaa aaa aaa."))))
5031 (ert-deftest test-markdown-filling/pandoc-line-blocks ()
5032 "Filling should leave Pandoc line blocks undisturbed.
5033 This includes preserving whitespace after the pipe."
5034 (let ((text "| The limerick packs laughs anatomical
5035 | In space that is quite economical.
5036 | But the good ones I've seen
5037 | So seldom are clean
5038 | And the clean ones so seldom are comical
5040 | 200 Main St.
5041 | Berkeley, CA 94718"))
5042 (markdown-test-string text
5043 (fill-region (point-min) (point-max))
5044 (should (string-equal (buffer-string) text)))))
5046 ;;; Export tests:
5048 (ert-deftest test-markdown-hook/xhtml-standalone ()
5049 "Test `markdown-xhtml-standalone-regexp' and `markdown-output-standalone-p'."
5050 (should (string-match markdown-xhtml-standalone-regexp
5051 "<?xml version='1.0' encoding='UTF-8'?>"))
5052 (should (string-match markdown-xhtml-standalone-regexp
5053 "<!DOCTYPE html>"))
5054 (should (string-match markdown-xhtml-standalone-regexp
5055 "<html>"))
5056 (should-not (string-match markdown-xhtml-standalone-regexp
5057 "<h1>title</h1>"))
5058 (should-not (string-match markdown-xhtml-standalone-regexp
5059 "<div id=\"name\">")))
5061 (ert-deftest test-markdown-export/kill-buffer-nil ()
5062 "Test `markdown-export-kill-buffer' equal to nil."
5063 (markdown-test-temp-file "inline.text"
5064 (let* ((markdown-export-kill-buffer nil)
5065 (export-file (markdown-export))
5066 (export-buffer (get-file-buffer export-file)))
5067 ;; Output buffer should remain open.
5068 (should (member export-buffer (buffer-list))))))
5070 (ert-deftest test-markdown-export/kill-buffer-t ()
5071 "Test `markdown-export-kill-buffer' equal to t."
5072 (markdown-test-temp-file "inline.text"
5073 (let* ((markdown-export-kill-buffer t)
5074 (export-file (markdown-export))
5075 (export-buffer (get-file-buffer export-file)))
5076 ;; Output buffer should be killed.
5077 (should-not export-buffer))))
5079 ;;; Hook tests:
5081 (ert-deftest test-markdown-hook/before-export ()
5082 "Test hook run before export XHTML."
5083 (markdown-test-temp-file "lists.text"
5084 (let* ((before-hook-run nil)
5085 (orig-point (point))
5086 (func (lambda ()
5087 ;; Change value of a variable
5088 (setq before-hook-run t)
5089 ;; Insert some text
5090 (goto-char (point-min))
5091 (insert "#")
5092 ;; Deliberately move the point
5093 (end-of-line)
5094 ;; Verify changes
5095 (should (looking-back "^## List Cases" nil))
5096 (should-not (= (point) orig-point))))
5097 (ofile (progn
5098 ;; Register hook
5099 (add-hook 'markdown-before-export-hook func)
5100 ;; Export XHTML and return filename
5101 (markdown-export)))
5102 (obuffer (get-file-buffer ofile)))
5103 ;; Test side effects of hook
5104 (should (eq before-hook-run t))
5105 ;; Test position of point
5106 (should (= (point) orig-point))
5107 ;; Test that buffer was restored to original state
5108 (goto-char (point-min))
5109 (should (looking-at "^# List Cases"))
5110 ;; Clean
5111 (remove-hook 'markdown-before-export-hook func)
5112 (kill-buffer obuffer)
5113 (delete-file ofile))))
5115 (ert-deftest test-markdown-hook/after-export ()
5116 "Test hook run after export XHTML."
5117 (markdown-test-temp-file "lists.text"
5118 (let* ((after-hook-run nil)
5119 (markdown-export-kill-buffer nil)
5120 (func (lambda ()
5121 ;; Change variable value
5122 (setq after-hook-run t)
5123 ;; Add comment to output buffer
5124 (goto-char (point-min))
5125 (insert "<!-- after-export-hook -->\n")))
5126 (ofile (progn
5127 ;; Register hook
5128 (add-hook 'markdown-after-export-hook func)
5129 ;; Export XHTML and return filename
5130 (markdown-export)))
5131 (obuffer (get-file-buffer ofile)))
5132 (message "obuffer = %S" obuffer)
5133 ;; Test that variable was changed
5134 (should (eq after-hook-run t))
5135 ;; Test that output buffer remains open
5136 (should (get-buffer obuffer))
5137 ;; Test that output buffer modification remains
5138 (with-current-buffer obuffer
5139 (goto-char (point-min))
5140 (should (looking-at "<!-- after-export-hook -->\n")))
5141 ;; Test that buffer modification was saved
5142 (should-not (buffer-modified-p obuffer))
5143 ;; Clean up
5144 (remove-hook 'markdown-after-export-hook func)
5145 (kill-buffer obuffer)
5146 (delete-file ofile))))
5148 ;;; Extension: math support
5150 (ert-deftest test-markdown-math/file-local-variable ()
5151 "Test enabling math mode via `hack-local-variables-hook'."
5152 (markdown-test-file "math.text"
5153 (should-not markdown-enable-math)
5154 (hack-local-variables)
5155 (should markdown-enable-math)))
5157 (ert-deftest test-markdown-math/reload ()
5158 "Test enabling math mode via variable `markdown-enable-math'."
5159 (let ((markdown-enable-math t))
5160 (markdown-test-file "math.text"
5161 ;; Flag should be set to t
5162 (should markdown-enable-math)
5163 ;; Font-lock keywords should be updated.
5164 (should (member (car markdown-mode-font-lock-keywords-math)
5165 (cadr font-lock-keywords))))))
5167 (ert-deftest test-markdown-math/preserve-user-keywords ()
5168 "Test preserving user-specified font-lock keywords."
5169 (let ((user-keyword '("\\<\\(FIXME\\):" 1 font-lock-warning-face t)))
5170 ;; Add user font-lock keyword using `font-lock-add-keywords'.
5171 (font-lock-add-keywords 'markdown-mode (list user-keyword))
5172 ;; Visit a file using `markdown-mode'.
5173 (markdown-test-file "math.text"
5174 ;; User keyword should be present initially.
5175 (should (member user-keyword (cadr font-lock-keywords)))
5176 ;; User keyword should persist after calling `markdown-reload-extensions'.
5177 (markdown-reload-extensions)
5178 (should (member user-keyword (cadr font-lock-keywords))))
5179 ;; Remove the user keyword using `font-lock-remove-keywords'.
5180 (font-lock-remove-keywords 'markdown-mode (list user-keyword))
5181 ;; Visit a file using `markdown-mode'.
5182 (markdown-test-file "inline.text"
5183 ;; User keyword should not be present after removal.
5184 (should-not (member user-keyword (cadr font-lock-keywords))))))
5186 (ert-deftest test-markdown-math/preserve-local-user-keywords ()
5187 "Test preserving buffer-specific user-specified font-lock keywords."
5188 (let ((user-keyword '("\\<\\(FIXME\\):" 1 font-lock-warning-face t)))
5189 ;; Visit a file using `markdown-mode'.
5190 (markdown-test-file "math.text"
5191 ;; Add user font-lock keyword using `font-lock-add-keywords'.
5192 (font-lock-add-keywords nil (list user-keyword))
5193 ;; User keyword should be present initially.
5194 (should (member user-keyword (cadr font-lock-keywords)))
5195 ;; User keyword should persist after calling `markdown-reload-extensions'.
5196 (markdown-reload-extensions)
5197 (should (member user-keyword (cadr font-lock-keywords)))
5198 ;; Remove the user keyword using `font-lock-remove-keywords'.
5199 (font-lock-remove-keywords nil (list user-keyword))
5200 ;; User keyword should not be present after removal.
5201 (should-not (member user-keyword (cadr font-lock-keywords))))))
5203 (ert-deftest test-markdown-math/font-lock ()
5204 "Test markdown math mode."
5205 (let ((markdown-enable-math t))
5206 (markdown-test-file "math.text"
5207 (markdown-test-range-has-face 1 32 nil)
5208 (markdown-test-range-has-face 33 33 markdown-markup-face)
5209 (markdown-test-range-has-face 34 45 markdown-math-face)
5210 (markdown-test-range-has-face 46 46 markdown-markup-face)
5211 (markdown-test-range-has-face 47 49 nil)
5212 (markdown-test-range-has-face 50 51 markdown-markup-face)
5213 (markdown-test-range-has-face 52 63 markdown-math-face)
5214 (markdown-test-range-has-face 64 65 markdown-markup-face)
5215 (markdown-test-range-has-face 66 98 nil)
5216 (markdown-test-range-has-face 99 100 markdown-markup-face)
5217 (markdown-test-range-has-face 101 112 markdown-math-face)
5218 (markdown-test-range-has-face 113 114 markdown-markup-face)
5219 (markdown-test-range-has-face 113 114 markdown-markup-face)
5220 (markdown-test-range-has-face 117 117 markdown-header-delimiter-face)
5221 (markdown-test-range-has-face 119 152 markdown-header-face-1)
5222 (markdown-test-range-has-face 129 129 markdown-markup-face)
5223 (markdown-test-range-has-face 136 136 markdown-markup-face)
5225 (markdown-test-range-has-face 174 177 markdown-markup-face)
5226 (markdown-test-range-has-face 179 179 markdown-markup-face)
5227 (markdown-test-range-has-face 180 187 markdown-language-keyword-face)
5228 (markdown-test-range-has-face 188 188 markdown-markup-face)
5229 (markdown-test-range-has-face 190 211 markdown-pre-face)
5230 (markdown-test-range-has-face 212 215 markdown-markup-face)
5232 (markdown-test-range-has-face 218 218 markdown-markup-face)
5233 (markdown-test-range-has-face 219 223 markdown-math-face)
5234 (markdown-test-range-has-face 224 224 markdown-markup-face)
5235 (markdown-test-range-has-face 350 351 markdown-markup-face)
5236 (markdown-test-range-has-face 352 356 markdown-math-face)
5237 (markdown-test-range-has-face 357 358 markdown-markup-face)
5238 (markdown-test-range-has-face 359 391 nil)
5239 (markdown-test-range-has-face 392 393 markdown-markup-face)
5240 (markdown-test-range-has-face 394 398 markdown-math-face)
5241 (markdown-test-range-has-face 399 400 markdown-markup-face))))
5243 (ert-deftest test-markdown-math/double-slash-display-math ()
5244 "Test double slash display math font lock."
5245 (let ((markdown-enable-math t))
5246 (markdown-test-file "math.text"
5247 (markdown-test-range-has-face 403 474 nil)
5248 (markdown-test-range-has-face 475 477 markdown-markup-face)
5249 (markdown-test-range-has-face 478 543 markdown-math-face)
5250 (markdown-test-range-has-face 544 546 markdown-markup-face))))
5252 (ert-deftest test-markdown-math/font-lock-italics ()
5253 "Test markdown math mode with underscores."
5254 (let ((markdown-enable-math t))
5255 (markdown-test-file "math.text"
5256 (markdown-test-range-has-face 227 227 markdown-markup-face)
5257 (markdown-test-range-has-face 228 233 markdown-math-face)
5258 (markdown-test-range-has-face 234 234 markdown-markup-face)
5259 (markdown-test-range-has-face 235 270 nil)
5260 (markdown-test-range-has-face 271 271 markdown-markup-face)
5261 (markdown-test-range-has-face 272 274 markdown-math-face)
5262 (markdown-test-range-has-face 275 275 markdown-markup-face))))
5264 (ert-deftest test-markdown-math/font-lock-no-bold ()
5265 "Bold markers in math should not trigger bold."
5266 (let ((markdown-enable-math t))
5267 (markdown-test-file "math.text"
5268 (markdown-test-range-has-face 279 299 markdown-math-face)
5269 (markdown-test-range-has-face 301 308 nil)
5270 (markdown-test-range-has-face 310 312 markdown-math-face))))
5272 ;;; gfm-mode tests:
5274 (ert-deftest test-markdown-gfm/pre-1 ()
5275 "GFM pre block font lock test."
5276 (markdown-test-file-gfm "gfm.text"
5277 (markdown-test-range-has-face 2626 2637 nil)
5278 (markdown-test-range-has-face 2639 2641 markdown-markup-face)
5279 (markdown-test-range-has-face 2642 2645 markdown-language-keyword-face)
5280 (markdown-test-range-has-face 2647 2728 markdown-pre-face)
5281 (markdown-test-range-has-face 2730 2732 markdown-markup-face)))
5283 (ert-deftest test-markdown-gfm/italic-1 ()
5284 "GFM italic font lock test."
5285 (markdown-test-file-gfm "gfm.text"
5286 (markdown-test-range-has-face 1483 1483 markdown-markup-face)
5287 (markdown-test-range-has-face 1484 1487 markdown-italic-face)
5288 (markdown-test-range-has-face 1488 1488 markdown-markup-face)
5289 (markdown-test-range-has-face 1729 1790 nil)))
5291 (ert-deftest test-markdown-gfm/strike-through-1 ()
5292 "GFM strike through font lock test."
5293 (markdown-test-string-gfm "one ~~two~~ three"
5294 (markdown-test-range-has-face 1 4 nil)
5295 (markdown-test-range-has-face 5 6 markdown-markup-face)
5296 (markdown-test-range-has-face 7 9 markdown-strike-through-face)
5297 (markdown-test-range-has-face 10 11 markdown-markup-face)
5298 (markdown-test-range-has-face 12 17 nil)))
5300 (ert-deftest test-markdown-gfm/toggle-strike-through ()
5301 "Test toggling functionality of `markdown-insert-strike-through'."
5302 (markdown-test-string-gfm "one ~~two~~ three"
5303 (forward-word 2)
5304 (markdown-insert-strike-through)
5305 (should (string-equal (buffer-string) "one two three"))
5306 (should (= (point) 8))
5307 (forward-word)
5308 (markdown-insert-strike-through)
5309 (should (= (point) 16))
5310 (should (string-equal (buffer-string) "one two ~~three~~"))))
5312 (ert-deftest test-markdown-gfm/insert-code-block ()
5313 "GFM code block insertion test."
5314 ;; Test empty markup insertion
5315 (markdown-test-string-gfm "line 1\nline 2\n"
5316 (end-of-line)
5317 (markdown-insert-gfm-code-block "elisp")
5318 (should (equal (car markdown-gfm-used-languages) "elisp"))
5319 (should (equal (car (markdown-gfm-get-corpus)) "elisp"))
5320 (should (string-equal (buffer-string)
5321 "line 1\n\n``` elisp\n\n```\n\nline 2\n")))
5322 ;; Test ‘markdown-spaces-after-code-fence’.
5323 (markdown-test-string-gfm ""
5324 (let ((markdown-spaces-after-code-fence 0))
5325 (markdown-insert-gfm-code-block "elisp")
5326 (should (equal (buffer-string) "```elisp\n\n```"))))
5327 ;; Test with active region
5328 (markdown-test-string-gfm "line 1\nline 2\nline 3\n"
5329 (forward-line)
5330 (transient-mark-mode)
5331 (push-mark (point) t t)
5332 (end-of-line)
5333 (should (markdown-use-region-p))
5334 (markdown-insert-gfm-code-block "elisp")
5335 (should (string-equal (buffer-string)
5336 "line 1\n\n``` elisp\nline 2\n```\n\nline 3\n")))
5337 ;; Test indented list item
5338 (markdown-test-string-gfm "1. foo\n "
5339 (goto-char (point-max))
5340 (markdown-insert-gfm-code-block "elisp")
5341 (should (equal (buffer-substring-no-properties (point-min) (point-max))
5342 "1. foo\n\n ``` elisp\n \n ```"))
5343 (should (equal (buffer-substring-no-properties (point) (point-max))
5344 "\n ```")))
5345 ;; Test indented list item with active region
5346 (markdown-test-string-gfm "1. foo\n bar\n"
5347 (let ((transient-mark-mode t))
5348 (forward-line)
5349 (push-mark nil :nomsg :activate)
5350 (end-of-line)
5351 (should (markdown-use-region-p))
5352 (markdown-insert-gfm-code-block "elisp"))
5353 (should (equal (buffer-substring-no-properties (point-min) (point-max))
5354 "1. foo\n\n ``` elisp\n bar\n ```\n\n"))
5355 (should (equal (buffer-substring-no-properties (point) (point-max))
5356 "\n bar\n ```\n\n"))))
5358 (ert-deftest test-markdown-gfm/gfm-parse-buffer-for-languages ()
5359 "Parse buffer for existing languages for `markdown-gfm-used-languages' test."
5360 (markdown-test-string-gfm "``` MADEUP\n\n```\n``` LANGUAGES\n\n```\n```MaDeUp\n\n```\n```\n\n```\n``` \n\n```\n"
5361 (markdown-gfm-parse-buffer-for-languages)
5362 (should (equal markdown-gfm-used-languages
5363 (list "MaDeUp" "LANGUAGES" "MADEUP")))
5364 (should (equal (car markdown-gfm-used-languages) "MaDeUp"))
5365 (should (equal (car (markdown-gfm-get-corpus)) "MaDeUp"))
5366 (goto-char (point-max))
5367 (markdown-insert-gfm-code-block "newlang")
5368 (should (equal markdown-gfm-used-languages
5369 (list "newlang" "MaDeUp" "LANGUAGES" "MADEUP")))
5370 (should (equal (car markdown-gfm-used-languages) "newlang"))
5371 (should (equal (car (markdown-gfm-get-corpus)) "newlang"))
5372 (let ((markdown-gfm-downcase-languages nil))
5373 (should
5374 (equal (markdown-gfm-get-corpus)
5375 (append markdown-gfm-used-languages
5376 markdown-gfm-additional-languages
5377 markdown-gfm-recognized-languages))))
5378 (let ((markdown-gfm-downcase-languages t))
5379 (should
5380 (equal
5381 (markdown-gfm-get-corpus)
5382 (append markdown-gfm-used-languages
5383 (cl-mapcar #'downcase
5384 (append markdown-gfm-additional-languages
5385 markdown-gfm-recognized-languages))))))))
5387 (ert-deftest test-markdown-gfm/code-block-font-lock ()
5388 "GFM code block font lock test."
5389 (markdown-test-file-gfm "gfm.text"
5390 (markdown-test-range-has-face 2639 2641 markdown-markup-face) ; ```
5391 (markdown-test-range-has-face 2642 2645 markdown-language-keyword-face) ; lang
5392 (markdown-test-range-has-face 2647 2728 markdown-pre-face) ; code
5393 (markdown-test-range-has-face 2730 2732 markdown-markup-face))) ; ```
5395 (ert-deftest test-markdown-gfm/code-block-font-lock-2 ()
5396 "GFM code block font lock test without language identifier."
5397 (markdown-test-string-gfm "Plain code block:\n\n```\nfoo\n```\n"
5398 (markdown-test-range-has-face 20 22 markdown-markup-face)
5399 (markdown-test-range-has-face 24 26 markdown-pre-face)
5400 (markdown-test-range-has-face 28 30 markdown-markup-face)))
5402 ;;; Tests for other extensions:
5404 (ert-deftest test-markdown-ext/pandoc-fancy-lists ()
5405 "Test basic support for font lock and filling of Pandoc 'fancy lists'."
5406 (markdown-test-string " #. abc\ndef\n"
5407 ;; font lock
5408 (markdown-test-range-has-face 1 1 nil)
5409 (markdown-test-range-has-face 2 3 markdown-list-face)
5410 (markdown-test-range-has-face 4 11 nil)
5411 ;; filling
5412 (forward-line)
5413 (markdown-indent-region (line-beginning-position) (line-end-position) nil)
5414 (should (string-equal (buffer-string) " #. abc\n def\n"))
5415 (markdown-indent-region (line-beginning-position) (line-end-position) nil)
5416 (should (string-equal (buffer-string) " #. abc\n def\n"))))
5418 (ert-deftest test-markdown-ext/wiki-link-rules ()
5419 "Test wiki link search rules and font lock for missing pages."
5420 (let ((markdown-enable-wiki-links t)
5421 (markdown-wiki-link-fontify-missing t)
5422 (markdown-wiki-link-search-subdirectories t)
5423 (markdown-wiki-link-search-parent-directories t))
5424 (progn
5425 (find-file "wiki/root")
5426 (unwind-protect
5427 (progn
5428 (markdown-mode)
5429 ;; search rules
5430 (should (string-match-p
5431 "/sub/foo$"
5432 (markdown-convert-wiki-link-to-filename "foo")))
5433 (should (string-equal
5434 (markdown-convert-wiki-link-to-filename "doesnotexist")
5435 "doesnotexist"))
5436 ;; font lock
5437 (markdown-test-range-has-property 1 11 'font-lock-face markdown-link-face)
5438 (markdown-test-range-has-property 14 33 'font-lock-face markdown-missing-link-face)
5439 (markdown-test-range-has-property 36 42 'font-lock-face markdown-link-face)
5440 (markdown-test-range-has-property 45 60 'font-lock-face markdown-missing-link-face))
5441 (kill-buffer)))
5442 (progn
5443 (find-file "wiki/sub/foo")
5444 (unwind-protect
5445 (progn
5446 (markdown-mode)
5447 ;; search rules
5448 (should (string-match-p
5449 "/wiki/root$"
5450 (markdown-convert-wiki-link-to-filename "root")))
5451 (should (string-equal
5452 (markdown-convert-wiki-link-to-filename "doesnotexist")
5453 "doesnotexist"))
5454 ;; font lock
5455 (markdown-test-range-has-property 1 16 'font-lock-face markdown-missing-link-face)
5456 (markdown-test-range-has-property 19 26 'font-lock-face markdown-link-face))
5457 (kill-buffer)))))
5459 (defadvice markdown-live-preview-window-eww
5460 (around markdown-test-create-fake-eww disable)
5461 (setq ad-return-value (get-buffer-create "*eww*")))
5463 (defmacro markdown-test-fake-eww (&rest body)
5464 `(progn
5465 ,@(if (and (fboundp 'libxml-parse-html-region) (require 'eww nil t)) body
5466 `((ad-enable-advice #'markdown-live-preview-window-eww
5467 'around 'markdown-test-create-fake-eww)
5468 (ad-activate #'markdown-live-preview-window-eww)
5469 ,@body
5470 (ad-disable-advice #'markdown-live-preview-window-eww
5471 'around 'markdown-test-create-fake-eww)
5472 (ad-activate #'markdown-live-preview-window-eww)))))
5474 (defmacro markdown-test-eww-or-nothing (test &rest body)
5475 (if (and (fboundp 'libxml-parse-html-region) (require 'eww nil t)
5476 (executable-find markdown-command))
5477 `(progn ,@body)
5478 (message "no eww, no libxml2, or no %s found: skipping %s" markdown-command test)
5479 nil))
5481 (ert-deftest test-markdown-ext/live-preview-no-file ()
5482 "Live-preview a `markdown-mode' buffer without a file."
5483 (with-temp-buffer
5484 (markdown-mode)
5486 ;; Activating `markdown-live-preview-mode' signals error
5487 (should-error (markdown-live-preview-mode))
5489 ;; After trying to activate live preview mode, mode is not activated
5490 (should-not markdown-live-preview-mode)
5492 ;; `markdown-live-preview-export' does nothing
5493 (should-not (markdown-live-preview-export))
5495 ;; `markdown-live-preview-remove' does nothing
5496 (should-not (markdown-live-preview-remove))))
5498 (ert-deftest test-markdown-ext/live-preview-exports ()
5499 (markdown-test-temp-file "inline.text"
5500 (unless (and (fboundp 'libxml-parse-html-region) (require 'eww nil t))
5501 (should-error (markdown-live-preview-mode)))
5502 (markdown-test-fake-eww
5503 (markdown-live-preview-mode)
5504 (should (buffer-live-p markdown-live-preview-buffer))
5505 (should (eq (current-buffer)
5506 (with-current-buffer markdown-live-preview-buffer
5507 markdown-live-preview-source-buffer)))
5508 (kill-buffer markdown-live-preview-buffer)
5509 (should (null markdown-live-preview-buffer))
5510 (set-buffer-modified-p t)
5511 (save-buffer) ; should create new export
5512 (should (buffer-live-p markdown-live-preview-buffer)))))
5514 (ert-deftest test-markdown-ext/live-preview-delete-exports ()
5515 (markdown-test-fake-eww
5516 (let ((markdown-live-preview-delete-export 'delete-on-destroy)
5517 file-output)
5518 (markdown-test-temp-file "inline.text"
5519 (markdown-live-preview-mode)
5520 (setq file-output (markdown-export-file-name)))
5521 (should-not (file-exists-p file-output)))
5522 (let ((markdown-live-preview-delete-export 'delete-on-export)
5523 file-output)
5524 (markdown-test-temp-file "inline.text"
5525 (markdown-live-preview-mode)
5526 (setq file-output (markdown-export-file-name))
5527 (should-not (file-exists-p file-output))))
5528 (let ((markdown-live-preview-delete-export nil)
5529 file-output)
5530 (unwind-protect
5531 (markdown-test-temp-file "inline.text"
5532 (markdown-live-preview-mode)
5533 (setq file-output (markdown-export-file-name))
5534 (should (file-exists-p file-output)))
5535 (delete-file file-output)))))
5537 (ert-deftest test-markdown-ext/live-preview-follow-min-max ()
5538 (markdown-test-eww-or-nothing "live-preview-follow-min-max"
5539 (markdown-test-temp-file "inline.text"
5540 (markdown-live-preview-mode)
5541 (should (buffer-live-p markdown-live-preview-buffer))
5542 (should (window-live-p (get-buffer-window markdown-live-preview-buffer)))
5543 (with-selected-window (get-buffer-window markdown-live-preview-buffer)
5544 (goto-char (point-min)))
5545 (goto-char (point-min))
5546 (insert "a test ")
5547 (markdown-live-preview-export)
5548 (let (final-pt final-win-st-diff)
5549 ;; test that still starts at point-min
5550 (with-selected-window (get-buffer-window markdown-live-preview-buffer)
5551 (should (= (window-point) 1))
5552 (should (= (markdown-visual-lines-between-points
5553 (window-start) (window-point))
5555 (set-window-point (selected-window) (point-max))
5556 (setq final-pt (window-point)
5557 final-win-st-diff (markdown-visual-lines-between-points
5558 (window-start) (window-point))))
5559 (goto-char (point-min))
5560 (insert "this is ")
5561 (markdown-live-preview-export)
5562 (with-selected-window (get-buffer-window markdown-live-preview-buffer)
5563 (should (= (window-point) (+ final-pt (length "this is "))))
5564 (should (= (markdown-visual-lines-between-points
5565 (window-start) (window-point))
5566 final-win-st-diff))
5567 ;; test that still starts at point-max, with correct line difference
5568 (goto-char (floor (/ (float (- (point-max) (point-min))) 2)))
5569 (setq final-pt (window-point)
5570 final-win-st-diff (markdown-visual-lines-between-points
5571 (window-start) final-pt)))
5572 (markdown-live-preview-export)
5573 ;; test that still starts at same point, with correct line difference
5574 (with-selected-window (get-buffer-window markdown-live-preview-buffer)
5575 (should (= (window-point) final-pt))
5576 (should (= (markdown-visual-lines-between-points
5577 (window-start) (window-point))
5578 final-win-st-diff)))))))
5580 ;; Tests for imenu
5582 (ert-deftest test-markdown-imenu/metadata ()
5583 "Don't correct header like statement in metadata.
5584 https://github.com/jrblevin/markdown-mode/issues/145"
5585 (markdown-test-string "---
5586 title = \"Blah\"
5587 comments = false
5590 # Header1
5592 ## Header2
5594 (let ((headers (mapcar #'car (markdown-imenu-create-flat-index))))
5595 (should (member "Header1" headers))
5596 (should (member "Header2" headers))
5597 (should-not (member "comments = false" headers)))))
5599 (ert-deftest test-markdown-command/function ()
5600 "Test ‘markdown’ with ‘markdown-command’ being a function."
5601 (markdown-test-string "foo"
5602 (let* ((calls ())
5603 (markdown-command (lambda (&rest args) (push args calls)))
5604 (buffer-name (markdown))
5605 (buffer (get-buffer buffer-name)))
5606 (should (stringp buffer-name))
5607 (should (buffer-live-p buffer))
5608 (should (equal calls `((1 4 ,buffer)))))))
5610 (ert-deftest test-markdown-open-command/function ()
5611 "Test ‘markdown-open’ with ‘markdown-open-command’ being a function."
5612 (markdown-test-string ""
5613 (let* ((calls 0)
5614 (markdown-open-command (lambda () (cl-incf calls))))
5615 (markdown-open)
5616 (should (equal calls 1)))))
5618 (provide 'markdown-test)
5620 ;;; markdown-test.el ends here