add _extensions
This commit is contained in:
@@ -0,0 +1,16 @@
|
||||
title: Authors and affiliation formatting for quarto
|
||||
authors:
|
||||
- name: Ming Su
|
||||
email: mingsu@rcees.ac.cn
|
||||
orcid: 0000-0001-9821-1268
|
||||
url: https://drwater.net/team/ming-su/
|
||||
- name: Lorenz A. Kapsner
|
||||
orcid: 0000-0003-1866-860X
|
||||
- name: Albert Krewinkel
|
||||
orcid: 0000-0002-9455-0796
|
||||
- name: Robert Winkler
|
||||
version: 0.3.2
|
||||
quarto-required: ">=1.3.0"
|
||||
contributes:
|
||||
filters:
|
||||
- authoraffil.lua
|
||||
@@ -0,0 +1,16 @@
|
||||
title: Authors and affiliation formatting for quarto
|
||||
authors:
|
||||
- name: Ming Su
|
||||
email: mingsu@rcees.ac.cn
|
||||
orcid: 0000-0001-9821-1268
|
||||
url: https://drwater.net/team/ming-su/
|
||||
- name: Lorenz A. Kapsner
|
||||
orcid: 0000-0003-1866-860X
|
||||
- name: Albert Krewinkel
|
||||
orcid: 0000-0002-9455-0796
|
||||
- name: Robert Winkler
|
||||
version: 0.3.2
|
||||
quarto-required: ">=1.3.0"
|
||||
contributes:
|
||||
filters:
|
||||
- authoraffil.lua
|
||||
@@ -0,0 +1,75 @@
|
||||
--[[
|
||||
authors-block – affiliations block extension for quarto
|
||||
Copyright (c) 2023 Lorenz A. Kapsner
|
||||
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 from_utils = require("utils")
|
||||
local normalize_affiliations = from_utils.normalize_affiliations
|
||||
local normalize_authors = from_utils.normalize_authors
|
||||
local from_authors = require("from_author_info_blocks")
|
||||
local default_marks = from_authors.default_marks
|
||||
local create_equal_contributors_block = from_authors.create_equal_contributors_block
|
||||
local create_affiliations_blocks = from_authors.create_affiliations_blocks
|
||||
local create_correspondence_blocks = from_authors.create_correspondence_blocks
|
||||
local is_corresponding_author = from_authors.is_corresponding_author
|
||||
local author_inline_generator = from_authors.author_inline_generator
|
||||
local create_authors_inlines = from_authors.create_authors_inlines
|
||||
|
||||
function Pandoc(doc)
|
||||
local meta = doc.meta
|
||||
local body = List:new({})
|
||||
local mark = function(mark_name)
|
||||
return default_marks[mark_name]
|
||||
end
|
||||
|
||||
-- Process CRediT roles
|
||||
if meta.authors then
|
||||
local credit_roles = List:new({})
|
||||
for i, author in ipairs(meta.authors) do
|
||||
if author.role then
|
||||
local roles = List:new({})
|
||||
for role, level in pairs(author.role) do
|
||||
roles:insert(pandoc.Str(role .. ": " .. stringify(level)))
|
||||
end
|
||||
if #roles > 0 then
|
||||
local author_name = stringify(author.name)
|
||||
credit_roles:insert(pandoc.Para({
|
||||
pandoc.Str(author_name .. ": "),
|
||||
pandoc.Str(table.concat(roles:map(stringify), ", ")),
|
||||
}))
|
||||
end
|
||||
end
|
||||
end
|
||||
if #credit_roles > 0 then
|
||||
body:insert(pandoc.Header(2, pandoc.Str("Author Contributions")))
|
||||
body:extend(credit_roles)
|
||||
end
|
||||
end
|
||||
|
||||
body:extend(create_equal_contributors_block(meta.authors, mark) or {})
|
||||
body:extend(create_affiliations_blocks(meta.affiliations, meta) or {})
|
||||
body:extend(create_correspondence_blocks(meta.authors, mark) or {})
|
||||
body:extend(doc.blocks)
|
||||
|
||||
for _i, author in ipairs(meta.authors) do
|
||||
author.test = is_corresponding_author(author)
|
||||
end
|
||||
|
||||
meta.affiliations = normalize_affiliations(meta.affiliations or {})
|
||||
meta.author = meta.authors:map(normalize_authors(meta.affiliations))
|
||||
meta.author = pandoc.MetaInlines(create_authors_inlines(meta.author, mark, meta))
|
||||
meta.affiliations = nil
|
||||
|
||||
return pandoc.Pandoc(body, meta)
|
||||
end
|
||||
+297
@@ -0,0 +1,297 @@
|
||||
--[[
|
||||
affiliation-blocks – generate title components
|
||||
Copyright © 2017–2021 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 from_utils = require("utils")
|
||||
local has_key = from_utils.has_key
|
||||
local List = require("pandoc.List")
|
||||
local utils = require("pandoc.utils")
|
||||
local stringify = utils.stringify
|
||||
|
||||
local M = {}
|
||||
|
||||
local default_marks = {
|
||||
corresponding_author = FORMAT == "latex" and { pandoc.RawInline("latex", "*") } or { pandoc.Str("*") },
|
||||
equal_contributor = FORMAT == "latex" and { pandoc.RawInline("latex", "\\#") } or { pandoc.Str("#") },
|
||||
}
|
||||
|
||||
local function get_orcid_mark(orcid_value)
|
||||
if not orcid_value then
|
||||
return {}
|
||||
end
|
||||
local orcid_str
|
||||
if type(orcid_value) == "string" then
|
||||
orcid_str = orcid_value
|
||||
elseif type(orcid_value) == "table" then
|
||||
if orcid_value.text then
|
||||
orcid_str = orcid_value.text
|
||||
elseif orcid_value[1] and orcid_value[1].text then
|
||||
orcid_str = orcid_value[1].text
|
||||
else
|
||||
return {}
|
||||
end
|
||||
else
|
||||
return {}
|
||||
end
|
||||
orcid_str = orcid_str:gsub("[%-%s]", "")
|
||||
if FORMAT == "latex" then
|
||||
return { pandoc.RawInline("latex", "\\orcidlink{" .. orcid_str .. "}") }
|
||||
elseif FORMAT:match("docx") then
|
||||
local orcid_url = "https://orcid.org/" .. orcid_str
|
||||
return {
|
||||
pandoc.Str(" "),
|
||||
pandoc.Link("ID", orcid_url),
|
||||
}
|
||||
else
|
||||
local orcid_url = "https://orcid.org/" .. orcid_str
|
||||
return { pandoc.Link(pandoc.Str(""), orcid_url, "", { class = "orcid" }) }
|
||||
end
|
||||
end
|
||||
|
||||
M.default_marks = default_marks
|
||||
|
||||
local function is_equal_contributor(author)
|
||||
if has_key(author, "attributes") then
|
||||
return author.attributes["equal-contributor"]
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
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
|
||||
M.create_equal_contributors_block = create_equal_contributors_block
|
||||
|
||||
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
|
||||
|
||||
local function is_corresponding_author(author)
|
||||
if has_key(author, "attributes") then
|
||||
if author.attributes["corresponding"] then
|
||||
return author.email
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
M.is_corresponding_author = is_corresponding_author
|
||||
|
||||
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:" .. stringify(author.email)
|
||||
local author_with_mail = List:new(
|
||||
author.name.literal
|
||||
.. 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("Corresponding to:"),
|
||||
pandoc.Space(),
|
||||
})
|
||||
local sep = List:new({ pandoc.Str(","), pandoc.Space() })
|
||||
return { pandoc.Para(correspondence .. intercalate(corresponding_authors, sep)) }
|
||||
end
|
||||
|
||||
M.create_correspondence_blocks = create_correspondence_blocks
|
||||
|
||||
local function author_inline_generator(get_mark, meta)
|
||||
return function(author)
|
||||
local author_marks = List:new({})
|
||||
if has_key(author, "orcid") then
|
||||
author_marks[#author_marks + 1] = get_orcid_mark(author.orcid)
|
||||
end
|
||||
local affilstyle = meta and meta.affilstyle and stringify(meta.affilstyle) or "alphabeta"
|
||||
for _, idx in ipairs(author.affiliations) do
|
||||
local idx_num = tonumber(stringify(idx)) -- Convert MetaString/MetaInlines to number
|
||||
if not idx_num then
|
||||
error("Invalid affiliation index: " .. tostring(idx))
|
||||
end
|
||||
local idx_str
|
||||
if affilstyle == "number" then
|
||||
idx_str = tostring(idx_num)
|
||||
else
|
||||
if idx_num > 26 then
|
||||
error("Too many affiliations: only up to 26 (a-z) are supported")
|
||||
end
|
||||
idx_str = string.char(96 + idx_num)
|
||||
end
|
||||
author_marks[#author_marks + 1] = { pandoc.Str(idx_str) }
|
||||
end
|
||||
if has_key(author, "attributes") then
|
||||
if author.attributes["equal-contributor"] then
|
||||
author_marks[#author_marks + 1] = get_mark("equal_contributor")
|
||||
end
|
||||
end
|
||||
if is_corresponding_author(author) then
|
||||
author_marks[#author_marks + 1] = get_mark("corresponding_author")
|
||||
end
|
||||
if FORMAT:match("latex") then
|
||||
author.name.literal[#author.name.literal + 1] = pandoc.Superscript(intercalate(author_marks, { pandoc.Str(",") }))
|
||||
return author
|
||||
else
|
||||
local res = List.clone(author.name.literal)
|
||||
res[#res + 1] = pandoc.Superscript(intercalate(author_marks, { pandoc.Str(",") }))
|
||||
return res
|
||||
end
|
||||
end
|
||||
end
|
||||
M.author_inline_generator = author_inline_generator
|
||||
|
||||
local function create_authors_inlines(authors, mark, meta)
|
||||
local inlines_generator = author_inline_generator(mark, meta)
|
||||
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
|
||||
if #authors == 2 then
|
||||
result:extend(and_str)
|
||||
else
|
||||
result:extend(List:new({ pandoc.Str(",") }) .. and_str)
|
||||
end
|
||||
end
|
||||
result:extend(last_author)
|
||||
return result
|
||||
end
|
||||
M.create_authors_inlines = create_authors_inlines
|
||||
|
||||
local function create_affiliations_blocks_alphabeta(affiliations, meta)
|
||||
local affilstyle = meta and meta.affilstyle and stringify(meta.affilstyle) or "alphabeta"
|
||||
local affil_lines = List:new(affiliations):map(function(affil, i)
|
||||
if affilstyle == "number" then
|
||||
num_inlines = pandoc.List:new({
|
||||
pandoc.Superscript(pandoc.Str(tostring(i))),
|
||||
pandoc.Space(),
|
||||
})
|
||||
else
|
||||
num_inlines = pandoc.List:new({
|
||||
pandoc.Superscript(pandoc.Str(string.char(96 + i))),
|
||||
pandoc.Space(),
|
||||
})
|
||||
end
|
||||
local name_inlines = type(affil.name) == "table" and affil.name or { pandoc.Str(tostring(affil.name)) }
|
||||
local city_inlines = type(affil.city) == "table" and affil.city or { pandoc.Str(tostring(affil.city)) }
|
||||
local postcode_inlines = type(affil["postal-code"]) == "table" and affil["postal-code"]
|
||||
or { pandoc.Str(tostring(affil["postal-code"])) }
|
||||
local country_inlines = type(affil.country) == "table" and affil.country
|
||||
or { pandoc.Str(tostring(affil.country or affil["postal-code"])) }
|
||||
return num_inlines
|
||||
:extend(name_inlines)
|
||||
:extend({ pandoc.Str(", ") })
|
||||
:extend(city_inlines)
|
||||
:extend({ pandoc.Space() })
|
||||
:extend(postcode_inlines)
|
||||
:extend({ pandoc.Str(", ") })
|
||||
:extend(country_inlines)
|
||||
:extend({ pandoc.Str(".") })
|
||||
end)
|
||||
local combined_inlines = pandoc.List:new()
|
||||
for i, line in ipairs(affil_lines) do
|
||||
combined_inlines:extend(line)
|
||||
if i < #affil_lines then
|
||||
combined_inlines:extend({ pandoc.LineBreak() })
|
||||
end
|
||||
end
|
||||
return { pandoc.Para(combined_inlines) }
|
||||
end
|
||||
|
||||
local function create_affiliations_blocks_number(affiliations, meta)
|
||||
local affilstyle = meta and meta.affilstyle and stringify(meta.affilstyle) or "alphabeta"
|
||||
local affil_lines = List:new(affiliations):map(function(affil, i)
|
||||
local num_inlines = pandoc.List:new({
|
||||
pandoc.Superscript(pandoc.Str(tostring(i))),
|
||||
pandoc.Space(),
|
||||
})
|
||||
local name_inlines = type(affil.name) == "table" and affil.name or { pandoc.Str(tostring(affil.name)) }
|
||||
local city_inlines = type(affil.city) == "table" and affil.city or { pandoc.Str(tostring(affil.city)) }
|
||||
local postcode_inlines = type(affil["postal-code"]) == "table" and affil["postal-code"]
|
||||
or { pandoc.Str(tostring(affil["postal-code"])) }
|
||||
local country_inlines = type(affil.country) == "table" and affil.country
|
||||
or { pandoc.Str(tostring(affil.country or affil["postal-code"])) }
|
||||
return num_inlines
|
||||
:extend(name_inlines)
|
||||
:extend({ pandoc.Str(", ") })
|
||||
:extend(city_inlines)
|
||||
:extend({ pandoc.Space() })
|
||||
:extend(postcode_inlines)
|
||||
:extend({ pandoc.Str(", ") })
|
||||
:extend(country_inlines)
|
||||
:extend({ pandoc.Str(".") })
|
||||
end)
|
||||
local combined_inlines = pandoc.List:new()
|
||||
for i, line in ipairs(affil_lines) do
|
||||
combined_inlines:extend(line)
|
||||
if i < #affil_lines then
|
||||
combined_inlines:extend({ pandoc.LineBreak() })
|
||||
end
|
||||
end
|
||||
return { pandoc.Para(combined_inlines) }
|
||||
end
|
||||
|
||||
M.create_affiliations_blocks = create_affiliations_blocks_alphabeta
|
||||
|
||||
function Meta(meta)
|
||||
local affilstyle = meta and meta.affilstyle and stringify(meta.affilstyle) or "alphabeta"
|
||||
M.create_affiliations_blocks = affilstyle == "number" and create_affiliations_blocks_number
|
||||
or create_affiliations_blocks_alphabeta
|
||||
if meta.authors then
|
||||
meta.author = create_authors_inlines(meta.authors, M.default_marks, meta)
|
||||
end
|
||||
if meta.affiliations then
|
||||
meta.institute = M.create_affiliations_blocks(meta.affiliations, meta)
|
||||
end
|
||||
if meta.authors then
|
||||
local equal_contributors = create_equal_contributors_block(meta.authors, M.default_marks)
|
||||
if equal_contributors then
|
||||
meta["equal-contributors"] = equal_contributors
|
||||
end
|
||||
local correspondence = create_correspondence_blocks(meta.authors, M.default_marks)
|
||||
if correspondence then
|
||||
meta.correspondence = correspondence
|
||||
end
|
||||
end
|
||||
return meta
|
||||
end
|
||||
|
||||
return M
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
--[[
|
||||
ScholarlyMeta – normalize author/affiliation meta variables
|
||||
Copyright (c) 2017-2021 Albert Krewinkel, Robert Winkler
|
||||
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 M = {}
|
||||
|
||||
local function has_id(id)
|
||||
return function(x)
|
||||
return x.id == id
|
||||
end
|
||||
end
|
||||
|
||||
local function resolve_institutes(institute, known_institutes)
|
||||
local unresolved_institutes
|
||||
if institute == nil then
|
||||
unresolved_institutes = {}
|
||||
elseif type(institute) == "string" or type(institute) == "number" then
|
||||
unresolved_institutes = { institute }
|
||||
else
|
||||
unresolved_institutes = institute
|
||||
end
|
||||
local result = List:new({})
|
||||
for i, inst in ipairs(unresolved_institutes) do
|
||||
local intermed_val = known_institutes:find_if(has_id(stringify(inst)))
|
||||
if intermed_val then
|
||||
result[i] = pandoc.MetaString(tostring(intermed_val.index))
|
||||
else
|
||||
result[i] = pandoc.MetaString(tostring(inst))
|
||||
end
|
||||
end
|
||||
return result
|
||||
end
|
||||
M.resolve_institutes = resolve_institutes
|
||||
|
||||
return M
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
--[[
|
||||
authors-block – affiliations block extension for quarto
|
||||
Copyright (c) 2023 Lorenz A. Kapsner
|
||||
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 from_scholarly = require("from_scholarly_metadata")
|
||||
local resolve_institutes = from_scholarly.resolve_institutes
|
||||
|
||||
local M = {}
|
||||
|
||||
local function normalize_affiliations(affiliations)
|
||||
local affiliations_norm = List:new(affiliations or {}):map(function(affil, i)
|
||||
affil.index = pandoc.MetaString(tostring(i))
|
||||
affil.id = pandoc.MetaString(stringify(affil.id or affil.name))
|
||||
return affil
|
||||
end)
|
||||
return affiliations_norm
|
||||
end
|
||||
M.normalize_affiliations = normalize_affiliations
|
||||
|
||||
local function has_key(set, key)
|
||||
return set[key] ~= nil
|
||||
end
|
||||
M.has_key = has_key
|
||||
|
||||
local function normalize_authors(affiliations)
|
||||
return function(auth)
|
||||
auth.id = pandoc.MetaString(stringify(auth.name))
|
||||
auth.affiliations = resolve_institutes(auth.affiliations or {}, affiliations)
|
||||
return auth
|
||||
end
|
||||
end
|
||||
M.normalize_authors = normalize_authors
|
||||
|
||||
return M
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
--[[
|
||||
authors-block – affiliations block extension for quarto
|
||||
Copyright (c) 2023 Lorenz A. Kapsner
|
||||
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 from_utils = require("utils")
|
||||
local normalize_affiliations = from_utils.normalize_affiliations
|
||||
local normalize_authors = from_utils.normalize_authors
|
||||
local from_authors = require("from_author_info_blocks")
|
||||
local default_marks = from_authors.default_marks
|
||||
local create_equal_contributors_block = from_authors.create_equal_contributors_block
|
||||
local create_affiliations_blocks = from_authors.create_affiliations_blocks
|
||||
local create_correspondence_blocks = from_authors.create_correspondence_blocks
|
||||
local is_corresponding_author = from_authors.is_corresponding_author
|
||||
local author_inline_generator = from_authors.author_inline_generator
|
||||
local create_authors_inlines = from_authors.create_authors_inlines
|
||||
|
||||
function Pandoc(doc)
|
||||
local meta = doc.meta
|
||||
local body = List:new({})
|
||||
local mark = function(mark_name)
|
||||
return default_marks[mark_name]
|
||||
end
|
||||
|
||||
-- Process CRediT roles
|
||||
if meta.authors then
|
||||
local credit_roles = List:new({})
|
||||
for i, author in ipairs(meta.authors) do
|
||||
if author.role then
|
||||
local roles = List:new({})
|
||||
for role, level in pairs(author.role) do
|
||||
roles:insert(pandoc.Str(role .. ": " .. stringify(level)))
|
||||
end
|
||||
if #roles > 0 then
|
||||
local author_name = stringify(author.name)
|
||||
credit_roles:insert(pandoc.Para({
|
||||
pandoc.Str(author_name .. ": "),
|
||||
pandoc.Str(table.concat(roles:map(stringify), ", ")),
|
||||
}))
|
||||
end
|
||||
end
|
||||
end
|
||||
if #credit_roles > 0 then
|
||||
body:insert(pandoc.Header(2, pandoc.Str("Author Contributions")))
|
||||
body:extend(credit_roles)
|
||||
end
|
||||
end
|
||||
|
||||
body:extend(create_equal_contributors_block(meta.authors, mark) or {})
|
||||
body:extend(create_affiliations_blocks(meta.affiliations, meta) or {})
|
||||
body:extend(create_correspondence_blocks(meta.authors, mark) or {})
|
||||
body:extend(doc.blocks)
|
||||
|
||||
for _i, author in ipairs(meta.authors) do
|
||||
author.test = is_corresponding_author(author)
|
||||
end
|
||||
|
||||
meta.affiliations = normalize_affiliations(meta.affiliations or {})
|
||||
meta.author = meta.authors:map(normalize_authors(meta.affiliations))
|
||||
meta.author = pandoc.MetaInlines(create_authors_inlines(meta.author, mark, meta))
|
||||
meta.affiliations = nil
|
||||
|
||||
return pandoc.Pandoc(body, meta)
|
||||
end
|
||||
@@ -0,0 +1,297 @@
|
||||
--[[
|
||||
affiliation-blocks – generate title components
|
||||
Copyright © 2017–2021 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 from_utils = require("utils")
|
||||
local has_key = from_utils.has_key
|
||||
local List = require("pandoc.List")
|
||||
local utils = require("pandoc.utils")
|
||||
local stringify = utils.stringify
|
||||
|
||||
local M = {}
|
||||
|
||||
local default_marks = {
|
||||
corresponding_author = FORMAT == "latex" and { pandoc.RawInline("latex", "*") } or { pandoc.Str("*") },
|
||||
equal_contributor = FORMAT == "latex" and { pandoc.RawInline("latex", "\\#") } or { pandoc.Str("#") },
|
||||
}
|
||||
|
||||
local function get_orcid_mark(orcid_value)
|
||||
if not orcid_value then
|
||||
return {}
|
||||
end
|
||||
local orcid_str
|
||||
if type(orcid_value) == "string" then
|
||||
orcid_str = orcid_value
|
||||
elseif type(orcid_value) == "table" then
|
||||
if orcid_value.text then
|
||||
orcid_str = orcid_value.text
|
||||
elseif orcid_value[1] and orcid_value[1].text then
|
||||
orcid_str = orcid_value[1].text
|
||||
else
|
||||
return {}
|
||||
end
|
||||
else
|
||||
return {}
|
||||
end
|
||||
orcid_str = orcid_str:gsub("[%-%s]", "")
|
||||
if FORMAT == "latex" then
|
||||
return { pandoc.RawInline("latex", "\\orcidlink{" .. orcid_str .. "}") }
|
||||
elseif FORMAT:match("docx") then
|
||||
local orcid_url = "https://orcid.org/" .. orcid_str
|
||||
return {
|
||||
pandoc.Str(" "),
|
||||
pandoc.Link("ID", orcid_url),
|
||||
}
|
||||
else
|
||||
local orcid_url = "https://orcid.org/" .. orcid_str
|
||||
return { pandoc.Link(pandoc.Str(""), orcid_url, "", { class = "orcid" }) }
|
||||
end
|
||||
end
|
||||
|
||||
M.default_marks = default_marks
|
||||
|
||||
local function is_equal_contributor(author)
|
||||
if has_key(author, "attributes") then
|
||||
return author.attributes["equal-contributor"]
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
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
|
||||
M.create_equal_contributors_block = create_equal_contributors_block
|
||||
|
||||
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
|
||||
|
||||
local function is_corresponding_author(author)
|
||||
if has_key(author, "attributes") then
|
||||
if author.attributes["corresponding"] then
|
||||
return author.email
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
M.is_corresponding_author = is_corresponding_author
|
||||
|
||||
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:" .. stringify(author.email)
|
||||
local author_with_mail = List:new(
|
||||
author.name.literal
|
||||
.. 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("Corresponding to:"),
|
||||
pandoc.Space(),
|
||||
})
|
||||
local sep = List:new({ pandoc.Str(","), pandoc.Space() })
|
||||
return { pandoc.Para(correspondence .. intercalate(corresponding_authors, sep)) }
|
||||
end
|
||||
|
||||
M.create_correspondence_blocks = create_correspondence_blocks
|
||||
|
||||
local function author_inline_generator(get_mark, meta)
|
||||
return function(author)
|
||||
local author_marks = List:new({})
|
||||
if has_key(author, "orcid") then
|
||||
author_marks[#author_marks + 1] = get_orcid_mark(author.orcid)
|
||||
end
|
||||
local affilstyle = meta and meta.affilstyle and stringify(meta.affilstyle) or "alphabeta"
|
||||
for _, idx in ipairs(author.affiliations) do
|
||||
local idx_num = tonumber(stringify(idx)) -- Convert MetaString/MetaInlines to number
|
||||
if not idx_num then
|
||||
error("Invalid affiliation index: " .. tostring(idx))
|
||||
end
|
||||
local idx_str
|
||||
if affilstyle == "number" then
|
||||
idx_str = tostring(idx_num)
|
||||
else
|
||||
if idx_num > 26 then
|
||||
error("Too many affiliations: only up to 26 (a-z) are supported")
|
||||
end
|
||||
idx_str = string.char(96 + idx_num)
|
||||
end
|
||||
author_marks[#author_marks + 1] = { pandoc.Str(idx_str) }
|
||||
end
|
||||
if has_key(author, "attributes") then
|
||||
if author.attributes["equal-contributor"] then
|
||||
author_marks[#author_marks + 1] = get_mark("equal_contributor")
|
||||
end
|
||||
end
|
||||
if is_corresponding_author(author) then
|
||||
author_marks[#author_marks + 1] = get_mark("corresponding_author")
|
||||
end
|
||||
if FORMAT:match("latex") then
|
||||
author.name.literal[#author.name.literal + 1] = pandoc.Superscript(intercalate(author_marks, { pandoc.Str(",") }))
|
||||
return author
|
||||
else
|
||||
local res = List.clone(author.name.literal)
|
||||
res[#res + 1] = pandoc.Superscript(intercalate(author_marks, { pandoc.Str(",") }))
|
||||
return res
|
||||
end
|
||||
end
|
||||
end
|
||||
M.author_inline_generator = author_inline_generator
|
||||
|
||||
local function create_authors_inlines(authors, mark, meta)
|
||||
local inlines_generator = author_inline_generator(mark, meta)
|
||||
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
|
||||
if #authors == 2 then
|
||||
result:extend(and_str)
|
||||
else
|
||||
result:extend(List:new({ pandoc.Str(",") }) .. and_str)
|
||||
end
|
||||
end
|
||||
result:extend(last_author)
|
||||
return result
|
||||
end
|
||||
M.create_authors_inlines = create_authors_inlines
|
||||
|
||||
local function create_affiliations_blocks_alphabeta(affiliations, meta)
|
||||
local affilstyle = meta and meta.affilstyle and stringify(meta.affilstyle) or "alphabeta"
|
||||
local affil_lines = List:new(affiliations):map(function(affil, i)
|
||||
if affilstyle == "number" then
|
||||
num_inlines = pandoc.List:new({
|
||||
pandoc.Superscript(pandoc.Str(tostring(i))),
|
||||
pandoc.Space(),
|
||||
})
|
||||
else
|
||||
num_inlines = pandoc.List:new({
|
||||
pandoc.Superscript(pandoc.Str(string.char(96 + i))),
|
||||
pandoc.Space(),
|
||||
})
|
||||
end
|
||||
local name_inlines = type(affil.name) == "table" and affil.name or { pandoc.Str(tostring(affil.name)) }
|
||||
local city_inlines = type(affil.city) == "table" and affil.city or { pandoc.Str(tostring(affil.city)) }
|
||||
local postcode_inlines = type(affil["postal-code"]) == "table" and affil["postal-code"]
|
||||
or { pandoc.Str(tostring(affil["postal-code"])) }
|
||||
local country_inlines = type(affil.country) == "table" and affil.country
|
||||
or { pandoc.Str(tostring(affil.country or affil["postal-code"])) }
|
||||
return num_inlines
|
||||
:extend(name_inlines)
|
||||
:extend({ pandoc.Str(", ") })
|
||||
:extend(city_inlines)
|
||||
:extend({ pandoc.Space() })
|
||||
:extend(postcode_inlines)
|
||||
:extend({ pandoc.Str(", ") })
|
||||
:extend(country_inlines)
|
||||
:extend({ pandoc.Str(".") })
|
||||
end)
|
||||
local combined_inlines = pandoc.List:new()
|
||||
for i, line in ipairs(affil_lines) do
|
||||
combined_inlines:extend(line)
|
||||
if i < #affil_lines then
|
||||
combined_inlines:extend({ pandoc.LineBreak() })
|
||||
end
|
||||
end
|
||||
return { pandoc.Para(combined_inlines) }
|
||||
end
|
||||
|
||||
local function create_affiliations_blocks_number(affiliations, meta)
|
||||
local affilstyle = meta and meta.affilstyle and stringify(meta.affilstyle) or "alphabeta"
|
||||
local affil_lines = List:new(affiliations):map(function(affil, i)
|
||||
local num_inlines = pandoc.List:new({
|
||||
pandoc.Superscript(pandoc.Str(tostring(i))),
|
||||
pandoc.Space(),
|
||||
})
|
||||
local name_inlines = type(affil.name) == "table" and affil.name or { pandoc.Str(tostring(affil.name)) }
|
||||
local city_inlines = type(affil.city) == "table" and affil.city or { pandoc.Str(tostring(affil.city)) }
|
||||
local postcode_inlines = type(affil["postal-code"]) == "table" and affil["postal-code"]
|
||||
or { pandoc.Str(tostring(affil["postal-code"])) }
|
||||
local country_inlines = type(affil.country) == "table" and affil.country
|
||||
or { pandoc.Str(tostring(affil.country or affil["postal-code"])) }
|
||||
return num_inlines
|
||||
:extend(name_inlines)
|
||||
:extend({ pandoc.Str(", ") })
|
||||
:extend(city_inlines)
|
||||
:extend({ pandoc.Space() })
|
||||
:extend(postcode_inlines)
|
||||
:extend({ pandoc.Str(", ") })
|
||||
:extend(country_inlines)
|
||||
:extend({ pandoc.Str(".") })
|
||||
end)
|
||||
local combined_inlines = pandoc.List:new()
|
||||
for i, line in ipairs(affil_lines) do
|
||||
combined_inlines:extend(line)
|
||||
if i < #affil_lines then
|
||||
combined_inlines:extend({ pandoc.LineBreak() })
|
||||
end
|
||||
end
|
||||
return { pandoc.Para(combined_inlines) }
|
||||
end
|
||||
|
||||
M.create_affiliations_blocks = create_affiliations_blocks_alphabeta
|
||||
|
||||
function Meta(meta)
|
||||
local affilstyle = meta and meta.affilstyle and stringify(meta.affilstyle) or "alphabeta"
|
||||
M.create_affiliations_blocks = affilstyle == "number" and create_affiliations_blocks_number
|
||||
or create_affiliations_blocks_alphabeta
|
||||
if meta.authors then
|
||||
meta.author = create_authors_inlines(meta.authors, M.default_marks, meta)
|
||||
end
|
||||
if meta.affiliations then
|
||||
meta.institute = M.create_affiliations_blocks(meta.affiliations, meta)
|
||||
end
|
||||
if meta.authors then
|
||||
local equal_contributors = create_equal_contributors_block(meta.authors, M.default_marks)
|
||||
if equal_contributors then
|
||||
meta["equal-contributors"] = equal_contributors
|
||||
end
|
||||
local correspondence = create_correspondence_blocks(meta.authors, M.default_marks)
|
||||
if correspondence then
|
||||
meta.correspondence = correspondence
|
||||
end
|
||||
end
|
||||
return meta
|
||||
end
|
||||
|
||||
return M
|
||||
@@ -0,0 +1,51 @@
|
||||
--[[
|
||||
ScholarlyMeta – normalize author/affiliation meta variables
|
||||
Copyright (c) 2017-2021 Albert Krewinkel, Robert Winkler
|
||||
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 M = {}
|
||||
|
||||
local function has_id(id)
|
||||
return function(x)
|
||||
return x.id == id
|
||||
end
|
||||
end
|
||||
|
||||
local function resolve_institutes(institute, known_institutes)
|
||||
local unresolved_institutes
|
||||
if institute == nil then
|
||||
unresolved_institutes = {}
|
||||
elseif type(institute) == "string" or type(institute) == "number" then
|
||||
unresolved_institutes = { institute }
|
||||
else
|
||||
unresolved_institutes = institute
|
||||
end
|
||||
local result = List:new({})
|
||||
for i, inst in ipairs(unresolved_institutes) do
|
||||
local intermed_val = known_institutes:find_if(has_id(stringify(inst)))
|
||||
if intermed_val then
|
||||
result[i] = pandoc.MetaString(tostring(intermed_val.index))
|
||||
else
|
||||
result[i] = pandoc.MetaString(tostring(inst))
|
||||
end
|
||||
end
|
||||
return result
|
||||
end
|
||||
M.resolve_institutes = resolve_institutes
|
||||
|
||||
return M
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
---
|
||||
title: "MANUSCRIPT TITLE"
|
||||
subtitle: "Supplementary Information"
|
||||
submitjournal: "JOURNAL"
|
||||
submitid:
|
||||
lang: en
|
||||
date: ""
|
||||
# bibliography: [BB/Ref.bib, BB/localRef.bib]
|
||||
affilstyle: alphabeta # number
|
||||
author:
|
||||
- name: Xxxxx Yyyy
|
||||
affiliations:
|
||||
- ref: kleac
|
||||
# email: 13586740928@163.com
|
||||
attributes:
|
||||
corresponding: false
|
||||
equal-contributor: true
|
||||
role:
|
||||
- data-curation: lead
|
||||
- methodology: lead
|
||||
- formalanalysis: lead
|
||||
- writingoriginal: equal
|
||||
- writingediting: eqaul
|
||||
- visualisation: supporting
|
||||
- name: Ming Su
|
||||
email: mingsu@rcees.ac.cn
|
||||
url: https://drwater.net/team/ming-su/
|
||||
role:
|
||||
- conceptualization: lead
|
||||
- methodology: supporting
|
||||
- formalanalysis: lead
|
||||
- writingoriginal: equal
|
||||
- writingediting: equal
|
||||
- visualisation: lead
|
||||
- projectadmin: lead
|
||||
- supervision
|
||||
affiliations:
|
||||
- ref: kleac
|
||||
- ref: ucas
|
||||
attributes:
|
||||
corresponding: true
|
||||
equal-contributor: true
|
||||
- name: Min Yang
|
||||
email: yangmin@rcees.ac.cn
|
||||
affiliations:
|
||||
- ref: kleac
|
||||
- ref: ucas
|
||||
attributes:
|
||||
corresponding: true
|
||||
affiliations:
|
||||
- id: kleac
|
||||
name: State Key Laboratory of Environmental Aquatic Chemistry, Research Center for Eco-Environmental Sciences, Chinese Academy of Sciences
|
||||
# address: No. 18 Shuangqing Road
|
||||
city: Beijing
|
||||
postal-code: 100085
|
||||
country: China
|
||||
url: https://www.skleac.ac.cn
|
||||
- id: ucas
|
||||
name: University of Chinese Academy of Sciences
|
||||
# address: No. 19A Yuquan Road
|
||||
city: Beijing
|
||||
postal-code: 100049
|
||||
country: China
|
||||
url: https://www.ucas.ac.cn
|
||||
prefer-html: true
|
||||
format:
|
||||
# elsevier-html:
|
||||
# toc: true
|
||||
# css: _extensions/drwater/dwms/inst/css/style.css
|
||||
# docx:
|
||||
# reference-doc: _extensions/drwater/dwms/inst/word/MS.docx
|
||||
pdf:
|
||||
fontsize: 12pt
|
||||
keep-md: false
|
||||
keep-tex: false
|
||||
filters:
|
||||
# - latex-environment
|
||||
- authoraffil
|
||||
---
|
||||
|
||||
|
||||
```{r}
|
||||
#| include: false
|
||||
#| cache: false
|
||||
|
||||
lang <- "en"
|
||||
isRendering <- isTRUE(getOption("knitr.in.progress"))
|
||||
require(tidyverse)
|
||||
require(drwateR)
|
||||
require(patchwork)
|
||||
rmdify::rmd_init()
|
||||
dwfun::init()
|
||||
```
|
||||
|
||||
|
||||
{{< pagebreak >}}
|
||||
|
||||
# Abstract {-}
|
||||
|
||||
|
||||
{{< pagebreak >}}
|
||||
|
||||
|
||||
{{< pagebreak >}}
|
||||
|
||||
<!-- {{< include _est.qmd >}} -->
|
||||
|
||||
# References {-}
|
||||
|
||||
::: {#refs}
|
||||
:::
|
||||
|
||||
{{< pagebreak >}}
|
||||
|
||||
<!-- {{< include _nature.qmd >}} -->
|
||||
@@ -0,0 +1,49 @@
|
||||
--[[
|
||||
authors-block – affiliations block extension for quarto
|
||||
Copyright (c) 2023 Lorenz A. Kapsner
|
||||
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 from_scholarly = require("from_scholarly_metadata")
|
||||
local resolve_institutes = from_scholarly.resolve_institutes
|
||||
|
||||
local M = {}
|
||||
|
||||
local function normalize_affiliations(affiliations)
|
||||
local affiliations_norm = List:new(affiliations or {}):map(function(affil, i)
|
||||
affil.index = pandoc.MetaString(tostring(i))
|
||||
affil.id = pandoc.MetaString(stringify(affil.id or affil.name))
|
||||
return affil
|
||||
end)
|
||||
return affiliations_norm
|
||||
end
|
||||
M.normalize_affiliations = normalize_affiliations
|
||||
|
||||
local function has_key(set, key)
|
||||
return set[key] ~= nil
|
||||
end
|
||||
M.has_key = has_key
|
||||
|
||||
local function normalize_authors(affiliations)
|
||||
return function(auth)
|
||||
auth.id = pandoc.MetaString(stringify(auth.name))
|
||||
auth.affiliations = resolve_institutes(auth.affiliations or {}, affiliations)
|
||||
return auth
|
||||
end
|
||||
end
|
||||
M.normalize_authors = normalize_authors
|
||||
|
||||
return M
|
||||
|
||||
Reference in New Issue
Block a user