diff options
author | Norbert Preining <norbert@preining.info> | 2022-08-19 03:00:56 +0000 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2022-08-19 03:00:56 +0000 |
commit | 1772be123f1cfa713b25548f6fec135e7ab339a3 (patch) | |
tree | 1ba6586dc52536e962cb28380567183f6f90bbc1 | |
parent | 982d5e88b736a798b356bf5cabe5e6c9b115f182 (diff) |
CTAN sync 202208190300
68 files changed, 10909 insertions, 6979 deletions
diff --git a/FILES.byname b/FILES.byname index 766586f702..5e96684943 100644 --- a/FILES.byname +++ b/FILES.byname @@ -1788,105 +1788,108 @@ 1995/06/20 | 49681 | biblio/bibtex/vms/bibtex.vms-changes 1995/04/14 | 620 | biblio/bibtex/vms/link_bibtex.com 1995/04/14 | 1316 | biblio/bibtex/vms/make_bibtex.com -2022/03/21 | 9898 | biblio/citation-style-language/american-chemical-society.csl -2022/03/21 | 10684 | biblio/citation-style-language/american-medical-association.csl -2022/03/21 | 8052 | biblio/citation-style-language/american-political-science-association.csl -2022/03/21 | 10503 | biblio/citation-style-language/american-sociological-association.csl -2022/03/21 | 69389 | biblio/citation-style-language/apa.csl -2022/03/21 | 1142 | biblio/citation-style-language/CHANGELOG.md -2022/03/21 | 22195 | biblio/citation-style-language/chicago-author-date.csl -2022/03/21 | 47520 | biblio/citation-style-language/chicago-fullnote-bibliography.csl -2022/03/21 | 45970 | biblio/citation-style-language/chicago-note-bibliography.csl -2022/03/21 | 219427 | biblio/citation-style-language/citation-style-language-doc.pdf -2022/03/21 | 13296 | biblio/citation-style-language/citation-style-language-doc.tex -2022/03/21 | 29414 | biblio/citation-style-language/citation-style-language.sty -2022/03/21 | 4815 | biblio/citation-style-language/citeproc -2022/03/21 | 605 | biblio/citation-style-language/citeproc.1 -2022/03/21 | 61229 | biblio/citation-style-language/citeproc-bib-data.json -2022/03/21 | 14177 | biblio/citation-style-language/citeproc-bib.lua -2022/03/21 | 10421 | biblio/citation-style-language/citeproc-element.lua -2022/03/21 | 11279 | biblio/citation-style-language/citeproc-engine.lua -2022/03/21 | 7287 | biblio/citation-style-language/citeproc-formats.lua -2022/03/21 | 411 | biblio/citation-style-language/citeproc.lua -2022/03/21 | 3504 | biblio/citation-style-language/citeproc-node-choose.lua -2022/03/21 | 10463 | biblio/citation-style-language/citeproc-node-date.lua -2022/03/21 | 826 | biblio/citation-style-language/citeproc-node-group.lua -2022/03/21 | 3110 | biblio/citation-style-language/citeproc-node-label.lua -2022/03/21 | 6840 | biblio/citation-style-language/citeproc-node-layout.lua -2022/03/21 | 3183 | biblio/citation-style-language/citeproc-node-locale.lua -2022/03/21 | 20062 | biblio/citation-style-language/citeproc-node-names.lua -2022/03/21 | 2491 | biblio/citation-style-language/citeproc-node-number.lua -2022/03/21 | 1476 | biblio/citation-style-language/citeproc-nodes.lua -2022/03/21 | 5080 | biblio/citation-style-language/citeproc-node-sort.lua -2022/03/21 | 5163 | biblio/citation-style-language/citeproc-node-style.lua -2022/03/21 | 6204 | biblio/citation-style-language/citeproc-node-text.lua -2022/03/21 | 20541 | biblio/citation-style-language/citeproc-richtext.lua -2022/03/21 | 17094 | biblio/citation-style-language/citeproc-util.lua -2022/03/21 | 7765 | biblio/citation-style-language/csl-core.lua -2022/03/21 | 21433 | biblio/citation-style-language/csl-locales-af-ZA.xml -2022/03/21 | 19817 | biblio/citation-style-language/csl-locales-ar.xml -2022/03/21 | 24466 | biblio/citation-style-language/csl-locales-bg-BG.xml -2022/03/21 | 21302 | biblio/citation-style-language/csl-locales-ca-AD.xml -2022/03/21 | 21579 | biblio/citation-style-language/csl-locales-cs-CZ.xml -2022/03/21 | 21576 | biblio/citation-style-language/csl-locales-cy-GB.xml -2022/03/21 | 21470 | biblio/citation-style-language/csl-locales-da-DK.xml -2022/03/21 | 22218 | biblio/citation-style-language/csl-locales-de-AT.xml -2022/03/21 | 21681 | biblio/citation-style-language/csl-locales-de-CH.xml -2022/03/21 | 22143 | biblio/citation-style-language/csl-locales-de-DE.xml -2022/03/21 | 23024 | biblio/citation-style-language/csl-locales-el-GR.xml -2022/03/21 | 22355 | biblio/citation-style-language/csl-locales-en-GB.xml -2022/03/21 | 22510 | biblio/citation-style-language/csl-locales-en-US.xml -2022/03/21 | 21406 | biblio/citation-style-language/csl-locales-es-CL.xml -2022/03/21 | 21327 | biblio/citation-style-language/csl-locales-es-ES.xml -2022/03/21 | 22434 | biblio/citation-style-language/csl-locales-es-MX.xml -2022/03/21 | 21261 | biblio/citation-style-language/csl-locales-et-EE.xml -2022/03/21 | 21512 | biblio/citation-style-language/csl-locales-eu.xml -2022/03/21 | 22337 | biblio/citation-style-language/csl-locales-fa-IR.xml -2022/03/21 | 21623 | biblio/citation-style-language/csl-locales-fi-FI.xml -2022/03/21 | 22098 | biblio/citation-style-language/csl-locales-fr-CA.xml -2022/03/21 | 22101 | biblio/citation-style-language/csl-locales-fr-FR.xml -2022/03/21 | 21822 | biblio/citation-style-language/csl-locales-he-IL.xml -2022/03/21 | 24345 | biblio/citation-style-language/csl-locales-hi-IN.xml -2022/03/21 | 21363 | biblio/citation-style-language/csl-locales-hr-HR.xml -2022/03/21 | 21466 | biblio/citation-style-language/csl-locales-hu-HU.xml -2022/03/21 | 21654 | biblio/citation-style-language/csl-locales-id-ID.xml -2022/03/21 | 21469 | biblio/citation-style-language/csl-locales-is-IS.xml -2022/03/21 | 23360 | biblio/citation-style-language/csl-locales-it-IT.xml -2022/03/21 | 21482 | biblio/citation-style-language/csl-locales-ja-JP.xml -2022/03/21 | 21966 | biblio/citation-style-language/csl-locales-km-KH.xml -2022/03/21 | 21414 | biblio/citation-style-language/csl-locales-ko-KR.xml -2022/03/21 | 21302 | biblio/citation-style-language/csl-locales-la.xml -2022/03/21 | 22752 | biblio/citation-style-language/csl-locales-lt-LT.xml -2022/03/21 | 23553 | biblio/citation-style-language/csl-locales-lv-LV.xml -2022/03/21 | 21941 | biblio/citation-style-language/csl-locales-mn-MN.xml -2022/03/21 | 21323 | biblio/citation-style-language/csl-locales-nb-NO.xml -2022/03/21 | 22358 | biblio/citation-style-language/csl-locales-nl-NL.xml -2022/03/21 | 21301 | biblio/citation-style-language/csl-locales-nn-NO.xml -2022/03/21 | 21446 | biblio/citation-style-language/csl-locales-pl-PL.xml -2022/03/21 | 22542 | biblio/citation-style-language/csl-locales-pt-BR.xml -2022/03/21 | 22454 | biblio/citation-style-language/csl-locales-pt-PT.xml -2022/03/21 | 21462 | biblio/citation-style-language/csl-locales-ro-RO.xml -2022/03/21 | 25715 | biblio/citation-style-language/csl-locales-ru-RU.xml -2022/03/21 | 21574 | biblio/citation-style-language/csl-locales-sk-SK.xml -2022/03/21 | 21330 | biblio/citation-style-language/csl-locales-sl-SI.xml -2022/03/21 | 22122 | biblio/citation-style-language/csl-locales-sr-RS.xml -2022/03/21 | 21715 | biblio/citation-style-language/csl-locales-sv-SE.xml -2022/03/21 | 23467 | biblio/citation-style-language/csl-locales-th-TH.xml -2022/03/21 | 21635 | biblio/citation-style-language/csl-locales-tr-TR.xml -2022/03/21 | 20747 | biblio/citation-style-language/csl-locales-uk-UA.xml -2022/03/21 | 21812 | biblio/citation-style-language/csl-locales-vi-VN.xml -2022/03/21 | 19056 | biblio/citation-style-language/csl-locales-zh-CN.xml -2022/03/21 | 19423 | biblio/citation-style-language/csl-locales-zh-TW.xml -2022/03/21 | 3443 | biblio/citation-style-language/csl.lua -2022/03/21 | 8128 | biblio/citation-style-language/elsevier-harvard.csl -2022/03/21 | 10619 | biblio/citation-style-language/harvard-cite-them-right.csl -2022/03/21 | 15413 | biblio/citation-style-language/ieee.csl -2022/03/21 | 16054 | biblio/citation-style-language/modern-humanities-research-association.csl -2022/03/21 | 11226 | biblio/citation-style-language/modern-language-association.csl -2022/03/21 | 4534 | biblio/citation-style-language/nature.csl -2022/03/21 | 1669 | biblio/citation-style-language/README.md -2022/03/21 | 11927 | biblio/citation-style-language/vancouver.csl -2022/03/21 | 555431 | biblio/citation-style-language.zip +2022/08/19 | 10019 | biblio/citation-style-language/american-chemical-society.csl +2022/08/19 | 11034 | biblio/citation-style-language/american-medical-association.csl +2022/08/19 | 8052 | biblio/citation-style-language/american-political-science-association.csl +2022/08/19 | 11060 | biblio/citation-style-language/american-sociological-association.csl +2022/08/19 | 69907 | biblio/citation-style-language/apa.csl +2022/08/19 | 2145 | biblio/citation-style-language/CHANGELOG.md +2022/08/19 | 23079 | biblio/citation-style-language/chicago-author-date.csl +2022/08/19 | 47520 | biblio/citation-style-language/chicago-fullnote-bibliography.csl +2022/08/19 | 45970 | biblio/citation-style-language/chicago-note-bibliography.csl +2022/08/19 | 220489 | biblio/citation-style-language/citation-style-language-doc.pdf +2022/08/19 | 13278 | biblio/citation-style-language/citation-style-language-doc.tex +2022/08/19 | 31273 | biblio/citation-style-language/citation-style-language.sty +2022/08/19 | 40700 | biblio/citation-style-language/citeproc-bib-data.lua +2022/08/19 | 14024 | biblio/citation-style-language/citeproc-bib.lua +2022/08/19 | 4797 | biblio/citation-style-language/citeproc-cli.lua +2022/08/19 | 8425 | biblio/citation-style-language/citeproc-context.lua +2022/08/19 | 14833 | biblio/citation-style-language/citeproc-element.lua +2022/08/19 | 61972 | biblio/citation-style-language/citeproc-engine.lua +2022/08/19 | 2993 | biblio/citation-style-language/citeproc-ir-node.lua +2022/08/19 | 7685 | biblio/citation-style-language/citeproc-latex-core.lua +2022/08/19 | 3696 | biblio/citation-style-language/citeproc-latex.lua +2022/08/19 | 411 | biblio/citation-style-language/citeproc.lua +2022/08/19 | 617 | biblio/citation-style-language/citeproc-lua.1 +2022/08/19 | 240 | biblio/citation-style-language/citeproc-lua.lua +2022/08/19 | 7308 | biblio/citation-style-language/citeproc-node-choose.lua +2022/08/19 | 13585 | biblio/citation-style-language/citeproc-node-date.lua +2022/08/19 | 904 | biblio/citation-style-language/citeproc-node-group.lua +2022/08/19 | 2655 | biblio/citation-style-language/citeproc-node-label.lua +2022/08/19 | 1702 | biblio/citation-style-language/citeproc-node-layout.lua +2022/08/19 | 6100 | biblio/citation-style-language/citeproc-node-locale.lua +2022/08/19 | 33702 | biblio/citation-style-language/citeproc-node-names.lua +2022/08/19 | 1675 | biblio/citation-style-language/citeproc-node-number.lua +2022/08/19 | 1476 | biblio/citation-style-language/citeproc-nodes.lua +2022/08/19 | 6283 | biblio/citation-style-language/citeproc-node-sort.lua +2022/08/19 | 15617 | biblio/citation-style-language/citeproc-node-style.lua +2022/08/19 | 5498 | biblio/citation-style-language/citeproc-node-text.lua +2022/08/19 | 44466 | biblio/citation-style-language/citeproc-output.lua +2022/08/19 | 21517 | biblio/citation-style-language/citeproc-util.lua +2022/08/19 | 21433 | biblio/citation-style-language/csl-locales-af-ZA.xml +2022/08/19 | 19817 | biblio/citation-style-language/csl-locales-ar.xml +2022/08/19 | 24466 | biblio/citation-style-language/csl-locales-bg-BG.xml +2022/08/19 | 21302 | biblio/citation-style-language/csl-locales-ca-AD.xml +2022/08/19 | 21579 | biblio/citation-style-language/csl-locales-cs-CZ.xml +2022/08/19 | 21576 | biblio/citation-style-language/csl-locales-cy-GB.xml +2022/08/19 | 21470 | biblio/citation-style-language/csl-locales-da-DK.xml +2022/08/19 | 22218 | biblio/citation-style-language/csl-locales-de-AT.xml +2022/08/19 | 21681 | biblio/citation-style-language/csl-locales-de-CH.xml +2022/08/19 | 22143 | biblio/citation-style-language/csl-locales-de-DE.xml +2022/08/19 | 23024 | biblio/citation-style-language/csl-locales-el-GR.xml +2022/08/19 | 22472 | biblio/citation-style-language/csl-locales-en-GB.xml +2022/08/19 | 22627 | biblio/citation-style-language/csl-locales-en-US.xml +2022/08/19 | 21406 | biblio/citation-style-language/csl-locales-es-CL.xml +2022/08/19 | 21327 | biblio/citation-style-language/csl-locales-es-ES.xml +2022/08/19 | 22434 | biblio/citation-style-language/csl-locales-es-MX.xml +2022/08/19 | 21261 | biblio/citation-style-language/csl-locales-et-EE.xml +2022/08/19 | 21512 | biblio/citation-style-language/csl-locales-eu.xml +2022/08/19 | 22337 | biblio/citation-style-language/csl-locales-fa-IR.xml +2022/08/19 | 21623 | biblio/citation-style-language/csl-locales-fi-FI.xml +2022/08/19 | 22098 | biblio/citation-style-language/csl-locales-fr-CA.xml +2022/08/19 | 22356 | biblio/citation-style-language/csl-locales-fr-FR.xml +2022/08/19 | 21822 | biblio/citation-style-language/csl-locales-he-IL.xml +2022/08/19 | 24345 | biblio/citation-style-language/csl-locales-hi-IN.xml +2022/08/19 | 21363 | biblio/citation-style-language/csl-locales-hr-HR.xml +2022/08/19 | 21466 | biblio/citation-style-language/csl-locales-hu-HU.xml +2022/08/19 | 21654 | biblio/citation-style-language/csl-locales-id-ID.xml +2022/08/19 | 21469 | biblio/citation-style-language/csl-locales-is-IS.xml +2022/08/19 | 23360 | biblio/citation-style-language/csl-locales-it-IT.xml +2022/08/19 | 21482 | biblio/citation-style-language/csl-locales-ja-JP.xml +2022/08/19 | 21966 | biblio/citation-style-language/csl-locales-km-KH.xml +2022/08/19 | 21414 | biblio/citation-style-language/csl-locales-ko-KR.xml +2022/08/19 | 21302 | biblio/citation-style-language/csl-locales-la.xml +2022/08/19 | 22752 | biblio/citation-style-language/csl-locales-lt-LT.xml +2022/08/19 | 23553 | biblio/citation-style-language/csl-locales-lv-LV.xml +2022/08/19 | 21941 | biblio/citation-style-language/csl-locales-mn-MN.xml +2022/08/19 | 21323 | biblio/citation-style-language/csl-locales-nb-NO.xml +2022/08/19 | 22358 | biblio/citation-style-language/csl-locales-nl-NL.xml +2022/08/19 | 21301 | biblio/citation-style-language/csl-locales-nn-NO.xml +2022/08/19 | 21446 | biblio/citation-style-language/csl-locales-pl-PL.xml +2022/08/19 | 22542 | biblio/citation-style-language/csl-locales-pt-BR.xml +2022/08/19 | 22454 | biblio/citation-style-language/csl-locales-pt-PT.xml +2022/08/19 | 21462 | biblio/citation-style-language/csl-locales-ro-RO.xml +2022/08/19 | 25715 | biblio/citation-style-language/csl-locales-ru-RU.xml +2022/08/19 | 21574 | biblio/citation-style-language/csl-locales-sk-SK.xml +2022/08/19 | 21330 | biblio/citation-style-language/csl-locales-sl-SI.xml +2022/08/19 | 22122 | biblio/citation-style-language/csl-locales-sr-RS.xml +2022/08/19 | 21715 | biblio/citation-style-language/csl-locales-sv-SE.xml +2022/08/19 | 23467 | biblio/citation-style-language/csl-locales-th-TH.xml +2022/08/19 | 21635 | biblio/citation-style-language/csl-locales-tr-TR.xml +2022/08/19 | 20747 | biblio/citation-style-language/csl-locales-uk-UA.xml +2022/08/19 | 21812 | biblio/citation-style-language/csl-locales-vi-VN.xml +2022/08/19 | 19056 | biblio/citation-style-language/csl-locales-zh-CN.xml +2022/08/19 | 19423 | biblio/citation-style-language/csl-locales-zh-TW.xml +2022/08/19 | 196 | biblio/citation-style-language/DEPENDS.txt +2022/08/19 | 8128 | biblio/citation-style-language/elsevier-harvard.csl +2022/08/19 | 10723 | biblio/citation-style-language/harvard-cite-them-right.csl +2022/08/19 | 15413 | biblio/citation-style-language/ieee.csl +2022/08/19 | 16054 | biblio/citation-style-language/modern-humanities-research-association.csl +2022/08/19 | 11209 | biblio/citation-style-language/modern-language-association.csl +2022/08/19 | 5288 | biblio/citation-style-language/nature.csl +2022/08/19 | 1673 | biblio/citation-style-language/README.md +2022/08/19 | 11958 | biblio/citation-style-language/vancouver.csl +2022/08/18 | 577055 | biblio/citation-style-language.zip 2022/02/06 | 3110 | biblio/pbibtex/pbibtex-base/cpp.awk 2022/02/06 | 1009 | biblio/pbibtex/pbibtex-base/generate.sh 2022/02/06 | 22422 | biblio/pbibtex/pbibtex-base/jabbrv.bst @@ -5264,7 +5267,7 @@ 1990/10/02 | 5440 | dviware/vutex/vaxvms.hlp 1990/10/02 | 812 | dviware/vutex/vaxvms.ins 1990/10/02 | 127576 | dviware/vutex/vutex.web -2022/08/17 | 89208 | FILES.last07days +2022/08/18 | 95093 | FILES.last07days 2021/07/24 | 1139410 | fonts/aboensis/Aboensis.glyphs 2021/07/24 | 18907382 | fonts/aboensis/aboensis.pdf 2021/07/24 | 137860 | fonts/aboensis/Aboensis-Regular.otf @@ -158429,6 +158432,12 @@ 2021/07/17 | 313369 | graphics/pgf/contrib/easing/easing.pdf 2021/07/17 | 399 | graphics/pgf/contrib/easing/README 2021/07/17 | 319237 | graphics/pgf/contrib/easing.zip +2022/08/18 | 248260 | graphics/pgf/contrib/fancyqr/fancyqr-doc.pdf +2022/08/18 | 4485 | graphics/pgf/contrib/fancyqr/fancyqr-doc.tex +2022/08/18 | 10265 | graphics/pgf/contrib/fancyqr/fancyqr.sty +2022/08/18 | 813 | graphics/pgf/contrib/fancyqr/qr-example.tex +2022/08/18 | 3582 | graphics/pgf/contrib/fancyqr/README.md +2022/08/18 | 251020 | graphics/pgf/contrib/fancyqr.zip 2013/02/27 | 17141 | graphics/pgf/contrib/fast-diagram/fast-diagram.sty 2013/02/27 | 1050633 | graphics/pgf/contrib/fast-diagram/help.pdf 2013/02/27 | 1437 | graphics/pgf/contrib/fast-diagram/help.tex @@ -188723,7 +188732,7 @@ 2022/06/20 | 140748 | info/yet-another-guide-latex2e/Yet-Another-Guide-LaTeX2e_v1.tex 2022/06/20 | 899385 | info/yet-another-guide-latex2e.zip 2021/02/04 | 4944311 | install/biblio/bibtex/contrib/gost.tds.zip -2022/03/21 | 559357 | install/biblio/citation-style-language.tds.zip +2022/08/19 | 580030 | install/biblio/citation-style-language.tds.zip 2013/11/06 | 795801 | install/fonts/accanthis.tds.zip 2009/05/23 | 246025 | install/fonts/ae.tds.zip 2019/10/12 | 38525845 | install/fonts/alegreya.tds.zip @@ -276442,7 +276451,7 @@ 2021/05/03 | 629 | support/TeX4ht/doc/README 2020/08/24 | 358454 | support/TeX4ht/doc/TeX4ht-doc.tex 2021/05/11 | 262 | support/TeX4ht/README -2022/08/11 | 199643 | support/TeX4ht/source/ChangeLog +2022/08/17 | 200199 | support/TeX4ht/source/ChangeLog 2021/05/03 | 1375 | support/TeX4ht/source/checklog.lua 2021/05/03 | 1189 | support/TeX4ht/source/common-code.tex 2021/05/03 | 2727 | support/TeX4ht/source/common-info.tex @@ -276450,11 +276459,11 @@ 2021/05/06 | 15 | support/TeX4ht/source/extra-bin/vcss 2021/05/06 | 15 | support/TeX4ht/source/extra-bin/xmllint 2022/08/07 | 27321 | support/TeX4ht/source/Makefile -2022/06/20 | 8082 | support/TeX4ht/source/mktex4ht-cnf.tex +2022/08/17 | 8111 | support/TeX4ht/source/mktex4ht-cnf.tex 2021/05/03 | 1121 | support/TeX4ht/source/README 2021/05/03 | 1744 | support/TeX4ht/source/t1fontmake.lua 2021/05/03 | 297 | support/TeX4ht/source/t1fontsample.tex -2022/08/07 | 1127331 | support/TeX4ht/source/tex4ht-4ht.tex +2022/08/17 | 1128043 | support/TeX4ht/source/tex4ht-4ht.tex 2021/05/03 | 7127 | support/TeX4ht/source/tex4ht-auto-script.tex 2021/05/16 | 1539 | support/TeX4ht/source/tex4ht-bibtex2.tex 2022/06/05 | 21307 | support/TeX4ht/source/tex4ht-cond4ht.tex @@ -276480,7 +276489,7 @@ 2021/05/03 | 14218 | support/TeX4ht/source/tex4ht-htcmd.tex 2021/05/03 | 70683 | support/TeX4ht/source/tex4ht-html0.tex 2021/05/03 | 164748 | support/TeX4ht/source/tex4ht-html32.tex -2022/05/22 | 617510 | support/TeX4ht/source/tex4ht-html4.tex +2022/08/17 | 617532 | support/TeX4ht/source/tex4ht-html4.tex 2022/08/11 | 11077 | support/TeX4ht/source/tex4ht-html5.tex 2021/06/17 | 648233 | support/TeX4ht/source/tex4ht-html-speech.tex 2021/05/03 | 59483 | support/TeX4ht/source/tex4ht-html-speech-xtpipes.tex @@ -277780,10 +277789,10 @@ 2007/07/22 | 600 | support/wp2latex/readme.1st 2021/08/01 | 7401 | support/wp2latex/readme.txt 2020/02/11 | 305310 | support/wp2latex/wp2latex-3.87.deb -2020/10/12 | 3641715 | support/wp2latex/wp2latex-3.92.zip +2021/01/23 | 3690318 | support/wp2latex/wp2latex-3.93.zip 2018/01/26 | 45297 | support/wp2latex/wp2latex.doc.htm 2018/01/26 | 7259 | support/wp2latex/wp2latex.faq -2020/10/11 | 1642418 | support/wp2latex/WP2LaTeX_Installer-3.92.exe +2021/01/23 | 1635025 | support/wp2latex/WP2LaTeX_Installer-3.93b.exe 2021/08/01 | 1241 | support/wp2latex/wp2latex.lsm 2018/01/26 | 35145 | support/wp2latex/wp2latex_pas-2.3.zip 2000/02/22 | 481 | support/wsuipa2tipa/README @@ -284422,14 +284431,14 @@ 2019/02/28 | 377000 | systems/texlive/tlnet/archive/examdesign.doc.r15878.tar.xz 2019/02/28 | 10780 | systems/texlive/tlnet/archive/examdesign.r15878.tar.xz 2019/02/28 | 29924 | systems/texlive/tlnet/archive/examdesign.source.r15878.tar.xz -2021/03/02 | 515428 | systems/texlive/tlnet/archive/exam.doc.r58023.tar.xz +2022/08/18 | 524800 | systems/texlive/tlnet/archive/exam.doc.r64134.tar.xz 2019/02/28 | 820032 | systems/texlive/tlnet/archive/exam-n.doc.r42755.tar.xz 2019/02/28 | 11804 | systems/texlive/tlnet/archive/exam-n.r42755.tar.xz 2019/02/28 | 34424 | systems/texlive/tlnet/archive/exam-n.source.r42755.tar.xz 2020/05/25 | 379128 | systems/texlive/tlnet/archive/examplep.doc.r55265.tar.xz 2020/05/25 | 33788 | systems/texlive/tlnet/archive/examplep.r55265.tar.xz 2019/02/28 | 5516 | systems/texlive/tlnet/archive/example.r33398.tar.xz -2021/03/02 | 49904 | systems/texlive/tlnet/archive/exam.r58023.tar.xz +2022/08/18 | 49900 | systems/texlive/tlnet/archive/exam.r64134.tar.xz 2022/01/24 | 313712 | systems/texlive/tlnet/archive/exam-randomizechoices.doc.r61719.tar.xz 2022/01/24 | 5624 | systems/texlive/tlnet/archive/exam-randomizechoices.r61719.tar.xz 2022/08/16 | 1739528 | systems/texlive/tlnet/archive/exam-zh.doc.r64123.tar.xz @@ -284726,9 +284735,9 @@ 2019/02/28 | 496576 | systems/texlive/tlnet/archive/fitbox.doc.r50088.tar.xz 2019/02/28 | 2228 | systems/texlive/tlnet/archive/fitbox.r50088.tar.xz 2019/02/28 | 5812 | systems/texlive/tlnet/archive/fitbox.source.r50088.tar.xz -2021/10/19 | 729804 | systems/texlive/tlnet/archive/fithesis.doc.r60795.tar.xz -2021/10/19 | 791532 | systems/texlive/tlnet/archive/fithesis.r60795.tar.xz -2021/10/19 | 44752 | systems/texlive/tlnet/archive/fithesis.source.r60795.tar.xz +2022/08/18 | 730120 | systems/texlive/tlnet/archive/fithesis.doc.r64135.tar.xz +2022/08/18 | 792156 | systems/texlive/tlnet/archive/fithesis.r64135.tar.xz +2022/08/18 | 45332 | systems/texlive/tlnet/archive/fithesis.source.r64135.tar.xz 2019/02/28 | 212644 | systems/texlive/tlnet/archive/fix2col.doc.r38770.tar.xz 2019/02/28 | 2684 | systems/texlive/tlnet/archive/fix2col.r38770.tar.xz 2019/02/28 | 6376 | systems/texlive/tlnet/archive/fix2col.source.r38770.tar.xz @@ -285644,8 +285653,8 @@ 2021/11/28 | 6640 | systems/texlive/tlnet/archive/hep-title.source.r61173.tar.xz 2020/04/16 | 100060 | systems/texlive/tlnet/archive/hepunits.doc.r54758.tar.xz 2020/04/16 | 1804 | systems/texlive/tlnet/archive/hepunits.r54758.tar.xz -2022/08/15 | 63056 | systems/texlive/tlnet/archive/hereapplies.doc.r64117.tar.xz -2022/08/15 | 3216 | systems/texlive/tlnet/archive/hereapplies.r64117.tar.xz +2022/08/18 | 64028 | systems/texlive/tlnet/archive/hereapplies.doc.r64136.tar.xz +2022/08/18 | 3748 | systems/texlive/tlnet/archive/hereapplies.r64136.tar.xz 2019/02/28 | 596 | systems/texlive/tlnet/archive/here.doc.r16135.tar.xz 2019/02/28 | 896 | systems/texlive/tlnet/archive/here.r16135.tar.xz 2019/02/28 | 213100 | systems/texlive/tlnet/archive/he-she.doc.r41359.tar.xz @@ -289779,8 +289788,8 @@ 2019/02/28 | 378272 | systems/texlive/tlnet/archive/productbox.doc.r20886.tar.xz 2019/02/28 | 4944 | systems/texlive/tlnet/archive/productbox.r20886.tar.xz 2019/02/28 | 15512 | systems/texlive/tlnet/archive/productbox.source.r20886.tar.xz -2022/08/03 | 10015344 | systems/texlive/tlnet/archive/profcollege.doc.r64032.tar.xz -2022/08/03 | 1210836 | systems/texlive/tlnet/archive/profcollege.r64032.tar.xz +2022/08/18 | 10136040 | systems/texlive/tlnet/archive/profcollege.doc.r64137.tar.xz +2022/08/18 | 1211724 | systems/texlive/tlnet/archive/profcollege.r64137.tar.xz 2022/04/27 | 134096 | systems/texlive/tlnet/archive/proflabo.doc.r63147.tar.xz 2022/04/27 | 2748 | systems/texlive/tlnet/archive/proflabo.r63147.tar.xz 2022/08/17 | 855220 | systems/texlive/tlnet/archive/proflycee.doc.r64130.tar.xz @@ -291650,14 +291659,14 @@ 2022/02/27 | 108804 | systems/texlive/tlnet/archive/tex4ht.amd64-freebsd.r62206.tar.xz 2022/02/27 | 87364 | systems/texlive/tlnet/archive/tex4ht.amd64-netbsd.r62220.tar.xz 2022/04/21 | 69948 | systems/texlive/tlnet/archive/tex4ht.armhf-linux.r63092.tar.xz -2022/08/12 | 136384 | systems/texlive/tlnet/archive/tex4ht.doc.r64099.tar.xz +2022/08/18 | 136388 | systems/texlive/tlnet/archive/tex4ht.doc.r64138.tar.xz 2022/03/01 | 58328 | systems/texlive/tlnet/archive/tex4ht.i386-cygwin.r62282.tar.xz 2022/02/27 | 93760 | systems/texlive/tlnet/archive/tex4ht.i386-freebsd.r62206.tar.xz 2022/02/27 | 91280 | systems/texlive/tlnet/archive/tex4ht.i386-linux.r62210.tar.xz 2022/02/27 | 76200 | systems/texlive/tlnet/archive/tex4ht.i386-netbsd.r62220.tar.xz 2022/02/27 | 83964 | systems/texlive/tlnet/archive/tex4ht.i386-solaris.r62206.tar.xz -2022/08/12 | 952476 | systems/texlive/tlnet/archive/tex4ht.r64099.tar.xz -2022/08/12 | 1272264 | systems/texlive/tlnet/archive/tex4ht.source.r64099.tar.xz +2022/08/18 | 952684 | systems/texlive/tlnet/archive/tex4ht.r64138.tar.xz +2022/08/18 | 1274892 | systems/texlive/tlnet/archive/tex4ht.source.r64138.tar.xz 2022/02/28 | 184748 | systems/texlive/tlnet/archive/tex4ht.universal-darwin.r62258.tar.xz 2022/02/27 | 57768 | systems/texlive/tlnet/archive/tex4ht.win32.r62199.tar.xz 2022/03/01 | 58016 | systems/texlive/tlnet/archive/tex4ht.x86_64-cygwin.r62279.tar.xz @@ -291892,7 +291901,7 @@ 2020/05/17 | 592 | systems/texlive/tlnet/archive/texlive-scripts.amd64-freebsd.r55172.tar.xz 2020/05/17 | 588 | systems/texlive/tlnet/archive/texlive-scripts.amd64-netbsd.r55172.tar.xz 2020/05/17 | 592 | systems/texlive/tlnet/archive/texlive-scripts.armhf-linux.r55172.tar.xz -2022/08/17 | 419496 | systems/texlive/tlnet/archive/texlive-scripts.doc.r64126.tar.xz +2022/08/18 | 419376 | systems/texlive/tlnet/archive/texlive-scripts.doc.r64133.tar.xz 2020/01/27 | 916 | systems/texlive/tlnet/archive/texlive-scripts-extra.aarch64-linux.r53577.tar.xz 2020/01/27 | 924 | systems/texlive/tlnet/archive/texlive-scripts-extra.amd64-freebsd.r53577.tar.xz 2020/01/27 | 916 | systems/texlive/tlnet/archive/texlive-scripts-extra.amd64-netbsd.r53577.tar.xz @@ -291916,7 +291925,7 @@ 2020/05/17 | 588 | systems/texlive/tlnet/archive/texlive-scripts.i386-linux.r55172.tar.xz 2020/05/17 | 592 | systems/texlive/tlnet/archive/texlive-scripts.i386-netbsd.r55172.tar.xz 2020/05/17 | 588 | systems/texlive/tlnet/archive/texlive-scripts.i386-solaris.r55172.tar.xz -2022/08/17 | 113524 | systems/texlive/tlnet/archive/texlive-scripts.r64126.tar.xz +2022/08/18 | 113500 | systems/texlive/tlnet/archive/texlive-scripts.r64133.tar.xz 2021/02/25 | 572 | systems/texlive/tlnet/archive/texlive-scripts.universal-darwin.r57908.tar.xz 2022/04/19 | 36296 | systems/texlive/tlnet/archive/texlive-scripts.win32.r63068.tar.xz 2020/05/17 | 588 | systems/texlive/tlnet/archive/texlive-scripts.x86_64-cygwin.r55172.tar.xz @@ -293741,16 +293750,16 @@ 2020/07/18 | 47816 | systems/texlive/tlnet/archive/zztex.doc.r55862.tar.xz 2020/07/18 | 101724 | systems/texlive/tlnet/archive/zztex.r55862.tar.xz 2022/07/17 | 124404 | systems/texlive/tlnet/install-tl -2022/08/17 | 5831896 | systems/texlive/tlnet/install-tl-unx.tar.gz -2022/08/17 | 152 | systems/texlive/tlnet/install-tl-unx.tar.gz.sha512 -2022/08/17 | 455 | systems/texlive/tlnet/install-tl-unx.tar.gz.sha512.asc +2022/08/18 | 5831895 | systems/texlive/tlnet/install-tl-unx.tar.gz +2022/08/18 | 152 | systems/texlive/tlnet/install-tl-unx.tar.gz.sha512 +2022/08/18 | 455 | systems/texlive/tlnet/install-tl-unx.tar.gz.sha512.asc 2021/04/11 | 4945 | systems/texlive/tlnet/install-tl-windows.bat -2022/08/17 | 20436545 | systems/texlive/tlnet/install-tl-windows.exe -2022/08/17 | 153 | systems/texlive/tlnet/install-tl-windows.exe.sha512 -2022/08/17 | 455 | systems/texlive/tlnet/install-tl-windows.exe.sha512.asc -2022/08/17 | 25516446 | systems/texlive/tlnet/install-tl.zip -2022/08/17 | 145 | systems/texlive/tlnet/install-tl.zip.sha512 -2022/08/17 | 455 | systems/texlive/tlnet/install-tl.zip.sha512.asc +2022/08/18 | 20433402 | systems/texlive/tlnet/install-tl-windows.exe +2022/08/18 | 153 | systems/texlive/tlnet/install-tl-windows.exe.sha512 +2022/08/18 | 455 | systems/texlive/tlnet/install-tl-windows.exe.sha512.asc +2022/08/18 | 25516427 | systems/texlive/tlnet/install-tl.zip +2022/08/18 | 145 | systems/texlive/tlnet/install-tl.zip.sha512 +2022/08/18 | 455 | systems/texlive/tlnet/install-tl.zip.sha512.asc 2022/04/03 | 1229 | systems/texlive/tlnet/README.md 2022/04/03 | 0 | systems/texlive/tlnet/TEXLIVE_2022 2022/02/28 | 7791 | systems/texlive/tlnet/tlpkg/gpg/pubring.gpg @@ -293760,7 +293769,7 @@ 2022/02/28 | 1280 | systems/texlive/tlnet/tlpkg/gpg/trustdb.gpg 2022/05/27 | 49794 | systems/texlive/tlnet/tlpkg/installer/config.guess 2010/11/11 | 11651 | systems/texlive/tlnet/tlpkg/installer/COPYING.MinGW-runtime.txt -2022/08/16 | 7321 | systems/texlive/tlnet/tlpkg/installer/ctan-mirrors.pl +2022/08/17 | 7221 | systems/texlive/tlnet/tlpkg/installer/ctan-mirrors.pl 2022/07/21 | 222477 | systems/texlive/tlnet/tlpkg/installer/curl/curl-ca-bundle.crt 2020/04/15 | 2606592 | systems/texlive/tlnet/tlpkg/installer/curl/curl.exe 2017/04/16 | 2629 | systems/texlive/tlnet/tlpkg/installer/installer-options.txt @@ -293803,12 +293812,12 @@ 2021/05/16 | 20371 | systems/texlive/tlnet/tlpkg/TeXLive/TLCrypto.pm 2021/12/21 | 5429 | systems/texlive/tlnet/tlpkg/TeXLive/TLDownload.pm 2021/12/21 | 27582 | systems/texlive/tlnet/tlpkg/TeXLive/TLPaper.pm -2022/08/17 | 17582689 | systems/texlive/tlnet/tlpkg/texlive.tlpdb -2022/08/17 | 48 | systems/texlive/tlnet/tlpkg/texlive.tlpdb.md5 +2022/08/18 | 17582691 | systems/texlive/tlnet/tlpkg/texlive.tlpdb +2022/08/18 | 48 | systems/texlive/tlnet/tlpkg/texlive.tlpdb.md5 2022/04/18 | 86658 | systems/texlive/tlnet/tlpkg/TeXLive/TLPDB.pm -2022/08/17 | 144 | systems/texlive/tlnet/tlpkg/texlive.tlpdb.sha512 -2022/08/17 | 455 | systems/texlive/tlnet/tlpkg/texlive.tlpdb.sha512.asc -2022/08/17 | 2397600 | systems/texlive/tlnet/tlpkg/texlive.tlpdb.xz +2022/08/18 | 144 | systems/texlive/tlnet/tlpkg/texlive.tlpdb.sha512 +2022/08/18 | 455 | systems/texlive/tlnet/tlpkg/texlive.tlpdb.sha512.asc +2022/08/18 | 2399360 | systems/texlive/tlnet/tlpkg/texlive.tlpdb.xz 2021/12/21 | 58848 | systems/texlive/tlnet/tlpkg/TeXLive/TLPOBJ.pm 2022/08/01 | 42206 | systems/texlive/tlnet/tlpkg/TeXLive/TLPSRC.pm 2021/12/21 | 16130 | systems/texlive/tlnet/tlpkg/TeXLive/TLTREE.pm @@ -299081,7 +299090,7 @@ 2020/10/03 | 318630 | systems/win32/miktex/tm/packages/filehook.tar.lzma 2012/12/04 | 924573 | systems/win32/miktex/tm/packages/fileinfo.tar.lzma 2011/09/21 | 281409 | systems/win32/miktex/tm/packages/filemod.tar.lzma -2022/08/17 | 659342 | systems/win32/miktex/tm/packages/files.csv.lzma +2022/08/18 | 659342 | systems/win32/miktex/tm/packages/files.csv.lzma 2001/05/14 | 5617 | systems/win32/miktex/tm/packages/finbib.tar.lzma 2015/10/20 | 44379 | systems/win32/miktex/tm/packages/findhyph.tar.lzma 2011/10/21 | 89323 | systems/win32/miktex/tm/packages/fink.tar.lzma @@ -300763,9 +300772,9 @@ 2018/01/12 | 157226 | systems/win32/miktex/tm/packages/miktex-zip-bin-x64.tar.lzma 2022/07/26 | 39695 | systems/win32/miktex/tm/packages/miktex-zlib-bin-2.9.tar.lzma 2022/08/13 | 43580 | systems/win32/miktex/tm/packages/miktex-zlib-bin-x64-2.9.tar.lzma -2022/08/17 | 289560 | systems/win32/miktex/tm/packages/miktex-zzdb1-2.9.tar.lzma -2022/08/17 | 1482162 | systems/win32/miktex/tm/packages/miktex-zzdb2-2.9.tar.lzma -2022/08/17 | 1364924 | systems/win32/miktex/tm/packages/miktex-zzdb3-2.9.tar.lzma +2022/08/18 | 289514 | systems/win32/miktex/tm/packages/miktex-zzdb1-2.9.tar.lzma +2022/08/18 | 1483018 | systems/win32/miktex/tm/packages/miktex-zzdb2-2.9.tar.lzma +2022/08/18 | 1364956 | systems/win32/miktex/tm/packages/miktex-zzdb3-2.9.tar.lzma 2022/07/26 | 13519 | systems/win32/miktex/tm/packages/miktex-zzip-bin-2.9.tar.lzma 2022/08/13 | 14417 | systems/win32/miktex/tm/packages/miktex-zzip-bin-x64-2.9.tar.lzma 2016/07/15 | 35914 | systems/win32/miktex/tm/packages/mil3.tar.lzma @@ -301006,102 +301015,102 @@ 2018/04/09 | 400132 | systems/win32/miktex/tm/packages/newunicodechar.tar.lzma 2011/09/19 | 101312 | systems/win32/miktex/tm/packages/newvbtm.tar.lzma 2021/03/17 | 232249 | systems/win32/miktex/tm/packages/newverbs.tar.lzma -2022/08/17 | 659852 | systems/win32/miktex/tm/packages/next/files.csv.lzma -2022/08/17 | 57317 | systems/win32/miktex/tm/packages/next/miktex-arctrl-bin-x64-2.9.tar.lzma -2022/08/17 | 1161751 | systems/win32/miktex/tm/packages/next/miktex-asymptote-bin-x64-2.9.tar.lzma -2022/08/17 | 31585 | systems/win32/miktex/tm/packages/next/miktex-autosp-bin-x64-2.9.tar.lzma -2022/08/17 | 35264 | systems/win32/miktex/tm/packages/next/miktex-axohelp-bin-x64-2.9.tar.lzma -2022/08/17 | 65130 | systems/win32/miktex/tm/packages/next/miktex-bibarts-bin-x64-2.9.tar.lzma -2022/08/17 | 95467 | systems/win32/miktex/tm/packages/next/miktex-bibtex8bit-bin-x64-2.9.tar.lzma -2022/08/17 | 77209 | systems/win32/miktex/tm/packages/next/miktex-bibtex-bin-x64-2.9.tar.lzma -2022/08/17 | 31561 | systems/win32/miktex/tm/packages/next/miktex-bzip2-bin-x64-2.9.tar.lzma -2022/08/17 | 394142 | systems/win32/miktex/tm/packages/next/miktex-cairo-bin-x64-2.9.tar.lzma -2022/08/17 | 37050 | systems/win32/miktex/tm/packages/next/miktex-chktex-bin-x64-2.9.tar.lzma -2022/08/17 | 57505 | systems/win32/miktex/tm/packages/next/miktex-cjkutils-bin-x64-2.9.tar.lzma -2022/08/17 | 270464 | systems/win32/miktex/tm/packages/next/miktex-console-bin-x64-2.9.tar.lzma -2022/08/17 | 196212 | systems/win32/miktex/tm/packages/next/miktex-curl-bin-x64-2.9.tar.lzma -2022/08/17 | 103245 | systems/win32/miktex/tm/packages/next/miktex-cweb-bin-x64-2.9.tar.lzma -2022/08/17 | 24210 | systems/win32/miktex/tm/packages/next/miktex-devnag-bin-x64-2.9.tar.lzma -2022/08/17 | 481892 | systems/win32/miktex/tm/packages/next/miktex-doc.tar.lzma -2022/08/17 | 52037 | systems/win32/miktex/tm/packages/next/miktex-dvicopy-bin-x64-2.9.tar.lzma -2022/08/17 | 325978 | systems/win32/miktex/tm/packages/next/miktex-dvipdfmx-bin-x64-2.9.tar.lzma -2022/08/17 | 45793 | systems/win32/miktex/tm/packages/next/miktex-dvipng-bin-x64-2.9.tar.lzma -2022/08/17 | 135465 | systems/win32/miktex/tm/packages/next/miktex-dvips-bin-x64-2.9.tar.lzma -2022/08/17 | 1458151 | systems/win32/miktex/tm/packages/next/miktex-dvisvgm-bin-x64-2.9.tar.lzma -2022/08/17 | 112979 | systems/win32/miktex/tm/packages/next/miktex-epstopdf-bin-x64-2.9.tar.lzma -2022/08/17 | 48851 | systems/win32/miktex/tm/packages/next/miktex-expat-bin-x64-2.9.tar.lzma -2022/08/17 | 28509 | systems/win32/miktex/tm/packages/next/miktex-findtexmf-bin-x64-2.9.tar.lzma -2022/08/17 | 63239 | systems/win32/miktex/tm/packages/next/miktex-fmt-bin-x64-2.9.tar.lzma -2022/08/17 | 155431 | systems/win32/miktex/tm/packages/next/miktex-fontconfig-bin-x64-2.9.tar.lzma -2022/08/17 | 79062 | systems/win32/miktex/tm/packages/next/miktex-fonts-bin-x64-2.9.tar.lzma -2022/08/17 | 81448 | systems/win32/miktex/tm/packages/next/miktex-freeglut-bin-x64-2.9.tar.lzma -2022/08/17 | 295943 | systems/win32/miktex/tm/packages/next/miktex-freetype2-bin-x64-2.9.tar.lzma -2022/08/17 | 25118 | systems/win32/miktex/tm/packages/next/miktex-fribidixetex-bin-x64-2.9.tar.lzma -2022/08/17 | 112877 | systems/win32/miktex/tm/packages/next/miktex-gd-bin-x64-2.9.tar.lzma -2022/08/17 | 73262 | systems/win32/miktex/tm/packages/next/miktex-graphite2-bin-x64-2.9.tar.lzma -2022/08/17 | 115580 | systems/win32/miktex/tm/packages/next/miktex-gregorio-bin-x64-2.9.tar.lzma -2022/08/17 | 43888 | systems/win32/miktex/tm/packages/next/miktex-gsf2pk-bin-x64-2.9.tar.lzma -2022/08/17 | 565081 | systems/win32/miktex/tm/packages/next/miktex-harfbuzz-bin-x64-2.9.tar.lzma -2022/08/17 | 247205 | systems/win32/miktex/tm/packages/next/miktex-hitex-bin-x64.tar.lzma -2022/08/17 | 169677 | systems/win32/miktex/tm/packages/next/miktex-hunspell-bin-x64-2.9.tar.lzma -2022/08/17 | 109650 | systems/win32/miktex/tm/packages/next/miktex-jpeg-bin-x64-2.9.tar.lzma -2022/08/17 | 18382 | systems/win32/miktex/tm/packages/next/miktex-kpathsea-bin-x64-2.9.tar.lzma -2022/08/17 | 30570 | systems/win32/miktex/tm/packages/next/miktex-lacheck-bin-x64-2.9.tar.lzma -2022/08/17 | 682213 | systems/win32/miktex/tm/packages/next/miktex-lcdf-typetools-bin-x64-2.9.tar.lzma -2022/08/17 | 599105 | systems/win32/miktex/tm/packages/next/miktex-libressl-bin-x64-2.9.tar.lzma -2022/08/17 | 527570 | systems/win32/miktex/tm/packages/next/miktex-log4cxx-bin-x64-2.9.tar.lzma -2022/08/17 | 103596 | systems/win32/miktex/tm/packages/next/miktex-lua53-bin-x64-2.9.tar.lzma -2022/08/17 | 2023133 | systems/win32/miktex/tm/packages/next/miktex-luatex-bin-x64-2.9.tar.lzma -2022/08/17 | 74099 | systems/win32/miktex/tm/packages/next/miktex-lzma-bin-x64-2.9.tar.lzma -2022/08/17 | 32072 | systems/win32/miktex/tm/packages/next/miktex-makeindex-bin-x64-2.9.tar.lzma -2022/08/17 | 8824 | systems/win32/miktex/tm/packages/next/miktex-md5-bin-x64-2.9.tar.lzma -2022/08/17 | 209137 | systems/win32/miktex/tm/packages/next/miktex-metafont-bin-x64-2.9.tar.lzma -2022/08/17 | 286684 | systems/win32/miktex/tm/packages/next/miktex-metapost-bin-x64-2.9.tar.lzma -2022/08/17 | 104921 | systems/win32/miktex/tm/packages/next/miktex-mfware-bin-x64-2.9.tar.lzma -2022/08/17 | 140012 | systems/win32/miktex/tm/packages/next/miktex-mktex-bin-x64-2.9.tar.lzma -2022/08/17 | 325483 | systems/win32/miktex/tm/packages/next/miktex-mo-bin-x64-2.9.tar.lzma -2022/08/17 | 181723 | systems/win32/miktex/tm/packages/next/miktex-mpfr-bin-x64-2.9.tar.lzma -2022/08/17 | 55319 | systems/win32/miktex/tm/packages/next/miktex-mpmcli-bin-x64-2.9.tar.lzma -2022/08/17 | 35228 | systems/win32/miktex/tm/packages/next/miktex-mspack-bin-x64-2.9.tar.lzma -2022/08/17 | 43616 | systems/win32/miktex/tm/packages/next/miktex-mthelp-bin-x64-2.9.tar.lzma -2022/08/17 | 48037 | systems/win32/miktex/tm/packages/next/miktex-mtprint-bin-x64-2.9.tar.lzma -2022/08/17 | 52369 | systems/win32/miktex/tm/packages/next/miktex-m-tx-bin-x64-2.9.tar.lzma -2022/08/17 | 213846 | systems/win32/miktex/tm/packages/next/miktex-omegaware-bin-x64-2.9.tar.lzma -2022/08/17 | 41179 | systems/win32/miktex/tm/packages/next/miktex-patgen-bin-x64.tar.lzma -2022/08/17 | 824994 | systems/win32/miktex/tm/packages/next/miktex-pdftex-bin-x64-2.9.tar.lzma -2022/08/17 | 203418 | systems/win32/miktex/tm/packages/next/miktex-pixman-bin-x64-2.9.tar.lzma -2022/08/17 | 245151 | systems/win32/miktex/tm/packages/next/miktex-pmx-bin-x64-2.9.tar.lzma -2022/08/17 | 88483 | systems/win32/miktex/tm/packages/next/miktex-png-bin-x64-2.9.tar.lzma -2022/08/17 | 1323744 | systems/win32/miktex/tm/packages/next/miktex-poppler-bin-x64-2.9.tar.lzma -2022/08/17 | 23949 | systems/win32/miktex/tm/packages/next/miktex-popt-bin-x64-2.9.tar.lzma -2022/08/17 | 37507 | systems/win32/miktex/tm/packages/next/miktex-posix-bin-x64-2.9.tar.lzma -2022/08/17 | 72978 | systems/win32/miktex/tm/packages/next/miktex-ps2pk-bin-x64-2.9.tar.lzma -2022/08/17 | 58633 | systems/win32/miktex/tm/packages/next/miktex-psutils-bin-x64-2.9.tar.lzma -2022/08/17 | 769650 | systems/win32/miktex/tm/packages/next/miktex-ptex-bin-x64.tar.lzma -2022/08/17 | 1503052 | systems/win32/miktex/tm/packages/next/miktex-runtime-bin-x64-2.9.tar.lzma -2022/08/17 | 52627 | systems/win32/miktex/tm/packages/next/miktex-synctex-bin-x64-2.9.tar.lzma -2022/08/17 | 63801 | systems/win32/miktex/tm/packages/next/miktex-tdsutil-bin-x64.tar.lzma -2022/08/17 | 27464 | systems/win32/miktex/tm/packages/next/miktex-teckit-bin-x64-2.9.tar.lzma -2022/08/17 | 18510 | systems/win32/miktex/tm/packages/next/miktex-tex2xindy-bin-x64-2.9.tar.lzma -2022/08/17 | 70939 | systems/win32/miktex/tm/packages/next/miktex-tex4ht-bin-x64-2.9.tar.lzma -2022/08/17 | 173177 | systems/win32/miktex/tm/packages/next/miktex-tex-bin-x64-2.9.tar.lzma -2022/08/17 | 68146 | systems/win32/miktex/tm/packages/next/miktex-texify-bin-x64-2.9.tar.lzma -2022/08/17 | 107436 | systems/win32/miktex/tm/packages/next/miktex-texware-bin-x64-2.9.tar.lzma -2022/08/17 | 2821670 | systems/win32/miktex/tm/packages/next/miktex-texworks-bin-x64-2.9.tar.lzma -2022/08/17 | 62359 | systems/win32/miktex/tm/packages/next/miktex-ttf2pk2-bin-x64-2.9.tar.lzma -2022/08/17 | 41189 | systems/win32/miktex/tm/packages/next/miktex-upmendex-bin-x64.tar.lzma -2022/08/17 | 33861 | systems/win32/miktex/tm/packages/next/miktex-uriparser-bin-x64-2.9.tar.lzma -2022/08/17 | 73684 | systems/win32/miktex/tm/packages/next/miktex-web-bin-x64-2.9.tar.lzma -2022/08/17 | 352464 | systems/win32/miktex/tm/packages/next/miktex-xetex-bin-x64-2.9.tar.lzma -2022/08/17 | 57501 | systems/win32/miktex/tm/packages/next/miktex-xml2pmx-bin-x64.tar.lzma -2022/08/17 | 630433 | systems/win32/miktex/tm/packages/next/miktex-yap-bin-x64-2.9.tar.lzma -2022/08/17 | 43527 | systems/win32/miktex/tm/packages/next/miktex-zlib-bin-x64-2.9.tar.lzma -2022/08/17 | 289497 | systems/win32/miktex/tm/packages/next/miktex-zzdb1-2.9.tar.lzma -2022/08/17 | 1481405 | systems/win32/miktex/tm/packages/next/miktex-zzdb2-2.9.tar.lzma -2022/08/17 | 1364461 | systems/win32/miktex/tm/packages/next/miktex-zzdb3-2.9.tar.lzma -2022/08/17 | 14433 | systems/win32/miktex/tm/packages/next/miktex-zzip-bin-x64-2.9.tar.lzma +2022/08/18 | 659852 | systems/win32/miktex/tm/packages/next/files.csv.lzma +2022/08/18 | 57316 | systems/win32/miktex/tm/packages/next/miktex-arctrl-bin-x64-2.9.tar.lzma +2022/08/18 | 1161753 | systems/win32/miktex/tm/packages/next/miktex-asymptote-bin-x64-2.9.tar.lzma +2022/08/18 | 31587 | systems/win32/miktex/tm/packages/next/miktex-autosp-bin-x64-2.9.tar.lzma +2022/08/18 | 35264 | systems/win32/miktex/tm/packages/next/miktex-axohelp-bin-x64-2.9.tar.lzma +2022/08/18 | 65131 | systems/win32/miktex/tm/packages/next/miktex-bibarts-bin-x64-2.9.tar.lzma +2022/08/18 | 95468 | systems/win32/miktex/tm/packages/next/miktex-bibtex8bit-bin-x64-2.9.tar.lzma +2022/08/18 | 77211 | systems/win32/miktex/tm/packages/next/miktex-bibtex-bin-x64-2.9.tar.lzma +2022/08/18 | 31563 | systems/win32/miktex/tm/packages/next/miktex-bzip2-bin-x64-2.9.tar.lzma +2022/08/18 | 394143 | systems/win32/miktex/tm/packages/next/miktex-cairo-bin-x64-2.9.tar.lzma +2022/08/18 | 37051 | systems/win32/miktex/tm/packages/next/miktex-chktex-bin-x64-2.9.tar.lzma +2022/08/18 | 57503 | systems/win32/miktex/tm/packages/next/miktex-cjkutils-bin-x64-2.9.tar.lzma +2022/08/18 | 270467 | systems/win32/miktex/tm/packages/next/miktex-console-bin-x64-2.9.tar.lzma +2022/08/18 | 196213 | systems/win32/miktex/tm/packages/next/miktex-curl-bin-x64-2.9.tar.lzma +2022/08/18 | 103246 | systems/win32/miktex/tm/packages/next/miktex-cweb-bin-x64-2.9.tar.lzma +2022/08/18 | 24207 | systems/win32/miktex/tm/packages/next/miktex-devnag-bin-x64-2.9.tar.lzma +2022/08/18 | 481893 | systems/win32/miktex/tm/packages/next/miktex-doc.tar.lzma +2022/08/18 | 52037 | systems/win32/miktex/tm/packages/next/miktex-dvicopy-bin-x64-2.9.tar.lzma +2022/08/18 | 325980 | systems/win32/miktex/tm/packages/next/miktex-dvipdfmx-bin-x64-2.9.tar.lzma +2022/08/18 | 45794 | systems/win32/miktex/tm/packages/next/miktex-dvipng-bin-x64-2.9.tar.lzma +2022/08/18 | 135465 | systems/win32/miktex/tm/packages/next/miktex-dvips-bin-x64-2.9.tar.lzma +2022/08/18 | 1458151 | systems/win32/miktex/tm/packages/next/miktex-dvisvgm-bin-x64-2.9.tar.lzma +2022/08/18 | 112980 | systems/win32/miktex/tm/packages/next/miktex-epstopdf-bin-x64-2.9.tar.lzma +2022/08/18 | 48852 | systems/win32/miktex/tm/packages/next/miktex-expat-bin-x64-2.9.tar.lzma +2022/08/18 | 28510 | systems/win32/miktex/tm/packages/next/miktex-findtexmf-bin-x64-2.9.tar.lzma +2022/08/18 | 63240 | systems/win32/miktex/tm/packages/next/miktex-fmt-bin-x64-2.9.tar.lzma +2022/08/18 | 155431 | systems/win32/miktex/tm/packages/next/miktex-fontconfig-bin-x64-2.9.tar.lzma +2022/08/18 | 79063 | systems/win32/miktex/tm/packages/next/miktex-fonts-bin-x64-2.9.tar.lzma +2022/08/18 | 81448 | systems/win32/miktex/tm/packages/next/miktex-freeglut-bin-x64-2.9.tar.lzma +2022/08/18 | 295944 | systems/win32/miktex/tm/packages/next/miktex-freetype2-bin-x64-2.9.tar.lzma +2022/08/18 | 25118 | systems/win32/miktex/tm/packages/next/miktex-fribidixetex-bin-x64-2.9.tar.lzma +2022/08/18 | 112878 | systems/win32/miktex/tm/packages/next/miktex-gd-bin-x64-2.9.tar.lzma +2022/08/18 | 73263 | systems/win32/miktex/tm/packages/next/miktex-graphite2-bin-x64-2.9.tar.lzma +2022/08/18 | 115580 | systems/win32/miktex/tm/packages/next/miktex-gregorio-bin-x64-2.9.tar.lzma +2022/08/18 | 43887 | systems/win32/miktex/tm/packages/next/miktex-gsf2pk-bin-x64-2.9.tar.lzma +2022/08/18 | 565082 | systems/win32/miktex/tm/packages/next/miktex-harfbuzz-bin-x64-2.9.tar.lzma +2022/08/18 | 247208 | systems/win32/miktex/tm/packages/next/miktex-hitex-bin-x64.tar.lzma +2022/08/18 | 169678 | systems/win32/miktex/tm/packages/next/miktex-hunspell-bin-x64-2.9.tar.lzma +2022/08/18 | 109651 | systems/win32/miktex/tm/packages/next/miktex-jpeg-bin-x64-2.9.tar.lzma +2022/08/18 | 18382 | systems/win32/miktex/tm/packages/next/miktex-kpathsea-bin-x64-2.9.tar.lzma +2022/08/18 | 30570 | systems/win32/miktex/tm/packages/next/miktex-lacheck-bin-x64-2.9.tar.lzma +2022/08/18 | 682214 | systems/win32/miktex/tm/packages/next/miktex-lcdf-typetools-bin-x64-2.9.tar.lzma +2022/08/18 | 599103 | systems/win32/miktex/tm/packages/next/miktex-libressl-bin-x64-2.9.tar.lzma +2022/08/18 | 527569 | systems/win32/miktex/tm/packages/next/miktex-log4cxx-bin-x64-2.9.tar.lzma +2022/08/18 | 103598 | systems/win32/miktex/tm/packages/next/miktex-lua53-bin-x64-2.9.tar.lzma +2022/08/18 | 2023132 | systems/win32/miktex/tm/packages/next/miktex-luatex-bin-x64-2.9.tar.lzma +2022/08/18 | 74099 | systems/win32/miktex/tm/packages/next/miktex-lzma-bin-x64-2.9.tar.lzma +2022/08/18 | 32073 | systems/win32/miktex/tm/packages/next/miktex-makeindex-bin-x64-2.9.tar.lzma +2022/08/18 | 8825 | systems/win32/miktex/tm/packages/next/miktex-md5-bin-x64-2.9.tar.lzma +2022/08/18 | 209139 | systems/win32/miktex/tm/packages/next/miktex-metafont-bin-x64-2.9.tar.lzma +2022/08/18 | 286685 | systems/win32/miktex/tm/packages/next/miktex-metapost-bin-x64-2.9.tar.lzma +2022/08/18 | 104920 | systems/win32/miktex/tm/packages/next/miktex-mfware-bin-x64-2.9.tar.lzma +2022/08/18 | 140012 | systems/win32/miktex/tm/packages/next/miktex-mktex-bin-x64-2.9.tar.lzma +2022/08/18 | 325483 | systems/win32/miktex/tm/packages/next/miktex-mo-bin-x64-2.9.tar.lzma +2022/08/18 | 181724 | systems/win32/miktex/tm/packages/next/miktex-mpfr-bin-x64-2.9.tar.lzma +2022/08/18 | 55320 | systems/win32/miktex/tm/packages/next/miktex-mpmcli-bin-x64-2.9.tar.lzma +2022/08/18 | 35231 | systems/win32/miktex/tm/packages/next/miktex-mspack-bin-x64-2.9.tar.lzma +2022/08/18 | 43618 | systems/win32/miktex/tm/packages/next/miktex-mthelp-bin-x64-2.9.tar.lzma +2022/08/18 | 48038 | systems/win32/miktex/tm/packages/next/miktex-mtprint-bin-x64-2.9.tar.lzma +2022/08/18 | 52369 | systems/win32/miktex/tm/packages/next/miktex-m-tx-bin-x64-2.9.tar.lzma +2022/08/18 | 213847 | systems/win32/miktex/tm/packages/next/miktex-omegaware-bin-x64-2.9.tar.lzma +2022/08/18 | 41179 | systems/win32/miktex/tm/packages/next/miktex-patgen-bin-x64.tar.lzma +2022/08/18 | 824995 | systems/win32/miktex/tm/packages/next/miktex-pdftex-bin-x64-2.9.tar.lzma +2022/08/18 | 203420 | systems/win32/miktex/tm/packages/next/miktex-pixman-bin-x64-2.9.tar.lzma +2022/08/18 | 245151 | systems/win32/miktex/tm/packages/next/miktex-pmx-bin-x64-2.9.tar.lzma +2022/08/18 | 88483 | systems/win32/miktex/tm/packages/next/miktex-png-bin-x64-2.9.tar.lzma +2022/08/18 | 1323744 | systems/win32/miktex/tm/packages/next/miktex-poppler-bin-x64-2.9.tar.lzma +2022/08/18 | 23948 | systems/win32/miktex/tm/packages/next/miktex-popt-bin-x64-2.9.tar.lzma +2022/08/18 | 37506 | systems/win32/miktex/tm/packages/next/miktex-posix-bin-x64-2.9.tar.lzma +2022/08/18 | 72978 | systems/win32/miktex/tm/packages/next/miktex-ps2pk-bin-x64-2.9.tar.lzma +2022/08/18 | 58634 | systems/win32/miktex/tm/packages/next/miktex-psutils-bin-x64-2.9.tar.lzma +2022/08/18 | 769652 | systems/win32/miktex/tm/packages/next/miktex-ptex-bin-x64.tar.lzma +2022/08/18 | 1503053 | systems/win32/miktex/tm/packages/next/miktex-runtime-bin-x64-2.9.tar.lzma +2022/08/18 | 52628 | systems/win32/miktex/tm/packages/next/miktex-synctex-bin-x64-2.9.tar.lzma +2022/08/18 | 63803 | systems/win32/miktex/tm/packages/next/miktex-tdsutil-bin-x64.tar.lzma +2022/08/18 | 27465 | systems/win32/miktex/tm/packages/next/miktex-teckit-bin-x64-2.9.tar.lzma +2022/08/18 | 18511 | systems/win32/miktex/tm/packages/next/miktex-tex2xindy-bin-x64-2.9.tar.lzma +2022/08/18 | 70939 | systems/win32/miktex/tm/packages/next/miktex-tex4ht-bin-x64-2.9.tar.lzma +2022/08/18 | 173177 | systems/win32/miktex/tm/packages/next/miktex-tex-bin-x64-2.9.tar.lzma +2022/08/18 | 68147 | systems/win32/miktex/tm/packages/next/miktex-texify-bin-x64-2.9.tar.lzma +2022/08/18 | 107437 | systems/win32/miktex/tm/packages/next/miktex-texware-bin-x64-2.9.tar.lzma +2022/08/18 | 2821671 | systems/win32/miktex/tm/packages/next/miktex-texworks-bin-x64-2.9.tar.lzma +2022/08/18 | 62359 | systems/win32/miktex/tm/packages/next/miktex-ttf2pk2-bin-x64-2.9.tar.lzma +2022/08/18 | 41190 | systems/win32/miktex/tm/packages/next/miktex-upmendex-bin-x64.tar.lzma +2022/08/18 | 33862 | systems/win32/miktex/tm/packages/next/miktex-uriparser-bin-x64-2.9.tar.lzma +2022/08/18 | 73685 | systems/win32/miktex/tm/packages/next/miktex-web-bin-x64-2.9.tar.lzma +2022/08/18 | 352464 | systems/win32/miktex/tm/packages/next/miktex-xetex-bin-x64-2.9.tar.lzma +2022/08/18 | 57501 | systems/win32/miktex/tm/packages/next/miktex-xml2pmx-bin-x64.tar.lzma +2022/08/18 | 630436 | systems/win32/miktex/tm/packages/next/miktex-yap-bin-x64-2.9.tar.lzma +2022/08/18 | 43527 | systems/win32/miktex/tm/packages/next/miktex-zlib-bin-x64-2.9.tar.lzma +2022/08/18 | 289517 | systems/win32/miktex/tm/packages/next/miktex-zzdb1-2.9.tar.lzma +2022/08/18 | 1480825 | systems/win32/miktex/tm/packages/next/miktex-zzdb2-2.9.tar.lzma +2022/08/18 | 1364365 | systems/win32/miktex/tm/packages/next/miktex-zzdb3-2.9.tar.lzma +2022/08/18 | 14433 | systems/win32/miktex/tm/packages/next/miktex-zzip-bin-x64-2.9.tar.lzma 2019/03/12 | 1412 | systems/win32/miktex/tm/packages/nextpage.tar.lzma -2022/08/17 | 1172 | systems/win32/miktex/tm/packages/next/pr.ini +2022/08/18 | 1172 | systems/win32/miktex/tm/packages/next/pr.ini 2018/07/06 | 145915 | systems/win32/miktex/tm/packages/nexus-otf.tar.lzma 2017/03/30 | 191149 | systems/win32/miktex/tm/packages/nfssext-cfr.tar.lzma 2012/12/20 | 612251 | systems/win32/miktex/tm/packages/nicefilelist.tar.lzma @@ -301590,7 +301599,7 @@ 2022/02/22 | 6917 | systems/win32/miktex/tm/packages/preview.tar.lzma 2019/06/20 | 375963 | systems/win32/miktex/tm/packages/prftree.tar.lzma 2021/04/23 | 274028 | systems/win32/miktex/tm/packages/principia.tar.lzma -2022/08/17 | 933 | systems/win32/miktex/tm/packages/pr.ini +2022/08/18 | 933 | systems/win32/miktex/tm/packages/pr.ini 2010/09/27 | 248469 | systems/win32/miktex/tm/packages/printlen.tar.lzma 2008/06/17 | 77313 | systems/win32/miktex/tm/packages/proba.tar.lzma 2017/07/12 | 988486 | systems/win32/miktex/tm/packages/probsoln.tar.lzma @@ -303529,7 +303538,7 @@ 2004/06/04 | 404 | tds/tds.sed 2004/06/23 | 65418 | tds/tds.tex 2019/05/29 | 304264 | tds.zip -2022/08/18 | 186 | timestamp +2022/08/19 | 186 | timestamp 2002/08/26 | 61898 | usergrps/dante/antrag.pdf 2002/08/26 | 118217 | usergrps/dante/antrag.ps 2022/02/28 | 917 | usergrps/dante/dtk/doc/beispiel.bib diff --git a/FILES.byname.gz b/FILES.byname.gz Binary files differindex 712b8678b3..39453ea6d4 100644 --- a/FILES.byname.gz +++ b/FILES.byname.gz diff --git a/FILES.last07days b/FILES.last07days index 26cc067371..9d4a18f0ba 100644 --- a/FILES.last07days +++ b/FILES.last07days @@ -1,3 +1,240 @@ +2022/08/19 | 904 | biblio/citation-style-language/citeproc-node-group.lua +2022/08/19 | 8425 | biblio/citation-style-language/citeproc-context.lua +2022/08/19 | 8128 | biblio/citation-style-language/elsevier-harvard.csl +2022/08/19 | 8052 | biblio/citation-style-language/american-political-science-association.csl +2022/08/19 | 7685 | biblio/citation-style-language/citeproc-latex-core.lua +2022/08/19 | 7308 | biblio/citation-style-language/citeproc-node-choose.lua +2022/08/19 | 69907 | biblio/citation-style-language/apa.csl +2022/08/19 | 6283 | biblio/citation-style-language/citeproc-node-sort.lua +2022/08/19 | 61972 | biblio/citation-style-language/citeproc-engine.lua +2022/08/19 | 617 | biblio/citation-style-language/citeproc-lua.1 +2022/08/19 | 6100 | biblio/citation-style-language/citeproc-node-locale.lua +2022/08/19 | 580030 | install/biblio/citation-style-language.tds.zip +2022/08/19 | 5498 | biblio/citation-style-language/citeproc-node-text.lua +2022/08/19 | 5288 | biblio/citation-style-language/nature.csl +2022/08/19 | 4797 | biblio/citation-style-language/citeproc-cli.lua +2022/08/19 | 47520 | biblio/citation-style-language/chicago-fullnote-bibliography.csl +2022/08/19 | 45970 | biblio/citation-style-language/chicago-note-bibliography.csl +2022/08/19 | 44466 | biblio/citation-style-language/citeproc-output.lua +2022/08/19 | 411 | biblio/citation-style-language/citeproc.lua +2022/08/19 | 40700 | biblio/citation-style-language/citeproc-bib-data.lua +2022/08/19 | 3696 | biblio/citation-style-language/citeproc-latex.lua +2022/08/19 | 33702 | biblio/citation-style-language/citeproc-node-names.lua +2022/08/19 | 31273 | biblio/citation-style-language/citation-style-language.sty +2022/08/19 | 2993 | biblio/citation-style-language/citeproc-ir-node.lua +2022/08/19 | 2655 | biblio/citation-style-language/citeproc-node-label.lua +2022/08/19 | 25715 | biblio/citation-style-language/csl-locales-ru-RU.xml +2022/08/19 | 24466 | biblio/citation-style-language/csl-locales-bg-BG.xml +2022/08/19 | 24345 | biblio/citation-style-language/csl-locales-hi-IN.xml +2022/08/19 | 240 | biblio/citation-style-language/citeproc-lua.lua +2022/08/19 | 23553 | biblio/citation-style-language/csl-locales-lv-LV.xml +2022/08/19 | 23467 | biblio/citation-style-language/csl-locales-th-TH.xml +2022/08/19 | 23360 | biblio/citation-style-language/csl-locales-it-IT.xml +2022/08/19 | 23079 | biblio/citation-style-language/chicago-author-date.csl +2022/08/19 | 23024 | biblio/citation-style-language/csl-locales-el-GR.xml +2022/08/19 | 22752 | biblio/citation-style-language/csl-locales-lt-LT.xml +2022/08/19 | 22627 | biblio/citation-style-language/csl-locales-en-US.xml +2022/08/19 | 22542 | biblio/citation-style-language/csl-locales-pt-BR.xml +2022/08/19 | 22472 | biblio/citation-style-language/csl-locales-en-GB.xml +2022/08/19 | 22454 | biblio/citation-style-language/csl-locales-pt-PT.xml +2022/08/19 | 22434 | biblio/citation-style-language/csl-locales-es-MX.xml +2022/08/19 | 22358 | biblio/citation-style-language/csl-locales-nl-NL.xml +2022/08/19 | 22356 | biblio/citation-style-language/csl-locales-fr-FR.xml +2022/08/19 | 22337 | biblio/citation-style-language/csl-locales-fa-IR.xml +2022/08/19 | 22218 | biblio/citation-style-language/csl-locales-de-AT.xml +2022/08/19 | 22143 | biblio/citation-style-language/csl-locales-de-DE.xml +2022/08/19 | 22122 | biblio/citation-style-language/csl-locales-sr-RS.xml +2022/08/19 | 22098 | biblio/citation-style-language/csl-locales-fr-CA.xml +2022/08/19 | 220489 | biblio/citation-style-language/citation-style-language-doc.pdf +2022/08/19 | 21966 | biblio/citation-style-language/csl-locales-km-KH.xml +2022/08/19 | 21941 | biblio/citation-style-language/csl-locales-mn-MN.xml +2022/08/19 | 21822 | biblio/citation-style-language/csl-locales-he-IL.xml +2022/08/19 | 21812 | biblio/citation-style-language/csl-locales-vi-VN.xml +2022/08/19 | 21715 | biblio/citation-style-language/csl-locales-sv-SE.xml +2022/08/19 | 21681 | biblio/citation-style-language/csl-locales-de-CH.xml +2022/08/19 | 21654 | biblio/citation-style-language/csl-locales-id-ID.xml +2022/08/19 | 21635 | biblio/citation-style-language/csl-locales-tr-TR.xml +2022/08/19 | 21623 | biblio/citation-style-language/csl-locales-fi-FI.xml +2022/08/19 | 21579 | biblio/citation-style-language/csl-locales-cs-CZ.xml +2022/08/19 | 21576 | biblio/citation-style-language/csl-locales-cy-GB.xml +2022/08/19 | 21574 | biblio/citation-style-language/csl-locales-sk-SK.xml +2022/08/19 | 21517 | biblio/citation-style-language/citeproc-util.lua +2022/08/19 | 21512 | biblio/citation-style-language/csl-locales-eu.xml +2022/08/19 | 21482 | biblio/citation-style-language/csl-locales-ja-JP.xml +2022/08/19 | 21470 | biblio/citation-style-language/csl-locales-da-DK.xml +2022/08/19 | 21469 | biblio/citation-style-language/csl-locales-is-IS.xml +2022/08/19 | 21466 | biblio/citation-style-language/csl-locales-hu-HU.xml +2022/08/19 | 21462 | biblio/citation-style-language/csl-locales-ro-RO.xml +2022/08/19 | 2145 | biblio/citation-style-language/CHANGELOG.md +2022/08/19 | 21446 | biblio/citation-style-language/csl-locales-pl-PL.xml +2022/08/19 | 21433 | biblio/citation-style-language/csl-locales-af-ZA.xml +2022/08/19 | 21414 | biblio/citation-style-language/csl-locales-ko-KR.xml +2022/08/19 | 21406 | biblio/citation-style-language/csl-locales-es-CL.xml +2022/08/19 | 21363 | biblio/citation-style-language/csl-locales-hr-HR.xml +2022/08/19 | 21330 | biblio/citation-style-language/csl-locales-sl-SI.xml +2022/08/19 | 21327 | biblio/citation-style-language/csl-locales-es-ES.xml +2022/08/19 | 21323 | biblio/citation-style-language/csl-locales-nb-NO.xml +2022/08/19 | 21302 | biblio/citation-style-language/csl-locales-la.xml +2022/08/19 | 21302 | biblio/citation-style-language/csl-locales-ca-AD.xml +2022/08/19 | 21301 | biblio/citation-style-language/csl-locales-nn-NO.xml +2022/08/19 | 21261 | biblio/citation-style-language/csl-locales-et-EE.xml +2022/08/19 | 20747 | biblio/citation-style-language/csl-locales-uk-UA.xml +2022/08/19 | 19817 | biblio/citation-style-language/csl-locales-ar.xml +2022/08/19 | 196 | biblio/citation-style-language/DEPENDS.txt +2022/08/19 | 19423 | biblio/citation-style-language/csl-locales-zh-TW.xml +2022/08/19 | 19056 | biblio/citation-style-language/csl-locales-zh-CN.xml +2022/08/19 | 1702 | biblio/citation-style-language/citeproc-node-layout.lua +2022/08/19 | 1675 | biblio/citation-style-language/citeproc-node-number.lua +2022/08/19 | 1673 | biblio/citation-style-language/README.md +2022/08/19 | 16054 | biblio/citation-style-language/modern-humanities-research-association.csl +2022/08/19 | 15617 | biblio/citation-style-language/citeproc-node-style.lua +2022/08/19 | 15413 | biblio/citation-style-language/ieee.csl +2022/08/19 | 14833 | biblio/citation-style-language/citeproc-element.lua +2022/08/19 | 1476 | biblio/citation-style-language/citeproc-nodes.lua +2022/08/19 | 14024 | biblio/citation-style-language/citeproc-bib.lua +2022/08/19 | 13585 | biblio/citation-style-language/citeproc-node-date.lua +2022/08/19 | 13278 | biblio/citation-style-language/citation-style-language-doc.tex +2022/08/19 | 11958 | biblio/citation-style-language/vancouver.csl +2022/08/19 | 11209 | biblio/citation-style-language/modern-language-association.csl +2022/08/19 | 11060 | biblio/citation-style-language/american-sociological-association.csl +2022/08/19 | 11034 | biblio/citation-style-language/american-medical-association.csl +2022/08/19 | 10723 | biblio/citation-style-language/harvard-cite-them-right.csl +2022/08/19 | 10019 | biblio/citation-style-language/american-chemical-society.csl +2022/08/18 | 95468 | systems/win32/miktex/tm/packages/next/miktex-bibtex8bit-bin-x64-2.9.tar.lzma +2022/08/18 | 952684 | systems/texlive/tlnet/archive/tex4ht.r64138.tar.xz +2022/08/18 | 933 | systems/win32/miktex/tm/packages/pr.ini +2022/08/18 | 88483 | systems/win32/miktex/tm/packages/next/miktex-png-bin-x64-2.9.tar.lzma +2022/08/18 | 8825 | systems/win32/miktex/tm/packages/next/miktex-md5-bin-x64-2.9.tar.lzma +2022/08/18 | 824995 | systems/win32/miktex/tm/packages/next/miktex-pdftex-bin-x64-2.9.tar.lzma +2022/08/18 | 81448 | systems/win32/miktex/tm/packages/next/miktex-freeglut-bin-x64-2.9.tar.lzma +2022/08/18 | 813 | graphics/pgf/contrib/fancyqr/qr-example.tex +2022/08/18 | 792156 | systems/texlive/tlnet/archive/fithesis.r64135.tar.xz +2022/08/18 | 79063 | systems/win32/miktex/tm/packages/next/miktex-fonts-bin-x64-2.9.tar.lzma +2022/08/18 | 77211 | systems/win32/miktex/tm/packages/next/miktex-bibtex-bin-x64-2.9.tar.lzma +2022/08/18 | 769652 | systems/win32/miktex/tm/packages/next/miktex-ptex-bin-x64.tar.lzma +2022/08/18 | 74099 | systems/win32/miktex/tm/packages/next/miktex-lzma-bin-x64-2.9.tar.lzma +2022/08/18 | 73685 | systems/win32/miktex/tm/packages/next/miktex-web-bin-x64-2.9.tar.lzma +2022/08/18 | 73263 | systems/win32/miktex/tm/packages/next/miktex-graphite2-bin-x64-2.9.tar.lzma +2022/08/18 | 730120 | systems/texlive/tlnet/archive/fithesis.doc.r64135.tar.xz +2022/08/18 | 72978 | systems/win32/miktex/tm/packages/next/miktex-ps2pk-bin-x64-2.9.tar.lzma +2022/08/18 | 70939 | systems/win32/miktex/tm/packages/next/miktex-tex4ht-bin-x64-2.9.tar.lzma +2022/08/18 | 682214 | systems/win32/miktex/tm/packages/next/miktex-lcdf-typetools-bin-x64-2.9.tar.lzma +2022/08/18 | 68147 | systems/win32/miktex/tm/packages/next/miktex-texify-bin-x64-2.9.tar.lzma +2022/08/18 | 659852 | systems/win32/miktex/tm/packages/next/files.csv.lzma +2022/08/18 | 659342 | systems/win32/miktex/tm/packages/files.csv.lzma +2022/08/18 | 65131 | systems/win32/miktex/tm/packages/next/miktex-bibarts-bin-x64-2.9.tar.lzma +2022/08/18 | 64028 | systems/texlive/tlnet/archive/hereapplies.doc.r64136.tar.xz +2022/08/18 | 63803 | systems/win32/miktex/tm/packages/next/miktex-tdsutil-bin-x64.tar.lzma +2022/08/18 | 63240 | systems/win32/miktex/tm/packages/next/miktex-fmt-bin-x64-2.9.tar.lzma +2022/08/18 | 630436 | systems/win32/miktex/tm/packages/next/miktex-yap-bin-x64-2.9.tar.lzma +2022/08/18 | 62359 | systems/win32/miktex/tm/packages/next/miktex-ttf2pk2-bin-x64-2.9.tar.lzma +2022/08/18 | 599103 | systems/win32/miktex/tm/packages/next/miktex-libressl-bin-x64-2.9.tar.lzma +2022/08/18 | 58634 | systems/win32/miktex/tm/packages/next/miktex-psutils-bin-x64-2.9.tar.lzma +2022/08/18 | 5831895 | systems/texlive/tlnet/install-tl-unx.tar.gz +2022/08/18 | 577055 | biblio/citation-style-language.zip +2022/08/18 | 57503 | systems/win32/miktex/tm/packages/next/miktex-cjkutils-bin-x64-2.9.tar.lzma +2022/08/18 | 57501 | systems/win32/miktex/tm/packages/next/miktex-xml2pmx-bin-x64.tar.lzma +2022/08/18 | 57316 | systems/win32/miktex/tm/packages/next/miktex-arctrl-bin-x64-2.9.tar.lzma +2022/08/18 | 565082 | systems/win32/miktex/tm/packages/next/miktex-harfbuzz-bin-x64-2.9.tar.lzma +2022/08/18 | 55320 | systems/win32/miktex/tm/packages/next/miktex-mpmcli-bin-x64-2.9.tar.lzma +2022/08/18 | 527569 | systems/win32/miktex/tm/packages/next/miktex-log4cxx-bin-x64-2.9.tar.lzma +2022/08/18 | 52628 | systems/win32/miktex/tm/packages/next/miktex-synctex-bin-x64-2.9.tar.lzma +2022/08/18 | 524800 | systems/texlive/tlnet/archive/exam.doc.r64134.tar.xz +2022/08/18 | 52369 | systems/win32/miktex/tm/packages/next/miktex-m-tx-bin-x64-2.9.tar.lzma +2022/08/18 | 52037 | systems/win32/miktex/tm/packages/next/miktex-dvicopy-bin-x64-2.9.tar.lzma +2022/08/18 | 49900 | systems/texlive/tlnet/archive/exam.r64134.tar.xz +2022/08/18 | 48 | systems/texlive/tlnet/tlpkg/texlive.tlpdb.md5 +2022/08/18 | 48852 | systems/win32/miktex/tm/packages/next/miktex-expat-bin-x64-2.9.tar.lzma +2022/08/18 | 481893 | systems/win32/miktex/tm/packages/next/miktex-doc.tar.lzma +2022/08/18 | 48038 | systems/win32/miktex/tm/packages/next/miktex-mtprint-bin-x64-2.9.tar.lzma +2022/08/18 | 45794 | systems/win32/miktex/tm/packages/next/miktex-dvipng-bin-x64-2.9.tar.lzma +2022/08/18 | 455 | systems/texlive/tlnet/tlpkg/texlive.tlpdb.sha512.asc +2022/08/18 | 455 | systems/texlive/tlnet/install-tl.zip.sha512.asc +2022/08/18 | 455 | systems/texlive/tlnet/install-tl-windows.exe.sha512.asc +2022/08/18 | 455 | systems/texlive/tlnet/install-tl-unx.tar.gz.sha512.asc +2022/08/18 | 45332 | systems/texlive/tlnet/archive/fithesis.source.r64135.tar.xz +2022/08/18 | 4485 | graphics/pgf/contrib/fancyqr/fancyqr-doc.tex +2022/08/18 | 43887 | systems/win32/miktex/tm/packages/next/miktex-gsf2pk-bin-x64-2.9.tar.lzma +2022/08/18 | 43618 | systems/win32/miktex/tm/packages/next/miktex-mthelp-bin-x64-2.9.tar.lzma +2022/08/18 | 43527 | systems/win32/miktex/tm/packages/next/miktex-zlib-bin-x64-2.9.tar.lzma +2022/08/18 | 419376 | systems/texlive/tlnet/archive/texlive-scripts.doc.r64133.tar.xz +2022/08/18 | 41190 | systems/win32/miktex/tm/packages/next/miktex-upmendex-bin-x64.tar.lzma +2022/08/18 | 41179 | systems/win32/miktex/tm/packages/next/miktex-patgen-bin-x64.tar.lzma +2022/08/18 | 394143 | systems/win32/miktex/tm/packages/next/miktex-cairo-bin-x64-2.9.tar.lzma +2022/08/18 | 37506 | systems/win32/miktex/tm/packages/next/miktex-posix-bin-x64-2.9.tar.lzma +2022/08/18 | 3748 | systems/texlive/tlnet/archive/hereapplies.r64136.tar.xz +2022/08/18 | 37051 | systems/win32/miktex/tm/packages/next/miktex-chktex-bin-x64-2.9.tar.lzma +2022/08/18 | 3582 | graphics/pgf/contrib/fancyqr/README.md +2022/08/18 | 35264 | systems/win32/miktex/tm/packages/next/miktex-axohelp-bin-x64-2.9.tar.lzma +2022/08/18 | 352464 | systems/win32/miktex/tm/packages/next/miktex-xetex-bin-x64-2.9.tar.lzma +2022/08/18 | 35231 | systems/win32/miktex/tm/packages/next/miktex-mspack-bin-x64-2.9.tar.lzma +2022/08/18 | 33862 | systems/win32/miktex/tm/packages/next/miktex-uriparser-bin-x64-2.9.tar.lzma +2022/08/18 | 325980 | systems/win32/miktex/tm/packages/next/miktex-dvipdfmx-bin-x64-2.9.tar.lzma +2022/08/18 | 325483 | systems/win32/miktex/tm/packages/next/miktex-mo-bin-x64-2.9.tar.lzma +2022/08/18 | 32073 | systems/win32/miktex/tm/packages/next/miktex-makeindex-bin-x64-2.9.tar.lzma +2022/08/18 | 31587 | systems/win32/miktex/tm/packages/next/miktex-autosp-bin-x64-2.9.tar.lzma +2022/08/18 | 31563 | systems/win32/miktex/tm/packages/next/miktex-bzip2-bin-x64-2.9.tar.lzma +2022/08/18 | 30570 | systems/win32/miktex/tm/packages/next/miktex-lacheck-bin-x64-2.9.tar.lzma +2022/08/18 | 295944 | systems/win32/miktex/tm/packages/next/miktex-freetype2-bin-x64-2.9.tar.lzma +2022/08/18 | 289517 | systems/win32/miktex/tm/packages/next/miktex-zzdb1-2.9.tar.lzma +2022/08/18 | 289514 | systems/win32/miktex/tm/packages/miktex-zzdb1-2.9.tar.lzma +2022/08/18 | 286685 | systems/win32/miktex/tm/packages/next/miktex-metapost-bin-x64-2.9.tar.lzma +2022/08/18 | 28510 | systems/win32/miktex/tm/packages/next/miktex-findtexmf-bin-x64-2.9.tar.lzma +2022/08/18 | 2821671 | systems/win32/miktex/tm/packages/next/miktex-texworks-bin-x64-2.9.tar.lzma +2022/08/18 | 27465 | systems/win32/miktex/tm/packages/next/miktex-teckit-bin-x64-2.9.tar.lzma +2022/08/18 | 270467 | systems/win32/miktex/tm/packages/next/miktex-console-bin-x64-2.9.tar.lzma +2022/08/18 | 25516427 | systems/texlive/tlnet/install-tl.zip +2022/08/18 | 25118 | systems/win32/miktex/tm/packages/next/miktex-fribidixetex-bin-x64-2.9.tar.lzma +2022/08/18 | 251020 | graphics/pgf/contrib/fancyqr.zip +2022/08/18 | 248260 | graphics/pgf/contrib/fancyqr/fancyqr-doc.pdf +2022/08/18 | 247208 | systems/win32/miktex/tm/packages/next/miktex-hitex-bin-x64.tar.lzma +2022/08/18 | 245151 | systems/win32/miktex/tm/packages/next/miktex-pmx-bin-x64-2.9.tar.lzma +2022/08/18 | 24207 | systems/win32/miktex/tm/packages/next/miktex-devnag-bin-x64-2.9.tar.lzma +2022/08/18 | 2399360 | systems/texlive/tlnet/tlpkg/texlive.tlpdb.xz +2022/08/18 | 23948 | systems/win32/miktex/tm/packages/next/miktex-popt-bin-x64-2.9.tar.lzma +2022/08/18 | 213847 | systems/win32/miktex/tm/packages/next/miktex-omegaware-bin-x64-2.9.tar.lzma +2022/08/18 | 209139 | systems/win32/miktex/tm/packages/next/miktex-metafont-bin-x64-2.9.tar.lzma +2022/08/18 | 20433402 | systems/texlive/tlnet/install-tl-windows.exe +2022/08/18 | 203420 | systems/win32/miktex/tm/packages/next/miktex-pixman-bin-x64-2.9.tar.lzma +2022/08/18 | 2023132 | systems/win32/miktex/tm/packages/next/miktex-luatex-bin-x64-2.9.tar.lzma +2022/08/18 | 196213 | systems/win32/miktex/tm/packages/next/miktex-curl-bin-x64-2.9.tar.lzma +2022/08/18 | 18511 | systems/win32/miktex/tm/packages/next/miktex-tex2xindy-bin-x64-2.9.tar.lzma +2022/08/18 | 18382 | systems/win32/miktex/tm/packages/next/miktex-kpathsea-bin-x64-2.9.tar.lzma +2022/08/18 | 181724 | systems/win32/miktex/tm/packages/next/miktex-mpfr-bin-x64-2.9.tar.lzma +2022/08/18 | 17582691 | systems/texlive/tlnet/tlpkg/texlive.tlpdb +2022/08/18 | 173177 | systems/win32/miktex/tm/packages/next/miktex-tex-bin-x64-2.9.tar.lzma +2022/08/18 | 169678 | systems/win32/miktex/tm/packages/next/miktex-hunspell-bin-x64-2.9.tar.lzma +2022/08/18 | 155431 | systems/win32/miktex/tm/packages/next/miktex-fontconfig-bin-x64-2.9.tar.lzma +2022/08/18 | 153 | systems/texlive/tlnet/install-tl-windows.exe.sha512 +2022/08/18 | 152 | systems/texlive/tlnet/install-tl-unx.tar.gz.sha512 +2022/08/18 | 1503053 | systems/win32/miktex/tm/packages/next/miktex-runtime-bin-x64-2.9.tar.lzma +2022/08/18 | 1483018 | systems/win32/miktex/tm/packages/miktex-zzdb2-2.9.tar.lzma +2022/08/18 | 1480825 | systems/win32/miktex/tm/packages/next/miktex-zzdb2-2.9.tar.lzma +2022/08/18 | 145 | systems/texlive/tlnet/install-tl.zip.sha512 +2022/08/18 | 1458151 | systems/win32/miktex/tm/packages/next/miktex-dvisvgm-bin-x64-2.9.tar.lzma +2022/08/18 | 144 | systems/texlive/tlnet/tlpkg/texlive.tlpdb.sha512 +2022/08/18 | 14433 | systems/win32/miktex/tm/packages/next/miktex-zzip-bin-x64-2.9.tar.lzma +2022/08/18 | 140012 | systems/win32/miktex/tm/packages/next/miktex-mktex-bin-x64-2.9.tar.lzma +2022/08/18 | 1364956 | systems/win32/miktex/tm/packages/miktex-zzdb3-2.9.tar.lzma +2022/08/18 | 1364365 | systems/win32/miktex/tm/packages/next/miktex-zzdb3-2.9.tar.lzma +2022/08/18 | 136388 | systems/texlive/tlnet/archive/tex4ht.doc.r64138.tar.xz +2022/08/18 | 135465 | systems/win32/miktex/tm/packages/next/miktex-dvips-bin-x64-2.9.tar.lzma +2022/08/18 | 1323744 | systems/win32/miktex/tm/packages/next/miktex-poppler-bin-x64-2.9.tar.lzma +2022/08/18 | 1274892 | systems/texlive/tlnet/archive/tex4ht.source.r64138.tar.xz +2022/08/18 | 1211724 | systems/texlive/tlnet/archive/profcollege.r64137.tar.xz +2022/08/18 | 1172 | systems/win32/miktex/tm/packages/next/pr.ini +2022/08/18 | 1161753 | systems/win32/miktex/tm/packages/next/miktex-asymptote-bin-x64-2.9.tar.lzma +2022/08/18 | 115580 | systems/win32/miktex/tm/packages/next/miktex-gregorio-bin-x64-2.9.tar.lzma +2022/08/18 | 113500 | systems/texlive/tlnet/archive/texlive-scripts.r64133.tar.xz +2022/08/18 | 112980 | systems/win32/miktex/tm/packages/next/miktex-epstopdf-bin-x64-2.9.tar.lzma +2022/08/18 | 112878 | systems/win32/miktex/tm/packages/next/miktex-gd-bin-x64-2.9.tar.lzma +2022/08/18 | 109651 | systems/win32/miktex/tm/packages/next/miktex-jpeg-bin-x64-2.9.tar.lzma +2022/08/18 | 107437 | systems/win32/miktex/tm/packages/next/miktex-texware-bin-x64-2.9.tar.lzma +2022/08/18 | 104920 | systems/win32/miktex/tm/packages/next/miktex-mfware-bin-x64-2.9.tar.lzma +2022/08/18 | 103598 | systems/win32/miktex/tm/packages/next/miktex-lua53-bin-x64-2.9.tar.lzma +2022/08/18 | 103246 | systems/win32/miktex/tm/packages/next/miktex-cweb-bin-x64-2.9.tar.lzma +2022/08/18 | 10265 | graphics/pgf/contrib/fancyqr/fancyqr.sty +2022/08/18 | 10136040 | systems/texlive/tlnet/archive/profcollege.doc.r64137.tar.xz 2022/08/17 | 9955 | macros/latex/contrib/fithesis/logo/mu/fithesis-med-color.pdf 2022/08/17 | 9945 | macros/latex/contrib/fithesis/logo/mu/fithesis-fsps-czech-color.eps 2022/08/17 | 9931 | macros/latex/contrib/fithesis/logo/mu/fithesis-fsps-czech.eps @@ -6,13 +243,11 @@ 2022/08/17 | 9661 | macros/luatex/generic/luavlna/luavlna-doc.tex 2022/08/17 | 9654 | macros/latex/contrib/fithesis/logo/mu/fithesis-econ-czech.eps 2022/08/17 | 95 | macros/latex/contrib/fithesis/style/mu/pharm.ins -2022/08/17 | 95467 | systems/win32/miktex/tm/packages/next/miktex-bibtex8bit-bin-x64-2.9.tar.lzma 2022/08/17 | 9528 | macros/latex/contrib/fithesis/logo/mu/fithesis-fss-czech-color.eps 2022/08/17 | 9514 | macros/latex/contrib/fithesis/logo/mu/fithesis-fss-czech.eps 2022/08/17 | 93 | macros/latex/contrib/fithesis/style/mu/phil.ins 2022/08/17 | 93 | macros/latex/contrib/fithesis/style/mu/fsps.ins 2022/08/17 | 93 | macros/latex/contrib/fithesis/style/mu/econ.ins -2022/08/17 | 933 | systems/win32/miktex/tm/packages/pr.ini 2022/08/17 | 92320 | macros/luatex/generic/luavlna/luavlna-doc.pdf 2022/08/17 | 91 | macros/latex/contrib/fithesis/style/mu/sci.ins 2022/08/17 | 91 | macros/latex/contrib/fithesis/style/mu/ped.ins @@ -23,9 +258,7 @@ 2022/08/17 | 8995 | macros/latex/contrib/fithesis/logo/mu/fithesis-sci-czech-color.eps 2022/08/17 | 8981 | macros/latex/contrib/fithesis/logo/mu/fithesis-sci-czech.eps 2022/08/17 | 893 | macros/latex/contrib/fithesis/locale/english.ins -2022/08/17 | 88483 | systems/win32/miktex/tm/packages/next/miktex-png-bin-x64-2.9.tar.lzma 2022/08/17 | 88348 | macros/latex/contrib/fithesis/fithesis.dtx -2022/08/17 | 8824 | systems/win32/miktex/tm/packages/next/miktex-md5-bin-x64-2.9.tar.lzma 2022/08/17 | 8817716 | macros/latex/contrib/profcollege/doc/ProfCollege-doc.pdf 2022/08/17 | 87 | macros/latex/contrib/fithesis/style/base.ins 2022/08/17 | 8732 | macros/latex/contrib/fithesis/style/mu/med.dtx @@ -33,34 +266,24 @@ 2022/08/17 | 867213 | macros/latex/contrib/profcollege/latex/ProfCollege.sty 2022/08/17 | 855220 | systems/texlive/tlnet/archive/proflycee.doc.r64130.tar.xz 2022/08/17 | 845 | macros/latex/contrib/fithesis/locale/czech.ins -2022/08/17 | 824994 | systems/win32/miktex/tm/packages/next/miktex-pdftex-bin-x64-2.9.tar.lzma -2022/08/17 | 81448 | systems/win32/miktex/tm/packages/next/miktex-freeglut-bin-x64-2.9.tar.lzma +2022/08/17 | 8111 | support/TeX4ht/source/mktex4ht-cnf.tex 2022/08/17 | 8082 | macros/latex/contrib/fithesis/logo/mu/fithesis-ped-czech-color.eps 2022/08/17 | 8068 | macros/latex/contrib/fithesis/logo/mu/fithesis-ped-czech.eps -2022/08/17 | 79062 | systems/win32/miktex/tm/packages/next/miktex-fonts-bin-x64-2.9.tar.lzma 2022/08/17 | 7740 | macros/latex/contrib/fithesis/logo/mu/fithesis-pharm-czech-color.eps 2022/08/17 | 7726 | macros/latex/contrib/fithesis/logo/mu/fithesis-pharm-czech.eps -2022/08/17 | 77209 | systems/win32/miktex/tm/packages/next/miktex-bibtex-bin-x64-2.9.tar.lzma -2022/08/17 | 769650 | systems/win32/miktex/tm/packages/next/miktex-ptex-bin-x64.tar.lzma 2022/08/17 | 767427 | macros/latex/contrib/fithesis/fithesis.pdf 2022/08/17 | 7560 | systems/texlive/tlnet/archive/pygmentex.r64131.tar.xz 2022/08/17 | 74997 | macros/latex/contrib/fithesis/style/mu/base.dtx -2022/08/17 | 74099 | systems/win32/miktex/tm/packages/next/miktex-lzma-bin-x64-2.9.tar.lzma -2022/08/17 | 73684 | systems/win32/miktex/tm/packages/next/miktex-web-bin-x64-2.9.tar.lzma -2022/08/17 | 73262 | systems/win32/miktex/tm/packages/next/miktex-graphite2-bin-x64-2.9.tar.lzma -2022/08/17 | 72978 | systems/win32/miktex/tm/packages/next/miktex-ps2pk-bin-x64-2.9.tar.lzma 2022/08/17 | 7256 | macros/latex/contrib/fithesis/logo/mu/fithesis-base-czech.eps 2022/08/17 | 7245 | macros/latex/contrib/fithesis/logo/mu/fithesis-base-czech-color.eps +2022/08/17 | 7221 | systems/texlive/tlnet/tlpkg/installer/ctan-mirrors.pl 2022/08/17 | 7188 | macros/latex/contrib/fithesis/logo/mu/fithesis-phil-czech-color.eps 2022/08/17 | 7174 | macros/latex/contrib/fithesis/logo/mu/fithesis-phil-czech.eps 2022/08/17 | 715568 | systems/texlive/tlnet/archive/pygmentex.doc.r64131.tar.xz -2022/08/17 | 70939 | systems/win32/miktex/tm/packages/next/miktex-tex4ht-bin-x64-2.9.tar.lzma 2022/08/17 | 705 | macros/luatex/generic/luavlna/luavlna-predegrees.lua 2022/08/17 | 7015 | macros/latex/contrib/fithesis/style/mu/fsps.dtx 2022/08/17 | 6917 | macros/latex/contrib/fithesis/logo/mu/fithesis-base-english-color.eps 2022/08/17 | 6905 | macros/latex/contrib/fithesis/logo/mu/fithesis-base-english.eps -2022/08/17 | 682213 | systems/win32/miktex/tm/packages/next/miktex-lcdf-typetools-bin-x64-2.9.tar.lzma -2022/08/17 | 68146 | systems/win32/miktex/tm/packages/next/miktex-texify-bin-x64-2.9.tar.lzma 2022/08/17 | 6778 | macros/latex/contrib/fithesis/logo/mu/fithesis-fi-czech-color.eps 2022/08/17 | 6765 | macros/latex/contrib/fithesis/logo/mu/fithesis-law-czech-color.eps 2022/08/17 | 6764 | macros/latex/contrib/fithesis/logo/mu/fithesis-fi-czech.eps @@ -69,39 +292,17 @@ 2022/08/17 | 6734 | macros/latex/contrib/fithesis/logo/mu/fithesis-med-czech-color.eps 2022/08/17 | 6720 | macros/latex/contrib/fithesis/logo/mu/fithesis-med-czech.eps 2022/08/17 | 662 | macros/latex/contrib/fithesis/style/base.dtx -2022/08/17 | 659852 | systems/win32/miktex/tm/packages/next/files.csv.lzma -2022/08/17 | 659342 | systems/win32/miktex/tm/packages/files.csv.lzma -2022/08/17 | 65130 | systems/win32/miktex/tm/packages/next/miktex-bibarts-bin-x64-2.9.tar.lzma -2022/08/17 | 63801 | systems/win32/miktex/tm/packages/next/miktex-tdsutil-bin-x64.tar.lzma 2022/08/17 | 6364 | macros/latex/contrib/fithesis/style/mu/law.dtx -2022/08/17 | 63239 | systems/win32/miktex/tm/packages/next/miktex-fmt-bin-x64-2.9.tar.lzma 2022/08/17 | 63156 | macros/latex/contrib/fithesis/logo/mu/fithesis-sci.eps -2022/08/17 | 630433 | systems/win32/miktex/tm/packages/next/miktex-yap-bin-x64-2.9.tar.lzma -2022/08/17 | 62359 | systems/win32/miktex/tm/packages/next/miktex-ttf2pk2-bin-x64-2.9.tar.lzma -2022/08/17 | 599105 | systems/win32/miktex/tm/packages/next/miktex-libressl-bin-x64-2.9.tar.lzma +2022/08/17 | 617532 | support/TeX4ht/source/tex4ht-html4.tex 2022/08/17 | 595510 | macros/latex/contrib/fithesis/logo/mu/fithesis-base.eps 2022/08/17 | 588830 | macros/latex/contrib/exam.zip -2022/08/17 | 58633 | systems/win32/miktex/tm/packages/next/miktex-psutils-bin-x64-2.9.tar.lzma -2022/08/17 | 5831896 | systems/texlive/tlnet/install-tl-unx.tar.gz -2022/08/17 | 57505 | systems/win32/miktex/tm/packages/next/miktex-cjkutils-bin-x64-2.9.tar.lzma -2022/08/17 | 57501 | systems/win32/miktex/tm/packages/next/miktex-xml2pmx-bin-x64.tar.lzma -2022/08/17 | 57317 | systems/win32/miktex/tm/packages/next/miktex-arctrl-bin-x64-2.9.tar.lzma 2022/08/17 | 569182 | macros/latex/contrib/fithesis/logo/mu/fithesis-fss.eps -2022/08/17 | 565081 | systems/win32/miktex/tm/packages/next/miktex-harfbuzz-bin-x64-2.9.tar.lzma -2022/08/17 | 55319 | systems/win32/miktex/tm/packages/next/miktex-mpmcli-bin-x64-2.9.tar.lzma 2022/08/17 | 53503 | macros/latex/contrib/fithesis/logo/mu/fithesis-sci-color.eps -2022/08/17 | 527570 | systems/win32/miktex/tm/packages/next/miktex-log4cxx-bin-x64-2.9.tar.lzma -2022/08/17 | 52627 | systems/win32/miktex/tm/packages/next/miktex-synctex-bin-x64-2.9.tar.lzma -2022/08/17 | 52369 | systems/win32/miktex/tm/packages/next/miktex-m-tx-bin-x64-2.9.tar.lzma 2022/08/17 | 5215 | macros/latex/contrib/fithesis/logo/mu/fithesis-fsps-english-color.eps -2022/08/17 | 52037 | systems/win32/miktex/tm/packages/next/miktex-dvicopy-bin-x64-2.9.tar.lzma 2022/08/17 | 5201 | macros/latex/contrib/fithesis/logo/mu/fithesis-fsps-english.eps 2022/08/17 | 5106 | macros/latex/contrib/fithesis/style/mu/phil.dtx -2022/08/17 | 48 | systems/texlive/tlnet/tlpkg/texlive.tlpdb.md5 -2022/08/17 | 48851 | systems/win32/miktex/tm/packages/next/miktex-expat-bin-x64-2.9.tar.lzma 2022/08/17 | 485896 | systems/texlive/tlnet/archive/lt3luabridge.doc.r64128.tar.xz -2022/08/17 | 481892 | systems/win32/miktex/tm/packages/next/miktex-doc.tar.lzma -2022/08/17 | 48037 | systems/win32/miktex/tm/packages/next/miktex-mtprint-bin-x64-2.9.tar.lzma 2022/08/17 | 4793 | macros/latex/contrib/fithesis/logo/mu/fithesis-fss-english-color.eps 2022/08/17 | 4779 | macros/latex/contrib/fithesis/logo/mu/fithesis-fss-english.eps 2022/08/17 | 46 | macros/luatex/generic/luavlna/luavlna.4ht @@ -114,12 +315,7 @@ 2022/08/17 | 4600 | macros/latex/contrib/fithesis/logo/mu/fithesis-econ-czech.pdf 2022/08/17 | 45934 | macros/latex/contrib/fithesis/logo/mu/fithesis-law.eps 2022/08/17 | 4591 | macros/latex/contrib/fithesis/logo/mu/fithesis-sci-english-color.eps -2022/08/17 | 45793 | systems/win32/miktex/tm/packages/next/miktex-dvipng-bin-x64-2.9.tar.lzma 2022/08/17 | 4577 | macros/latex/contrib/fithesis/logo/mu/fithesis-sci-english.eps -2022/08/17 | 455 | systems/texlive/tlnet/tlpkg/texlive.tlpdb.sha512.asc -2022/08/17 | 455 | systems/texlive/tlnet/install-tl.zip.sha512.asc -2022/08/17 | 455 | systems/texlive/tlnet/install-tl-windows.exe.sha512.asc -2022/08/17 | 455 | systems/texlive/tlnet/install-tl-unx.tar.gz.sha512.asc 2022/08/17 | 4558 | macros/latex/contrib/fithesis/logo/mu/fithesis-pharm-english-color.eps 2022/08/17 | 4544 | macros/latex/contrib/fithesis/logo/mu/fithesis-pharm-english.eps 2022/08/17 | 4524 | macros/latex/contrib/fithesis/logo/mu/fithesis-econ-english-color.eps @@ -130,15 +326,9 @@ 2022/08/17 | 449 | macros/luatex/generic/luavlna/luavlna-csplain-langs.lua 2022/08/17 | 4398 | macros/latex/contrib/fithesis/logo/mu/fithesis-sci-czech-color.pdf 2022/08/17 | 4393 | macros/latex/contrib/fithesis/logo/mu/fithesis-sci-czech.pdf -2022/08/17 | 43888 | systems/win32/miktex/tm/packages/next/miktex-gsf2pk-bin-x64-2.9.tar.lzma -2022/08/17 | 43616 | systems/win32/miktex/tm/packages/next/miktex-mthelp-bin-x64-2.9.tar.lzma -2022/08/17 | 43527 | systems/win32/miktex/tm/packages/next/miktex-zlib-bin-x64-2.9.tar.lzma 2022/08/17 | 4289 | macros/luatex/generic/luavlna/luavlna.tex 2022/08/17 | 420604 | systems/texlive/tlnet/archive/msu-thesis.doc.r64129.tar.xz -2022/08/17 | 419496 | systems/texlive/tlnet/archive/texlive-scripts.doc.r64126.tar.xz 2022/08/17 | 4119 | macros/latex/contrib/fithesis/logo/mu/fithesis-ped-czech-color.pdf -2022/08/17 | 41189 | systems/win32/miktex/tm/packages/next/miktex-upmendex-bin-x64.tar.lzma -2022/08/17 | 41179 | systems/win32/miktex/tm/packages/next/miktex-patgen-bin-x64.tar.lzma 2022/08/17 | 4113 | macros/latex/contrib/fithesis/logo/mu/fithesis-ped-czech.pdf 2022/08/17 | 41114 | macros/latex/contrib/fithesis/logo/mu/fithesis-pharm-color.pdf 2022/08/17 | 41093 | macros/latex/contrib/fithesis/logo/mu/fithesis-pharm.pdf @@ -148,7 +338,6 @@ 2022/08/17 | 4002 | macros/latex/contrib/fithesis/logo/mu/fithesis-pharm-czech.pdf 2022/08/17 | 4000 | macros/latex/contrib/fithesis/logo/mu/fithesis-ped-english.eps 2022/08/17 | 3953 | macros/latex/contrib/fithesis/logo/mu/fithesis-med-english-color.eps -2022/08/17 | 394142 | systems/win32/miktex/tm/packages/next/miktex-cairo-bin-x64-2.9.tar.lzma 2022/08/17 | 3939 | macros/latex/contrib/fithesis/logo/mu/fithesis-med-english.eps 2022/08/17 | 3866 | macros/latex/contrib/fithesis/style/mu/ped.dtx 2022/08/17 | 38432 | macros/latex/contrib/fithesis/logo/mu/fithesis-law-color.eps @@ -163,28 +352,17 @@ 2022/08/17 | 3776 | macros/latex/contrib/fithesis/logo/mu/fithesis-med-czech.pdf 2022/08/17 | 3771 | macros/latex/contrib/fithesis/logo/mu/fithesis-base-english-color.pdf 2022/08/17 | 3767 | macros/latex/contrib/fithesis/logo/mu/fithesis-base-english.pdf -2022/08/17 | 37507 | systems/win32/miktex/tm/packages/next/miktex-posix-bin-x64-2.9.tar.lzma 2022/08/17 | 3742 | macros/latex/contrib/fithesis/logo/mu/fithesis-law-english-color.eps 2022/08/17 | 3728 | macros/latex/contrib/fithesis/logo/mu/fithesis-law-english.eps -2022/08/17 | 37050 | systems/win32/miktex/tm/packages/next/miktex-chktex-bin-x64-2.9.tar.lzma 2022/08/17 | 3702 | macros/latex/contrib/fithesis/logo/mu/fithesis-fi-czech-color.pdf 2022/08/17 | 3697 | macros/latex/contrib/fithesis/logo/mu/fithesis-fi-czech.pdf 2022/08/17 | 3631 | macros/latex/contrib/fithesis/README.md 2022/08/17 | 3611 | macros/latex/contrib/fithesis/logo/mu/fithesis-fi-english-color.eps 2022/08/17 | 3597 | macros/latex/contrib/fithesis/logo/mu/fithesis-fi-english.eps -2022/08/17 | 35264 | systems/win32/miktex/tm/packages/next/miktex-axohelp-bin-x64-2.9.tar.lzma -2022/08/17 | 352464 | systems/win32/miktex/tm/packages/next/miktex-xetex-bin-x64-2.9.tar.lzma -2022/08/17 | 35228 | systems/win32/miktex/tm/packages/next/miktex-mspack-bin-x64-2.9.tar.lzma -2022/08/17 | 33861 | systems/win32/miktex/tm/packages/next/miktex-uriparser-bin-x64-2.9.tar.lzma 2022/08/17 | 3320 | macros/luatex/generic/luavlna/README.md 2022/08/17 | 3307 | macros/latex/contrib/fithesis/logo/mu/fithesis-fsps-english-color.pdf 2022/08/17 | 3303 | macros/latex/contrib/fithesis/logo/mu/fithesis-fsps-english.pdf -2022/08/17 | 325978 | systems/win32/miktex/tm/packages/next/miktex-dvipdfmx-bin-x64-2.9.tar.lzma -2022/08/17 | 325483 | systems/win32/miktex/tm/packages/next/miktex-mo-bin-x64-2.9.tar.lzma -2022/08/17 | 32072 | systems/win32/miktex/tm/packages/next/miktex-makeindex-bin-x64-2.9.tar.lzma 2022/08/17 | 3189 | macros/latex/contrib/fithesis/style/mu/fss.dtx -2022/08/17 | 31585 | systems/win32/miktex/tm/packages/next/miktex-autosp-bin-x64-2.9.tar.lzma -2022/08/17 | 31561 | systems/win32/miktex/tm/packages/next/miktex-bzip2-bin-x64-2.9.tar.lzma 2022/08/17 | 31390 | macros/latex/contrib/fithesis/logo/mu/fithesis-fsps.eps 2022/08/17 | 3131 | macros/luatex/generic/luavlna/luavlna-langno.lua 2022/08/17 | 3128 | macros/latex/contrib/fithesis/logo/mu/fithesis-phil-english-color.pdf @@ -196,43 +374,27 @@ 2022/08/17 | 3069 | macros/latex/contrib/fithesis/logo/mu/fithesis-pharm-english.pdf 2022/08/17 | 3068 | macros/latex/contrib/fithesis/logo/mu/fithesis-sci-english-color.pdf 2022/08/17 | 3063 | macros/latex/contrib/fithesis/logo/mu/fithesis-sci-english.pdf -2022/08/17 | 30570 | systems/win32/miktex/tm/packages/next/miktex-lacheck-bin-x64-2.9.tar.lzma 2022/08/17 | 30559 | macros/latex/contrib/fithesis/logo/mu/fithesis-econ.eps 2022/08/17 | 3033 | macros/latex/contrib/fithesis/logo/mu/fithesis-econ-english-color.pdf 2022/08/17 | 3027 | macros/latex/contrib/fithesis/logo/mu/fithesis-econ-english.pdf 2022/08/17 | 29847 | macros/latex/contrib/fithesis/logo/mu/fithesis-fi-color.eps -2022/08/17 | 295943 | systems/win32/miktex/tm/packages/next/miktex-freetype2-bin-x64-2.9.tar.lzma 2022/08/17 | 2948 | systems/texlive/tlnet/archive/lt3luabridge.r64128.tar.xz 2022/08/17 | 29260 | macros/latex/contrib/fithesis/logo/mu/fithesis-fi.eps 2022/08/17 | 2902 | macros/latex/contrib/fithesis/logo/mu/fithesis-ped-english-color.pdf 2022/08/17 | 289 | macros/luatex/generic/luavlna/luavlna-si.lua -2022/08/17 | 289560 | systems/win32/miktex/tm/packages/miktex-zzdb1-2.9.tar.lzma 2022/08/17 | 2894 | macros/latex/contrib/fithesis/logo/mu/fithesis-ped-english.pdf -2022/08/17 | 289497 | systems/win32/miktex/tm/packages/next/miktex-zzdb1-2.9.tar.lzma 2022/08/17 | 286 | macros/latex/contrib/fithesis/style/mu/base.ins -2022/08/17 | 286684 | systems/win32/miktex/tm/packages/next/miktex-metapost-bin-x64-2.9.tar.lzma 2022/08/17 | 2852 | macros/latex/contrib/fithesis/logo/mu/fithesis-med-english-color.pdf -2022/08/17 | 28509 | systems/win32/miktex/tm/packages/next/miktex-findtexmf-bin-x64-2.9.tar.lzma 2022/08/17 | 2849 | macros/latex/contrib/fithesis/logo/mu/fithesis-med-english.pdf 2022/08/17 | 28441 | macros/latex/contrib/fithesis/logo/mu/fithesis-phil.eps -2022/08/17 | 2821670 | systems/win32/miktex/tm/packages/next/miktex-texworks-bin-x64-2.9.tar.lzma 2022/08/17 | 2808 | macros/latex/contrib/fithesis/logo/mu/fithesis-law-english-color.pdf 2022/08/17 | 2804 | macros/latex/contrib/fithesis/logo/mu/fithesis-law-english.pdf 2022/08/17 | 279 | macros/latex/contrib/fithesis/fithesis.ins -2022/08/17 | 27464 | systems/win32/miktex/tm/packages/next/miktex-teckit-bin-x64-2.9.tar.lzma 2022/08/17 | 2732 | macros/latex/contrib/fithesis/logo/mu/fithesis-fi-english-color.pdf 2022/08/17 | 2727 | macros/latex/contrib/fithesis/logo/mu/fithesis-fi-english.pdf -2022/08/17 | 270464 | systems/win32/miktex/tm/packages/next/miktex-console-bin-x64-2.9.tar.lzma -2022/08/17 | 25516446 | systems/texlive/tlnet/install-tl.zip 2022/08/17 | 25396 | macros/latex/contrib/fithesis/logo/mu/fithesis-sci.pdf 2022/08/17 | 25297 | macros/latex/contrib/fithesis/logo/mu/fithesis-econ-color.eps -2022/08/17 | 25118 | systems/win32/miktex/tm/packages/next/miktex-fribidixetex-bin-x64-2.9.tar.lzma -2022/08/17 | 247205 | systems/win32/miktex/tm/packages/next/miktex-hitex-bin-x64.tar.lzma -2022/08/17 | 245151 | systems/win32/miktex/tm/packages/next/miktex-pmx-bin-x64-2.9.tar.lzma 2022/08/17 | 24328 | macros/latex/contrib/fithesis/logo/mu/fithesis-sci-color.pdf -2022/08/17 | 24210 | systems/win32/miktex/tm/packages/next/miktex-devnag-bin-x64-2.9.tar.lzma -2022/08/17 | 2397600 | systems/texlive/tlnet/tlpkg/texlive.tlpdb.xz -2022/08/17 | 23949 | systems/win32/miktex/tm/packages/next/miktex-popt-bin-x64-2.9.tar.lzma 2022/08/17 | 23708 | macros/latex/contrib/fithesis/logo/mu/fithesis-phil-color.eps 2022/08/17 | 23539 | macros/latex/contrib/fithesis/logo/mu/fithesis-ped.eps 2022/08/17 | 23529 | macros/latex/contrib/fithesis/logo/mu/fithesis-med.eps @@ -240,76 +402,40 @@ 2022/08/17 | 2218015 | macros/latex/contrib/profcollege/doc/ProfCollege-doc.zip 2022/08/17 | 217 | macros/luatex/generic/luavlna/luavlna-presi.lua 2022/08/17 | 2175294 | install/macros/latex/contrib/fithesis.tds.zip -2022/08/17 | 213846 | systems/win32/miktex/tm/packages/next/miktex-omegaware-bin-x64-2.9.tar.lzma 2022/08/17 | 21247 | macros/latex/contrib/fithesis/logo/mu/fithesis-fss-color.eps -2022/08/17 | 209137 | systems/win32/miktex/tm/packages/next/miktex-metafont-bin-x64-2.9.tar.lzma 2022/08/17 | 2056051 | macros/latex/contrib/fithesis.zip 2022/08/17 | 204 | macros/luatex/generic/luavlna/luavlna-sufdegrees.lua -2022/08/17 | 20436545 | systems/texlive/tlnet/install-tl-windows.exe -2022/08/17 | 203418 | systems/win32/miktex/tm/packages/next/miktex-pixman-bin-x64-2.9.tar.lzma 2022/08/17 | 20324 | macros/latex/contrib/fithesis/locale/czech.dtx -2022/08/17 | 2023133 | systems/win32/miktex/tm/packages/next/miktex-luatex-bin-x64-2.9.tar.lzma 2022/08/17 | 20058 | macros/latex/contrib/fithesis/locale/slovak.dtx -2022/08/17 | 196212 | systems/win32/miktex/tm/packages/next/miktex-curl-bin-x64-2.9.tar.lzma +2022/08/17 | 200199 | support/TeX4ht/source/ChangeLog 2022/08/17 | 19569 | macros/latex/contrib/fithesis/logo/mu/fithesis-med-color.eps 2022/08/17 | 19363 | macros/latex/contrib/fithesis/logo/mu/fithesis-ped-color.eps -2022/08/17 | 18510 | systems/win32/miktex/tm/packages/next/miktex-tex2xindy-bin-x64-2.9.tar.lzma -2022/08/17 | 18382 | systems/win32/miktex/tm/packages/next/miktex-kpathsea-bin-x64-2.9.tar.lzma 2022/08/17 | 18339 | macros/latex/contrib/fithesis/logo/mu/fithesis-law.pdf -2022/08/17 | 181723 | systems/win32/miktex/tm/packages/next/miktex-mpfr-bin-x64-2.9.tar.lzma 2022/08/17 | 1760 | macros/latex/contrib/fithesis/LICENSE.tex -2022/08/17 | 17582689 | systems/texlive/tlnet/tlpkg/texlive.tlpdb 2022/08/17 | 17579 | macros/latex/contrib/fithesis/logo/mu/fithesis-law-color.pdf -2022/08/17 | 173177 | systems/win32/miktex/tm/packages/next/miktex-tex-bin-x64-2.9.tar.lzma -2022/08/17 | 169677 | systems/win32/miktex/tm/packages/next/miktex-hunspell-bin-x64-2.9.tar.lzma 2022/08/17 | 15892 | macros/latex/contrib/fithesis/logo/mu/fithesis-base.pdf -2022/08/17 | 155431 | systems/win32/miktex/tm/packages/next/miktex-fontconfig-bin-x64-2.9.tar.lzma -2022/08/17 | 153 | systems/texlive/tlnet/install-tl-windows.exe.sha512 -2022/08/17 | 152 | systems/texlive/tlnet/install-tl-unx.tar.gz.sha512 2022/08/17 | 15264 | macros/latex/contrib/fithesis/locale/english.dtx 2022/08/17 | 15062 | macros/latex/contrib/fithesis/logo/mu/fithesis-base-color.pdf -2022/08/17 | 1503052 | systems/win32/miktex/tm/packages/next/miktex-runtime-bin-x64-2.9.tar.lzma -2022/08/17 | 1482162 | systems/win32/miktex/tm/packages/miktex-zzdb2-2.9.tar.lzma -2022/08/17 | 1481405 | systems/win32/miktex/tm/packages/next/miktex-zzdb2-2.9.tar.lzma -2022/08/17 | 145 | systems/texlive/tlnet/install-tl.zip.sha512 2022/08/17 | 1459 | macros/luatex/generic/luavlna/luavlna.sty -2022/08/17 | 1458151 | systems/win32/miktex/tm/packages/next/miktex-dvisvgm-bin-x64-2.9.tar.lzma 2022/08/17 | 14512 | systems/texlive/tlnet/archive/proflycee.r64130.tar.xz -2022/08/17 | 144 | systems/texlive/tlnet/tlpkg/texlive.tlpdb.sha512 -2022/08/17 | 14433 | systems/win32/miktex/tm/packages/next/miktex-zzip-bin-x64-2.9.tar.lzma -2022/08/17 | 140012 | systems/win32/miktex/tm/packages/next/miktex-mktex-bin-x64-2.9.tar.lzma -2022/08/17 | 1364924 | systems/win32/miktex/tm/packages/miktex-zzdb3-2.9.tar.lzma -2022/08/17 | 1364461 | systems/win32/miktex/tm/packages/next/miktex-zzdb3-2.9.tar.lzma -2022/08/17 | 135465 | systems/win32/miktex/tm/packages/next/miktex-dvips-bin-x64-2.9.tar.lzma -2022/08/17 | 1323744 | systems/win32/miktex/tm/packages/next/miktex-poppler-bin-x64-2.9.tar.lzma 2022/08/17 | 13150370 | macros/latex/contrib/profcollege.zip 2022/08/17 | 12838 | macros/latex/contrib/fithesis/logo/mu/fithesis-econ.pdf 2022/08/17 | 12347 | macros/luatex/generic/luavlna/luavlna.lua 2022/08/17 | 12305 | macros/latex/contrib/fithesis/logo/mu/fithesis-econ-color.pdf 2022/08/17 | 12083 | macros/latex/contrib/fithesis/logo/mu/fithesis-phil.pdf 2022/08/17 | 12007 | macros/latex/contrib/fithesis/style/mu/econ.dtx -2022/08/17 | 1172 | systems/win32/miktex/tm/packages/next/pr.ini 2022/08/17 | 11709 | macros/latex/contrib/fithesis/logo/mu/fithesis-fi-color.pdf 2022/08/17 | 11634 | macros/latex/contrib/fithesis/logo/mu/fithesis-fsps.pdf -2022/08/17 | 1161751 | systems/win32/miktex/tm/packages/next/miktex-asymptote-bin-x64-2.9.tar.lzma 2022/08/17 | 11596 | macros/latex/contrib/fithesis/logo/mu/fithesis-phil-color.pdf -2022/08/17 | 115580 | systems/win32/miktex/tm/packages/next/miktex-gregorio-bin-x64-2.9.tar.lzma 2022/08/17 | 11529 | macros/latex/contrib/fithesis/logo/mu/fithesis-fi.pdf 2022/08/17 | 11492 | macros/latex/contrib/fithesis/logo/mu/fithesis-fss.pdf 2022/08/17 | 11356 | systems/texlive/tlnet/archive/msu-thesis.r64129.tar.xz -2022/08/17 | 113524 | systems/texlive/tlnet/archive/texlive-scripts.r64126.tar.xz -2022/08/17 | 112979 | systems/win32/miktex/tm/packages/next/miktex-epstopdf-bin-x64-2.9.tar.lzma -2022/08/17 | 112877 | systems/win32/miktex/tm/packages/next/miktex-gd-bin-x64-2.9.tar.lzma +2022/08/17 | 1128043 | support/TeX4ht/source/tex4ht-4ht.tex 2022/08/17 | 11199 | macros/latex/contrib/fithesis/logo/mu/fithesis-fsps-color.pdf -2022/08/17 | 109650 | systems/win32/miktex/tm/packages/next/miktex-jpeg-bin-x64-2.9.tar.lzma 2022/08/17 | 10758 | macros/latex/contrib/fithesis/logo/mu/fithesis-fss-color.pdf -2022/08/17 | 107436 | systems/win32/miktex/tm/packages/next/miktex-texware-bin-x64-2.9.tar.lzma 2022/08/17 | 10494 | macros/latex/contrib/fithesis/logo/mu/fithesis-med.pdf -2022/08/17 | 104921 | systems/win32/miktex/tm/packages/next/miktex-mfware-bin-x64-2.9.tar.lzma 2022/08/17 | 104682 | macros/luatex/generic/luavlna.zip 2022/08/17 | 10396 | macros/latex/contrib/fithesis/logo/mu/fithesis-ped.pdf -2022/08/17 | 103596 | systems/win32/miktex/tm/packages/next/miktex-lua53-bin-x64-2.9.tar.lzma -2022/08/17 | 103245 | systems/win32/miktex/tm/packages/next/miktex-cweb-bin-x64-2.9.tar.lzma 2022/08/17 | 101310 | macros/latex/contrib/fithesis/logo/mu/fithesis-pharm-color.eps 2022/08/17 | 101282 | macros/latex/contrib/fithesis/logo/mu/fithesis-pharm.eps 2022/08/16 | 9602 | graphics/pgf/contrib/tikz-ext/doc/tikz-ext-manual-en-library-misc.tex @@ -319,7 +445,6 @@ 2022/08/16 | 823 | graphics/pgf/contrib/tikz-ext/doc/tikz-ext-manual.tex 2022/08/16 | 784594 | macros/latex/contrib/pygmentex.zip 2022/08/16 | 773 | macros/latex/contrib/pygmentex/README -2022/08/16 | 7321 | systems/texlive/tlnet/tlpkg/installer/ctan-mirrors.pl 2022/08/16 | 7188 | macros/latex/contrib/msu-thesis/samples/MSU-thesis-template.tex 2022/08/16 | 69999 | macros/latex/contrib/hereapplies.zip 2022/08/16 | 689500 | systems/texlive/tlnet/archive/xduts.doc.r64124.tar.xz @@ -390,7 +515,6 @@ 2022/08/15 | 736 | macros/latex/contrib/proflycee/doc/perroquet.csv 2022/08/15 | 707491 | macros/xetex/latex/xduts/xduts.pdf 2022/08/15 | 69340 | macros/xetex/latex/exam-zh/tex/exam-zh.cls -2022/08/15 | 63056 | systems/texlive/tlnet/archive/hereapplies.doc.r64117.tar.xz 2022/08/15 | 62157 | macros/latex/contrib/proflycee/tex/ProfLycee.sty 2022/08/15 | 62108 | macros/latex/contrib/elegantbook/elegantbook-cn.tex 2022/08/15 | 5868 | graphics/pgf/contrib/tikz-ext/doc/tikz-ext-manual-en-library-paths.ortho.tex @@ -402,7 +526,6 @@ 2022/08/15 | 431480 | systems/texlive/tlnet/archive/armtex.doc.r64119.tar.xz 2022/08/15 | 38903 | macros/latex/contrib/elegantbook/elegantbook-en.tex 2022/08/15 | 32 | macros/latex/contrib/proflycee/doc/basique.csv -2022/08/15 | 3216 | systems/texlive/tlnet/archive/hereapplies.r64117.tar.xz 2022/08/15 | 3061 | macros/latex/contrib/elegantbook/README.md 2022/08/15 | 2947940 | macros/latex/contrib/elegantbook.zip 2022/08/15 | 2861 | macros/xetex/latex/xduts/README.md @@ -712,7 +835,6 @@ 2022/08/12 | 9861 | macros/latex/contrib/ucs/data/uni-148.def 2022/08/12 | 9831 | macros/latex/contrib/ucs/data/uni-30.def 2022/08/12 | 9571 | macros/latex/contrib/ucs/config/pifont.ucf -2022/08/12 | 952476 | systems/texlive/tlnet/archive/tex4ht.r64099.tar.xz 2022/08/12 | 9515 | macros/latex/contrib/ucs/data/uni-37.def 2022/08/12 | 9504 | macros/latex/contrib/ucs/config/math.ucf 2022/08/12 | 9412 | macros/latex/contrib/ucs/data/uni-250.def @@ -980,7 +1102,6 @@ 2022/08/12 | 13691 | macros/latex/contrib/ucs/data/uni-114.def 2022/08/12 | 13690 | macros/latex/contrib/ucs/data/uni-105.def 2022/08/12 | 13680 | macros/latex/contrib/ucs/data/uni-107.def -2022/08/12 | 136384 | systems/texlive/tlnet/archive/tex4ht.doc.r64099.tar.xz 2022/08/12 | 1353 | macros/latex/contrib/ucs/data/uni-182.def 2022/08/12 | 13517 | dviware/dvisvgm/tests/data/Makefile.in 2022/08/12 | 13472 | macros/latex/contrib/ucs/data/uni-97.def @@ -1002,7 +1123,6 @@ 2022/08/12 | 12804 | macros/latex/contrib/ucs/data/uni-142.def 2022/08/12 | 12764 | macros/latex/contrib/ucs/data/uni-249.def 2022/08/12 | 12752 | macros/latex/contrib/ucs/data/uni-141.def -2022/08/12 | 1272264 | systems/texlive/tlnet/archive/tex4ht.source.r64099.tar.xz 2022/08/12 | 12677 | macros/latex/contrib/ucs/data/uni-151.def 2022/08/12 | 12660 | macros/latex/contrib/ucs/data/uni-120.def 2022/08/12 | 12651 | macros/latex/contrib/ucs/data/uni-115.def @@ -1062,147 +1182,3 @@ 2022/08/12 | 10122 | macros/latex/contrib/ucs/data/uni-147.def 2022/08/12 | 10028 | macros/latex/contrib/ucs/data/uni-48.def 2022/08/12 | 10001 | macros/latex/contrib/ucs/data/uni-146.def -2022/08/11 | 97323 | macros/latex/contrib/fixdif/fixdif.pdf -2022/08/11 | 962390 | systems/win32/miktex/tm/packages/postnotes__doc.tar.lzma -2022/08/11 | 9021 | systems/win32/miktex/tm/packages/ptex2pdf__doc.tar.lzma -2022/08/11 | 90135 | systems/win32/miktex/tm/packages/xecjk__source.tar.lzma -2022/08/11 | 8933 | systems/win32/miktex/tm/packages/projlib__doc.tar.lzma -2022/08/11 | 890197 | systems/win32/miktex/tm/packages/l3backend__doc.tar.lzma -2022/08/11 | 84332 | macros/latex/contrib/create-theorem/create-theorem-doc.pdf -2022/08/11 | 83300 | systems/texlive/tlnet/archive/luatexja.source.r64092.tar.xz -2022/08/11 | 8252 | systems/win32/miktex/tm/packages/texlogsieve__source.tar.lzma -2022/08/11 | 81419 | systems/win32/miktex/tm/packages/proflycee__source.tar.lzma -2022/08/11 | 79649 | systems/win32/miktex/tm/packages/tagpdf__source.tar.lzma -2022/08/11 | 7936874 | systems/win32/miktex/tm/packages/profcollege__doc.tar.lzma -2022/08/11 | 787 | macros/latex/contrib/fixdif/README.md -2022/08/11 | 7751 | systems/win32/miktex/tm/packages/customdice__source.tar.lzma -2022/08/11 | 74250 | systems/win32/miktex/tm/packages/texlogsieve__doc.tar.lzma -2022/08/11 | 7408 | systems/texlive/tlnet/archive/customdice.source.r64089.tar.xz -2022/08/11 | 7343 | systems/win32/miktex/tm/packages/postnotes.tar.lzma -2022/08/11 | 728710 | systems/win32/miktex/tm/packages/bodeplot__doc.tar.lzma -2022/08/11 | 717703 | systems/win32/miktex/tm/packages/proflycee__doc.tar.lzma -2022/08/11 | 68258 | systems/win32/miktex/tm/packages/olsak-misc.tar.lzma -2022/08/11 | 676 | macros/latex/contrib/create-theorem/README.md -2022/08/11 | 66837 | macros/latex/contrib/runcode/troubleshoot.pdf -2022/08/11 | 6679 | systems/win32/miktex/tm/packages/ocgx2__doc.tar.lzma -2022/08/11 | 65091 | systems/win32/miktex/tm/packages/siunitx.tar.lzma -2022/08/11 | 6489 | systems/win32/miktex/tm/packages/tikz-relay.tar.lzma -2022/08/11 | 642560 | systems/win32/miktex/tm/packages/europecv__doc.tar.lzma -2022/08/11 | 63738 | systems/win32/miktex/tm/packages/njuthesis__source.tar.lzma -2022/08/11 | 622691 | systems/win32/miktex/tm/packages/colortbl__doc.tar.lzma -2022/08/11 | 610698 | systems/win32/miktex/tm/packages/tikz-relay__doc.tar.lzma -2022/08/11 | 6105 | systems/win32/miktex/tm/packages/unbtex.tar.lzma -2022/08/11 | 6080 | systems/win32/miktex/tm/packages/bookcover.tar.lzma -2022/08/11 | 590455 | systems/win32/miktex/tm/packages/l3kernel__source.tar.lzma -2022/08/11 | 5725 | systems/win32/miktex/tm/packages/bodeplot.tar.lzma -2022/08/11 | 56780 | macros/latex/contrib/runcode/runcode.pdf -2022/08/11 | 5478 | systems/win32/miktex/tm/packages/unbtex__source.tar.lzma -2022/08/11 | 53831 | systems/win32/miktex/tm/packages/yfonts-otf.tar.lzma -2022/08/11 | 534525 | systems/win32/miktex/tm/packages/lt3rawobjects__doc.tar.lzma -2022/08/11 | 5236 | systems/win32/miktex/tm/packages/lt3luabridge__source.tar.lzma -2022/08/11 | 5065 | systems/win32/miktex/tm/packages/ptex2pdf.tar.lzma -2022/08/11 | 5040 | systems/win32/miktex/tm/packages/sillypage__source.tar.lzma -2022/08/11 | 492218 | systems/win32/miktex/tm/packages/gentombow__doc.tar.lzma -2022/08/11 | 487082 | systems/win32/miktex/tm/packages/lt3luabridge__doc.tar.lzma -2022/08/11 | 4685 | systems/win32/miktex/tm/packages/xsavebox__source.tar.lzma -2022/08/11 | 4620 | systems/win32/miktex/tm/packages/yfonts-otf__source.tar.lzma -2022/08/11 | 45480 | systems/win32/miktex/tm/packages/texlogsieve.tar.lzma -2022/08/11 | 4398 | systems/win32/miktex/tm/packages/bhcexam.tar.lzma -2022/08/11 | 4380 | systems/win32/miktex/tm/packages/xsavebox.tar.lzma -2022/08/11 | 43809 | systems/win32/miktex/tm/packages/tuda-ci.tar.lzma -2022/08/11 | 4168 | systems/texlive/tlnet/archive/bhcexam.r64093.tar.xz -2022/08/11 | 3977562 | systems/win32/miktex/tm/packages/tudscr__doc.tar.lzma -2022/08/11 | 396799 | systems/win32/miktex/tm/packages/europecv__source.tar.lzma -2022/08/11 | 3945 | systems/win32/miktex/tm/packages/colortbl.tar.lzma -2022/08/11 | 379622 | systems/win32/miktex/tm/packages/xsavebox__doc.tar.lzma -2022/08/11 | 3788 | systems/win32/miktex/tm/packages/biblatex-software.tar.lzma -2022/08/11 | 3668 | systems/win32/miktex/tm/packages/lt3rawobjects.tar.lzma -2022/08/11 | 3666626 | systems/win32/miktex/tm/packages/media9__doc.tar.lzma -2022/08/11 | 361526 | systems/win32/miktex/tm/packages/customdice__doc.tar.lzma -2022/08/11 | 360976 | systems/texlive/tlnet/archive/customdice.doc.r64089.tar.xz -2022/08/11 | 359746 | systems/win32/miktex/tm/packages/bhcexam__doc.tar.lzma -2022/08/11 | 359312 | systems/texlive/tlnet/archive/bhcexam.doc.r64093.tar.xz -2022/08/11 | 3584 | systems/win32/miktex/tm/packages/nimsticks__source.tar.lzma -2022/08/11 | 3549 | systems/win32/miktex/tm/packages/zlmtt.tar.lzma -2022/08/11 | 34279 | macros/latex/contrib/create-theorem/create-theorem-doc.tex -2022/08/11 | 33280 | systems/win32/miktex/tm/packages/l3backend__source.tar.lzma -2022/08/11 | 325945 | systems/win32/miktex/tm/packages/tudscr__source.tar.lzma -2022/08/11 | 3254072 | systems/texlive/tlnet/archive/luatexja.doc.r64092.tar.xz -2022/08/11 | 3206 | systems/win32/miktex/tm/packages/zlmtt__source.tar.lzma -2022/08/11 | 3179 | macros/latex/contrib/fixdif/fixdif.ins -2022/08/11 | 3145071 | systems/win32/miktex/tm/packages/animate__doc.tar.lzma -2022/08/11 | 31275 | systems/win32/miktex/tm/packages/postnotes__source.tar.lzma -2022/08/11 | 3116019 | systems/win32/miktex/tm/packages/luatexja__doc.tar.lzma -2022/08/11 | 3078 | systems/win32/miktex/tm/packages/lt3luabridge.tar.lzma -2022/08/11 | 30566 | systems/win32/miktex/tm/packages/animate__source.tar.lzma -2022/08/11 | 305383 | systems/win32/miktex/tm/packages/biblatex-software__doc.tar.lzma -2022/08/11 | 292032 | systems/win32/miktex/tm/packages/sillypage__doc.tar.lzma -2022/08/11 | 2863 | systems/win32/miktex/tm/packages/simplebnf.tar.lzma -2022/08/11 | 2821 | systems/win32/miktex/tm/packages/customdice.tar.lzma -2022/08/11 | 28135 | systems/win32/miktex/tm/packages/tagpdf.tar.lzma -2022/08/11 | 268190 | macros/latex/contrib/fixdif.zip -2022/08/11 | 2632 | systems/texlive/tlnet/archive/simplebnf.r64091.tar.xz -2022/08/11 | 2616 | systems/texlive/tlnet/archive/customdice.r64089.tar.xz -2022/08/11 | 25812 | systems/win32/miktex/tm/packages/projlib__source.tar.lzma -2022/08/11 | 25649 | systems/win32/miktex/tm/packages/hfutthesis.tar.lzma -2022/08/11 | 25424 | systems/win32/miktex/tm/packages/projlib.tar.lzma -2022/08/11 | 24749 | systems/win32/miktex/tm/packages/uni-titlepage__source.tar.lzma -2022/08/11 | 24078 | systems/win32/miktex/tm/packages/animate.tar.lzma -2022/08/11 | 23446 | macros/latex/contrib/fixdif/fixdif.dtx -2022/08/11 | 233590 | systems/win32/miktex/tm/packages/zlmtt__doc.tar.lzma -2022/08/11 | 2257 | systems/win32/miktex/tm/packages/simplebnf__source.tar.lzma -2022/08/11 | 222030 | systems/win32/miktex/tm/packages/xecjk.tar.lzma -2022/08/11 | 220662 | systems/win32/miktex/tm/packages/luatexja__source.tar.lzma -2022/08/11 | 210366 | systems/win32/miktex/tm/packages/optex.tar.lzma -2022/08/11 | 2084919 | systems/win32/miktex/tm/packages/profcollege__source.tar.lzma -2022/08/11 | 2038852 | systems/win32/miktex/tm/packages/optex__doc.tar.lzma -2022/08/11 | 199643 | support/TeX4ht/source/ChangeLog -2022/08/11 | 1990 | systems/win32/miktex/tm/packages/nimsticks.tar.lzma -2022/08/11 | 19403 | systems/win32/miktex/tm/packages/njuthesis.tar.lzma -2022/08/11 | 191980 | systems/texlive/tlnet/archive/luatexja.r64092.tar.xz -2022/08/11 | 191633 | systems/win32/miktex/tm/packages/luatexja.tar.lzma -2022/08/11 | 19106 | macros/latex/contrib/create-theorem/LICENSE -2022/08/11 | 19103 | systems/win32/miktex/tm/packages/colortbl__source.tar.lzma -2022/08/11 | 1907971 | systems/win32/miktex/tm/packages/tagpdf__doc.tar.lzma -2022/08/11 | 1900612 | systems/win32/miktex/tm/packages/media9.tar.lzma -2022/08/11 | 18941 | macros/latex/contrib/runcode/troubleshoot.tex -2022/08/11 | 1837729 | systems/win32/miktex/tm/packages/uni-titlepage__doc.tar.lzma -2022/08/11 | 1785916 | systems/win32/miktex/tm/packages/bookcover__doc.tar.lzma -2022/08/11 | 1782167 | systems/win32/miktex/tm/packages/media9__source.tar.lzma -2022/08/11 | 17397 | systems/win32/miktex/tm/packages/ocgx2.tar.lzma -2022/08/11 | 172729 | systems/win32/miktex/tm/packages/l3kernel.tar.lzma -2022/08/11 | 17189 | systems/win32/miktex/tm/packages/bodeplot__source.tar.lzma -2022/08/11 | 17120 | systems/win32/miktex/tm/packages/tikz-relay__source.tar.lzma -2022/08/11 | 16822 | macros/latex/contrib/fixdif/fixdif-zh-cn.tex -2022/08/11 | 163865 | systems/win32/miktex/tm/packages/tudscr.tar.lzma -2022/08/11 | 163015 | macros/latex/contrib/fixdif/fixdif-zh-cn.pdf -2022/08/11 | 1625928 | systems/win32/miktex/tm/packages/xecjk__doc.tar.lzma -2022/08/11 | 15769 | macros/latex/contrib/runcode/runcode.sty -2022/08/11 | 15636 | systems/win32/miktex/tm/packages/l3backend.tar.lzma -2022/08/11 | 15529 | systems/win32/miktex/tm/packages/europecv.tar.lzma -2022/08/11 | 15233 | systems/win32/miktex/tm/packages/bookcover__source.tar.lzma -2022/08/11 | 151428 | systems/texlive/tlnet/archive/simplebnf.doc.r64091.tar.xz -2022/08/11 | 150414 | systems/win32/miktex/tm/packages/simplebnf__doc.tar.lzma -2022/08/11 | 146626 | systems/win32/miktex/tm/packages/yfonts-otf__doc.tar.lzma -2022/08/11 | 1444792 | systems/win32/miktex/tm/packages/unbtex__doc.tar.lzma -2022/08/11 | 1395 | systems/win32/miktex/tm/packages/olsak-misc__doc.tar.lzma -2022/08/11 | 13662 | systems/win32/miktex/tm/packages/sillypage.tar.lzma -2022/08/11 | 13273 | systems/win32/miktex/tm/packages/gentombow__source.tar.lzma -2022/08/11 | 132560 | macros/latex/contrib/runcode.zip -2022/08/11 | 12 | macros/latex/contrib/create-theorem/DEPENDS.txt -2022/08/11 | 12832 | systems/win32/miktex/tm/packages/proflycee.tar.lzma -2022/08/11 | 1246141 | systems/win32/miktex/tm/packages/siunitx__doc.tar.lzma -2022/08/11 | 1212673 | systems/win32/miktex/tm/packages/profcollege.tar.lzma -2022/08/11 | 11889 | systems/win32/miktex/tm/packages/biblatex-software__source.tar.lzma -2022/08/11 | 1182741 | systems/win32/miktex/tm/packages/njuthesis__doc.tar.lzma -2022/08/11 | 116799 | systems/win32/miktex/tm/packages/siunitx__source.tar.lzma -2022/08/11 | 11673083 | systems/win32/miktex/tm/packages/l3kernel__doc.tar.lzma -2022/08/11 | 1133492 | systems/win32/miktex/tm/packages/tuda-ci__doc.tar.lzma -2022/08/11 | 11324 | macros/latex/contrib/runcode/runcode.tex -2022/08/11 | 11119 | systems/win32/miktex/tm/packages/gentombow.tar.lzma -2022/08/11 | 11077 | support/TeX4ht/source/tex4ht-html5.tex -2022/08/11 | 108622 | macros/latex/contrib/create-theorem.zip -2022/08/11 | 10761 | systems/win32/miktex/tm/packages/uni-titlepage.tar.lzma -2022/08/11 | 106565 | systems/win32/miktex/tm/packages/nimsticks__doc.tar.lzma -2022/08/11 | 10170 | systems/win32/miktex/tm/packages/lt3rawobjects__source.tar.lzma -2022/08/11 | 100673 | macros/latex/contrib/create-theorem/create-theorem.sty diff --git a/biblio/citation-style-language/CHANGELOG.md b/biblio/citation-style-language/CHANGELOG.md index 1c6b2df688..e351714b3a 100644 --- a/biblio/citation-style-language/CHANGELOG.md +++ b/biblio/citation-style-language/CHANGELOG.md @@ -7,6 +7,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [v0.2.0] - 2022-08-18 + +### Added + +- The cite grouping, collapsing, and disambiguation features are now implemented. + +### Changed + +- The `citeproc` executable is renamed to `citeproc-lua` to avoid conflicts with other processor implementations. +- Package configuration can also be given in the package loading options. +- A warning is raised instead of and error in case of duplicate entry keys ([#14](https://github.com/zepinglee/citeproc-lua/issues/14)). + +### Fixed + +- Fix an infinite loop error when bib entry keys contain hyphens or underscores ([#18](https://github.com/zepinglee/citeproc-lua/issues/18)). +- Fix incorrect item position in note style ([#20](https://github.com/zepinglee/citeproc-lua/issues/20)). +- Fix compatibility with `\blockquote` of `csquotes` ([#21](https://github.com/zepinglee/citeproc-lua/issues/21)). +- Fix non-lowercase field names ([#22](https://github.com/zepinglee/citeproc-lua/issues/22)). + ## [v0.1.1] - 2022-03-21 ### Added @@ -27,6 +46,7 @@ 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.1.1...HEAD +[Unreleased]: https://github.com/zepinglee/citeproc-lua/compare/v0.2.0...HEAD +[v0.2.0]: https://github.com/zepinglee/citeproc-lua/compare/v0.1.1...0.2.0 [v0.1.1]: https://github.com/zepinglee/citeproc-lua/compare/v0.1.0...v0.1.1 [v0.1.0]: https://github.com/zepinglee/citeproc-lua/releases/tag/v0.1.0 diff --git a/biblio/citation-style-language/DEPENDS.txt b/biblio/citation-style-language/DEPENDS.txt new file mode 100644 index 0000000000..3d0edb73de --- /dev/null +++ b/biblio/citation-style-language/DEPENDS.txt @@ -0,0 +1,10 @@ +# The format of this file is described in https://www.tug.org/texlive/pkgcontrib.html#deps. + +hard luatex +hard l3kernel +hard l3packages +hard filehook +hard url +hard luaxml +hard lua-uca +hard lualibs diff --git a/biblio/citation-style-language/README.md b/biblio/citation-style-language/README.md index 74c27590c6..6ad5a87602 100644 --- a/biblio/citation-style-language/README.md +++ b/biblio/citation-style-language/README.md @@ -48,7 +48,7 @@ lualatex example.tex ```bash pdflatex example.tex -citeproc example.aux +citeproc-lua example.aux pdflatex example.tex ``` diff --git a/biblio/citation-style-language/american-chemical-society.csl b/biblio/citation-style-language/american-chemical-society.csl index bf75b2d8de..cde0e0c50f 100644 --- a/biblio/citation-style-language/american-chemical-society.csl +++ b/biblio/citation-style-language/american-chemical-society.csl @@ -21,7 +21,7 @@ <category citation-format="numeric"/> <category field="chemistry"/> <summary>The American Chemical Society style</summary> - <updated>2021-05-22T12:00:00+00:00</updated> + <updated>2022-05-04T19:44:25-04:00</updated> <rights license="http://creativecommons.org/licenses/by-sa/3.0/">This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 License</rights> </info> <locale xml:lang="en"> @@ -250,14 +250,17 @@ </group> </else-if> <else-if type="webpage"> - <group delimiter=" "> - <text variable="title"/> - <text variable="URL"/> - <date variable="accessed" prefix="(accessed " suffix=")" delimiter=" "> - <date-part name="year"/> - <date-part name="month" prefix="-" form="numeric-leading-zeros"/> - <date-part name="day" prefix="-" form="numeric-leading-zeros"/> - </date> + <group delimiter=". "> + <text variable="title" font-style="italic"/> + <text variable="container-title"/> + <group delimiter=" "> + <text variable="URL"/> + <date variable="accessed" prefix="(accessed " suffix=")"> + <date-part name="year"/> + <date-part name="month" prefix="-" form="numeric-leading-zeros"/> + <date-part name="day" prefix="-" form="numeric-leading-zeros"/> + </date> + </group> </group> </else-if> <else> diff --git a/biblio/citation-style-language/american-medical-association.csl b/biblio/citation-style-language/american-medical-association.csl index 44520822d0..b36bbb5488 100644 --- a/biblio/citation-style-language/american-medical-association.csl +++ b/biblio/citation-style-language/american-medical-association.csl @@ -27,7 +27,7 @@ <category citation-format="numeric"/> <category field="medicine"/> <summary>The American Medical Association style as used in JAMA. Version 11 as per November-2019.</summary> - <updated>2021-10-28T13:38:04+00:00</updated> + <updated>2022-03-17T08:48:24+00:00</updated> <rights license="http://creativecommons.org/licenses/by-sa/3.0/">This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 License</rights> </info> <locale xml:lang="en"> @@ -86,7 +86,7 @@ </macro> <macro name="title"> <choose> - <if type="bill book graphic legal_case legislation motion_picture report song" match="any"> + <if type="bill book graphic legal_case legislation motion_picture report song thesis" match="any"> <text variable="title" font-style="italic" text-case="title"/> </if> <else> @@ -247,6 +247,15 @@ <text variable="event-place"/> </group> </else-if> + <else-if type="thesis" match="any"> + <group delimiter=". " prefix=" " suffix="."> + <text variable="genre"/> + <group delimiter="; "> + <text variable="publisher"/> + <date date-parts="year" form="text" variable="issued"/> + </group> + </group> + </else-if> <else> <text macro="editor" prefix=" " suffix="."/> <group prefix=" " suffix="."> diff --git a/biblio/citation-style-language/american-sociological-association.csl b/biblio/citation-style-language/american-sociological-association.csl index 6657716cde..cf4ab0fc0d 100644 --- a/biblio/citation-style-language/american-sociological-association.csl +++ b/biblio/citation-style-language/american-sociological-association.csl @@ -16,7 +16,7 @@ <category citation-format="author-date"/> <category field="sociology"/> <summary>The ASA style following the 6th edition of the Style Guide</summary> - <updated>2020-09-18T10:38:12+00:00</updated> + <updated>2022-05-08T17:48:56-04:00</updated> <rights license="http://creativecommons.org/licenses/by-sa/3.0/">This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 License</rights> </info> <locale xml:lang="en"> @@ -125,13 +125,25 @@ <macro name="year-date"> <choose> <if variable="issued"> - <group delimiter=" "> - <date variable="original-date" form="numeric" date-parts="year" prefix="[" suffix="]"/> - <date variable="issued" form="numeric" date-parts="year"/> + <group> + <group delimiter=" "> + <date variable="original-date" form="numeric" date-parts="year" prefix="[" suffix="]"/> + <date variable="issued" form="numeric" date-parts="year"/> + </group> + <text variable="year-suffix"/> </group> </if> + <else-if variable="status"> + <group> + <text variable="status" text-case="lowercase"/> + <text variable="year-suffix" prefix="-"/> + </group> + </else-if> <else> - <text term="no date" form="short"/> + <group> + <text term="no date" form="short"/> + <text variable="year-suffix" prefix="-"/> + </group> </else> </choose> </macro> @@ -140,6 +152,12 @@ <if variable="issued"> <date variable="issued" form="numeric" date-parts="year"/> </if> + <else-if variable="status"> + <group> + <text variable="status" text-case="lowercase"/> + <text variable="year-suffix" prefix="-"/> + </group> + </else-if> <else> <text term="no date" form="short"/> </else> diff --git a/biblio/citation-style-language/apa.csl b/biblio/citation-style-language/apa.csl index 5ba01a9423..43a8e5932f 100644 --- a/biblio/citation-style-language/apa.csl +++ b/biblio/citation-style-language/apa.csl @@ -14,7 +14,7 @@ <category citation-format="author-date"/> <category field="psychology"/> <category field="generic-base"/> - <updated>2022-01-31T09:43:56-05:00</updated> + <updated>2022-08-11T09:14:19-04:00</updated> <rights license="http://creativecommons.org/licenses/by-sa/3.0/">This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 License</rights> </info> <locale xml:lang="en"> @@ -320,8 +320,8 @@ <!-- General categories of item types: Periodical: article-journal article-magazine article-newspaper post-weblog review review-book Periodical or Booklike: paper-conference - Booklike: article book broadcast chapter dataset entry entry-dictionary entry-encyclopedia figure - graphic interview manuscript map motion_picture musical_score pamphlet patent + Booklike: article book broadcast chapter dataset entry entry-dictionary entry-encyclopedia figure + graphic interview manuscript map motion_picture musical_score pamphlet patent personal_communication report song speech thesis post webpage Legal: bill legal_case legislation treaty --> @@ -389,7 +389,7 @@ </if> <else-if type="interview personal_communication" match="any"> <choose> - <!-- These variables indicate that the letter is retrievable by the reader. + <!-- These variables indicate that the letter is retrievable by the reader. If not, then use the APA in-text-only personal communication format --> <if variable="archive container-title DOI publisher URL" match="none"> <group delimiter=", "> @@ -470,7 +470,7 @@ </if> </choose> </else-if> - <!-- Only year: article article-journal book chapter entry entry-dictionary entry-encyclopedia dataset figure graphic + <!-- Only year: article article-journal book chapter entry entry-dictionary entry-encyclopedia dataset figure graphic manuscript map musical_score paper-conference[published] patent report review review-book thesis --> </choose> </if> @@ -530,7 +530,7 @@ <if type="interview personal_communication" match="any"> <choose> <if variable="archive container-title DOI publisher URL" match="none"> - <!-- These variables indicate that the communication is retrievable by the reader. + <!-- These variables indicate that the communication is retrievable by the reader. If not, then use the in-text-only personal communication format --> <date variable="issued" form="text"/> </if> @@ -1295,7 +1295,7 @@ <macro name="reviewed-title"> <choose> <if variable="reviewed-title"> - <!-- Not possible to distinguish TV series episode from other reviewed + <!-- Not possible to distinguish TV series episode from other reviewed works [Ex. 69] --> <text variable="reviewed-title" font-style="italic"/> </if> @@ -1553,14 +1553,14 @@ </macro> <macro name="event"> <choose> - <if variable="event"> + <if variable="event event-title" match="any"> <!-- To prevent Zotero from printing event-place due to its double-mapping of all 'place' to both publisher-place and event-place. Remove this 'choose' when that is changed. --> <choose> <if variable="collection-editor editor editorial-director issue page volume" match="none"> <!-- Don't print event info if published in a proceedings --> <group delimiter=", "> - <text variable="event"/> + <text macro="event-title"/> <text variable="event-place"/> </group> </if> @@ -1568,6 +1568,20 @@ </if> </choose> </macro> + <macro name="event-title"> + <choose> + <!-- TODO: We expect "event-title" to be used, + but processors and applications may not be updated yet. + This macro ensures that either "event" or "event-title" can be accpeted. + Remove if procesor logic and application adoption can handle this. --> + <if variable="event-title"> + <text variable="event-title"/> + </if> + <else> + <text variable="event"/> + </else> + </choose> + </macro> <!-- After 'source', APA also prints publication history (original publication, reprint info, retraction info) --> <macro name="publication-history"> <choose> @@ -1575,7 +1589,7 @@ <group prefix="(" suffix=")"> <choose> <if variable="references"> - <!-- This provides the option for more elaborate description + <!-- This provides the option for more elaborate description of publication history, such as full "reprinted" references (examples 11, 43, 44) or retracted references --> <text variable="references"/> diff --git a/biblio/citation-style-language/chicago-author-date.csl b/biblio/citation-style-language/chicago-author-date.csl index 8c133354b3..f8c640cd7f 100644 --- a/biblio/citation-style-language/chicago-author-date.csl +++ b/biblio/citation-style-language/chicago-author-date.csl @@ -45,6 +45,30 @@ <term name="translator" form="short">trans.</term> </terms> </locale> + <locale xml:lang="pt-PT"> + <terms> + <term name="accessed">acedido a</term> + </terms> + </locale> + <locale xml:lang="pt"> + <terms> + <term name="editor" form="verb">editado por</term> + <term name="editor" form="verb-short">ed.</term> + <term name="container-author" form="verb">por</term> + <term name="translator" form="verb-short">traduzido por</term> + <term name="translator" form="short">trad.</term> + <term name="editortranslator" form="verb">editado e traduzido por</term> + <term name="and">e</term> + <term name="no date" form="long">s.d</term> + <term name="no date" form="short">s.d.</term> + <term name="in">em</term> + <term name="at">em</term> + <term name="by">por</term> + <!-- PUNCTUATION --> + <term name="open-quote">"</term> + <term name="close-quote">"</term> + </terms> + </locale> <macro name="secondary-contributors"> <choose> <if type="chapter entry-dictionary entry-encyclopedia paper-conference" match="none"> diff --git a/biblio/citation-style-language/chicago-fullnote-bibliography.csl b/biblio/citation-style-language/chicago-fullnote-bibliography.csl index fb2f1ae943..da4969f115 100644 --- a/biblio/citation-style-language/chicago-fullnote-bibliography.csl +++ b/biblio/citation-style-language/chicago-fullnote-bibliography.csl @@ -34,7 +34,7 @@ <category citation-format="note"/> <category field="generic-base"/> <summary>Chicago format with full notes and bibliography</summary> - <updated>2022-01-16T14:46:01-05:00</updated> + <updated>2017-10-12T12:00:00+00:00</updated> <rights license="http://creativecommons.org/licenses/by-sa/3.0/">This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 License</rights> </info> <locale xml:lang="en"> diff --git a/biblio/citation-style-language/chicago-note-bibliography.csl b/biblio/citation-style-language/chicago-note-bibliography.csl index 6ec4a29534..83da96cb4d 100644 --- a/biblio/citation-style-language/chicago-note-bibliography.csl +++ b/biblio/citation-style-language/chicago-note-bibliography.csl @@ -34,7 +34,7 @@ <category citation-format="note"/> <category field="generic-base"/> <summary>Chicago format with short notes and bibliography</summary> - <updated>2022-01-16T14:46:01-05:00</updated> + <updated>2017-10-12T12:00:00+00:00</updated> <rights license="http://creativecommons.org/licenses/by-sa/3.0/">This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 License</rights> </info> <locale xml:lang="en"> diff --git a/biblio/citation-style-language/citation-style-language-doc.pdf b/biblio/citation-style-language/citation-style-language-doc.pdf Binary files differindex b4ccbe55d3..af42980a81 100644 --- a/biblio/citation-style-language/citation-style-language-doc.pdf +++ b/biblio/citation-style-language/citation-style-language-doc.pdf diff --git a/biblio/citation-style-language/citation-style-language-doc.tex b/biblio/citation-style-language/citation-style-language-doc.tex index 538aaae00a..1dda26c5fa 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{2022-03-21 v0.1.1} +\date{2022-08-18 v0.2.0} \maketitle @@ -73,7 +73,7 @@ citations and bibliography according to the selected CSL style. A LaTeX package (\file{citation-style-language.sty}) is provided to communicate with the processor. Note that this project is in early development stage and some features of CSL -are not implemented yet (especially collapsing and disambiguation). +are not implemented yet. Comments, suggestions, and bug reports are welcome. @@ -131,14 +131,14 @@ The general procedure is similar to the traditional BibTeX workflow. \end{syntax} \end{function} -The behavior of the \pkg{citation-style-language} package is controlled by several key-value -options which can be set with the \cs{cslsetup} command. -For example, +Package options may be set when the package is loaded or at any later stage +with the \cs{cslsetup} command. +These two methods are equivalent. \begin{LaTeXdemo} - \cslsetup{ - style = apa, - locale = zh-CN, - } + \usepackage[style = apa]{citation-style-langugage} + % OR + \usepackage{citation-style-langugage} + \cslsetup{style = apa} \end{LaTeXdemo} \DescribeOption{style} @@ -278,13 +278,11 @@ recommended. If only one optional argument is provided, it is treated as \meta{postnote}. The \meta{postnote} is used as a page locator if it consists of only digits. -In other packages, several commands are provided for producing citations in -different styles such as \cs{citet}, \cs{citep}, \cs{parencite}, and -\cs{footnotecite}. -In \pkg{citation-style-language} package, however, the format of citations is -fixed as defined in CSL style and it is impossible to select another format -without modifying the \file{.csl} style file. -Note that narrative citation (like ``Doe (2018)'') will be supported in CSL 1.1. +For author-date styles, there are also narrative in-text citations where the +author names appear in running text and only dates are enclosed in parentheses +(\cs{citet} in \pkg{natbib} pacakge or \cs{textcite} in \pkg{biblatex}). +However such cite command in this pakcage is not available at the momment and +it will be implemented in the next release. \begin{function}{\cites} \begin{syntax} @@ -302,6 +300,17 @@ scanning process. The following example illustrates its usage. \cites[prefix = {See }, page = 6]{key1}[section = 2.3]{key2}\relax [Text] \end{LaTeXdemo} +\begin{function}{\nocite} + \begin{syntax} + \cs{nocite}\marg{keys} + \end{syntax} +\end{function} + +This command produces no output but makes the entries included in the +bibliography, which is the same in standard \LaTeX. +If the special key |*| is given (\cs{notecite\{*\}}), all the entries in the +database are included. + \begin{function}{\printbibliography} @@ -368,16 +377,11 @@ An error will be triggered if any of them is loaded together with \pkg{citation- The \pkg{citation-style-language} package is in early development stage and there are some issues with it. \begin{itemize} - \item The \pkg{citeproc-lua} has not implemented all the features of CSL, - especially disambiguation and collapsing. + \item The \pkg{citeproc-lua} has not implemented all the features of CSL. For detailed information of the coverage on the CSL standard test suite\footnote{\url{https://github.com/citation-style-language/test-suite}}, see \href{https://github.com/zepinglee/citeproc-lua/blob/main/test/citeproc-test.log}{citeproc-test.log} in the GitHub repository. - \item The processor is much slower than expected compared to other - reference engines. - This is because little care has been taken in the development so far. - Optimization is needed in the future. \item When used with \pkg{hyperref}, the citations are not correctly rendered as hyperlinks. \item The Unicode sorting method is provided by \pkg{lua-uca} package and diff --git a/biblio/citation-style-language/citation-style-language.sty b/biblio/citation-style-language/citation-style-language.sty index 546ac13eec..87165c4be2 100644 --- a/biblio/citation-style-language/citation-style-language.sty +++ b/biblio/citation-style-language/citation-style-language.sty @@ -9,9 +9,10 @@ \RequirePackage{expl3} \RequirePackage{xparse} -\ProvidesExplPackage {citation-style-language} {2022-01-22} {v0.1.0} +\ProvidesExplPackage {citation-style-language} {2022-08-18} {v0.2.0} {Citation Style Language for LaTeX} +\RequirePackage { l3keys2e } \RequirePackage { filehook } \RequirePackage { url } @@ -34,7 +35,7 @@ \__csl_load_check:n \sys_if_engine_luatex:T - { \lua_now:n { csl = require("csl") } } + { \lua_now:n { csl = require("citeproc-latex") } } \NewDocumentCommand \cslsetup { m } @@ -82,8 +83,11 @@ } +% Appends the cite key into \l__csl_cite_keys_seq and cite-items into +% \l__csl_cite_items_seq +% #1, #2: prenote/postnote +% #3: keys \cs_new:Npn \__csl_process_cite_items:nnn #1#2#3 - % #1,#2: prenote/postnote, #3: keys { \tl_if_novalue:nTF {#2} { @@ -120,25 +124,27 @@ { \prop_clear:N \l__csl_cite_item_prop \prop_put:Nnn \l__csl_cite_item_prop { id } {#3} + % \bool_if:T \l__csl_suppress_author_bool + % { \prop_put:Nnn \l__csl_cite_item_prop { suppress-author } { true } } + % \bool_if:T \l__csl_author_only_bool + % { \prop_put:Nnn \l__csl_cite_item_prop { author-only } { true } } \tl_if_empty:nF {#1} { \tl_set:Nn \l__csl_prefix_tl {#1} \tl_put_right:NV \l__csl_prefix_tl \l__csl_prefix_separator_tl - \prop_put:NnV \l__csl_cite_item_prop { prefix } { \l__csl_prefix_tl } + \prop_put:NnV \l__csl_cite_item_prop { prefix } \l__csl_prefix_tl } - \tl_if_in:nnTF {#2} { = } + \tl_if_empty:nF {#2} { - \keys_set:nn { csl / cite-item } {#2} - } - { - \tl_if_empty:nF {#2} + \tl_if_in:nnTF {#2} { = } + { \keys_set:nn { csl / cite-item } {#2} } { \regex_match:nnTF { \d+ } {#2} { \__csl_set_locator:nn { page } {#2} } { \tl_set:Nn \l__csl_suffix_tl {#2} \tl_put_left:NV \l__csl_suffix_tl \l__csl_suffix_separator_tl - \prop_put:NnV \l__csl_cite_item_prop { suffix } { \l__csl_suffix_tl } + \prop_put:NnV \l__csl_cite_item_prop { suffix } \l__csl_suffix_tl } } } @@ -202,20 +208,26 @@ \tl_new:N \l__csl_citation_info_tl \tl_new:N \l__csl_citation_tl \prop_new:N \g__csl_citations_prop +\prop_clear:N \l__csl_citation_prop \cs_new:Npn \__csl_make_citation:NN #1#2 % #1: \l__csl_cite_keys_seq % #2: \l__csl_cite_items_seq { + \prop_clear:N \l__csl_citation_prop \__csl_process_citation_id:NN \l__csl_citation_id_tl #1 + \prop_put:NnV \l__csl_citation_prop { citationID } \l__csl_citation_id_tl \tl_set:Nx \l__csl_cite_items_tl { \seq_use:Nn #2 { , } } - \exp_args:NNV \__csl_process_note_index:Nn \l__csl_note_index_tl \l__csl_citation_id_tl - \tl_set:Nx \l__csl_citation_info_tl + \prop_put:NnV \l__csl_citation_prop { citationItems } \l__csl_cite_items_tl + \__csl_get_note_index:N \l__csl_note_index_tl + \prop_put:Nnx \l__csl_citation_prop { properties } { noteIndex = { \l__csl_note_index_tl } } + \tl_clear:N \l__csl_citation_info_tl + \prop_map_inline:Nn \l__csl_citation_prop { - { \l__csl_citation_id_tl } - { \l__csl_cite_items_tl } - { \l__csl_note_index_tl } + \tl_if_empty:NF \l__csl_citation_info_tl + { \tl_put_right:Nn \l__csl_citation_info_tl { , } } + \tl_put_right:Nn \l__csl_citation_info_tl { ##1 = { ##2 } } } \exp_args:NV \__csl_write_aux_citation:n \l__csl_citation_info_tl \prop_get:NVNTF \g__csl_citations_prop \l__csl_citation_id_tl @@ -224,8 +236,9 @@ { \bool_if:NTF \l__csl_engine_initialized_bool { - \tl_set:Nx \l__csl_citation_tl + \tl_set:Nf \l__csl_citation_tl { \lua_now:e { csl.cite("\l__csl_citation_info_tl") } } + \exp_args:NV \__csl_print_citation:n \l__csl_citation_tl } { \exp_args:Nx \__csl_print_undefined_citation:n @@ -261,26 +274,18 @@ } -\int_new:N \l__csl_note_index_int -\int_gzero_new:N \g__csl_last_note_index_int -\int_gzero_new:N \g__csl_citation_note_count_int - -\cs_new:Npn \__csl_process_note_index:Nn #1#2 - % #1 \l__csl_note_index_tl - % #2: citationID +% Save the note number to \l__csl_note_index_tl +% TODO: multiple citations in a note +\cs_new:Npn \__csl_get_note_index:N #1 + % #1: \l__csl_note_index_tl { - \int_set_eq:Nc \l__csl_note_index_int { c@ \@mpfn } - \prop_if_in:NnTF \g__csl_citations_prop {#2} - { \int_incr:N \l__csl_note_index_int } - { \int_gincr:N \g__csl_citation_note_count_int } - \int_add:Nn \l__csl_note_index_int { \g__csl_citation_note_count_int } - \tl_set:Nx #1 { \int_use:N \l__csl_note_index_int } - \int_gset_eq:NN \g__csl_last_note_index_int \l__csl_note_index_int - \int_compare:nT { \l__csl_note_index_int < \g__csl_last_note_index_int } + \bool_if:NTF \l__csl_note_style_bool { - \int_gzero:N \g__csl_last_note_index_int - \int_gzero:N \g__csl_citation_note_count_int + \int_set_eq:Nc \l_tmpa_int { c@ \@mpfn } + \int_incr:N \l_tmpa_int + \tl_set:Nx #1 { \int_use:N \l_tmpa_int } } + { \tl_set:Nn #1 { 0 } } } @@ -294,6 +299,16 @@ } +% \cs_new:Npn \__csl_print_citation:n #1 +% % #1: citation text +% { +% \bool_if:NTF \l__csl_note_style_bool +% { +% \footnote {#1} +% } +% {#1} +% } + \cs_new:Npn \__csl_print_citation:n #1 % #1: "{<type>}{<citation text>}" { \__csl_print_citation_aux:nn #1 } @@ -330,17 +345,36 @@ \cs_new:Npn \__csl_no_cite:n #1 { - \__csl_if_preamble:TF + \seq_clear:N \l__csl_cite_keys_seq + \seq_clear:N \l__csl_cite_items_seq + \__csl_process_cite_items:nnn { } { } {#1} + \tl_set:Nx \l__csl_cite_items_tl + { \seq_use:Nn \l__csl_cite_items_seq { , } } + \tl_set:Nx \l__csl_citation_info_tl { - \AtBeginDocument - { \__csl_write_aux_citation:n { { nocite } {#1} { } } } + citationID = { @nocite } , + citationItems = { \l__csl_cite_items_tl } , + properties = { noteIndex = { 0 } } } - { \__csl_write_aux_citation:n { { nocite } {#1} { } } } + \exp_args:NV \__csl_no_cite_write_aux:n \l__csl_citation_info_tl \sys_if_engine_luatex:T { \lua_now:n { csl.nocite("#1") } } } +\cs_new:Npn \__csl_no_cite_write_aux:n #1 + { + \__csl_if_preamble:TF + { + \AtBeginDocument + { \exp_args:Nx \__csl_write_aux_citation:n { #1 } } + } + { + \exp_args:Nx \__csl_write_aux_citation:n { #1 } + } + } + + \prg_new_conditional:Nnn \__csl_if_preamble: { T , F , TF } { \if_meaning:w \@begindocumenthook \@undefined @@ -352,6 +386,7 @@ % Used in aux files to register cite items. +% #1: a citation object \cs_set:Npn \citation #1 { \sys_if_engine_luatex:T @@ -362,9 +397,9 @@ \cs_new:Npn \cslcite #1#2 { \bibcite {#1} {#2} - \if@filesw - \iow_now:Nn \@auxout { \bibcite {#1} {#2} } - \fi + % \if@filesw + % \iow_now:Nn \@auxout { \bibcite {#1} {#2} } + % \fi } @@ -444,6 +479,8 @@ entry-spacing = { 1 } , } +\ProcessKeysPackageOptions { csl } + \bool_new:N \l__csl_engine_initialized_bool \prop_set_from_keyval:Nn \l__csl_babel_locale_mapping_prop @@ -590,6 +627,7 @@ } \str_if_eq:eeT { \lua_now:n { tex.print(csl.initialized) } } { true } { \bool_set_true:N \l__csl_engine_initialized_bool } + \__csl_get_style_class: \@ifpackageloaded { hyperref } { \lua_now:n { csl.enable_linking() } } { } @@ -614,6 +652,21 @@ \fi } + +\str_new:N \l__csl_style_class_str +% In-text (including numeric or author-date) or note style +\bool_new:N \l__csl_note_style_bool + +\cs_new:Npn \__csl_get_style_class: { + \bool_if:NT \l__csl_engine_initialized_bool + { + \str_set:Nx \l__csl_style_class_str { \lua_now:n { csl.get_style_class() } } + \str_if_eq:VnT \l__csl_style_class_str { note } + { \bool_set_true:N \l__csl_note_style_bool } + } +} + + \clist_new:N \l__csl_options_clist \cs_new:Npn \__csl_write_aux_csl_options: @@ -972,6 +1025,19 @@ } +% csquotes + +\AtEndOfPackageFile* { csquotes } + { + \BlockquoteDisable + { + \cs_set_eq:NN \__csl_make_citation:NN \use_none:nn + % \sys_if_engine_luatex:T + % { \lua_now:n { csl.preview_mode = true } } + } + } + + % hyperref % The hyperref package also patches \bibcite but it cannot provide hyperlinks diff --git a/biblio/citation-style-language/citeproc-bib-data.json b/biblio/citation-style-language/citeproc-bib-data.json deleted file mode 100644 index 69e26e16c3..0000000000 --- a/biblio/citation-style-language/citeproc-bib-data.json +++ /dev/null @@ -1,2349 +0,0 @@ -{ - "description": "Bib CSL mapping", - "types": { - "archival": { - "csl": "collection", - "source": "jurabib.bst" - }, - "archive": { - "csl": "collection", - "notes": "New in CSL v1.0.2.", - "source": "gbt7714-numerical.bst" - }, - "article": { - "csl": "article-journal", - "notes": "May also be `article-magazine` or `article-newspaper` depending upon the field `entrysubtype`.", - "source": "bibtex" - }, - "artifactdataset": { - "csl": "dataset", - "source": "ACM-Reference-Format.bst" - }, - "artifactsoftware": { - "csl": "software", - "source": "ACM-Reference-Format.bst" - }, - "artwork": { - "csl": "graphic", - "source": "biblatex" - }, - "atlas": { - "csl": null, - "source": "ametsoc2014.bst" - }, - "audio": { - "csl": "song", - "notes": "CSL's `song` can be used for any audio recording (not only music).", - "source": "biblatex" - }, - "bachelor": { - "csl": "thesis", - "source": "dlfltxbbibtex.bst" - }, - "bibnote": { - "csl": null, - "notes": "Not supported.", - "source": "biblatex" - }, - "book": { - "csl": "book", - "source": "bibtex" - }, - "bookinbook": { - "csl": "chapter", - "source": "biblatex" - }, - "booklet": { - "csl": "pamphlet", - "source": "bibtex" - }, - "brochure": { - "csl": "pamphlet", - "source": "thesnumb.bst" - }, - "cconference": { - "csl": null, - "source": "seuthesis.bst" - }, - "collection": { - "csl": "book", - "source": "biblatex" - }, - "comment": { - "csl": null, - "notes": "Special entry type for Scribe compatibility", - "source": "bibtex" - }, - "commentary": { - "csl": "book", - "notes": "Not supported.", - "source": "biblatex" - }, - "commented": { - "csl": null, - "source": "jurabib.bst" - }, - "conference": { - "alias": "inproceedings", - "csl": "paper-conference", - "source": "bibtex" - }, - "ctan": { - "csl": "software", - "source": "tugboat.bst" - }, - "customa": { - "csl": null, - "source": "biblatex" - }, - "customb": { - "csl": null, - "source": "biblatex" - }, - "customc": { - "csl": null, - "source": "biblatex" - }, - "customd": { - "csl": null, - "source": "biblatex" - }, - "custome": { - "csl": null, - "source": "biblatex" - }, - "customf": { - "csl": null, - "source": "biblatex" - }, - "database": { - "csl": "dataset", - "source": "gbt7714-numerical.bst" - }, - "dataset": { - "csl": "dataset", - "source": "biblatex" - }, - "dictionary": { - "csl": "book", - "source": "vancouver.bst" - }, - "docthesis": { - "csl": "thesis", - "source": "gost2003.bst" - }, - "electronic": { - "alias": "online", - "csl": "webpage", - "source": "biblatex" - }, - "eulegislation": { - "csl": "legislation", - "source": "bath.bst" - }, - "footnote": { - "csl": null, - "source": "apsrev4-2.bst" - }, - "game": { - "csl": "software", - "source": "ACM-Reference-Format.bst" - }, - "govpub": { - "csl": "regulation", - "source": "thesnumb.bst" - }, - "habthesis": { - "csl": "thesis", - "source": "bestpapers-export.bst" - }, - "heading": { - "csl": null, - "source": "bookdb.bst" - }, - "hidden": { - "csl": null, - "source": "abntex2-alf.bst" - }, - "image": { - "csl": "graphic", - "source": "biblatex" - }, - "inbook": { - "csl": "chapter", - "source": "bibtex" - }, - "incollection": { - "csl": "chapter", - "source": "bibtex" - }, - "inloosecollection": { - "csl": "chapter", - "source": "resphilosophica.bst" - }, - "inpress": { - "csl": "article", - "notes": "Use for preprints, working papers, and similar works posted on a platform where some level of persistence or stewardship is expected (e.g. arXiv or other preprint repositories, working paper series).", - "source": "bjnano.bst" - }, - "inproceedings": { - "csl": "paper-conference", - "source": "bibtex" - }, - "inreference": { - "csl": "entry", - "notes": "May also be `entry`, `entry-dictionary` or `entry-encyclopedia`.", - "source": "biblatex" - }, - "inserialcollection": { - "csl": null, - "source": "asmejour.bst" - }, - "internet": { - "csl": "webpage", - "source": "IEEEtran.bst" - }, - "journalpart": { - "csl": null, - "source": "abntex2-alf.bst" - }, - "journals": { - "csl": "periodical", - "source": "bestpapers-export.bst" - }, - "jurisdiction": { - "csl": null, - "notes": "\"Court decisions, court recordings, and similar things.\"", - "source": "biblatex" - }, - "jurthesis": { - "csl": "thesis", - "source": "jurabib.bst" - }, - "legal": { - "csl": "treaty", - "notes": "\"Legal documents such as treaties.\"", - "source": "biblatex" - }, - "legislation": { - "csl": "legislation", - "notes": "\"Laws, bills, legislative proposals, and similar things.\" May also be `bill`", - "source": "biblatex" - }, - "letter": { - "csl": "personal_communication", - "source": "biblatex" - }, - "lexicon": { - "csl": "book", - "source": "jurabib.bst" - }, - "majorthesis": { - "csl": "thesis", - "source": "achicago.bst" - }, - "manual": { - "csl": "report", - "nots": "CSL's `report` is also used for manuals and similar technical documentation (e.g. a software, instrument, or test manual).", - "source": "bibtex" - }, - "map": { - "csl": "map", - "source": "vancouver.bst" - }, - "mastersthesis": { - "alias": "thesis", - "csl": "thesis", - "source": "bibtex" - }, - "masterthesis": { - "csl": "thesis", - "source": "asaetr.bst" - }, - "minorthesis": { - "csl": "thesis", - "source": "achicago.bst" - }, - "misc": { - "csl": "document", - "notes": "New in CSL v1.0.2.", - "source": "bibtex" - }, - "monograph": { - "csl": "book", - "source": "gbt7714-numerical.bst" - }, - "monography": { - "csl": "book", - "source": "abntex2-alf.bst" - }, - "movie": { - "csl": "motion_picture", - "source": "biblatex" - }, - "music": { - "csl": "song", - "source": "biblatex" - }, - "mvbook": { - "csl": "book", - "source": "biblatex" - }, - "mvcollection": { - "csl": "book", - "source": "biblatex" - }, - "mvproceedings": { - "csl": "book", - "source": "biblatex" - }, - "mvreference": { - "csl": "book", - "source": "biblatex" - }, - "news": { - "csl": "article-newspaper", - "source": "seuthesix.bst" - }, - "newspaper": { - "csl": "article-newspaper", - "source": "gbt7714-numerical.bst" - }, - "online": { - "csl": "webpage", - "source": "biblatex" - }, - "other": { - "csl": null, - "source": "bjnano.bst" - }, - "patent": { - "csl": "patent", - "source": "biblatex" - }, - "performance": { - "csl": "performance", - "notes": "New in CSL v1.0.2.", - "source": "biblatex" - }, - "periodical": { - "csl": "periodical", - "notes": "New in CSL v1.0.2.", - "source": "biblatex" - }, - "phdthesis": { - "alias": "thesis", - "csl": "thesis", - "source": "bibtex" - }, - "preamble": { - "csl": null, - "notes": "Special entry type for inserting commands or text in the bbl", - "source": "bibtex" - }, - "preprint": { - "csl": "article", - "notes": "Use for preprints, working papers, and similar works posted on a platform where some level of persistence or stewardship is expected (e.g. arXiv or other preprint repositories, working paper series).", - "source": "gbt7714-numerical.bst" - }, - "presentation": { - "csl": "speech", - "notes": "A speech or other presentation (e.g. a paper, talk, poster, or symposium at a conference).", - "source": "apsrev4-2.bst" - }, - "proceedings": { - "csl": "book", - "source": "bibtex" - }, - "program": { - "csl": "software", - "source": "ChemCommun.bst" - }, - "reference": { - "csl": "book", - "source": "biblatex" - }, - "report": { - "csl": "report", - "source": "biblatex" - }, - "review": { - "csl": "review", - "notes": "\"A more specific variant of the `@article` type\"", - "source": "biblatex" - }, - "set": { - "csl": null, - "notes": "Not supported.", - "source": "biblatex" - }, - "setup": { - "csl": null, - "source": "bestpapers-export.bst" - }, - "software": { - "csl": "software", - "notes": "New in CSL v1.0.2.", - "source": "biblatex" - }, - "standard": { - "csl": "standard", - "notes": "New in CSL v1.0.2.", - "source": "biblatex" - }, - "string": { - "csl": null, - "notes": "Special entry type for defining abbreviations", - "source": "bibtex" - }, - "suppbook": { - "csl": "chapter", - "notes": "lossy mapping; \"Supplemental material in a `@book`. This type is closely related to the @inbook entry type. While `@inbook` is primarily intended for a part of a book with its own title (e. g., a single essay in a collection of essays by the same author), this type is provided for elements such as prefaces, introductions, forewords, afterwords, etc. which often have a generic title only. Style guides may require such items to be formatted differently from other `@inbook` items.\"", - "source": "biblatex" - }, - "suppcollection": { - "csl": "chapter", - "notes": "lossy mapping; see `suppbook`", - "source": "biblatex" - }, - "suppperiodical": { - "csl": "article", - "notes": "see `article`", - "source": "biblatex" - }, - "techreport": { - "alias": "report", - "csl": "report", - "source": "bibtex" - }, - "techstandard": { - "csl": "standard", - "notes": "New in CSL v1.0.2.", - "source": "udesoftec.bst" - }, - "thesis": { - "csl": "thesis", - "source": "biblatex" - }, - "uklegislation": { - "csl": "legislation", - "source": "bath.bst" - }, - "unpublished": { - "csl": "manuscript", - "notes": "For unpublished works not made widely available or only hosted on personal websites, use manuscript", - "source": "bibtex" - }, - "video": { - "csl": "motion_picture", - "source": "biblatex" - }, - "webpage": { - "csl": "webpage", - "source": "IEEEtran.bst" - }, - "www": { - "alias": "online", - "csl": "webpage", - "source": "biblatex" - }, - "xdata": { - "csl": null, - "notes": "special item type: \"`@xdata` entries hold data which may be inherited by other entries using the xdata field. Entries of this type only serve as data containers; they may not be cited or added to the bibliography.\"", - "source": "biblatex" - } - }, - "fields": { - "abstract": { - "csl": "abstract", - "source": "biblatex", - "type": "literal" - }, - "account": { - "csl": null, - "source": "address-html.bst" - }, - "acronym": { - "csl": null, - "source": "export.bst" - }, - "add": { - "csl": null, - "source": "figbib.bst" - }, - "add1": { - "csl": null, - "source": "figbib1.bst" - }, - "addendum": { - "csl": null, - "notes": "Not supported.", - "source": "biblatex", - "type": "literal" - }, - "address": { - "alias": "location", - "csl": "publisher-place", - "source": "bibtex", - "type": "literal" - }, - "adsurl": { - "csl": null, - "source": "mnras.bst" - }, - "advisor": { - "csl": null, - "source": "ACM-Reference-Format.bst" - }, - "afterword": { - "csl": null, - "notes": "Not supported.", - "source": "biblatex", - "type": "name" - }, - "annotate": { - "csl": "note", - "source": "apacite.bst" - }, - "annotation": { - "csl": "note", - "notes": "Descriptive text or notes about an item (e.g. in an annotated bibliography)", - "source": "biblatex", - "type": "literal" - }, - "annotator": { - "csl": null, - "source": "biblatex", - "type": "name" - }, - "annote": { - "alias": "annotation", - "csl": "note", - "source": "biblatex", - "type": "literal" - }, - "annotelanguage": { - "csl": null, - "source": "bababbr3-fl.bst" - }, - "applicant": { - "csl": null, - "source": "seuthesix.bst" - }, - "archive": { - "csl": "archive", - "source": "apsrev4-2.bst" - }, - "archiveprefix": { - "alias": "eprinttype", - "csl": "archive", - "source": "biblatex", - "type": "literal" - }, - "archname": { - "csl": "archive", - "source": "jurabib.bst" - }, - "articleno": { - "csl": null, - "source": "ACM-Reference-Format.bst" - }, - "arxiv": { - "csl": null, - "source": "aomalpha.bst" - }, - "assignee": { - "csl": null, - "source": "vancouver.bst" - }, - "author": { - "csl": "author", - "source": "bibtex", - "type": "name" - }, - "authorcountry": { - "csl": null, - "source": "gost2003.bst" - }, - "authorfa": { - "csl": null, - "source": "asa-fa.bst" - }, - "authortype": { - "csl": null, - "source": "biblatex", - "type": "key" - }, - "bibsource": { - "csl": null, - "source": "export.bst" - }, - "biburl": { - "csl": null, - "source": "export.bst" - }, - "binding": { - "csl": null, - "source": "bookdb.bst" - }, - "birthday": { - "csl": null, - "source": "adrbirthday.bst" - }, - "birthyear": { - "csl": null, - "source": "address-html.bst" - }, - "bookaddress": { - "csl": null, - "source": "apsrev4-2.bst" - }, - "bookauthor": { - "csl": "container-author", - "source": "biblatex", - "type": "name" - }, - "booklanguage": { - "csl": null, - "source": "gost2003.bst" - }, - "bookpages": { - "csl": null, - "source": "ACM-Reference-Format.bst" - }, - "bookpagination": { - "csl": null, - "source": "biblatex", - "type": "key" - }, - "booksubtitle": { - "csl": null, - "source": "biblatex", - "type": "literal" - }, - "booktitle": { - "csl": "container-title", - "source": "bibtex", - "type": "literal" - }, - "booktitleaddon": { - "csl": null, - "source": "biblatex", - "type": "literal" - }, - "caption": { - "csl": null, - "source": "figbib.bst" - }, - "caption1": { - "csl": null, - "source": "figbib1.bst" - }, - "cartographer": { - "csl": null, - "source": "vancouver.bst" - }, - "casenumber": { - "csl": null, - "source": "bath.bst" - }, - "category": { - "csl": null, - "source": "bookdb.bst" - }, - "cellular": { - "csl": null, - "source": "address-html.bst" - }, - "chair": { - "csl": null, - "source": "apacite.bst" - }, - "chapter": { - "csl": "chapter-number", - "source": "bibtex", - "type": "literal" - }, - "citedate": { - "csl": null, - "source": "seuthesis.bst" - }, - "city": { - "csl": null, - "source": "ACM-Reference-Format.bst" - }, - "coden": { - "csl": null, - "source": "is-abbrv.bst" - }, - "collaboration": { - "csl": null, - "source": "apsrev4-2.bst" - }, - "collator": { - "csl": null, - "source": "bookdb.bst" - }, - "commentator": { - "csl": null, - "source": "biblatex", - "type": "name" - }, - "compiler": { - "csl": null, - "source": "gost2003.bst" - }, - "condition": { - "csl": null, - "source": "bookdb.bst" - }, - "conference-location": { - "csl": null, - "source": "abntex2-alf.bst" - }, - "conference-number": { - "csl": null, - "source": "abntex2-alf.bst" - }, - "conference-year": { - "csl": null, - "source": "abntex2-alf.bst" - }, - "copy": { - "csl": null, - "source": "bookdb.bst" - }, - "country": { - "csl": null, - "source": "adrbirthday.bst" - }, - "credits": { - "csl": null, - "source": "gost2003.bst" - }, - "crossref": { - "csl": null, - "notes": "Inherits data from a parent entry.", - "source": "biblatex", - "type": "entrykey" - }, - "ctrl-article-title": { - "csl": null, - "source": "achemso.bst" - }, - "ctrl-chapter-title": { - "csl": null, - "source": "achemso.bst" - }, - "ctrl-doi": { - "csl": null, - "source": "achemso.bst" - }, - "ctrl-etal-firstonly": { - "csl": null, - "source": "achemso.bst" - }, - "ctrl-etal-number": { - "csl": null, - "source": "achemso.bst" - }, - "ctrl-link-doi": { - "csl": null, - "source": "angew.bst" - }, - "ctrl-use-doi-all": { - "csl": null, - "source": "angew.bst" - }, - "ctrl-use-title": { - "csl": null, - "source": "achemso.bst" - }, - "dataset": { - "csl": null, - "source": "apalike-ejor.bst" - }, - "date": { - "csl": "issued", - "source": "biblatex", - "type": "date" - }, - "day": { - "csl": null, - "source": "apacite.bst" - }, - "dayfiled": { - "csl": null, - "source": "IEEEtran.bst" - }, - "definition": { - "csl": null, - "source": "glsplain.bst" - }, - "department": { - "csl": null, - "source": "ametsoc2014.bst" - }, - "description": { - "csl": null, - "source": "ChemCommun.bst" - }, - "designator": { - "csl": null, - "source": "thesnumb.bst" - }, - "dimensions": { - "csl": null, - "source": "abntex2-alf.bst" - }, - "dissyear": { - "csl": null, - "source": "jurabib.bst" - }, - "doi": { - "csl": "DOI", - "source": "biblatex", - "type": "verbatim" - }, - "dticnumber": { - "csl": null, - "source": "thesnumb.bst" - }, - "dummy": { - "csl": null, - "source": "expcites.bst" - }, - "edition": { - "csl": "edition", - "source": "bibtex", - "type": "literal" - }, - "editor": { - "csl": "editor", - "source": "bibtex", - "type": "name" - }, - "editora": { - "csl": null, - "source": "biblatex", - "type": "name" - }, - "editoratype": { - "csl": null, - "source": "biblatex", - "type": "key" - }, - "editorb": { - "csl": null, - "source": "biblatex", - "type": "name" - }, - "editorbtype": { - "csl": null, - "source": "biblatex", - "type": "key" - }, - "editorc": { - "csl": null, - "source": "biblatex", - "type": "name" - }, - "editorctype": { - "csl": null, - "source": "biblatex", - "type": "key" - }, - "editortype": { - "csl": null, - "source": "biblatex", - "type": "key" - }, - "eid": { - "csl": null, - "source": "biblatex", - "type": "literal" - }, - "email": { - "csl": null, - "source": "adrbirthday.bst" - }, - "endnumber": { - "csl": null, - "source": "seuthesis.bst" - }, - "endvolume": { - "csl": null, - "source": "seuthesis.bst" - }, - "endyear": { - "csl": null, - "source": "seuthesis.bst" - }, - "englishtitle": { - "csl": null, - "source": "apacite.bst" - }, - "entryset": { - "csl": null, - "notes": "Not supported.", - "source": "biblatex", - "type": "entrykey" - }, - "entrysubtype": { - "csl": null, - "notes": "Not supported.", - "source": "biblatex", - "type": "literal" - }, - "epilog": { - "csl": null, - "source": "iopart-num.bst" - }, - "eprint": { - "csl": null, - "notes": "Mapped to `PMID` if `eprinttype` is \"PubMed\".", - "source": "biblatex", - "type": "verbatim" - }, - "eprintclass": { - "csl": null, - "source": "biblatex", - "type": "literal" - }, - "eprints": { - "csl": null, - "source": "databib.bst" - }, - "eprinttype": { - "csl": "archive", - "source": "biblatex", - "type": "literal" - }, - "erratumeid": { - "csl": null, - "source": "ChemCommun.bst" - }, - "erratumgermanpages": { - "csl": null, - "source": "ChemCommun.bst" - }, - "erratumnumpages": { - "csl": null, - "source": "ChemCommun.bst" - }, - "erratumpages": { - "csl": null, - "source": "ChemCommun.bst" - }, - "erratumvolume": { - "csl": null, - "source": "ChemCommun.bst" - }, - "erratumyear": { - "csl": null, - "source": "ChemCommun.bst" - }, - "eventdate": { - "csl": "event-date", - "source": "biblatex", - "type": "date" - }, - "eventtitle": { - "csl": "event-title", - "notes": "Supercedes `event` in CSL v1.0.2.", - "source": "biblatex", - "type": "literal" - }, - "eventtitleaddon": { - "csl": null, - "source": "biblatex", - "type": "literal" - }, - "eventyear": { - "csl": null, - "source": "bath.bst" - }, - "execute": { - "csl": null, - "notes": "Not supported.", - "source": "biblatex", - "type": "code" - }, - "faddress": { - "csl": null, - "source": "achicago.bst" - }, - "fakeset": { - "csl": null, - "source": "biblatex.bst" - }, - "fax": { - "csl": null, - "source": "adrbirthday.bst" - }, - "file": { - "csl": null, - "source": "biblatex", - "type": "verbatim" - }, - "firstkey": { - "csl": null, - "source": "apacite.bst" - }, - "fjournal": { - "csl": null, - "source": "ijmart.bst" - }, - "flanguage": { - "csl": null, - "source": "achicago.bst" - }, - "font": { - "csl": null, - "source": "nederlands.bst" - }, - "foreword": { - "csl": null, - "source": "biblatex", - "type": "name" - }, - "founder": { - "csl": null, - "source": "jurabib.bst" - }, - "fpublisher": { - "csl": null, - "source": "achicago.bst" - }, - "ftitle": { - "csl": null, - "source": "achicago.bst" - }, - "furtherresp": { - "csl": null, - "source": "abntex2-alf.bst" - }, - "fyear": { - "csl": null, - "source": "achicago.bst" - }, - "gender": { - "csl": null, - "notes": "Not supported.", - "source": "biblatex", - "type": "literal" - }, - "germanpages": { - "csl": null, - "source": "ChemCommun.bst" - }, - "group": { - "csl": null, - "source": "glsplain.bst" - }, - "heading": { - "csl": null, - "source": "glsplain.bst" - }, - "hereafter": { - "csl": null, - "source": "opcit.bst" - }, - "holder": { - "csl": null, - "source": "biblatex", - "type": "name" - }, - "howcited": { - "csl": null, - "source": "jox.bst" - }, - "howpublished": { - "csl": null, - "notes": "Check if a URL is contained.", - "source": "bibtex", - "type": "literal" - }, - "hyphenation": { - "alias": "langid", - "csl": "language", - "source": "biblatex", - "type": "literal" - }, - "ids": { - "csl": null, - "source": "biblatex", - "type": "entrykey" - }, - "illustrated": { - "csl": null, - "source": "abntex2-alf.bst" - }, - "illustrations": { - "csl": null, - "source": "bookdb.bst" - }, - "illustrator": { - "csl": null, - "source": "achicago.bst" - }, - "indexsorttitle": { - "csl": null, - "notes": "Not supported.", - "source": "biblatex", - "type": "literal" - }, - "indextitle": { - "csl": null, - "source": "biblatex", - "type": "literal" - }, - "institution": { - "csl": "publisher", - "source": "bibtex", - "type": "literal" - }, - "introduction": { - "csl": null, - "source": "biblatex", - "type": "name" - }, - "intype": { - "csl": null, - "source": "IEEEtran.bst" - }, - "inventor": { - "csl": null, - "source": "vancouver.bst" - }, - "ipc": { - "csl": null, - "source": "gost2003.bst" - }, - "isan": { - "csl": null, - "source": "biblatex", - "type": "literal" - }, - "isbn": { - "csl": "ISBN", - "source": "biblatex", - "type": "literal" - }, - "ismn": { - "csl": null, - "source": "biblatex", - "type": "literal" - }, - "iso-abbreviation": { - "csl": null, - "source": "abntex2-alf.bst" - }, - "iso-author-punctuation": { - "csl": null, - "source": "abntex2-alf.bst" - }, - "iso-date-place": { - "csl": null, - "source": "abntex2-alf.bst" - }, - "isrn": { - "csl": null, - "source": "biblatex", - "type": "literal" - }, - "issn": { - "csl": "ISSN", - "source": "biblatex", - "type": "literal" - }, - "issue": { - "csl": "issue", - "source": "biblatex", - "type": "literal" - }, - "issuesubtitle": { - "csl": null, - "source": "biblatex", - "type": "literal" - }, - "issuetitle": { - "csl": null, - "source": "biblatex", - "type": "literal" - }, - "issuetitleaddon": { - "csl": null, - "source": "biblatex", - "type": "literal" - }, - "iswc": { - "csl": null, - "source": "biblatex", - "type": "literal" - }, - "jfmnumber": { - "csl": null, - "source": "aomalpha.bst" - }, - "journal": { - "alias": "journaltitle", - "csl": "container-title", - "source": "bibtex", - "type": "literal" - }, - "journalsubtitle": { - "csl": null, - "notes": "It should be concatenated to the `container-title`.", - "source": "biblatex", - "type": "literal" - }, - "journaltie": { - "csl": null, - "source": "tugboat.bst" - }, - "journaltitle": { - "csl": "container-title", - "source": "biblatex", - "type": "literal" - }, - "journaltitleaddon": { - "csl": null, - "source": "biblatex", - "type": "literal" - }, - "juraauthor": { - "csl": null, - "source": "jox.bst" - }, - "juratitle": { - "csl": null, - "source": "jox.bst" - }, - "key": { - "alias": "sortkey", - "csl": null, - "notes": "Not supported.", - "source": "bibtex", - "type": "literal" - }, - "keywords": { - "csl": null, - "source": "biblatex", - "type": "keyword" - }, - "label": { - "csl": null, - "source": "biblatex", - "type": "literal" - }, - "lang": { - "csl": null, - "source": "hustthesis.bst" - }, - "langid": { - "csl": "language", - "notes": "The language id of the bibliography entry. The identifier must be a language name known to the babel/polyglossia packages. It should be converted to ISO 639-1 language code in CSL.", - "source": "biblatex", - "type": "literal" - }, - "langidopts": { - "csl": null, - "source": "biblatex", - "type": "literal" - }, - "language": { - "csl": null, - "notes": "The `language` field in `biblatex` has no special internal meaning thus it is used only when langid is missing.", - "source": "biblatex", - "type": "key" - }, - "lastaccessed": { - "csl": "accessed", - "source": "ACM-Reference-Format.bst" - }, - "lastchecked": { - "csl": "accessed", - "source": "apacite.bst" - }, - "lccn": { - "csl": null, - "source": "is-abbrv.bst" - }, - "library": { - "csl": null, - "source": "biblatex", - "type": "literal" - }, - "lista": { - "csl": null, - "source": "biblatex", - "type": "literal" - }, - "listb": { - "csl": null, - "source": "biblatex", - "type": "literal" - }, - "listc": { - "csl": null, - "source": "biblatex", - "type": "literal" - }, - "listd": { - "csl": null, - "source": "biblatex", - "type": "literal" - }, - "liste": { - "csl": null, - "source": "biblatex", - "type": "literal" - }, - "listf": { - "csl": null, - "source": "biblatex", - "type": "literal" - }, - "littype": { - "csl": null, - "source": "seuthesix.bst" - }, - "location": { - "csl": "publisher-place", - "source": "biblatex", - "type": "literal" - }, - "madadurltest": { - "csl": null, - "source": "alpha-persian.bst" - }, - "main": { - "csl": null, - "source": "figbib.bst" - }, - "main1": { - "csl": null, - "source": "figbib1.bst" - }, - "mainsubtitle": { - "csl": null, - "source": "biblatex", - "type": "literal" - }, - "maintitle": { - "csl": null, - "source": "biblatex", - "type": "literal" - }, - "maintitleaddon": { - "csl": null, - "source": "biblatex", - "type": "literal" - }, - "majorcode": { - "csl": null, - "source": "gost2003.bst" - }, - "marginnote": { - "csl": null, - "source": "abntex2-alf.bst" - }, - "mark": { - "csl": null, - "source": "gbt7714-numerical.bst" - }, - "max.best.papers": { - "csl": null, - "source": "bestpapers-export.bst" - }, - "mcitetail": { - "csl": null, - "source": "apsrmpM.bst" - }, - "media": { - "csl": "medium", - "source": "gost2003.bst" - }, - "medium": { - "csl": "medium", - "source": "gbt7714-numerical.bst" - }, - "meeting": { - "csl": null, - "source": "amsra.bst" - }, - "misctitle": { - "csl": null, - "source": "aasjournal.bst" - }, - "miscyear": { - "csl": null, - "source": "seuthesis.bst" - }, - "mobile": { - "csl": null, - "source": "adrbirthday.bst" - }, - "modifydate": { - "csl": null, - "source": "seuthesis.bst" - }, - "month": { - "csl": null, - "notes": "Used only when `date` is empty.", - "source": "bibtex", - "type": "literal" - }, - "monthfiled": { - "csl": null, - "source": "IEEEtran.bst" - }, - "mrnumber": { - "csl": null, - "source": "amsplain.bst" - }, - "name": { - "csl": null, - "source": "adrbirthday.bst" - }, - "namea": { - "csl": null, - "source": "biblatex", - "type": "name" - }, - "nameaddon": { - "csl": null, - "source": "biblatex", - "type": "literal" - }, - "nameatype": { - "csl": null, - "source": "biblatex", - "type": "key" - }, - "nameb": { - "csl": null, - "source": "biblatex", - "type": "name" - }, - "namebtype": { - "csl": null, - "source": "biblatex", - "type": "key" - }, - "namec": { - "csl": null, - "source": "biblatex", - "type": "name" - }, - "namectype": { - "csl": null, - "source": "biblatex", - "type": "key" - }, - "nationality": { - "csl": null, - "source": "IEEEtran.bst" - }, - "nbirthday": { - "csl": null, - "source": "adrbirthday.bst" - }, - "newpage": { - "csl": null, - "source": "tugboat.bst" - }, - "newspaper": { - "csl": "container-title", - "source": "seuthesix.bst" - }, - "nickname": { - "csl": null, - "source": "address-html.bst" - }, - "nihms": { - "csl": null, - "source": "apacite.bst" - }, - "noed": { - "csl": null, - "source": "jox.bst" - }, - "normal": { - "csl": null, - "source": "bookdb.bst" - }, - "normalauthor": { - "csl": null, - "source": "seuthesis.bst" - }, - "normaleditor": { - "csl": null, - "source": "seuthesis.bst" - }, - "note": { - "csl": "note", - "source": "bibtex", - "type": "literal" - }, - "nowarning": { - "csl": null, - "source": "tugboat.bst" - }, - "number": { - "csl": "number", - "notes": "It is mapped to `issue` in `@ariticle` but to `number` in `@patent` or `@report`.", - "source": "bibtex", - "type": "literal" - }, - "numpages": { - "csl": null, - "source": "ACM-Reference-Format.bst" - }, - "oaddress": { - "csl": null, - "source": "achicago.bst" - }, - "options": { - "csl": null, - "notes": "Not supported.", - "source": "biblatex", - "type": "option" - }, - "opublisher": { - "csl": null, - "source": "achicago.bst" - }, - "org-short": { - "csl": null, - "source": "abntex2-alf.bst" - }, - "organization": { - "csl": "publisher", - "notes": "It is mapped to `author` (in `institution` property) if possible.", - "source": "bibtex", - "type": "literal" - }, - "origdate": { - "csl": "original-date", - "source": "biblatex", - "type": "date" - }, - "originaladdress": { - "csl": "original-publisher-place", - "source": "apacite.bst" - }, - "originalbooktitle": { - "csl": null, - "source": "apacite.bst" - }, - "originaledition": { - "csl": null, - "source": "apacite.bst" - }, - "originaleditor": { - "csl": null, - "source": "apacite.bst" - }, - "originaljournal": { - "csl": null, - "source": "apacite.bst" - }, - "originalnumber": { - "csl": null, - "source": "apacite.bst" - }, - "originalpages": { - "csl": null, - "source": "apacite.bst" - }, - "originalpublisher": { - "csl": "original-publisher", - "source": "apacite.bst" - }, - "originalvolume": { - "csl": null, - "source": "apacite.bst" - }, - "originalyear": { - "csl": "original-date", - "source": "apacite.bst" - }, - "origlanguage": { - "csl": null, - "source": "biblatex", - "type": "key" - }, - "origlocation": { - "csl": "original-publisher-place", - "source": "biblatex", - "type": "literal" - }, - "origpublisher": { - "csl": "original-publisher", - "source": "biblatex", - "type": "literal" - }, - "origtitle": { - "csl": "original-title", - "source": "biblatex", - "type": "literal" - }, - "oyear": { - "csl": null, - "source": "achicago.bst" - }, - "pagename": { - "csl": null, - "source": "abntex2-alf.bst" - }, - "pages": { - "csl": "page", - "source": "bibtex", - "type": "range" - }, - "pagetotal": { - "csl": "number-of-pages", - "source": "biblatex", - "type": "literal" - }, - "pagination": { - "csl": null, - "source": "biblatex", - "type": "key" - }, - "paper": { - "csl": null, - "source": "IEEEtran.bst" - }, - "part": { - "csl": "part", - "source": "biblatex", - "type": "literal" - }, - "patentid": { - "csl": null, - "source": "seuthesis.bst" - }, - "pdf": { - "alias": "file", - "csl": null, - "source": "biblatex", - "type": "verbatim" - }, - "phone": { - "csl": null, - "source": "adrbirthday.bst" - }, - "pid": { - "csl": null, - "source": "seuthesix.bst" - }, - "pii": { - "csl": null, - "source": "amsra.bst" - }, - "pmcid": { - "csl": "PMCID", - "source": "apacite.bst" - }, - "prebibitem": { - "csl": null, - "source": "tugboat.bst" - }, - "preface": { - "csl": null, - "source": "bookdb.bst" - }, - "preprint": { - "csl": null, - "source": "amsra.bst" - }, - "presort": { - "csl": null, - "notes": "Not supported.", - "source": "biblatex", - "type": "literal" - }, - "price": { - "csl": null, - "source": "is-abbrv.bst" - }, - "primaryclass": { - "alias": "eprintclass", - "csl": null, - "source": "biblatex", - "type": "literal" - }, - "printing": { - "csl": null, - "source": "dk-abbrv.bst" - }, - "prioritycountry": { - "csl": null, - "source": "gost2003.bst" - }, - "prioritydate": { - "csl": null, - "source": "gost2003.bst" - }, - "prioritynumber": { - "csl": null, - "source": "gost2003.bst" - }, - "pseudonym": { - "csl": null, - "source": "jox.bst" - }, - "publication": { - "csl": null, - "source": "gost2003.bst" - }, - "publicationdate": { - "csl": null, - "source": "gost2003.bst" - }, - "publisher": { - "csl": "publisher", - "source": "bibtex", - "type": "literal" - }, - "pubmed": { - "csl": "PMID", - "source": "urlbst" - }, - "pubstate": { - "csl": null, - "source": "biblatex", - "type": "key" - }, - "related": { - "csl": null, - "notes": "Not supported.", - "source": "biblatex", - "type": "entrykey" - }, - "relatedoptions": { - "csl": null, - "notes": "Not supported.", - "source": "biblatex", - "type": "option" - }, - "relatedstring": { - "csl": null, - "notes": "Not supported.", - "source": "biblatex", - "type": "literal" - }, - "relatedtype": { - "csl": null, - "notes": "Not supported.", - "source": "biblatex", - "type": "literal" - }, - "reprinted-from": { - "csl": null, - "source": "abntex2-alf.bst" - }, - "reprinted-text": { - "csl": null, - "source": "abntex2-alf.bst" - }, - "reprinttitle": { - "csl": null, - "source": "biblatex", - "type": "literal" - }, - "requestdate": { - "csl": null, - "source": "gost2003.bst" - }, - "requestnumber": { - "csl": null, - "source": "gost2003.bst" - }, - "responsible": { - "csl": null, - "source": "rusnat.bst" - }, - "review": { - "csl": null, - "source": "amsra.bst" - }, - "revision": { - "csl": null, - "source": "IEEEtran.bst" - }, - "school": { - "alias": "institution", - "csl": "publisher", - "source": "bibtex", - "type": "literal" - }, - "score": { - "csl": null, - "source": "bestpapers-export.bst" - }, - "section": { - "csl": null, - "source": "abntex2-alf.bst" - }, - "series": { - "csl": "collection-title", - "source": "bibtex", - "type": "literal" - }, - "seriesedition": { - "csl": null, - "source": "achicago.bst" - }, - "short": { - "csl": null, - "source": "glsplain.bst" - }, - "shortarchive": { - "csl": null, - "source": "jurabib.bst" - }, - "shortauthor": { - "csl": null, - "source": "biblatex", - "type": "name" - }, - "shorteditor": { - "csl": null, - "source": "biblatex", - "type": "name" - }, - "shorthand": { - "csl": null, - "notes": "Not supported.", - "source": "biblatex", - "type": "literal" - }, - "shorthandintro": { - "csl": null, - "notes": "Not supported.", - "source": "biblatex", - "type": "literal" - }, - "shortjournal": { - "csl": "container-title-short", - "source": "biblatex", - "type": "literal" - }, - "shortseries": { - "csl": null, - "source": "biblatex", - "type": "literal" - }, - "shortsubarchive": { - "csl": null, - "source": "jurabib.bst" - }, - "shorttitle": { - "csl": "title-short", - "source": "biblatex", - "type": "literal" - }, - "sig1": { - "csl": null, - "source": "jurabib.bst" - }, - "sig2": { - "csl": null, - "source": "jurabib.bst" - }, - "sig3": { - "csl": null, - "source": "jurabib.bst" - }, - "sig4": { - "csl": null, - "source": "jurabib.bst" - }, - "size": { - "csl": null, - "source": "bookdb.bst" - }, - "slaccitation": { - "csl": null, - "source": "apsrev4-2.bst" - }, - "sort-short": { - "csl": null, - "source": "glsplain.bst" - }, - "sort-word": { - "csl": null, - "source": "glsplain.bst" - }, - "sortas": { - "csl": null, - "source": "adrbirthday.bst" - }, - "sortkey": { - "csl": null, - "notes": "Not supported.", - "source": "biblatex", - "type": "literal" - }, - "sortname": { - "csl": null, - "notes": "Not supported.", - "source": "biblatex", - "type": "name" - }, - "sortshorthand": { - "csl": null, - "notes": "Not supported.", - "source": "biblatex", - "type": "literal" - }, - "sorttitle": { - "csl": null, - "notes": "Not supported.", - "source": "biblatex", - "type": "literal" - }, - "sortyear": { - "csl": null, - "source": "biblatex", - "type": "integer" - }, - "source": { - "csl": null, - "source": "figbib.bst" - }, - "source1": { - "csl": null, - "source": "figbib1.bst" - }, - "specialitycode": { - "csl": null, - "source": "gost2003.bst" - }, - "ssedition": { - "csl": null, - "source": "jox.bst" - }, - "standard": { - "csl": null, - "source": "udesoftec.bst" - }, - "startnumber": { - "csl": null, - "source": "seuthesis.bst" - }, - "startvolume": { - "csl": null, - "source": "seuthesis.bst" - }, - "startyear": { - "csl": null, - "source": "seuthesis.bst" - }, - "state": { - "csl": null, - "source": "address-html.bst" - }, - "status": { - "csl": null, - "source": "amsra.bst" - }, - "stdcode": { - "csl": null, - "source": "seuthesix.bst" - }, - "stitle": { - "csl": null, - "source": "jox.bst" - }, - "street": { - "csl": null, - "source": "adrbirthday.bst" - }, - "subarchive": { - "csl": null, - "source": "jurabib.bst" - }, - "subtitle": { - "csl": null, - "source": "biblatex", - "type": "literal" - }, - "symposium": { - "csl": null, - "source": "apacite.bst" - }, - "text": { - "csl": null, - "source": "apacite.bst" - }, - "timestamp": { - "csl": null, - "source": "export.bst" - }, - "title": { - "csl": "title", - "source": "bibtex", - "type": "literal" - }, - "titleaddon": { - "csl": null, - "source": "biblatex", - "type": "literal" - }, - "titlenote": { - "csl": null, - "source": "aomalpha.bst" - }, - "totalpages": { - "csl": null, - "source": "aomalpha.bst" - }, - "transissue": { - "csl": null, - "source": "iopart-num.bst" - }, - "transjournal": { - "csl": null, - "source": "iopart-num.bst" - }, - "translation": { - "csl": null, - "source": "apsrev4-2.bst" - }, - "translator": { - "csl": "translator", - "source": "biblatex", - "type": "name" - }, - "transnumber": { - "csl": null, - "source": "iopart-num.bst" - }, - "transpages": { - "csl": null, - "source": "iopart-num.bst" - }, - "transsection": { - "csl": null, - "source": "iopart-num.bst" - }, - "transvolume": { - "csl": null, - "source": "iopart-num.bst" - }, - "transyear": { - "csl": null, - "source": "iopart-num.bst" - }, - "type": { - "csl": "genre", - "source": "bibtex", - "type": "key" - }, - "typeoflit": { - "csl": null, - "source": "seuthesis.bst" - }, - "umfnumber": { - "csl": null, - "source": "thesnumb.bst" - }, - "updated": { - "csl": null, - "source": "vancouver.bst" - }, - "url": { - "csl": "URL", - "source": "biblatex", - "type": "uri" - }, - "urlaccessdate": { - "csl": "accessed", - "source": "abntex2-alf.bst" - }, - "urldate": { - "csl": "accessed", - "source": "biblatex", - "type": "date" - }, - "urlnewline": { - "csl": null, - "source": "tugboat.bst" - }, - "urltype": { - "csl": null, - "source": "asmeconf.bst" - }, - "urlyear": { - "csl": null, - "source": "bath.bst" - }, - "urn": { - "csl": null, - "source": "export.bst" - }, - "usera": { - "csl": null, - "source": "biblatex", - "type": "literal" - }, - "userb": { - "csl": null, - "source": "biblatex", - "type": "literal" - }, - "userc": { - "csl": null, - "source": "biblatex", - "type": "literal" - }, - "userd": { - "csl": null, - "source": "biblatex", - "type": "literal" - }, - "usere": { - "csl": null, - "source": "biblatex", - "type": "literal" - }, - "userf": { - "csl": null, - "source": "biblatex", - "type": "literal" - }, - "value": { - "csl": null, - "source": "bookdb.bst" - }, - "venue": { - "csl": "event-place", - "source": "biblatex", - "type": "literal" - }, - "verba": { - "csl": null, - "source": "biblatex", - "type": "verbatim" - }, - "verbb": { - "csl": null, - "source": "biblatex", - "type": "verbatim" - }, - "verbc": { - "csl": null, - "source": "biblatex", - "type": "verbatim" - }, - "version": { - "csl": "version", - "source": "biblatex", - "type": "literal" - }, - "versiontype": { - "csl": null, - "source": "asmeconf.bst" - }, - "volformat": { - "csl": null, - "source": "jox.bst" - }, - "volume": { - "csl": "volume", - "source": "bibtex", - "type": "integer" - }, - "volumes": { - "csl": "number-of-volumes", - "source": "biblatex", - "type": "integer" - }, - "volumetitle": { - "csl": null, - "source": "iopart-num.bst" - }, - "word": { - "csl": null, - "source": "vancouver.bst" - }, - "xdata": { - "csl": null, - "notes": "inherits fields from other items.", - "source": "biblatex", - "type": "entrykey" - }, - "xid": { - "csl": null, - "source": "amsra.bst" - }, - "xref": { - "csl": null, - "notes": "Establishes a parent-child relationship in biblatex, but without inheriting data => no need to parse this.", - "source": "biblatex", - "type": "entrykey" - }, - "year": { - "csl": null, - "notes": "Used only when `date` is empty.", - "source": "bibtex", - "type": "date" - }, - "year-presented": { - "csl": null, - "source": "abntex2-alf.bst" - }, - "yearcomp": { - "csl": null, - "source": "achicago.bst" - }, - "yearfiled": { - "csl": null, - "source": "IEEEtran.bst" - }, - "zblnumber": { - "csl": null, - "source": "aomalpha.bst" - }, - "zip": { - "csl": null, - "source": "adrbirthday.bst" - } - }, - "macros": { - "jan": { - "value": "1", - "notes": "Use numeric form for easy conversion.", - "source": "bibtex" - }, - "feb": { - "value": "2", - "source": "bibtex" - }, - "mar": { - "value": "3", - "source": "bibtex" - }, - "apr": { - "value": "4", - "source": "bibtex" - }, - "may": { - "value": "5", - "source": "bibtex" - }, - "jun": { - "value": "6", - "source": "bibtex" - }, - "jul": { - "value": "7", - "source": "bibtex" - }, - "aug": { - "value": "8", - "source": "bibtex" - }, - "sep": { - "value": "9", - "source": "bibtex" - }, - "oct": { - "value": "10", - "source": "bibtex" - }, - "nov": { - "value": "11", - "source": "bibtex" - }, - "dec": { - "value": "12", - "source": "bibtex" - }, - "acmcs": { - "value": "ACM Computing Surveys", - "source": "bibtex" - }, - "acta": { - "value": "Acta Informatica", - "source": "bibtex" - }, - "cacm": { - "value": "Communications of the ACM", - "source": "bibtex" - }, - "ibmjrd": { - "value": "IBM Journal of Research and Development", - "source": "bibtex" - }, - "ibmsj": { - "value": "IBM Systems Journal", - "source": "bibtex" - }, - "ieeese": { - "value": "IEEE Transactions on Software Engineering", - "source": "bibtex" - }, - "ieeetc": { - "value": "IEEE Transactions on Computers", - "source": "bibtex" - }, - "ieeetcad": { - "value": "IEEE Transactions on Computer-Aided Design of Integrated Circuits", - "source": "bibtex" - }, - "ipl": { - "value": "Information Processing Letters", - "source": "bibtex" - }, - "jacm": { - "value": "Journal of the ACM", - "source": "bibtex" - }, - "jcss": { - "value": "Journal of Computer and System Sciences", - "source": "bibtex" - }, - "scp": { - "value": "Science of Computer Programming", - "source": "bibtex" - }, - "sicomp": { - "value": "SIAM Journal on Computing", - "source": "bibtex" - }, - "tocs": { - "value": "ACM Transactions on Computer Systems", - "source": "bibtex" - }, - "tods": { - "value": "ACM Transactions on Database Systems", - "source": "bibtex" - }, - "tog": { - "value": "ACM Transactions on Graphics", - "source": "bibtex" - }, - "toms": { - "value": "ACM Transactions on Mathematical Software", - "source": "bibtex" - }, - "toois": { - "value": "ACM Transactions on Office Information Systems", - "source": "bibtex" - }, - "toplas": { - "value": "ACM Transactions on Programming Languages and Systems", - "source": "bibtex" - }, - "tcs": { - "value": "Theoretical Computer Science", - "source": "bibtex" - } - } -} diff --git a/biblio/citation-style-language/citeproc-bib-data.lua b/biblio/citation-style-language/citeproc-bib-data.lua new file mode 100644 index 0000000000..dafd3d05b4 --- /dev/null +++ b/biblio/citation-style-language/citeproc-bib-data.lua @@ -0,0 +1,1759 @@ +-- This file is generated from citeproc-bib-data.json by update-bib-date.py + +return { + ["description"] = "Bib CSL mapping", + ["types"] = { + ["archival"] = { + ["csl"] = "collection", + }, + ["archive"] = { + ["csl"] = "collection", + }, + ["article"] = { + ["csl"] = "article-journal", + }, + ["artifactdataset"] = { + ["csl"] = "dataset", + }, + ["artifactsoftware"] = { + ["csl"] = "software", + }, + ["artwork"] = { + ["csl"] = "graphic", + }, + ["atlas"] = { + ["csl"] = nil, + }, + ["audio"] = { + ["csl"] = "song", + }, + ["bachelor"] = { + ["csl"] = "thesis", + }, + ["bibnote"] = { + ["csl"] = nil, + }, + ["book"] = { + ["csl"] = "book", + }, + ["bookinbook"] = { + ["csl"] = "chapter", + }, + ["booklet"] = { + ["csl"] = "pamphlet", + }, + ["brochure"] = { + ["csl"] = "pamphlet", + }, + ["cconference"] = { + ["csl"] = nil, + }, + ["collection"] = { + ["csl"] = "book", + }, + ["comment"] = { + ["csl"] = nil, + }, + ["commentary"] = { + ["csl"] = "book", + }, + ["commented"] = { + ["csl"] = nil, + }, + ["conference"] = { + ["csl"] = "paper-conference", + }, + ["ctan"] = { + ["csl"] = "software", + }, + ["customa"] = { + ["csl"] = nil, + }, + ["customb"] = { + ["csl"] = nil, + }, + ["customc"] = { + ["csl"] = nil, + }, + ["customd"] = { + ["csl"] = nil, + }, + ["custome"] = { + ["csl"] = nil, + }, + ["customf"] = { + ["csl"] = nil, + }, + ["database"] = { + ["csl"] = "dataset", + }, + ["dataset"] = { + ["csl"] = "dataset", + }, + ["dictionary"] = { + ["csl"] = "book", + }, + ["docthesis"] = { + ["csl"] = "thesis", + }, + ["electronic"] = { + ["csl"] = "webpage", + }, + ["eulegislation"] = { + ["csl"] = "legislation", + }, + ["footnote"] = { + ["csl"] = nil, + }, + ["game"] = { + ["csl"] = "software", + }, + ["govpub"] = { + ["csl"] = "regulation", + }, + ["habthesis"] = { + ["csl"] = "thesis", + }, + ["heading"] = { + ["csl"] = nil, + }, + ["hidden"] = { + ["csl"] = nil, + }, + ["image"] = { + ["csl"] = "graphic", + }, + ["inbook"] = { + ["csl"] = "chapter", + }, + ["incollection"] = { + ["csl"] = "chapter", + }, + ["inloosecollection"] = { + ["csl"] = "chapter", + }, + ["inpress"] = { + ["csl"] = "article", + }, + ["inproceedings"] = { + ["csl"] = "paper-conference", + }, + ["inreference"] = { + ["csl"] = "entry", + }, + ["inserialcollection"] = { + ["csl"] = nil, + }, + ["internet"] = { + ["csl"] = "webpage", + }, + ["journalpart"] = { + ["csl"] = nil, + }, + ["journals"] = { + ["csl"] = "periodical", + }, + ["jurisdiction"] = { + ["csl"] = nil, + }, + ["jurthesis"] = { + ["csl"] = "thesis", + }, + ["legal"] = { + ["csl"] = "treaty", + }, + ["legislation"] = { + ["csl"] = "legislation", + }, + ["letter"] = { + ["csl"] = "personal_communication", + }, + ["lexicon"] = { + ["csl"] = "book", + }, + ["majorthesis"] = { + ["csl"] = "thesis", + }, + ["manual"] = { + ["csl"] = "report", + }, + ["map"] = { + ["csl"] = "map", + }, + ["mastersthesis"] = { + ["csl"] = "thesis", + }, + ["masterthesis"] = { + ["csl"] = "thesis", + }, + ["minorthesis"] = { + ["csl"] = "thesis", + }, + ["misc"] = { + ["csl"] = "document", + }, + ["monograph"] = { + ["csl"] = "book", + }, + ["monography"] = { + ["csl"] = "book", + }, + ["movie"] = { + ["csl"] = "motion_picture", + }, + ["music"] = { + ["csl"] = "song", + }, + ["mvbook"] = { + ["csl"] = "book", + }, + ["mvcollection"] = { + ["csl"] = "book", + }, + ["mvproceedings"] = { + ["csl"] = "book", + }, + ["mvreference"] = { + ["csl"] = "book", + }, + ["news"] = { + ["csl"] = "article-newspaper", + }, + ["newspaper"] = { + ["csl"] = "article-newspaper", + }, + ["online"] = { + ["csl"] = "webpage", + }, + ["other"] = { + ["csl"] = nil, + }, + ["patent"] = { + ["csl"] = "patent", + }, + ["performance"] = { + ["csl"] = "performance", + }, + ["periodical"] = { + ["csl"] = "periodical", + }, + ["phdthesis"] = { + ["csl"] = "thesis", + }, + ["preamble"] = { + ["csl"] = nil, + }, + ["preprint"] = { + ["csl"] = "article", + }, + ["presentation"] = { + ["csl"] = "speech", + }, + ["proceedings"] = { + ["csl"] = "book", + }, + ["program"] = { + ["csl"] = "software", + }, + ["reference"] = { + ["csl"] = "book", + }, + ["report"] = { + ["csl"] = "report", + }, + ["repository"] = { + ["csl"] = nil, + }, + ["review"] = { + ["csl"] = "review", + }, + ["set"] = { + ["csl"] = nil, + }, + ["setup"] = { + ["csl"] = nil, + }, + ["software"] = { + ["csl"] = "software", + }, + ["standard"] = { + ["csl"] = "standard", + }, + ["string"] = { + ["csl"] = nil, + }, + ["suppbook"] = { + ["csl"] = "chapter", + }, + ["suppcollection"] = { + ["csl"] = "chapter", + }, + ["suppperiodical"] = { + ["csl"] = "article", + }, + ["techreport"] = { + ["csl"] = "report", + }, + ["techstandard"] = { + ["csl"] = "standard", + }, + ["thesis"] = { + ["csl"] = "thesis", + }, + ["uklegislation"] = { + ["csl"] = "legislation", + }, + ["unpublished"] = { + ["csl"] = "manuscript", + }, + ["video"] = { + ["csl"] = "motion_picture", + }, + ["webpage"] = { + ["csl"] = "webpage", + }, + ["website"] = { + ["csl"] = nil, + }, + ["www"] = { + ["csl"] = "webpage", + }, + ["xdata"] = { + ["csl"] = nil, + }, + }, + ["fields"] = { + ["abstract"] = { + ["csl"] = "abstract", + ["type"] = "literal", + }, + ["account"] = { + ["csl"] = nil, + }, + ["acronym"] = { + ["csl"] = nil, + }, + ["add"] = { + ["csl"] = nil, + }, + ["add1"] = { + ["csl"] = nil, + }, + ["addendum"] = { + ["csl"] = nil, + ["type"] = "literal", + }, + ["address"] = { + ["csl"] = "publisher-place", + ["type"] = "literal", + }, + ["adsurl"] = { + ["csl"] = nil, + }, + ["advisor"] = { + ["csl"] = nil, + }, + ["afterword"] = { + ["csl"] = nil, + ["type"] = "name", + }, + ["annotate"] = { + ["csl"] = "note", + }, + ["annotation"] = { + ["csl"] = "note", + ["type"] = "literal", + }, + ["annotator"] = { + ["csl"] = nil, + ["type"] = "name", + }, + ["annote"] = { + ["csl"] = "note", + ["type"] = "literal", + }, + ["annotelanguage"] = { + ["csl"] = nil, + }, + ["applicant"] = { + ["csl"] = nil, + }, + ["archive"] = { + ["csl"] = "archive", + }, + ["archiveprefix"] = { + ["csl"] = "archive", + ["type"] = "literal", + }, + ["archname"] = { + ["csl"] = "archive", + }, + ["articleno"] = { + ["csl"] = nil, + }, + ["arxiv"] = { + ["csl"] = nil, + }, + ["assignee"] = { + ["csl"] = nil, + }, + ["author"] = { + ["csl"] = "author", + ["type"] = "name", + }, + ["authorcountry"] = { + ["csl"] = nil, + }, + ["authorfa"] = { + ["csl"] = nil, + }, + ["authortype"] = { + ["csl"] = nil, + ["type"] = "key", + }, + ["bibsource"] = { + ["csl"] = nil, + }, + ["biburl"] = { + ["csl"] = nil, + }, + ["binding"] = { + ["csl"] = nil, + }, + ["birthday"] = { + ["csl"] = nil, + }, + ["birthyear"] = { + ["csl"] = nil, + }, + ["bookaddress"] = { + ["csl"] = nil, + }, + ["bookauthor"] = { + ["csl"] = "container-author", + ["type"] = "name", + }, + ["booklanguage"] = { + ["csl"] = nil, + }, + ["bookpages"] = { + ["csl"] = nil, + }, + ["bookpagination"] = { + ["csl"] = nil, + ["type"] = "key", + }, + ["booksubtitle"] = { + ["csl"] = nil, + ["type"] = "literal", + }, + ["booktitle"] = { + ["csl"] = "container-title", + ["type"] = "literal", + }, + ["booktitleaddon"] = { + ["csl"] = nil, + ["type"] = "literal", + }, + ["caption"] = { + ["csl"] = nil, + }, + ["caption1"] = { + ["csl"] = nil, + }, + ["cartographer"] = { + ["csl"] = nil, + }, + ["casenumber"] = { + ["csl"] = nil, + }, + ["category"] = { + ["csl"] = nil, + }, + ["cellular"] = { + ["csl"] = nil, + }, + ["chair"] = { + ["csl"] = nil, + }, + ["chapter"] = { + ["csl"] = "chapter-number", + ["type"] = "literal", + }, + ["citedate"] = { + ["csl"] = nil, + }, + ["city"] = { + ["csl"] = nil, + }, + ["code"] = { + ["csl"] = nil, + }, + ["coden"] = { + ["csl"] = nil, + }, + ["collaboration"] = { + ["csl"] = nil, + }, + ["collator"] = { + ["csl"] = nil, + }, + ["commentator"] = { + ["csl"] = nil, + ["type"] = "name", + }, + ["commit"] = { + ["csl"] = nil, + }, + ["compiler"] = { + ["csl"] = nil, + }, + ["condition"] = { + ["csl"] = nil, + }, + ["conference-location"] = { + ["csl"] = nil, + }, + ["conference-number"] = { + ["csl"] = nil, + }, + ["conference-year"] = { + ["csl"] = nil, + }, + ["copy"] = { + ["csl"] = nil, + }, + ["country"] = { + ["csl"] = nil, + }, + ["credits"] = { + ["csl"] = nil, + }, + ["crossref"] = { + ["csl"] = nil, + ["type"] = "entrykey", + }, + ["ctrl-article-title"] = { + ["csl"] = nil, + }, + ["ctrl-chapter-title"] = { + ["csl"] = nil, + }, + ["ctrl-doi"] = { + ["csl"] = nil, + }, + ["ctrl-etal-firstonly"] = { + ["csl"] = nil, + }, + ["ctrl-etal-number"] = { + ["csl"] = nil, + }, + ["ctrl-link-doi"] = { + ["csl"] = nil, + }, + ["ctrl-use-doi-all"] = { + ["csl"] = nil, + }, + ["ctrl-use-title"] = { + ["csl"] = nil, + }, + ["dataset"] = { + ["csl"] = nil, + }, + ["date"] = { + ["csl"] = "issued", + ["type"] = "date", + }, + ["day"] = { + ["csl"] = nil, + }, + ["dayfiled"] = { + ["csl"] = nil, + }, + ["definition"] = { + ["csl"] = nil, + }, + ["department"] = { + ["csl"] = nil, + }, + ["description"] = { + ["csl"] = nil, + }, + ["designator"] = { + ["csl"] = nil, + }, + ["dimensions"] = { + ["csl"] = nil, + }, + ["dissyear"] = { + ["csl"] = nil, + }, + ["doi"] = { + ["csl"] = "DOI", + ["type"] = "verbatim", + }, + ["dticnumber"] = { + ["csl"] = nil, + }, + ["dummy"] = { + ["csl"] = nil, + }, + ["edition"] = { + ["csl"] = "edition", + ["type"] = "literal", + }, + ["editor"] = { + ["csl"] = "editor", + ["type"] = "name", + }, + ["editora"] = { + ["csl"] = nil, + ["type"] = "name", + }, + ["editoratype"] = { + ["csl"] = nil, + ["type"] = "key", + }, + ["editorb"] = { + ["csl"] = nil, + ["type"] = "name", + }, + ["editorbtype"] = { + ["csl"] = nil, + ["type"] = "key", + }, + ["editorc"] = { + ["csl"] = nil, + ["type"] = "name", + }, + ["editorctype"] = { + ["csl"] = nil, + ["type"] = "key", + }, + ["editortype"] = { + ["csl"] = nil, + ["type"] = "key", + }, + ["eid"] = { + ["csl"] = nil, + ["type"] = "literal", + }, + ["email"] = { + ["csl"] = nil, + }, + ["endnumber"] = { + ["csl"] = nil, + }, + ["endvolume"] = { + ["csl"] = nil, + }, + ["endyear"] = { + ["csl"] = nil, + }, + ["englishtitle"] = { + ["csl"] = nil, + }, + ["entryset"] = { + ["csl"] = nil, + ["type"] = "entrykey", + }, + ["entrysubtype"] = { + ["csl"] = nil, + ["type"] = "literal", + }, + ["epilog"] = { + ["csl"] = nil, + }, + ["eprint"] = { + ["csl"] = nil, + ["type"] = "verbatim", + }, + ["eprintclass"] = { + ["csl"] = nil, + ["type"] = "literal", + }, + ["eprints"] = { + ["csl"] = nil, + }, + ["eprinttype"] = { + ["csl"] = "archive", + ["type"] = "literal", + }, + ["erratumeid"] = { + ["csl"] = nil, + }, + ["erratumgermanpages"] = { + ["csl"] = nil, + }, + ["erratumnumpages"] = { + ["csl"] = nil, + }, + ["erratumpages"] = { + ["csl"] = nil, + }, + ["erratumvolume"] = { + ["csl"] = nil, + }, + ["erratumyear"] = { + ["csl"] = nil, + }, + ["eventdate"] = { + ["csl"] = "event-date", + ["type"] = "date", + }, + ["eventtitle"] = { + ["csl"] = "event-title", + ["type"] = "literal", + }, + ["eventtitleaddon"] = { + ["csl"] = nil, + ["type"] = "literal", + }, + ["eventyear"] = { + ["csl"] = nil, + }, + ["execute"] = { + ["csl"] = nil, + ["type"] = "code", + }, + ["faddress"] = { + ["csl"] = nil, + }, + ["fakeset"] = { + ["csl"] = nil, + }, + ["fax"] = { + ["csl"] = nil, + }, + ["file"] = { + ["csl"] = nil, + ["type"] = "verbatim", + }, + ["firstkey"] = { + ["csl"] = nil, + }, + ["fjournal"] = { + ["csl"] = nil, + }, + ["flanguage"] = { + ["csl"] = nil, + }, + ["font"] = { + ["csl"] = nil, + }, + ["foreword"] = { + ["csl"] = nil, + ["type"] = "name", + }, + ["founder"] = { + ["csl"] = nil, + }, + ["fpublisher"] = { + ["csl"] = nil, + }, + ["ftitle"] = { + ["csl"] = nil, + }, + ["furtherresp"] = { + ["csl"] = nil, + }, + ["fyear"] = { + ["csl"] = nil, + }, + ["gender"] = { + ["csl"] = nil, + ["type"] = "literal", + }, + ["germanpages"] = { + ["csl"] = nil, + }, + ["group"] = { + ["csl"] = nil, + }, + ["heading"] = { + ["csl"] = nil, + }, + ["hereafter"] = { + ["csl"] = nil, + }, + ["holder"] = { + ["csl"] = nil, + ["type"] = "name", + }, + ["howcited"] = { + ["csl"] = nil, + }, + ["howpublished"] = { + ["csl"] = nil, + ["type"] = "literal", + }, + ["hyphenation"] = { + ["csl"] = "language", + ["type"] = "literal", + }, + ["ids"] = { + ["csl"] = nil, + ["type"] = "entrykey", + }, + ["illustrated"] = { + ["csl"] = nil, + }, + ["illustrations"] = { + ["csl"] = nil, + }, + ["illustrator"] = { + ["csl"] = nil, + }, + ["indexsorttitle"] = { + ["csl"] = nil, + ["type"] = "literal", + }, + ["indextitle"] = { + ["csl"] = nil, + ["type"] = "literal", + }, + ["institution"] = { + ["csl"] = "publisher", + ["type"] = "literal", + }, + ["introduction"] = { + ["csl"] = nil, + ["type"] = "name", + }, + ["intype"] = { + ["csl"] = nil, + }, + ["inventor"] = { + ["csl"] = nil, + }, + ["ipc"] = { + ["csl"] = nil, + }, + ["isan"] = { + ["csl"] = nil, + ["type"] = "literal", + }, + ["isbn"] = { + ["csl"] = "ISBN", + ["type"] = "literal", + }, + ["ismn"] = { + ["csl"] = nil, + ["type"] = "literal", + }, + ["iso-abbreviation"] = { + ["csl"] = nil, + }, + ["iso-author-punctuation"] = { + ["csl"] = nil, + }, + ["iso-date-place"] = { + ["csl"] = nil, + }, + ["isrn"] = { + ["csl"] = nil, + ["type"] = "literal", + }, + ["issn"] = { + ["csl"] = "ISSN", + ["type"] = "literal", + }, + ["issue"] = { + ["csl"] = "issue", + ["type"] = "literal", + }, + ["issuesubtitle"] = { + ["csl"] = nil, + ["type"] = "literal", + }, + ["issuetitle"] = { + ["csl"] = nil, + ["type"] = "literal", + }, + ["issuetitleaddon"] = { + ["csl"] = nil, + ["type"] = "literal", + }, + ["iswc"] = { + ["csl"] = nil, + ["type"] = "literal", + }, + ["jfmnumber"] = { + ["csl"] = nil, + }, + ["journal"] = { + ["csl"] = "container-title", + ["type"] = "literal", + }, + ["journalsubtitle"] = { + ["csl"] = nil, + ["type"] = "literal", + }, + ["journaltie"] = { + ["csl"] = nil, + }, + ["journaltitle"] = { + ["csl"] = "container-title", + ["type"] = "literal", + }, + ["journaltitleaddon"] = { + ["csl"] = nil, + ["type"] = "literal", + }, + ["juraauthor"] = { + ["csl"] = nil, + }, + ["juratitle"] = { + ["csl"] = nil, + }, + ["key"] = { + ["csl"] = nil, + ["type"] = "literal", + }, + ["keywords"] = { + ["csl"] = nil, + ["type"] = "keyword", + }, + ["label"] = { + ["csl"] = nil, + ["type"] = "literal", + }, + ["lang"] = { + ["csl"] = nil, + }, + ["langid"] = { + ["csl"] = "language", + ["type"] = "literal", + }, + ["langidopts"] = { + ["csl"] = nil, + ["type"] = "literal", + }, + ["language"] = { + ["csl"] = nil, + ["type"] = "key", + }, + ["lastaccessed"] = { + ["csl"] = "accessed", + }, + ["lastchecked"] = { + ["csl"] = "accessed", + }, + ["lccn"] = { + ["csl"] = nil, + }, + ["library"] = { + ["csl"] = nil, + ["type"] = "literal", + }, + ["lista"] = { + ["csl"] = nil, + ["type"] = "literal", + }, + ["listb"] = { + ["csl"] = nil, + ["type"] = "literal", + }, + ["listc"] = { + ["csl"] = nil, + ["type"] = "literal", + }, + ["listd"] = { + ["csl"] = nil, + ["type"] = "literal", + }, + ["liste"] = { + ["csl"] = nil, + ["type"] = "literal", + }, + ["listf"] = { + ["csl"] = nil, + ["type"] = "literal", + }, + ["littype"] = { + ["csl"] = nil, + }, + ["location"] = { + ["csl"] = "publisher-place", + ["type"] = "literal", + }, + ["madadurltest"] = { + ["csl"] = nil, + }, + ["main"] = { + ["csl"] = nil, + }, + ["main1"] = { + ["csl"] = nil, + }, + ["mainsubtitle"] = { + ["csl"] = nil, + ["type"] = "literal", + }, + ["maintitle"] = { + ["csl"] = nil, + ["type"] = "literal", + }, + ["maintitleaddon"] = { + ["csl"] = nil, + ["type"] = "literal", + }, + ["majorcode"] = { + ["csl"] = nil, + }, + ["marginnote"] = { + ["csl"] = nil, + }, + ["mark"] = { + ["csl"] = nil, + }, + ["max.best.papers"] = { + ["csl"] = nil, + }, + ["mcitetail"] = { + ["csl"] = nil, + }, + ["media"] = { + ["csl"] = "medium", + }, + ["medium"] = { + ["csl"] = "medium", + }, + ["meeting"] = { + ["csl"] = nil, + }, + ["misctitle"] = { + ["csl"] = nil, + }, + ["miscyear"] = { + ["csl"] = nil, + }, + ["mobile"] = { + ["csl"] = nil, + }, + ["modifydate"] = { + ["csl"] = nil, + }, + ["month"] = { + ["csl"] = nil, + ["type"] = "literal", + }, + ["monthfiled"] = { + ["csl"] = nil, + }, + ["mrnumber"] = { + ["csl"] = nil, + }, + ["name"] = { + ["csl"] = nil, + }, + ["namea"] = { + ["csl"] = nil, + ["type"] = "name", + }, + ["nameaddon"] = { + ["csl"] = nil, + ["type"] = "literal", + }, + ["nameatype"] = { + ["csl"] = nil, + ["type"] = "key", + }, + ["nameb"] = { + ["csl"] = nil, + ["type"] = "name", + }, + ["namebtype"] = { + ["csl"] = nil, + ["type"] = "key", + }, + ["namec"] = { + ["csl"] = nil, + ["type"] = "name", + }, + ["namectype"] = { + ["csl"] = nil, + ["type"] = "key", + }, + ["nationality"] = { + ["csl"] = nil, + }, + ["nbirthday"] = { + ["csl"] = nil, + }, + ["newpage"] = { + ["csl"] = nil, + }, + ["newspaper"] = { + ["csl"] = "container-title", + }, + ["nickname"] = { + ["csl"] = nil, + }, + ["nihms"] = { + ["csl"] = nil, + }, + ["noed"] = { + ["csl"] = nil, + }, + ["nolink"] = { + ["csl"] = nil, + }, + ["normal"] = { + ["csl"] = nil, + }, + ["normalauthor"] = { + ["csl"] = nil, + }, + ["normaleditor"] = { + ["csl"] = nil, + }, + ["note"] = { + ["csl"] = "note", + ["type"] = "literal", + }, + ["nowarning"] = { + ["csl"] = nil, + }, + ["number"] = { + ["csl"] = "number", + ["type"] = "literal", + }, + ["numpages"] = { + ["csl"] = nil, + }, + ["oaddress"] = { + ["csl"] = nil, + }, + ["options"] = { + ["csl"] = nil, + ["type"] = "option", + }, + ["opublisher"] = { + ["csl"] = nil, + }, + ["org-short"] = { + ["csl"] = nil, + }, + ["organization"] = { + ["csl"] = "publisher", + ["type"] = "literal", + }, + ["origdate"] = { + ["csl"] = "original-date", + ["type"] = "date", + }, + ["originaladdress"] = { + ["csl"] = "original-publisher-place", + }, + ["originalbooktitle"] = { + ["csl"] = nil, + }, + ["originaledition"] = { + ["csl"] = nil, + }, + ["originaleditor"] = { + ["csl"] = nil, + }, + ["originaljournal"] = { + ["csl"] = nil, + }, + ["originalnumber"] = { + ["csl"] = nil, + }, + ["originalpages"] = { + ["csl"] = nil, + }, + ["originalpublisher"] = { + ["csl"] = "original-publisher", + }, + ["originalvolume"] = { + ["csl"] = nil, + }, + ["originalyear"] = { + ["csl"] = "original-date", + }, + ["origlanguage"] = { + ["csl"] = nil, + ["type"] = "key", + }, + ["origlocation"] = { + ["csl"] = "original-publisher-place", + ["type"] = "literal", + }, + ["origpublisher"] = { + ["csl"] = "original-publisher", + ["type"] = "literal", + }, + ["origtitle"] = { + ["csl"] = "original-title", + ["type"] = "literal", + }, + ["oyear"] = { + ["csl"] = nil, + }, + ["pagename"] = { + ["csl"] = nil, + }, + ["pages"] = { + ["csl"] = "page", + ["type"] = "range", + }, + ["pagetotal"] = { + ["csl"] = "number-of-pages", + ["type"] = "literal", + }, + ["pagination"] = { + ["csl"] = nil, + ["type"] = "key", + }, + ["paper"] = { + ["csl"] = nil, + }, + ["part"] = { + ["csl"] = "part", + ["type"] = "literal", + }, + ["patentid"] = { + ["csl"] = nil, + }, + ["pdf"] = { + ["csl"] = nil, + ["type"] = "verbatim", + }, + ["phone"] = { + ["csl"] = nil, + }, + ["pid"] = { + ["csl"] = nil, + }, + ["pii"] = { + ["csl"] = nil, + }, + ["pmcid"] = { + ["csl"] = "PMCID", + }, + ["prebibitem"] = { + ["csl"] = nil, + }, + ["preface"] = { + ["csl"] = nil, + }, + ["preprint"] = { + ["csl"] = nil, + }, + ["presort"] = { + ["csl"] = nil, + ["type"] = "literal", + }, + ["price"] = { + ["csl"] = nil, + }, + ["primaryclass"] = { + ["csl"] = nil, + ["type"] = "literal", + }, + ["printing"] = { + ["csl"] = nil, + }, + ["prioritycountry"] = { + ["csl"] = nil, + }, + ["prioritydate"] = { + ["csl"] = nil, + }, + ["prioritynumber"] = { + ["csl"] = nil, + }, + ["pseudonym"] = { + ["csl"] = nil, + }, + ["publication"] = { + ["csl"] = nil, + }, + ["publicationdate"] = { + ["csl"] = nil, + }, + ["publisher"] = { + ["csl"] = "publisher", + ["type"] = "literal", + }, + ["pubmed"] = { + ["csl"] = "PMID", + }, + ["pubstate"] = { + ["csl"] = nil, + ["type"] = "key", + }, + ["related"] = { + ["csl"] = nil, + ["type"] = "entrykey", + }, + ["relatedoptions"] = { + ["csl"] = nil, + ["type"] = "option", + }, + ["relatedstring"] = { + ["csl"] = nil, + ["type"] = "literal", + }, + ["relatedtype"] = { + ["csl"] = nil, + ["type"] = "literal", + }, + ["reprinted-from"] = { + ["csl"] = nil, + }, + ["reprinted-text"] = { + ["csl"] = nil, + }, + ["reprinttitle"] = { + ["csl"] = nil, + ["type"] = "literal", + }, + ["requestdate"] = { + ["csl"] = nil, + }, + ["requestnumber"] = { + ["csl"] = nil, + }, + ["responsible"] = { + ["csl"] = nil, + }, + ["review"] = { + ["csl"] = nil, + }, + ["revision"] = { + ["csl"] = nil, + }, + ["school"] = { + ["csl"] = "publisher", + ["type"] = "literal", + }, + ["score"] = { + ["csl"] = nil, + }, + ["section"] = { + ["csl"] = nil, + }, + ["series"] = { + ["csl"] = "collection-title", + ["type"] = "literal", + }, + ["seriesedition"] = { + ["csl"] = nil, + }, + ["short"] = { + ["csl"] = nil, + }, + ["shortarchive"] = { + ["csl"] = nil, + }, + ["shortauthor"] = { + ["csl"] = nil, + ["type"] = "name", + }, + ["shorteditor"] = { + ["csl"] = nil, + ["type"] = "name", + }, + ["shorthand"] = { + ["csl"] = nil, + ["type"] = "literal", + }, + ["shorthandintro"] = { + ["csl"] = nil, + ["type"] = "literal", + }, + ["shortjournal"] = { + ["csl"] = "container-title-short", + ["type"] = "literal", + }, + ["shortseries"] = { + ["csl"] = nil, + ["type"] = "literal", + }, + ["shortsubarchive"] = { + ["csl"] = nil, + }, + ["shorttitle"] = { + ["csl"] = "title-short", + ["type"] = "literal", + }, + ["shorturl"] = { + ["csl"] = nil, + }, + ["sig1"] = { + ["csl"] = nil, + }, + ["sig2"] = { + ["csl"] = nil, + }, + ["sig3"] = { + ["csl"] = nil, + }, + ["sig4"] = { + ["csl"] = nil, + }, + ["size"] = { + ["csl"] = nil, + }, + ["slaccitation"] = { + ["csl"] = nil, + }, + ["sort-short"] = { + ["csl"] = nil, + }, + ["sort-word"] = { + ["csl"] = nil, + }, + ["sortas"] = { + ["csl"] = nil, + }, + ["sortkey"] = { + ["csl"] = nil, + ["type"] = "literal", + }, + ["sortname"] = { + ["csl"] = nil, + ["type"] = "name", + }, + ["sortshorthand"] = { + ["csl"] = nil, + ["type"] = "literal", + }, + ["sorttitle"] = { + ["csl"] = nil, + ["type"] = "literal", + }, + ["sortyear"] = { + ["csl"] = nil, + ["type"] = "integer", + }, + ["source1"] = { + ["csl"] = nil, + }, + ["specialitycode"] = { + ["csl"] = nil, + }, + ["ssedition"] = { + ["csl"] = nil, + }, + ["standard"] = { + ["csl"] = nil, + }, + ["startnumber"] = { + ["csl"] = nil, + }, + ["startvolume"] = { + ["csl"] = nil, + }, + ["startyear"] = { + ["csl"] = nil, + }, + ["state"] = { + ["csl"] = nil, + }, + ["status"] = { + ["csl"] = nil, + }, + ["stdcode"] = { + ["csl"] = nil, + }, + ["stitle"] = { + ["csl"] = nil, + }, + ["street"] = { + ["csl"] = nil, + }, + ["subarchive"] = { + ["csl"] = nil, + }, + ["subtitle"] = { + ["csl"] = nil, + ["type"] = "literal", + }, + ["symposium"] = { + ["csl"] = nil, + }, + ["text"] = { + ["csl"] = nil, + }, + ["timestamp"] = { + ["csl"] = nil, + }, + ["title"] = { + ["csl"] = "title", + ["type"] = "literal", + }, + ["titleaddon"] = { + ["csl"] = nil, + ["type"] = "literal", + }, + ["titlenote"] = { + ["csl"] = nil, + }, + ["totalpages"] = { + ["csl"] = nil, + }, + ["transissue"] = { + ["csl"] = nil, + }, + ["transjournal"] = { + ["csl"] = nil, + }, + ["translation"] = { + ["csl"] = nil, + }, + ["translator"] = { + ["csl"] = "translator", + ["type"] = "name", + }, + ["transnumber"] = { + ["csl"] = nil, + }, + ["transpages"] = { + ["csl"] = nil, + }, + ["transsection"] = { + ["csl"] = nil, + }, + ["transvolume"] = { + ["csl"] = nil, + }, + ["transyear"] = { + ["csl"] = nil, + }, + ["type"] = { + ["csl"] = "genre", + ["type"] = "key", + }, + ["typeoflit"] = { + ["csl"] = nil, + }, + ["umfnumber"] = { + ["csl"] = nil, + }, + ["updated"] = { + ["csl"] = nil, + }, + ["url"] = { + ["csl"] = "URL", + ["type"] = "uri", + }, + ["urlaccessdate"] = { + ["csl"] = "accessed", + }, + ["urldate"] = { + ["csl"] = "accessed", + ["type"] = "date", + }, + ["urlnewline"] = { + ["csl"] = nil, + }, + ["urltype"] = { + ["csl"] = nil, + }, + ["urlyear"] = { + ["csl"] = nil, + }, + ["urn"] = { + ["csl"] = nil, + }, + ["usera"] = { + ["csl"] = nil, + ["type"] = "literal", + }, + ["userb"] = { + ["csl"] = nil, + ["type"] = "literal", + }, + ["userc"] = { + ["csl"] = nil, + ["type"] = "literal", + }, + ["userd"] = { + ["csl"] = nil, + ["type"] = "literal", + }, + ["usere"] = { + ["csl"] = nil, + ["type"] = "literal", + }, + ["userf"] = { + ["csl"] = nil, + ["type"] = "literal", + }, + ["value"] = { + ["csl"] = nil, + }, + ["venue"] = { + ["csl"] = "event-place", + ["type"] = "literal", + }, + ["verba"] = { + ["csl"] = nil, + ["type"] = "verbatim", + }, + ["verbb"] = { + ["csl"] = nil, + ["type"] = "verbatim", + }, + ["verbc"] = { + ["csl"] = nil, + ["type"] = "verbatim", + }, + ["version"] = { + ["csl"] = "version", + ["type"] = "literal", + }, + ["versiontype"] = { + ["csl"] = nil, + }, + ["volformat"] = { + ["csl"] = nil, + }, + ["volume"] = { + ["csl"] = "volume", + ["type"] = "integer", + }, + ["volumes"] = { + ["csl"] = "number-of-volumes", + ["type"] = "integer", + }, + ["volumetitle"] = { + ["csl"] = nil, + }, + ["word"] = { + ["csl"] = nil, + }, + ["xdata"] = { + ["csl"] = nil, + ["type"] = "entrykey", + }, + ["xid"] = { + ["csl"] = nil, + }, + ["xref"] = { + ["csl"] = nil, + ["type"] = "entrykey", + }, + ["year"] = { + ["csl"] = nil, + ["type"] = "date", + }, + ["year-presented"] = { + ["csl"] = nil, + }, + ["yearcomp"] = { + ["csl"] = nil, + }, + ["yearfiled"] = { + ["csl"] = nil, + }, + ["zblnumber"] = { + ["csl"] = nil, + }, + ["zip"] = { + ["csl"] = nil, + }, + }, + ["macros"] = { + ["jan"] = { + ["value"] = "1", + }, + ["feb"] = { + ["value"] = "2", + }, + ["mar"] = { + ["value"] = "3", + }, + ["apr"] = { + ["value"] = "4", + }, + ["may"] = { + ["value"] = "5", + }, + ["jun"] = { + ["value"] = "6", + }, + ["jul"] = { + ["value"] = "7", + }, + ["aug"] = { + ["value"] = "8", + }, + ["sep"] = { + ["value"] = "9", + }, + ["oct"] = { + ["value"] = "10", + }, + ["nov"] = { + ["value"] = "11", + }, + ["dec"] = { + ["value"] = "12", + }, + ["acmcs"] = { + ["value"] = "ACM Computing Surveys", + }, + ["acta"] = { + ["value"] = "Acta Informatica", + }, + ["cacm"] = { + ["value"] = "Communications of the ACM", + }, + ["ibmjrd"] = { + ["value"] = "IBM Journal of Research and Development", + }, + ["ibmsj"] = { + ["value"] = "IBM Systems Journal", + }, + ["ieeese"] = { + ["value"] = "IEEE Transactions on Software Engineering", + }, + ["ieeetc"] = { + ["value"] = "IEEE Transactions on Computers", + }, + ["ieeetcad"] = { + ["value"] = "IEEE Transactions on Computer-Aided Design of Integrated Circuits", + }, + ["ipl"] = { + ["value"] = "Information Processing Letters", + }, + ["jacm"] = { + ["value"] = "Journal of the ACM", + }, + ["jcss"] = { + ["value"] = "Journal of Computer and System Sciences", + }, + ["scp"] = { + ["value"] = "Science of Computer Programming", + }, + ["sicomp"] = { + ["value"] = "SIAM Journal on Computing", + }, + ["tocs"] = { + ["value"] = "ACM Transactions on Computer Systems", + }, + ["tods"] = { + ["value"] = "ACM Transactions on Database Systems", + }, + ["tog"] = { + ["value"] = "ACM Transactions on Graphics", + }, + ["toms"] = { + ["value"] = "ACM Transactions on Mathematical Software", + }, + ["toois"] = { + ["value"] = "ACM Transactions on Office Information Systems", + }, + ["toplas"] = { + ["value"] = "ACM Transactions on Programming Languages and Systems", + }, + ["tcs"] = { + ["value"] = "Theoretical Computer Science", + }, + }, +}
\ No newline at end of file diff --git a/biblio/citation-style-language/citeproc-bib.lua b/biblio/citation-style-language/citeproc-bib.lua index b99ba955dd..7e24b1a6a5 100644 --- a/biblio/citation-style-language/citeproc-bib.lua +++ b/biblio/citation-style-language/citeproc-bib.lua @@ -16,24 +16,12 @@ local bib = {} -require("lualibs") local unicode = require("unicode") +bib.bib_data = require("citeproc-bib-data") local util = require("citeproc-util") -local path = "citeproc-bib-data.json" -if kpse then - path = kpse.find_file(path) -end -if path then - local contents = util.read_file(path) - if not contents then - error(string.format('Failed to find "%s"', path)) - end - bib.bib_data = utilities.json.tolua(contents) -end - function bib.parse(contents) local items = {} for item_contents in string.gmatch(contents, "(@%w+%b{})") do @@ -80,9 +68,9 @@ end function bib.parse_fields(contents) local fields = {} local field_patterns = { - "^(%w+)%s*=%s*(%b{}),?%s*(.-)$", - '^(%w+)%s*=%s*"([^"]*)",?%s*(.-)$', - "^(%w+)%s*=%s*(%w+),?%s*(.-)$", + "^([^,}%s]+)%s*=%s*(%b{}),?%s*(.-)$", + '^([^,}%s]+)%s*=%s*"([^"]*)",?%s*(.-)$', + "^([^,}%s]+)%s*=%s*(%w+),?%s*(.-)$", } while #contents > 0 do @@ -91,6 +79,7 @@ function bib.parse_fields(contents) for pattern_index, pattern in ipairs(field_patterns) do field, value, rest = string.match(contents, pattern) if value then + field = string.lower(field) if pattern_index == 1 then -- Strip braces "{}" value = string.sub(value, 2, -2) @@ -106,10 +95,14 @@ function bib.parse_fields(contents) end end fields[field] = value - contents = rest break end end + if value then + contents = rest + else + break + end end return fields end diff --git a/biblio/citation-style-language/citeproc b/biblio/citation-style-language/citeproc-cli.lua index 27663952bd..97a51d724c 100755..100644 --- a/biblio/citation-style-language/citeproc +++ b/biblio/citation-style-language/citeproc-cli.lua @@ -1,4 +1,3 @@ -#!/usr/bin/env texlua -- -- Copyright (c) 2021-2022 Zeping Lee @@ -6,12 +5,14 @@ -- Repository: https://github.com/zepinglee/citeproc-lua -- -kpse.set_program_name("luatex") +local cli = {} + require("lualibs") local citeproc = require("citeproc") local util = require("citeproc-util") -local core = require("csl-core") +local core = require("citeproc-latex-core") + local function getopt( arg, options ) local tab = {} @@ -52,12 +53,12 @@ end local function print_version() - io.write(string.format("CiteProc-Lua %s\n", citeproc.__VERSION__)) + io.write(string.format("citeproc-lua %s\n", citeproc.__VERSION__)) end local function print_help() - io.write("Usage: citeproc [options] auxname[.aux]\n") + io.write("Usage: citeproc-lua [options] auxname[.aux]\n") io.write("Options:\n") io.write(" -h, --help Print this message and exit.\n") io.write(" -V, --version Print the version number and exit.\n") @@ -143,7 +144,7 @@ local function process_aux_file(aux_file) for _, citation in ipairs(citations) do local citation_id = citation.citationID - if citation_id ~= "nocite" then + if citation_id ~= "@nocite" then local citation_str = citation_strings[citation_id] output_string = output_string .. string.format("\\cslcite{%s}{{%s}{%s}}\n", citation_id, style_class, citation_str) end @@ -161,7 +162,7 @@ local function process_aux_file(aux_file) end -local function main() +function cli.main() local args = getopt(arg, "o") -- for k, v in pairs(args) do @@ -191,4 +192,5 @@ local function main() end -main() + +return cli diff --git a/biblio/citation-style-language/citeproc-context.lua b/biblio/citation-style-language/citeproc-context.lua new file mode 100644 index 0000000000..08be158bcf --- /dev/null +++ b/biblio/citation-style-language/citeproc-context.lua @@ -0,0 +1,335 @@ +-- +-- Copyright (c) 2021-2022 Zeping Lee +-- Released under the MIT license. +-- Repository: https://github.com/zepinglee/citeproc-lua +-- + +local context = {} + +local LocalizedQuotes = require("citeproc-output").LocalizedQuotes + +local util = require("citeproc-util") + + +local Context = { + reference = nil, + format = nil, + cite_id = nil, + style = nil, + locale = nil, + name_citation = nil, + names_delimiter = nil, + + position = nil, + + disamb_pass = nil, + + cite = nil, + bib_number = nil, + + in_bibliography = false, + sort_key = nil, + + year_suffix = nil, +} + +function Context:new() + local o = { + in_bibliography = false + } + setmetatable(o, self) + self.__index = self + return o +end + +function Context:get_variable(name, form) + local variable_type = util.variable_types[name] + if variable_type == "number" then + return self:get_number(name) + -- elseif variable_type == "date" then + -- return self:get_date(name) + elseif variable_type == "name" then + return self:get_name(name) + else + return self:get_ordinary(name, form) + end +end + +function Context:get_number(name) + if name == "locator" then + return self.cite.locator + elseif name == "citation-number" then + -- return self.bib_number + return self.reference["citation-number"] + elseif name == "first-reference-note-number" then + return self.cite["first-reference-note-number"] + elseif name == "page-first" then + return self.page_first(self.reference.page) + else + return self.reference[name] + end +end + +function Context:get_ordinary(name, form) + local res = nil + local variable_name = name + if form and form ~= "long" then + variable_name = variable_name .. "-" .. form + end + + if variable_name == "locator" or variable_name == "label" then + res = self.cite[variable_name] + else + res = self.reference[variable_name] + end + if res then + return res + end + + if variable_name == "container-title-short" then + res = self.reference["journalAbbreviation"] + if res then + return res + end + end + + if form then + res = self.reference[name] + if res then + return res + end + end + + -- if name == "title-short" or name == "container-title-short" then + -- variable_name = string.gsub(name, "%-short$", "") + -- res = self.reference[variable_name] + -- end + + return res +end + +-- TODO: optimize: process only once +-- TODO: organize the name parsing code +function Context:get_name(variable_name) + local names = self.reference[variable_name] + if names then + for _, name in ipairs(names) do + if name.family == "" then + name.family = nil + end + if name.given == "" then + name.given = nil + end + if name.given and not name.family then + name.family = name.given + name.given = nil + end + self:parse_name_suffix(name) + self:split_ndp_family(name) + -- self:split_given_ndp(name) + self:split_given_dp(name) + end + end + return names +end + +function Context:parse_name_suffix(name) + if not name.suffix and name.family and string.match(name.family, ",") then + local words = util.split(name.family, ",%s*") + name.suffix = words[#words] + name.family = table.concat(util.slice(words, 1, -2), ", ") + end + if not name.suffix and name.given and string.match(name.given, ",") then + -- Split name suffix: magic_NameSuffixNoComma.txt + -- "John, III" => given: "John", suffix: "III" + local words = util.split(name.given, ",%s*") + name.suffix = words[#words] + name.given = table.concat(util.slice(words, 1, -2), ", ") + end +end + +function Context:split_ndp_family(name) + if name["non-dropping-particle"] or not name.family then + return + end + if util.startswith(name.family, '"') and util.endswith(name.family, '"') then + -- Stop parsing family name if surrounded by quotation marks + -- bugreports_parseName.txt + name.family = string.gsub(name.family, '"', "") + return + end + local ndp_parts = {} + local family_parts = {} + local parts = util.split(name.family) + for i, part in ipairs(parts) do + local ndp, family + -- d'Aubignac + ndp, family = string.match(part, "^(%l')(.+)$") + if ndp and family then + table.insert(ndp_parts, ndp) + parts[i] = family + else + ndp, family = string.match(part, "^(%l’)(.+)$") + if ndp and family then + table.insert(ndp_parts, ndp) + parts[i] = family + else + -- al-Aswānī + ndp, family = string.match(part, "^(%l+%-)(.+)$") + if ndp and family then + table.insert(ndp_parts, ndp) + parts[i] = family + elseif i < #parts and util.is_lower(part) then + table.insert(ndp_parts, part) + end + end + end + if ndp or i == #parts then + for j = i, #parts do + table.insert(family_parts, parts[j]) + end + break + end + if not util.is_lower(part) then + for j = i, #parts do + table.insert(family_parts, parts[j]) + end + break + end + end + if #ndp_parts > 0 then + name["non-dropping-particle"] = table.concat(ndp_parts, " ") + name.family = table.concat(family_parts, " ") + end +end + +function Context:split_given_dp(name) + if name["dropping-particle"] or not name.given then + return + end + local dp_parts = {} + local given_parts = {} + local parts = util.split(name.given) + for i = #parts, 1, -1 do + local part = parts[i] + if i == 1 or not util.is_lower(part) then + for j = 1, i do + table.insert(given_parts, parts[j]) + end + break + end + -- name_ParsedDroppingParticleWithApostrophe.txt + -- given: "François Hédelin d'" => + -- given: "François Hédelin", dropping-particle: "d'" + if string.match(part, "^%l+'?$") or string.match(part, "^%l+’$") then + table.insert(dp_parts, 1, part) + end + end + if #dp_parts > 0 then + name["dropping-particle"] = table.concat(dp_parts, " ") + name.given = table.concat(given_parts, " ") + end +end + +-- function Context:split_given_ndp(name) +-- if name["non-dropping-particle"] or not name.given then +-- return +-- end + +-- if not (string.match(name.given, "%l'$") or string.match(name.given, "%l’$")) then +-- return +-- end + +-- local words = util.split(name.given) +-- if #words < 2 then +-- return +-- end +-- local last_word = words[#words] +-- if util.endswith(last_word, "'") or util.endswith(last_word, util.unicode["apostrophe"]) then +-- name["non-dropping-particle"] = last_word +-- name.given = table.concat(util.slice(words, 1, -2), " ") +-- end +-- util.debug(name) +-- end + +function Context:get_localized_date(form) + return self.locale.dates[form] +end + +function Context:get_macro(name) + local res = self.style.macros[name] + if not res then + util.error(string.format('Undefined macro "%s"', name)) + end + return res +end + +function Context:get_simple_term(name, form, plural) + assert(self.locale) + return self.locale:get_simple_term(name, form, plural) +end + +function Context:get_localized_quotes() + return LocalizedQuotes:new( + self:get_simple_term("open-quote"), + self:get_simple_term("close-quote"), + self:get_simple_term("open-inner-quote"), + self:get_simple_term("close-inner-quote"), + self.locale.style_options.punctuation_in_quote + ) +end + +function Context.page_first(page) + local page_first = util.split(page, "%s*[&,-]%s*")[1] + return util.split(page_first, util.unicode["en dash"])[1] +end + +-- https://docs.citationstyles.org/en/stable/specification.html#non-english-items +function Context:is_english() + local language = self:get_variable("language") + if util.startswith(self.engine.lang, "en") then + if not language or util.startswith(language, "en") then + return true + else + return false + end + else + if language and util.startswith(language, "en") then + return true + else + return false + end + end +end + + +local IrState = {} + +function IrState:new(style, cite_id, cite, reference) + local o = { + macro_stack = {}, + suppressed = {}, + } + setmetatable(o, self) + self.__index = self + return o +end + +function IrState:push_macro(macro_name) + for _, name in ipairs(macro_name) do + if name == macro_name then + util.error(string.format('Recursive macro "%s".', macro_name)) + end + table.insert(self.macro_stack, macro_name) + end +end + +function IrState:pop_macro(macro_name) + table.remove(self.macro_stack) +end + + +context.Context = Context +context.IrState = IrState + +return context diff --git a/biblio/citation-style-language/citeproc-element.lua b/biblio/citation-style-language/citeproc-element.lua index 0e7abf87e3..197616cb08 100644 --- a/biblio/citation-style-language/citeproc-element.lua +++ b/biblio/citation-style-language/citeproc-element.lua @@ -6,410 +6,536 @@ local element = {} -local unicode = require("unicode") +local SeqIr = require("citeproc-ir-node").SeqIr + +local InlineElement = require("citeproc-output").InlineElement +local Micro = require("citeproc-output").Micro -local richtext = require("citeproc-richtext") local util = require("citeproc-util") local Element = { - default_options = {}, + element_name = nil, + children = nil, + element_type_map = {}, } -function Element:new () - local o = {} +function Element:new(element_name) + local o = { + element_name = element_name or self.element_name, + } setmetatable(o, self) self.__index = self return o end -Element.option_type = { - ["et-al-min"] = "integer", - ["et-al-use-first"] = "integer", - ["et-al-subsequent-min"] = "integer", - ["et-al-subsequent-use-first"] = "integer", - ["near-note-distance"] = "integer", - ["line-spacing"] = "integer", - ["entry-spacing"] = "integer", - ["names-min"] = "integer", - ["names-use-first"] = "integer", - ["limit-day-ordinals-to-day-1"] = "boolean", - ["punctuation-in-quote"] = "boolean", - ["et-al-use-last"] = "boolean", - ["initialize"] = "boolean", - ["initialize-with-hyphen"] = "boolean", - ["disambiguate-add-names"] = "boolean", - ["disambiguate-add-givenname"] = "boolean", - ["disambiguate-add-year-suffix"] = "boolean", - ["hanging-indent"] = "boolean", - ["names-use-last"] = "boolean", - ["quotes"] = "boolean", - ["strip-periods"] = "boolean", -} +function Element:derive(element_name, default_options) + local o = { + element_name = element_name or self.element_name, + children = nil, + } -Element.inheritable_options = { - -- Style - ["initialize-with-hyphen"] = true, - ["page-range-format"] = true, - ["demote-non-dropping-particle"] = true, - -- Citation - ["disambiguate-add-givenname"] = true, - ["givenname-disambiguation-rule"] = true, - ["disambiguate-add-names"] = true, - ["disambiguate-add-year-suffix"] = true, - ["cite-group-delimiter"] = true, - ["collapse"] = true, - ["year-suffix-delimiter"] = true, - ["after-collapse-delimiter"] = true, - ["near-note-distance"] = true, - -- Bibliography - ["second-field-align"] = true, -- for use in layout - ["subsequent-author-substitute"] = true, - ["subsequent-author-substitute-rule"] = true, - -- Date - ["date-parts"] = true, - -- Names - ["and"] = true, - ["delimiter-precedes-et-al"] = true, - ["delimiter-precedes-last"] = true, - ["et-al-min"] = true, - ["et-al-use-first"] = true, - ["et-al-use-last"] = true, - ["et-al-subsequent-min"] = true, - ["et-al-subsequent-use-first"] = true, - ["names-min"] = true, - ["names-use-first"] = true, - ["names-use-last"] = true, - ["initialize-with"] = true, - ["name-as-sort-order"] = true, - ["sort-separator"] = true, - ["name-form"] = true, - ["name-delimiter"] = true, - ["names-delimiter"] = true, -} + if default_options then + for key, value in pairs(default_options) do + o[key] = value + end + end + + Element.element_type_map[element_name] = o + setmetatable(o, self) + self.__index = self + return o +end -function Element:render (item, context) - self:debug_info(context) - context = self:process_context(context) - return self:render_children(item, context) +function Element:from_node(node, parent) + local o = self:new() + o.element_name = self.element_name or node:get_element_name() + return o end -function Element:render_children (item, context) - local output = {} - for i, child in ipairs(self:get_children()) do - if child:is_element() then - if child.render == nil then - local element_name = child:get_element_name() - util.warning("Unkown type \"" .. element_name .. "\"") - end - local str = child:render(item, context) - table.insert(output, str) - end +function Element:set_attribute(node, attribute) + local value = node:get_attribute(attribute) + if value then + local key = string.gsub(attribute, "%-" , "_") + self[key] = value end - return self:concat(output, context) end -function Element:set_base_class (node) - if node:is_element() then - local org_meta_table = getmetatable(node) - setmetatable(node, {__index = function (_, key) - if self[key] then - return self[key] - else - return org_meta_table[key] - end - end}) +function Element:set_bool_attribute(node, attribute) + local value = node:get_attribute(attribute) + if value == "true" then + local key = string.gsub(attribute, "%-" , "_") + self[key] = true + elseif value == "false" then + local key = string.gsub(attribute, "%-" , "_") + self[key] = false end end -function Element:debug_info (context, debug) - -- debug = true - if debug then - local text = "" - local level = 0 - if context and context.level then - level = context.level + 1 - end - text = text .. string.rep(" ", 2 * level) - text = text .. self:get_element_name() - local attrs = {} - if self._attr then - for attr, value in pairs(self._attr) do - table.insert(attrs, attr .. "=\"" .. value .. "\"") - end - text = text .. "[" .. table.concat(attrs, " ") .. "]" - end - io.stderr:write(text .. "\n") +function Element:set_number_attribute(node, attribute) + local value = node:get_attribute(attribute) + if value then + local key = string.gsub(attribute, "%-" , "_") + self[key] = tonumber(value) end end -function Element:get_child (type) - for _, child in ipairs(self:get_children()) do - if child:get_element_name() == type then - return child +function Element:process_children_nodes(node) + if not self.children then + self.children = {} + end + for _, child in ipairs(node:get_children()) do + if child:is_element() then + local element_name = child:get_element_name() + local element_type = self.element_type_map[element_name] or Element + local child_element = element_type:from_node(child, self) + table.insert(self.children, child_element) end end - return nil -end -function Element:get_style () - local style = self:root_node().style - assert(style ~= nil) - return style end -function Element:get_engine () - local engine = self:root_node().engine - assert(engine ~= nil) - return engine +function Element:build_ir(engine, state, context) + return self:build_children_ir(engine, state, context) end -function Element:process_context (context) - local state = { - -- The `build` table is directly passed to new context. - build = context.build or {}, - -- The `option` table is copied. - options = {}, - -- Other items in `context` is copied. - } - for key, value in pairs(self.default_options) do - state.options[key] = value - end - if context then - local element_name = self:get_element_name() - for key, value in pairs(context) do - if key == "options" then - for k, v in pairs(context.options) do - if self.inheritable_options[k] then - state.options[k] = v - if element_name == "name" then - if k == "name-form" then - state.options["form"] = v - end - if k == "name-delimiter" then - state.options["delimiter"] = v - end - elseif element_name == "names" then - if k == "names-delimiter" then - state.options["delimiter"] = v - end - end - end +function Element:build_children_ir(engine, state, context) + local child_irs = {} + local ir_sort_key + local group_var = "plain" + if self.children then + for _, child_element in ipairs(self.children) do + local child_ir = child_element:build_ir(engine, state, context) + if child_ir then + if child_ir.sort_key ~= nil then + ir_sort_key = child_ir.sort_key end - else - state[key] = value + if child_ir.group_var == "important" then + group_var = "important" + end + table.insert(child_irs, child_ir) end end - if state.level then - state.level = state.level + 1 - else - state.level = 0 - end end - if self._attr then - for key, value in pairs(self._attr) do - if self.option_type[key] == "integer" then - value = tonumber(value) - elseif self.option_type[key] == "boolean" then - value = (value == "true") - end - state.options[key] = value - end + local ir = SeqIr:new(child_irs, self) + ir.sort_key = ir_sort_key + ir.group_var = group_var + if #child_irs == 0 then + ir.group_var = "missing" + else + ir.group_var = group_var end - return state + return ir end -function Element:get_option (key, context) - assert(context ~= nil) - return context.options[key] -end - -function Element:get_locale_option (key) - local locales = self:get_style():get_locales() - for i, locale in ipairs(locales) do - local option = locale:get_option(key) - if option ~= nil then - return option - end +-- Used in cs:group and cs:macro +function Element:build_group_ir(engine, state, context) + if not self.children then + return nil end - return nil -end + local irs = {} + local name_count + local ir_sort_key + local group_var = "plain" + + for _, child_element in ipairs(self.children) do + -- util.debug(child_element.element_name) + local child_ir = child_element:build_ir(engine, state, context) + -- util.debug(child_ir) + -- util.debug(child_ir.group_var) + + if child_ir then + -- cs:group and its child elements are suppressed if + -- a) at least one rendering element in cs:group calls a variable (either + -- directly or via a macro), and + -- b) all variables that are called are empty. This accommodates + -- descriptive cs:text and `cs:label` elements. + local child_group_var = child_ir.group_var + if child_group_var == "important" then + group_var = "important" + elseif child_group_var == "missing" and child_ir._type ~= "YearSuffix" then + if group_var == "plain" then + group_var = "missing" + end + end -function Element:get_variable (item, name, context) - if context.suppressed_variables and context.suppressed_variables[name] then - return nil - else - local res = item[name] - if type(res) == "table" and res._type == "RichText" then - -- TODO: should be deep copy - res = res:shallow_copy() - end + if child_ir.name_count then + if not name_count then + name_count = 0 + end + name_count = name_count + child_ir.name_count + end - if res and res ~= "" then - if context.suppress_subsequent_variables then - context.suppressed_variables[name] = true + if child_ir.sort_key ~= nil then + ir_sort_key = child_ir.sort_key end + + table.insert(irs, child_ir) end - return res end -end -function Element:get_macro (name) - local query = string.format("macro[name=\"%s\"]", name) - local macro = self:root_node():query_selector(query)[1] - if not macro then - error(string.format("Failed to find %s.", query)) + -- A non-empty nested cs:group is treated as a non-empty variable for the + -- puropses of determining suppression of the outer cs:group. + if #irs > 0 and group_var == "plain" then + group_var = "important" end - return macro -end -function Element:get_term (name, form, number, gender) - return self:get_style():get_term(name, form, number, gender) -end + local ir = SeqIr:new(irs, self) + ir.name_count = name_count + ir.sort_key = ir_sort_key + ir.group_var = group_var --- Formatting -function Element:escape (str, context) - return str - -- return self:get_engine().formatter.text_escape(str) + return ir end -function Element:format(text, context) - if not text or text == "" then - return nil +function Element:render_text_inlines(str, context) + if str == "" then + return {} end - if text._type ~= "RichText" then - text = richtext.new(text) + + str = self:apply_strip_periods(str) + -- TODO: try links + + local output_format = context.format + local localized_quotes = nil + if self.quotes then + localized_quotes = context:get_localized_quotes() end - local attributes = { + + local inlines = InlineElement:parse(str, context) + local is_english = context:is_english() + output_format:apply_text_case(inlines, self.text_case, is_english) + inlines = {Micro:new(inlines)} + inlines = output_format:with_format(inlines, self.formatting) + inlines = output_format:affixed_quoted(inlines, self.affixes, localized_quotes) + return output_format:with_display(inlines, self.display) +end + +function Element:set_formatting_attributes(node) + for _, attribute in ipairs({ "font-style", "font-variant", "font-weight", "text-decoration", "vertical-align", - } - for _, attribute in ipairs(attributes) do - local value = context.options[attribute] + }) do + local value = node:get_attribute(attribute) if value then - if text.formats[attribute] then - local new = richtext.new() - new.contents = {text} - text = new + if not self.formatting then + self.formatting = {} end - text:add_format(attribute, value) + self.formatting[attribute] = value end end - return text end --- Affixes -function Element:wrap (str, context) - if not str or str == "" then - return nil - end - local prefix = context.options["prefix"] - local suffix = context.options["suffix"] - local res = str - if prefix and prefix ~= "" then - local linkable = false - local variable_name = context.options["variable"] - if variable_name == "DOI" or variable_name == "PMID" or variable_name == "PMCID" then - linkable = true +function Element:set_affixes_attributes(node) + for _, attribute in ipairs({"prefix", "suffix"}) do + local value = node:get_attribute(attribute) + if value then + if not self.affixes then + self.affixes = {} + end + self.affixes[attribute] = value end - if variable_name == "URL" or (linkable and not string.match(prefix, "^https?://")) then - res:add_format(variable_name, "true") + end +end + +function Element:get_delimiter_attribute(node) + self:set_attribute(node, "delimiter") +end + +function Element:set_display_attribute(node) + self:set_attribute(node, "display") +end + +function Element:set_quotes_attribute(node) + self:set_bool_attribute(node, "quotes") +end + +function Element:set_strip_periods_attribute(node) + self:set_bool_attribute(node, "strip-periods") +end + +function Element:set_text_case_attribute(node) + self:set_attribute(node, "text-case") +end + +-- function Element:apply_formatting(ir) +-- local attributes = { +-- "font_style", +-- "font_variant", +-- "font_weight", +-- "text_decoration", +-- "vertical_align", +-- } +-- for _, attribute in ipairs(attributes) do +-- local value = self[attribute] +-- if value then +-- if not ir.formatting then +-- ir.formatting = {} +-- end +-- ir.formatting[attribute] = value +-- end +-- end +-- return ir +-- end + +function Element:apply_affixes(ir) + if ir then + if self.prefix then + ir.prefix = self.prefix end - res = richtext.concat(prefix, res) - if linkable and string.match(prefix, "^https?://") then - res:add_format("URL", "true") + if self.suffix then + ir.suffix = self.suffix end end - if suffix and suffix ~= "" then - res = richtext.concat(res, suffix) + return ir +end + +function Element:apply_delimiter(ir) + if ir and ir.children then + ir.delimiter = self.delimiter end - return res + return ir end --- Delimiters -function Element:concat (strings, context) - local delimiter = context.options["delimiter"] - return richtext.concat_list(strings, delimiter) +function Element:apply_display(ir) + ir.display = self.display + return ir end --- Display -function Element:display(text, context) - if not text then - return text - end - local value = context.options["display"] - if not value then - return text +function Element:apply_quotes(ir) + if ir and self.quotes then + ir.quotes = true + ir.children = {ir} + ir.open_quote = nil + ir.close_quote = nil + ir.open_inner_quote = nil + ir.close_inner_quote = nil + ir.punctuation_in_quote = false end - if type(text) == "string" then - text = richtext.new(text) + return ir +end + +function Element:apply_strip_periods(str) + local res = str + if str and self.strip_periods then + res = string.gsub(str, "%.", "") end - text:add_format("display", value) - return text + return res end --- Quotes -function Element:quote (str, context) - if not str then - return nil + +function Element:format_number(number, variable, form, context) + -- if not util.is_numeric(number) then + -- number = string.gsub(number, "\\%-", "-") + -- return number + -- end + number = util.strip(number) + if variable == "locator" then + variable = context:get_variable("label") end - if context.sorting then - return str + form = form or "numeric" + local number_part_list = self:split_number_parts(number, context) + -- { + -- {"1", "", " & "} + -- {"5", "8", ", "} + -- } + -- util.debug(number_part_list) + + for _, number_parts in ipairs(number_part_list) do + if form == "roman" then + self:format_roman_number_parts(number_parts) + elseif form == "ordinal" or form == "long-ordinal" then + local gender = context.locale:get_number_gender(variable) + self:format_ordinal_number_parts(number_parts, form, gender, context) + elseif number_parts[2] ~= "" and variable == "page" then + local page_range_format = context.style.page_range_format + self:format_page_range(number_parts, page_range_format) + else + self:format_numeric_number_parts(number_parts) + end end - if not str._type == "RichText" then - str = richtext.new(str) + + local range_delimiter = util.unicode["en dash"] + if variable == "page" then + local page_range_delimiter = context:get_simple_term("page-range-delimiter") + if page_range_delimiter then + range_delimiter = page_range_delimiter + end end - local quotes = context.options["quotes"] or false - if quotes then - str:add_format("quotes", "true") + + local res = "" + for _, number_parts in ipairs(number_part_list) do + res = res .. number_parts[1] + if number_parts[2] ~= "" then + res = res .. range_delimiter + res = res .. number_parts[2] + end + res = res .. number_parts[3] end - return str + return res + end --- Strip periods -function Element:strip_periods (str, context) - if not str then - return nil +function Element:split_number_parts(number, context) + -- number = string.gsub(number, util.unicode["en dash"], "-") + local and_symbol + and_symbol = context.locale:get_simple_term("and", "symbol") + if and_symbol then + and_symbol = " " .. and_symbol .. " " end - if str._type ~= "RichText" then - str = richtext.new(str) + local number_part_list = {} + for _, tuple in ipairs(util.split_multiple(number, "%s*[,&]%s*", true)) do + local single_number, delim = table.unpack(tuple) + delim = util.strip(delim) + if delim == "," then + delim = ", " + elseif delim == "&" then + delim = and_symbol or " & " + end + local start = single_number + local stop = "" + local splits = util.split(start, "%s*%-%s*") + if #splits == 2 then + start, stop = table.unpack(splits) + if util.endswith(start, "\\") then + start = string.sub(start, 1, -2) + start = start .. "-" .. stop + stop = "" + end + -- if string.match(start, "^%a*%d+%a*$") and string.match(stop, "^%a*%d+%a*$") then + -- if s + table.insert(number_part_list, {start, stop, delim}) + -- else + -- table.insert(number_part_list, {start .. "-" .. stop, "", delim}) + -- end + else + table.insert(number_part_list, {start, stop, delim}) + end end - local strip_periods = context.options["strip-periods"] - if strip_periods then - str:strip_periods() + return number_part_list +end + +function Element:format_roman_number_parts(number_parts) + for i = 1, 2 do + local part = number_parts[i] + if string.match(part, "%d+") then + number_parts[i] = util.convert_roman(tonumber(part)) + end end - return str end --- Text-case -function Element:case (text, context) - if not text or text == "" then - return nil +function Element:format_ordinal_number_parts(number_parts, form, gender, context) + for i = 1, 2 do + local part = number_parts[i] + if string.match(part, "%d+") then + local number = tonumber(part) + if form == "long-ordinal" and number >= 1 and number <= 10 then + number_parts[i] = context:get_simple_term(string.format("long-ordinal-%02d", number)) + else + local suffix = context.locale:get_ordinal_term(number, gender) + if suffix then + number_parts[i] = number_parts[i] .. suffix + end + end + end + end +end + +function Element:format_numeric_number_parts(number_parts) + -- if number_parts[2] ~= "" then + -- local first_prefix = string.match(number_parts[1], "^(.-)%d+") + -- local second_prefix = string.match(number_parts[2], "^(.-)%d+") + -- if first_prefix == second_prefix then + -- number_parts[1] = number_parts[1] .. "-" .. number_parts[2] + -- number_parts[2] = "" + -- end + -- end +end + +-- https://docs.citationstyles.org/en/stable/specification.html#appendix-v-page-range-formats +function Element:format_page_range(number_parts, page_range_format) + local start = number_parts[1] + local stop = number_parts[2] + local start_prefix, start_num = string.match(start, "^(.-)(%d+)$") + local stop_prefix, stop_num = string.match(stop, "^(.-)(%d+)$") + if start_prefix ~= stop_prefix then + -- Not valid range: "n11564-1568" -> "n11564-1568" + -- 110-N6 + -- N110-P5 + number_parts[1] = start .. "-" .. stop + number_parts[2] = "" + return end - if text._type ~= "RichText" then - text = richtext.new(text) + + if not page_range_format then + return end - local text_case = context.options["text-case"] - if not text_case then - return text + if page_range_format == "chicago-16" then + stop = self:_format_range_chicago_16(start_num, stop_num) + elseif page_range_format == "chicago-15" then + stop = self:_format_range_chicago_15(start_num, stop_num) + elseif page_range_format == "expanded" then + stop = stop_prefix .. self:_format_range_expanded(start_num, stop_num) + elseif page_range_format == "minimal" then + stop = self:_format_range_minimal(start_num, stop_num) + elseif page_range_format == "minimal-two" then + stop = self:_format_range_minimal(start_num, stop_num, 2) end - if text_case == "title" then - -- title case conversion only affects English-language items - local language = context.item["language"] - if not language then - language = self:get_style():get_attribute("default-locale") or "en-US" - end - if not util.startswith(language, "en") then - return text + number_parts[2] = stop +end + +function Element:_format_range_chicago_16(start, stop) + if #start < 3 or string.sub(start, -2) == "00" then + return self:_format_range_expanded(start, stop) + elseif string.sub(start, -2, -2) == "0" then + return self:_format_range_minimal(start, stop) + else + return self:_format_range_minimal(start, stop, 2) + end + return stop +end + +function Element:_format_range_chicago_15(start, stop) + if #start < 3 or string.sub(start, -2) == "00" then + return self:_format_range_expanded(start, stop) + else + local changed_digits = self:_format_range_minimal(start, stop) + if string.sub(start, -2, -2) == "0" then + return changed_digits + elseif #start == 4 and #changed_digits == 3 then + return self:_format_range_expanded(start, stop) + else + return self:_format_range_minimal(start, stop, 2) end end - text:add_format("text-case", text_case) - return text + return stop end +function Element:_format_range_expanded(start, stop) + -- Expand "1234–56" -> "1234–1256" + if #start <= #stop then + return stop + end + return string.sub(start, 1, #start - #stop) .. stop +end + +function Element:_format_range_minimal(start, stop, threshold) + threshold = threshold or 1 + if #start < #stop then + return stop + end + local offset = #start - #stop + for i = 1, #stop - threshold do + local j = i + offset + if string.sub(stop, i, i) ~= string.sub(start, j, j) then + return string.sub(stop, i) + end + end + return string.sub(stop, -threshold) +end element.Element = Element diff --git a/biblio/citation-style-language/citeproc-engine.lua b/biblio/citation-style-language/citeproc-engine.lua index 33a5a08e08..2e9f4c4a61 100644 --- a/biblio/citation-style-language/citeproc-engine.lua +++ b/biblio/citation-style-language/citeproc-engine.lua @@ -8,17 +8,29 @@ local engine = {} local dom = require("luaxml-domobject") -local richtext = require("citeproc-richtext") -local element = require("citeproc-element") local nodes = require("citeproc-nodes") -local formats = require("citeproc-formats") +local Style = require("citeproc-node-style").Style +local Locale = require("citeproc-node-locale").Locale +local Context = require("citeproc-context").Context +local IrState = require("citeproc-context").IrState +local Rendered = require("citeproc-ir-node").Rendered +local YearSuffix = require("citeproc-ir-node").YearSuffix +-- local OutputFormat = require("citeproc-output").OutputFormat +local LatexWriter = require("citeproc-output").LatexWriter +local HtmlWriter = require("citeproc-output").HtmlWriter +local SortStringFormat = require("citeproc-output").SortStringFormat +local DisamStringFormat = require("citeproc-output").DisamStringFormat +local InlineElement = require("citeproc-output").InlineElement +local Micro = require("citeproc-output").Micro +local Formatted = require("citeproc-output").Formatted +local PlainText = require("citeproc-output").PlainText local util = require("citeproc-util") local CiteProc = {} -function CiteProc.new (sys, style, lang, force_lang) - if sys == nil then +function CiteProc.new(sys, style, lang, force_lang) + if not sys then error("\"citeprocSys\" required") end if sys.retrieveLocale == nil then @@ -28,213 +40,1579 @@ function CiteProc.new (sys, style, lang, force_lang) error("\"citeprocSys.retrieveItem\" required") end local o = {} + + o.style = Style:parse(style) + + o.sys = sys + o.locales = {} + o.system_locales = {} + + o.lang = o.style.default_locale + if not o.lang or force_lang then + o.lang = lang or "en-US" + end + + o.output_format = LatexWriter:new() + + o.opt = { + -- Similar to citeproc-js's development_extensions.wrap_url_and_doi + url_link = false, + doi_link = false, -- also applied to PMID and PMCID + title_link = false, + } + o.registry = { - citations = {}, -- A map - citation_strings = {}, -- A list - registry = {}, -- A map - reflist = {}, -- A list + citations_by_id = {}, -- A map + citation_list = {}, -- A list + citations_by_item_id = {}, -- A map from item id to a map of citations + registry = {}, -- A map of bibliographic meta data + reflist = {}, -- list of cited ids + uncited_list = {}, previous_citation = nil, requires_sorting = false, + longest_label = "", + maxoffset = 0, } - o.sys = sys - o.system_locales = {} + o.cite_first_note_numbers = {} + o.cite_last_note_numbers = {} + o.note_citations_map = {} - if type(style) == "string" then - o.csl = dom.parse(style) - else - o.csl = style - end - o.csl:traverse_elements(CiteProc.set_base_class) - o.csl:root_node().engine = o - o.style = o.csl:get_path("style")[1] - o.style.lang = lang - o.csl:root_node().style = o.style + o.tainted_item_ids = {} - o.style:set_lang(lang, force_lang) + o.disam_irs = {} + -- { <ir1>, <ir2>, ... } - o.formatter = formats.latex - o.linking_enabled = false + o.cite_irs_by_output = {} + -- { + -- ["Roe, J"] = {<ir1>}, + -- ["Doe, J"] = {<ir2>, <ir3>}, + -- ["Doe, John"] = {<ir2>}, + -- ["Doe, Jack"] = {<ir2>}, + -- } + + o.person_names = {} + o.person_names_by_output = {} setmetatable(o, { __index = CiteProc }) return o end -function CiteProc:updateItems (ids) +function CiteProc:updateItems(ids) self.registry.reflist = {} self.registry.registry = {} + self.person_names = {} + self.person_names_by_output = {} + self.disam_irs = {} + self.cite_irs_by_output = {} + + local cite_items = {} + local loaded_ids = {} + for _, id in ipairs(ids) do - self:get_item(id) + table.insert(cite_items, {id = id}) + loaded_ids[id] = true + end + for _, id in ipairs(self.registry.uncited_list) do + if not loaded_ids[id] then + table.insert(cite_items, {id = id}) + loaded_ids[id] = true + end end + + -- TODO: optimize this + self:makeCitationCluster(cite_items) + + self.registry.previous_citation = nil + self.cite_first_note_numbers = {} + self.cite_last_note_numbers = {} + self.note_citations_map = {} end -function CiteProc:updateUncitedItems(ids) - for _, id in ipairs(ids) do - if not self.registry.registry[id] then - self:get_item(id) +function CiteProc:updateUncitedItems(uncited_ids) + -- self.registry.reflist = {} + self.registry.registry = {} + self.registry.uncited_list = {} + self.person_names = {} + self.person_names_by_output = {} + self.disam_irs = {} + self.cite_irs_by_output = {} + + local cite_items = {} + local loaded_ids = {} + + for _, id in ipairs(self.registry.reflist) do + if not loaded_ids[id] then + table.insert(cite_items, {id = id}) + loaded_ids[id] = true end end - -- TODO: disambiguation + self.registry.reflist = {} + + for _, id in ipairs(uncited_ids) do + if not loaded_ids[id] then + table.insert(cite_items, {id = id}) + loaded_ids[id] = true + end + end + + loaded_ids = {} + for _, id in ipairs(uncited_ids) do + if not loaded_ids[id] then + table.insert(self.registry.uncited_list, id) + loaded_ids[id] = true + end + end + + -- TODO: optimize this + self:makeCitationCluster(cite_items) + + self.registry.previous_citation = nil + self.cite_first_note_numbers = {} + self.cite_last_note_numbers = {} + self.note_citations_map = {} end function CiteProc:processCitationCluster(citation, citationsPre, citationsPost) - -- citation = { - -- citationID = "CITATION-3", - -- citationItems = { - -- { id = "ITEM-1" }, - -- { id = "ITEM-2" }, - -- }, - -- properties = { - -- noteIndex = 3, - -- }, - -- } - -- citationsPre = { - -- {"CITATION-1", 1}, - -- {"CITATION-2", 2}, - -- } - -- citationsPost = { - -- {"CITATION-4", 4}, - -- } - -- returns = { - -- { - -- bibchange = true, - -- citation_errors = {}, - -- }, - -- { - -- { 2, "[1,2]", "CITATION-3" } - -- } - -- } - self.registry.citations[citation.citationID] = citation + -- util.debug(citation) + -- util.debug(citationsPre) + -- Fix missing noteIndex: sort_CitationNumberPrimaryAscendingViaMacroCitation.txt + if not citation.properties then + citation.properties = {} + end + if not citation.properties.noteIndex then + citation.properties.noteIndex = 0 + end - local items = {} + -- Registor citation + self.registry.citations_by_id[citation.citationID] = citation + + local citation_note_pairs = {} + util.extend(citation_note_pairs, citationsPre) + table.insert(citation_note_pairs, {citation.citationID, citation.properties.noteIndex}) + util.extend(citation_note_pairs, citationsPost) + -- util.debug(citation_note_pairs) + + local citations_by_id = {} + local citation_list = {} + for _, pair in ipairs(citation_note_pairs) do + local citation_id, note_number = table.unpack(pair) + local citation_ = self.registry.citations_by_id[citation_id] + if not citation_ then + util.error("Citation not in registry.") + end + citations_by_id[citation_.citationID] = citation_ + table.insert(citation_list, citation_) + end + self.registry.citations_by_id = citations_by_id + self.registry.citation_list = citation_list + + -- update self.registry.citations_by_item_id + local item_ids = {} + self.registry.citations_by_item_id = {} + for _, citation_ in ipairs(citation_list) do + for _, cite_item in ipairs(citation_.citationItems) do + if not self.registry.citations_by_item_id[cite_item.id] then + self.registry.citations_by_item_id[cite_item.id] = {} + table.insert(item_ids, cite_item.id) + end + self.registry.citations_by_item_id[cite_item.id][citation_.citationID] = true + end + end + self:updateItems(item_ids) + + local params = { + bibchange = false, + citation_errors = {}, + } + local output = {} + local tainted_citation_ids = self:get_tainted_citaion_ids(citation_note_pairs) + -- util.debug(tainted_citation_ids) + + -- params.bibchange = #tainted_citation_ids > 0 + for citation_id, _ in pairs(tainted_citation_ids) do + local citation_ = self.registry.citations_by_id[citation_id] + + local citation_index = citation_.citation_index + local citation_str = self:build_citation_str(citation_) + table.insert(output, {citation_index, citation_str, citation_id}) + end + + -- util.debug(output) + return {params, output} +end + +-- A variant of processCitationCluster() for easy use with LaTeX. +-- It should be run after refreshing the registry (updateItems()) with all items +function CiteProc:process_citation(citation) + -- util.debug(citation) + -- util.debug(citationsPre) + -- Fix missing noteIndex: sort_CitationNumberPrimaryAscendingViaMacroCitation.txt + if not citation.properties then + citation.properties = {} + end + if not citation.properties.noteIndex then + citation.properties.noteIndex = 0 + end + + -- Registor citation + self.registry.citations_by_id[citation.citationID] = citation + + table.insert(self.registry.citation_list, citation) + + local citation_note_pairs = {} + for _, citation_ in ipairs(self.registry.citation_list) do + table.insert(citation_note_pairs, {citation_.citationID, citation_.properties.noteIndex}) + end + + -- update self.registry.citations_by_item_id for _, cite_item in ipairs(citation.citationItems) do + if not self.registry.citations_by_item_id[cite_item.id] then + self.registry.citations_by_item_id[cite_item.id] = {} + end + self.registry.citations_by_item_id[cite_item.id][citation.citationID] = true + end + + -- self:updateItems(item_ids) + for i, cite_item in ipairs(citation.citationItems) do cite_item.id = tostring(cite_item.id) - local position_first = (self.registry.registry[cite_item.id] == nil) - local item_data = self:get_item(cite_item.id) + self:get_item(cite_item.id) + end - if item_data then - -- Create a wrapper of the orignal item from registry so that - -- it may hold different `locator` or `position` values for cites. - local item = setmetatable({}, {__index = function (_, key) - if cite_item[key] then - return cite_item[key] - else - return item_data[key] + local tainted_citation_ids = self:get_tainted_citaion_ids(citation_note_pairs) + local citation_str = self:build_citation_str(citation) + + return citation_str +end + + +function CiteProc:get_tainted_citaion_ids(citation_note_pairs) + local tainted_citation_ids = {} + + self.cite_first_note_numbers = {} + self.cite_last_note_numbers = {} + self.note_citations_map = {} + -- { + -- 1 = {"citation-1", "citation-2"}, + -- 2 = {"citation-2"}, + -- } + + local previous_citation + for citation_index, pair in ipairs(citation_note_pairs) do + local citation_id, note_number = table.unpack(pair) + -- util.debug(citation_id) + local citation = self.registry.citations_by_id[citation_id] + citation.properties.noteIndex = note_number + citation.citation_index = citation_index + + local tainted = false + + local previous_cite + for _, cite_item in ipairs(citation.citationItems) do + tainted = self:set_cite_item_position(cite_item, note_number, previous_cite, previous_citation) + self.cite_last_note_numbers[cite_item.id] = note_number + previous_cite = cite_item + end + + if tainted then + tainted_citation_ids[citation.citationID] = true + end + + if not self.note_citations_map[note_number] then + self.note_citations_map[note_number] = {} + end + table.insert(self.note_citations_map[note_number], citation.citationID) + previous_citation = citation + end + + -- Update tainted citation ids because of citation-number's change + -- The self.tainted_item_ids were added in the sort_bibliography() procedure. + for item_id, _ in pairs(self.tainted_item_ids) do + if self.registry.citations_by_item_id[item_id] then + for citation_id, _ in pairs(self.registry.citations_by_item_id[item_id]) do + tainted_citation_ids[citation_id] = true + end + end + end + + return tainted_citation_ids +end + +function CiteProc:set_cite_item_position(cite_item, note_number, previous_cite, previous_citation) + local position = util.position_map["first"] + + local first_reference_note_number = self.cite_first_note_numbers[cite_item.id] + if first_reference_note_number then + position = util.position_map["subsequent"] + else + self.cite_first_note_numbers[cite_item.id] = note_number + end + + local preceding_cite_item = self:get_preceding_cite_item(cite_item, previous_cite, previous_citation, note_number) + if preceding_cite_item then + position = self:_get_cite_position(cite_item, preceding_cite_item) + end + + local near_note = false + local last_note_number = self.cite_last_note_numbers[cite_item.id] + if last_note_number then + local note_distance = note_number - last_note_number + if note_distance <= self.style.citation.near_note_distance then + near_note = true + end + end + + local tainted = false + if cite_item.position_level ~= position then + tainted = true + cite_item.position_level = position + end + if cite_item["first-reference-note-number"] ~= first_reference_note_number then + tainted = true + cite_item["first-reference-note-number"] = first_reference_note_number + end + if cite_item.near_note ~= near_note then + tainted = true + cite_item.near_note = near_note + end + return tainted +end + +-- Find the preceding cite referencing the same item +function CiteProc:get_preceding_cite_item(cite_item, previous_cite, previous_citation, note_number) + if previous_cite then + -- a. the current cite immediately follows on another cite, within the same + -- citation, that references the same item + if cite_item.id == previous_cite.id then + return previous_cite + end + elseif previous_citation then + -- (hidden) The previous citation is the only one in the previous note. + -- See also + -- https://github.com/citation-style-language/documentation/issues/121 + -- position_IbidWithMultipleSoloCitesInBackref.txt + -- b. the current cite is the first cite in the citation, and the previous + -- citation consists of a single cite referencing the same item + local previous_note_number = previous_citation.properties.noteIndex + local num_previous_note_citations = #self.note_citations_map[previous_note_number] + if (previous_note_number == note_number - 1 and num_previous_note_citations == 1) + or previous_note_number == note_number then + if #previous_citation.citationItems == 1 then + previous_cite = previous_citation.citationItems[1] + if previous_cite.id == cite_item.id then + return previous_cite end - end}) + end + end + end + return nil +end - if not item.position and position_first then - item.position = util.position_map["first"] +function CiteProc:_get_cite_position(item, preceding_cite) + if preceding_cite.locator then + if item.locator then + if item.locator == preceding_cite.locator and item.label == preceding_cite.label then + return util.position_map["ibid"] + else + return util.position_map["ibid-with-locator"] end + else + return util.position_map["subsequent"] + end + else + if item.locator then + return util.position_map["ibid-with-locator"] + else + return util.position_map["ibid"] + end + end +end + +function CiteProc:build_citation_str(citation) + -- util.debug(citation.citationID) + local items = {} + for i, cite_item in ipairs(citation.citationItems) do + cite_item.id = tostring(cite_item.id) + -- util.debug(cite_item.id) + + -- Use "page" as locator label if missing + -- label_PluralWithAmpersand.txt + if cite_item.locator and not cite_item.label then + cite_item.label = "page" + end + + table.insert(items, cite_item) + end - local first_reference_note_number = nil - for _, pre_citation in ipairs(citationsPre) do - pre_citation = self.registry.citations[pre_citation[1]] - for _, pre_cite_item in ipairs(pre_citation.citationItems) do - if pre_cite_item.id == cite_item.id then - first_reference_note_number = pre_citation.properties.noteIndex + if self.registry.requires_sorting then + self:sort_bibliography() + end + + local citation_str = self:build_cluster(items) + return citation_str +end + +function CiteProc:build_cluster(citation_items) + local output_format = self.output_format + local irs = {} + citation_items = self:sorted_citation_items(citation_items) + for _, cite_item in ipairs(citation_items) do + local ir = self:build_fully_disambiguated_ir(cite_item, output_format) + table.insert(irs, ir) + end + + if self.style.citation.cite_grouping then + irs = self:group_cites(irs) + else + local citation_collapse = self.style.citation.collapse + if citation_collapse == "year" or citation_collapse == "year-suffix" or + citation_collapse == "year-suffix-ranged" then + irs = self:group_cites(irs) + end + end + + if self.style.citation.collapse then + self:collapse_cites(irs) + end + + -- Capitalize first + for i, ir in ipairs(irs) do + -- local layout_prefix + -- local layout_affixes = self.style.citation.layout.affixes + -- if layout_affixes then + -- layout_prefix = layout_affixes.prefix + -- end + local prefix = citation_items[i].prefix + if prefix then + if prefix and string.match(prefix, "[.!?]%s*$") and #util.split(util.strip(prefix)) > 1 then + ir:capitalize_first_term() + end + else + local delimiter = self.style.citation.layout.delimiter + if i == 1 or not delimiter or string.match(delimiter, "[.!?]%s*$") then + ir:capitalize_first_term() + end + end + end + + -- util.debug(irs) + + local citation_delimiter = self.style.citation.layout.delimiter + local citation_stream = {} + + local context = Context:new() + context.engine = self + context.style = self.style + context.area = self.style.citation + context.in_bibliography = false + context.locale = self:get_locale(self.lang) + context.name_inheritance = self.style.citation.name_inheritance + context.format = output_format + + local previous_ir + for i, ir in ipairs(irs) do + local cite_prefix = citation_items[i].prefix + local cite_suffix = citation_items[i].suffix + if not ir.collapse_suppressed then + local ir_inlines = ir:flatten(output_format) + if #ir_inlines > 0 then + -- Make sure ir_inlines has outputs contents. + -- collapse_AuthorCollapseNoDateSorted.txt + if previous_ir then + if previous_ir.own_delimiter then + table.insert(citation_stream, PlainText:new(previous_ir.own_delimiter)) + elseif citation_delimiter and not (cite_prefix and util.startswith(cite_prefix, ",")) then + table.insert(citation_stream, PlainText:new(citation_delimiter)) end - break end - if first_reference_note_number then - break + + if cite_prefix then + table.insert(citation_stream, Micro:new(InlineElement:parse(cite_prefix, context))) + end + + -- util.debug(ir) + util.extend(citation_stream, ir_inlines) + previous_ir = ir + + if cite_suffix then + table.insert(citation_stream, Micro:new(InlineElement:parse(cite_suffix, context))) end end - item["first-reference-note-number"] = first_reference_note_number + end + end + -- util.debug(citation_stream) - table.insert(items, item) + if context.area.layout.affixes then + local affixes = context.area.layout.affixes + if affixes.prefix then + table.insert(citation_stream, 1, PlainText:new(affixes.prefix)) + end + if affixes.suffix then + table.insert(citation_stream, PlainText:new(affixes.suffix)) end end + -- util.debug(citation_stream) - if #citationsPre > 0 then - local previous_citation_id = citationsPre[#citationsPre][1] - local previous_citation = self.registry.citations[previous_citation_id] - self.registry.previous_citation = previous_citation + if #citation_stream > 0 and context.area.layout.formatting then + citation_stream = {Formatted:new(citation_stream, context.area.layout.formatting)} end - if self.registry.requires_sorting then - self:sort_bibliography() + if #citation_stream == 0 then + citation_stream = {PlainText:new("[CSL STYLE ERROR: reference with no printed form.]")} end - local params = { - bibchange = false, - citation_errors = {}, - } + -- util.debug(citation_stream) + local str = output_format:output(citation_stream, context) + str = util.strip(str) - local citation_id_note_list = {} - for _, citation_id_note in ipairs(citationsPre) do - table.insert(citation_id_note_list, citation_id_note) + return str +end + +function CiteProc:sorted_citation_items(items) + local citation_sort = self.style.citation.sort + if not citation_sort then + return items end - local note_index = 0 - if citation.properties and citation.properties.noteIndex then - note_index = citation.properties.noteIndex + + local state = IrState:new() + local context = Context:new() + context.engine = self + context.style = self.style + context.area = self.style.citation + context.in_bibliography = false + context.locale = self:get_locale(self.lang) + context.name_inheritance = self.style.citation.name_inheritance + context.format = SortStringFormat:new() + -- context.id = id + context.cite = nil + -- context.reference = self:get_item(id) + + items = citation_sort:sort(items, state, context) + return items +end + +function CiteProc:build_fully_disambiguated_ir(cite_item, output_format) + local cite_ir = self:build_ambiguous_ir(cite_item, output_format) + -- util.debug(cite_ir) + cite_ir = self:disambiguate_add_givenname(cite_ir) + cite_ir = self:disambiguate_add_names(cite_ir) + cite_ir = self:disambiguate_conditionals(cite_ir) + cite_ir = self:disambiguate_add_year_suffix(cite_ir) + return cite_ir +end + +function CiteProc:build_ambiguous_ir(cite_item, output_format) + local state = IrState:new(self.style) + cite_item.id = tostring(cite_item.id) + local context = Context:new() + context.engine = self + context.style = self.style + context.area = self.style.citation + context.locale = self:get_locale(self.lang) + context.name_inheritance = self.style.citation.name_inheritance + context.format = output_format + context.id = cite_item.id + context.cite = cite_item + -- context.reference = self:get_item(cite_item.id) + context.reference = self.registry.registry[cite_item.id] + + local ir + if context.reference then + ir = self.style.citation:build_ir(self, state, context) + else + -- The warning has been given in the retrieving procedure. + -- util.warning(string.format('Failed to find the entry "%s" in database.', cite_item.id)) + ir = Rendered:new({Formatted:new({PlainText:new(cite_item.id)}, {["font-weight"] = "bold"})}, self) end - table.insert(citation_id_note_list, {citation.citationID, note_index}) - for _, citation_id_note in ipairs(citationsPost) do - table.insert(citation_id_note_list, citation_id_note) + + ir.cite_item = cite_item + ir.reference = context.reference + ir.ir_index = #self.disam_irs + 1 + table.insert(self.disam_irs, ir) + ir.is_ambiguous = false + ir.disam_level = 0 + + -- Formattings like font-style are ignored for disambiguation. + local disam_format = DisamStringFormat:new() + local inlines = ir:flatten(disam_format) + local disam_str = disam_format:output(inlines, context) + ir.disam_str = disam_str + + if not self.cite_irs_by_output[disam_str] then + self.cite_irs_by_output[disam_str] = {} end - local citation_id_cited = {} - for _, citation_id_note in ipairs(citation_id_note_list) do - citation_id_cited[citation_id_note[1]] = true + for ir_index, ir_ in pairs(self.cite_irs_by_output[disam_str]) do + if ir_.cite_item.id ~= cite_item.id then + ir.is_ambiguous = true + break + end end - for citation_id, _ in pairs(self.registry.citations) do - if not citation_id_cited[citation_id] then - self.registry.citations[citation_id] = nil - self.registry.citation_strings[citation_id] = nil + self.cite_irs_by_output[disam_str][ir.ir_index] = ir + + return ir +end + +function CiteProc:disambiguate_add_givenname(cite_ir) + if self.style.citation.disambiguate_add_givenname then + -- util.debug("disambiguate_add_givenname: " .. cite_ir.cite_item.id) + + local gn_disam_rule = self.style.citation.givenname_disambiguation_rule + if gn_disam_rule == "all-names" or gn_disam_rule == "all-names-with-initials" then + cite_ir = self:disambiguate_add_givenname_all_names(cite_ir) + elseif gn_disam_rule == "primary-name" or gn_disam_rule == "primary-name-with-initials" then + cite_ir = self:disambiguate_add_givenname_primary_name(cite_ir) + elseif gn_disam_rule == "by-cite" then + cite_ir = self:disambiguate_add_givenname_by_cite(cite_ir) end end + return cite_ir +end - local output = {} +-- TODO: reorganize this code +function CiteProc:disambiguate_add_givenname_all_names(cite_ir) + -- util.debug("disambiguate_add_givenname_all_names: " .. cite_ir.cite_item.id) + if not cite_ir.person_name_irs or #cite_ir.person_name_irs == 0 then + return cite_ir + end + + -- util.debug(cite_ir.disam_str) + + for _, person_name_ir in ipairs(cite_ir.person_name_irs) do + local name_output = person_name_ir.name_output + -- util.debug(name_output) + + if not person_name_ir.person_name_index then + person_name_ir.person_name_index = #self.person_names + 1 + table.insert(self.person_names, person_name_ir) + end + + if not self.person_names_by_output[name_output] then + self.person_names_by_output[name_output] = {} + end + self.person_names_by_output[name_output][person_name_ir.person_name_index] = person_name_ir + + local ambiguous_name_irs = {} + local ambiguous_same_output_irs = {} + + for _, pn_ir in pairs(self.person_names_by_output[person_name_ir.name_output]) do + if pn_ir.full_name ~= person_name_ir.full_name then + table.insert(ambiguous_name_irs, pn_ir) + end + if pn_ir.name_output == person_name_ir.name_output then + table.insert(ambiguous_same_output_irs, pn_ir) + end + end + + -- util.debug(person_name_ir.name_output) + -- util.debug(person_name_ir.full_name) + -- util.debug(#ambiguous_name_irs) + -- util.debug(person_name_ir.disam_variants_index) + -- util.debug(person_name_ir.disam_variants) + + while person_name_ir.disam_variants_index < #person_name_ir.disam_variants do + if #ambiguous_name_irs == 0 then + break + end + + for _, pn_ir in ipairs(ambiguous_same_output_irs) do + -- expand one name + if pn_ir.disam_variants_index < #pn_ir.disam_variants then + pn_ir.disam_variants_index = pn_ir.disam_variants_index + 1 + pn_ir.name_output = pn_ir.disam_variants[pn_ir.disam_variants_index] + pn_ir.inlines = pn_ir.disam_inlines[pn_ir.name_output] + + if not self.person_names_by_output[pn_ir.name_output] then + self.person_names_by_output[pn_ir.name_output] = {} + end + self.person_names_by_output[pn_ir.name_output][pn_ir.person_name_index] = pn_ir + end + end + + -- util.debug(person_name_ir.name_output) + + -- update ambiguous_name_irs and ambiguous_same_output_irs + ambiguous_name_irs = {} + ambiguous_same_output_irs = {} + for _, pn_ir in pairs(self.person_names_by_output[person_name_ir.name_output]) do + if pn_ir.full_name ~= person_name_ir.full_name then + -- util.debug(pn_ir.full_name .. ": " .. pn_ir.name_output) + table.insert(ambiguous_name_irs, pn_ir) + end + if pn_ir.name_output == person_name_ir.name_output then + table.insert(ambiguous_same_output_irs, pn_ir) + end + end + + end + end + + -- update cite_ir output + local disam_format = DisamStringFormat:new() + local inlines = cite_ir:flatten(disam_format) + local disam_str = disam_format:output(inlines, context) + cite_ir.disam_str = disam_str + if not self.cite_irs_by_output[disam_str] then + self.cite_irs_by_output[disam_str] = {} + end + self.cite_irs_by_output[disam_str][cite_ir.ir_index] = cite_ir + + -- update ambiguous_cite_irs and ambiguous_same_output_irs + local ambiguous_cite_irs = {} + for ir_index, ir_ in pairs(self.cite_irs_by_output[cite_ir.disam_str]) do + -- util.debug(ir_.cite_item.id) + if ir_.cite_item.id ~= cite_ir.cite_item.id then + table.insert(ambiguous_cite_irs, ir_) + end + end + if #ambiguous_cite_irs == 0 then + cite_ir.is_ambiguous = false + end + + return cite_ir +end + +function CiteProc:disambiguate_add_givenname_primary_name(cite_ir) + if not cite_ir.person_name_irs or #cite_ir.person_name_irs == 0 then + return cite_ir + end + local person_name_ir = cite_ir.person_name_irs[1] + local name_output = person_name_ir.name_output + -- util.debug(name_output) + + if not person_name_ir.person_name_index then + person_name_ir.person_name_index = #self.person_names + 1 + table.insert(self.person_names, person_name_ir) + end + if not self.person_names_by_output[name_output] then + self.person_names_by_output[name_output] = {} + end + self.person_names_by_output[name_output][person_name_ir.person_name_index] = person_name_ir + + local ambiguous_name_irs = {} + local ambiguous_same_output_irs = {} + + for _, pn_ir in pairs(self.person_names_by_output[person_name_ir.name_output]) do + if pn_ir.full_name ~= person_name_ir.full_name then + table.insert(ambiguous_name_irs, pn_ir) + end + if pn_ir.name_output == person_name_ir.name_output then + table.insert(ambiguous_same_output_irs, pn_ir) + end + end + + for _, name_variant in ipairs(person_name_ir.disam_variants) do + if #ambiguous_name_irs == 0 then + break + end + + for _, pn_ir in ipairs(ambiguous_same_output_irs) do + -- expand one name + if pn_ir.disam_variants_index < #pn_ir.disam_variants then + pn_ir.disam_variants_index = pn_ir.disam_variants_index + 1 + pn_ir.name_output = pn_ir.disam_variants[pn_ir.disam_variants_index] + pn_ir.inlines = pn_ir.disam_inlines[pn_ir.name_output] + + if not self.person_names_by_output[pn_ir.name_output] then + self.person_names_by_output[pn_ir.name_output] = {} + end + self.person_names_by_output[pn_ir.name_output][person_name_ir.person_name_index] = person_name_ir + end + end + + -- update ambiguous_name_irs and ambiguous_same_output_irs + ambiguous_name_irs = {} + ambiguous_same_output_irs = {} + for _, pn_ir in pairs(self.person_names_by_output[person_name_ir.name_output]) do + if pn_ir.full_name ~= person_name_ir.full_name then + table.insert(ambiguous_name_irs, pn_ir) + end + if pn_ir.name_output == person_name_ir.name_output then + table.insert(ambiguous_same_output_irs, pn_ir) + end + end + end + + return cite_ir +end + +function CiteProc:disambiguate_add_givenname_by_cite(cite_ir) + if not cite_ir.is_ambiguous then + return cite_ir + end + if not cite_ir.person_name_irs or #cite_ir.person_name_irs == 0 then + return cite_ir + end + + for _, ir_ in ipairs(self.disam_irs) do + -- util.debug(ir_.cite_item.id) + -- util.debug(ir_.disam_str) + end + + local disam_format = DisamStringFormat:new() + + local ambiguous_cite_irs = {} + local ambiguous_same_output_irs = {} + + for ir_index, ir_ in pairs(self.cite_irs_by_output[cite_ir.disam_str]) do + if ir_.cite_item.id ~= cite_ir.cite_item.id then + table.insert(ambiguous_cite_irs, ir_) + end + if ir_.disam_str == cite_ir.disam_str then + table.insert(ambiguous_same_output_irs, ir_) + end + end + + for i, person_name_ir in ipairs(cite_ir.person_name_irs) do + -- util.debug(person_name_ir.name_output) + -- util.debug(person_name_ir.disam_variants) + if #ambiguous_cite_irs == 0 then + cite_ir.is_ambiguous = false + break + end + + -- util.debug(person_name_ir.disam_variants) + while person_name_ir.disam_variants_index < #person_name_ir.disam_variants do + -- util.debug(person_name_ir.name_output) + + local is_different_name = false + for _, ir_ in ipairs(ambiguous_cite_irs) do + if ir_.person_name_irs[i] then + if ir_.person_name_irs[i].full_name ~= person_name_ir.full_name then + -- util.debug(ir_.cite_item.id) + is_different_name = true + break + end + end + end + -- util.debug(is_different_name) + if not is_different_name then + break + end + + for _, ir_ in ipairs(ambiguous_same_output_irs) do + -- util.debug(ir_.cite_item.id) + local person_name_ir_ = ir_.person_name_irs[i] + if person_name_ir_ then + if person_name_ir_.disam_variants_index < #person_name_ir_.disam_variants then + person_name_ir_.disam_variants_index = person_name_ir_.disam_variants_index + 1 + local disam_variant = person_name_ir_.disam_variants[person_name_ir_.disam_variants_index] + person_name_ir_.name_output = disam_variant + -- util.debug(disam_variant) + person_name_ir_.inlines = person_name_ir_.disam_inlines[disam_variant] + -- Update cite ir output + local inlines = ir_:flatten(disam_format) + local disam_str = disam_format:output(inlines, context) + ir_.disam_str = disam_str + if not self.cite_irs_by_output[disam_str] then + self.cite_irs_by_output[disam_str] = {} + end + self.cite_irs_by_output[disam_str][ir_.ir_index] = ir_ + end + end + end + + -- update ambiguous_cite_irs and ambiguous_same_output_irs + ambiguous_cite_irs = {} + ambiguous_same_output_irs = {} + for ir_index, ir_ in pairs(self.cite_irs_by_output[cite_ir.disam_str]) do + -- util.debug(ir_.cite_item.id) + if ir_.cite_item.id ~= cite_ir.cite_item.id then + table.insert(ambiguous_cite_irs, ir_) + end + if ir_.disam_str == cite_ir.disam_str then + table.insert(ambiguous_same_output_irs, ir_) + end + end + + -- util.debug(#ambiguous_cite_irs) + + if #ambiguous_cite_irs == 0 then + cite_ir.is_ambiguous = false + return cite_ir + end + + end + end + + return cite_ir +end + +local function find_first_name_ir(ir) + if ir._type == "NameIr" then + return ir + end + if ir.children then + for _, child in ipairs(ir.children) do + local name_ir = find_first_name_ir(child) + if name_ir then + return name_ir + end + end + end + return nil +end + +function CiteProc:disambiguate_add_names(cite_ir) + if not self.style.citation.disambiguate_add_names then + return cite_ir + end + + if not cite_ir.name_ir then + cite_ir.name_ir = find_first_name_ir(cite_ir) + end + local name_ir = cite_ir.name_ir + + if not cite_ir.is_ambiguous then + return cite_ir + end + + if not name_ir or not name_ir.et_al_abbreviation then + return cite_ir + end + + -- util.debug("disambiguate_add_names: " .. cite_ir.cite_item.id) + + if name_ir then + -- util.debug(cite_ir.disam_str) + -- util.debug(cite_ir.name_ir.full_name_str) + -- util.debug(cite_ir.is_ambiguous) + end + + local disam_format = DisamStringFormat:new() + + while cite_ir.is_ambiguous do + if #cite_ir.name_ir.hidden_name_irs == 0 then + break + end + + local ambiguous_cite_irs = {} + local ambiguous_same_output_irs = {} + for _, ir_ in pairs(self.cite_irs_by_output[cite_ir.disam_str]) do + if ir_.cite_item.id ~= cite_ir.cite_item.id then + table.insert(ambiguous_cite_irs, ir_) + end + if ir_.disam_str == cite_ir.disam_str then + table.insert(ambiguous_same_output_irs, ir_) + end + end + + -- util.debug(#ambiguous_same_output_irs) + if #ambiguous_cite_irs == 0 then + cite_ir.is_ambiguous = false + break + end + + -- check if the cite can be (fully) disambiguated by adding names + local can_be_disambuguated = false + for _, ir_ in ipairs(ambiguous_cite_irs) do + if ir_.name_ir.full_name_str ~= cite_ir.name_ir.full_name_str then + can_be_disambuguated = true + break + end + end + -- util.debug(can_be_disambuguated) + if not can_be_disambuguated then + break + end + + for _, ir_ in ipairs(ambiguous_same_output_irs) do + local added_person_name_ir = ir_.name_ir.name_inheritance:expand_one_name(ir_.name_ir) + if added_person_name_ir then + -- util.debug("Updated: " .. ir_.cite_item.id) + table.insert(ir_.person_name_irs, added_person_name_ir) + + if not added_person_name_ir.person_name_index then + added_person_name_ir.person_name_index = #self.person_names + 1 + table.insert(self.person_names, added_person_name_ir) + end + local name_output = added_person_name_ir.name_output + if not self.person_names_by_output[name_output] then + self.person_names_by_output[name_output] = {} + end + self.person_names_by_output[name_output][added_person_name_ir.person_name_index] = added_person_name_ir + + -- Update ir output + local inlines = ir_:flatten(disam_format) + local disam_str = disam_format:output(inlines, context) + -- util.debug(disam_str) + ir_.disam_str = disam_str + if not self.cite_irs_by_output[disam_str] then + self.cite_irs_by_output[disam_str] = {} + end + self.cite_irs_by_output[disam_str][ir_.ir_index] = ir_ + end + end + + -- util.debug("disambiguate_add_givenname") + + if self.style.citation.disambiguate_add_givenname then + local gn_disam_rule = self.style.citation.givenname_disambiguation_rule + if gn_disam_rule == "all-names" or gn_disam_rule == "all-names-with-initials" then + cite_ir = self:disambiguate_add_givenname_all_names(cite_ir) + elseif gn_disam_rule == "by-cite" then + cite_ir = self:disambiguate_add_givenname_by_cite(cite_ir) + end + end + + cite_ir.is_ambiguous = self:check_ambiguity(cite_ir) + + for _, ir_ in ipairs(self.disam_irs) do + -- util.debug(ir_.cite_item.id .. ": " .. ir_.disam_str) + end + + end + + + return cite_ir +end + +function CiteProc:collect_irs_with_disambiguate_branch(ir) + local irs_with_disambiguate_branch = {} + if ir.children then + for i, child_ir in ipairs(ir.children) do + if child_ir.disambiguate_branch_ir then + table.insert(irs_with_disambiguate_branch, child_ir) + elseif child_ir.children then + util.extend(irs_with_disambiguate_branch, + self:collect_irs_with_disambiguate_branch(child_ir)) + end + end + end + return irs_with_disambiguate_branch +end + +function CiteProc:disambiguate_conditionals(cite_ir) + -- util.debug(cite_ir) + + cite_ir.irs_with_disambiguate_branch = self:collect_irs_with_disambiguate_branch(cite_ir) + + local disam_format = DisamStringFormat:new() + + while cite_ir.is_ambiguous do + if #cite_ir.irs_with_disambiguate_branch == 0 then + break + end + + -- util.debug(cite_ir.cite_item.id) + -- util.debug(cite_ir.disam_str) + + -- update ambiguous_same_output_irs + local ambiguous_same_output_irs = {} + for _, ir_ in pairs(self.cite_irs_by_output[cite_ir.disam_str]) do + if ir_.disam_str == cite_ir.disam_str then + table.insert(ambiguous_same_output_irs, ir_) + end + end + + for _, ir_ in ipairs(ambiguous_same_output_irs) do + if #ir_.irs_with_disambiguate_branch > 0 then + -- Disambiguation is incremental + -- disambiguate_IncrementalExtraText.txt + local condition_ir = ir_.irs_with_disambiguate_branch[1] + condition_ir.children[1] = condition_ir.disambiguate_branch_ir + condition_ir.group_var = condition_ir.disambiguate_branch_ir.group_var + table.remove(ir_.irs_with_disambiguate_branch, 1) + -- disambiguate_DisambiguateTrueReflectedInBibliography.txt + ir_.reference.disambiguate = true + + -- Update ir output + local inlines = ir_:flatten(disam_format) + local disam_str = disam_format:output(inlines, context) + -- util.debug("update: " .. ir_.cite_item.id .. ": " .. disam_str) + ir_.disam_str = disam_str + if not self.cite_irs_by_output[disam_str] then + self.cite_irs_by_output[disam_str] = {} + end + self.cite_irs_by_output[disam_str][ir_.ir_index] = ir_ + end + end + + cite_ir.is_ambiguous = self:check_ambiguity(cite_ir) + -- util.debug(cite_ir.is_ambiguous) + for _, ir_ in ipairs(self.disam_irs) do + -- util.debug(ir_.cite_item.id .. ": " .. ir_.disam_str) + end + + end + return cite_ir +end + +function CiteProc:check_ambiguity(cite_ir) + for _, ir_ in pairs(self.cite_irs_by_output[cite_ir.disam_str]) do + if ir_.cite_item.id ~= cite_ir.cite_item.id then + return true + end + end + return false +end + +function CiteProc:get_same_output_irs(cite_ir) + local ambiguous_same_output_irs = {} + for _, ir_ in pairs(self.cite_irs_by_output[cite_ir.disam_str]) do + if ir_.disam_str == cite_ir.disam_str then + table.insert(ambiguous_same_output_irs, ir_) + end + end + return ambiguous_same_output_irs +end + +function CiteProc:disambiguate_add_year_suffix(cite_ir) + if not cite_ir.is_ambiguous or not self.style.citation.disambiguate_add_year_suffix then + return cite_ir + end + + local same_output_irs = self:get_same_output_irs(cite_ir) + + table.sort(same_output_irs, function (a, b) + -- return a.ir_index < b.ir_index + return a.reference["citation-number"] < b.reference["citation-number"] + end) + + local year_suffix_number = 0 + -- util.debug(cite_ir) + + local disam_format = DisamStringFormat:new() + + for _, ir_ in ipairs(same_output_irs) do + ir_.reference.year_suffix_number = nil + end + + for _, ir_ in ipairs(same_output_irs) do + -- print(ir_.cite_item.id) + -- print(ir_.reference) + if not ir_.reference.year_suffix_number then + year_suffix_number = year_suffix_number + 1 + ir_.reference.year_suffix_number = year_suffix_number + ir_.reference["year-suffix"] = self:render_year_suffix(year_suffix_number) + end - for i, citation_id_note in ipairs(citation_id_note_list) do - local citation_id = citation_id_note[1] - -- local note_index = citation_id_note[2] - if citation_id == citation.citationID then - local context = { - build = {}, - engine = self, - } - local citation_str = self.style:render_citation(items, context) - - self.registry.citation_strings[citation_id] = citation_str - table.insert(output, {i - 1, citation_str, citation_id}) + if not ir_.year_suffix_irs then + ir_.year_suffix_irs = self:collect_year_suffix_irs(ir_) + if #ir_.year_suffix_irs == 0 then + -- By default, the year-suffix is appended the first year rendered through cs:date + local year_ir = self:find_first_year_ir(ir_) + -- util.debug(year_ir) + if year_ir then + local year_suffix_ir = YearSuffix:new({}, self.style.citation) + table.insert(year_ir.children, year_suffix_ir) + table.insert(ir_.year_suffix_irs, year_suffix_ir) + end + end + end + + for _, year_suffix_ir in ipairs(ir_.year_suffix_irs) do + year_suffix_ir.inlines = {PlainText:new(ir_.reference["year-suffix"])} + year_suffix_ir.year_suffix_number = ir_.reference.year_suffix_number + year_suffix_ir.group_var = "important" + end + + local inlines = ir_:flatten(disam_format) + local disam_str = disam_format:output(inlines, context) + -- util.debug("update: " .. ir_.cite_item.id .. ": " .. disam_str) + ir_.disam_str = disam_str + if not self.cite_irs_by_output[disam_str] then + self.cite_irs_by_output[disam_str] = {} + end + self.cite_irs_by_output[disam_str][ir_.ir_index] = ir_ + + end + + cite_ir.is_ambiguous = false + + return cite_ir +end + +function CiteProc:collect_year_suffix_irs(ir) + local year_suffix_irs = {} + if ir.children then + for i, child_ir in ipairs(ir.children) do + if child_ir._type == "YearSuffix" then + table.insert(year_suffix_irs, child_ir) + elseif child_ir.children then + util.extend(year_suffix_irs, + self:collect_year_suffix_irs(child_ir)) + end + end + end + return year_suffix_irs +end + +function CiteProc:find_first_year_ir(ir) + if ir.is_year then + return ir + end + if ir.children then + for _, child_ir in ipairs(ir.children) do + local year_ir = self:find_first_year_ir(child_ir) + if year_ir then + return year_ir + end + end + end + return nil +end + +function CiteProc:render_year_suffix(year_suffix_number) + if year_suffix_number <= 0 then + return nil + end + local year_suffix = "" + while year_suffix_number > 0 do + local i = (year_suffix_number - 1) % 26 + year_suffix = string.char(i + 97) .. year_suffix + year_suffix_number = (year_suffix_number - 1) // 26 + end + -- util.debug(year_suffix) + return year_suffix +end + +local function find_first(ir, check) + if check(ir) then + return ir + end + if ir.children then + for _, child in ipairs(ir.children) do + local target_ir = find_first(child, check) + if target_ir then + return target_ir + end + end + end + return nil +end + +function CiteProc:group_cites(irs) + local disam_format = DisamStringFormat:new() + for _, ir in ipairs(irs) do + local first_names_ir = ir.first_names_ir + if not first_names_ir then + first_names_ir = find_first(ir, function (ir_) + return ir_._element == "names" + end) + if first_names_ir then + local inlines = first_names_ir:flatten(disam_format) + first_names_ir.disam_str = disam_format:output(inlines, context) + end + ir.first_names_ir = first_names_ir + end + end + + local irs_by_name = {} + local name_list = {} + + for _, ir in ipairs(irs) do + local name_str = "" + if ir.first_names_ir then + name_str = ir.first_names_ir.disam_str + end + if not irs_by_name[name_str] then + irs_by_name[name_str] = {} + table.insert(name_list, name_str) + end + table.insert(irs_by_name[name_str], ir) + end + + local grouped = {} + for _, name_str in ipairs(name_list) do + local irs_with_same_name = irs_by_name[name_str] + for i, ir in ipairs(irs_with_same_name) do + if i < #irs_with_same_name then + ir.own_delimiter = self.style.citation.cite_group_delimiter + end + table.insert(grouped, ir) + end + end + return grouped +end + +function CiteProc:collapse_cites(irs) + if self.style.citation.collapse == "citation-number" then + self:collapse_cites_by_citation_number(irs) + elseif self.style.citation.collapse == "year" then + self:collapse_cites_by_year(irs) + elseif self.style.citation.collapse == "year-suffix" then + self:collapse_cites_by_year_suffix(irs) + elseif self.style.citation.collapse == "year-suffix-ranged" then + self:collapse_cites_by_year_suffix_ranged(irs) + end +end + +function CiteProc:collapse_cites_by_citation_number(irs) + local cite_groups = {} + local current_group = {} + local previous_citation_number + for i, ir in ipairs(irs) do + local citation_number + local only_citation_number_ir = self:get_only_citation_number(ir) + if only_citation_number_ir then + -- Other irs like locators are not rendered. + -- collapse_CitationNumberRangesWithAffixesGrouped.txt + citation_number = only_citation_number_ir.citation_number + end + if i == 1 then + table.insert(current_group, ir) + elseif citation_number and previous_citation_number and + previous_citation_number + 1 == citation_number then + table.insert(current_group, ir) else - -- TODO: correct note_index - -- TODO: update other citations after disambiguation - local citation_str = self.registry.citation_strings[citation_id] - if self.registry.citation_strings[citation_id] ~= citation_str then - params.bibchange = true - self.registry.citation_strings[citation_id] = citation_str - table.insert(output, {i - 1, citation_str, citation_id}) + table.insert(cite_groups, current_group) + current_group = {ir} + end + previous_citation_number = citation_number + end + table.insert(cite_groups, current_group) + + for _, cite_group in ipairs(cite_groups) do + if #cite_group >= 3 then + cite_group[1].own_delimiter = util.unicode["en dash"] + for i = 2, #cite_group - 1 do + cite_group[i].collapse_suppressed = true end + cite_group[#cite_group].own_delimiter = self.style.citation.after_collapse_delimiter end end +end - return {params, output} +function CiteProc:get_only_citation_number(ir) + if ir.citation_number then + return ir + end + if not ir.children then + return nil + end + local only_citation_number_ir + for _, child in ipairs(ir.children) do + if child.group_var ~= "missing" then + local citation_number_ir = self:get_only_citation_number(child) + if citation_number_ir then + if only_citation_number_ir then + return nil + else + only_citation_number_ir = citation_number_ir + end + else + return false + end + end + end + return only_citation_number_ir end -function CiteProc:makeCitationCluster (citation_items) +function CiteProc:collapse_cites_by_year(irs) + local cite_groups = {{}} + local previous_name_str + for i, ir in ipairs(irs) do + local name_str + if ir.first_names_ir then + name_str = ir.first_names_ir.disam_str + end + if i == 1 then + table.insert(cite_groups[#cite_groups], ir) + elseif name_str and name_str == previous_name_str then + -- ir.fist_names_ir was set in the cite grouping stage + -- TODO: and not previous cite suffix + table.insert(cite_groups[#cite_groups], ir) + else + table.insert(cite_groups, {ir}) + end + previous_name_str = name_str + end + + for _, cite_group in ipairs(cite_groups) do + if #cite_group > 1 then + for i, cite_ir in ipairs(cite_group) do + if i > 1 and cite_ir.first_names_ir then + cite_ir.first_names_ir.collapse_suppressed = true + end + if i == #cite_group then + cite_ir.own_delimiter = self.style.citation.after_collapse_delimiter + elseif i < #cite_group then + -- The delimiter depends on the citation > sort. + -- https://github.com/citation-style-language/test-suite/issues/39#issuecomment-687901688 + if cite_ir.cite_item.locator then + -- Special hack for + cite_ir.own_delimiter = self.style.citation.after_collapse_delimiter + elseif self.style.citation.cite_grouping then + if self.style.citation.sort then + cite_ir.own_delimiter = self.style.citation.cite_group_delimiter + else + cite_ir.own_delimiter = self.style.citation.layout.delimiter + end + else + if self.style.citation.sort then + cite_ir.own_delimiter = self.style.citation.cite_group_delimiter + else + -- disambiguate_YearCollapseWithInstitution.txt + -- disambiguate_InitializeWithButNoDisambiguation.txt ? + cite_ir.own_delimiter = self.style.citation.layout.delimiter + end + end + end + end + end + end +end + +local function find_rendered_year_suffix(ir) + if ir._type == "YearSuffix" then + return ir + end + if ir.children then + for _, child in ipairs(ir.children) do + if child.group_var ~= "missing" then + local year_suffix = find_rendered_year_suffix(child) + if year_suffix then + return year_suffix + end + end + end + end + return nil +end + +function CiteProc:collapse_cites_by_year_suffix(irs) + self:collapse_cites_by_year(irs) + -- Group by disam_str + -- The year-suffix is ommitted in DisamStringFormat + local cite_groups = {{}} + local previous_ir + local previous_year_suffix + for i, ir in ipairs(irs) do + local year_suffix = find_rendered_year_suffix(ir) + ir.rendered_year_suffix_ir = year_suffix + if i == 1 then + table.insert(cite_groups[#cite_groups], ir) + elseif year_suffix and previous_ir.disam_str == ir.disam_str and previous_year_suffix then + -- TODO: and not previous cite suffix + table.insert(cite_groups[#cite_groups], ir) + else + table.insert(cite_groups, {ir}) + end + previous_ir = ir + previous_year_suffix = year_suffix + end + + for _, cite_group in ipairs(cite_groups) do + if #cite_group > 1 then + for i, cite_ir in ipairs(cite_group) do + if i > 1 then + -- cite_ir.children = {cite_ir.rendered_year_suffix_ir} + -- Set the collapse_suppressed flag rather than removing the child irs. + -- This leaves the disamb ir structure unchanged. + self:suppress_ir_except_child(cite_ir, cite_ir.rendered_year_suffix_ir) + end + if i < #cite_group then + if self.style.citation.cite_grouping then + -- In the current citeproc-js impplementation, explicitly set + -- cite-group-delimiter takes precedence over year-suffix-delimiter. + -- May be changed in the future. + -- https://github.com/citation-style-language/test-suite/issues/50 + cite_ir.own_delimiter = self.style.citation.cite_group_delimiter + else + cite_ir.own_delimiter = self.style.citation.year_suffix_delimiter + end + elseif i == #cite_group then + cite_ir.own_delimiter = self.style.citation.after_collapse_delimiter + end + end + end + end +end + +function CiteProc:suppress_ir_except_child(ir, target) + if ir == target then + ir.collapse_suppressed = false + return false + end + ir.collapse_suppressed = true + if ir.children then + for _, child in ipairs(ir.children) do + if child.group_var ~= "missing" and not child.collapse_suppressed then + if not self:suppress_ir_except_child(child, target) then + ir.collapse_suppressed = false + end + end + end + end + return ir.collapse_suppressed +end + +function CiteProc:collapse_cites_by_year_suffix_ranged(irs) + self:collapse_cites_by_year_suffix(irs) + -- Group by disam_str + local cite_groups = {{}} + local previous_ir + local previous_year_suffix + for i, ir in ipairs(irs) do + local year_suffix_ir = find_rendered_year_suffix(ir) + ir.rendered_year_suffix_ir = year_suffix_ir + if i == 1 then + table.insert(cite_groups[#cite_groups], ir) + elseif year_suffix_ir and previous_ir.disam_str == ir.disam_str and previous_year_suffix and + year_suffix_ir.year_suffix_number == previous_year_suffix.year_suffix_number + 1 then + -- TODO: and not previous cite suffix + table.insert(cite_groups[#cite_groups], ir) + else + table.insert(cite_groups, {ir}) + end + previous_ir = ir + previous_year_suffix = year_suffix_ir + end + + for _, cite_group in ipairs(cite_groups) do + if #cite_group > 2 then + for i, cite_ir in ipairs(cite_group) do + if i == 1 then + cite_ir.own_delimiter = util.unicode["en dash"] + elseif i < #cite_group then + cite_ir.collapse_suppressed = true + end + end + end + end +end + +function CiteProc:makeCitationCluster(citation_items) local items = {} - for _, cite_item in ipairs(citation_items) do + for i, cite_item in ipairs(citation_items) do cite_item.id = tostring(cite_item.id) - local position_first = (self.registry.registry[cite_item.id] == nil) local item_data = self:get_item(cite_item.id) -- Create a wrapper of the orignal item from registry so that -- it may hold different `locator` or `position` values for cites. - local item = setmetatable({}, {__index = function (_, key) - if cite_item[key] then - return cite_item[key] - else - return item_data[key] + local item = setmetatable(cite_item, {__index = item_data}) + + -- Use "page" as locator label if missing + -- label_PluralWithAmpersand.txt + if item.locator and not item.label then + item.label = "page" + end + + item.position_level = util.position_map["first"] + if self.cite_first_note_numbers[cite_item.id] then + item.position_level = util.position_map["subsequent"] + else + self.cite_first_note_numbers[cite_item.id] = 0 + end + + local preceding_cite + if i == 1 then + local previous_citation = self.registry.previous_citation + if previous_citation then + if #previous_citation.citationItems == 1 and previous_citation.citationItems[1].id == item.id then + preceding_cite = previous_citation.citationItems[1] + end end - end}) + elseif citation_items[i - 1].id == item.id then + preceding_cite = citation_items[i - 1] + end - if not item.position and position_first then - item.position = util.position_map["first"] + if preceding_cite then + item.position_level = self:_get_cite_position(item, preceding_cite) end + table.insert(items, item) end @@ -242,134 +1620,252 @@ function CiteProc:makeCitationCluster (citation_items) self:sort_bibliography() end - local context = { - build = {}, - engine=self, - } - local res = self.style:render_citation(items, context) + local res = self:build_cluster(items) + + -- local context = { + -- build = {}, + -- engine=self, + -- } + -- local res = self.style:render_citation(items, context) + self.registry.previous_citation = { citationID = "pseudo-citation", citationItems = items, properties = { - noteIndex = 1, + noteIndex = 0, } } return res end function CiteProc:makeBibliography() - local items = {} + if not self.style.bibliography then + return {{}, {}} + end + + local output_format = self.output_format + + local res = {} + + self.registry.longest_label = "" + self.registry.maxoffset = 0 + + for _, id in ipairs(self:get_sorted_refs()) do + local ref = self.registry.registry[id] + + local state = IrState:new() + local context = Context:new() + context.engine = self + context.style = self.style + context.area = self.style.bibliography + context.in_bibliography = true + context.locale = self:get_locale(self.lang) + context.name_inheritance = self.style.bibliography.name_inheritance + context.format = output_format + context.id = id + context.cite = nil + context.reference = self:get_item(id) + + local ir = self.style.bibliography:build_ir(self, state, context) + -- util.debug(ir) + ir.reference = context.reference + + -- Add year-suffix + self:add_bibliography_year_suffix(ir) + + -- The layout output may be empty: sort_OmittedBibRefNonNumericStyle.txt + if ir then + local flat = ir:flatten(output_format) + local str = output_format:output_bibliography_entry(flat, context) + table.insert(res, str) + end + end + + local bib_start = self.output_format.markups["bibstart"] + local bib_end = self.output_format.markups["bibend"] + if type(bib_start) == "function" then + bib_start = bib_start(self) + end + if type(bib_end) == "function" then + bib_end = bib_end(self) + end + + local params = { + hangingindent = self.style.bibliography.hanging_indent, + ["second-field-align"] = self.style.bibliography.second_field_align ~= nil, + linespacing = self.style.bibliography.line_spacing, + entryspacing = self.style.bibliography.entry_spacing, + maxoffset = self.registry.maxoffset, + bibstart = bib_start, + bibend = bib_end, + entry_ids = util.clone(self.registry.reflist), + } + return {params, res} +end + +function CiteProc:get_sorted_refs() if self.registry.requires_sorting then self:sort_bibliography() end + return self.registry.reflist +end - for _, id in ipairs(self.registry.reflist) do - local item = self.registry.registry[id] - table.insert(items, item) +function CiteProc:add_bibliography_year_suffix(ir) + if not ir.reference.year_suffix_number then + return end - local context = { - build = {}, - engine=self, - } - local res = self.style:render_biblography(items, context) - return res + local year_suffix_number = ir.reference.year_suffix_number + + if not ir.year_suffix_irs then + ir.year_suffix_irs = self:collect_year_suffix_irs(ir) + if #ir.year_suffix_irs == 0 then + local year_ir = self:find_first_year_ir(ir) + -- util.debug(year_ir) + if year_ir then + local year_suffix_ir = YearSuffix:new({}, self.style.citation) + table.insert(year_ir.children, year_suffix_ir) + table.insert(ir.year_suffix_irs, year_suffix_ir) + end + end + end + + for _, year_suffix_ir in ipairs(ir.year_suffix_irs) do + year_suffix_ir.inlines = {PlainText:new(ir.reference["year-suffix"])} + year_suffix_ir.group_var = "important" + end + + end -function CiteProc:set_formatter(format) - self.formatter = formats[format] +function CiteProc:set_output_format(format) + if format == "latex" then + self.output_format = LatexWriter:new() + elseif format == "html" then + self.output_format = HtmlWriter:new() + end end function CiteProc:enable_linking() - self.linking_enabled = true + self.opt.url_link = true + self.opt.doi_link = true end function CiteProc:disable_linking() - self.linking_enabled = false + self.opt.url_link = false + self.opt.doi_link = false end -function CiteProc.set_base_class (node) - if node:is_element() then - local name = node:get_element_name() - local element_class = nodes[name] - if element_class then - element_class:set_base_class(node) - else - element.Element:set_base_class(node) +function CiteProc.create_element_tree(node) + local element_name = node:get_element_name() + local element_class = nodes[element_name] + local el = nil + if element_class then + el = element_class:from_node(node) + end + if el then + for i, child in ipairs(node:get_children()) do + if child:is_element() then + local child_element = CiteProc.create_element_tree(child) + if child_element then + if not el.children then + el.children = {} + end + table.insert(el.children, child_element) + end + end end end + return el end -function CiteProc:get_style_class() - return self.style:get_attribute("class") or "in-text" -end - -function CiteProc:get_item (id) +function CiteProc:get_item(id) local item = self.registry.registry[id] if not item then item = self:_retrieve_item(id) if not item then return nil end + item = self:process_extra_note(item) table.insert(self.registry.reflist, id) item["citation-number"] = #self.registry.reflist self.registry.registry[id] = item self.registry.requires_sorting = true end - local res = {} - setmetatable(res, {__index = item}) - return res + -- local res = {} + -- setmetatable(res, {__index = item}) + -- return res + return item end -function CiteProc:_retrieve_item (id) +function CiteProc:_retrieve_item(id) -- Retrieve, copy, and normalize local res = {} local item = self.sys.retrieveItem(id) if not item then - util.warning(string.format('Failed to retrieve item "%s"', id)) + util.warning(string.format('Failed to find entry "%s"', id)) return nil end item.id = tostring(item.id) for key, value in pairs(item) do - if key == "title" then - value = self.normalize_string(value) - end res[key] = value end - if res["page"] and not res["page-first"] then - local page_first = util.split(res["page"], "%s*[&,-]%s*")[1] - page_first = util.split(page_first, util.unicode["en dash"])[1] - res["page-first"] = page_first - end + -- if res["page"] and not res["page-first"] then + -- local page_first = util.split(res["page"], "%s*[&,-]%s*")[1] + -- page_first = util.split(page_first, util.unicode["en dash"])[1] + -- res["page-first"] = page_first + -- end return res end -function CiteProc.normalize_string (str) - if not str or str == "" then - return str - end - -- French punctuation spacing - if type(str) == "string" then - str = string.gsub(str, " ;", util.unicode["narrow no-break space"] .. ";") - str = string.gsub(str, " %?", util.unicode["narrow no-break space"] .. "?") - str = string.gsub(str, " !", util.unicode["narrow no-break space"] .. "!") - str = string.gsub(str, " »", util.unicode["narrow no-break space"] .. "»") - str = string.gsub(str, "« ", "«" .. util.unicode["narrow no-break space"]) +-- TODO: Nomalize all inputs +function CiteProc:process_extra_note(item) + if item.note then + local note_fields = {} + for _, line in ipairs(util.split(item.note, "%s*\r?\n%s*")) do + -- util.debug(line) + local splits = util.split(line, ":%s+", 1) + -- util.debug(splits) + if #splits == 2 then + local field, value = table.unpack(splits) + -- util.debug(field) + + local variable_type = util.variable_types[field] + if not item[field] or field == "type" or variable_type == "date" then + if variable_type == "number" then + item[field] = value + elseif variable_type == "date" then + item[field] = util.parse_iso_date(value) + elseif variable_type == "name" then + if not note_fields[field] then + note_fields[field] = {} + end + table.insert(note_fields[field], util.parse_extra_name(value)) + else + item[field] = value + end + end + end + end + for field, value in pairs(note_fields) do + item[field] = value + end end - -- local text = str - local text = richtext.new(str) - return text + return item end function CiteProc:sort_bibliography() -- Sort the items in registry according to the `sort` in `bibliography.` -- This will update the `citation-number` of each item. - local bibliography_sort = self.style:get_path("style bibliography sort")[1] + local bibliography_sort = nil + if self.style.bibliography and self.style.bibliography.sort then + bibliography_sort = self.style.bibliography.sort + end if not bibliography_sort then return end @@ -378,44 +1874,119 @@ function CiteProc:sort_bibliography() table.insert(items, self.registry.registry[id]) end - local context = { - engine = self, - style = self.style, - mode = "bibliography", - } - context = self.style:process_context(context) - context = self.style:get_path("style bibliography")[1]:process_context(context) + local state = IrState:new() + local context = Context:new() + context.engine = self + context.style = self.style + context.area = self.style.bibliography + context.in_bibliography = true + context.locale = self:get_locale(self.lang) + context.name_inheritance = self.style.bibliography.name_inheritance + context.format = SortStringFormat:new() + -- context.id = id + context.cite = nil + -- context.reference = self:get_item(id) - bibliography_sort:sort(items, context) + bibliography_sort:sort(items, state, context) self.registry.reflist = {} + self.tainted_item_ids = {} for i, item in ipairs(items) do + if item["citation-number"] ~= i then + self.tainted_item_ids[item.id] = true + end item["citation-number"] = i - table.insert(self.registry.reflist, item.id) + self.registry.reflist[i] = item.id end self.registry.requires_sorting = false end -function CiteProc:get_system_locale (lang) +function CiteProc:get_locale(lang) + if string.len(lang) == 2 then + lang = util.primary_dialects[lang] or lang + end + local locale = self.locales[lang] + if locale then + return locale + else + return self:get_merged_locales(lang) + end +end + +function CiteProc:get_merged_locales(lang) + local fall_back_locales = {} + + local language = string.sub(lang, 1, 2) + local primary_dialect = util.primary_dialects[language] + + -- 1. In-style cs:locale elements + -- i. `xml:lang` set to chosen dialect, “de-AT” + table.insert(fall_back_locales, self.style.locales[lang]) + + -- ii. `xml:lang` set to matching language, “de” (German) + if language and language ~= lang then + table.insert(fall_back_locales, self.style.locales[language]) + end + + -- iii. `xml:lang` not set + table.insert(fall_back_locales, self.style.locales["@generic"]) + + -- 2. Locale files + -- iv. `xml:lang` set to chosen dialect, “de-AT” + if lang then + table.insert(fall_back_locales, self:get_system_locale(lang)) + end + + -- v. `xml:lang` set to matching primary dialect, “de-DE” (Standard German) + -- (only applicable when the chosen locale is a secondary dialect) + if primary_dialect and primary_dialect ~= lang then + table.insert(fall_back_locales, self:get_system_locale(primary_dialect)) + end + + -- vi. `xml:lang` set to “en-US” (American English) + if lang ~= "en-US" and primary_dialect ~= "en-US" then + table.insert(fall_back_locales, self:get_system_locale("en-US")) + end + + -- Merge locales + + local locale = Locale:new() + for i = #fall_back_locales, 1, -1 do + local fall_back_locale = fall_back_locales[i] + locale:merge(fall_back_locale) + end + + self.locales[lang] = locale + return locale +end + +function CiteProc:get_system_locale(lang) local locale = self.system_locales[lang] - if not locale then - locale = self.sys.retrieveLocale(lang) - if not locale then - util.warning(string.format("Failed to retrieve locale \"%s\"", lang)) - return nil - end - if type(locale) == "string" then - locale = dom.parse(locale) - end - locale:traverse_elements(self.set_base_class) - locale = locale:get_path("locale")[1] - locale:root_node().engine = self - locale:root_node().style = self.style - self.system_locales[lang] = locale + if locale then + return locale + end + + local locale_str = self.sys.retrieveLocale(lang) + if not locale_str then + util.warning(string.format("Failed to retrieve locale \"%s\"", lang)) + return nil end + local locale_xml = dom.parse(locale_str) + local root_element = locale_xml:get_path("locale")[1] + locale = Locale:from_node(root_element) + self.system_locales[lang] = locale return locale end +function CiteProc:get_style_class() + if self.style and self.style.class then + return self.style.class + else + return nil + end +end + + engine.CiteProc = CiteProc return engine diff --git a/biblio/citation-style-language/citeproc-formats.lua b/biblio/citation-style-language/citeproc-formats.lua deleted file mode 100644 index fd9621936c..0000000000 --- a/biblio/citation-style-language/citeproc-formats.lua +++ /dev/null @@ -1,211 +0,0 @@ --- --- Copyright (c) 2021-2022 Zeping Lee --- Released under the MIT license. --- Repository: https://github.com/zepinglee/citeproc-lua --- - -local util = require("citeproc-util") - - -local formats = {} - -formats.html = { - ["text_escape"] = function (str) - str = string.gsub(str, "%&", "&") - str = string.gsub(str, "<", "<") - str = string.gsub(str, ">", ">") - for char, sub in pairs(util.superscripts) do - str = string.gsub(str, char, "<sup>" .. sub .. "</sup>") - end - return str - end, - ["bibstart"] = "<div class=\"csl-bib-body\">\n", - ["bibend"] = "</div>", - ["@font-style/italic"] = "<i>%s</i>", - ["@font-style/oblique"] = "<em>%s</em>", - ["@font-style/normal"] = '<span style="font-style:normal;">%s</span>', - ["@font-variant/small-caps"] = '<span style="font-variant:small-caps;">%s</span>', - ["@font-variant/normal"] = '<span style="font-variant:normal;">%s</span>', - ["@font-weight/bold"] = "<b>%s</b>", - ["@font-weight/normal"] = '<span style="font-weight:normal;">%s</span>', - ["@font-weight/light"] = false, - ["@text-decoration/none"] = '<span style="text-decoration:none;">%s</span>', - ["@text-decoration/underline"] = '<span style="text-decoration:underline;">%s</span>', - ["@vertical-align/sup"] = "<sup>%s</sup>", - ["@vertical-align/sub"] = "<sub>%s</sub>", - ["@vertical-align/baseline"] = '<span style="baseline">%s</span>', - ["@quotes/true"] = function (str, context) - local open_quote = context.style:get_term("open-quote"):render(context) - local close_quote = context.style:get_term("close-quote"):render(context) - return open_quote .. str .. close_quote - end, - ["@quotes/inner"] = function (str, context) - local open_quote = context.style:get_term("open-inner-quote"):render(context) - local close_quote = context.style:get_term("close-inner-quote"):render(context) - return open_quote .. str .. close_quote - end, - ["@bibliography/entry"] = function (str, context) - return '<div class="csl-entry">' .. str .. "</div>\n" - end, - ["@display/block"] = function (str, state) - return '\n\n <div class="csl-block">' .. str .. "</div>\n" - end, - ["@display/left-margin"] = function (str, state) - return '\n <div class="csl-left-margin">' .. str .. "</div>" - end, - ["@display/right-inline"] = function (str, state) - str = util.rstrip(str) - return '<div class="csl-right-inline">' .. str .. "</div>\n " - end, - ["@display/indent"] = function (str, state) - return '<div class="csl-indent">' .. str .. "</div>\n " - end, - ["@URL/true"] = function (str, state) - if state.engine.linking_enabled then - return string.format('<a href="%s">%s</a>', str, str) - else - return str - end - end, - ["@DOI/true"] = function (str, state) - if state.engine.linking_enabled then - local href = str - if not string.match(href, "^https?://") then - href = "https://doi.org/" .. str; - end - return string.format('<a href="%s">%s</a>', href, str) - else - return str - end - end, - ["@PMID/true"] = function (str, state) - if state.engine.linking_enabled then - local href = str - if not string.match(href, "^https?://") then - href = "https://www.ncbi.nlm.nih.gov/pubmed/" .. str; - end - return string.format('<a href="%s">%s</a>', href, str) - else - return str - end - end, - ["@PMCID/true"] = function (str, state) - if state.engine.linking_enabled then - local href = str - if not string.match(href, "^https?://") then - href = "https://www.ncbi.nlm.nih.gov/pmc/articles/" .. str; - end - return string.format('<a href="%s">%s</a>', href, str) - else - return str - end - end, -} - -formats.latex = { - ["text_escape"] = function (str) - str = str:gsub("\\", "\\textbackslash") - str = str:gsub("#", "\\#") - str = str:gsub("%$", "\\$") - str = str:gsub("%%", "\\%%") - str = str:gsub("&", "\\&") - str = str:gsub("{", "\\{") - str = str:gsub("}", "\\}") - str = str:gsub("_", "\\_") - str = str:gsub(util.unicode["no-break space"], "~") - for char, sub in pairs(util.superscripts) do - str = string.gsub(str, char, "\\textsuperscript{" .. sub .. "}") - end - return str - end, - ["bibstart"] = function (context) - return string.format("\\begin{thebibliography}{%s}\n", context.build.longest_label) - end, - ["bibend"] = "\\end{thebibliography}", - ["@font-style/normal"] = "{\\normalshape %s}", - ["@font-style/italic"] = "\\emph{%s}", - ["@font-style/oblique"] = "\\textsl{%s}", - ["@font-variant/normal"] = "{\\normalshape %s}", - ["@font-variant/small-caps"] = "\\textsc{%s}", - ["@font-weight/normal"] = "\\fontseries{m}\\selectfont %s", - ["@font-weight/bold"] = "\\textbf{%s}", - ["@font-weight/light"] = "\\fontseries{l}\\selectfont %s", - ["@text-decoration/none"] = false, - ["@text-decoration/underline"] = "\\underline{%s}", - ["@vertical-align/sup"] = "\\textsuperscript{%s}", - ["@vertical-align/sub"] = "\\textsubscript{%s}", - ["@vertical-align/baseline"] = false, - ["@quotes/true"] = function (str, context) - local open_quote = context.style:get_term("open-quote"):render(context) - local close_quote = context.style:get_term("close-quote"):render(context) - return open_quote .. str .. close_quote - end, - ["@quotes/inner"] = function (str, context) - local open_quote = context.style:get_term("open-inner-quote"):render(context) - local close_quote = context.style:get_term("close-inner-quote"):render(context) - return open_quote .. str .. close_quote - end, - ["@bibliography/entry"] = function (str, context) - if not string.match(str, "\\bibitem") then - str = "\\bibitem{".. context.item.id .. "}\n" .. str - end - return str .. "\n" - end, - ["@display/block"] = function (str, state) - return str - end, - ["@display/left-margin"] = function (str, state) - if #str > #state.build.longest_label then - state.build.longest_label = str - end - if string.match(str, "%]") then - str = "{" .. str .. "}" - end - return string.format("\\bibitem[%s]{%s}\n", str, state.item.id) - end, - ["@display/right-inline"] = function (str, state) - return str - end, - ["@display/indent"] = function (str, state) - return str - end, - ["@URL/true"] = function (str, state) - return "\\url{" .. str .. "}" - end, - ["@DOI/true"] = function (str, state) - if state.engine.linking_enabled then - local href = str - if not string.match(href, "^https?://") then - href = "https://doi.org/" .. str; - end - return string.format("\\href{%s}{%s}", href, str) - else - return str - end - end, - ["@PMID/true"] = function (str, state) - if state.engine.linking_enabled then - local href = str - if not string.match(href, "^https?://") then - href = "https://www.ncbi.nlm.nih.gov/pubmed/" .. str; - end - return string.format("\\href{%s}{%s}", href, str) - else - return str - end - end, - ["@PMCID/true"] = function (str, state) - if state.engine.linking_enabled then - local href = str - if not string.match(href, "^https?://") then - href = "https://www.ncbi.nlm.nih.gov/pmc/articles/" .. str; - end - return string.format("\\href{%s}{%s}", href, str) - else - return str - end - end, -} - - -return formats diff --git a/biblio/citation-style-language/citeproc-ir-node.lua b/biblio/citation-style-language/citeproc-ir-node.lua new file mode 100644 index 0000000000..01cca4abf6 --- /dev/null +++ b/biblio/citation-style-language/citeproc-ir-node.lua @@ -0,0 +1,153 @@ +-- +-- Copyright (c) 2021-2022 Zeping Lee +-- Released under the MIT license. +-- Repository: https://github.com/zepinglee/citeproc-lua +-- + +local irnode = {} + +local util = require("citeproc-util") + + +local IrNode = { + _element = nil, + _type = "IrNode", + _base_class = "IrNode", + text = nil, + formatting = nil, + affixes = nil, + children = nil, + delimiter = nil, +} + +function IrNode:new(children, element) + local o = { + _element = element.element_name, + _type = self._type, + children = children, + group_var = "plain", + } + + o.group_var = "missing" + for _, child_ir in ipairs(children) do + if child_ir.group_var == "important" then + o.group_var = "important" + break + elseif child_ir.group_var == "plain" then + o.group_var = "plain" + end + end + + o.person_name_irs = {} + if children then + for _, child in ipairs(children) do + if child.person_name_irs then + util.extend(o.person_name_irs, child.person_name_irs) + end + end + end + + setmetatable(o, self) + self.__index = self + return o +end + +function IrNode:derive(type) + local o = { + _type = type, + } + setmetatable(o, self) + self.__index = self + return o +end + +function IrNode:flatten(format) + return format:flatten_ir(self) +end + +function IrNode:capitalize_first_term() + -- util.debug(self) + if self._type == "Rendered" and self.element and (self.element.term == "ibid" or self.element.term == "and") then + self.inlines[1]:capitalize_first_term() + elseif self._type == "SeqIr" and self.children[1] then + self.children[1]:capitalize_first_term() + end +end + + + +local Rendered = IrNode:derive("Rendered") + +function Rendered:new(inlines, element) + local o = { + _element = element.element_name, + _type = self._type, + element = element, -- required for capitalizing first term + inlines = inlines, + group_var = "plain", + } + + setmetatable(o, self) + self.__index = self + return o +end + + +local YearSuffix = IrNode:derive("YearSuffix") + +function YearSuffix:new(inlines, element) + local o = { + _element = element.element_name, + _type = self._type, + element = element, + inlines = inlines, + group_var = "plain", + } + + setmetatable(o, self) + self.__index = self + return o +end + + +local NameIr = IrNode:derive("NameIr") + + +local PersonNameIr = IrNode:derive("PersonNameIr") + +function PersonNameIr:new(inlines, element) + local o = { + _element = element.element_name, + _type = self._type, + inlines = inlines, + group_var = "plain", + } + setmetatable(o, self) + self.__index = self + return o +end + + +local SeqIr = IrNode:derive("SeqIr") + +-- function SeqIr:new(children) +-- o = IrNode.new(self, children) +-- local o = { +-- children = children, +-- group_var = "plain", +-- } +-- setmetatable(o, self) +-- self.__index = self +-- return o +-- end + + + +irnode.IrNode = IrNode +irnode.Rendered = Rendered +irnode.YearSuffix = YearSuffix +irnode.NameIr = NameIr +irnode.PersonNameIr = PersonNameIr +irnode.SeqIr = SeqIr + +return irnode diff --git a/biblio/citation-style-language/csl-core.lua b/biblio/citation-style-language/citeproc-latex-core.lua index e4e2fed32e..0be2381797 100644 --- a/biblio/citation-style-language/csl-core.lua +++ b/biblio/citation-style-language/citeproc-latex-core.lua @@ -12,8 +12,7 @@ require("lualibs") core.locale_file_format = "csl-locales-%s.xml" -core.ids = {} -core.loaded_ids = {} +core.uncited_ids = {} core.uncite_all_items = false function core.error(message) @@ -112,9 +111,10 @@ local function read_data_files(data_files) for _, item in ipairs(csl_items) do local id = item.id if bib[id] then - core.error(string.format('Duplicate entry key "%s" in "%s".', id, file_name)) + core.warning(string.format('Duplicate entry key "%s" in "%s".', id, file_name)) + else + bib[id] = item end - bib[id] = item end end return bib @@ -164,44 +164,51 @@ function core.init(style_name, data_files, lang) return engine end - -function core.make_citation(citation_info) - -- `citation_info`: "{ITEM-1@2}{{id={ITEM-1},label={page},locator={6}}}{3}" - local arguments = {} - for argument in string.gmatch(citation_info, "(%b{})") do - table.insert(arguments, string.sub(argument, 2, -2)) +local function parse_latex_seq(s) + local t = {} + for item in string.gmatch(s, "(%b{})") do + item = string.sub(item, 2, -2) + table.insert(t, item) end - if #arguments ~= 3 then - error(string.format('Invalid citation "%s"', citation_info)) - return nil - end - local citation_id, cite_items_str, note_index = table.unpack(arguments) + return t +end - local cite_items = {} - if citation_id == "nocite" then - for _, cite_id in ipairs(util.split(cite_items_str, "%s*,%s*")) do - table.insert(cite_items, {id = cite_id}) +local function parse_latex_prop(s) + local t = {} + for key, value in string.gmatch(s, "([%w%-]+)%s*=%s*(%b{})") do + value = string.sub(value, 2, -2) + if value == "true" then + value = true + elseif value == "false" then + value = false end + t[key] = value + end + return t +end - else - for item_str in string.gmatch(cite_items_str, "(%b{})") do - item_str = string.sub(item_str, 2, -2) - local cite_item = {} - for key, value in string.gmatch(item_str, "([%w%-]+)=(%b{})") do - value = string.sub(value, 2, -2) - cite_item[key] = value - end - table.insert(cite_items, cite_item) - end +function core.make_citation(citation_info) + -- `citation_info`: "citationID={ITEM-1@2},citationItems={{id={ITEM-1},label={page},locator={6}}},properties={noteIndex={3}}" + local citation = parse_latex_prop(citation_info) + assert(citation.citationID) + assert(citation.citationItems) + assert(citation.properties) + + citation.citationItems = parse_latex_seq(citation.citationItems) + + for i, item in ipairs(citation.citationItems) do + citation.citationItems[i] = parse_latex_prop(item) end - local citation = { - citationID = citation_id, - citationItems = cite_items, - properties = { - noteIndex = tonumber(note_index), - }, - } + citation.properties = parse_latex_prop(citation.properties) + local note_index = citation.properties.noteIndex + if not note_index or note_index == "" then + citation.properties.noteIndex = 0 + elseif type(note_index) == "string" and string.match(note_index, "^%d+$") then + citation.properties.noteIndex = tonumber(note_index) + else + util.error(string.format('Invalid note index "%s".', note_index)) + end return citation end @@ -210,19 +217,13 @@ end function core.process_citations(engine, citations) local citations_pre = {} - -- Save the time of bibliography sorting by update all ids at one time. - core.update_item_ids(engine, citations) + core.update_uncited_items(engine, citations) local citation_strings = {} for _, citation in ipairs(citations) do - if citation.citationID ~= "nocite" then - local res = engine:processCitationCluster(citation, citations_pre, {}) - - for _, citation_res in ipairs(res[2]) do - local citation_str = citation_res[2] - local citation_id = citation_res[3] - citation_strings[citation_id] = citation_str - end + if citation.citationID ~= "@nocite" then + local citation_str = engine:process_citation(citation) + citation_strings[citation.citationID] = citation_str table.insert(citations_pre, {citation.citationID, citation.properties.noteIndex}) end @@ -232,35 +233,30 @@ function core.process_citations(engine, citations) end -function core.update_item_ids(engine, citations) +function core.update_uncited_items(engine, citations) + -- util.debug(core.uncite_all_items) if core.uncite_all_items then - for item_id, _ in pairs(core.bib) do - if not core.loaded_ids[item_id] then - table.insert(core.ids, item_id) - core.loaded_ids[item_id] = true - end + -- \nocite{*} + for id, _ in pairs(core.bib) do + table.insert(core.uncited_ids, id) end - end - for _, citation in ipairs(citations) do - for _, cite_item in ipairs(citation.citationItems) do - local id = cite_item.id - if id == "*" then - for item_id, _ in pairs(core.bib) do - if not core.loaded_ids[item_id] then - table.insert(core.ids, item_id) - core.loaded_ids[item_id] = true + else + for _, citation in ipairs(citations) do + if citation.citationID == "@nocite" then + for _, cite_item in ipairs(citation.citationItems) do + table.insert(core.uncited_ids, cite_item.id) + if cite_item.id == "*" then + for id, _ in pairs(core.bib) do + table.insert(core.uncited_ids, id) + end + else + table.insert(core.uncited_ids, cite_item.id) end end - else - if not core.loaded_ids[id] then - table.insert(core.ids, id) - core.loaded_ids[id] = true - end end end end - engine:updateItems(core.ids) - -- TODO: engine:updateUncitedItems(ids) + engine:updateUncitedItems(core.uncited_ids) end diff --git a/biblio/citation-style-language/citeproc-latex.lua b/biblio/citation-style-language/citeproc-latex.lua new file mode 100644 index 0000000000..19348635b0 --- /dev/null +++ b/biblio/citation-style-language/citeproc-latex.lua @@ -0,0 +1,150 @@ +-- +-- Copyright (c) 2021-2022 Zeping Lee +-- Released under the MIT license. +-- Repository: https://github.com/zepinglee/citeproc-lua +-- + +local csl = {} + +local citeproc = require("citeproc") +local util = citeproc.util +require("lualibs") +local core = require("citeproc-latex-core") + + +csl.initialized = "false" +csl.id_list = {} +csl.id_map = {} -- Boolean map for checking if id in list +csl.uncited_id_list = {} +csl.uncited_id_map = {} +csl.citations_pre = {} + +csl.preview_mode = false -- Whether to use citeproc:preview_citation + + +function csl.error(str) + luatexbase.module_error("csl", str) +end +function csl.warning(str) + luatexbase.module_warning("csl", str) +end +function csl.info(str) + luatexbase.module_info("csl", str) +end + + +function csl.init(style_name, bib_files, lang) + bib_files = util.split(util.strip(bib_files), "%s*,%s*") + + csl.engine = core.init(style_name, bib_files, lang) + + if csl.engine then + csl.initialized = "true" + else + return + end + + -- csl.init is called via \AtBeginDocument and it's executed after + -- loading .aux file. The csl.id_list are already registered. + csl.engine:updateItems(csl.id_list) + + if core.uncite_all_items then + for id, _ in pairs(core.bib) do + if not csl.uncited_id_map[id] then + table.insert(csl.uncited_id_list, id) + csl.uncited_id_map[id] = true + end + end + end + csl.engine:updateUncitedItems(csl.uncited_id_list) + csl.style_class = csl.engine:get_style_class() +end + + +function csl.get_style_class() + tex.sprint(csl.style_class) +end + + +function csl.register_citation_info(citation_info) + local citation = core.make_citation(citation_info) + for _, cite_item in ipairs(citation.citationItems) do + if not csl.id_map[cite_item.id] then + table.insert(csl.id_list, cite_item.id) + csl.id_map[cite_item.id] = true + end + end +end + + +function csl.enable_linking() + csl.engine:enable_linking() +end + + +function csl.cite(citation_info) + -- "citationID={ITEM-UNAVAILABLE@1},citationItems={{id={ITEM-UNAVAILABLE}}},properties={noteIndex={1}}" + -- util.debug(citation_info) + if not csl.engine then + csl.error("CSL engine is not initialized.") + end + + local citation = core.make_citation(citation_info) + + local citation_str + if csl.preview_mode then + -- TODO: preview mode in first pass of \blockquote of csquotes + -- citation_str = csl.engine:preview_citation(citation) + citation_str = "" + else + citation_str = csl.engine:process_citation(citation) + end + + tex.sprint(string.format("{%s}{%s}", csl.style_class, citation_str)) + -- tex.sprint(citation_str) + + table.insert(csl.citations_pre, {citation.citationID, citation.properties.noteIndex}) +end + + +function csl.nocite(ids_string) + local uncited_ids = util.split(ids_string, "%s*,%s*") + for _, uncited_id in ipairs(uncited_ids) do + if uncited_id == "*" then + if csl.engine then + for id, _ in pairs(core.bib) do + if not csl.uncited_id_map[id] then + table.insert(csl.uncited_id_list, id) + csl.uncited_id_map[id] = true + end + end + csl.engine:updateUncitedItems(csl.uncited_id_list) + else + core.uncite_all_items = true + end + else + if not csl.uncited_id_map[uncited_id] then + table.insert(csl.uncited_id_list, uncited_id) + csl.uncited_id_map[uncited_id] = true + if csl.engine then + csl.engine:updateUncitedItems(csl.uncited_id_list) + end + end + end + end +end + + +function csl.bibliography() + if not csl.engine then + csl.error("CSL engine is not initialized.") + return + end + + local result = core.make_bibliography(csl.engine) + + tex.print(util.split(result, "\n")) +end + + +return csl diff --git a/biblio/citation-style-language/citeproc.1 b/biblio/citation-style-language/citeproc-lua.1 index bb891d9f41..c8fe3c3d68 100644 --- a/biblio/citation-style-language/citeproc.1 +++ b/biblio/citation-style-language/citeproc-lua.1 @@ -1,8 +1,8 @@ -.TH citeproc 1 "0.1.1" +.TH citeproc-lua 1 "0.1.1" .SH NAME -citeproc \- make CSL citations and bibliography for LaTeX +citeproc-lua \- make CSL citations and bibliography for LaTeX .SH SYNOPSIS -.B citeproc +.B citeproc-lua .RB [<options>] .IR auxname [ \fB.aux\fP ] .SH DESCRIPTION diff --git a/biblio/citation-style-language/citeproc-lua.lua b/biblio/citation-style-language/citeproc-lua.lua new file mode 100755 index 0000000000..c670866813 --- /dev/null +++ b/biblio/citation-style-language/citeproc-lua.lua @@ -0,0 +1,12 @@ +#!/usr/bin/env texlua + +-- +-- Copyright (c) 2021-2022 Zeping Lee +-- Released under the MIT license. +-- Repository: https://github.com/zepinglee/citeproc-lua +-- + +kpse.set_program_name("luatex") + +local cli = require("citeproc-cli") +cli.main() diff --git a/biblio/citation-style-language/citeproc-node-choose.lua b/biblio/citation-style-language/citeproc-node-choose.lua index e48731406c..3a4fc3f79e 100644 --- a/biblio/citation-style-language/citeproc-node-choose.lua +++ b/biblio/citation-style-language/citeproc-node-choose.lua @@ -6,123 +6,299 @@ local choose = {} -local element = require("citeproc-element") +local Element = require("citeproc-element").Element +local SeqIr = require("citeproc-ir-node").SeqIr local util = require("citeproc-util") +-- [Choose](https://docs.citationstyles.org/en/stable/specification.html#choose) +local Choose = Element:derive("choose") -local Choose = element.Element:new() +function Choose:from_node(node) + local o = Choose:new() + o.children = {} + o:process_children_nodes(node) + if #o.children == 0 then + return nil + end + return o +end + +function Choose:build_ir(engine, state, context) + local branch + local branch_ir + for _, child in ipairs(self.children) do + if child:evaluate_conditions(engine, state, context) then + branch = child + branch_ir = child:build_ir(engine, state, context) + break + end + end + + if not branch_ir then + branch_ir = SeqIr:new({}, self) + branch_ir.group_var = "missing" + end + + local ir = SeqIr:new({branch_ir}, self) + ir.group_var = branch_ir.group_var + ir.name_count = branch_ir.name_count + ir.sort_key = branch_ir.sort_key + + if not context.disambiguate then + context.disambiguate = true -function Choose:render (item, context) - self:debug_info(context) - context = self:process_context(context) - for i, child in ipairs(self:get_children()) do - if child:is_element() then - local result, status = child:render(item, context) - if status then - return result + for _, child in ipairs(self.children) do + if child:evaluate_conditions(engine, state, context) then + if child ~= branch then + ir.disambiguate_branch_ir = child:build_ir(engine, state, context) + end + break end end + + context.disambiguate = false end - return nil + + return ir end -local If = element.Element:new() +local Condition = { + condition = nil, + value = nil, + match_type = "all", +} + +function Condition:new(condition, value, match_type) + local o = { + condition = condition, + value = value, + match_type = match_type or "all" + } + setmetatable(o, self) + self.__index = self + return o +end -If.render = function (self, item, context) - self:debug_info(context) - context = self:process_context(context) - local results = {} - local variable_names = context.options["is-numeric"] - if variable_names then - for _, variable_name in ipairs(util.split(variable_names)) do - local variable = self:get_variable(item, variable_name, context) - table.insert(results, util.is_numeric(variable)) - end +local If = Element:derive("if", { + conditions = nil, + match = "all" +}) + +function If:new() + local o = Element.new(self) + o.conditions = {} + o.match = "all" + return o +end + +function If:from_node(node) + local o = If:new() + -- TODO: disambiguate + -- o:set_bool_attribute(node, "disambiguate") + + o:add_conditions(node, "disambiguate") + o:add_conditions(node, "is-numeric") + o:add_conditions(node, "is-uncertain-date") + o:add_conditions(node, "locator") + o:add_conditions(node, "position") + o:add_conditions(node, "type") + o:add_conditions(node, "variable") + + o.match = node:get_attribute("match") + + o:process_children_nodes(node) + + return o +end + +function If:add_conditions(node, attribute) + local values = node:get_attribute(attribute) + if not values then + return + end + for _, value in ipairs(util.split(values)) do + local condition = Condition:new(attribute, value, self.match) + table.insert(self.conditions, condition) end +end - variable_names = context.options["is-uncertain-date"] - if variable_names then - for _, variable_name in ipairs(util.split(variable_names)) do - local variable = self:get_variable(item, variable_name, context) - table.insert(results, util.is_uncertain_date(variable)) - end +function If:build_children_ir(engine, state, context) + if not self.children then + return nil end + local irs = {} + local name_count + local ir_sort_key + local group_var = "plain" - local locator_types = context.options["locator"] - if locator_types then - for _, locator_type in ipairs(util.split(locator_types)) do - local locator_label = item.label or "page" - local res = locator_label == locator_type - if locator_type == "sub-verbo" then - res = locator_label == "sub-verbo" or locator_label == "sub verbo" + for _, child_element in ipairs(self.children) do + local child_ir = child_element:build_ir(engine, state, context) + + if child_ir then + local child_group_var = child_ir.group_var + if child_group_var == "important" then + group_var = "important" + elseif child_group_var == "missing" and child_ir._type ~= "YearSuffix" then + if group_var == "plain" then + group_var = "missing" + end end - table.insert(results, res) - end - end - local positions = context.options["position"] - if positions then - for _, position in ipairs(util.split(positions)) do - local res = false - if context.mode == "citation" then - if position == "first" then - res = (item.position == util.position_map["first"]) - elseif position == "near-note" then - res = item["near-note"] ~= nil and item["near-note"] ~= false - else - res = (item.position >= util.position_map[position]) + if child_ir.name_count then + if not name_count then + name_count = 0 end + name_count = name_count + child_ir.name_count + end + + if child_ir.sort_key ~= nil then + ir_sort_key = child_ir.sort_key end - table.insert(results, res) + + -- The condition can be simplified + table.insert(irs, child_ir) end end - local type_names = context.options["type"] - if type_names then - for _, type_name in ipairs(util.split(type_names)) do - table.insert(results, item["type"] == type_name) + if #irs == 0 then + group_var = "missing" + end + + local ir = SeqIr:new(irs, self) + ir.name_count = name_count + ir.sort_key = ir_sort_key + ir.group_var = group_var + return ir +end + +function If:build_ir(engine, state, context) + if not self:evaluate_conditions(engine, state, context) then + return nil + end + + local ir = self:build_children_ir(engine, state, context) + if not ir then + return nil + end + + ir.should_inherit_delim = true + return ir +end + +function If:evaluate_conditions(engine, state, context) + local res = false + -- util.debug(self.conditions) + for _, condition in ipairs(self.conditions) do + if self:evaluate_condition(condition, state, context) then + if self.match == "any" then + return true + elseif self.match == "none" then + return false + end + else + if self.match == "all" then + return false + end end end + if self.match == "any" then + return false + else + return true + end +end + +function If:evaluate_condition(condition, state, context) + -- util.debug(context.cite) + -- util.debug(condition) + if condition.condition == "disambiguate" then + return context.disambiguate or (context.in_bibliography and context.reference.disambiguate) - variable_names = context.options["variable"] - if variable_names then - for _, variable_name in ipairs(util.split(variable_names)) do - local variable = self:get_variable(item, variable_name, context) - local res = (variable ~= nil and variable ~= "") - table.insert(results, res) + elseif condition.condition == "is-numeric" then + local variable = context:get_variable(condition.value) + return util.is_numeric(variable) + + elseif condition.condition == "is-uncertain-date" then + local variable = context:get_variable(condition.value) + -- TODO + return self:is_uncertain_date(variable) + + elseif condition.condition == "locator" then + local locator_label = context:get_variable("label") + if locator_label == "sub verbo" then + locator_label = "sub-verbo" + end + return locator_label == condition.value + + elseif condition.condition == "position" then + return self:check_position(condition.value, context) + + elseif condition.condition == "type" then + local item_type = context:get_variable("type") + return item_type == condition.value + + elseif condition.condition == "variable" then + local var = condition.value + if var == "locator" or var == "label" then + if context.in_bibliography then + return false + else + return context.cite[var] ~= nil + end + else + local res = context.reference[var] ~= nil + return res end end +end + +function If:is_uncertain_date(variable) + if variable == nil then + return false + end + local circa = variable["circa"] + return circa and circa ~= "" +end - local match = context.options["match"] or "all" - local status = false - if match == "any" then - status = util.any(results) - elseif match == "none" then - status = not util.any(results) - else - status = util.all(results) +function If:check_position(position, context) + -- util.debug(context.cite) + if context.in_bibliography then + return false end - if status then - return self:render_children(item, context), status + + local position_level = context.cite.position or context.cite.position_level or 0 + -- context.cite.position is for hacking in debugging + -- bugreports_DemoPageFullCiteCruftOnSubsequent.txt + if position == "first" then + return (position_level == util.position_map["first"]) + elseif position == "near-note" then + return context.cite["near-note"] or context.cite.near_note else - return nil, false + return (position_level >= util.position_map[position]) end end -local ElseIf = If:new() +local ElseIf = If:derive("else-if") + +local Else = Element:derive("else") -local Else = element.Element:new() +function Else:from_node(node) + local o = Else:new() + o:process_children_nodes(node) + return o +end -Else.render = function (self, item, context) - self:debug_info(context) - context = self:process_context(context) - return self:render_children(item, context), true +function Else:evaluate_conditions(engine, state, context) + return true end +Else.build_children_ir = If.build_children_ir +Else.build_ir = If.build_ir + choose.Choose = Choose choose.If = If diff --git a/biblio/citation-style-language/citeproc-node-date.lua b/biblio/citation-style-language/citeproc-node-date.lua index e10c1a9ac2..7ec1f439b8 100644 --- a/biblio/citation-style-language/citeproc-node-date.lua +++ b/biblio/citation-style-language/citeproc-node-date.lua @@ -6,376 +6,481 @@ local date_module = {} -local element = require("citeproc-element") +local Element = require("citeproc-element").Element +local IrNode = require("citeproc-ir-node").IrNode +local Rendered = require("citeproc-ir-node").Rendered +local SeqIr = require("citeproc-ir-node").SeqIr +local PlainText = require("citeproc-output").PlainText local util = require("citeproc-util") -local Date = element.Element:new() +-- [Date](https://docs.citationstyles.org/en/stable/specification.html#date) +local Date = Element:derive("date") -function Date:render (item, context) - self:debug_info(context) - context = self:process_context(context) +function Date:from_node(node) + local o = Date:new() - if context.sorting then - return self:render_sort_key(item, context) + o:set_attribute(node, "variable") + o:set_attribute(node, "form") + o:set_attribute(node, "date-parts") + + if o.form and not o.date_parts then + o.date_parts = "year-month-day" end - local variable_name = context.options["variable"] + o:get_delimiter_attribute(node) + o:set_formatting_attributes(node) + o:set_affixes_attributes(node) + o:set_display_attribute(node) + o:set_text_case_attribute(node) - local is_locale_date - if variable_name then - context.variable = variable_name - is_locale_date = false - else - variable_name = context.variable - is_locale_date = true + o.children = {} + o:process_children_nodes(node) + + for _, date_part in ipairs(o.children) do + o[date_part.name] = date_part end - local date = self:get_variable(item, variable_name, context) - if not date then - return nil + return o +end + +function Date:build_ir(engine, state, context) + local variable + if not state.suppressed[self.variable] then + variable = context:get_variable(self.variable) + end + + if not variable then + local ir = Rendered:new({}, self) + ir.group_var = "missing" + return ir end - local res = nil - local form = context.options["form"] - if form and not is_locale_date then - for _, date_part in ipairs(self:query_selector("date-part")) do - local name = date_part:get_attribute("name") - if not context.date_part_attributes then - context.date_part_attributes = {} + local ir + + if variable["date-parts"] and #variable["date-parts"] > 0 then + + -- TODO: move input normlization in one place + for i = 1, 2 do + if variable["date-parts"][i] then + for j = 1, 3 do + local variabel_part = variable["date-parts"][i][j] + if variabel_part == 0 or variabel_part == "" then + variable["date-parts"][i][j] = nil + else + variable["date-parts"][i][j] = tonumber(variabel_part) + end + end end - if not context.date_part_attributes[name] then - context.date_part_attributes[name] = {} + end + if variable["season"] and not variable["date-parts"][1][2] then + variable["date-parts"][1][2] = 20 + tonumber(variable["season"]) + end + + variable = variable["date-parts"] + if self.form then + ir = self:build_localized_date_ir(variable, engine, state, context) + else + ir = self:build_independent_date_ir(variable, engine, state, context) + end + ir.affixes = self.affixes + + elseif variable["literal"] then + local inlines = self:render_text_inlines(variable["literal"], context) + ir = Rendered:new(inlines, self) + ir.group_var = "important" + + elseif variable["raw"] then + local inlines = self:render_text_inlines(variable["raw"], context) + ir = Rendered:new(inlines, self) + ir.group_var = "important" + + end + + if not ir then + -- date_LiteralFailGracefullyIfNoValue.txt + ir = Rendered:new({}, self) + if context.sort_key then + ir.sort_key = false + end + ir.group_var = "missing" + return ir + end + + if ir.group_var == "important" then + -- Suppress substituted name variable + if state.name_override and not context.sort_key then + state.suppressed[self.variable] = true + end + end + + if context.sort_key then + ir.sort_key = self:render_sort_key(engine, state, context) + end + + return ir +end + +function Date:build_independent_date_ir(variable, engine, state, context) + -- else + -- local literal = variable["literal"] + -- if literal then + -- res = literal + -- else + -- local raw = variable["raw"] + -- if raw then + -- res = raw + -- end + -- end + + return self:build_date_parts(self.children, variable, self.delimiter, engine, state, context) +end + +function Date:build_localized_date_ir(variable, engine, state, context) + local date_part_mask = {} + for _, part in ipairs(util.split(self.date_parts or "year-month-day", "%-")) do + date_part_mask[part] = true + end + -- local date_parts = {} + -- for _, date_part in ipairs(self.children) do + -- date_parts[date_part.name] = date_part + -- end + local localized_date = context:get_localized_date(self.form) + local date_parts = {} + for _, date_part in ipairs(localized_date.children) do + if date_part_mask[date_part.name] then + date_part = date_part:copy() + local local_date_part = self[date_part.name] + if local_date_part then + local_date_part:override(date_part) end + table.insert(date_parts, date_part) + end + end + return self:build_date_parts(date_parts, variable, localized_date.delimiter, engine, state, context) +end - for attr, value in pairs(date_part._attr) do - if attr ~= name then - context.date_part_attributes[name][attr] = value - end +function Date:build_date_parts(date_parts, variable, delimiter, engine, state, context) + if #variable >= 2 then + return self:build_date_range(date_parts, variable, delimiter, engine, state, context) + elseif #variable == 1 then + return self:build_single_date(date_parts, variable[1], delimiter, engine, state, context) + end +end + +function Date:build_single_date(date_parts, single_date, delimiter, engine, state, context) + local irs = {} + for _, date_part in ipairs(date_parts) do + local part_ir = date_part:build_ir(single_date, engine, state, context) + table.insert(irs, part_ir) + end + + local ir = SeqIr:new(irs, self) + ir.delimiter = self.delimiter + + -- return Rendered:new(inlines, self) + return ir +end + +local date_part_index = { + year = 1, + month = 2, + day = 3, +} + +function Date:build_date_range(date_parts, variable, delimiter, engine, state, context) + local first, second = variable[1], variable[2] + local diff_level = 4 + for _, date_part in ipairs(date_parts) do + local part_index = date_part_index[date_part.name] + if first[part_index] and first[part_index] ~= second[part_index] then + if part_index < diff_level then + diff_level = part_index end end - res = self:get_locale_date(context, form):render(item, context) - else - if not date["date-parts"] or #date["date-parts"] == 0 then - local literal = date["literal"] - if literal then - res = literal + end + + local irs = {} + + local range_part_queue = {} + local range_delimiter + for i, date_part in ipairs(date_parts) do + local part_index = date_part_index[date_part.name] + if part_index == diff_level then + range_delimiter = date_part.range_delimiter or util.unicode["en dash"] + end + if first[part_index] then + if part_index >= diff_level then + table.insert(range_part_queue, date_part) else - local raw = date["raw"] - if raw then - res = raw + if #range_part_queue > 0 then + table.insert(irs, self:build_date_range_parts(range_part_queue, variable, + delimiter, engine, state, context, range_delimiter)) + range_part_queue = {} end - end - - else - if #date["date-parts"] == 1 then - res = self:_render_single_date(date, context) - elseif #date["date-parts"] == 2 then - res = self:_render_date_range(date, context) + table.insert(irs, date_part:build_ir(first, engine, state, context)) end end end + if #range_part_queue > 0 then + table.insert(irs, self:build_date_range_parts(range_part_queue, variable, + delimiter, engine, state, context, range_delimiter)) + end - table.insert(context.variable_attempt, res ~= nil) + local ir = SeqIr:new(irs, self) + ir.delimiter = delimiter - res = self:format(res, context) - res = self:wrap(res, context) - return res + return ir end -function Date:get_locale_date(context, form) - local date = nil - local style = context.style - local query = string.format("date[form=\"%s\"]", form) - for _, locale in ipairs(style:get_locales()) do - date = locale:query_selector(query)[1] - if date then - break +function Date:build_date_range_parts(range_part_queue, variable, delimiter, engine, state, context, range_delimiter) + local irs = {} + local first, second = variable[1], variable[2] + + local date_part_irs = {} + for i, diff_part in ipairs(range_part_queue) do + -- if delimiter and i > 1 then + -- table.insert(date_part_irs, PlainText:new(delimiter)) + -- end + if i == #range_part_queue then + table.insert(date_part_irs, diff_part:build_ir(first, engine, state, context, "suffix")) + else + table.insert(date_part_irs, diff_part:build_ir(first, engine, state, context)) end end - if not date then - error(string.format("Failed to find '%s'", query)) + local range_part_ir = SeqIr:new(date_part_irs, self) + range_part_ir.delimiter = delimiter + table.insert(irs, range_part_ir) + + table.insert(irs, Rendered:new({PlainText:new(range_delimiter)}, self)) + + date_part_irs = {} + for i, diff_part in ipairs(range_part_queue) do + if i == 1 then + table.insert(date_part_irs, diff_part:build_ir(second, engine, state, context, "prefix")) + else + table.insert(date_part_irs, diff_part:build_ir(second, engine, state, context)) + end end - return date + range_part_ir = SeqIr:new(date_part_irs, self) + range_part_ir.delimiter = delimiter + table.insert(irs, range_part_ir) + + local ir = SeqIr:new(irs, self) + + return ir end -function Date:render_sort_key (item, context) - local variable_name = context.options["variable"] - local date = self:get_variable(item, variable_name, context) - if not date or not date["date-parts"] then - return nil +function Date:render_sort_key(engine, state, context) + local date = context:get_variable(self.variable) + if not date then + return false end + if not date["date-parts"] then + if self.literal then + return "1" .. self.literal + else + return false + end + end + local show_parts = { year = false, month = false, day = false, } - if self:get_attribute("form") then - local date_parts = self:get_attribute("date-parts") or "year-month-day" - for _, dp_name in ipairs(util.split(date_parts, "%-")) do + if self.form then + for _, dp_name in ipairs(util.split(self.date_parts, "%-")) do show_parts[dp_name] = true end else - for _, child in ipairs(self:query_selector("date-part")) do - show_parts[child:get_attribute("name")] = true + for _, date_part in ipairs(self.children) do + show_parts[date_part.name] = true end end local res = "" - for _, date_parts in ipairs(date["date-parts"]) do + for _, range_part in ipairs(date["date-parts"]) do + if res ~= "" then + res = res .. "/" + end for i, dp_name in ipairs({"year", "month", "day"}) do - local value = date_parts[i] - if not value or not show_parts[dp_name] then - value = 0 + local value = 0 + if show_parts[dp_name] and range_part[i] then + value = range_part[i] end if i == 1 then res = res .. string.format("%05d", value + 10000) else - res = res .. string.format("%02d", value) + res = res .. "-" .. string.format("%02d", value) end end end return res end -function Date:_render_single_date (date, context) - local show_parts = self:_get_show_parts(context) - local output = {} - for _, child in ipairs(self:query_selector("date-part")) do - if show_parts[child:get_attribute("name")] then - table.insert(output, child:render(date, context)) - end +-- [Date-part](https://docs.citationstyles.org/en/stable/specification.html#date-part) +local DatePart = Element:derive("date-part") + +function DatePart:from_node(node) + local o = DatePart:new() + o:set_attribute(node, "name") + o:set_attribute(node, "form") + if o.name == "month" then + o:set_strip_periods_attribute(node) end - return self:concat(output, context) + o:set_formatting_attributes(node) + o:set_text_case_attribute(node) + o:set_attribute(node, "range-delimiter") + o:set_affixes_attributes(node) + return o end -function Date:_render_date_range (date, context) - local show_parts = self:_get_show_parts(context) - local part_index = {} - - local largest_diff_part = nil - for i, name in ipairs({"year", "month", "day"}) do - part_index[name] = i - local part_value1 = date["date-parts"][1][i] - if show_parts[name] and part_value1 then - if not largest_diff_part then - largest_diff_part = name - end - end +function DatePart:build_ir(single_date, engine, state, context, suppressed_affix) + local text + if self.name == "year" then + text = self:render_year(single_date[1], engine, state, context) + elseif self.name == "month" then + text = self:render_month(single_date[2], engine, state, context) + elseif self.name == "day" then + text = self:render_day(single_date[3], single_date[2], engine, state, context) end - local date_parts = {} - for _, date_part in ipairs(self:query_selector("date-part")) do - if show_parts[date_part:get_attribute("name")] then - table.insert(date_parts, date_part) - end + if not text then + local ir = Rendered:new({}, self) + ir.group_var = "missing" + return ir end - local diff_begin = 0 - local diff_end = #date_parts - local range_delimiter = nil - - for i, date_part in ipairs(date_parts) do - local name = date_part:get_attribute("name") - if name == largest_diff_part then - range_delimiter = date_part:get_attribute("range-delimiter") - if not range_delimiter then - range_delimiter = util.unicode["en dash"] - end - end - - local index = part_index[name] - local part_value1 = date["date-parts"][1][index] - local part_value2 = date["date-parts"][2][index] - if part_value1 and part_value1 ~= part_value2 then - if diff_begin == 0 then - diff_begin = i - end - diff_end = i - end + local inlines = {PlainText:new(text)} + local output_format = context.format + if not context.is_english then + print(debug.traceback()) end + local is_english = context:is_english() + output_format:apply_text_case(inlines, self.text_case, is_english) + inlines = output_format:with_format(inlines, self.formatting) - local same_prefix = {} - local range_begin = {} - local range_end = {} - local same_suffix = {} + local ir = Rendered:new(inlines, self) + ir.group_var = "important" - local no_suffix_context = self:process_context(context) - no_suffix_context.options["suffix"] = nil - - for i, date_part in ipairs(date_parts) do - local res = nil - if i == diff_end then - res = date_part:render(date, no_suffix_context, true) - else - res = date_part:render(date, context) - end - if i < diff_begin then - table.insert(same_prefix, res) - elseif i <= diff_end then - table.insert(range_begin, res) - table.insert(range_end, date_part:render(date, context, false, true)) - else - table.insert(same_suffix, res) - end + if self.name == "year" then + ir = SeqIr:new({ir}, self) + ir.is_year = true end - local prefix_output = self:concat(same_prefix, context) or "" - local range_begin_output = self:concat(range_begin, context) or "" - local range_end_output = self:concat(range_end, context) or "" - local suffix_output = self:concat(same_suffix, context) - local range_output = range_begin_output .. range_delimiter .. range_end_output - - local res = self:concat({prefix_output, range_output, suffix_output}, context) + ir.affixes = util.clone(self.affixes) + if ir.affixes and suppressed_affix then + ir.affixes[suppressed_affix] = nil + end - return res + return ir end -function Date:_get_show_parts (context) - local show_parts = {} - local date_parts = context.options["date-parts"] or "year-month-day" - for _, date_part in ipairs(util.split(date_parts, "%-")) do - show_parts[date_part] = true +function DatePart:render_day(day, month, engine, state, context) + if not day or day == "" then + return nil + end + day = tonumber(day) + if day < 1 or day > 31 then + return nil + end + local form = self.form or "numeric" + if form == "ordinal" then + local limit_day_1 = context.locale.style_options.limit_day_ordinals_to_day_1 + if limit_day_1 and day > 1 then + form = "numeric" + end + end + if form == "numeric-leading-zeros" then + return string.format("%02d", day) + elseif form == "ordinal" then + -- When the “day” date-part is rendered in the “ordinal” form, the ordinal + -- gender is matched against that of the month term. + local gender = context.locale:get_number_gender(string.format("month-%02d", month)) + local suffix = context.locale:get_ordinal_term(day, gender) + return tostring(day) .. suffix + else -- numeric + return tostring(day) end - return show_parts end - -local DatePart = element.Element:new() - -DatePart.render = function (self, date, context, last_range_begin, range_end) - self:debug_info(context) - context = self:process_context(context) - local name = context.options["name"] - local range_delimiter = context.options["range-delimiter"] or false - - -- The attributes set on cs:date-part elements of a cs:date with form - -- attribute override those specified for the localized date formats - if context.date_part_attributes then - local context_attributes = context.date_part_attributes[name] - if context_attributes then - for attr, value in pairs(context_attributes) do - context.options[attr] = value +function DatePart:render_month(month, engine, state, context) + if not month or month == "" then + return nil + end + month = tonumber(month) + if not month or month < 1 or month > 24 then + return nil + end + local form = self.form or "long" + local res + if form == "long" or form == "short" then + if month >= 1 and month <= 12 then + res = context:get_simple_term(string.format("month-%02d", month), form) + else + local season = month % 4 + if season == 0 then + season = 4 end + res = context:get_simple_term(string.format("season-%02d", season)) end + elseif form == "numeric-leading-zeros" then + res = string.format("%02d", month) + else + res = tostring(month) end + return self:apply_strip_periods(res) +end - if last_range_begin then - context.options["suffix"] = "" +function DatePart:render_year(year, engine, state, context) + if not year or year == "" then + return nil end - - local date_parts_index = 1 - if range_end then - date_parts_index = 2 + year = tonumber(year) + if year == 0 then + return nil end - - local res = nil - if name == "day" then - local day = date["date-parts"][date_parts_index][3] - if not day then - return nil - end - day = tonumber(day) - -- range open - if day == 0 then - return nil - end - local form = context.options["form"] or "numeric" - - if form == "ordinal" then - local option = self:get_locale_option("limit-day-ordinals-to-day-1") - if option and option ~= "false" and day > 1 then - form = "numeric" - end - end - if form == "numeric" then - res = tostring(day) - elseif form == "numeric-leading-zeros" then - -- TODO: day == nil? - if not day then - return nil - end - res = string.format("%02d", day) - elseif form == "ordinal" then - res = util.to_ordinal(day) + local form = self.form or "long" + if form == "long" then + if year < 0 then + return tostring(-year) .. context:get_simple_term("bc") + elseif year < 1000 then + return tostring(year) .. context:get_simple_term("ad") + else + return tostring(year) end + elseif form == "short" then + return string.sub(tostring(year), -2) + end +end - elseif name == "month" then - local form = context.options["form"] or "long" - - local month = date["date-parts"][date_parts_index][2] - if month then - month = tonumber(month) - -- range open - if month == 0 then - return nil +function DatePart:copy() + local o = {} + for key, value in pairs(self) do + if type(value) == "table" then + o[key] = {} + for k, v in pairs(value) do + o[key][k] = v end + else + o[key] = value end + end + setmetatable(o, DatePart) + return o +end - if form == "long" or form == "short" then - local term_name = nil - if month then - if month >= 1 and month <= 12 then - term_name = string.format("month-%02d", month) - elseif month >= 13 and month <= 24 then - local season = month % 4 - if season == 0 then - season = 4 - end - term_name = string.format("season-%02d", season) - else - util.warning("Invalid month value") - return nil - end - else - local season = date["season"] - if season then - season = tonumber(season) - term_name = string.format("season-%02d", season) - else - return nil - end - end - res = self:get_term(term_name, form):render(context) - elseif form == "numeric" then - res = tostring(month) - elseif form == "numeric-leading-zeros" then - -- TODO: month == nil? - if not month then - return nil - end - res = string.format("%02d", month) - end - res = self:strip_periods(res, context) - - elseif name == "year" then - local year = date["date-parts"][date_parts_index][1] - if year then - year = tonumber(year) - -- range open - if year == 0 then - return nil - end - local form = context.options["form"] or "long" - if form == "long" then - year = tonumber(year) - if year < 0 then - res = tostring(-year) .. self:get_term("bc"):render(context) - elseif year < 1000 then - res = tostring(year) .. self:get_term("ad"):render(context) - else - res = tostring(year) - end - elseif form == "short" then - res = string.sub(tostring(year), -2) +function DatePart:override(localized_date_part) + for key, value in pairs(self) do + if type(value) == "table" and localized_date_part[key] then + for k, v in pairs(value) do + localized_date_part[key][k] = v end + else + localized_date_part[key] = value end end - res = self:case(res, context) - res = self:format(res, context) - res = self:wrap(res, context) - res = self:display(res, context) - return res end diff --git a/biblio/citation-style-language/citeproc-node-group.lua b/biblio/citation-style-language/citeproc-node-group.lua index 51969212ba..81132a77dc 100644 --- a/biblio/citation-style-language/citeproc-node-group.lua +++ b/biblio/citation-style-language/citeproc-node-group.lua @@ -6,33 +6,36 @@ local group = {} -local element = require("citeproc-element") +local SeqIr = require("citeproc-ir-node").SeqIr +local Element = require("citeproc-element").Element local util = require("citeproc-util") -local Group = element.Element:new() +local Group = Element:derive("group") -function Group:render (item, context) - self:debug_info(context) - context = self:process_context(context) +function Group:from_node(node) + local o = Group:new() + o:get_delimiter_attribute(node) + o:set_affixes_attributes(node) + o:set_display_attribute(node) + o:set_formatting_attributes(node) - local num_variable_attempt = #context.variable_attempt + o:process_children_nodes(node) - local res = self:render_children(item, context) + return o +end - if #context.variable_attempt > num_variable_attempt then - if not util.any(util.slice(context.variable_attempt, num_variable_attempt + 1)) then - res = nil - end +function Group:build_ir(engine, state, context) + local ir = self:build_group_ir(engine, state, context) + if ir then + ir.delimiter = self.delimiter + ir.formatting = util.clone(self.formatting) + ir.affixes = util.clone(self.affixes) + ir.display = self.display end - - res = self:format(res, context) - res = self:wrap(res, context) - res = self:display(res, context) - return res + return ir end - group.Group = Group return group diff --git a/biblio/citation-style-language/citeproc-node-label.lua b/biblio/citation-style-language/citeproc-node-label.lua index 828f5e9122..27cafa2f18 100644 --- a/biblio/citation-style-language/citeproc-node-label.lua +++ b/biblio/citation-style-language/citeproc-node-label.lua @@ -6,104 +6,88 @@ local label = {} -local element = require("citeproc-element") +local Element = require("citeproc-element").Element +local IrNode = require("citeproc-ir-node").IrNode +local Rendered = require("citeproc-ir-node").Rendered +local PlainText = require("citeproc-output").PlainText local util = require("citeproc-util") -local Label = element.Element:new() +-- [Label](https://docs.citationstyles.org/en/stable/specification.html#label) +local Label = Element:derive("label") -function Label:render (item, context) - self:debug_info(context) - context = self:process_context(context) +Label.form = "long" +Label.plural = "contextual" - local variable_name - if context.names_element then - -- The `variable` attribute of names may hold multiple roles. - -- Each of them may call `Label:render()` to render the term. - -- When used in `names` element, the role name is the first argument - -- and the item is accessed via `context.item`. - -- Bad design - -- TODO: Redesign the arguments of render() - variable_name = item - else - variable_name = context.options["variable"] - end - - local form = context.options["form"] - local plural = context.options["plural"] or "contextual" +function Label:from_node(node) + local o = Label:new() + o:set_attribute(node, "variable") + o:set_attribute(node, "form") + o:set_attribute(node, "plural") + o:set_affixes_attributes(node) + o:set_formatting_attributes(node) + o:set_text_case_attribute(node) + o:set_strip_periods_attribute(node) + return o +end - if not context.names_element then - local variable_type = util.variable_types[variable_name] - -- variable must be or one of the number variables. - if variable_type ~= "number" then - return nil - end - -- The term is only rendered if the selected variable is non-empty - local variable = item[variable_name] - if not variable then - return nil - end - if type(variable) == "string" then - if not (string.match(variable, "^%d") or util.is_numeric(variable)) then - return nil - end - end - end +function Label:build_ir(engine, state, context) + -- local variable = context:get_variable(self.variable, self.form) - local term - if variable_name == "locator" then - local locator_type = item.label or "page" - term = self:get_term(locator_type, form) - else - term = self:get_term(variable_name, form) + local is_plural = false + if self.plural == "always" then + is_plural = true + elseif self.plural == "never" then + is_plural = false + elseif self.plural == "contextual" then + is_plural = self:_is_variable_plural(self.variable, context) end - local res = nil - if term then - if plural == "contextual" and self:_is_plural(variable_name, context) or plural == "always" then - res = term:render(context, true) - else - res = term:render(context, false) + local variable = self.variable + if variable == "locator" then + variable = context:get_variable("label") or "page" + if variable == "sub verbo" then + -- bugreports_MovePunctuationInsideQuotesForLocator.txt + variable = "sub-verbo" end - - res = self:strip_periods(res, context) - res = self:case(res, context) - res = self:format(res, context) - res = self:wrap(res, context) end - return res + local text = context:get_simple_term(variable, self.form, is_plural) + if not text or text == "" then + return nil + end + + local inlines = self:render_text_inlines(text, context) + return Rendered:new(inlines, self) end -function Label:_is_plural (variable_name, context) - local variable_type = util.variable_types[variable_name] - -- Don't use self:get_variable here - local variable = context.item[variable_name] - local res = false +function Label:_is_variable_plural(variable, context) + local value = context:get_variable(variable) + if not value then + return false + end + local variable_type = util.variable_types[variable] if variable_type == "name" then - -- Label inside `names` - res = #variable > 1 - + return #variable > 1 elseif variable_type == "number" then - if util.startswith(variable_name, "number-of-") then - res = tonumber(variable) > 1 + if util.startswith(variable, "number-of-") then + return tonumber(value) > 1 else - variable = tostring(variable) - variable = string.gsub(variable, "\\%-", "") - if #util.split(variable, "%s*[,&-]%s*") > 1 then - -- check if contains multiple numbers - -- "i–ix": true - -- res = string.match(tostring(variable), "%d+%D+%d+") ~= nil - res = true - elseif string.match(variable, "%Aand%A") or string.match(variable, "%Aet%A") then - res = true - else - res = false + value = tostring(value) + -- label_CollapsedPageNumberPluralDetection.txt + -- 327\-30 => single + value = string.gsub(value, "\\%-", "") + if string.match(value, "[,&-]") then + return true + elseif string.match(value, util.unicode["en dash"]) then + return true + elseif string.match(value, "%Wand%W") then + return true + elseif string.match(value, "%Wet%W") then + return true end end - else - util.warning("Invalid attribute \"variable\".") end - return res + return false end diff --git a/biblio/citation-style-language/citeproc-node-layout.lua b/biblio/citation-style-language/citeproc-node-layout.lua index 944ed883a3..168f923b08 100644 --- a/biblio/citation-style-language/citeproc-node-layout.lua +++ b/biblio/citation-style-language/citeproc-node-layout.lua @@ -6,229 +6,56 @@ local layout = {} -local richtext = require("citeproc-richtext") -local element = require("citeproc-element") +local Element = require("citeproc-element").Element +local SeqIr = require("citeproc-ir-node").SeqIr local util = require("citeproc-util") -local Layout = element.Element:new() +local Layout = Element:derive("layout") -function Layout:render (items, context) - self:debug_info(context) +function Layout:from_node(node) + local o = Layout:new() + o:set_affixes_attributes(node) + o:set_formatting_attributes(node) + o:get_delimiter_attribute(node) - context.items = items + o:process_children_nodes(node) - -- When used within cs:citation, the delimiter attribute may be used to specify a delimiter for cites within a citation. - -- Thus the processing of context is put after render_children(). - if context.mode == "citation" then - if context.options["collapse"] == "citation-number" then - context.build.item_citation_numbers = {} - context.build.item_citation_number_text = {} - end - elseif context.mode == "bibliography" then - context.build.longest_label = "" - context.build.preceding_first_rendered_names = nil - context = self:process_context(context) - end - - local output = {} - local previous_cite = nil - for _, item in ipairs(items) do - - context.item = item - context.variable_attempt = {} - context.suppressed_variables = {} - context.suppress_subsequent_variables = false - if context.mode == "bibliography" then - context.build.first_rendered_names = {} - end - - if not item.position then - item.position = self:_get_position(item, previous_cite, context) - end - - local first = nil - local second = {} - local element_index = 0 - for _, child in ipairs(self:get_children()) do - if child:is_element() then - element_index = element_index + 1 - local text = child:render(item, context) - if element_index == 1 then - first = text - else - table.insert(second, text) - end - end - end - second = self:concat(second, context) - - if context.mode == "bibliography" then - if first and context.options["prefix"] then - first = richtext.new(context.options["prefix"]) .. first - end - if second and context.options["suffix"] then - second = second .. richtext.new(context.options["suffix"]) - end - end - - local res = nil - if context.options["second-field-align"] == "flush" then - if first then - first:add_format("display", "left-margin") - res = first - end - if second then - second:add_format("display", "right-inline") - if res then - res = richtext.concat(res, second) - else - res = second - end - end - else - res = self:concat({first, second}, context) - end - - if context.mode == "citation" then - if res and item["prefix"] then - res = richtext.new(item["prefix"]) .. res - end - if res and item["suffix"] then - res = res .. richtext.new(item["suffix"]) - end - elseif context.mode == "bibliography" then - if not res then - res = richtext.new("[CSL STYLE ERROR: reference with no printed form.]") - end - res = self:wrap(res, context) - -- util.debug(text) - res = res:render(context.engine.formatter, context) - res = context.engine.formatter["@bibliography/entry"](res, context) - end - table.insert(output, res) - previous_cite = item - end - - if context.mode == "citation" then - if next(output) == nil then - return "[CSL STYLE ERROR: reference with no printed form.]" - end - - context = self:process_context(context) - local res - if context.options["collapse"] then - res = self:_collapse_citations(output, context) - else - res = self:concat(output, context) - end - res = self:wrap(res, context) - res = self:format(res, context) - if res then - -- util.debug(res) - res = res:render(context.engine.formatter, context) - end - return res - - else - local params = { - maxoffset = #context.build.longest_label, - } - - return {params, output} - end + return o end -function Layout:_get_position (item, previous_cite, context) - local engine = context.engine - if not engine.registry.registry[item.id] then - return util.position_map["first"] +function Layout:build_ir(engine, state, context) + local ir = self:build_children_ir(engine, state, context) + if not ir then + return nil end - - local position = util.position_map["subsequent"] - -- Find the preceding cite referencing the same item - local preceding_cite = nil - if previous_cite then - -- a. the current cite immediately follows on another cite - if item.id == previous_cite.id then - preceding_cite = previous_cite - end - elseif engine.registry.previous_citation then - -- b. first cite in the citation and previous citation exists - for _, cite in ipairs(engine.registry.previous_citation.citationItems) do - if item.id == cite.id then - preceding_cite = cite - break - end - end - end - - if preceding_cite then - if preceding_cite.locator then - -- Preceding cite does have a locator - if item.locator then - if item.locator == preceding_cite.locator then - position = util.position_map["ibid"] - else - position = util.position_map["ibid-with-locator"] + if context.in_bibliography then + ir.delimiter = self.delimiter + + -- Move affixes of `bibliography > layout` into the right-inline element + -- bugreports_SmallCapsEscape.txt + local has_right_inline = false + if self.affixes or self.formatting then + for i, child_ir in ipairs(ir.children) do + if child_ir.display == "right-inline" then + has_right_inline = true + local right_inline_with_affixes = SeqIr:new({child_ir}, self) + right_inline_with_affixes.affixes = util.clone(self.affixes) + right_inline_with_affixes.formatting = util.clone(self.formatting) + child_ir.display = nil + right_inline_with_affixes.display = "right-inline" + ir.children[i] = right_inline_with_affixes + break end - else - -- the current cite lacks a locator - position = util.position_map["subsequent"] - end - else - -- Preceding cite does not have a locator - if item.locator then - position = util.position_map["ibid-with-locator"] - else - position = util.position_map["ibid"] end end - end - return position -end - -function Layout:_collapse_citations(output, context) - if context.options["collapse"] == "citation-number" then - assert(#output == #context.items) - local citation_numbers = {} - for i, item in ipairs(context.items) do - citation_numbers[i] = context.build.item_citation_numbers[item.id] or 0 + if not has_right_inline then + ir.affixes = util.clone(self.affixes) + ir.formatting = util.clone(self.formatting) end - - local collapsed_output = {} - local citation_number_range_delimiter = util.unicode["en dash"] - local index = 1 - while index <= #citation_numbers do - local stop_index = index + 1 - if output[index] == context.build.item_citation_number_text[index] then - while stop_index <= #citation_numbers do - if output[stop_index] ~= context.build.item_citation_number_text[stop_index] then - break - end - if citation_numbers[stop_index - 1] + 1 ~= citation_numbers[stop_index] then - break - end - stop_index = stop_index + 1 - end - end - - if stop_index >= index + 3 then - local range_text = output[index] .. citation_number_range_delimiter .. output[stop_index - 1] - table.insert(collapsed_output, range_text) - else - for i = index, stop_index - 1 do - table.insert(collapsed_output, output[i]) - end - end - - index = stop_index - end - - return self:concat(collapsed_output, context) end - return self:concat(output, context) + return ir end diff --git a/biblio/citation-style-language/citeproc-node-locale.lua b/biblio/citation-style-language/citeproc-node-locale.lua index 92a604992c..0e8cdd0787 100644 --- a/biblio/citation-style-language/citeproc-node-locale.lua +++ b/biblio/citation-style-language/citeproc-node-locale.lua @@ -6,127 +6,227 @@ local locale = {} -local element = require("citeproc-element") - +local Element = require("citeproc-element").Element +local util = require("citeproc-util") + + +local Locale = Element:derive("locale") + +function Locale:new() + local o = { + xml_lang = nil, + terms = {}, + ordinal_terms = nil, + dates = {}, + style_options = { + -- limit_day_ordinals_to_day_1 = false, + -- punctuation_in_quote = false, + }, + } + setmetatable(o, self) + self.__index = self + return o +end -local Locale = element.Element:new() +function Locale:from_node(node) + local o = Locale:new() + o.xml_lang = node:get_attribute("xml:lang") + o:process_children_nodes(node) + + for _, child in ipairs(o.children) do + local element_name = child.element_name + if element_name == "terms" then + o.terms = child.terms_map + o.ordinal_terms = child.ordinal_terms + elseif element_name == "date" then + o.dates[child.form] = child + end + end -function Locale:get_option (key) - local query = string.format("style-options[%s]", key) - local option = self:query_selector(query)[1] - if option then - local value = option:get_attribute(key) - if self.option_type[key] == "integer" then - value = tonumber(value) - elseif self.option_type[key] == "boolean" then - value = (value == "true") - end - return value - else - return nil + for _, child in ipairs(node:get_children()) do + if child:is_element() and child:get_element_name() == "style-options" then + local style_options = child + o.style_options.limit_day_ordinals_to_day_1 = util.to_boolean( + style_options:get_attribute("limit-day-ordinals-to-day-1") + ) + o.style_options.punctuation_in_quote = util.to_boolean( + style_options:get_attribute("punctuation-in-quote") + ) + end end -end -function Locale:get_term (name, form, number, gender) + return o +end - if form == "long" then - form = nil +function Locale:merge(other) + for key, value in pairs(other.terms) do + self.terms[key] = value end - - local match_last - local match_last_two - local match_whole - if number then - assert(type(number) == "number") - match_last = string.format("%s-%02d", name, number % 10) - match_last_two = string.format("%s-%02d", name, number % 100) - match_whole = string.format("%s-%02s", name, number) + -- https://docs.citationstyles.org/en/stable/specification.html#ordinal-suffixes + -- The “ordinal” term, and “ordinal-00” through “ordinal-99” terms, behave + -- differently from other terms when it comes to Locale Fallback. + -- Whereas other terms can be (re)defined individually, (re)defining any of + -- the ordinal terms through cs:locale replaces all previously defined + -- ordinal terms. + if other.ordinal_terms then + self.ordinal_terms = other.ordinal_terms + end + for key, value in pairs(other.dates) do + self.dates[key] = value end + for key, value in pairs(other.style_options) do + if value ~= nil then + self.style_options[key] = value + end + end + return self +end - local res = nil - for _, term in ipairs(self:query_selector("term")) do - -- Use get_path? - local match_name = name - - if number then - local term_match = term:get_attribute("last-two-digits") - if term_match == "whole-number" then - match_name = match_whole - elseif term_match == "last-two-digits" then - match_name = match_last_two - elseif number < 10 then - -- "13" can match only "ordinal-13" not "ordinal-03" - -- It is sliced to "3" in a later checking pass. - match_name = match_last_two +Locale.form_fallbacks = { + ["verb-short"] = {"verb-short", "verb", "long"}, + ["verb"] = {"verb", "long"}, + ["symbol"] = {"symbol", "short", "long"}, + ["short"] = {"short", "long"}, + ["long"] = {"long"}, +} + +-- Keep in sync with Terms:from_node +function Locale:get_simple_term(name, form, plural) + form = form or "long" + for _, fallback_form in ipairs(self.form_fallbacks[form]) do + local key = name + if form ~= "long" then + if not key then print(debug.traceback()) end + key = key .. "/form-" .. fallback_form + end + local term = self.terms[key] + if term then + if plural then + return term.multiple or term.text else - match_name = match_last + return term.single or term.text end end + end + return nil +end - local term_name = term:get_attribute("name") - local term_form = term:get_attribute("form") - if term_form == "long" then - term_form = nil - end - local term_gender = term:get_attribute("gender-form") +function Locale:get_ordinal_term(number, gender) + -- TODO: match and gender - if term_name == match_name and term_form == form and term_gender == gender then - return term - end + local keys = {} + if gender then + if number < 100 then + table.insert(keys, string.format("ordinal-%02d/gender-form-%s/match-whole-number", number, gender)) + end + table.insert(keys, string.format("ordinal-%02d/gender-form-%s/match-last-two-digits", number % 100, gender)) + table.insert(keys, string.format("ordinal-%02d/gender-form-%s/match-last-digit", number % 10, gender)) end - -- Fallback - if form == "verb-sort" then - return self:get_term(name, "verb") - elseif form == "symbol" then - return self:get_term(name, "short") - elseif form == "verb" then - return self:get_term(name, "long") - elseif form == "short" then - return self:get_term(name, "long") + if number < 100 then + table.insert(keys, string.format("ordinal-%02d/match-whole-number", number)) end - - if number and number > 10 then - return self:get_term(name, nil, number % 10, gender) + table.insert(keys, string.format("ordinal-%02d/match-last-two-digits", number % 100)) + table.insert(keys, string.format("ordinal-%02d/match-last-digit", number % 10)) + table.insert(keys, "ordinal") + + for _, key in ipairs(keys) do + local term = self.ordinal_terms[key] + if term then + return term.text + end end + return nil +end - if gender then - return self:get_term(name, nil, number, nil) +function Locale:get_number_gender(name) + local term = self.terms[name] + if term and term.gender then + return term.gender + else + return nil end +end - if number then - return self:get_term(name, nil, nil, nil) - end - return nil +local Terms = Element:derive("terms") + +function Terms:new() + local o = Element.new(self) + o.element_name = "terms" + o.children = {} + o.terms_map = {} + o.ordinal_terms = nil + return o end -local Term = element.Element:new() +function Terms:from_node(node) + local o = Terms:new() + o:process_children_nodes(node) + for _, term in ipairs(o.children) do + local form = term.form + local gender = term.gender + local gender_form = term.gender_form + local match + if util.startswith(term.name, "ordinal-0") then + match = term.match or "last-digit" + elseif util.startswith(term.name, "ordinal-") then + match = term.match or "last-two-digits" + end -function Term:render (context, is_plural) - self:debug_info(context) - context = self:process_context(context) + local key = term.name + if form then + key = key .. '/form-' .. form + end + -- if gender then + -- key = key .. '/gender-' .. gender + -- end + if gender_form then + key = key .. '/gender-form-' .. gender_form + end + if match then + key = key .. '/match-' .. match + end - local output = { - single = self:get_text(), - } - for _, child in ipairs(self:get_children()) do - if child:is_element() then - output[child:get_element_name()] = self:escape(child:get_text()) + if term.name == "ordinal" or util.startswith(term.name, "ordinal-") then + if not o.ordinal_terms then + o.ordinal_terms = {} + end + o.ordinal_terms[key] = term + else + o.terms_map[key] = term end end - local res = output.single - if is_plural then - if output.multiple then - res = output.multiple + return o +end + + +local Term = Element:derive("term") + +function Term:from_node(node) + local o = Term:new() + + o.name = node:get_attribute("name") + o.form = node:get_attribute("form") + o.match = node:get_attribute("match") + o.gender = node:get_attribute("gender") + o.gender_form = node:get_attribute("gender-form") + o.text = node:get_text() + for _, child in ipairs(node:get_children()) do + if child:is_element() then + local element_name = child:get_element_name() + if element_name == "single" then + o.single = child:get_text() + o.text = o.single + elseif element_name == "multiple" then + o.multiple = child:get_text() + end end end - if res == "" then - return nil - end - return res + + return o end diff --git a/biblio/citation-style-language/citeproc-node-names.lua b/biblio/citation-style-language/citeproc-node-names.lua index 72096a58f9..2f02367eea 100644 --- a/biblio/citation-style-language/citeproc-node-names.lua +++ b/biblio/citation-style-language/citeproc-node-names.lua @@ -8,320 +8,839 @@ local names_module = {} local unicode = require("unicode") -local richtext = require("citeproc-richtext") -local element = require("citeproc-element") +local IrNode = require("citeproc-ir-node").IrNode +local NameIr = require("citeproc-ir-node").NameIr +local PersonNameIr = require("citeproc-ir-node").PersonNameIr +local SeqIr = require("citeproc-ir-node").SeqIr +local Rendered = require("citeproc-ir-node").Rendered +local InlineElement = require("citeproc-output").InlineElement +local PlainText = require("citeproc-output").PlainText +local SortStringFormat = require("citeproc-output").SortStringFormat + +local Element = require("citeproc-element").Element local util = require("citeproc-util") -local Name = element.Element:new() - -Name.default_options = { - ["delimiter"] = ", ", - ["delimiter-precedes-et-al"] = "contextual", - ["delimiter-precedes-last"] = "contextual", - ["et-al-min"] = nil, - ["et-al-use-first"] = nil, - ["et-al-subsequent-min"] = nil, - ["et-al-subsequent-use-first "] = nil, - ["et-al-use-last"] = false, - ["form"] = "long", - ["initialize"] = true, - ["initialize-with"] = false, - ["name-as-sort-order"] = false, - ["sort-separator"] = ", ", - ["prefix"] = "", - ["suffix"] = "", -} - -function Name:render (names, context) - self:debug_info(context) - context = self:process_context(context) - - local and_ = context.options["and"] - local delimiter = context.options["delimiter"] - local delimiter_precedes_et_al = context.options["delimiter-precedes-et-al"] - local delimiter_precedes_last = context.options["delimiter-precedes-last"] - local et_al_min = context.options["et-al-min"] - local et_al_use_first = context.options["et-al-use-first"] - local et_al_subsequent_min = context.options["et-al-subsequent-min"] - local et_al_subsequent_use_first = context.options["et-al-subsequent-use-first "] - local et_al_use_last = context.options["et-al-use-last"] - - -- sorting - if context.options["names-min"] then - et_al_min = context.options["names-min"] - end - if context.options["names-use-first"] then - et_al_use_first = context.options["names-use-first"] - end - if context.options["names-use-last"] ~= nil then - et_al_use_last = context.options["names-use-last"] - end - - local form = context.options["form"] - - local et_al_truncate = et_al_min and et_al_use_first and #names >= et_al_min - local et_al_last = et_al_use_last and et_al_use_first <= et_al_min - 2 - - if form == "count" then - if et_al_truncate then - return et_al_use_first +local Names = Element:derive("names") +local Name = Element:derive("name", { + delimiter = ", ", + delimiter_precedes_et_al = "contextual", + delimiter_precedes_last = "contextual", + et_al_use_last = false, + form = "long", + initialize = true, + sort_separator = ", ", +}) +local NamePart = Element:derive("name-part") +local EtAl = Element:derive("et-al") +local Substitute = Element:derive("substitute") + + +-- [Names](https://docs.citationstyles.org/en/stable/specification.html#names) +function Names:new() + local o = Element.new(self) + o.name = nil + o.et_al = nil + o.substitute = nil + o.label = nil + return o +end + +function Names:from_node(node) + local o = Names:new() + o:set_attribute(node, "variable") + o.name = nil + o.et_al = nil + o.substitute = nil + o.label = nil + o.children = {} + o:process_children_nodes(node) + for _, child in ipairs(o.children) do + local element_name = child.element_name + if element_name == "name" then + o.name = child + elseif element_name == "et-al" then + o.et_al = child + elseif element_name == "substitute" then + o.substitute = child + elseif element_name == "label" then + o.label = child + if o.name then + child.after_name = true + end else - return #names + util.warning(string.format('Unkown element "{}".', element_name)) end end + o:get_delimiter_attribute(node) + o:set_affixes_attributes(node) + o:set_display_attribute(node) + o:set_formatting_attributes(node) + o:set_text_case_attribute(node) + return o +end - local output = nil +function Names:build_ir(engine, state, context) + -- names_inheritance: names and name attributes inherited from cs:style + -- and cs:citaiton or cs:bibliography + -- name_override: names, name, et-al, label elements inherited in substitute element + local names_inheritance = Names:new() + names_inheritance.delimiter = context.name_inheritance.names_delimiter - local res = nil - local inverted = false + names_inheritance.variable = self.variable - for i, name in ipairs(names) do - if et_al_truncate and i > et_al_use_first then - if et_al_last then - if i == #names then - output = richtext.concat(output, delimiter) - output = output .. util.unicode["horizontal ellipsis"] - output = output .. " " - res = self:render_single_name(name, i, context) - output = output .. res - end - else - if not self:_check_delimiter(delimiter_precedes_et_al, i, inverted) then - delimiter = " " - end - if output then - output = richtext.concat_list({output, context.et_al:render(context)}, delimiter) + for _, attr in ipairs({"delimiter", "affixes", "formatting", "display"}) do + if self[attr] then + names_inheritance[attr] = util.clone(self[attr]) + elseif state.name_override and state.name_override[attr] then + names_inheritance[attr] = util.clone(state.name_override[attr]) + end + end + + if self.name then + names_inheritance.name = util.clone(context.name_inheritance) + for key, value in pairs(self.name) do + names_inheritance.name[key] = util.clone(value) + end + else + if state.name_override then + names_inheritance.name = util.clone(state.name_override.name) + else + names_inheritance.name = util.clone(context.name_inheritance) + end + end + + if self.et_al then + names_inheritance.et_al = util.clone(self.et_al) + elseif state.name_override then + names_inheritance.et_al = util.clone(state.name_override.et_al) + else + names_inheritance.et_al = EtAl:new() + end + + if self.label then + names_inheritance.label = util.clone(self.label) + elseif state.name_override then + names_inheritance.label = util.clone(state.name_override.label) + end + + if context.cite then + local position_level = context.cite.position or context.cite.position_level + if position_level and position_level >= util.position_map["subsequent"] then + if names_inheritance.name.et_al_subsequent_min then + names_inheritance.name.et_al_min = names_inheritance.name.et_al_subsequent_min + end + if names_inheritance.name.et_al_subsequent_use_first then + names_inheritance.name.et_al_use_first = names_inheritance.name.et_al_subsequent_use_first + end + end + end + + local irs = {} + local num_names = 0 + -- util.debug(self.name) + + -- The names element may not hold a variable attribute. + -- substitute_SubstituteOnlyOnceString.txt + if names_inheritance.variable then + for _, variable in ipairs(util.split(names_inheritance.variable)) do + local name_ir = names_inheritance.name:build_ir(variable, names_inheritance.et_al, names_inheritance.label, engine, state, context) + if name_ir and names_inheritance.name.form == "count" then + num_names = num_names + name_ir.name_count + end + if name_ir and name_ir.group_var ~= "missing" then + table.insert(irs, name_ir) + end + end + end + + if names_inheritance.name.form == "count" then + if num_names > 0 then + local ir = Rendered:new({PlainText:new(tostring(num_names))}, self) + ir.name_count = num_names + ir.group_var = "important" + ir = NameIr:new({ir}, self) + ir.name_count = num_names + ir.group_var = "important" + -- util.debug(ir) + return ir + end + else + if #irs > 0 then + local ir = SeqIr:new(irs, self) + ir.group_var = "important" + ir.delimiter = names_inheritance.delimiter + ir.formatting = util.clone(names_inheritance.formatting) + ir.affixes = util.clone(names_inheritance.affixes) + ir.display = names_inheritance.display + return ir + end + end + + if self.substitute then + local new_state = util.clone(state) + new_state.name_override = names_inheritance + for _, substitution in ipairs(self.substitute.children) do + local ir = substitution:build_ir(engine, new_state, context) + if ir and ir.group_var ~= "missing" then + if not ir.person_name_irs or #ir.person_name_irs == 0 then + -- In case of a <text variable="title"/> in <substitute> + local name_count = ir.name_count + ir = NameIr:new({ir}, self) + ir.name_count = name_count -- sort_AguStyle.txt + ir.group_var = "important" end - break + return ir end - else - if i > 1 then - if i == #names and context.options["and"] then - if self:_check_delimiter(delimiter_precedes_last, i, inverted) then - output = richtext.concat(output, delimiter) - else - output = output .. " " - end - local and_term = "" - if context.options["and"] == "text" then - and_term = self:get_term("and"):render(context) - elseif context.options["and"] == "symbol" then - and_term = self:escape("&") - end - output = output .. and_term .. " " + end + end + + local ir = Rendered:new({}, self) + ir.group_var = "missing" + return ir + +end + + +function Names:substitute_single_field(result, context) + if not result then + return nil + end + if context.build.first_rendered_names and #context.build.first_rendered_names == 0 then + context.build.first_rendered_names[1] = result + end + result = self:substitute_names(result, context) + return result +end + +function Names:substitute_names(result, context) + if not context.build.first_rendered_names then + return result + end + local name_strings = {} + local match_all + + if #context.build.first_rendered_names > 0 then + match_all = true + else + match_all = false + end + for i, text in ipairs(context.build.first_rendered_names) do + local str = text:render(context.engine.formatter, context) + name_strings[i] = str + if context.build.preceding_first_rendered_names and str ~= context.build.preceding_first_rendered_names[i] then + match_all = false + end + end + + if context.build.preceding_first_rendered_names then + local sub_str = context.options["subsequent-author-substitute"] + local sub_rule = context.options["subsequent-author-substitute-rule"] + + if sub_rule == "complete-all" then + if match_all then + if sub_str == "" then + result = nil else - output = richtext.concat(output, delimiter) + result.contents = {sub_str} end end - res, inverted = self:render_single_name(name, i, context) - if res and res ~= "" then - res = richtext.new(res) - if context.build.first_rendered_names then - table.insert(context.build.first_rendered_names, res) + elseif sub_rule == "complete-each" then + -- In-place substitution + if match_all then + for _, text in ipairs(context.build.first_rendered_names) do + text.contents = {sub_str} end + result = self:concat(context.build.first_rendered_names, context) + end - if output then - output = richtext.concat(output, res) + elseif sub_rule == "partial-each" then + for i, text in ipairs(context.build.first_rendered_names) do + if name_strings[i] == context.build.preceding_first_rendered_names[i] then + text.contents = {sub_str} else - output = res + break end end + result = self:concat(context.build.first_rendered_names, context) + + elseif sub_rule == "partial-first" then + if name_strings[1] == context.build.preceding_first_rendered_names[1] then + context.build.first_rendered_names[1].contents = {sub_str} + end + result = self:concat(context.build.first_rendered_names, context) end end - local ret = self:format(output, context) - ret = self:wrap(ret, context) - return ret + if #context.build.first_rendered_names > 0 then + context.build.first_rendered_names = nil + end + context.build.preceding_first_rendered_names = name_strings + return result end -function Name:_check_delimiter (delimiter_attribute, index, inverted) - -- `delimiter-precedes-et-al` and `delimiter-precedes-last` - if delimiter_attribute == "always" then - return true - elseif delimiter_attribute == "never" then - return false - elseif delimiter_attribute == "contextual" then - if index > 2 then - return true - else - return false - end - elseif delimiter_attribute == "after-inverted-name" then - if inverted then - return true - else - return false +-- [Name](https://docs.citationstyles.org/en/stable/specification.html#name) +function Name:new() + local o = Element.new(self, "name") + + o.family = NamePart:new("family") + o.given = NamePart:new("given") + return o +end + +function Name:from_node(node) + local o = Name:new() + o:set_attribute(node, "and") + o:get_delimiter_attribute(node) + o:set_attribute(node, "delimiter-precedes-et-al") + o:set_attribute(node, "delimiter-precedes-last") + o:set_number_attribute(node, "et-al-min") + o:set_number_attribute(node, "et-al-use-first") + o:set_number_attribute(node, "et-al-subsequent-min") + o:set_number_attribute(node, "et-al-subsequent-use-first") + o:set_bool_attribute(node, "et-al-use-last") + o:set_attribute(node, "form") + o:set_bool_attribute(node, "initialize") + o:set_attribute(node, "initialize-with") + o:set_attribute(node, "name-as-sort-order") + o:set_attribute(node, "sort-separator") + o:set_affixes_attributes(node) + o:set_formatting_attributes(node) + o:process_children_nodes(node) + for _, child in ipairs(o.children) do + if child.name == "family" then + o.family = child + elseif child.name == "given" then + o.given = child end end - return false + if not o.family then + o.family = NamePart:new() + o.family.name = "family" + end + if not o.given then + o.given = NamePart:new() + o.family.name = "given" + end + return o end -function Name:render_single_name (name, index, context) - local form = context.options["form"] - local initialize = context.options["initialize"] - local initialize_with = context.options["initialize-with"] - local name_as_sort_order = context.options["name-as-sort-order"] - if context.sorting then - name_as_sort_order = "all" + +function Name:build_ir(variable, et_al, label, engine, state, context) + -- Returns NameIR + local names + if not state.suppressed[variable] then + names = context:get_variable(variable) + end + if not names then + return nil end - local sort_separator = context.options["sort-separator"] - local demote_non_dropping_particle = context.options["demote-non-dropping-particle"] + if context.sort_key then + self.delimiter = " " + self.name_as_sort_order = "all" + if context.sort_key.names_min then + self.et_al_min = context.sort_key.names_min + end + if context.sort_key.names_use_first then + self.et_al_use_first = context.sort_key.names_use_first + end + if context.sort_key.names_use_last then + self.et_al_use_last = context.sort_key.names_use_last + end + et_al = nil + label = nil + end - -- TODO: make it a module - local function _strip_quotes(str) - if str then - str = string.gsub(str, '"', "") - str = string.gsub(str, "'", util.unicode["apostrophe"]) + local et_al_abbreviation = self.et_al_min and self.et_al_use_first and #names >= self.et_al_min + local use_last = et_al_abbreviation and self.et_al_use_last and self.et_al_use_first <= self.et_al_min - 2 + + if self.form == "count" then + local count + if et_al_abbreviation then + count = self.et_al_use_first + else + count = #names end - return str + local ir = Rendered:new({PlainText:new(tostring(count))}, {}) + ir.name_count = count + ir.group_var = "important" + return ir end - local family = _strip_quotes(name["family"]) or "" - local given = _strip_quotes(name["given"]) or "" - local dp = _strip_quotes(name["dropping-particle"]) or "" - local ndp = _strip_quotes(name["non-dropping-particle"]) or "" - local suffix = _strip_quotes(name["suffix"]) or "" - local literal = _strip_quotes(name["literal"]) or "" + -- TODO: only build names as needed + local full_name_irs = {} + local full_name_str = "" + for i, name_var in ipairs(names) do + local person_name_ir = self:build_person_name_ir(name_var, i == 1, context) + table.insert(full_name_irs, person_name_ir) - if family == "" then - family = literal - if family == "" then - family = given - given = "" + local name_variants = person_name_ir.disam_variants + if full_name_str ~= "" then + full_name_str = full_name_str .. " " end - if family ~= "" then - return family - else - error("Name not avaliable") + full_name_str = full_name_str .. name_variants[#name_variants] + end + + local person_name_irs -- TODO: rename to rendered_name_irs + local hidden_name_irs + if et_al_abbreviation then + person_name_irs = util.slice(full_name_irs, 1, self.et_al_use_first) + hidden_name_irs = util.slice(full_name_irs, self.et_al_use_first + 1, #full_name_irs) + if use_last then + table.insert(person_name_irs, full_name_irs[#full_name_irs]) + table.remove(hidden_name_irs, #hidden_name_irs) + end + else + person_name_irs = util.slice(full_name_irs, 1, #full_name_irs) + hidden_name_irs = {} + end + + + local and_term_ir + if not context.sort_key then + -- sort_WithAndInOneEntry.txt + local and_term + if self["and"] == "text" then + and_term = context.locale:get_simple_term("and") + elseif self["and"] == "symbol" then + and_term = "&" + end + if and_term then + and_term_ir = Rendered:new({PlainText:new(and_term .. " ")}, {}) end end - if initialize_with then - given = self:initialize(given, initialize_with, context) + local et_al_ir + if et_al and et_al_abbreviation and not use_last then + et_al_ir = et_al:build_ir(engine, state, context) end - local demote_ndp = false -- only active when form == "long" - if demote_non_dropping_particle == "display-and-sort" or - demote_non_dropping_particle == "sort-only" and context.sorting then - demote_ndp = true - else -- demote_non_dropping_particle == "never" - demote_ndp = false + local irs = self:join_person_name_irs(person_name_irs, and_term_ir, et_al_ir, use_last) + + local ir = NameIr:new(irs, self) + + ir.name_inheritance = self + ir.name_variable = names + ir.and_term_ir = and_term_ir + ir.et_al_ir = et_al_ir + ir.et_al_abbreviation = et_al_abbreviation + ir.use_last = use_last + + ir.full_name_irs = full_name_irs + ir.full_name_str = full_name_str + ir.person_name_irs = person_name_irs + ir.hidden_name_irs = hidden_name_irs + + -- etal_UseZeroFirst.txt: et-al-use-first="0" + if #irs == 0 then + ir.group_var = "missing" + return ir + else + ir.group_var = "important" end - local family_name_part = nil - local given_name_part = nil - for _, child in ipairs(self:get_children()) do - if child:is_element() and child:get_element_name() == "name-part" then - local name_part = child:get_attribute("name") - if name_part == "family" then - family_name_part = child - elseif name_part == "given" then - given_name_part = child + ir.formatting = self.formatting + ir.affixes = self.affixes + + irs = {ir} + + if label then + local is_plural = (label.plural == "always" or (label.plural == "contextual" and #names > 1)) + local label_term = context.locale:get_simple_term(variable, label.form, is_plural) + if label_term and label_term ~= "" then + local inlines = label:render_text_inlines(label_term, context) + local label_ir = Rendered:new(inlines, label) + if label.after_name then + table.insert(irs, label_ir) + else + table.insert(irs, 1, label_ir) end end end - local res = nil - local inverted = false - if form == "long" then - local order - local suffix_separator = sort_separator - if not util.has_romanesque_char(name["family"]) then - order = {family, given} - inverted = true - sort_separator = "" - elseif name_as_sort_order == "all" or (name_as_sort_order == "first" and index == 1) then - - -- "Alan al-One" - local hyphen_parts = util.split(family, "%-", 1) - if #hyphen_parts > 1 then - local particle - particle, family = table.unpack(hyphen_parts) - particle = particle .. "-" - ndp = richtext.concat(ndp, particle) + ir = SeqIr:new(irs, self) + + -- Suppress substituted name variable + if state.name_override and not context.sort_key then + state.suppressed[variable] = true + end + + return ir +end + +function Name:build_person_name_ir(name, is_first, context) + local is_latin = util.has_romanesque_char(name.family) + local is_inverted = (name.family and name.family ~= "" and is_latin and + (self.name_as_sort_order == "all" or (self.name_as_sort_order == "first" and is_first))) + + local inlines = self:render_person_name(name, is_first, is_latin, is_inverted, context) + local person_name_ir = PersonNameIr:new(inlines, self) + + person_name_ir.is_inverted = is_inverted + + local output_format = SortStringFormat:new() + person_name_ir.name_output = output_format:output(inlines) + person_name_ir.disam_variants_index = 1 + + person_name_ir.disam_variants = {person_name_ir.name_output} + person_name_ir.disam_inlines = {inlines} + + if context.area.disambiguate_add_givenname and not context.sort_key then + local disam_name = util.clone(self) + if disam_name.form == "short" then + disam_name.form = "long" + if disam_name.initialize and disam_name.initialize_with then + local name_inlines = disam_name:render_person_name(name, is_first, is_latin, is_inverted, context) + local disam_variant = output_format:output(name_inlines) + local last_variant = person_name_ir.disam_variants[#person_name_ir.disam_variants] + if disam_variant ~= last_variant then + table.insert(person_name_ir.disam_variants, disam_variant) + person_name_ir.disam_inlines[disam_variant] = name_inlines + end end + end - if family_name_part then - family = family_name_part:format_name_part(family, context) - ndp = family_name_part:format_name_part(ndp, context) + local givenname_disambiguation_rule = context.area.givenname_disambiguation_rule + local only_initials = (givenname_disambiguation_rule == "all-names-with-initials" or + givenname_disambiguation_rule == "primary-name-with-initials") + if disam_name.initialize and not only_initials then + disam_name.initialize = false + local name_inlines = disam_name:render_person_name(name, is_first, is_latin, is_inverted, context) + local disam_variant = output_format:output(name_inlines) + local last_variant = person_name_ir.disam_variants[#person_name_ir.disam_variants] + if disam_variant ~= last_variant then + table.insert(person_name_ir.disam_variants, disam_variant) + person_name_ir.disam_inlines[disam_variant] = name_inlines end - if given_name_part then - given = given_name_part:format_name_part(given, context) - dp = family_name_part:format_name_part(dp, context) + end + + context.sort_key = true + local full_name_inlines = disam_name:render_person_name(name, is_first, is_latin, is_inverted, context) + -- full_name is used for comparison in disambiguation + person_name_ir.full_name = output_format:output(full_name_inlines) + context.sort_key = false + end + + return person_name_ir +end + +function Name:render_person_name(name, is_first, is_latin, is_inverted, context) + -- Return: inlines + -- TODO + local is_sort = context.sort_key + local demote_ndp = (context.style.demote_non_dropping_particle == "display-and-sort" or + (is_sort and context.style.demote_non_dropping_particle == "sort-only")) + + local name_part_tokens = self:get_display_order(name, self.form, is_latin, is_sort, is_inverted, demote_ndp) + -- util.debug(name) + -- util.debug(name_part_tokens) + + local inlines = {} + for i, token in ipairs(name_part_tokens) do + if token == "family" or token == "ndp-family" or token == "dp-ndp-family-suffix" then + local family_inlines = self:render_family(name, token, context) + util.extend(inlines, family_inlines) + + elseif token == "given" or token == "given-dp" or token == "given-dp-ndp" then + local given_inlines = self:render_given(name, token, context) + util.extend(inlines, given_inlines) + + elseif token == "dp" or token == "dp-ndp" then + local particle_inlines = self:render_particle(name, token, context) + util.extend(inlines, particle_inlines) + + elseif token == "suffix" then + local text = name.suffix or "" + util.extend(inlines, InlineElement:parse(text, context)) + + elseif token == "literal" then + local literal_inlines = self.family:format_text_case(name.literal, context) + util.extend(inlines, literal_inlines) + + elseif token == "space" then + table.insert(inlines, PlainText:new(" ")) + + elseif token == "wide-space" then + table.insert(inlines, PlainText:new(" ")) + + elseif token == "sort-separator" then + table.insert(inlines, PlainText:new(self.sort_separator)) + end + end + -- util.debug(inlines) + return inlines +end + +-- Name-part Order +-- https://docs.citationstyles.org/en/stable/specification.html#name-part-order +function Name:get_display_order(name, form, is_latin, is_sort, is_inverted, demote_ndp) + if is_sort then + if not name.family then + -- The literal is compared with the literal + if self.form == "long" then + return {"literal", "wide-space", "wide-space", "wide-space"} + else + return {"literal", "wide-space"} end + end + if not is_latin then + if form == "long" and name.given then + return {"family", "given"} + else + return {"family"} + end + end + + if self.form == "long" then if demote_ndp then - given = richtext.concat_list({given, dp, ndp}, " ") + return {"family", "wide-space", "dp-ndp", "wide-space", "given", "wide-space", "suffix"} else - family = richtext.concat_list({ndp, family}, " ") - given = richtext.concat_list({given, dp}, " ") + return {"ndp-family", "wide-space", "dp", "wide-space", "given", "wide-space", "suffix"} end + else + if demote_ndp then + return {"family", "wide-space", "dp-ndp"} + else + return {"ndp-family", "wide-space", "dp"} + end + end + end + + if not name.family then + if name.literal then + return {"literal"} + else + util.error("Invalid name") + end + end + + if not is_latin then + if form == "long" and name.given then + return {"family", "given"} + else + return {"family"} + end + end - if family_name_part then - family = family_name_part:wrap_name_part(family, context) + if form == "short" then + return {"ndp-family"} + end + + local ndp = name["non-dropping-particle"] + local dp = name["dropping-particle"] + + local name_part_tokens = {"family"} + if name.given then + if is_inverted then + if demote_ndp then + name_part_tokens = {"family", "sort-separator", "given-dp-ndp"} + else + name_part_tokens = {"ndp-family", "sort-separator", "given-dp"} end - if given_name_part then - given = given_name_part:wrap_name_part(given, context) + else + name_part_tokens = {"given", "space", "dp-ndp-family-suffix"} + end + else + if is_inverted then + if demote_ndp then + if ndp or dp then + name_part_tokens = {"family", "sort-separator", "dp-ndp"} + else + name_part_tokens = {"family"} + end + else + name_part_tokens = {"ndp-family"} end + else + name_part_tokens = {"dp-ndp-family-suffix"} + end + end - order = {family, given, suffix} - inverted = true + if name.suffix and is_inverted then + if is_inverted or name["comma-suffix"] then + table.insert(name_part_tokens, "sort-separator") + table.insert(name_part_tokens, "suffix") + elseif string.match(name.suffix, "^%p") then + table.insert(name_part_tokens, "sort-separator") + table.insert(name_part_tokens, "suffix") else - if family_name_part then - family = family_name_part:format_name_part(family, context) - ndp = family_name_part:format_name_part(ndp, context) + table.insert(name_part_tokens, "space") + table.insert(name_part_tokens, "suffix") + end + end + + return name_part_tokens +end + +function Name:render_family(name, token, context) + local inlines = {} + local name_part + + if token == "dp-ndp-family-suffix" then + local dp_part = name["dropping-particle"] + if dp_part then + name_part = dp_part + local dp_inlines = self.given:format_text_case(dp_part, context) + util.extend(inlines, dp_inlines) + end + end + + if token == "dp-ndp-family-suffix" or token == "ndp-family" then + local ndp_part = name["non-dropping-particle"] + if ndp_part then + if context.sort_key then + ndp_part = self:format_sort_particle(ndp_part) end - if given_name_part then - given = given_name_part:format_name_part(given, context) - dp = family_name_part:format_name_part(dp, context) + if #inlines > 0 then + table.insert(inlines, PlainText:new(" ")) end + name_part = ndp_part + local ndp_inlines = self.family:format_text_case(ndp_part, context) + util.extend(inlines, ndp_inlines) + end + end - family = richtext.concat_list({dp, ndp, family}, " ") - if name["comma-suffix"] then - suffix_separator = ", " + local family = name.family + if context.sort_key then + -- Remove brackets for sorting: sort_NameVariable.txt + family = string.gsub(family, "[%[%]]", "") + end + + local family_inlines = self.family:format_text_case(family, context) + if #inlines > 0 then + if not string.match(name_part, "^%l'$") and + not string.match(name_part, "^%l’$") and + not util.endswith(name_part, "-") then + table.insert(inlines, PlainText:new(" ")) + end + end + util.extend(inlines, family_inlines) + + if token == "dp-ndp-family-suffix" then + local suffix_part = name.suffix + if suffix_part then + if name["comma-suffix"] or util.startswith(suffix_part, "!") then + -- force use sort-separator exclamation prefix: magic_NameSuffixWithComma.txt + -- "! Jr." => "Jr." + table.insert(inlines, PlainText:new(self.sort_separator)) + suffix_part = string.gsub(suffix_part, "^%p%s*", "") else - suffix_separator = " " + table.insert(inlines, PlainText:new(" ")) end - family = richtext.concat_list({family, suffix}, suffix_separator) + table.insert(inlines, PlainText:new(suffix_part)) + end + end - if family_name_part then - family = family_name_part:wrap_name_part(family, context) - end - if given_name_part then - given = given_name_part:wrap_name_part(given, context) - end + inlines = self.family:affixed(inlines) + return inlines +end + +function Name:render_given(name, token, context) + local given = name.given - order = {given, family} - sort_separator = " " + if context.sort_key then + -- The empty given name is needed for evaluate the sort key. + if not given then + return {PlainText:new("")} end - res = richtext.concat_list(order, sort_separator) + -- Remove brackets for sorting: sort_NameVariable.txt + given = string.gsub(given, "[%[%]]", "") + end - elseif form == "short" then - if family_name_part then - family = family_name_part:format_name_part(family, context) - ndp = family_name_part:format_name_part(ndp, context) + if self.initialize_with then + given = self:initialize_name(given, self.initialize_with, context.style.initialize_with_hyphen) + end + local inlines = self.given:format_text_case(given, context) + + if token == "given-dp" or token == "given-dp-ndp" then + local name_part = name["dropping-particle"] + if name_part then + table.insert(inlines, PlainText:new(" ")) + local dp_inlines = self.given:format_text_case(name_part, context) + util.extend(inlines, dp_inlines) end - family = util.concat({ndp, family}, " ") - if family_name_part then - family = family_name_part:wrap_name_part(family, context) + end + + if token == "given-dp-ndp" then + local name_part = name["non-dropping-particle"] + if name_part then + table.insert(inlines, PlainText:new(" ")) + local ndp_inlines = self.family:format_text_case(name_part, context) + util.extend(inlines, ndp_inlines) + end + end + + inlines = self.given:affixed(inlines) + return inlines +end + +-- sort_LeadingApostropheOnNameParticle.txt +-- "’t " => "t" +function Name:format_sort_particle(particle) + particle = string.gsub(particle, "^'", "") + particle = string.gsub(particle, "^’", "") + return particle +end + +function Name:render_particle(name, token, context) + local inlines = {} + + local dp_part = name["dropping-particle"] + if dp_part then + dp_part = self:format_sort_particle(dp_part) + local dp_inlines = self.given:format_text_case(dp_part, context) + util.extend(inlines, dp_inlines) + end + + if token == "dp-ndp" then + local ndp_part = name["non-dropping-particle"] + if ndp_part then + if #inlines > 0 then + table.insert(inlines, PlainText:new(" ")) end - res = family - else - error(string.format('Invalid attribute form="%s" of "name".', form)) + ndp_part = self:format_sort_particle(ndp_part) + local ndp_inlines = self.family:format_text_case(ndp_part, context) + util.extend(inlines, ndp_inlines) + end + end + + return inlines +end + +function Name:_check_delimiter(delimiter_attribute, num_first_names, inverted) + -- `delimiter-precedes-et-al` and `delimiter-precedes-last` + if delimiter_attribute == "always" then + return true + elseif delimiter_attribute == "never" then + return false + elseif delimiter_attribute == "contextual" then + if num_first_names > 1 then + return true + else + return false + end + elseif delimiter_attribute == "after-inverted-name" then + if inverted then + return true + else + return false + end end - return res, inverted + return false end -function Name:initialize (given, terminator, context) +-- TODO: initialize name with markups +-- name_InTextMarkupInitialize.txt +-- name_InTextMarkupNormalizeInitials.txt +function Name:initialize_name(given, with, initialize_with_hyphen) if not given or given == "" then return "" end - local initialize = context.options["initialize"] - if context.options["initialize-with-hyphen"] == false then + if initialize_with_hyphen == false then given = string.gsub(given, "-", " ") end @@ -367,9 +886,9 @@ function Name:initialize (given, terminator, context) name_list[i-1] = name_list[i-1] .. " " end elseif is_abbreviation then - name_list[i] = name .. terminator + name_list[i] = name .. with else - if initialize then + if self.initialize then if util.is_upper(name) then name = first_letter else @@ -389,7 +908,7 @@ function Name:initialize (given, terminator, context) end name = abbreviation end - name_list[i] = name .. terminator + name_list[i] = name .. with else name_list[i] = name .. " " end @@ -412,287 +931,176 @@ function Name:initialize (given, terminator, context) end -local NamePart = element.Element:new() - -function NamePart:format_name_part(name_part, context) - context = self:process_context(context) - local res = self:case(name_part, context) - res = self:format(res, context) - return res -end - -function NamePart:wrap_name_part(name_part, context) - context = self:process_context(context) - local res = self:wrap(name_part, context) - return res -end - - -local EtAl = element.Element:new() - -EtAl.default_options = { - term = "et-al", -} - -EtAl.render = function (self, context) - self:debug_info(context) - context = self:process_context(context) - local res = self:get_term(context.options["term"]):render(context) - res = self:format(res, context) - return res -end - - -local Substitute = element.Element:new() +function Name:join_person_name_irs(rendered_name_irs, and_term_ir, et_al_ir, use_last) + local first_items = rendered_name_irs + local last_item + if et_al_ir then + first_items = rendered_name_irs + last_item = et_al_ir + elseif #rendered_name_irs > 1 then + first_items = util.slice(rendered_name_irs, 1, #rendered_name_irs - 1) + last_item = rendered_name_irs[#rendered_name_irs] + end -function Substitute:render (item, context) - self:debug_info(context) + local irs = {} - if context.suppressed_variables then - -- true in layout, not in sort - context.suppress_subsequent_variables = true + for i, person_name_ir in ipairs(first_items) do + if i > 1 then + table.insert(irs, Rendered:new({PlainText:new(self.delimiter)}, self)) + end + table.insert(irs, person_name_ir) end - for i, child in ipairs(self:get_children()) do - if child:is_element() then - local result = child:render(item, context) - if result and result ~= "" then - return result + if last_item then + if use_last then + local delimiter = self.delimiter .. util.unicode["horizontal ellipsis"] .. " " + table.insert(irs, Rendered:new({PlainText:new(delimiter)}, self)) + table.insert(irs, last_item) + elseif et_al_ir then + if #first_items > 0 then + local inverted = first_items[#first_items].is_inverted + local use_delimiter = self:_check_delimiter(self.delimiter_precedes_et_al, #first_items, inverted) + if use_delimiter then + table.insert(irs, Rendered:new({PlainText:new(self.delimiter)}, self)) + elseif not et_al_ir.starts_with_cjk then + -- name_EtAlWithCombined.txt + table.insert(irs, Rendered:new({PlainText:new(" ")}, self)) + end + table.insert(irs, last_item) end + else + local inverted = first_items[#first_items].is_inverted + local use_delimiter = self:_check_delimiter(self.delimiter_precedes_last, #first_items, inverted) + if use_delimiter or not and_term_ir then + table.insert(irs, Rendered:new({PlainText:new(self.delimiter)}, self)) + else + table.insert(irs, Rendered:new({PlainText:new(" ")}, self)) + end + if and_term_ir and not et_al_ir then + table.insert(irs, and_term_ir) + end + table.insert(irs, last_item) end end - return nil -end - -local Names = element.Element:new() - -function Names:render (item, context) - self:debug_info(context) - context = self:process_context(context) + return irs +end - local names_delimiter = context.options["names-delimiter"] - if names_delimiter then - context.options["delimiter"] = names_delimiter +-- For use in disambiguate-add-names +function Name:expand_one_name(name_ir) + local rendered_name_irs = name_ir.person_name_irs + local hidden_name_irs = name_ir.hidden_name_irs + if #hidden_name_irs == 0 then + return nil end - - -- Inherit attributes of parent `names` element - local names_element = context.names_element - if names_element then - for key, value in pairs(names_element._attr) do - context.options[key] = value - end - for key, value in pairs(self._attr) do - context.options[key] = value - end + local person_name_ir_to_add = hidden_name_irs[1] + if name_ir.use_last then + table.insert(rendered_name_irs, #rendered_name_irs, person_name_ir_to_add) else - context.names_element = self - context.variable = context.options["variable"] - end - - local name, et_al, label - -- The position of cs:label relative to cs:name determines the order of - -- the name and label in the rendered text. - local label_position = nil - for _, child in ipairs(self:get_children()) do - if child:is_element() then - local element_name = child:get_element_name() - if element_name == "name" then - name = child - if label then - label_position = "before" - end - elseif element_name == "et-al" then - et_al = child - elseif element_name == "label" then - label = child - if name then - label_position = "after" - end - end - end + table.insert(rendered_name_irs, person_name_ir_to_add) end - if label_position then - context.label_position = label_position - else - label_position = context.label_position or "after" + table.remove(hidden_name_irs, 1) + if #hidden_name_irs == 0 then + if name_ir.et_al_abbreviation then + name_ir.et_al_abbreviation = false + end + if name_ir.use_last then + name_ir.use_last = false + end end - -- local name = self:get_child("name") - if not name then - name = context.name_element + local and_term_ir = name_ir.and_term_ir + local et_al_ir + if name_ir.et_al_abbreviation then + et_al_ir = name_ir.et_al_ir end - if not name then - name = self:create_element("name", {}, self) - Name:set_base_class(name) - end - context.name_element = name + local use_last = name_ir.use_last - -- local et_al = self:get_child("et-al") - if not et_al then - et_al = context.et_al - end - if not et_al then - et_al = self:create_element("et-al", {}, self) - EtAl:set_base_class(et_al) - end - context.et_al = et_al + name_ir.children = self:join_person_name_irs(rendered_name_irs, and_term_ir, et_al_ir, use_last) + return person_name_ir_to_add +end - -- local label = self:get_child("label") - if label then - context.label = label - else - label = context.label - end - - local sub_str = nil - if context.mode == "bibliography" and not context.sorting then - sub_str = context.options["subsequent-author-substitute"] - -- if sub_str and #context.build.preceding_first_rendered_names == 0 then - -- context.rendered_names = {} - -- else - -- sub_str = nil - -- context.rendered_names = nil - -- end - end - - local variable_names = context.options["variable"] or context.variable - local ret = nil - - if variable_names then - local output = {} - local num_names = 0 - for _, role in ipairs(util.split(variable_names)) do - local names = self:get_variable(item, role, context) - - table.insert(context.variable_attempt, names ~= nil) - - if names then - local res = name:render(names, context) - if res then - if type(res) == "number" then -- name[form="count"] - num_names = num_names + res - elseif label and not context.sorting then - -- drop name label in sorting - local label_result = label:render(role, context) - if label_result then - if label_position == "before" then - res = richtext.concat(label_result, res) - else - res = richtext.concat(res, label_result) - end - end - end - end - table.insert(output, res) - end - end - if num_names > 0 then - ret = tostring(num_names) - else - ret = self:concat(output, context) - if ret and sub_str and context.build.first_rendered_names then - ret = self:substitute_names(ret, context) - end - end +-- [Name-part](https://docs.citationstyles.org/en/stable/specification.html#name-part-formatting) +function NamePart:new(name) + local o = Element.new(self) + o.name = name + return o +end + +function NamePart:from_node(node) + local o = NamePart:new() + o:set_attribute(node, "name") + o:set_formatting_attributes(node) + o:set_text_case_attribute(node) + o:set_affixes_attributes(node) + return o +end + +function NamePart:format_text_case(text, context) + local output_format = context.format + local inlines = InlineElement:parse(text, context) + local is_english = context:is_english() + if not output_format then + print(debug.traceback()) end + output_format:apply_text_case(inlines, self.text_case, is_english) - if ret then - ret = self:format(ret, context) - ret = self:wrap(ret, context) - ret = self:display(ret, context) - return ret - else - local substitute = self:get_child("substitute") - if substitute then - ret = substitute:render(item, context) + inlines = output_format:with_format(inlines, self.formatting) + return inlines +end + +function NamePart:affixed(inlines) + if self.affixes then + if self.affixes.prefix then + table.insert(inlines, 1, PlainText:new(self.affixes.prefix)) end - if ret and sub_str then - ret = self:substitute_single_field(ret, context) + if self.affixes.suffix then + table.insert(inlines, PlainText:new(self.affixes.suffix)) end - return ret end + return inlines end -function Names:substitute_single_field(result, context) - if not result then - return nil - end - if context.build.first_rendered_names and #context.build.first_rendered_names == 0 then - context.build.first_rendered_names[1] = result - end - result = self:substitute_names(result, context) - return result -end -function Names:substitute_names(result, context) - if not context.build.first_rendered_names then - return result - end - local name_strings = {} - local match_all +-- [Et-al](https://docs.citationstyles.org/en/stable/specification.html#et-al) +EtAl.term = "et-al" - if #context.build.first_rendered_names > 0 then - match_all = true - else - match_all = false +function EtAl:from_node(node) + local o = EtAl:new() + o:set_attribute(node, "term") + o:set_formatting_attributes(node) + return o +end + +function EtAl:build_ir(engine, state, context) + local term = context.locale:get_simple_term(self.term) + if not term then + return term end - for i, text in ipairs(context.build.first_rendered_names) do - local str = text:render(context.engine.formatter, context) - name_strings[i] = str - if context.build.preceding_first_rendered_names and str ~= context.build.preceding_first_rendered_names[i] then - match_all = false - end + local inlines = InlineElement:parse(term, context) + if #inlines == 0 then + return nil end - if context.build.preceding_first_rendered_names then - local sub_str = context.options["subsequent-author-substitute"] - local sub_rule = context.options["subsequent-author-substitute-rule"] + inlines = context.format:with_format(inlines, self.formatting) - if sub_rule == "complete-all" then - if match_all then - if sub_str == "" then - result = nil - else - result.contents = {sub_str} - end - end + local ir = Rendered:new(inlines, self) - elseif sub_rule == "complete-each" then - -- In-place substitution - if match_all then - for _, text in ipairs(context.build.first_rendered_names) do - text.contents = {sub_str} - end - result = self:concat(context.build.first_rendered_names, context) - end - - elseif sub_rule == "partial-each" then - for i, text in ipairs(context.build.first_rendered_names) do - if name_strings[i] == context.build.preceding_first_rendered_names[i] then - text.contents = {sub_str} - else - break - end - end - result = self:concat(context.build.first_rendered_names, context) - - elseif sub_rule == "partial-first" then - if name_strings[1] == context.build.preceding_first_rendered_names[1] then - context.build.first_rendered_names[1].contents = {sub_str} - end - result = self:concat(context.build.first_rendered_names, context) - end + if util.is_cjk_char(utf8.codepoint(term, 1)) then + ir.starts_with_cjk = true end - if #context.build.first_rendered_names > 0 then - context.build.first_rendered_names = nil - end - context.build.preceding_first_rendered_names = name_strings - return result + return ir end +function Substitute:from_node(node) + local o = Substitute:new() + o:process_children_nodes(node) + return o +end + + names_module.Names = Names names_module.Name = Name names_module.NamePart = NamePart diff --git a/biblio/citation-style-language/citeproc-node-number.lua b/biblio/citation-style-language/citeproc-node-number.lua index ba096157aa..4ef308e3d0 100644 --- a/biblio/citation-style-language/citeproc-node-number.lua +++ b/biblio/citation-style-language/citeproc-node-number.lua @@ -6,97 +6,63 @@ local number_module = {} -local element = require("citeproc-element") -local util = require("citeproc-util") - - -local Number = element.Element:new() - -function Number:render (item, context) - self:debug_info(context) - context = self:process_context(context) - local variable = context.options["variable"] - local content = self:get_variable(item, variable, context) +local Element = require("citeproc-element").Element - table.insert(context.variable_attempt, content ~= nil) +local Rendered = require("citeproc-ir-node").Rendered - if not content then - return nil - end - - local numbers = {} - local punct_list = {} - local last_position = 1 - for number, punct, pos in string.gmatch(content, "(.-)%s*([-,&])%s*()") do - table.insert(numbers, number) - table.insert(punct_list, punct) - last_position = pos - end - table.insert(numbers, string.sub(content, last_position)) +local util = require("citeproc-util") - local res = "" - for i, number in ipairs(numbers) do - local punct = punct_list[i] - number = self:_format_single_number(number, context) - res = res .. number - if punct == "-" then - res = res .. punct - elseif punct == "," then - res = res .. punct .. " " - elseif punct == "&" then - res = res .. " " .. punct .. " " - end - end +local Number = Element:derive("number") - res = self:case(res, context) - res = self:wrap(res, context) - res = self:display(res, context) +function Number:new(node) + local o = { + element_name = "number", + form = "numeric", + } + setmetatable(o, self) + self.__index = self + return o +end - return res +function Number:from_node(node) + local o = Number:new() + o:set_attribute(node, "variable") + o:set_attribute(node, "form") + o:set_affixes_attributes(node) + o:set_display_attribute(node) + o:set_formatting_attributes(node) + o:set_text_case_attribute(node) + return o end -function Number:_format_single_number(number, context) - local form = context.options["form"] or "numeric" - if form == "numeric" or not string.match(number, "^%d+$") then - return number +function Number:build_ir(engine, state, context) + local number + if not state.suppressed[self.variable] then + number = context:get_variable(self.variable, self.form) end - number = tonumber(number) - if form == "ordinal" or form == "long-ordinal" then - return self:_format_oridinal(number, form, context) - elseif form == "roman" then - return util.convert_roman(number) + if not number then + local ir = Rendered:new({}, self) + ir.group_var = "missing" + return ir end -end - -function Number:_format_oridinal(number, form, context) - assert(type(number) == "number") - local variable = context.options["variable"] - if form == "long-ordinal" then - if number < 1 or number > 10 then - form = "ordinal" - end + if type(number) == "number" then + number = tostring(number) + number = self:format_number(number, self.variable, self.form, context) + elseif util.is_numeric(number) then + number = self:format_number(number, self.variable, self.form, context) end - local gender = nil - local term = self:get_term(variable) - if term then - gender = term:get_attribute("gender") - end + local inlines = self:render_text_inlines(number, context) + local ir = Rendered:new(inlines, self) + ir.group_var = "important" - term = self:get_term(form, nil, number, gender) - local res = term:render(context) - if form == "ordinal" then - if res then - return tostring(number) .. res - else - res = tostring(number) - end - else - return res + -- Suppress substituted name variable + if state.name_override and not context.sort_key then + state.suppressed[self.variable] = true end - return res + return ir end diff --git a/biblio/citation-style-language/citeproc-node-sort.lua b/biblio/citation-style-language/citeproc-node-sort.lua index 1b82d21b55..876c3257da 100644 --- a/biblio/citation-style-language/citeproc-node-sort.lua +++ b/biblio/citation-style-language/citeproc-node-sort.lua @@ -8,57 +8,80 @@ local sort = {} local unicode = require("unicode") -local element = require("citeproc-element") +local Element = require("citeproc-element").Element +local Date = require("citeproc-node-date").Date local names = require("citeproc-node-names") -local date = require("citeproc-node-date") +local InlineElement = require("citeproc-output").InlineElement local util = require("citeproc-util") -local Sort = element.Element:new() +-- [Sorting](https://docs.citationstyles.org/en/stable/specification.html#sorting) +local Sort = Element:derive("sort") -function Sort:sort (items, context) +function Sort:from_node(node) + local o = Sort:new() + o.children = {} + + o:process_children_nodes(node) + o.sort_directions = {} + for i, key in ipairs(o.children) do + o.sort_directions[i] = (key.sort ~= "descending") + end + table.insert(o.sort_directions, true) + + return o +end + +function Sort:sort(items, state, context) -- key_map = { -- id1 = {key1, key2, ...}, -- id2 = {key1, key2, ...}, -- ... -- } - context.variable_attempt = {} - local key_map = {} - local sort_directions = {} + local sort_directions = self.sort_directions -- true: ascending -- false: descending - if not Sort.collator_obj then - local lang = context.style.lang + if not Sort.collator then + local lang = context.engine.lang local language = string.sub(lang, 1, 2) -- It's 6 seconds slower to run the whole test-suite if these package -- loading statements are put in the header. - local ducet = require("lua-uca.lua-uca-ducet") - local collator = require("lua-uca.lua-uca-collator") - local languages = require("lua-uca.lua-uca-languages") - local collator_obj = collator.new(ducet) - if languages[language] then - Sort.collator_obj = languages[language](collator_obj) - else - util.warning(string.format('Lcoale "%s" is not supported.', lang)) + local uca_ducet = require("lua-uca.lua-uca-ducet") + local uca_collator = require("lua-uca.lua-uca-collator") + Sort.collator = uca_collator.new(uca_ducet) + if language ~= "en" then + local uca_languages = require("lua-uca.lua-uca-languages") + if uca_languages[language] then + Sort.collator = uca_languages[language](Sort.collator) + else + util.warning(string.format('Locale "%s" is not provided by lua-uca. The sorting order may be incorrect.', lang)) + end end end - for _, item in ipairs(items) do - if not key_map[item.id] then - key_map[item.id] = {} - - context.item = item - for i, key in ipairs(self:query_selector("key")) do - if sort_directions[i] == nil then - local direction = (key:get_attribute("sort") ~= "descending") - sort_directions[i] = direction - end - local value = key:render(item, context) - table.insert(key_map[item.id], value) + -- TODO: optimize: use cached values for fixed keys + for i, item in ipairs(items) do + key_map[item.id] = {} + + context.id = item.id + context.cite = item + context.reference = context.engine.registry.registry[item.id] + + for j, key in ipairs(self.children) do + if context.reference then + context.sort_key = key + local key_str = key:eval(context.engine, state, context) + key_map[item.id][j] = key_str + else + -- The entry is missing + key_map[item.id][j] = false end end + -- To preserve the original order of items with same sort keys + -- sort_NameImplicitSortOrderAndForm.txt + table.insert(key_map[item.id], i) end -- util.debug(key_map) @@ -66,6 +89,7 @@ function Sort:sort (items, context) local function compare_entry(item1, item2) return self.compare_entry(key_map, sort_directions, item1, item2) end + -- util.debug(items) table.sort(items, compare_entry) return items @@ -80,8 +104,8 @@ function Sort.compare(value1, value2) end function Sort.compare_strings(str1, str2) - if Sort.collator_obj then - return Sort.collator_obj:compare_strings(str1, str2) + if Sort.collator then + return Sort.collator:compare_strings(str1, str2) else return str1 < str2 end @@ -109,77 +133,98 @@ function Sort.compare_entry(key_map, sort_directions, item1, item2) end end -local Key = element.Element:new() - -function Key:render (item, context) - context = self:process_context(context) - context.options["name-as-sort-order"] = "all" - context.sorting = true - local variable = self:get_attribute("variable") - local res = nil - if variable then - context.variable = variable - local variable_type = util.variable_types[variable] +local Key = Element:derive("key") + +function Key:new() + local o = Element.new(self) + Key.sort = "ascending" + return o +end + +function Key:from_node(node) + local o = Key:new() + o:set_attribute(node, "sort") + o:set_attribute(node, "variable") + o:set_attribute(node, "macro") + o:set_number_attribute(node, "names-min") + o:set_number_attribute(node, "names-use-first") + o:set_bool_attribute(node, "names-use-last") + return o +end + +function Key:eval(engine, state, context) + local res + if self.variable then + local variable_type = util.variable_types[self.variable] if variable_type == "name" then - res = self:_render_name(item, context) + res = self:eval_name(engine, state, context) elseif variable_type == "date" then - res = self:_render_date(item, context) + res = self:eval_date(context) elseif variable_type == "number" then - res = item[variable] + local value = context:get_variable(self.variable) + if type(value) == "string" and string.match(value, "%s+") then + value = tonumber(value) + end + res = value else - res = item[variable] + res = context:get_variable(self.variable) + if type(res) == "string" then + local inlines = InlineElement:parse(res, context) + res = context.format:output(inlines) + end end - else - local macro = self:get_attribute("macro") - if macro then - res = self:get_macro(macro):render(item, context) + elseif self.macro then + local macro = context:get_macro(self.macro) + state:push_macro(self.macro) + local ir = macro:build_ir(engine, state, context) + state:pop_macro(self.macro) + if ir.name_count then + return ir.name_count + elseif ir.sort_key ~= nil then + return ir.sort_key end + local output_format = context.format + local inlines = ir:flatten(output_format) + -- util.debug(inlines) + local str = output_format:output(inlines) + return str end if res == nil then + -- make table.insert(_, nil) work res = false - elseif type(res) == "table" and res._type == "RichText" then - res = res:render(nil, context) - end - if type(res) == "string" then - res = self._normalize_string(res) end return res end -function Key:_render_name (item, context) - if not self.names then - self.names = self:create_element("names", {}, self) - names.Names:set_base_class(self.names) - self.names:set_attribute("variable", context.options["variable"]) - self.names:set_attribute("form", "long") +function Key:eval_name(engine, state, context) + if not self.name_inheritance then + self.name_inheritance = util.clone(context.name_inheritance) end - local res = self.names:render(item, context) - return res + local name = context:get_variable(self.variable) + if not name then + return false + end + local ir = self.name_inheritance:build_ir(self.variable, nil, nil, engine, state, context) + if ir.name_count then + -- name count + return ir.name_count + end + local output_format = context.format + local inlines = ir:flatten(output_format) + + local str = output_format:output(inlines) + + return str end -function Key:_render_date (item, context) +function Key:eval_date(context) if not self.date then - self.date = self:create_element("date", {}, self) - date.Date:set_base_class(self.date) - self.date:set_attribute("variable", context.options["variable"]) - self.date:set_attribute("form", "numeric") + self.date = Date:new() + self.date.variable = self.variable + self.date.form = "numeric" + self.date.date_parts = "year-month-day" end - local res = self.date:render(item, context) - return res -end -function Key._normalize_string(str) - str = unicode.utf8.lower(str) - str = string.gsub(str, "[%[%]]", "") - local words = {} - for _, word in ipairs(util.split(str, " ")) do - -- TODO: strip leading prepositions - -- remove leading apostrophe on name particle - word = string.gsub(word, "^" .. util.unicode["apostrophe"], "") - table.insert(words, word) - end - str = table.concat(words, " ") - str = string.gsub(str, util.unicode["apostrophe"], "'") - return str + return self.date:render_sort_key(context.engine, nil, context) end diff --git a/biblio/citation-style-language/citeproc-node-style.lua b/biblio/citation-style-language/citeproc-node-style.lua index 2fb10cc79c..5c387bd6c8 100644 --- a/biblio/citation-style-language/citeproc-node-style.lua +++ b/biblio/citation-style-language/citeproc-node-style.lua @@ -4,15 +4,126 @@ -- Repository: https://github.com/zepinglee/citeproc-lua -- -local style = {} +local style_module = {} -local element = require("citeproc-element") +local dom = require("luaxml-domobject") + +local Element = require("citeproc-element").Element +local IrNode = require("citeproc-ir-node").IrNode +local Rendered = require("citeproc-ir-node").Rendered +local SeqIr = require("citeproc-ir-node").SeqIr +local PlainText = require("citeproc-output").PlainText +local DisamStringFormat = require("citeproc-output").DisamStringFormat local util = require("citeproc-util") -local Style = element.Element:new() +local Style = Element:derive("style") + +function Style:new() + local o = { + children = {}, + macros = {}, + locales = {}, + initialize_with_hyphen = true, + demote_non_dropping_particle = "display-and-sort", + } + setmetatable(o, self) + self.__index = self + return o +end + +function Style:parse(xml_str) + local csl_xml = dom.parse(xml_str) + if not csl_xml then + error("Failed to parse CSL style.") + end + local style_node = csl_xml:get_path("style")[1] + if not csl_xml then + error('Element "style" not found.') + end + return Style:from_node(style_node) +end + +local function make_name_inheritance(name, node) + name:set_attribute(node, "and") + name:set_attribute(node, "delimiter-precedes-et-al") + name:set_attribute(node, "delimiter-precedes-last") + name:set_number_attribute(node, "et-al-min") + name:set_number_attribute(node, "et-al-use-first") + name:set_number_attribute(node, "et-al-subsequent-min") + name:set_number_attribute(node, "et-al-subsequent-use-first") + name:set_bool_attribute(node, "et-al-use-last") + name:set_bool_attribute(node, "initialize") + name:set_attribute(node, "initialize-with") + name:set_attribute(node, "name-as-sort-order") + name:set_attribute(node, "sort-separator") + local delimiter = node:get_attribute("name-delimiter") + if delimiter then + name.delimiter = delimiter + end + local form = node:get_attribute("name-form") + if form then + name.form = form + end + local names_delimiter = node:get_attribute("names-delimiter") + if names_delimiter then + name.names_delimiter = names_delimiter + end +end + +function Style:from_node(node) + local o = Style:new() + + o:set_attribute(node, "class") + o:set_attribute(node, "default-locale") + o:set_attribute(node, "version") + + -- Global Options + o.initialize_with_hyphen = true + o:set_bool_attribute(node, "initialize-with-hyphen") + o:set_attribute(node, "page-range-format") + o:set_attribute(node, "demote-non-dropping-particle") + + -- Inheritable Name Options + -- https://docs.citationstyles.org/en/stable/specification.html#inheritable-name-options + o.name_inheritance = require("citeproc-node-names").Name:new() + make_name_inheritance(o.name_inheritance, node) + + if o.page_range_format == "chicago" then + if o.version < "1.1" then + o.page_range_format = "chicago-15" + else + o.page_range_format = "chicago-16" + end + end + + o.macros = {} + o.locales = {} + + o.children = {} + o:process_children_nodes(node) + + for _, child in ipairs(o.children) do + local element_name = child.element_name + if element_name == "info" then + o.info = child + elseif element_name == "citation" then + o.citation = child + elseif element_name == "bibliography" then + o.bibliography = child + elseif element_name == "macro" then + o.macros[child.name] = child + elseif element_name == "locale" then + local xml_lang = child.xml_lang or "@generic" + o.locales[xml_lang] = child + end + end + + return o +end + -Style.default_options = { +Style._default_options = { ["initialize-with-hyphen"] = true, ["page-range-format"] = nil, ["demote-non-dropping-particle"] = "display-and-sort", @@ -29,171 +140,385 @@ function Style:set_lang(lang, force_lang) end end -function Style:render_citation (items, context) - self:debug_info(context) - context = self:process_context(context) - context.style = self - local citation = self:get_child("citation") - return citation:render(items, context) -end -function Style:render_biblography (items, context) - self:debug_info(context) - context = self:process_context(context) - context.style = self - local bibliography = self:get_child("bibliography") - return bibliography:render(items, context) -end +local Info = Element:derive("info") + + +function Info:from_node(node) + local o = Info:new() + + -- o.authors = nil + -- o.contributors = nil + o.categories = {} + o.id = nil + -- o.issn = nil + -- o.eissn = nil + -- o.issnl = nil + o.links = { + independent_parent = nil, + } + -- o.published = nil + -- o.rights = nil + -- o.summary = nil + o.title = nil + -- o.title_short = nil + o.updated = nil + + for _, child in ipairs(node:get_children()) do + if child:is_element() then + local element_name = child:get_element_name() + if element_name == "category" then + local citation_format = child:get_attribute("citation-format") + if citation_format then + o.categories.citation_format = citation_format + end + + elseif element_name == "id" then + o.id = child:get_text() + + elseif element_name == "link" then + local href = child:get_attribute("href") + local rel = child:get_attribute("rel") + if href and rel == "independent-parent" then + o.links.independent_parent = href + end + + elseif element_name == "title" then + o.title = child:get_text() + + elseif element_name == "updated" then + o.updated = child:get_text() + + end + end + end -function Style:get_version () - return self:get_attribute("version") + return o end -function Style:get_locales() - if not self.locale_dict then - self.locale_dict = {} - end - local locales = self.locale_dict[self.lang] - if not locales then - locales = self:get_locale_list(self.lang) - self.locale_dict[self.lang] = locales - end - return locales -end -function Style:get_locale_list (lang) - assert(lang ~= nil) - local language = string.sub(lang, 1, 2) - local primary_dialect = util.primary_dialects[language] - if not primary_dialect then - -- util.warning(string.format("Failed to find primary dialect of \"%s\"", language)) - end - local locale_list = {} +local Citation = Element:derive("citation", { + givenname_disambiguation_rule = "by-cite", + -- https://github.com/citation-style-language/schema/issues/338 + -- The cite_group_delimiter may be changed to inherit the delimiter in citaion > layout. + cite_group_delimiter = ", ", + near_note_distance = 5, +}) - -- 1. In-style cs:locale elements - -- i. `xml:lang` set to chosen dialect, “de-AT” - if lang == language then - lang = primary_dialect - end - table.insert(locale_list, self:get_in_style_locale(lang)) +function Citation:from_node(node, style) - -- ii. `xml:lang` set to matching language, “de” (German) - if language and language ~= lang then - table.insert(locale_list, self:get_in_style_locale(language)) - end + local o = Citation:new() + o.children = {} - -- iii. `xml:lang` not set - table.insert(locale_list, self:get_in_style_locale(nil)) + o:process_children_nodes(node) - -- 2. Locale files - -- iv. `xml:lang` set to chosen dialect, “de-AT” - if lang then - table.insert(locale_list, self:get_engine():get_system_locale(lang)) + -- o.layouts = nil -- CSL-M extension + + for _, child in ipairs(o.children) do + local element_name = child.element_name + if element_name == "layout" then + o.layout = child + elseif element_name == "sort" then + o.sort = child + end end - -- v. `xml:lang` set to matching primary dialect, “de-DE” (Standard German) - -- (only applicable when the chosen locale is a secondary dialect) - if primary_dialect and primary_dialect ~= lang then - table.insert(locale_list, self:get_engine():get_system_locale(primary_dialect)) + -- Disambiguation + o:set_bool_attribute(node, "disambiguate-add-givenname") + o:set_attribute(node, "givenname-disambiguation-rule") + o:set_bool_attribute(node, "disambiguate-add-names") + o:set_bool_attribute(node, "disambiguate-add-year-suffix") + + -- Cite Grouping + o:set_attribute(node, "cite-group-delimiter") + -- In the current citeproc-js implementation and test suite, + -- cite grouping is activated by setting the cite-group-delimiter + -- attribute or the collapse attributes on cs:citation. + -- It may be changed to an independent procedure. + -- https://github.com/citation-style-language/schema/issues/338 + if node:get_attribute("cite-group-delimiter") then + o.cite_grouping = true + else + o.cite_grouping = false end - -- vi. `xml:lang` set to “en-US” (American English) - if lang ~= "en-US" and primary_dialect ~= "en-US" then - table.insert(locale_list, self:get_engine():get_system_locale("en-US")) + + -- Cite Collapsing + o:set_attribute(node, "collapse") + o:set_attribute(node, "year-suffix-delimiter") + if not o.year_suffix_delimiter then + o.year_suffix_delimiter = o.layout.delimiter + end + o:set_attribute(node, "after-collapse-delimiter") + if not o.after_collapse_delimiter then + o.after_collapse_delimiter = o.layout.delimiter end - return locale_list -end + -- Note Distance + o:set_number_attribute(node, "near-note-distance") -function Style:get_in_style_locale (lang) - for _, locale in ipairs(self:query_selector("locale")) do - if locale:get_attribute("xml:lang") == lang then - return locale + local name_inheritance = require("citeproc-node-names").Name:new() + for key, value in pairs(style.name_inheritance) do + if value ~= nil then + name_inheritance[key] = value end end - return nil + make_name_inheritance(name_inheritance, node) + o.name_inheritance = name_inheritance + + -- update_mode = "plain" or "numeric" or "position" (or "both"?) + + return o end -function Style:get_term (...) - for _, locale in ipairs(self:get_locales()) do - local res = locale:get_term(...) - if res then - return res - end +function Citation:build_ir(engine, state, context) + if not self.layout then + util.error("Missing citation layout.") end - return nil + return self.layout:build_ir(engine, state, context) end -local Citation = element.Element:new() +local Bibliography = Element:derive("bibliography", { + hanging_indent = false, + line_spacing = 1, + entry_spacing = 1, + subsequent_author_substitute_rule = "complete-all" +}) + +function Bibliography:from_node(node, style) + local o = Bibliography:new() + o.children = {} -function Citation:render (items, context) - self:debug_info(context) - context = self:process_context(context) + o:process_children_nodes(node) - context.mode = "citation" - context.citation = self + -- o.layouts = nil -- CSL-M extension - local sort = self:get_child("sort") - if sort then - sort:sort(items, context) + for _, child in ipairs(o.children) do + local element_name = child.element_name + if element_name == "layout" then + o.layout = child + elseif element_name == "sort" then + o.sort = child + end end - local layout = self:get_child("layout") - return layout:render(items, context) + -- Whitespace + o:set_bool_attribute(node, "hanging-indent") + o:set_attribute(node, "second-field-align") + o:set_number_attribute(node, "line-spacing") + o:set_number_attribute(node, "entry-spacing") + + -- Reference Grouping + o:set_attribute(node, "subsequent-author-substitute") + o:set_attribute(node, "subsequent-author-substitute-rule") + + local name_inheritance = require("citeproc-node-names").Name:new() + for key, value in pairs(style.name_inheritance) do + if value ~= nil then + name_inheritance[key] = value + end + end + make_name_inheritance(name_inheritance, node) + o.name_inheritance = name_inheritance + + return o end +function Bibliography:build_ir(engine, state, context) + if not self.layout then + util.error("Missing bibliography layout.") + end + local ir = self.layout:build_ir(engine, state, context) + -- util.debug(ir) + if self.second_field_align == "flush" and #ir.children >= 2 then + ir.children[1].display = "left-margin" + local right_inline_ir = SeqIr:new(util.slice(ir.children, 2), self) + right_inline_ir.display = "right-inline" + if ir.affixes then + right_inline_ir.affixes = ir.affixes + right_inline_ir.formatting = ir.formatting + ir.affixes = nil + ir.formatting = nil + end + ir.children = {ir.children[1], right_inline_ir} + end -local Bibliography = element.Element:new() + if self.subsequent_author_substitute then + self:substitute_subsequent_authors(engine, ir) + end -Bibliography.default_options = { - ["hanging-indent"] = false, - ["second-field-align"] = nil, - ["line-spacing"] = 1, - ["entry-spacing"] = 1, - ["subsequent-author-substitute"] = nil, - ["subsequent-author-substitute-rule"] = "complete-all", -} + if not ir then + ir = Rendered:new(PlainText:new("[CSL STYLE ERROR: reference with no printed form.]"), self) + end + return ir +end -function Bibliography:render (items, context) - self:debug_info(context) - context = self:process_context(context) - -- util.debug(context) +function Bibliography:substitute_subsequent_authors(engine, ir) + ir.first_name_ir = self:find_first_name_ir(ir) -- should be a SeqIr wiht _element = "names" + if not ir.first_name_ir then + engine.previous_bib_names_ir = nil + return + end + if self.subsequent_author_substitute_rule == "complete-all" then + self:substitute_subsequent_authors_complete_all(engine, ir) + elseif self.subsequent_author_substitute_rule == "complete-each" then + self:substitute_subsequent_authors_complete_each(engine, ir) + elseif self.subsequent_author_substitute_rule == "partial-each" then + self:substitute_subsequent_authors_partial_each(engine, ir) + elseif self.subsequent_author_substitute_rule == "partial-first" then + self:substitute_subsequent_authors_partial_first(engine, ir) + end + engine.previous_bib_names_ir = ir.first_name_ir +end - context.mode = "bibliography" - context.bibliography = self +function Bibliography:find_first_name_ir(ir) + if ir._type == "NameIr" then + return ir + elseif ir.children then + for _, child_ir in ipairs(ir.children) do + local first_name_ir = self:find_first_name_ir(child_ir) + if first_name_ir then + return first_name_ir + end + end + end + return nil +end - -- Already sorted in CiteProc:sort_bibliography() +function Bibliography:substitute_subsequent_authors_complete_all(engine, ir) + local bib_names_str = "" - local layout = self:get_child("layout") - local res = layout:render(items, context) + if #ir.first_name_ir.person_name_irs > 0 then + for _, person_name_ir in ipairs(ir.first_name_ir.person_name_irs) do + if bib_names_str ~= "" then + bib_names_str = bib_names_str .. " " + end + local name_variants = person_name_ir.disam_variants + bib_names_str = bib_names_str .. name_variants[#name_variants] + end + else + -- In case of a <text variable="title"/> in <substitute> + local disam_format = DisamStringFormat:new() + local inlines = ir.first_name_ir:flatten(disam_format) + bib_names_str = disam_format:output(inlines) + end + ir.first_name_ir.bib_names_str = bib_names_str + + if engine.previous_bib_names_ir and + engine.previous_bib_names_ir.bib_names_str == bib_names_str then + local text = self.subsequent_author_substitute + if text == "" then + ir.first_name_ir.children = {} + ir.first_name_ir.group_var = "missing" + else + -- the output of label is not substituted + -- util.debug(ir.first_name_ir) + ir.first_name_ir.children = {Rendered:new({PlainText:new(text)}, self)} + end + end +end - local params = res[1] +function Bibliography:substitute_subsequent_authors_complete_each(engine, ir) + local bib_names_str = "" - params.entryspacing = context.options["entry-spacing"] - params.linespacing = context.options["line-spacing"] - params.hangingindent = context.options["hanging-indent"] - params["second-field-align"] = context.options["second-field-align"] - for _, key in ipairs({"bibstart", "bibend"}) do - local value = context.engine.formatter[key] - if type(value) == "function" then - value = value(context) + if #ir.first_name_ir.person_name_irs > 0 then + for _, person_name_ir in ipairs(ir.first_name_ir.person_name_irs) do + if bib_names_str ~= "" then + bib_names_str = bib_names_str .. " " + end + local name_variants = person_name_ir.disam_variants + bib_names_str = bib_names_str .. name_variants[#name_variants] end - params[key] = value + else + -- In case of a <text variable="title"/> in <substitute> + local disam_format = DisamStringFormat:new() + local inlines = ir.first_name_ir:flatten(disam_format) + bib_names_str = disam_format:output(inlines) end + ir.first_name_ir.bib_names_str = bib_names_str + + if engine.previous_bib_names_ir and + engine.previous_bib_names_ir.bib_names_str == bib_names_str then + local text = self.subsequent_author_substitute + if #ir.first_name_ir.person_name_irs > 0 then + for _, person_name_ir in ipairs(ir.first_name_ir.person_name_irs) do + person_name_ir.inlines = {PlainText:new(text)} + end + else + -- In case of a <text variable="title"/> in <substitute> + if text == "" then + ir.first_name_ir.children = {} + ir.first_name_ir.group_var = "missing" + else + ir.first_name_ir.children = {Rendered:new({PlainText:new(text)}, self)} + end + end + end +end - params.bibliography_errors = {} - params.entry_ids = {} - for _, item in ipairs(items) do - table.insert(params.entry_ids, item.id) +function Bibliography:substitute_subsequent_authors_partial_each(engine, ir) + local bib_names_str = "" + + if #ir.first_name_ir.person_name_irs > 0 then + if engine.previous_bib_names_ir then + for i, person_name_ir in ipairs(ir.first_name_ir.person_name_irs) do + local prev_name_ir = engine.previous_bib_names_ir.person_names[i] + if prev_name_ir then + local prev_name_variants = prev_name_ir.disam_variants + local prev_full_name_str = prev_name_variants[#prev_name_variants] + local name_variants = person_name_ir.disam_variants + local full_name_str = name_variants[#name_variants] + if prev_full_name_str == full_name_str then + local text = self.subsequent_author_substitute + person_name_ir.inlines = {PlainText:new(text)} + else + break + end + end + end + end + else + -- In case of a <text variable="title"/> in <substitute> + local disam_format = DisamStringFormat:new() + local inlines = ir.first_name_ir:flatten(disam_format) + bib_names_str = disam_format:output(inlines) + ir.first_name_ir.bib_names_str = bib_names_str + if engine.previous_bib_names_ir and + engine.previous_bib_names_ir.bib_names_str == bib_names_str then + local text = self.subsequent_author_substitute + if text == "" then + ir.first_name_ir.children = {} + ir.first_name_ir.group_var = "missing" + else + ir.first_name_ir.children = {Rendered:new({PlainText:new(text)}, self)} + end + end end +end + +function Bibliography:substitute_subsequent_authors_partial_first(engine, ir) +end + +local Macro = Element:derive("macro") - return res +function Macro:from_node(node) + local o = Macro:new() + o.children = {} + o:set_attribute(node, "name") + o:process_children_nodes(node) + return o end -style.Style = Style -style.Citation = Citation -style.Bibliography = Bibliography +function Macro:build_ir(engine, state, context) + local ir = self:build_group_ir(engine, state, context) + return ir +end + + +style_module.Style = Style +style_module.Citation = Citation +style_module.Bibliography = Bibliography -return style +return style_module diff --git a/biblio/citation-style-language/citeproc-node-text.lua b/biblio/citation-style-language/citeproc-node-text.lua index e26a480438..fae3535013 100644 --- a/biblio/citation-style-language/citeproc-node-text.lua +++ b/biblio/citation-style-language/citeproc-node-text.lua @@ -4,224 +4,196 @@ -- Repository: https://github.com/zepinglee/citeproc-lua -- -local text = {} +local text_module = {} -local element = require("citeproc-element") -local richtext = require("citeproc-richtext") +local Element = require("citeproc-element").Element +local Rendered = require("citeproc-ir-node").Rendered +local YearSuffix = require("citeproc-ir-node").YearSuffix +local PlainText = require("citeproc-output").PlainText +local Linked = require("citeproc-output").Linked local util = require("citeproc-util") -local Text = element.Element:new() - -function Text:render (item, context) - self:debug_info(context) - context = self:process_context(context) +-- [Text](https://docs.citationstyles.org/en/stable/specification.html#text) +local Text = Element:derive("text", { + -- Default attributes + variable = nil, + form = "long", + macro = nil, + term = nil, + plural = false, + value = nil, + -- Style behavior + formatting = nil, + affixes = nil, + delimiter = nil, + display = nil, + quotes = false, + strip_periods = false, + text_case = nil, +}) + +function Text:from_node(node) + local o = Text:new() + o:set_attribute(node, "variable") + o:set_attribute(node, "form") + o:set_attribute(node, "macro") + o:set_attribute(node, "term") + o:set_bool_attribute(node, "plural") + o:set_attribute(node, "value") + + o:set_formatting_attributes(node) + o:set_affixes_attributes(node) + o:set_display_attribute(node) + o:set_quotes_attribute(node) + o:set_strip_periods_attribute(node) + o:set_text_case_attribute(node) + return o +end - local res = nil +function Text:build_ir(engine, state, context) + local ir = nil + if self.variable then + ir = self:build_variable_ir(engine, state, context) + elseif self.macro then + ir = self:build_macro_ir(engine, state, context) + elseif self.term then + ir = self:build_term_ir(engine, state, context) + elseif self.value then + ir = self:build_value_ir(engine, state, context) + end + return ir +end - local variable = nil - local variable_name = self:get_attribute("variable") - if variable_name then - local form = self:get_attribute("form") - if form == "short" then - variable = self:get_variable(item, variable_name .. "-" .. form, context) - end - if not variable then - variable = self:get_variable(item, variable_name, context) - end - if variable then - res = variable - if type(res) == "number" then - res = tostring(res) - end - if variable_name == "page" or variable_name == "locator" then - res = util.lstrip(res) - res = self:_format_page(res, context) - end - end +function Text:build_variable_ir(engine, state, context) + local variable = self.variable + local text - table.insert(context.variable_attempt, res ~= nil) + if variable == "year-suffix" then + return self:build_year_suffix_ir(engine, state, context) end - local macro_name = self:get_attribute("macro") - if macro_name then - local macro = self:get_macro(macro_name) - res = macro:render(item, context) + if not state.suppressed[variable] then + text = context:get_variable(variable, self.form) end - local term_name = self:get_attribute("term") - if term_name then - local form = self:get_attribute("form") - - local term = self:get_term(term_name, form) - if term then - res = term:render(context) - end + if not text then + local ir = Rendered:new({}, self) + ir.group_var = "missing" + return ir end - - local value = self:get_attribute("value") - if value then - res = value - res = self:escape(res) + if type(text) == "number" then + text = tostring(text) end - - if type(res) == "string" and res ~= "" then - res = richtext.new(res) + if util.variable_types[variable] == "number" then + text = self:format_number(text, variable, "numeric", context) end - if res and variable_name == "URL" then - res:add_format("URL", "true") + local inlines + if (variable == "URL" and engine.opt.url_link) or + (variable == "DOI" and engine.opt.doi_link) or + (variable == "PMID" and engine.opt.doi_link) or + (variable == "PMID" and engine.opt.doi_link) then + inlines = self:render_linked(engine, state, context, variable, text) + else + inlines = self:render_text_inlines(text, context) end - res = self:strip_periods(res, context) - res = self:case(res, context) - res = self:format(res, context) - res = self:quote(res, context) - res = self:wrap(res, context) - res = self:display(res, context) + local ir = Rendered:new(inlines, self) + ir.group_var = "important" - if variable_name == "citation-number" then - res = self:_process_citation_number(variable, res, context) + if variable == "citation-number" then + ir.citation_number = context.reference["citation-number"] end - return res -end - - -function Text:_process_citation_number(citation_number, res, context) - if context.mode == "citation" and not context.sorting and context.options["collapse"] == "citation-number" then - context.build.item_citation_numbers[context.item.id] = citation_number - if type(res) == "string" then - res = richtext.new(res) - end - table.insert(context.build.item_citation_number_text, res) + -- Suppress substituted name variable + if state.name_override and not context.sort_key then + state.suppressed[variable] = true end - return res -end - -function Text:_format_page (page, context) - local res = nil - - local page_range_delimiter = self:get_term("page-range-delimiter"):render(context) or util.unicode["en dash"] - local page_range_format = context.options["page-range-format"] - if page_range_format == "chicago" then - if self:get_style():get_version() >= "1.1" then - page_range_format = "chicago-16" - else - page_range_format = "chicago-15" - end - end + return ir +end - local last_position = 1 - local page_parts = {} - local punct_list = {} - for part, punct, pos in string.gmatch(page, "(.-)%s*([,&])%s*()") do - table.insert(page_parts, part) - table.insert(punct_list, punct) - last_position = pos - end - table.insert(page_parts, string.sub(page, last_position)) - - res = "" - for i, part in ipairs(page_parts) do - res = res .. self:_format_range(part, page_range_format, page_range_delimiter) - local punct = punct_list[i] - if punct then - if punct == "&" then - res = res .. " " .. punct .. " " - else - res = res .. punct .. " " - end +function Text:render_linked(engine, state, context, variable, text) + local href + if variable == "URL" then + href = text + elseif self.affixes and self.affixes.prefix then + if string.match(self.affixes.prefix, "https?://") then + text = self.affixes.prefix .. text + self.affixes.prefix = nil + href = text end - end - res = self:escape(res) - return res + elseif variable == "DOI" then + href = "https://doi.org/" .. text + elseif variable == "PMID" then + href = "https://www.ncbi.nlm.nih.gov/pubmed/" .. text + elseif variable == "PMCID" then + href = "https://www.ncbi.nlm.nih.gov/pmc/articles/" .. text + end + local inlines = {Linked:new(text, href)} + local output_format = context.format + local localized_quotes = nil + if self.quotes then + localized_quotes = context:get_localized_quotes() + end + inlines = output_format:with_format(inlines, self.formatting) + inlines = output_format:affixed_quoted(inlines, self.affixes, localized_quotes) + return output_format:with_display(inlines, self.display) end -function Text:_format_range (str, format, range_delimiter) - local start, delimiter, stop = string.match(str, "(%w+)%s*(%-+)%s*(%S*)") - if not stop or stop == "" then - return string.gsub(str, "\\%-", "-") - end - - - local start_prefix, start_num = string.match(start, "(.-)(%d*)$") - local stop_prefix, stop_num = string.match(stop, "(.-)(%d*)$") - - if start_prefix ~= stop_prefix then - -- Not valid range: "n11564-1568" -> "n11564-1568" - -- 110-N6 - -- N110-P5 - return start .. delimiter .. stop - end - - if format == "chicago-16" then - stop = self:_format_range_chicago_16(start_num, stop_num) - elseif format == "chicago-15" then - stop = self:_format_range_chicago_15(start_num, stop_num) - elseif format == "expanded" then - stop = stop_prefix .. self:_format_range_expanded(start_num, stop_num) - elseif format == "minimal" then - stop = self:_format_range_minimal(start_num, stop_num) - elseif format == "minimal-two" then - stop = self:_format_range_minimal(start_num, stop_num, 2) +function Text:build_year_suffix_ir(engine, state, context) + local text = context:get_variable(self.variable, self.form) + local group_var + if text then + group_var = "important" + else + text = "" + group_var = "missing" end - return start .. range_delimiter .. stop -end - -function Text:_format_range_chicago_16(start, stop) - if #start < 3 or string.sub(start, -2) == "00" then - return self:_format_range_expanded(start, stop) - elseif string.sub(start, -2, -2) == "0" then - return self:_format_range_minimal(start, stop) - else - return self:_format_range_minimal(start, stop, 2) + local ir = YearSuffix:new({PlainText:new(text)}, self) + ir.group_var = group_var + ir.affixes = util.clone(self.affixes) + ir.display = self.display + ir.formatting = util.clone(self.formatting) + if self.quotes then + ir.quotes = context:get_localized_quotes() end - return stop + return ir end -function Text:_format_range_chicago_15(start, stop) - if #start < 3 or string.sub(start, -2) == "00" then - return self:_format_range_expanded(start, stop) - else - local changed_digits = self:_format_range_minimal(start, stop) - if string.sub(start, -2, -2) == "0" then - return changed_digits - elseif #start == 4 and #changed_digits == 3 then - return self:_format_range_expanded(start, stop) - else - return self:_format_range_minimal(start, stop, 2) +function Text:build_macro_ir(engine, state, context) + local macro = context:get_macro(self.macro) + state:push_macro(self.macro) + local ir = macro:build_ir(engine, state, context) + state:pop_macro(self.macro) + if ir then + ir.affixes = util.clone(self.affixes) + ir.display = self.display + ir.formatting = util.clone(self.formatting) + if self.quotes then + ir.quotes = context:get_localized_quotes() end end - return stop + return ir end -function Text:_format_range_expanded(start, stop) - -- Expand "1234–56" -> "1234–1256" - if #start <= #stop then - return stop +function Text:build_term_ir(engine, state, context) + local str = context:get_simple_term(self.term, self.form, self.plural) + if not str then + return nil end - return string.sub(start, 1, #start - #stop) .. stop + local inlines = self:render_text_inlines(str, context) + return Rendered:new(inlines, self) end -function Text:_format_range_minimal(start, stop, threshold) - threshold = threshold or 1 - if #start < #stop then - return stop - end - local offset = #start - #stop - for i = 1, #stop - threshold do - local j = i + offset - if string.sub(stop, i, i) ~= string.sub(start, j, j) then - return string.sub(stop, i) - end - end - return string.sub(stop, -threshold) +function Text:build_value_ir(engine, state, context) + local inlines = self:render_text_inlines(self.value, context) + return Rendered:new(inlines, self) end -text.Text = Text +text_module.Text = Text -return text +return text_module diff --git a/biblio/citation-style-language/citeproc-output.lua b/biblio/citation-style-language/citeproc-output.lua new file mode 100644 index 0000000000..6aca4533da --- /dev/null +++ b/biblio/citation-style-language/citeproc-output.lua @@ -0,0 +1,1534 @@ +-- +-- Copyright (c) 2021-2022 Zeping Lee +-- Released under the MIT license. +-- Repository: https://github.com/zepinglee/citeproc-lua +-- + +local output_module = {} + +local unicode = require("unicode") +local dom = require("luaxml-domobject") + +local util = require("citeproc-util") + + +local LocalizedQuotes = { + outer_open = util.unicode['left double quotation mark'], + outer_close = util.unicode['right double quotation mark'], + inner_open = util.unicode['left single quotation mark'], + inner_close = util.unicode['right single quotation mark'], + punctuation_in_quote = false, +} + +function LocalizedQuotes:new(outer_open, outer_close, inner_open, inner_close, punctuation_in_quote) + local o = { + outer_open = outer_open or util.unicode['left double quotation mark'], + outer_close = outer_close or util.unicode['right double quotation mark'], + inner_open = inner_open or util.unicode['left single quotation mark'], + inner_close = inner_close or util.unicode['right single quotation mark'], + punctuation_in_quote = punctuation_in_quote, + } + setmetatable(o, self) + self.__index = self + return o +end + + +local InlineElement = { + _type = "InlineElement", + _base_class = "InlineElement", +} + +function InlineElement:derive(type) + local o = { + _type = type, + } + self[type] = o + setmetatable(o, self) + self.__index = self + o.__index = o + return o +end + +function InlineElement:new(inlines) + local o = { + inlines = inlines, + _type = self._type, + } + setmetatable(o, self) + return o +end + + +local PlainText = InlineElement:derive("PlainText") + +function PlainText:new(value) + local o = InlineElement.new(self) + o.value = value + setmetatable(o, self) + return o +end + + +local Formatted = InlineElement:derive("Formatted") + +function Formatted:new(inlines, formatting) + local o = InlineElement.new(self) + o.inlines = inlines + o.formatting = formatting + setmetatable(o, self) + return o +end + + +local Micro = InlineElement:derive("Micro") + +-- This is how we can flip-flop only user-supplied styling. +-- Inside this is parsed micro html +function Micro:new(inlines) + local o = InlineElement.new(self) + o.inlines = inlines + setmetatable(o, self) + return o +end + + +local Quoted = InlineElement:derive("Quoted") + +function Quoted:new(inlines, localized_quotes) + local o = InlineElement.new(self) + o.inlines = inlines + o.is_inner = false + if localized_quotes then + o.quotes = localized_quotes + else + o.quotes = LocalizedQuotes:new() + end + + setmetatable(o, self) + return o +end + + +local NoCase = InlineElement:derive("NoCase") + +function NoCase:new(inlines) + local o = InlineElement.new(self) + o.inlines = inlines + setmetatable(o, self) + return o +end + + +local NoDecor = InlineElement:derive("NoDecor") + +function NoDecor:new(inlines) + local o = InlineElement.new(self) + o.inlines = inlines + setmetatable(o, self) + return o +end + + +local Linked = InlineElement:derive("Linked") + +function Linked:new(value, href) + local o = InlineElement.new(self) + o.value = value + o.href = href + setmetatable(o, self) + return o +end + + +local Div = InlineElement:derive("Div") + +function Div:new(inlines, display) + local o = InlineElement.new(self) + o.inlines = inlines + o.div = display + setmetatable(o, self) + return o +end + + +function InlineElement:parse(str, context) + -- Return a list of inlines + if type(str) ~= "string" then + print(debug.traceback()) + end + local html_str = "<div>" .. str .. "</div>" + local ok, html = pcall(dom.parse, html_str) + local inlines + if ok then + local div = html:get_path("div")[1] + local el = InlineElement:from_node(div) + inlines = el.inlines + else + local el = PlainText:new(str) + inlines = {el} + end + + inlines = InlineElement:parse_quotes(inlines, context) + return inlines +end + +function InlineElement:from_node(node) + local tag_name = node:get_element_name() + local inlines = {} + + for _, child in ipairs(node:get_children()) do + local inline + if child:is_text() then + inline = PlainText:new(child:get_text()) + elseif child:is_element() then + inline = InlineElement:from_node(child) + end + table.insert(inlines, inline) + end + + if tag_name == "i" then + return Formatted:new(inlines, {["font-style"] = "italic"}) + elseif tag_name == "b" then + return Formatted:new(inlines, {["font-weight"] = "bold"}) + elseif tag_name == "sup" then + return Formatted:new(inlines, {["vertical-align"] = "sup"}) + elseif tag_name == "sub" then + return Formatted:new(inlines, {["vertical-align"] = "sub"}) + elseif tag_name == "sc" then + return Formatted:new(inlines, {["font-variant"] = "small-caps"}) + elseif tag_name == "span" then + local style = node:get_attribute("style") + local class = node:get_attribute("class") + if style == "font-variant:small-caps;" or style == "font-variant: small-caps;" then + return Formatted:new(inlines, {["font-variant"] = "small-caps"}) + elseif class == "nocase" then + return NoCase:new(inlines) + elseif class == "nodecor" then + return NoDecor:new(inlines) + end + end + + return InlineElement:new(inlines) +end + +function InlineElement:parse_quotes(inlines, context) + local quote_fragments = InlineElement:get_quote_fragments(inlines) + -- util.debug(quote_fragments) + + local quote_stack = {} + local text_stack = {{}} + + local localized_quotes = context:get_localized_quotes() + + for _, fragment in ipairs(quote_fragments) do + local top_text_list = text_stack[#text_stack] + + if type(fragment) == "table" then + if fragment.inlines then + fragment.inlines = self:parse_quotes(fragment.inlines, context) + end + table.insert(top_text_list, fragment) + + elseif type(fragment) == "string" then + local quote = fragment + local top_quote = quote_stack[#quote_stack] + + if quote == "'" then + if top_quote == "'" and #top_text_list > 0 then + table.remove(quote_stack) + local quoted = Quoted:new(top_text_list, localized_quotes) + table.remove(text_stack) + table.insert(text_stack[#text_stack], quoted) + else + table.insert(quote_stack, quote) + table.insert(text_stack, {}) + end + + elseif quote == '"' then + if top_quote == '"' then + table.remove(quote_stack) + local quoted = Quoted:new(top_text_list, localized_quotes) + table.remove(text_stack) + table.insert(text_stack[#text_stack], quoted) + else + table.insert(quote_stack, quote) + table.insert(text_stack, {}) + end + + elseif quote == util.unicode["left single quotation mark"] or + quote == util.unicode["left double quotation mark"] or + quote == util.unicode["left-pointing double angle quotation mark"] then + table.insert(quote_stack, quote) + table.insert(text_stack, {}) + + elseif (quote == util.unicode["right single quotation mark"] and + top_quote == util.unicode["left single quotation mark"]) or + (quote == util.unicode["right double quotation mark"] and + top_quote == util.unicode["left double quotation mark"]) or + (quote == util.unicode["right-pointing double angle quotation mark"] and + top_quote == util.unicode["left-pointing double angle quotation mark"]) then + table.remove(quote_stack) + local quoted = Quoted:new(top_text_list, localized_quotes) + table.remove(text_stack) + table.insert(text_stack[#text_stack], quoted) + + else + local last_inline = top_text_list[#top_text_list] + if last_inline and last_inline._type == "PlainText" then + last_inline.value = last_inline.value .. fragment + else + table.insert(top_text_list, PlainText:new(fragment)) + end + end + + end + end + + local elements = text_stack[1] + if #text_stack > 1 then + assert(#text_stack == #quote_stack + 1) + for i, quote in ipairs(quote_stack) do + if quote == "'" then + quote = util.unicode["apostrophe"] + end + local last_inline = elements[#elements] + if last_inline and last_inline._type == "PlainText" then + last_inline.value = last_inline.value .. quote + else + table.insert(elements, PlainText:new(quote)) + end + + for _, inline in ipairs(text_stack[i + 1]) do + if inline._type == "PlainText" then + local last_inline = elements[#elements] + if last_inline and last_inline._type == "PlainText" then + last_inline.value = last_inline.value .. inline.value + else + table.insert(elements, inline) + end + else + table.insert(elements, inline) + end + end + end + end + + return elements +end + +local function merge_fragments_at(fragments, i) + if type(fragments[i+1]) == "string" then + fragments[i] = fragments[i] .. fragments[i+1] + table.remove(fragments, i+1) + end + if type(fragments[i-1]) == "string" then + fragments[i-1] = fragments[i-1] .. fragments[i] + table.remove(fragments, i) + end +end + +-- Return a list of strings and InlineElement +function InlineElement:get_quote_fragments(inlines) + local fragments = {} + for _, inline in ipairs(inlines) do + if inline._type == "PlainText" then + local quote_tuples = {} + for _, quote in ipairs({ + "'", + '"', + util.unicode["left single quotation mark"], + util.unicode["right single quotation mark"], + util.unicode["left double quotation mark"], + util.unicode["right double quotation mark"], + util.unicode["left-pointing double angle quotation mark"], + util.unicode["right-pointing double angle quotation mark"], + }) do + string.gsub(inline.value, "()(" .. quote .. ")()", function (idx, qt, next_idx) + table.insert(quote_tuples, {idx, qt, next_idx}) + end) + end + table.sort(quote_tuples, function (a, b) + return a[1] < b[1] + end) + local start_idx = 1 + for _, quote_tuple in ipairs(quote_tuples) do + local idx, qt, next_idx = table.unpack(quote_tuple) + local fragment = string.sub(inline.value, start_idx, idx-1) + if fragment ~= "" then + table.insert(fragments, fragment) + end + table.insert(fragments, qt) + start_idx = next_idx + end + -- Insert last fragment + local fragment = string.sub(inline.value, start_idx, #inline.value) + if fragment ~= "" then + table.insert(fragments, fragment) + end + else + table.insert(fragments, inline) + end + + for i = #fragments, 1, -1 do + local fragment = fragments[i] + if fragment == "'" or fragment == '"' then + local left, right + if i > 1 then + left = fragments[i - 1] + if type(left) == "table" then + left = left:get_right_most_string() + end + end + if i < #fragments then + right = fragments[i + 1] + if type(right) == "table" then + right = right:get_left_most_string() + end + end + -- TODO: consider utf-8 + if left and right then + if string.match(left, "%s$") and string.match(right, "^%s") then + -- Orphan quote: bugreports_SingleQuote.txt + if fragment == "'" then + fragments[i] = util.unicode['apostrophe'] + end + merge_fragments_at(fragments, i) + end + if not string.match(left, "[%s%p]$") and not string.match(right, "^[%s%p]") then + if fragment == "'" then + fragments[i] = util.unicode['apostrophe'] + end + merge_fragments_at(fragments, i) + end + end + end + end + end + return fragments +end + +function InlineElement:get_left_most_string() + if self.value then + return self.value + elseif self.inlines then + return self.inlines[1]:get_left_most_string() + end +end + +function InlineElement:get_right_most_string() + if self.value then + return self.value + elseif self.inlines then + return self.inlines[#self.inlines]:get_left_most_string() + end +end + +function InlineElement:capitalize_first_term() + -- util.debug(self) + if self._type == "PlainText" then + self.value = util.capitalize(self.value) + elseif self.inlines[1] then + self.inlines[1]:capitalize_first_term() + end +end + + +local OutputFormat = {} + +function OutputFormat:new(format_name) + local o = { + name = format_name, + } + setmetatable(o, self) + self.__index = self + return o +end + +function OutputFormat:flatten_ir(ir) + if self.group_var == "missing" or self.collapse_suppressed then + return {} + end + local inlines = {} + if ir._type == "SeqIr" or ir._type == "NameIr" then + inlines = self:flatten_seq_ir(ir) + else + inlines = self:with_format(ir.inlines, ir.formatting) + inlines = self:affixed_quoted(inlines, ir.affixes, ir.quotes); + inlines = self:with_display(inlines, ir.display); + end + return inlines +end + +function OutputFormat:flatten_seq_ir(ir) + if not ir.children then + print(debug.traceback()) + end + if #ir.children == 0 then + return {} + end + local inlines_list = {} + for _, child in ipairs(ir.children) do + if child.group_var ~= "missing" and not child.collapse_suppressed then + local child_inlines = self:flatten_ir(child) + if #child_inlines > 0 then + table.insert(inlines_list, child_inlines) + end + end + end + + if #inlines_list == 0 then + return {} + end + + local inlines = self:group(inlines_list, ir.delimiter, ir.formatting) + -- assert ir.quotes == localized quotes + inlines = self:affixed_quoted(inlines, ir.affixes, ir.quotes); + inlines = self:with_display(inlines, ir.display); + return inlines +end + +function OutputFormat:group(inlines_list, delimiter, formatting) + -- Each node is list of InlineElements + if #inlines_list == 1 then + return self:format_list(inlines_list[1], formatting) + else + local inlines = OutputFormat:join_many(inlines_list, delimiter) + return self:format_list(inlines, formatting) + end +end + +function OutputFormat:format_list(inlines, formatting) + if formatting then + return {Formatted:new(inlines, formatting)} + else + return inlines + end +end + +function OutputFormat:join_many(lists, delimiter) + local res = {} + for i, list in ipairs(lists) do + if delimiter and i > 1 then + table.insert(res, PlainText:new(delimiter)) + end + for _, el in ipairs(list) do + table.insert(res, el) + end + end + return res +end + +function OutputFormat:with_format(inlines, formatting) + return self:format_list(inlines, formatting) +end + +function OutputFormat:apply_text_case(inlines, text_case, is_english) + if not inlines or #inlines == 0 or not text_case then + return + end + -- Title case conversion only affects English-language items. + if text_case == "title" and not is_english then + return + end + local is_uppercase = false -- TODO + self:apply_text_case_inner(inlines, text_case, false, is_uppercase) +end + +local function string_contains_word(str) + return string.match(str, "%w") ~= nil +end + +local function inline_contains_word(inline) + if inline._type == "PlainText" then + return string_contains_word(inline.value) + elseif inline.inlines then + for _, el in ipairs(inline.inlines) do + if inline_contains_word(el) then + return true + end + end + end + return false +end + +function OutputFormat:apply_text_case_inner(inlines, text_case, seen_one, is_uppercase) + for i, inline in ipairs(inlines) do + if seen_one and text_case == "capitalize-first" then + break + end + local is_last = (i == #inlines) + if inline._type == "PlainText" then + inline.value = self:transform_case(inline.value, text_case, seen_one, is_last, is_uppercase); + seen_one = seen_one or string_contains_word(inline.value) + elseif inline._type == "NoCase" or + inline._type == "NoDecor" or + (inline._type == "Formatted" and inline.formatting["font-variant"] == "small-caps") or + (inline._type == "Formatted" and inline.formatting["vertical-align"] == "sup") or + (inline._type == "Formatted" and inline.formatting["vertical-align"] == "sub") then + seen_one = seen_one or inline_contains_word(inline) + + elseif inline._type == "Formatted" or inline._type == "Quoted" then + seen_one = self:apply_text_case_inner(inline.inlines, text_case, seen_one, is_uppercase) or seen_one + end + end + return seen_one +end + +local function transform_lowercase(str) + return string.gsub(str, utf8.charpattern, unicode.utf8.lower) +end + +local function transform_uppercase(str) + -- TODO: locale specific uppercase: textcase_LocaleUnicode.txt + return string.gsub(str, utf8.charpattern, unicode.utf8.upper) +end + +local function transform_first_word(str, transform) + -- TODO: [Unicode word boundaries](https://www.unicode.org/reports/tr29/#Word_Boundaries) + local segments = util.segment_words(str) + for _, segment in ipairs(segments) do + if segment[1] ~= "" then + segment[1] = transform(segment[1]) + break + end + end + local res = "" + for _, segment in ipairs(segments) do + res = res .. segment[1] .. segment[2] + end + return res +end + +local function transform_each_word(str, seen_one, is_last, transform) + -- util.debug(str) + local segments = util.segment_words(str) + -- util.debug(segments) + -- print(debug.traceback()) + + local first_idx + local last_idx + for i, segment in ipairs(segments) do + if segment[1] ~= "" then + if not first_idx then + first_idx = i + end + last_idx = i + end + end + + local immediate_before = "" + local last_punct = "" + for i, segment in ipairs(segments) do + local is_first_word = not seen_one and i == first_idx + local is_last_word = is_last and i == last_idx + local follows_colon = ( + last_punct == ":" or + last_punct == "!" or + last_punct == "?" or + last_punct == "?") + local no_stop_word = is_first_word or is_last_word or follows_colon or (segment[2] == "-" and immediate_before ~= "-") + + if (immediate_before == "." or immediate_before == "-") and #segment[1] == 1 then + else + segment[1] = transform(segment[1], no_stop_word) + end + + if segment[1] ~= "" then + immediate_before = segment[1] + last_punct = string.match(segment[1], "(%S)%s*$") or last_punct + end + if segment[2] ~= "" then + immediate_before = segment[2] + last_punct = string.match(segment[2], "(%S)%s*$") or last_punct + end + end + local res = "" + for _, segment in ipairs(segments) do + res = res .. segment[1] .. segment[2] + end + return res +end + +local function transform_capitalize_word_if_lower(word) + if util.is_lower(word) then + return string.gsub(word, utf8.charpattern, unicode.utf8.upper, 1) + else + return word + end +end + +local function title_case_word(word, no_stop_word) + -- Entirely non-English + -- e.g. "β" in "β-Carotine" + if string.match(word, "%a") and (not util.stop_words[word] or no_stop_word) and util.is_lower(word) then + return string.gsub(word, utf8.charpattern, unicode.utf8.upper, 1) + else + return word + end +end + +function OutputFormat:transform_case(str, text_case, seen_one, is_last, is_uppercase) + local res = str + if text_case == "lowercase" then + res = transform_lowercase(str) + elseif text_case == "uppercase" then + res = transform_uppercase(str) + elseif text_case == "capitalize-first" then + res = transform_first_word(str, transform_capitalize_word_if_lower) + elseif text_case == "capitalize-all" then + res = transform_each_word(str, false, false, transform_capitalize_word_if_lower) + elseif text_case == "sentence" then + -- TODO: if uppercase convert all to lowercase + res = transform_first_word(str, transform_capitalize_word_if_lower) + elseif text_case == "title" then + -- TODO: if uppercase convert all to lowercase + res = transform_each_word(str, seen_one, is_last, title_case_word) + end + return res +end + +function OutputFormat:affixed(inlines, affixes) + if affixes and affixes.prefix then + table.insert(inlines, 1, PlainText:new(affixes.prefix)) + end + if affixes and affixes.suffix then + table.insert(inlines, PlainText:new(affixes.suffix)) + end + return inlines +end + +function OutputFormat:affixed_quoted(inlines, affixes, localized_quotes) + inlines = util.clone(inlines) + if localized_quotes then + inlines = self:quoted(inlines, localized_quotes) + end + if affixes and affixes.prefix then + table.insert(inlines, 1, PlainText:new(affixes.prefix)) + end + if affixes and affixes.suffix then + table.insert(inlines, PlainText:new(affixes.suffix)) + end + return inlines +end + +function OutputFormat:quoted(inlines, localized_quotes) + return {Quoted:new(inlines, localized_quotes)} +end + +function OutputFormat:with_display(nodes, display) + if display then + return {Div:new(nodes, display)} + else + return nodes + end +end + +function OutputFormat:output(inlines, context) + self:flip_flop_inlines(inlines) + + self:move_punctuation(inlines) + + -- util.debug(inlines) + + return self:write_inlines(inlines, context) +end + +function OutputFormat:output_bibliography_entry(inlines, context) + self:flip_flop_inlines(inlines) + -- util.debug(inlines) + self:move_punctuation(inlines) + -- TODO: + -- if self.format == "html" then + -- elseif self.format == "latex" then + -- end + local res = self:write_inlines(inlines, context) + local markup = self.markups["@bibliography/entry"] + if type(markup) == "string" then + res = string.format(markup, res) + elseif type(markup) == "function" then + res = markup(res, context) + end + return res +end + +function OutputFormat:flip_flop_inlines(inlines) + local flip_flop_state = { + ["font-style"] = "normal", + ["font-variant"] = "normal", + ["font-weight"] = "normal", + ["text-decoration"] = "none", + ["vertical-alignment"] = "baseline", + in_inner_quotes = false, + } + self:flip_flop(inlines, flip_flop_state) +end + +function OutputFormat:flip_flop(inlines, state) + for i, inline in ipairs(inlines) do + if inline._type == "Micro" then + self:flip_flop_micro_inlines(inline.inlines, state) + + elseif inline._type == "Formatted" then + local new_state = util.clone(state) + local formatting = inline.formatting + + for _, attribute in ipairs({"font-style", "font-variant", "font-weight"}) do + local value = formatting[attribute] + if value then + if value == state[attribute] then + if value == "normal" then + formatting[attribute] = nil + -- Formatting outside Micro is not reset to "normal". + -- else + -- formatting[attribute] = "normal" + end + end + new_state[attribute] = value + end + end + self:flip_flop(inline.inlines, new_state) + + elseif inline._type == "Quoted" then + inline.is_inner = state.in_inner_quotes + local new_state = util.clone(state) + new_state.in_inner_quotes = not new_state.in_inner_quotes + self:flip_flop(inline.inlines, new_state) + + elseif inline._type == "NoDecor" then + local new_state = { + ["font-style"] = "normal", + ["font-variant"] = "normal", + ["font-weight"] = "normal", + ["text-decoration"] = "none", + } + self:flip_flop(inline.inlines, new_state) + for attr, value in pairs(new_state) do + if value and state[attr] ~= value then + if not inline.formatting then + inline._type = "Formatted" + inline.formatting = {} + end + inline.formatting[attr] = value + end + end + + elseif inline.inlines then -- Div, ... + self:flip_flop(inline.inlines, state) + end + end +end + +function OutputFormat:flip_flop_micro_inlines(inlines, state) + for i, inline in ipairs(inlines) do + if inline._type == "Micro" then + self:flip_flop_micro_inlines(inline.inlines, state) + + elseif inline._type == "Formatted" then + local new_state = util.clone(state) + local formatting = inline.formatting + + for _, attribute in ipairs({"font-style", "font-variant", "font-weight"}) do + local value = formatting[attribute] + if value then + if value == state[attribute] then + if value == "normal" then + formatting[attribute] = nil + else + -- Formatting inside Micro is reset to "normal". + formatting[attribute] = "normal" + value = "normal" + end + end + new_state[attribute] = value + end + end + self:flip_flop_micro_inlines(inline.inlines, new_state) + + elseif inline._type == "Quoted" then + inline.is_inner = state.in_inner_quotes + local new_state = util.clone(state) + new_state.in_inner_quotes = not new_state.in_inner_quotes + self:flip_flop_micro_inlines(inline.inlines, new_state) + + elseif inline._type == "NoDecor" then + local new_state = { + ["font-style"] = "normal", + ["font-variant"] = "normal", + ["font-weight"] = "normal", + ["text-decoration"] = "none", + } + self:flip_flop_micro_inlines(inline.inlines, new_state) + for attr, value in pairs(new_state) do + if value and state[attr] ~= value then + if not inline.formatting then + inline._type = "Formatted" + inline.formatting = {} + end + inline.formatting[attr] = value + end + end + + elseif inline.inlines then -- Div, ... + self:flip_flop_micro_inlines(inline.inlines, state) + end + end +end + +local function find_left(inline) + if not inline then + print(debug.traceback()) + end + if inline._type == "PlainText" then + return inline + -- elseif inline._type == "Micro" then + -- return nil + elseif inline.inlines and inline._type~="Quoted" then + return find_left(inline.inlines[1]) + else + return nil + end +end + +local function find_right(inline) + if inline._type == "PlainText" then + return inline + -- elseif inline._type == "Micro" then + -- return nil + elseif inline.inlines and #inline.inlines > 0 and inline._type ~= "Quoted" then + return find_right(inline.inlines[#inline.inlines]) + else + return nil + end +end + +local function find_right_in_quoted(inline) + if inline._type == "PlainText" then + return inline + -- elseif inline._type == "Micro" then + -- return nil + elseif inline.inlines and #inline.inlines > 0 then + return find_right_in_quoted(inline.inlines[#inline.inlines]) + else + return nil + end +end + +-- "'Foo,' bar" => , +local function find_right_quoted(inline) + if inline._type == "Quoted" and #inline.inlines > 0 then + return find_right_in_quoted(inline.inlines[#inline.inlines]), inline.quotes.punctuation_in_quote + -- elseif inline._type == "Micro" then + -- return nil + elseif inline.inlines and #inline.inlines > 0 then + return find_right_quoted(inline.inlines[#inline.inlines]) + else + return nil, false + end +end + +local function smash_string_push(first, second) + local first_char = string.sub(first.value, -1) + local second_char = string.sub(second.value, 1, 1) + -- util.debug(first_char) + -- util.debug(second_char) + + local punct_map = output_module.quote_punctuation_map + if second_char == " " and (first_char == " " or + util.endswith(first.value, util.unicode["no-break space"])) then + second.value = string.sub(second.value, 2) + elseif punct_map[first_char] then + if first_char == second_char then + second.value = string.sub(second.value, 2) + else + local combined = punct_map[first_char][second_char] + if combined and #combined == 1 then + second.value = string.sub(second.value, 2) + first.value = string.sub(first.value, 1, -2) .. combined + end + end + end +end + +local function smash_just_punc(first, second) + first = find_right(first) -- PlainText + second = find_left(second) -- PlainText + if first and second then + local first_char = string.sub(first.value, -1) + local second_char = string.sub(second.value, 1, 1) + -- util.debug(first_char) + -- util.debug(second_char) + + local punct_map = output_module.quote_punctuation_map + if second_char == " " and (first_char == " " or + util.endswith(first.value, util.unicode["no-break space"])) then + second.value = string.sub(second.value, 2) + return true + elseif punct_map[first_char] then + if first_char == second_char then + second.value = string.sub(second.value, 2) + return true + else + local combined = punct_map[first_char][second_char] + if combined and #combined == 1 then + second.value = string.sub(second.value, 2) + first.value = string.sub(first.value, 1, -2) .. combined + return true + end + end + end + else + return false + end +end + +local function normalise_text_elements(inlines) + -- 1. Merge punctuations: "?." => "?" + -- 2. Merge spaces: " " => " " + local idx = 1 + while idx < #inlines do + local first = inlines[idx] + local second = inlines[idx+1] + + if first._type == "PlainText" and second._type == "PlainText" then + smash_string_push(first, second) + first.value = first.value .. second.value + table.remove(inlines, idx + 1) + + elseif first._type == "Micro" and second._type == "PlainText" then + local success = smash_just_punc(first, second) + if success then + if second.value == "" then + table.remove(inlines, idx + 1) + end + else + idx = idx + 1 + end + + elseif first._type == "Formatted" and second._type == "PlainText" then + local success = smash_just_punc(first, second) + if success then + if second.value == "" then + table.remove(inlines, idx + 1) + end + else + idx = idx + 1 + end + + else + idx = idx + 1 + end + end + +end + +local function move_in_quotes(first, second) + local first_char = string.sub(first.value, -1) + local second_char = string.sub(second.value, 1, 1) + local success = false + if output_module.move_in_puncts[second_char] then + if first_char == second_char then + second.value = string.sub(second.value, 2) + success = true + elseif output_module.quote_punctuation_map[first_char] then + local combined = output_module.quote_punctuation_map[first_char][second_char] + first.value = string.sub(first.value, 1, -2) .. combined + second.value = string.sub(second.value, 2) + success = true + else + first.value = first.value .. second_char + second.value = string.sub(second.value, 2) + success = true + end + end + return success +end + +local function move_out_quotes(first, second) + local first_char = string.sub(first.value, -1) + local second_char = string.sub(second.value, 1, 1) + local success = false + if output_module.move_out_puncts[first_char] then + if first_char == second_char then + first.value = string.sub(first.value, 1, -2) + success = true + elseif output_module.quote_punctuation_map[second_char] then + local combined = output_module.quote_punctuation_map[first_char][second_char] + first.value = string.sub(first.value, 1, -2) + second.value = combined .. string.sub(second.value, 2) + success = true + else + first.value = string.sub(first.value, 1, -2) + second.value = first_char .. second.value + success = true + end + end + return success +end + +local function move_around_quote(inlines) + local idx = 1 + + while idx < #inlines do + -- Move punctuation into quotes as needed + local first, punctuation_in_quote = find_right_quoted(inlines[idx]) + + local second = find_left(inlines[idx+1]) + local success = false + if first and second then + if punctuation_in_quote then + success = move_in_quotes(first, second) + else + success = move_out_quotes(first, second) + end + if not success then + idx = idx + 1 + end + else + idx = idx + 1 + end + end +end + +function OutputFormat:move_punctuation(inlines, piq) + -- Merge punctuations + normalise_text_elements(inlines) + + move_around_quote(inlines) + + for _, inline in ipairs(inlines) do + if inline._type == "Quoted" or inline._type == "Formatted" or + inline._type == "Div" then + self:move_punctuation(inline.inlines) + end + end +end + +function OutputFormat:write_inlines(inlines, context) + local res = "" + for _, inline in ipairs(inlines) do + res = res .. self:write_inline(inline, context) + end + return res +end + +function OutputFormat:write_inline(inline, context) + if inline.value then + return self:write_escaped(inline.value) + elseif inline.inlines then + return self:write_inlines(inline.inlines) + end + return "" +end + +function OutputFormat:write_escaped(str, context) + return str +end + +function OutputFormat:write_link(inline, context) + return self:write_escaped(inline.value) +end + + + +local Markup = OutputFormat:new() + +function Markup:write_inline(inline, context) + -- Should be deprecated code + if type(inline) == "string" then + return self:write_escaped(inline, context) + + elseif type(inline) == "table" then + -- util.debug(inline._type) + if inline._type == "PlainText" then + return self:write_escaped(inline.value, context) + + elseif inline._type == "InlineElement" then + return self:write_children(inline, context) + + elseif inline._type == "Formatted" then + return self:write_formatted(inline, context) + + elseif inline._type == "Quoted" then + return self:write_quoted(inline, context) + + elseif inline._type == "Div" then + return self:write_display(inline, context) + + elseif inline._type == "Linked" then + return self:write_link(inline, context) + + elseif inline._type == "NoCase" or inline._type == "NoDecor" then + return self:write_inlines(inline.inlines) + + else + return self:write_inlines(inline.inlines) + end + end + return "" +end + +function Markup:write_children(inline, context) + local res = "" + for _, child_inline in ipairs(inline.inlines) do + res = res .. self:write_inline(child_inline, context) + end + return res +end + +function Markup:write_quoted(inline, context) + local res = self:write_children(inline, context) + local quotes = inline.quotes + if inline.is_inner then + return quotes.inner_open .. res .. quotes.inner_close + else + return quotes.outer_open .. res .. quotes.outer_close + end +end + + +local LatexWriter = Markup:new() + +LatexWriter.markups = { + ["bibstart"] = function (engine) + return string.format("\\begin{thebibliography}{%s}\n\n", engine.registry.longest_label) + end, + ["bibend"] = "\\end{thebibliography}", + ["@font-style/normal"] = "{\\normalshape %s}", + ["@font-style/italic"] = "\\textit{%s}", + ["@font-style/oblique"] = "\\textsl{%s}", + ["@font-variant/normal"] = "{\\normalshape %s}", + ["@font-variant/small-caps"] = "\\textsc{%s}", + ["@font-weight/normal"] = "{\\fontseries{m}\\selectfont %s}", + ["@font-weight/bold"] = "\\textbf{%s}", + ["@font-weight/light"] = "{\\fontseries{l}\\selectfont %s}", + ["@text-decoration/none"] = false, + ["@text-decoration/underline"] = "\\underline{%s}", + ["@vertical-align/sup"] = "\\textsuperscript{%s}", + ["@vertical-align/sub"] = "\\textsubscript{%s}", + ["@vertical-align/baseline"] = false, + ["@cite/entry"] = false, + ["@bibliography/entry"] = function (str, context) + if not string.match(str, "\\bibitem") then + str = "\\bibitem{".. context.id .. "}\n" .. str .. "\n" + end + return str + end, + ["@display/block"] = false, + ["@display/left-margin"] = '\n <div class="csl-left-margin">%s</div>', + ["@display/right-inline"] = '<div class="csl-right-inline">%s</div>\n ', + ["@display/indent"] = '<div class="csl-indent">%s</div>\n ', +} + +function LatexWriter:write_escaped(str, context) + -- TeXbook, p. 38 + str = str:gsub("\\", "\\textbackslash{}") + str = str:gsub("{", "\\{") + str = str:gsub("}", "\\}") + str = str:gsub("%$", "\\$") + str = str:gsub("&", "\\&") + str = str:gsub("#", "\\#") + str = str:gsub("%^", "\\^") + str = str:gsub("_", "\\_") + str = str:gsub("%%", "\\%%") + str = str:gsub("~", "\\~") + str = str:gsub(util.unicode["em space"], "\\quad ") + str = str:gsub(util.unicode["no-break space"], "~") + for char, sub in pairs(util.superscripts) do + str = string.gsub(str, char, "\\textsuperscript{" .. sub .. "}") + end + return str +end + +function LatexWriter:write_formatted(inline, context) + local res = self:write_children(inline, context) + for _, key in ipairs({"font-style", "font-variant", "font-weight", "text-decoration", "vertical-align"}) do + local value = inline.formatting[key] + if value then + key = "@" .. key .. "/" .. value + local format_str = self.markups[key] + if format_str then + res = string.format(format_str, res) + end + end + end + return res +end + +function LatexWriter:write_display(inline, context) + local plainter_text_writer = output_module.PlainTextWriter:new() + local str = plainter_text_writer:write_inline(inline) + local len = utf8.len(str) + if len > context.engine.registry.maxoffset then + context.engine.registry.maxoffset = len + context.engine.registry.longest_label = str + end + + local res = self:write_children(inline, context) + if inline.display == "left-margin" then + if string.match(res, "%]") then + res = "{" .. res .. "}" + end + res = string.format("\\bibitem[%s]{%s}\n", res, context.id) + + elseif inline.display == "right-inline" then + return res + + elseif inline.display == "block" then + return "" + end + return res +end + +function LatexWriter:write_link(inline, context) + if inline.href == inline.value then + return string.format("\\url{%s}", inline.value) + else + return string.format("\\href{%s}{%s}", inline.href, inline.value) + end +end + + +local HtmlWriter = Markup:new() + +HtmlWriter.markups = { + ["bibstart"] = "<div class=\"csl-bib-body\">\n", + ["bibend"] = "</div>", + ["@font-style/italic"] = "<i>%s</i>", + ["@font-style/oblique"] = "<em>%s</em>", + ["@font-style/normal"] = '<span style="font-style:normal;">%s</span>', + ["@font-variant/small-caps"] = '<span style="font-variant:small-caps;">%s</span>', + ["@font-variant/normal"] = '<span style="font-variant:normal;">%s</span>', + ["@font-weight/bold"] = "<b>%s</b>", + ["@font-weight/normal"] = '<span style="font-weight:normal;">%s</span>', + ["@font-weight/light"] = false, + ["@text-decoration/none"] = '<span style="text-decoration:none;">%s</span>', + ["@text-decoration/underline"] = '<span style="text-decoration:underline;">%s</span>', + ["@vertical-align/sup"] = "<sup>%s</sup>", + ["@vertical-align/sub"] = "<sub>%s</sub>", + ["@vertical-align/baseline"] = '<span style="baseline">%s</span>', + ["@cite/entry"] = nil, + ["@bibliography/entry"] = "<div class=\"csl-entry\">%s</div>\n", + ["@display/block"] = '\n\n <div class="csl-block">%s</div>\n', + ["@display/left-margin"] = '\n <div class="csl-left-margin">%s</div>', + ["@display/right-inline"] = '<div class="csl-right-inline">%s</div>\n ', + ["@display/indent"] = '<div class="csl-indent">%s</div>\n ', +} + +function HtmlWriter:write_escaped(str, context) + str = string.gsub(str, "%&", "&") + str = string.gsub(str, "<", "<") + str = string.gsub(str, ">", ">") + for char, sub in pairs(util.superscripts) do + str = string.gsub(str, char, "<sup>" .. sub .. "</sup>") + end + return str +end + +function HtmlWriter:write_formatted(inline, context) + local res = self:write_children(inline, context) + for _, key in ipairs({"font-style", "font-variant", "font-weight", "text-decoration", "vertical-align"}) do + local value = inline.formatting[key] + if value then + key = "@" .. key .. "/" .. value + local format_str = self.markups[key] + if format_str then + res = string.format(format_str, res) + end + end + end + return res +end + +function HtmlWriter:write_display(inline, context) + local plainter_text_writer = output_module.PlainTextWriter:new() + local str = plainter_text_writer:write_inline(inline) + local len = utf8.len(str) + if len > context.engine.registry.maxoffset then + context.engine.registry.maxoffset = len + context.engine.registry.longest_label = str + end + + if #inline.inlines == 0 then + return "" + end + local res = self:write_children(inline, context) + local key = string.format("@display/%s", inline.div) + if inline.div == "right-inline" then + -- Strip trailing spaces + -- variables_ContainerTitleShort.txt + res = string.gsub(res, "%s+$", "") + end + local format_str = self.markups[key] + res = string.format(format_str, res) + return res +end + +function HtmlWriter:write_link(inline, context) + return string.format('<a href="%s">%s</a>', inline.href, inline.value) +end + + +local PlainTextWriter = Markup:new() + +PlainTextWriter.markups = {} + +function PlainTextWriter:write_escaped(str, context) + return str +end + +function PlainTextWriter:write_formatted(inline, context) + return self:write_children(inline, context) +end + +function PlainTextWriter:write_display(inline, context) + return self:write_children(inline, context) +end + + +local SortStringFormat = OutputFormat:new() + +function SortStringFormat:output(inlines, context) + -- self:flip_flop_inlines(inlines) + -- self:move_punctuation(inlines) + return self:write_inlines(inlines, context) +end + +function SortStringFormat:write_escaped(str, context) + str = string.gsub(str, ",", "") + return str +end + + +local DisamStringFormat = OutputFormat:new() + +function DisamStringFormat:output(inlines, context) + -- self:flip_flop_inlines(inlines) + -- self:move_punctuation(inlines) + return self:write_inlines(inlines, context) +end + +function DisamStringFormat:flatten_ir(ir) + if self.group_var == "missing" then + return {} + end + local inlines + if ir._type == "SeqIr" or ir._type == "NameIr" then + inlines = self:flatten_seq_ir(ir) + elseif ir._type == "YearSuffix" then + -- Don't include year-suffix in disambiguation + inlines = {} + else + inlines = self:affixed_quoted(ir.inlines, ir.affixes, ir.quotes); + inlines = self:with_display(inlines, ir.display); + end + return inlines +end + +function DisamStringFormat:flatten_seq_ir(ir) + if not ir.children then + print(debug.traceback()) + end + if #ir.children == 0 then + return {} + end + local inlines_list = {} + for _, child in ipairs(ir.children) do + if child.group_var ~= "missing" then + -- and not child.collapse_suppressed + -- Suppressed irs are stil kept in the DisamStringFormat + table.insert(inlines_list, self:flatten_ir(child)) + end + end + + local inlines = self:group(inlines_list, ir.delimiter, ir.formatting) + -- assert ir.quotes == localized quotes + inlines = self:affixed_quoted(inlines, ir.affixes, ir.quotes); + inlines = self:with_display(inlines, ir.display); + return inlines +end + + +output_module.move_in_puncts = { + ["."] = true, + ["!"] = true, + ["?"] = true, + [","] = true, +} + +output_module.move_out_puncts = { + [","] = true, + [";"] = true, + [":"] = true, +} + +-- https://github.com/Juris-M/citeproc-js/blob/aa2683f48fe23be459f4ed3be3960e2bb56203f0/src/queue.js#L724 +-- Also merge duplicate punctuations. +output_module.quote_punctuation_map = { + ["!"] = { + ["."] = "!", + ["?"] = "!?", + [":"] = "!", + [","] = "!,", + [";"] = "!;", + }, + ["?"] = { + ["!"] = "?!", + ["."] = "?", + [":"] = "?", + [","] = "?,", + [";"] = "?;", + }, + ["."] = { + ["!"] = ".!", + ["?"] = ".?", + [":"] = ".:", + [","] = ".,", + [";"] = ".;", + }, + [":"] = { + ["!"] = "!", + ["?"] = "?", + ["."] = ":", + [","] = ":,", + [";"] = ":;", + }, + [","] = { + ["!"] = ",!", + ["?"] = ",?", + [":"] = ",:", + ["."] = ",.", + [";"] = ",;", + }, + [";"] = { + ["!"] = "!", + ["?"] = "?", + [":"] = ";", + [","] = ";,", + ["."] = ";", + } +} + + +output_module.LocalizedQuotes = LocalizedQuotes + +output_module.InlineElement = InlineElement +output_module.PlainText = PlainText +output_module.Formatted = Formatted +output_module.Micro = Micro +output_module.Quoted = Quoted +output_module.Linked = Linked +output_module.Div = Div +output_module.NoCase = NoCase +output_module.NoDecor = NoDecor + +output_module.OutputFormat = OutputFormat + +output_module.Markup = Markup +output_module.LatexWriter = LatexWriter +output_module.HtmlWriter = HtmlWriter +output_module.PlainTextWriter = PlainTextWriter +output_module.DisamStringFormat = DisamStringFormat +output_module.SortStringFormat = SortStringFormat + +return output_module diff --git a/biblio/citation-style-language/citeproc-richtext.lua b/biblio/citation-style-language/citeproc-richtext.lua deleted file mode 100644 index f9afd3acc6..0000000000 --- a/biblio/citation-style-language/citeproc-richtext.lua +++ /dev/null @@ -1,779 +0,0 @@ --- --- Copyright (c) 2021-2022 Zeping Lee --- Released under the MIT license. --- Repository: https://github.com/zepinglee/citeproc-lua --- - -local richtext = {} - -local unicode = require("unicode") - -local util = require("citeproc-util") - - -local RichText = { - contents = nil, - formats = nil, - _type = "RichText", -} - -function RichText:shallow_copy() - local res = richtext.new() - for _, text in ipairs(self.contents) do - table.insert(res.contents, text) - end - for key, value in pairs(self.formats) do - res.formats[key] = value - end - return res -end - -function RichText:render(formatter, context, punctuation_in_quote) - self:merge_punctuations() - - if punctuation_in_quote == nil and context then - punctuation_in_quote = context.style:get_locale_option("punctuation-in-quote") - end - if punctuation_in_quote then - self:move_punctuation_in_quote() - end - - self:change_case() - - self:flip_flop() - - self:clean_formats() - - return self:_render(formatter, context) -end - -function RichText:_render(formatter, context) - local res = "" - for _, text in ipairs(self.contents) do - local str - if type(text) == "string" then - if formatter and formatter.text_escape then - str = formatter.text_escape(text) - else - str = text - end - else -- RichText - str = text:_render(formatter, context) - end - -- Remove leading spaces - if string.sub(res, -1) == " " and string.sub(str, 1, 1) == " " then - str = string.gsub(str, "^%s+", "") - end - res = res .. str - end - for _, attr in ipairs(richtext.format_sequence) do - local value = self.formats[attr] - if value then - local key = string.format("@%s/%s", attr, value) - if formatter then - local format = formatter[key] - if type(format) == "string" then - res = string.format(format, res) - elseif type(format) == "function" then - res = format(res, context) - end - end - end - end - return res -end - -function RichText:merge_punctuations(contents, index) - for i, text in ipairs(self.contents) do - if text._type == "RichText" then - contents, index = text:merge_punctuations(contents, index) - elseif type(text) == "string" then - if contents and index then - local previous_string = contents[index] - local last_char = string.sub(previous_string, -1) - local right_punct_map = richtext.punctuation_map[last_char] - if right_punct_map then - local first_char = string.sub(text, 1, 1) - local new_punctuations = nil - if first_char == last_char then - new_punctuations = last_char - elseif contents == self.contents then - new_punctuations = right_punct_map[first_char] - end - if new_punctuations then - if #text == 1 then - table.remove(self.contents, i) - else - self.contents[i] = string.sub(text, 2) - end - contents[index] = string.sub(previous_string, 1, -2) .. new_punctuations - end - end - end - contents = self.contents - index = i - end - end - return contents, index -end - -function RichText:move_punctuation_in_quote() - local i = 1 - while i <= #self.contents do - local text = self.contents[i] - if type(text) == "table" and text._type == "RichText" then - text:move_punctuation_in_quote() - - if text.formats["quotes"] then - local contents = self.contents - local last_string = text - while type(last_string) == "table" and last_string._type == "RichText" do - contents = last_string.contents - last_string = contents[#contents] - end - - local done = false - while not done do - done = true - last_string = contents[#contents] - local last_char = string.sub(last_string, -1) - if i < #self.contents then - local next_text = self.contents[i + 1] - if type(next_text) == "string" then - local first_char = string.sub(next_text, 1, 1) - if richtext.in_quote_punctuations[first_char] then - done = false - local right_punct_map = richtext.punctuation_map[last_char] - if right_punct_map then - first_char = right_punct_map[first_char] - last_string = string.sub(last_string, 1, -2) - end - contents[#contents] = last_string .. first_char - if #next_text == 1 then - table.remove(self.contents, i + 1) - else - self.contents[i + 1] = string.sub(next_text, 2) - end - end - end - end - end - end - end - i = i + 1 - end -end - -function RichText:change_case() - for _, text in ipairs(self.contents) do - if type(text) == "table" and text._type == "RichText" then - text:change_case() - end - end - local text_case = self.formats["text-case"] - if text_case then - if text_case == "lowercase" then - self:lowercase() - elseif text_case == "uppercase" then - self:uppercase() - elseif text_case == "capitalize-first" then - self:capitalize_first() - elseif text_case == "capitalize-all" then - self:capitalize_all() - elseif text_case == "sentence" then - self:sentence() - elseif text_case == "title" then - self:title() - end - end -end - -function RichText:_change_word_case(state, word_transform, first_tranform, is_phrase) - if self.formats["text-case"] == "nocase" then - return - end - if is_phrase and (self.formats["vertical-align"] == "sup" or - self.formats["vertical-align"] == "sub" or - self.formats["font-variant"] == "small-caps") then - return - end - state = state or "after-sentence" - word_transform = word_transform or function (x) return x end - first_tranform = first_tranform or word_transform - for i, text in ipairs(self.contents) do - if type(text) == "string" then - - local res = "" - local word_seps = { - " ", - "%-", - "/", - util.unicode["no-break space"], - util.unicode["en dash"], - util.unicode["em dash"], - } - for _, tuple in ipairs(util.split(text, word_seps, nil, true)) do - local word, punctuation = table.unpack(tuple) - if state == "after-sentence" then - res = res .. first_tranform(word) - if string.match(word, "%w") then - state = "after-word" - end - else - res = res .. word_transform(word, punctuation) - end - res = res .. punctuation - if string.match(word, "[.!?:]%s*$") then - state = "after-sentence" - end - end - - -- local word_index = 0 - -- local res = string.gsub(text, "%w+", function (word) - -- word_index = word_index + 1 - -- if word_index == 1 then - -- return first_tranform(word) - -- else - -- return word_transform(word) - -- end - -- end) - -- if string.match(res, "[.!?:]%s*$") then - -- state = "after-sentence" - -- end - - self.contents[i] = res - else - state = text:_change_word_case(state, word_transform, first_tranform, true) - end - end - return state -end - -function RichText:lowercase() - local word_transform = unicode.utf8.lower - self:_change_word_case("after-sentence", word_transform) -end - -function RichText:uppercase() - local word_transform = unicode.utf8.upper - self:_change_word_case("after-sentence", word_transform) -end - -local function capitalize(str) - local res = string.gsub(str, utf8.charpattern, unicode.utf8.upper, 1) - return res -end - -local function capitalize_if_lower(word) - if util.is_lower(word) then - return capitalize(word) - else - return word - end -end - -function RichText:capitalize_first(state) - local first_tranform = capitalize_if_lower - self:_change_word_case("after-sentence", nil, first_tranform) -end - -function RichText:capitalize_all() - local word_transform = capitalize_if_lower - self:_change_word_case("after-sentence", word_transform) -end - -function RichText:is_upper() - for _, text in ipairs(self.contents) do - if type(text) == "string" then - if not util.is_upper(text) then - return false - end - else - local res = text:is_upper() - if not res then - return false - end - end - end - return true -end - -function RichText:sentence() - if self:is_upper() then - local first_tranform = function(word) - return capitalize(unicode.utf8.lower(word)) - end - local word_transform = unicode.utf8.lower - self:_change_word_case("after-sentence", word_transform, first_tranform) - else - local first_tranform = capitalize_if_lower - self:_change_word_case("after-sentence", nil, first_tranform) - end -end - -function RichText:title() - if self:is_upper() then - local first_tranform = function(word) - return capitalize(unicode.utf8.lower(word)) - end - local word_transform = function(word, sep) - local res = unicode.utf8.lower(word) - if not util.stop_words[res] then - res = capitalize(res) - end - return res - end - self:_change_word_case("after-sentence", word_transform, first_tranform) - else - local first_tranform = capitalize_if_lower - local word_transform = function(word, sep) - local lower = unicode.utf8.lower(word) - -- Stop word before hyphen is treated as a normal word. - if util.stop_words[lower] and sep ~= "-" then - return lower - elseif word == lower then - return capitalize(word) - else - return word - end - end - self:_change_word_case("after-sentence", word_transform, first_tranform) - end -end - -function richtext.concat(str1, str2) - assert(str1 and str2) - - if type(str1) == "string" then - str1 = richtext.new(str1) - end - - local res - if next(str1.formats) == nil or str2 == "" then - -- shallow copy - res = str1 - else - res = richtext.new() - res.contents = {str1} - end - - if str2._type == "RichText" then - if next(str2.formats) == nil then - for _, text in ipairs(str2.contents) do - table.insert(res.contents, text) - end - else - table.insert(res.contents, str2) - end - elseif str2 ~= "" then - table.insert(res.contents, str2) - end - return res -end - -function richtext.concat_list(list, delimiter) - -- Strings in the list may be nil thus ipairs() should be avoided. - -- The delimiter may be nil. - local res = nil - for i = 1, #list do - local text = list[i] - if text and text ~= "" then - if res then - if delimiter and delimiter ~= "" then - res = richtext.concat(res, delimiter) - end - res = richtext.concat(res, text) - else - if type(text) == "string" then - text = richtext.new(text) - end - res = text - end - end - end - return res -end - -function RichText:strip_periods() - local last_string = self - local contents = self.contents - while last_string._type == "RichText" do - contents = last_string.contents - last_string = contents[#contents] - end - if string.sub(last_string, -1) == "." then - contents[#contents] = string.sub(last_string, 1, -2) - end -end - -function RichText:add_format(attr, value) - self.formats[attr] = value -end - -function RichText:flip_flop(attr, value) - if not attr then - for attr, _ in pairs(richtext.flip_flop_formats) do - self:flip_flop(attr) - end - return - end - - local default_value = richtext.default_formats[attr] - - if value and value ~= default_value and self.formats[attr] == value then - self.formats[attr] = richtext.flip_flop_values[attr][value] - end - if self.formats[attr] then - value = self.formats[attr] - end - - for _, text in ipairs(self.contents) do - if type(text) == "table" and text._type == "RichText" then - text:flip_flop(attr, value) - end - end -end - -function RichText:clean_formats(format) - -- Remove the formats that are default values - if not format then - for format, _ in pairs(richtext.default_formats) do - self:clean_formats(format) - end - return - end - if self.formats[format] then - if self.formats[format] == richtext.default_formats[format] then - self.formats[format] = nil - else - return - end - end - for _, text in ipairs(self.contents) do - if type(text) == "table" and text._type == "RichText" then - text:clean_formats(format) - end - end -end - -local RichText_mt = { - __index = RichText, - __concat = richtext.concat, -} - -local function table_update(t, new_t) - for key, value in pairs(new_t) do - t[key] = value - end - return t -end - -function RichText._split_tags(str) - -- Normalize markup - str = string.gsub(str, '<span%s+style="font%-variant:%s*small%-caps;?">', '<span style="font-variant:small-caps;">') - str = string.gsub(str, '<span%s+class="nocase">', '<span class="nocase">') - str = string.gsub(str, '<span%s+class="nodecor">', '<span class="nodecor">') - - local strings = {} - - local start_index = 1 - local i = 1 - - while i <= #str do - local substr = string.sub(str, i) - local starts_with_tag = false - for tag, _ in pairs(richtext.tags) do - if util.startswith(substr, tag) then - if start_index <= i - 1 then - table.insert(strings, string.sub(str, start_index, i-1)) - end - table.insert(strings, tag) - i = i + #tag - start_index = i - starts_with_tag = true - break - end - end - if not starts_with_tag then - i = i + 1 - end - end - if start_index <= #str then - table.insert(strings, string.sub(str, start_index)) - end - - for i = 1, #strings do - str = strings[i] - if str == "'" or str == util.unicode["apostrophe"] then - local previous_str = strings[i - 1] - local next_str = strings[i + 1] - if previous_str and next_str then - local previous_code_point = nil - for _, code_point in utf8.codes(previous_str) do - previous_code_point = code_point - end - local next_code_point = utf8.codepoint(next_str) - if util.is_romanesque(previous_code_point) and util.is_romanesque(next_code_point) then - -- An apostrophe - strings[i-1] = strings[i-1] .. util.unicode["apostrophe"] .. strings[i+1] - table.remove(strings, i+1) - table.remove(strings, i) - end - end - end - end - - return strings -end - -function richtext.new(text, formats) - local res = { - contents = {}, - formats = formats or {}, - } - - setmetatable(res, RichText_mt) - - if not text then - return res - end - - if type(text) == "string" then - - local strings = RichText._split_tags(text) - local contents = {} - for _, str in ipairs(strings) do - table.insert(contents, str) - - local end_tag = nil - if str == '"' then - local last_text = contents[#contents - 1] - if last_text and type(last_text) == "string" and string.match(last_text, "%s$") then - end_tag = nil - else - end_tag = str - end - elseif richtext.end_tags[str] then - end_tag = str - end - - if end_tag then - for i = #contents - 1, 1, -1 do - local start_tag = contents[i] - if type(start_tag) == "string" and richtext.tag_pairs[start_tag] == end_tag then - local subtext = richtext.new() - -- subtext.contents = util.slice(contents, i + 1, #contents - 1) - if start_tag == "'" and end_tag == "'" and i == #contents - 1 then - contents[i] = util.unicode["apostrophe"] - contents[#contents] = util.unicode["apostrophe"] - break - end - - for j = i + 1, #contents - 1 do - local substr = contents[j] - if substr == "'" then - substr = util.unicode["apostrophe"] - end - local last_text = subtext.contents[#subtext.contents] - if type(substr) == "string" and type(last_text) == "string" then - subtext.contents[#subtext.contents] = last_text .. substr - else - table.insert(subtext.contents, substr) - end - end - - if start_tag == '<span class="nodecor">' then - for attr, value in pairs(richtext.default_formats) do - subtext.formats[attr] = value - end - subtext.formats["text-case"] = "nocase" - else - for attr, value in pairs(richtext.tag_formats[start_tag]) do - subtext.formats[attr] = value - end - end - - for j = #contents, i, -1 do - table.remove(contents, j) - end - table.insert(contents, subtext) - break - end - end - end - end - - for i = #contents, 1, -1 do - if contents[i] == "'" then - contents[i] = util.unicode["apostrophe"] - end - if type(contents[i]) == "string" and type(contents[i+1]) == "string" then - contents[i] = contents[i] .. contents[i+1] - table.remove(contents, i+1) - end - end - - if #contents == 1 and type(contents[1]) == "table" then - res = contents[1] - else - res.contents = contents - end - - return res - - elseif type(text) == "table" and text._type == "RichText" then - return text - - elseif type(text) == "table" then - return text - end - return nil -end - -richtext.tag_formats = { - ["<i>"] = {["font-style"] = "italic"}, - ["<b>"] = {["font-weight"] = "bold"}, - ["<sup>"] = {["vertical-align"] = "sup"}, - ["<sub>"] = {["vertical-align"] = "sub"}, - ["<sc>"] = {["font-variant"] = "small-caps"}, - ['<span style="font-variant:small-caps;">'] = {["font-variant"] = "small-caps"}, - ['<span class="nocase">'] = {["text-case"] = "nocase"}, - ['"'] = {["quotes"] = "true"}, - [util.unicode['left double quotation mark']] = {["quotes"] = "true"}, - ["'"] = {["quotes"] = "true"}, - [util.unicode['left single quotation mark']] = {["quotes"] = "true"}, -} - -richtext.default_formats = { - ["URL"] = "false", - ["DOI"] = "false", - ["PMID"] = "false", - ["PMCID"] = "false", - ["font-style"] = "normal", - ["font-variant"] = "normal", - ["font-weight"] = "normal", - ["text-decoration"] = "none", - ["vertical-align"] = "baseline", - ["quotes"] = "false", -} - -richtext.format_sequence = { - "URL", - "DOI", - "PMID", - "PMCID", - "font-style", - "font-variant", - "font-weight", - "text-decoration", - "vertical-align", - "quotes", - "display", -} - -richtext.flip_flop_formats = { - ["font-style"] = true, - ["font-weight"] = true, - ["font-variant"] = true, - ["quotes"] = true, -} - -richtext.flip_flop_values = { - ["font-style"] = { - italic = "normal", - normal = "italic", - }, - ["font-weight"] = { - bold = "normal", - normal = "bold", - }, - ["font-variant"] = { - ["small-caps"] = "normal", - normal = "small-caps", - }, - ["quotes"] = { - ["true"] = "inner", - inner = "true", - }, -} - --- https://github.com/Juris-M/citeproc-js/blob/aa2683f48fe23be459f4ed3be3960e2bb56203f0/src/queue.js#L724 --- Also merge duplicate punctuations. -richtext.punctuation_map = { - ["!"] = { - ["."] = "!", - ["?"] = "!?", - [":"] = "!", - [","] = "!,", - [";"] = "!;", - }, - ["?"] = { - ["!"] = "?!", - ["."] = "?", - [":"] = "?", - [","] = "?,", - [";"] = "?;", - }, - ["."] = { - ["!"] = ".!", - ["?"] = ".?", - [":"] = ".:", - [","] = ".,", - [";"] = ".;", - }, - [":"] = { - ["!"] = "!", - ["?"] = "?", - ["."] = ":", - [","] = ":,", - [";"] = ":;", - }, - [","] = { - ["!"] = ",!", - ["?"] = ",?", - [":"] = ",:", - ["."] = ",.", - [";"] = ",;", - }, - [";"] = { - ["!"] = "!", - ["?"] = "?", - [":"] = ";", - [","] = ";,", - ["."] = ";", - } -} - -richtext.in_quote_punctuations = { - [","] = true, - ["."] = true, - ["?"] = true, - ["!"] = true, -} - -richtext.tag_pairs = { - ["<i>"] = "</i>", - ["<b>"] = "</b>", - ["<sup>"] = "</sup>", - ["<sub>"] = "</sub>", - ["<sc>"] = "</sc>", - ['<span style="font-variant:small-caps;">'] = "</span>", - ['<span class="nocase">'] = "</span>", - ['<span class="nodecor">'] = "</span>", - ['"'] = '"', - [util.unicode['left double quotation mark']] = util.unicode['right double quotation mark'], - ["'"] = "'", - [util.unicode['left single quotation mark']] = util.unicode['right single quotation mark'], -} - -richtext.tags = {} - -richtext.end_tags = {} - -for start_tag, end_tag in pairs(richtext.tag_pairs) do - richtext.tags[start_tag] = true - richtext.tags[end_tag] = true - richtext.end_tags[end_tag] = true -end - -return richtext diff --git a/biblio/citation-style-language/citeproc-util.lua b/biblio/citation-style-language/citeproc-util.lua index c9adb6558f..38de3b5751 100644 --- a/biblio/citation-style-language/citeproc-util.lua +++ b/biblio/citation-style-language/citeproc-util.lua @@ -6,11 +6,55 @@ -- load `slnunicode` from LuaTeX local unicode = require("unicode") -local inspect = require("inspect") +local inspect -- only load it when debugging local util = {} +function util.clone(obj) + if type(obj) == "table" then + local res = {} + for key, value in pairs(obj) do + res[key] = value + end + return setmetatable(res, getmetatable(obj)) + else + return obj + end +end + +function util.join(list, delimiter) + local res = {} + for i, item in ipairs(list) do + if i > 1 then + table.insert(res, delimiter) + end + table.insert(res, item) + end + return res +end + +function util.to_boolean(str) + if not str then + return false + end + if str == "true" then + return true + elseif str == "false" then + return false + else + util.warning(string.format('Invalid boolean string "%s"', str)) + return false + end +end + +function util.to_list(str) + if not str then + return nil + end + return util.split(str) +end + function util.to_ordinal (n) assert(type(n) == "number") local last_digit = n % 10 @@ -44,21 +88,60 @@ function util.warning(message) end end -local function remove_all_metatables(item, path) - if path[#path] ~= inspect.METATABLE then return item end -end +local remove_all_metatables = nil -function util.debug(...) - -- io.stderr:write(inspect(..., {process = remove_all_metatables})) - io.stderr:write(inspect(...)) +function util.debug(obj) + if not inspect then + inspect = require("inspect") + remove_all_metatables = function (item, path) + if path[#path] ~= inspect.METATABLE then + return item + end + end + end + io.stderr:write("[") + io.stderr:write(debug.getinfo(2, "S").source:sub(2)) + io.stderr:write(":") + io.stderr:write(debug.getinfo(2, "l").currentline) + io.stderr:write("] ") + io.stderr:write(inspect(obj, {process = remove_all_metatables})) io.stderr:write("\n") end -- Similar to re.split() in Python -function util.split(str, seps, maxsplit, include_sep) +function util.split(str, sep, maxsplit) if not str then - error("Invalid string.") + util.error("Invalid string.") + end + sep = sep or "%s+" + if sep == "" then + util.error("Empty separator") end + if string.find(str, sep) == nil then + return { str } + end + + if maxsplit == nil or maxsplit < 0 then + maxsplit = -1 -- No limit + end + local result = {} + local pattern = "(.-)" .. sep .. "()" + local num_splits = 0 + local lastPos = 1 + for part, pos in string.gmatch(str, pattern) do + if num_splits == maxsplit then + break + end + num_splits = num_splits + 1 + result[num_splits] = part + lastPos = pos + end + -- Handle the last field + result[num_splits + 1] = string.sub(str, lastPos) + return result +end + +function util.split_multiple(str, seps, include_sep) seps = seps or "%s+" if seps == "" then error("Empty separator") @@ -97,6 +180,15 @@ function util.split(str, seps, maxsplit, include_sep) return res end +-- TODO: [Unicode word boundaries](https://www.unicode.org/reports/tr29/#Word_Boundaries) +-- Returns: { +-- {word, boundary}, +-- {word, boundary}, +-- } +function util.segment_words(str) + return util.split_multiple(str, util.word_boundaries, true) +end + function util.slice (t, start, stop) start = start or 1 stop = stop or #t @@ -132,6 +224,31 @@ function util.concat (list, sep) return res end +-- Python list.extend() +function util.extend(first, second) + if not second then + print(debug.traceback()) + end + local l = #first + for i, element in ipairs(second) do + first[l + i] = element + end + return first +end + +-- Concat two lists in place +function util.concat_list(first, second) + local res + for i, element in ipairs(first) do + res[i] = element + end + local i = #res + for j, element in ipairs(second) do + res[i + j] = element + end + return res +end + function util.lstrip (str) if not str then return nil @@ -153,22 +270,34 @@ function util.strip (str) end function util.startswith (str, prefix) + if not str then + return false + end return string.sub(str, 1, #prefix) == prefix end function util.endswith (str, suffix) + if not str then + return false + end return string.sub(str, -#suffix) == suffix end +function util.is_punct(str) + return string.match(str, "^%p$") +end + function util.is_numeric (str) if str == nil or str == "" then return false end local res = true for w in string.gmatch(str, "%w+") do - if string.match(w, "^[a-zA-Z]*%d+[a-zA-Z]*$") == nil then - res = false - break + if not string.match(w, "^%a*%d+%a*$") and + not string.match(w, "^[MDCLXVI]+$") and + not string.match(w, "^[mdclxvi]+$") then + -- Roman number withou validation + return false end end for w in string.gmatch(str, "%W+") do @@ -180,19 +309,84 @@ function util.is_numeric (str) return res end -function util.is_uncertain_date (variable) - if variable == nil then - return false - end - local value = variable["circa"] - return value ~= nil and value ~= "" -end - util.variable_types = {} -- schema/schemas/styles/csl-variables.rnc util.variables = {} +-- -- Standard variables +-- util.variables.standard = { +-- "abstract", +-- "annote", +-- "archive", +-- "archive_collection", +-- "archive_location", +-- "archive-place", +-- "authority", +-- "call-number", +-- "citation-key", +-- "citation-label", +-- "collection-title", +-- "container-title", +-- "container-title-short", +-- "dimensions", +-- "division", +-- "DOI", +-- "event", +-- "event-title", +-- "event-place", +-- "genre", +-- "ISBN", +-- "ISSN", +-- "jurisdiction", +-- "keyword", +-- "language", +-- "license", +-- "medium", +-- "note", +-- "original-publisher", +-- "original-publisher-place", +-- "original-title", +-- "part-title", +-- "PMCID", +-- "PMID", +-- "publisher", +-- "publisher-place", +-- "references", +-- "reviewed-genre", +-- "reviewed-title", +-- "scale", +-- "source", +-- "status", +-- "title", +-- "title-short", +-- "URL", +-- "volume-title", +-- "year-suffix", +-- } + +-- Number variables +util.variables.number = { + "chapter-number", + "citation-number", + "collection-number", + "edition", + "first-reference-note-number", + "issue", + "locator", + "number", + "number-of-pages", + "number-of-volumes", + "page", + "page-first", + "part-number", + "printing-number", + "section", + "supplement-number", + "version", + "volume", +} + -- Date variables util.variables.date = { "accessed", @@ -234,28 +428,6 @@ util.variables.name = { "translator", } --- Number variables -util.variables.number = { - "chapter-number", - "citation-number", - "collection-number", - "edition", - "first-reference-note-number", - "issue", - "locator", - "number", - "number-of-pages", - "number-of-volumes", - "page", - "page-first", - "part-number", - "printing-number", - "section", - "supplement-number", - "version", - "volume", -} - util.variable_types = {} for type, variables in pairs(util.variables) do @@ -327,10 +499,22 @@ util.unicode = { ["apostrophe"] = "\u{2019}", ["left double quotation mark"] = "\u{201C}", ["right double quotation mark"] = "\u{201D}", + ["left-pointing double angle quotation mark"] = "\u{00AB}", + ["right-pointing double angle quotation mark"] = "\u{00BB}", ["horizontal ellipsis"] = "\u{2026}", ["narrow no-break space"] = "\u{202F}", } +util.word_boundaries = { + ":", + " ", + "%-", + "/", + util.unicode["no-break space"], + util.unicode["en dash"], + util.unicode["em dash"], +} + -- Text-case @@ -342,9 +526,11 @@ function util.is_upper (str) return unicode.utf8.upper(str) == str end -function util.capitalize (str) - str = unicode.utf8.lower(str) - local res = string.gsub(str, "%w", unicode.utf8.upper, 1) +function util.capitalize(str) + -- if not str then + -- print(debug.traceback()) + -- end + local res = string.gsub(str, utf8.charpattern, unicode.utf8.upper, 1) return res end @@ -635,7 +821,7 @@ function util.convert_roman (number) local output = {} for _, tuple in ipairs(util.roman_numerals) do local letter, value = table.unpack(tuple) - table.insert(output, string.rep(letter, number // value)) + table.insert(output, string.rep(letter, math.floor(number / value))) number = number % value end return table.concat(output, "") @@ -793,4 +979,35 @@ function util.read_file(path) end +function util.parse_iso_date(str) + local date + local date_parts = util.split(str, "/") + if #date_parts <= 2 then + date = {["date-parts"] = {}} + for _, date_part in ipairs(date_parts) do + table.insert(date["date-parts"], util.split(date_part, "%-")) + end + end + if not date then + date = {literal = str} + end + return date +end + + +function util.parse_extra_name(str) + local name + local name_parts = util.split(str, "%s*||%s*") + if #name_parts == 2 then + name = { + family = name_parts[1], + given = name_parts[2], + } + else + name = {literal = str} + end + return name +end + + return util diff --git a/biblio/citation-style-language/citeproc.lua b/biblio/citation-style-language/citeproc.lua index 828d951403..b266abbdc5 100644 --- a/biblio/citation-style-language/citeproc.lua +++ b/biblio/citation-style-language/citeproc.lua @@ -10,7 +10,7 @@ local engine = require("citeproc-engine") local bib = require("citeproc-bib") local util = require("citeproc-util") -citeproc.__VERSION__ = "0.1.1" +citeproc.__VERSION__ = "0.2.0" citeproc.new = engine.CiteProc.new citeproc.parse_bib = bib.parse diff --git a/biblio/citation-style-language/csl-locales-en-GB.xml b/biblio/citation-style-language/csl-locales-en-GB.xml index 11239a37d9..2e1d04ada2 100644 --- a/biblio/citation-style-language/csl-locales-en-GB.xml +++ b/biblio/citation-style-language/csl-locales-en-GB.xml @@ -11,7 +11,7 @@ <name>Rintze M. Zelle</name> </translator> <rights license="http://creativecommons.org/licenses/by-sa/3.0/">This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 License</rights> - <updated>2022-01-01T21:32:03-05:00</updated> + <updated>2022-03-12T05:55:43-05:00</updated> </info> <style-options punctuation-in-quote="false"/> <date form="text"> @@ -309,39 +309,39 @@ </term> <!-- SHORT LOCATOR FORMS --> - <term name="appendix"> + <term name="appendix" form="short"> <single>app.</single> <multiple>apps.</multiple> </term> - <term name="article-locator"> + <term name="article-locator" form="short"> <single>art.</single> <multiple>arts.</multiple> </term> - <term name="elocation"> + <term name="elocation" form="short"> <single>loc.</single> <multiple>locs.</multiple> </term> - <term name="equation"> + <term name="equation" form="short"> <single>eq.</single> <multiple>eqs.</multiple> </term> - <term name="rule"> + <term name="rule" form="short"> <single>r.</single> <multiple>rr.</multiple> </term> - <term name="scene"> + <term name="scene" form="short"> <single>sc.</single> <multiple>scs.</multiple> </term> - <term name="table"> + <term name="table" form="short"> <single>tbl.</single> <multiple>tbls.</multiple> </term> - <term name="timestamp"> <!-- generally blank --> + <term name="timestamp" form="short"> <!-- generally blank --> <single></single> <multiple></multiple> </term> - <term name="title-locator"> + <term name="title-locator" form="short"> <single>tit.</single> <multiple>tits.</multiple> </term> diff --git a/biblio/citation-style-language/csl-locales-en-US.xml b/biblio/citation-style-language/csl-locales-en-US.xml index 03ffc42f9f..7fa0207e6a 100644 --- a/biblio/citation-style-language/csl-locales-en-US.xml +++ b/biblio/citation-style-language/csl-locales-en-US.xml @@ -17,7 +17,7 @@ <name>Brenton M. Wiernik</name> </translator> <rights license="http://creativecommons.org/licenses/by-sa/3.0/">This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 License</rights> - <updated>2022-01-01T21:32:03-05:00</updated> + <updated>2022-03-12T05:55:43-05:00</updated> </info> <style-options punctuation-in-quote="true"/> <date form="text"> @@ -315,39 +315,39 @@ </term> <!-- SHORT LOCATOR FORMS --> - <term name="appendix"> + <term name="appendix" form="short"> <single>app.</single> <multiple>apps.</multiple> </term> - <term name="article-locator"> + <term name="article-locator" form="short"> <single>art.</single> <multiple>arts.</multiple> </term> - <term name="elocation"> + <term name="elocation" form="short"> <single>loc.</single> <multiple>locs.</multiple> </term> - <term name="equation"> + <term name="equation" form="short"> <single>eq.</single> <multiple>eqs.</multiple> </term> - <term name="rule"> + <term name="rule" form="short"> <single>r.</single> <multiple>rr.</multiple> </term> - <term name="scene"> + <term name="scene" form="short"> <single>sc.</single> <multiple>scs.</multiple> </term> - <term name="table"> + <term name="table" form="short"> <single>tbl.</single> <multiple>tbls.</multiple> </term> - <term name="timestamp"> <!-- generally blank --> + <term name="timestamp" form="short"> <!-- generally blank --> <single></single> <multiple></multiple> </term> - <term name="title-locator"> + <term name="title-locator" form="short"> <single>tit.</single> <multiple>tits.</multiple> </term> diff --git a/biblio/citation-style-language/csl-locales-fr-FR.xml b/biblio/citation-style-language/csl-locales-fr-FR.xml index e6a71687d4..c94055ef8a 100644 --- a/biblio/citation-style-language/csl-locales-fr-FR.xml +++ b/biblio/citation-style-language/csl-locales-fr-FR.xml @@ -4,8 +4,11 @@ <translator> <name>Grégoire Colly</name> </translator> + <translator> + <name>Collectif Zotero francophone</name> + </translator> <rights license="http://creativecommons.org/licenses/by-sa/3.0/">This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 License</rights> - <updated>2022-01-01T21:32:03-05:00</updated> + <updated>2022-04-01T14:30:37+02:00</updated> </info> <style-options punctuation-in-quote="false" limit-day-ordinals-to-day-1="true"/> <date form="text"> @@ -19,33 +22,33 @@ <date-part name="year"/> </date> <terms> - <term name="advance-online-publication">advance online publication</term> + <term name="advance-online-publication">publication en ligne anticipée</term> <term name="album">album</term> - <term name="audio-recording">audio recording</term> + <term name="audio-recording">enregistrement audio</term> <term name="film">film</term> - <term name="henceforth">henceforth</term> - <term name="loc-cit">loc. cit.</term> <!-- like ibid., the abbreviated form is the regular form --> - <term name="no-place">no place</term> - <term name="no-place" form="short">n.p.</term> - <term name="no-publisher">no publisher</term> <!-- sine nomine --> - <term name="no-publisher" form="short">n.p.</term> - <term name="on">on</term> - <term name="op-cit">op. cit.</term> <!-- like ibid., the abbreviated form is the regular form --> - <term name="original-work-published">original work published</term> + <term name="henceforth">désormais</term> + <term name="loc-cit">loc. cit.</term> <!-- like ibid., the abbreviated form is the regular form --> + <term name="no-place">sans lieu</term> + <term name="no-place" form="short">s. l.</term> + <term name="no-publisher">sans nom</term> <!-- sine nomine --> + <term name="no-publisher" form="short">s. n.</term> + <term name="on">sur</term> + <term name="op-cit">op. cit.</term> <!-- like ibid., the abbreviated form is the regular form --> + <term name="original-work-published">édition originale</term> <term name="personal-communication">communication personnelle</term> <term name="podcast">podcast</term> - <term name="podcast-episode">podcast episode</term> - <term name="preprint">preprint</term> - <term name="radio-broadcast">radio broadcast</term> - <term name="radio-series">radio series</term> - <term name="radio-series-episode">radio series episode</term> - <term name="special-issue">special issue</term> - <term name="special-section">special section</term> - <term name="television-broadcast">television broadcast</term> - <term name="television-series">television series</term> - <term name="television-series-episode">television series episode</term> - <term name="video">video</term> - <term name="working-paper">working paper</term> + <term name="podcast-episode">épisode de podcast</term> + <term name="preprint">prépublication</term> + <term name="radio-broadcast">émission de radio</term> + <term name="radio-series">série radiophonique</term> + <term name="radio-series-episode">épisode de série radiophonique</term> + <term name="special-issue">numéro spécial</term> + <term name="special-section">section spéciale</term> + <term name="television-broadcast">émission de télévision</term> + <term name="television-series">série télévisée</term> + <term name="television-series-episode">épisode de série télévisée</term> + <term name="video">vidéo</term> + <term name="working-paper">document de travail</term> <term name="accessed">consulté le</term> <term name="and">et</term> <term name="and others">et autres</term> @@ -88,74 +91,74 @@ <term name="version">version</term> <!-- LONG ITEM TYPE FORMS --> - <term name="article">preprint</term> - <term name="article-journal">journal article</term> - <term name="article-magazine">magazine article</term> - <term name="article-newspaper">newspaper article</term> - <term name="bill">bill</term> - <term name="book">book</term> - <term name="broadcast">broadcast</term> - <term name="chapter">book chapter</term> - <term name="classic">classic</term> + <term name="article">article</term> + <term name="article-journal">article de revue</term> + <term name="article-magazine">article de magazine</term> + <term name="article-newspaper">article de presse</term> + <term name="bill">projet de loi</term> + <term name="book">livre</term> + <term name="broadcast">émission</term> + <term name="chapter">chapitre de livre</term> + <term name="classic">classique</term> <term name="collection">collection</term> - <term name="dataset">dataset</term> + <term name="dataset">jeu de données</term> <term name="document">document</term> - <term name="entry">entry</term> - <term name="entry-dictionary">dictionary entry</term> - <term name="entry-encyclopedia">encyclopedia entry</term> - <term name="event">event</term> + <term name="entry">entrée</term> + <term name="entry-dictionary">entrée de dictionnaire</term> + <term name="entry-encyclopedia">entrée d'encyclopédie</term> + <term name="event">événement</term> <!-- figure is in the list of locator terms --> - <term name="graphic">graphic</term> - <term name="hearing">hearing</term> + <term name="graphic">image</term> + <term name="hearing">audience</term> <term name="interview">interview</term> - <term name="legal_case">legal case</term> - <term name="legislation">legislation</term> - <term name="manuscript">manuscript</term> - <term name="map">map</term> - <term name="motion_picture">video recording</term> - <term name="musical_score">musical score</term> + <term name="legal_case">affaire</term> + <term name="legislation">acte juridique</term> + <term name="manuscript">manuscrit</term> + <term name="map">carte</term> + <term name="motion_picture">enregistrement vidéo</term> + <term name="musical_score">partition</term> <term name="pamphlet">pamphlet</term> - <term name="paper-conference">conference paper</term> - <term name="patent">patent</term> - <term name="performance">performance</term> - <term name="periodical">periodical</term> + <term name="paper-conference">article de colloque</term> + <term name="patent">brevet</term> + <term name="performance">interprétation</term> + <term name="periodical">périodique</term> <term name="personal_communication">communication personnelle</term> - <term name="post">post</term> - <term name="post-weblog">blog post</term> - <term name="regulation">regulation</term> - <term name="report">report</term> - <term name="review">review</term> - <term name="review-book">book review</term> - <term name="software">software</term> - <term name="song">audio recording</term> - <term name="speech">presentation</term> - <term name="standard">standard</term> - <term name="thesis">thesis</term> - <term name="treaty">treaty</term> - <term name="webpage">webpage</term> + <term name="post">billet</term> + <term name="post-weblog">billet de blog</term> + <term name="regulation">règlement</term> + <term name="report">rapport</term> + <term name="review">recension</term> + <term name="review-book">recension de livre</term> + <term name="software">logiciel</term> + <term name="song">chanson</term> + <term name="speech">présentation</term> + <term name="standard">norme</term> + <term name="thesis">thèse</term> + <term name="treaty">traité</term> + <term name="webpage">page web</term> <!-- SHORT ITEM TYPE FORMS --> - <term name="article-journal" form="short">journal art.</term> - <term name="article-magazine" form="short">mag. art.</term> - <term name="article-newspaper" form="short">newspaper art.</term> - <term name="book" form="short">bk.</term> - <term name="chapter" form="short">bk. chap.</term> + <term name="article-journal" form="short">art. de revue</term> + <term name="article-magazine" form="short">art. de mag.</term> + <term name="article-newspaper" form="short">art. de presse</term> + <term name="book" form="short">liv.</term> + <term name="chapter" form="short">chap. de liv.</term> <term name="document" form="short">doc.</term> <!-- figure is in the list of locator terms --> <term name="graphic" form="short">graph.</term> <term name="interview" form="short">interv.</term> - <term name="manuscript" form="short">MS</term> - <term name="motion_picture" form="short">video rec.</term> - <term name="report" form="short">rep.</term> - <term name="review" form="short">rev.</term> - <term name="review-book" form="short">bk. rev.</term> - <term name="song" form="short">audio rec.</term> + <term name="manuscript" form="short">ms</term> + <term name="motion_picture" form="short">enr. vidéo</term> + <term name="report" form="short">rap.</term> + <term name="review" form="short">recens.</term> + <term name="review-book" form="short">recens. de liv.</term> + <term name="song" form="short">enr. audio</term> <!-- HISTORICAL ERA TERMS --> <term name="ad">apr. J.-C.</term> <term name="bc">av. J.-C.</term> - <term name="bce">BCE</term> - <term name="ce">CE</term> + <term name="bce">av. n. è.</term> + <term name="ce">n. è.</term> <!-- PUNCTUATION --> <term name="open-quote">« </term> @@ -163,15 +166,15 @@ <term name="open-inner-quote">“</term> <term name="close-inner-quote">”</term> <term name="page-range-delimiter">‑</term> <!-- non-breaking hyphen --> - <term name="colon">:</term> + <term name="colon"> :</term> <term name="comma">,</term> - <term name="semicolon">;</term> + <term name="semicolon"> ;</term> <!-- ORDINALS --> <term name="ordinal">ᵉ</term> <term name="ordinal-01" gender-form="feminine" match="whole-number">ʳᵉ</term> <term name="ordinal-01" gender-form="masculine" match="whole-number">ᵉʳ</term> - + <!-- LONG ORDINALS --> <term name="long-ordinal-01">premier</term> <term name="long-ordinal-02">deuxième</term> @@ -185,49 +188,49 @@ <term name="long-ordinal-10">dixième</term> <!-- LONG LOCATOR FORMS --> - <term name="act"> - <single>act</single> - <multiple>acts</multiple> + <term name="act"> + <single>acte</single> + <multiple>actes</multiple> </term> - <term name="appendix"> - <single>appendix</single> - <multiple>appendices</multiple> + <term name="appendix"> + <single>appendice</single> + <multiple>appendices</multiple> </term> - <term name="article-locator"> + <term name="article-locator"> <single>article</single> - <multiple>articles</multiple> + <multiple>articles</multiple> </term> - <term name="canon"> + <term name="canon"> <single>canon</single> - <multiple>canons</multiple> + <multiple>canons</multiple> </term> - <term name="elocation"> - <single>location</single> - <multiple>locations</multiple> + <term name="elocation"> + <single>emplacement</single> + <multiple>emplacements</multiple> </term> - <term name="equation"> - <single>equation</single> - <multiple>equations</multiple> + <term name="equation"> + <single>équation</single> + <multiple>équations</multiple> </term> - <term name="rule"> - <single>rule</single> - <multiple>rules</multiple> + <term name="rule"> + <single>règle</single> + <multiple>règles</multiple> </term> - <term name="scene"> - <single>scene</single> - <multiple>scenes</multiple> + <term name="scene"> + <single>scène</single> + <multiple>scènes</multiple> </term> - <term name="table"> - <single>table</single> - <multiple>tables</multiple> + <term name="table"> + <single>tableau</single> + <multiple>tableaux</multiple> </term> <term name="timestamp"> <!-- generally blank --> <single></single> - <multiple></multiple> + <multiple></multiple> </term> - <term name="title-locator"> - <single>title</single> - <multiple>titles</multiple> + <term name="title-locator"> + <single>titre</single> + <multiple>titres</multiple> </term> <term name="book"> <single>livre</single> @@ -299,41 +302,41 @@ </term> <!-- SHORT LOCATOR FORMS --> - <term name="appendix"> - <single>app.</single> - <multiple>apps.</multiple> + <term name="appendix"> + <single>append.</single> + <multiple>append.</multiple> </term> - <term name="article-locator"> + <term name="article-locator"> <single>art.</single> - <multiple>arts.</multiple> + <multiple>art.</multiple> </term> - <term name="elocation"> - <single>loc.</single> - <multiple>locs.</multiple> + <term name="elocation"> + <single>emplact</single> + <multiple>emplact</multiple> </term> - <term name="equation"> + <term name="equation"> <single>eq.</single> - <multiple>eqs.</multiple> + <multiple>eq.</multiple> </term> - <term name="rule"> - <single>r.</single> - <multiple>rr.</multiple> + <term name="rule"> + <single>règle</single> + <multiple>règles</multiple> </term> - <term name="scene"> + <term name="scene"> <single>sc.</single> - <multiple>scs.</multiple> + <multiple>sc.</multiple> </term> - <term name="table"> - <single>tbl.</single> - <multiple>tbls.</multiple> + <term name="table"> + <single>tab.</single> + <multiple>tab.</multiple> </term> <term name="timestamp"> <!-- generally blank --> <single></single> - <multiple></multiple> + <multiple></multiple> </term> - <term name="title-locator"> + <term name="title-locator"> <single>tit.</single> - <multiple>tits.</multiple> + <multiple>tit.</multiple> </term> <term name="book" form="short">liv.</term> <term name="chapter" form="short">chap.</term> @@ -386,56 +389,56 @@ <!-- LONG ROLE FORMS --> <term name="chair"> - <single>chair</single> - <multiple>chairs</multiple> + <single>président</single> + <multiple>présidents</multiple> </term> <term name="compiler"> - <single>compiler</single> - <multiple>compilers</multiple> + <single>compilateur</single> + <multiple>compilateurs</multiple> </term> <term name="contributor"> - <single>contributor</single> - <multiple>contributors</multiple> + <single>contributeur</single> + <multiple>contributeurs</multiple> </term> <term name="curator"> - <single>curator</single> - <multiple>curators</multiple> + <single>commissaire</single> + <multiple>commissaires</multiple> </term> <term name="executive-producer"> - <single>executive producer</single> - <multiple>executive producers</multiple> + <single>producteur exécutif</single> + <multiple>producteurs exécutifs</multiple> </term> <term name="guest"> - <single>guest</single> - <multiple>guests</multiple> + <single>invité</single> + <multiple>invités</multiple> </term> <term name="host"> - <single>host</single> - <multiple>hosts</multiple> + <single>hôte</single> + <multiple>hôtes</multiple> </term> <term name="narrator"> - <single>narrator</single> - <multiple>narrators</multiple> + <single>narrateur</single> + <multiple>narrateurs</multiple> </term> <term name="organizer"> - <single>organizer</single> - <multiple>organizers</multiple> + <single>organisateur</single> + <multiple>organisateurs</multiple> </term> <term name="performer"> - <single>performer</single> - <multiple>performers</multiple> + <single>interprète</single> + <multiple>interprètes</multiple> </term> <term name="producer"> - <single>producer</single> - <multiple>producers</multiple> + <single>producteur</single> + <multiple>producteurs</multiple> </term> <term name="script-writer"> - <single>writer</single> - <multiple>writers</multiple> + <single>scénariste</single> + <multiple>scénaristes</multiple> </term> <term name="series-creator"> - <single>series creator</single> - <multiple>series creators</multiple> + <single>créateur de série</single> + <multiple>créateurs de série</multiple> </term> <term name="director"> <single>réalisateur</single> @@ -464,44 +467,44 @@ <!-- SHORT ROLE FORMS --> <term name="compiler" form="short"> - <single>comp.</single> - <multiple>comps.</multiple> + <single>compil.</single> + <multiple>compil.</multiple> </term> <term name="contributor" form="short"> <single>contrib.</single> - <multiple>contribs.</multiple> + <multiple>contrib.</multiple> </term> <term name="curator" form="short"> - <single>cur.</single> - <multiple>curs.</multiple> + <single>commiss.</single> + <multiple>commiss.</multiple> </term> <term name="executive-producer" form="short"> - <single>exec. prod.</single> - <multiple>exec. prods.</multiple> + <single>prod. exé.</single> + <multiple>prod. exé.</multiple> </term> <term name="narrator" form="short"> <single>narr.</single> - <multiple>narrs.</multiple> + <multiple>narr.</multiple> </term> <term name="organizer" form="short"> <single>org.</single> - <multiple>orgs.</multiple> + <multiple>org.</multiple> </term> <term name="performer" form="short"> - <single>perf.</single> - <multiple>perfs.</multiple> + <single>interpr.</single> + <multiple>interpr.</multiple> </term> <term name="producer" form="short"> <single>prod.</single> - <multiple>prods.</multiple> + <multiple>prod.</multiple> </term> <term name="script-writer" form="short"> - <single>writ.</single> - <multiple>writs.</multiple> + <single>scénar.</single> + <multiple>scénar.</multiple> </term> <term name="series-creator" form="short"> - <single>cre.</single> - <multiple>cres.</multiple> + <single>créat.</single> + <multiple>créat.</multiple> </term> <term name="director" form="short"> <single>réal.</single> @@ -529,19 +532,19 @@ </term> <!-- VERB ROLE FORMS --> - <term name="chair" form="verb">chaired by</term> - <term name="compiler" form="verb">compiled by</term> - <term name="contributor" form="verb">with</term> - <term name="curator" form="verb">curated by</term> - <term name="executive-producer" form="verb">executive produced by</term> - <term name="guest" form="verb">with guest</term> - <term name="host" form="verb">hosted by</term> - <term name="narrator" form="verb">narrated by</term> - <term name="organizer" form="verb">organized by</term> - <term name="performer" form="verb">performed by</term> - <term name="producer" form="verb">produced by</term> - <term name="script-writer" form="verb">written by</term> - <term name="series-creator" form="verb">created by</term> + <term name="chair" form="verb">présidé par</term> + <term name="compiler" form="verb">compilé par</term> + <term name="contributor" form="verb">avec</term> + <term name="curator" form="verb">organisé par</term> + <term name="executive-producer" form="verb">production exécutive par</term> + <term name="guest" form="verb">avec pour invité</term> + <term name="host" form="verb">animé par</term> + <term name="narrator" form="verb">lu par</term> + <term name="organizer" form="verb">organisé par</term> + <term name="performer" form="verb">interprété par</term> + <term name="producer" form="verb">produit par</term> + <term name="script-writer" form="verb">scénario de</term> + <term name="series-creator" form="verb">créé par</term> <term name="container-author" form="verb">par</term> <term name="director" form="verb">réalisé par</term> <term name="editor" form="verb">édité par</term> @@ -554,18 +557,18 @@ <term name="editortranslator" form="verb">édité et traduit par</term> <!-- SHORT VERB ROLE FORMS --> - <term name="compiler" form="verb-short">comp. by</term> - <term name="contributor" form="verb-short">w.</term> - <term name="curator" form="verb-short">cur. by</term> - <term name="executive-producer" form="verb-short">exec. prod. by</term> - <term name="guest" form="verb-short">w. guest</term> - <term name="host" form="verb-short">hosted by</term> - <term name="narrator" form="verb-short">narr. by</term> - <term name="organizer" form="verb-short">org. by</term> - <term name="performer" form="verb-short">perf. by</term> - <term name="producer" form="verb-short">prod. by</term> - <term name="script-writer" form="verb-short">writ. by</term> - <term name="series-creator" form="verb-short">cre. by</term> + <term name="compiler" form="verb-short">compil. par</term> + <term name="contributor" form="verb-short">ac</term> + <term name="curator" form="verb-short">org. par</term> + <term name="executive-producer" form="verb-short">prod. exé. par</term> + <term name="guest" form="verb-short">ac pr inv.</term> + <term name="host" form="verb-short">anim. par</term> + <term name="narrator" form="verb-short">lu par</term> + <term name="organizer" form="verb-short">org. par</term> + <term name="performer" form="verb-short">interpr. par</term> + <term name="producer" form="verb-short">prod. par</term> + <term name="script-writer" form="verb-short">scénar. de</term> + <term name="series-creator" form="verb-short">créé par</term> <term name="director" form="verb-short">réal. par</term> <term name="editor" form="verb-short">éd. par</term> <term name="editorial-director" form="verb-short">ss la dir. de</term> diff --git a/biblio/citation-style-language/csl.lua b/biblio/citation-style-language/csl.lua deleted file mode 100644 index 90f5bea588..0000000000 --- a/biblio/citation-style-language/csl.lua +++ /dev/null @@ -1,143 +0,0 @@ --- --- Copyright (c) 2021-2022 Zeping Lee --- Released under the MIT license. --- Repository: https://github.com/zepinglee/citeproc-lua --- - -local csl = {} - -local citeproc = require("citeproc") -local util = citeproc.util -require("lualibs") -local core = require("csl-core") - - -csl.initialized = "false" -csl.citations = {} -csl.citations_pre = {} - - -function csl.error(str) - luatexbase.module_error("csl", str) -end -function csl.warning(str) - luatexbase.module_warning("csl", str) -end -function csl.info(str) - luatexbase.module_info("csl", str) -end - - -function csl.init(style_name, bib_files, lang) - bib_files = util.split(util.strip(bib_files), "%s*,%s*") - - csl.engine = core.init(style_name, bib_files, lang) - - if csl.engine then - csl.initialized = "true" - else - return - end - - -- csl.init is called via \AtBeginDocument and it's executed after - -- loading .aux file. The csl.ids are already registered. - csl.citation_strings = core.process_citations(csl.engine, csl.citations) - csl.style_class = csl.engine:get_style_class() - - for _, citation in ipairs(csl.citations) do - local citation_id = citation.citationID - local citation_str = csl.citation_strings[citation_id] - local bibcite_command = string.format("\\bibcite{%s}{{%s}{%s}}", citation.citationID, csl.style_class, citation_str) - tex.sprint(bibcite_command) - end - -end - - -function csl.register_citation_info(citation_info) - local citation = core.make_citation(citation_info) - table.insert(csl.citations, citation) -end - - -function csl.enable_linking() - csl.engine:enable_linking() -end - - -function csl.cite(citation_info) - if not csl.engine then - csl.error("CSL engine is not initialized.") - end - - local citation = core.make_citation(citation_info) - - local res = csl.engine:processCitationCluster(citation, csl.citations_pre, {}) - - local citation_str - for _, citation_res in ipairs(res[2]) do - local citation_id = citation_res[3] - -- csl.citation_strings[citation_id] = citation_res[2] - if citation_id == citation.citationID then - citation_str = citation_res[2] - end - end - tex.sprint(citation_str) - - table.insert(csl.citations_pre, {citation.citationID, citation.properties.noteIndex}) -end - - -function csl.nocite(ids_string) - local cite_ids = util.split(ids_string, "%s*,%s*") - if csl.engine then - local ids = {} - for _, cite_id in ipairs(cite_ids) do - if cite_id == "*" then - for item_id, _ in pairs(core.bib) do - table.insert(ids, item_id) - end - else - table.insert(ids, cite_id) - end - end - csl.engine:updateUncitedItems(ids) - else - -- `\nocite` in preamble, where csl.engine is not initialized yet - for _, cite_id in ipairs(cite_ids) do - if cite_id == "*" then - core.uncite_all_items = true - else - if not core.loaded_ids[cite_id] then - table.insert(core.ids, cite_id) - core.loaded_ids[cite_id] = true - end - end - end - end -end - - -function csl.bibliography() - if not csl.engine then - csl.error("CSL engine is not initialized.") - return - end - - -- if csl.include_all_items then - -- for id, _ in pairs(csl.bib) do - -- if not csl.loaded_ids[id] then - -- table.insert(csl.ids, id) - -- csl.loaded_ids[id] = true - -- end - -- end - -- end - -- csl.engine:updateItems(csl.ids) - - local result = core.make_bibliography(csl.engine) - - tex.print(util.split(result, "\n")) -end - - -return csl diff --git a/biblio/citation-style-language/harvard-cite-them-right.csl b/biblio/citation-style-language/harvard-cite-them-right.csl index 2800678205..360f0833c6 100644 --- a/biblio/citation-style-language/harvard-cite-them-right.csl +++ b/biblio/citation-style-language/harvard-cite-them-right.csl @@ -1,10 +1,10 @@ <?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="sort-only" default-locale="en-GB"> <info> - <title>Cite Them Right 11th edition - Harvard</title> + <title>Cite Them Right 12th edition - Harvard</title> <id>http://www.zotero.org/styles/harvard-cite-them-right</id> <link href="http://www.zotero.org/styles/harvard-cite-them-right" rel="self"/> - <link href="http://www.zotero.org/styles/harvard-cite-them-right-10th-edition" rel="template"/> + <link href="http://www.zotero.org/styles/harvard-cite-them-right-11th-edition" rel="template"/> <link href="http://www.citethemrightonline.com/" rel="documentation"/> <author> <name>Patrick O'Brien</name> @@ -12,7 +12,7 @@ <category citation-format="author-date"/> <category field="generic-base"/> <summary>Harvard according to Cite Them Right, 11th edition.</summary> - <updated>2021-09-01T07:43:59+00:00</updated> + <updated>2022-06-28T22:44:10-04:00</updated> <rights license="http://creativecommons.org/licenses/by-sa/3.0/">This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 License</rights> </info> <locale xml:lang="en-GB"> @@ -34,7 +34,7 @@ <choose> <if variable="container-author" match="none"> <names variable="editor translator" delimiter=", "> - <name and="text" initialize-with="." name-as-sort-order="all"/> + <name and="text" initialize-with="."/> <label form="short" prefix=" (" suffix=")"/> </names> </if> @@ -98,7 +98,10 @@ <macro name="access"> <choose> <if variable="DOI"> - <text variable="DOI" prefix="doi:"/> + <group delimiter=": "> + <text term="available at" text-case="capitalize-first"/> + <text variable="DOI" prefix="https://doi.org/"/> + </group> </if> <else-if variable="URL"> <text term="available at" suffix=": " text-case="capitalize-first"/> diff --git a/biblio/citation-style-language/ieee.csl b/biblio/citation-style-language/ieee.csl index a4c76e3d56..bff5b9197e 100644 --- a/biblio/citation-style-language/ieee.csl +++ b/biblio/citation-style-language/ieee.csl @@ -45,7 +45,7 @@ <category field="engineering"/> <category field="generic-base"/> <summary>IEEE style as per the 2021 guidelines, V 01.29.2021.</summary> - <updated>2022-02-05T21:19:36-05:00</updated> + <updated>2021-05-07T00:52:46+10:00</updated> <rights license="http://creativecommons.org/licenses/by-sa/3.0/">This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 License</rights> </info> <locale xml:lang="en"> diff --git a/biblio/citation-style-language/modern-language-association.csl b/biblio/citation-style-language/modern-language-association.csl index 11db55d19a..fcb9845c4c 100644 --- a/biblio/citation-style-language/modern-language-association.csl +++ b/biblio/citation-style-language/modern-language-association.csl @@ -12,7 +12,7 @@ <category citation-format="author"/> <category field="generic-base"/> <summary>This style adheres to the MLA 9th edition handbook. Follows the structure of references as outlined in the MLA Manual closely</summary> - <updated>2022-01-23T06:46:03-05:00</updated> + <updated>2022-04-24T09:59:40-04:00</updated> <rights license="http://creativecommons.org/licenses/by-sa/3.0/">This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 License</rights> </info> <locale xml:lang="en"> @@ -205,7 +205,7 @@ <if type="book chapter paper-conference motion_picture" match="any"> <date variable="issued" form="numeric" date-parts="year"/> </if> - <else-if type="article-journal article-magazine" match="any"> + <else-if type="article-journal" match="any"> <date variable="issued" form="text" date-parts="year-month"/> </else-if> <else-if type="speech" match="none"> diff --git a/biblio/citation-style-language/nature.csl b/biblio/citation-style-language/nature.csl index 2646cfe922..08d9db6ae9 100644 --- a/biblio/citation-style-language/nature.csl +++ b/biblio/citation-style-language/nature.csl @@ -15,7 +15,7 @@ <category field="generic-base"/> <issn>0028-0836</issn> <eissn>1476-4687</eissn> - <updated>2019-10-08T13:18:12+00:00</updated> + <updated>2022-07-02T09:18:26-04:00</updated> <rights license="http://creativecommons.org/licenses/by-sa/3.0/">This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 License</rights> </info> <macro name="title"> @@ -37,7 +37,7 @@ </macro> <macro name="access"> <choose> - <if variable="volume"/> + <if variable="volume" type="article" match="any"/> <else-if variable="DOI"> <text variable="DOI" prefix="doi:"/> </else-if> @@ -55,6 +55,28 @@ </group> </group> </if> + <else-if type="article"> + <group delimiter=" "> + <choose> + <if variable="genre" match="any"> + <text variable="genre" text-case="capitalize-first"/> + </if> + <else> + <text term="article" text-case="capitalize-first"/> + </else> + </choose> + <text term="at"/> + <choose> + <if variable="DOI" match="any"> + <text variable="DOI" prefix="https://doi.org/"/> + </if> + <else> + <text variable="URL"/> + </else> + </choose> + <date date-parts="year" form="text" variable="issued" prefix="(" suffix=")"/> + </group> + </else-if> <else-if type="report webpage post post-weblog" match="any"> <group delimiter=" "> <text variable="URL"/> diff --git a/biblio/citation-style-language/vancouver.csl b/biblio/citation-style-language/vancouver.csl index edbb69b411..71c9203228 100644 --- a/biblio/citation-style-language/vancouver.csl +++ b/biblio/citation-style-language/vancouver.csl @@ -1,5 +1,5 @@ <?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="sort-only" page-range-format="minimal"> +<style xmlns="http://purl.org/net/xbiblio/csl" class="in-text" version="1.0" demote-non-dropping-particle="sort-only" initialize-with-hyphen="false" page-range-format="minimal"> <info> <title>Vancouver</title> <id>http://www.zotero.org/styles/vancouver</id> diff --git a/graphics/pgf/contrib/fancyqr/README.md b/graphics/pgf/contrib/fancyqr/README.md new file mode 100644 index 0000000000..ebb2173348 --- /dev/null +++ b/graphics/pgf/contrib/fancyqr/README.md @@ -0,0 +1,36 @@ +# fancyqr + +[![made-with-latex](https://img.shields.io/badge/Made%20with-LaTeX-1f425f.svg)](https://www.latex-project.org/) [![GPLv3 License](https://img.shields.io/badge/License-GPL%20v3-yellow.svg)](https://opensource.org/licenses/GPL-3.0) [![PR's Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat)](http://makeapullrequest.com) [![compile qr](https://github.com/EagleoutIce/fancyqr/actions/workflows/compile.yaml/badge.svg)](https://github.com/EagleoutIce/fancyqr/actions/workflows/compile.yaml) + +[<img src="https://github.com/EagleoutIce/fancyqr/blob/gh-pages/preview-1.png?raw=true" width="600"/>](qr-example.tex) + +Simple package to create fancy qr-codes with the help of the [`qrcode`](https://www.ctan.org/pkg/qrcode)-package. +You may use `\fancyqr` just like the normal `\qrcode` (`\fancyqr[<qr-options>]{<url>}`). See the [documentation](https://media.githubusercontent.com/media/EagleoutIce/fancyqr/blob/gh-pages/build/fancyqr-doc.pdf). + +*fancyqr* is actively developed by *Florian Sihler* (contact me at: <florian.sihler@uni-ulm.de>) under the [GPLv3 License](LICENSE). I am very happy about every contribution (see [CONTRIBUTING.md](CONTRIBUTING.md)). + +If you do want to hide a center square (e.g, because you want to embed an image) you can use `\FancyQrDoNotPrintSquare{<x>}{<y>}` to hide a rectangle with radius x and y set from the center. If you choose this option, the default `\FancyQrRoundCut` that rounds cut corners can be changed with `\FancyQrHardCut`. +At the moment, there are six other styles `flat`, `frame`, `blob`, `glitch`, `swift`, and `dots`, that you can load (locally) by using `\FancyQrLoad{<name>}`. The default style is named `default` and can be 'reset' by `\FancyQrLoad{default}` or `\FancyLoadDefault`. + +There are the following extra qr-options (you can set all of them with `\fancyqrset{<keys>}`): +| Option | Type | Default | Explanation | +| ----------------- | ------- | :------: | ---------------------------------------------------------- | +| `image` | LaTeX | | Automatically center an image.[^1] | +| `image padding` | number | | Additionally hide blocks (x & y) around the image. | +| `image x padding` | number | `0` | Additionally hide blocks (x) around the image. | +| `image y padding` | number | `0` | Additionally hide blocks (y) around the image. | +| `gradient` | boolean | true | Toggle the color gradient | +| `color` | color | | Disables the `gradient` and sets the qr color accordingly. | +| `l color` | color | `purple` | Set the top left gradient color. | +| `left color` | color | | Alias for `l color`. | +| `r color` | color | `teal` | Set the bottom right gradient color. | +| `right color` | color | | Alias for `r color`. | +| `gradient angle` | angle | `135` | Change the gradient angle. | + +The defaults are set like this: + +```LateX +\fancyqrset{image padding=0,gradient=true,gradient angle=135,r color=teal,l color=purple} +``` + +[^1]: The package will automatically calculate the required `\FancyQrDoNotPrintSquare` (you have to make sure the, the qr code still has enough information to be readable). Therefore, the image will not scale with the qr code. diff --git a/graphics/pgf/contrib/fancyqr/fancyqr-doc.pdf b/graphics/pgf/contrib/fancyqr/fancyqr-doc.pdf Binary files differnew file mode 100644 index 0000000000..c2a0ae9661 --- /dev/null +++ b/graphics/pgf/contrib/fancyqr/fancyqr-doc.pdf diff --git a/graphics/pgf/contrib/fancyqr/fancyqr-doc.tex b/graphics/pgf/contrib/fancyqr/fancyqr-doc.tex new file mode 100644 index 0000000000..40712060b9 --- /dev/null +++ b/graphics/pgf/contrib/fancyqr/fancyqr-doc.tex @@ -0,0 +1,87 @@ +% Florian Sihler, 2022 +% Licensed under GNU General Public License version 3 +% https://opensource.org/licenses/gpl-3.0.html +\documentclass[parskip=half,english,numbers=noenddot,footnotes=nomultiple,oneside]{scrartcl} + +\usepackage[T1]{fontenc} +\usepackage[utf8]{inputenc} +\usepackage{babel} + +\usepackage{microtype} +\usepackage[hidelinks]{hyperref} + +\usepackage{lmodern} +\usepackage{array,booktabs} +\usepackage{footnote} +\usepackage{fontawesome} + +\usepackage{fancyqr} +\usepackage{xcolor} +\usepackage[tex]{listings} + +\lstdefinelanguage{ltx}{ + language={[LaTeX]TeX}, + moretexcs=[1]{fancyqr,qrcode,FancyQrDoNotPrintSquare,FancyQrRoundCut,FancyQrHardCut,FancyQrLoad,FancyLoadDefault,fancyqrset,faGithub} +} +\lstset{basicstyle=\ttfamily,breaklines,texcsstyle=*\color{purple}\bfseries,language=ltx} +\lstMakeShortInline| +\def\ltx#1{\lstinline/#1/} +\interfootnotelinepenalty=10000 + + +\title{The \texttt{fancyqr} package} +\author{% + \texorpdfstring{Florian Sihler\medskip\\* + \fancyqr{https://github.com/EagleoutIce/fancyqr} + }{Florian Sihler}} +\date{Version v1.0 \textendash\ 2022/08/18} + + +\begin{document} + \maketitle + + + \texttt{fancyqr} is a simple package to create fancy qr codes with the help of the \textit{\href{https://www.ctan.org/pkg/qrcode}{qrcode}}-package. + You can use the |\fancyqr|-macro just like the normal |\qrcode|.\footnote{\ltx{\\fancyqr[<qr-options>]\{<url>\}}} + + If you do want to hide a center square (e.g, because you want to embed an image) you can use |\FancyQrDoNotPrintSquare{<x>}{<y>}| to hide a rectangle with radius x and y set from the center. If you choose this option, the default |\FancyQrRoundCut| that rounds cut corners can be changed with |\FancyQrHardCut|. + At the moment, there are six other styles for the qr-code |flat|, |frame|, |blob|, |glitch|, |swift|, and |dots|, that you can load (locally) by using |\FancyQrLoad{<name>}|. The default style is named |default| and can be 'reset' by |\FancyQrLoad{default}| or |\FancyLoadDefault|. + + All of the extra qr-options (you can set all of them with |\fancyqrset{<keys>}|) are showcased in \autoref{tbl:extra-keys}. + The defaults are set like this: +\begin{lstlisting} +\fancyqrset{image padding=0,gradient=true, + gradient angle=135,r color=teal,l color=purple} +\end{lstlisting} + Consider the following example (uses \href{https://www.ctan.org/pkg/fontawesome}{fontawesome} for the symbol, but you can use include images,~\ldots): +\begin{lstlisting} +\fancyqr[image=\huge\faGithub,image padding=1,color=black!90!gray]{https://github.com/EagleoutIce/fancyqr} +\end{lstlisting} + + \parbox[c]{.3\linewidth}{Which produces:}\hfill\parbox[c]{.4\linewidth}{\raggedleft\fancyqr[image=\Huge\faGithub,image padding=1,color=black!90!gray]{https://github.com/EagleoutIce/fancyqr}}\par + + \begin{savenotes} + \begin{table} + \centering\begin{tabular}{>{\ttfamily}ll>{\ttfamily}cp{.5\linewidth}} + \toprule + \multicolumn{1}{l}{Option} & Type & \multicolumn{1}{c}{Default} & Explanation \\ + \midrule + image & \LaTeX & & Automatically center an image.\footnote{The package will automatically calculate the required \ltx{\\FancyQrDoNotPrintSquare} (you have to make sure that the qr code still has enough information to be readable). Therefore, the image will not scale with the qr code.} \\ + image padding & number & & Additionally hide blocks (x \& y) around the image. \\ + image x padding & number & 0 & Additionally hide blocks (x) around the image. \\ + image y padding & number & 0 & Additionally hide blocks (y) around the image. \\ + gradient & boolean & true & Toggle the color gradient \\ + color & color & & Disables the |gradient| and sets the color accordingly. \\ + l color & color & purple & Set the top left gradient color. \\ + left color & color & & Alias for |l color|. \\ + r color & color & teal & Set the bottom right gradient color. \\ + right color & color & & Alias for |r color|. \\ + gradient angle & angle & 135 & Change the gradient angle. \\ + \bottomrule + \end{tabular} + \caption{Overview of special qr-options.} + \label{tbl:extra-keys} + \end{table} + \end{savenotes} + +\end{document}
\ No newline at end of file diff --git a/graphics/pgf/contrib/fancyqr/fancyqr.sty b/graphics/pgf/contrib/fancyqr/fancyqr.sty new file mode 100644 index 0000000000..e727b5e039 --- /dev/null +++ b/graphics/pgf/contrib/fancyqr/fancyqr.sty @@ -0,0 +1,235 @@ +% Florian Sihler, 2022 +% Licensed under GNU General Public License version 3 +% https://opensource.org/licenses/gpl-3.0.html +\def\filename{fancyqr} +\ProvidesPackage{\filename}[2022/08/18 version v1.0 Fancy QR-Codes] +\RequirePackage{tikz, qrcode} + +% element +% x: {\the\j}; y: {\the\i} | \@max@x \@max@y +\def\FancyQrColor#1{\if@fancyqr@gradient +\pgfmathsetmacro\angle{Mod(\fancyqr@gradient@angle+225,360)}% rotate to align 0 to the right +\pgfmathsetmacro\gradient{% + % we do rotate the x and y points before color drawing by + % Mod(\fancyqr@gradient@angle,360) with the shifted origin + % Old: #3/2 #4/2 + ((\the\j-\@max@x/2)*cos(\angle) - (\the\i-\@max@y/2)*sin(\angle) + \@max@x/2)/\@max@x * 50% rel x [0,1] + + ((\the\j-\@max@x/2)*sin(\angle) + (\the\i-\@max@y/2)*cos(\angle) + \@max@y/2)/\@max@y * 50% rel y [0,1] + }\@declaredcolor{qr@fancy@gradient@br!\gradient!qr@fancy@gradient@tl}\else\@declaredcolor{qr@fancy@gradient@tl}\fi{#1}} + +% O 1 O +% 2 X 3 +% O 4 O +% uses \@up\@left\@right\@down +\def\GetPattern{% +\ifcsname qcc\@up\@left\@right\@down\endcsname + \csname qcc\@up\@left\@right\@down\endcsname +\else\rule\qr@modulesize\z@\fi} + +\tikzset{qrrc/.style={rounded corners=.5\qr@modulesize},qrrd/.style={fill}} + +% is larger to be compensated by overlaps +\def\qrm{\dimexpr\qr@modulesize+.15\p@\relax} +\long\def\qr@newpattern#1#2#3#4#5{% +\expandafter\def\csname qcc#1#2#3#4\endcsname{% + \parbox[b][\qr@modulesize]\qr@modulesize{\kern-.075\p@\smash{\clap{\tikz[x=\qrm,y=\qrm,inner sep=\z@,outer sep=\z@]{\path[qrrd]#5;}}}}% +}} + +\def\FancyLoadDefault{% +% . +\qr@newpattern0000{[qrrc](0,0)rectangle(\qrm,\qrm)}% +% | | - - +\qr@newpattern1000{(0,\qrm)[qrrc]--(0,0)--(\qrm,0)[sharp corners]--(\qrm,\qrm)--cycle}% +\qr@newpattern0001{(0,0)[qrrc]--(0,\qrm)--(\qrm,\qrm)[sharp corners]--(\qrm,0)--cycle}% +\qr@newpattern0100{(0,0)[qrrc]--(\qrm,0)--(\qrm,\qrm)[sharp corners]--(0,\qrm)--cycle}% +\qr@newpattern0010{(\qrm,0)[qrrc]--(0,0)--(0,\qrm)[sharp corners]--(\qrm,\qrm)--cycle}% +% corners +\qr@newpattern1100{(\qrm,\qrm)[qrrc]--(\qrm,0)[sharp corners]--(0,0)--(0,\qrm)--cycle}% top left +\qr@newpattern1010{(0,\qrm)[qrrc]--(0,0)[sharp corners]--(\qrm,0)--(\qrm,\qrm)--cycle}% top right +\qr@newpattern0101{(0,\qrm)[qrrc]--(\qrm,\qrm)[sharp corners]--(\qrm,0)--(0,0)--cycle}% bottom left +\qr@newpattern0011{(0,0)[qrrc]--(0,\qrm)[sharp corners]--(\qrm,\qrm)--(\qrm,0)--cycle}% bottom right +% straights | -- +\qr@newpattern1001{(0,0)rectangle(\qrm,\qrm)}% +\qr@newpattern0110{(0,0)rectangle(\qrm,\qrm)}% +% enclosed +\qr@newpattern1111{(0,0)rectangle(\qrm,\qrm)}% +% t's +\qr@newpattern0111{(0,0)rectangle(\qrm,\qrm)}% +\qr@newpattern1011{(0,0)rectangle(\qrm,\qrm)}% +\qr@newpattern1101{(0,0)rectangle(\qrm,\qrm)}% +\qr@newpattern1110{(0,0)rectangle(\qrm,\qrm)}% +} +\FancyLoadDefault % allows to reset the style after other loads +\def\@fancy@qr@default@name{default} + +\def\FancyQrLoad#1{\let\@tmp\newpattern\let\newpattern\qr@newpattern\@bsphack\def\@@tmp{#1}\ifx\@@tmp\@fancy@qr@default@name\FancyLoadDefault\else +\expandafter\edef\csname pingu@lib@#1@atcode\endcsname{\the\catcode`\@}% +\catcode`\@=11\relax +\input{fancyqr-style-#1.code} +\catcode`\@=\csname pingu@lib@#1@atcode\endcsname +\fi\@esphack\let\newpattern\@tmp\let\@tmp\relax} + + +% modify the getter so everything that is not defined is white: +\def\fancy@qr@matrixentry#1#2#3{% + \ifcsname #1@#2@#3\endcsname + % #1 = matrix name + % #2 = row number + % #3 = column number + \csname #1@#2@#3\endcsname + \else\qr@white@format\fi +}% + +\def\FancyQrDoNotPrintSquare#1#2{\def\fancy@qr@donotprint@center@x{#1}\def\fancy@qr@donotprint@center@y{#2}} +\FancyQrDoNotPrintSquare00 + +\newif\iffancy@qr@do@print@ +\def\qr@fancy@updateif#1#2{\fancy@qr@do@print@true +\ifnum#1>\@do@y@min\relax \ifnum#1<\@do@y@max\relax \ifnum#2>\@do@x@min\relax \ifnum#2<\@do@x@max\relax \fancy@qr@do@print@false \fi\fi\fi\fi} + +\newif\iffancy@qr@roundcut@ +\fancy@qr@roundcut@true +\let\FancyQrHardCut\fancy@qr@roundcut@false +\let\FancyQrRoundCut\fancy@qr@roundcut@true + +% clear plus if not to be printed +\def\qr@fancy@clear@surround#1#2#3{% + \qr@fancy@updateif{\the\numexpr#2-1}{#3}% + \iffancy@qr@do@print@\else \expandafter\let\csname #1@\the\numexpr#2-1 @#3\endcsname\@undefined \fi + \qr@fancy@updateif{\the\numexpr#2+1}{#3}% + \iffancy@qr@do@print@\else \expandafter\let\csname #1@\the\numexpr#2+1 @#3\endcsname\@undefined \fi + \qr@fancy@updateif{#2}{\the\numexpr#3-1}% + \iffancy@qr@do@print@\else \expandafter\let\csname #1@#2@\the\numexpr#3-1\endcsname\@undefined \fi + \qr@fancy@updateif{#2}{\the\numexpr#3+1}% + \iffancy@qr@do@print@\else \expandafter\let\csname #1@#2@\the\numexpr#3+1\endcsname\@undefined \fi +} + +\newif\if@fancyqr@image@ + +\def\fancy@qr@printmatrix#1{% + \def\qr@white{0}\def\qr@black{1}% + \let\qr@black@fixed\qr@black + \let\qr@white@fixed\qr@white + \let\qr@black@format\qr@black + \let\qr@white@format\qr@white + %Set module size + \qr@modulesize=\qr@desiredheight + \divide\qr@modulesize by \qr@size\relax + \qr@minipagewidth=\qr@modulesize + \if@fancyqr@image@% image is in \fancyqr@imgbox + \pgfmathsetmacro\@x{int(ceil((.5\wd\fancyqr@imgbox)/\qr@modulesize)+\fancyqr@img@padding@x)}% + \pgfmathsetmacro\@y{int(ceil((.5\ht\fancyqr@imgbox+.5\dp\fancyqr@imgbox)/\qr@modulesize)+\fancyqr@img@padding@y)}% + \FancyQrDoNotPrintSquare\@x\@y + \fi + \multiply\qr@minipagewidth by \qr@size\relax + \ifqr@tight \else \advance\qr@minipagewidth by 8\qr@modulesize \fi + \minipage\qr@minipagewidth + \baselineskip=\qr@modulesize + \ifqr@tight\else\rule\z@{4\qr@modulesize}\par\fi% %Blank space at top. + \edef\@max@x{\qr@numberofrowsinmatrix{#1}}% + \edef\@max@y{\qr@numberofcolsinmatrix{#1}}% + \edef\@do@x@min{\the\numexpr\@max@x/2-\fancy@qr@donotprint@center@x-1}% + \edef\@do@x@max{\the\numexpr\@max@x/2+\fancy@qr@donotprint@center@x+1}% + \edef\@do@y@min{\the\numexpr\@max@y/2-\fancy@qr@donotprint@center@y-1}% + \edef\@do@y@max{\the\numexpr\@max@y/2+\fancy@qr@donotprint@center@y+1}% + \qr@for \i=1 to \@max@y by 1{% + \ifqr@tight\else\rule{4\qr@modulesize}\z@\fi% %Blank space at left. + \qr@for \j=1 to \@max@x by 1{% + \qr@fancy@updateif\i\j + \iffancy@qr@do@print@ + \edef\@mid{\qr@matrixentry{#1}{\the\i}{\the\j}}% + \ifnum\@mid=\qr@white + \rule\qr@modulesize\z@ + \else% if not white, get its pattern + \iffancy@qr@roundcut@\qr@fancy@clear@surround{#1}{\the\i}{\the\j}\fi + \edef\@up{\qr@matrixentry{#1}{\the\numexpr\the\i-1}{\the\j}}% + \edef\@left{\qr@matrixentry{#1}{\the\i}{\the\numexpr\the\j-1}}% + \edef\@right{\qr@matrixentry{#1}{\the\i}{\the\numexpr\the\j+1}}% + \edef\@down{\qr@matrixentry{#1}{\the\numexpr\the\i+1}{\the\j}}% + \FancyQrColor{\GetPattern}% + \fi\else \rule\qr@modulesize\z@\fi + }\par}% + \ifqr@tight\else\rule\z@{4\qr@modulesize}\par\fi + \endminipage + \if@fancyqr@image@\nobreak + \llap{\parbox\qr@minipagewidth{\centering\usebox\fancyqr@imgbox}}\fi +}% + +\def\fancy@qr@setup#1{% + \qr@creatematrix{#1}% + \expandafter\gdef\csname #1@numrows\endcsname{\qr@size}% + \expandafter\gdef\csname #1@numcols\endcsname{\qr@size}% + % we do not need to create blank because we store all + \qr@placefinderpatterns{#1}% + \qr@placetimingpatterns{#1}% + \qr@placealignmentpatterns{#1}% +} + +\newcount\c@fancy@a \newcount\c@fancy@b +% the normal data is... well... +\def\fancy@qr@writedata#1#2{% + % #1 = name of a matrix that has been prepared with finder patterns, timing patterns, etc. + % #2 = a string consisting of 0's and 1's to write into the matrix. + \expandafter\c@fancy@a\the\numexpr\qr@numberofrowsinmatrix{#1}\relax + \expandafter\c@fancy@b\the\numexpr\qr@numberofcolsinmatrix{#1}\relax + \edef\qr@datatowrite{#2\relax}% + \c@qr@i0\relax + \@whilenum\c@qr@i<\c@fancy@a\do{% + \c@qr@j0 \advance\c@qr@i\@ne + \@whilenum\c@qr@j<\c@fancy@b\do{% + \advance\c@qr@j\@ne + \expandafter\fancy@qr@writebit\qr@datatowrite:{#1}% + }% + }% +} + +\def\fancy@qr@writebit#1#2:#3{% + % #3 = matrix name + % (qr@i,qr@j) = position to write in (LaTeX counters) + % #1 = bit to be written + % #2 = remaining bits plus '\relax' as an end-of-file marker + \edef\qr@datatowrite{#2}% + \ifnum#1=1 + \qr@storetomatrix{#3}{\number\c@qr@i}{\number\c@qr@j}{\qr@black}% + \else + \qr@storetomatrix{#3}{\number\c@qr@i}{\number\c@qr@j}{\qr@white}% + \fi +}% + + +\def\fancy@qr@printsavedbinarymatrix#1{% + \def\qr@binarystring{#1\relax\relax}% + \fancy@qr@setup{@tmp}% + \fancy@qr@writedata{@tmp}{\qr@binarystring}% + \fancy@qr@printmatrix{@tmp}% +}% + +\newsavebox\fancyqr@imgbox +\define@key{fancyqr}{image x padding}{\def\fancyqr@img@padding@x{#1}} +\define@key{fancyqr}{image y padding}{\def\fancyqr@img@padding@y{#1}} +\define@key{fancyqr}{image padding}{\def\fancyqr@img@padding@x{#1}\def\fancyqr@img@padding@y{#1}} +\define@key{fancyqr}{image}{\@fancyqr@image@true\savebox\fancyqr@imgbox{#1}} +\define@key{fancyqr}{color}{\@fancyqr@gradientfalse\colorlet{qr@fancy@gradient@tl}{#1}} +\define@key{fancyqr}{left color}{\colorlet{qr@fancy@gradient@br}{#1}} +\define@key{fancyqr}{l color}{\colorlet{qr@fancy@gradient@br}{#1}} +\define@key{fancyqr}{right color}{\colorlet{qr@fancy@gradient@tl}{#1}} +\define@key{fancyqr}{r color}{\colorlet{qr@fancy@gradient@tl}{#1}} +\define@key{fancyqr}{gradient angle}{\def\fancyqr@gradient@angle{#1}} +\define@boolkey{fancyqr}[@fancyqr@]{gradient}[true]{}% if@fancyqr@gradient + +\def\fancyqrset#1{\setkeys{qr,fancyqr}{#1}} +\fancyqrset{image padding=0,gradient=true,gradient angle=135,r color=teal,l color=purple} + +\def\@fancyqr@init{\let\qr@printsavedbinarymatrix\fancy@qr@printsavedbinarymatrix\let\qr@matrixentry\fancy@qr@matrixentry\let\qr@printmatrix\fancy@qr@printmatrix} +\def\fancyqr{\@ifstar\s@fancyqr\ns@fancyqr} +% we rebuild some parts of qrcode to allow this macro to extend the keys while keeping the wrapper +\def\s@fancyqr{\qr@starinvokedtrue\@@fancyqr} +\def\ns@fancyqr{\qr@starinvokedfalse\@@fancyqr} +\newcommand\@@fancyqr[1][]{\begingroup\@fancyqr@init +\ifqr@starinvoked\qr@hyperlinkfalse\fi +\setkeys{qr,fancyqr}{#1}\bgroup +\qr@verbatimcatcodes\qr@setescapedspecials\qrcode@in} +\endinput + +% TODO: NEGATIVE PATTERNS IF MIDDLE IS 0 +% => make rounded negative corners
\ No newline at end of file diff --git a/graphics/pgf/contrib/fancyqr/qr-example.tex b/graphics/pgf/contrib/fancyqr/qr-example.tex new file mode 100644 index 0000000000..d58e7f835d --- /dev/null +++ b/graphics/pgf/contrib/fancyqr/qr-example.tex @@ -0,0 +1,25 @@ +% Florian Sihler, 2022 +% Licensed under GNU General Public License version 3 +% https://opensource.org/licenses/gpl-3.0.html +\documentclass{article} + +\usepackage{fontawesome} + +\usepackage{fancyqr} + +\usepackage[active,tightpage]{preview} % for presentation +\setlength\PreviewBorder{15pt} + +\fancyqrset{height=3.25cm,level=H,padding} + +\begin{document} +\preview +% \FancyQrDoNotPrintSquare{8}{9} +% \FancyQrHardCut +\mbox{\FancyQrLoad{blobs} +\fancyqr[image=\scalebox{2.9}{\faGithub\kern1pt},image padding=1,color=black!90!gray]{https://github.com/EagleoutIce/fancyqr} +\FancyQrLoad{default} +\fancyqr{https://github.com/EagleoutIce/fancyqr} +\FancyQrLoad{dots}\fancyqr[image={\tikz\node[align=center,draw]{\huge Ha\\Huhu};},r color=gray,gradient angle=45]{https://github.com/EagleoutIce/fancyqr}}% +\endpreview +\end{document}
\ No newline at end of file diff --git a/macros/texinfo/latest/texinfo.tex b/macros/texinfo/latest/texinfo.tex index 8fc17de28c..c7ebff708f 100644 --- a/macros/texinfo/latest/texinfo.tex +++ b/macros/texinfo/latest/texinfo.tex @@ -3,7 +3,7 @@ % Load plain if necessary, i.e., if running under initex. \expandafter\ifx\csname fmtname\endcsname\relax\input plain\fi % -\def\texinfoversion{2022-04-09.08} +\def\texinfoversion{2022-08-18.14} % % Copyright 1985, 1986, 1988, 1990-2022 Free Software Foundation, Inc. % @@ -2558,7 +2558,7 @@ end \def\it{\fam=\itfam \setfontstyle{it}} \def\sl{\fam=\slfam \setfontstyle{sl}} \def\bf{\fam=\bffam \setfontstyle{bf}}\def\bfstylename{bf} -\def\tt{\fam=\ttfam \setfontstyle{tt}}\def\ttstylename{tt} +\def\tt{\fam=\ttfam \setfontstyle{tt}} % Texinfo sort of supports the sans serif font style, which plain TeX does not. % So we set up a \sf. @@ -2691,6 +2691,14 @@ end % \def\ifmonospace{\ifdim\fontdimen3\font=0pt } +% Check if internal flag is clear, i.e. has not been @set. +\def\ifflagclear#1#2#3{% + \expandafter\ifx\csname SET#1\endcsname\relax + #2\else#3\fi +} + + + { \catcode`\'=\active \catcode`\`=\active @@ -2707,14 +2715,14 @@ end % \def\codequoteright{% \ifmonospace - \expandafter\ifx\csname SETtxicodequoteundirected\endcsname\relax - \expandafter\ifx\csname SETcodequoteundirected\endcsname\relax + \ifflagclear{txicodequoteundirected}{% + \ifflagclear{codequoteundirected}{% '% - \else \char'15 \fi - \else \char'15 \fi - \else - '% - \fi + }{\char'15 }% + }{\char'15 }% + \else + '% + \fi } % % and a similar option for the left quote char vs. a grave accent. @@ -2723,16 +2731,16 @@ end % \def\codequoteleft{% \ifmonospace - \expandafter\ifx\csname SETtxicodequotebacktick\endcsname\relax - \expandafter\ifx\csname SETcodequotebacktick\endcsname\relax + \ifflagclear{txicodequotebacktick}{% + \ifflagclear{codequotebacktick}{% % [Knuth] pp. 380,381,391 % \relax disables Spanish ligatures ?` and !` of \tt font. \relax`% - \else \char'22 \fi - \else \char'22 \fi - \else - \relax`% - \fi + }{\char'22 }% + }{\char'22 }% + \else + \relax`% + \fi } % Commands to set the quote options. @@ -2779,15 +2787,16 @@ end \def\dosmartslant#1#2{% \ifusingtt {{\ttsl #2}\let\next=\relax}% - {\def\next{{#1#2}\futurelet\next\smartitaliccorrection}}% + {\def\next{{#1#2}\smartitaliccorrection}}% \next } \def\smartslanted{\dosmartslant\sl} \def\smartitalic{\dosmartslant\it} -% Output an italic correction unless \next (presumed to be the following -% character) is such as not to need one. -\def\smartitaliccorrection{% +% Output an italic correction unless the following character is such as +% not to need one. +\def\smartitaliccorrection{\futurelet\next\smartitaliccorrectionx} +\def\smartitaliccorrectionx{% \ifx\next,% \else\ifx\next-% \else\ifx\next.% @@ -2798,18 +2807,18 @@ end \aftersmartic } -% Unconditional use \ttsl, and no ic. @var is set to this for defuns. -\def\ttslanted#1{{\ttsl #1}} - -% @cite is like \smartslanted except unconditionally use \sl. We never want -% ttsl for book titles, do we? -\def\cite#1{{\sl #1}\futurelet\next\smartitaliccorrection} +% @cite unconditionally uses \sl with \smartitaliccorrection. +\def\cite#1{{\sl #1}\smartitaliccorrection} +% @var unconditionally uses \sl. This gives consistency for +% parameter names whether they are in @def, @table @code or a +% regular paragraph. +% The \null is to reset \spacefactor. \def\aftersmartic{} \def\var#1{% \let\saveaftersmartic = \aftersmartic \def\aftersmartic{\null\let\aftersmartic=\saveaftersmartic}% - \smartslanted{#1}% + {\sl #1}\smartitaliccorrection } \let\i=\smartitalic @@ -2817,8 +2826,14 @@ end \let\dfn=\smartslanted \let\emph=\smartitalic -% Explicit font changes: @r, @sc, undocumented @ii. -\def\r#1{{\rm #1}} % roman font +% @r for roman font, used for code comment +\def\r#1{{% + \usenormaldash % get --, --- ligatures even if in @code + \defcharsdefault % in case on def line + \rm #1}} +{\catcode`-=\active \gdef\usenormaldash{\let-\normaldash}} + +% @sc, undocumented @ii. \def\sc#1{{\smallcaps#1}} % smallcaps font \def\ii#1{{\it #1}} % italic font @@ -2856,7 +2871,7 @@ end % @t, explicit typewriter. \def\t#1{% - {\tt \plainfrenchspacing #1}% + {\tt \defcharsdefault \plainfrenchspacing #1}% \null } @@ -4432,7 +4447,7 @@ $$% \message{conditionals,} -% @iftex, @ifnotdocbook, @ifnothtml, @ifnotinfo, @ifnotplaintext, +% @iftex, @ifnotdocbook, @ifnothtml, @ifnotinfo, @ifnotlatex, @ifnotplaintext, % @ifnotxml always succeed. They currently do nothing; we don't % attempt to check whether the conditionals are properly nested. But we % have to remember that they are conditionals, so that @end doesn't @@ -4446,6 +4461,7 @@ $$% \makecond{ifnotdocbook} \makecond{ifnothtml} \makecond{ifnotinfo} +\makecond{ifnotlatex} \makecond{ifnotplaintext} \makecond{ifnotxml} @@ -4458,10 +4474,12 @@ $$% \def\ifdocbook{\doignore{ifdocbook}} \def\ifhtml{\doignore{ifhtml}} \def\ifinfo{\doignore{ifinfo}} +\def\iflatex{\doignore{iflatex}} \def\ifnottex{\doignore{ifnottex}} \def\ifplaintext{\doignore{ifplaintext}} \def\ifxml{\doignore{ifxml}} \def\ignore{\doignore{ignore}} +\def\latex{\doignore{latex}} \def\menu{\doignore{menu}} \def\xml{\doignore{xml}} @@ -4985,25 +5003,24 @@ $$% \catcode`\-=13 \catcode`\`=13 \gdef\indexnonalnumdisappear{% - \expandafter\ifx\csname SETtxiindexlquoteignore\endcsname\relax\else + \ifflagclear{txiindexlquoteignore}{}{% % @set txiindexlquoteignore makes us ignore left quotes in the sort term. % (Introduced for FSFS 2nd ed.) \let`=\empty - \fi + }% % - \expandafter\ifx\csname SETtxiindexbackslashignore\endcsname\relax\else + \ifflagclear{txiindexbackslashignore}{}{% \backslashdisappear - \fi - % - \expandafter\ifx\csname SETtxiindexhyphenignore\endcsname\relax\else + }% + \ifflagclear{txiindexhyphenignore}{}{% \def-{}% - \fi - \expandafter\ifx\csname SETtxiindexlessthanignore\endcsname\relax\else + }% + \ifflagclear{txiindexlessthanignore}{}{% \def<{}% - \fi - \expandafter\ifx\csname SETtxiindexatsignignore\endcsname\relax\else + }% + \ifflagclear{txiindexatsignignore}{}{% \def\@{}% - \fi + }% } \gdef\indexnonalnumreappear{% @@ -5295,9 +5312,7 @@ $$% % \atdummies % - \expandafter\ifx\csname SETtxiindexescapeisbackslash\endcsname\relax\else - \escapeisbackslash - \fi + \ifflagclear{txiindexescapeisbackslash}{}{\escapeisbackslash}% % % For texindex which always views { and } as separators. \def\{{\lbracechar{}}% @@ -5481,9 +5496,9 @@ $$% % old index files using \ as the escape character. Reading this would % at best lead to typesetting garbage, at worst a TeX syntax error. \def\printindexzz#1#2\finish{% - \expandafter\ifx\csname SETtxiindexescapeisbackslash\endcsname\relax + \ifflagclear{txiindexescapeisbackslash}{% \uccode`\~=`\\ \uppercase{\if\noexpand~}\noexpand#1 - \expandafter\ifx\csname SETtxiskipindexfileswithbackslash\endcsname\relax + \ifflagclear{txiskipindexfileswithbackslash}{% \errmessage{% ERROR: A sorted index file in an obsolete format was skipped. To fix this problem, please upgrade your version of 'texi2dvi' @@ -5499,15 +5514,15 @@ this, Texinfo will try to use index files in the old format. If you continue to have problems, deleting the index files and starting again might help (with 'rm \jobname.?? \jobname.??s')% }% - \else + }{% (Skipped sorted index file in obsolete format) - \fi + }% \else \begindoublecolumns \input \jobname.\indexname s \enddoublecolumns \fi - \else + }{% \begindoublecolumns \catcode`\\=0\relax % @@ -5517,7 +5532,7 @@ might help (with 'rm \jobname.?? \jobname.??s')% \catcode`\@=0\relax \input \jobname.\indexname s \enddoublecolumns - \fi + }% } % These macros are used by the sorted index file itself. @@ -7277,22 +7292,6 @@ might help (with 'rm \jobname.?? \jobname.??s')% } \let\Eraggedright\par -\envdef\raggedleft{% - \parindent=0pt \leftskip0pt plus2em - \spaceskip.3333em \xspaceskip.5em \parfillskip=0pt - \hbadness=10000 % Last line will usually be underfull, so turn off - % badness reporting. -} -\let\Eraggedleft\par - -\envdef\raggedcenter{% - \parindent=0pt \rightskip0pt plus1em \leftskip0pt plus1em - \spaceskip.3333em \xspaceskip.5em \parfillskip=0pt - \hbadness=10000 % Last line will usually be underfull, so turn off - % badness reporting. -} -\let\Eraggedcenter\par - % @quotation does normal linebreaking (hence we can't use \nonfillstart) % and narrows the margins. We keep \parskip nonzero in general, since @@ -7515,9 +7514,11 @@ might help (with 'rm \jobname.?? \jobname.??s')% % file; b) letting users define the frontmatter in as flexible order as % possible is desirable. % -\def\copying{\checkenv{}\begingroup\scanargctxt\docopying} -\def\docopying#1@end copying{\endgroup\def\copyingtext{#1}} -% +\def\copying{\checkenv{}\begingroup\macrobodyctxt\docopying} +{\catcode`\ =\other +\gdef\docopying#1@end copying{\endgroup\def\copyingtext{#1}} +} + \def\insertcopying{% \begingroup \parindent = 0pt % paragraph indentation looks wrong on title page @@ -7599,21 +7600,15 @@ might help (with 'rm \jobname.?? \jobname.??s')% \def\Edefun{\endgraf\medbreak} -% \makedefun{deffn} creates \deffn, \deffnx and \Edeffn; -% the only thing remaining is to define \deffnheader. +% \makedefun{deffoo}{ (definition of \deffooheader) } % +% Define \deffoo, \deffoox \Edeffoo and \deffooheader. \def\makedefun#1{% \expandafter\let\csname E#1\endcsname = \Edefun \edef\temp{\noexpand\domakedefun \makecsname{#1}\makecsname{#1x}\makecsname{#1header}}% \temp } - -% \domakedefun \deffn \deffnx \deffnheader { (defn. of \deffnheader) } -% -% Define \deffn and \deffnx, without parameters. -% \deffnheader has to be defined explicitly. -% \def\domakedefun#1#2#3{% \envdef#1{% \startdefun @@ -7646,74 +7641,51 @@ might help (with 'rm \jobname.?? \jobname.??s')% \fi\fi } -% \dosubind {index}{topic}{subtopic} -% -% If SUBTOPIC is present, precede it with a space, and call \doind. -% (At some time during the 20th century, this made a two-level entry in an -% index such as the operation index. Nobody seemed to notice the change in -% behaviour though.) -\def\dosubind#1#2#3{% - \def\thirdarg{#3}% - \ifx\thirdarg\empty - \doind{#1}{#2}% - \else - \doind{#1}{#2\space#3}% - \fi -} - % Untyped functions: % @deffn category name args -\makedefun{deffn}{\deffngeneral{}} - -% @deffn category class name args -\makedefun{defop}#1 {\defopon{#1\ \putwordon}} - -% \defopon {category on}class name args -\def\defopon#1#2 {\deffngeneral{\putwordon\ \code{#2}}{#1\ \code{#2}} } +\makedefun{deffn}#1 #2 #3\endheader{% + \doind{fn}{\code{#2}}% + \defname{#1}{}{#2}\magicamp\defunargs{#3\unskip}% +} -% \deffngeneral {subind}category name args -% -\def\deffngeneral#1#2 #3 #4\endheader{% - \dosubind{fn}{\code{#3}}{#1}% - \defname{#2}{}{#3}\magicamp\defunargs{#4\unskip}% +% @defop category class name args +\makedefun{defop}#1 {\defopheaderx{#1\ \putwordon}} +\def\defopheaderx#1#2 #3 #4\endheader{% + \doind{fn}{\code{#3}\space\putwordon\ \code{#2}}% + \defname{#1\ \code{#2}}{}{#3}\magicamp\defunargs{#4\unskip}% } % Typed functions: % @deftypefn category type name args -\makedefun{deftypefn}{\deftypefngeneral{}} +\makedefun{deftypefn}#1 #2 #3 #4\endheader{% + \doind{fn}{\code{#3}}% + \doingtypefntrue + \defname{#1}{#2}{#3}\defunargs{#4\unskip}% +} % @deftypeop category class type name args -\makedefun{deftypeop}#1 {\deftypeopon{#1\ \putwordon}} - -% \deftypeopon {category on}class type name args -\def\deftypeopon#1#2 {\deftypefngeneral{\putwordon\ \code{#2}}{#1\ \code{#2}} } - -% \deftypefngeneral {subind}category type name args -% -\def\deftypefngeneral#1#2 #3 #4 #5\endheader{% - \dosubind{fn}{\code{#4}}{#1}% +\makedefun{deftypeop}#1 {\deftypeopheaderx{#1\ \putwordon}} +\def\deftypeopheaderx#1#2 #3 #4 #5\endheader{% + \doind{fn}{\code{#4}\space\putwordon\ \code{#1\ \code{#2}}}% \doingtypefntrue - \defname{#2}{#3}{#4}\defunargs{#5\unskip}% + \defname{#1\ \code{#2}}{#3}{#4}\defunargs{#5\unskip}% } % Typed variables: % @deftypevr category type var args -\makedefun{deftypevr}{\deftypecvgeneral{}} +\makedefun{deftypevr}#1 #2 #3 #4\endheader{% + \doind{vr}{\code{#3}}% + \defname{#1}{#2}{#3}\defunargs{#4\unskip}% +} % @deftypecv category class type var args -\makedefun{deftypecv}#1 {\deftypecvof{#1\ \putwordof}} - -% \deftypecvof {category of}class type var args -\def\deftypecvof#1#2 {\deftypecvgeneral{\putwordof\ \code{#2}}{#1\ \code{#2}} } - -% \deftypecvgeneral {subind}category type var args -% -\def\deftypecvgeneral#1#2 #3 #4 #5\endheader{% - \dosubind{vr}{\code{#4}}{#1}% - \defname{#2}{#3}{#4}\defunargs{#5\unskip}% +\makedefun{deftypecv}#1 {\deftypecvheaderx{#1\ \putwordof}} +\def\deftypecvheaderx#1#2 #3 #4 #5\endheader{% + \doind{vr}{\code{#4}\space\putwordof\ \code{#2}}% + \defname{#1\ \code{#2}}{#3}{#4}\defunargs{#5\unskip}% } % Untyped variables: @@ -7722,10 +7694,8 @@ might help (with 'rm \jobname.?? \jobname.??s')% \makedefun{defvr}#1 {\deftypevrheader{#1} {} } % @defcv category class var args -\makedefun{defcv}#1 {\defcvof{#1\ \putwordof}} - -% \defcvof {category of}class var args -\def\defcvof#1#2 {\deftypecvof{#1}#2 {} } +\makedefun{defcv}#1 {\defcvheaderx{#1\ \putwordof}} +\def\defcvheaderx#1#2 {\deftypecvheaderx{#1}#2 {} } % Types: @@ -7743,10 +7713,10 @@ might help (with 'rm \jobname.?? \jobname.??s')% \makedefun{defvar}{\defvrheader{\putwordDefvar} } \makedefun{defopt}{\defvrheader{\putwordDefopt} } \makedefun{deftypevar}{\deftypevrheader{\putwordDefvar} } -\makedefun{defmethod}{\defopon\putwordMethodon} -\makedefun{deftypemethod}{\deftypeopon\putwordMethodon} -\makedefun{defivar}{\defcvof\putwordInstanceVariableof} -\makedefun{deftypeivar}{\deftypecvof\putwordInstanceVariableof} +\makedefun{defmethod}{\defopheaderx\putwordMethodon} +\makedefun{deftypemethod}{\deftypeopheaderx\putwordMethodon} +\makedefun{defivar}{\defcvheaderx\putwordInstanceVariableof} +\makedefun{deftypeivar}{\deftypecvheaderx\putwordInstanceVariableof} % \defname, which formats the name of the @def (not the args). % #1 is the category, such as "Function". @@ -7765,9 +7735,7 @@ might help (with 'rm \jobname.?? \jobname.??s')% \rettypeownlinefalse \ifdoingtypefn % doing a typed function specifically? % then check user option for putting return type on its own line: - \expandafter\ifx\csname SETtxideftypefnnl\endcsname\relax \else - \rettypeownlinetrue - \fi + \ifflagclear{txideftypefnnl}{}{\rettypeownlinetrue}% \fi % % How we'll format the category name. Putting it in brackets helps @@ -7832,30 +7800,18 @@ might help (with 'rm \jobname.?? \jobname.??s')% \fi % no return type #3% output function name }% - {\rm\enskip}% hskip 0.5 em of \rmfont + \ifflagclear{txidefnamenospace}{% + {\rm\enskip}% hskip 0.5 em of \rmfont + }{}% % \boldbrax % arguments will be output next, if any. } -% Print arguments in slanted roman (not ttsl), inconsistently with using -% tt for the name. This is because literal text is sometimes needed in -% the argument list (groff manual), and ttsl and tt are not very -% distinguishable. Prevent hyphenation at `-' chars. -% +% Print arguments. Use slanted for @def*, typewriter for @deftype*. \def\defunargs#1{% - % use sl by default (not ttsl), - % tt for the names. - \df \sl \hyphenchar\font=0 - % - % On the other hand, if an argument has two dashes (for instance), we - % want a way to get ttsl. We used to recommend @var for that, so - % leave the code in, but it's strange for @var to lead to typewriter. - % Nowadays we recommend @code, since the difference between a ttsl hyphen - % and a tt hyphen is pretty tiny. @code also disables ?` !`. - \def\var##1{{\setregularquotes\ttslanted{##1}}}% + \df \ifdoingtypefn \tt \else \sl \fi #1% - \sl\hyphenchar\font=45 } % We want ()&[] to print specially on the defun line. @@ -7874,9 +7830,12 @@ might help (with 'rm \jobname.?? \jobname.??s')% % so TeX would otherwise complain about undefined control sequence. { \activeparens - \global\let(=\lparen \global\let)=\rparen - \global\let[=\lbrack \global\let]=\rbrack - \global\let& = \& + \gdef\defcharsdefault{% + \let(=\lparen \let)=\rparen + \let[=\lbrack \let]=\rbrack + \let& = \&% + } + \globaldefs=1 \defcharsdefault \gdef\boldbrax{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb} \gdef\magicamp{\let&=\amprm} @@ -8060,24 +8019,17 @@ might help (with 'rm \jobname.?? \jobname.??s')% \catcode`\_=\other \catcode`\|=\other \catcode`\~=\other - \passthroughcharstrue -} - -\def\scanargctxt{% used for copying and captions, not macros. - \scanctxt \catcode`\@=\other - \catcode`\\=\other \catcode`\^^M=\other + \catcode`\\=\active + \passthroughcharstrue } -\def\macrobodyctxt{% used for @macro definitions +\def\macrobodyctxt{% used for @macro definitions and @copying \scanctxt \catcode`\ =\other - \catcode`\@=\other \catcode`\{=\other \catcode`\}=\other - \catcode`\^^M=\other - \usembodybackslash } % Used when scanning braced macro arguments. Note, however, that catcode @@ -8086,14 +8038,10 @@ might help (with 'rm \jobname.?? \jobname.??s')% \def\macroargctxt{% \scanctxt \catcode`\ =\active - \catcode`\@=\other - \catcode`\^^M=\other - \catcode`\\=\active } \def\macrolineargctxt{% used for whole-line arguments without braces \scanctxt - \catcode`\@=\other \catcode`\{=\other \catcode`\}=\other } @@ -8137,7 +8085,7 @@ might help (with 'rm \jobname.?? \jobname.??s')% \global\expandafter\let\csname ismacro.\the\macname\endcsname=1% \addtomacrolist{\the\macname}% \fi - \begingroup \macrobodyctxt + \begingroup \macrobodyctxt \usembodybackslash \ifrecursive \expandafter\parsermacbody \else \expandafter\parsemacbody \fi} @@ -8941,7 +8889,7 @@ might help (with 'rm \jobname.?? \jobname.??s')% % output the `[mynode]' via the macro below so it can be overridden. \xrefprintnodename\printedrefname % - \expandafter\ifx\csname SETtxiomitxrefpg\endcsname\relax + \ifflagclear{txiomitxrefpg}{% % But we always want a comma and a space: ,\space % @@ -8956,7 +8904,7 @@ might help (with 'rm \jobname.?? \jobname.??s')% \tokenafterxref ,% @NL \else\ifx\tie\tokenafterxref ,% @tie \fi\fi\fi\fi\fi\fi - \fi + }{}% \fi\fi \fi \endlink @@ -9604,7 +9552,7 @@ might help (with 'rm \jobname.?? \jobname.??s')% % \def\caption{\docaption\thiscaption} \def\shortcaption{\docaption\thisshortcaption} -\def\docaption{\checkenv\float \bgroup\scanargctxt\defcaption} +\def\docaption{\checkenv\float \bgroup\scanctxt\defcaption} \def\defcaption#1#2{\egroup \def#1{#2}} % The parameter is the control sequence identifying the counter we are @@ -10324,9 +10272,9 @@ directory should work if nowhere else does.} % Given the value in \countUTFz as a Unicode code point, set \UTFviiiTmp % to the corresponding UTF-8 sequence. \gdef\parseXMLCharref{% - \ifnum\countUTFz < "A0\relax + \ifnum\countUTFz < "20\relax \errhelp = \EMsimple - \errmessage{Cannot define Unicode char value < 00A0}% + \errmessage{Cannot define Unicode char value < 0020}% \else\ifnum\countUTFz < "800\relax \parseUTFviiiA,% \parseUTFviiiB C\UTFviiiTwoOctetsName.,% @@ -10396,6 +10344,103 @@ directory should work if nowhere else does.} % least make most of the characters not bomb out. % \def\unicodechardefs{% + \DeclareUnicodeCharacter{0020}{ } % space + \DeclareUnicodeCharacter{0021}{\char"21} + \DeclareUnicodeCharacter{0022}{\char"22} + \DeclareUnicodeCharacter{0023}{\char"23} + \DeclareUnicodeCharacter{0024}{\char"24} + \DeclareUnicodeCharacter{0025}{\char"25} + \DeclareUnicodeCharacter{0026}{\char"26} + \DeclareUnicodeCharacter{0027}{\char"27} + \DeclareUnicodeCharacter{0028}{\char"28} + \DeclareUnicodeCharacter{0029}{\char"29} + \DeclareUnicodeCharacter{002A}{\char"2A} + \DeclareUnicodeCharacter{002B}{\char"2B} + \DeclareUnicodeCharacter{002C}{\char"2C} + \DeclareUnicodeCharacter{002D}{\char"2D} + \DeclareUnicodeCharacter{002E}{\char"2E} + \DeclareUnicodeCharacter{002F}{\char"2F} + \DeclareUnicodeCharacter{0030}{0}% + \DeclareUnicodeCharacter{0031}{1}% + \DeclareUnicodeCharacter{0032}{2}% + \DeclareUnicodeCharacter{0033}{3}% + \DeclareUnicodeCharacter{0034}{4}% + \DeclareUnicodeCharacter{0035}{5}% + \DeclareUnicodeCharacter{0036}{6}% + \DeclareUnicodeCharacter{0037}{7}% + \DeclareUnicodeCharacter{0038}{8}% + \DeclareUnicodeCharacter{0039}{9}% + \DeclareUnicodeCharacter{003A}{\char"3A} + \DeclareUnicodeCharacter{003B}{\char"3B} + \DeclareUnicodeCharacter{003C}{\char"3C} + \DeclareUnicodeCharacter{003D}{\char"3D} + \DeclareUnicodeCharacter{003E}{\char"3E} + \DeclareUnicodeCharacter{003F}{\char"3F} + \DeclareUnicodeCharacter{0040}{\char"40} + \DeclareUnicodeCharacter{0041}{A}% + \DeclareUnicodeCharacter{0042}{B}% + \DeclareUnicodeCharacter{0043}{C}% + \DeclareUnicodeCharacter{0044}{D}% + \DeclareUnicodeCharacter{0045}{E}% + \DeclareUnicodeCharacter{0046}{F}% + \DeclareUnicodeCharacter{0047}{G}% + \DeclareUnicodeCharacter{0048}{H}% + \DeclareUnicodeCharacter{0049}{I}% + \DeclareUnicodeCharacter{004A}{J}% + \DeclareUnicodeCharacter{004B}{K}% + \DeclareUnicodeCharacter{004C}{L}% + \DeclareUnicodeCharacter{004D}{M}% + \DeclareUnicodeCharacter{004E}{N}% + \DeclareUnicodeCharacter{004F}{O}% + \DeclareUnicodeCharacter{0050}{P}% + \DeclareUnicodeCharacter{0051}{Q}% + \DeclareUnicodeCharacter{0052}{R}% + \DeclareUnicodeCharacter{0053}{S}% + \DeclareUnicodeCharacter{0054}{T}% + \DeclareUnicodeCharacter{0055}{U}% + \DeclareUnicodeCharacter{0056}{V}% + \DeclareUnicodeCharacter{0057}{W}% + \DeclareUnicodeCharacter{0058}{X}% + \DeclareUnicodeCharacter{0059}{Y}% + \DeclareUnicodeCharacter{005A}{Z}% + \DeclareUnicodeCharacter{005B}{\char"5B} + \DeclareUnicodeCharacter{005C}{\char"5C} + \DeclareUnicodeCharacter{005D}{\char"5D} + \DeclareUnicodeCharacter{005E}{\char"5E} + \DeclareUnicodeCharacter{005F}{\char"5F} + \DeclareUnicodeCharacter{0060}{\char"60} + \DeclareUnicodeCharacter{0061}{a}% + \DeclareUnicodeCharacter{0062}{b}% + \DeclareUnicodeCharacter{0063}{c}% + \DeclareUnicodeCharacter{0064}{d}% + \DeclareUnicodeCharacter{0065}{e}% + \DeclareUnicodeCharacter{0066}{f}% + \DeclareUnicodeCharacter{0067}{g}% + \DeclareUnicodeCharacter{0068}{h}% + \DeclareUnicodeCharacter{0069}{i}% + \DeclareUnicodeCharacter{006A}{j}% + \DeclareUnicodeCharacter{006B}{k}% + \DeclareUnicodeCharacter{006C}{l}% + \DeclareUnicodeCharacter{006D}{m}% + \DeclareUnicodeCharacter{006E}{n}% + \DeclareUnicodeCharacter{006F}{o}% + \DeclareUnicodeCharacter{0070}{p}% + \DeclareUnicodeCharacter{0071}{q}% + \DeclareUnicodeCharacter{0072}{r}% + \DeclareUnicodeCharacter{0073}{s}% + \DeclareUnicodeCharacter{0074}{t}% + \DeclareUnicodeCharacter{0075}{u}% + \DeclareUnicodeCharacter{0076}{v}% + \DeclareUnicodeCharacter{0077}{w}% + \DeclareUnicodeCharacter{0078}{x}% + \DeclareUnicodeCharacter{0079}{y}% + \DeclareUnicodeCharacter{007A}{z}% + \DeclareUnicodeCharacter{007B}{\char"7B} + \DeclareUnicodeCharacter{007C}{\char"7C} + \DeclareUnicodeCharacter{007D}{\char"7D} + \DeclareUnicodeCharacter{007E}{\char"7E} + % \DeclareUnicodeCharacter{007F}{} % DEL + % \DeclareUnicodeCharacter{00A0}{\tie}% \DeclareUnicodeCharacter{00A1}{\exclamdown}% \DeclareUnicodeCharacter{00A2}{{\tcfont \char162}}% 0242=cent @@ -11276,7 +11321,7 @@ directory should work if nowhere else does.} \textleading = 12.5pt % \internalpagesizes{160mm}{120mm}% - {\voffset}{\hoffset}% + {\voffset}{-11.4mm}% {\bindingoffset}{8pt}% {210mm}{148mm}% % @@ -11358,6 +11403,7 @@ directory should work if nowhere else does.} \message{and turning on texinfo input format.} \def^^L{\par} % remove \outer, so ^L can appear in an @comment +\catcode`\^^K = 10 % treat vertical tab as whitespace % DEL is a comment character, in case @c does not suffice. \catcode`\^^? = 14 diff --git a/systems/texlive/tlnet/tlpkg/installer/ctan-mirrors.pl b/systems/texlive/tlnet/tlpkg/installer/ctan-mirrors.pl index 79e3fb8221..b7f4fe2ec8 100644 --- a/systems/texlive/tlnet/tlpkg/installer/ctan-mirrors.pl +++ b/systems/texlive/tlnet/tlpkg/installer/ctan-mirrors.pl @@ -48,6 +48,8 @@ $mirrors = { 'http://ftp.ktug.org/tex-archive/' => 1, 'https://cran.asia/tex/' => 1, 'https://ftp.kaist.ac.kr/pub/tex-archive/' => 1, + 'https://lab.uklee.pe.kr/tex-archive/' => 1, + 'https://mirror.kakao.com/CTAN/' => 1, 'https://mirror.navercorp.com/CTAN/' => 1, }, 'Philippines' => { diff --git a/systems/texlive/tlnet/tlpkg/texlive.tlpdb b/systems/texlive/tlnet/tlpkg/texlive.tlpdb index 95ee38115f..dd620a8491 100644 --- a/systems/texlive/tlnet/tlpkg/texlive.tlpdb +++ b/systems/texlive/tlnet/tlpkg/texlive.tlpdb @@ -26,11 +26,11 @@ depend container_split_src_files/1 depend frozen/0 depend minrelease/2016 depend release/2022 -depend revision/64138 +depend revision/64143 name 00texlive.image category TLCore -revision 64119 +revision 64143 shortdesc TeX Live files only in the source repository longdesc The files here are not copied by the installer and containers longdesc are not built for them; they exist only in the source @@ -1733,6 +1733,7 @@ runfiles size=12913 tlpkg/tlpsrc/fancylabel.tlpsrc tlpkg/tlpsrc/fancynum.tlpsrc tlpkg/tlpsrc/fancypar.tlpsrc + tlpkg/tlpsrc/fancyqr.tlpsrc tlpkg/tlpsrc/fancyref.tlpsrc tlpkg/tlpsrc/fancyslides.tlpsrc tlpkg/tlpsrc/fancytabs.tlpsrc @@ -4611,7 +4612,7 @@ depend setting_available_architectures:aarch64-linux amd64-freebsd amd64-netbsd name 00texlive.installer category TLCore -revision 64133 +revision 64140 shortdesc TeX Live standalone installer package longdesc This package defines the files to go into the installer longdesc archives (install-tl-unx.tar.gz, install-tl.zip) built by the @@ -57965,7 +57966,7 @@ catalogue-version 1.5.3 name citation-style-language category Package -revision 63023 +revision 64143 shortdesc Bibliography formatting with Citation Style Language longdesc The Citation Style Language (CSL) is an XML-based language that longdesc defines the formats of citations and bibliography. There are @@ -57979,27 +57980,37 @@ longdesc both citations and bibliography according to the selected CSL longdesc style. A LaTeX package (citation-style-language.sty) is longdesc provided to communicate with the processor. depend citation-style-language.ARCH -containersize 108620 -containerchecksum 9195782dfdbc9a53eb93087faf87e93adc0aaab12aea4fed33f382fe31a0ec581e67e3104f7a2d997a19b7b02b58ccb29270d448f3ed160c38abaceee3e2c9c9 -doccontainersize 234896 -doccontainerchecksum da36eb08775cd79fa2d75beb69609bb162bffd469a168a2b532440ef16a7839caf57c332bf35b04cbe7d57e5c71fb3a336d08c0b2023f7ca61f786e7886d89c9 -docfiles size=65 +depend filehook +depend l3kernel +depend l3packages +depend lua-uca +depend lualibs +depend luatex +depend luaxml +depend url +containersize 123848 +containerchecksum 03a04ba7cf862ebf609a1f4b6ab689f157cafa9ecbdc48c60ca9b9968c7770b185fbb9d1f420b60c61b49138bb57a62d5a5513e9161df79fe60cfe4d83e2142f +doccontainersize 236380 +doccontainerchecksum 8df0347098ac6ba3cdad0c43e8b1222e8e511d21e25a55566792d109c7b1b1a40fe3d0c1ccac4151b3f21684cd07459cd809841c7f2f192178009ba449ed921a +docfiles size=66 texmf-dist/doc/latex/citation-style-language/CHANGELOG.md + texmf-dist/doc/latex/citation-style-language/DEPENDS.txt texmf-dist/doc/latex/citation-style-language/README.md details="Readme" texmf-dist/doc/latex/citation-style-language/citation-style-language-doc.pdf details="Package documentation" texmf-dist/doc/latex/citation-style-language/citation-style-language-doc.tex - texmf-dist/doc/man/man1/citeproc.1 - texmf-dist/doc/man/man1/citeproc.man1.pdf -srccontainersize 1132 -srccontainerchecksum 2855310fedad682b34f011d222d5f9e014aac741cfb361cba4b53e8036477d665d9bb59ab36e5ecdecc6e25774baee1c51929768be1727cac6fd25577192b513 -srcfiles size=1 - texmf-dist/source/latex/citation-style-language/README.md -runfiles size=475 - texmf-dist/scripts/citation-style-language/citeproc + texmf-dist/doc/man/man1/citeproc-lua.1 + texmf-dist/doc/man/man1/citeproc-lua.man1.pdf +runfiles size=502 + texmf-dist/scripts/citation-style-language/citeproc-bib-data.lua texmf-dist/scripts/citation-style-language/citeproc-bib.lua + texmf-dist/scripts/citation-style-language/citeproc-cli.lua + texmf-dist/scripts/citation-style-language/citeproc-context.lua texmf-dist/scripts/citation-style-language/citeproc-element.lua texmf-dist/scripts/citation-style-language/citeproc-engine.lua - texmf-dist/scripts/citation-style-language/citeproc-formats.lua + texmf-dist/scripts/citation-style-language/citeproc-ir-node.lua + texmf-dist/scripts/citation-style-language/citeproc-latex-core.lua + texmf-dist/scripts/citation-style-language/citeproc-latex.lua + texmf-dist/scripts/citation-style-language/citeproc-lua.lua texmf-dist/scripts/citation-style-language/citeproc-node-choose.lua texmf-dist/scripts/citation-style-language/citeproc-node-date.lua texmf-dist/scripts/citation-style-language/citeproc-node-group.lua @@ -58012,13 +58023,10 @@ runfiles size=475 texmf-dist/scripts/citation-style-language/citeproc-node-style.lua texmf-dist/scripts/citation-style-language/citeproc-node-text.lua texmf-dist/scripts/citation-style-language/citeproc-nodes.lua - texmf-dist/scripts/citation-style-language/citeproc-richtext.lua + texmf-dist/scripts/citation-style-language/citeproc-output.lua texmf-dist/scripts/citation-style-language/citeproc-util.lua texmf-dist/scripts/citation-style-language/citeproc.lua - texmf-dist/scripts/citation-style-language/csl-core.lua - texmf-dist/scripts/citation-style-language/csl.lua texmf-dist/tex/latex/citation-style-language/citation-style-language.sty - texmf-dist/tex/latex/citation-style-language/citeproc-bib-data.json texmf-dist/tex/latex/citation-style-language/locales/csl-locales-af-ZA.xml texmf-dist/tex/latex/citation-style-language/locales/csl-locales-ar.xml texmf-dist/tex/latex/citation-style-language/locales/csl-locales-bg-BG.xml @@ -58093,151 +58101,167 @@ catalogue-contact-repository https://github.com/zepinglee/citeproc-lua catalogue-ctan /biblio/citation-style-language catalogue-license mit cc-by-sa-3 catalogue-topics biblio use-lua -catalogue-version 0.1.1 +catalogue-version 0.2.0 name citation-style-language.aarch64-linux category Package -revision 61687 +revision 64143 shortdesc aarch64-linux files of citation-style-language -containersize 356 -containerchecksum cd0d5ba7fbcdc48db6a116a55a583cb4d68c0c92c75041b6b5b53b798972160eb589d30e1542d2080871ec936a91fe4c32af15931bb0dbcc00319d4cad875c1f -binfiles arch=aarch64-linux size=1 +containersize 384 +containerchecksum f82a7ef1c649ecf7b44f2feb503d6661eaea3a03a677c685d1a0b938b5ea8511b3fefae62470b619ec1e342d51fc2391be322c7e98716def2741d2a108617a68 +binfiles arch=aarch64-linux size=2 bin/aarch64-linux/citeproc + bin/aarch64-linux/citeproc-lua name citation-style-language.amd64-freebsd category Package -revision 61687 +revision 64143 shortdesc amd64-freebsd files of citation-style-language -containersize 360 -containerchecksum 89d110f0118ef6a7b9ce4001e1bc604fdfb1cbe156cfbb7254d96639296c461352131b556b2b11363473789abdd93036f9aca54c20c74f1b3615f0049037bbc3 -binfiles arch=amd64-freebsd size=1 +containersize 388 +containerchecksum c14279a791de16ae9ef3146d0ab7565a30d0537870f474b095652eab130fdfe30c6f7008cb6e7f9685a9bb28d209d7e3ee7e7dc3bc35516c23bcacaefe2da9c6 +binfiles arch=amd64-freebsd size=2 bin/amd64-freebsd/citeproc + bin/amd64-freebsd/citeproc-lua name citation-style-language.amd64-netbsd category Package -revision 61687 +revision 64143 shortdesc amd64-netbsd files of citation-style-language -containersize 360 -containerchecksum 646e20fead81e3197c9b7bff5b391e2ababd471bf10c3d3abde37f070ff276a5f92722e386d75ddc2cf9170a024e82475f8a9daa7ef9026fa41a403776362251 -binfiles arch=amd64-netbsd size=1 +containersize 388 +containerchecksum fb441c93cf15de009873f341bfa7f6284f44b8111e9fa15dbabe4b310c28b0fde7629c21a4a7a797a55cdcee27b605ff1e6cdc29fc44bc611cf90e6f97a0cda8 +binfiles arch=amd64-netbsd size=2 bin/amd64-netbsd/citeproc + bin/amd64-netbsd/citeproc-lua name citation-style-language.armhf-linux category Package -revision 61687 +revision 64143 shortdesc armhf-linux files of citation-style-language -containersize 356 -containerchecksum 60c487247a8a97a8adc98fa81a0c8ce425e01269a243f3b0f6211102eea330cd6a94bef5aa3fd0b3b76589fb94bb4e650313fba75200e0f27939381335c10293 -binfiles arch=armhf-linux size=1 +containersize 388 +containerchecksum 21825b1f5c53a91a3695fd6b62fdb9c99dceacb1b80289145eaa4f54615e9db92acd1d50583c683fab98d1664489e1c128228e75e33c857dc7075d47ded82264 +binfiles arch=armhf-linux size=2 bin/armhf-linux/citeproc + bin/armhf-linux/citeproc-lua name citation-style-language.i386-cygwin category Package -revision 61687 +revision 64143 shortdesc i386-cygwin files of citation-style-language -containersize 356 -containerchecksum e3c4ca4d0b4fc3d078acedccd1b792fe8f6c70b4b0aa75d13ca7510bf4b0a6397ad33b9f3198ba2c468e15169e0921dcee60eab3d207a25f4205e33979e971c8 -binfiles arch=i386-cygwin size=1 +containersize 388 +containerchecksum be1598d06bfc2fdbeb7a449cc6c0f9cb278df2d215c8cda739905d7d0ef964485160b40b28ef4aee8aa91bf81c45ee0e8748c2fedc614394f11f89515ff080b3 +binfiles arch=i386-cygwin size=2 bin/i386-cygwin/citeproc + bin/i386-cygwin/citeproc-lua name citation-style-language.i386-freebsd category Package -revision 61687 +revision 64143 shortdesc i386-freebsd files of citation-style-language -containersize 360 -containerchecksum c63cd4a26cd0895bd6fdcb83ae4d60b9583b22250c37e091a574ee2963aa87f168993d2d547d0054c7367586ad00f77f772697ac234924f2d31eceb48ebf1410 -binfiles arch=i386-freebsd size=1 +containersize 388 +containerchecksum 0c76bd732f6f833037d8d837cfb5930255012c9fa677bd24f5712dcf1c4d9961e0baf6eaff57ede0874b395418f903b0d2272bb3ae823e22d1f6512ffbc1ed4d +binfiles arch=i386-freebsd size=2 bin/i386-freebsd/citeproc + bin/i386-freebsd/citeproc-lua name citation-style-language.i386-linux category Package -revision 61687 +revision 64143 shortdesc i386-linux files of citation-style-language -containersize 356 -containerchecksum 8025d70df1bc6b2614aa2d2606c533802ce58595a943a06b40c15b39dff5eecb5b03f8b09d902f029ea9e738b643c590e11db876fd3ef2f34cdff2c6dc46b23b -binfiles arch=i386-linux size=1 +containersize 388 +containerchecksum 544d47662c16eb5f618dfab2c9b734886a4803077ad290c6902d8f2988de65810d4d50877dda0566dd6e14fddca715135b16929ea9eb307c5d5631e99bcd52fb +binfiles arch=i386-linux size=2 bin/i386-linux/citeproc + bin/i386-linux/citeproc-lua name citation-style-language.i386-netbsd category Package -revision 61687 +revision 64143 shortdesc i386-netbsd files of citation-style-language -containersize 356 -containerchecksum e309afb37117e0085e4a5398f3e06681786b76026fc104cd671c383d923ea91c9cd4a2b99e6cb5cf7a56228af24c3d5ff9750ca32ff32aec619b1d6d713d0c33 -binfiles arch=i386-netbsd size=1 +containersize 388 +containerchecksum 6ba20c9af55e6ad69e4804ee948aba1cc3bbe296e3754ce78e0b568f601c3cd5fce25b74c7a557827336e03989be68484465508b527a77d94715a2e525294ea9 +binfiles arch=i386-netbsd size=2 bin/i386-netbsd/citeproc + bin/i386-netbsd/citeproc-lua name citation-style-language.i386-solaris category Package -revision 61687 +revision 64143 shortdesc i386-solaris files of citation-style-language -containersize 356 -containerchecksum 871517bc3e718869a4bccf9ce9a6b917bca1d01caad2910b604c70f132caa6bd1eaa345e0afb5c06d2d143303d1dc747f64380142449713d59abf24ed1efcc1a -binfiles arch=i386-solaris size=1 +containersize 388 +containerchecksum f33c074e65fbf2a89c1b4c439a37bfec08284dbd85194011c13805398b7240c20d6d736df6a8370c20238daaecb07c9cc2c5a85ff179ab5d4234a8c514b63909 +binfiles arch=i386-solaris size=2 bin/i386-solaris/citeproc + bin/i386-solaris/citeproc-lua name citation-style-language.universal-darwin category Package -revision 61687 +revision 64143 shortdesc universal-darwin files of citation-style-language -containersize 360 -containerchecksum 45eae030cc33df8bb31cb9d060c9b487d1cb9fdc45c3749ba98df46378cf72b2079abd262f237541eb7275f0a9c0576384684a9de3b90cc7420b3834b34af1cd -binfiles arch=universal-darwin size=1 +containersize 388 +containerchecksum b5c93e5d4e08402253adb6d09349062db8042d2957290d6b7c4d8c015bba8b448e69d116e732405d4dce99f76c1d060463199b8469d130cf5ac89cd7edd77b92 +binfiles arch=universal-darwin size=2 bin/universal-darwin/citeproc + bin/universal-darwin/citeproc-lua name citation-style-language.win32 category Package -revision 61687 +revision 64143 shortdesc win32 files of citation-style-language -containersize 700 -containerchecksum 09c0cb26b34d5610f21e7d3623eec3028f31f895bc901736def15e566e69d146cc8ce37242c413039dc11c752b24fb0434a85536451b9865b56b657304157b11 -binfiles arch=win32 size=1 +containersize 724 +containerchecksum 72f00ac5e5bba688d46afa19b3c4428d2bc1fddaaf4101222ff14dd0e9ad804c1d035d4ac78b1612ce4185ee1aedfbefcda6fcf373d42bc1c1eecf4aa14f2bf1 +binfiles arch=win32 size=2 + bin/win32/citeproc-lua.exe bin/win32/citeproc.exe name citation-style-language.x86_64-cygwin category Package -revision 61687 +revision 64143 shortdesc x86_64-cygwin files of citation-style-language -containersize 360 -containerchecksum ac453db6259cd643d3887bb224a2516be9ea4d091b92262a278e6ef3c58ca3be627b19277d6acf80a8d19694c8cb3cef085c95ed0c5c397c4b81376f0909e645 -binfiles arch=x86_64-cygwin size=1 +containersize 388 +containerchecksum 292305621b71086c797769aed0d8b01ac9917fe0e209e8b132343eaa01181c87a1a07673680131f0a34946e58d20464e70a56b7f4533e743470fb9eff96df5c1 +binfiles arch=x86_64-cygwin size=2 bin/x86_64-cygwin/citeproc + bin/x86_64-cygwin/citeproc-lua name citation-style-language.x86_64-darwinlegacy category Package -revision 61687 +revision 64143 shortdesc x86_64-darwinlegacy files of citation-style-language -containersize 368 -containerchecksum 77f6c7f558e3c8777392a0c9556627bb13d2fac36fa0e5575cff76e4e87b467997a0fc78fc9a3d0de37149391ca3ef080a6eb350b0ce797d5ac0d9a1c38afd45 -binfiles arch=x86_64-darwinlegacy size=1 +containersize 396 +containerchecksum 3eed74223cac8e80f2f7e812facfc58880a83a3ae2e5c7d71cbc7861e86f72aa106edc3be11aa4bb8b28d024ede160f813ef852d2da7ca15c9fdd546ae351bd1 +binfiles arch=x86_64-darwinlegacy size=2 bin/x86_64-darwinlegacy/citeproc + bin/x86_64-darwinlegacy/citeproc-lua name citation-style-language.x86_64-linux category Package -revision 61687 +revision 64143 shortdesc x86_64-linux files of citation-style-language -containersize 360 -containerchecksum fb08bd011571ed8730849cfafca1ecea8647430fbb991bc68076d168fa2712ab445733be21b81c9bf1ab868f2280fdb4f64174f14d848f1227627efeb5aa1058 -binfiles arch=x86_64-linux size=1 +containersize 388 +containerchecksum b64e7a48faca7b798a8ec2c7acf1a484288ef22af1fc61d7be29c4a252818dbb0e633b5c4ac6c4d100c0d1d531d48f95182c731bf800bc1efe333acb9a61227d +binfiles arch=x86_64-linux size=2 bin/x86_64-linux/citeproc + bin/x86_64-linux/citeproc-lua name citation-style-language.x86_64-linuxmusl category Package -revision 61687 +revision 64143 shortdesc x86_64-linuxmusl files of citation-style-language -containersize 364 -containerchecksum bd8b6ddd3e84abcc3e4f8d6fbc657be5a0817d1cd92495ac76cc1c38848573fc0f0574512c8fd51a1ea32fcaea78304d55a60f058f74cfac1e558315ca71d37e -binfiles arch=x86_64-linuxmusl size=1 +containersize 392 +containerchecksum 56d51af38eac9e50ec94900a73eb215ed742016105c195da5c89f56515d2e686fe10aeb734c2c99c07f947ea61f476da92888889dd82b14fdfe558da0e28a676 +binfiles arch=x86_64-linuxmusl size=2 bin/x86_64-linuxmusl/citeproc + bin/x86_64-linuxmusl/citeproc-lua name citation-style-language.x86_64-solaris category Package -revision 61687 +revision 64143 shortdesc x86_64-solaris files of citation-style-language -containersize 356 -containerchecksum a15ebb727819155d9aedd472cdda08b4fb39a09e6036a7914bbf2002b717038e94f09b6c5297e779ff5ed26e5d59b5ff64544ad294a6d41fb8a0b3ce897eb46d -binfiles arch=x86_64-solaris size=1 +containersize 384 +containerchecksum eab0764eb7d86b58bb2302e5b9ad250e964f7bb089131e52b3fffbfaa1ecc4a6eca1b9d50ef2dc3c8f6959c3472755b916f7a43bf8045dd2c478cf195d42cfc0 +binfiles arch=x86_64-solaris size=2 bin/x86_64-solaris/citeproc + bin/x86_64-solaris/citeproc-lua name cite category Package @@ -69036,7 +69060,7 @@ containerchecksum c73220abd1545907a1d8de37cb534d2c6bd2534f1b55f03c069f39f535c326 name collection-latexextra category Collection -revision 64106 +revision 64141 shortdesc LaTeX additional packages relocated 1 longdesc A very large collection of add-on packages for LaTeX. @@ -69513,6 +69537,7 @@ depend fancyhandout depend fancylabel depend fancynum depend fancypar +depend fancyqr depend fancyslides depend fancytabs depend fancytooltips @@ -70490,8 +70515,8 @@ depend zref-clever depend zref-vario depend zwgetfdate depend zwpagelayout -containersize 6712 -containerchecksum 25cf86ccdffd5de6c8e6a3806d16dc9cb7b3e8b32bbb837e65c6ef39e21cf0b64e6cf9e4538d37a31138ade26a3059d70ab099817dd434ebe0371c23836f3974 +containersize 6720 +containerchecksum 7d56a6b33f849453b6c62a09e42f87139087ea051e3ecab25fb9287566a2fa6a5bd91907d44f9efe433d5dc2bf8469061f2b75b821b05ce91084d8ebe9bfc953 name collection-latexrecommended category Collection @@ -115558,6 +115583,22 @@ catalogue-license lppl1.3 catalogue-topics decoration catalogue-version 1.3 +name fancyqr +category Package +revision 64141 +relocated 1 +containersize 3384 +containerchecksum 61664c94bf5c432f3e6b9498471bba1c16503decbc274bafc9cae755b6073d84b41c747e5e739b0a4d9dff1630578df262003446cf3960b920862bf480e77eb9 +doccontainersize 248004 +doccontainerchecksum e97d2eeb84fdea0111b11914a5c670386c925d1534bcfda429e0fd1a17c1ffd80da4f147a6e7f214cf8d14e28407379ea43c6339f23ac559428a0915ab9c4b82 +docfiles size=65 + RELOC/doc/latex/fancyqr/README.md + RELOC/doc/latex/fancyqr/fancyqr-doc.pdf + RELOC/doc/latex/fancyqr/fancyqr-doc.tex + RELOC/doc/latex/fancyqr/qr-example.tex +runfiles size=3 + RELOC/tex/latex/fancyqr/fancyqr.sty + name fancyref category Package revision 15878 @@ -192456,7 +192497,7 @@ catalogue-version 0.5 name luavlna category Package -revision 58087 +revision 64142 shortdesc Prevent line breaks after single letter words, units, or academic titles relocated 1 longdesc In some languages, like Czech or Polish, there should be no @@ -192472,10 +192513,10 @@ longdesc units. The package supports both plain LuaTeX and LuaLaTeX. longdesc BTW: "vlna" is the Czech word for "wave" or "curl" and also longdesc denotes the tilde which, in TeX, is used for "unbreakable longdesc spaces". -containersize 7628 -containerchecksum ccef03e521ab96c6ba786bc6d2651c1178935902c6889fbb98156f04105498292b500c824474551bafe23ab76967c212730cdd781d8cb7f86cf8c8aa1aa64d56 -doccontainersize 95132 -doccontainerchecksum 7f484b73c1ed198a325a7835d647b4be21db1fdbf4065988d2f45f0a07bd6ca1697509186be4b911080bc8e5e753262a2a62f1f89cbf8e95aedf3cc1e21844b9 +containersize 7636 +containerchecksum 58c16981ec1515c74a2ffd7632f16d0fb28b9fe32e6e954b49be602c721110e3537a66059b149a4d5c9b652ee717ee1c736ea03d2e4df3803c1b6c4465c50bf1 +doccontainersize 95244 +doccontainerchecksum a8d808e891ee8eb4958061912d0cd7b8c89da3d352ae984b08c92f56ae1222209132e8612172392787bc27e2e62a8a487e48fe1c728c545d8afef5fb7f23747e docfiles size=27 RELOC/doc/luatex/luavlna/README.md details="Readme" RELOC/doc/luatex/luavlna/luavlna-doc.pdf details="Package documentation" @@ -192497,7 +192538,7 @@ catalogue-contact-repository https://github.com/michal-h21/luavlna catalogue-ctan /macros/luatex/generic/luavlna catalogue-license lppl1.3 catalogue-topics typesetting czech slovak polish luatex -catalogue-version 0.1i +catalogue-version 0.1j name luaxml category Package @@ -306242,7 +306283,7 @@ docfiles size=376 name texlive-scripts category TLCore -revision 64133 +revision 64140 shortdesc TeX Live infrastructure programs longdesc Includes install-tl, tl-portable, rungs, etc.; not needed for longdesc tlmgr to run but still ours. Not included in tlcritical. @@ -306250,10 +306291,10 @@ depend texlive-scripts.ARCH depend texlive.infra execute addMap mathpple.map postaction shortcut type=menu name="TeX Live command-line" cmd=TEXDIR/tlpkg/installer/tl-cmd.bat -containersize 113500 -containerchecksum c484dd10b45309e9098db9b431040c37325a9eb6e6a3db3cadd5c7663892577271bf4bf83194f3a1f161516066aa64a839141b8bc5181ea9d7236c932c66bac6 +containersize 113524 +containerchecksum a3e5cad4f847f276edd5875aa70fe3259f7136e53ab93e216ee28f3720a75535354466aa34d4a0075b919abc3be096f3cf27a1f2ef5b0dd2f44273467b56ae6c doccontainersize 419376 -doccontainerchecksum 3d16d680c65fe1a044fb2b2f1e92e420c99ddeae17fd1e73420e65aba38fbcd74181278f9ef70fa1981bf9332d702804cd292393c5b4e1e6329e6fd0a37c1a77 +doccontainerchecksum f760e10cf2187cf1025a0703a83df4f131b41749f18bc94aeecdaa4932fc8a2ae17c09f474944fe269413f56907cb75eee6e86617344effa4ffd576d1b68b887 docfiles size=517 doc.html texmf-dist/doc/man/man1/fmtutil-sys.1 diff --git a/systems/texlive/tlnet/tlpkg/texlive.tlpdb.md5 b/systems/texlive/tlnet/tlpkg/texlive.tlpdb.md5 index 1261a4504c..36e4c711a0 100644 --- a/systems/texlive/tlnet/tlpkg/texlive.tlpdb.md5 +++ b/systems/texlive/tlnet/tlpkg/texlive.tlpdb.md5 @@ -1 +1 @@ -ad6dadb8fd3bdd05429fb2ad25392ce9 texlive.tlpdb +d77be122c44dca09cbf13708b65bc36d texlive.tlpdb diff --git a/systems/texlive/tlnet/tlpkg/texlive.tlpdb.sha512 b/systems/texlive/tlnet/tlpkg/texlive.tlpdb.sha512 index 82c10db0f7..9653420561 100644 --- a/systems/texlive/tlnet/tlpkg/texlive.tlpdb.sha512 +++ b/systems/texlive/tlnet/tlpkg/texlive.tlpdb.sha512 @@ -1 +1 @@ -6f6a86ee411cc63fac661c9b90eb12024a7e0ac4dd5ed8b284ee0c84b86fab78020441b440c9a243d72745225095af5b7442bbfcb57ee0d108795714d81884f3 texlive.tlpdb +2040651c186185803ffd2c4d70a6256aaa73416ed5a4d92e15d2155730f6ceb1c970f7fcb18488b43602de5a9a56a984e4bb59d9895b30b8e09773148c9a9591 texlive.tlpdb diff --git a/systems/texlive/tlnet/tlpkg/texlive.tlpdb.sha512.asc b/systems/texlive/tlnet/tlpkg/texlive.tlpdb.sha512.asc index b904641690..db18b8177b 100644 --- a/systems/texlive/tlnet/tlpkg/texlive.tlpdb.sha512.asc +++ b/systems/texlive/tlnet/tlpkg/texlive.tlpdb.sha512.asc @@ -1,10 +1,10 @@ -----BEGIN PGP SIGNATURE----- -iQEcBAEBCgAGBQJi/X9sAAoJEEzhh34ZQ4xwjtUH/20lgYHnnhrH1OJUw+x/JbJf -8X22Qjvm/3+j4blBX4IuGfBqmRMRF1pZTAkMXyz3S/0Fe/nXv+grl+2rL3Vw2vny -BB4qCwremQmt7s8cNJbHMAYHb3C4aa/javJB3NlhajAqw3hDXhqpZWE8A8XYvIvF -2cFmsSPI1LgnmRCIgjcQ43VyQonIE09nx/8j4h+hwv19mYPpv9vaGEkLvQ3Bmj/U -9Kx5As8v1oMhL/rePhu2P8LQmEtdr70hmrVWK3m7qbS+izJL1w6ckam61t8cCyWt -d4DWSds7VBThvAzvzJEY1rB9+V+dpuqJIloRvtHIYKXQCm1l6BkMKoT35dDPOus= -=5Cht +iQEcBAEBCgAGBQJi/tC7AAoJEEzhh34ZQ4xwpssIAJdvIXfjzwW+R5zdHkn/QSMY +gGoq//FSQQnrduS7+2TdLVk63NtpLIpfzp4aRgjb5YXYLct4yuJwOsEDBpD7sJpU +Vv16q7E5XhZ2GaX/290P5Ku4IL3dwVvbfxi8166vBD5jcTM0QneBHI9pUbW/PZB5 +ZLe2JrzHh4O58O3c9bxRVeaSCFrZ9wwm3jTZK+mp+wbMk141N6uTXbvphn7+3C8+ +WMKPT2/ul/3cRJPDXdy9g4t25tNJ+eFplvJVudoGhuYv+LzZwhMyVQoe10lekAVN +o7A1v9de2cP22BOgaSNy5aDbGo/5CiMitrY3oVYyUyGRCPB9LCDbbhXA+oqKOCs= +=Qwhd -----END PGP SIGNATURE----- diff --git a/systems/texlive/tlnet/tlpkg/texlive.tlpdb.xz b/systems/texlive/tlnet/tlpkg/texlive.tlpdb.xz Binary files differindex 8373e7c31f..209ba558bf 100644 --- a/systems/texlive/tlnet/tlpkg/texlive.tlpdb.xz +++ b/systems/texlive/tlnet/tlpkg/texlive.tlpdb.xz diff --git a/systems/win32/miktex/tm/packages/next/pr.ini b/systems/win32/miktex/tm/packages/next/pr.ini index 78097f5b25..1d42f0f922 100644 --- a/systems/win32/miktex/tm/packages/next/pr.ini +++ b/systems/win32/miktex/tm/packages/next/pr.ini @@ -1,13 +1,13 @@ [repository]
-date=1660767344
+date=1660853743
lastupd=miktex-arctrl-bin-x64-2.9 miktex-asymptote-bin-x64-2.9 miktex-autosp-bin-x64-2.9 miktex-axohelp-bin-x64-2.9 miktex-bibarts-bin-x64-2.9 miktex-bibtex-bin-x64-2.9 miktex-bibtex8bit-bin-x64-2.9 miktex-bzip2-bin-x64-2.9 miktex-cairo-bin-x64-2.9 miktex-chktex-bin-x64-2.9 miktex-cjkutils-bin-x64-2.9 miktex-console-bin-x64-2.9 miktex-curl-bin-x64-2.9 miktex-cweb-bin-x64-2.9 miktex-devnag-bin-x64-2.9 miktex-doc miktex-dvicopy-bin-x64-2.9 miktex-dvipdfmx-bin-x64-2.9 miktex-dvipng-bin-x64-2.9 miktex-dvips-bin-x64-2.9
-lstdigest=96dfacf3fc5d4799de13949cbce96e2c
+lstdigest=9bc8600c929a31899b341547adc423d8
numpkg=5869
relstate=next
-version=8264
+version=8265
;;;;This configuration file is signed by a MiKTeX maintainer. The signature follows.
;;;;-----BEGIN MIKTEX SIGNATURE-----
-;;;; signature/miktex: V03wfEOs33tFJcQMPw0lUfXdzQweiOvxw0cJrAX2edn3KGGCYb3vrzc+d8Xo1+EVbid8Af1sOP+fW2IflLM2m616JCqM/yXVHj7Zxo+3INa4qGSatNMtkoVnzrG5d1ytVW5dsynkvVlKnLqEVhqFaeiGdsdPkDI9Icy+qc7A3IRvgrFSCFSCMwBuqMHDVfWGoNaRH93XpK8TC0Z3WEPnHuPS/QFpb6Lcv0GzV0BgmY1/Q3Fmzt7edQQL1SQMUUEAMdrNArKoIYarbz8isSz1iXQbivpbb2e/Cn7d8r70mBbnSp+yBmhqOG6pjF58oZD40NO1O4J571+FdI6limzGxA==
+;;;; signature/miktex: mJEJizlXb3/deFyJknfB0EmCUzvfzJaB7NJOrDqckjPT9+0/C8byibZ4een6O4xWPTiYTsYkZE4UC7zB0va3Sq05k/PzyMFuizWYpk2TeWV9ED8nQOwnSXIf3FVgT4gVlZqtqKhD/y96b1Y/IGFzaSwMGMNGHa6yk0CejZlpMom8bQSFQdRX7cQ5uRQ7jIwA2c04ulx5/EVVhu/wKYM6StYKq0dpSAy7AdxIDW9o15K4QaeOq3TZF2kyCYUHxpODKG4meN6FpTvVam1ySBC6BNTpAu+tFLrznf9S7fgnC2RGsNQpB+HFYvuBmzmhHkpb9GpmP0tCwVQFzmc3561L2g==
;;;;-----END MIKTEX SIGNATURE-----
diff --git a/systems/win32/miktex/tm/packages/pr.ini b/systems/win32/miktex/tm/packages/pr.ini index 75c79593dd..d00c3f88d5 100644 --- a/systems/win32/miktex/tm/packages/pr.ini +++ b/systems/win32/miktex/tm/packages/pr.ini @@ -1,13 +1,13 @@ [repository]
-date=1660767066
+date=1660853464
lastupd=asymptote create-theorem create-theorem__doc create-theorem__source easybook easybook__doc easybook__source exam-zh exam-zh__doc exam-zh__source ffcode ffcode__doc ffcode__source fixdif fixdif__doc fixdif__source hereapplies hereapplies__doc hereapplies__source media4svg
-lstdigest=244f161274be109beb6719bb42976e33
+lstdigest=a977a4f1bfc637ec3e13271156d54dae
numpkg=5869
relstate=stable
-version=8264
+version=8265
;;;;This configuration file is signed by a MiKTeX maintainer. The signature follows.
;;;;-----BEGIN MIKTEX SIGNATURE-----
-;;;; signature/miktex: RJ3OyCf2wTVTc5Me2Z/fO6JwKYIP/uG2r0cjUSpYWNw5Ffaw8UdsTSy37Ebnbu/fJOhs3xKLZ1o7pStPgZs+PJMp3eNLKgQg6Vi5pL1lK0T1avwvEibAYekxuU54C1oKmbbTO3lzB0n1qlly8KBDh28bj/3TzWrh15PuhSIe5oo5jlhy1eVElWLBi9pgketod0gm1gTcMpu2U8RvzXi1PgcUwzIOfJ1KXIvd+M/4KJ1tTK5BUEb0cYtcPwQqTQUCLLwW87vT9vuoKVsZa3zObx4bcUfTLkp6iyVZxbASvPLia+hliLqq9xmNZWMtcoYp6fZfLj3nEoKPVynhv/qNvQ==
+;;;; signature/miktex: R1+svlioVBG79y7M2+F0DNfVKwYDhB9sPkPocOlBrpCEZuPDgHjF1gyEen0tv+fN0SC+7BJGe1ZxR+65y4+7eSWtJu7Qk/lQt8Z03JgzL3YHkWhzjbJmXjUxa8VgjY4EcT50fZAXe2XdFaPmynz8Xflvsf6DELDFiunyEclvC3YzmdHQmOuWRFVDdlZ99dOwDtpBFZ0UQJ11ucRKVc2zW8fT5kYRSs6UeEIanKJokw0u2CMg0cElLQjR3/GVao4TIzgzeBiuGeheO2zg9C6I7p18atH/37aS2Kh8ei8Qt7tSjWfqxYtkxKYF/xCVxeiqRUwcomp5AqbqDrP0fLSrzw==
;;;;-----END MIKTEX SIGNATURE-----
@@ -2,4 +2,4 @@ # The source CTAN of this site's material: dante.ctan.org # The year-month-day-hour-minute of this site's material: -2022-08-18-02-02 +2022-08-19-02-02 |