summaryrefslogtreecommitdiff
path: root/biblio
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2024-03-11 03:02:52 +0000
committerNorbert Preining <norbert@preining.info>2024-03-11 03:02:52 +0000
commitd0e99dfc632984d24851f9160409ef583a011f48 (patch)
treec4135f83059d24d568e89d91b17d94d64dc4f371 /biblio
parent0977b5581b838e81912bc5f34fff3672359e236a (diff)
CTAN sync 202403110302
Diffstat (limited to 'biblio')
-rw-r--r--biblio/bibtex/contrib/chicagolinks/LICENSE21
-rw-r--r--biblio/bibtex/contrib/chicagolinks/README3
-rw-r--r--biblio/bibtex/contrib/chicagolinks/chicagolinks.bst1618
-rw-r--r--biblio/citation-style-language/CHANGELOG.md15
-rw-r--r--biblio/citation-style-language/citation-style-language-cite.sty67
-rw-r--r--biblio/citation-style-language/citation-style-language-doc.pdfbin229003 -> 229002 bytes
-rw-r--r--biblio/citation-style-language/citation-style-language-doc.tex2
-rw-r--r--biblio/citation-style-language/citation-style-language.sty2
-rw-r--r--biblio/citation-style-language/citeproc-bibtex-parser.lua84
-rw-r--r--biblio/citation-style-language/citeproc-context.lua3
-rw-r--r--biblio/citation-style-language/citeproc-engine.lua13
-rw-r--r--biblio/citation-style-language/citeproc-latex-core.lua3
-rw-r--r--biblio/citation-style-language/citeproc-lua.12
-rw-r--r--biblio/citation-style-language/citeproc-node-choose.lua34
-rw-r--r--biblio/citation-style-language/citeproc-node-citation.lua13
-rw-r--r--biblio/citation-style-language/citeproc-node-style.lua2
-rw-r--r--biblio/citation-style-language/citeproc-output.lua23
-rw-r--r--biblio/citation-style-language/citeproc-util.lua4
-rw-r--r--biblio/citation-style-language/citeproc.lua2
-rw-r--r--biblio/ctan-bibdata/ctan.bib50
20 files changed, 1889 insertions, 72 deletions
diff --git a/biblio/bibtex/contrib/chicagolinks/LICENSE b/biblio/bibtex/contrib/chicagolinks/LICENSE
new file mode 100644
index 0000000000..a9a469ec01
--- /dev/null
+++ b/biblio/bibtex/contrib/chicagolinks/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2021
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE. \ No newline at end of file
diff --git a/biblio/bibtex/contrib/chicagolinks/README b/biblio/bibtex/contrib/chicagolinks/README
new file mode 100644
index 0000000000..586496fa84
--- /dev/null
+++ b/biblio/bibtex/contrib/chicagolinks/README
@@ -0,0 +1,3 @@
+The is chicagolinks available at GitHub at: mariabnd/miscellaneous/LaTeX/chicagolinks.bst
+
+The purpose of this bibliography style is to extend the "Chicago" bibliography style such that it can be annotated with notes while allowing for DOI and URL fields \ No newline at end of file
diff --git a/biblio/bibtex/contrib/chicagolinks/chicagolinks.bst b/biblio/bibtex/contrib/chicagolinks/chicagolinks.bst
new file mode 100644
index 0000000000..f76d7aad9d
--- /dev/null
+++ b/biblio/bibtex/contrib/chicagolinks/chicagolinks.bst
@@ -0,0 +1,1618 @@
+% GitHub: mariabnd/miscellaneous/LaTeX/chicagolinks.bst
+
+
+%%% ====================================================================
+%%% @BibTeX-style-file{
+%%% version = "2.1",
+%%% date = "27th November 2021",
+%%% filename = "chicagolinks.bst",
+%%% }
+%%% ====================================================================
+%
+% "Chicago" BibTeX style with added url, doi, and annote fields: chicagolinks.bst
+% ===================================
+%
+% V1 2021-05-25
+% This "chicagolinks" style is based on chicago.bst which is in turn based on newapa.bst
+% which is made from plain.bst, named.bst, and apalike.bst. The additional changes
+% included here are inspired by apalikedoiurl.bst by Samuel Pawel (github.com/SamCH93)
+% as well as unsrtnat.bst
+%
+% V2 2021-11-25
+% The additional changes now also include an annote field allowing for the creation of
+% annotated bibliographies. These changes are inspired by Mico (https://tex.stackexchange.com/a/225453)
+%
+% V2.1 2021-11-27
+% Include missing empty.misc.check from plainnat.bst
+%
+% Modification from chicago.bst:
+% ===========================================
+% - Includes field URL for internet address
+% - Includes field DOI for Digital Object Idenfifier
+% - Includes field annote for annotation text
+
+ENTRY
+ { address
+ annote
+ author
+ booktitle
+ chapter
+ doi
+ edition
+ editor
+ howpublished
+ institution
+ journal
+ key
+ month
+ note
+ number
+ organization
+ pages
+ publisher
+ school
+ series
+ title
+ type
+ url
+ volume
+ year
+ }
+ {}
+ { label.year extra.label sort.year sort.label }
+
+INTEGERS { output.state before.all mid.sentence after.sentence after.block }
+
+FUNCTION {init.state.consts}
+{ #0 'before.all :=
+ #1 'mid.sentence :=
+ #2 'after.sentence :=
+ #3 'after.block :=
+}
+
+STRINGS { s t u }
+
+FUNCTION {output.nonnull}
+{ 's :=
+ output.state mid.sentence =
+ { ", " * write$ }
+ { output.state after.block =
+ { add.period$ write$
+ newline$
+ "\newblock " write$
+ }
+ { output.state before.all =
+ 'write$
+ { add.period$ " " * write$ }
+ if$
+ }
+ if$
+ mid.sentence 'output.state :=
+ }
+ if$
+ s
+}
+
+% Use a colon to separate output. Used only for address/publisher
+% combination in book/inbook types, address/institution for manuals,
+% and organization:publisher for proceedings (inproceedings).
+%
+FUNCTION {output.nonnull.colon}
+{ 's :=
+ output.state mid.sentence =
+ { ": " * write$ }
+ { output.state after.block =
+ { add.period$ write$
+ newline$
+ "\newblock " write$
+ }
+ { output.state before.all =
+ 'write$
+ { add.period$ " " * write$ }
+ if$
+ }
+ if$
+ mid.sentence 'output.state :=
+ }
+ if$
+ s
+}
+
+FUNCTION {output}
+{ duplicate$ empty$
+ 'pop$
+ 'output.nonnull
+ if$
+}
+
+FUNCTION {output.colon}
+{ duplicate$ empty$
+ 'pop$
+ 'output.nonnull.colon
+ if$
+}
+
+FUNCTION {output.check}
+{ 't :=
+ duplicate$ empty$
+ { pop$ "empty " t * " in " * cite$ * warning$ }
+ 'output.nonnull
+ if$
+}
+
+FUNCTION {output.check.colon}
+{ 't :=
+ duplicate$ empty$
+ { pop$ "empty " t * " in " * cite$ * warning$ }
+ 'output.nonnull.colon
+ if$
+}
+
+FUNCTION {output.year.check}
+{ year empty$
+ { "empty year in " cite$ * warning$ }
+ { write$
+ " (" year * extra.label *
+ month empty$
+ { ")" * }
+ { ", " * month * ")" * }
+ if$
+ mid.sentence 'output.state :=
+ }
+ if$
+}
+
+FUNCTION {fin.entry}
+{ add.period$
+ write$
+ newline$
+}
+
+FUNCTION {new.block}
+{ output.state before.all =
+ 'skip$
+ { after.block 'output.state := }
+ if$
+}
+
+FUNCTION {new.sentence}
+{ output.state after.block =
+ 'skip$
+ { output.state before.all =
+ 'skip$
+ { after.sentence 'output.state := }
+ if$
+ }
+ if$
+}
+
+FUNCTION {not}
+{ { #0 }
+ { #1 }
+ if$
+}
+
+FUNCTION {and}
+{ 'skip$
+ { pop$ #0 }
+ if$
+}
+
+FUNCTION {or}
+{ { pop$ #1 }
+ 'skip$
+ if$
+}
+
+FUNCTION {new.block.checka}
+{ empty$
+ 'skip$
+ 'new.block
+ if$
+}
+
+FUNCTION {new.block.checkb}
+{ empty$
+ swap$ empty$
+ and
+ 'skip$
+ 'new.block
+ if$
+}
+
+FUNCTION {new.sentence.checka}
+{ empty$
+ 'skip$
+ 'new.sentence
+ if$
+}
+
+FUNCTION {new.sentence.checkb}
+{ empty$
+ swap$ empty$
+ and
+ 'skip$
+ 'new.sentence
+ if$
+}
+
+FUNCTION {field.or.null}
+{ duplicate$ empty$
+ { pop$ "" }
+ 'skip$
+ if$
+}
+
+%
+% Emphasize the top string on the stack.
+%
+FUNCTION {emphasize}
+{ duplicate$ empty$
+ { pop$ "" }
+ { "{\em " swap$ * "}" * }
+ if$
+}
+
+%
+% Emphasize the top string on the stack, but add a trailing space.
+%
+FUNCTION {emphasize.space}
+{ duplicate$ empty$
+ { pop$ "" }
+ { "{\em " swap$ * "\/}" * }
+ if$
+}
+
+INTEGERS { nameptr namesleft numnames }
+%
+% Format bibliographical entries with the first author last name first,
+% and subsequent authors with initials followed by last name.
+% All names are formatted in this routine.
+%
+FUNCTION {format.names}
+{ 's :=
+ #1 'nameptr := % nameptr = 1;
+ s num.names$ 'numnames := % numnames = num.name$(s);
+ numnames 'namesleft :=
+ { namesleft #0 > }
+
+ { nameptr #1 =
+ {s nameptr "{vv~}{ll}{, jj}{, f.}" format.name$ 't := }
+ {s nameptr "{f.~}{vv~}{ll}{, jj}" format.name$ 't := }
+ if$
+ nameptr #1 >
+ { namesleft #1 >
+ { ", " * t * }
+ { numnames #2 >
+ { "," * }
+ 'skip$
+ if$
+ t "others" =
+ { " et~al." * }
+ { " and " * t * } % from Chicago Manual of Style
+ if$
+ }
+ if$
+ }
+ 't
+ if$
+ nameptr #1 + 'nameptr := % nameptr += 1;
+ namesleft #1 - 'namesleft := % namesleft =- 1;
+ }
+ while$
+}
+
+FUNCTION {my.full.label}
+{ 's :=
+ #1 'nameptr := % nameptr = 1;
+ s num.names$ 'numnames := % numnames = num.name$(s);
+ numnames 'namesleft :=
+ { namesleft #0 > }
+
+ { s nameptr "{vv~}{ll}" format.name$ 't := % get the next name
+ nameptr #1 >
+ { namesleft #1 >
+ { ", " * t * }
+ { numnames #2 >
+ { "," * }
+ 'skip$
+ if$
+ t "others" =
+ { " et~al." * }
+ { " and " * t * } % from Chicago Manual of Style
+ if$
+ }
+ if$
+ }
+ 't
+ if$
+ nameptr #1 + 'nameptr := % nameptr += 1;
+ namesleft #1 - 'namesleft := % namesleft =- 1;
+ }
+ while$
+
+}
+
+FUNCTION {format.names.fml}
+%
+% Format names in "familiar" format, with first initial followed by
+% last name. Like format.names, ALL names are formatted.
+%
+{ 's :=
+ #1 'nameptr := % nameptr = 1;
+ s num.names$ 'numnames := % numnames = num.name$(s);
+ numnames 'namesleft :=
+ { namesleft #0 > }
+
+ { s nameptr "{f.~}{vv~}{ll}{, jj}" format.name$ 't :=
+
+ nameptr #1 >
+ { namesleft #1 >
+ { ", " * t * }
+ { numnames #2 >
+ { "," * }
+ 'skip$
+ if$
+ t "others" =
+ { " et~al." * }
+ { " and " * t * }
+% { " \& " * t * }
+ if$
+ }
+ if$
+ }
+ 't
+ if$
+ nameptr #1 + 'nameptr := % nameptr += 1;
+ namesleft #1 - 'namesleft := % namesleft =- 1;
+ }
+ while$
+}
+
+FUNCTION {format.authors}
+{ author empty$
+ { "" }
+ { author format.names }
+ if$
+}
+
+FUNCTION {format.annote}
+{ annote empty$
+ { "" }
+ { " \begin{quotation}\noindent "
+ annote
+ * " \end{quotation} " *
+ }
+ if$
+}
+
+FUNCTION {format.key}
+{ empty$
+ { key field.or.null }
+ { "" }
+ if$
+}
+
+%
+% Format editor names for use in the "in" types: inbook, incollection,
+% inproceedings: first initial, then last names. When editors are the
+% LABEL for an entry, then format.editor is used which lists editors
+% by last name first.
+%
+FUNCTION {format.editors.fml}
+{ editor empty$
+ { "" }
+ { editor format.names.fml
+ editor num.names$ #1 >
+ { " (Eds.)" * }
+ { " (Ed.)" * }
+ if$
+ }
+ if$
+}
+
+%
+% Format editor names for use in labels, last names first.
+%
+FUNCTION {format.editors}
+{ editor empty$
+ { "" }
+ { editor format.names
+ editor num.names$ #1 >
+ { " (Eds.)" * }
+ { " (Ed.)" * }
+ if$
+ }
+ if$
+}
+
+FUNCTION {format.title}
+{ title empty$
+ { "" }
+ { title "t" change.case$ }
+ if$
+}
+
+% Note that the APA style requres case changes
+% in article titles. The following does not
+% change cases. If you perfer it, uncomment the
+% following and comment out the above.
+
+%FUNCTION {format.title}
+%{ title empty$
+% { "" }
+% { title }
+% if$
+%}
+
+% ADDITIONS that make it the links version
+FUNCTION {format.url}
+{ url empty$
+ { "" }
+ { new.block "URL \url{" url * "}" * }
+ if$
+}
+
+FUNCTION {format.doi}
+{ doi empty$
+ { "" }
+ { new.block "\doi{" doi * "}" * }
+ if$
+}
+
+FUNCTION {n.dashify}
+{ 't :=
+ ""
+ { t empty$ not }
+ { t #1 #1 substring$ "-" =
+ { t #1 #2 substring$ "--" = not
+ { "--" *
+ t #2 global.max$ substring$ 't :=
+ }
+ { { t #1 #1 substring$ "-" = }
+ { "-" *
+ t #2 global.max$ substring$ 't :=
+ }
+ while$
+ }
+ if$
+ }
+ { t #1 #1 substring$ *
+ t #2 global.max$ substring$ 't :=
+ }
+ if$
+ }
+ while$
+}
+
+FUNCTION {format.btitle}
+{ edition empty$
+ { title emphasize }
+ { title empty$
+ { title emphasize }
+ { volume empty$ % gnp - check for volume, then don't need period
+ { "{\em " title * "\/} (" * edition * " ed.)" * "." * }
+ { "{\em " title * "\/} (" * edition * " ed.)" * }
+ if$
+ }
+ if$
+ }
+ if$
+}
+
+FUNCTION {format.emphasize.booktitle}
+{ edition empty$
+ { booktitle emphasize }
+ { booktitle empty$
+ { booktitle emphasize }
+ { volume empty$ % gnp - extra period an error if book has a volume
+ { "{\em " booktitle * "\/} (" * edition * " ed.)" * "." *}
+ { "{\em " booktitle * "\/} (" * edition * " ed.)" * }
+ if$
+ }
+ if$
+ }
+ if$
+ }
+
+FUNCTION {tie.or.space.connect}
+{ duplicate$ text.length$ #3 <
+ { "~" }
+ { " " }
+ if$
+ swap$ * *
+}
+
+FUNCTION {either.or.check}
+{ empty$
+ 'pop$
+ { "can't use both " swap$ * " fields in " * cite$ * warning$ }
+ if$
+}
+
+FUNCTION {format.bvolume}
+{ volume empty$
+ { "" }
+ { "Volume" volume tie.or.space.connect % gnp - changed to mixed case
+ series empty$
+ 'skip$
+ { " of " * series emphasize * }
+ if$
+ "volume and number" number either.or.check
+ }
+ if$
+}
+
+FUNCTION {format.number.series}
+{ volume empty$
+ { number empty$
+ { series field.or.null }
+ { output.state mid.sentence =
+ { "Number" } % gnp - changed to mixed case always
+ { "Number" }
+ if$
+ number tie.or.space.connect
+ series empty$
+ { "there's a number but no series in " cite$ * warning$ }
+ { " in " * series * }
+ if$
+ }
+ if$
+ }
+ { "" }
+ if$
+}
+
+INTEGERS { multiresult }
+
+FUNCTION {multi.page.check}
+{ 't :=
+ #0 'multiresult :=
+ { multiresult not
+ t empty$ not
+ and
+ }
+ { t #1 #1 substring$
+ duplicate$ "-" =
+ swap$ duplicate$ "," =
+ swap$ "+" =
+ or or
+ { #1 'multiresult := }
+ { t #2 global.max$ substring$ 't := }
+ if$
+ }
+ while$
+ multiresult
+}
+
+FUNCTION {format.pages}
+{ pages empty$
+ { "" }
+ { pages multi.page.check
+ { "pp.\ " pages n.dashify tie.or.space.connect } % gnp - removed ()
+ { "pp.\ " pages tie.or.space.connect }
+ if$
+ }
+ if$
+}
+
+% By Young (and Spencer)
+% GNP - fixed bugs with missing volume, number, and/or pages
+%
+% Format journal, volume, number, pages for article types.
+%
+FUNCTION {format.jour.vol}
+{ journal empty$
+ { "no journal in " cite$ * warning$
+ "" }
+ { journal emphasize.space }
+ if$
+ number empty$
+ { volume empty$
+ { "no number and no volume in " cite$ * warning$
+ "" * }
+ { "~{\em " * Volume * "}" * }
+ if$
+ }
+ { volume empty$
+ {"no volume for " cite$ * warning$
+ "~(" * number * ")" * }
+ { "~" *
+ volume emphasize.space
+ "(" * number * ")" * * }
+ if$
+ }
+ if$
+ pages empty$
+ {"page numbers missing in " cite$ * warning$
+ "" * } % gnp - place a null string on the stack for output
+ { duplicate$ empty$
+ { pop$ format.pages }
+ { ", " * pages n.dashify * } % gnp - removed pp. for articles
+ if$
+ }
+ if$
+}
+
+FUNCTION {format.chapter.pages}
+{ chapter empty$
+ 'format.pages
+ { type empty$
+ { "Chapter" } % gnp - changed to mixed case
+ { type "t" change.case$ }
+ if$
+ chapter tie.or.space.connect
+ pages empty$
+ {"page numbers missing in " cite$ * warning$} % gnp - added check
+ { ", " * format.pages * }
+ if$
+ }
+ if$
+}
+
+FUNCTION {format.in.ed.booktitle}
+{ booktitle empty$
+ { "" }
+ { editor empty$
+ { "In " format.emphasize.booktitle * }
+ { "In " format.editors.fml * ", " * format.emphasize.booktitle * }
+ if$
+ }
+ if$
+}
+
+FUNCTION {empty.misc.check}
+{ author empty$ title empty$ howpublished empty$
+ month empty$ year empty$ note empty$
+ and and and and and
+ key empty$ not and
+ { "all relevant fields are empty in " cite$ * warning$ }
+ 'skip$
+ if$
+}
+
+FUNCTION {format.thesis.type}
+{ type empty$
+ 'skip$
+ { pop$
+ type "t" change.case$
+ }
+ if$
+}
+
+FUNCTION {format.tr.number}
+{ type empty$
+ { "Technical Report" }
+ 'type
+ if$
+ number empty$
+ { "t" change.case$ }
+ { number tie.or.space.connect }
+ if$
+}
+
+FUNCTION {format.article.crossref}
+{ "See"
+ "\citeN{" * crossref * "}" *
+}
+
+FUNCTION {format.crossref.editor}
+{ editor #1 "{vv~}{ll}" format.name$
+ editor num.names$ duplicate$
+ #2 >
+ { pop$ " et~al." * }
+ { #2 <
+ 'skip$
+ { editor #2 "{ff }{vv }{ll}{ jj}" format.name$ "others" =
+ { " et~al." * }
+ { " and " * editor #2 "{vv~}{ll}" format.name$ * }
+ if$
+ }
+ if$
+ }
+ if$
+}
+
+FUNCTION {format.book.crossref}
+{ volume empty$
+ { "empty volume in " cite$ * "'s crossref of " * crossref * warning$
+ "In "
+ }
+ { "Volume" volume tie.or.space.connect % gnp - changed to mixed case
+ " of " *
+ }
+ if$
+ editor empty$
+ editor field.or.null author field.or.null =
+ or
+ { key empty$
+ { series empty$
+ { "need editor, key, or series for " cite$ * " to crossref " *
+ crossref * warning$
+ "" *
+ }
+ { "{\em " * series * "\/}" * }
+ if$
+ }
+ { key * }
+ if$
+ }
+ { format.crossref.editor * }
+ if$
+ " \citeN{" * crossref * "}" *
+}
+
+FUNCTION {format.incoll.inproc.crossref}
+{ "See"
+ " \citeN{" * crossref * "}" *
+}
+
+% format.lab.names:
+%
+% determines "short" names for the abbreviated author information.
+% "Long" labels are created in calc.label, using the routine my.full.label
+% to format author and editor fields.
+%
+% There are 4 cases for labels. (n=3 in the example)
+% a) one author Foo
+% b) one to n Foo, Bar and Baz
+% c) use of "and others" Foo, Bar et al.
+% d) more than n Foo et al.
+%
+FUNCTION {format.lab.names}
+{ 's :=
+ s num.names$ 'numnames :=
+ numnames #2 > % change number to number of others allowed before
+ % forcing "et al".
+ { s #1 "{vv~}{ll}" format.name$ " et~al." * }
+ {
+ numnames #1 - 'namesleft :=
+ #2 'nameptr :=
+ s #1 "{vv~}{ll}" format.name$
+ { namesleft #0 > }
+ { nameptr numnames =
+ { s nameptr "{ff }{vv }{ll}{ jj}" format.name$ "others" =
+ { " et~al." * }
+ { " and " * s nameptr "{vv~}{ll}" format.name$ * }
+ if$
+ }
+ { ", " * s nameptr "{vv~}{ll}" format.name$ * }
+ if$
+ nameptr #1 + 'nameptr :=
+ namesleft #1 - 'namesleft :=
+ }
+ while$
+ }
+ if$
+}
+
+FUNCTION {author.key.label}
+{ author empty$
+ { key empty$
+ { "no key, author in " cite$ * warning$
+ cite$ #1 #3 substring$ }
+ 'key
+ if$
+ }
+ { author format.lab.names }
+ if$
+}
+
+FUNCTION {editor.key.label}
+{ editor empty$
+ { key empty$
+ { "no key, editor in " cite$ * warning$
+ cite$ #1 #3 substring$ }
+ 'key
+ if$
+ }
+ { editor format.lab.names }
+ if$
+}
+
+FUNCTION {author.key.organization.label}
+%
+% added - gnp. Provide label formatting by organization if author is null.
+%
+{ author empty$
+ { organization empty$
+ { key empty$
+ { "no key, author or organization in " cite$ * warning$
+ cite$ #1 #3 substring$ }
+ 'key
+ if$
+ }
+ { organization }
+ if$
+ }
+ { author format.lab.names }
+ if$
+}
+
+FUNCTION {editor.key.organization.label}
+%
+% added - gnp. Provide label formatting by organization if editor is null.
+%
+{ editor empty$
+ { organization empty$
+ { key empty$
+ { "no key, editor or organization in " cite$ * warning$
+ cite$ #1 #3 substring$ }
+ 'key
+ if$
+ }
+ { organization }
+ if$
+ }
+ { editor format.lab.names }
+ if$
+}
+
+FUNCTION {author.editor.key.label}
+{ author empty$
+ { editor empty$
+ { key empty$
+ { "no key, author, or editor in " cite$ * warning$
+ cite$ #1 #3 substring$ }
+ 'key
+ if$
+ }
+ { editor format.lab.names }
+ if$
+ }
+ { author format.lab.names }
+ if$
+}
+
+FUNCTION {calc.label}
+%
+% Changed - GNP. See also author.organization.sort, editor.organization.sort
+% Form label for BibTeX entry. The classification of which fields are used
+% for which type of entry (book, inbook, etc.) are taken from alpha.bst.
+% The change here from newapa is to also include organization as a
+% citation label if author or editor is missing.
+%
+{ type$ "book" =
+ type$ "inbook" =
+ or
+ 'author.editor.key.label
+ { type$ "proceedings" =
+ 'editor.key.organization.label
+ { type$ "manual" =
+ 'author.key.organization.label
+ 'author.key.label
+ if$
+ }
+ if$
+ }
+ if$
+
+ author empty$ % generate the full label citation information.
+ { editor empty$
+ { organization empty$
+ { "no author, editor, or organization in " cite$ * warning$
+ "??" }
+ { organization }
+ if$
+ }
+ { editor my.full.label }
+ if$
+ }
+ { author my.full.label }
+ if$
+
+% leave label on the stack, to be popped when required.
+
+ "}{" * swap$ * "}{" *
+% year field.or.null purify$ #-1 #4 substring$ *
+%
+% save the year for sort processing afterwards (adding a, b, c, etc.)
+%
+ year field.or.null purify$ #-1 #4 substring$
+ 'label.year :=
+}
+
+FUNCTION {output.bibitem}
+{ newline$
+
+ "\bibitem[\protect\citeauthoryear{" write$
+ calc.label write$
+ sort.year write$
+ "}]{" write$
+
+ cite$ write$
+ "}" write$
+ newline$
+ ""
+ before.all 'output.state :=
+}
+
+FUNCTION {article}
+{ output.bibitem
+ format.authors
+ "author" output.check
+ author format.key output % added
+ output.year.check % added
+ new.block
+ format.title
+ "title" output.check
+ new.block
+ crossref missing$
+ { format.jour.vol output
+ }
+ { format.article.crossref output.nonnull
+ format.pages output
+ }
+ if$
+ format.doi output
+ format.url output
+ new.block
+ note output
+ fin.entry
+ format.annote write$
+ newline$
+}
+
+FUNCTION {book}
+{ output.bibitem
+ author empty$
+ { format.editors
+ "author and editor" output.check }
+ { format.authors
+ output.nonnull
+ crossref missing$
+ { "author and editor" editor either.or.check }
+ 'skip$
+ if$
+ }
+ if$
+ output.year.check % added
+ new.block
+ format.btitle
+ "title" output.check
+ crossref missing$
+ { format.bvolume output
+ new.block
+ format.number.series output
+ new.sentence
+ address output
+ publisher "publisher" output.check.colon
+ }
+ { new.block
+ format.book.crossref output.nonnull
+ }
+ if$
+ format.doi output
+ format.url output
+ new.block
+ note output
+ fin.entry
+ format.annote write$
+ newline$
+}
+
+FUNCTION {booklet}
+{ output.bibitem
+ format.authors output
+ author format.key output % added
+ output.year.check % added
+ new.block
+ format.title
+ "title" output.check
+ new.block
+ howpublished output
+ address output
+ new.block
+ note output
+ fin.entry
+ format.annote write$
+}
+
+FUNCTION {inbook}
+{ output.bibitem
+ author empty$
+ { format.editors
+ "author and editor" output.check
+ }
+ { format.authors output.nonnull
+ crossref missing$
+ { "author and editor" editor either.or.check }
+ 'skip$
+ if$
+ }
+ if$
+ output.year.check % added
+ new.block
+ format.btitle
+ "title" output.check
+ crossref missing$
+ { format.bvolume output
+ format.chapter.pages
+ "chapter and pages" output.check
+ new.block
+ format.number.series output
+ new.sentence
+ address output
+ publisher
+ "publisher" output.check.colon
+ }
+ { format.chapter.pages "chapter and pages" output.check
+ new.block
+ format.book.crossref output.nonnull
+ }
+ if$
+ format.doi output
+ format.url output
+ new.block
+ note output
+ fin.entry
+ format.annote write$
+}
+
+FUNCTION {incollection}
+{ output.bibitem
+ format.authors
+ "author" output.check
+ author format.key output % added
+ output.year.check % added
+ new.block
+ format.title
+ "title" output.check
+ new.block
+ crossref missing$
+ { format.in.ed.booktitle
+ "booktitle" output.check
+ format.bvolume output
+ format.number.series output
+ format.chapter.pages output % gnp - was special.output.nonnull
+% left out comma before page numbers
+ new.sentence
+ address output
+ publisher "publisher" output.check.colon
+ }
+ { format.incoll.inproc.crossref
+ output.nonnull
+ format.chapter.pages output
+ }
+ if$
+ format.doi output
+ format.url output
+ new.block
+ note output
+ fin.entry
+ format.annote write$
+}
+
+FUNCTION {inproceedings}
+{ output.bibitem
+ format.authors
+ "author" output.check
+ author format.key output % added
+ output.year.check % added
+ new.block
+ format.title
+ "title" output.check
+ new.block
+ crossref missing$
+ { format.in.ed.booktitle
+ "booktitle" output.check
+ format.bvolume output
+ format.number.series output
+ address output
+ format.pages output
+ new.sentence
+ organization output
+ publisher output.colon
+ }
+ { format.incoll.inproc.crossref output.nonnull
+ format.pages output
+ }
+ if$
+ format.doi output
+ format.url output
+ new.block
+ note output
+ fin.entry
+ format.annote write$
+}
+
+FUNCTION {conference} { inproceedings }
+
+FUNCTION {manual}
+{ output.bibitem
+ author empty$
+ { editor empty$
+ { organization "organization" output.check
+ organization format.key output } % if all else fails, use key
+ { format.editors "author and editor" output.check }
+ if$
+ }
+ { format.authors output.nonnull }
+ if$
+ output.year.check % added
+ new.block
+ format.btitle
+ "title" output.check
+ organization address new.block.checkb
+% Reversed the order of "address" and "organization", added the ":".
+ address output
+ organization "organization" output.check.colon
+% address output
+% ":" output
+% organization output
+ format.doi output
+ format.url output
+ new.block
+ note output
+ fin.entry
+ format.annote write$
+}
+
+FUNCTION {mastersthesis}
+{ output.bibitem
+ format.authors
+ "author" output.check
+ author format.key output % added
+ output.year.check % added
+ new.block
+ format.title
+ "title" output.check
+ new.block
+ "Master's thesis" format.thesis.type output.nonnull
+ school "school" output.check
+ address output
+ format.doi output
+ format.url output
+ new.block
+ note output
+ fin.entry
+ format.annote write$
+}
+
+FUNCTION {misc}
+{ output.bibitem
+ format.authors output
+ author format.key output % added
+ output.year.check % added
+ title howpublished new.block.checkb
+ format.title output
+ new.block
+ howpublished output
+ format.doi output
+ format.url output
+ new.block
+ note output
+ fin.entry
+ format.annote write$
+ empty.misc.check
+}
+
+FUNCTION {phdthesis}
+{ output.bibitem
+ format.authors
+ "author" output.check
+ author format.key output % added
+ output.year.check % added
+ new.block
+ format.btitle
+ "title" output.check
+ new.block
+ "Ph.\ D. thesis" format.thesis.type output.nonnull
+ school "school" output.check
+ address output
+ format.doi output
+ format.url output
+ new.block
+ note output
+ fin.entry
+ format.annote write$
+}
+
+FUNCTION {proceedings}
+{ output.bibitem
+ editor empty$
+ { organization output
+ organization format.key output } % gnp - changed from author format.key
+ { format.editors output.nonnull }
+ if$
+% author format.key output % gnp - removed (should be either
+% editor or organization
+ output.year.check % added (newapa)
+ new.block
+ format.btitle
+ "title" output.check
+ format.bvolume output
+ format.number.series output
+ address output
+ new.sentence
+ organization output
+ publisher output.colon
+ format.doi output
+ format.url output
+ new.block
+ note output
+ fin.entry
+ format.annote write$
+}
+
+FUNCTION {techreport}
+{ output.bibitem
+ format.authors
+ "author" output.check
+ author format.key output % added
+ output.year.check % added
+ new.block
+ format.title
+ "title" output.check
+ new.block
+ format.tr.number output.nonnull
+ institution
+ "institution" output.check
+ address output
+ format.doi output
+ format.url output
+ new.block
+ note output
+ fin.entry
+ format.annote write$
+}
+
+FUNCTION {unpublished}
+{ output.bibitem
+ format.authors
+ "author" output.check
+ author format.key output % added
+ output.year.check % added
+ new.block
+ format.title
+ "title" output.check
+ format.doi output
+ format.url output
+ new.block
+ note "note" output.check
+ fin.entry
+ format.annote write$
+}
+
+FUNCTION {default.type} { misc }
+
+MACRO {jan} {"January"}
+
+MACRO {feb} {"February"}
+
+MACRO {mar} {"March"}
+
+MACRO {apr} {"April"}
+
+MACRO {may} {"May"}
+
+MACRO {jun} {"June"}
+
+MACRO {jul} {"July"}
+
+MACRO {aug} {"August"}
+
+MACRO {sep} {"September"}
+
+MACRO {oct} {"October"}
+
+MACRO {nov} {"November"}
+
+MACRO {dec} {"December"}
+
+MACRO {acmcs} {"ACM Computing Surveys"}
+
+MACRO {acta} {"Acta Informatica"}
+
+MACRO {ai} {"Artificial Intelligence"}
+
+MACRO {cacm} {"Communications of the ACM"}
+
+MACRO {ibmjrd} {"IBM Journal of Research and Development"}
+
+MACRO {ibmsj} {"IBM Systems Journal"}
+
+MACRO {ieeese} {"IEEE Transactions on Software Engineering"}
+
+MACRO {ieeetc} {"IEEE Transactions on Computers"}
+
+MACRO {ieeetcad}
+ {"IEEE Transactions on Computer-Aided Design of Integrated Circuits"}
+
+MACRO {ipl} {"Information Processing Letters"}
+
+MACRO {jacm} {"Journal of the ACM"}
+
+MACRO {jcss} {"Journal of Computer and System Sciences"}
+
+MACRO {scp} {"Science of Computer Programming"}
+
+MACRO {sicomp} {"SIAM Journal on Computing"}
+
+MACRO {tocs} {"ACM Transactions on Computer Systems"}
+
+MACRO {tods} {"ACM Transactions on Database Systems"}
+
+MACRO {tog} {"ACM Transactions on Graphics"}
+
+MACRO {toms} {"ACM Transactions on Mathematical Software"}
+
+MACRO {toois} {"ACM Transactions on Office Information Systems"}
+
+MACRO {toplas} {"ACM Transactions on Programming Languages and Systems"}
+
+MACRO {tcs} {"Theoretical Computer Science"}
+
+READ
+
+FUNCTION {sortify}
+{ purify$
+ "l" change.case$
+}
+
+INTEGERS { len }
+
+FUNCTION {chop.word}
+{ 's :=
+ 'len :=
+ s #1 len substring$ =
+ { s len #1 + global.max$ substring$ }
+ 's
+ if$
+}
+
+
+
+FUNCTION {sort.format.names}
+{ 's :=
+ #1 'nameptr :=
+ ""
+ s num.names$ 'numnames :=
+ numnames 'namesleft :=
+ { namesleft #0 > }
+ { nameptr #1 >
+ { " " * }
+ 'skip$
+ if$
+ s nameptr "{vv{ } }{ll{ }}{ f{ }}{ jj{ }}" format.name$ 't :=
+ nameptr numnames = t "others" = and
+ { " et~al" * }
+ { t sortify * }
+ if$
+ nameptr #1 + 'nameptr :=
+ namesleft #1 - 'namesleft :=
+ }
+ while$
+}
+
+FUNCTION {sort.format.title}
+{ 't :=
+ "A " #2
+ "An " #3
+ "The " #4 t chop.word
+ chop.word
+ chop.word
+ sortify
+ #1 global.max$ substring$
+}
+
+FUNCTION {author.sort}
+{ author empty$
+ { key empty$
+ { "to sort, need author or key in " cite$ * warning$
+ "" }
+ { key sortify }
+ if$
+ }
+ { author sort.format.names }
+ if$
+}
+
+FUNCTION {editor.sort}
+{ editor empty$
+ { key empty$
+ { "to sort, need editor or key in " cite$ * warning$
+ ""
+ }
+ { key sortify }
+ if$
+ }
+ { editor sort.format.names }
+ if$
+}
+
+FUNCTION {author.editor.sort}
+{ author empty$
+ { "missing author in " cite$ * warning$
+ editor empty$
+ { key empty$
+ { "to sort, need author, editor, or key in " cite$ * warning$
+ ""
+ }
+ { key sortify }
+ if$
+ }
+ { editor sort.format.names }
+ if$
+ }
+ { author sort.format.names }
+ if$
+}
+
+FUNCTION {author.organization.sort}
+%
+% added - GNP. Stack author or organization for sorting (from alpha.bst).
+% Unlike alpha.bst, we need entire names, not abbreviations
+%
+{ author empty$
+ { organization empty$
+ { key empty$
+ { "to sort, need author, organization, or key in " cite$ * warning$
+ ""
+ }
+ { key sortify }
+ if$
+ }
+ { organization sortify }
+ if$
+ }
+ { author sort.format.names }
+ if$
+}
+
+FUNCTION {editor.organization.sort}
+%
+% added - GNP. Stack editor or organization for sorting (from alpha.bst).
+% Unlike alpha.bst, we need entire names, not abbreviations
+%
+{ editor empty$
+ { organization empty$
+ { key empty$
+ { "to sort, need editor, organization, or key in " cite$ * warning$
+ ""
+ }
+ { key sortify }
+ if$
+ }
+ { organization sortify }
+ if$
+ }
+ { editor sort.format.names }
+ if$
+}
+
+FUNCTION {presort}
+%
+% Presort creates the bibentry's label via a call to calc.label, and then
+% sorts the entries based on entry type. Chicago.bst adds support for
+% including organizations as the sort key; the following is stolen from
+% alpha.bst.
+%
+{ calc.label sortify % recalculate bibitem label
+ year field.or.null purify$ #-1 #4 substring$ * % add year
+ " "
+ *
+ type$ "book" =
+ type$ "inbook" =
+ or
+ 'author.editor.sort
+ { type$ "proceedings" =
+ 'editor.organization.sort
+ { type$ "manual" =
+ 'author.organization.sort
+ 'author.sort
+ if$
+ }
+ if$
+ }
+ if$
+ #1 entry.max$ substring$ % added for newapa
+ 'sort.label := % added for newapa
+ sort.label % added for newapa
+ *
+ " "
+ *
+ title field.or.null
+ sort.format.title
+ *
+ #1 entry.max$ substring$
+ 'sort.key$ :=
+}
+
+ITERATE {presort}
+
+SORT % by label, year, author/editor, title
+
+STRINGS { last.label next.extra }
+
+INTEGERS { last.extra.num }
+
+FUNCTION {initialize.extra.label.stuff}
+{ #0 int.to.chr$ 'last.label :=
+ "" 'next.extra :=
+ #0 'last.extra.num :=
+}
+
+FUNCTION {forward.pass}
+%
+% Pass through all entries, comparing current entry to last one.
+% Need to concatenate year to the stack (done by calc.label) to determine
+% if two entries are the same (see presort)
+%
+{ last.label
+ calc.label year field.or.null purify$ #-1 #4 substring$ * % add year
+ #1 entry.max$ substring$ = % are they equal?
+ { last.extra.num #1 + 'last.extra.num :=
+ last.extra.num int.to.chr$ 'extra.label :=
+ }
+ { "a" chr.to.int$ 'last.extra.num :=
+ "" 'extra.label :=
+ calc.label year field.or.null purify$ #-1 #4 substring$ * % add year
+ #1 entry.max$ substring$ 'last.label := % assign to last.label
+ }
+ if$
+}
+
+FUNCTION {reverse.pass}
+{ next.extra "b" =
+ { "a" 'extra.label := }
+ 'skip$
+ if$
+ label.year extra.label * 'sort.year :=
+ extra.label 'next.extra :=
+}
+
+EXECUTE {initialize.extra.label.stuff}
+
+ITERATE {forward.pass}
+
+REVERSE {reverse.pass}
+
+FUNCTION {bib.sort.order}
+{ sort.label
+ " "
+ *
+ year field.or.null sortify
+ *
+ " "
+ *
+ title field.or.null
+ sort.format.title
+ *
+ #1 entry.max$ substring$
+ 'sort.key$ :=
+}
+
+ITERATE {bib.sort.order}
+
+SORT % by sort.label, year, title --- giving final bib. order.
+
+FUNCTION {begin.bib}
+
+{ preamble$ empty$
+ 'skip$
+ { preamble$ write$ newline$ }
+ if$
+ "\begin{thebibliography}{}" write$ newline$
+ "\providecommand{\url}[1]{\texttt{#1}}"
+ write$ newline$
+ "\expandafter\ifx\csname urlstyle\endcsname\relax"
+ write$ newline$
+ " \providecommand{\doi}[1]{doi: #1}\else"
+ write$ newline$
+ " \providecommand{\doi}{doi: \begingroup \urlstyle{rm}\Url}\fi"
+ write$ newline$
+}
+
+EXECUTE {begin.bib}
+
+EXECUTE {init.state.consts}
+
+ITERATE {call.type$}
+
+FUNCTION {end.bib}
+{ newline$
+ "\end{thebibliography}" write$ newline$
+}
+
+EXECUTE {end.bib} \ No newline at end of file
diff --git a/biblio/citation-style-language/CHANGELOG.md b/biblio/citation-style-language/CHANGELOG.md
index 47802475f8..c79e3805f0 100644
--- a/biblio/citation-style-language/CHANGELOG.md
+++ b/biblio/citation-style-language/CHANGELOG.md
@@ -7,6 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
+## [0.4.7] - 2024-03-10
+
+### Added
+
+- Add support of biblatex's extended name format ([#48](https://github.com/zepinglee/citeproc-lua/issues/48)).
+
+- Add `\citeyearpar` and `\parencite*` commands ([#52](https://github.com/zepinglee/citeproc-lua/issues/52)).
+
+### Fixed
+
+- Fix an error in parsing TeX math contents ([#49](https://github.com/zepinglee/citeproc-lua/issues/49)).
+
## [0.4.6] - 2024-02-20
### Fixed
@@ -160,7 +172,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Initial CTAN release.
-[Unreleased]: https://github.com/zepinglee/citeproc-lua/compare/v0.4.6...HEAD
+[Unreleased]: https://github.com/zepinglee/citeproc-lua/compare/v0.4.7...HEAD
+[0.4.7]: https://github.com/zepinglee/citeproc-lua/compare/v0.4.6...v0.4.7
[0.4.6]: https://github.com/zepinglee/citeproc-lua/compare/v0.4.5...v0.4.6
[0.4.5]: https://github.com/zepinglee/citeproc-lua/compare/v0.4.4...v0.4.5
[0.4.4]: https://github.com/zepinglee/citeproc-lua/compare/v0.4.3...v0.4.4
diff --git a/biblio/citation-style-language/citation-style-language-cite.sty b/biblio/citation-style-language/citation-style-language-cite.sty
index 1482a34383..6ebb300536 100644
--- a/biblio/citation-style-language/citation-style-language-cite.sty
+++ b/biblio/citation-style-language/citation-style-language-cite.sty
@@ -6,14 +6,14 @@
% ## Citation commands
-\DeclareDocumentCommand \cite { o o m }
- { \__csl_cite:nnn {#1} {#2} {#3} }
+\DeclareDocumentCommand \cite { s o o m }
+ { \__csl_cite:nnnn {#1} {#2} {#3} {#4} }
-\NewDocumentCommand \parencite { o o m }
- { \__csl_cite:nnn {#1} {#2} {#3} }
+\NewDocumentCommand \parencite { s o o m }
+ { \__csl_cite:nnnn {#1} {#2} {#3} {#4} }
\NewDocumentCommand \citep { o o m }
- { \__csl_cite:nnn {#1} {#2} {#3} }
+ { \__csl_cite:nnnn { \BooleanFalse } {#1} {#2} {#3} }
\NewDocumentCommand \textcite { o o m }
{ \__csl_text_cite:nnn {#1} {#2} {#3} }
@@ -22,7 +22,7 @@
{ \__csl_text_cite:nnn {#1} {#2} {#3} }
\NewDocumentCommand \footcite { o o m }
- { \__csl_cite:nnn {#1} {#2} {#3} }
+ { \__csl_cite:nnnn { \BooleanFalse } {#1} {#2} {#3} }
% \cites[⟨prenote⟩][⟨postnote⟩]{⟨key⟩}...[⟨prenote⟩][⟨postnote⟩]{⟨key⟩}
@@ -32,27 +32,56 @@
\NewDocumentCommand \citeauthor { o o m }
{ \__csl_cite_author:nnn {#1} {#2} {#3} }
+% TODO: \citeyear
+
+% ATM the starred form is the same as non-star form.
+\NewDocumentCommand \citeyearpar { s o o m }
+ {
+ \IfBooleanT {#1}
+ {
+ \bool_if:NTF \l__csl_note_bool
+ { \msg_error:nn { citation-style-language } { starred-cite-in-note-style } }
+ }
+ \__csl_cite_suppress_author:nnn {#2} {#3} {#4}
+ }
+
\seq_new:N \l__csl_cite_keys_seq
\seq_new:N \l__csl_citation_items_seq
\prop_new:N \l__csl_citation_properties_prop
\prop_new:N \l__csl_citation_info_prop
-% \__csl_cite:nnn #1#2#3
-\cs_new:Npn \__csl_cite:nnn #1#2#3
+% \__csl_cite:nnnn #1#2#3#
+% #1: boolean of star form
+% #2: prenote
+% #3: postnote
+% #4: cite keys
+\cs_new:Npn \__csl_cite:nnnn #1#2#3#4
{
- \tl_if_blank:nTF {#3}
- { \__csl_print_undefined_citation:n {#3} }
+ \tl_if_blank:nTF {#4}
+ { \__csl_print_undefined_citation:n {#4} }
{
\seq_clear:N \l__csl_cite_keys_seq
\seq_clear:N \l__csl_citation_items_seq
\prop_clear:N \l__csl_citation_properties_prop
- \__csl_process_cite_input:nnn {#1} {#2} {#3}
+ \__csl_process_cite_input:nnn {#2} {#3} {#4}
\__csl_process_citation_info:NN \l__csl_cite_keys_seq \l__csl_citation_items_seq
+ \IfBooleanT {#1}
+ {
+ \bool_if:NTF \l__csl_note_bool
+ { \msg_warning:nn { citation-style-language } { starred-cite-in-note-style } }
+ {
+ \prop_put:Nnn \l__csl_citation_properties_prop { noteIndex } { 0 }
+ \prop_put:Nnn \l__csl_citation_properties_prop { mode } { suppress-author }
+ }
+ }
\__csl_make_citation:N \l__csl_citation_info_prop
}
}
+\msg_new:nnn { citation-style-language } { starred-cite-in-note-style }
+ { Starred~ variant~ of~ cite~ command~ does~ not~ work~ with~ note~ styles. }
+
\cs_new:Npn \__csl_text_cite:nnn #1#2#3
{
@@ -62,7 +91,7 @@
\bool_set_false:N \l__csl_note_bool
\__csl_cite_author:nnn {#1} {#2} {#3}
\bool_set_true:N \l__csl_note_bool
- \__csl_cite:nnn {#1} {#2} {#3}
+ \__csl_cite:nnnn { \BooleanFalse } {#1} {#2} {#3}
}
{
\seq_clear:N \l__csl_cite_keys_seq
@@ -113,6 +142,20 @@
}
+\cs_new:Npn \__csl_cite_suppress_author:nnn #1#2#3
+ {
+ \seq_clear:N \l__csl_cite_keys_seq
+ \seq_clear:N \l__csl_citation_items_seq
+ \prop_clear:N \l__csl_citation_properties_prop
+ \__csl_process_cite_input:nnn {#1} {#2} {#3}
+ \__csl_process_citation_info:NN \l__csl_cite_keys_seq \l__csl_citation_items_seq
+ \prop_put:Nnn \l__csl_citation_properties_prop { noteIndex } { 0 }
+ \prop_put:Nnn \l__csl_citation_properties_prop { mode } { suppress-author }
+ \bool_set_false:N \l__csl_note_bool
+ \__csl_make_citation:N \l__csl_citation_info_prop
+ }
+
+
% Appends the cite key into \l__csl_cite_keys_seq and cite-items into
% \l__csl_citation_items_seq
% #1, #2: prenote/postnote
diff --git a/biblio/citation-style-language/citation-style-language-doc.pdf b/biblio/citation-style-language/citation-style-language-doc.pdf
index 06e7930fa6..560691af59 100644
--- a/biblio/citation-style-language/citation-style-language-doc.pdf
+++ b/biblio/citation-style-language/citation-style-language-doc.pdf
Binary files differ
diff --git a/biblio/citation-style-language/citation-style-language-doc.tex b/biblio/citation-style-language/citation-style-language-doc.tex
index 5710e7e38c..e68d49e56e 100644
--- a/biblio/citation-style-language/citation-style-language-doc.tex
+++ b/biblio/citation-style-language/citation-style-language-doc.tex
@@ -49,7 +49,7 @@
}%
}
-\date{2024-02-20 v0.4.6}
+\date{2024-03-10 v0.4.7}
\maketitle
diff --git a/biblio/citation-style-language/citation-style-language.sty b/biblio/citation-style-language/citation-style-language.sty
index 603312dcf8..4dd3456b78 100644
--- a/biblio/citation-style-language/citation-style-language.sty
+++ b/biblio/citation-style-language/citation-style-language.sty
@@ -9,7 +9,7 @@
\RequirePackage{expl3}
\RequirePackage{xparse}
-\ProvidesExplPackage {citation-style-language} {2024-02-20} {0.4.6}
+\ProvidesExplPackage {citation-style-language} {2024-03-10} {0.4.7}
{Citation Style Language for LaTeX}
\RequirePackage { l3keys2e }
diff --git a/biblio/citation-style-language/citeproc-bibtex-parser.lua b/biblio/citation-style-language/citeproc-bibtex-parser.lua
index 36238791cc..39f4826ca1 100644
--- a/biblio/citation-style-language/citeproc-bibtex-parser.lua
+++ b/biblio/citation-style-language/citeproc-bibtex-parser.lua
@@ -183,7 +183,7 @@ function BibtexParser:parse(bib_str, strings)
strings = setmetatable({}, {__index = self.strings})
end
if type(bib_str) ~= "string" then
- util.error("Invalid string.")
+ util.error("Invalid string")
end
local bib_objects = self.grammar:match(bib_str)
if not bib_objects then
@@ -292,7 +292,7 @@ local function ignore_case(str)
end
----@alias NameDict table
+---@alias NameDict table<string, string>
---@alias NameStr string
---Split BibTeX names
@@ -320,8 +320,16 @@ function bibtex_parser.split_name_parts(str)
local comma_parts = Ct(C(comma_part) * (comma * white_space * C(comma_part))^0)
local parts = comma_parts:match(str)
+ local is_biblatex_extended_format = false
+ if #parts > 0 and (string.match(parts[1], "^[a-zA-Z]+%-?i?%s*=")
+ or string.match(parts[1], '^"[a-zA-Z]+%-?i?%s*=.*"$')) then
+ is_biblatex_extended_format = true
+ end
+
local name = {}
- if #parts == 1 then
+ if is_biblatex_extended_format then
+ name = bibtex_parser._split_extended_name_format(parts)
+ elseif #parts == 1 then
name = bibtex_parser._split_first_von_last_parts(parts[1])
elseif #parts == 2 then
name = bibtex_parser._split_von_last_parts(parts[1])
@@ -329,18 +337,10 @@ function bibtex_parser.split_name_parts(str)
name.first = parts[2]
end
elseif #parts == 3 then
- name = bibtex_parser._split_von_last_parts(parts[1])
- if parts[2] ~= "" then
- name.jr = parts[2]
- end
- if parts[3] ~= "" then
- name.first = parts[3]
- end
+ name = bibtex_parser._split_last_jr_first_parts(parts)
elseif #parts > 3 then
- util.warning()
- name = bibtex_parser._split_last_jr_fist_parts(util.slice(parts, 1, 3))
- else
- util.warning()
+ util.error(string.format('Too many commas in name "%s"', str))
+ name = bibtex_parser._split_last_jr_first_parts(util.slice(parts, 1, 3))
end
return name
@@ -396,6 +396,49 @@ local function join_words_and_seps(words, seps, start, stop)
return res
end
+
+---@param parts string[]
+---@return table<string, string>
+function bibtex_parser._split_extended_name_format(parts)
+ local name = {}
+ for _, part in ipairs(parts) do
+ local key, value = string.match(part, "^([a-zA-Z]+%-?i?)%s*=%s*(.-)%s*$")
+ if not key then
+ key, value = string.match(part, '^"([a-zA-Z]+%-?i?)%s*=%s*(.-)%s*"%s*$')
+ end
+ if not key then
+ util.error(string.format('Invalid extended name part "%s"', part))
+ end
+
+ if key == "given" then
+ key = "first"
+ elseif key == "given-i" then
+ key = "first-i"
+ elseif key == "prefix" then
+ key = "von"
+ elseif key == "prefix-i" then
+ key = "von-i"
+ elseif key == "family" then
+ key = "last"
+ elseif key == "family-i" then
+ key = "last-i"
+ elseif key == "suffix" then
+ key = "jr"
+ elseif key == "suffix-i" then
+ key = "jr-i"
+ end
+
+ local braced_pattern = P"{" * C(balanced^0) * P"}" * P(-1)
+ local stripped = braced_pattern:match(value)
+ if stripped then
+ value = stripped
+ end
+
+ name[key] = value
+ end
+ return name
+end
+
function bibtex_parser._split_first_von_last_parts(str)
local word_sep = P"-" + P"~" + P(util.unicode['no-break space'])
local word_tokens = Ct(C(utf8_balanced - space_char - word_sep)^0)
@@ -490,6 +533,19 @@ function bibtex_parser._split_von_last_parts(str)
return name
end
+---@param parts string[]
+---@return NameDict
+function bibtex_parser._split_last_jr_first_parts(parts)
+ local name = bibtex_parser._split_von_last_parts(parts[1])
+ if parts[2] ~= "" then
+ name.jr = parts[2]
+ end
+ if parts[3] ~= "" then
+ name.first = parts[3]
+ end
+ return name
+end
+
--- Note that BibTeX find crossref in a case-insensitive manner (see
--- `article-crossref` in `xampl.bib`) which is unlike biber/biblatex.
diff --git a/biblio/citation-style-language/citeproc-context.lua b/biblio/citation-style-language/citeproc-context.lua
index 58efc0f37b..ba7bf9fe14 100644
--- a/biblio/citation-style-language/citeproc-context.lua
+++ b/biblio/citation-style-language/citeproc-context.lua
@@ -318,7 +318,10 @@ function Context:get_localized_quotes()
)
end
+---@param page string|number
+---@return string
function Context.page_first(page)
+ page = tostring(page)
local page_first = util.split(page, "%s*[&,-]%s*")[1]
return util.split(page_first, util.unicode["en dash"])[1]
end
diff --git a/biblio/citation-style-language/citeproc-engine.lua b/biblio/citation-style-language/citeproc-engine.lua
index 0f65f66b87..485d3f5835 100644
--- a/biblio/citation-style-language/citeproc-engine.lua
+++ b/biblio/citation-style-language/citeproc-engine.lua
@@ -52,7 +52,9 @@ local Position = util.Position
---@alias ItemId string | number
---@alias NoteIndex integer
---@alias CitationId string
----@alias CitationData {citationID: CitationId, citationItems: table[], properties: table, citation_index: integer}
+---@alias CitationData {citationID: CitationId, citationItems: CitationItem[], properties: CitationProperties, citation_index: integer}
+
+---@alias CitationProperties { noteIndex: integer, mode: string? }
---@class NameVariable
---@field family string?
@@ -95,7 +97,7 @@ local Registry = {}
---@field locales Locale[]
---@field system_locales Locale[]
---@field lang string
----@field output_format any
+---@field output_format OutputFormat
---@field opt table
---@field registry Registry
---@field cite_first_note_numbers table<ItemId, NoteIndex>
@@ -197,6 +199,7 @@ function CiteProc:check_valid_citation_element()
end
end
+---@param ids CiteId[]
function CiteProc:updateItems(ids)
-- util.debug(string.format('updateItems(%s)', table.concat(ids, ", ")))
self.registry.reflist = {}
@@ -282,8 +285,12 @@ function CiteProc:updateUncitedItems(uncited_ids)
end
+---@param citation CitationData
+---@param citationsPre (CitationId | NoteIndex)[]
+---@param citationsPost (CitationId | NoteIndex)[]
+---@return (table | (integer | string | CitationId)[])[]
function CiteProc:processCitationCluster(citation, citationsPre, citationsPost)
- -- util.debug(citation.citationID)
+ -- util.debug(string.format('processCitationCluster(%s)', citation.citationID))
self:check_valid_citation_element()
citation = self:normalize_citation_input(citation)
diff --git a/biblio/citation-style-language/citeproc-latex-core.lua b/biblio/citation-style-language/citeproc-latex-core.lua
index 367646c513..e8f7fcd651 100644
--- a/biblio/citation-style-language/citeproc-latex-core.lua
+++ b/biblio/citation-style-language/citeproc-latex-core.lua
@@ -318,6 +318,9 @@ function core.make_citation(citation_info)
end
+---@param engine CiteProc
+---@param citations CitationData[]
+---@return table<CitationId, string>
function core.process_citations(engine, citations)
local citations_pre = {}
diff --git a/biblio/citation-style-language/citeproc-lua.1 b/biblio/citation-style-language/citeproc-lua.1
index ce1743c695..da8e441f74 100644
--- a/biblio/citation-style-language/citeproc-lua.1
+++ b/biblio/citation-style-language/citeproc-lua.1
@@ -1,4 +1,4 @@
-.TH citeproc-lua 1 "0.4.6"
+.TH citeproc-lua 1 "0.4.7"
.SH NAME
citeproc-lua \- make CSL citations and bibliography for LaTeX
.SH SYNOPSIS
diff --git a/biblio/citation-style-language/citeproc-node-choose.lua b/biblio/citation-style-language/citeproc-node-choose.lua
index c8e4e14cc8..b3c827dc62 100644
--- a/biblio/citation-style-language/citeproc-node-choose.lua
+++ b/biblio/citation-style-language/citeproc-node-choose.lua
@@ -250,13 +250,37 @@ function If:evaluate_condition(condition, state, context)
return context.disambiguate or (context.in_bibliography and context.reference.disambiguate)
elseif condition.condition == "is-numeric" then
- local variable = context:get_variable(condition.value)
- return util.is_numeric(variable)
+ local variable = condition.value
+ local variable_type = util.variable_types[variable] or "standard"
+
+ if variable_type ~= "standard" and variable_type ~= "number" then
+ util.warning(string.format('Expecting number variable for condition "is-numeric", got %s "%s"', variable_type, variable))
+ return false
+ end
+
+ local value = context:get_variable(variable)
+ if not value then
+ return false
+ end
+ if type(value) ~= "string" and type(value) ~= "number" then
+ util.error(string.format('Expecting a string or number for variable "%s", got "%s"', variable, type(value)))
+ end
+ return util.is_numeric(value)
elseif condition.condition == "is-uncertain-date" then
- local variable = context:get_variable(condition.value)
- -- TODO
- return self:is_uncertain_date(variable)
+ local variable = condition.value
+
+ local variable_type = util.variable_types[variable] or "standard"
+
+ if variable_type ~= "date" then
+ util.warning(string.format('Expecting date variable for condition "is-uncertain-date", got "%s"', variable_type, variable))
+ return false
+ end
+ local value = context:get_variable(variable)
+ if not value then
+ return false
+ end
+ return self:is_uncertain_date(value)
elseif condition.condition == "locator" then
local locator_label = context:get_variable("label")
diff --git a/biblio/citation-style-language/citeproc-node-citation.lua b/biblio/citation-style-language/citeproc-node-citation.lua
index d16cd7b945..45e1335b30 100644
--- a/biblio/citation-style-language/citeproc-node-citation.lua
+++ b/biblio/citation-style-language/citeproc-node-citation.lua
@@ -150,6 +150,9 @@ function Citation:from_node(node, style)
return o
end
+---@param citation CitationData
+---@param engine CiteProc
+---@return string
function Citation:build_citation_str(citation, engine)
if engine.registry.requires_sorting then
engine:sort_bibliography()
@@ -172,8 +175,10 @@ local function remove_name_formatting(ir)
end
end
+---@alias CiteId string | number
+
---@class CitationItem
----@field id string | number
+---@field id CiteId
---@field prefix string?
---@field suffix string?
---@field locator string?
@@ -417,12 +422,8 @@ end
---@param properties table
---@return CiteIr
function Citation:build_fully_disambiguated_ir(cite_item, output_format, engine, properties)
+ -- util.debug(cite_item.id)
local cite_ir = self:build_ambiguous_ir(cite_item, output_format, engine)
- -- util.debug(cite_ir)
- -- if cite_item.id == "ITEM-3" then
- -- util.debug(cite_item.id)
- -- util.debug(cite_ir)
- -- end
cite_ir = self:apply_disambiguate_add_givenname(cite_ir, engine)
cite_ir = self:apply_disambiguate_add_names(cite_ir, engine)
cite_ir = self:apply_disambiguate_conditionals(cite_ir, engine)
diff --git a/biblio/citation-style-language/citeproc-node-style.lua b/biblio/citation-style-language/citeproc-node-style.lua
index 0914289a20..5cc3df5579 100644
--- a/biblio/citation-style-language/citeproc-node-style.lua
+++ b/biblio/citation-style-language/citeproc-node-style.lua
@@ -80,7 +80,7 @@ function Style:parse(xml_str)
return nil
end
local style_node = csl_xml:get_path("style")[1]
- if not csl_xml then
+ if not style_node then
error('Element "style" not found.')
end
return Style:from_node(style_node)
diff --git a/biblio/citation-style-language/citeproc-output.lua b/biblio/citation-style-language/citeproc-output.lua
index 0c056fa748..2b3661c9b1 100644
--- a/biblio/citation-style-language/citeproc-output.lua
+++ b/biblio/citation-style-language/citeproc-output.lua
@@ -415,7 +415,7 @@ local function get_inline_element_grammar()
local spaces = P(" ")^1
local grammar = P{
"content";
- token = V"italic" + V"bold" + V"sup" + V"sub" + V"sc" + V"small_caps" + V"span_nocase" + V"nodecor" + V"mathtex" + V"mathml" + V"code" + V"script" + C(1),
+ token = V"italic" + V"bold" + V"sup" + V"sub" + V"sc" + V"small_caps" + V"span_nocase" + V"nodecor" + V"math_tex" + V"math_ml" + V"code" + V"script" + C(1),
content = Ct((V"token")^0) / tokens2inlines,
italic = P"<i>" * Ct((V"token" - P"</i>")^0) * P"</i>" / function (tokens)
return Formatted:new(tokens2inlines(tokens), {["font-style"] = "italic"})
@@ -453,10 +453,10 @@ local function get_inline_element_grammar()
nodecor = P"<span" * spaces * P'class="nodecor">' * Ct((V"token" - P"</span>")^0) * P"</span>" / function (tokens)
return NoDecor:new(tokens2inlines(tokens))
end,
- mathtex = P"<mathtex>" * Ct((1- P"</mathtex>")^0) * P"</mathtex>" / function (text)
- return MathML:new(text)
+ math_tex = P"<math-tex>" * C((1- P"</math-tex>")^0) * P"</math-tex>" / function (text)
+ return MathTeX:new(text)
end,
- mathml = P"<math>" * C((1- P"</math>")^0) * P"</math>" / function (text)
+ math_ml = P"<math>" * C((1- P"</math>")^0) * P"</math>" / function (text)
return MathML:new(text)
end,
code = P"<code>" * C((1 - P"</code>")^0) * P"</code>" / function (text)
@@ -1639,7 +1639,7 @@ function Markup:write_inline(inline, context)
return self:write_code(inline, context)
elseif inline._type == "MathML" then
- return self:write_mathml(inline, context)
+ return self:write_math_ml(inline, context)
elseif inline._type == "MathTeX" then
return self:write_math_tex(inline, context)
@@ -1690,7 +1690,7 @@ function Markup:write_code(inline, context)
return inline.value
end
-function Markup:write_mathml(inline, context)
+function Markup:write_math_ml(inline, context)
return inline.value
end
@@ -1806,7 +1806,8 @@ function LatexWriter:write_display(inline, context)
return res
elseif inline.div == "block" then
- return ""
+ util.warning("display=\"block\" is not supported in LaTeX output.")
+ return res
end
return res
end
@@ -1834,7 +1835,7 @@ function LatexWriter:write_code(inline, context)
return inline.value
end
-function LatexWriter:write_mathml(inline, context)
+function LatexWriter:write_math_ml(inline, context)
util.error("MathML is not supported in LaTeX output.")
return ""
end
@@ -1941,7 +1942,7 @@ function HtmlWriter:write_code(inline, context)
return string.format("<code>%s</code>", inline.value)
end
-function HtmlWriter:write_mathml(inline, context)
+function HtmlWriter:write_math_ml(inline, context)
return string.format('<math xmlns="http://www.w3.org/1998/Math/MathML">%s</math>', inline.value)
end
@@ -2057,12 +2058,12 @@ function PseudoHtml :write_escaped(str, context)
return str
end
-function PseudoHtml:write_mathml(inline, context)
+function PseudoHtml:write_math_ml(inline, context)
return string.format('<math>%s</math>', inline.value)
end
function PseudoHtml:write_math_tex(inline, context)
- return string.format("<mathtex>%s</mathtex>", inline.value)
+ return string.format("<math-tex>%s</math-tex>", inline.value)
end
function PseudoHtml:write_nocase(inline, context)
diff --git a/biblio/citation-style-language/citeproc-util.lua b/biblio/citation-style-language/citeproc-util.lua
index 302e5b72c5..97ac6d010e 100644
--- a/biblio/citation-style-language/citeproc-util.lua
+++ b/biblio/citation-style-language/citeproc-util.lua
@@ -233,7 +233,7 @@ end
---@return string[]
function util.split(str, sep, maxsplit)
if type(str) ~= "string" then
- util.error("Invalid string.")
+ util.error("Invalid string")
end
sep = sep or "%s+"
if sep == "" then
@@ -398,6 +398,8 @@ function util.endswith(str, suffix)
return string.sub(str, -#suffix) == suffix
end
+---@param str string | number
+---@return boolean
function util.is_numeric(str)
if str == nil or str == "" then
return false
diff --git a/biblio/citation-style-language/citeproc.lua b/biblio/citation-style-language/citeproc.lua
index 90b0273219..0c673c67e3 100644
--- a/biblio/citation-style-language/citeproc.lua
+++ b/biblio/citation-style-language/citeproc.lua
@@ -16,7 +16,7 @@ else
util = require("citeproc.util")
end
-citeproc.__VERSION__ = "0.4.6"
+citeproc.__VERSION__ = "0.4.7"
citeproc.new = engine.CiteProc.new
citeproc.util = util
diff --git a/biblio/ctan-bibdata/ctan.bib b/biblio/ctan-bibdata/ctan.bib
index fbc5a84d5f..5252cf0db6 100644
--- a/biblio/ctan-bibdata/ctan.bib
+++ b/biblio/ctan-bibdata/ctan.bib
@@ -1,7 +1,7 @@
%% bib file of all CTAN packages
%% (C) Herbert Voß
%%
-%% created at 09-03-2024, 02:00:03
+%% created at 10-03-2024, 02:00:04
%%
%% This file is provided under the terms of the LPPL v1.3 or
@@ -11995,7 +11995,7 @@
title = {The \texttt{chemformula-ru} package},
subtitle = {Using the chemformula package with babel-russian settings},
author = {Alexey Kuznetsov},
- date = {2024-03-03},
+ date = {2024-03-09},
version = {},
license = {lppl1.3c},
mirror = {https://mirror.ctan.org/macros/latex/contrib/chemformula-ru},
@@ -13887,8 +13887,8 @@
title = {The \texttt{cochineal} package},
subtitle = {Cochineal fonts with \LaTeX{} support},
author = {Michael Sharpe},
- date = {2024-03-06},
- version = {1.084},
+ date = {2024-03-09},
+ version = {1.085},
license = {ofl,lppl1.3},
mirror = {https://mirror.ctan.org/fonts/cochineal},
url = {https://ctan.org/pkg/cochineal},
@@ -18788,7 +18788,7 @@
title = {The \texttt{didec} package},
subtitle = {Fixed-point arithmetic with two decimal places},
author = {Thomas F. Sturm},
- date = {2024-02-29},
+ date = {2024-03-09},
version = {1.0.0},
license = {lppl1.3},
mirror = {https://mirror.ctan.org/macros/latex/contrib/didec},
@@ -24583,6 +24583,17 @@
url = {https://ctan.org/pkg/facture},
}
+@manual{ctan-fadingimage,
+ title = {The \texttt{FadingImage} package},
+ subtitle = {Add full width fading pictures at the top or bottom of a page},
+ author = {Mingyu Xia},
+ date = {2024-03-09},
+ version = {0.1b},
+ license = {lppl1.3c},
+ mirror = {https://mirror.ctan.org/macros/latex/contrib/fadingimage},
+ url = {https://ctan.org/pkg/fadingimage},
+}
+
@manual{ctan-fahyph,
title = {The \texttt{fahyph} package},
subtitle = {Hyphenation patterns for Persian (in Unicode)},
@@ -25965,8 +25976,8 @@
title = {The \texttt{fithesis} package},
subtitle = {Thesis class and template for Masaryk University (Brno, Czech Republic)},
author = {Vít Starý Novotný},
- date = {2022-08-17},
- version = {1.1.0},
+ date = {2024-03-09},
+ version = {1.1.1},
license = {lppl1.3},
mirror = {https://mirror.ctan.org/macros/latex/contrib/fithesis},
url = {https://ctan.org/pkg/fithesis},
@@ -27098,7 +27109,7 @@
title = {The \texttt{fontscale} package},
subtitle = {A flexible interface for setting font sizes},
author = {Oliver Beery},
- date = {2024-03-08},
+ date = {2024-03-09},
version = {1.0.1},
license = {lppl1.3c},
mirror = {https://mirror.ctan.org/macros/latex/contrib/fontscale},
@@ -31096,8 +31107,8 @@
title = {The \texttt{gzt} package},
subtitle = {Bundle of classes for “La Gazette des Mathématiciens”},
author = {Denis Bitouzé},
- date = {2022-06-13},
- version = {1.1.3},
+ date = {2024-03-09},
+ version = {1.1.4},
license = {lppl1.3c},
mirror = {https://mirror.ctan.org/macros/latex/contrib/gzt},
url = {https://ctan.org/pkg/gzt},
@@ -37735,7 +37746,7 @@
title = {The \texttt{lastbib} package},
subtitle = {Record the number of citations in a document},
author = {Berik I. Tuleuov},
- date = {2024-03-04},
+ date = {2024-03-09},
version = {2.1},
license = {lppl},
mirror = {https://mirror.ctan.org/macros/latex/contrib/lastbib},
@@ -40339,6 +40350,17 @@
url = {https://ctan.org/pkg/listofsymbols},
}
+@manual{ctan-litebook,
+ title = {The \texttt{LiteBook} package},
+ subtitle = {A fresh cover and chapter design for books},
+ author = {Mingyu Xia},
+ date = {2024-03-09},
+ version = {0.1a},
+ license = {lppl1.3c},
+ mirror = {https://mirror.ctan.org/macros/latex/contrib/litebook},
+ url = {https://ctan.org/pkg/litebook},
+}
+
@manual{ctan-literate,
title = {The \texttt{literate} package},
subtitle = {A literate programming system, not tied to any language},
@@ -43718,8 +43740,8 @@
title = {The \texttt{markdown} package},
subtitle = {Converting and rendering markdown documents inside \TeX{}},
author = {Vít Starý Novotný},
- date = {2024-02-18},
- version = {3.4.1-0-g457226ae},
+ date = {2024-03-09},
+ version = {3.4.2-0-ga45cf0ed},
license = {lppl1.3c},
mirror = {https://mirror.ctan.org/macros/generic/markdown},
url = {https://ctan.org/pkg/markdown},
@@ -75241,7 +75263,7 @@
title = {The \texttt{useclass} package},
subtitle = {Load classes as packages},
author = {Yuxi HUANG},
- date = {2024-03-06},
+ date = {2024-03-09},
version = {1.0},
license = {lppl1.3c},
mirror = {https://mirror.ctan.org/macros/latex/contrib/useclass},