-
Notifications
You must be signed in to change notification settings - Fork 5
Add 'multibib-renumber.lua' filter #18
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
wlupton
wants to merge
2
commits into
pandoc-ext:main
Choose a base branch
from
wlupton:feature/renumber-references
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
--[[ | ||
multibib-renumber – renumber numbered references and their citations | ||
|
||
Copyright © 2024 William Lupton and contributors | ||
|
||
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 pandoc = require 'pandoc' | ||
local List = require 'pandoc.List' | ||
|
||
local stringify = pandoc.utils.stringify | ||
|
||
-- logging | ||
local script_dir = require('pandoc.path').directory(PANDOC_SCRIPT_FILE) | ||
package.path = string.format('%s/?.lua;%s/../?.lua;%s/../scripts/?.lua;%s', | ||
script_dir, script_dir, script_dir, package.path) | ||
local logging = require 'logging' | ||
logging.setlogprefix() | ||
if false then logging.setloglevel(1) end | ||
|
||
-- this filter should run after the multibib filter | ||
-- (the logic is too dependent on the CSL, although it should do no harm) | ||
|
||
-- map from reference id to its new label | ||
local ref_map = List() | ||
|
||
-- ref counter | ||
local ref_counter = 1 | ||
|
||
-- pass 1: process references: | ||
-- * populate ref_map, mapping reference ids to their new labels (numbers) | ||
-- * modify reference labels to be the new numbers | ||
-- | ||
-- this will operate on divs (created by citeproc) like this one (markdown): | ||
-- | ||
-- ::: {#ref-Bel .csl-entry} | ||
-- [\[1\] ]{.csl-left-margin}[Bellori, *Le vite de' pittori, scultori e | ||
-- architetti moderni*, 1672]{.csl-right-inline} | ||
-- ::: | ||
local function collect_refs(div) | ||
if div.attr.classes:includes('csl-entry') then | ||
logging.debug('csl entry', div) | ||
local identifier = div.attr.identifier | ||
local content = div.content | ||
-- expect single Para with a Span (depending on style) possibly containing | ||
-- the citation number (only do anything if it does) | ||
if (#div.content > 0 and #div.content[1].content > 0 and | ||
div.content[1].content[1].tag == 'Span') then | ||
local span = div.content[1].content[1] | ||
local content = span.content | ||
if #content > 0 then | ||
local id = identifier:gsub('^ref%-', '') | ||
local text = content[1].text | ||
local pre, num, post = content[1].text:match("^(%p*)(%d+)(%p*)$") | ||
if pre and num and post then | ||
-- replace num with the current ref counter (1, 2, ...) | ||
local label = string.format('%s%d%s', pre, ref_counter, post) | ||
content[1] = pandoc.Str(label) | ||
ref_map[id] = tostring(ref_counter) | ||
logging.info('collect refs', 'id', id, 'label', text, '->', label) | ||
ref_counter = ref_counter + 1 | ||
return div | ||
end | ||
end | ||
end | ||
end | ||
end | ||
|
||
-- pass 2: process citations: | ||
-- * for each citation, use ref_map to find its new label (number) | ||
-- * update the citation content to use the new label (this is the messy bit, | ||
-- because we have to do string processing, which we do at the Str level so | ||
-- as to retain formatting, links etc.) | ||
-- | ||
-- for example, given '([3, Knu86]; [1, Bae])', map the '3' in '[3,' to '1' | ||
-- and the '[1,' to '3', resulting in '([4, Knu86]; [3, Bae])' | ||
local function renumber_cites(cite) | ||
logging.debug('cite', cite) | ||
local content = cite.content | ||
local changed = false | ||
for _, citation in ipairs(cite.citations) do | ||
local id = citation.id | ||
local label = ref_map[id] | ||
-- only change the content if the label is defined | ||
if label then | ||
local found = false | ||
|
||
-- only substitute the first, because we assume that the citations are | ||
-- referenced in the content in citation order (see below for the other | ||
-- trick) | ||
-- XXX the opening '[' should be configurable | ||
local function substitute_first(str) | ||
if not found then | ||
local pre, num, post = | ||
str.text:match('^(.-%[)(%d+)(%D)') | ||
if pre and num and post then | ||
-- the other trick is that we use '!label!' to avoid the | ||
-- substituted value from being substituted again | ||
local text = pre .. '!' .. label .. '!' .. post | ||
logging.debug('citation id', id, 'label', label, str, '->', text) | ||
str.text = text | ||
found = true | ||
return str | ||
end | ||
end | ||
end | ||
|
||
content = content:walk({Str = substitute_first}) | ||
if found then | ||
changed = true | ||
end | ||
end | ||
end | ||
|
||
if changed then | ||
-- map '!label!' back to 'label' | ||
content = content:walk({Str = function(str) | ||
str.text = str.text:gsub('!(%d+)!', '%1') | ||
return str end}) | ||
logging.info('renumber cites', stringify(cite.content), '->', | ||
stringify(content)) | ||
cite.content = content | ||
return cite | ||
end | ||
end | ||
|
||
return { | ||
{ Div = collect_refs }, | ||
{ Cite = renumber_cites } | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
_extensions/multibib/multibib-renumber.lua |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,19 @@ | ||
Multiple Bibliographies Demo | ||
|
||
|
||
Nietzsche (1872), Bellori (1672) | ||
(see [2, Nie72/section/1]), ([1, Bel]) | ||
|
||
([4, Knu86]; [3, Bae]) | ||
|
||
References | ||
|
||
Bellori. 1672. Le Vite de’ Pittori, Scultori e Architetti Moderni. | ||
[1] Bellori, Le vite de’ pittori, scultori e architetti moderni, 1672 | ||
|
||
Nietzsche, Friedrich. 1872. Die Geburt Der Tragödie Aus Dem Geiste Der | ||
Musik. | ||
[2] Friedrich Nietzsche, Die geburt der tragödie aus dem geiste der | ||
musik, 1872 | ||
|
||
Recommended Reading | ||
|
||
Bätschmann, Oskar. 1985. Pygmalion Als Betrachter. | ||
[3] Oskar Bätschmann, Pygmalion als betrachter, 1985 | ||
|
||
Knuth, Donald E. 1986. The TeXbook. | ||
[4] Donald E. Knuth, The TeXbook, 1986 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,7 +5,9 @@ bibliography: | |
recommended-reading: test/secondary.bib | ||
nocite: '@Knu86, @Bae' | ||
--- | ||
@Nie72, @Bel | ||
[see @Nie72, Section 1], [@Bel] | ||
|
||
[@Knu86; @Bae] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd like to keep at least one citation as "nocite-only". |
||
|
||
# References | ||
|
||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<style xmlns="http://purl.org/net/xbiblio/csl" | ||
class="in-text" version="1.0" | ||
demote-non-dropping-particle="never" | ||
page-range-format="chicago" | ||
default-locale="en-GB"> | ||
<citation> | ||
<layout prefix="(" suffix=")" delimiter="; "> | ||
<group prefix="[" suffix="]" delimiter=", "> | ||
<text variable="citation-number"/> | ||
<group delimiter="/"> | ||
<text variable="id"/> | ||
<text variable="author"/> | ||
<label variable="locator"/> | ||
<text variable="locator"/> | ||
</group> | ||
</group> | ||
</layout> | ||
</citation> | ||
<bibliography> | ||
<sort> | ||
<key variable="id"/> | ||
</sort> | ||
<layout> | ||
<text variable="citation-number" prefix="[" suffix="]" | ||
display="left-margin"/> | ||
<group delimiter=", " display="right-inline"> | ||
<names variable="author"/> | ||
<text variable="title" font-style="italic"/> | ||
<date date-parts="year" form="text" variable="issued"/> | ||
</group> | ||
</layout> | ||
</bibliography> | ||
</style> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,9 @@ | ||
input-files: ['test/input.md'] | ||
to: plain | ||
standalone: true | ||
metadata: | ||
link-citations: true | ||
filters: | ||
- multibib.lua | ||
- multibib-renumber.lua | ||
csl: test/test.csl |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The logging library should probably be a "soft" dependency: