diff options
Diffstat (limited to 'paper/scholar-filters/json-ld.lua')
-rw-r--r-- | paper/scholar-filters/json-ld.lua | 233 |
1 files changed, 233 insertions, 0 deletions
diff --git a/paper/scholar-filters/json-ld.lua b/paper/scholar-filters/json-ld.lua new file mode 100644 index 0000000..b9cd101 --- /dev/null +++ b/paper/scholar-filters/json-ld.lua @@ -0,0 +1,233 @@ +-- json-ld.lua: add a JSON-LD metadata field describing the document. +-- +-- Copyright (c) 2017-2018 Albert Krewinkel +-- +-- This program is free software; you can redistribute it and/or modify it +-- under the terms of the GNU public license version 2 or later. +-- See the LICENSE file for details. +local SCRIPT_DIR = PANDOC_SCRIPT_FILE:gsub('/[^/]*$', '') + +package.path = SCRIPT_DIR .. '/?.lua;' .. package.path + +local json = require "dkjson" +local List = require 'pandoc.List' + +local function stringify(x) + if x == nil then + return nil + elseif type(x) == 'string' then + return x + end + return pandoc.utils.stringify(x) +end + +local function Organizations(orgs) + local orgs_json = {} + for i, org in ipairs(orgs) do + orgs_json[i] = { + ["@type"] = "Organization", + ["name"] = org.name and stringify(org.name), + ['url'] = org.url and stringify(org.url), + } + end + return orgs_json +end + +local function Authors(authors) + local authors_json = pandoc.MetaList{} + for i, author in ipairs(authors) do + authors_json[i] = { + ['@type'] = "Person", + ['@id'] = authors[i].orcid and + ("https://orcid.org/" .. stringify(authors[i].orcid)), + ["name"] = author.name and stringify(author.name), + ["affiliation"] = author.institute and Organizations(author.institute), + ['email'] = author.email and stringify(author.email), + ['url'] = author.url and stringify(author.url), + } + end + return authors_json +end + +local function Cito (bibjson, cites_by_cito_property) + function find_citation(id) + -- sloooow + for i = 1, #bibjson do + if bibjson[i].id == id then + return bibjson[i] + end + end + end + + local result = {} + local bibentry, citation_ld + for citation_type, typed_citation_ids in pairs(cites_by_cito_property) do + for i = 1, #typed_citation_ids do + bibentry = find_citation(typed_citation_ids[i]) + if bibentry and bibentry.DOI then + citation_ld = { + ["@id"] = "http://dx.doi.org/" .. bibentry.DOI + } + cito_type_str = "cito:" .. citation_type + if not result[cito_type_str] then + result[cito_type_str] = {} + end + table.insert(result[cito_type_str], citation_ld) + end + end + end + return result +end + +local function Citations (bibjson, citation_ids) + function find_citation(id) + -- sloooow + for i = 1, #bibjson do + if bibjson[i].id == id then + return bibjson[i] + end + end + end + + function CitationSchema(record) + local type + if record.type == "report" then + type = "Report" + elseif record.type == "article-journal" then + type = "ScholarlyArticle" + else + type = "Article" + end + + local authors = {} + if record.author then + for i = 1, #record.author do + local name = { + record.author[i].family, + record.author[i].given + } + authors[i] = { + name = table.concat(name, ", ") + } + end + end + + return { + ["@context"] = { + ["@vocab"] = "http://schema.org/", + ["title"] = "headline", + ["page"] = "pagination", + ["date"] = "datePublished", + ["publisher"] = "publisher", + ["author"] = "author", + }, + ["@type"] = type, + ["@id"] = record.DOI and ("http://dx.doi.org/" .. record.DOI), + ["title"] = record.title, + ["author"] = Authors(authors), + ["date"] = record.issued and + record.issued["date-parts"] and + table.concat(record.issued["date-parts"][1], "-"), + ["publisher"] = record.publisher and + { ["@type"] = "Organization", ["name"] = record.publisher }, + ["page"] = record.page, + } + end + + local res = {} + for cit_id, _ in pairs(citation_ids) do + local citation_record = find_citation(cit_id) + if citation_record then + res[#res + 1] = CitationSchema(citation_record) + end + end + return res +end + +function json_ld (meta) + local default_image = "https://upload.wikimedia.org/wikipedia/commons/f/fa/Globe.svg" + local accessible_for_free + if meta.accessible_for_free ~= nil then + accessible_for_free = meta.accessible_for_free + else + accessible_for_free = true + end + local context = { + ["@vocab"] = "http://schema.org/", + ["cito"] = "http://purl.org/spar/cito/", + ["author"] = "author", + ["name"] = "name", + ["title"] = "headline", + ["subtitle"] = "alternativeTitle", + ["publisher"] = "publisher", + ["date"] = "datePublished", + ["isFree"] = accessible_for_free and "isAccessibleForFree" or nil, + ["image"] = "image", + ["citation"] = "citation", + } + + local citation_ids = {} + for _, ids in pairs(meta.cito_cites) do + for _, id in ipairs(ids) do citation_ids[id] = true end + end + local result = { + ["@context"] = context, + ["@type"] = "ScholarlyArticle", + ["author"] = Authors(meta.author), + ["name"] = stringify(meta.title), + ["title"] = stringify(meta.title), + ["subtitle"] = meta.subtitle and stringify(meta.subtitle), + ["date"] = meta.date and stringify(meta.date) or os.date("%Y-%m-%d"), + -- -- ["image"] = meta.image or default_image, + ["isFree"] = accessible_for_free, + ["citation"] = Citations(meta.bibliography_records, citation_ids), + } + for k, v in pairs(Cito(meta.bibliography_records, meta.cito_cites)) do + result[k] = v + end + return result +end + +local function bibliography(bibfilename) + if not bibfilename then + return {} + end + local bibfile = io.popen("pandoc-citeproc --bib2json " .. bibfilename, "r") + local jsonstr = bibfile:read("*a") + bibfile:close() + return json.decode(jsonstr) +end + +local function institute_resolver (institutes) + return function (inst_idx) + return institutes[tonumber(stringify(inst_idx))] + end +end + +function Meta (meta) + local function clone (obj) + local result = {} + for k, v in pairs(obj) do result[k] = v end + return result + end + local metadata = clone(meta) + + local resolve_institute = function (idx) + return meta.institute[tonumber(idx)] + end + local tmp_authors = {} + for i, author_orig in ipairs(meta.author) do + local author = clone(author_orig) + if author.institute then + author.institute = List.map(author.institute, resolve_institute) + end + tmp_authors[i] = author + end + metadata.author = tmp_authors + + metadata.bibliography_records = bibliography(meta.bibliography) + local jsonld_object = json_ld(metadata) + meta.jsonld = json.encode(jsonld_object) + + return meta +end |