Skip to content

Commit

Permalink
Make TOC generation work with num set to nil too
Browse files Browse the repository at this point in the history
This commit changes the TOC style quite a bit from the earlier
version. Read the below mini-blog-in-commit for more info.

- Add new function org-hugo--get-headline-number
- org-hugo-heading - Use above.

- org-hugo--build-toc - Generate unordered list instead of ordered
- Update/add tests!

@punchagan: You are most likely one of the few affected by the
backward incompatible change in this commit. To get sort of the old
style of numbered headings in TOC (while unnumbered headings in post
body), set `num' to `onlytoc`. Let me know how it works.

=== mini blog ===

Earlier, the TOC was exported as ordered list in Markdown. That
imposed a limitation that allowed exporting only the last number from
a section number.

So instead of:

  1. Section 1
      1.1 Section 1.1
      1.2 Section 1.2

It would export as:

  1. Section 1
      1. Section 1.1
      2. Section 1.2

Now the TOC is generated as an *unordered* list in Markdown.

  - 1. Section 1
      - 1.1 Section 1.1
      - 1.2 Section 1.2

That would cause both bullets and numbers to show in HTML, so I am
using a nifty little trick I discovered in
#93 to hide those
bullets **if the section numbers are present**.

In addition, I also wrap the section numbers in "section-num" class so
that user can choose to format them however they like using CSS (May
be even hide them).

===

Fixes #76
  • Loading branch information
kaushalmodi committed Nov 10, 2017
1 parent 0bf0c7f commit 4be378e
Show file tree
Hide file tree
Showing 22 changed files with 585 additions and 414 deletions.
7 changes: 5 additions & 2 deletions doc/ox-hugo-manual.org
Original file line number Diff line number Diff line change
Expand Up @@ -912,8 +912,11 @@ control on:
Org content.
- How many headlines to include in the TOC --- /Example: =#+TOC:
headlines 2=/ or =:EXPORT_OPTIONS: toc:2=.
- Whether you want to *not* include a headline in the TOC --- Set the
=UNNUMBERED= property of that headline to =t=.
- Whether you want *all* the headlines in the TOC to be numbered or
not --- See =org-hugo-export-with-section-numbers=.
- Whether you want *only some* headlines numbered (both in post body
and the TOC) --- Set the =UNNUMBERED= property of that headline to
=t=.

If you'd like to use the Org-generated TOC instead of the
Hugo-generated one, you can do it one of these many ways:
Expand Down
78 changes: 48 additions & 30 deletions ox-hugo.el
Original file line number Diff line number Diff line change
Expand Up @@ -482,11 +482,12 @@ e.g. \"toc:nil\", \"toc:t\" or \"toc:3\"."
:safe (lambda (x) (or (booleanp x)
(integerp x))))

(defcustom org-hugo-export-with-section-numbers 'onlytoc
(defcustom org-hugo-export-with-section-numbers nil
"Configuration for adding section numbers to headlines.
When set to `onlytoc', none of the headlines will be numbered
in the body, but TOC generation will use the section numbers.
When set to `onlytoc', none of the headlines will be numbered in
the exported post body, but TOC generation will use the section
numbers.
When set to an integer N, numbering will only happen for
headlines whose relative level is higher or equal to N.
Expand Down Expand Up @@ -729,6 +730,25 @@ This function is called in the very end of
This is an internal function."
(advice-remove 'org-babel-exp-code #'org-hugo--org-babel-exp-code))

(defun org-hugo--get-headline-number (headline info &optional toc)
"Return htmlized section number for the HEADLINE.
INFO is a plist used as a communication channel.
When the \"num\" export option is `onlytoc', headline number is
returned only if the optional argument TOC is non-nil.
Return nil if there is no headline number, or if it has been
disabled."
(let ((onlytoc (equal 'onlytoc (plist-get info :section-numbers))))
(when (and (if toc
t
(not onlytoc)) ;If `toc' is nil, but `onlytoc' is non-nil, return nil
(org-export-numbered-headline-p headline info))
(let ((number-str (mapconcat
'number-to-string
(org-export-get-headline-number headline info) ".")))
(format "<span class=\"section-num\">%s</span> " number-str)))))

(defun org-hugo--build-toc (info &optional n keyword local)
"Return table of contents as a string.
Expand All @@ -751,16 +771,13 @@ contents according to the current headline."
(toc-items
(mapconcat
(lambda (headline)
(let* ((indentation
(make-string
(* 4 (1- (org-export-get-relative-level headline info)))
?\s))
(let* ((level (org-export-get-relative-level headline info))
(indentation (make-string (* 4 (1- level)) ?\s))
(headline-num-list (org-export-get-headline-number headline info))
(number (when headline-num-list
;; (message "[ox-hugo TOC DBG] headline-num-list: %S" headline-num-list)
(format "%d." (org-last headline-num-list))))
(bullet (when number
(concat number (make-string (- 4 (length number)) ?\s))))
(number (if headline-num-list
;; (message "[ox-hugo TOC DBG] headline-num-list: %S" headline-num-list)
(org-hugo--get-headline-number headline info :toc)
""))
(title (org-export-data (org-element-property :title headline) info))
(toc-entry
(format "[%s](#%s)"
Expand All @@ -778,8 +795,8 @@ contents according to the current headline."
(and tags
(format ":%s:"
(mapconcat #'identity tags ":")))))))
(when bullet
(concat indentation bullet toc-entry tags))))
;; (message "[ox-hugo build-toc DBG] level:%d, number:%s" level number)
(concat indentation "- " number toc-entry tags)))
(org-export-collect-headlines info n (and local keyword))
"\n")) ;Newline between TOC items
;; Remove blank lines from in-between TOC items, which can
Expand All @@ -789,8 +806,19 @@ contents according to the current headline."
(replace-regexp-in-string "\n\\{2,\\}" "\n" toc-items))))
;; (message "[ox-hugo build-toc DBG] toc-items:%s" toc-items)
(when toc-items
(concat toc-headline
toc-items
(concat (when (string-match-p "^\\s-*\\-\\s-<span class=\"section\\-num\"" toc-items)
;; Hide the bullets if section numbers are present for
;; even one heading.
(concat "<style>\n"
" .ox-hugo ul {\n"
" list-style: none;\n"
" }"
"</style>\n"))
"<div class=\"ox-hugo toc\">\n" ;This is a nasty workaround
"<div></div>\n" ;till Hugo/Blackfriday support
toc-headline ;wrapping Markdown in HTML div's.
toc-items ;https://github.com/kaushalmodi/ox-hugo/issues/93
"\n</div>"
"\n")))) ;Final newline at the end of TOC

(defalias 'org-hugo--has-caption-p 'org-html--has-caption-p
Expand Down Expand Up @@ -868,14 +896,7 @@ information."
CONTENTS is the headline contents. INFO is a plist used as
a communication channel."
(unless (org-element-property :footnote-section-p headline)
(let* ((numbers
(when (and (not (equal 'onlytoc (plist-get info :section-numbers)))
(org-export-numbered-headline-p headline info))
(concat
(mapconcat
'number-to-string
(org-export-get-headline-number headline info) ".")
" ")))
(let* ((numbers (org-hugo--get-headline-number headline info nil))
(level (org-export-get-relative-level headline info))
(title (org-export-data (org-element-property :title headline) info))
(todo (and (org-hugo--plist-get-true-p info :with-todo-keywords)
Expand Down Expand Up @@ -984,12 +1005,9 @@ Optional argument TODO is the Org TODO string.
Optional argument ANCHOR is the Hugo anchor tag for the section as a
string.
Optional argument NUMBERS, if non-nil, is a string containing the
TITLE's number."
(let* ((numbers-html (when numbers
(concat "<span class=\"section-num\">"
numbers "</span>")))
(headline (concat todo numbers-html title " " anchor "\n")))
Optional argument NUMBERS, if non-nil, is an htmlized string
containing the TITLE's number."
(let ((headline (concat todo numbers title " " anchor "\n")))
;; Use "Setext" style
(if (and (eq style 'setext) (< level 3))
(let* ((underline-char (if (= level 1) ?= ?-))
Expand Down
192 changes: 102 additions & 90 deletions test/site/content-org/all-posts.org
Original file line number Diff line number Diff line change
Expand Up @@ -545,37 +545,6 @@ property needs to be left *empty* instead of setting to =nil=!
:END:
- [[http://orgmode.org/manual/Literal-examples.html][Org reference]]
- [[https://gohugo.io/content-management/syntax-highlighting/][Hugo =highlight= shortcode with line numbers]]
*** Source block with line numbers examples :noexport:
:PROPERTIES:
:CUSTOM_ID: source-block-with-line-numbers-examples
:END:
#+BEGIN_SRC org :noweb-ref src-block-n-default-start
,#+BEGIN_SRC emacs-lisp -n
;; this will export with line number 1 (default)
(message "This is line 2")
,#+END_SRC
#+END_SRC

#+BEGIN_SRC org :noweb-ref src-block-n-custom-start
,#+BEGIN_SRC emacs-lisp -n 20
;; this will export with line number 20
(message "This is line 21")
,#+END_SRC
#+END_SRC

#+BEGIN_SRC org :noweb-ref src-block-n-default-continue
,#+BEGIN_SRC emacs-lisp +n
;; This will be listed as line 22
(message "This is line 23")
,#+END_SRC
#+END_SRC

#+BEGIN_SRC org :noweb-ref src-block-n-custom-continue
,#+BEGIN_SRC emacs-lisp +n 10
;; This will be listed as line 33
(message "This is line 34")
,#+END_SRC
#+END_SRC
*** Cases
:PROPERTIES:
:CUSTOM_ID: source-block-line-number-cases
Expand Down Expand Up @@ -621,42 +590,6 @@ property needs to be left *empty* instead of setting to =nil=!
:EXPORT_FILE_NAME: source-block-with-highlighting
:CUSTOM_ID: source-blocks-with-highlighting
:END:
*** Source block with line highlighting examples :noexport:
:PROPERTIES:
:CUSTOM_ID: source-block-with-line-highlighting-examples
:END:
#+BEGIN_SRC org :noweb-ref src-block-hl-without-n
,#+BEGIN_SRC emacs-lisp :hl_lines 1,3-5
(message "This is line 1")
(message "This is line 2")
(message "This is line 3")
(message "This is line 4")
(message "This is line 5")
(message "This is line 6")
,#+END_SRC
#+END_SRC

#+BEGIN_SRC org :noweb-ref src-block-hl-with-n-not-1
,#+BEGIN_SRC emacs-lisp -n 7 :hl_lines 1,3-5
(message "This is line 7 in code, but line 1 for highlighting reference")
(message "This is line 8 in code, but line 2 for highlighting reference")
(message "This is line 9 in code, but line 3 for highlighting reference")
(message "This is line 10 in code, but line 4 for highlighting reference")
(message "This is line 11 in code, but line 5 for highlighting reference")
(message "This is line 12 in code, but line 6 for highlighting reference")
,#+END_SRC
#+END_SRC

#+BEGIN_SRC org :noweb-ref src-block-hl-with-n
,#+BEGIN_SRC emacs-lisp -n :hl_lines 1,3-5
(message "This is line 1")
(message "This is line 2")
(message "This is line 3")
(message "This is line 4")
(message "This is line 5")
(message "This is line 6")
,#+END_SRC
#+END_SRC
*** Without line numbers
:PROPERTIES:
:CUSTOM_ID: source-blocks-with-highlighting-no-linenums
Expand Down Expand Up @@ -2442,40 +2375,55 @@ Still some people might prefer to use the Org generated TOC.
:END:
#+INCLUDE: "./all-posts.org::#nested-sections-example" :only-contents t
*** TOC
**** Post with toc set to non-nil
**** =num= set to =nil=
***** TOC with all headings (unnumbered)
:PROPERTIES:
:EXPORT_FILE_NAME: post-with-export-options-toc-t-num-nil
:EXPORT_OPTIONS: num:nil toc:t
:END:
#+INCLUDE: "./all-posts.org::#nested-sections-example" :only-contents t
***** TOC with headings (unnumbered) only till level 2
:PROPERTIES:
:EXPORT_FILE_NAME: post-with-toc-export-option-t
:EXPORT_OPTIONS: toc:t
:EXPORT_FILE_NAME: post-with-export-options-toc-2-num-nil
:EXPORT_OPTIONS: num:nil toc:2
:END:
#+INCLUDE: "./all-posts.org::#nested-sections-example" :only-contents t
**** Post with toc set to 2
***** No TOC as toc set to nil
:PROPERTIES:
:EXPORT_FILE_NAME: post-with-toc-export-option-2
:EXPORT_OPTIONS: toc:2
:EXPORT_FILE_NAME: post-with-export-options-toc-nil-num-nil
:EXPORT_OPTIONS: num:nil toc:nil
:END:
#+INCLUDE: "./all-posts.org::#nested-sections-example" :only-contents t
**** Post with toc set to nil
**** =num= set to =t=
***** TOC with all headings (numbered, except for selected unnumbered)
:PROPERTIES:
:EXPORT_FILE_NAME: post-with-toc-export-option-nil
:EXPORT_OPTIONS: toc:nil
:EXPORT_FILE_NAME: post-with-export-options-toc-t-num-t
:EXPORT_OPTIONS: num:t toc:t
:END:
#+INCLUDE: "./all-posts.org::#nested-sections-example" :only-contents t
**** Post with toc set to 0
***** TOC with headings (numbered, except for selected unnumbered) only till level 2
:PROPERTIES:
:EXPORT_FILE_NAME: post-with-toc-export-option-0
:EXPORT_OPTIONS: toc:0
:EXPORT_FILE_NAME: post-with-export-options-toc-2-num-t
:EXPORT_OPTIONS: num:t toc:2
:END:
#+INCLUDE: "./all-posts.org::#nested-sections-example" :only-contents t
**** Post with toc set to non-nil and num set to nil
***** No TOC as toc set to 0
:PROPERTIES:
:EXPORT_FILE_NAME: post-with-toc-export-option-t-and-num-nil
:EXPORT_OPTIONS: toc:t num:nil
:EXPORT_FILE_NAME: post-with-export-options-toc-0-num-t
:EXPORT_OPTIONS: num:t toc:0
:END:
#+INCLUDE: "./all-posts.org::#nested-sections-example" :only-contents t
**** Post with toc set to non-nil and num set to onlytoc
**** =num= set to =onlytoc=
***** TOC with all headings (post-unnumbered, TOC-numbered)
:PROPERTIES:
:EXPORT_FILE_NAME: post-with-toc-export-option-t-and-num-onlytoc
:EXPORT_OPTIONS: toc:t num:onlytoc
:EXPORT_FILE_NAME: post-with-export-options-toc-t-num-onlytoc
:EXPORT_OPTIONS: num:onlytoc toc:t
:END:
#+INCLUDE: "./all-posts.org::#nested-sections-example" :only-contents t
***** TOC with headings (post-unnumbered, TOC-numbered) only till level 2
:PROPERTIES:
:EXPORT_FILE_NAME: post-with-export-options-toc-1-num-onlytoc
:EXPORT_OPTIONS: num:onlytoc toc:1
:END:
#+INCLUDE: "./all-posts.org::#nested-sections-example" :only-contents t
* Hugo Aliases :aliases:
Expand Down Expand Up @@ -2565,14 +2513,78 @@ immediately after the post heading.
:PROPERTIES:
:UNNUMBERED: t
:END:
The =UNNUMBERED= property for this subtree is set to =t=. So even when
the TOC export option is set to =t= or a number ≥ 3, this title will
*not* show up in the TOC. That's because the TOC is exported as a
Markdown /ordered list/, and you cannot have ordered list items
without a number prefix!
The =UNNUMBERED= property for this subtree is set to =t=. So this
heading will show up as unnumbered in both the post body and the TOC.
***** Post sub-heading 2.2.3
*** Post sub-heading 3
**** Post sub-heading 3.1
** Source block with line numbers examples
:PROPERTIES:
:CUSTOM_ID: source-block-with-line-numbers-examples
:END:
#+BEGIN_SRC org :noweb-ref src-block-n-default-start
,#+BEGIN_SRC emacs-lisp -n
;; this will export with line number 1 (default)
(message "This is line 2")
,#+END_SRC
#+END_SRC

#+BEGIN_SRC org :noweb-ref src-block-n-custom-start
,#+BEGIN_SRC emacs-lisp -n 20
;; this will export with line number 20
(message "This is line 21")
,#+END_SRC
#+END_SRC

#+BEGIN_SRC org :noweb-ref src-block-n-default-continue
,#+BEGIN_SRC emacs-lisp +n
;; This will be listed as line 22
(message "This is line 23")
,#+END_SRC
#+END_SRC

#+BEGIN_SRC org :noweb-ref src-block-n-custom-continue
,#+BEGIN_SRC emacs-lisp +n 10
;; This will be listed as line 33
(message "This is line 34")
,#+END_SRC
#+END_SRC
** Source block with line highlighting examples
:PROPERTIES:
:CUSTOM_ID: source-block-with-line-highlighting-examples
:END:
#+BEGIN_SRC org :noweb-ref src-block-hl-without-n
,#+BEGIN_SRC emacs-lisp :hl_lines 1,3-5
(message "This is line 1")
(message "This is line 2")
(message "This is line 3")
(message "This is line 4")
(message "This is line 5")
(message "This is line 6")
,#+END_SRC
#+END_SRC

#+BEGIN_SRC org :noweb-ref src-block-hl-with-n-not-1
,#+BEGIN_SRC emacs-lisp -n 7 :hl_lines 1,3-5
(message "This is line 7 in code, but line 1 for highlighting reference")
(message "This is line 8 in code, but line 2 for highlighting reference")
(message "This is line 9 in code, but line 3 for highlighting reference")
(message "This is line 10 in code, but line 4 for highlighting reference")
(message "This is line 11 in code, but line 5 for highlighting reference")
(message "This is line 12 in code, but line 6 for highlighting reference")
,#+END_SRC
#+END_SRC

#+BEGIN_SRC org :noweb-ref src-block-hl-with-n
,#+BEGIN_SRC emacs-lisp -n :hl_lines 1,3-5
(message "This is line 1")
(message "This is line 2")
(message "This is line 3")
(message "This is line 4")
(message "This is line 5")
(message "This is line 6")
,#+END_SRC
#+END_SRC
** Lorem Ipsum
:PROPERTIES:
:CUSTOM_ID: lorem-ipsum
Expand Down
7 changes: 2 additions & 5 deletions test/site/content/posts/options-num-0.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,8 @@ draft = false

#### Post sub-heading 2.2.2 {#post-sub-heading-2-dot-2-dot-2}

The `UNNUMBERED` property for this subtree is set to `t`. So even when
the TOC export option is set to `t` or a number ≥ 3, this title will
**not** show up in the TOC. That's because the TOC is exported as a
Markdown _ordered list_, and you cannot have ordered list items
without a number prefix!
The `UNNUMBERED` property for this subtree is set to `t`. So this
heading will show up as unnumbered in both the post body and the TOC.


#### Post sub-heading 2.2.3 {#post-sub-heading-2-dot-2-dot-3}
Expand Down
Loading

0 comments on commit 4be378e

Please sign in to comment.