├── .ert-runner
├── .gitignore
├── test
├── biblatex_csl
│ ├── video.txt
│ ├── 179-escaped_curly_brackets.txt
│ ├── periodical.txt
│ ├── 95-non-standard_biblatex_date_fields.txt
│ ├── book-title-maintitle-series.txt
│ ├── 75-extended_biblatex_name_spec.txt
│ ├── 65-map_type_to_genre.txt
│ ├── britannica.txt
│ ├── 143-capitalize_subtitles_starting_with_quote.txt
│ ├── corporate_author.txt
│ ├── kant-ku.txt
│ ├── ctan.txt
│ ├── basic.txt
│ ├── averroes-bland.txt
│ ├── manual.txt
│ ├── thesis.txt
│ ├── online.txt
│ ├── article.txt
│ ├── inproceedings.txt
│ ├── inspect.org
│ ├── incollection.txt
│ ├── inbook.txt
│ ├── report.txt
│ └── patent.txt
├── citeproc-test-int-humans.el
├── citeproc-test-csl-suite.el
├── human
│ ├── extlink_DOI.txt
│ ├── extlink_URLOrgNoLinkIfTargetEqualsAnchor.txt
│ ├── extlink_PMID.txt
│ ├── extlink_PMCID.txt
│ ├── extlink_TitleFallback.txt
│ ├── extlink_URL.txt
│ ├── extlink_TitleFallbackDOIPriority.txt
│ ├── extlink_LinkImmediateURLPrefix.txt
│ ├── extlink_DontLinkNonimmediateURLPrefix.txt
│ ├── textcase_StopWordBeforeHyphen.txt
│ ├── citation_YearOnly.txt
│ ├── citation_AuthorOnly.txt
│ ├── citation_TextualDontApplyForNumericOrLabel.txt
│ ├── citation_LocatorOnly.txt
│ ├── citation_Textual.txt
│ ├── citation_SuppressAuthor.txt
│ ├── citation_TextualCapitalizeFirst.txt
│ ├── intlink_NonNoteStyle.txt
│ ├── intlink_NoteStyle.txt
│ ├── citation_ApplyModeAfterSortingCites.txt
│ ├── citation_IgnoreEtAl.txt
│ └── citation_TextualGroupedCites.txt
├── citeproc-test-int-formatters.el
├── etc
│ └── subbibs.json
├── citeproc-test-int-subbibs.el
├── citeproc-test-int-biblatex.el
└── expected_fails.lst
├── Cask
├── Makefile
├── .github
└── workflows
│ └── ci.yml
├── citeproc-macro.el
├── citeproc-subbibs.el
├── citeproc-locale.el
├── citeproc-itemdata.el
├── citeproc-term.el
├── citeproc-choose.el
├── citeproc-prange.el
├── citeproc-lib.el
├── citeproc-number.el
├── citeproc-generic-elements.el
├── citeproc-itemgetters.el
├── citeproc-sort.el
├── citeproc-test-human.el
├── citeproc-proc.el
├── citeproc-disamb.el
└── citeproc-s.el
/.ert-runner:
--------------------------------------------------------------------------------
1 | -L ./
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Compiled
2 | *.elc
3 |
4 | # Packaging
5 | .cask
6 |
7 | # Backup files
8 | *~
9 |
10 | # Undo-tree save-files
11 | *.~undo-tree
12 |
13 | # CSL suite
14 | test/locales
15 | test/suite
16 | dist
17 |
--------------------------------------------------------------------------------
/test/biblatex_csl/video.txt:
--------------------------------------------------------------------------------
1 | ---
2 | @video{x1,title={Blah}}
3 | @movie{x2,title={Blah}}
4 | ---
5 | - blt-type: video
6 | id: x1
7 | title: Blah
8 | type: motion_picture
9 | - blt-type: movie
10 | id: x2
11 | title: Blah
12 | type: motion_picture
13 |
--------------------------------------------------------------------------------
/Cask:
--------------------------------------------------------------------------------
1 | (source gnu)
2 | (source melpa)
3 | (source org)
4 |
5 | (package-file "citeproc.el")
6 |
7 | (files "*.el")
8 |
9 | (development
10 | (depends-on "ert-runner")
11 | (depends-on "org-plus-contrib")
12 | (depends-on "yaml")
13 | (depends-on "parsebib")
14 | (depends-on "ht"))
15 |
--------------------------------------------------------------------------------
/test/citeproc-test-int-humans.el:
--------------------------------------------------------------------------------
1 | ;;; citeproc-test-int-humans.el --- internal tests in CSL humanly readable format
2 |
3 | (require 'citeproc-test-human)
4 |
5 | (citeproc-test-human-create-from-dir "./test/human")
6 |
7 | (provide 'citeproc-test-int-humans)
8 |
9 | ;;; citeproc-test-int-humans.el ends here
10 |
--------------------------------------------------------------------------------
/test/citeproc-test-csl-suite.el:
--------------------------------------------------------------------------------
1 | ;;; citeproc-test-csl-suite.el --- CSL tests from the official suite
2 |
3 | (require 'citeproc-test-human)
4 |
5 | (citeproc-test-human-create-from-dir
6 | "./test/suite/processor-tests/humans" "./test/expected_fails.lst" "suite")
7 |
8 | (provide 'citeproc-test-csl-suite)
9 |
10 | ;;; citeproc-test-csl-suite.el ends here
11 |
--------------------------------------------------------------------------------
/test/biblatex_csl/179-escaped_curly_brackets.txt:
--------------------------------------------------------------------------------
1 | ---
2 | @software{expressionTest,
3 | author = {Myself, Me},
4 | title = {Regex:[01]\{20\}},
5 | year = {2025}
6 | }
7 | ---
8 | - author:
9 | - family: Myself
10 | given: Me
11 | blt-type: software
12 | id: expressionTest
13 | issued: 2025
14 | title: Regex:[01]{20}
15 | type: software
16 |
17 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | CASK ?= cask
2 | CASK_EXEC ?= ${CASK} exec
3 |
4 | all: update clean compile csl_suite
5 |
6 | update:
7 | $(CASK) update
8 |
9 | compile:
10 | $(CASK) build
11 |
12 | test_csl_suite:
13 | ${CASK_EXEC} ert-runner test/citeproc-test-csl-suite.el
14 |
15 | test_internals:
16 | ${CASK_EXEC} ert-runner test/citeproc-test-int*.el
17 |
18 | test:
19 | ${CASK_EXEC} ert-runner test/*.el
20 |
21 | clean:
22 | rm -f *.elc
23 |
24 | .PHONY: all clean test
25 |
--------------------------------------------------------------------------------
/test/biblatex_csl/periodical.txt:
--------------------------------------------------------------------------------
1 | ---
2 | @periodical{jcg,
3 | Annotation = {This is a periodical entry with an issn field.},
4 | Issn = {0097-8493},
5 | Issuetitle = {Semantic {3D} media and content},
6 | Number = 4,
7 | Title = {Computers and Graphics},
8 | Volume = 35,
9 | Year = 2011}
10 | ---
11 | - annote: This is a periodical entry with an issn field.
12 | blt-type: periodical
13 | container-title: Computers and graphics
14 | id: jcg
15 | ISSN: 0097-8493
16 | issue: 4
17 | issued: 2011
18 | title: Semantic 3D media and content
19 | type: article-journal
20 | volume: 35
21 |
--------------------------------------------------------------------------------
/test/biblatex_csl/95-non-standard_biblatex_date_fields.txt:
--------------------------------------------------------------------------------
1 | ---
2 | @article{article-req,
3 | Author = {Author, Ann},
4 | Date = {2013-01},
5 | Urldate = {2021-12-12T19:00:12},
6 | Journaltitle = {The Journaltitle},
7 | Title = {An article entry with just the required fields},
8 | Langid = {english}}
9 | ---
10 | - accessed: 2021-12-12
11 | author:
12 | - family: Author
13 | given: Ann
14 |
15 | blt-type: article
16 | container-title: The journaltitle
17 | id: article-req
18 | issued: 2013-01
19 | language: en-US
20 | title: An article entry with just the required fields
21 | type: article-journal
22 |
--------------------------------------------------------------------------------
/test/human/extlink_DOI.txt:
--------------------------------------------------------------------------------
1 | >>===== OUTPUT-FORMAT =====>>
2 | org
3 | <<===== OUTPUT-FORMAT =====<<
4 |
5 |
6 | >>===== MODE =====>>
7 | bibliography
8 | <<===== MODE =====<<
9 |
10 |
11 | >>===== RESULT =====>>
12 | [[https://doi.org/10.1000/xyz123][10.1000/xyz123]]
13 | <<===== RESULT =====<<
14 |
15 |
16 | >>===== CSL =====>>
17 |
24 | <<===== CSL =====<<
25 |
26 |
27 | >>===== INPUT =====>>
28 | [
29 | {
30 | "id": "ITEM-1",
31 | "DOI": "10.1000/xyz123"
32 | }
33 | ]
34 | <<===== INPUT =====<<
35 |
--------------------------------------------------------------------------------
/test/human/extlink_URLOrgNoLinkIfTargetEqualsAnchor.txt:
--------------------------------------------------------------------------------
1 | >>===== OUTPUT-FORMAT =====>>
2 | org
3 | <<===== OUTPUT-FORMAT =====<<
4 |
5 |
6 | >>===== MODE =====>>
7 | bibliography
8 | <<===== MODE =====<<
9 |
10 |
11 | >>===== RESULT =====>>
12 | http://orgmode.org
13 | <<===== RESULT =====<<
14 |
15 |
16 | >>===== CSL =====>>
17 |
24 | <<===== CSL =====<<
25 |
26 |
27 | >>===== INPUT =====>>
28 | [
29 | {
30 | "id": "ITEM-1",
31 | "URL": "http://orgmode.org"
32 | }
33 | ]
34 | <<===== INPUT =====<<
35 |
--------------------------------------------------------------------------------
/test/human/extlink_PMID.txt:
--------------------------------------------------------------------------------
1 | >>===== OUTPUT-FORMAT =====>>
2 | org
3 | <<===== OUTPUT-FORMAT =====<<
4 |
5 |
6 | >>===== MODE =====>>
7 | bibliography
8 | <<===== MODE =====<<
9 |
10 |
11 | >>===== RESULT =====>>
12 | [[https://www.ncbi.nlm.nih.gov/pubmed/25166873][25166873]]
13 | <<===== RESULT =====<<
14 |
15 |
16 | >>===== CSL =====>>
17 |
24 | <<===== CSL =====<<
25 |
26 |
27 | >>===== INPUT =====>>
28 | [
29 | {
30 | "id": "ITEM-1",
31 | "PMID": "25166873",
32 | "PMCID": "PMC3531190"
33 | }
34 | ]
35 | <<===== INPUT =====<<
36 |
--------------------------------------------------------------------------------
/test/human/extlink_PMCID.txt:
--------------------------------------------------------------------------------
1 | >>===== OUTPUT-FORMAT =====>>
2 | org
3 | <<===== OUTPUT-FORMAT =====<<
4 |
5 |
6 | >>===== MODE =====>>
7 | bibliography
8 | <<===== MODE =====<<
9 |
10 |
11 | >>===== RESULT =====>>
12 | [[https://www.ncbi.nlm.nih.gov/pmc/articles/PMC3531190][PMC3531190]]
13 | <<===== RESULT =====<<
14 |
15 |
16 | >>===== CSL =====>>
17 |
24 | <<===== CSL =====<<
25 |
26 |
27 | >>===== INPUT =====>>
28 | [
29 | {
30 | "id": "ITEM-1",
31 | "PMID": "25166873",
32 | "PMCID": "PMC3531190"
33 | }
34 | ]
35 | <<===== INPUT =====<<
36 |
--------------------------------------------------------------------------------
/test/human/extlink_TitleFallback.txt:
--------------------------------------------------------------------------------
1 | >>===== OUTPUT-FORMAT =====>>
2 | org
3 | <<===== OUTPUT-FORMAT =====<<
4 |
5 |
6 | >>===== MODE =====>>
7 | bibliography
8 | <<===== MODE =====<<
9 |
10 |
11 | >>===== RESULT =====>>
12 | [[http://orgmode.org][Org mode is great]]
13 | <<===== RESULT =====<<
14 |
15 |
16 | >>===== CSL =====>>
17 |
24 | <<===== CSL =====<<
25 |
26 |
27 | >>===== INPUT =====>>
28 | [
29 | {
30 | "id": "ITEM-1",
31 | "title": "Org mode is great",
32 | "URL": "http://orgmode.org"
33 | }
34 | ]
35 | <<===== INPUT =====<<
36 |
--------------------------------------------------------------------------------
/test/human/extlink_URL.txt:
--------------------------------------------------------------------------------
1 | >>===== OUTPUT-FORMAT =====>>
2 | html
3 | <<===== OUTPUT-FORMAT =====<<
4 |
5 |
6 | >>===== MODE =====>>
7 | bibliography
8 | <<===== MODE =====<<
9 |
10 |
11 | >>===== RESULT =====>>
12 |
15 | <<===== RESULT =====<<
16 |
17 |
18 | >>===== CSL =====>>
19 |
26 | <<===== CSL =====<<
27 |
28 |
29 | >>===== INPUT =====>>
30 | [
31 | {
32 | "id": "ITEM-1",
33 | "URL": "http://orgmode.org"
34 | }
35 | ]
36 | <<===== INPUT =====<<
37 |
--------------------------------------------------------------------------------
/test/human/extlink_TitleFallbackDOIPriority.txt:
--------------------------------------------------------------------------------
1 | >>===== OUTPUT-FORMAT =====>>
2 | org
3 | <<===== OUTPUT-FORMAT =====<<
4 |
5 |
6 | >>===== MODE =====>>
7 | bibliography
8 | <<===== MODE =====<<
9 |
10 |
11 | >>===== RESULT =====>>
12 | [[https://doi.org/10.1000/xyz123][Org mode is great]]
13 | <<===== RESULT =====<<
14 |
15 |
16 | >>===== CSL =====>>
17 |
24 | <<===== CSL =====<<
25 |
26 |
27 | >>===== INPUT =====>>
28 | [
29 | {
30 | "id": "ITEM-1",
31 | "title": "Org mode is great",
32 | "URL": "http://orgmode.org",
33 | "DOI": "10.1000/xyz123"
34 | }
35 | ]
36 | <<===== INPUT =====<<
37 |
--------------------------------------------------------------------------------
/test/human/extlink_LinkImmediateURLPrefix.txt:
--------------------------------------------------------------------------------
1 | >>===== OUTPUT-FORMAT =====>>
2 | latex
3 | <<===== OUTPUT-FORMAT =====<<
4 |
5 |
6 | >>===== MODE =====>>
7 | bibliography
8 | <<===== MODE =====<<
9 |
10 |
11 | >>===== RESULT =====>>
12 | A title. \url{https://doi.org/10.1000/xyz123}\bigskip
13 | <<===== RESULT =====<<
14 |
15 |
16 | >>===== CSL =====>>
17 |
25 | <<===== CSL =====<<
26 |
27 |
28 | >>===== INPUT =====>>
29 | [
30 | {
31 | "id": "ITEM-1",
32 | "DOI": "10.1000/xyz123",
33 | "title": "A title"
34 | }
35 | ]
36 | <<===== INPUT =====<<
37 |
--------------------------------------------------------------------------------
/test/biblatex_csl/book-title-maintitle-series.txt:
--------------------------------------------------------------------------------
1 | ---
2 | @book{item1,
3 | Author = {Author, Al},
4 | Date = {2013},
5 | Location = {Location},
6 | Mainsubtitle = {Mainsubtitle},
7 | Maintitle = {Maintitle},
8 | Maintitleaddon = {Maintitleaddon},
9 | Number = {3},
10 | Publisher = {Publisher},
11 | Series = {Series},
12 | Subtitle = {Subtitle},
13 | Title = {Title of the book},
14 | Titleaddon = {Titleaddon},
15 | }
16 | ---
17 | - author:
18 | - family: Author
19 | given: Al
20 | blt-type: book
21 | collection-number: 3
22 | collection-title: Series
23 | id: item1
24 | issued: 2013
25 | publisher: Publisher
26 | publisher-place: Location
27 | title: "Maintitle: Mainsubtitle. Maintitleaddon"
28 | type: book
29 | volume-title: "Title of the book: Subtitle. Titleaddon"
30 |
--------------------------------------------------------------------------------
/test/biblatex_csl/75-extended_biblatex_name_spec.txt:
--------------------------------------------------------------------------------
1 | ---
2 | @book{goethe2005,
3 | langid = {german},
4 | location = {{Frankfurt am Main}},
5 | title = {Not A Real Book},
6 | date = {2005},
7 | author = {family=Goethe, given=Johann Wolfgang, prefix=von, useprefix=false and given=Antonie, prefix=van, family=Leeuwenhoek, useprefix=true},
8 | editor = {Schöne, Albrecht}}
9 | ---
10 | - author:
11 | - dropping-particle: von
12 | family: Goethe
13 | given: Johann Wolfgang
14 | - family: Leeuwenhoek
15 | given: Antonie
16 | non-dropping-particle: van
17 | blt-type: book
18 | editor:
19 | - family: Schöne
20 | given: Albrecht
21 | id: goethe2005
22 | issued: 2005
23 | language: de-DE
24 | publisher-place: Frankfurt am Main
25 | title: Not A Real Book
26 | type: book
27 |
--------------------------------------------------------------------------------
/test/human/extlink_DontLinkNonimmediateURLPrefix.txt:
--------------------------------------------------------------------------------
1 | >>===== OUTPUT-FORMAT =====>>
2 | latex
3 | <<===== OUTPUT-FORMAT =====<<
4 |
5 |
6 | >>===== MODE =====>>
7 | bibliography
8 | <<===== MODE =====<<
9 |
10 |
11 | >>===== RESULT =====>>
12 | A title. https://doi.org/ \href{https://doi.org/10.1000/xyz123}{10.1000/xyz123}\bigskip
13 | <<===== RESULT =====<<
14 |
15 |
16 | >>===== CSL =====>>
17 |
25 | <<===== CSL =====<<
26 |
27 |
28 | >>===== INPUT =====>>
29 | [
30 | {
31 | "id": "ITEM-1",
32 | "DOI": "10.1000/xyz123",
33 | "title": "A title"
34 | }
35 | ]
36 | <<===== INPUT =====<<
37 |
--------------------------------------------------------------------------------
/test/biblatex_csl/65-map_type_to_genre.txt:
--------------------------------------------------------------------------------
1 | ---
2 | @Jurisdiction{bgh2013usedsoft-ii,
3 | author = {BGH},
4 | type = {Urteil},
5 | number = {I ZR 129/08},
6 | eventdate = {2013-07-17},
7 | shortjournal = {GRUR},
8 | journaltitle = {Gewerblicher Rechtsschutz und Urheberrecht},
9 | year = {2014},
10 | pages = {264-272},
11 | title = {UsedSoft II},
12 | commentator = {Malte Stieper},
13 | langid = {german}
14 | }
15 | ---
16 | - author:
17 | - family: BGH
18 | blt-type: jurisdiction
19 | container-title: Gewerblicher Rechtsschutz und Urheberrecht
20 | container-title-short: GRUR
21 | event-date: 2013-07-17
22 | genre: Urteil
23 | id: bgh2013usedsoft-ii
24 | issued: 2014
25 | language: de-DE
26 | number: I ZR 129/08
27 | page: 264-272
28 | title: UsedSoft II
29 | type: legal_case
30 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 |
3 | on: [ push, pull_request, workflow_dispatch ]
4 |
5 |
6 | jobs:
7 | test:
8 | runs-on: ubuntu-latest
9 | strategy:
10 | matrix:
11 | emacs_version:
12 | # - 26.3
13 | - 28.1
14 | - 29.1
15 | - 30.1
16 | steps:
17 | - uses: purcell/setup-emacs@master
18 | with:
19 | version: ${{ matrix.emacs_version }}
20 | - uses: conao3/setup-cask@master
21 | - uses: actions/checkout@v2
22 | - name: Test
23 | env:
24 | COVERALLS_FLAG_NAME: Emacs ${{ matrix.emacs_version }}
25 | run: |
26 | git clone --depth 1 https://github.com/citation-style-language/test-suite.git test/suite
27 | git clone --depth 1 https://github.com/citation-style-language/locales.git test/locales
28 | cask install
29 | cask build
30 | make test
31 |
--------------------------------------------------------------------------------
/test/biblatex_csl/britannica.txt:
--------------------------------------------------------------------------------
1 | ---
2 | @Collection{britannica,
3 | editor = {Preece, Warren E.},
4 | title = {The New Encyclop{\ae}dia {Britannica}},
5 | date = 2003,
6 | edition = 15,
7 | volumes = 32,
8 | publisher = {Encyclop{\ae}dia Britannica},
9 | location = {Chicago, Ill.},
10 | label = {EB},
11 | sorttitle = {Encyclop{\ae}dia Britannica},
12 | indextitle = {Encyclop{\ae}dia Britannica, The New},
13 | shorttitle = {Encyclop{\ae}dia {Britannica}}
14 | }
15 | ---
16 | - blt-type: collection
17 | citation-label: EB
18 | edition: 15
19 | editor:
20 | - family: Preece
21 | given: Warren E.
22 | id: britannica
23 | issued: 2003
24 | number-of-volumes: 32
25 | publisher: Encyclopædia Britannica
26 | publisher-place: Chicago, Ill.
27 | title: The new encyclopædia Britannica
28 | title-short: Encyclopædia Britannica
29 | type: book
30 |
--------------------------------------------------------------------------------
/test/biblatex_csl/143-capitalize_subtitles_starting_with_quote.txt:
--------------------------------------------------------------------------------
1 | ---
2 | @Article{myers-1988,
3 | author = {Myers, Norman},
4 | title = {Threatened biotas},
5 | journal = {Environmentalist},
6 | year = 1988,
7 | volume = 8,
8 | number = 3,
9 | pages = {187-208},
10 | month = {Sep},
11 | type = {Abstract},
12 | subtitle = {"Hot spots" in tropical forests},
13 | day = 01,
14 | issn = {1573-2991},
15 | doi = {10.1007/BF02240252}
16 | }
17 | ---
18 | - DOI: 10.1007/BF02240252
19 | ISSN: 1573-2991
20 | author:
21 | - family: Myers
22 | given: Norman
23 | blt-type: article
24 | container-title: Environmentalist
25 | genre: Abstract
26 | id: myers-1988
27 | issue: 3
28 | issued: 1988-09
29 | page: 187-208
30 | title: "Threatened biotas: \"Hot spots\" in tropical forests"
31 | title-short: "Threatened biotas"
32 | type: article-journal
33 | volume: 8
34 |
--------------------------------------------------------------------------------
/test/human/textcase_StopWordBeforeHyphen.txt:
--------------------------------------------------------------------------------
1 | >>==== MODE ====>>
2 | citation
3 | <<==== MODE ====<<
4 |
5 | >>==== RESULT ====>>
6 | Employee pro-Environmental Behavior
7 | <<==== RESULT ====<<
8 |
9 | >>==== CITATION-ITEMS ====>>
10 | [
11 | [
12 | {
13 | "id": "ITEM-1"
14 | }
15 | ]
16 | ]
17 | <<==== CITATION-ITEMS ====<<
18 |
19 | >>==== CSL ====>>
20 |
35 | <<==== CSL ====<<
36 |
37 | >>==== INPUT ====>>
38 | [
39 | {
40 | "container-title": "Employee pro-environmental behavior",
41 | "id": "ITEM-1",
42 | "type": "book"
43 | }
44 | ]
45 | <<==== INPUT ====<<
46 |
47 |
--------------------------------------------------------------------------------
/test/biblatex_csl/corporate_author.txt:
--------------------------------------------------------------------------------
1 | ---
2 | @legislation{bt12-4022,
3 | author = {{Deutscher Bundestag}},
4 | title = {Entwurf eines Zweiten Gesetzes zur Änderung des Urheberrechtsgesetzes},
5 | langid = {german},
6 | date = {1992-12-18}}
7 |
8 | @book{CUDA,
9 | author = {{NVIDIA Corporation}},
10 | title = {{NVIDIA CUDA} Compute Unified Device Architecture Programming Guide},
11 | publisher = {NVIDIA Corporation},
12 | year = {2007}}
13 |
14 | @book{corp,
15 | author = {{Big corporation} and Smith, John},
16 | title = {A book by a corporation and an actual person},
17 | year = {1998}}
18 | ---
19 | - author:
20 | - literal: Deutscher Bundestag
21 | blt-type: legislation
22 | issued: 1992-12-18
23 | id: "bt12-4022"
24 | language: de-DE
25 | title: Entwurf eines Zweiten Gesetzes zur Änderung des Urheberrechtsgesetzes
26 | type: bill
27 | - author:
28 | - literal: NVIDIA Corporation
29 | blt-type: book
30 | id: "CUDA"
31 | issued: 2007
32 | publisher: NVIDIA Corporation
33 | title: NVIDIA CUDA compute unified device architecture programming guide
34 | type: book
35 | - author:
36 | - literal: Big corporation
37 | - family: Smith
38 | given: John
39 | blt-type: book
40 | id: "corp"
41 | issued: 1998
42 | title: A book by a corporation and an actual person
43 | type: book
44 |
--------------------------------------------------------------------------------
/test/biblatex_csl/kant-ku.txt:
--------------------------------------------------------------------------------
1 | An edition of Kant's Collected Works, volume five. This is
2 | an inbook entry which explicitly refers to the Critique of
3 | Judgment only, not to the entire fifth volume.
4 | ---
5 | @InBook{kant:ku,
6 | title = {Kritik der Urtheilskraft},
7 | date = {1968},
8 | author = {Kant, Immanuel},
9 | booktitle = {Kritik der praktischen Vernunft. Kritik der Urtheilskraft},
10 | bookauthor = {Kant, Immanuel},
11 | maintitle = {Kants Werke. Akademie Textausgabe},
12 | volume = {V},
13 | publisher = {Walter de Gruyter},
14 | location = {Berlin},
15 | pages = {165-485},
16 | shorthand = {KU},
17 | langid = {german},
18 | annotation = {An edition of Kant's Collected Works, volume five.}}
19 | ---
20 | - annote: An edition of Kant's Collected Works, volume five.
21 | author:
22 | - given: Immanuel
23 | family: Kant
24 | blt-type: inbook
25 | container-author:
26 | - given: Immanuel
27 | family: Kant
28 | container-title: Kants Werke. Akademie Textausgabe
29 | id: kant:ku
30 | issued: 1968
31 | language: de-DE
32 | page: 165-485
33 | publisher: Walter de Gruyter
34 | publisher-place: Berlin
35 | title: Kritik der Urtheilskraft
36 | type: chapter
37 | volume: V
38 | volume-title: Kritik der praktischen Vernunft. Kritik der
39 | Urtheilskraft
40 |
--------------------------------------------------------------------------------
/test/biblatex_csl/ctan.txt:
--------------------------------------------------------------------------------
1 | ---
2 | @Online{ctan,
3 | title = {{CTAN}},
4 | date = 2006,
5 | url = {http://www.ctan.org},
6 | subtitle = {{The Comprehensive TeX Archive Network}},
7 | urldate = {2006-10-01},
8 | label = {CTAN},
9 | annotation = {This is an online entry. The \textsc{url}, which is
10 | given in the url field, is transformed into a
11 | clickable link if hyperref support has been
12 | enabled. Note the format of the urldate field
13 | (yyyy-mm-dd) in the database file. Also note the
14 | label field which may be used as a fallback by
15 | citation styles which need an author and/or a
16 | year}}
17 | ---
18 | - blt-type: online
19 | URL: "http://www.ctan.org"
20 | accessed: 2006-10-01
21 | annote: This is an online entry. The url, which is given
22 | in the url field, is transformed into a clickable link if hyperref
23 | support has been enabled. Note the format of the urldate field
24 | (yyyy-mm-dd) in the database file. Also note the label field which
25 | may be used as a fallback by citation styles which need an author
26 | and/or a year
27 | citation-label: CTAN
28 | id: ctan
29 | issued: 2006
30 | title: "CTAN: The Comprehensive TeX Archive Network"
31 | title-short: CTAN
32 | type: webpage
33 |
34 |
--------------------------------------------------------------------------------
/test/biblatex_csl/basic.txt:
--------------------------------------------------------------------------------
1 | ---
2 | @Book{item1,
3 | author="John Doe",
4 | title="First Book",
5 | year="2005",
6 | address="Cambridge",
7 | publisher="Cambridge University Press"
8 | }
9 |
10 | @Article{item2,
11 | author="John Doe",
12 | title="Article",
13 | year="2006",
14 | journal="Journal of Generic Studies",
15 | volume="6",
16 | pages="33-34"
17 | }
18 |
19 | @InCollection{пункт3,
20 | author="John Doe and Jenny Roe",
21 | title="Why Water Is Wet",
22 | booktitle="Third Book",
23 | editor="Sam Smith",
24 | publisher="Oxford University Press",
25 | address="Oxford",
26 | year="2007"
27 | }
28 | ---
29 | - author:
30 | - family: Doe
31 | given: John
32 | blt-type: book
33 | id: item1
34 | issued: 2005
35 | publisher: Cambridge University Press
36 | publisher-place: Cambridge
37 | title: First book
38 | type: book
39 | - author:
40 | - family: Doe
41 | given: John
42 | blt-type: article
43 | container-title: Journal of generic studies
44 | id: item2
45 | issued: 2006
46 | page: 33-34
47 | title: Article
48 | type: article-journal
49 | volume: 6
50 | - author:
51 | - family: Doe
52 | given: John
53 | - family: Roe
54 | given: Jenny
55 | blt-type: incollection
56 | container-title: Third book
57 | editor:
58 | - family: Smith
59 | given: Sam
60 | id: пункт3
61 | issued: 2007
62 | publisher: Oxford University Press
63 | publisher-place: Oxford
64 | title: Why water is wet
65 | type: chapter
66 |
--------------------------------------------------------------------------------
/test/biblatex_csl/averroes-bland.txt:
--------------------------------------------------------------------------------
1 | ---
2 | @Book{averroes-bland,
3 | author = {Averroes},
4 | title = {The Epistle on the Possibility of Conjunction with the Active
5 | Intellect by {Ibn Rushd} with the Commentary of {Moses Narboni}},
6 | date = 1982,
7 | editor = {Bland, Kalman P.},
8 | translator = {Bland, Kalman P.},
9 | series = {Moreshet: {Studies} in {Jewish} History, Literature and Thought},
10 | number = 7,
11 | publisher = {Jewish Theological Seminary of America},
12 | location = {New York},
13 | keywords = {primary},
14 | indextitle = {Epistle on the Possibility of Conjunction, The},
15 | shorttitle = {Possibility of Conjunction},
16 | annotation = {A book entry with a series and a
17 | number. Note the concatenation of the editor
18 | and translator fields as well as the
19 | indextitle field},
20 | langid = {english}
21 | }
22 | ---
23 | - annote: A book entry with a series and a number. Note the
24 | concatenation of the editor and translator fields as well as the
25 | indextitle field
26 | author:
27 | - family: Averroes
28 | blt-type: book
29 | collection-number: 7
30 | collection-title: "Moreshet: Studies in Jewish history, literature and thought"
31 | editor:
32 | - family: Bland
33 | given: Kalman P.
34 | id: averroes-bland
35 | issued: 1982
36 | keyword: primary
37 | language: en-US
38 | publisher: Jewish Theological Seminary of America
39 | publisher-place: New York
40 | title: The epistle on the possibility of conjunction with the active
41 | intellect by Ibn Rushd with the commentary of Moses Narboni
42 | title-short: Possibility of conjunction
43 | translator:
44 | - family: Bland
45 | given: Kalman P.
46 | type: book
47 |
--------------------------------------------------------------------------------
/test/biblatex_csl/manual.txt:
--------------------------------------------------------------------------------
1 | ---
2 | @Manual{cms,
3 | title = {The {Chicago} Manual of Style},
4 | date = 2003,
5 | subtitle = {The Essential Guide for Writers, Editors, and Publishers},
6 | edition = 15,
7 | publisher = {University of Chicago Press},
8 | location = {Chicago, Ill.},
9 | isbn = {0-226-10403-6},
10 | label = {CMS},
11 | sorttitle = {Chicago Manual of Style},
12 | indextitle = {Chicago Manual of Style, The},
13 | shorttitle = {Chicago Manual of Style},
14 | annotation = {This is a manual entry without an author or
15 | editor. Note the label field in the database
16 | file which is provided for author-year citation styles. Also
17 | note the sorttitle and indextitle fields. By
18 | default, all entries without an author or
19 | editor are alphabetized by title but we want
20 | this entry to be alphabetized under C rather than
21 | T. There's also an isbn field},
22 | }
23 | ---
24 | - annote: This is a manual entry without an author or editor. Note the
25 | label field in the database file which is provided for author-year
26 | citation styles. Also note the sorttitle and indextitle fields. By
27 | default, all entries without an author or editor are alphabetized by
28 | title but we want this entry to be alphabetized under C rather
29 | than T. There's also an isbn field
30 | blt-type: manual
31 | citation-label: CMS
32 | edition: 15
33 | id: cms
34 | ISBN: 0-226-10403-6
35 | issued: 2003
36 | publisher: University of Chicago Press
37 | publisher-place: Chicago, Ill.
38 | title: "The Chicago manual of style: The essential guide for writers,
39 | editors, and publishers"
40 | title-short: Chicago manual of style
41 | type: book
42 |
--------------------------------------------------------------------------------
/test/human/citation_YearOnly.txt:
--------------------------------------------------------------------------------
1 | >>===== MODE =====>>
2 | citation
3 | <<===== MODE =====<<
4 |
5 |
6 | >>===== RESULT =====>>
7 | (1986)
8 | <<===== RESULT =====<<
9 |
10 |
11 | >>===== CITATIONS =====>>
12 | [
13 | [
14 | {
15 | "citationID": "CITATION-1",
16 | "citationItems": [
17 | {
18 | "id": "ITEM-1"
19 | }
20 | ],
21 | "properties": {
22 | "noteIndex": 0,
23 | "mode": "year-only"
24 | }
25 | },
26 | [],
27 | []
28 | ]
29 |
30 | ]
31 | <<===== CITATIONS =====<<
32 |
33 |
34 |
35 | >>===== CSL =====>>
36 |
65 | <<===== CSL =====<<
66 |
67 |
68 | >>===== INPUT =====>>
69 | [
70 | {
71 | "author": [
72 | {
73 | "family": "Smith",
74 | "given": "John"
75 | }
76 | ],
77 | "issued": {
78 | "date-parts": [
79 | [
80 | 1986
81 | ]
82 | ]
83 | },
84 | "type": "book",
85 | "id": "ITEM-1"
86 | }
87 | ]
88 | <<===== INPUT =====<<
89 |
--------------------------------------------------------------------------------
/test/human/citation_AuthorOnly.txt:
--------------------------------------------------------------------------------
1 | >>===== MODE =====>>
2 | citation
3 | <<===== MODE =====<<
4 |
5 |
6 | >>===== RESULT =====>>
7 | (Smith)
8 | <<===== RESULT =====<<
9 |
10 |
11 | >>===== CITATIONS =====>>
12 | [
13 | [
14 | {
15 | "citationID": "CITATION-1",
16 | "citationItems": [
17 | {
18 | "id": "ITEM-1"
19 | }
20 | ],
21 | "properties": {
22 | "noteIndex": 0,
23 | "mode": "author-only"
24 | }
25 | },
26 | [],
27 | []
28 | ]
29 |
30 | ]
31 | <<===== CITATIONS =====<<
32 |
33 |
34 |
35 | >>===== CSL =====>>
36 |
66 | <<===== CSL =====<<
67 |
68 |
69 | >>===== INPUT =====>>
70 | [
71 | {
72 | "author": [
73 | {
74 | "family": "Smith",
75 | "given": "John"
76 | }
77 | ],
78 | "title": "A nice title",
79 | "issued": {
80 | "date-parts": [
81 | [
82 | 1986
83 | ]
84 | ]
85 | },
86 | "type": "book",
87 | "id": "ITEM-1"
88 | }
89 | ]
90 | <<===== INPUT =====<<
91 |
--------------------------------------------------------------------------------
/test/human/citation_TextualDontApplyForNumericOrLabel.txt:
--------------------------------------------------------------------------------
1 | >>===== MODE =====>>
2 | citation
3 | <<===== MODE =====<<
4 |
5 |
6 | >>===== RESULT =====>>
7 | [1]
8 | [1]
9 | <<===== RESULT =====<<
10 |
11 |
12 | >>===== CITATIONS =====>>
13 | [
14 | [
15 | {
16 | "citationID": "CITATION-1",
17 | "citationItems": [
18 | {
19 | "id": "ITEM-1"
20 | }
21 | ],
22 | "properties": {
23 | "noteIndex": 0,
24 | "mode": "textual"
25 | }
26 | },
27 | [],
28 | []
29 | ],
30 | [
31 | {
32 | "citationID": "CITATION-2",
33 | "citationItems": [
34 | {
35 | "id": "ITEM-1"
36 | }
37 | ],
38 | "properties": {
39 | "noteIndex": 1
40 | }
41 | },
42 | [],
43 | []
44 | ]
45 |
46 | ]
47 | <<===== CITATIONS =====<<
48 |
49 |
50 |
51 | >>===== CSL =====>>
52 |
73 | <<===== CSL =====<<
74 |
75 |
76 | >>===== INPUT =====>>
77 | [
78 | {
79 | "author": [
80 | {
81 | "family": "Smith",
82 | "given": "John"
83 | }
84 | ],
85 | "issued": {
86 | "date-parts": [
87 | [
88 | 1986
89 | ]
90 | ]
91 | },
92 | "type": "book",
93 | "id": "ITEM-1"
94 | }
95 | ]
96 | <<===== INPUT =====<<
97 |
98 |
--------------------------------------------------------------------------------
/test/human/citation_LocatorOnly.txt:
--------------------------------------------------------------------------------
1 | >>===== MODE =====>>
2 | citation
3 | <<===== MODE =====<<
4 |
5 |
6 | >>===== RESULT =====>>
7 | (32)
8 | <<===== RESULT =====<<
9 |
10 |
11 | >>===== CITATIONS =====>>
12 | [
13 | [
14 | {
15 | "citationID": "CITATION-1",
16 | "citationItems": [
17 | {
18 | "id": "ITEM-1",
19 | "locator": "32"
20 | }
21 | ],
22 | "properties": {
23 | "noteIndex": 0,
24 | "mode": "locator-only"
25 | }
26 | },
27 | [],
28 | []
29 | ]
30 |
31 | ]
32 | <<===== CITATIONS =====<<
33 |
34 |
35 |
36 | >>===== CSL =====>>
37 |
68 | <<===== CSL =====<<
69 |
70 |
71 | >>===== INPUT =====>>
72 | [
73 | {
74 | "author": [
75 | {
76 | "family": "Smith",
77 | "given": "John"
78 | }
79 | ],
80 | "title": "A nice title",
81 | "issued": {
82 | "date-parts": [
83 | [
84 | 1986
85 | ]
86 | ]
87 | },
88 | "type": "book",
89 | "id": "ITEM-1"
90 | }
91 | ]
92 | <<===== INPUT =====<<
93 |
--------------------------------------------------------------------------------
/test/citeproc-test-int-formatters.el:
--------------------------------------------------------------------------------
1 | ;;; citeproc-test-int-formatters.el --- formatter tests -*- lexical-binding: t; -*-
2 |
3 | (require 'ert)
4 | (require 'citeproc)
5 | (require 'citeproc-formatters)
6 |
7 | (ert-deftest citeproc-test-formatters-html ()
8 | (let ((f (citeproc-formatter-rt
9 | (citeproc-formatter-for-format 'html))))
10 | (should (string= (funcall f '(((href . "http://orgmode.org")) "Org website"))
11 | "Org website"))))
12 |
13 | (ert-deftest citeproc-test-formatters-org ()
14 | (let ((f (citeproc-formatter-rt
15 | (citeproc-formatter-for-format 'org))))
16 | (should (string= (funcall f '(((href . "http://orgmode.org")) "Org website"))
17 | "[[http://orgmode.org][Org website]]"))
18 | (should (string= (funcall f '(((href . "http://orgmode.org")) "http://orgmode.org"))
19 | "http://orgmode.org"))
20 | (should (string= (funcall f '(((bib-item-no . "1")) "text"))
21 | "<>text"))))
22 |
23 | (ert-deftest citeproc-test-formatters-plain ()
24 | (let ((f (citeproc-formatter-rt
25 | (citeproc-formatter-for-format 'plain))))
26 | (should (string= (funcall f '(((href . "http://orgmode.org")) "Org website"))
27 | "Org website"))))
28 |
29 | (ert-deftest citeproc-test-formatters-latex ()
30 | (let ((f (citeproc-formatter-rt
31 | (citeproc-formatter-for-format 'latex))))
32 | (should (string= (funcall f '(((href . "http://orgmode.org")) "Org website"))
33 | "\\href{http://orgmode.org}{Org website}"))
34 | (should (string=
35 | (funcall f
36 | '(((href . "https://scholar.google.com/scholar?q=%22functional+data%22"))
37 | "https://scholar.google.com/scholar?q=%22functional+data%22"))
38 | "\\url{https://scholar.google.com/scholar?q=\\%22functional+data\\%22}"))))
39 |
40 | (ert-deftest citeproc-test-formatters-csl ()
41 | (let ((f (citeproc-formatter-rt
42 | (citeproc-formatter-for-format 'csl-test))))
43 | (should (string= (funcall f '(((href . "http://orgmode.org")) "Org website"))
44 | "Org website"))))
45 |
46 | (provide 'citeproc-test-int-formatters)
47 |
48 | ;;; citeproc-test-int-formatters.el ends here
49 |
--------------------------------------------------------------------------------
/test/biblatex_csl/thesis.txt:
--------------------------------------------------------------------------------
1 | ---
2 | @thesis{geer,
3 | Annotation = {This is a typical thesis entry for a PhD thesis. Note the type field in the database file which uses a localization key. Also note the format of the printed name and compare the useprefix option in the options field as well as vangennep},
4 | Author = {de Geer, Ingrid},
5 | Date = 1985,
6 | Institution = {Uppsala Universitet},
7 | Location = {Uppsala},
8 | Options = {useprefix=false},
9 | Subtitle = {The {Orkney} earldom of the twelfth century. {A} musicological study},
10 | Title = {Earl, saint, bishop, skald and music},
11 | Type = {phdthesis}}
12 |
13 | @thesis{loh,
14 | Annotation = {This is a typical thesis entry for an MA thesis. Note the type field in the database file which uses a localization key},
15 | Author = {Loh, Nin C.},
16 | Date = 1992,
17 | Institution = {Massachusetts Institute of Technology},
18 | Location = {Cambridge, Mass.},
19 | Title = {High-resolution micromachined interferometric accelerometer},
20 | Type = {mathesis}}
21 | ---
22 | - annote: This is a typical thesis entry for a PhD thesis. Note the type
23 | field in the database file which uses a localization key. Also note
24 | the format of the printed name and compare the useprefix option in
25 | the options field as well as vangennep
26 | author:
27 | - family: Geer
28 | given: Ingrid
29 | non-dropping-particle: de
30 | blt-type: thesis
31 | genre: PhD thesis
32 | id: geer
33 | issued: 1985
34 | publisher: Uppsala Universitet
35 | publisher-place: Uppsala
36 | title: "Earl, saint, bishop, skald and music: The Orkney earldom of
37 | the twelfth century. A musicological study"
38 | title-short: Earl, saint, bishop, skald and music
39 | type: thesis
40 | - annote: This is a typical thesis entry for an MA thesis. Note the type
41 | field in the database file which uses a localization key
42 | author:
43 | - family: Loh
44 | given: Nin C.
45 | blt-type: thesis
46 | genre: Master's thesis
47 | id: loh
48 | issued: 1992
49 | publisher: Massachusetts Institute of Technology
50 | publisher-place: Cambridge, Mass.
51 | title: High-resolution micromachined interferometric accelerometer
52 | type: thesis
53 |
--------------------------------------------------------------------------------
/citeproc-macro.el:
--------------------------------------------------------------------------------
1 | ;; citeproc-macro.el --- functions to render CSL macros -*- lexical-binding: t; -*-
2 |
3 | ;; Copyright (C) 2017 András Simonyi
4 |
5 | ;; Author: András Simonyi
6 |
7 | ;; This program is free software; you can redistribute it and/or modify
8 | ;; it under the terms of the GNU General Public License as published by
9 | ;; the Free Software Foundation, either version 3 of the License, or
10 | ;; (at your option) any later version.
11 |
12 | ;; This program is distributed in the hope that it will be useful,
13 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | ;; GNU General Public License for more details.
16 |
17 | ;; You should have received a copy of the GNU General Public License
18 | ;; along with this program. If not, see .
19 |
20 | ;; This file is not part of GNU Emacs.
21 |
22 | ;;; Commentary:
23 |
24 | ;; Functions to render the output of CSL macros.
25 |
26 | ;;; Code:
27 |
28 | (require 'citeproc-lib)
29 | (require 'citeproc-rt)
30 | (require 'citeproc-context)
31 |
32 | ;;; For macro evaluation
33 | (defun citeproc--macro (attrs context &rest body)
34 | "Render the content of a macro element with ATTRS and BODY."
35 | (let* ((spliced-body (citeproc-lib-splice-into body 'splice))
36 | (val (citeproc-rt-typed-join attrs spliced-body context)))
37 | (if (eq 'empty-vars (cdr val))
38 | (cons nil 'text-only)
39 | val)))
40 |
41 | (defun citeproc-macro-output (macro context)
42 | "Return the output of MACRO.
43 | MACRO is the macro's name as a string and the returned value is a
44 | (RICH-TEXT-CONTENT . CONTENT-TYPE) cons cell."
45 | (let ((macro-fun (assoc-default macro (citeproc-context-macros context))))
46 | (if macro-fun
47 | (funcall macro-fun context)
48 | (error "There is no macro called `%s' in style" macro))))
49 |
50 | (defun citeproc-macro-output-as-text (macro context)
51 | "Return the output of MACRO as plain text.
52 | MACRO is the macro's name as a string."
53 | (citeproc-rt-to-plain (citeproc-rt-render-affixes
54 | (car (citeproc-macro-output macro context)))))
55 |
56 | (provide 'citeproc-macro)
57 |
58 | ;;; citeproc-macro.el ends here
59 |
--------------------------------------------------------------------------------
/test/biblatex_csl/online.txt:
--------------------------------------------------------------------------------
1 | ---
2 | @comment{adapted from http://mirrors.ctan.org/macros/latex/contrib/biblatex/doc/examples/biblatex-examples.bib}
3 |
4 | @online{markey,
5 | Annotation = {An online entry for a tutorial. Note the format of the date field (yyyy-mm-dd) in the database file.},
6 | Author = {Markey, Nicolas},
7 | Date = {2005-10-16},
8 | Sorttitle = {Tame the Beast},
9 | Subtitle = {The {B} to {X} of {BibTeX}},
10 | Title = {Tame the {BeaST}},
11 | Url = {http://tug.ctan.org/tex-archive/info/bibtex/tamethebeast/ttb_en.pdf},
12 | Urldate = {2006-10-01},
13 | Version = {1.3},
14 | }
15 |
16 | @online{CTAN,
17 | Annotation = {This is an online entry. The url, which is given in the url field, is transformed into a clickable link if hyperref support has been enabled. Note the format of the urldate field (yyyy-mm-dd) in the database file. Also note the label field which may be used as a fallback by citation styles which need an author and/or a year},
18 | Date = 2006,
19 | Label = {CTAN},
20 | Subtitle = {The {Comprehensive TeX Archive Network}},
21 | Title = {{CTAN}},
22 | Url = {http://www.ctan.org},
23 | Urldate = {2006-10-01},
24 | }
25 | ---
26 | - accessed: 2006-10-01
27 | annote: An online entry for a tutorial. Note the format of the date
28 | field (yyyy-mm-dd) in the database file.
29 | author:
30 | - family: Markey
31 | given: Nicolas
32 | blt-type: online
33 | id: markey
34 | issued: 2005-10-16
35 | title: "Tame the BeaST: The B to X of BibTeX"
36 | title-short: Tame the BeaST
37 | type: webpage
38 | URL: "http://tug.ctan.org/tex-archive/info/bibtex/tamethebeast/ttb_en.pdf"
39 | version: 1.3
40 | - accessed: 2006-10-01
41 | annote: This is an online entry. The url, which is given
42 | in the url field, is transformed into a clickable link if hyperref
43 | support has been enabled. Note the format of the urldate field
44 | (yyyy-mm-dd) in the database file. Also note the label field which
45 | may be used as a fallback by citation styles which need an author
46 | and/or a year
47 | blt-type: online
48 | citation-label: "CTAN"
49 | id: CTAN
50 | issued: 2006
51 | title: "CTAN: The Comprehensive TeX Archive Network"
52 | title-short: CTAN
53 | type: webpage
54 | URL: "http://www.ctan.org"
55 |
--------------------------------------------------------------------------------
/test/human/citation_Textual.txt:
--------------------------------------------------------------------------------
1 | >>===== MODE =====>>
2 | citation
3 | <<===== MODE =====<<
4 |
5 |
6 | >>===== RESULT =====>>
7 | Smith (1986)
8 | (Smith 1986)
9 | <<===== RESULT =====<<
10 |
11 |
12 | >>===== CITATIONS =====>>
13 | [
14 | [
15 | {
16 | "citationID": "CITATION-1",
17 | "citationItems": [
18 | {
19 | "id": "ITEM-1"
20 | }
21 | ],
22 | "properties": {
23 | "noteIndex": 0,
24 | "mode": "textual"
25 | }
26 | },
27 | [],
28 | []
29 | ],
30 | [
31 | {
32 | "citationID": "CITATION-2",
33 | "citationItems": [
34 | {
35 | "id": "ITEM-1"
36 | }
37 | ],
38 | "properties": {
39 | "noteIndex": 1
40 | }
41 | },
42 | [],
43 | []
44 | ]
45 |
46 | ]
47 | <<===== CITATIONS =====<<
48 |
49 |
50 |
51 | >>===== CSL =====>>
52 |
81 | <<===== CSL =====<<
82 |
83 |
84 | >>===== INPUT =====>>
85 | [
86 | {
87 | "author": [
88 | {
89 | "family": "Smith",
90 | "given": "John"
91 | }
92 | ],
93 | "issued": {
94 | "date-parts": [
95 | [
96 | 1986
97 | ]
98 | ]
99 | },
100 | "type": "book",
101 | "id": "ITEM-1"
102 | }
103 | ]
104 | <<===== INPUT =====<<
105 |
106 |
--------------------------------------------------------------------------------
/test/human/citation_SuppressAuthor.txt:
--------------------------------------------------------------------------------
1 | >>===== MODE =====>>
2 | citation
3 | <<===== MODE =====<<
4 |
5 |
6 | >>===== RESULT =====>>
7 | (1986 A nice title)
8 | (Smith 1986 A nice title)
9 | <<===== RESULT =====<<
10 |
11 |
12 | >>===== CITATIONS =====>>
13 | [
14 | [
15 | {
16 | "citationID": "CITATION-1",
17 | "citationItems": [
18 | {
19 | "id": "ITEM-1"
20 | }
21 | ],
22 | "properties": {
23 | "noteIndex": 0,
24 | "mode": "suppress-author"
25 | }
26 | },
27 | [],
28 | []
29 | ],
30 | [
31 | {
32 | "citationID": "CITATION-1",
33 | "citationItems": [
34 | {
35 | "id": "ITEM-1"
36 | }
37 | ],
38 | "properties": {
39 | "noteIndex": 0
40 | }
41 | },
42 | [],
43 | []
44 | ]
45 | ]
46 | <<===== CITATIONS =====<<
47 |
48 |
49 |
50 | >>===== CSL =====>>
51 |
81 | <<===== CSL =====<<
82 |
83 |
84 | >>===== INPUT =====>>
85 | [
86 | {
87 | "author": [
88 | {
89 | "family": "Smith",
90 | "given": "John"
91 | }
92 | ],
93 | "title": "A nice title",
94 | "issued": {
95 | "date-parts": [
96 | [
97 | 1986
98 | ]
99 | ]
100 | },
101 | "type": "book",
102 | "id": "ITEM-1"
103 | }
104 | ]
105 | <<===== INPUT =====<<
106 |
107 |
--------------------------------------------------------------------------------
/test/etc/subbibs.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 |
4 | "id": "doe2001",
5 | "type": "article-journal",
6 | "container-title": "The Mind Scientific",
7 | "issue": "1",
8 | "page": "45-58",
9 | "title": "The Title",
10 | "volume": "103",
11 | "author": [
12 | {
13 | "family": "Doe",
14 | "given": "John"
15 | }
16 | ],
17 | "issued": {
18 | "date-parts": [
19 | [
20 | "2001",
21 | 3
22 | ]
23 | ]
24 | },
25 | "keyword": "primary,philosophy"
26 | },
27 | {
28 | "id": "smith1952",
29 | "type": "book",
30 | "title": "The Book Title",
31 | "author": [
32 | {
33 | "family": "Smith",
34 | "given": "Peter"
35 | }
36 | ],
37 | "issued": {
38 | "date-parts": [
39 | [
40 | "1952"
41 | ]
42 | ]
43 | },
44 | "keyword": "primary"
45 | },
46 | {
47 | "id": "doe1972",
48 | "type": "book",
49 | "title": "The Second Book Title",
50 | "author": [
51 | {
52 | "family": "Doe",
53 | "given": "Jane"
54 | }
55 | ],
56 | "issued": {
57 | "date-parts": [
58 | [
59 | "1972"
60 | ]
61 | ]
62 | }
63 | },
64 | {
65 | "id": "doe1972b",
66 | "type": "book",
67 | "title": "The Second 1972 Jane Doe book",
68 | "author": [
69 | {
70 | "family": "Doe",
71 | "given": "Jane"
72 | }
73 | ],
74 | "issued": {
75 | "date-parts": [
76 | [
77 | "1972"
78 | ]
79 | ]
80 | },
81 | "keyword": "secondary"
82 | },
83 | {
84 | "id": "doe1972c",
85 | "type": "book",
86 | "title": "The Third 1972 Jane Doe book",
87 | "author": [
88 | {
89 | "family": "Doe",
90 | "given": "Jane"
91 | }
92 | ],
93 | "issued": {
94 | "date-parts": [
95 | [
96 | "1972"
97 | ]
98 | ]
99 | },
100 | "keyword": "primary"
101 | }
102 | ]
103 |
--------------------------------------------------------------------------------
/test/human/citation_TextualCapitalizeFirst.txt:
--------------------------------------------------------------------------------
1 | >>===== MODE =====>>
2 | citation
3 | <<===== MODE =====<<
4 |
5 |
6 | >>===== RESULT =====>>
7 | (della Robbia 1986)
8 | Della Robbia (1986)
9 | <<===== RESULT =====<<
10 |
11 |
12 | >>===== CITATIONS =====>>
13 | [
14 | [
15 | {
16 | "citationID": "CITATION-1",
17 | "citationItems": [
18 | {
19 | "id": "ITEM-1"
20 | }
21 | ],
22 | "properties": {
23 | "noteIndex": 0
24 |
25 | }
26 | },
27 | [],
28 | []
29 | ],
30 | [
31 | {
32 | "citationID": "CITATION-1",
33 | "citationItems": [
34 | {
35 | "id": "ITEM-1"
36 | }
37 | ],
38 | "properties": {
39 | "noteIndex": 1,
40 | "capitalize-first": 1,
41 | "mode": "textual"
42 | }
43 | },
44 | [],
45 | []
46 | ]
47 | ]
48 | <<===== CITATIONS =====<<
49 |
50 |
51 |
52 | >>===== CSL =====>>
53 |
82 | <<===== CSL =====<<
83 |
84 |
85 | >>===== INPUT =====>>
86 | [
87 | {
88 | "author": [
89 | {
90 | "family": "della Robbia",
91 | "given": "Luca"
92 | }
93 | ],
94 | "title": "A nice title",
95 | "issued": {
96 | "date-parts": [
97 | [
98 | 1986
99 | ]
100 | ]
101 | },
102 | "type": "book",
103 | "id": "ITEM-1"
104 | }
105 | ]
106 | <<===== INPUT =====<<
107 |
108 |
--------------------------------------------------------------------------------
/test/human/intlink_NonNoteStyle.txt:
--------------------------------------------------------------------------------
1 | >>===== OUTPUT-FORMAT =====>>
2 | org
3 | <<===== OUTPUT-FORMAT =====<<
4 |
5 | >>===== MODE =====>>
6 | citation
7 | <<===== MODE =====<<
8 |
9 |
10 | >>===== RESULT =====>>
11 | Smith ([[citeproc_bib_item_1][1986]])
12 | ([[citeproc_bib_item_1][Smith 1986]])
13 | <<===== RESULT =====<<
14 |
15 |
16 | >>===== CITATIONS =====>>
17 | [
18 | [
19 | {
20 | "citationID": "CITATION-1",
21 | "citationItems": [
22 | {
23 | "id": "ITEM-1"
24 | }
25 | ],
26 | "properties": {
27 | "noteIndex": 0,
28 | "mode": "textual"
29 | }
30 | },
31 | [],
32 | []
33 | ],
34 | [
35 | {
36 | "citationID": "CITATION-2",
37 | "citationItems": [
38 | {
39 | "id": "ITEM-1"
40 | }
41 | ],
42 | "properties": {
43 | "noteIndex": 1
44 | }
45 | },
46 | [],
47 | []
48 | ]
49 |
50 | ]
51 | <<===== CITATIONS =====<<
52 |
53 |
54 |
55 | >>===== CSL =====>>
56 |
85 | <<===== CSL =====<<
86 |
87 |
88 | >>===== INPUT =====>>
89 | [
90 | {
91 | "author": [
92 | {
93 | "family": "Smith",
94 | "given": "John"
95 | }
96 | ],
97 | "issued": {
98 | "date-parts": [
99 | [
100 | 1986
101 | ]
102 | ]
103 | },
104 | "type": "book",
105 | "id": "ITEM-1"
106 | }
107 | ]
108 | <<===== INPUT =====<<
109 |
110 |
--------------------------------------------------------------------------------
/test/human/intlink_NoteStyle.txt:
--------------------------------------------------------------------------------
1 | >>===== OUTPUT-FORMAT =====>>
2 | org
3 | <<===== OUTPUT-FORMAT =====<<
4 |
5 | >>===== MODE =====>>
6 | citation
7 | <<===== MODE =====<<
8 |
9 | >>===== RESULT =====>>
10 | (<>Smith 1986)
11 | ([[citeproc_bib_item_1][Smith 1986]])
12 | <<===== RESULT =====<<
13 |
14 |
15 | >>===== CITATIONS =====>>
16 | [
17 | [
18 | {
19 | "citationID": "CITATION-1",
20 | "citationItems": [
21 | {
22 | "id": "ITEM-1"
23 | }
24 | ],
25 | "properties": {
26 | "noteIndex": 0
27 | }
28 | },
29 | [],
30 | []
31 | ],
32 | [
33 | {
34 | "citationID": "CITATION-2",
35 | "citationItems": [
36 | {
37 | "id": "ITEM-1"
38 | }
39 | ],
40 | "properties": {
41 | "noteIndex": 1
42 | }
43 | },
44 | [],
45 | []
46 | ]
47 |
48 | ]
49 | <<===== CITATIONS =====<<
50 |
51 |
52 |
53 | >>===== CSL =====>>
54 |
84 | <<===== CSL =====<<
85 |
86 |
87 | >>===== INPUT =====>>
88 | [
89 | {
90 | "author": [
91 | {
92 | "family": "Smith",
93 | "given": "John"
94 | }
95 | ],
96 | "issued": {
97 | "date-parts": [
98 | [
99 | 1986
100 | ]
101 | ]
102 | },
103 | "type": "book",
104 | "id": "ITEM-1"
105 | }
106 | ]
107 | <<===== INPUT =====<<
108 |
109 |
--------------------------------------------------------------------------------
/test/human/citation_ApplyModeAfterSortingCites.txt:
--------------------------------------------------------------------------------
1 | >>===== MODE =====>>
2 | citation
3 | <<===== MODE =====<<
4 |
5 |
6 | >>===== RESULT =====>>
7 | Smith (1986, 1992)
8 | <<===== RESULT =====<<
9 |
10 |
11 | >>===== CITATIONS =====>>
12 | [
13 | [
14 | {
15 | "citationID": "CITATION-1",
16 | "citationItems": [
17 | {
18 | "id": "ITEM-2"
19 | },
20 | {
21 | "id": "ITEM-1"
22 | }
23 | ],
24 | "properties": {
25 | "noteIndex": 0,
26 | "mode": "textual"
27 | }
28 | },
29 | [],
30 | []
31 | ]
32 | ]
33 | <<===== CITATIONS =====<<
34 |
35 |
36 |
37 | >>===== CSL =====>>
38 |
71 | <<===== CSL =====<<
72 |
73 |
74 | >>===== INPUT =====>>
75 | [
76 | {
77 | "author": [
78 | {
79 | "family": "Smith",
80 | "given": "John"
81 | }
82 | ],
83 | "issued": {
84 | "date-parts": [
85 | [
86 | 1986
87 | ]
88 | ]
89 | },
90 | "type": "book",
91 | "id": "ITEM-1"
92 | },
93 | {
94 | "author": [
95 | {
96 | "family": "Smith",
97 | "given": "John"
98 | }
99 | ],
100 | "issued": {
101 | "date-parts": [
102 | [
103 | 1992
104 | ]
105 | ]
106 | },
107 | "type": "book",
108 | "id": "ITEM-2"
109 | }
110 | ]
111 | <<===== INPUT =====<<
112 |
113 |
--------------------------------------------------------------------------------
/test/biblatex_csl/article.txt:
--------------------------------------------------------------------------------
1 | ---
2 | @article{article-req,
3 | Author = {Author, Ann},
4 | Date = {2013-01-01},
5 | Journaltitle = {The Journaltitle},
6 | Title = {An article entry with just the required fields},
7 | Langid = {english}},
8 |
9 | @article{article-opt,
10 | Addendum = {The Addendum},
11 | Annotator = {Annotator, A.},
12 | Author = {Author, Jr., Ann A.},
13 | Commentator = {Commentator, C.},
14 | Date = {2013-01-01},
15 | Doi = {10.1086/520976},
16 | Editor = {Editor, Edward},
17 | Editora = {Editor, A.},
18 | Editorb = {Editor, B.},
19 | Editorc = {Editor, C.},
20 | Eid = {eid},
21 | Eprint = {eprint},
22 | Eprintclass = {eprintclass},
23 | Eprinttype = {eprinttype},
24 | Issn = {issn},
25 | Issue = {issue},
26 | Issuesubtitle = {The Issuesubtitle},
27 | Issuetitle = {The Issuetitle},
28 | Journalsubtitle = {The Journalsubtitle},
29 | Journaltitle = {The Journaltitle},
30 | Journal = {The Journal},
31 | Language = {language},
32 | Month = {01},
33 | Year = {2013},
34 | Note = {The Note},
35 | Number = {number},
36 | Origlanguage = {origlanguage},
37 | Pages = {pages},
38 | Pubstate = {in press},
39 | Series = {new series},
40 | Subtitle = {The subtitle},
41 | Title = {An article entry with the required and all optional fields},
42 | Titleaddon = {The titleaddon},
43 | Translator = {Translator, Ted},
44 | Url = {http://foo.bar.baz/},
45 | Urldate = {2013-01-01},
46 | Version = {version},
47 | Volume = {volume},
48 | Langid = {english}
49 | }
50 | ---
51 | - author:
52 | - family: Author
53 | given: Ann
54 | blt-type: article
55 | container-title: The journaltitle
56 | id: article-req
57 | issued: 2013-01-01
58 | language: en-US
59 | title: An article entry with just the required fields
60 | type: article-journal
61 | - accessed: 2013-01-01
62 | author:
63 | - family: Author
64 | given: Ann A.
65 | suffix: Jr.
66 | blt-type: article
67 | collection-title: New series
68 | container-title: "The journaltitle: The journalsubtitle"
69 | DOI: 10.1086/520976
70 | editor:
71 | - family: Editor
72 | given: Edward
73 | blt-type: article
74 | id: article-opt
75 | ISSN: issn
76 | issue: number, issue
77 | issued: 2013-01-01
78 | language: en-US
79 | note: The Note. The Addendum
80 | page: pages
81 | status: in press
82 | title: "An article entry with the required and all optional fields:
83 | The subtitle. The titleaddon"
84 | title-short: An article entry with the required and all optional
85 | fields
86 | translator:
87 | - family: Translator
88 | given: Ted
89 | type: article-journal
90 | URL: "http://foo.bar.baz/"
91 | version: version
92 | volume: volume
93 |
--------------------------------------------------------------------------------
/test/human/citation_IgnoreEtAl.txt:
--------------------------------------------------------------------------------
1 | >>===== MODE =====>>
2 | citation
3 | <<===== MODE =====<<
4 |
5 |
6 | >>===== RESULT =====>>
7 | (Smith et al. 1986)
8 | (Smith, Doe, Taylor & Carpenter 1986)
9 | <<===== RESULT =====<<
10 |
11 |
12 | >>===== CITATIONS =====>>
13 | [
14 | [
15 | {
16 | "citationID": "CITATION-1",
17 | "citationItems": [
18 | {
19 | "id": "ITEM-1"
20 | }
21 | ],
22 | "properties": {
23 | "noteIndex": 0
24 |
25 | }
26 | },
27 | [],
28 | []
29 | ],
30 | [
31 | {
32 | "citationID": "CITATION-1",
33 | "citationItems": [
34 | {
35 | "id": "ITEM-1"
36 | }
37 | ],
38 | "properties": {
39 | "noteIndex": 0,
40 | "ignore-et-al": 1
41 | }
42 | },
43 | [],
44 | []
45 | ]
46 | ]
47 | <<===== CITATIONS =====<<
48 |
49 |
50 |
51 | >>===== CSL =====>>
52 |
81 | <<===== CSL =====<<
82 |
83 |
84 | >>===== INPUT =====>>
85 | [
86 | {
87 | "author": [
88 | {
89 | "family": "Smith",
90 | "given": "John"
91 | },
92 | {
93 | "family": "Doe",
94 | "given": "Jane"
95 | },
96 | {
97 | "family": "Taylor",
98 | "given": "Tom"
99 | },
100 | {
101 | "family": "Carpenter",
102 | "given": "Emma"
103 | }
104 |
105 | ],
106 | "title": "A nice title",
107 | "issued": {
108 | "date-parts": [
109 | [
110 | 1986
111 | ]
112 | ]
113 | },
114 | "type": "book",
115 | "id": "ITEM-1"
116 | }
117 | ]
118 | <<===== INPUT =====<<
119 |
120 |
--------------------------------------------------------------------------------
/test/biblatex_csl/inproceedings.txt:
--------------------------------------------------------------------------------
1 | ---
2 | @string{cup = {Cambridge University Press}}
3 |
4 | @inproceedings{moraux,
5 | Annotation = {This is a typical inproceedings entry. Note the booksubtitle, shorttitle, indextitle, and indexsorttitle fields. Also note the eventdate field.},
6 | Author = {Moraux, Paul},
7 | Booktitle = {Aristotle on Mind and the Senses},
8 | Booktitleaddon = {Proceedings of the Seventh Symposium Aristotelicum},
9 | Date = 1979,
10 | Editor = {Lloyd, G. E. R. and Owen, G. E. L.},
11 | Eventdate = 1975,
12 | Indexsorttitle = {De Anima dans la tradition grecque},
13 | Indextitle = {De Anima dans la tradition grècque, Le},
14 | Keywords = {secondary},
15 | Location = {Cambridge},
16 | Pages = {281-324},
17 | Publisher = cup,
18 | Shorttitle = {De Anima dans la tradition grècque},
19 | Subtitle = {Quelques aspects de l'interpretation du traité, de Theophraste à Themistius},
20 | Title = {Le De Anima dans la tradition grècque},
21 | Langid = {french}}
22 |
23 | @inproceedings{salam,
24 | Author = {Salam, Abdus},
25 | Booksubtitle = {Relativistic groups and analyticity},
26 | Booktitle = {Elementary particle theory},
27 | Booktitleaddon = {Proceedings of the Eighth {Nobel} Symposium},
28 | Date = 1968,
29 | Editor = {Svartholm, Nils},
30 | Eventdate = {1968-05-19/1968-05-25},
31 | Location = {Stockholm},
32 | Pages = {367-377},
33 | Publisher = {Almquist \& Wiksell},
34 | Title = {Weak and Electromagnetic Interactions},
35 | Venue = {Aspenäsgarden, Lerum}}
36 | ---
37 | - annote: This is a typical inproceedings entry. Note the booksubtitle,
38 | shorttitle, indextitle, and indexsorttitle fields. Also note the
39 | eventdate field.
40 | author:
41 | - family: Moraux
42 | given: Paul
43 | blt-type: inproceedings
44 | container-title: Aristotle on Mind and the Senses. Proceedings of the
45 | Seventh Symposium Aristotelicum
46 | editor:
47 | - family: Lloyd
48 | given: G. E. R.
49 | - family: Owen
50 | given: G. E. L.
51 | event-date: 1975
52 | id: moraux
53 | issued: 1979
54 | language: fr-FR
55 | keyword: secondary
56 | page: 281-324
57 | publisher: Cambridge University Press
58 | publisher-place: Cambridge
59 | title: "Le De Anima dans la tradition grècque: Quelques aspects de
60 | l'interpretation du traité, de Theophraste à Themistius"
61 | title-short: "De Anima dans la tradition grècque"
62 | type: paper-conference
63 | - author:
64 | - family: Salam
65 | given: Abdus
66 | blt-type: inproceedings
67 | container-title: "Elementary particle theory: Relativistic groups and
68 | analyticity. Proceedings of the eighth Nobel symposium"
69 | editor:
70 | - family: Svartholm
71 | given: Nils
72 | event-date: 1968-05-19/1968-05-25
73 | event-place: Aspenäsgarden, Lerum
74 | id: salam
75 | issued: 1968
76 | page: 367-377
77 | publisher: Almquist & Wiksell
78 | publisher-place: Stockholm
79 | title: Weak and electromagnetic interactions
80 | type: paper-conference
81 |
--------------------------------------------------------------------------------
/test/biblatex_csl/inspect.org:
--------------------------------------------------------------------------------
1 | * Test
2 |
3 | #+begin_src emacs-lisp
4 | (setq citeproc-test-blt-current "thesis")
5 | #+end_src
6 |
7 | #+RESULTS:
8 | : thesis
9 |
10 | * Expected
11 |
12 | #+begin_src emacs-lisp :results value code
13 | (let* ((file (concat "./" citeproc-test-blt-current ".txt"))
14 | (csl-entries (cdr
15 | (citeproc-test-blt--parse file))))
16 | (citeproc-test-blt--normalize-csl-entries
17 | csl-entries))
18 | #+end_src
19 |
20 | #+RESULTS:
21 | #+begin_src emacs-lisp
22 | (((annote . "This is a typical thesis entry for a PhD thesis. Note the type field in the database file which uses a localization key. Also note the format of the printed name and compare the useprefix option in the options field as well as vangennep")
23 | (author
24 | ((dropping-particle . "de")
25 | (family . "Geer")
26 | (given . "Ingrid")))
27 | (genre . "PhD thesis")
28 | (id . "geer")
29 | (issued
30 | (date-parts
31 | (1985)))
32 | (publisher . "Uppsala Universitet")
33 | (publisher-place . "Uppsala")
34 | (title . "Earl, saint, bishop, skald and music: The Orkney earldom of the twelfth century. A musicological study")
35 | (title-short . "Earl, saint, bishop, skald and music")
36 | (type . "thesis"))
37 | ((annote . "This is a typical thesis entry for an MA thesis. Note the type field in the database file which uses a localization key")
38 | (author
39 | ((family . "Loh")
40 | (given . "Nin C.")))
41 | (genre . "Master's thesis")
42 | (id . "loh")
43 | (issued
44 | (date-parts
45 | (1992)))
46 | (publisher . "Massachusetts Institute of Technology")
47 | (publisher-place . "Cambridge, Mass.")
48 | (title . "High-resolution micromachined interferometric accelerometer")
49 | (type . "thesis")))
50 | #+end_src
51 | * Output
52 | #+begin_src emacs-lisp :results value code
53 | (let* ((file (concat "./" citeproc-test-blt-current ".txt"))
54 | (blt (car
55 | (citeproc-test-blt--parse file))))
56 | (citeproc-test-blt--output blt))
57 | #+end_src
58 |
59 | #+RESULTS:
60 | #+begin_src emacs-lisp
61 | (((annote . "This is a typical thesis entry for a PhD thesis. Note the type field in the database file which uses a localization key. Also note the format of the printed name and compare the useprefix option in the options field as well as vangennep")
62 | (author
63 | ((dropping-particle . "de")
64 | (family . "Geer")
65 | (given . "Ingrid")))
66 | (genre . "PhD thesis")
67 | (id . "geer")
68 | (issued
69 | (date-parts
70 | (1985)))
71 | (publisher . "Uppsala Universitet")
72 | (publisher-place . "Uppsala")
73 | (title . "Earl, Saint, Bishop, Skald and Music: The Orkney Earldom of the Twelfth Century. A Musicological Study")
74 | (title-short . "Earl, Saint, Bishop, Skald and Music")
75 | (type . "thesis"))
76 | ((annote . "This is a typical thesis entry for an MA thesis. Note the type field in the database file which uses a localization key")
77 | (author
78 | ((family . "Loh")
79 | (given . "Nin C.")))
80 | (genre . "Master's thesis")
81 | (id . "loh")
82 | (issued
83 | (date-parts
84 | (1992)))
85 | (publisher . "Massachusetts Institute of Technology")
86 | (publisher-place . "Cambridge, Mass.")
87 | (title . "High-Resolution Micromachined Interferometric Accelerometer")
88 | (type . "thesis")))
89 | #+end_src
90 |
91 |
--------------------------------------------------------------------------------
/citeproc-subbibs.el:
--------------------------------------------------------------------------------
1 | ;;; citeproc-subbibs.el --- support for subbibliographies -*- lexical-binding: t; -*-
2 |
3 | ;; Copyright (C) 2021-2022 András Simonyi
4 |
5 | ;; Author: András Simonyi
6 |
7 | ;; This program is free software; you can redistribute it and/or modify
8 | ;; it under the terms of the GNU General Public License as published by
9 | ;; the Free Software Foundation, either version 3 of the License, or
10 | ;; (at your option) any later version.
11 |
12 | ;; This program is distributed in the hope that it will be useful,
13 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | ;; GNU General Public License for more details.
16 |
17 | ;; You should have received a copy of the GNU General Public License
18 | ;; along with this program. If not, see .
19 |
20 | ;; This file is not part of GNU Emacs.
21 |
22 | ;;; Commentary:
23 |
24 | ;; Support for generating subbibliographies based on filtering items.
25 |
26 | ;;; Code:
27 |
28 | (require 'subr-x)
29 | (require 'compat)
30 | (require 'dash)
31 |
32 | (require 'citeproc-proc)
33 | (require 'citeproc-itemdata)
34 |
35 | (defun citeproc-sb--match-p (vv filter)
36 | "Return whether var-vals alist VV matches all conditions in FILTER.
37 | FILTER should be an alist containing symbol keys and string
38 | values, each pair describing an atomic condition to be
39 | satisified. For a list and description of the supported keys
40 | see the documentation of `citeproc-add-subbib-filters'."
41 | (let* ((csl-type (alist-get 'type vv))
42 | (type (or (alist-get 'blt-type vv) csl-type))
43 | (keyword (alist-get 'keyword vv))
44 | (keywords (and keyword (mapcar #'string-clean-whitespace
45 | (split-string keyword "[,;]" t)))))
46 | (--every-p
47 | (pcase it
48 | (`(type . ,key) (string= type key))
49 | (`(nottype . ,key) (not (string= type key)))
50 | (`(keyword . ,key) (member key keywords))
51 | (`(notkeyword . ,key) (not (member key keywords)))
52 | (`(filter . ,key) (funcall (intern key) vv))
53 | (`(csltype . ,key) (string= csl-type key))
54 | (`(notcsltype . ,key) (not (string= csl-type key)))
55 | (`(,key . ,_) (error "Unsupported Citeproc filter keyword `%s'" key)))
56 | filter)))
57 |
58 | (defun citeproc-sb-add-subbib-info (proc)
59 | "Add subbibliography information to the items in PROC."
60 | (when (citeproc-proc-filtered-bib-p proc)
61 | (let ((filters (citeproc-proc-bib-filters proc)))
62 | (maphash
63 | (lambda (_ itemdata)
64 | (let* ((varvals (citeproc-itemdata-varvals itemdata))
65 | (subbib-nos
66 | (-non-nil
67 | (--map-indexed
68 | (when (citeproc-sb--match-p varvals it) it-index)
69 | filters))))
70 | (setf (citeproc-itemdata-subbib-nos itemdata) subbib-nos)))
71 | (citeproc-proc-itemdata proc)))))
72 |
73 | (defun citeproc-sb-prune-unrendered (proc)
74 | "Remove all itemdata about unrendered items from PROC.
75 | An item is unrendered if
76 | - there are subbibfilters but none of them matches it, and
77 | - it is not cited."
78 | (when (citeproc-proc-filtered-bib-p proc)
79 | (let ((itemdata (citeproc-proc-itemdata proc)))
80 | (maphash
81 | (lambda (id data)
82 | (when (and (citeproc-itemdata-uncited data)
83 | (null (citeproc-itemdata-subbib-nos data)))
84 | (remhash id itemdata)))
85 | itemdata))))
86 |
87 | (provide 'citeproc-subbibs)
88 |
89 | ;;; citeproc-subbibs.el ends here
90 |
--------------------------------------------------------------------------------
/test/human/citation_TextualGroupedCites.txt:
--------------------------------------------------------------------------------
1 | >>===== MODE =====>>
2 | citation
3 | <<===== MODE =====<<
4 |
5 |
6 | >>===== RESULT =====>>
7 | Smith (1986, 1992; Doe 1971)
8 | Doe (1971; Smith 1986, 1992)
9 | <<===== RESULT =====<<
10 |
11 |
12 | >>===== CITATIONS =====>>
13 | [
14 | [
15 | {
16 | "citationID": "CITATION-1",
17 | "citationItems": [
18 | {
19 | "id": "ITEM-1"
20 | },
21 | {
22 | "id": "ITEM-2"
23 | },
24 | {
25 | "id": "ITEM-3"
26 | }
27 | ],
28 | "properties": {
29 | "noteIndex": 0,
30 | "mode": "textual"
31 | }
32 | },
33 | [],
34 | []
35 | ],
36 | [
37 | {
38 | "citationID": "CITATION-2",
39 | "citationItems": [
40 | {
41 | "id": "ITEM-3"
42 | },
43 | {
44 | "id": "ITEM-1"
45 | },
46 | {
47 | "id": "ITEM-2"
48 | }
49 | ],
50 | "properties": {
51 | "noteIndex": 1,
52 | "mode": "textual"
53 | }
54 | },
55 | [],
56 | []
57 | ]
58 |
59 | ]
60 | <<===== CITATIONS =====<<
61 |
62 |
63 |
64 | >>===== CSL =====>>
65 |
95 | <<===== CSL =====<<
96 |
97 |
98 | >>===== INPUT =====>>
99 | [
100 | {
101 | "author": [
102 | {
103 | "family": "Smith",
104 | "given": "John"
105 | }
106 | ],
107 | "issued": {
108 | "date-parts": [
109 | [
110 | 1986
111 | ]
112 | ]
113 | },
114 | "type": "book",
115 | "id": "ITEM-1"
116 | },
117 | {
118 | "author": [
119 | {
120 | "family": "Smith",
121 | "given": "John"
122 | }
123 | ],
124 | "issued": {
125 | "date-parts": [
126 | [
127 | 1992
128 | ]
129 | ]
130 | },
131 | "type": "book",
132 | "id": "ITEM-2"
133 | },
134 | {
135 | "author": [
136 | {
137 | "family": "Doe",
138 | "given": "Peter"
139 | }
140 | ],
141 | "issued": {
142 | "date-parts": [
143 | [
144 | 1971
145 | ]
146 | ]
147 | },
148 | "type": "book",
149 | "id": "ITEM-3"
150 | }
151 |
152 | ]
153 | <<===== INPUT =====<<
154 |
155 |
--------------------------------------------------------------------------------
/citeproc-locale.el:
--------------------------------------------------------------------------------
1 | ;; citeproc-locale.el --- CSL locale related functions -*- lexical-binding: t; -*-
2 |
3 | ;; Copyright (C) 2017-2022 András Simonyi
4 |
5 | ;; Author: András Simonyi
6 |
7 | ;; This program is free software; you can redistribute it and/or modify
8 | ;; it under the terms of the GNU General Public License as published by
9 | ;; the Free Software Foundation, either version 3 of the License, or
10 | ;; (at your option) any later version.
11 |
12 | ;; This program is distributed in the hope that it will be useful,
13 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | ;; GNU General Public License for more details.
16 |
17 | ;; You should have received a copy of the GNU General Public License
18 | ;; along with this program. If not, see .
19 |
20 | ;; This file is not part of GNU Emacs.
21 |
22 | ;;; Commentary:
23 |
24 | ;; In addition to some locale handling helpers, this file provides the function
25 | ;; `citeproc-locale-getter-from-dir', which constructs locale getter functions
26 | ;; that retrieve locales from a given directory.
27 |
28 | ;;; Code:
29 |
30 | (require 'dash)
31 | (require 'f)
32 | (require 's)
33 |
34 | (require 'citeproc-lib)
35 | (require 'citeproc-term)
36 |
37 | (defconst citeproc-locale--default-variants-alist
38 | '(("af" . "ZA") ("ca" . "AD") ("cs" . "CZ") ("cy" . "GB")
39 | ("da" . "DK") ("en" . "US") ("el" . "GR") ("et" . "EE")
40 | ("fa" . "IR") ("he" . "IR") ("ja" . "JP") ("km" . "KH")
41 | ("ko" . "KR") ("nb" . "NO") ("nn" . "NO") ("sl" . "SI")
42 | ("sr" . "RS") ("sv" . "SE") ("uk" . "UA") ("vi" . "VN")
43 | ("zh" . "CN"))
44 | "Alist mapping locales to their default variants.
45 | Only those locales are given for which the default variant is not
46 | simply the result of upcasing.")
47 |
48 | (defconst citeproc-locale--simple-locales
49 | '("la" "eu" "ar")
50 | "List of simple locale names (without dash).")
51 |
52 | (defun citeproc-locale--extend (loc)
53 | "Extend simple locale LOC to default variant."
54 | (let ((variant (assoc-default loc citeproc-locale--default-variants-alist)))
55 | (concat loc "-" (or variant (s-upcase loc)))))
56 |
57 | (defun citeproc-locale--compatible-p (l1 l2)
58 | "Whether locales L1 and L2 are compatible."
59 | (or (not (and l1 l2))
60 | (s-prefix-p l1 l2)
61 | (s-prefix-p l2 l1)))
62 |
63 | (defun citeproc-locale-getter-from-dir (dir)
64 | "Return a locale getter getting parsed locales from a local DIR.
65 | If the requested locale couldn't be read then return the parsed
66 | en-US locale, which must exist, and warn the user."
67 | (let ((default-loc-file (f-join dir "locales-en-US.xml")))
68 | (lambda (loc)
69 | (let* ((ext-loc (if (or (member loc citeproc-locale--simple-locales)
70 | (s-contains-p "-" loc))
71 | loc
72 | (citeproc-locale--extend loc)))
73 | (loc-file (concat dir "/locales-" ext-loc ".xml"))
74 | (loc-available (f-readable-p loc-file)))
75 | (citeproc-lib-remove-xml-comments
76 | (citeproc-lib-parse-xml-file
77 | (if loc-available loc-file
78 | (if (not (f-readable-p default-loc-file))
79 | (error
80 | "The default CSL locale file %s doesn't exist or is unreadable"
81 | default-loc-file)
82 | (display-warning
83 | 'citeproc
84 | (format
85 | "Could not read CSL locale file %s, using the fallback en-US locale"
86 | loc-file))
87 | default-loc-file))))))))
88 |
89 | (defun citeproc-locale-termlist-from-xml-frag (frag)
90 | "Transform xml FRAG representing citeproc--terms into a citeproc-term list."
91 | (--mapcat (if (eq 'term (car it))
92 | (citeproc-term--from-xml-frag (cdr it))
93 | nil)
94 | frag))
95 |
96 | (provide 'citeproc-locale)
97 |
98 | ;;; citeproc-locale.el ends here
99 |
--------------------------------------------------------------------------------
/test/citeproc-test-int-subbibs.el:
--------------------------------------------------------------------------------
1 | ;;; citeproc-test-int-subbibs.el --- subbib tests -*- lexical-binding: t; -*-
2 |
3 | (require 'citeproc)
4 |
5 | (require 'ert)
6 |
7 | (defvar citeproc-test-int-root-dir "./test/")
8 |
9 | (ert-deftest citeproc-test-int-sb/add-subbib-info ()
10 | (let* ((ig (citeproc-itemgetter-from-csl-json
11 | (concat citeproc-test-int-root-dir "etc/subbibs.json")))
12 | (lg (citeproc-locale-getter-from-dir
13 | (concat citeproc-test-int-root-dir "locales")))
14 | (proc (citeproc-create
15 | (concat citeproc-test-int-root-dir "etc/chicago-author-date.csl") ig lg)))
16 | (citeproc-add-uncited '("doe2001" "smith1952" "doe1972") proc)
17 | (setf (citeproc-proc-bib-filters proc)
18 | '(((type . "book"))
19 | ((type . "article-journal"))
20 | ((keyword . "primary"))
21 | ((notkeyword . "primary") (nottype . "article-journal"))))
22 | (citeproc-proc-finalize proc)
23 | (citeproc-sb-add-subbib-info proc)
24 | (should (equal (citeproc-itemdata-subbib-nos
25 | (gethash "doe2001" (citeproc-proc-itemdata proc)))
26 | '(1 2)))
27 | (should (equal (citeproc-itemdata-subbib-nos
28 | (gethash "smith1952" (citeproc-proc-itemdata proc)))
29 | '(0 2)))
30 | (should (equal (citeproc-itemdata-subbib-nos
31 | (gethash "doe1972" (citeproc-proc-itemdata proc)))
32 | '(0 3)))))
33 |
34 | (ert-deftest citeproc-test-int-sb/end2end ()
35 | (let* ((ig (citeproc-itemgetter-from-csl-json
36 | (concat citeproc-test-int-root-dir "etc/subbibs.json")))
37 | (lg (citeproc-locale-getter-from-dir
38 | (concat citeproc-test-int-root-dir "locales")))
39 | (proc (citeproc-create
40 | (concat citeproc-test-int-root-dir "etc/chicago-author-date.csl") ig lg)))
41 | ;; Basic subdivision according to type
42 | (citeproc-add-uncited '("doe2001" "smith1952" "doe1972") proc)
43 | (citeproc-add-subbib-filters
44 | '(((type . "book"))
45 | ((type . "article-journal")))
46 | proc)
47 | (should (equal (car (citeproc-render-bib proc 'plain))
48 | '("Doe, Jane. 1972. The Second Book Title.\n\nSmith, Peter. 1952. The Book Title."
49 | "Doe, John. 2001. “The Title.” The Mind Scientific 103 (1): 45–58.")))
50 | (citeproc-clear proc)
51 | ;; Subsequent author substitution
52 | (citeproc-add-uncited '("doe1972" "doe1972b" "doe1972c") proc)
53 | (citeproc-add-subbib-filters
54 | '(((type . "book"))
55 | ((keyword . "primary")))
56 | proc)
57 | (should (equal (car (citeproc-render-bib proc 'plain))
58 | '("Doe, Jane. 1972a. The Second 1972 Jane Doe Book.\n\n———. 1972b. The Second Book Title.\n\n———. 1972c. The Third 1972 Jane Doe Book.\n\nSmith, Peter. 1952. The Book Title."
59 | "Doe, Jane. 1972c. The Third 1972 Jane Doe Book.\n\nDoe, John. 2001. “The Title.” The Mind Scientific 103 (1): 45–58.\n\nSmith, Peter. 1952. The Book Title.")))))
60 |
61 | (ert-deftest citeproc-test-int-sb/single-filter ()
62 | (let* ((ig (citeproc-itemgetter-from-csl-json
63 | (concat citeproc-test-int-root-dir "etc/subbibs.json")))
64 | (lg (citeproc-locale-getter-from-dir
65 | (concat citeproc-test-int-root-dir "locales")))
66 | (proc (citeproc-create
67 | (concat citeproc-test-int-root-dir "etc/chicago-author-date.csl") ig lg)))
68 | (citeproc-add-uncited '("doe1972" "doe1972b" "doe1972c") proc)
69 | ;; Single empty filter
70 | (citeproc-add-subbib-filters '(nil) proc)
71 | (should (equal (car (citeproc-render-bib proc 'plain))
72 | '("Doe, Jane. 1972a. The Second 1972 Jane Doe Book.\n\n———. 1972b. The Second Book Title.\n\n———. 1972c. The Third 1972 Jane Doe Book.")))
73 | (citeproc-clear proc)
74 | ;; Single non-empty filter
75 | (citeproc-add-uncited '("doe1972" "doe1972b" "doe1972c" "doe2001") proc)
76 | (citeproc-add-subbib-filters
77 | '(((type . "article-journal")))
78 | proc)
79 | (should (equal (car (citeproc-render-bib proc 'plain))
80 | '("Doe, John. 2001. “The Title.” The Mind Scientific 103 (1): 45–58.")))))
81 |
82 | (provide 'citeproc-test-int-subbibs)
83 |
84 | ;;; citeproc-test-int-subbibs.el ends here
85 |
--------------------------------------------------------------------------------
/citeproc-itemdata.el:
--------------------------------------------------------------------------------
1 | ;;; citeproc-itemdata.el --- represent and access bibliography items -*- lexical-binding: t; -*-
2 |
3 | ;; Copyright (C) 2017 András Simonyi
4 |
5 | ;; Author: András Simonyi
6 |
7 | ;; This program is free software; you can redistribute it and/or modify
8 | ;; it under the terms of the GNU General Public License as published by
9 | ;; the Free Software Foundation, either version 3 of the License, or
10 | ;; (at your option) any later version.
11 |
12 | ;; This program is distributed in the hope that it will be useful,
13 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | ;; GNU General Public License for more details.
16 |
17 | ;; You should have received a copy of the GNU General Public License
18 | ;; along with this program. If not, see .
19 |
20 | ;; This file is not part of GNU Emacs.
21 |
22 | ;;; Commentary:
23 |
24 | ;; Structure type and functions to handle data about bibliography items.
25 |
26 | ;;; Code:
27 |
28 | (require 'citeproc-rt)
29 | (require 'citeproc-context)
30 |
31 | (cl-defstruct (citeproc-itemdata (:constructor citeproc-itemdata-create))
32 | "Struct for storing bibliography item data.
33 | VARVALS is an alist containg variable-name symbols as keys and
34 | their values for the item as values,
35 | RAWCITE is the cached cite of the item in internal rich-text
36 | format,
37 | RC-UPTODATE is t iff the RAWCITE field is up-to-date,
38 | RAWBIBITEM is the cached bibliograhy item in internal rich-text
39 | format.
40 | SORT-KEY is the bibliography sort-key of the item,
41 | OCCURRED-BEFORE is used during bibliography generation to
42 | indicate whether the item was referred to earlier. If the first
43 | occurrence is in a note then the actual value is the
44 | note-number,
45 | DISAMB-POS contains the position on which cite disambiguation is
46 | based. Possible values are 'first, 'ibid and 'subsequent,
47 | SUBBIB-NOS is a list of numeric indexes of sub-bibliographies
48 | in which the item occurs,
49 | UNCITED is t iff the item has no associated citation."
50 | varvals rawcite rawbibitem rc-uptodate sort-key occurred-before
51 | disamb-pos subbib-nos uncited)
52 |
53 | (defun citeproc-itd-getvar (itd var)
54 | "Return itemdata ITD's value for VAR ."
55 | (alist-get var (citeproc-itemdata-varvals itd)))
56 |
57 | (defun citeproc-itd-setvar (itd var val)
58 | "Set itemdata ITD's value for VAR to VAL."
59 | (setf (alist-get var (citeproc-itemdata-varvals itd) nil t) val
60 | (citeproc-itemdata-rc-uptodate itd) nil))
61 |
62 | (defun citeproc-itd-rt-cite (itd style)
63 | "Return the rich-text cite of itemdata ITD using STYLE."
64 | (if (citeproc-itemdata-rc-uptodate itd)
65 | (citeproc-itemdata-rawcite itd)
66 | (let ((rc (citeproc-render-varlist-in-rt
67 | (cons (cons 'position (citeproc-itemdata-disamb-pos itd))
68 | (citeproc-itemdata-varvals itd))
69 | style
70 | 'cite 'display 'no-links t)))
71 | (setf (citeproc-itemdata-rawcite itd) rc
72 | (citeproc-itemdata-rc-uptodate itd) t)
73 | rc)))
74 |
75 | (defun citeproc-itd-plain-cite (itd style)
76 | "Return the plain text cite of itemdata ITD using STYLE."
77 | (citeproc-rt-to-plain (citeproc-itd-rt-cite itd style)))
78 |
79 | (defun citeproc-itd-namevars (itd style)
80 | "Rendered namevars in the cite of itemdata ITD using STYLE."
81 | (citeproc-rt-rendered-name-vars (citeproc-itd-rt-cite itd style)))
82 |
83 | (defun citeproc-itd-nameids (itd style)
84 | "Rendered name ids in the cite of itemdata ITD using STYLE."
85 | (citeproc-rt-rendered-name-ids (citeproc-itd-rt-cite itd style)))
86 |
87 | (defun citeproc-itd-update-disamb-pos (itd pos)
88 | "Update the highest position of ITD with position POS."
89 | (let ((old (citeproc-itemdata-disamb-pos itd)))
90 | (unless (eq old 'subsequent)
91 | (let ((new (pcase pos
92 | ('first 'first)
93 | ((or 'ibid 'ibid-with-locator) 'ibid)
94 | (_ 'subsequent))))
95 | (setf (citeproc-itemdata-disamb-pos itd)
96 | (cond ((memq old '(nil first)) new)
97 | ((eq new 'subsequent) 'subsequent)
98 | (t 'ibid)))))))
99 |
100 | (provide 'citeproc-itemdata)
101 |
102 | ;;; citeproc-itemdata.el ends here
103 |
--------------------------------------------------------------------------------
/citeproc-term.el:
--------------------------------------------------------------------------------
1 | ;;; citeproc-term.el --- functions for term localization -*- lexical-binding: t; -*-
2 |
3 | ;; Copyright (C) 2017 András Simonyi
4 |
5 | ;; Author: András Simonyi
6 |
7 | ;; This program is free software; you can redistribute it and/or modify
8 | ;; it under the terms of the GNU General Public License as published by
9 | ;; the Free Software Foundation, either version 3 of the License, or
10 | ;; (at your option) any later version.
11 |
12 | ;; This program is distributed in the hope that it will be useful,
13 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | ;; GNU General Public License for more details.
16 |
17 | ;; You should have received a copy of the GNU General Public License
18 | ;; along with this program. If not, see .
19 |
20 | ;; This file is not part of GNU Emacs.
21 |
22 | ;;; Commentary:
23 |
24 | ;; Functions for localizing the terms of a CSL style according to a locale.
25 |
26 | ;;; Code:
27 |
28 | (require 'dash)
29 | (require 'cl-lib)
30 | (require 'let-alist)
31 |
32 | (require 'citeproc-lib)
33 | (require 'citeproc-s)
34 |
35 | (cl-defstruct (citeproc-term (:constructor citeproc-term--create))
36 | "A struct representing a localized term."
37 | (name nil) (form nil) (number nil) (gender nil) (gender-form nil)
38 | (match nil) (text nil))
39 |
40 | (defun citeproc-term--compare (t1 t2)
41 | "Compare terms T1 and T2.
42 | The comparison is based on the term fields except the last one,
43 | and relies on the alphabetical ordering of fields' string
44 | content (see the function `citeproc-lib-s-content'). Return 1, -1
45 | or 0 iff T1 precedes, succeeds or is equal according to the
46 | ordering."
47 | (cond ((not t2) 1)
48 | ((not t1) -1)
49 | (t (let ((idx 1)
50 | (result 0))
51 | (while (and (= result 0) (< idx 7))
52 | (let ((s1 (citeproc-s-content (aref t1 idx)))
53 | (s2 (citeproc-s-content (aref t2 idx))))
54 | (cond ((string< s1 s2) (setq result 1))
55 | ((string> s1 s2) (setq result -1))))
56 | (cl-incf idx)) result))))
57 |
58 | (defun citeproc-term-list--sort (tl)
59 | "Sort termlist TL in place using `citeproc-term--compare'."
60 | (cl-sort tl (lambda (x y) (> (citeproc-term--compare x y) -1))))
61 |
62 | (defun citeproc-term-list-update (tl1 tl2 &optional sorted-input)
63 | "Return a term list which is TL1 updated with term list TL2.
64 | TL1 and TL2 are list of citeproc-term structs. The order of terms
65 | in the returned term list is undetermined. If the optional
66 | SORTED-INPUT is non-nil then the term lists are supposed to be
67 | already sorted according to `citeproc-term--compare', otherwise
68 | they are sorted in-place."
69 | (let (result)
70 | (unless sorted-input
71 | (setq tl1 (citeproc-term-list--sort tl1)
72 | tl2 (citeproc-term-list--sort tl2)))
73 | (while (or tl1 tl2)
74 | (let* ((t1 (car tl1))
75 | (t2 (car tl2))
76 | (cmp (citeproc-term--compare t1 t2)))
77 | (cond ((= cmp 1) (push t1 result) (pop tl1))
78 | ((= cmp -1) (push t2 result) (pop tl2))
79 | (t (push t2 result) (pop tl1) (pop tl2)))))
80 | result))
81 |
82 | (defun citeproc-term--from-xml-frag (frag)
83 | "Transform xml FRAG representing a term into a citeproc-term struct."
84 | (let-alist (car frag)
85 | (-let* ((.form (or .form "long"))
86 | (term (citeproc-term--create
87 | :name .name
88 | :form (citeproc-lib-intern .form)
89 | :gender (citeproc-lib-intern .gender)
90 | :match (citeproc-lib-intern .match)
91 | :gender-form (citeproc-lib-intern .gender-form))))
92 | (if (= (length frag) 2)
93 | (progn
94 | (setf (citeproc-term-text term) (cadr frag))
95 | (list term))
96 | (setf (citeproc-term-text term) (cl-caddr (cadr frag)))
97 | (setf (citeproc-term-number term) 'single)
98 | (let ((multi-term (copy-citeproc-term term)))
99 | (setf (citeproc-term-text multi-term) (cl-caddr (cl-caddr frag)))
100 | (setf (citeproc-term-number multi-term) 'multiple)
101 | (list term multi-term))))))
102 |
103 | (defun citeproc-term-text-from-terms (term terms)
104 | "Return the first text associated with TERM in TERMS.
105 | Return nil if TERM is not in TERMS."
106 | (-if-let (match (--first (string= term (citeproc-term-name it))
107 | terms))
108 | (citeproc-term-text match)
109 | nil))
110 |
111 | (provide 'citeproc-term)
112 |
113 | ;;; citeproc-term.el ends here
114 |
--------------------------------------------------------------------------------
/test/biblatex_csl/incollection.txt:
--------------------------------------------------------------------------------
1 | ---
2 | @comment{adapted from http://mirrors.ctan.org/macros/latex/contrib/biblatex/doc/examples/biblatex-examples.bib}
3 |
4 | @string{hup = {Harvard University Press}}
5 |
6 | @incollection{brandt,
7 | Annotation = {An incollection entry with a series and a number. Note the format of the printed name and compare the useprefix option in the options field as well as vangennep. Also note the indextitle, and indexsorttitle fields},
8 | Author = {von Brandt, Ahasver and Hoffmann, Erich},
9 | Booktitle = {Europa im Hoch- und Spätmittelalter},
10 | Date = 1987,
11 | Editor = {Seibt, Ferdinand},
12 | Indexsorttitle = {Nordischen Lander von der Mitte des 11. Jahrhunderts bis 1448},
13 | Indextitle = {Nordischen Länder von der Mitte des 11.~Jahrhunderts bis 1448, Die},
14 | Location = {Stuttgart},
15 | Number = 2,
16 | Options = {useprefix=false},
17 | Pages = {884-917},
18 | Publisher = {Klett-Cotta},
19 | Series = {Handbuch der europäischen Geschichte},
20 | Shorttitle = {Die nordischen Länder},
21 | Title = {Die nordischen Länder von der Mitte des 11. Jahrhunderts bis 1448},
22 | Langid = {german}}
23 |
24 | @incollection{hyman,
25 | Annotation = {An incollection entry with a series and number field},
26 | Author = {Hyman, Arthur},
27 | Booktitle = {Studies in {Aristotle}},
28 | Date = 1981,
29 | Editor = {O'Meara, Dominic J.},
30 | Indextitle = {Aristotle's Theory of the Intellect},
31 | Keywords = {secondary},
32 | Location = {Washington, D.C.},
33 | Number = 9,
34 | Pages = {161-191},
35 | Publisher = {The Catholic University of America Press},
36 | Series = {Studies in Philosophy and the History of Philosophy},
37 | Shorttitle = {Aristotle's Theory of the Intellect},
38 | Title = {Aristotle's Theory of the Intellect and its Interpretation by {Averroes}}}
39 |
40 | @incollection{pines,
41 | Annotation = {A typical incollection entry. Note the indextitle field},
42 | Author = {Pines, Shlomo},
43 | Booktitle = {Studies in Medieval {Jewish} History and Literature},
44 | Date = 1979,
45 | Editor = {Twersky, Isadore},
46 | Indextitle = {Limitations of Human Knowledge According to Al-Farabi, ibn Bajja, and Maimonides, The},
47 | Keywords = {secondary},
48 | Location = {Cambridge, Mass.},
49 | Pages = {82-109},
50 | Publisher = hup,
51 | Shorttitle = {Limitations of Human Knowledge},
52 | Title = {The Limitations of Human Knowledge According to {Al-Farabi}, {ibn Bajja}, and {Maimonides}}}
53 | ---
54 | - annote: An incollection entry with a series and a number. Note the
55 | format of the printed name and compare the useprefix option in the
56 | options field as well as vangennep. Also note the indextitle, and
57 | indexsorttitle fields
58 | author:
59 | - non-dropping-particle: von
60 | family: Brandt
61 | given: Ahasver
62 | - family: Hoffmann
63 | given: Erich
64 | blt-type: incollection
65 | collection-number: 2
66 | collection-title: Handbuch der europäischen Geschichte
67 | container-title: Europa im Hoch- und Spätmittelalter
68 | editor:
69 | - family: Seibt
70 | given: Ferdinand
71 | id: brandt
72 | issued: 1987
73 | language: de-DE
74 | page: 884-917
75 | publisher: Klett-Cotta
76 | publisher-place: Stuttgart
77 | title: Die nordischen Länder von der Mitte des 11. Jahrhunderts bis
78 | 1448
79 | title-short: Die nordischen Länder
80 | type: chapter
81 | - annote: An incollection entry with a series and number field
82 | author:
83 | - family: Hyman
84 | given: Arthur
85 | blt-type: incollection
86 | collection-number: 9
87 | collection-title: Studies in philosophy and the history of philosophy
88 | container-title: Studies in Aristotle
89 | editor:
90 | - family: O'Meara
91 | given: Dominic J.
92 | id: hyman
93 | issued: 1981
94 | keyword: secondary
95 | page: 161-191
96 | publisher: The Catholic University of America Press
97 | publisher-place: Washington, D.C.
98 | title: Aristotle's theory of the intellect and its interpretation by Averroes
99 | title-short: Aristotle's theory of the intellect
100 | type: chapter
101 | - annote: A typical incollection entry. Note the indextitle field
102 | author:
103 | - family: Pines
104 | given: Shlomo
105 | blt-type: incollection
106 | container-title: Studies in medieval Jewish history and literature
107 | editor:
108 | - family: Twersky
109 | given: Isadore
110 | id: pines
111 | issued: 1979
112 | keyword: secondary
113 | page: 82-109
114 | publisher: Harvard University Press
115 | publisher-place: Cambridge, Mass.
116 | title: The limitations of human knowledge according to Al-Farabi, ibn
117 | Bajja, and Maimonides
118 | title-short: Limitations of human knowledge
119 | type: chapter
120 |
--------------------------------------------------------------------------------
/test/citeproc-test-int-biblatex.el:
--------------------------------------------------------------------------------
1 | ;;; citeproc-test-int-biblatex.el --- biblatex tests -*- lexical-binding: t; -*-
2 |
3 | (require 'ert)
4 | (require 'yaml)
5 | (require 'string-inflection)
6 | (require 'ht)
7 | (require 'parsebib)
8 |
9 | (require 'citeproc-biblatex)
10 | (require 'citeproc-lib)
11 |
12 | (defun citeproc-test-blt--parse (file)
13 | "Parse a biblatex->CSL test file.
14 | Returns a (BLT . CSL) pair where BLT is the `parsebib'-parsed
15 | form of the biblatex part and CSL is the `yaml'-parsed form of
16 | the CSL part."
17 | (let (blt csl blt-start blt-end blt-string)
18 | (with-temp-buffer
19 | (insert-file-contents file)
20 | (goto-char 1)
21 | (re-search-forward "---" nil)
22 | (forward-line)
23 | (move-beginning-of-line nil)
24 | (setq blt-start (point))
25 | (re-search-forward "---" nil)
26 | (forward-line -1)
27 | (move-end-of-line nil)
28 | (setq blt-end (point)
29 | blt-string (buffer-substring-no-properties blt-start blt-end))
30 | (with-temp-buffer
31 | (insert blt-string)
32 | (goto-char 1)
33 | (setq blt (ht->alist
34 | (car (parsebib-parse-bib-buffer :expand-strings t :inheritance t)))))
35 | (forward-line 2)
36 | (move-beginning-of-line nil)
37 | (setq csl (yaml-parse-string
38 | (buffer-substring-no-properties (point) (point-max))
39 | :object-type 'alist
40 | :sequence-type 'list))
41 | (cons blt csl))))
42 |
43 | (defun citeproc-test-blt--sort-alist (alist)
44 | "Sort alist A according to key alphabetic order."
45 | (sort alist (lambda (x y) (string< (car x) (car y)))))
46 |
47 | (defun citeproc-test-blt--sort-nparts (csl-entry)
48 | "Sort the name-parts in a CSL entry."
49 | (dolist (kv csl-entry)
50 | (when (memq (car kv) citeproc--name-vars)
51 | (let* ((names (cdr kv))
52 | (sorted-names (mapcar #'citeproc-test-blt--sort-alist names)))
53 | (setf (cdr kv) sorted-names))))
54 | csl-entry)
55 |
56 | (defun citeproc-test-blt--simplify-dates (csl-entry)
57 | "Convert date entries to readable, simple fields"
58 | (dolist (kv csl-entry)
59 | (when (memq (car kv) citeproc--date-vars)
60 | (let* ((interval-date-parts (cdadr kv))
61 | (simplified-int-parts
62 | (mapconcat
63 | (lambda (int-part)
64 | (mapconcat
65 | (lambda (x)
66 | (let ((str (number-to-string x)))
67 | (if (= (length str) 1)
68 | (concat "0" str)
69 | str)))
70 | int-part "-"))
71 | interval-date-parts "/")) )
72 | (setf (cdr kv) simplified-int-parts))))
73 | csl-entry)
74 |
75 | (defun citeproc-test-blt--stringify (alist)
76 | "Convert all numerical values to strings."
77 | (dolist (kv alist)
78 | (when (numberp (cdr kv))
79 | (setf (cdr kv) (number-to-string (cdr kv)))))
80 | alist)
81 |
82 | (defun citeproc-test-blt--normalize-csl-entries (entries)
83 | "Normalize a list of csl entries.
84 | Performs the following steps:
85 | - sorts the entries according to the id field,
86 | - sorts the kv pairs according to key inside entries,
87 | - converts numerical values to strings,
88 | - sorts name-parts according to keys.
89 | All sorts are alphanumerically increasing."
90 | (let* ((stringified (mapcar #'citeproc-test-blt--stringify entries))
91 | (id-sorted (sort stringified
92 | (lambda (x y)
93 | (string< (alist-get 'id x)
94 | (alist-get 'id y)))))
95 | (internally-sorted (mapcar #'citeproc-test-blt--sort-alist id-sorted)))
96 | (mapcar #'citeproc-test-blt--sort-nparts internally-sorted)))
97 |
98 | (defun citeproc-test-blt--output (blt)
99 | "Generate normalized output from biblatex parse BLT."
100 | (let* ((processed (mapcar (lambda (x)
101 | (let ((csl-entry (citeproc-blt-entry-to-csl (cdr x) t)))
102 | (push (cons 'id (car x)) csl-entry)
103 | (citeproc-test-blt--simplify-dates
104 | csl-entry)))
105 | blt)))
106 | (citeproc-test-blt--normalize-csl-entries processed)))
107 |
108 | (defun citeproc-test-blt-create-from-file (file)
109 | "Create an ERT test from a blt-csl mapping file."
110 | (pcase-let* ((`(,blt . ,csl)
111 | (citeproc-test-blt--parse file))
112 | (expected (citeproc-test-blt--normalize-csl-entries csl))
113 | (file-name (f-filename file))
114 | (test-name (intern
115 | (concat "citeproc-int-blt-"
116 | (string-inflection-kebab-case-function
117 | (substring file-name 0 -4))))))
118 | (eval `(ert-deftest ,test-name ()
119 | (should (equal
120 | ',expected
121 | (citeproc-test-blt--output ',blt)))))))
122 |
123 | (defun citeproc-test-blt-create-from-dir (dir)
124 | "Create all blt-csl mapping tests from DIR."
125 | (dolist (test-file (f-glob (concat dir "/*.txt")))
126 | (citeproc-test-blt-create-from-file test-file)))
127 |
128 | (citeproc-test-blt-create-from-dir "./test/biblatex_csl")
129 |
130 | (provide 'citeproc-test-int-biblatex)
131 |
132 | ;;; citeproc-test-int-biblatex.el ends here
133 |
--------------------------------------------------------------------------------
/citeproc-choose.el:
--------------------------------------------------------------------------------
1 | ;; citeproc-choose.el --- conditionally rendered CSL elements -*- lexical-binding: t; -*-
2 |
3 | ;; Copyright (C) 2017 András Simonyi
4 |
5 | ;; Author: András Simonyi
6 |
7 | ;; This program is free software; you can redistribute it and/or modify
8 | ;; it under the terms of the GNU General Public License as published by
9 | ;; the Free Software Foundation, either version 3 of the License, or
10 | ;; (at your option) any later version.
11 |
12 | ;; This program is distributed in the hope that it will be useful,
13 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | ;; GNU General Public License for more details.
16 |
17 | ;; You should have received a copy of the GNU General Public License
18 | ;; along with this program. If not, see .
19 |
20 | ;; This file is not part of GNU Emacs.
21 |
22 | ;;; Commentary:
23 |
24 | ;; CSL supports conditional rendering via the cs:choose rendering element, which
25 | ;; can contain cs:if, cs:else-if and cs:else elements as children. This file
26 | ;; contains functions corresponding to all these elements with some auxiliary
27 | ;; functions.
28 |
29 | ;; In order to support conditional rendering by cs:choose, the functions
30 | ;; corresponding to cs:if, cs:else-if and cs:else (`citeproc--if',
31 | ;; `citeproc--else-if', `citeproc--else') return the generalized boolean value
32 | ;; of their condition in addition to their rendered content in the form of a
33 | ;; (BOOLEAN . CONTENT) pair.
34 |
35 | ;;; Code:
36 |
37 | (require 's)
38 |
39 | (require 'citeproc-lib)
40 | (require 'citeproc-context)
41 | (require 'citeproc-date)
42 |
43 | (defun citeproc-choose-eval-conditions (attrs context)
44 | "Eval (possibly complex) boolean conditions in ATTRS."
45 | (-let* ((conditions (citeproc-choose--elementary-conditions
46 | (--remove (eq (car it) 'match) attrs)))
47 | (match (or (alist-get 'match attrs) "all"))
48 | (values (--map (citeproc-choose--eval-elementary-condition (car it)
49 | (intern (cdr it))
50 | context)
51 | conditions)))
52 | (pcase match
53 | ("all" (--all? it values))
54 | ("any" (--any? it values))
55 | ("none" (--none? it values)))))
56 |
57 | (defun citeproc-choose--elementary-conditions (attrs)
58 | "Expand complex conditions in ATTRS into elementary ones.
59 | Return a list of elementary (CONDITION-TYPE . PARAM) pairs."
60 | (cl-mapcan (lambda (x)
61 | (--map (cons (car x) it)
62 | (s-split " " (cdr x))))
63 | attrs))
64 |
65 | (defun citeproc-choose--eval-elementary-condition (type param context)
66 | "Evaluate an elementary choose condition of TYPE with PARAM.
67 | TYPE is one of the symbols `variable', `type', `locator',
68 | `is-numeric', `is-uncertain-date', `position' and `disambiguate'.
69 | Return the result of evaluation, which is a generalized boolean."
70 | (pcase type
71 | ('variable (citeproc-var-value param context))
72 | ('type (string= param (citeproc-var-value 'type context)))
73 | ('locator (string= param (citeproc-var-value 'label context)))
74 | ('is-numeric (let ((val (citeproc-var-value param context)))
75 | (citeproc-lib-numeric-p val)))
76 | ;; We return t iff the first date is uncertain. A more complicated alternative
77 | ;; would be to test the second date of date ranges as well.
78 | ('is-uncertain-date (-when-let (dates (citeproc-var-value param context))
79 | (citeproc-date-circa (car dates))))
80 | ('position (and (eq (citeproc-context-mode context) 'cite)
81 | (or (and (eq param 'near-note) (citeproc-var-value 'near-note context))
82 | (let ((pos (citeproc-var-value 'position context)))
83 | (or (eq param pos)
84 | (and (eq param 'subsequent)
85 | (or (eq pos 'ibid) (eq pos 'ibid-with-locator)))
86 | (and (eq param 'ibid)
87 | (eq pos 'ibid-with-locator)))))))
88 | ('disambiguate (citeproc-var-value 'disambiguate context))))
89 |
90 | (defmacro citeproc--choose (_attrs _context &rest body)
91 | "Return the content of the first element in BODY with t boolean value.
92 | Return the empty (nil . `text-only') content if there is no such
93 | element."
94 | `(let ((first-true
95 | (--first (car it) (list ,@body))))
96 | (if first-true
97 | (cdr first-true)
98 | (cons nil (quote text-only)))))
99 |
100 | (defmacro citeproc--if (attrs context &rest body)
101 | "If conditions in ATTRS eval to t return t with rendered BODY.
102 | Return nil otherwise."
103 | `(if (citeproc-choose-eval-conditions ,attrs ,context)
104 | (cons t (citeproc-lib-add-splice-tag
105 | (citeproc-lib-splice-into (list ,@body) 'splice)
106 | 'splice))
107 | nil))
108 |
109 | (defalias 'citeproc--else-if 'citeproc--if)
110 |
111 | (defun citeproc--else (_attrs _context &rest body)
112 | "Always return t boolean plus rendered BODY"
113 | (let ((spliced-body (citeproc-lib-splice-into body 'splice)))
114 | (cons t (citeproc-lib-add-splice-tag spliced-body 'splice))))
115 |
116 | (provide 'citeproc-choose)
117 |
118 | ;;; citeproc-choose.el ends here
119 |
--------------------------------------------------------------------------------
/test/biblatex_csl/inbook.txt:
--------------------------------------------------------------------------------
1 | ---
2 | @string{dtv = {Deutscher Taschenbuch-Verlag}}
3 |
4 | @inbook{kant:kpv,
5 | Annotation = {An edition of Kant's Collected Works, volume five. This is an inbook entry which explicitly refers to the Critique of Practical Reason only, not to the entire fifth volume. Note the author and bookauthor fields in the database file. By default, the bookauthor is omitted if the values of the author and bookauthor fields are identical},
6 | Author = {Kant, Immanuel},
7 | Bookauthor = {Kant, Immanuel},
8 | Booktitle = {Kritik der praktischen Vernunft. Kritik der Urtheilskraft},
9 | Date = 1968,
10 | Location = {Berlin},
11 | Maintitle = {Kants Werke. Akademie Textausgabe},
12 | Pages = {1-163},
13 | Publisher = {Walter de Gruyter},
14 | Shorthand = {KpV},
15 | Shorttitle = {Kritik der praktischen Vernunft},
16 | Title = {Kritik der praktischen Vernunft},
17 | Volume = 5,
18 | Langid = {german}}
19 |
20 | @inbook{kant:ku,
21 | Annotation = {An edition of Kant's Collected Works, volume five. This is an inbook entry which explicitly refers to the Critique of Judgment only, not to the entire fifth volume},
22 | Author = {Kant, Immanuel},
23 | Bookauthor = {Kant, Immanuel},
24 | Booktitle = {Kritik der praktischen Vernunft. Kritik der Urtheilskraft},
25 | Date = 1968,
26 | Location = {Berlin},
27 | Maintitle = {Kants Werke. Akademie Textausgabe},
28 | Pages = {165-485},
29 | Publisher = {Walter de Gruyter},
30 | Shorthand = {KU},
31 | Title = {Kritik der Urtheilskraft},
32 | Langid = {german},
33 | Volume = 5}
34 |
35 | @inbook{nietzsche:historie,
36 | Annotation = {A single essay from the critical edition of Nietzsche's works. This inbook entry explicitly refers to an essay found in the first volume. Note the title, booktitle, and maintitle fields. Also note the sorttitle and sortyear fields. We want this entry to be listed after the entry referring to the entire first volume},
37 | Author = {Nietzsche, Friedrich},
38 | Bookauthor = {Nietzsche, Friedrich},
39 | Booktitle = {Die Geburt der Tragödie. Unzeitgemäße Betrachtungen I--IV. Nachgelassene Schriften 1870--1973},
40 | Date = 1988,
41 | Editor = {Colli, Giorgio and Montinari, Mazzino},
42 | Hyphenation = {german},
43 | Indexsorttitle = {Vom Nutzen und Nachtheil der Historie fur das Leben},
44 | Indextitle = {Vom Nutzen und Nachtheil der Historie für das Leben},
45 | Location = {München and Berlin and New York},
46 | Mainsubtitle = {Kritische Studienausgabe},
47 | Maintitle = {Sämtliche Werke},
48 | Pages = {243-334},
49 | Publisher = dtv # { and Walter de Gruyter},
50 | Shorttitle = {Vom Nutzen und Nachtheil der Historie},
51 | Sorttitle = {Werke-01-243},
52 | Sortyear = {1988-2},
53 | Subtitle = {Vom Nutzen und Nachtheil der Historie für das Leben},
54 | Title = {Unzeitgemässe Betrachtungen. Zweites Stück},
55 | Volume = 1,
56 | Langid = {german}}
57 | ---
58 | - annote: An edition of Kant's Collected Works, volume five. This is
59 | an inbook entry which explicitly refers to the Critique of
60 | Practical Reason only, not to the entire fifth volume. Note the
61 | author and bookauthor fields in the database file. By default, the
62 | bookauthor is omitted if the values of the author and bookauthor
63 | fields are identical
64 | author:
65 | - family: Kant
66 | given: Immanuel
67 | blt-type: inbook
68 | container-author:
69 | - family: Kant
70 | given: Immanuel
71 | container-title: Kants Werke. Akademie Textausgabe
72 | id: "kant:kpv"
73 | issued: 1968
74 | language: de-DE
75 | page: 1-163
76 | publisher: Walter de Gruyter
77 | publisher-place: Berlin
78 | title: Kritik der praktischen Vernunft
79 | title-short: Kritik der praktischen Vernunft
80 | type: chapter
81 | volume: 5
82 | volume-title: Kritik der praktischen Vernunft. Kritik der
83 | Urtheilskraft
84 | - annote: An edition of Kant's Collected Works, volume five. This is
85 | an inbook entry which explicitly refers to the Critique of
86 | Judgment only, not to the entire fifth volume
87 | author:
88 | - family: Kant
89 | given: Immanuel
90 | blt-type: inbook
91 | container-author:
92 | - family: Kant
93 | given: Immanuel
94 | container-title: Kants Werke. Akademie Textausgabe
95 | id: "kant:ku"
96 | issued: 1968
97 | language: de-DE
98 | page: 165-485
99 | publisher: Walter de Gruyter
100 | publisher-place: Berlin
101 | title: Kritik der Urtheilskraft
102 | type: chapter
103 | volume: 5
104 | volume-title: Kritik der praktischen Vernunft. Kritik der
105 | Urtheilskraft
106 | - annote: A single essay from the critical edition of Nietzsche's works.
107 | This inbook entry explicitly refers to an essay found in the first
108 | volume. Note the title, booktitle, and maintitle fields. Also note
109 | the sorttitle and sortyear fields. We want this entry to be listed
110 | after the entry referring to the entire first volume
111 | author:
112 | - family: Nietzsche
113 | given: Friedrich
114 | blt-type: inbook
115 | container-author:
116 | - family: Nietzsche
117 | given: Friedrich
118 | container-title: "Sämtliche Werke: Kritische Studienausgabe"
119 | editor:
120 | - family: Colli
121 | given: Giorgio
122 | - family: Montinari
123 | given: Mazzino
124 | id: "nietzsche:historie"
125 | issued: 1988
126 | language: de-DE
127 | page: 243-334
128 | publisher: Deutscher Taschenbuch-Verlag and Walter de Gruyter
129 | publisher-place: München and Berlin and New York
130 | title: "Unzeitgemässe Betrachtungen. Zweites Stück: Vom Nutzen und
131 | Nachtheil der Historie für das Leben"
132 | title-short: Vom Nutzen und Nachtheil der Historie
133 | type: chapter
134 | volume: 1
135 | volume-title: Die Geburt der Tragödie. Unzeitgemäße Betrachtungen
136 | I–IV. Nachgelassene Schriften 1870–1973
137 |
--------------------------------------------------------------------------------
/test/biblatex_csl/report.txt:
--------------------------------------------------------------------------------
1 | ---
2 | @report{chiu,
3 | Annotation = {This is a report entry for a research report. Note the format of the type field in the database file which uses a localization key. The number of the report is given in the number field. Also note the sorttitle and indextitle fields},
4 | Author = {Chiu, Willy W. and Chow, We Min},
5 | Date = 1978,
6 | Indextitle = {Hybrid Hierarchical Model, A},
7 | Institution = {IBM},
8 | Number = {RC-6947},
9 | Sorttitle = {Hybrid Hierarchical Model of a Multiple Virtual Storage (MVS) Operating System},
10 | Title = {A Hybrid Hierarchical Model of a {Multiple Virtual Storage} ({MVS}) Operating System},
11 | Type = {resreport}}
12 |
13 | @report{padhye,
14 | Annotation = {This is a report entry for a technical report. Note the format of the type field in the database file which uses a localization key. The number of the report is given in the number field. Also note the sorttitle and indextitle fields},
15 | Author = {Padhye, Jitendra and Firoiu, Victor and Towsley, Don},
16 | Date = 1999,
17 | File = {ftp://gaia.cs.umass.edu/pub/Padhey99-markov.ps},
18 | Indextitle = {Stochastic Model of TCP Reno Congestion Avoidance and Control, A},
19 | Institution = {University of Massachusetts},
20 | Location = {Amherst, Mass.},
21 | Number = {99-02},
22 | Sorttitle = {A Stochastic Model of TCP Reno Congestion Avoidance and Control},
23 | Title = {A Stochastic Model of {TCP Reno} Congestion Avoidance and Control},
24 | Type = {techreport},
25 | Abstract = {The steady state performance of a bulk transfer TCP flow
26 | (i.e., a flow with a large amount of data to send, such as FTP
27 | transfers) may be characterized by three quantities. The first
28 | is the send rate, which is the amount of data sent by the
29 | sender in unit time. The second is the throughput, which is
30 | the amount of data received by the receiver in unit time. Note
31 | that the throughput will always be less than or equal to the
32 | send rate due to losses. Finally, the number of non-duplicate
33 | packets received by the receiver in unit time gives us the
34 | goodput of the connection. The goodput is always less than or
35 | equal to the throughput, since the receiver may receive two
36 | copies of the same packet due to retransmissions by the
37 | sender. In a previous paper, we presented a simple model for
38 | predicting the steady state send rate of a bulk transfer TCP
39 | flow as a function of loss rate and round trip time. In this
40 | paper, we extend that work in two ways. First, we analyze the
41 | performance of bulk transfer TCP flows using more precise,
42 | stochastic analysis. Second, we build upon the previous
43 | analysis to provide both an approximate formula as well as a
44 | more accurate stochastic model for the steady state throughput
45 | of a bulk transfer TCP flow.}}
46 | ---
47 | - annote: This is a report entry for a research report. Note the format
48 | of the type field in the database file which uses a localization
49 | key. The number of the report is given in the number field. Also
50 | note the sorttitle and indextitle fields
51 | author:
52 | - family: Chiu
53 | given: Willy W.
54 | - family: Chow
55 | given: We Min
56 | blt-type: report
57 | genre: research report
58 | id: chiu
59 | issued: 1978
60 | number: RC-6947
61 | publisher: IBM
62 | title: A hybrid hierarchical model of a Multiple Virtual Storage (MVS) operating system
63 | type: report
64 | - abstract: The steady state performance of a bulk transfer TCP flow
65 | (i.e., a flow with a large amount of data to send, such as FTP
66 | transfers) may be characterized by three quantities. The first is
67 | the send rate, which is the amount of data sent by the sender in
68 | unit time. The second is the throughput, which is the amount of data
69 | received by the receiver in unit time. Note that the throughput will
70 | always be less than or equal to the send rate due to losses.
71 | Finally, the number of non-duplicate packets received by the
72 | receiver in unit time gives us the goodput of the connection. The
73 | goodput is always less than or equal to the throughput, since the
74 | receiver may receive two copies of the same packet due to
75 | retransmissions by the sender. In a previous paper, we presented a
76 | simple model for predicting the steady state send rate of a bulk
77 | transfer TCP flow as a function of loss rate and round trip time. In
78 | this paper, we extend that work in two ways. First, we analyze the
79 | performance of bulk transfer TCP flows using more precise,
80 | stochastic analysis. Second, we build upon the previous analysis to
81 | provide both an approximate formula as well as a more accurate
82 | stochastic model for the steady state throughput of a bulk transfer
83 | TCP flow.
84 | annote: This is a report entry for a technical report. Note the format
85 | of the type field in the database file which uses a localization
86 | key. The number of the report is given in the number field. Also
87 | note the sorttitle and indextitle fields
88 | author:
89 | - family: Padhye
90 | given: Jitendra
91 | - family: Firoiu
92 | given: Victor
93 | - family: Towsley
94 | given: Don
95 | blt-type: report
96 | genre: technical report
97 | id: padhye
98 | issued: 1999
99 | number: 99-02
100 | publisher: University of Massachusetts
101 | publisher-place: Amherst, Mass.
102 | title: A stochastic model of TCP Reno congestion avoidance and control
103 | type: report
104 |
--------------------------------------------------------------------------------
/citeproc-prange.el:
--------------------------------------------------------------------------------
1 | ;;; citeproc-prange.el --- page-range rendering -*- lexical-binding: t; -*-
2 |
3 | ;; Copyright (C) 2017 András Simonyi
4 |
5 | ;; Author: András Simonyi
6 |
7 | ;; This program is free software; you can redistribute it and/or modify
8 | ;; it under the terms of the GNU General Public License as published by
9 | ;; the Free Software Foundation, either version 3 of the License, or
10 | ;; (at your option) any later version.
11 |
12 | ;; This program is distributed in the hope that it will be useful,
13 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | ;; GNU General Public License for more details.
16 |
17 | ;; You should have received a copy of the GNU General Public License
18 | ;; along with this program. If not, see .
19 |
20 | ;; This file is not part of GNU Emacs.
21 |
22 | ;;; Commentary:
23 |
24 | ;; Functions to render CSL page-ranges.
25 |
26 | ;;; Code:
27 |
28 | (require 'citeproc-s)
29 |
30 | (defun citeproc-prange--end-significant (start end len)
31 | "Return the significant digits of the end in page range START END.
32 | START and END are strings of equal length containing integers. If
33 | the significant part of END is shorter than LEN then add
34 | insignificant digits from END until the string is LEN long or
35 | there are no more digits left."
36 | (let ((first (min (max 1 (1+ (- (length end) len)))
37 | (abs (compare-strings start nil nil end nil nil)))))
38 | (substring end (1- first))))
39 |
40 | (defun citeproc-prange--end-complete (start end len)
41 | "Complete the closing form of a START END pagerange to LEN."
42 | (citeproc-prange--end-significant start (citeproc-s-fill-copy end start) len))
43 |
44 | (defun citeproc-prange--end-expanded (_start end end-pref)
45 | "Render the end of range _START END in `expanded' format.
46 | END-PREF is an optional non-numeric prefix preceding END. All
47 | arguments are strings, END has the same length as START."
48 | (concat end-pref end))
49 |
50 | (defun citeproc-prange--end-minimal (start end _end-pref)
51 | "Render the end of range START END in `minimal' format.
52 | END-PREFIX is an optional non-numeric prefix preceding END. All
53 | arguments are strings, END has the same length as START."
54 | (citeproc-prange--end-significant start end 1))
55 |
56 | (defun citeproc-prange--end-minimal-two (start end _end-pref)
57 | "Render the end of range START END in `minimal-two' format.
58 | END-PREFIX is an optional non-numeric prefix preceding END. All
59 | arguments are strings, END has the same length as START."
60 | (citeproc-prange--end-significant start end 2))
61 |
62 | (defun citeproc-prange--end-chicago (start end _end-pref &optional 15th-ed)
63 | "Render the end of range START END in `chicago' format.
64 | END-PREFIX is an optional non-numeric prefix preceding END. All
65 | arguments are strings, END has the same length as START. If
66 | optional 15TH-ED is non-nil then use the special 4digit rule of
67 | the 15th edition."
68 | (let ((len (length start)))
69 | (cond ((or (< len 3) (string= (substring start -2) "00"))
70 | end)
71 | ((string= (substring start -2 -1) "0")
72 | (citeproc-prange--end-significant start end 1))
73 | ((and 15th-ed (= 4 (length start)))
74 | (let ((min-two (citeproc-prange--end-significant start end 2)))
75 | (if (> (length min-two) 2) end min-two)))
76 | (t (citeproc-prange--end-significant start end 2)))))
77 |
78 | (defconst citeproc-prange-formatters-alist
79 | `((chicago . ,(lambda (start end end-pref)
80 | (citeproc-prange--end-chicago start end end-pref t)))
81 | (chicago-15 . ,(lambda (start end end-pref)
82 | (citeproc-prange--end-chicago start end end-pref t)))
83 | (chicago-16 . citeproc-prange--end-chicago)
84 | (minimal . citeproc-prange--end-minimal)
85 | (minimal-two . citeproc-prange--end-minimal-two)
86 | (expanded . citeproc-prange--end-expanded))
87 | "Alist mapping page range formats to formatter functions.")
88 |
89 | (defun citeproc-prange-render (p format sep)
90 | "Render page range P in FORMAT with separator SEP."
91 | (with-temp-buffer
92 | (insert p)
93 | (goto-char 0)
94 | (while (search-forward-regexp
95 | "\\([[:digit:]]*[[:alpha:]]\\)?\\([[:digit:]]+\\)\\( ?\\)\\([-–—]+\\)\\( ?\\)\\([[:digit:]]*[[:alpha:]]\\)?\\([[:digit:]]+\\)"
96 | nil t)
97 | (let* ((start-pref (match-string 1))
98 | (start-num (match-string 2))
99 | (orig-dash (match-string 4))
100 | (orig-sep (concat (match-string 3) orig-dash (match-string 5)))
101 | (end-pref (match-string 6))
102 | (end-num (match-string 7))
103 | (end (concat end-pref end-num))
104 | (old-sep-w-end (concat orig-sep end))
105 | ;; Note: To conform with the official CSL tests we don't replace the separating
106 | ;; dash with SEP if collapse cannot be applied because of incompatible prefixes
107 | ;; but we still remove spaces surrounding the dash. It would make far more
108 | ;; sense to replace the dash as well.
109 | (new-sep-w-end (cond ((not (string= start-pref end-pref))
110 | (concat orig-dash end))
111 | ;; Deal with degenerate single page "ranges"
112 | ((string= start-num end-num)
113 | "")
114 | ((or (not format) (> (length end-num) (length start-num)))
115 | (concat sep end))
116 | (t (concat
117 | sep
118 | (funcall (alist-get format
119 | citeproc-prange-formatters-alist)
120 | start-num
121 | (citeproc-s-fill-copy end-num start-num)
122 | end-pref))))))
123 | (unless (string-equal new-sep-w-end old-sep-w-end)
124 | (delete-char (- (length old-sep-w-end)))
125 | (insert new-sep-w-end))))
126 | (buffer-string)))
127 |
128 | (provide 'citeproc-prange)
129 |
130 | ;;; citeproc-prange.el ends here
131 |
--------------------------------------------------------------------------------
/citeproc-lib.el:
--------------------------------------------------------------------------------
1 | ;;; citeproc-lib.el --- misc functions and variables for citeproc-el -*- lexical-binding: t; -*-
2 |
3 | ;; Copyright (C) 2017-2021 András Simonyi
4 |
5 | ;; Author: András Simonyi
6 |
7 | ;; This program is free software; you can redistribute it and/or modify
8 | ;; it under the terms of the GNU General Public License as published by
9 | ;; the Free Software Foundation, either version 3 of the License, or
10 | ;; (at your option) any later version.
11 |
12 | ;; This program is distributed in the hope that it will be useful,
13 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | ;; GNU General Public License for more details.
16 |
17 | ;; You should have received a copy of the GNU General Public License
18 | ;; along with this program. If not, see .
19 |
20 | ;; This file is not part of GNU Emacs.
21 |
22 | ;;; Commentary:
23 |
24 | ;; General utility functions used in citeproc-el.
25 |
26 | ;;; Code:
27 |
28 | (require 'dash)
29 | (require 's)
30 |
31 | (defconst citeproc--number-vars
32 | '(chapter-number citation-number collection-number edition first-reference-note-number
33 | issue number number-of-pages number-of-volumes page page-first
34 | part-number printing-number section supplement-number version volume)
35 | "CSL number variables."
36 | ;; Note: `locator', which is also on the official list, is omitted because
37 | ;; it's treated specially in the code.
38 | )
39 |
40 | (defconst citeproc--date-vars
41 | '(accessed available-date event-date issued original-date submitted locator-date)
42 | "CSL date variables.")
43 |
44 | (defconst citeproc--name-vars
45 | '(author chair collection-editor compiler composer container-author contributor
46 | curator director editor editorial-director editor-translator executive-producer
47 | guest host illustrator interviewer narrator organizer original-author
48 | performer producer recipient reviewed-author script-writer series-creator
49 | translator)
50 | "CSL name variables.")
51 |
52 | (defconst citeproc--linked-vars
53 | '(DOI PMCID PMID URL)
54 | "Variables whose rendered content should be linked.
55 | The ordering is according to priority ")
56 |
57 | (defconst citeproc--link-prefix-alist
58 | '((DOI . "https://doi.org/")
59 | (PMID . "https://www.ncbi.nlm.nih.gov/pubmed/")
60 | (PMCID . "https://www.ncbi.nlm.nih.gov/pmc/articles/"))
61 | "Alist mapping variable names to uri prefixes.")
62 |
63 | (defun citeproc-lib-parse-xml-file (file)
64 | "Return the parsed xml representation of FILE."
65 | (with-temp-buffer
66 | (insert-file-contents file)
67 | (libxml-parse-xml-region (point-min) (point-max))))
68 |
69 | (defun citeproc-lib-remove-xml-comments (tree)
70 | "Remove comments from xml TREE."
71 | (let ((head (car tree))
72 | (attrs (cadr tree))
73 | (body (cddr tree))
74 | result)
75 | (while body
76 | (pcase (car body)
77 | ((pred atom) (push (pop body) result))
78 | (`(comment . ,_) (pop body))
79 | (_ (push (citeproc-lib-remove-xml-comments (pop body)) result))))
80 | (let ((full-result (cons head (cons attrs (nreverse result)))))
81 | ;; Handle the problem of the top element added by the libxml parser when
82 | ;; there is a comment after the xml declaration.
83 | (if (eq (car full-result) 'top)
84 | (caddr full-result)
85 | full-result))))
86 |
87 | (defun citeproc-lib-parse-html-frag (s)
88 | "Return the parsed representation of html in string S."
89 | (with-temp-buffer
90 | (insert s)
91 | (libxml-parse-html-region (point-min) (point-max))))
92 |
93 | (defun citeproc-lib-intern (s)
94 | "Intern S if it is a string, return nil if it is nil."
95 | (cond ((not s) nil)
96 | ((stringp s) (intern s))
97 | (t (error "Function citeproc-lib-intern was called with an argument that is neither string nor nil"))))
98 |
99 | (defun citeproc-lib-named-parts-to-alist (e)
100 | "Collect the attrs of parsed xml element E's enclosed elements.
101 | The attributes are collected into an alist consisting
102 | of (PARTNAME . ATTRS) pairs, where PARTNAME is the value of the
103 | enclosed element's `name' attr"
104 | (--map (cons (intern (alist-get 'name it))
105 | (assq-delete-all 'name it))
106 | (mapcar #'cadr (-remove #'stringp (cddr e)))))
107 |
108 | (defun citeproc-lib-lex-compare (l1 l2 cmp-fun sort-orders)
109 | "Whether list L1 lexicographically precedes list L2.
110 | CMP-FUN is a three-valued (1, 0, -1) comparator function,
111 | SORT-ORDERS is a list of sort orders (see the bib- and
112 | cite-sort-orders slots of `citeproc-style' for details). Return t
113 | iff L1 is strictly ordered before L2, nil otherwise."
114 | (unless sort-orders
115 | (setq sort-orders (make-list (length l1) t)))
116 | (let (result)
117 | (while (and l1 (not result))
118 | (let ((comp
119 | (funcall cmp-fun (pop l1) (pop l2) (not (pop sort-orders)))))
120 | (unless (= comp 0)
121 | (setq result comp))))
122 | (equal result 1)))
123 |
124 | (defun citeproc-lib-splice-into (list tag)
125 | "Splice elements with car TAG into LIST."
126 | (let (result)
127 | (dolist (elt list)
128 | (if (and (consp elt) (eq tag (car elt)))
129 | (dolist (e (cdr elt))
130 | (push e result))
131 | (push elt result)))
132 | (nreverse result)))
133 |
134 | (defun citeproc-lib-add-splice-tag (list tag)
135 | "Add TAG as car if LIST is not a singleton.
136 | Return the first element if LIST is singleton."
137 | (if (cdr list) (cons tag list) (car list)))
138 |
139 | (defun citeproc-lib-numeric-p (val)
140 | "Return whether VAL is numeric content.
141 | VAL has numeric content if it is a number or a string containing
142 | numeric content."
143 | (or (numberp val)
144 | (and (stringp val)
145 | (s-matches-p "\\`[[:alpha:]]?[[:digit:]]+[[:alpha:]]*\\(\\( *\\([,&-]\\|--\\) *\\)?[[:alpha:]]?[[:digit:]]+[[:alpha:]]*\\)?\\'"
146 | val))))
147 |
148 | (provide 'citeproc-lib)
149 |
150 | ;;; citeproc-lib.el ends here
151 |
--------------------------------------------------------------------------------
/test/biblatex_csl/patent.txt:
--------------------------------------------------------------------------------
1 | ---
2 | @patent{almendro,
3 | Annotation = {This is a patent entry with a location field. The number is given in the number field. Note the format of the location field in the database file. Compare laufenberg, sorace, and kowalik},
4 | Author = {Almendro, José L. and Martín, Jacinto and Sánchez, Alberto and Nozal, Fernando},
5 | Date = 1998,
6 | Location = {France; United Kingdom; Germany},
7 | Number = {EU-29702195U},
8 | Title = {Elektromagnetisches Signalhorn},
9 | Langid = {german}}
10 |
11 | @patent{kowalik,
12 | Annotation = {This is a patent entry for a French patent request with a full date. The number is given in the number field. Note the format of the type and date fields in the database file. Compare almendro, laufenberg, and sorace},
13 | Author = {Kowalik, F. and Isard, M.},
14 | Date = {1995-01-11},
15 | Indextitle = {Estimateur d'un défaut de fonctionnement},
16 | Number = 9500261,
17 | Title = {Estimateur d'un défaut de fonctionnement d'un modulateur en quadrature et étage de modulation l'utilisant},
18 | Type = {patreqfr},
19 | Langid = {french}}
20 |
21 | @patent{laufenberg,
22 | Annotation = {This is a patent entry with a holder field. Note the format of the type and location fields in the database file. Compare almendro, sorace, and kowalik},
23 | Author = {Laufenberg, Xaver and Eynius, Dominique and Suelzle, Helmut and Usbeck, Stephan and Spaeth, Matthias and Neuser-Hoffmann, Miriam and Myrzik, Christian and Schmid, Manfred and Nietfeld, Franz and Thiel, Alexander and Braun, Harald and Ebner, Norbert},
24 | Date = {2006-09-13},
25 | File = {http://v3.espacenet.com/textdoc?IDX=EP1700367},
26 | Holder = {{Robert Bosch GmbH} and {Daimler Chrysler AG} and {Bayerische Motoren Werke AG}},
27 | Number = 1700367,
28 | Title = {Elektrische Einrichtung und Betriebsverfahren},
29 | Type = {patenteu},
30 | Abstract = {The invention relates to an electric device comprising a
31 | generator, in particular for use in the vehicle electric
32 | system of a motor vehicle and a controller for controlling the
33 | generator voltage. The device is equipped with a control zone,
34 | in which the voltage is controlled and zones, in which the
35 | torque is controlled. The invention also relates to methods
36 | for operating a device of this type.},
37 | Langid = {german}}
38 |
39 | @patent{sorace,
40 | Annotation = {This is a patent entry with a holder field. Note the format of the type and date fields in the database file. Compare almendro, laufenberg, and kowalik},
41 | Author = {Sorace, Ronald E. and Reinhardt, Victor S. and Vaughn, Steven A.},
42 | Date = {1997-09-16},
43 | Date-Modified = {2013-10-16 13:44:15 +0000},
44 | Holder = {{Hughes Aircraft Company}},
45 | Hyphenation = {american},
46 | Number = 5668842,
47 | Title = {High-Speed Digital-to-{RF} Converter},
48 | Type = {patentus}}
49 |
50 | ---
51 | - annote: This is a patent entry with a location field. The number is
52 | given in the number field. Note the format of the location field in
53 | the database file. Compare laufenberg, sorace, and kowalik
54 | author:
55 | - family: Almendro
56 | given: José L.
57 | - family: Martín
58 | given: Jacinto
59 | - family: Sánchez
60 | given: Alberto
61 | - family: Nozal
62 | given: Fernando
63 | blt-type: patent
64 | id: almendro
65 | issued: 1998
66 | language: de-DE
67 | jurisdiction: France; United Kingdom; Germany
68 | number: EU-29702195U
69 | title: Elektromagnetisches Signalhorn
70 | type: patent
71 | - annote: This is a patent entry for a French patent request with a full
72 | date. The number is given in the number field. Note the format of
73 | the type and date fields in the database file. Compare almendro,
74 | laufenberg, and sorace
75 | author:
76 | - family: Kowalik
77 | given: F.
78 | - family: Isard
79 | given: M.
80 | blt-type: patent
81 | genre: French patent request
82 | id: kowalik
83 | issued: 1995-01-11
84 | language: fr-FR
85 | number: 9500261
86 | title: Estimateur d'un défaut de fonctionnement d'un modulateur en
87 | quadrature et étage de modulation l'utilisant
88 | type: patent
89 | - abstract: The invention relates to an electric device comprising a
90 | generator, in particular for use in the vehicle electric system of a
91 | motor vehicle and a controller for controlling the generator
92 | voltage. The device is equipped with a control zone, in which the
93 | voltage is controlled and zones, in which the torque is controlled.
94 | The invention also relates to methods for operating a device of this
95 | type.
96 | annote: This is a patent entry with a holder field. Note the format of
97 | the type and location fields in the database file. Compare almendro,
98 | sorace, and kowalik
99 | author:
100 | - family: Laufenberg
101 | given: Xaver
102 | - family: Eynius
103 | given: Dominique
104 | - family: Suelzle
105 | given: Helmut
106 | - family: Usbeck
107 | given: Stephan
108 | - family: Spaeth
109 | given: Matthias
110 | - family: Neuser-Hoffmann
111 | given: Miriam
112 | - family: Myrzik
113 | given: Christian
114 | - family: Schmid
115 | given: Manfred
116 | - family: Nietfeld
117 | given: Franz
118 | - family: Thiel
119 | given: Alexander
120 | - family: Braun
121 | given: Harald
122 | - family: Ebner
123 | given: Norbert
124 | blt-type: patent
125 | genre: European patent
126 | id: laufenberg
127 | issued: 2006-09-13
128 | language: de-DE
129 | number: 1700367
130 | title: Elektrische Einrichtung und Betriebsverfahren
131 | type: patent
132 | - annote: This is a patent entry with a holder field. Note the format of
133 | the type and date fields in the database file. Compare almendro,
134 | laufenberg, and kowalik
135 | author:
136 | - family: Sorace
137 | given: Ronald E.
138 | - family: Reinhardt
139 | given: Victor S.
140 | - family: Vaughn
141 | given: Steven A.
142 | blt-type: patent
143 | genre: U.S. patent
144 | id: sorace
145 | issued: 1997-09-16
146 | number: 5668842
147 | title: High-speed digital-to-RF converter
148 | type: patent
149 |
150 |
--------------------------------------------------------------------------------
/citeproc-number.el:
--------------------------------------------------------------------------------
1 | ;;; citeproc-number.el --- render CSL number elements -*- lexical-binding: t; -*-
2 |
3 | ;; Copyright "(C) 2017 András Simonyi
4 |
5 | ;; Author: András Simonyi
6 |
7 | ;; This program is free software; you can redistribute it and/or modify
8 | ;; it under the terms of the GNU General Public License as published by
9 | ;; the Free Software Foundation, either version 3 of the License, or
10 | ;; (at your option) any later version.
11 |
12 | ;; This program is distributed in the hope that it will be useful,
13 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | ;; GNU General Public License for more details.
16 |
17 | ;; You should have received a copy of the GNU General Public License
18 | ;; along with this program. If not, see .
19 |
20 | ;; This file is not part of GNU Emacs.
21 |
22 | ;;; Commentary:
23 |
24 | ;; Functions to render CSL number elements.
25 |
26 | ;;; Code:
27 |
28 | (require 'subr-x)
29 | (require 'rst)
30 | (require 's)
31 |
32 | (require 'citeproc-context)
33 | (require 'citeproc-lib)
34 | (require 'citeproc-s)
35 | (require 'citeproc-rt)
36 |
37 | (defun citeproc-number-extract (val)
38 | "Return the parse of string VAL holding numeric content."
39 | (cdr (s-match
40 | "\\`\\([[:alpha:]]?[[:digit:]]+[[:alpha:]]*\\)\\(?:\\(?: *\\([,&-–—―]\\|--\\) *\\)\\([[:alpha:]]?[[:digit:]]+[[:alpha:]]*\\)\\)?\\'"
41 | val)))
42 |
43 | (defun citeproc--number (attrs context &rest _body)
44 | "Render a cs:number element with the given ATTRS in CONTEXT."
45 | (-let* (((&alist 'variable var
46 | 'form form)
47 | attrs)
48 | (variable (intern var))
49 | (value (citeproc-var-value variable context))
50 | (form (citeproc-lib-intern form)))
51 | (if (not value)
52 | (cons nil 'empty-var)
53 | (let ((result-attrs
54 | (cons `(rendered-var . ,variable) attrs))
55 | (result-cont
56 | (citeproc-number-var-value value variable form context)))
57 | (cons (citeproc-rt-format-single result-attrs result-cont context)
58 | 'present-var)))))
59 |
60 | (defconst citeproc--format-numsep-alist
61 | '(("&" . " & ")
62 | ("," . ", ")
63 | ("-" . "-")
64 | ("--" . "-")
65 | ("—" . "-")
66 | ("―" . "-"))
67 | "Alist specifying the proper formatting of number-pair separators.")
68 |
69 | (defun citeproc-number-var-value (value variable form context)
70 | "Return the numeric VALUE of VARIABLE formatted in FORM.
71 | VARIABLE is a symbol."
72 | (cond ((not value) nil)
73 | ((numberp value) (number-to-string value))
74 | (t (--if-let (citeproc-number-extract value)
75 | (let ((formatted-first
76 | (citeproc-number--format (car it) form variable context)))
77 | (if (> (length it) 1)
78 | (concat
79 | formatted-first
80 | (assoc-default (cadr it) citeproc--format-numsep-alist)
81 | (citeproc-number--format (cl-caddr it) form variable context))
82 | formatted-first))
83 | value))))
84 |
85 | (defun citeproc-number--format (s form term context)
86 | "Render the number in string S for TERM in format FORM."
87 | (if (s-matches-p "[[:alpha:]]" s) s
88 | (pcase form
89 | ('roman (downcase (rst-arabic-to-roman (string-to-number s))))
90 | ('ordinal (citeproc-number--format-as-ordinal s term context))
91 | ('long-ordinal (citeproc-number--format-as-long-ordinal s term context))
92 | (_ s))))
93 |
94 | (defun citeproc-number--format-as-ordinal (s term context)
95 | "Format numeric string S as ordinal agreeing with TERM."
96 | (let* ((terms (citeproc-context-terms context))
97 | (padded (if (= 1 (length s))
98 | (concat "0" s)
99 | s))
100 | (gender (citeproc-term-get-gender term context))
101 | (matches
102 | (--filter (and (string= (s-left 8 (citeproc-term-name it)) "ordinal-")
103 | (citeproc-number--ordinal-matches-p padded gender it))
104 | terms))
105 | (suffix
106 | (citeproc-term-text
107 | (if (not matches)
108 | (-when-let (ordinal-matches
109 | (--filter (string= (citeproc-term-name it) "ordinal")
110 | terms))
111 | (-if-let (match (--first (eq (citeproc-term-gender-form it) gender)
112 | ordinal-matches))
113 | match
114 | (car ordinal-matches)))
115 | (let ((first-term (car matches)))
116 | (-if-let (second-term (cadr matches))
117 | (if (= (elt (citeproc-term-name first-term) 8) ?0)
118 | second-term
119 | first-term)
120 | first-term))))))
121 | (concat s suffix)))
122 |
123 | (defconst citeproc-number--ordinal-match-alist
124 | '((last-two-digits . 2)
125 | (last-digit . 1)
126 | (whole-number . nil))
127 | "Alist mapping ordinal match attributes to the required match lengths.")
128 |
129 | (defun citeproc-number--ordinal-matches-p (s gender ord-term)
130 | "Whether S term with GENDER matches ordinal-term ORD-TERM."
131 | (and (eq gender (citeproc-term-gender-form ord-term))
132 | (let ((match (citeproc-term-match ord-term))
133 | (term-num (s-right 2 (citeproc-term-name ord-term))))
134 | (unless match
135 | (setq match
136 | (if (= (elt (citeproc-term-name ord-term) 8) ?0)
137 | 'last-digit
138 | 'last-two-digits)))
139 | (let ((l (assoc-default match citeproc-number--ordinal-match-alist)))
140 | (string= (citeproc-s-tail s l)
141 | (citeproc-s-tail term-num l))))))
142 |
143 | (defun citeproc-number--format-as-long-ordinal (s term context)
144 | "Format numeric string S as a long ordinal agreeing with TERM."
145 | (let ((num-val (string-to-number s)))
146 | (if (> num-val 10)
147 | (citeproc-number--format-as-ordinal s term context)
148 | (when (= 1 (length s)) (setq s (concat "0" s)))
149 | (let* ((name (concat "long-ordinal-" s))
150 | (gender (citeproc-term-get-gender term context))
151 | (match (--first (and (string= (citeproc-term-name it) name)
152 | (eq (citeproc-term-gender-form it) gender))
153 | (citeproc-context-terms context))))
154 | (if match
155 | (citeproc-term-text match)
156 | (citeproc-term-get-text name context))))))
157 |
158 | (provide 'citeproc-number)
159 |
160 | ;;; citeproc-number ends here
161 |
--------------------------------------------------------------------------------
/citeproc-generic-elements.el:
--------------------------------------------------------------------------------
1 | ;;; citeproc-generic-elements.el --- render generic CSL elements -*- lexical-binding: t; -*-
2 |
3 | ;; Copyright (C) 2017-2021 András Simonyi
4 |
5 | ;; Author: András Simonyi
6 |
7 | ;; This program is free software; you can redistribute it and/or modify
8 | ;; it under the terms of the GNU General Public License as published by
9 | ;; the Free Software Foundation, either version 3 of the License, or
10 | ;; (at your option) any later version.
11 |
12 | ;; This program is distributed in the hope that it will be useful,
13 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | ;; GNU General Public License for more details.
16 |
17 | ;; You should have received a copy of the GNU General Public License
18 | ;; along with this program. If not, see .
19 |
20 | ;; This file is not part of GNU Emacs.
21 |
22 | ;;; Commentary:
23 |
24 | ;; Functions corresponding to the generic CSL rendering elements cs:layout,
25 | ;; cs:group and cs:text. With the exception of `citeproc--layout' they return a
26 | ;; (CONTENT . CONTENT-TYPE) pair, where CONTENT is the rendered rich-text output
27 | ;; and CONTENT-TYPE is one of the symbols `text-only', `empty-vars' and
28 | ;; `present-var.' In contrast, `citeproc--layout' returns only the rendered
29 | ;; rich-text content.
30 |
31 | ;;; Code:
32 |
33 | (require 'dash)
34 | (require 'let-alist)
35 | (require 's)
36 |
37 | (require 'citeproc-rt)
38 | (require 'citeproc-context)
39 | (require 'citeproc-macro)
40 |
41 | (defun citeproc--layout (attrs context &rest body)
42 | "Render the content of a layout element with ATTRS and BODY."
43 | (let* ((attrs (if (eq (citeproc-context-mode context) 'bib) attrs
44 | nil)) ; No attrs if mode is cite -- they are used for citations
45 | (spliced-body (citeproc-lib-splice-into body 'splice))
46 | (suffix (alist-get 'suffix attrs))
47 | (attrs-wo-suffix (--remove (eq (car it) 'suffix) attrs))
48 | (rendered-body (--map (car it) spliced-body)))
49 | ;; Handle second-field align
50 | (when (and (alist-get 'second-field-align (citeproc-context-opts context))
51 | (> (length rendered-body) 1))
52 | (setq rendered-body `((((display . "left-margin")) ,(car rendered-body))
53 | (((display . "right-inline")) ,@(cdr rendered-body)))))
54 | (let* ((affix-rendered (citeproc-rt-render-affixes
55 | (citeproc-rt-dedup (citeproc-rt-join-formatted attrs-wo-suffix rendered-body
56 | context))))
57 | (last-elt (and (listp affix-rendered) (-last-item affix-rendered)))
58 | (last-display (and (consp last-elt) (car last-elt)
59 | (--any-p (eq (car it) 'display) (car last-elt)))))
60 | (when suffix
61 | (if last-display
62 | ;; If the last element has a display attribute then we have to append the
63 | ;; suffix string to this last element
64 | (setf (nth (1- (length affix-rendered)) affix-rendered)
65 | (-snoc (-last-item affix-rendered) suffix))
66 | ;; Else we simply append it to the already rendered content
67 | (setq affix-rendered (if (listp affix-rendered)
68 | (-snoc affix-rendered suffix)
69 | (concat affix-rendered suffix)))))
70 | affix-rendered)))
71 |
72 | (defun citeproc--group (attrs context &rest body)
73 | "Render the content of a group element with ATTRS and BODY."
74 | (-let* ((spliced-body (citeproc-lib-splice-into body 'splice))
75 | (types (--map (cdr it) spliced-body))
76 | (type (cond ((--all? (eq it 'text-only) types)
77 | 'text-only)
78 | ((--any? (eq it 'present-var) types)
79 | 'present-var)
80 | (t 'empty-vars))))
81 | (cons (if (or (eq type 'text-only)
82 | (eq type 'present-var))
83 | (citeproc-rt-join-formatted attrs (--map (car it) spliced-body) context)
84 | nil)
85 | type)))
86 |
87 | (defconst citeproc-generic-elements--url-prefix-re "https?://\\S *\\'"
88 | "Regex matching an URL prefix at the end of a string.")
89 |
90 | (defun citeproc--text (attrs context &rest _body)
91 | "Render the content of a text element with ATTRS and BODY."
92 | (let-alist attrs
93 | (let ((content nil)
94 | (type 'text-only)
95 | (no-external-links (citeproc-context-no-external-links context)))
96 | (cond (.value (setq content .value))
97 | (.variable
98 | (let ((val (citeproc-var-value (intern .variable) context (citeproc-lib-intern
99 | .form))))
100 | (setq content val)
101 | (cond
102 | (val (let ((var (intern .variable)))
103 | (setq type 'present-var)
104 | (push `(rendered-var . ,var) attrs)
105 | (when (and (not no-external-links)
106 | (memq var citeproc--linked-vars))
107 | (let ((target
108 | (concat
109 | (alist-get var citeproc--link-prefix-alist
110 | "")
111 | content)))
112 | (-when-let (match-pos
113 | (and .prefix (s-matched-positions-all
114 | citeproc-generic-elements--url-prefix-re
115 | .prefix)))
116 | ;; If the prefix ends with an URL then it is moved
117 | ;; from the prefix to the rendered variable
118 | ;; content.
119 | (let ((start (caar match-pos)))
120 | (setq content (concat (substring .prefix start) content))
121 | (push (cons 'prefix (substring .prefix 0 start))
122 | attrs)))
123 | (push (cons 'href target) attrs)))))
124 | ;; Don't report empty var for year-suffix, see issue #70.
125 | ((not (string= .variable "year-suffix")) (setq type 'empty-vars)))))
126 | (.term (setq .form (if .form (intern .form) 'long)
127 | .plural (if (or (not .plural)
128 | (string= .plural "false"))
129 | 'single 'multiple)
130 | content (let ((cont (citeproc-term-inflected-text
131 | .term .form .plural context)))
132 | ;; Annotate the 'no date' term as if it'd be
133 | ;; the value of the 'issue' variable to
134 | ;; handle implicit year suffix addition and
135 | ;; suppression issues.
136 | (if (string= .term "no date")
137 | (progn
138 | (setq type 'present-var)
139 | `(((rendered-var . issued)) ,cont))
140 | cont))))
141 | (.macro (let ((macro-val (citeproc-macro-output .macro context)))
142 | (setq content (car macro-val))
143 | (setq type (cdr macro-val)))))
144 | ;; We stop if only the title had to be rendered.
145 | (let ((result (cons (citeproc-rt-format-single attrs content context) type)))
146 | (citeproc-context-maybe-stop-rendering
147 | 'title context result (or (and .variable (intern .variable)) t))))))
148 |
149 | (provide 'citeproc-generic-elements)
150 |
151 | ;;; citeproc-generic-elements.el ends here
152 |
--------------------------------------------------------------------------------
/citeproc-itemgetters.el:
--------------------------------------------------------------------------------
1 | ;; citeproc-itemgetters.el --- functions for constructing itemgetters -*- lexical-binding: t; -*-
2 |
3 | ;; Copyright (C) 2017-2021 András Simonyi
4 |
5 | ;; Author: András Simonyi
6 |
7 | ;; This program is free software; you can redistribute it and/or modify
8 | ;; it under the terms of the GNU General Public License as published by
9 | ;; the Free Software Foundation, either version 3 of the License, or
10 | ;; (at your option) any later version.
11 |
12 | ;; This program is distributed in the hope that it will be useful,
13 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | ;; GNU General Public License for more details.
16 |
17 | ;; You should have received a copy of the GNU General Public License
18 | ;; along with this program. If not, see .
19 |
20 | ;; This file is not part of GNU Emacs.
21 |
22 | ;;; Commentary:
23 |
24 | ;; Functions for constructing various types of bibliographic itemgetter
25 | ;; functions. The returned itemgetter functions can, in turn, be used to create
26 | ;; `citeproc-style' and `citeproc-proc' structures.
27 |
28 | ;;; Code:
29 |
30 | (require 'dash)
31 | (require 'org)
32 | ;; Handle the fact that org-bibtex has been renamed to ol-bibtex -- for the time
33 | ;; being we support both feature names.
34 | (or (require 'ol-bibtex nil t)
35 | (require 'org-bibtex))
36 | (require 'json)
37 | (require 'bibtex)
38 | (require 'parsebib)
39 |
40 | (require 'citeproc-bibtex)
41 | (require 'citeproc-biblatex)
42 |
43 | (defun citeproc-itemgetters--parsebib-buffer (entries strings)
44 | "Parse a BibTeX/biblatex buffer with Parsebib."
45 | ;; Note: this is needed to support different Parsebib versions in use.
46 | (cond ((fboundp 'parsebib-parse-buffer)
47 | (parsebib-parse-buffer entries strings t t))
48 | ((fboundp 'parsebib-parse-bib-buffer)
49 | (parsebib-parse-bib-buffer :entries entries :strings strings
50 | :expand-strings t :inheritance t))
51 | (t (error "No Parsebib buffer parsing function is available"))))
52 |
53 | (defun citeproc-hash-itemgetter-from-csl-json (file)
54 | "Return a hash-based getter for csl json bibliography FILE."
55 | (let* ((json-array-type 'list)
56 | (json-key-type 'symbol)
57 | (item-list (json-read-file file))
58 | (hash (make-hash-table :test 'equal)))
59 | (--each item-list
60 | (puthash (alist-get 'id it) it hash))
61 | (lambda (itemids) (--map (cons it (gethash it hash))
62 | itemids))))
63 |
64 | (defun citeproc-itemgetter-from-csl-json (file)
65 | "Return an item-getter for csl json bibliography FILE."
66 | (lambda (itemids)
67 | (let* ((json-array-type 'list)
68 | (json-key-type 'symbol)
69 | (item-list (json-read-file file))
70 | result)
71 | (dolist (item item-list result)
72 | (let ((id (alist-get 'id item)))
73 | (when (member id itemids)
74 | (push (cons id item) result)))))))
75 |
76 | (defun citeproc-itemgetter-from-bibtex (file-or-files)
77 | "Return a getter for BibTeX bibliography FILE-OR-FILES."
78 | (if (listp file-or-files)
79 | (lambda (itemids)
80 | (let (result
81 | (remaining-ids (cl-copy-list itemids))
82 | (remaining-files file-or-files))
83 | (while (and remaining-ids remaining-files)
84 | (let ((file (pop remaining-files)))
85 | (with-temp-buffer
86 | (insert-file-contents file)
87 | (goto-char (point-min))
88 | (bibtex-set-dialect 'BibTeX t)
89 | (bibtex-map-entries
90 | (lambda (key _beg _end)
91 | (when (member key itemids)
92 | (push (cons key (citeproc-bt-entry-to-csl (bibtex-parse-entry)))
93 | result)
94 | (setq remaining-ids (delete key remaining-ids))))))))
95 | result))
96 | (lambda (itemids)
97 | (let (result)
98 | (with-temp-buffer
99 | (insert-file-contents file-or-files)
100 | (goto-char (point-min))
101 | (bibtex-set-dialect 'BibTeX t)
102 | (bibtex-map-entries
103 | (lambda (key _beg _end)
104 | (when (member key itemids)
105 | (push (cons key (citeproc-bt-entry-to-csl (bibtex-parse-entry)))
106 | result)))))
107 | result))))
108 |
109 | (defun citeproc-itemgetter-from-org-bibtex (file-or-files)
110 | "Return a getter for org-bibtex bibliography FILE-OR-FILES."
111 | (let ((files (if (listp file-or-files)
112 | file-or-files
113 | (list file-or-files))))
114 | (lambda (itemids)
115 | (let (result)
116 | (org-map-entries
117 | (lambda ()
118 | (-when-let (key-w-entry (citeproc-bt-from-org-headline itemids))
119 | (push (cons (car key-w-entry)
120 | (citeproc-bt-entry-to-csl (cdr key-w-entry)))
121 | result)))
122 | t files)
123 | result))))
124 |
125 | (defun citeproc-hash-itemgetter-from-any (file-or-files &optional no-sentcase-wo-langid)
126 | "Return a getter for FILE-OR-FILES in any supported format.
127 | The format is determined on the basis of file extensions.
128 | Supported formats:
129 | - CSL-JSON (.json extension) the recommended native format;
130 | - BibTeX/biblatex (.bib or .bibtex extension),
131 | - org-bibtex (.org extension).
132 | If NO-SENTCASE-WO-LANGID is non-nil then title fields in items
133 | without a `langid' field are not converted to sentence-case."
134 | (let ((files (if (listp file-or-files)
135 | file-or-files
136 | (list file-or-files)))
137 | (cache (make-hash-table :test #'equal))
138 | (bt-entries (make-hash-table :test #'equal))
139 | (bt-strings (make-hash-table :test #'equal)))
140 | (dolist (file files)
141 | (pcase (file-name-extension file)
142 | ("json"
143 | (let ((json-array-type 'list)
144 | (json-key-type 'symbol))
145 | (dolist (item (json-read-file file))
146 | (puthash (cdr (assq 'id item)) item cache))))
147 | ((and (or "bib" "bibtex") ext)
148 | (with-temp-buffer
149 | (insert-file-contents file)
150 | (bibtex-set-dialect (if (string= ext "bib") 'biblatex 'BibTeX) t)
151 | (citeproc-itemgetters--parsebib-buffer bt-entries bt-strings)))
152 | ("org"
153 | (org-map-entries
154 | (lambda ()
155 | (-when-let (key-w-entry (citeproc-bt-from-org-headline))
156 | (condition-case err
157 | (puthash (car key-w-entry) (citeproc-blt-entry-to-csl
158 | (cdr key-w-entry))
159 | cache)
160 | (error
161 | (user-error
162 | "Couldn't parse the bib(la)tex entry with key '%s', the error was: %s"
163 | (car key-w-entry) err)))))
164 | t (list file)))
165 | (ext
166 | (user-error "Unknown bibliography extension: %S" ext))))
167 | (maphash
168 | (lambda (key entry)
169 | (condition-case err
170 | (puthash key (citeproc-blt-entry-to-csl entry nil no-sentcase-wo-langid)
171 | cache)
172 | (error
173 | (user-error
174 | "Couldn't parse the bib(la)tex entry with key '%s', the error was: %s"
175 | key err))))
176 | bt-entries)
177 | (lambda (x)
178 | (pcase x
179 | ('itemids
180 | (hash-table-keys cache))
181 | ((pred listp) (mapcar (lambda (id)
182 | (cons id (gethash id cache)))
183 | x))
184 | (_ (error "Unsupported citeproc itemgetter retrieval method"))))))
185 |
186 | (provide 'citeproc-itemgetters)
187 |
188 | ;;; citeproc-itemgetters.el ends here
189 |
--------------------------------------------------------------------------------
/citeproc-sort.el:
--------------------------------------------------------------------------------
1 | ;;; citeproc-sort.el --- cite and bibliography sorting -*- lexical-binding: t; -*-
2 |
3 | ;; Copyright (C) 2017 András Simonyi
4 |
5 | ;; Author: András Simonyi
6 |
7 | ;; This program is free software; you can redistribute it and/or modify
8 | ;; it under the terms of the GNU General Public License as published by
9 | ;; the Free Software Foundation, either version 3 of the License, or
10 | ;; (at your option) any later version.
11 |
12 | ;; This program is distributed in the hope that it will be useful,
13 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | ;; GNU General Public License for more details.
16 |
17 | ;; You should have received a copy of the GNU General Public License
18 | ;; along with this program. If not, see .
19 |
20 | ;; This file is not part of GNU Emacs.
21 |
22 | ;;; Commentary:
23 |
24 | ;; Functions to sort cites and bibliography items.
25 |
26 | ;;; Code:
27 |
28 | (require 'subr-x)
29 | (require 'cl-lib)
30 | (require 'dash)
31 | (require 's)
32 |
33 | (require 'citeproc-lib)
34 | (require 'citeproc-s)
35 | (require 'citeproc-rt)
36 | (require 'citeproc-macro)
37 | (require 'citeproc-proc)
38 | (require 'citeproc-name)
39 | (require 'citeproc-number)
40 |
41 | (defun citeproc--sort (_attrs _context &rest body)
42 | "Placeholder function corresponding to the cs:sort element of CSL."
43 | body)
44 |
45 | (defun citeproc-sort--name-var-key (var context)
46 | "Return the sort-key for name-var VAR using CONTEXT.
47 | VAR is a CSL name-var name as a symbol. The returned value is a
48 | string containing a semicolon-separated list of all full names in
49 | sort order."
50 | (citeproc-rt-to-plain
51 | (citeproc-rt-render-affixes
52 | (citeproc-name--render-var var '((form . "long") (name-as-sort-order . "all")
53 | (et-al-min . nil) (et-al-use-first . "0")
54 | (delimiter . "; "))
55 | nil nil nil nil nil context))))
56 |
57 | (defun citeproc-sort--date-as-key (d _context)
58 | "Render D citeproc-date struct as a sort key."
59 | (if d (let ((year (citeproc-date-year d))
60 | (month (or (citeproc-date-month d) 0))
61 | (day (or (citeproc-date-day d) 0)))
62 | ;; We add 5000 as an offset to deal with sorting BC years properly
63 | (concat (number-to-string (+ 5000 year))
64 | (citeproc-s-fill-left-to-len (number-to-string month) 2 ?0)
65 | (citeproc-s-fill-left-to-len (number-to-string day) 2 ?0)))
66 | ""))
67 |
68 | (defun citeproc-sort--date-var-key (var context)
69 | "Return the sort-key for name-var VAR using CONTEXT.
70 | VAR is a symbol."
71 | (-let* (((d1 d2) (citeproc-var-value var context))
72 | (rendered-first (citeproc-sort--date-as-key d1 context)))
73 | (if d2
74 | (concat rendered-first "–" (citeproc-sort--date-as-key d2 context))
75 | rendered-first)))
76 |
77 | (defun citeproc--key (attrs context &rest _body)
78 | "Return a sort key corresponding to ATTRS and CONTEXT."
79 | (-let (((&alist 'macro macro
80 | 'variable var)
81 | attrs)
82 | (global-attrs (--filter (memq (car it)
83 | '(names-min names-use-first names-use-last))
84 | attrs)))
85 | (if var (let ((var-sym (intern var)))
86 | (cond
87 | ((memq var-sym citeproc--number-vars)
88 | ;; OPTIMIZE: This is way too complicated to simply get a filled
89 | ;; numeric value..
90 | (citeproc-s-fill-left-to-len
91 | (citeproc-number-var-value
92 | (citeproc-var-value var-sym context) var-sym 'numeric context)
93 | 5))
94 | ((memq var-sym citeproc--date-vars)
95 | (citeproc-sort--date-var-key var-sym context))
96 | ((memq var-sym citeproc--name-vars)
97 | (citeproc-sort--name-var-key var-sym context))
98 | (t (citeproc-rt-to-plain (citeproc-var-value var-sym context)))))
99 | (let ((new-context (citeproc-context--create
100 | :vars (citeproc-context-vars context)
101 | :macros (citeproc-context-macros context)
102 | :terms (citeproc-context-terms context)
103 | :date-text (citeproc-context-date-text context)
104 | :date-numeric (citeproc-context-date-numeric context)
105 | :opts (nconc global-attrs (citeproc-context-opts context))
106 | :mode (citeproc-context-mode context)
107 | :render-mode 'sort
108 | :render-year-suffix nil)))
109 | (citeproc-macro-output-as-text macro new-context)))))
110 |
111 | (defun citeproc-sort--compare-keys (k1 k2 &optional desc)
112 | "Return 1, 0 or -1 depending on the sort-order of keys K1 and K2.
113 | If optional DESC is non-nil then reverse the comparison for
114 | descending sort."
115 | (cond ((string-collate-equalp k1 k2) 0)
116 | ((s-blank? k1) -1)
117 | ((s-blank? k2) 1)
118 | (t (* (if (string-collate-lessp k1 k2) 1 -1)
119 | (if desc -1 1)))))
120 |
121 | (defun citeproc-sort--compare-keylists (k1 k2 sort-orders)
122 | "Whether keylist K1 precedes keylist K2 in the sort order.
123 | SORT-ORDERS is a list of sort orders to use (see the bib- and
124 | cite-sort-orders slots of `citeproc-style' for details)."
125 | (citeproc-lib-lex-compare k1 k2 #'citeproc-sort--compare-keys sort-orders))
126 |
127 | (defun citeproc-sort--render-keys (style var-alist mode)
128 | "Render the sort keys of an item with STYLE and VAR-ALIST.
129 | MODE is either `cite' or `bib'."
130 | (let ((context (citeproc-context-create var-alist style mode 'sort))
131 | (sort (cl-ecase mode
132 | (cite (citeproc-style-cite-sort style))
133 | (bib (citeproc-style-bib-sort style)))))
134 | (if sort (funcall sort context) nil)))
135 |
136 | (defun citeproc-itd-update-sortkey (itd style)
137 | "Update the sort key of itemdata ITD for STYLE."
138 | (setf (citeproc-itemdata-sort-key itd)
139 | (citeproc-sort--render-keys style (citeproc-itemdata-varvals itd) 'bib)))
140 |
141 | (defun citeproc-proc-update-sortkeys (proc)
142 | "Update all sort keys of the itemdata in PROC."
143 | (let ((style (citeproc-proc-style proc))
144 | (itds (citeproc-proc-itemdata proc)))
145 | (maphash (lambda (_id itd)
146 | (citeproc-itd-update-sortkey itd style))
147 | itds)))
148 |
149 | (defun citeproc-sort-itds-on-citnum (itds)
150 | "Sort itemdata struct list ITDS according to citation number."
151 | (sort itds
152 | (lambda (x y)
153 | (< (string-to-number (citeproc-itd-getvar x 'citation-number))
154 | (string-to-number (citeproc-itd-getvar y 'citation-number))))))
155 |
156 | (defun citeproc-sort-itds-on-subbib (itd1 itd2)
157 | "Sort itemdata structs ITD1 ITD2 according to subbib order."
158 | (let ((idx1 (car (citeproc-itemdata-subbib-nos itd1)))
159 | (idx2 (car (citeproc-itemdata-subbib-nos itd2))))
160 | (and idx1
161 | (or (null idx2) (< idx1 idx2)))))
162 |
163 | (defun citeproc-sort-itds (itds sort-orders)
164 | "Sort the itemdata struct list ITDS according to SORT-ORDERS."
165 | (sort itds
166 | (lambda (x y)
167 | (citeproc-sort--compare-keylists (citeproc-itemdata-sort-key x)
168 | (citeproc-itemdata-sort-key y)
169 | sort-orders))))
170 |
171 | (defun citeproc-proc-sort-itds (proc)
172 | "Sort the itemdata in PROC."
173 | (let ((is-sorted-bib (citeproc-style-bib-sort (citeproc-proc-style proc)))
174 | (is-filtered (citeproc-proc-filtered-bib-p proc)))
175 | (when (or is-sorted-bib is-filtered)
176 | (let* ((itds (citeproc-sort-itds-on-citnum
177 | (hash-table-values (citeproc-proc-itemdata proc)))))
178 | (when is-sorted-bib
179 | (let ((sort-orders (citeproc-style-bib-sort-orders
180 | (citeproc-proc-style proc))))
181 | (setq itds (citeproc-sort-itds itds sort-orders))))
182 | ;; Additionally sort according to subbibliographies if there are filters.
183 | (when is-filtered
184 | (setq itds (sort itds #'citeproc-sort-itds-on-subbib)))
185 | ;; Set the CSL citation-number field according to the sort order.
186 | (--each-indexed itds
187 | (citeproc-itd-setvar it 'citation-number
188 | (number-to-string (1+ it-index))))))))
189 |
190 | (provide 'citeproc-sort)
191 |
192 | ;;; citeproc-sort.el ends here
193 |
--------------------------------------------------------------------------------
/citeproc-test-human.el:
--------------------------------------------------------------------------------
1 | ;; citeproc-test-human.el --- support tests in CSL suite format -*- lexical-binding: t; -*-
2 |
3 | ;; Copyright (C) 2017-2021 András Simonyi
4 |
5 | ;; Author: András Simonyi
6 |
7 | ;; This program is free software; you can redistribute it and/or modify
8 | ;; it under the terms of the GNU General Public License as published by
9 | ;; the Free Software Foundation, either version 3 of the License, or
10 | ;; (at your option) any later version.
11 |
12 | ;; This program is distributed in the hope that it will be useful,
13 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | ;; GNU General Public License for more details.
16 |
17 | ;; You should have received a copy of the GNU General Public License
18 | ;; along with this program. If not, see .
19 |
20 | ;; This file is not part of GNU Emacs.
21 |
22 | ;;; Commentary:
23 |
24 | ;; Functions to create ERT tests from tests in CSL test suite format. The
25 | ;; official tests can be found at
26 | ;; .
27 |
28 | ;;; Code:
29 |
30 | (require 'f)
31 | (require 's)
32 | (require 'json)
33 | (require 'ert)
34 | (require 'string-inflection)
35 |
36 | (require 'citeproc)
37 |
38 | (defvar citeproc-test-human--locale-dir "./test/locales")
39 |
40 | (defun citeproc-test-human--parse-testfile (file)
41 | "Return a parsed form of CSL test FILE."
42 | (let (result
43 | (json-array-type 'list)
44 | (json-key-type 'symbol))
45 | (with-temp-buffer
46 | (insert-file-contents file)
47 | (goto-char 1)
48 | (setq result (list (cons 'YEAR-SUFF
49 | (re-search-forward "variable=\"year-suffix\"" nil t))))
50 | (goto-char 1)
51 | (while (re-search-forward ">>=+ \\{1,2\\}\\([[:graph:]]+\\) =+>>" nil t)
52 | (let ((section (intern (buffer-substring (nth 2 (match-data))
53 | (nth 3 (match-data)))))
54 | (start (1+ (point)))
55 | end)
56 | (re-search-forward "<<=" nil t)
57 | (setq end (- (car (match-data)) 1))
58 | (push (cons section (pcase section
59 | ('OUTPUT-FORMAT
60 | (intern (buffer-substring-no-properties start end)))
61 | ('CSL (buffer-substring-no-properties start end))
62 | ((or 'INPUT 'CITATIONS 'CITATION-ITEMS)
63 | (goto-char (- start 1)) (json-read))
64 | (_ (buffer-substring start end))))
65 | result))))
66 | result))
67 |
68 | (defun citeproc-test-human--create-getter (items)
69 | "Return a getter function for ITEMS.
70 | ITEMS is the parsed representation of the `INPUT' section of a
71 | CSL test."
72 | (lambda (itemids)
73 | (let (result)
74 | (dolist (item items result)
75 | (let ((id (citeproc-s-from-num-or-s (alist-get 'id item))))
76 | (when (member id itemids)
77 | (push (cons id item) result)))))))
78 |
79 | (defun citeproc-test-human--proc-from-style (style parsed-input)
80 | "Create a processor from STYLE and PARSED-INPUT."
81 | (citeproc-create style
82 | (citeproc-test-human--create-getter parsed-input)
83 | (citeproc-locale-getter-from-dir citeproc-test-human--locale-dir)))
84 |
85 | (defun citeproc-test-human--proc-from-testfile (file)
86 | "Create an (itemless) processor from a test FILE."
87 | (let ((style-string (alist-get 'CSL (citeproc-test-human--parse-testfile file)))
88 | (locale-getter (citeproc-locale-getter-from-dir citeproc-test-human--locale-dir)))
89 | (citeproc-create style-string nil locale-getter)))
90 |
91 | (defun citeproc-test-human--parse-citation (ct-desc &optional cites-only)
92 | "Parse test citations description CT-DESC.
93 | Return a list of citation structures. If CITES-ONLY is non-nil
94 | then the input is list of cites."
95 | (if cites-only
96 | (citeproc-citation-create
97 | :cites (-map #'citeproc-test-human--normalize-cite ct-desc))
98 | (let ((citation-info (car ct-desc)))
99 | (let-alist (alist-get 'properties citation-info)
100 | (citeproc-citation-create
101 | :cites (-map #'citeproc-test-human--normalize-cite
102 | (alist-get 'citationItems citation-info))
103 | :note-index .noteIndex
104 | :mode (citeproc-lib-intern .mode)
105 | :capitalize-first .capitalize-first
106 | :suppress-affixes .suppress-affixes
107 | :ignore-et-al .ignore-et-al)))))
108 |
109 | (defun citeproc-test-human--normalize-cite (cite)
110 | "Normalize a test CITE."
111 | (--map (let ((val (cdr it)))
112 | (if (numberp val) (cons (car it) (number-to-string val)) it))
113 | cite))
114 |
115 | (defun citeproc-test-human--run-parsed (parsed)
116 | "Run the parsed CSL test PARSED.
117 | Return the resulting output."
118 | (-let* (((&alist 'CSL style
119 | 'INPUT input
120 | 'MODE mode
121 | 'CITATION-ITEMS citation-items
122 | 'CITATIONS citations
123 | 'OUTPUT-FORMAT output-format)
124 | parsed)
125 | (output-format (or output-format 'csl-test))
126 | (proc (citeproc-test-human--proc-from-style style input)))
127 | (--each input
128 | (citeproc-proc-put-item-by-id proc
129 | (citeproc-s-from-num-or-s (alist-get 'id it))))
130 | (when (string= mode "citation")
131 | (cond
132 | (citation-items
133 | (citeproc-append-citations (--map (citeproc-test-human--parse-citation it t)
134 | citation-items)
135 | proc))
136 | (citations
137 | (citeproc-append-citations (mapcar #'citeproc-test-human--parse-citation citations)
138 | proc))
139 | (t (citeproc-append-citations (list (citeproc-test-human--parse-citation input t))
140 | proc))))
141 | (let ((output (if (string= mode "citation")
142 | (citeproc-render-citations proc output-format
143 | (when (eq 'csl-test output-format)
144 | 'no-links))
145 | (car (citeproc-render-bib proc output-format 'no-links)))))
146 | (if (string= mode "citation") (s-join "\n" output) output))))
147 |
148 | (defun citeproc-test-human--expected-from-parsed (parsed)
149 | "Return the expected output of parsed CSL test PARSED."
150 | (let ((expected (alist-get 'RESULT parsed)))
151 | (if (or (string= (s-left 5 expected) "..[0]")
152 | (string= (s-left 5 expected) ">>[0]"))
153 | (s-join "\n" (--map (substring it 6)
154 | (split-string expected "\n")))
155 | expected)))
156 |
157 | (defun citeproc-test-human-create-from-file (file expected-fails &optional name-prefix)
158 | "Create an ERT test from a CSL test FILE.
159 | If optional NAME-PREFIX is non-nil then it is added the name of
160 | the created test after the obligatory `citeproc'."
161 | (let* ((parsed (citeproc-test-human--parse-testfile file))
162 | (expected (citeproc-test-human--expected-from-parsed parsed))
163 | (file-name (f-filename file))
164 | (test-name (intern
165 | (concat "citeproc-"
166 | (if name-prefix (concat name-prefix "-") "")
167 | (string-inflection-kebab-case-function
168 | (substring file-name 0 -4)))))
169 | (expected-fail (memq test-name expected-fails)))
170 | (eval `(ert-deftest ,test-name ()
171 | :expected-result ,(if expected-fail :failed :passed)
172 | (let ((citeproc-disambiguation-cite-pos 'subsequent))
173 | (should (string=
174 | ,expected
175 | (citeproc-test-human--run-parsed ',parsed))))))))
176 |
177 | (defun citeproc-test-human---read-expected-fails (expected-fails-file)
178 | "Read the list of tests expected to fail from EXPECTED-FAILS-FILE."
179 | (let* ((list-as-str (with-temp-buffer
180 | (insert-file-contents expected-fails-file)
181 | (buffer-string)))
182 | (split (split-string list-as-str "\n")))
183 | (--map (intern it) (butlast split))))
184 |
185 | (defun citeproc-test-human-create-from-dir (dir &optional
186 | expected-fails-file name-prefix)
187 | "Create all CSL tests from DIR.
188 | Each file in DIR having the `txt' extension is read as a
189 | human-readable CSL test, and a corresponding ERT test is created.
190 | The created test's name will be constructed by prefixing the
191 | test's filename (without the extension) with `citeproc-'. If the
192 | optional EXPECTED-FAILS-FILE is non-nil then read that file as a
193 | list of tests whose failure is expected. If optional NAME-PREFIX
194 | is non-nil then it is added the names of the created tests after
195 | the obligatory `citeproc'. The file should contain one test-name
196 | per line (together with the `citeproc-' prefix)."
197 | (let ((expected-fails
198 | (if expected-fails-file
199 | (citeproc-test-human---read-expected-fails expected-fails-file)
200 | nil)))
201 | (dolist (test-file (f-glob (concat dir "/*.txt")))
202 | (citeproc-test-human-create-from-file test-file expected-fails
203 | name-prefix))))
204 |
205 | (provide 'citeproc-test-human)
206 |
207 | ;;; citeproc-test-human.el ends here
208 |
--------------------------------------------------------------------------------
/citeproc-proc.el:
--------------------------------------------------------------------------------
1 | ;;; citeproc-proc.el --- construct and manage citation processors -*- lexical-binding: t; -*-
2 |
3 | ;; Copyright (C) 2017 András Simonyi
4 |
5 | ;; Author: András Simonyi
6 |
7 | ;; This program is free software; you can redistribute it and/or modify
8 | ;; it under the terms of the GNU General Public License as published by
9 | ;; the Free Software Foundation, either version 3 of the License, or
10 | ;; (at your option) any later version.
11 |
12 | ;; This program is distributed in the hope that it will be useful,
13 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | ;; GNU General Public License for more details.
16 |
17 | ;; You should have received a copy of the GNU General Public License
18 | ;; along with this program. If not, see .
19 |
20 | ;; This file is not part of GNU Emacs.
21 |
22 | ;;; Commentary:
23 |
24 | ;; Structure type and functions to construct citation processor objects, add or
25 | ;; clear stored bibliography items, and disambiguate and finalize the rendering
26 | ;; of the stored items.
27 |
28 | ;;; Code:
29 |
30 | (require 'subr-x)
31 | (require 'dash)
32 | (require 'cl-lib)
33 | (require 'queue)
34 | (require 's)
35 |
36 | (require 'citeproc-date)
37 | (require 'citeproc-itemdata)
38 | (require 'citeproc-disamb)
39 |
40 | (cl-defstruct (citeproc-proc (:constructor citeproc-proc--create))
41 | "Citation processor struct.
42 | STYLE is a `citeproc-style' struct,
43 | GETTER is a bibliography item getter,
44 | ITEMDATA is a hash table that maps itemids to `citeproc-itemdata'
45 | structs,
46 | CITATIONS is a queue containing citations,
47 | NAMES is hash table that maps name alists to ids,
48 | FINALIZED is non-nil iff the processor is finalized
49 | (bibliography items are properly sorted, citation positions are
50 | updated etc),
51 | UNCITED is a list of lists of uncited itemids to be added during
52 | finalization,
53 | BIB-FILTERS is a list of filters defining sub-bibliographies."
54 | style getter itemdata citations names finalized uncited bib-filters)
55 |
56 | (defun citeproc-proc--internalize-name (name proc)
57 | "Find or add name-alist NAME in/to the names stored in PROC.
58 | Return an internalized version which contains the name-id, and is
59 | sorted."
60 | (let* ((sorted (sort name (lambda (x y)
61 | (string< (car x) (car y)))))
62 | (names (citeproc-proc-names proc))
63 | (val (gethash sorted names)))
64 | (cons (cons 'name-id
65 | (or val (puthash sorted (hash-table-count names) names)))
66 | sorted)))
67 |
68 | (defconst citeproc-proc--nonstd-csl-vars-alist
69 | '((shortTitle . title-short) (journalAbbreviation . container-title-short))
70 | "Alist mapping non-standard citeproc.js vars to their standard CSL peers.")
71 |
72 | (defun citeproc-proc--internalize-item (proc item)
73 | "Return the internal form of a CSL json ITEM for PROC."
74 | (let* (label
75 | page-first
76 | (result
77 | (--map
78 | (let* ((orig-var (car it))
79 | (var (-if-let (mapped (alist-get orig-var
80 | citeproc-proc--nonstd-csl-vars-alist))
81 | mapped
82 | orig-var))
83 | (value (citeproc-proc--parse-csl-var-val (cdr it) var proc)))
84 | (pcase var
85 | ('page (-when-let (page-first-match (s-match "[[:digit:]]+" value))
86 | (setq page-first (car page-first-match))))
87 | ('label (setq label t)))
88 | (cons var value))
89 | item)))
90 | (when page-first (push (cons 'page-first page-first) result))
91 | (unless label (push (cons 'label "page") result))
92 | ;; Generate the editor-translator variable if needed
93 | ;; (required by CSL 1.02)
94 | (when-let* (((null (alist-get 'editor-translator result)))
95 | (editor (alist-get 'editor result))
96 | (translator (alist-get 'translator result))
97 | ((string= (alist-get 'name-id editor)
98 | (alist-get 'name-id translator))))
99 | (push (cons 'editor-translator editor) result))
100 | result))
101 |
102 | (defun citeproc-proc--put-item (proc item itemid &optional uncited)
103 | "Put parsed csl-json ITEM with ITEMID into PROC.
104 | Return the added itemdata structure."
105 | (let* ((int-vars (citeproc-proc--internalize-item proc item))
106 | (itemdata (citeproc-itemdata-create :varvals int-vars :uncited uncited)))
107 | (citeproc-proc-put-itd-put itemid itemdata proc)
108 | (citeproc-itd-setvar itemdata 'citation-number
109 | (number-to-string (hash-table-count
110 | (citeproc-proc-itemdata proc))))
111 | (setf (citeproc-proc-finalized proc) nil)
112 | itemdata))
113 |
114 | (defun citeproc-proc-put-item-by-id (proc itemid)
115 | "Put item with ITEMID into the itemlist of PROC.
116 | Return the itemdata struct that was added."
117 | (let ((item (cdar (funcall (citeproc-proc-getter proc)
118 | (list itemid)))))
119 | (citeproc-proc--put-item proc
120 | (or item `((unprocessed-with-id . ,itemid)))
121 | itemid)))
122 |
123 | (defun citeproc-proc-put-items-by-id (proc itemids)
124 | "Add items with ITEMIDS into the itemlist of PROC."
125 | (let* ((received (funcall (citeproc-proc-getter proc) itemids))
126 | ;; OPTIMIZE: putting the received items into the original order could/should be
127 | ;; made more efficient
128 | (items (--map (cons it (assoc-default it received))
129 | itemids)))
130 | (cl-loop for (itemid . item) in items do
131 | (citeproc-proc--put-item proc
132 | (or item `((unprocessed-with-id . ,itemid)))
133 | itemid))))
134 |
135 | (defun citeproc-proc-put-itd-put (id data proc)
136 | "Put the DATA of item with ID in processor PROC."
137 | (let ((itemdata (citeproc-proc-itemdata proc)))
138 | (puthash id data itemdata)))
139 |
140 | (defun citeproc-proc-process-uncited (proc)
141 | "Add uncited items to the itemdata in PROC."
142 | (when-let ((unciteds (citeproc-proc-uncited proc)))
143 | (let* ((itemids (cl-delete-duplicates (apply #'append unciteds))))
144 | (when (member "*" itemids)
145 | (setq itemids (funcall (citeproc-proc-getter proc) 'itemids)))
146 | (let* ((itemdata (citeproc-proc-itemdata proc))
147 | (new-ids (--remove (gethash it itemdata) itemids))
148 | (id-items (funcall (citeproc-proc-getter proc) new-ids)))
149 | (pcase-dolist (`(,id . ,item) id-items)
150 | (citeproc-proc--put-item
151 | proc
152 | (or item `((unprocessed-with-id . ,id)))
153 | id t))))))
154 |
155 | (defun citeproc-proc-delete-occurrence-info (proc)
156 | "Remove all itemdata occurrence info from PROC."
157 | (maphash (lambda (_ itd)
158 | (setf (citeproc-itemdata-occurred-before itd) nil))
159 | (citeproc-proc-itemdata proc)))
160 |
161 | (defun citeproc-proc--parse-csl-json-name (rep)
162 | "Parse the json representation REP of a csl name variable."
163 | (if-let ((literal (alist-get 'literal rep)))
164 | (list (cons 'family (citeproc-s-smart-apostrophes literal)))
165 | (let ((filtered (-remove (lambda (x) (eq (car x) 'isInstitution)) rep)))
166 | (--map (cons
167 | (car it)
168 | (let ((text-field (cdr it)))
169 | (if (stringp text-field)
170 | (citeproc-s-smart-apostrophes text-field)
171 | text-field)))
172 | filtered))))
173 |
174 | (defun citeproc-proc--parse-csl-var-val (rep var proc)
175 | "Parse the json representation REP of csl variable VAR.
176 | VAR is a csl variable as symbol;
177 | REP is its value in standard csl json representation as parsed by
178 | the Emacs `json' library;
179 | PROC is the target citeproc-processor of the internal representation.
180 | Return the PROC-internal representation of REP."
181 | (cond ((memq var citeproc--name-vars)
182 | (--map (citeproc-proc--internalize-name
183 | (citeproc-proc--parse-csl-json-name it)
184 | proc)
185 | rep))
186 | ((memq var citeproc--date-vars)
187 | (citeproc-date-parse rep))
188 | ;;FIXME: We handle here the id... do we need it in the itemdata at all?
189 | ((or (memq var citeproc--number-vars) (eq 'id var))
190 | (citeproc-s-from-num-or-s rep))
191 | ((stringp rep)
192 | (let* ((w-aposts (citeproc-s-smart-apostrophes rep))
193 | (rt (citeproc-rt-from-str w-aposts)))
194 | (if (s-contains-p "\"" rep)
195 | (let* ((terms (citeproc-style-terms (citeproc-proc-style proc)))
196 | (oq (citeproc-term-text-from-terms "open-quote" terms))
197 | (cq (citeproc-term-text-from-terms "close-quote" terms)))
198 | (citeproc-rt-change-case
199 | rt (lambda (x) (citeproc-s-smart-quotes x oq cq))))
200 | rt)))
201 | (t rep)))
202 |
203 | (defun citeproc-proc-disamb (proc)
204 | "Disambiguate the items stored in PROC."
205 | (let* ((cite-opts (citeproc-style-cite-opts (citeproc-proc-style proc)))
206 | (name (string= "true" (alist-get 'disambiguate-add-names cite-opts)))
207 | (given (string= "true" (alist-get 'disambiguate-add-givenname cite-opts)))
208 | (yearsuff (string= "true" (alist-get 'disambiguate-add-year-suffix cite-opts))))
209 | (citeproc-disamb-itds (hash-table-values (citeproc-proc-itemdata proc))
210 | (citeproc-proc-style proc)
211 | name given yearsuff)))
212 |
213 | (defun citeproc-proc-byte-compile (proc)
214 | "Byte-compile all lambdas in PROC."
215 | (let* ((style (citeproc-proc-style proc))
216 | (bib-sort (citeproc-style-bib-sort style))
217 | (cite-sort (citeproc-style-cite-sort style)))
218 | (setf (citeproc-style-macros style)
219 | (--map (cons (car it) (byte-compile (cdr it)))
220 | (citeproc-style-macros style))
221 | (citeproc-style-cite-layout style)
222 | (byte-compile (citeproc-style-cite-layout style))
223 | (citeproc-style-bib-layout style)
224 | (byte-compile (citeproc-style-bib-layout style)))
225 | (when bib-sort (setf (citeproc-style-bib-sort style) (byte-compile bib-sort)))
226 | (when cite-sort (setf (citeproc-style-cite-sort style) (byte-compile cite-sort)))))
227 |
228 | (defun citeproc-proc-filtered-bib-p (proc)
229 | "Return whether PROC has nontrivial filters"
230 | (let ((filters (citeproc-proc-bib-filters proc)))
231 | (and filters (not (equal filters '(nil))))))
232 |
233 | (defun citeproc-proc-max-offset (itds)
234 | "Return the maximal first field width of bibitems in ITDS.
235 | ITDS should be the value of the itemdata field of a citeproc-proc
236 | structure."
237 | (cl-loop for itd being the hash-values of itds
238 | when (listp (citeproc-itemdata-rawbibitem itd)) maximize
239 | (length (citeproc-rt-to-plain (cadr (citeproc-itemdata-rawbibitem itd))))))
240 |
241 | (provide 'citeproc-proc)
242 |
243 | ;;; citeproc-proc.el ends here
244 |
--------------------------------------------------------------------------------
/citeproc-disamb.el:
--------------------------------------------------------------------------------
1 | ;;; citeproc-disamb.el --- disambiguate ambiguous cites -*- lexical-binding: t; -*-
2 |
3 | ;; Copyright (C) 2017 András Simonyi
4 |
5 | ;; Author: András Simonyi
6 |
7 | ;; This program is free software; you can redistribute it and/or modify
8 | ;; it under the terms of the GNU General Public License as published by
9 | ;; the Free Software Foundation, either version 3 of the License, or
10 | ;; (at your option) any later version.
11 |
12 | ;; This program is distributed in the hope that it will be useful,
13 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | ;; GNU General Public License for more details.
16 |
17 | ;; You should have received a copy of the GNU General Public License
18 | ;; along with this program. If not, see .
19 |
20 | ;; This file is not part of GNU Emacs.
21 |
22 | ;;; Commentary:
23 |
24 | ;; Functions to disambiguate cites of different bibliography items that would
25 | ;; have the same rendering. Disambiguation steps (e.g., adding more names,
26 | ;; expanding names, adding year-suffixes) are performed according to the
27 | ;; disambiguation rules specified by the CSL style in use.
28 |
29 | ;;; Code:
30 |
31 | (require 'dash)
32 | (require 'cl-lib)
33 | (require 'subr-x)
34 |
35 | (require 'citeproc-itemdata)
36 |
37 | (defun citeproc-itd-inc-disamb-level (key itd type)
38 | "Increment the disambiguation level of KEY in itemdata ITD.
39 | TYPE is either `add-names' or `show-given-names.'"
40 | (let ((vv (citeproc-itemdata-varvals itd)))
41 | (if (alist-get type vv)
42 | (let* ((cur-level (alist-get key (alist-get type vv)))
43 | (new-level (if cur-level (1+ cur-level) 1)))
44 | (setf (alist-get key (alist-get type vv)) new-level))
45 | (push `(,type . ((,key . 1))) (citeproc-itemdata-varvals itd))))
46 | (setf (citeproc-itemdata-rc-uptodate itd) nil))
47 |
48 | (defun citeproc-itd-add-name (itd style &optional _first-step)
49 | "Perform an add-name disambig. step on itemdata ITD with STYLE.
50 | FIRST-STEP is ignored -- it is there to get the same signature as
51 | the other two disamb. step functions. Return nil if no disambiguation
52 | could be performed and t otherwise. Disambiguation is performed
53 | from left to right: an item is attempted to be expanded only if
54 | no previous items to the left could be."
55 | (let* ((vars (citeproc-itd-namevars itd style))
56 | (cite (citeproc-itd-plain-cite itd style))
57 | (vv (citeproc-itemdata-varvals itd))
58 | (levels (alist-get 'add-names vv))
59 | (remaining-vars (if levels (memq (caar levels) vars) vars))
60 | (success nil))
61 | (while (and (not success) remaining-vars)
62 | (citeproc-itd-inc-disamb-level (car remaining-vars) itd 'add-names)
63 | (if (string= cite (citeproc-itd-plain-cite itd style))
64 | (pop remaining-vars)
65 | (setq success t)))
66 | success))
67 |
68 | (defun citeproc-itd-add-given (itd style &optional first-step)
69 | "Perform an add-given disambig. step on itemdata ITD with STYLE.
70 | Unless FIRST-STEP is non-nil, remove the last previously added
71 | given name if the last added given name is shown in its entirety.
72 | Return nil if no disambig. step could be performed and t
73 | otherwise."
74 | (let* ((nids (citeproc-itd-nameids itd style))
75 | (cite (citeproc-itd-plain-cite itd style))
76 | (vv (citeproc-itemdata-varvals itd))
77 | (levels (alist-get 'show-given-names vv))
78 | (remaining-nids (if levels (memq (caar levels) nids) nids))
79 | (success nil))
80 | (while (and (not success) remaining-nids)
81 | (let* ((current-nid (car remaining-nids))
82 | (vv (citeproc-itemdata-varvals itd))
83 | (levels (alist-get 'show-given-names vv))
84 | (current-level (alist-get current-nid levels)))
85 | (if (and current-level (>= current-level 2))
86 | (pop remaining-nids)
87 | (citeproc-itd-inc-disamb-level current-nid itd 'show-given-names)
88 | (unless (string= cite (citeproc-itd-plain-cite itd style))
89 | (setq success t)
90 | (unless (or first-step current-level)
91 | (let ((ls (alist-get 'show-given-names vv)))
92 | (setf (alist-get 'show-given-names vv)
93 | (cons (car ls) (cddr ls))))
94 | (setf (citeproc-itemdata-rc-uptodate itd) nil))))))
95 | success))
96 |
97 | (defun citeproc-itd-addgiven-with-addname (itd style &optional first-step)
98 | "Perform a combined disambig. step on itemdata ITD with STYLE.
99 | If FIRST-STEP is non-nil then (i) add a new name even if the last
100 | add-given step showed only initials, (ii) don't remove the
101 | previously added given name. Return nil if no disambig. step
102 | could be performed and t otherwise."
103 | (let* ((vv (citeproc-itemdata-varvals itd))
104 | (gn (alist-get 'show-given-names vv))
105 | (success nil)
106 | (remaining-names t))
107 | (if (and (not first-step) gn (= 1 (cdar gn)) (citeproc-itd-add-given itd style))
108 | t
109 | (while (and (not success) remaining-names)
110 | (let ((nids (citeproc-itd-nameids itd style)))
111 | (if (citeproc-itd-add-name itd style)
112 | (let* ((new-nids (citeproc-itd-nameids itd style))
113 | (new-nid (car (cl-set-difference new-nids nids))))
114 | ;;next sexp is to direct the add-given function to the just added name
115 | (when first-step
116 | (setf (alist-get new-nid
117 | (alist-get 'show-given-names
118 | (citeproc-itemdata-varvals itd)))
119 | 0))
120 | (when (citeproc-itd-add-given itd style first-step)
121 | (setq success t)))
122 | (setq remaining-names nil))))
123 | success)))
124 |
125 | (defun citeproc-disamb--different-cites-p (itds style)
126 | "Whether some itemdata in ITDS have different cites with STYLE."
127 | (--any-p (not (string= (citeproc-itd-plain-cite it style)
128 | (citeproc-itd-plain-cite (car itds) style)))
129 | (cdr itds)))
130 |
131 | (defun citeproc-disamb--with-method (itds style disamb-fun)
132 | "Disambiguate itemdatas in ITDS for STYLE with DISAMB-FUN.
133 | Return t if the disambiguation was (at least partially)
134 | successful and nil otherwise."
135 | (let ((orig-settings (copy-tree (citeproc-disamb--settings itds)))
136 | success
137 | (first-step t))
138 | (while (and (not success)
139 | (--all-p (funcall disamb-fun it style first-step) itds))
140 | (setq first-step nil)
141 | (when (citeproc-disamb--different-cites-p itds style)
142 | (setq success t)))
143 | (unless success
144 | (citeproc-disamb--restore-settings itds orig-settings))
145 | success))
146 |
147 | (defun citeproc-disamb--settings (itds)
148 | "Return a list with the disamb settings of ITDS."
149 | (--map (cons (citeproc-itd-getvar it 'add-names)
150 | (citeproc-itd-getvar it 'show-given-names))
151 | itds))
152 |
153 | (defun citeproc-disamb--restore-settings (itds settings)
154 | "Restore the disamb settings of ITDS from SETTINGS.
155 | SETTINGS should have the structure produced by citeproc--disamb-settings."
156 | (cl-loop for itd in itds
157 | for (add-names-val . show-given-val) in settings do
158 | (citeproc-itd-setvar itd 'add-names add-names-val)
159 | (citeproc-itd-setvar itd 'show-given-names show-given-val)))
160 |
161 | (defun citeproc-disamb--num-to-yearsuffix (n)
162 | "Return year-suffix no. N (starting from 0)."
163 | (cond ((< n 26)
164 | (char-to-string (+ 97 n)))
165 | ((< n 702)
166 | (let* ((rem (% n 26))
167 | (d (/ (- n rem) 26)))
168 | (concat (char-to-string (+ 96 d))
169 | (char-to-string (+ 97 rem)))))
170 | (t (error "Number too large to convert into a year-suffix"))))
171 |
172 | (defun citeproc-disamb--add-yearsuffix (itds _style)
173 | "Disambiguate itemdata in ITDS by adding year suffices.
174 | Return t (for the sake of consistency with other disamb methods)."
175 | (--each-indexed (--sort (< (string-to-number (citeproc-itd-getvar it 'citation-number))
176 | (string-to-number (citeproc-itd-getvar other 'citation-number)))
177 | itds)
178 | (citeproc-itd-setvar it 'year-suffix (citeproc-disamb--num-to-yearsuffix it-index))
179 | (setf (citeproc-itemdata-rc-uptodate it) nil))
180 | t)
181 |
182 | (defun citeproc-disamb--set-fields (itds)
183 | "Disambiguate ITDS by setting their disambiguate fields."
184 | (--each itds
185 | (citeproc-itd-setvar it 'disambiguate t)))
186 |
187 | (defun citeproc-disamb-amb-itds (itds style name given yearsuff)
188 | "Disambiguate ITDS ambigous for STYLE with the given methods.
189 | NAME, GIVEN and YEARSUFF are generalized booleans specifying
190 | whether or not the add-name, show-given or add-year-suffix
191 | disambiguation methods should be used. Return t if the
192 | disambiguation was (at least partially) successful, nil
193 | otherwise."
194 | (or (and name (citeproc-disamb--with-method itds style 'citeproc-itd-add-name))
195 | (and given (citeproc-disamb--with-method itds style 'citeproc-itd-add-given))
196 | (and name given
197 | (citeproc-disamb--with-method itds style 'citeproc-itd-addgiven-with-addname))
198 | (progn
199 | (citeproc-disamb--set-fields itds)
200 | (citeproc-disamb--different-cites-p itds style))
201 | (and yearsuff
202 | (citeproc-disamb--add-yearsuffix itds style)
203 | (citeproc-disamb--different-cites-p itds style))))
204 |
205 | (defun citeproc-amb-itds (itds style)
206 | "Return a list of ambigous sets in ITDS for STYLE.
207 | The returned value is a (possibly empty) list of lists."
208 | (let* ((sorted (-sort (lambda (x y)
209 | (string< (citeproc-itd-plain-cite x style)
210 | (citeproc-itd-plain-cite y style)))
211 | itds))
212 | (result nil)
213 | (remaining (cdr sorted))
214 | (act (car sorted))
215 | (act-list (list act))
216 | (ambig nil))
217 | (while remaining
218 | (let ((next (car remaining)))
219 | (if (string= (citeproc-itd-plain-cite act style)
220 | (citeproc-itd-plain-cite next style))
221 | (progn
222 | (push next act-list)
223 | (setq ambig t))
224 | (when ambig (push act-list result))
225 | (setq act-list (list next)
226 | act next
227 | ambig nil))
228 | (pop remaining)))
229 | (when ambig (push act-list result))
230 | result))
231 |
232 | (defun citeproc-disamb-itds (itds style name given yearsuff)
233 | "Disambiguate itemdatas in list ITDS for STYLE.
234 | NAME, GIVEN and YEARSUFF are generalized booleans specifying
235 | whether or not the add-name, show-given or add-year-suffix
236 | disambiguation methods should be used."
237 | (let ((amb-itds (citeproc-amb-itds itds style)))
238 | (while amb-itds
239 | (let ((act-set (pop amb-itds)))
240 | (citeproc-disamb-amb-itds act-set style name given yearsuff)
241 | (when (citeproc-disamb--different-cites-p act-set style)
242 | (-when-let (new-ambs (citeproc-amb-itds act-set style))
243 | (setq amb-itds (nconc new-ambs amb-itds))))))))
244 |
245 | (provide 'citeproc-disamb)
246 |
247 | ;;; citeproc-disamb.el ends here
248 |
--------------------------------------------------------------------------------
/citeproc-s.el:
--------------------------------------------------------------------------------
1 | ;;; citeproc-s.el --- citeproc-el string functions -*- lexical-binding: t; -*-
2 |
3 | ;; Copyright (C) 2017 András Simonyi
4 |
5 | ;; Author: András Simonyi
6 |
7 | ;; This program is free software; you can redistribute it and/or modify
8 | ;; it under the terms of the GNU General Public License as published by
9 | ;; the Free Software Foundation, either version 3 of the License, or
10 | ;; (at your option) any later version.
11 |
12 | ;; This program is distributed in the hope that it will be useful,
13 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | ;; GNU General Public License for more details.
16 |
17 | ;; You should have received a copy of the GNU General Public License
18 | ;; along with this program. If not, see .
19 |
20 | ;; This file is not part of GNU Emacs.
21 |
22 | ;;; Commentary:
23 |
24 | ;; String utility functions for citeproc-el.
25 |
26 | ;;; Code:
27 |
28 | (require 'thingatpt)
29 | (require 's)
30 | (require 'compat)
31 |
32 | (defun citeproc-s-camelcase-p (s)
33 | "Return whether string S is in camel case."
34 | (let ((case-fold-search nil))
35 | (and (< 1 (length s))
36 | (s-matches-p "[[:upper:]]" (substring s 1))
37 | (s-matches-p "[[:lower:]]" s))))
38 |
39 | (defun citeproc-s-fill-copy (s1 s2)
40 | "Return a copy of string S1 filled by characters from string S2.
41 | If string S1 is shorter than string S2 then prepend enough
42 | characters from to beginning of S2 to the beginning of a copy of
43 | S2 to make their length equal, and return the filled copy."
44 | (if (>= (length s1) (length s2)) s1
45 | (concat (substring s2 0 (- (length s2) (length s1))) s1)))
46 |
47 | (defun citeproc-s-fill-left-to-len (s len &optional char)
48 | "Fill string S to length LEN with CHAR from left."
49 | (let ((len-s (length s))
50 | (char (or char ?0)))
51 | (if (>= len-s len) s
52 | (concat (make-string (- len len-s) char) s))))
53 |
54 | (defun citeproc-s-nil-or-s-to-num (s)
55 | "Convert S, which is a string or nil to a number.
56 | A nil value is converted to 0."
57 | (if s (string-to-number s) 0))
58 |
59 | (defun citeproc-s-from-num-or-s (x)
60 | "Return the content of string or number X as a number."
61 | (if (numberp x) (number-to-string x) x))
62 |
63 | (defun citeproc-s-content (s)
64 | "Return the string content of string or symbol or nil S.
65 | The string content of nil is defined as \"\"."
66 | (pcase s
67 | ((\` nil) "")
68 | ((pred symbolp) (symbol-name s))
69 | (_ s)))
70 |
71 | (defun citeproc-s-slice-by-matches (s regexp &optional start annot)
72 | "Slice S up at the boundaries of each REGEXP match.
73 | Optionally start from index START. Matches are also included
74 | among the slices, but all zero-length slices are omitted. If
75 | optional ANNOT is non-nil then slices are given as (S . B) cons
76 | cells where S is the slice string, while B is nil if the S slice
77 | is a separating REGEXP match and t otherwise."
78 | (unless start (setq start 0))
79 | (save-match-data
80 | (let ((begin (string-match regexp s start)))
81 | (if begin
82 | (let ((end (match-end 0)))
83 | (if (and (= begin start) (= end start))
84 | (citeproc-s-slice-by-matches s regexp (1+ start) annot)
85 | (let ((result (citeproc-s-slice-by-matches (substring s end)
86 | regexp 0 annot)))
87 | (unless (= begin end)
88 | (let ((slice (substring s begin end)))
89 | (push (if annot (list slice) slice) result)))
90 | (unless (= 0 begin)
91 | (let ((slice (substring s 0 begin)))
92 | (push (if annot (cons slice t) slice) result)))
93 | result)))
94 | (list (if annot (cons s t) s))))))
95 |
96 | (defun citeproc-s-tail (s length)
97 | "Return the closing substring of string S with length LENGTH.
98 | Return S if LENGTH is nil or not less than the length of S."
99 | (let ((l (length s)))
100 | (if (and length (< length l))
101 | (substring s (- l length))
102 | s)))
103 |
104 | (defun citeproc-s-capitalize-first (s)
105 | "Capitalize the first word in string S.
106 | Return the capitalized version of S. If S contains no word or the
107 | first word is not in lowercase then return S."
108 | (if (s-present-p s)
109 | (with-temp-buffer
110 | (insert s)
111 | (goto-char 1)
112 | (forward-word)
113 | (backward-word)
114 | (let ((word (word-at-point)))
115 | (when (s-lowercase-p word)
116 | (capitalize-word 1)))
117 | (buffer-string))
118 | s))
119 |
120 | (defun citeproc-s-capitalize-all (s)
121 | "Capitalize all lowercase words in string S.
122 | Return the capitalized version of S. If S contains no word or the
123 | first word is not in lowercase then return S."
124 | (if (s-present-p s)
125 | (with-temp-buffer
126 | (insert s)
127 | (goto-char 1)
128 | (while (forward-word)
129 | (let ((word (word-at-point)))
130 | (when (s-lowercase-p word)
131 | (capitalize-word -1))))
132 | (buffer-string))
133 | s))
134 |
135 | (defun citeproc-s-sentence-case (s)
136 | "Return a sentence-cased version of string S."
137 | (if (s-present-p s)
138 | (with-temp-buffer
139 | (insert s)
140 | (goto-char 1)
141 | (let ((first t))
142 | (while (forward-word)
143 | (let ((word (word-at-point)))
144 | (cond ((s-uppercase-p word) (capitalize-word -1))
145 | ((and first (s-lowercase-p word)) (capitalize-word -1))))
146 | (when first (setq first nil))))
147 | (buffer-string))
148 | s))
149 |
150 | (defun citeproc-s-sentence-case-title (s &optional omit-nocase)
151 | "Return a sentence-cased version of title string S.
152 | If optional OMIT-NOCASE is non-nil then omit the nocase tags from the output."
153 | (if (s-blank-p s) s
154 | (let ((sliced (citeproc-s-slice-by-matches
155 | s "\\(\\|\\|: +[\"'“‘]*[[:alpha:]]\\)"))
156 | (protect-level 0)
157 | (first t)
158 | result)
159 | (dolist (slice sliced)
160 | (push
161 | (pcase slice
162 | ("" (cl-incf protect-level) (if omit-nocase nil slice))
163 | ("" (cl-decf protect-level) (if omit-nocase nil slice))
164 | ;; Don't touch the first letter after a colon since it probably
165 | ;; starts a subtitle.
166 | ((pred (string-match-p "^: +[\"'“‘]*[[:alpha:]]")) (setq first nil) slice)
167 | (_ (cond ((< 0 protect-level) (setq first nil) slice)
168 | ((not first) (downcase slice))
169 | (t (setq first nil)
170 | ;; We upcase the first letter and downcase the rest.
171 | (let ((pos (string-match "[[:alpha:]]" slice)))
172 | (if pos (concat (substring slice 0 pos)
173 | (upcase (substring slice pos (1+ pos)))
174 | (downcase (substring slice (1+ pos))))
175 | slice))))))
176 | result))
177 | (apply #'concat (nreverse result)))))
178 |
179 | (defconst citeproc-s-english-stopwords
180 | '("a" "according to" "across" "afore" "after" "against" "ahead of" "along" "alongside"
181 | "amid" "amidst" "among" "amongst" "an" "and" "anenst" "apart from" "apropos"
182 | "around" "as" "as regards" "aside" "astride" "at" "athwart" "atop" "back to"
183 | "barring" "because of" "before" "behind" "below" "beneath" "beside" "besides"
184 | "between" "beyond" "but" "by" "c" "ca" "circa" "close to" "d'" "de" "despite" "down"
185 | "due to" "during" "et" "except" "far from" "for" "forenenst" "from" "given" "in"
186 | "inside" "instead of" "into" "lest" "like" "modulo" "near" "next" "nor" "of" "off"
187 | "on" "onto" "or" "out" "outside of" "over" "per" "plus" "prior to" "pro" "pursuant
188 | to" "qua" "rather than" "regardless of" "sans" "since" "so" "such as" "than"
189 | "that of" "the" "through" "throughout" "thru" "thruout" "till" "to" "toward" "towards"
190 | "under" "underneath" "until" "unto" "up" "upon" "v." "van" "versus" "via" "vis-à-vis"
191 | "von" "vs." "where as" "with" "within" "without" "yet"))
192 |
193 | (defun citeproc-s-title-case (s)
194 | "Return a title-cased version of string S."
195 | (if (s-present-p s)
196 | (with-temp-buffer
197 | (insert s)
198 | (goto-char 1)
199 | (let ((first t)
200 | after-colon)
201 | (while (forward-word)
202 | (let ((word (word-at-point)))
203 | (cond ((and (not (or first after-colon))
204 | (member (downcase word) citeproc-s-english-stopwords)
205 | ;; Don't downcase A before a period:
206 | (or (not (string= word "A"))
207 | (= (point) (point-max))
208 | (/= (char-after) ?.)))
209 | (downcase-word -1))
210 | ((s-lowercase-p word)
211 | (capitalize-word -1))))
212 | (when first (setq first nil))
213 | (when (< (point) (point-max))
214 | (setq after-colon (or (= (char-after) ?:)
215 | (= (char-after) ?.))))))
216 | (buffer-string))
217 | s))
218 |
219 | (defun citeproc-s-smart-quotes (s oq cq)
220 | "Replace dumb quotes in string S with smart ones OQ and CQ.
221 | OQ is the opening quote, CQ is the closing quote to use."
222 | (with-temp-buffer
223 | (insert s)
224 | (goto-char 1)
225 | (while (search-forward "\"" nil 1)
226 | (let ((w-a-p (word-at-point)))
227 | (delete-char -1)
228 | (insert (if w-a-p oq cq))))
229 | (buffer-string)))
230 |
231 | (defun citeproc-s-replace-all-seq (s replacements)
232 | "Make replacements in S according to REPLACEMENTS sequentially.
233 | REPLACEMENTS is an alist with (FROM . TO) elements."
234 | (let ((result s))
235 | (pcase-dolist (`(,from . ,to) replacements)
236 | (setq result (string-replace from to result)))
237 | result))
238 |
239 | (defun citeproc-s-replace-all-sim (s regex replacements)
240 | "Replace all matches of REGEX in S according to REPLACEMENTS simultaneously.
241 | REPLACEMENTS is an alist with (FROM . TO) elements."
242 | (replace-regexp-in-string regex
243 | (lambda (match) (cdr (assoc-string match replacements)))
244 | s t t))
245 |
246 | (defun citeproc-s-smart-apostrophes (s)
247 | "Replace dumb apostophes in string S with smart ones.
248 | The replacement character used is the unicode character `modifier
249 | letter apostrophe'."
250 | (string-replace "'" "ʼ" (string-replace "’" "ʼ" s)))
251 |
252 | (defconst citeproc-s--cull-spaces-alist
253 | '((" " . " ") (";;" . ";") ("..." . ".") (",," . ",") (".." . "."))
254 | "Alist describing replacements for space and punct culling.")
255 |
256 | (defconst citeproc-s--cull-spaces-alist-rx
257 | (regexp-opt (mapcar #'car citeproc-s--cull-spaces-alist)))
258 |
259 | (defun citeproc-s-cull-spaces-puncts (s)
260 | "Replace unnecessary characters with delete chars in string S."
261 | (let ((result (citeproc-s-replace-all-seq s citeproc-s--cull-spaces-alist)))
262 | (dolist (match-rep '(("\\([:;!?]\\):" . "\\1")
263 | ("\\([:.;!?]\\)\\." . "\\1")
264 | ("\\([:;!]\\)!" . "!")
265 | ("\\([:;?]\\)\\?" . "?")
266 | ("\\.\\([”’‹›«»]\\)\\." . ".\\1")
267 | (",\\([”’‹›«»]\\)," . ",\\1"))
268 | result)
269 | (setq result (replace-regexp-in-string (car match-rep)
270 | (cdr match-rep)
271 | result)))))
272 |
273 | (provide 'citeproc-s)
274 |
275 | ;;; citeproc-s.el ends here
276 |
--------------------------------------------------------------------------------
/test/expected_fails.lst:
--------------------------------------------------------------------------------
1 | citeproc-suite-affix-comma-after-quote
2 | citeproc-suite-affix-moving-punctuation
3 | citeproc-suite-affix-space-with-quotes
4 | citeproc-suite-affix-with-commas
5 | citeproc-suite-bugreports-automatically-delete-items-fails
6 | citeproc-suite-bugreports-caps-after-one-word-prefix
7 | citeproc-suite-bugreports-chicago-author-date-looping
8 | citeproc-suite-bugreports-creeping-add-names
9 | citeproc-suite-bugreports-demo-page-full-cite-cruft-on-subsequent
10 | citeproc-suite-bugreports-env-and-urb
11 | citeproc-suite-bugreports-french-apostrophe
12 | citeproc-suite-bugreports-ikey-one
13 | citeproc-suite-bugreports-move-punctuation-inside-quotes-for-locator
14 | citeproc-suite-bugreports-no-case-escape
15 | citeproc-suite-bugreports-no-title
16 | citeproc-suite-bugreports-number-affix-escape
17 | citeproc-suite-bugreports-number-in-macro-with-vertical-align
18 | citeproc-suite-bugreports-overwrite-citation-items
19 | citeproc-suite-bugreports-parse-name
20 | citeproc-suite-bugreports-single-quote-xml
21 | citeproc-suite-bugreports-small-caps-escape
22 | citeproc-suite-collapse-author-collapse-no-date-sorted
23 | citeproc-suite-collapse-chicago-after-collapse
24 | citeproc-suite-collapse-citation-number-ranges-insert
25 | citeproc-suite-date-date-no-date-no-test
26 | citeproc-suite-date-empty-strings
27 | citeproc-suite-date-in-press
28 | citeproc-suite-date-other-alone
29 | citeproc-suite-date-other-with-date
30 | citeproc-suite-date-range-delimiter
31 | citeproc-suite-date-season-range1
32 | citeproc-suite-date-season-range2
33 | citeproc-suite-date-season-range3
34 | citeproc-suite-date-season-substitute-in-group
35 | citeproc-suite-date-string
36 | citeproc-suite-date-text-form-yeardate-year-range-open
37 | citeproc-suite-date-various-invalid-dates
38 | citeproc-suite-date-year-suffix-implicit-with-no-date
39 | citeproc-suite-date-year-suffix-with-no-date
40 | citeproc-suite-decorations-nested-quotes-inner-reverse
41 | citeproc-suite-decorations-no-normal-without-decoration
42 | citeproc-suite-decorations-simple-flip-flop
43 | citeproc-suite-disambiguate-all-names-generally
44 | citeproc-suite-disambiguate-all-names-simple-sequence
45 | citeproc-suite-disambiguate-all-names-with-initials-generally
46 | citeproc-suite-disambiguate-based-on-subsequent-form-with-backref2
47 | citeproc-suite-disambiguate-by-cite-incremental2
48 | citeproc-suite-disambiguate-citation-label-default
49 | citeproc-suite-disambiguate-citation-label-in-data
50 | citeproc-suite-disambiguate-disambiguation-hang
51 | citeproc-suite-disambiguate-incremental-extra-text
52 | citeproc-suite-disambiguate-initialize-with-but-no-disambiguation
53 | citeproc-suite-disambiguate-primary-name-generally
54 | citeproc-suite-disambiguate-primary-name-with-initials-limited-to-primary
55 | citeproc-suite-disambiguate-to-initial-only
56 | citeproc-suite-disambiguate-trigraph
57 | citeproc-suite-disambiguate-year-collapse-with-institution
58 | citeproc-suite-disambiguate-year-suffix-fifty-two-entries
59 | citeproc-suite-disambiguate-year-suffix-fifty-two-entries-by-cite
60 | citeproc-suite-disambiguate-year-suffix-with-et-al-subsequent
61 | citeproc-suite-display-author-as-heading
62 | citeproc-suite-etal-use-zero-first
63 | citeproc-suite-flipflop-apostrophes
64 | citeproc-suite-flipflop-boldface-node-level-markup
65 | citeproc-suite-flipflop-complete-cite-in-prefix
66 | citeproc-suite-flipflop-italics-flipped
67 | citeproc-suite-flipflop-italics-simple
68 | citeproc-suite-flipflop-italics-with-ok
69 | citeproc-suite-flipflop-italics-with-ok-and-textcase
70 | citeproc-suite-flipflop-leading-single-quote
71 | citeproc-suite-flipflop-orphan-quote
72 | citeproc-suite-flipflop-quotes-in-field-not-on-node
73 | citeproc-suite-flipflop-quotes-node-level-markup
74 | citeproc-suite-flipflop-single-before-colon
75 | citeproc-suite-flipflop-small-caps
76 | citeproc-suite-fullstyles-a-bd-nt
77 | citeproc-suite-fullstyles-chicago-author-date-simple
78 | citeproc-suite-integration-delete-name
79 | citeproc-suite-integration-disambiguate-add-givenname1
80 | citeproc-suite-integration-disambiguate-add-givenname2
81 | citeproc-suite-integration-duplicate-item
82 | citeproc-suite-integration-duplicate-item2
83 | citeproc-suite-integration-first-reference-note-number-position-change
84 | citeproc-suite-integration-ibid-on-insert
85 | citeproc-suite-integration-year-suffix-on-off-on
86 | citeproc-suite-label-collapsed-page-number-plural-detection
87 | citeproc-suite-label-editor-translator1
88 | citeproc-suite-label-editor-translator2
89 | citeproc-suite-label-name-label-through-substitute
90 | citeproc-suite-label-plural-with-localized-ampersand
91 | citeproc-suite-locale-empty-plus-override-date
92 | citeproc-suite-locale-non-existent-locale-def
93 | citeproc-suite-locale-overload-with-empty-string
94 | citeproc-suite-locator-simple-locators
95 | citeproc-suite-locator-tricky-entry-for-plurals
96 | citeproc-suite-locator-with-leading-space
97 | citeproc-suite-magic-capitalize-first-occurring-term
98 | citeproc-suite-magic-citation-label-in-bibliography
99 | citeproc-suite-magic-citation-label-in-citation
100 | citeproc-suite-magic-name-suffix-no-comma
101 | citeproc-suite-magic-name-suffix-with-comma
102 | citeproc-suite-magic-punctuation-in-quote-nested
103 | citeproc-suite-magic-superscript-chars
104 | citeproc-suite-magic-suppress-layout-delimiter-if-prefix-comma
105 | citeproc-suite-magic-term-capitalization-with-prefix
106 | citeproc-suite-name-articular-name-as-sort-order
107 | citeproc-suite-name-articular-with-comma
108 | citeproc-suite-name-articular-with-comma-name-as-sort-order
109 | citeproc-suite-name-asian-glyphs
110 | citeproc-suite-name-celts-and-toffs-crowded-initials
111 | citeproc-suite-name-celts-and-toffs-spaced-initials
112 | citeproc-suite-name-cite-group-delimiter-with-year-suffix-collapse
113 | citeproc-suite-name-cite-group-delimiter-with-year-suffix-collapse2
114 | citeproc-suite-name-cite-group-delimiter-with-year-suffix-collapse3
115 | citeproc-suite-name-delimiter-after-inverted
116 | citeproc-suite-name-editor-translator-same-empty-term
117 | citeproc-suite-name-et-al-with-combined
118 | citeproc-suite-name-hebrew-and
119 | citeproc-suite-name-hyphenated-non-dropping-particle1
120 | citeproc-suite-name-hyphenated-non-dropping-particle2
121 | citeproc-suite-name-in-text-markup-initialize
122 | citeproc-suite-name-in-text-markup-normalize-initials
123 | citeproc-suite-name-initials-initialize-false
124 | citeproc-suite-name-initials-initialize-false-empty
125 | citeproc-suite-name-initials-initialize-false-period
126 | citeproc-suite-name-initials-initialize-false-period-space
127 | citeproc-suite-name-initials-initialize-true
128 | citeproc-suite-name-initials-initialize-true-empty
129 | citeproc-suite-name-initials-initialize-true-period
130 | citeproc-suite-name-initials-initialize-true-period-space
131 | citeproc-suite-name-long-abbreviation
132 | citeproc-suite-name-lowercase-surname-suffix
133 | citeproc-suite-name-namepart-affixes
134 | citeproc-suite-name-namepart-affixes-name-as-sort-order
135 | citeproc-suite-name-namepart-affixes-name-as-sort-order-demote-non-dropping-particle
136 | citeproc-suite-name-only-givenname
137 | citeproc-suite-name-parse-names
138 | citeproc-suite-name-parsed-dropping-particle-with-apostrophe
139 | citeproc-suite-name-parsed-non-dropping-particle-with-apostrophe
140 | citeproc-suite-name-particle-caps3
141 | citeproc-suite-name-particles-demote-non-dropping-never
142 | citeproc-suite-name-split-initials
143 | citeproc-suite-name-subsequent-author-substitute-single-field
144 | citeproc-suite-name-substitute-on-names-span-group-span-fail
145 | citeproc-suite-name-substitute-on-names-span-names-span-fail
146 | citeproc-suite-name-substitute-partial-each
147 | citeproc-suite-name-with-non-breaking-space
148 | citeproc-suite-nameorder-long-name-as-sort-demote-display-and-sort
149 | citeproc-suite-nameorder-long-name-as-sort-demote-never
150 | citeproc-suite-number-limit-ordinals-to-day-one
151 | citeproc-suite-number-new-ordinals-edition
152 | citeproc-suite-number-new-ordinals-with-gender-change
153 | citeproc-suite-number-ordinal-spacing
154 | citeproc-suite-number-plain-hyphen-or-en-dash-always-plural
155 | citeproc-suite-number-separate-ordinal-namespaces
156 | citeproc-suite-page-chicago16
157 | citeproc-suite-position-first-true-only-once
158 | citeproc-suite-position-ibid-in-text
159 | citeproc-suite-position-ibid-with-locator
160 | citeproc-suite-position-ibid-with-multiple-solo-cites-in-backref
161 | citeproc-suite-position-ibid-with-prefix-full-stop
162 | citeproc-suite-position-if-ibid-with-locator-is-true-then-ibid-is-true
163 | citeproc-suite-position-near-note-false
164 | citeproc-suite-position-reset-note-numbers
165 | citeproc-suite-punctuation-french-orthography
166 | citeproc-suite-punctuation-full-monty-quotes-in
167 | citeproc-suite-quotes-punctuation-with-inner-quote
168 | citeproc-suite-sort-bibliography-citation-number-descending-via-composite-macro
169 | citeproc-suite-sort-bibliography-citation-number-descending-via-macro
170 | citeproc-suite-sort-case-insensitive-bibliography
171 | citeproc-suite-sort-case-insensitive-citation
172 | citeproc-suite-sort-citation-number-primary-descending-via-macro-bibliography
173 | citeproc-suite-sort-citation-number-primary-descending-via-macro-citation
174 | citeproc-suite-sort-citation-number-primary-descending-via-variable-bibliography
175 | citeproc-suite-sort-citation-number-primary-descending-via-variable-citation
176 | citeproc-suite-sort-conditional-macro-dates
177 | citeproc-suite-sort-drop-name-label-in-sort
178 | citeproc-suite-sort-family-only
179 | citeproc-suite-sort-leading-a
180 | citeproc-suite-sort-leading-apostrophe-on-name-particle
181 | citeproc-suite-sort-name-variable
182 | citeproc-suite-sort-omitted-bib-ref-mixed-numeric-style
183 | citeproc-suite-sort-omitted-bib-ref-non-numeric-style
184 | citeproc-suite-sort-quotes
185 | citeproc-suite-sort-range-unaffected
186 | citeproc-suite-sort-separate-authors-and-others
187 | citeproc-suite-sort-with-and-in-one-entry
188 | citeproc-suite-substitute-substitute-only-once-term
189 | citeproc-suite-substitute-substitute-only-once-term-empty
190 | citeproc-suite-substitute-suppress-ordinary-variable
191 | citeproc-suite-testers-first-auto-generated-zotero-plugin-test
192 | citeproc-suite-testers-second-auto-generated-zotero-plugin-test
193 | citeproc-suite-textcase-implicit-nocase
194 | citeproc-suite-textcase-in-quotes
195 | citeproc-suite-textcase-last-char
196 | citeproc-suite-textcase-locale-unicode
197 | citeproc-suite-textcase-no-space-before-apostrophe
198 | citeproc-suite-textcase-non-english-chars
199 | citeproc-suite-textcase-repeated-title-bug
200 | citeproc-suite-textcase-sentence-capitalization
201 | citeproc-suite-textcase-skip-name-particles-in-title-case
202 | citeproc-suite-textcase-stop-word-before-hyphen
203 | citeproc-suite-variables-container-title-short
204 | citeproc-suite-variables-container-title-short2
205 | citeproc-suite-variables-title-short-on-short-title-no-title-condition
206 | citeproc-suite-bugreports-sorted-ieee-italics-fail
207 | citeproc-suite-bugreports-undefined-in-name3
208 | citeproc-suite-date-negative-date-sort
209 | citeproc-suite-date-negative-date-sort-via-macro-on-year-month-only
210 | citeproc-suite-magic-subsequent-author-substitute-not-fooled
211 | citeproc-suite-punctuation-delimiter-with-strip-periods-and-substitute3
212 | citeproc-suite-bugreports-sorted-ieee-italics-fail
213 | citeproc-suite-bugreports-undefined-in-name3
214 | citeproc-suite-date-negative-date-sort
215 | citeproc-suite-date-negative-date-sort-via-macro-on-year-month-only
216 | citeproc-suite-magic-subsequent-author-substitute-not-fooled
217 | citeproc-suite-punctuation-delimiter-with-strip-periods-and-substitute3
218 |
--------------------------------------------------------------------------------