diff options
author | Norbert Preining <norbert@preining.info> | 2021-05-23 03:00:39 +0000 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2021-05-23 03:00:39 +0000 |
commit | f1261b349e875b842745b63258c3e338cb1fe3bf (patch) | |
tree | b5d402b3e80818cde2c079a42249f3dcb9732247 /support/texlab/src/citeproc | |
parent | 58aa1ac09b1d9e4769d0a0661cf12e2b2db41b14 (diff) |
CTAN sync 202105230300
Diffstat (limited to 'support/texlab/src/citeproc')
-rw-r--r-- | support/texlab/src/citeproc/apa.csl | 1526 | ||||
-rw-r--r-- | support/texlab/src/citeproc/bibutils.rs | 188 | ||||
-rw-r--r-- | support/texlab/src/citeproc/mod.rs | 213 | ||||
-rw-r--r-- | support/texlab/src/citeproc/name/mod.rs | 278 | ||||
-rw-r--r-- | support/texlab/src/citeproc/name/parser.lalrpop | 150 | ||||
-rw-r--r-- | support/texlab/src/citeproc/ris.rs | 466 |
6 files changed, 0 insertions, 2821 deletions
diff --git a/support/texlab/src/citeproc/apa.csl b/support/texlab/src/citeproc/apa.csl deleted file mode 100644 index 8454246a98..0000000000 --- a/support/texlab/src/citeproc/apa.csl +++ /dev/null @@ -1,1526 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<style xmlns="http://purl.org/net/xbiblio/csl" class="in-text" version="1.0" demote-non-dropping-particle="never" page-range-format="expanded"> - <info> - <title>American Psychological Association 6th edition</title> - <title-short>APA</title-short> - <id>http://www.zotero.org/styles/apa</id> - <link href="http://www.zotero.org/styles/apa" rel="self"/> - <link href="http://owl.english.purdue.edu/owl/resource/560/01/" rel="documentation"/> - <author> - <name>Simon Kornblith</name> - <email>simon@simonster.com</email> - </author> - <author> - <name> Brenton M. Wiernik</name> - <email>zotero@wiernik.org</email> - </author> - <contributor> - <name>Bruce D'Arcus</name> - </contributor> - <contributor> - <name>Curtis M. Humphrey</name> - </contributor> - <contributor> - <name>Richard Karnesky</name> - <email>karnesky+zotero@gmail.com</email> - <uri>http://arc.nucapt.northwestern.edu/Richard_Karnesky</uri> - </contributor> - <contributor> - <name>Sebastian Karcher</name> - </contributor> - <category citation-format="author-date"/> - <category field="psychology"/> - <category field="generic-base"/> - <updated>2016-09-28T13:09:49+00:00</updated> - <rights license="http://creativecommons.org/licenses/by-sa/3.0/">This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 License</rights> - </info> - <locale xml:lang="en"> - <terms> - <term name="editortranslator" form="short"> - <single>ed. & trans.</single> - <multiple>eds. & trans.</multiple> - </term> - <term name="translator" form="short">trans.</term> - <term name="interviewer" form="short">interviewer</term> - <term name="circa" form="short">ca.</term> - <term name="collection-editor" form="short">series ed.</term> - </terms> - </locale> - <locale xml:lang="es"> - <terms> - <term name="from">de</term> - </terms> - </locale> - <locale xml:lang="de"> - <terms> - <term name="et-al">et al.</term> - </terms> - </locale> - <locale xml:lang="da"> - <terms> - <term name="et-al">et al.</term> - </terms> - </locale> - <locale xml:lang="nn"> - <terms> - <term name="et-al">et al.</term> - </terms> - </locale> - <locale xml:lang="nb"> - <terms> - <term name="et-al">et al.</term> - </terms> - </locale> - <macro name="container-contributors-booklike"> - <choose> - <if variable="container-title"> - <names variable="editor translator" delimiter=", & "> - <name and="symbol" initialize-with=". " delimiter=", "/> - <label form="short" prefix=" (" text-case="title" suffix=")"/> - <substitute> - <names variable="editorial-director"/> - <names variable="collection-editor"/> - <names variable="container-author"/> - </substitute> - </names> - </if> - </choose> - </macro> - <macro name="container-contributors"> - <choose> - <!-- book is here to catch software with container titles --> - <if type="book broadcast chapter entry entry-dictionary entry-encyclopedia graphic map personal_communication report speech" match="any"> - <text macro="container-contributors-booklike"/> - </if> - <else-if type="paper-conference"> - <choose> - <if variable="collection-editor container-author editor" match="any"> - <text macro="container-contributors-booklike"/> - </if> - </choose> - </else-if> - </choose> - </macro> - <macro name="secondary-contributors-booklike"> - <group delimiter="; "> - <choose> - <if variable="title"> - <names variable="interviewer"> - <name and="symbol" initialize-with=". " delimiter=", "/> - <label form="short" prefix=", " text-case="title"/> - </names> - </if> - </choose> - <choose> - <if variable="container-title" match="none"> - <group delimiter="; "> - <names variable="container-author"> - <label form="verb-short" suffix=" " text-case="title"/> - <name and="symbol" initialize-with=". " delimiter=", "/> - </names> - <names variable="editor translator" delimiter="; "> - <name and="symbol" initialize-with=". " delimiter=", "/> - <label form="short" prefix=", " text-case="title"/> - </names> - </group> - </if> - </choose> - </group> - </macro> - <macro name="secondary-contributors"> - <choose> - <!-- book is here to catch software with container titles --> - <if type="book broadcast chapter entry entry-dictionary entry-encyclopedia graphic map report" match="any"> - <text macro="secondary-contributors-booklike"/> - </if> - <else-if type="personal_communication"> - <group delimiter="; "> - <group delimiter=" "> - <choose> - <if variable="genre" match="any"> - <text variable="genre" text-case="capitalize-first"/> - </if> - <else> - <text term="letter" text-case="capitalize-first"/> - </else> - </choose> - <names variable="recipient" delimiter=", "> - <label form="verb" suffix=" "/> - <name and="symbol" delimiter=", "/> - </names> - </group> - <text variable="medium" text-case="capitalize-first"/> - <choose> - <if variable="container-title" match="none"> - <names variable="editor translator" delimiter="; "> - <name and="symbol" initialize-with=". " delimiter=", "/> - <label form="short" prefix=", " text-case="title"/> - </names> - </if> - </choose> - </group> - </else-if> - <else-if type="song"> - <choose> - <if variable="original-author composer" match="any"> - <group delimiter="; "> - <!-- Replace prefix with performer label as that becomes available --> - <names variable="author" prefix="Recorded by "> - <label form="verb" text-case="title"/> - <name and="symbol" initialize-with=". " delimiter=", "/> - </names> - <names variable="translator"> - <name and="symbol" initialize-with=". " delimiter=", "/> - <label form="short" prefix=", " text-case="title"/> - </names> - </group> - </if> - </choose> - </else-if> - <else-if type="article-journal article-magazine article-newspaper" match="any"> - <group delimiter="; "> - <choose> - <if variable="title"> - <names variable="interviewer" delimiter="; "> - <name and="symbol" initialize-with=". " delimiter=", "/> - <label form="short" prefix=", " text-case="title"/> - </names> - </if> - </choose> - <names variable="translator" delimiter="; "> - <name and="symbol" initialize-with=". " delimiter=", "/> - <label form="short" prefix=", " text-case="title"/> - </names> - </group> - </else-if> - <else-if type="paper-conference"> - <choose> - <if variable="collection-editor editor" match="any"> - <text macro="secondary-contributors-booklike"/> - </if> - <else> - <group delimiter="; "> - <choose> - <if variable="title"> - <names variable="interviewer" delimiter="; "> - <name and="symbol" initialize-with=". " delimiter=", "/> - <label form="short" prefix=", " text-case="title"/> - </names> - </if> - </choose> - <names variable="translator" delimiter="; "> - <name and="symbol" initialize-with=". " delimiter=", "/> - <label form="short" prefix=", " text-case="title"/> - </names> - </group> - </else> - </choose> - </else-if> - <else> - <group delimiter="; "> - <choose> - <if variable="title"> - <names variable="interviewer"> - <name and="symbol" initialize-with=". " delimiter="; "/> - <label form="short" prefix=", " text-case="title"/> - </names> - </if> - </choose> - <names variable="editor translator" delimiter="; "> - <name and="symbol" initialize-with=". " delimiter=", "/> - <label form="short" prefix=", " text-case="title"/> - </names> - </group> - </else> - </choose> - </macro> - <macro name="author"> - <choose> - <if type="song"> - <names variable="composer" delimiter=", "> - <name name-as-sort-order="all" and="symbol" sort-separator=", " initialize-with=". " delimiter=", " delimiter-precedes-last="always"/> - <substitute> - <names variable="original-author"/> - <names variable="author"/> - <names variable="translator"> - <name name-as-sort-order="all" and="symbol" sort-separator=", " initialize-with=". " delimiter=", " delimiter-precedes-last="always"/> - <label form="short" prefix=" (" suffix=")" text-case="title"/> - </names> - <group delimiter=" "> - <text macro="title"/> - <text macro="description"/> - <text macro="format"/> - </group> - </substitute> - </names> - </if> - <else-if type="treaty"/> - <else> - <names variable="author" delimiter=", "> - <name name-as-sort-order="all" and="symbol" sort-separator=", " initialize-with=". " delimiter=", " delimiter-precedes-last="always"/> - <substitute> - <names variable="illustrator"/> - <names variable="composer"/> - <names variable="director"> - <name name-as-sort-order="all" and="symbol" sort-separator=", " initialize-with=". " delimiter=", " delimiter-precedes-last="always"/> - <label form="long" prefix=" (" suffix=")" text-case="title"/> - </names> - <choose> - <if variable="container-title"> - <choose> - <if type="book entry entry-dictionary entry-encyclopedia"> - <text macro="title"/> - </if> - <else> - <names variable="translator"/> - </else> - </choose> - <names variable="translator"> - <name name-as-sort-order="all" and="symbol" sort-separator=", " initialize-with=". " delimiter=", " delimiter-precedes-last="always"/> - <label form="short" prefix=" (" suffix=")" text-case="title"/> - </names> - </if> - </choose> - <names variable="editor translator" delimiter=", "> - <name name-as-sort-order="all" and="symbol" sort-separator=", " initialize-with=". " delimiter=", " delimiter-precedes-last="always"/> - <label form="short" prefix=" (" suffix=")" text-case="title"/> - </names> - <names variable="editorial-director"> - <name name-as-sort-order="all" and="symbol" sort-separator=", " initialize-with=". " delimiter=", " delimiter-precedes-last="always"/> - <label form="short" prefix=" (" suffix=")" text-case="title"/> - </names> - <names variable="collection-editor"> - <name name-as-sort-order="all" and="symbol" sort-separator=", " initialize-with=". " delimiter=", " delimiter-precedes-last="always"/> - <label form="short" prefix=" (" suffix=")" text-case="title"/> - </names> - <choose> - <if type="report"> - <text variable="publisher"/> - </if> - </choose> - <group delimiter=" "> - <text macro="title"/> - <text macro="description"/> - <text macro="format"/> - </group> - </substitute> - </names> - </else> - </choose> - </macro> - <macro name="author-short"> - <choose> - <if type="patent" variable="number" match="all"> - <text macro="patent-number"/> - </if> - <else-if type="treaty"> - <text variable="title" form="short"/> - </else-if> - <else-if type="personal_communication"> - <choose> - <if variable="archive DOI publisher URL" match="none"> - <group delimiter=", "> - <names variable="author"> - <name and="symbol" delimiter=", " initialize-with=". "/> - <substitute> - <text variable="title" form="short" quotes="true"/> - </substitute> - </names> - <!-- This should be localized --> - <text value="personal communication"/> - </group> - </if> - <else> - <names variable="author" delimiter=", "> - <name form="short" and="symbol" delimiter=", " initialize-with=". "/> - <substitute> - <names variable="editor"/> - <names variable="translator"/> - <choose> - <if variable="container-title"> - <text variable="title" form="short" quotes="true"/> - </if> - <else> - <text variable="title" form="short" font-style="italic"/> - </else> - </choose> - <text macro="format-short" prefix="[" suffix="]"/> - </substitute> - </names> - </else> - </choose> - </else-if> - <else-if type="song"> - <names variable="composer" delimiter=", "> - <name form="short" and="symbol" delimiter=", " initialize-with=". "/> - <substitute> - <names variable="original-author"/> - <names variable="author"/> - <names variable="translator"/> - <choose> - <if variable="container-title"> - <text variable="title" form="short" quotes="true"/> - </if> - <else> - <text variable="title" form="short" font-style="italic"/> - </else> - </choose> - <text macro="format-short" prefix="[" suffix="]"/> - </substitute> - </names> - </else-if> - <else> - <names variable="author" delimiter=", "> - <name form="short" and="symbol" delimiter=", " initialize-with=". "/> - <substitute> - <names variable="illustrator"/> - <names variable="composer"/> - <names variable="director"/> - <choose> - <if variable="container-title"> - <choose> - <if type="book entry entry-dictionary entry-encyclopedia"> - <text variable="title" form="short" quotes="true"/> - </if> - <else> - <names variable="translator"/> - </else> - </choose> - </if> - </choose> - <names variable="editor"/> - <names variable="editorial-director"/> - <names variable="translator"/> - <choose> - <if type="report" variable="publisher" match="all"> - <text variable="publisher"/> - </if> - <else-if type="legal_case"> - <text variable="title" font-style="italic"/> - </else-if> - <else-if type="bill legislation" match="any"> - <text variable="title" form="short"/> - </else-if> - <else-if variable="reviewed-author" type="review review-book" match="any"> - <text macro="format-short" prefix="[" suffix="]"/> - </else-if> - <else-if type="post post-weblog webpage" variable="container-title" match="any"> - <text variable="title" form="short" quotes="true"/> - </else-if> - <else> - <text variable="title" form="short" font-style="italic"/> - </else> - </choose> - <text macro="format-short" prefix="[" suffix="]"/> - </substitute> - </names> - </else> - </choose> - </macro> - <macro name="patent-number"> - <!-- authority: U.S. ; genre: patent ; number: 123,445 --> - <group delimiter=" "> - <text variable="authority"/> - <choose> - <if variable="genre"> - <text variable="genre" text-case="capitalize-first"/> - </if> - <else> - <!-- This should be localized --> - <text value="patent" text-case="capitalize-first"/> - </else> - </choose> - <group delimiter=" "> - <text term="issue" form="short" text-case="capitalize-first"/> - <text variable="number"/> - </group> - </group> - </macro> - <macro name="access"> - <choose> - <if type="bill legal_case legislation" match="any"/> - <else-if variable="DOI" match="any"> - <text variable="DOI" prefix="https://doi.org/"/> - </else-if> - <else-if variable="URL"> - <group delimiter=" "> - <text term="retrieved" text-case="capitalize-first"/> - <choose> - <if type="post post-weblog webpage" match="any"> - <date variable="accessed" form="text" suffix=","/> - </if> - </choose> - <text term="from"/> - <choose> - <if type="report"> - <choose> - <if variable="author editor translator" match="any"> - <!-- This should be localized --> - <text variable="publisher" suffix=" website:"/> - </if> - </choose> - </if> - <else-if type="post post-weblog webpage" match="any"> - <!-- This should be localized --> - <text variable="container-title" suffix=" website:"/> - </else-if> - </choose> - <text variable="URL"/> - </group> - </else-if> - <else-if variable="archive"> - <choose> - <if type="article article-journal article-magazine article-newspaper dataset paper-conference report speech thesis" match="any"> - <!-- This section is for electronic database locations. Physical archives for these and other item types are called in 'publisher' macro --> - <choose> - <if variable="archive-place" match="none"> - <group delimiter=" "> - <text term="retrieved" text-case="capitalize-first"/> - <text term="from"/> - <text variable="archive" suffix="."/> - <text variable="archive_location" prefix="(" suffix=")"/> - </group> - </if> - <else> - <text macro="publisher" suffix="."/> - </else> - </choose> - </if> - <else> - <text macro="publisher" suffix="."/> - </else> - </choose> - </else-if> - <else> - <text macro="publisher" suffix="."/> - </else> - </choose> - </macro> - <macro name="title"> - <choose> - <if type="treaty"> - <group delimiter=", "> - <text variable="title" text-case="title"/> - <names variable="author"> - <name initialize-with="." form="short" delimiter="-"/> - </names> - </group> - </if> - <else-if type="patent" variable="number" match="all"> - <text macro="patent-number" font-style="italic"/> - </else-if> - <else-if variable="title"> - <choose> - <if variable="version" type="book" match="all"> - <!---This is a hack until we have a software type --> - <text variable="title"/> - </if> - <else-if variable="reviewed-author reviewed-title" type="review review-book" match="any"> - <choose> - <if variable="reviewed-title"> - <choose> - <if type="post post-weblog webpage" variable="container-title" match="any"> - <text variable="title"/> - </if> - <else> - <text variable="title" font-style="italic"/> - </else> - </choose> - </if> - </choose> - </else-if> - <else-if type="post post-weblog webpage" variable="container-title" match="any"> - <text variable="title"/> - </else-if> - <else> - <text variable="title" font-style="italic"/> - </else> - </choose> - </else-if> - <else-if variable="interviewer" type="interview" match="any"> - <names variable="interviewer"> - <label form="verb-short" suffix=" " text-case="capitalize-first"/> - <name and="symbol" initialize-with=". " delimiter=", "/> - </names> - </else-if> - </choose> - </macro> - <!-- APA has four descriptive sections following the title: --> - <!-- (description), [format], container, event --> - <macro name="description"> - <group prefix="(" suffix=")"> - <choose> - <!-- book is here to catch software with container titles --> - <if type="book report" match="any"> - <choose> - <if variable="container-title"> - <text macro="secondary-contributors"/> - </if> - <else> - <group delimiter="; "> - <text macro="description-report"/> - <text macro="secondary-contributors"/> - </group> - </else> - </choose> - </if> - <else-if type="thesis"> - <group delimiter="; "> - <group delimiter=", "> - <text variable="genre" text-case="capitalize-first"/> - <choose> - <!-- In APA journals, the university of a thesis is always cited, even if another locator is given --> - <if variable="DOI URL archive" match="any"> - <text variable="publisher"/> - </if> - </choose> - </group> - <text macro="locators"/> - <text macro="secondary-contributors"/> - </group> - </else-if> - <else-if type="book interview manuscript motion_picture musical_score pamphlet post-weblog speech webpage" match="any"> - <group delimiter="; "> - <text macro="locators"/> - <text macro="secondary-contributors"/> - </group> - </else-if> - <else-if type="song"> - <choose> - <if variable="container-title" match="none"> - <text macro="locators"/> - </if> - </choose> - </else-if> - <else-if type="article dataset figure" match="any"> - <choose> - <if variable="container-title"> - <text macro="secondary-contributors"/> - </if> - <else> - <group delimiter="; "> - <text macro="locators"/> - <text macro="secondary-contributors"/> - </group> - </else> - </choose> - </else-if> - <else-if type="bill legislation legal_case patent treaty personal_communication" match="none"> - <text macro="secondary-contributors"/> - </else-if> - </choose> - </group> - </macro> - <macro name="format"> - <group prefix="[" suffix="]"> - <choose> - <if variable="reviewed-author reviewed-title" type="review review-book" match="any"> - <group delimiter=", "> - <choose> - <if variable="genre"> - <!-- Delimiting by , rather than "of" to avoid incorrect grammar --> - <group delimiter=", "> - <text variable="genre" text-case="capitalize-first"/> - <choose> - <if variable="reviewed-title"> - <text variable="reviewed-title" font-style="italic"/> - </if> - <else> - <!-- Assume `title` is title of reviewed work --> - <text variable="title" font-style="italic"/> - </else> - </choose> - </group> - </if> - <else> - <!-- This should be localized --> - <group delimiter=" "> - <text value="Review of"/> - <choose> - <if variable="reviewed-title"> - <text variable="reviewed-title" font-style="italic"/> - </if> - <else> - <!-- Assume `title` is title of reviewed work --> - <text variable="title" font-style="italic"/> - </else> - </choose> - </group> - </else> - </choose> - <names variable="reviewed-author"> - <label form="verb-short" suffix=" "/> - <name and="symbol" initialize-with=". " delimiter=", "/> - </names> - </group> - </if> - <else> - <text macro="format-short"/> - </else> - </choose> - </group> - </macro> - <macro name="format-short"> - <choose> - <if variable="reviewed-author reviewed-title" type="review review-book" match="any"> - <choose> - <if variable="reviewed-title" match="none"> - <choose> - <if variable="genre"> - <!-- Delimiting by , rather than "of" to avoid incorrect grammar --> - <group delimiter=", "> - <text variable="genre" text-case="capitalize-first"/> - <text variable="title" form="short" font-style="italic"/> - </group> - </if> - <else> - <!-- This should be localized --> - <group delimiter=" "> - <text value="Review of"/> - <text variable="title" form="short" font-style="italic"/> - </group> - </else> - </choose> - </if> - <else> - <text variable="title" form="short" quotes="true"/> - </else> - </choose> - </if> - <else-if type="speech thesis" match="any"> - <text variable="medium" text-case="capitalize-first"/> - </else-if> - <!-- book is here to catch software with container titles --> - <else-if type="book report" match="any"> - <choose> - <if variable="container-title" match="none"> - <text macro="format-report"/> - </if> - </choose> - </else-if> - <else-if type="manuscript pamphlet" match="any"> - <text variable="medium" text-case="capitalize-first"/> - </else-if> - <else-if type="personal_communication"> - <text macro="secondary-contributors"/> - </else-if> - <else-if type="song"> - <group delimiter="; "> - <text macro="secondary-contributors"/> - <choose> - <if variable="container-title" match="none"> - <group delimiter=", "> - <text variable="genre" text-case="capitalize-first"/> - <text variable="medium" text-case="capitalize-first"/> - </group> - </if> - </choose> - </group> - </else-if> - <else-if type="paper-conference"> - <group delimiter=", "> - <choose> - <if variable="collection-editor editor issue page volume" match="any"> - <text variable="genre" text-case="capitalize-first"/> - </if> - </choose> - <text variable="medium" text-case="capitalize-first"/> - </group> - </else-if> - <else-if type="bill legislation legal_case patent treaty" match="none"> - <choose> - <if variable="genre medium" match="any"> - <group delimiter=", "> - <text variable="genre" text-case="capitalize-first"/> - <text variable="medium" text-case="capitalize-first"/> - </group> - </if> - <else-if type="dataset"> - <!-- This should be localized --> - <text value="Data set"/> - </else-if> - </choose> - </else-if> - </choose> - </macro> - <macro name="description-report"> - <choose> - <if variable="number"> - <group delimiter="; "> - <group delimiter=" "> - <text variable="genre" text-case="title"/> - <!-- Replace with term="number" if that becomes available --> - <text term="issue" form="short" text-case="capitalize-first"/> - <text variable="number"/> - </group> - <text macro="locators"/> - </group> - </if> - <else> - <text macro="locators"/> - </else> - </choose> - </macro> - <macro name="format-report"> - <choose> - <if variable="number"> - <text variable="medium" text-case="capitalize-first"/> - </if> - <else> - <group delimiter=", "> - <text variable="genre" text-case="capitalize-first"/> - <text variable="medium" text-case="capitalize-first"/> - </group> - </else> - </choose> - </macro> - <macro name="archive"> - <group delimiter=". "> - <group delimiter=", "> - <choose> - <if type="manuscript"> - <text variable="genre"/> - </if> - </choose> - <group delimiter=" "> - <!-- Replace "archive" with "archive_collection" as that becomes available --> - <text variable="archive"/> - <text variable="archive_location" prefix="(" suffix=")"/> - </group> - </group> - <group delimiter=", "> - <!-- Move "archive" here when "archive_collection" becomes available --> - <text variable="archive-place"/> - </group> - </group> - </macro> - <macro name="publisher"> - <choose> - <if type="manuscript pamphlet" match="any"> - <choose> - <if variable="archive archive_location archive-place" match="any"> - <group delimiter=". "> - <group delimiter=": "> - <text variable="publisher-place"/> - <text variable="publisher"/> - </group> - <text macro="archive"/> - </group> - </if> - <else> - <group delimiter=", "> - <text variable="genre"/> - <text variable="publisher"/> - <text variable="publisher-place"/> - </group> - </else> - </choose> - </if> - <else-if type="thesis" match="any"> - <group delimiter=". "> - <group delimiter=", "> - <text variable="publisher"/> - <text variable="publisher-place"/> - </group> - <text macro="archive"/> - </group> - </else-if> - <else-if type="patent"> - <group delimiter=". "> - <group delimiter=": "> - <text variable="publisher-place"/> - <text variable="publisher"/> - </group> - <text macro="archive"/> - </group> - </else-if> - <else-if type="article-journal article-magazine article-newspaper" match="any"> - <text macro="archive"/> - </else-if> - <else-if type="post post-weblog webpage" match="none"> - <group delimiter=". "> - <choose> - <if variable="event"> - <choose> - <!-- Only print publisher info if published in a proceedings --> - <if variable="collection-editor editor issue page volume" match="any"> - <group delimiter=": "> - <text variable="publisher-place"/> - <text variable="publisher"/> - </group> - </if> - </choose> - </if> - <else> - <group delimiter=": "> - <text variable="publisher-place"/> - <text variable="publisher"/> - </group> - </else> - </choose> - <text macro="archive"/> - </group> - </else-if> - </choose> - </macro> - <macro name="event"> - <choose> - <if variable="event" type="speech paper-conference" match="any"> - <choose> - <!-- Don't print event info if published in a proceedings --> - <if variable="collection-editor editor issue page volume" match="none"> - <group delimiter=" "> - <text variable="genre" text-case="capitalize-first"/> - <group delimiter=" "> - <choose> - <if variable="genre"> - <text term="presented at"/> - </if> - <else> - <text term="presented at" text-case="capitalize-first"/> - </else> - </choose> - <group delimiter=", "> - <text variable="event"/> - <text variable="event-place"/> - </group> - </group> - </group> - </if> - </choose> - </if> - </choose> - </macro> - <macro name="issued"> - <choose> - <if type="bill legal_case legislation" match="any"/> - <else-if variable="issued"> - <group> - <date variable="issued"> - <date-part name="year"/> - </date> - <text variable="year-suffix"/> - <choose> - <if type="speech"> - <date variable="issued" delimiter=" "> - <date-part prefix=", " name="month"/> - </date> - </if> - <else-if type="article article-magazine article-newspaper broadcast interview pamphlet personal_communication post post-weblog treaty webpage" match="any"> - <date variable="issued"> - <date-part prefix=", " name="month"/> - <date-part prefix=" " name="day"/> - </date> - </else-if> - <else-if type="paper-conference"> - <choose> - <if variable="container-title" match="none"> - <date variable="issued"> - <date-part prefix=", " name="month"/> - <date-part prefix=" " name="day"/> - </date> - </if> - </choose> - </else-if> - <!-- Only year: article-journal chapter entry entry-dictionary entry-encyclopedia dataset figure graphic motion_picture manuscript map musical_score paper-conference [published] patent report review review-book song thesis --> - </choose> - </group> - </else-if> - <else-if variable="status"> - <group> - <text variable="status" text-case="lowercase"/> - <text variable="year-suffix" prefix="-"/> - </group> - </else-if> - <else> - <group> - <text term="no date" form="short"/> - <text variable="year-suffix" prefix="-"/> - </group> - </else> - </choose> - </macro> - <macro name="issued-sort"> - <choose> - <if type="article article-magazine article-newspaper broadcast interview pamphlet personal_communication post post-weblog speech treaty webpage" match="any"> - <date variable="issued"> - <date-part name="year"/> - <date-part name="month"/> - <date-part name="day"/> - </date> - </if> - <else> - <date variable="issued"> - <date-part name="year"/> - </date> - </else> - </choose> - </macro> - <macro name="issued-year"> - <group> - <choose> - <if type="personal_communication"> - <choose> - <if variable="archive DOI publisher URL" match="none"> - <!-- These variables indicate that the letter is retrievable by the reader. If not, then use the APA in-text-only personal communication format --> - <date variable="issued" form="text"/> - </if> - <else> - <date variable="issued"> - <date-part name="year"/> - </date> - </else> - </choose> - </if> - <else> - <date variable="issued"> - <date-part name="year"/> - </date> - </else> - </choose> - <text variable="year-suffix"/> - </group> - </macro> - <macro name="issued-citation"> - <choose> - <if variable="issued"> - <group delimiter="/"> - <choose> - <if is-uncertain-date="original-date"> - <group prefix="[" suffix="]" delimiter=" "> - <text term="circa" form="short"/> - <date variable="original-date"> - <date-part name="year"/> - </date> - </group> - </if> - <else> - <date variable="original-date"> - <date-part name="year"/> - </date> - </else> - </choose> - <choose> - <if is-uncertain-date="issued"> - <group prefix="[" suffix="]" delimiter=" "> - <text term="circa" form="short"/> - <text macro="issued-year"/> - </group> - </if> - <else> - <text macro="issued-year"/> - </else> - </choose> - </group> - </if> - <else-if variable="status"> - <text variable="status" text-case="lowercase"/> - <text variable="year-suffix" prefix="-"/> - </else-if> - <else> - <text term="no date" form="short"/> - <text variable="year-suffix" prefix="-"/> - </else> - </choose> - </macro> - <macro name="original-date"> - <choose> - <if type="bill legal_case legislation" match="any"/> - <else-if type="speech"> - <date variable="original-date" delimiter=" "> - <date-part name="month"/> - <date-part name="year"/> - </date> - </else-if> - <else-if type="article article-magazine article-newspaper broadcast interview pamphlet personal_communication post post-weblog treaty webpage" match="any"> - <date variable="original-date" form="text"/> - </else-if> - <else> - <date variable="original-date"> - <date-part name="year"/> - </date> - </else> - </choose> - </macro> - <macro name="original-published"> - <!--This should be localized --> - <choose> - <if type="bill legal_case legislation" match="any"/> - <else-if type="interview motion_picture song" match="any"> - <text value="Original work recorded"/> - </else-if> - <else-if type="broadcast"> - <text value="Original work broadcast"/> - </else-if> - <else> - <text value="Original work published"/> - </else> - </choose> - </macro> - <macro name="edition"> - <choose> - <if is-numeric="edition"> - <group delimiter=" "> - <number variable="edition" form="ordinal"/> - <text term="edition" form="short"/> - </group> - </if> - <else> - <text variable="edition"/> - </else> - </choose> - </macro> - <macro name="locators"> - <choose> - <if type="article-journal article-magazine figure review review-book" match="any"> - <group delimiter=", "> - <group> - <text variable="volume" font-style="italic"/> - <text variable="issue" prefix="(" suffix=")"/> - </group> - <text variable="page"/> - </group> - </if> - <else-if type="article-newspaper"> - <group delimiter=" "> - <label variable="page" form="short"/> - <text variable="page"/> - </group> - </else-if> - <else-if type="paper-conference"> - <choose> - <if variable="collection-editor editor" match="any"> - <text macro="locators-booklike"/> - </if> - <else> - <group delimiter=", "> - <group> - <text variable="volume" font-style="italic"/> - <text variable="issue" prefix="(" suffix=")"/> - </group> - <text variable="page"/> - </group> - </else> - </choose> - </else-if> - <else-if type="bill broadcast interview legal_case legislation patent post post-weblog speech treaty webpage" match="none"> - <text macro="locators-booklike"/> - </else-if> - </choose> - </macro> - <macro name="locators-booklike"> - <group delimiter=", "> - <text macro="edition"/> - <group delimiter=" "> - <text term="version" text-case="capitalize-first"/> - <text variable="version"/> - </group> - <choose> - <if variable="volume" match="any"> - <choose> - <if is-numeric="volume" match="none"/> - <else-if variable="collection-title"> - <choose> - <if variable="editor translator" match="none"> - <choose> - <if variable="collection-number"> - <group> - <text term="volume" form="short" text-case="capitalize-first" suffix=" "/> - <number variable="volume" form="numeric"/> - </group> - </if> - </choose> - </if> - </choose> - </else-if> - <else> - <group> - <text term="volume" form="short" text-case="capitalize-first" suffix=" "/> - <number variable="volume" form="numeric"/> - </group> - </else> - </choose> - </if> - <else> - <group> - <text term="volume" form="short" plural="true" text-case="capitalize-first" suffix=" "/> - <number variable="number-of-volumes" form="numeric" prefix="1–"/> - </group> - </else> - </choose> - <group> - <label variable="page" form="short" suffix=" "/> - <text variable="page"/> - </group> - </group> - </macro> - <macro name="citation-locator"> - <group> - <choose> - <if locator="chapter"> - <label variable="locator" text-case="capitalize-first"/> - </if> - <else> - <label variable="locator" form="short"/> - </else> - </choose> - <text variable="locator" prefix=" "/> - </group> - </macro> - <macro name="container"> - <choose> - <if type="article article-journal article-magazine article-newspaper review review-book" match="any"> - <group delimiter=", "> - <text macro="container-title"/> - <text macro="locators"/> - </group> - <choose> - <!--for advance online publication--> - <if variable="issued"> - <choose> - <if variable="page issue" match="none"> - <text variable="status" text-case="capitalize-first" prefix=". "/> - </if> - </choose> - </if> - </choose> - </if> - <else-if type="article dataset figure" match="any"> - <choose> - <if variable="container-title"> - <group delimiter=", "> - <text macro="container-title"/> - <text macro="locators"/> - </group> - <choose> - <!--for advance online publication--> - <if variable="issued"> - <choose> - <if variable="page issue" match="none"> - <text variable="status" text-case="capitalize-first" prefix=". "/> - </if> - </choose> - </if> - </choose> - </if> - </choose> - </else-if> - <!-- book is here to catch software with container titles --> - <else-if type="book" variable="container-title" match="all"> - <group delimiter=" "> - <text term="in" text-case="capitalize-first" suffix=" "/> - <group delimiter=", "> - <text macro="container-contributors"/> - <group delimiter=" "> - <text macro="container-title"/> - <text macro="description-report" prefix="(" suffix=")"/> - <text macro="format-report" prefix="[" suffix="]"/> - </group> - </group> - </group> - </else-if> - <else-if type="report" variable="container-title" match="all"> - <group delimiter=" "> - <text term="in" text-case="capitalize-first" suffix=" "/> - <group delimiter=", "> - <text macro="container-contributors"/> - <group delimiter=" "> - <text macro="container-title"/> - <text macro="description-report" prefix="(" suffix=")"/> - <text macro="format-report" prefix="[" suffix="]"/> - </group> - </group> - </group> - </else-if> - <else-if type="song" variable="container-title" match="all"> - <group delimiter=" "> - <text term="in" text-case="capitalize-first" suffix=" "/> - <group delimiter=", "> - <text macro="container-contributors"/> - <group delimiter=" "> - <text macro="container-title"/> - <text macro="locators" prefix="(" suffix=")"/> - <group delimiter=", " prefix="[" suffix="]"> - <text variable="genre" text-case="capitalize-first"/> - <text variable="medium" text-case="capitalize-first"/> - </group> - </group> - </group> - </group> - </else-if> - <else-if type="paper-conference"> - <choose> - <if variable="editor collection-editor container-author" match="any"> - <text macro="container-booklike"/> - </if> - <else> - <group delimiter=", "> - <text macro="container-title"/> - <text macro="locators"/> - </group> - </else> - </choose> - </else-if> - <else-if type="book"> - <choose> - <!-- book and software should not cite collection-title, only container-title --> - <if variable="container-title"> - <text macro="container-booklike"/> - </if> - </choose> - </else-if> - <else-if type="broadcast chapter entry entry-dictionary entry-encyclopedia graphic map speech" match="any"> - <text macro="container-booklike"/> - </else-if> - <else-if type="bill legal_case legislation treaty" match="any"> - <text macro="legal-cites"/> - </else-if> - </choose> - </macro> - <macro name="container-booklike"> - <choose> - <if variable="container-title collection-title" match="any"> - <group delimiter=" "> - <text term="in" text-case="capitalize-first"/> - <group delimiter=", "> - <text macro="container-contributors"/> - <choose> - <if variable="container-author editor translator" match="none"> - <group delimiter=". "> - <group delimiter=": "> - <text variable="collection-title" font-style="italic" text-case="title"/> - <choose> - <if variable="collection-title"> - <group delimiter=" "> - <text term="volume" form="short" font-style="italic" text-case="capitalize-first"/> - <number variable="collection-number" font-style="italic" form="numeric"/> - <choose> - <if variable="collection-number" match="none"> - <number variable="volume" font-style="italic" form="numeric"/> - </if> - </choose> - </group> - </if> - </choose> - </group> - <!-- Replace with volume-title as that becomes available --> - <group delimiter=": "> - <text macro="container-title"/> - <choose> - <if variable="collection-title" is-numeric="volume" match="none"> - <group delimiter=" "> - <text term="volume" form="short" font-style="italic" text-case="capitalize-first"/> - <text variable="volume" font-style="italic"/> - </group> - </if> - </choose> - </group> - </group> - </if> - <else> - <!-- Replace with volume-title as that becomes available --> - <group delimiter=": "> - <text macro="container-title"/> - <choose> - <if is-numeric="volume" match="none"> - <group delimiter=" "> - <text term="volume" form="short" font-style="italic" text-case="capitalize-first"/> - <text variable="volume" font-style="italic"/> - </group> - </if> - </choose> - </group> - </else> - </choose> - </group> - <group delimiter="; " prefix="(" suffix=")"> - <text macro="locators"/> - <names variable="container-author"> - <label form="verb-short" suffix=" " text-case="title"/> - <name and="symbol" initialize-with=". " delimiter=", "/> - </names> - </group> - </group> - </if> - </choose> - </macro> - <macro name="container-title"> - <choose> - <if type="article article-journal article-magazine article-newspaper dataset" match="any"> - <text variable="container-title" font-style="italic" text-case="title"/> - </if> - <else-if type="paper-conference speech"> - <choose> - <if variable="collection-editor container-author editor" match="any"> - <text variable="container-title" font-style="italic"/> - </if> - <else> - <text variable="container-title" font-style="italic" text-case="title"/> - </else> - </choose> - </else-if> - <else-if type="bill legal_case legislation post-weblog webpage" match="none"> - <text variable="container-title" font-style="italic"/> - </else-if> - </choose> - </macro> - <macro name="legal-cites"> - <choose> - <if type="legal_case"> - <group prefix=", " delimiter=" "> - <group delimiter=" "> - <choose> - <if variable="container-title"> - <text variable="volume"/> - <text variable="container-title"/> - <group delimiter=" "> - <!--change to label variable="section" as that becomes available --> - <text term="section" form="symbol"/> - <text variable="section"/> - </group> - <text variable="page"/> - </if> - <else> - <group delimiter=" "> - <choose> - <if is-numeric="number"> - <!-- Replace with term="number" if that becomes available --> - <text term="issue" form="short" text-case="capitalize-first"/> - </if> - </choose> - <text variable="number"/> - </group> - </else> - </choose> - </group> - <group prefix="(" suffix=")" delimiter=" "> - <text variable="authority"/> - <choose> - <if variable="container-title" match="any"> - <!--Only print year for cases published in reporters--> - <date variable="issued" form="numeric" date-parts="year"/> - </if> - <else> - <date variable="issued" form="text"/> - </else> - </choose> - </group> - </group> - </if> - <else-if type="bill legislation" match="any"> - <group prefix=", " delimiter=" "> - <group delimiter=", "> - <choose> - <if variable="number"> - <!--There's a public law number--> - <text variable="number" prefix="Pub. L. No. "/> - <group delimiter=" "> - <!--change to label variable="section" as that becomes available --> - <text term="section" form="symbol"/> - <text variable="section"/> - </group> - <group delimiter=" "> - <text variable="volume"/> - <text variable="container-title"/> - <text variable="page-first"/> - </group> - </if> - <else> - <group delimiter=" "> - <text variable="volume"/> - <text variable="container-title"/> - <!--change to label variable="section" as that becomes available --> - <text term="section" form="symbol"/> - <text variable="section"/> - </group> - </else> - </choose> - </group> - <date variable="issued" prefix="(" suffix=")"> - <date-part name="year"/> - </date> - </group> - </else-if> - <else-if type="treaty"> - <group delimiter=" "> - <number variable="volume"/> - <text variable="container-title"/> - <text variable="page"/> - </group> - </else-if> - </choose> - </macro> - <citation et-al-min="6" et-al-use-first="1" et-al-subsequent-min="3" et-al-subsequent-use-first="1" disambiguate-add-year-suffix="true" disambiguate-add-names="true" disambiguate-add-givenname="true" collapse="year" givenname-disambiguation-rule="primary-name"> - <sort> - <key macro="author" names-min="8" names-use-first="6"/> - <key macro="issued-sort"/> - </sort> - <layout prefix="(" suffix=")" delimiter="; "> - <group delimiter=", "> - <text macro="author-short"/> - <text macro="issued-citation"/> - <text macro="citation-locator"/> - </group> - </layout> - </citation> - <bibliography hanging-indent="true" et-al-min="8" et-al-use-first="6" et-al-use-last="true" entry-spacing="0" line-spacing="2"> - <sort> - <key macro="author"/> - <key macro="issued-sort" sort="ascending"/> - <key macro="title"/> - </sort> - <layout> - <group suffix="."> - <group delimiter=". "> - <text macro="author"/> - <choose> - <if is-uncertain-date="issued"> - <group prefix=" [" suffix="]" delimiter=" "> - <text term="circa" form="short"/> - <text macro="issued"/> - </group> - </if> - <else> - <text macro="issued" prefix=" (" suffix=")"/> - </else> - </choose> - <group delimiter=" "> - <text macro="title"/> - <choose> - <if variable="title interviewer" type="interview" match="any"> - <group delimiter=" "> - <text macro="description"/> - <text macro="format"/> - </group> - </if> - <else> - <group delimiter=" "> - <text macro="format"/> - <text macro="description"/> - </group> - </else> - </choose> - </group> - <text macro="container"/> - </group> - <text macro="event" prefix=". "/> - </group> - <text macro="access" prefix=" "/> - <choose> - <if is-uncertain-date="original-date"> - <group prefix=" [" suffix="]" delimiter=" "> - <text macro="original-published"/> - <text term="circa" form="short"/> - <text macro="original-date"/> - </group> - </if> - <else-if variable="original-date"> - <group prefix=" (" suffix=")" delimiter=" "> - <text macro="original-published"/> - <text macro="original-date"/> - </group> - </else-if> - </choose> - </layout> - </bibliography> -</style>
\ No newline at end of file diff --git a/support/texlab/src/citeproc/bibutils.rs b/support/texlab/src/citeproc/bibutils.rs deleted file mode 100644 index b69ed66ed1..0000000000 --- a/support/texlab/src/citeproc/bibutils.rs +++ /dev/null @@ -1,188 +0,0 @@ -use bibutils_sys::{ - bibl, bibl_free, bibl_freeparams, bibl_init, bibl_initparams, bibl_read, bibl_write, fclose, - fopen, param, BIBL_ADSABSOUT, BIBL_BIBLATEXIN, BIBL_BIBTEXIN, BIBL_BIBTEXOUT, BIBL_COPACIN, - BIBL_EBIIN, BIBL_ENDNOTEIN, BIBL_ENDNOTEOUT, BIBL_ENDNOTEXMLIN, BIBL_ISIOUT, BIBL_MEDLINEIN, - BIBL_MODSIN, BIBL_MODSOUT, BIBL_NBIBIN, BIBL_NBIBOUT, BIBL_OK, BIBL_RISIN, BIBL_RISOUT, - BIBL_WORD2007OUT, BIBL_WORDIN, FILE, -}; -use std::{ffi::CString, fs, mem::MaybeUninit, path::Path}; -use tempfile::tempdir; - -#[derive(Debug, PartialEq, Eq, Clone, Copy)] -pub enum InputFormat { - Bibtex, - Biblatex, - Copac, - Ebi, - Endnote, - EndnoteXml, - Medline, - Mods, - Nbib, - Ris, - Word, -} - -impl InputFormat { - fn read_mode(self) -> u32 { - match self { - Self::Bibtex => BIBL_BIBTEXIN, - Self::Biblatex => BIBL_BIBLATEXIN, - Self::Copac => BIBL_COPACIN, - Self::Ebi => BIBL_EBIIN, - Self::Endnote => BIBL_ENDNOTEIN, - Self::EndnoteXml => BIBL_ENDNOTEXMLIN, - Self::Medline => BIBL_MEDLINEIN, - Self::Mods => BIBL_MODSIN, - Self::Nbib => BIBL_NBIBIN, - Self::Ris => BIBL_RISIN, - Self::Word => BIBL_WORDIN, - } - } -} - -#[derive(Debug, PartialEq, Eq, Clone, Copy)] -pub enum OutputFormat { - Adsabs, - Bibtex, - Endnote, - Isi, - Mods, - Nbib, - Ris, - Word2007, -} - -impl OutputFormat { - fn write_mode(self) -> u32 { - match self { - Self::Adsabs => BIBL_ADSABSOUT, - Self::Bibtex => BIBL_BIBTEXOUT, - Self::Endnote => BIBL_ENDNOTEOUT, - Self::Isi => BIBL_ISIOUT, - Self::Mods => BIBL_MODSOUT, - Self::Nbib => BIBL_NBIBOUT, - Self::Ris => BIBL_RISOUT, - Self::Word2007 => BIBL_WORD2007OUT, - } - } -} - -struct Context { - inner: MaybeUninit<bibl>, -} - -impl Context { - fn new() -> Self { - let mut inner = MaybeUninit::zeroed(); - unsafe { - bibl_init(inner.as_mut_ptr()); - } - Self { inner } - } -} - -impl Drop for Context { - fn drop(&mut self) { - unsafe { - bibl_free(self.inner.as_mut_ptr()); - } - } -} - -unsafe impl Send for Context {} - -struct Params { - inner: MaybeUninit<param>, -} - -impl Params { - fn new(from: InputFormat, to: OutputFormat) -> Self { - let program = CString::new("texlab").unwrap(); - let mut inner = MaybeUninit::zeroed(); - unsafe { - bibl_initparams( - inner.as_mut_ptr(), - from.read_mode() as i32, - to.write_mode() as i32, - program.as_ptr() as *mut std::os::raw::c_char, - ); - } - Self { inner } - } -} - -impl Drop for Params { - fn drop(&mut self) { - unsafe { - bibl_freeparams(self.inner.as_mut_ptr()); - } - } -} - -unsafe impl Send for Params {} - -struct File { - path: CString, - handle: *mut FILE, -} - -impl File { - fn new<M: Into<Vec<u8>>>(path: &Path, mode: M) -> Self { - let path = CString::new(path.to_str().unwrap()).unwrap(); - let mode = CString::new(mode).unwrap(); - let handle = unsafe { fopen(path.as_ptr(), mode.as_ptr()) }; - Self { path, handle } - } -} - -impl Drop for File { - fn drop(&mut self) { - unsafe { - fclose(self.handle); - } - } -} - -unsafe impl Send for File {} - -pub fn convert(input: &str, from: InputFormat, to: OutputFormat) -> Option<String> { - let mut context = Context::new(); - let mut params = Params::new(from, to); - let dir = tempdir().expect("failed to create a temporary directory"); - - let input_path = dir.path().join("input"); - fs::write(&input_path, input).ok()?; - let input_file = File::new(&input_path, "r"); - unsafe { - let status = bibl_read( - context.inner.as_mut_ptr(), - input_file.handle, - input_file.path.as_ptr() as *mut std::os::raw::c_char, - params.inner.as_mut_ptr(), - ); - - if status != BIBL_OK as i32 { - return None; - } - } - - let output_path = dir.path().join("output"); - let output_file = File::new(&output_path, "w"); - unsafe { - let status = bibl_write( - context.inner.as_mut_ptr(), - output_file.handle, - params.inner.as_mut_ptr(), - ); - - if status != BIBL_OK as i32 { - return None; - } - } - - // Remove BOM - let data = fs::read(&output_path).ok()?; - let text = String::from_utf8_lossy(&data[3..]).into_owned(); - Some(text) -} diff --git a/support/texlab/src/citeproc/mod.rs b/support/texlab/src/citeproc/mod.rs deleted file mode 100644 index 6def2ed8a4..0000000000 --- a/support/texlab/src/citeproc/mod.rs +++ /dev/null @@ -1,213 +0,0 @@ -mod bibutils; -mod name; -mod ris; - -use self::{ - bibutils::{InputFormat, OutputFormat}, - ris::{RisLibrary, RisReference}, -}; -use crate::{ - protocol::{BibtexFormattingOptions, MarkupContent, MarkupKind}, - syntax::bibtex, -}; -use citeproc::prelude::*; -use citeproc_db::PredefinedLocales; -use once_cell::sync::Lazy; -use regex::Regex; -use std::sync::Arc; - -static APA_STYLE: &str = include_str!("apa.csl"); - -static DOI_URL_PATTERN: &str = r#"https://doi.org/\[.*\]\(.*\)"#; - -static DOI_URL_REGEX: Lazy<Regex> = Lazy::new(|| Regex::new(DOI_URL_PATTERN).unwrap()); - -pub fn render_citation(tree: &bibtex::Tree, key: &str) -> Option<MarkupContent> { - let ris_reference = convert_to_ris(tree, key)?; - let doi_url = get_doi_url_markdown(&ris_reference); - let csl_reference: Reference = ris_reference.into(); - let html = generate_bibliography(csl_reference)?; - - let mut markdown = html2md::parse_html(&html).trim().to_owned(); - if markdown == "" { - return None; - } - - if let Some(doi_url) = doi_url { - markdown = DOI_URL_REGEX - .replace(&markdown, doi_url.as_str()) - .into_owned(); - } - - markdown = markdown - .replace("..", ".") - .replace("\\\'", "'") - .replace("\\-", "-") - .replace("\\\\textsubscript", "") - .replace("\\\\textsuperscript", ""); - let content = MarkupContent { - kind: MarkupKind::Markdown, - value: markdown, - }; - Some(content) -} - -fn convert_to_ris(tree: &bibtex::Tree, key: &str) -> Option<RisReference> { - let options = BibtexFormattingOptions { - line_length: None, - formatter: None, - }; - let params = bibtex::FormattingParams { - insert_spaces: true, - tab_size: 4, - options: &options, - }; - - let mut bib_code = String::new(); - tree.children(tree.root) - .filter(|node| tree.as_string(*node).is_some()) - .map(|node| bibtex::format(tree, node, params)) - .for_each(|string| { - bib_code.push_str(&string); - bib_code.push('\n'); - }); - - let entry = tree.entry_by_key(key)?; - if let Some(crossref) = tree.crossref(entry) { - bib_code.push_str(&bibtex::format(tree, crossref, params)); - bib_code.push('\n'); - } - - bib_code.push_str(&bibtex::format(tree, entry, params)); - bib_code.push('\n'); - bib_code = bib_code.replace("\\hypen", "-"); - - let ris_code = bibutils::convert(&bib_code, InputFormat::Biblatex, OutputFormat::Ris)?; - let ris_lib = RisLibrary::parse(ris_code.lines()); - ris_lib - .references - .into_iter() - .find(|reference| reference.id.as_ref().map(AsRef::as_ref) == Some(key)) -} - -fn get_doi_url_markdown(ris_reference: &RisReference) -> Option<String> { - ris_reference - .doi - .as_ref() - .map(|doi| format!("[doi:{}](https://doi.org/{})", doi, doi)) -} - -fn generate_bibliography(reference: Reference) -> Option<String> { - let locales = Arc::new(PredefinedLocales::bundled_en_us()); - let mut processor = Processor::new(APA_STYLE, locales, false, SupportedFormat::Html).unwrap(); - let cite = Cite::basic(&reference.id); - let cluster = Cluster { - id: 1, - cites: vec![cite], - }; - processor.insert_reference(reference); - processor.init_clusters(vec![cluster]); - processor - .set_cluster_order(&[ClusterPosition { - id: 1, - note: Some(1), - }]) - .unwrap(); - processor.get_bibliography().pop() -} - -#[cfg(test)] -mod tests { - use super::*; - use indoc::indoc; - - #[test] - fn simple() { - let tree = bibtex::open(indoc!( - r#" - @article{foo, - author = {Foo Bar}, - title = {Baz Qux}, - year = {2020} - } - "# - )); - - let actual_md = render_citation(&tree, "foo").unwrap(); - - let expected_md = MarkupContent { - kind: MarkupKind::Markdown, - value: "Bar, F. (2020). *Baz Qux*.".into(), - }; - - assert_eq!(actual_md, expected_md); - } - - #[test] - fn crossref() { - let tree = bibtex::open(indoc!( - r#" - https://tex.stackexchange.com/questions/401138/what-is-the-bibtex-crossref-field-used-for - - @inproceedings{duck2015, - author = {Duck, D.}, - title = {Duck tales}, - crossref = {ICRC2015}, - } - - @inproceedings{mouse2015, - author = {Mouse, M.}, - title = {Mouse stories}, - crossref = {ICRC2015}, - } - - @proceedings{ICRC2015, - title = "{Proceedings of the 34\textsuperscript{th} International Cosmic Ray Conference}", - year = "2015", - month = aug, - } - "# - )); - - let actual_md = render_citation(&tree, "mouse2015").unwrap(); - - let expected_md = MarkupContent { - kind: MarkupKind::Markdown, - value: "Mouse, M. (2015). Mouse stories. In *Proceedings of the 34th International Cosmic Ray Conference*.".into(), - }; - - assert_eq!(actual_md, expected_md); - } - - #[test] - fn string() { - let tree = bibtex::open(indoc!( - r#" - @string{author = "Foo Bar"} - @article{foo, - author = author, - title = {Baz Qux}, - year = {2020} - } - "# - )); - - let actual_md = render_citation(&tree, "foo").unwrap(); - - let expected_md = MarkupContent { - kind: MarkupKind::Markdown, - value: "Bar, F. (2020). *Baz Qux*.".into(), - }; - - assert_eq!(actual_md, expected_md); - } - - #[test] - fn unknown_key() { - let tree = bibtex::open(""); - - let actual_md = render_citation(&tree, "foo"); - - assert_eq!(actual_md, None); - } -} diff --git a/support/texlab/src/citeproc/name/mod.rs b/support/texlab/src/citeproc/name/mod.rs deleted file mode 100644 index ef97d30130..0000000000 --- a/support/texlab/src/citeproc/name/mod.rs +++ /dev/null @@ -1,278 +0,0 @@ -// Ported from: https://github.com/michel-kraemer/citeproc-java/blob/master/citeproc-java/grammars/InternalName.g4 -// Michel Kraemer -// Apache License 2.0 -mod parser { - #![allow(warnings)] - include!(concat!(env!("OUT_DIR"), "/citeproc/name/parser.rs")); -} - -use self::parser::NamesParser; -use citeproc_io::Name; - -pub fn parse(input: &str) -> Vec<Name> { - let parser = NamesParser::new(); - parser.parse(input).unwrap_or_else(|_| { - vec![Name::Literal { - literal: input.into(), - }] - }) -} - -#[cfg(test)] -mod tests { - use super::*; - use citeproc_io::PersonName; - - #[test] - fn family_only() { - let name = Name::Person(PersonName { - family: Some("Thompson".into()), - given: None, - non_dropping_particle: None, - dropping_particle: None, - suffix: None, - }); - assert_eq!(parse("Thompson"), vec![name]); - } - - #[test] - fn simple() { - let name = Name::Person(PersonName { - family: Some("Thompson".into()), - given: Some("Ken".into()), - non_dropping_particle: None, - dropping_particle: None, - suffix: None, - }); - assert_eq!(parse("Ken Thompson"), vec![name]); - } - - #[test] - fn middle_name() { - let name = Name::Person(PersonName { - family: Some("Ritchie".into()), - given: Some("Dennis M.".into()), - non_dropping_particle: None, - dropping_particle: None, - suffix: None, - }); - assert_eq!(parse("Dennis M. Ritchie"), vec![name]); - } - - #[test] - fn initials() { - let name = Name::Person(PersonName { - family: Some("Johnson".into()), - given: Some("S. C.".into()), - non_dropping_particle: None, - dropping_particle: None, - suffix: None, - }); - assert_eq!(parse("S. C. Johnson"), vec![name]); - } - - #[test] - fn non_dropping_particle() { - let name = Name::Person(PersonName { - family: Some("Gerwen".into()), - given: Some("Michael".into()), - non_dropping_particle: Some("van".into()), - dropping_particle: None, - suffix: None, - }); - assert_eq!(parse("Michael van Gerwen"), vec![name]); - } - - #[test] - fn non_dropping_particle_family_only() { - let name = Name::Person(PersonName { - family: Some("Gerwen".into()), - given: None, - non_dropping_particle: Some("van".into()), - dropping_particle: None, - suffix: None, - }); - assert_eq!(parse("van Gerwen"), vec![name]); - } - - #[test] - fn comma() { - let name = Name::Person(PersonName { - family: Some("Thompson".into()), - given: Some("Ken".into()), - non_dropping_particle: None, - dropping_particle: None, - suffix: None, - }); - assert_eq!(parse("Thompson, Ken"), vec![name]); - } - - #[test] - fn comma_junior() { - let name = Name::Person(PersonName { - family: Some("Friedman".into()), - given: Some("George".into()), - non_dropping_particle: None, - dropping_particle: None, - suffix: Some("Jr.".into()), - }); - assert_eq!(parse("Friedman, Jr., George"), vec![name]); - } - - #[test] - fn comma_no_junior() { - let name = Name::Person(PersonName { - family: Some("Familya Familyb".into()), - given: Some("Given".into()), - non_dropping_particle: None, - dropping_particle: None, - suffix: None, - }); - assert_eq!(parse("Familya Familyb, Given"), vec![name]); - } - - #[test] - fn comma_initials() { - let name = Name::Person(PersonName { - family: Some("Ritchie".into()), - given: Some("Dennis M.".into()), - non_dropping_particle: None, - dropping_particle: None, - suffix: None, - }); - assert_eq!(parse("Ritchie, Dennis M."), vec![name]); - } - - #[test] - fn comma_non_dropping_particle() { - let name = Name::Person(PersonName { - family: Some("Gerwen".into()), - given: Some("Michael".into()), - non_dropping_particle: Some("van".into()), - dropping_particle: None, - suffix: None, - }); - assert_eq!(parse("van Gerwen, Michael"), vec![name]); - } - - #[test] - fn comma_non_dropping_particles() { - let name = Name::Person(PersonName { - family: Some("Voort".into()), - given: Some("Vincent".into()), - non_dropping_particle: Some("Van der".into()), - dropping_particle: None, - suffix: None, - }); - assert_eq!(parse("Van der Voort, Vincent"), vec![name]); - } - - #[test] - fn and() { - let name1 = Name::Person(PersonName { - family: Some("Gerwen".into()), - given: Some("Michael".into()), - non_dropping_particle: Some("van".into()), - dropping_particle: None, - suffix: None, - }); - let name2 = Name::Person(PersonName { - family: Some("Voort".into()), - given: Some("Vincent".into()), - non_dropping_particle: Some("van der".into()), - dropping_particle: None, - suffix: None, - }); - assert_eq!( - parse("Michael van Gerwen and Vincent van der Voort"), - vec![name1, name2] - ); - } - - #[test] - fn and_comma1() { - let name1 = Name::Person(PersonName { - family: Some("Gerwen".into()), - given: Some("Michael".into()), - non_dropping_particle: Some("van".into()), - dropping_particle: None, - suffix: None, - }); - let name2 = Name::Person(PersonName { - family: Some("Voort".into()), - given: Some("Vincent".into()), - non_dropping_particle: Some("Van der".into()), - dropping_particle: None, - suffix: None, - }); - assert_eq!( - parse("van Gerwen, Michael and Van der Voort, Vincent"), - vec![name1, name2] - ); - } - - #[test] - fn and_comma2() { - let name1 = Name::Person(PersonName { - family: Some("Gerwen".into()), - given: Some("Michael".into()), - non_dropping_particle: Some("van".into()), - dropping_particle: None, - suffix: None, - }); - let name2 = Name::Person(PersonName { - family: Some("Voort".into()), - given: Some("Vincent".into()), - non_dropping_particle: Some("van der".into()), - dropping_particle: None, - suffix: None, - }); - assert_eq!( - parse("van Gerwen, Michael and van der Voort, Vincent"), - vec![name1, name2] - ); - } - - #[test] - fn and_comma_mix() { - let name1 = Name::Person(PersonName { - family: Some("Gerwen".into()), - given: Some("Michael".into()), - non_dropping_particle: Some("van".into()), - dropping_particle: None, - suffix: None, - }); - let name2 = Name::Person(PersonName { - family: Some("Voort".into()), - given: Some("Vincent".into()), - non_dropping_particle: Some("van der".into()), - dropping_particle: None, - suffix: None, - }); - assert_eq!( - parse("van Gerwen, Michael and Vincent van der Voort"), - vec![name1, name2] - ); - } - - #[test] - fn junior() { - let name = Name::Person(PersonName { - family: Some("Friedman".into()), - given: Some("George".into()), - non_dropping_particle: None, - dropping_particle: None, - suffix: Some("Jr.".into()), - }); - assert_eq!(parse("George Friedman, Jr."), vec![name]); - } - - #[test] - fn non_parseable() { - let literal = "Jerry Peek and Tim O'Reilly and Mike Loukides and other authors of the Nutshell handbooks"; - let name = Name::Literal { - literal: literal.into(), - }; - assert_eq!(parse(literal), vec![name]); - } -} diff --git a/support/texlab/src/citeproc/name/parser.lalrpop b/support/texlab/src/citeproc/name/parser.lalrpop deleted file mode 100644 index e7bce8a302..0000000000 --- a/support/texlab/src/citeproc/name/parser.lalrpop +++ /dev/null @@ -1,150 +0,0 @@ -// Ported from: https://github.com/michel-kraemer/citeproc-java/blob/master/citeproc-java/grammars/InternalName.g4 -// Michel Kraemer -// Apache License 2.0 -use citeproc_io::{Name, PersonName}; -use itertools::Itertools; - -grammar; - -pub Names: Vec<Name> = And<Name>; - -And<T>: Vec<T> = { - <v:(<T> "and")*> <e:T?> => match e { - None => v, - Some(e) => { - let mut v = v; - v.push(e); - v - } - } -}; - -Name: Name = { - <np1:UWord+> <np2:Von> <fam:Last> "," <fst:First> => { - let (fst1, fst2) = fst; - let name = PersonName { - family: Some(fam.join(" ")), - given: fst2, - non_dropping_particle: Some(format!("{} {}", np1.join(" "), np2)), - dropping_particle: None, - suffix: fst1, - }; - Name::Person(name) - }, - <np:Von> <fam:Last> "," <fst:First> => { - let (fst1, fst2) = fst; - let name = PersonName { - family: Some(fam.join(" ")), - given: fst2, - non_dropping_particle: Some(np), - dropping_particle: None, - suffix: fst1, - }; - Name::Person(name) - }, - <last:Last> "," <fst:First> => { - let (fst1, fst2) = fst; - let first_text = format!( - "{} {}", - fst1.as_ref().map(|s| s.as_str()).unwrap_or_default(), - fst2.as_ref().map(|s| s.as_str()).unwrap_or_default(), - ).trim().to_owned(); - - let name = if first_text == "Jr." { - if last.len() == 1 { - PersonName { - family: Some(last.join(" ")), - given: None, - non_dropping_particle: None, - dropping_particle: None, - suffix: Some(first_text), - } - } else { - let mut last = last.into_iter(); - let given = last.next().map(ToOwned::to_owned); - PersonName { - family: Some(last.join(" ")), - given, - non_dropping_particle: None, - dropping_particle: None, - suffix: Some(first_text), - } - } - } else { - PersonName { - family: Some(last.join(" ")), - given: fst2, - non_dropping_particle: None, - dropping_particle: None, - suffix: fst1, - } - }; - Name::Person(name) - }, - <np:Von> <fam:Last> => { - let name = PersonName { - family: Some(fam.join(" ")), - given: None, - non_dropping_particle: Some(np), - dropping_particle: None, - suffix: None, - }; - Name::Person(name) - }, - <giv:UWord+> <np:Von> <fam:Last> => { - let name = PersonName { - family: Some(fam.join(" ")), - given: Some(giv.join(" ")), - non_dropping_particle: Some(np), - dropping_particle: None, - suffix: None, - }; - Name::Person(name) - }, - <giv:UWord+> <fam:Word> => { - let name = PersonName { - family: Some(fam.into()), - given: Some(giv.join(" ")), - non_dropping_particle: None, - dropping_particle: None, - suffix: None, - }; - Name::Person(name) - }, - <fam:Word> => { - let name = PersonName { - family: Some(fam.into()), - given: None, - non_dropping_particle: None, - dropping_particle: None, - suffix: None, - }; - Name::Person(name) - }, -}; - -First: (Option<String>, Option<String>) = { - <a:Word*> "," <b:Word*> => (Some(a.join(" ")), Some(b.join(" "))), - <a:Word*> => (None, Some(a.join(" "))), -}; - -Last: Vec<&'input str> = { - LWord => vec![(<>)], - UWord+ => (<>), -}; - -Von: String = { - LWord => String::from(<>), - <a:Von> <b:LWord> => format!("{} {}", a, b), - <a:Von> <b:UWord+> <c:LWord> => format!("{} {} {}", a, b.join(" "), c), -}; - -Word: &'input str = { - UWord => (<>), - LWord => (<>), -}; - - -UWord: &'input str = r"[A-Z\u00C0-\uFFFF(?][A-Z\u00C0-\uFFFF(?a-z\-)&/.]+" => (<>); - -LWord: &'input str = r"[a-z\-)&/.][A-Z\u00C0-\uFFFF(?a-z\-)&/.]+" => (<>); diff --git a/support/texlab/src/citeproc/ris.rs b/support/texlab/src/citeproc/ris.rs deleted file mode 100644 index 1cb5754aec..0000000000 --- a/support/texlab/src/citeproc/ris.rs +++ /dev/null @@ -1,466 +0,0 @@ -// Ported from: https://github.com/michel-kraemer/citeproc-java/tree/master/citeproc-java/templates -// Michel Kraemer -// Apache License 2.0 -use super::name; -use citeproc_io::{Date, DateOrRange, Name, NumericValue, Reference}; -use csl::*; -use fnv::FnvHashMap; -use serde::{Deserialize, Serialize}; - -#[derive(Debug, PartialEq, Eq, Clone, Copy, Serialize, Deserialize)] -#[serde(rename_all = "UPPERCASE")] -pub enum RisType { - Abst, - Advs, - Aggr, - Ancient, - Art, - Bill, - Blog, - Book, - Case, - Chap, - Chart, - Clswk, - Comp, - Conf, - Cpaper, - Ctlg, - Data, - Dbase, - Dict, - Ebook, - Echap, - Edbook, - Ejour, - Elec, - Encyc, - Equa, - Figure, - Gen, - Govdoc, - Grant, - Hear, - Icomm, - Inpr, - Jfull, - Jour, - Legal, - Manscpt, - Map, - Mgzn, - Mpct, - Multi, - Music, - News, - Pamp, - Pat, - Pcomm, - Rprt, - Ser, - Slide, - Sound, - Stand, - Stat, - Std, - Thes, - Unpb, - Video, -} - -impl RisType { - pub fn parse(ty: &str) -> Option<Self> { - let ty = format!("\"{}\"", ty); - serde_json::from_str(&ty).ok() - } - - pub fn csl(self) -> CslType { - match self { - Self::Abst => CslType::Article, - Self::Advs => CslType::Article, - Self::Aggr => CslType::Dataset, - Self::Ancient => CslType::Article, - Self::Art => CslType::Article, - Self::Bill => CslType::Bill, - Self::Blog => CslType::Webpage, - Self::Book => CslType::Book, - Self::Case => CslType::LegalCase, - Self::Chap => CslType::Chapter, - Self::Chart => CslType::Article, - Self::Clswk => CslType::Article, - Self::Comp => CslType::Article, - Self::Conf => CslType::PaperConference, - Self::Cpaper => CslType::PaperConference, - Self::Ctlg => CslType::Book, - Self::Data => CslType::Dataset, - Self::Dbase => CslType::Dataset, - Self::Dict => CslType::EntryDictionary, - Self::Ebook => CslType::Book, - Self::Echap => CslType::Chapter, - Self::Edbook => CslType::Book, - Self::Ejour => CslType::ArticleJournal, - Self::Elec => CslType::Article, - Self::Encyc => CslType::EntryEncyclopedia, - Self::Equa => CslType::Article, - Self::Figure => CslType::Figure, - Self::Gen => CslType::Article, - Self::Govdoc => CslType::Legislation, - Self::Grant => CslType::Legislation, - Self::Hear => CslType::Article, - Self::Icomm => CslType::PersonalCommunication, - Self::Inpr => CslType::PaperConference, - Self::Jfull => CslType::ArticleJournal, - Self::Jour => CslType::ArticleJournal, - Self::Legal => CslType::Legislation, - Self::Manscpt => CslType::Manuscript, - Self::Map => CslType::Map, - Self::Mgzn => CslType::ArticleMagazine, - Self::Mpct => CslType::MotionPicture, - Self::Multi => CslType::Webpage, - Self::Music => CslType::Song, - Self::News => CslType::ArticleNewspaper, - Self::Pamp => CslType::Pamphlet, - Self::Pat => CslType::Patent, - Self::Pcomm => CslType::PersonalCommunication, - Self::Rprt => CslType::Report, - Self::Ser => CslType::Article, - Self::Slide => CslType::Article, - Self::Sound => CslType::Song, - Self::Stand => CslType::Article, - Self::Stat => CslType::Legislation, - Self::Std => CslType::Article, - Self::Thes => CslType::Thesis, - Self::Unpb => CslType::Article, - Self::Video => CslType::MotionPicture, - } - } -} - -#[derive(Debug, PartialEq, Eq, Clone, Default, Serialize, Deserialize)] -pub struct RisReference { - pub id: Option<String>, - pub ty: Option<RisType>, - pub editors: Vec<String>, - pub tertiary_authors: Vec<String>, - pub subsidiary_authors: Vec<String>, - pub abstrct: Option<String>, - pub author_address: Option<String>, - pub accession_number: Option<String>, - pub authors: Vec<String>, - pub book_or_conference: Option<String>, - pub custom1: Option<String>, - pub custom2: Option<String>, - pub custom3: Option<String>, - pub custom4: Option<String>, - pub custom5: Option<String>, - pub custom6: Option<String>, - pub custom7: Option<String>, - pub custom8: Option<String>, - pub caption: Option<String>, - pub call_number: Option<String>, - pub place: Option<String>, - pub date: Option<String>, - pub name_of_database: Option<String>, - pub doi: Option<String>, - pub database_provider: Option<String>, - pub end_page: Option<String>, - pub edition: Option<String>, - pub issue: Option<String>, - pub journal: Option<String>, - pub keywords: Vec<String>, - pub file_attachments: Vec<String>, - pub figure: Option<String>, - pub language: Option<String>, - pub label: Option<String>, - pub number: Option<String>, - pub type_of_work: Option<String>, - pub notes: Vec<String>, - pub number_of_volumes: Option<String>, - pub original_publication: Option<String>, - pub publisher: Option<String>, - pub year: Option<String>, - pub reviewed_item: Option<String>, - pub research_notes: Option<String>, - pub reprint_edition: Option<String>, - pub section: Option<String>, - pub isbn_or_issn: Option<String>, - pub start_page: Option<String>, - pub short_title: Option<String>, - pub primary_title: Option<String>, - pub secondardy_title: Option<String>, - pub tertiary_title: Option<String>, - pub translated_authors: Vec<String>, - pub title: Option<String>, - pub translated_title: Option<String>, - pub url: Option<String>, - pub volume: Option<String>, - pub access_date: Option<String>, -} - -#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] -pub struct RisLibrary { - pub references: Vec<RisReference>, -} - -impl RisLibrary { - pub fn parse<'a, I: Iterator<Item = &'a str>>(lines: I) -> Self { - let mut library = Self { - references: Vec::new(), - }; - - let mut reference: RisReference = RisReference::default(); - for line in lines { - let line = line.trim(); - if line == "" { - continue; - } - - if line == "ER -" { - library.references.push(reference); - reference = RisReference::default(); - continue; - } - - let chars: Vec<_> = line.chars().collect(); - if chars.len() < 7 || chars[4] != '-' { - continue; - } - - let key: String = (&chars[..2]).iter().collect(); - let value: String = (&chars[6..]).iter().collect(); - match key.to_uppercase().as_str() { - "TY" => reference.ty = RisType::parse(&value), - "A2" => reference.editors.push(value), - "A3" => reference.tertiary_authors.push(value), - "A4" => reference.subsidiary_authors.push(value), - "AB" => reference.abstrct = Some(value), - "AD" => reference.author_address = Some(value), - "AN" => reference.accession_number = Some(value), - "AU" => reference.authors.push(value), - "BT" => reference.book_or_conference = Some(value), - "C1" => reference.custom1 = Some(value), - "C2" => reference.custom2 = Some(value), - "C3" => reference.custom3 = Some(value), - "C4" => reference.custom4 = Some(value), - "C5" => reference.custom5 = Some(value), - "C6" => reference.custom6 = Some(value), - "C7" => reference.custom7 = Some(value), - "C8" => reference.custom8 = Some(value), - "CA" => reference.caption = Some(value), - "CN" => reference.call_number = Some(value), - "CY" => reference.place = Some(value), - "DA" => reference.date = Some(value), - "DB" => reference.name_of_database = Some(value), - "DO" => reference.doi = Some(value), - "DP" => reference.database_provider = Some(value), - "ED" => reference.editors.push(value), - "EP" => reference.end_page = Some(value), - "ET" => reference.edition = Some(value), - "ID" => reference.id = Some(value), - "IS" => reference.issue = Some(value), - "JO" => reference.journal = Some(value), - "J2" => reference.journal = Some(value), - "KW" => reference.keywords.push(value), - "L1" => reference.file_attachments.push(value), - "L4" => reference.figure = Some(value), - "LA" => reference.language = Some(value), - "LB" => reference.label = Some(value), - "M1" => reference.number = Some(value), - "M3" => reference.type_of_work = Some(value), - "N1" => reference.notes.push(value), - "N2" => reference.abstrct = Some(value), - "NV" => reference.number_of_volumes = Some(value), - "OP" => reference.original_publication = Some(value), - "PB" => reference.publisher = Some(value), - "PY" => reference.year = Some(value), - "RI" => reference.reviewed_item = Some(value), - "RN" => reference.research_notes = Some(value), - "RP" => reference.reprint_edition = Some(value), - "SE" => reference.section = Some(value), - "SN" => reference.isbn_or_issn = Some(value), - "SP" => reference.start_page = Some(value), - "ST" => reference.short_title = Some(value), - "T1" => reference.primary_title = Some(value), - "T2" => reference.secondardy_title = Some(value), - "T3" => reference.tertiary_title = Some(value), - "TA" => reference.translated_authors.push(value), - "TI" => reference.title = Some(value), - "TT" => reference.translated_title = Some(value), - "U1" => reference.type_of_work = Some(value), - "UR" => reference.url = Some(value), - "VL" => reference.volume = Some(value), - "Y2" => reference.access_date = Some(value), - _ => (), - } - } - library - } -} - -impl Into<Reference> for RisReference { - fn into(self) -> Reference { - let csl_type = self.ty.expect("RIS type is missing").csl(); - let mut date: FnvHashMap<DateVariable, DateOrRange> = FnvHashMap::default(); - let mut name: FnvHashMap<NameVariable, Vec<Name>> = FnvHashMap::default(); - let mut number: FnvHashMap<NumberVariable, NumericValue> = FnvHashMap::default(); - let mut ordinary: FnvHashMap<Variable, String> = FnvHashMap::default(); - - if let Some(access_date) = self.access_date { - date.insert(DateVariable::Accessed, parse_date_or_range(access_date)); - } - - name.insert(NameVariable::Author, parse_authors(self.authors)); - name.insert(NameVariable::Editor, parse_authors(self.editors)); - - if let Some(container_title) = self - .journal - .or(self.name_of_database) - .or(self.book_or_conference) - { - ordinary.insert(Variable::ContainerTitle, container_title.clone()); - ordinary.insert(Variable::CollectionTitle, container_title); - } - - if let Some(value) = self.date.or(self.year) { - let value = parse_date_or_range(value); - date.insert(DateVariable::Issued, value.clone()); - date.insert(DateVariable::EventDate, value); - } - - if let Some(url) = self.url { - ordinary.insert(Variable::URL, url); - } - - let notes = self.notes; - ordinary.insert( - Variable::Note, - self.research_notes.unwrap_or_else(|| notes.join("\n")), - ); - - if let Some(issue) = self.issue { - number.insert(NumberVariable::Issue, parse_number(issue)); - } - - if let Some(num) = self.number { - number.insert(NumberVariable::Number, parse_number(num)); - } - - if let Some(place) = self.place { - ordinary.insert(Variable::EventPlace, place.clone()); - ordinary.insert(Variable::PublisherPlace, place); - } - - if let Some(abstrct) = self.abstrct { - ordinary.insert(Variable::Abstract, abstrct); - } - - if let Some(call_number) = self.call_number { - ordinary.insert(Variable::CallNumber, call_number); - } - - if let Some(doi) = self.doi { - ordinary.insert(Variable::DOI, doi); - } - - if let Some(edition) = self.edition { - number.insert(NumberVariable::Edition, parse_number(edition)); - } - - if let Some(isbn_or_issn) = self.isbn_or_issn { - ordinary.insert(Variable::ISBN, isbn_or_issn.clone()); - ordinary.insert(Variable::ISSN, isbn_or_issn); - } - - ordinary.insert(Variable::Keyword, self.keywords.join(", ")); - - if let Some(number_of_volumes) = self.number_of_volumes { - number.insert( - NumberVariable::NumberOfVolumes, - parse_number(number_of_volumes), - ); - } - - if let Some(original_publication) = self.original_publication { - ordinary.insert(Variable::OriginalTitle, original_publication); - } - - match (self.start_page, self.end_page) { - (Some(start_page), Some(end_page)) => { - number.insert( - NumberVariable::Page, - NumericValue::Str(format!("{}-{}", start_page, end_page)), - ); - } - (Some(page), None) | (None, Some(page)) => { - number.insert(NumberVariable::Page, parse_number(page)); - } - (None, None) => {} - } - - if let Some(publisher) = self.publisher { - ordinary.insert(Variable::Publisher, publisher); - } - - if let Some(reviewed_item) = self.reviewed_item { - ordinary.insert(Variable::ReviewedTitle, reviewed_item); - } - - if let Some(section) = self.section { - ordinary.insert(Variable::Section, section); - } - - if let Some(short_title) = self.short_title { - ordinary.insert(Variable::TitleShort, short_title); - } - - if let Some(title) = self.title { - ordinary.insert(Variable::Title, title); - } - - if let Some(volume) = self.volume { - number.insert(NumberVariable::Volume, parse_number(volume)); - } - - Reference { - id: Atom::from(self.id.or(self.label).expect("RIS id is missing").as_str()), - csl_type, - language: None, - name, - number, - date, - ordinary, - } - } -} - -fn parse_number(value: String) -> NumericValue { - match value.parse() { - Ok(value) => NumericValue::num(value), - Err(_) => NumericValue::Str(value), - } -} - -fn parse_authors(authors: Vec<String>) -> Vec<Name> { - authors - .into_iter() - .flat_map(|author| name::parse(&author)) - .collect() -} - -fn parse_date_or_range(value: String) -> DateOrRange { - parse_date(&value) - .map(DateOrRange::Single) - .unwrap_or_else(|| DateOrRange::Literal(value)) -} - -fn parse_date(value: &str) -> Option<Date> { - let mut parts = value.split('/'); - let year: i32 = parts.next()?.parse().ok()?; - match parts.next().and_then(|p| p.parse().ok()) { - Some(month) => match parts.next().and_then(|p| p.parse().ok()) { - Some(day) => Some(Date::new(year, month, day)), - None => Some(Date::new(year, month, 0)), - }, - None => Some(Date::new(year, 0, 0)), - } -} |