Skip to content

Commit

Permalink
chore: Merge branch 'release-v1.1.0b'
Browse files Browse the repository at this point in the history
  • Loading branch information
odkr committed May 17, 2021
2 parents 1c4908c + 548949a commit 1df3d93
Show file tree
Hide file tree
Showing 3 changed files with 326 additions and 36 deletions.
235 changes: 200 additions & 35 deletions pandoc-zotxt.lua
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ local _ENV = M


-- Shorthands.
local concat = table.concat
local unpack = table.unpack

local stringify = pandoc.utils.stringify
Expand All @@ -141,6 +142,7 @@ local List = pandoc.List
local MetaInlines = pandoc.MetaInlines
local MetaList = pandoc.MetaList
local Str = pandoc.Str
local Span = pandoc.Span


-- Metadata
Expand Down Expand Up @@ -221,7 +223,7 @@ do
for i = 1, n do
assert(segs[i] ~= '', 'Path segment is the empty string ("").')
end
local path = table.concat(segs, PATH_SEP)
local path = concat(segs, PATH_SEP)
for i = 1, #san_es do path = path:gsub(unpack(san_es[i])) end
return path
end
Expand All @@ -246,7 +248,7 @@ do
local vers = {'5.4', '5.3'}
for i = 1, #vers do
local sub_dir = path_join('share', 'lua', vers[i], '?.lua')
package.path = table.concat({package.path,
package.path = concat({package.path,
path_join(SCPT_DIR, sub_dir),
path_join(SCPT_DIR, repo, sub_dir)
}, ';')
Expand Down Expand Up @@ -296,6 +298,22 @@ end
-- Tables
-- ------

function rmap (func, data, _rd)
if type(data) ~= 'table' then return func(nil, data) end
if not _rd then _rd = 0 end
assert(_rd < 512, 'Too much recursion.')
local ret = {}
local k = next(data, nil)
while k do
local v = data[k]
if type(v) == 'table' then v = rmap(func, v, _rd + 1) end
ret[k] = func(k, v)
k = next(data, k)
end
return ret
end


--- Return the keys and the length of a table.
--
-- @tab tab The table.
Expand Down Expand Up @@ -641,33 +659,173 @@ end
-- Converters
-- ----------

--- Convert numbers to strings recursively.
--
-- Also converts floating point numbers to integers. This is needed
-- because all numbers are floating point numbers in JSON, but some
-- versions of Pandoc expect integers.
--
-- @tab data The data.
-- @return A copy of `data` with numbers converted to strings.
-- @raise An error if the data is nested too deeply.
-- @within Converters
function rconv_nums_to_strs (data, _rd)
if not _rd then _rd = 0 end
assert(_rd < 1024, 'Too much recursion.')
local t = type(data)
if t == 'table' then
local ret = {}
for k, v in pairs(data) do
ret[k] = rconv_nums_to_strs(v, _rd + 1)
CSL_KEYS_FORMATTABLE = {
'abstract', -- The abstract.
'collection-title', -- E.g., a series.
'collection-title-short', -- A short version of the title.
'container-title', -- Publication the item was published in.
'container-title-short', -- A short version of that title.
'original-publisher', -- Original publisher.
'original-publisher-place', -- Place the item was originally published in.
'original-title', -- Original title.
'publisher', -- Publisher.
'publisher-place', -- The city/cities the item was published in.
'reviewed-title', -- Title reviewed in the item.
'title', -- The title.
'title-short', -- A short version of the title.
'short-title', -- A short version of the title.
}


do
local function esc_bold_and_italics (op, tx, cl)
if #op > 3 or #op ~= #cl then return nil end
if #op == 3 then return op:gsub('.', '\\%1') .. tx .. cl end
return '\\' .. op .. tx .. cl
end

local esc_es = {
{'(\\+)', '\\%1'},
{'(%*+)([^%*%s][^*]*)(%*+)', esc_bold_and_italics},
{'(_+)([^_%s][^_]*)(_+)', esc_bold_and_italics},
{'%^([^%^%s]+)%^', '\\^%1^'},
{'~([^~%s]+)~', '\\~%1~'},
{'(%b[][%({])', '\\%1'}
}

-- https://docs.citationstyles.org/en/1.0/release-notes.html#rich-text-markup-within-fields
-- other markdown is not supported. see also pandoc.
function esc_inline_md (str)
for i = 1, #esc_es do str = str:gsub(unpack(esc_es[i])) end
return str
end
end

do
local filter = {}

local function mk_elem_conv_f (char)
return function (elem)
local str = stringify(pandoc.walk_inline(elem, filter))
return Str(char .. str .. char)
end
end

filter.Emph = mk_elem_conv_f '*'
filter.Strong = mk_elem_conv_f '**'
filter.Subscript = mk_elem_conv_f '~'
filter.Superscript = mk_elem_conv_f '^'

function filter.Span (span)
local str = stringify(pandoc.walk_inline(span, filter))
local attrs = ''

if span.identifier then
local id = stringify(span.identifier)
if id ~= '' then attrs = '#' .. id end
end

if span.classes then
for i = 1, #span.classes do
if attrs ~= '' then attrs = attrs .. ' ' end
attrs = attrs .. '.' .. span.classes[i]
end
end

if span.attributes then
for k, v in pairs(span.attributes) do
if attrs ~= '' then attrs = attrs .. ' ' end
attrs = attrs .. k .. '="' .. v .. '"'
end
end

if attrs ~= '' then str = '[' .. str .. ']{' .. attrs .. '}' end
return Str(str)
end

function filter.SmallCaps (sc)
local span = Span(sc.content)
span.attributes.style = 'font-variant: small-caps'
return filter.Span(span)
end

local function conv_sc_to_span (str)
local tmp, n = str:gsub('<sc>', '<span style="font-variant: small-caps">')
if n == 0 then return str end
local ret, m = tmp:gsub('</sc>', '</span>')
if m == 0 then return str end
return ret
elseif t == 'number' then
end

function conv_html_to_md (str)
local md_escaped = esc_inline_md(str)
local sc_replaced = conv_sc_to_span(md_escaped)
local doc = pandoc.read(sc_replaced, 'html')
for i = 1, #doc.blocks do
doc.blocks[i] = pandoc.walk_block(doc.blocks[i], filter)
end
return stringify(doc)
end
end

do
local keys_formattable = {}
for i = 1, #CSL_KEYS_FORMATTABLE do
keys_formattable[CSL_KEYS_FORMATTABLE[i]] = true
end

local function conv (key, val)
if not keys_formattable[key] or
type(val) ~= 'string' then return val end
return conv_html_to_md(val)
end

-- https://docs.citationstyles.org/en/1.0/release-notes.html#rich-text-markup-within-fields
-- https://pandoc.org/MANUAL.html#specifying-bibliographic-data
function conv_zotfmt_to_pdfmt (item)
return rmap(conv, item)
end
end


do
function conv (_, data)
if type(data) ~= 'number' then return data end
return tostring(math.floor(data))
else
return data
end

--- Convert numbers to strings recursively.
--
-- Also converts floating point numbers to integers. This is needed
-- because all numbers are floating point numbers in JSON, but some
-- versions of Pandoc expect integers.
--
-- @tab data The data.
-- @return A copy of `data` with numbers converted to strings.
-- @raise An error if the data is nested too deeply.
-- @within Converters
-- function rconv_nums_to_strs (data, _rd)
-- if not _rd then _rd = 0 end
-- assert(_rd < 1024, 'Too much recursion.')
-- local t = type(data)
-- if t == 'table' then
-- local ret = {}
-- for k, v in pairs(data) do
-- ret[k] = rconv_nums_to_strs(v, _rd + 1)
-- end
-- return ret
-- elseif t == 'number' then
-- return tostring(math.floor(data))
-- else
-- return data
-- end
-- end
function rconv_nums_to_strs (data)
return rmap(conv, data)
end
end


do
local function spaces (n)
return string.rep(' ', n)
Expand Down Expand Up @@ -759,7 +917,6 @@ ZOTXT_KEYTYPES = {

do
local read = pandoc.read
local concat = table.concat
local decode = json.decode

local base_url = ZOTXT_BASE_URL
Expand Down Expand Up @@ -843,7 +1000,7 @@ do
--
-- @string str A CSL JSON string.
-- @return Pandoc metadata.
local function conv_json_to_pandoc (str)
local function conv_json_to_meta (str)
assert(str ~= '')
return read(str, 'csljson').meta.references[1]
end
Expand All @@ -863,7 +1020,7 @@ do
-- @within zotxt
function zotxt_get_item (id)
assert(id ~= '', 'ID is the empty string ("").')
local ref, err, errtype = get(conv_json_to_pandoc, id)
local ref, err, errtype = get(conv_json_to_meta, id)
if not ref then return nil, err, errtype end
ref.id = MetaInlines{Str(id)}
return ref
Expand Down Expand Up @@ -897,19 +1054,25 @@ CSL_KEY_ORDER = {
'status', -- Publication status (e.g., 'forthcoming').
'issued', -- When the item was published.
'title', -- The title.
'title-short', -- A short version of the title.
'short-title', -- A short version of the title.
'abstract', -- The abstract.
'original-title', -- Original title.
'translator', -- Translator(s).
'collection-editor', -- Editor(s).
'editor', -- Editor(s).
'container-title', -- Publication the item was published in.
'container-title-short', -- A short version of that title.
'collection-editor', -- E.g., series editor(s).
'collection-title', -- E.g., a series.
'collection-title-short', -- A short version of the title.
'edition', -- Container's edition.
'volume', -- Volume no.
'issue', -- Issue no.
'page-first', -- First page.
'page', -- Pages or page range *or* number of pages.
'publisher', -- Publisher.
'publisher-place', -- The city/cities the item was published in.
'publisher-place', -- City/cities the item was published in.
'original-publisher', -- Original publisher.
'original-publisher-place', -- Place the item was originally published in.
'doi', -- The DOI.
'pmcid', -- PubMed Central reference number.
'pmid', -- PubMed reference number.
Expand All @@ -918,7 +1081,8 @@ CSL_KEY_ORDER = {
'isbn', -- The ISBN of the item.
'issn', -- The ISSN of the container.
'call-number', -- Call number (of a library).
'language' -- Language the item is in.
'language', -- Language the item is in.
'abstract', -- The abstract.
}


Expand Down Expand Up @@ -1136,10 +1300,10 @@ function biblio_update (fname, ids)
if #ids == 0 then return true end
local fmt, err = biblio_write(fname)
if not fmt then return nil, err end
-- @todo Remove this once the test suite is complete,
-- the script has been dogfed, and was out in the open for a while.
if fmt == 'yaml' or fmt == 'yml' then
warnf 'YAML bibliography file support is INCOMPLETE and EXPERIMENTAL!'
warnf 'Markdown is NOT escaped!'
warnf 'Formatting is NOT supported.'
warnf 'YAML bibliography file support is EXPERIMENTAL!'
end
local items, err, errno = biblio_read(fname)
if not items then
Expand All @@ -1156,8 +1320,9 @@ function biblio_update (fname, ids)
if not ok then
return nil, 'Could not retrieve data from Zotero.'
elseif item then
-- @todo Escape Markdown if fmt == 'yaml'.
-- @todo Convert HTML to Markdown if fmt == 'yaml'.
if fmt == 'yaml' or fmt == 'yml' then
item = conv_zotfmt_to_pdfmt(item)
end
n = n + 1
items[n] = lower_keys(item)
else
Expand Down
2 changes: 1 addition & 1 deletion test/norms/test-bibliography-yaml.html
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ <h1 id="test">Test</h1>
———. 2015. <span>“In Defence of Historical Constructivism about Races.”</span> <em>Ergo, an Open Access Journal of Philosophy</em> 2. <a href="https://doi.org/10.3998/ergo.12405314.0002.021">https://doi.org/10.3998/ergo.12405314.0002.021</a>.
</div>
<div id="ref-díaz-león:2016woman" class="csl-entry" role="doc-biblioentry">
———. 2016. <span><i>Woman</i> as a Politically Significant Term: A Solution to the Puzzle.”</span> <em>Hypatia</em>, February, 245–58. <a href="https://doi.org/10.1111/hypa.12234">https://doi.org/10.1111/hypa.12234</a>.
———. 2016. <span><em>Woman</em> as a Politically Significant Term: A Solution to the Puzzle.”</span> <em>Hypatia</em>, February, 245–58. <a href="https://doi.org/10.1111/hypa.12234">https://doi.org/10.1111/hypa.12234</a>.
</div>
<div id="ref-dotson:2016word" class="csl-entry" role="doc-biblioentry">
Dotson, Kristie. 2016. <span>“Word to the Wise: Notes on a Black Feminist Metaphilosophy of Race.”</span> <em>Philosophy Compass</em> 11 (2): 69–74. <a href="https://doi.org/10.1111/phc3.12268">https://doi.org/10.1111/phc3.12268</a>.
Expand Down
Loading

0 comments on commit 1df3d93

Please sign in to comment.