Skip to content

Commit

Permalink
Support BIBLIOGRAPHY and pandoc-citeproc
Browse files Browse the repository at this point in the history
This is first commit of a series of commits to support
pandoc-citeproc.

New keywords/properties:
- HUGO_PANDOC_CITEPROC
- BIBLIOGRAPHY

Ref: #175
  • Loading branch information
kaushalmodi committed Jul 18, 2018
1 parent a1a2dbf commit ad2f5d0
Show file tree
Hide file tree
Showing 6 changed files with 224 additions and 6 deletions.
21 changes: 21 additions & 0 deletions doc/ox-hugo-manual.org
Expand Up @@ -2069,6 +2069,27 @@ What do you do? ..
You can find a bunch of examples if you search for /"Replace
front-matter keys"/ in {{{ox-hugo-test-file}}}.
- Those examples are exported as {{{testtag(replace)}}}.
*** Pandoc Citation
:PROPERTIES:
:EXPORT_FILE_NAME: pandoc-citation
:END:
Pandoc based citation parsing is enabled by setting the
~#+hugo_pandoc_citeproc:~ keyword or ~:EXPORT_HUGO_PANDOC_CITEPROC:~
subtree property to ~t~. With this property set, the exported
front-matter is *forced to YAML*, because Pandoc needs the
front-matter to be in YAML format to parse fields like ~bibliography~
~csl~ and ~nocite~.

#+begin_note
User needs to have the ~pandoc~ executable present in their ~PATH~.
#+end_note

Bibliography files (~example.bib~) are specified using the
~#+bibliography:~ keyword or ~:EXPORT_BIBLIOGRAPHY:~ subtree
property. Multiple bibliography files can be specified
comma-separated.

See [[https://pandoc.org/MANUAL.html#citations][Pandoc Manual -- Citations]] for more details.
** Meta
:PROPERTIES:
:EXPORT_HUGO_MENU: :menu "7.meta"
Expand Down
84 changes: 78 additions & 6 deletions ox-hugo.el
Expand Up @@ -781,6 +781,8 @@ newer."
(:hugo-front-matter-key-replace "HUGO_FRONT_MATTER_KEY_REPLACE" nil nil space)
(:hugo-date-format "HUGO_DATE_FORMAT" nil org-hugo-date-format)
(:hugo-paired-shortcodes "HUGO_PAIRED_SHORTCODES" nil org-hugo-paired-shortcodes space)
(:hugo-pandoc-citeproc "HUGO_PANDOC_CITEPROC" nil nil)
(:bibliography "BIBLIOGRAPHY" nil nil newline)

;; Front matter variables
;; https://gohugo.io/content-management/front-matter/#front-matter-variables
Expand Down Expand Up @@ -947,17 +949,45 @@ This is an internal function."
(setq org-hugo--subtree-coord nil))
(advice-add 'org-babel-exp-code :around #'org-hugo--org-babel-exp-code))

(defun org-hugo--after-export-function ()
(defun org-hugo--after-export-function (info outfile)
"Function to be run after an ox-hugo export.
This function is called in the very end of
`org-hugo-export-to-md', `org-hugo-export-as-md' and
`org-hugo-publish-to-md'.
INFO is a plist used as a communication channel.
OUTFILE is the Org exported file name.
This is an internal function."
(setq org-hugo--section nil)
(setq org-hugo--bundle nil)
(advice-remove 'org-babel-exp-code #'org-hugo--org-babel-exp-code))
(advice-remove 'org-babel-exp-code #'org-hugo--org-babel-exp-code)
;; (message "pandoc citeproc keyword: %S"
;; (org-hugo--plist-get-true-p info :hugo-pandoc-citeproc))
;; (message "pandoc citeproc prop: %S"
;; (org-entry-get nil "EXPORT_HUGO_PANDOC_CITEPROC" :inherit))
;; Optionally post-process the post for citations.
(when (and outfile
(or (org-entry-get nil "EXPORT_HUGO_PANDOC_CITEPROC" :inherit)
(org-hugo--plist-get-true-p info :hugo-pandoc-citeproc)))
(unless (executable-find "pandoc")
(user-error "[ox-hugo] pandoc executable not found in PATH"))
(unless (executable-find "pandoc-citeproc")
(user-error "[ox-hugo] pandoc-citeproc executable not found in PATH"))
;; TODO: Figure out how to transfer the error in this
;; `start-process' to the user.
(start-process "pandoc-parse-citations" " *Pandoc Parse Citations*"
"pandoc"
"--filter" "pandoc-citeproc"
"--from=markdown"
"--to=markdown-citations"
"--atx-headers" ;Use "# foo" style heading for output markdown
"--standalone" ;Include meta-data at the top
(concat "--output=" outfile) ;Output file
outfile ;Input file
)))

;;;; HTMLized section number for headline
(defun org-hugo--get-headline-number (headline info &optional toc)
Expand Down Expand Up @@ -2766,7 +2796,12 @@ the Hugo front-matter."
INFO is a plist used as a communication channel."
;; (message "[hugo front matter DBG] info: %S" (pp info))
(let* ((fm-format (plist-get info :hugo-front-matter-format))
(let* ((fm-format (if (org-hugo--plist-get-true-p info :hugo-pandoc-citeproc)
;; pandoc-citeproc parses fields like
;; bibliography, csl and nocite from YAML
;; front-matter.
"yaml"
(plist-get info :hugo-front-matter-format)))
(author-list (and (plist-get info :with-author)
(let ((author-raw
(org-string-nw-p
Expand All @@ -2786,6 +2821,34 @@ INFO is a plist used as a communication channel."
;; Don't allow spaces around author names.
;; Also remove duplicate authors.
(delete-dups (mapcar #'org-trim author-list-1)))))))
(bib-list (let ((bib-raw
(org-string-nw-p
(org-export-data (plist-get info :bibliography) info)))) ;`org-export-data' required
(when bib-raw
;; Multiple bibliographies can be comma
;; or newline separated. The newline
;; separated bibliographies work only for the
;; #+bibliography keyword; example:
;; #+bibliography: bibliographies-1.bib
;; #+bibliography: bibliographies-2.bib
;;
;; If using the subtree properties they need to
;; be comma-separated (now don't use commas in
;; those file names, you will suffer):
;; :EXPORT_BIBLIOGRAPHY: bibliographies-1.bib, bibliographies-2.bib
(let ((bib-list-1 (org-split-string bib-raw "[,\n]")))
;; - Don't allow spaces around bib names.
;; - Convert file names to absolute paths.
;; - Remove duplicate bibliographies.
(delete-dups (mapcar (lambda (bib-file)
(let ((fname (file-truename
(org-trim
bib-file))))
(unless (file-exists-p fname)
(user-error "Bibliography file %S does not exist"
fname))
fname))
bib-list-1))))))
(creator (and (plist-get info :with-creator)
(plist-get info :creator)))
(locale (and (plist-get info :hugo-with-locale)
Expand Down Expand Up @@ -2907,6 +2970,7 @@ INFO is a plist used as a communication channel."
(title . ,(org-hugo--sanitize-title info))
(audio . ,(plist-get info :hugo-audio))
(author . ,author-list)
(bibliography . ,bib-list)
(description . ,description)
(date . ,(org-hugo--format-date :date info))
(publishDate . ,(org-hugo--format-date :hugo-publishdate info))
Expand Down Expand Up @@ -2947,6 +3011,7 @@ INFO is a plist used as a communication channel."
;; (message "[fm tags DBG] %S" tags)
;; (message "[fm categories DBG] %S" categories)
;; (message "[fm keywords DBG] %S" keywords)
;; (message "[fm bib-list DBG] %S" bib-list)
(setq data (org-hugo--replace-keys-maybe data info))
(org-hugo--gen-front-matter data fm-format)))

Expand Down Expand Up @@ -3230,6 +3295,8 @@ are \"toml\" and \"yaml\"."
"HUGO_EXPIRYDATE"
"HUGO_LASTMOD"
"HUGO_SLUG" ;Useful for inheriting same slug to same posts in different languages
"HUGO_PANDOC_CITEPROC"
"BIBLIOGRAPHY"
"HUGO_AUTO_SET_LASTMOD")))
(mapcar (lambda (str)
(concat "EXPORT_" str))
Expand Down Expand Up @@ -3334,11 +3401,16 @@ Return the buffer the export happened to."
(interactive)
(org-hugo--before-export-function subtreep)
;; Allow certain `ox-hugo' properties to be inherited.
(let ((org-use-property-inheritance (org-hugo--selective-property-inheritance)))
(let ((org-use-property-inheritance (org-hugo--selective-property-inheritance))
(info (org-combine-plists
(org-export--get-export-attributes
'hugo subtreep visible-only)
(org-export--get-buffer-attributes)
(org-export-get-environment 'hugo subtreep))))
(prog1
(org-export-to-buffer 'hugo "*Org Hugo Export*"
async subtreep visible-only nil nil (lambda () (text-mode)))
(org-hugo--after-export-function))))
(org-hugo--after-export-function info nil))))

;;;###autoload
(defun org-hugo-export-to-md (&optional async subtreep visible-only)
Expand Down Expand Up @@ -3396,7 +3468,7 @@ Return output file's name."
(when do-export
(prog1
(org-export-to-file 'hugo outfile async subtreep visible-only)
(org-hugo--after-export-function)))))
(org-hugo--after-export-function info outfile)))))

;; FIXME: org-publish based exporting is not yet supported.
;; ;;;###autoload
Expand Down
23 changes: 23 additions & 0 deletions test/site/content-org/all-posts.org
Expand Up @@ -4589,6 +4589,27 @@ This post should also be created in =content/section-a/=.
:END:
#+toc: headlines 6
#+include: "./all-posts.org::#nested-sections-example" :only-contents t
* Pandoc :pandoc:
** Citeproc :citeproc:
*** Citations Example
:PROPERTIES:
:EXPORT_FILE_NAME: citations-example
:EXPORT_HUGO_PANDOC_CITEPROC: t
:EXPORT_BIBLIOGRAPHY: bib/bib1.bib, bib/bib2.bib
:EXPORT_HUGO_CUSTOM_FRONT_MATTER: :nocite '(@giovanelli2016 @eilan2016)
:END:
**** Section 1
Here is a test example file with an in-text citation where someone
important says something important (e.g. @loncar2016). And here is
another bit of blah with a footnote citation.[fn:5]

See [[#citation-example-section-2]].
**** Section 2
:PROPERTIES:
:CUSTOM_ID: citation-example-section-2
:END:
Content in section 2.
**** COMMENT References
* Export Options :export_option:
** Table of Contents (TOC) :toc:
=ox-hugo= has the =with-toc= option disabled by default as Hugo has an
Expand Down Expand Up @@ -6587,6 +6608,8 @@ blandit in.
Results from static site search implemented using /Fusejs/, /jquery/
and /mark.js/. -- [[https://gist.github.com/eddiewebb/735feb48f50f0ddd65ae5606a1cb41ae][Source]]
* Footnotes

[fn:5] See [@thompson2016].
[fn:4] Even if the user has set the =HUGO_CODE_FENCE= value to =t=
(via variable, keyword or subtree property), the Hugo =highlight=
shortcode will be used automatically instead of code fences if either
Expand Down
22 changes: 22 additions & 0 deletions test/site/content-org/bib/bib1.bib
@@ -0,0 +1,22 @@

@article{giovanelli2016,
title = {"...{{But I}} Still Can't Get Rid of a Sense of Artificiality" {{The Reichenbach}}–{{Einstein}} Debate on the Geometrization of the Electromagnetic Field},
volume = {54},
journaltitle = {Studies in History and Philosophy of Science},
date = {2016},
pages = {35--51},
keywords = {Einstein,physics,science},
author = {Giovanelli, Marco},
file = {/Users/roambot/Dropbox/Work/MasterLib/giovanelli2016_the_reichenbach–einstein_debate.pdf}
}

@article{eilan2016,
title = {You {{Me}} and the {{World}}},
volume = {76},
number = {3},
journaltitle = {Analysis},
date = {2016},
pages = {311--324},
author = {Eilan, Naomi},
file = {/Users/roambot/Dropbox/Work/MasterLib/eilan2016_you_me_and_the_world.pdf}
}
29 changes: 29 additions & 0 deletions test/site/content-org/bib/bib2.bib
@@ -0,0 +1,29 @@
@article{loncar2016,
title = {Why {{Listen}} to {{Philosophers}}? {{A Constructive Critique}} of {{Disciplinary Philosophy}}},
volume = {47},
number = {1},
journaltitle = {Metaphilosophy},
date = {2016},
pages = {3--25},
author = {Loncar, Samuel},
file = {/Users/roambot/Dropbox/Work/MasterLib/loncar2016_why_listen_to_philosophers.pdf}
}

@article{thompson2016,
title = {Why {{Do Women Leave Philosophy}}? {{Surveying Students}} at the {{Introductory Level}}},
abstract = {Abstract Although recent research suggests that women are underrepresented in philosophy after initial philosophy courses, there have been relatively few empirical investigations into the factors that lead to this early drop-off in women's representation. In this paper, we.},
date = {2016},
author = {Thompson, Morgan and Adleberg, Toni and Sims, Sam and Nahmias, Eddy},
file = {/Users/roambot/Dropbox/Work/MasterLib/thompson2016_why_do_women_leave_philosophy.pdf}
}

@article{fricker2016,
title = {What's the {{Point}} of {{Blame}}? {{A Paradigm Based Explanation}}: {{What}}'s the {{Point}} of {{Blame}}},
volume = {50},
number = {1},
journaltitle = {Noûs},
date = {2016},
pages = {165--183},
author = {Fricker, Miranda},
file = {/Users/roambot/Dropbox/Work/MasterLib/fricker2016_what's_the_point_of_blame.pdf}
}
51 changes: 51 additions & 0 deletions test/site/content/posts/citations-example.md
@@ -0,0 +1,51 @@
---
bibliography:
- '/home/kmodi/stow/pub\_dotfiles/emacs/dot-emacs.d/elisp/ox-hugo/test/site/content-org/bib/bib1.bib'
- '/home/kmodi/stow/pub\_dotfiles/emacs/dot-emacs.d/elisp/ox-hugo/test/site/content-org/bib/bib2.bib'
draft: False
nocite:
- '@giovanelli2016'
- '@eilan2016'
tags:
- pandoc
- citeproc
title: Citations Example
---

## Section 1

Here is a test example file with an in-text citation where someone
important says something important (e.g. Loncar (2016)). And here is
another bit of blah with a footnote citation.[^1]

See [Section 2](#citation-example-section-2).

## Section 2 {#citation-example-section-2}

Content in section 2.

::: {#refs .references}
::: {#ref-eilan2016}
Eilan, Naomi. 2016. "You Me and the World." *Analysis* 76 (3): 311--24.
:::

::: {#ref-giovanelli2016}
Giovanelli, Marco. 2016. "\"\...But I Still Can't Get Rid of a Sense of
Artificiality\" the Reichenbach--Einstein Debate on the Geometrization
of the Electromagnetic Field." *Studies in History and Philosophy of
Science* 54: 35--51.
:::

::: {#ref-loncar2016}
Loncar, Samuel. 2016. "Why Listen to Philosophers? A Constructive
Critique of Disciplinary Philosophy." *Metaphilosophy* 47 (1): 3--25.
:::

::: {#ref-thompson2016}
Thompson, Morgan, Toni Adleberg, Sam Sims, and Eddy Nahmias. 2016. "Why
Do Women Leave Philosophy? Surveying Students at the Introductory
Level."
:::
:::

[^1]: See (Thompson et al. 2016).

0 comments on commit ad2f5d0

Please sign in to comment.