diff options
Diffstat (limited to 'paper/lua-filters/author-info-blocks/author-info-blocks.lua')
-rw-r--r-- | paper/lua-filters/author-info-blocks/author-info-blocks.lua | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/paper/lua-filters/author-info-blocks/author-info-blocks.lua b/paper/lua-filters/author-info-blocks/author-info-blocks.lua new file mode 100644 index 0000000..27e32bc --- /dev/null +++ b/paper/lua-filters/author-info-blocks/author-info-blocks.lua @@ -0,0 +1,176 @@ +--[[ +affiliation-blocks – generate title components + +Copyright © 2017–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 default_marks +local default_marks = { + corresponding_author = FORMAT == 'latex' + and {pandoc.RawInline('latex', '*')} + or {pandoc.Str '✉'}, + equal_contributor = FORMAT == 'latex' + and {pandoc.RawInline('latex', '$\\dagger{}$')} + or {pandoc.Str '*'}, +} + +local function intercalate(lists, elem) + local result = List:new{} + for i = 1, (#lists - 1) do + result:extend(lists[i]) + result:extend(elem) + end + if #lists > 0 then + result:extend(lists[#lists]) + end + return result +end + +--- Check whether the given author is a corresponding author +local function is_corresponding_author(author) + return author.correspondence and author.email +end + +--- Create inlines for a single author (includes all author notes) +local function author_inline_generator (get_mark) + return function (author) + local author_marks = List:new{} + if author.equal_contributor then + author_marks[#author_marks + 1] = get_mark 'equal_contributor' + end + local idx_str + for _, idx in ipairs(author.institute) do + if type(idx) ~= 'table' then + idx_str = tostring(idx) + else + idx_str = stringify(idx) + end + author_marks[#author_marks + 1] = {pandoc.Str(idx_str)} + end + if is_corresponding_author(author) then + author_marks[#author_marks + 1] = get_mark 'corresponding_author' + end + local res = List.clone(author.name) + res[#res + 1] = pandoc.Superscript(intercalate(author_marks, {pandoc.Str ','})) + return res + end +end + +local function is_equal_contributor (author) + return author.equal_contributor +end + +--- Create equal contributors note. +local function create_equal_contributors_block(authors, mark) + local has_equal_contribs = List:new(authors):find_if(is_equal_contributor) + if not has_equal_contribs then + return nil + end + local contributors = { + pandoc.Superscript(mark'equal_contributor'), + pandoc.Space(), + pandoc.Str 'These authors contributed equally to this work.' + } + return List:new{pandoc.Para(contributors)} +end + +--- Generate a block list all affiliations, marked with arabic numbers. +local function create_affiliations_blocks(affiliations) + local affil_lines = List:new(affiliations):map( + function (affil, i) + local num_inlines = List:new{ + pandoc.Superscript{pandoc.Str(tostring(i))}, + pandoc.Space() + } + return num_inlines .. affil.name + end + ) + return {pandoc.Para(intercalate(affil_lines, {pandoc.LineBreak()}))} +end + +--- Generate a block element containing the correspondence information +local function create_correspondence_blocks(authors, mark) + local corresponding_authors = List:new{} + for _, author in ipairs(authors) do + if is_corresponding_author(author) then + local mailto = 'mailto:' .. pandoc.utils.stringify(author.email) + local author_with_mail = List:new( + author.name .. List:new{pandoc.Space(), pandoc.Str '<'} .. + author.email .. List:new{pandoc.Str '>'} + ) + local link = pandoc.Link(author_with_mail, mailto) + table.insert(corresponding_authors, {link}) + end + end + if #corresponding_authors == 0 then + return nil + end + local correspondence = List:new{ + pandoc.Superscript(mark'corresponding_author'), + pandoc.Space(), + pandoc.Str'Correspondence:', + pandoc.Space() + } + local sep = List:new{pandoc.Str',', pandoc.Space()} + return { + pandoc.Para(correspondence .. intercalate(corresponding_authors, sep)) + } +end + +--- Generate a list of inlines containing all authors. +local function create_authors_inlines(authors, mark) + local inlines_generator = author_inline_generator(mark) + local inlines = List:new(authors):map(inlines_generator) + local and_str = List:new{pandoc.Space(), pandoc.Str'and', pandoc.Space()} + + local last_author = inlines[#inlines] + inlines[#inlines] = nil + local result = intercalate(inlines, {pandoc.Str ',', pandoc.Space()}) + if #authors > 1 then + result:extend(List:new{pandoc.Str ","} .. and_str) + end + result:extend(last_author) + return result +end + +return { + { + Pandoc = function (doc) + local meta = doc.meta + local body = List:new{} + + local mark = function (mark_name) return default_marks[mark_name] end + + body:extend(create_equal_contributors_block(doc.meta.author, mark) or {}) + body:extend(create_affiliations_blocks(doc.meta.institute) or {}) + body:extend(create_correspondence_blocks(doc.meta.author, mark) or {}) + body:extend(doc.blocks) + + -- Overwrite authors with formatted values. We use a single, formatted + -- string for most formats. LaTeX output, however, looks nicer if we + -- provide a authors as a list. + meta.author = FORMAT:match 'latex' + and pandoc.MetaList(doc.meta.author):map(author_inline_generator(mark)) + or pandoc.MetaInlines(create_authors_inlines(doc.meta.author, mark)) + -- Institute info is now baked into the affiliations block. + meta.institute = nil + + return pandoc.Pandoc(body, meta) + end + } +} |