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