Reputation: 622
I am using emacs in markdown-mode to preview a markdown document, but there is no a table of contents in the HTML page previewed after typing C-x C-x p.
cat ~/.emacs
(add-to-list 'load-path "~/.emacs.d")
(autoload 'markdown-mode "markdown-mode"
"Major mode for editing Markdown files" t)
(add-to-list 'auto-mode-alist '("\\.markdown\\'" . markdown-mode))
(add-to-list 'auto-mode-alist '("\\.md\\'" . markdown-mode))
(autoload 'gfm-mode "markdown-mode"
"Major mode for editing GitHub Flavored Markdown files" t)
(add-to-list 'auto-mode-alist '("README\\.md\\'" . gfm-mode))
(custom-set-variables
'(markdown-command "/usr/bin/pandoc --toc -f markdown_github -t html"))
PS: I can use pandoc command pandoc --toc -f markdown_github
to make a HTML page with a table of contents from a markdown document.
How to solve it? Thx in advanced!
Upvotes: 7
Views: 6633
Reputation: 8357
From my own init file:
(defun px/markdown-toc ()
"Extract level 2 and 3 headings from the current Markdown buffer.
The generated and indented TOC will be inserted at point."
(interactive)
(let (toc-list markdown-toc)
(save-excursion
(goto-char (point-min))
(while (re-search-forward "^\\(##+\\)\\s-+\\(.*\\)" nil t)
(let* ((level (length (match-string 1)))
(heading-text (match-string 2))
(heading-id (downcase (replace-regexp-in-string "[[:space:]]+" "-" heading-text))))
(push (cons level (cons heading-text heading-id)) toc-list))))
(setq toc-list (reverse toc-list))
(dolist (item toc-list)
(let* ((level (car item))
(heading-text (cadr item))
(heading-id (cddr item))
(indentation (make-string (* 2 (1- level)) ?\ ))
(line (format "- [%s](#%s)\n" heading-text heading-id)))
(setq markdown-toc (concat markdown-toc (concat indentation line)))))
(insert markdown-toc)))
Upvotes: 0
Reputation: 18375
It's super easy with the package markdown-toc, in melpa. Just call it with M-x
.
source: http://wikemacs.org/wiki/Markdown#Generate_a_table_of_content
If you have many identical titles, the anchors have to be distinguished, and you'll rely on npm's markdown-toc.
Upvotes: 7
Reputation: 4118
If you have the discipline to insert named anchors under your headings like this:
## My heading
<a name="My heading"></a>
foo bar
My other heading
================
<a name="My other heading"></a>
baz qux
Then the following function ought to be a reasonable starting point (doesn't distinguish between heading levels or anything, just a little PoC).
(defun my/make-markdown-toc ()
"Makes a markdown ToC at the top of a md document."
(interactive)
(save-excursion
(goto-char (point-min))
(let ((list-of-headings))
(while (search-forward-regexp markdown-regex-header nil 'noerror)
(if (match-string 5)
(push (match-string 5) list-of-headings))
(if (match-string 1)
(push (match-string 1) list-of-headings)))
(message "I found %s matches" (length list-of-headings))
(goto-char (point-min))
(dolist (heading (reverse list-of-headings))
(insert "1. [" heading "](#" heading ")\n")))))
Note that the heavy lifting is just done by borrowing markdown-mode's regexes for headings.
Upvotes: 2