diff options
Diffstat (limited to 'paper/lua-filters/multiple-bibliographies')
7 files changed, 200 insertions, 0 deletions
diff --git a/paper/lua-filters/multiple-bibliographies/Makefile b/paper/lua-filters/multiple-bibliographies/Makefile new file mode 100644 index 0000000..a42ce28 --- /dev/null +++ b/paper/lua-filters/multiple-bibliographies/Makefile @@ -0,0 +1,6 @@ +test: sample.md multiple-bibliographies.lua + @pandoc --lua-filter=multiple-bibliographies.lua \ + --standalone --to=native $< 2>/dev/null \ + | diff -u - expected.native + +.PHONY: test diff --git a/paper/lua-filters/multiple-bibliographies/README.md b/paper/lua-filters/multiple-bibliographies/README.md new file mode 100644 index 0000000..0111ee6 --- /dev/null +++ b/paper/lua-filters/multiple-bibliographies/README.md @@ -0,0 +1,33 @@ +# multiple-bibliographies + +This filter allows to create multiple bibliographies using +`pandoc-citeproc`. The content of each bibliography is controlled +via YAML values and the file in which a bibliographic entry is +specified. + +## Usage + +Instead of using the usual *bibliography* metadata field, all +bibliographies must be defined via a separate field of the scheme +*bibliographyX*, e.g. + + --- + bibliography_main: main-bibliography.bib + bibliography_software: software.bib + --- + +The placement of bibliographies is controlled via special divs. + + # References + + ::: {#refs_main} + ::: + + # Software + + ::: {#refs_software} + ::: + +Each refsX div should have a matching bibliographyX entry in the +header. These divs are filled with citations from the respective +bib-file. diff --git a/paper/lua-filters/multiple-bibliographies/expected.native b/paper/lua-filters/multiple-bibliographies/expected.native new file mode 100644 index 0000000..a7ead12 --- /dev/null +++ b/paper/lua-filters/multiple-bibliographies/expected.native @@ -0,0 +1,14 @@ +Pandoc (Meta {unMeta = fromList [("bibliography_recommended_reading",MetaInlines [Str "secondary.bib"]),("bibliography_sources",MetaInlines [Str "primary.bib"]),("nocite",MetaInlines [Cite [Citation {citationId = "Knu86", citationPrefix = [], citationSuffix = [], citationMode = AuthorInText, citationNoteNum = 0, citationHash = 0}] [Str "@Knu86"],Str ",",Space,Cite [Citation {citationId = "Bae", citationPrefix = [], citationSuffix = [], citationMode = AuthorInText, citationNoteNum = 0, citationHash = 0}] [Str "@Bae"]]),("title",MetaInlines [Str "Multiple",Space,Str "Bibliographies",Space,Str "Demo"])]}) +[Para [Cite [Citation {citationId = "Nie72", citationPrefix = [], citationSuffix = [], citationMode = AuthorInText, citationNoteNum = 0, citationHash = 1}] [Str "Nietzsche",Space,Str "(1872)"],Str ",",Space,Cite [Citation {citationId = "Bel", citationPrefix = [], citationSuffix = [], citationMode = AuthorInText, citationNoteNum = 0, citationHash = 2}] [Str "Bellori",Space,Str "(1672)"]] +,Header 1 ("references",[],[]) [Str "References"] +,Div ("refs_sources",[],[]) + [Div ("ref-Bel",[],[]) + [Para [Str "Bellori.",Space,Str "1672.",Space,Emph [Str "Le",Space,Str "Vite",Space,Str "de\8217",Space,Str "Pittori,",Space,Str "Scultori",Space,Str "E",Space,Str "Architetti",Space,Str "Moderni"],Str "."]] + ,Div ("ref-Nie72",[],[]) + [Para [Str "Nietzsche,",Space,Str "Friedrich.",Space,Str "1872.",Space,Emph [Str "Die",Space,Str "Geburt",Space,Str "Der",Space,Str "Trag\246die",Space,Str "Aus",Space,Str "Dem",Space,Str "Geiste",Space,Str "Der",Space,Str "Musik"],Str "."]]] +,Header 1 ("recommended-reading",[],[]) [Str "Recommended",Space,Str "Reading"] +,Div ("refs_recommended_reading",[],[]) + [Div ("ref-Bae",[],[]) + [Para [Str "B\228tschmann,",Space,Str "Oskar.",Space,Str "1985.",Space,Emph [Str "Pygmalion",Space,Str "Als",Space,Str "Betrachter"],Str "."]] + ,Div ("ref-Knu86",[],[]) + [Para [Str "Knuth,",Space,Str "Donald",Space,Str "E.",Space,Str "1986.",Space,Emph [Str "The",Space,Str "Texbook"],Str "."]]]] diff --git a/paper/lua-filters/multiple-bibliographies/multiple-bibliographies.lua b/paper/lua-filters/multiple-bibliographies/multiple-bibliographies.lua new file mode 100644 index 0000000..934e6ea --- /dev/null +++ b/paper/lua-filters/multiple-bibliographies/multiple-bibliographies.lua @@ -0,0 +1,110 @@ +--[[ +multiple-bibliographies – create multiple bibliographies + +Copyright © 2018-2019 Albert Krewinkel + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +]] +local List = require 'pandoc.List' +local utils = require 'pandoc.utils' +local stringify = utils.stringify +local run_json_filter = utils.run_json_filter + +--- Collection of all cites in the document +local all_cites = {} +--- Document meta value +local doc_meta = pandoc.Meta{} + +--- Div used by pandoc-citeproc to insert the bibliography. +local refs_div = pandoc.Div({}, pandoc.Attr('refs')) + +local supports_quiet_flag = (function () + local version = pandoc.pipe('pandoc-citeproc', {'--version'}, '') + local major, minor, patch = version:match 'pandoc%-citeproc (%d+)%.(%d+)%.?(%d*)' + major, minor, patch = tonumber(major), tonumber(minor), tonumber(patch) + return major > 0 + or minor > 14 + or (minor == 14 and patch >= 5) +end)() + +--- Resolve citations in the document by combining all bibliographies +-- before running pandoc-citeproc on the full document. +local function resolve_doc_citations (doc) + -- combine all bibliographies + local meta = doc.meta + local orig_bib = meta.bibliography + meta.bibliography = pandoc.MetaList{orig_bib} + for name, value in pairs(meta) do + if name:match('^bibliography_') then + table.insert(meta.bibliography, value) + end + end + -- add dummy div to catch the created bibliography + table.insert(doc.blocks, refs_div) + -- resolve all citations + doc = run_json_filter(doc, 'pandoc-citeproc') + -- remove catch-all bibliography + table.remove(doc.blocks) + -- restore bibliography to original value + doc.meta.bibliography = orig_bib + return doc +end + +--- Explicitly create a new meta object with all fields relevant for +--- pandoc-citeproc. +local function meta_for_pandoc_citeproc (bibliography) + -- We could just indiscriminately copy all meta fields, but let's be + -- explicit about what's important. + local fields = { + 'bibliography', 'references', 'csl', 'citation-style', + 'link-citations', 'citation-abbreviations', 'lang', + 'suppress-bibliography', 'reference-section-title', + 'notes-after-punctuation', 'nocite' + } + local new_meta = pandoc.Meta{} + for _, field in ipairs(fields) do + new_meta[field] = doc_meta[field] + end + new_meta.bibliography = bibliography + return new_meta +end + +--- Create a bibliography for a given topic. This acts on all divs whose +-- ID starts with "refs", followed by nothing but underscores and +-- alphanumeric characters. +local function create_topic_bibliography (div) + local name = div.identifier:match('^refs([_%w]*)$') + local bibfile = name and doc_meta['bibliography' .. name] + if not bibfile then + return nil + end + local tmp_blocks = {pandoc.Para(all_cites), refs_div} + local tmp_meta = meta_for_pandoc_citeproc(bibfile) + local tmp_doc = pandoc.Pandoc(tmp_blocks, tmp_meta) + local filter_args = {FORMAT, supports_quiet_flag and '-q' or nil} + local res = run_json_filter(tmp_doc, 'pandoc-citeproc', filter_args) + -- First block of the result contains the dummy paragraph, second is + -- the refs Div filled by pandoc-citeproc. + div.content = res.blocks[2].content + return div +end + +return { + { + -- Collect all citations and the doc's Meta value for other filters. + Cite = function (c) all_cites[#all_cites + 1] = c end, + Meta = function (m) doc_meta = m end, + }, + { Pandoc = resolve_doc_citations }, + { Div = create_topic_bibliography }, +} diff --git a/paper/lua-filters/multiple-bibliographies/primary.bib b/paper/lua-filters/multiple-bibliographies/primary.bib new file mode 100644 index 0000000..8c9decc --- /dev/null +++ b/paper/lua-filters/multiple-bibliographies/primary.bib @@ -0,0 +1,10 @@ +@book{Bel,
+ author = {Bellori},
+ title = {Le vite de' pittori, scultori e architetti moderni},
+ year = {1672},
+}
+@book{Nie72,
+ author = {Nietzsche, Friedrich},
+ title = {Die Geburt der Tragödie aus dem Geiste der Musik},
+ year = {1872},
+}
diff --git a/paper/lua-filters/multiple-bibliographies/sample.md b/paper/lua-filters/multiple-bibliographies/sample.md new file mode 100644 index 0000000..d4ab2eb --- /dev/null +++ b/paper/lua-filters/multiple-bibliographies/sample.md @@ -0,0 +1,17 @@ +--- +title: Multiple Bibliographies Demo +bibliography_sources: primary.bib +bibliography_recommended_reading: secondary.bib +nocite: '@Knu86, @Bae' +--- +@Nie72, @Bel + +# References + +::: {#refs_sources} +::: + +# Recommended Reading + +::: {#refs_recommended_reading} +::: diff --git a/paper/lua-filters/multiple-bibliographies/secondary.bib b/paper/lua-filters/multiple-bibliographies/secondary.bib new file mode 100644 index 0000000..45e6306 --- /dev/null +++ b/paper/lua-filters/multiple-bibliographies/secondary.bib @@ -0,0 +1,10 @@ +@book{Bae,
+ author = {Bätschmann, Oskar},
+ title = {Pygmalion als Betrachter},
+ year = {1985}
+}
+@book{Knu86,
+ author = {Knuth, Donald E.},
+ year = {1986},
+ title = {The \TeX book},
+}
|