/BibLaTeX.js
JavaScript | 769 lines | 659 code | 63 blank | 47 comment | 207 complexity | d5f3186fe0aed3d7673e303aa2b2f782 MD5 | raw file
- {
- "translatorID": "b6e39b57-8942-4d11-8259-342c46ce395f",
- "translatorType": 2,
- "label": "BibLaTeX",
- "creator": "Simon Kornblith, Richard Karnesky and Anders Johansson",
- "target": "bib",
- "minVersion": "2.1.9",
- "maxVersion": "null",
- "priority": 100,
- "inRepository": true,
- "configOptions":{"getCollections": true},
- "displayOptions": {
- "exportCharset": "UTF-8",
- "exportNotes": false,
- "exportFileData": false,
- "useJournalAbbreviation": false
- },
- "lastUpdated": "2014-06-23 05:03:43"
- }
- //%a = first listed creator surname
- //%y = year
- //%t = first word of title
- var citeKeyFormat = "%a_%t_%y";
- var fieldMap = {
- location: "place",
- chapter: "chapter",
- edition: "edition",
- title: "title",
- volume: "volume",
- rights: "rights", //it's rights in zotero nowadays
- isbn: "ISBN",
- issn: "ISSN",
- url: "url",
- doi: "DOI",
- series: "series",
- shorttitle: "shortTitle",
- abstract: "abstractNote",
- volumes: "numberOfVolumes",
- version: "version",
- eventtitle: "conferenceName",
- pages: "pages",
- pagetotal: "numPages"
- };
- //more conversions done below with special rules
- /**
- * Identifiers from item.extra
- * Copied from BibTeX
- */
- // Exported in BibTeX and BibLaTeX
- var revExtraIds = {
- LCCN: 'lccn',
- MR: 'mrnumber',
- Zbl: 'zmnumber',
- PMCID: 'pmcid',
- PMID: 'pmid'
- };
- // Imported by BibTeX. Exported by BibLaTeX only
- var revEprintIds = {
- // eprinttype: Zotero label
-
- // From BibLaTeX manual
- arXiv: 'arxiv', // Sorry, but no support for eprintclass yet
- JSTOR: 'jstor',
- //PMID: 'pubmed', // Not sure if we should do this instead
- HDL: 'hdl',
- GoogleBooksID: 'googlebooks'
- }
- function parseExtraFields(extra) {
- var lines = extra.split(/[\r\n]+/);
- var fields = [];
- for(var i=0; i<lines.length; i++) {
- var rec = { raw: lines[i] };
- var line = lines[i].trim();
- var splitAt = line.indexOf(':');
- if(splitAt > 1) {
- rec.field = line.substr(0,splitAt).trim();
- rec.value = line.substr(splitAt + 1).trim();
- }
- fields.push(rec);
- }
- return fields;
- }
- function extraFieldsToString(extra) {
- var str = '';
- for(var i=0; i<extra.length; i++) {
- if(!extra[i].raw) {
- str += '\n' + extra[i].field + ': ' + extra[i].value;
- } else {
- str += '\n' + extra[i].raw;
- }
- }
-
- return str.substr(1);
- }
- //POTENTIAL ISSUES
- //accessDate:"accessDate", //only written on attached webpage snapshots by zotero
- var zotero2biblatexTypeMap = {
- "book": "book",
- "bookSection": "incollection",
- "journalArticle": "article",
- "magazineArticle": "article",
- "newspaperArticle": "article",
- "thesis": "thesis",
- "letter": "letter",
- "manuscript": "unpublished",
- "interview": "misc",
- "film": "movie",
- "artwork": "artwork",
- "webpage": "online",
- "conferencePaper": "inproceedings",
- "report": "report",
- "bill": "legislation",
- "case": "jurisdiction",
- "hearing": "jurisdiction",
- "patent": "patent",
- "statute": "legislation",
- "email": "letter",
- "map": "misc",
- "blogPost": "online",
- "instantMessage": "misc",
- "forumPost": "online",
- "audioRecording": "audio",
- "presentation": "unpublished",
- "videoRecording": "video",
- "tvBroadcast": "misc",
- "radioBroadcast": "misc",
- "podcast": "audio",
- "computerProgram": "software",
- "document": "misc",
- "encyclopediaArticle": "inreference",
- "dictionaryEntry": "inreference"
- };
- var alwaysMap = {
- "|": "{\\textbar}",
- "<": "{\\textless}",
- ">": "{\\textgreater}",
- "~": "{\\textasciitilde}",
- "^": "{\\textasciicircum}",
- "\\": "{\\textbackslash}",
- "{": "\\{",
- "}": "\\}"
- };
- //to map ISO language codes (tries to follow IETF RFC5646) to babel
- //language codes used in biblatex. Taken from Babel manual 3.9h.
- var babelLanguageMap = {
- "af": "afrikaans",
- "ar": "arabic",
- //bahasa (see malay and indonesian)
- "eu": "basque",
- "br": "breton",
- "bg": "bulgarian",
- "ca": "catalan",
- "hr": "croatian",
- "cz": "czech",
- "da": "danish",
- "nl": "dutch",
- "en": {
- "": "english", //same as american
- "US": "american",
- "GB": "british",
- "CA": "canadian",
- "AU": "australian",
- "NZ": "newzealand"
- },
- "eo": "esperanto",
- "et": "estonian",
- //ethiop (package for many languages)
- "fa": "farsi",
- "fi": "finnish",
- "fr": {
- "": "french",
- "CA": "canadien"
- //frenchle (a special package)
- },
- "fur": "friulan",
- "gl": "galician",
- "de": {
- "": "german",
- "AT": "austrian",
- "DE-1996": "ngerman", //these are valid IETF language codes
- "AT-1996": "naustrian",
- "1996": "ngerman"
- },
- "el": {
- "": "greek",
- "polyton": "polutonikogreek"
- },
- "he": "hebrew",
- "hi": "hindi",
- "is": "icelandic",
- "id": "indonesian", //aliases: bahasai, indon
- "ia": "interlingua",
- "ga": "irish",
- "it": "italian",
- "ja": "japanese",
- "la": "latin",
- "lv": "latvian",
- "lt": "lithuanian",
- "dsb": "lowersorbian",
- "hu": "magyar",
- "zlm": "malay", //aliases: bahasam, melayu (currently, there's no
- //real difference between bahasam and bahasai in babel)
- "mn": "mongolian",
- "se": "samin",
- "nn": "nynorsk", //nynorsk
- "nb": "norsk", //bokmål
- "no": "norwegian", //"no" could be used, norwegian is an alias for "norsk" in babel
- "zh": {
- "": "pinyin", //only supported chinese in babel is the romanization pinyin?
- "Latn": "pinyin"
- },
- "pl": "polish",
- "pt": {
- "": "portuguese",
- "PT": "portuguese",
- "BR": "brazil"
- },
- "ro": "romanian",
- "rm": "romansh",
- "ru": "russian",
- "gd": "scottish",
- "sr": {
- "": "serbian", //latin script as default?
- "Cyrl": "serbianc",
- "Latn": "serbian",
- },
- "sk": "slovak",
- "sl": "slovene",
- //spanglish (pseudo language)
- "es": "spanish",
- "sv": "swedish",
- "th": "thaicjk", //thaicjk preferred?
- "tr": "turkish",
- "tk": "turkmen",
- "uk": "ukrainian",
- "hsb": "uppersorbian",
- "vi": "vietnamese",
- "cy": "welsh",
- };
- // some fields are, in fact, macros. If that is the case then we should not put the
- // data in the braces as it will cause the macros to not expand properly
- function writeField(field, value, isMacro, noEscape) {
- if (!value && typeof value != "number") return;
- value = value + ""; // convert integers to strings
- Zotero.write(",\n\t" + field + " = ");
- if (!isMacro) Zotero.write("{");
- // url field is preserved, for use with \href and \url
- // Other fields (DOI?) may need similar treatment
- if (!noEscape && !isMacro && !(field == "url" || field == "doi" || field == "file" || field == "lccn")) {
- //var titleCase = isTitleCase(value); //figure this out before escaping all the characters
- // I hope these are all the escape characters! (except for < > which are handled later)
- value = value.replace(/[|\~\^\\\{\}]/g, mapEscape).replace(/[\#\$\%\&\_]/g, "\\$&");
- //convert the HTML markup allowed in Zotero for rich text to TeX
- value = mapHTMLmarkup(value);
- //escape < > if mapHTMLmarkup did not convert some
- value = value.replace(/[<>]/g, mapEscape);
- // Case of words with uppercase characters in non-initial positions is preserved with braces.
- // we're looking at all unicode letters
- var protectCaps = new ZU.XRegExp("\\b\\p{Letter}+\\p{Uppercase_Letter}\\p{Letter}*", 'g')
- if (field != "pages") {
- value = ZU.XRegExp.replace(value, protectCaps, "{$0}");
- }
- }
- //we write utf8
- //convert the HTML markup allowed in Zotero for rich text to TeX; excluding doi/url/file shouldn't be necessary, but better to be safe;
- if (!((field == "url") || (field == "doi") || (field == "file"))) value = mapHTMLmarkup(value);
- Zotero.write(value);
- if (!isMacro) Zotero.write("}");
- }
- function mapHTMLmarkup(characters) {
- //converts the HTML markup allowed in Zotero for rich text to TeX
- //since < and > have already been escaped, we need this rather hideous code - I couldn't see a way around it though.
- //italics and bold
- characters = characters.replace(/\{\\textless\}i\{\\textgreater\}(((?!\{\\textless\}\/i{\\textgreater\}).)+)\{\\textless\}\/i{\\textgreater\}/, "\\textit{$1}").replace(/\{\\textless\}b\{\\textgreater\}(((?!\{\\textless\}\/b{\\textgreater\}).)+)\{\\textless\}\/b{\\textgreater\}/g, "\\textbf{$1}");
- //sub and superscript
- characters = characters.replace(/\{\\textless\}sup\{\\textgreater\}(((?!\{\\textless\}\/sup\{\\textgreater\}).)+)\{\\textless\}\/sup{\\textgreater\}/g, "\$^{\\textrm{$1}}\$").replace(/\{\\textless\}sub\{\\textgreater\}(((?!\{\\textless\}\/sub\{\\textgreater\}).)+)\{\\textless\}\/sub\{\\textgreater\}/g, "\$_{\\textrm{$1}}\$");
- //two variants of small caps
- characters = characters.replace(/\{\\textless\}span\sstyle=\"small\-caps\"\{\\textgreater\}(((?!\{\\textless\}\/span\{\\textgreater\}).)+)\{\\textless\}\/span{\\textgreater\}/g, "\\textsc{$1}").replace(/\{\\textless\}sc\{\\textgreater\}(((?!\{\\textless\}\/sc\{\\textgreater\}).)+)\{\\textless\}\/sc\{\\textgreater\}/g, "\\textsc{$1}");
- return characters;
- }
- function mapEscape(character) {
- return alwaysMap[character];
- }
- // a little substitution function for BibTeX keys, where we don't want LaTeX
- // escaping, but we do want to preserve the base characters
- function tidyAccents(s) {
- var r = s.toLowerCase();
- // XXX Remove conditional when we drop Zotero 2.1.x support
- // This is supported in Zotero 3.0 and higher
- if (ZU.removeDiacritics !== undefined)
- r = ZU.removeDiacritics(r, true);
- else {
- // We fall back on the replacement list we used previously
- r = r.replace(new RegExp("[ä]", 'g'), "ae");
- r = r.replace(new RegExp("[ö]", 'g'), "oe");
- r = r.replace(new RegExp("[ü]", 'g'), "ue");
- r = r.replace(new RegExp("[àáâãå]", 'g'), "a");
- r = r.replace(new RegExp("æ", 'g'), "ae");
- r = r.replace(new RegExp("ç", 'g'), "c");
- r = r.replace(new RegExp("[èéêë]", 'g'), "e");
- r = r.replace(new RegExp("[ìíîï]", 'g'), "i");
- r = r.replace(new RegExp("ñ", 'g'), "n");
- r = r.replace(new RegExp("[òóôõ]", 'g'), "o");
- r = r.replace(new RegExp("œ", 'g'), "oe");
- r = r.replace(new RegExp("[ùúû]", 'g'), "u");
- r = r.replace(new RegExp("[ýÿ]", 'g'), "y");
- }
- return r;
- };
- var numberRe = /^[0-9]+/;
- // Below is a list of words that should not appear as part of the citation key
- // in includes the indefinite articles of English, German, French and Spanish, as well as a small set of English prepositions whose
- // force is more grammatical than lexical, i.e. which are likely to strike many as 'insignificant'.
- // The assumption is that most who want a title word in their key would prefer the first word of significance.
- var citeKeyTitleBannedRe = /\b(a|an|the|some|from|on|in|to|of|do|with|der|die|das|ein|eine|einer|eines|einem|einen|un|une|la|le|l\'|el|las|los|al|uno|una|unos|unas|de|des|del|d\')(\s+|\b)/g;
- var citeKeyConversionsRe = /%([a-zA-Z])/;
- var citeKeyCleanRe = /[^a-z0-9\!\$\&\*\+\-\.\/\:\;\<\>\?\[\]\^\_\`\|]+/g;
- var citeKeyConversions = {
- "a": function (flags, item) {
- if (item.creators && item.creators[0] && item.creators[0].lastName) {
- return item.creators[0].lastName.toLowerCase().replace(/ /g, "_").replace(/,/g, "");
- }
- return "";
- },
- "t": function (flags, item) {
- if (item["title"]) {
- return item["title"].toLowerCase().replace(citeKeyTitleBannedRe, "").split(/\s+/g)[0];
- }
- return "";
- },
- "y": function (flags, item) {
- if (item.date) {
- var date = Zotero.Utilities.strToDate(item.date);
- if (date.year && numberRe.test(date.year)) {
- return date.year;
- }
- }
- return "????";
- }
- }
- //checks whether an item contains any creator of type ctype
- function creatorCheck(item, ctype) {
- if (item.creators && item.creators.length) {
- for (var i=0; i<item.creators.length; i++) {
- if (item.creators[i].creatorType == ctype) {
- return true; //found a ctype creator
- }
- }
- }
- //didn't find any ctype creator (or no creators at all)
- return false;
- }
- function buildCiteKey(item, citekeys) {
- var basekey = "";
- var counter = 0;
- citeKeyFormatRemaining = citeKeyFormat;
- while (citeKeyConversionsRe.test(citeKeyFormatRemaining)) {
- if (counter > 100) {
- Zotero.debug("Pathological BibTeX format: " + citeKeyFormat);
- break;
- }
- var m = citeKeyFormatRemaining.match(citeKeyConversionsRe);
- if (m.index > 0) {
- //add data before the conversion match to basekey
- basekey = basekey + citeKeyFormatRemaining.substr(0, m.index);
- }
- var flags = ""; // for now
- var f = citeKeyConversions[m[1]];
- if (typeof (f) == "function") {
- var value = f(flags, item);
- Zotero.debug("Got value " + value + " for %" + m[1]);
- //add conversion to basekey
- basekey = basekey + value;
- }
- citeKeyFormatRemaining = citeKeyFormatRemaining.substr(m.index + m.length);
- counter++;
- }
- if (citeKeyFormatRemaining.length > 0) {
- basekey = basekey + citeKeyFormatRemaining;
- }
- // for now, remove any characters not explicitly known to be allowed;
- // we might want to allow UTF-8 citation keys in the future, depending
- // on implementation support.
- //
- // no matter what, we want to make sure we exclude
- // " # % ' ( ) , = { } ~ and backslash
- // however, we want to keep the base characters
- basekey = tidyAccents(basekey);
- basekey = basekey.replace(citeKeyCleanRe, "");
- var citekey = basekey;
- var i = 0;
- while (citekeys[citekey]) {
- i++;
- citekey = basekey + "-" + i;
- }
- citekeys[citekey] = true;
- return citekey;
- }
-
- var filePathSpecialChars = '\\\\:;{}$'; // $ for Mendeley
- var encodeFilePathRE = new RegExp('[' + filePathSpecialChars + ']', 'g');
- function encodeFilePathComponent(value) {
- return value.replace(encodeFilePathRE, "\\$&");
- }
- function doExport() {
- //Zotero.write("% biblatex export generated by Zotero "+Zotero.Utilities.getVersion());
- // to make sure the BOM gets ignored
- Zotero.write("\n");
- var first = true;
- var citekeys = new Object();
- var item;
- while (item = Zotero.nextItem()) {
- //don't export standalone notes and attachments
- if (item.itemType == "note" || item.itemType == "attachment") continue;
- var noteused = false; //a switch for keeping track whether the
- //field "note" has been written to
- // determine type
- var type = zotero2biblatexTypeMap[item.itemType];
- if (typeof (type) == "function") {
- type = type(item);
- }
- //inbook is reasonable at times, using a bookauthor should
- //indicate this
- if(item.itemType == "bookSection" &&
- creatorCheck(item, "bookAuthor")) type = "inbook";
- //a book without author but with editors is a collection
- if(item.itemType == "book" && !creatorCheck(item,"author") &&
- creatorCheck(item, "editor")) type = "collection";
- //biblatex recommends us to use mvbook for multi-volume books
- if (type == "book" && item.volume) type = "mvbook"
- if (!type) type = "misc";
- var citekey = "";
- if (!citekey) {
- // create a unique citation key
- citekey = buildCiteKey(item, citekeys);
- }
- // write citation key (removed the comma)
- Zotero.write((first ? "" : "\n\n") + "@" + type + "{" + citekey);
- first = false;
- for (var field in fieldMap) {
- if (item[fieldMap[field]]) {
- writeField(field, item[fieldMap[field]]);
- }
- }
- // Fields needing special treatment and not easily translatable via fieldMap
- //e.g. where fieldname translation is dependent upon type, or special transformations
- //has to be made
- //all kinds of numbers
- if (item.reportNumber || item.seriesNumber || item.patentNumber || item.billNumber || item.episodeNumber || item.number) {
- writeField("number", item.reportNumber || item.seriesNumber || item.patentNumber || item.billNumber || item.episodeNumber || item.number);
- }
- //split numeric and nonnumeric issue specifications (for journals) into "number" and "issue"
- if (item.issue) { //issue
- var jnumber = parseInt(item.issue);
- if (!isNaN(jnumber)) {
- writeField("number", jnumber);
- } else {
- writeField("issue", item.issue);
- }
- }
- //publicationTitles and special titles
- if (item.publicationTitle) {
- if (item.itemType == "bookSection" || item.itemType == "conferencePaper" || item.itemType == "dictionaryEntry" || item.itemType == "encyclopediaArticle") {
- writeField("booktitle", item.publicationTitle);
- } else if (item.itemType == "magazineArticle" || item.itemType == "newspaperArticle") {
- writeField("journaltitle", item.publicationTitle);
- } else if (item.itemType == "journalArticle") {
- if (Zotero.getOption("useJournalAbbreviation")) {
- writeField("journaltitle", item.journalAbbreviation);
- } else {
- writeField("journaltitle", item.publicationTitle);
- writeField("shortjournal", item.journalAbbreviation);
- }
- }
- }
- if (item.websiteTitle || item.forumTitle || item.blogTitle || item.programTitle) {
- writeField("titleaddon", item.websiteTitle || item.forumTitle || item.blogTitle || item.programTitle);
- }
- //publishers
- if (item.publisher) {
- if (item.itemType == "thesis" || item.itemType == "report") {
- writeField("institution", item.publisher);
- } else {
- writeField("publisher", item.publisher);
- }
- }
- //things concerning "type"
- if (item.itemType == "letter") {
- if (item.letterType) {
- writeField("type", item.letterType);
- } else {
- writeField("type", "Letter"); //this isn't optimal, perhaps later versions of biblatex will add some suitable localization key
- }
- } else if (item.itemType == "email") {
- writeField("type", "E-mail");
- } else if (item.itemType == "thesis" &&
- (!item.thesisType || item.thesisType.search(/ph\.?d/i) != -1)) {
- writeField("type", "phdthesis");
- } else if (item.manuscriptType || item.thesisType || item.websiteType || item.presentationType || item.reportType || item.mapType) {
- writeField("type", item.manuscriptType || item.thesisType || item.websiteType || item.presentationType || item.reportType || item.mapType);
- }
- if (item.presentationType || item.manuscriptType) {
- writeField("howpublished", item.presentationType || item.manuscriptType);
- }
- //case of specific eprint-archives in archive-fields
- if (item.archive && item.archiveLocation) {
- if (item.archive == "arXiv" || item.archive == "arxiv") {
- writeField("eprinttype", "arxiv");
- writeField("eprint", item.archiveLocation);
- if (item.callNumber) { //assume call number is used for arxiv class
- writeField("eprintclass", item.callNumber)
- }
- } else if (item.archive = "JSTOR" || item.archive == "jstor") {
- writeField("eprinttype", "jstor");
- writeField("eprint", item.archiveLocation);
- } else if (item.archive = "PubMed" || item.archive == "pubmed") {
- writeField("eprinttype", "pubmed");
- writeField("eprint", item.archiveLocation);
- } else if (item.archive = "HDL" || item.archive == "hdl") {
- writeField("eprinttype", "hdl");
- writeField("eprint", item.archiveLocation);
- } else if (item.archive = "googlebooks" || item.archive == "Google Books") {
- writeField("eprinttype", "googlebooks");
- writeField("eprint", item.archiveLocation);
- }
- }
- //presentations have a meetingName field which we want to
- //map to note
- if (item.meetingName) {
- writeField("note", item.meetingName);
- noteused = true;
- }
- if (item.creators && item.creators.length) {
- // split creators into subcategories
- var author = "";
- var bookauthor = "";
- var commentator = "";
- var editor = "";
- var editora = "";
- var editorb = "";
- var holder = "";
- var translator = "";
- var noEscape = false;
- for (var i=0; i<item.creators.length; i++) {
- var creator = item.creators[i];
- var creatorString;
- if (creator.firstName) {
- var fname = creator.firstName.split(/\s*,!?\s*/);
- fname.push(fname.shift()); // If we have a Jr. part(s), it should precede first name
- creatorString = creator.lastName + ", " + fname.join(', ');
- } else {
- creatorString = creator.lastName;
- }
-
- creatorString = creatorString.replace(/[|\<\>\~\^\\\{\}]/g, mapEscape)
- .replace(/([\#\$\%\&\_])/g, "\\$1");
-
- if (creator.fieldMode == true) { // fieldMode true, assume corporate author
- creatorString = "{" + creatorString + "}";
- noEscape = true;
- } else {
- creatorString = creatorString.replace(/ (and) /gi, ' {$1} ');
- }
- if (creator.creatorType == "author" || creator.creatorType == "interviewer" || creator.creatorType == "director" || creator.creatorType == "programmer" || creator.creatorType == "artist" || creator.creatorType == "podcaster" || creator.creatorType == "presenter") {
- author += " and " + creatorString;
- } else if (creator.creatorType == "bookAuthor") {
- bookauthor += " and " + creatorString;
- } else if (creator.creatorType == "commenter") {
- commentator += " and " + creatorString;
- } else if (creator.creatorType == "editor") {
- editor += " and " + creatorString;
- } else if (creator.creatorType == "inventor") {
- holder += " and " + creatorString;
- } else if (creator.creatorType == "translator") {
- translator += " and " + creatorString;
- } else if (creator.creatorType == "seriesEditor") { //let's call them redacors
- editorb += " and " + creatorString;
- } else { // the rest into editora with editoratype = collaborator
- editora += " and " + creatorString;
- }
- }
- //remove first " and " string
- if (author) {
- writeField("author", author.substr(5), false, noEscape);
- }
- if (bookauthor) {
- writeField("bookauthor", bookauthor.substr(5), false, noEscape);
- }
- if (commentator) {
- writeField("commentator", commenter.substr(5), false, noEscape);
- }
- if (editor) {
- writeField("editor", editor.substr(5), false, noEscape);
- }
- if (editora) {
- writeField("editora", editora.substr(5), false, noEscape);
- writeField("editoratype", "collaborator");
- }
- if (editorb) {
- writeField("editorb", editorb.substr(5), false, noEscape);
- writeField("editorbtype", "redactor");
- }
- if (holder) {
- writeField("holder", holder.substr(5), false, noEscape);
- }
- if (translator) {
- writeField("translator", translator.substr(5), false, noEscape);
- }
- }
- if (item.accessDate) {
- writeField("urldate", Zotero.Utilities.strToISO(item.accessDate));
- }
- //TODO enable handling of date ranges when that's added to zotero
- if (item.date) {
- writeField("date", Zotero.Utilities.strToISO(item.date));
- }
- //Map Languages to biblatex-field "langid" (used for
- //hyphenation with a correct setting of the "autolang" option)
- //if possible. See babelLanguageMap above for languagecodes to use
- if (item.language) {
- var langcode = item.language.match(/^([a-z]{2,3})(?:[^a-z](.+))?$/i); //not too strict
- if(langcode){
- var lang = babelLanguageMap[langcode[1]];
- if (typeof lang == 'string') {
- //if there are no variants for this language
- writeField("langid", lang);
- } else if (typeof lang == 'object') {
- var variant = lang[langcode[2]];
- if (variant) {
- writeField("langid", variant);
- } else {
- writeField("langid", lang[""]); //use default variant
- }
- }
- }
- }
- if(item.extra) {
- // Export identifiers
- var extraFields = parseExtraFields(item.extra);
- // Dedicated fields
- for(var i=0; i<extraFields.length; i++) {
- var rec = extraFields[i];
- if(!rec.field) continue;
-
- if(!revExtraIds[rec.field] && !revEprintIds[rec.field]) continue;
-
- var value = rec.value.trim();
- if(!value) continue;
-
- var label;
- if(label = revExtraIds[rec.field]) {
- writeField(label, '{'+value+'}', true);
- } else if (label = revEprintIds[rec.field]) {
- writeField('eprinttype', label);
- writeField('eprint', '{' + value + '}', true);
- }
- extraFields.splice(i, 1);
- i--;
- }
-
- var extra = extraFieldsToString(extraFields);
- if(extra && !noteused) writeField("note", extra);
- }
- if (item.tags && item.tags.length) {
- var tagString = "";
- for (var i=0; i<item.tags.length; i++) {
- tagString += ", " + item.tags[i].tag;
- }
- writeField("keywords", tagString.substr(2));
- }
- if (item.notes && Zotero.getOption("exportNotes")) {
- for (var i=0; i<item.notes.length; i++) {
- var note = item.notes[i];
- writeField("annotation", Zotero.Utilities.unescapeHTML(note["note"]));
- }
- }
- if (item.attachments) {
- var attachmentString = "";
- for (var i=0; i<item.attachments.length; i++) {
- var attachment = item.attachments[i];
- if (Zotero.getOption("exportFileData") && attachment.saveFile) {
- attachment.saveFile(attachment.defaultPath, true);
- attachmentString += ";" + encodeFilePathComponent(attachment.title) + ":"
- + encodeFilePathComponent(attachment.defaultPath) + ":"
- + encodeFilePathComponent(attachment.mimeType);
- } else if (attachment.localPath) {
- attachmentString += ";" + encodeFilePathComponent(attachment.title) + ":"
- + encodeFilePathComponent(attachment.localPath) + ":"
- + encodeFilePathComponent(attachment.mimeType);
- }
- }
- if (attachmentString) {
- writeField("file", attachmentString.substr(1));
- }
- }
- Zotero.write("\n}");
- }
- }