Skip to content

Instantly share code, notes, and snippets.

@spartanroc
Created May 5, 2011 06:17
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save spartanroc/956623 to your computer and use it in GitHub Desktop.
Save spartanroc/956623 to your computer and use it in GitHub Desktop.
New Features and Improvements on Zotero's Support of BibTeX Export
===============
For the better of the research world that enjoys Zotero, Latex/BibTeX,
JabRef, Mendeley, SciPlore MindMapping, etc.
first version: May 4, 2011
************************
* spartanroc@gmail.com *
************************
===============
New Updates:
updated: Mar 16, 2012
1. updated for Zotero 3.0.3
2. item_local.js is replaced by translate_item.js
3. installation guide:
(a) go to https://gist.github.com/956623/ and download the full tar file
or the following 4 files: translate.js, translate_item.js, BibTeXTan.js,
and BibTeXKeyOnly.js
(b) go to your firefox profile directory, then use any zip tool to open
extensions/zotero@chnm.gmu.edu/chrome/zotero.jar. Then navigate to the
archive directory: content/zotero/xpcom/translation/ and use drag & drop
to replace the two files of translate.js and translate_item.js in the jar
file.
(c) go to your zotero data directory (default location is called zotero
right under your firefox profile directory). copy the following files
to the translators directory: BibTeXTan.js and BibTeXKeyOnly.js
(d) restart your firefox.
===============
updated: May 7, 2011
1. unicode conversion of greek letters are also put in the reverse mapping
table per Rick Karnesky's suggestion.
2. getPref() can now access only the subtree preferences prefixed with
'translator.' based on the discussion with Avram Lyon. This is a modification
for one of the core files, translate.js.
3. export of the local path information of attachments is optional now to
address Rick Karnesky's concern. The new preference setting of a boolean
extensions.zotero.translator.bibtexExportLocalFilePath is used.
The default is no ( i.e., same as before).
4. escaping of Latex markups is controlled via a new preference setting of
extensions.zotero.translator.bibtexPreserveLatex. The default is not
preserving, i.e., escaping markups the same way as before.
5. use (last name, first name) format for creator's name output to remove
possible ambiguity of the current format (first name last name).
===============
List of files:
reame -- this file
bibtex_js_and_path.gz -- tarball of everything
BibTeXTan.js -- to replace the translator BibTeX.js
BibTeXTan.patch -- patch file relative to BibTeX.js of zotero v2.1.6
BibTeXKeyOnly.js -- new translator for quickcopy / drag&drop export of cite keys
BibTeXTanKeyOnly.patch -- patch file relative to BibTeXTan.js
item_local.js -- to replace content/zotero/xpcom/translation/item_local.js
item_local.patch -- patch file to that of zotero v2.1.6
translate.js -- to replace content/zotero/xpcom/translation/translate.js
translate.patch -- patch file to that of zotero v2.1.6
===============
New Features and Improvements on BibTeX Export:
1. very flexible bibtex key format definition using the fields of creators,
title, journal, year, volume, pages. including options of lower/upper cases,
initials, lengths, n-th author/word picking, etc. it is also easy to extend
to include new fields for key generation.
2. to resolve possible key collisions, users can specify their own suffix
either alphabetic or numeric.
3. a special field (e.g., callNumber or shortTitle) can be dedicated for export
of keys either pre-assigned or stored that are better done manually. Until
zotero provides a dedicated BibTeX key field or some type of local id field,
this is still a very appealing hack for most latex/bibtex users.
4. attachments like pdf files can be exported as file links only. The local
real path is stored in the file field. No need to export the large files
themselves. Keeping two copies on the machine is not good, in particular
for people who like to make comments on pdf files. This is also making zotero
cooperating better with other external applications like JabRef and SciPlore.
The real file export still works as expected if the option of exportFileData is
set to true. Only a small change in item_local.js is needed for such a benefit.
5. unicode conversions for greek letters.
6. the strings of controlling the 1,2,3 features are easily modified through
browser prefs: extensions.zotero.bibtexKeyFormat,
extensions.zotero.bibtexKeyCollisionFormat, extensions.zotero.bibtexKeyField.
No need to touch the translator itself for user's own definition. No formats
will be lost after upgrade. All of these only require a small modification in
translate.js. It also opens up access to prefs for all the other translators
which could be potentially very useful for others as well.
7. A Cite Key only stripped down translator is provided as well in a similar way
that Andrew Leifer did. This is very convenient for quickCopy or drag&drop in
latex editing.
8. some other minor improvements for bibtex export such as better treatment for
latex special characters like $,\,_,^, etc.
===============
How Key Format String is defined?
var citeKeyFormat = Zotero.getPrefs("bibtexKeyFormat") ? Zotero.getPrefs("bibtexKeyFormat") : "%au%yr%ti";
1. A general matching element is % followed by a two-letter label: for
matching field and specifying the lower/upper case for 1st/remaining letters.
2. Then it can be optionally followed by a number for the maximum length in
number of characters. (default=0: means all characters)
3. Last it can be also optionally followed by a number within curly brackets
for selecting the n-th word of the field (start from 0-th, the default).
4. The special repitive 2-letter labels like %TT, %aa, and %JJ are to group
the first letters only of surnames/words in corresponding fields.
5. Separators/indicators including +,-,:,., etc, and all letters and numbers
can be used in between the elements.
Some examples:
%au4%yr2%tt2 %AU_%yr_%TI %Au4-%Au4{1}:%JJ%yr:Vol%vo:Pg%pg-%pg{1}
%Au4{1} = first 4 letters of 2nd creator's surname (first letter capitalized)
%ti6{2} = first 6 letters of 3rd word in title (all lowercase)
%AA4 = initials of first 4 creators' surnames (uppercase)
%tt6 = first letters of first 6 words in title (lowercase)
%JJ5 = first letters of first 5 words in journal name (uppercase)
%yr = %yr4 = four-digit year, %yr2 = two-digit year
%vo = volume number
%pg = first page number
%pg{1} = last page number
===============
Collision Format: %a for alphabetic suffix, %n for numeric suffix
var citeKeyCollisionFormat = Zotero.getPrefs("bibtexKeyCollisionFormat") ? Zotero.getPrefs("bibtexKeyCollisionFormat") : "-%n";
===============
Specified Key Field: e.g. callNumber for using the stored key
var citeKeyField = Zotero.getPrefs("bibtexKeyField"); //e.g. callNumber
{
"translatorID": "12345",
"label": "BibTeX CiteKey-only Exporter",
"creator": "Simon Kornblith and Richard Karnesky with tweaks by Tan",
"target": "bib",
"minVersion": "2.1.9",
"maxVersion": "",
"priority": 200,
"inRepository": false,
"translatorType": 3,
"browserSupport": "gcs",
"lastUpdated": "2011-08-16 15:07:38"
}
/*
A hack similar to what Andrew Leifer did so that Zotero will Drag & Drop
citations in the latex form of "\cite{key1,key2,...}". The difference from
the full version is to have the output of doExport() cleaned out.
*/
// -- Tan --begin: read Key Format Strings and Field from prefs.
/*
1. A general matching element is % followed by a two-letter label: for
matching field and specifying the lower/upper case for 1st/remaining letters.
2. Then it can be optionally followed by a number for the maximum length in
number of characters. (default=0: means all characters)
3. Last it can be also optionally followed by a number within curly brackets
for selecting the n-th word of the field (start from 0-th, the default).
4. The special repitive 2-letter labels like %TT, %aa, and %JJ are to group
the first letters only of surnames/words in corresponding fields.
5. Separators/indicators including +,-,:,., etc, and all letters and numbers
can be used in between the elements.
Collision Format: %a for alphabetic suffix, %n for numeric suffix
Specified Key Field: e.g. callNumber for using the stored key
Some examples:
%au4%yr2%tt2 %AU_%yr_%TI %Au4-%Au4{1}:%JJ%yr:Vol%vo:Pg%pg-%pg{1}
%Au4{1} = first 4 letters of 2nd creator's surname (first letter capitalized)
%ti6{2} = first 6 letters of 3rd word in title (all lowercase)
%AA4 = initials of first 4 creators' surnames (uppercase)
%tt6 = first letters of first 6 words in title (lowercase)
%JJ5 = first letters of first 5 words in journal name (uppercase)
%yr = %yr4 = four-digit year, %yr2 = two-digit year
%vo = volume number
%pg = first page number
%pg{1} = last page number
*/
var citeKeyFormat = Zotero.getPrefs("bibtexKeyFormat") ? Zotero.getPrefs("bibtexKeyFormat") : "%au%yr%ti";
var citeKeyCollisionFormat = Zotero.getPrefs("bibtexKeyCollisionFormat") ? Zotero.getPrefs("bibtexKeyCollisionFormat") : "-%n";
var citeKeyField = Zotero.getPrefs("bibtexKeyField"); //e.g. callNumber
var exportLocalFilePath = Zotero.getPrefs("bibtexExportLocalFilePath"); // default=no
var preserveLatex = Zotero.getPrefs("bibtexPreserveLatex"); // default=no
// -- Tan --end
function detectImport() {
var maxChars = 1048576; // 1MB
var inComment = false;
var block = "";
var buffer = "";
var chr = "";
var charsRead = 0;
var re = /^\s*@[a-zA-Z]+[\(\{]/;
while((buffer = Zotero.read(4096)) && charsRead < maxChars) {
Zotero.debug("Scanning " + buffer.length + " characters for BibTeX");
charsRead += buffer.length;
for (var i=0; i<buffer.length; i++) {
chr = buffer[i];
if (inComment && chr != "\r" && chr != "\n") {
continue;
}
inComment = false;
if(chr == "%") {
// read until next newline
block = "";
inComment = true;
} else if((chr == "\n" || chr == "\r"
// allow one-line entries
|| i == (buffer.length - 1))
&& block) {
// check if this is a BibTeX entry
if(re.test(block)) {
return true;
}
block = "";
} else if(" \n\r\t".indexOf(chr) == -1) {
block += chr;
}
}
}
}
var fieldMap = {
address:"place",
chapter:"section",
edition:"edition",
type:"type",
series:"series",
title:"title",
volume:"volume",
copyright:"rights",
isbn:"ISBN",
issn:"ISSN",
lccn:"callNumber",
location:"archiveLocation",
shorttitle:"shortTitle",
url:"url",
doi:"DOI",
"abstract":"abstractNote"
};
var inputFieldMap = {
booktitle :"publicationTitle",
school:"publisher",
institution:"publisher",
publisher:"publisher",
issue:"issue"
};
var zotero2bibtexTypeMap = {
"book":"book",
"bookSection":"incollection",
"journalArticle":"article",
"magazineArticle":"article",
"newspaperArticle":"article",
"thesis":"phdthesis",
"letter":"misc",
"manuscript":"unpublished",
"interview":"misc",
"film":"misc",
"artwork":"misc",
"webpage":"misc",
"conferencePaper":"inproceedings",
"report":"techreport"
};
var bibtex2zoteroTypeMap = {
"book":"book", // or booklet, proceedings
"inbook":"bookSection",
"incollection":"bookSection",
"article":"journalArticle", // or magazineArticle or newspaperArticle
"phdthesis":"thesis",
"unpublished":"manuscript",
"inproceedings":"conferencePaper", // check for conference also
"conference":"conferencePaper",
"techreport":"report",
"booklet":"book",
"manual":"book",
"mastersthesis":"thesis",
"misc":"book",
"proceedings":"book"
};
/*
* three-letter month abbreviations. i assume these are the same ones that the
* docs say are defined in some appendix of the LaTeX book. (i don't have the
* LaTeX book.)
*/
var months = ["jan", "feb", "mar", "apr", "may", "jun",
"jul", "aug", "sep", "oct", "nov", "dec"];
/*
* new mapping table based on that from Matthias Steffens,
* then enhanced with some fields generated from the unicode table.
*/
var mappingTable = {
"\u00A0":"~", // NO-BREAK SPACE
"\u00A1":"{\\textexclamdown}", // INVERTED EXCLAMATION MARK
"\u00A2":"{\\textcent}", // CENT SIGN
"\u00A3":"{\\textsterling}", // POUND SIGN
"\u00A5":"{\\textyen}", // YEN SIGN
"\u00A6":"{\\textbrokenbar}", // BROKEN BAR
"\u00A7":"{\\textsection}", // SECTION SIGN
"\u00A8":"{\\textasciidieresis}", // DIAERESIS
"\u00A9":"{\\textcopyright}", // COPYRIGHT SIGN
"\u00AA":"{\\textordfeminine}", // FEMININE ORDINAL INDICATOR
"\u00AB":"{\\guillemotleft}", // LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
"\u00AC":"{\\textlnot}", // NOT SIGN
"\u00AD":"-", // SOFT HYPHEN
"\u00AE":"{\\textregistered}", // REGISTERED SIGN
"\u00AF":"{\\textasciimacron}", // MACRON
"\u00B0":"{\\textdegree}", // DEGREE SIGN
"\u00B1":"{\\textpm}", // PLUS-MINUS SIGN
"\u00B2":"{\\texttwosuperior}", // SUPERSCRIPT TWO
"\u00B3":"{\\textthreesuperior}", // SUPERSCRIPT THREE
"\u00B4":"{\\textasciiacute}", // ACUTE ACCENT
"\u00B5":"{\\textmu}", // MICRO SIGN
"\u00B6":"{\\textparagraph}", // PILCROW SIGN
"\u00B7":"{\\textperiodcentered}", // MIDDLE DOT
"\u00B8":"{\\c\\ }", // CEDILLA
"\u00B9":"{\\textonesuperior}", // SUPERSCRIPT ONE
"\u00BA":"{\\textordmasculine}", // MASCULINE ORDINAL INDICATOR
"\u00BB":"{\\guillemotright}", // RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
"\u00BC":"{\\textonequarter}", // VULGAR FRACTION ONE QUARTER
"\u00BD":"{\\textonehalf}", // VULGAR FRACTION ONE HALF
"\u00BE":"{\\textthreequarters}", // VULGAR FRACTION THREE QUARTERS
"\u00BF":"{\\textquestiondown}", // INVERTED QUESTION MARK
"\u00C6":"{\\AE}", // LATIN CAPITAL LETTER AE
"\u00D0":"{\\DH}", // LATIN CAPITAL LETTER ETH
"\u00D7":"{\\texttimes}", // MULTIPLICATION SIGN
"\U00D8":"{\\O}", // LATIN CAPITAL LETTER O WITH STROKE
"\u00DE":"{\\TH}", // LATIN CAPITAL LETTER THORN
"\u00DF":"{\\ss}", // LATIN SMALL LETTER SHARP S
"\u00E6":"{\\ae}", // LATIN SMALL LETTER AE
"\u00F0":"{\\dh}", // LATIN SMALL LETTER ETH
"\u00F7":"{\\textdiv}", // DIVISION SIGN
"\U00F8":"{\\o}", // LATIN SMALL LETTER O WITH STROKE
"\u00FE":"{\\th}", // LATIN SMALL LETTER THORN
"\u0131":"{\\i}", // LATIN SMALL LETTER DOTLESS I
"\u0132":"IJ", // LATIN CAPITAL LIGATURE IJ
"\u0133":"ij", // LATIN SMALL LIGATURE IJ
"\u0138":"k", // LATIN SMALL LETTER KRA
"\u0149":"'n", // LATIN SMALL LETTER N PRECEDED BY APOSTROPHE
"\u014A":"{\\NG}", // LATIN CAPITAL LETTER ENG
"\u014B":"{\\ng}", // LATIN SMALL LETTER ENG
"\u0152":"{\\OE}", // LATIN CAPITAL LIGATURE OE
"\u0153":"{\\oe}", // LATIN SMALL LIGATURE OE
"\u017F":"s", // LATIN SMALL LETTER LONG S
"\u02B9":"'", // MODIFIER LETTER PRIME
"\u02BB":"'", // MODIFIER LETTER TURNED COMMA
"\u02BC":"'", // MODIFIER LETTER APOSTROPHE
"\u02BD":"'", // MODIFIER LETTER REVERSED COMMA
"\u02C6":"{\\textasciicircum}", // MODIFIER LETTER CIRCUMFLEX ACCENT
"\u02C8":"'", // MODIFIER LETTER VERTICAL LINE
"\u02C9":"-", // MODIFIER LETTER MACRON
"\u02CC":",", // MODIFIER LETTER LOW VERTICAL LINE
"\u02D0":":", // MODIFIER LETTER TRIANGULAR COLON
"\u02DA":"o", // RING ABOVE
"\u02DC":"\\~{}", // SMALL TILDE
"\u02DD":"{\\textacutedbl}", // DOUBLE ACUTE ACCENT
"\u0374":"'", // GREEK NUMERAL SIGN
"\u0375":",", // GREEK LOWER NUMERAL SIGN
"\u037E":";", // GREEK QUESTION MARK
// -- Tan -begin greek symbols
"\u0393":"$\\Gamma$", // GREEK Gamma
"\u0394":"$\\Delta$", // GREEK Delta
"\u0398":"$\\Theta$", // GREEK Theta
"\u039B":"$\\Lambda$", // GREEK Lambda
"\u039E":"$\\Xi$", // GREEK Xi
"\u03A0":"$\\Pi$", // GREEK Pi
"\u03A3":"$\\Sigma$", // GREEK Sigma
"\u03A6":"$\\Phi$", // GREEK Phi
"\u03A8":"$\\Psi$", // GREEK Psi
"\u03A9":"$\\Omega$", // GREEK Omega
"\u03B1":"$\\alpha$", // GREEK alpha
"\u03B2":"$\\beta$", // GREEK beta
"\u03B3":"$\\gamma$", // GREEK gamma
"\u03B4":"$\\delta$", // GREEK delta
"\u03B5":"$\\varepsilon$", // GREEK var-epsilon
"\u03B6":"$\\zeta$", // GREEK zeta
"\u03B7":"$\\eta$", // GREEK eta
"\u03B8":"$\\theta$", // GREEK theta
"\u03B9":"$\\iota$", // GREEK iota
"\u03BA":"$\\kappa$", // GREEK kappa
"\u03BB":"$\\lambda$", // GREEK lambda
"\u03BC":"$\\mu$", // GREEK mu
"\u03BD":"$\\nu$", // GREEK nu
"\u03BE":"$\\xi$", // GREEK xi
"\u03C0":"$\\pi$", // GREEK pi
"\u03C1":"$\\rho$", // GREEK rho
"\u03C2":"$\\varsigma$", // GREEK var-sigma
"\u03C3":"$\\sigma$", // GREEK sigma
"\u03C4":"$\\tau$", // GREEK tau
"\u03C5":"$\\upsilon$", // GREEK upsilon
"\u03C6":"$\\varphi$", // GREEK var-phi
"\u03C7":"$\\chi$", // GREEK chi
"\u03C8":"$\\psi$", // GREEK psi
"\u03C9":"$\\omega$", // GREEK omega
"\u03D1":"$\\vartheta$", // GREEK var-theta
"\u03D2":"$\\Upsilon$", // GREEK Upsilon
"\u03D5":"$\\phi$", // GREEK phi
"\u03D6":"$\\varpi$", // GREEK var-pi
"\u03F1":"$\\varrho$", // GREEK var-rho
"\u03F5":"$\\epsilon$", // GREEK epsilon
// -- Tan -end greek symbols
"\u2000":" ", // EN QUAD
"\u2001":" ", // EM QUAD
"\u2002":" ", // EN SPACE
"\u2003":" ", // EM SPACE
"\u2004":" ", // THREE-PER-EM SPACE
"\u2005":" ", // FOUR-PER-EM SPACE
"\u2006":" ", // SIX-PER-EM SPACE
"\u2007":" ", // FIGURE SPACE
"\u2008":" ", // PUNCTUATION SPACE
"\u2009":" ", // THIN SPACE
"\u2010":"-", // HYPHEN
"\u2011":"-", // NON-BREAKING HYPHEN
"\u2012":"-", // FIGURE DASH
"\u2013":"{\\textendash}", // EN DASH
"\u2014":"{\\textemdash}", // EM DASH
"\u2015":"{\\textemdash}", // HORIZONTAL BAR or QUOTATION DASH (not in LaTeX -- use EM DASH)
"\u2016":"{\\textbardbl}", // DOUBLE VERTICAL LINE
"\u2017":"{\\textunderscore}", // DOUBLE LOW LINE
"\u2018":"{\\textquoteleft}", // LEFT SINGLE QUOTATION MARK
"\u2019":"{\\textquoteright}", // RIGHT SINGLE QUOTATION MARK
"`" : "\u2018", // LEFT SINGLE QUOTATION MARK
"'" : "\u2019", // RIGHT SINGLE QUOTATION MARK
"\u201A":"{\\quotesinglbase}", // SINGLE LOW-9 QUOTATION MARK
"\u201B":"'", // SINGLE HIGH-REVERSED-9 QUOTATION MARK
"\u201C":"{\\textquotedblleft}", // LEFT DOUBLE QUOTATION MARK
"\u201D":"{\\textquotedblright}", // RIGHT DOUBLE QUOTATION MARK
"\u201E":"{\\quotedblbase}", // DOUBLE LOW-9 QUOTATION MARK
"\u201F":"{\\quotedblbase}", // DOUBLE HIGH-REVERSED-9 QUOTATION MARK
"\u2020":"{\\textdagger}", // DAGGER
"\u2021":"{\\textdaggerdbl}", // DOUBLE DAGGER
"\u2022":"{\\textbullet}", // BULLET
"\u2023":">", // TRIANGULAR BULLET
"\u2024":".", // ONE DOT LEADER
"\u2025":"..", // TWO DOT LEADER
"\u2026":"{\\textellipsis}", // HORIZONTAL ELLIPSIS
"\u2027":"-", // HYPHENATION POINT
"\u202F":" ", // NARROW NO-BREAK SPACE
"\u2030":"{\\textperthousand}", // PER MILLE SIGN
"\u2032":"'", // PRIME
"\u2033":"'", // DOUBLE PRIME
"\u2034":"'''", // TRIPLE PRIME
"\u2035":"`", // REVERSED PRIME
"\u2036":"``", // REVERSED DOUBLE PRIME
"\u2037":"```", // REVERSED TRIPLE PRIME
"\u2039":"{\\guilsinglleft}", // SINGLE LEFT-POINTING ANGLE QUOTATION MARK
"\u203A":"{\\guilsinglright}", // SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
"\u203C":"!!", // DOUBLE EXCLAMATION MARK
"\u203E":"-", // OVERLINE
"\u2043":"-", // HYPHEN BULLET
"\u2044":"{\\textfractionsolidus}", // FRACTION SLASH
"\u2048":"?!", // QUESTION EXCLAMATION MARK
"\u2049":"!?", // EXCLAMATION QUESTION MARK
"\u204A":"7", // TIRONIAN SIGN ET
"\u2070":"$^{0}$", // SUPERSCRIPT ZERO
"\u2074":"$^{4}$", // SUPERSCRIPT FOUR
"\u2075":"$^{5}$", // SUPERSCRIPT FIVE
"\u2076":"$^{6}$", // SUPERSCRIPT SIX
"\u2077":"$^{7}$", // SUPERSCRIPT SEVEN
"\u2078":"$^{8}$", // SUPERSCRIPT EIGHT
"\u2079":"$^{9}$", // SUPERSCRIPT NINE
"\u207A":"$^{+}$", // SUPERSCRIPT PLUS SIGN
"\u207B":"$^{-}$", // SUPERSCRIPT MINUS
"\u207C":"$^{=}$", // SUPERSCRIPT EQUALS SIGN
"\u207D":"$^{(}$", // SUPERSCRIPT LEFT PARENTHESIS
"\u207E":"$^{)}$", // SUPERSCRIPT RIGHT PARENTHESIS
"\u207F":"$^{n}$", // SUPERSCRIPT LATIN SMALL LETTER N
"\u2080":"$_{0}$", // SUBSCRIPT ZERO
"\u2081":"$_{1}$", // SUBSCRIPT ONE
"\u2082":"$_{2}$", // SUBSCRIPT TWO
"\u2083":"$_{3}$", // SUBSCRIPT THREE
"\u2084":"$_{4}$", // SUBSCRIPT FOUR
"\u2085":"$_{5}$", // SUBSCRIPT FIVE
"\u2086":"$_{6}$", // SUBSCRIPT SIX
"\u2087":"$_{7}$", // SUBSCRIPT SEVEN
"\u2088":"$_{8}$", // SUBSCRIPT EIGHT
"\u2089":"$_{9}$", // SUBSCRIPT NINE
"\u208A":"$_{+}$", // SUBSCRIPT PLUS SIGN
"\u208B":"$_{-}$", // SUBSCRIPT MINUS
"\u208C":"$_{=}$", // SUBSCRIPT EQUALS SIGN
"\u208D":"$_{(}$", // SUBSCRIPT LEFT PARENTHESIS
"\u208E":"$_{)}$", // SUBSCRIPT RIGHT PARENTHESIS
"\u20AC":"{\\texteuro}", // EURO SIGN
"\u2100":"a/c", // ACCOUNT OF
"\u2101":"a/s", // ADDRESSED TO THE SUBJECT
"\u2103":"{\\textcelsius}", // DEGREE CELSIUS
"\u2105":"c/o", // CARE OF
"\u2106":"c/u", // CADA UNA
"\u2109":"F", // DEGREE FAHRENHEIT
"\u2113":"l", // SCRIPT SMALL L
"\u2116":"{\\textnumero}", // NUMERO SIGN
"\u2117":"{\\textcircledP}", // SOUND RECORDING COPYRIGHT
"\u2120":"{\\textservicemark}", // SERVICE MARK
"\u2121":"TEL", // TELEPHONE SIGN
"\u2122":"{\\texttrademark}", // TRADE MARK SIGN
"\u2126":"{\\textohm}", // OHM SIGN
"\u212A":"K", // KELVIN SIGN
"\u212B":"A", // ANGSTROM SIGN
"\u212E":"{\\textestimated}", // ESTIMATED SYMBOL
"\u2153":" 1/3", // VULGAR FRACTION ONE THIRD
"\u2154":" 2/3", // VULGAR FRACTION TWO THIRDS
"\u2155":" 1/5", // VULGAR FRACTION ONE FIFTH
"\u2156":" 2/5", // VULGAR FRACTION TWO FIFTHS
"\u2157":" 3/5", // VULGAR FRACTION THREE FIFTHS
"\u2158":" 4/5", // VULGAR FRACTION FOUR FIFTHS
"\u2159":" 1/6", // VULGAR FRACTION ONE SIXTH
"\u215A":" 5/6", // VULGAR FRACTION FIVE SIXTHS
"\u215B":" 1/8", // VULGAR FRACTION ONE EIGHTH
"\u215C":" 3/8", // VULGAR FRACTION THREE EIGHTHS
"\u215D":" 5/8", // VULGAR FRACTION FIVE EIGHTHS
"\u215E":" 7/8", // VULGAR FRACTION SEVEN EIGHTHS
"\u215F":" 1/", // FRACTION NUMERATOR ONE
"\u2160":"I", // ROMAN NUMERAL ONE
"\u2161":"II", // ROMAN NUMERAL TWO
"\u2162":"III", // ROMAN NUMERAL THREE
"\u2163":"IV", // ROMAN NUMERAL FOUR
"\u2164":"V", // ROMAN NUMERAL FIVE
"\u2165":"VI", // ROMAN NUMERAL SIX
"\u2166":"VII", // ROMAN NUMERAL SEVEN
"\u2167":"VIII", // ROMAN NUMERAL EIGHT
"\u2168":"IX", // ROMAN NUMERAL NINE
"\u2169":"X", // ROMAN NUMERAL TEN
"\u216A":"XI", // ROMAN NUMERAL ELEVEN
"\u216B":"XII", // ROMAN NUMERAL TWELVE
"\u216C":"L", // ROMAN NUMERAL FIFTY
"\u216D":"C", // ROMAN NUMERAL ONE HUNDRED
"\u216E":"D", // ROMAN NUMERAL FIVE HUNDRED
"\u216F":"M", // ROMAN NUMERAL ONE THOUSAND
"\u2170":"i", // SMALL ROMAN NUMERAL ONE
"\u2171":"ii", // SMALL ROMAN NUMERAL TWO
"\u2172":"iii", // SMALL ROMAN NUMERAL THREE
"\u2173":"iv", // SMALL ROMAN NUMERAL FOUR
"\u2174":"v", // SMALL ROMAN NUMERAL FIVE
"\u2175":"vi", // SMALL ROMAN NUMERAL SIX
"\u2176":"vii", // SMALL ROMAN NUMERAL SEVEN
"\u2177":"viii", // SMALL ROMAN NUMERAL EIGHT
"\u2178":"ix", // SMALL ROMAN NUMERAL NINE
"\u2179":"x", // SMALL ROMAN NUMERAL TEN
"\u217A":"xi", // SMALL ROMAN NUMERAL ELEVEN
"\u217B":"xii", // SMALL ROMAN NUMERAL TWELVE
"\u217C":"l", // SMALL ROMAN NUMERAL FIFTY
"\u217D":"c", // SMALL ROMAN NUMERAL ONE HUNDRED
"\u217E":"d", // SMALL ROMAN NUMERAL FIVE HUNDRED
"\u217F":"m", // SMALL ROMAN NUMERAL ONE THOUSAND
"\u2190":"{\\textleftarrow}", // LEFTWARDS ARROW
"\u2191":"{\\textuparrow}", // UPWARDS ARROW
"\u2192":"{\\textrightarrow}", // RIGHTWARDS ARROW
"\u2193":"{\\textdownarrow}", // DOWNWARDS ARROW
"\u2194":"<->", // LEFT RIGHT ARROW
"\u21D0":"<=", // LEFTWARDS DOUBLE ARROW
"\u21D2":"=>", // RIGHTWARDS DOUBLE ARROW
"\u21D4":"<=>", // LEFT RIGHT DOUBLE ARROW
"\u2212":"-", // MINUS SIGN
"\u2215":"/", // DIVISION SLASH
"\u2216":"\\", // SET MINUS
"\u2217":"*", // ASTERISK OPERATOR
"\u2218":"o", // RING OPERATOR
"\u2219":".", // BULLET OPERATOR
"\u221E":"$\\infty$", // INFINITY
"\u2223":"|", // DIVIDES
"\u2225":"||", // PARALLEL TO
"\u2236":":", // RATIO
"\u223C":"\\~{}", // TILDE OPERATOR
"\u2260":"/=", // NOT EQUAL TO
"\u2261":"=", // IDENTICAL TO
"\u2264":"<=", // LESS-THAN OR EQUAL TO
"\u2265":">=", // GREATER-THAN OR EQUAL TO
"\u226A":"<<", // MUCH LESS-THAN
"\u226B":">>", // MUCH GREATER-THAN
"\u2295":"(+)", // CIRCLED PLUS
"\u2296":"(-)", // CIRCLED MINUS
"\u2297":"(x)", // CIRCLED TIMES
"\u2298":"(/)", // CIRCLED DIVISION SLASH
"\u22A2":"|-", // RIGHT TACK
"\u22A3":"-|", // LEFT TACK
"\u22A6":"|-", // ASSERTION
"\u22A7":"|=", // MODELS
"\u22A8":"|=", // TRUE
"\u22A9":"||-", // FORCES
"\u22C5":".", // DOT OPERATOR
"\u22C6":"*", // STAR OPERATOR
"\u22D5":"$\\#$", // EQUAL AND PARALLEL TO
"\u22D8":"<<<", // VERY MUCH LESS-THAN
"\u22D9":">>>", // VERY MUCH GREATER-THAN
"\u2329":"{\\textlangle}", // LEFT-POINTING ANGLE BRACKET
"\u232A":"{\\textrangle}", // RIGHT-POINTING ANGLE BRACKET
"\u2400":"NUL", // SYMBOL FOR NULL
"\u2401":"SOH", // SYMBOL FOR START OF HEADING
"\u2402":"STX", // SYMBOL FOR START OF TEXT
"\u2403":"ETX", // SYMBOL FOR END OF TEXT
"\u2404":"EOT", // SYMBOL FOR END OF TRANSMISSION
"\u2405":"ENQ", // SYMBOL FOR ENQUIRY
"\u2406":"ACK", // SYMBOL FOR ACKNOWLEDGE
"\u2407":"BEL", // SYMBOL FOR BELL
"\u2408":"BS", // SYMBOL FOR BACKSPACE
"\u2409":"HT", // SYMBOL FOR HORIZONTAL TABULATION
"\u240A":"LF", // SYMBOL FOR LINE FEED
"\u240B":"VT", // SYMBOL FOR VERTICAL TABULATION
"\u240C":"FF", // SYMBOL FOR FORM FEED
"\u240D":"CR", // SYMBOL FOR CARRIAGE RETURN
"\u240E":"SO", // SYMBOL FOR SHIFT OUT
"\u240F":"SI", // SYMBOL FOR SHIFT IN
"\u2410":"DLE", // SYMBOL FOR DATA LINK ESCAPE
"\u2411":"DC1", // SYMBOL FOR DEVICE CONTROL ONE
"\u2412":"DC2", // SYMBOL FOR DEVICE CONTROL TWO
"\u2413":"DC3", // SYMBOL FOR DEVICE CONTROL THREE
"\u2414":"DC4", // SYMBOL FOR DEVICE CONTROL FOUR
"\u2415":"NAK", // SYMBOL FOR NEGATIVE ACKNOWLEDGE
"\u2416":"SYN", // SYMBOL FOR SYNCHRONOUS IDLE
"\u2417":"ETB", // SYMBOL FOR END OF TRANSMISSION BLOCK
"\u2418":"CAN", // SYMBOL FOR CANCEL
"\u2419":"EM", // SYMBOL FOR END OF MEDIUM
"\u241A":"SUB", // SYMBOL FOR SUBSTITUTE
"\u241B":"ESC", // SYMBOL FOR ESCAPE
"\u241C":"FS", // SYMBOL FOR FILE SEPARATOR
"\u241D":"GS", // SYMBOL FOR GROUP SEPARATOR
"\u241E":"RS", // SYMBOL FOR RECORD SEPARATOR
"\u241F":"US", // SYMBOL FOR UNIT SEPARATOR
"\u2420":"SP", // SYMBOL FOR SPACE
"\u2421":"DEL", // SYMBOL FOR DELETE
"\u2423":"{\\textvisiblespace}", // OPEN BOX
"\u2424":"NL", // SYMBOL FOR NEWLINE
"\u2425":"///", // SYMBOL FOR DELETE FORM TWO
"\u2426":"?", // SYMBOL FOR SUBSTITUTE FORM TWO
"\u2460":"(1)", // CIRCLED DIGIT ONE
"\u2461":"(2)", // CIRCLED DIGIT TWO
"\u2462":"(3)", // CIRCLED DIGIT THREE
"\u2463":"(4)", // CIRCLED DIGIT FOUR
"\u2464":"(5)", // CIRCLED DIGIT FIVE
"\u2465":"(6)", // CIRCLED DIGIT SIX
"\u2466":"(7)", // CIRCLED DIGIT SEVEN
"\u2467":"(8)", // CIRCLED DIGIT EIGHT
"\u2468":"(9)", // CIRCLED DIGIT NINE
"\u2469":"(10)", // CIRCLED NUMBER TEN
"\u246A":"(11)", // CIRCLED NUMBER ELEVEN
"\u246B":"(12)", // CIRCLED NUMBER TWELVE
"\u246C":"(13)", // CIRCLED NUMBER THIRTEEN
"\u246D":"(14)", // CIRCLED NUMBER FOURTEEN
"\u246E":"(15)", // CIRCLED NUMBER FIFTEEN
"\u246F":"(16)", // CIRCLED NUMBER SIXTEEN
"\u2470":"(17)", // CIRCLED NUMBER SEVENTEEN
"\u2471":"(18)", // CIRCLED NUMBER EIGHTEEN
"\u2472":"(19)", // CIRCLED NUMBER NINETEEN
"\u2473":"(20)", // CIRCLED NUMBER TWENTY
"\u2474":"(1)", // PARENTHESIZED DIGIT ONE
"\u2475":"(2)", // PARENTHESIZED DIGIT TWO
"\u2476":"(3)", // PARENTHESIZED DIGIT THREE
"\u2477":"(4)", // PARENTHESIZED DIGIT FOUR
"\u2478":"(5)", // PARENTHESIZED DIGIT FIVE
"\u2479":"(6)", // PARENTHESIZED DIGIT SIX
"\u247A":"(7)", // PARENTHESIZED DIGIT SEVEN
"\u247B":"(8)", // PARENTHESIZED DIGIT EIGHT
"\u247C":"(9)", // PARENTHESIZED DIGIT NINE
"\u247D":"(10)", // PARENTHESIZED NUMBER TEN
"\u247E":"(11)", // PARENTHESIZED NUMBER ELEVEN
"\u247F":"(12)", // PARENTHESIZED NUMBER TWELVE
"\u2480":"(13)", // PARENTHESIZED NUMBER THIRTEEN
"\u2481":"(14)", // PARENTHESIZED NUMBER FOURTEEN
"\u2482":"(15)", // PARENTHESIZED NUMBER FIFTEEN
"\u2483":"(16)", // PARENTHESIZED NUMBER SIXTEEN
"\u2484":"(17)", // PARENTHESIZED NUMBER SEVENTEEN
"\u2485":"(18)", // PARENTHESIZED NUMBER EIGHTEEN
"\u2486":"(19)", // PARENTHESIZED NUMBER NINETEEN
"\u2487":"(20)", // PARENTHESIZED NUMBER TWENTY
"\u2488":"1.", // DIGIT ONE FULL STOP
"\u2489":"2.", // DIGIT TWO FULL STOP
"\u248A":"3.", // DIGIT THREE FULL STOP
"\u248B":"4.", // DIGIT FOUR FULL STOP
"\u248C":"5.", // DIGIT FIVE FULL STOP
"\u248D":"6.", // DIGIT SIX FULL STOP
"\u248E":"7.", // DIGIT SEVEN FULL STOP
"\u248F":"8.", // DIGIT EIGHT FULL STOP
"\u2490":"9.", // DIGIT NINE FULL STOP
"\u2491":"10.", // NUMBER TEN FULL STOP
"\u2492":"11.", // NUMBER ELEVEN FULL STOP
"\u2493":"12.", // NUMBER TWELVE FULL STOP
"\u2494":"13.", // NUMBER THIRTEEN FULL STOP
"\u2495":"14.", // NUMBER FOURTEEN FULL STOP
"\u2496":"15.", // NUMBER FIFTEEN FULL STOP
"\u2497":"16.", // NUMBER SIXTEEN FULL STOP
"\u2498":"17.", // NUMBER SEVENTEEN FULL STOP
"\u2499":"18.", // NUMBER EIGHTEEN FULL STOP
"\u249A":"19.", // NUMBER NINETEEN FULL STOP
"\u249B":"20.", // NUMBER TWENTY FULL STOP
"\u249C":"(a)", // PARENTHESIZED LATIN SMALL LETTER A
"\u249D":"(b)", // PARENTHESIZED LATIN SMALL LETTER B
"\u249E":"(c)", // PARENTHESIZED LATIN SMALL LETTER C
"\u249F":"(d)", // PARENTHESIZED LATIN SMALL LETTER D
"\u24A0":"(e)", // PARENTHESIZED LATIN SMALL LETTER E
"\u24A1":"(f)", // PARENTHESIZED LATIN SMALL LETTER F
"\u24A2":"(g)", // PARENTHESIZED LATIN SMALL LETTER G
"\u24A3":"(h)", // PARENTHESIZED LATIN SMALL LETTER H
"\u24A4":"(i)", // PARENTHESIZED LATIN SMALL LETTER I
"\u24A5":"(j)", // PARENTHESIZED LATIN SMALL LETTER J
"\u24A6":"(k)", // PARENTHESIZED LATIN SMALL LETTER K
"\u24A7":"(l)", // PARENTHESIZED LATIN SMALL LETTER L
"\u24A8":"(m)", // PARENTHESIZED LATIN SMALL LETTER M
"\u24A9":"(n)", // PARENTHESIZED LATIN SMALL LETTER N
"\u24AA":"(o)", // PARENTHESIZED LATIN SMALL LETTER O
"\u24AB":"(p)", // PARENTHESIZED LATIN SMALL LETTER P
"\u24AC":"(q)", // PARENTHESIZED LATIN SMALL LETTER Q
"\u24AD":"(r)", // PARENTHESIZED LATIN SMALL LETTER R
"\u24AE":"(s)", // PARENTHESIZED LATIN SMALL LETTER S
"\u24AF":"(t)", // PARENTHESIZED LATIN SMALL LETTER T
"\u24B0":"(u)", // PARENTHESIZED LATIN SMALL LETTER U
"\u24B1":"(v)", // PARENTHESIZED LATIN SMALL LETTER V
"\u24B2":"(w)", // PARENTHESIZED LATIN SMALL LETTER W
"\u24B3":"(x)", // PARENTHESIZED LATIN SMALL LETTER X
"\u24B4":"(y)", // PARENTHESIZED LATIN SMALL LETTER Y
"\u24B5":"(z)", // PARENTHESIZED LATIN SMALL LETTER Z
"\u24B6":"(A)", // CIRCLED LATIN CAPITAL LETTER A
"\u24B7":"(B)", // CIRCLED LATIN CAPITAL LETTER B
"\u24B8":"(C)", // CIRCLED LATIN CAPITAL LETTER C
"\u24B9":"(D)", // CIRCLED LATIN CAPITAL LETTER D
"\u24BA":"(E)", // CIRCLED LATIN CAPITAL LETTER E
"\u24BB":"(F)", // CIRCLED LATIN CAPITAL LETTER F
"\u24BC":"(G)", // CIRCLED LATIN CAPITAL LETTER G
"\u24BD":"(H)", // CIRCLED LATIN CAPITAL LETTER H
"\u24BE":"(I)", // CIRCLED LATIN CAPITAL LETTER I
"\u24BF":"(J)", // CIRCLED LATIN CAPITAL LETTER J
"\u24C0":"(K)", // CIRCLED LATIN CAPITAL LETTER K
"\u24C1":"(L)", // CIRCLED LATIN CAPITAL LETTER L
"\u24C2":"(M)", // CIRCLED LATIN CAPITAL LETTER M
"\u24C3":"(N)", // CIRCLED LATIN CAPITAL LETTER N
"\u24C4":"(O)", // CIRCLED LATIN CAPITAL LETTER O
"\u24C5":"(P)", // CIRCLED LATIN CAPITAL LETTER P
"\u24C6":"(Q)", // CIRCLED LATIN CAPITAL LETTER Q
"\u24C7":"(R)", // CIRCLED LATIN CAPITAL LETTER R
"\u24C8":"(S)", // CIRCLED LATIN CAPITAL LETTER S
"\u24C9":"(T)", // CIRCLED LATIN CAPITAL LETTER T
"\u24CA":"(U)", // CIRCLED LATIN CAPITAL LETTER U
"\u24CB":"(V)", // CIRCLED LATIN CAPITAL LETTER V
"\u24CC":"(W)", // CIRCLED LATIN CAPITAL LETTER W
"\u24CD":"(X)", // CIRCLED LATIN CAPITAL LETTER X
"\u24CE":"(Y)", // CIRCLED LATIN CAPITAL LETTER Y
"\u24CF":"(Z)", // CIRCLED LATIN CAPITAL LETTER Z
"\u24D0":"(a)", // CIRCLED LATIN SMALL LETTER A
"\u24D1":"(b)", // CIRCLED LATIN SMALL LETTER B
"\u24D2":"(c)", // CIRCLED LATIN SMALL LETTER C
"\u24D3":"(d)", // CIRCLED LATIN SMALL LETTER D
"\u24D4":"(e)", // CIRCLED LATIN SMALL LETTER E
"\u24D5":"(f)", // CIRCLED LATIN SMALL LETTER F
"\u24D6":"(g)", // CIRCLED LATIN SMALL LETTER G
"\u24D7":"(h)", // CIRCLED LATIN SMALL LETTER H
"\u24D8":"(i)", // CIRCLED LATIN SMALL LETTER I
"\u24D9":"(j)", // CIRCLED LATIN SMALL LETTER J
"\u24DA":"(k)", // CIRCLED LATIN SMALL LETTER K
"\u24DB":"(l)", // CIRCLED LATIN SMALL LETTER L
"\u24DC":"(m)", // CIRCLED LATIN SMALL LETTER M
"\u24DD":"(n)", // CIRCLED LATIN SMALL LETTER N
"\u24DE":"(o)", // CIRCLED LATIN SMALL LETTER O
"\u24DF":"(p)", // CIRCLED LATIN SMALL LETTER P
"\u24E0":"(q)", // CIRCLED LATIN SMALL LETTER Q
"\u24E1":"(r)", // CIRCLED LATIN SMALL LETTER R
"\u24E2":"(s)", // CIRCLED LATIN SMALL LETTER S
"\u24E3":"(t)", // CIRCLED LATIN SMALL LETTER T
"\u24E4":"(u)", // CIRCLED LATIN SMALL LETTER U
"\u24E5":"(v)", // CIRCLED LATIN SMALL LETTER V
"\u24E6":"(w)", // CIRCLED LATIN SMALL LETTER W
"\u24E7":"(x)", // CIRCLED LATIN SMALL LETTER X
"\u24E8":"(y)", // CIRCLED LATIN SMALL LETTER Y
"\u24E9":"(z)", // CIRCLED LATIN SMALL LETTER Z
"\u24EA":"(0)", // CIRCLED DIGIT ZERO
"\u2500":"-", // BOX DRAWINGS LIGHT HORIZONTAL
"\u2501":"=", // BOX DRAWINGS HEAVY HORIZONTAL
"\u2502":"|", // BOX DRAWINGS LIGHT VERTICAL
"\u2503":"|", // BOX DRAWINGS HEAVY VERTICAL
"\u2504":"-", // BOX DRAWINGS LIGHT TRIPLE DASH HORIZONTAL
"\u2505":"=", // BOX DRAWINGS HEAVY TRIPLE DASH HORIZONTAL
"\u2506":"|", // BOX DRAWINGS LIGHT TRIPLE DASH VERTICAL
"\u2507":"|", // BOX DRAWINGS HEAVY TRIPLE DASH VERTICAL
"\u2508":"-", // BOX DRAWINGS LIGHT QUADRUPLE DASH HORIZONTAL
"\u2509":"=", // BOX DRAWINGS HEAVY QUADRUPLE DASH HORIZONTAL
"\u250A":"|", // BOX DRAWINGS LIGHT QUADRUPLE DASH VERTICAL
"\u250B":"|", // BOX DRAWINGS HEAVY QUADRUPLE DASH VERTICAL
"\u250C":"+", // BOX DRAWINGS LIGHT DOWN AND RIGHT
"\u250D":"+", // BOX DRAWINGS DOWN LIGHT AND RIGHT HEAVY
"\u250E":"+", // BOX DRAWINGS DOWN HEAVY AND RIGHT LIGHT
"\u250F":"+", // BOX DRAWINGS HEAVY DOWN AND RIGHT
"\u2510":"+", // BOX DRAWINGS LIGHT DOWN AND LEFT
"\u2511":"+", // BOX DRAWINGS DOWN LIGHT AND LEFT HEAVY
"\u2512":"+", // BOX DRAWINGS DOWN HEAVY AND LEFT LIGHT
"\u2513":"+", // BOX DRAWINGS HEAVY DOWN AND LEFT
"\u2514":"+", // BOX DRAWINGS LIGHT UP AND RIGHT
"\u2515":"+", // BOX DRAWINGS UP LIGHT AND RIGHT HEAVY
"\u2516":"+", // BOX DRAWINGS UP HEAVY AND RIGHT LIGHT
"\u2517":"+", // BOX DRAWINGS HEAVY UP AND RIGHT
"\u2518":"+", // BOX DRAWINGS LIGHT UP AND LEFT
"\u2519":"+", // BOX DRAWINGS UP LIGHT AND LEFT HEAVY
"\u251A":"+", // BOX DRAWINGS UP HEAVY AND LEFT LIGHT
"\u251B":"+", // BOX DRAWINGS HEAVY UP AND LEFT
"\u251C":"+", // BOX DRAWINGS LIGHT VERTICAL AND RIGHT
"\u251D":"+", // BOX DRAWINGS VERTICAL LIGHT AND RIGHT HEAVY
"\u251E":"+", // BOX DRAWINGS UP HEAVY AND RIGHT DOWN LIGHT
"\u251F":"+", // BOX DRAWINGS DOWN HEAVY AND RIGHT UP LIGHT
"\u2520":"+", // BOX DRAWINGS VERTICAL HEAVY AND RIGHT LIGHT
"\u2521":"+", // BOX DRAWINGS DOWN LIGHT AND RIGHT UP HEAVY
"\u2522":"+", // BOX DRAWINGS UP LIGHT AND RIGHT DOWN HEAVY
"\u2523":"+", // BOX DRAWINGS HEAVY VERTICAL AND RIGHT
"\u2524":"+", // BOX DRAWINGS LIGHT VERTICAL AND LEFT
"\u2525":"+", // BOX DRAWINGS VERTICAL LIGHT AND LEFT HEAVY
"\u2526":"+", // BOX DRAWINGS UP HEAVY AND LEFT DOWN LIGHT
"\u2527":"+", // BOX DRAWINGS DOWN HEAVY AND LEFT UP LIGHT
"\u2528":"+", // BOX DRAWINGS VERTICAL HEAVY AND LEFT LIGHT
"\u2529":"+", // BOX DRAWINGS DOWN LIGHT AND LEFT UP HEAVY
"\u252A":"+", // BOX DRAWINGS UP LIGHT AND LEFT DOWN HEAVY
"\u252B":"+", // BOX DRAWINGS HEAVY VERTICAL AND LEFT
"\u252C":"+", // BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
"\u252D":"+", // BOX DRAWINGS LEFT HEAVY AND RIGHT DOWN LIGHT
"\u252E":"+", // BOX DRAWINGS RIGHT HEAVY AND LEFT DOWN LIGHT
"\u252F":"+", // BOX DRAWINGS DOWN LIGHT AND HORIZONTAL HEAVY
"\u2530":"+", // BOX DRAWINGS DOWN HEAVY AND HORIZONTAL LIGHT
"\u2531":"+", // BOX DRAWINGS RIGHT LIGHT AND LEFT DOWN HEAVY
"\u2532":"+", // BOX DRAWINGS LEFT LIGHT AND RIGHT DOWN HEAVY
"\u2533":"+", // BOX DRAWINGS HEAVY DOWN AND HORIZONTAL
"\u2534":"+", // BOX DRAWINGS LIGHT UP AND HORIZONTAL
"\u2535":"+", // BOX DRAWINGS LEFT HEAVY AND RIGHT UP LIGHT
"\u2536":"+", // BOX DRAWINGS RIGHT HEAVY AND LEFT UP LIGHT
"\u2537":"+", // BOX DRAWINGS UP LIGHT AND HORIZONTAL HEAVY
"\u2538":"+", // BOX DRAWINGS UP HEAVY AND HORIZONTAL LIGHT
"\u2539":"+", // BOX DRAWINGS RIGHT LIGHT AND LEFT UP HEAVY
"\u253A":"+", // BOX DRAWINGS LEFT LIGHT AND RIGHT UP HEAVY
"\u253B":"+", // BOX DRAWINGS HEAVY UP AND HORIZONTAL
"\u253C":"+", // BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
"\u253D":"+", // BOX DRAWINGS LEFT HEAVY AND RIGHT VERTICAL LIGHT
"\u253E":"+", // BOX DRAWINGS RIGHT HEAVY AND LEFT VERTICAL LIGHT
"\u253F":"+", // BOX DRAWINGS VERTICAL LIGHT AND HORIZONTAL HEAVY
"\u2540":"+", // BOX DRAWINGS UP HEAVY AND DOWN HORIZONTAL LIGHT
"\u2541":"+", // BOX DRAWINGS DOWN HEAVY AND UP HORIZONTAL LIGHT
"\u2542":"+", // BOX DRAWINGS VERTICAL HEAVY AND HORIZONTAL LIGHT
"\u2543":"+", // BOX DRAWINGS LEFT UP HEAVY AND RIGHT DOWN LIGHT
"\u2544":"+", // BOX DRAWINGS RIGHT UP HEAVY AND LEFT DOWN LIGHT
"\u2545":"+", // BOX DRAWINGS LEFT DOWN HEAVY AND RIGHT UP LIGHT
"\u2546":"+", // BOX DRAWINGS RIGHT DOWN HEAVY AND LEFT UP LIGHT
"\u2547":"+", // BOX DRAWINGS DOWN LIGHT AND UP HORIZONTAL HEAVY
"\u2548":"+", // BOX DRAWINGS UP LIGHT AND DOWN HORIZONTAL HEAVY
"\u2549":"+", // BOX DRAWINGS RIGHT LIGHT AND LEFT VERTICAL HEAVY
"\u254A":"+", // BOX DRAWINGS LEFT LIGHT AND RIGHT VERTICAL HEAVY
"\u254B":"+", // BOX DRAWINGS HEAVY VERTICAL AND HORIZONTAL
"\u254C":"-", // BOX DRAWINGS LIGHT DOUBLE DASH HORIZONTAL
"\u254D":"=", // BOX DRAWINGS HEAVY DOUBLE DASH HORIZONTAL
"\u254E":"|", // BOX DRAWINGS LIGHT DOUBLE DASH VERTICAL
"\u254F":"|", // BOX DRAWINGS HEAVY DOUBLE DASH VERTICAL
"\u2550":"=", // BOX DRAWINGS DOUBLE HORIZONTAL
"\u2551":"|", // BOX DRAWINGS DOUBLE VERTICAL
"\u2552":"+", // BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE
"\u2553":"+", // BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE
"\u2554":"+", // BOX DRAWINGS DOUBLE DOWN AND RIGHT
"\u2555":"+", // BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE
"\u2556":"+", // BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE
"\u2557":"+", // BOX DRAWINGS DOUBLE DOWN AND LEFT
"\u2558":"+", // BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE
"\u2559":"+", // BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE
"\u255A":"+", // BOX DRAWINGS DOUBLE UP AND RIGHT
"\u255B":"+", // BOX DRAWINGS UP SINGLE AND LEFT DOUBLE
"\u255C":"+", // BOX DRAWINGS UP DOUBLE AND LEFT SINGLE
"\u255D":"+", // BOX DRAWINGS DOUBLE UP AND LEFT
"\u255E":"+", // BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE
"\u255F":"+", // BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE
"\u2560":"+", // BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
"\u2561":"+", // BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE
"\u2562":"+", // BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE
"\u2563":"+", // BOX DRAWINGS DOUBLE VERTICAL AND LEFT
"\u2564":"+", // BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE
"\u2565":"+", // BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE
"\u2566":"+", // BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
"\u2567":"+", // BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE
"\u2568":"+", // BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE
"\u2569":"+", // BOX DRAWINGS DOUBLE UP AND HORIZONTAL
"\u256A":"+", // BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE
"\u256B":"+", // BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE
"\u256C":"+", // BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
"\u256D":"+", // BOX DRAWINGS LIGHT ARC DOWN AND RIGHT
"\u256E":"+", // BOX DRAWINGS LIGHT ARC DOWN AND LEFT
"\u256F":"+", // BOX DRAWINGS LIGHT ARC UP AND LEFT
"\u2570":"+", // BOX DRAWINGS LIGHT ARC UP AND RIGHT
"\u2571":"/", // BOX DRAWINGS LIGHT DIAGONAL UPPER RIGHT TO LOWER LEFT
"\u2572":"\\", // BOX DRAWINGS LIGHT DIAGONAL UPPER LEFT TO LOWER RIGHT
"\u2573":"X", // BOX DRAWINGS LIGHT DIAGONAL CROSS
"\u257C":"-", // BOX DRAWINGS LIGHT LEFT AND HEAVY RIGHT
"\u257D":"|", // BOX DRAWINGS LIGHT UP AND HEAVY DOWN
"\u257E":"-", // BOX DRAWINGS HEAVY LEFT AND LIGHT RIGHT
"\u257F":"|", // BOX DRAWINGS HEAVY UP AND LIGHT DOWN
"\u25CB":"o", // WHITE CIRCLE
"\u25E6":"{\\textopenbullet}", // WHITE BULLET
"\u2605":"*", // BLACK STAR
"\u2606":"*", // WHITE STAR
"\u2612":"X", // BALLOT BOX WITH X
"\u2613":"X", // SALTIRE
"\u2639":":-(", // WHITE FROWNING FACE
"\u263A":":-)", // WHITE SMILING FACE
"\u263B":"(-:", // BLACK SMILING FACE
"\u266D":"b", // MUSIC FLAT SIGN
"\u266F":"$\\#$", // MUSIC SHARP SIGN
"\u2701":"$\\%<$", // UPPER BLADE SCISSORS
"\u2702":"$\\%<$", // BLACK SCISSORS
"\u2703":"$\\%<$", // LOWER BLADE SCISSORS
"\u2704":"$\\%<$", // WHITE SCISSORS
"\u270C":"V", // VICTORY HAND
"\u2713":"v", // CHECK MARK
"\u2714":"V", // HEAVY CHECK MARK
"\u2715":"x", // MULTIPLICATION X
"\u2716":"x", // HEAVY MULTIPLICATION X
"\u2717":"X", // BALLOT X
"\u2718":"X", // HEAVY BALLOT X
"\u2719":"+", // OUTLINED GREEK CROSS
"\u271A":"+", // HEAVY GREEK CROSS
"\u271B":"+", // OPEN CENTRE CROSS
"\u271C":"+", // HEAVY OPEN CENTRE CROSS
"\u271D":"+", // LATIN CROSS
"\u271E":"+", // SHADOWED WHITE LATIN CROSS
"\u271F":"+", // OUTLINED LATIN CROSS
"\u2720":"+", // MALTESE CROSS
"\u2721":"*", // STAR OF DAVID
"\u2722":"+", // FOUR TEARDROP-SPOKED ASTERISK
"\u2723":"+", // FOUR BALLOON-SPOKED ASTERISK
"\u2724":"+", // HEAVY FOUR BALLOON-SPOKED ASTERISK
"\u2725":"+", // FOUR CLUB-SPOKED ASTERISK
"\u2726":"+", // BLACK FOUR POINTED STAR
"\u2727":"+", // WHITE FOUR POINTED STAR
"\u2729":"*", // STRESS OUTLINED WHITE STAR
"\u272A":"*", // CIRCLED WHITE STAR
"\u272B":"*", // OPEN CENTRE BLACK STAR
"\u272C":"*", // BLACK CENTRE WHITE STAR
"\u272D":"*", // OUTLINED BLACK STAR
"\u272E":"*", // HEAVY OUTLINED BLACK STAR
"\u272F":"*", // PINWHEEL STAR
"\u2730":"*", // SHADOWED WHITE STAR
"\u2731":"*", // HEAVY ASTERISK
"\u2732":"*", // OPEN CENTRE ASTERISK
"\u2733":"*", // EIGHT SPOKED ASTERISK
"\u2734":"*", // EIGHT POINTED BLACK STAR
"\u2735":"*", // EIGHT POINTED PINWHEEL STAR
"\u2736":"*", // SIX POINTED BLACK STAR
"\u2737":"*", // EIGHT POINTED RECTILINEAR BLACK STAR
"\u2738":"*", // HEAVY EIGHT POINTED RECTILINEAR BLACK STAR
"\u2739":"*", // TWELVE POINTED BLACK STAR
"\u273A":"*", // SIXTEEN POINTED ASTERISK
"\u273B":"*", // TEARDROP-SPOKED ASTERISK
"\u273C":"*", // OPEN CENTRE TEARDROP-SPOKED ASTERISK
"\u273D":"*", // HEAVY TEARDROP-SPOKED ASTERISK
"\u273E":"*", // SIX PETALLED BLACK AND WHITE FLORETTE
"\u273F":"*", // BLACK FLORETTE
"\u2740":"*", // WHITE FLORETTE
"\u2741":"*", // EIGHT PETALLED OUTLINED BLACK FLORETTE
"\u2742":"*", // CIRCLED OPEN CENTRE EIGHT POINTED STAR
"\u2743":"*", // HEAVY TEARDROP-SPOKED PINWHEEL ASTERISK
"\u2744":"*", // SNOWFLAKE
"\u2745":"*", // TIGHT TRIFOLIATE SNOWFLAKE
"\u2746":"*", // HEAVY CHEVRON SNOWFLAKE
"\u2747":"*", // SPARKLE
"\u2748":"*", // HEAVY SPARKLE
"\u2749":"*", // BALLOON-SPOKED ASTERISK
"\u274A":"*", // EIGHT TEARDROP-SPOKED PROPELLER ASTERISK
"\u274B":"*", // HEAVY EIGHT TEARDROP-SPOKED PROPELLER ASTERISK
"\uFB00":"ff", // LATIN SMALL LIGATURE FF
"\uFB01":"fi", // LATIN SMALL LIGATURE FI
"\uFB02":"fl", // LATIN SMALL LIGATURE FL
"\uFB03":"ffi", // LATIN SMALL LIGATURE FFI
"\uFB04":"ffl", // LATIN SMALL LIGATURE FFL
"\uFB05":"st", // LATIN SMALL LIGATURE LONG S T
"\uFB06":"st", // LATIN SMALL LIGATURE ST
/* Derived accented characters */
"\u00C0":"\\`{A}", // LATIN CAPITAL LETTER A WITH GRAVE
"\u00C1":"\\'{A}", // LATIN CAPITAL LETTER A WITH ACUTE
"\u00C2":"\\^{A}", // LATIN CAPITAL LETTER A WITH CIRCUMFLEX
"\u00C3":"\\~{A}", // LATIN CAPITAL LETTER A WITH TILDE
"\u00C4":"\\\"{A}", // LATIN CAPITAL LETTER A WITH DIAERESIS
"\u00C5":"\\r{A}", // LATIN CAPITAL LETTER A WITH RING ABOVE
"\u00C7":"\\c{C}", // LATIN CAPITAL LETTER C WITH CEDILLA
"\u00C8":"\\`{E}", // LATIN CAPITAL LETTER E WITH GRAVE
"\u00C9":"\\'{E}", // LATIN CAPITAL LETTER E WITH ACUTE
"\u00CA":"\\^{E}", // LATIN CAPITAL LETTER E WITH CIRCUMFLEX
"\u00CB":"\\\"{E}", // LATIN CAPITAL LETTER E WITH DIAERESIS
"\u00CC":"\\`{I}", // LATIN CAPITAL LETTER I WITH GRAVE
"\u00CD":"\\'{I}", // LATIN CAPITAL LETTER I WITH ACUTE
"\u00CE":"\\^{I}", // LATIN CAPITAL LETTER I WITH CIRCUMFLEX
"\u00CF":"\\\"{I}", // LATIN CAPITAL LETTER I WITH DIAERESIS
"\u00D1":"\\~{N}", // LATIN CAPITAL LETTER N WITH TILDE
"\u00D2":"\\`{O}", // LATIN CAPITAL LETTER O WITH GRAVE
"\u00D3":"\\'{O}", // LATIN CAPITAL LETTER O WITH ACUTE
"\u00D4":"\\^{O}", // LATIN CAPITAL LETTER O WITH CIRCUMFLEX
"\u00D5":"\\~{O}", // LATIN CAPITAL LETTER O WITH TILDE
"\u00D6":"\\\"{O}", // LATIN CAPITAL LETTER O WITH DIAERESIS
"\u00D9":"\\`{U}", // LATIN CAPITAL LETTER U WITH GRAVE
"\u00DA":"\\'{U}", // LATIN CAPITAL LETTER U WITH ACUTE
"\u00DB":"\\^{U}", // LATIN CAPITAL LETTER U WITH CIRCUMFLEX
"\u00DC":"\\\"{U}", // LATIN CAPITAL LETTER U WITH DIAERESIS
"\u00DD":"\\'{Y}", // LATIN CAPITAL LETTER Y WITH ACUTE
"\u00E0":"\\`{a}", // LATIN SMALL LETTER A WITH GRAVE
"\u00E1":"\\'{a}", // LATIN SMALL LETTER A WITH ACUTE
"\u00E2":"\\^{a}", // LATIN SMALL LETTER A WITH CIRCUMFLEX
"\u00E3":"\\~{a}", // LATIN SMALL LETTER A WITH TILDE
"\u00E4":"\\\"{a}", // LATIN SMALL LETTER A WITH DIAERESIS
"\u00E5":"\\r{a}", // LATIN SMALL LETTER A WITH RING ABOVE
"\u00E7":"\\c{c}", // LATIN SMALL LETTER C WITH CEDILLA
"\u00E8":"\\`{e}", // LATIN SMALL LETTER E WITH GRAVE
"\u00E9":"\\'{e}", // LATIN SMALL LETTER E WITH ACUTE
"\u00EA":"\\^{e}", // LATIN SMALL LETTER E WITH CIRCUMFLEX
"\u00EB":"\\\"{e}", // LATIN SMALL LETTER E WITH DIAERESIS
"\u00EC":"\\`{i}", // LATIN SMALL LETTER I WITH GRAVE
"\u00ED":"\\'{i}", // LATIN SMALL LETTER I WITH ACUTE
"\u00EE":"\\^{i}", // LATIN SMALL LETTER I WITH CIRCUMFLEX
"\u00EF":"\\\"{i}", // LATIN SMALL LETTER I WITH DIAERESIS
"\u00F1":"\\~{n}", // LATIN SMALL LETTER N WITH TILDE
"\u00F2":"\\`{o}", // LATIN SMALL LETTER O WITH GRAVE
"\u00F3":"\\'{o}", // LATIN SMALL LETTER O WITH ACUTE
"\u00F4":"\\^{o}", // LATIN SMALL LETTER O WITH CIRCUMFLEX
"\u00F5":"\\~{o}", // LATIN SMALL LETTER O WITH TILDE
"\u00F6":"\\\"{o}", // LATIN SMALL LETTER O WITH DIAERESIS
"\u00F9":"\\`{u}", // LATIN SMALL LETTER U WITH GRAVE
"\u00FA":"\\'{u}", // LATIN SMALL LETTER U WITH ACUTE
"\u00FB":"\\^{u}", // LATIN SMALL LETTER U WITH CIRCUMFLEX
"\u00FC":"\\\"{u}", // LATIN SMALL LETTER U WITH DIAERESIS
"\u00FD":"\\'{y}", // LATIN SMALL LETTER Y WITH ACUTE
"\u00FF":"\\\"{y}", // LATIN SMALL LETTER Y WITH DIAERESIS
"\u0100":"\\={A}", // LATIN CAPITAL LETTER A WITH MACRON
"\u0101":"\\={a}", // LATIN SMALL LETTER A WITH MACRON
"\u0102":"\\u{A}", // LATIN CAPITAL LETTER A WITH BREVE
"\u0103":"\\u{a}", // LATIN SMALL LETTER A WITH BREVE
"\u0104":"\\k{A}", // LATIN CAPITAL LETTER A WITH OGONEK
"\u0105":"\\k{a}", // LATIN SMALL LETTER A WITH OGONEK
"\u0106":"\\'{C}", // LATIN CAPITAL LETTER C WITH ACUTE
"\u0107":"\\'{c}", // LATIN SMALL LETTER C WITH ACUTE
"\u0108":"\\^{C}", // LATIN CAPITAL LETTER C WITH CIRCUMFLEX
"\u0109":"\\^{c}", // LATIN SMALL LETTER C WITH CIRCUMFLEX
"\u010A":"\\.{C}", // LATIN CAPITAL LETTER C WITH DOT ABOVE
"\u010B":"\\.{c}", // LATIN SMALL LETTER C WITH DOT ABOVE
"\u010C":"\\v{C}", // LATIN CAPITAL LETTER C WITH CARON
"\u010D":"\\v{c}", // LATIN SMALL LETTER C WITH CARON
"\u010E":"\\v{D}", // LATIN CAPITAL LETTER D WITH CARON
"\u010F":"\\v{d}", // LATIN SMALL LETTER D WITH CARON
"\u0112":"\\={E}", // LATIN CAPITAL LETTER E WITH MACRON
"\u0113":"\\={e}", // LATIN SMALL LETTER E WITH MACRON
"\u0114":"\\u{E}", // LATIN CAPITAL LETTER E WITH BREVE
"\u0115":"\\u{e}", // LATIN SMALL LETTER E WITH BREVE
"\u0116":"\\.{E}", // LATIN CAPITAL LETTER E WITH DOT ABOVE
"\u0117":"\\.{e}", // LATIN SMALL LETTER E WITH DOT ABOVE
"\u0118":"\\k{E}", // LATIN CAPITAL LETTER E WITH OGONEK
"\u0119":"\\k{e}", // LATIN SMALL LETTER E WITH OGONEK
"\u011A":"\\v{E}", // LATIN CAPITAL LETTER E WITH CARON
"\u011B":"\\v{e}", // LATIN SMALL LETTER E WITH CARON
"\u011C":"\\^{G}", // LATIN CAPITAL LETTER G WITH CIRCUMFLEX
"\u011D":"\\^{g}", // LATIN SMALL LETTER G WITH CIRCUMFLEX
"\u011E":"\\u{G}", // LATIN CAPITAL LETTER G WITH BREVE
"\u011F":"\\u{g}", // LATIN SMALL LETTER G WITH BREVE
"\u0120":"\\.{G}", // LATIN CAPITAL LETTER G WITH DOT ABOVE
"\u0121":"\\.{g}", // LATIN SMALL LETTER G WITH DOT ABOVE
"\u0122":"\\c{G}", // LATIN CAPITAL LETTER G WITH CEDILLA
"\u0123":"\\c{g}", // LATIN SMALL LETTER G WITH CEDILLA
"\u0124":"\\^{H}", // LATIN CAPITAL LETTER H WITH CIRCUMFLEX
"\u0125":"\\^{h}", // LATIN SMALL LETTER H WITH CIRCUMFLEX
"\u0128":"\\~{I}", // LATIN CAPITAL LETTER I WITH TILDE
"\u0129":"\\~{i}", // LATIN SMALL LETTER I WITH TILDE
"\u012A":"\\={I}", // LATIN CAPITAL LETTER I WITH MACRON
"\u012B":"\\={i}", // LATIN SMALL LETTER I WITH MACRON
"\u012C":"\\u{I}", // LATIN CAPITAL LETTER I WITH BREVE
"\u012D":"\\u{i}", // LATIN SMALL LETTER I WITH BREVE
"\u012E":"\\k{I}", // LATIN CAPITAL LETTER I WITH OGONEK
"\u012F":"\\k{i}", // LATIN SMALL LETTER I WITH OGONEK
"\u0130":"\\.{I}", // LATIN CAPITAL LETTER I WITH DOT ABOVE
"\u0134":"\\^{J}", // LATIN CAPITAL LETTER J WITH CIRCUMFLEX
"\u0135":"\\^{j}", // LATIN SMALL LETTER J WITH CIRCUMFLEX
"\u0136":"\\c{K}", // LATIN CAPITAL LETTER K WITH CEDILLA
"\u0137":"\\c{k}", // LATIN SMALL LETTER K WITH CEDILLA
"\u0139":"\\'{L}", // LATIN CAPITAL LETTER L WITH ACUTE
"\u013A":"\\'{l}", // LATIN SMALL LETTER L WITH ACUTE
"\u013B":"\\c{L}", // LATIN CAPITAL LETTER L WITH CEDILLA
"\u013C":"\\c{l}", // LATIN SMALL LETTER L WITH CEDILLA
"\u013D":"\\v{L}", // LATIN CAPITAL LETTER L WITH CARON
"\u013E":"\\v{l}", // LATIN SMALL LETTER L WITH CARON
"\u0141":"\\L{}", //LATIN CAPITAL LETTER L WITH STROKE
"\u0142":"\\l{}", //LATIN SMALL LETTER L WITH STROKE
"\u0143":"\\'{N}", // LATIN CAPITAL LETTER N WITH ACUTE
"\u0144":"\\'{n}", // LATIN SMALL LETTER N WITH ACUTE
"\u0145":"\\c{N}", // LATIN CAPITAL LETTER N WITH CEDILLA
"\u0146":"\\c{n}", // LATIN SMALL LETTER N WITH CEDILLA
"\u0147":"\\v{N}", // LATIN CAPITAL LETTER N WITH CARON
"\u0148":"\\v{n}", // LATIN SMALL LETTER N WITH CARON
"\u014C":"\\={O}", // LATIN CAPITAL LETTER O WITH MACRON
"\u014D":"\\={o}", // LATIN SMALL LETTER O WITH MACRON
"\u014E":"\\u{O}", // LATIN CAPITAL LETTER O WITH BREVE
"\u014F":"\\u{o}", // LATIN SMALL LETTER O WITH BREVE
"\u0150":"\\H{O}", // LATIN CAPITAL LETTER O WITH DOUBLE ACUTE
"\u0151":"\\H{o}", // LATIN SMALL LETTER O WITH DOUBLE ACUTE
"\u0154":"\\'{R}", // LATIN CAPITAL LETTER R WITH ACUTE
"\u0155":"\\'{r}", // LATIN SMALL LETTER R WITH ACUTE
"\u0156":"\\c{R}", // LATIN CAPITAL LETTER R WITH CEDILLA
"\u0157":"\\c{r}", // LATIN SMALL LETTER R WITH CEDILLA
"\u0158":"\\v{R}", // LATIN CAPITAL LETTER R WITH CARON
"\u0159":"\\v{r}", // LATIN SMALL LETTER R WITH CARON
"\u015A":"\\'{S}", // LATIN CAPITAL LETTER S WITH ACUTE
"\u015B":"\\'{s}", // LATIN SMALL LETTER S WITH ACUTE
"\u015C":"\\^{S}", // LATIN CAPITAL LETTER S WITH CIRCUMFLEX
"\u015D":"\\^{s}", // LATIN SMALL LETTER S WITH CIRCUMFLEX
"\u015E":"\\c{S}", // LATIN CAPITAL LETTER S WITH CEDILLA
"\u015F":"\\c{s}", // LATIN SMALL LETTER S WITH CEDILLA
"\u0160":"\\v{S}", // LATIN CAPITAL LETTER S WITH CARON
"\u0161":"\\v{s}", // LATIN SMALL LETTER S WITH CARON
"\u0162":"\\c{T}", // LATIN CAPITAL LETTER T WITH CEDILLA
"\u0163":"\\c{t}", // LATIN SMALL LETTER T WITH CEDILLA
"\u0164":"\\v{T}", // LATIN CAPITAL LETTER T WITH CARON
"\u0165":"\\v{t}", // LATIN SMALL LETTER T WITH CARON
"\u0168":"\\~{U}", // LATIN CAPITAL LETTER U WITH TILDE
"\u0169":"\\~{u}", // LATIN SMALL LETTER U WITH TILDE
"\u016A":"\\={U}", // LATIN CAPITAL LETTER U WITH MACRON
"\u016B":"\\={u}", // LATIN SMALL LETTER U WITH MACRON
"\u016C":"\\u{U}", // LATIN CAPITAL LETTER U WITH BREVE
"\u016D":"\\u{u}", // LATIN SMALL LETTER U WITH BREVE
"\u0170":"\\H{U}", // LATIN CAPITAL LETTER U WITH DOUBLE ACUTE
"\u0171":"\\H{u}", // LATIN SMALL LETTER U WITH DOUBLE ACUTE
"\u0172":"\\k{U}", // LATIN CAPITAL LETTER U WITH OGONEK
"\u0173":"\\k{u}", // LATIN SMALL LETTER U WITH OGONEK
"\u0174":"\\^{W}", // LATIN CAPITAL LETTER W WITH CIRCUMFLEX
"\u0175":"\\^{w}", // LATIN SMALL LETTER W WITH CIRCUMFLEX
"\u0176":"\\^{Y}", // LATIN CAPITAL LETTER Y WITH CIRCUMFLEX
"\u0177":"\\^{y}", // LATIN SMALL LETTER Y WITH CIRCUMFLEX
"\u0178":"\\\"{Y}", // LATIN CAPITAL LETTER Y WITH DIAERESIS
"\u0179":"\\'{Z}", // LATIN CAPITAL LETTER Z WITH ACUTE
"\u017A":"\\'{z}", // LATIN SMALL LETTER Z WITH ACUTE
"\u017B":"\\.{Z}", // LATIN CAPITAL LETTER Z WITH DOT ABOVE
"\u017C":"\\.{z}", // LATIN SMALL LETTER Z WITH DOT ABOVE
"\u017D":"\\v{Z}", // LATIN CAPITAL LETTER Z WITH CARON
"\u017E":"\\v{z}", // LATIN SMALL LETTER Z WITH CARON
"\u01CD":"\\v{A}", // LATIN CAPITAL LETTER A WITH CARON
"\u01CE":"\\v{a}", // LATIN SMALL LETTER A WITH CARON
"\u01CF":"\\v{I}", // LATIN CAPITAL LETTER I WITH CARON
"\u01D0":"\\v{i}", // LATIN SMALL LETTER I WITH CARON
"\u01D1":"\\v{O}", // LATIN CAPITAL LETTER O WITH CARON
"\u01D2":"\\v{o}", // LATIN SMALL LETTER O WITH CARON
"\u01D3":"\\v{U}", // LATIN CAPITAL LETTER U WITH CARON
"\u01D4":"\\v{u}", // LATIN SMALL LETTER U WITH CARON
"\u01E6":"\\v{G}", // LATIN CAPITAL LETTER G WITH CARON
"\u01E7":"\\v{g}", // LATIN SMALL LETTER G WITH CARON
"\u01E8":"\\v{K}", // LATIN CAPITAL LETTER K WITH CARON
"\u01E9":"\\v{k}", // LATIN SMALL LETTER K WITH CARON
"\u01EA":"\\k{O}", // LATIN CAPITAL LETTER O WITH OGONEK
"\u01EB":"\\k{o}", // LATIN SMALL LETTER O WITH OGONEK
"\u01F0":"\\v{j}", // LATIN SMALL LETTER J WITH CARON
"\u01F4":"\\'{G}", // LATIN CAPITAL LETTER G WITH ACUTE
"\u01F5":"\\'{g}", // LATIN SMALL LETTER G WITH ACUTE
"\u1E02":"\\.{B}", // LATIN CAPITAL LETTER B WITH DOT ABOVE
"\u1E03":"\\.{b}", // LATIN SMALL LETTER B WITH DOT ABOVE
"\u1E04":"\\d{B}", // LATIN CAPITAL LETTER B WITH DOT BELOW
"\u1E05":"\\d{b}", // LATIN SMALL LETTER B WITH DOT BELOW
"\u1E06":"\\b{B}", // LATIN CAPITAL LETTER B WITH LINE BELOW
"\u1E07":"\\b{b}", // LATIN SMALL LETTER B WITH LINE BELOW
"\u1E0A":"\\.{D}", // LATIN CAPITAL LETTER D WITH DOT ABOVE
"\u1E0B":"\\.{d}", // LATIN SMALL LETTER D WITH DOT ABOVE
"\u1E0C":"\\d{D}", // LATIN CAPITAL LETTER D WITH DOT BELOW
"\u1E0D":"\\d{d}", // LATIN SMALL LETTER D WITH DOT BELOW
"\u1E0E":"\\b{D}", // LATIN CAPITAL LETTER D WITH LINE BELOW
"\u1E0F":"\\b{d}", // LATIN SMALL LETTER D WITH LINE BELOW
"\u1E10":"\\c{D}", // LATIN CAPITAL LETTER D WITH CEDILLA
"\u1E11":"\\c{d}", // LATIN SMALL LETTER D WITH CEDILLA
"\u1E1E":"\\.{F}", // LATIN CAPITAL LETTER F WITH DOT ABOVE
"\u1E1F":"\\.{f}", // LATIN SMALL LETTER F WITH DOT ABOVE
"\u1E20":"\\={G}", // LATIN CAPITAL LETTER G WITH MACRON
"\u1E21":"\\={g}", // LATIN SMALL LETTER G WITH MACRON
"\u1E22":"\\.{H}", // LATIN CAPITAL LETTER H WITH DOT ABOVE
"\u1E23":"\\.{h}", // LATIN SMALL LETTER H WITH DOT ABOVE
"\u1E24":"\\d{H}", // LATIN CAPITAL LETTER H WITH DOT BELOW
"\u1E25":"\\d{h}", // LATIN SMALL LETTER H WITH DOT BELOW
"\u1E26":"\\\"{H}", // LATIN CAPITAL LETTER H WITH DIAERESIS
"\u1E27":"\\\"{h}", // LATIN SMALL LETTER H WITH DIAERESIS
"\u1E28":"\\c{H}", // LATIN CAPITAL LETTER H WITH CEDILLA
"\u1E29":"\\c{h}", // LATIN SMALL LETTER H WITH CEDILLA
"\u1E30":"\\'{K}", // LATIN CAPITAL LETTER K WITH ACUTE
"\u1E31":"\\'{k}", // LATIN SMALL LETTER K WITH ACUTE
"\u1E32":"\\d{K}", // LATIN CAPITAL LETTER K WITH DOT BELOW
"\u1E33":"\\d{k}", // LATIN SMALL LETTER K WITH DOT BELOW
"\u1E34":"\\b{K}", // LATIN CAPITAL LETTER K WITH LINE BELOW
"\u1E35":"\\b{k}", // LATIN SMALL LETTER K WITH LINE BELOW
"\u1E36":"\\d{L}", // LATIN CAPITAL LETTER L WITH DOT BELOW
"\u1E37":"\\d{l}", // LATIN SMALL LETTER L WITH DOT BELOW
"\u1E3A":"\\b{L}", // LATIN CAPITAL LETTER L WITH LINE BELOW
"\u1E3B":"\\b{l}", // LATIN SMALL LETTER L WITH LINE BELOW
"\u1E3E":"\\'{M}", // LATIN CAPITAL LETTER M WITH ACUTE
"\u1E3F":"\\'{m}", // LATIN SMALL LETTER M WITH ACUTE
"\u1E40":"\\.{M}", // LATIN CAPITAL LETTER M WITH DOT ABOVE
"\u1E41":"\\.{m}", // LATIN SMALL LETTER M WITH DOT ABOVE
"\u1E42":"\\d{M}", // LATIN CAPITAL LETTER M WITH DOT BELOW
"\u1E43":"\\d{m}", // LATIN SMALL LETTER M WITH DOT BELOW
"\u1E44":"\\.{N}", // LATIN CAPITAL LETTER N WITH DOT ABOVE
"\u1E45":"\\.{n}", // LATIN SMALL LETTER N WITH DOT ABOVE
"\u1E46":"\\d{N}", // LATIN CAPITAL LETTER N WITH DOT BELOW
"\u1E47":"\\d{n}", // LATIN SMALL LETTER N WITH DOT BELOW
"\u1E48":"\\b{N}", // LATIN CAPITAL LETTER N WITH LINE BELOW
"\u1E49":"\\b{n}", // LATIN SMALL LETTER N WITH LINE BELOW
"\u1E54":"\\'{P}", // LATIN CAPITAL LETTER P WITH ACUTE
"\u1E55":"\\'{p}", // LATIN SMALL LETTER P WITH ACUTE
"\u1E56":"\\.{P}", // LATIN CAPITAL LETTER P WITH DOT ABOVE
"\u1E57":"\\.{p}", // LATIN SMALL LETTER P WITH DOT ABOVE
"\u1E58":"\\.{R}", // LATIN CAPITAL LETTER R WITH DOT ABOVE
"\u1E59":"\\.{r}", // LATIN SMALL LETTER R WITH DOT ABOVE
"\u1E5A":"\\d{R}", // LATIN CAPITAL LETTER R WITH DOT BELOW
"\u1E5B":"\\d{r}", // LATIN SMALL LETTER R WITH DOT BELOW
"\u1E5E":"\\b{R}", // LATIN CAPITAL LETTER R WITH LINE BELOW
"\u1E5F":"\\b{r}", // LATIN SMALL LETTER R WITH LINE BELOW
"\u1E60":"\\.{S}", // LATIN CAPITAL LETTER S WITH DOT ABOVE
"\u1E61":"\\.{s}", // LATIN SMALL LETTER S WITH DOT ABOVE
"\u1E62":"\\d{S}", // LATIN CAPITAL LETTER S WITH DOT BELOW
"\u1E63":"\\d{s}", // LATIN SMALL LETTER S WITH DOT BELOW
"\u1E6A":"\\.{T}", // LATIN CAPITAL LETTER T WITH DOT ABOVE
"\u1E6B":"\\.{t}", // LATIN SMALL LETTER T WITH DOT ABOVE
"\u1E6C":"\\d{T}", // LATIN CAPITAL LETTER T WITH DOT BELOW
"\u1E6D":"\\d{t}", // LATIN SMALL LETTER T WITH DOT BELOW
"\u1E6E":"\\b{T}", // LATIN CAPITAL LETTER T WITH LINE BELOW
"\u1E6F":"\\b{t}", // LATIN SMALL LETTER T WITH LINE BELOW
"\u1E7C":"\\~{V}", // LATIN CAPITAL LETTER V WITH TILDE
"\u1E7D":"\\~{v}", // LATIN SMALL LETTER V WITH TILDE
"\u1E7E":"\\d{V}", // LATIN CAPITAL LETTER V WITH DOT BELOW
"\u1E7F":"\\d{v}", // LATIN SMALL LETTER V WITH DOT BELOW
"\u1E80":"\\`{W}", // LATIN CAPITAL LETTER W WITH GRAVE
"\u1E81":"\\`{w}", // LATIN SMALL LETTER W WITH GRAVE
"\u1E82":"\\'{W}", // LATIN CAPITAL LETTER W WITH ACUTE
"\u1E83":"\\'{w}", // LATIN SMALL LETTER W WITH ACUTE
"\u1E84":"\\\"{W}", // LATIN CAPITAL LETTER W WITH DIAERESIS
"\u1E85":"\\\"{w}", // LATIN SMALL LETTER W WITH DIAERESIS
"\u1E86":"\\.{W}", // LATIN CAPITAL LETTER W WITH DOT ABOVE
"\u1E87":"\\.{w}", // LATIN SMALL LETTER W WITH DOT ABOVE
"\u1E88":"\\d{W}", // LATIN CAPITAL LETTER W WITH DOT BELOW
"\u1E89":"\\d{w}", // LATIN SMALL LETTER W WITH DOT BELOW
"\u1E8A":"\\.{X}", // LATIN CAPITAL LETTER X WITH DOT ABOVE
"\u1E8B":"\\.{x}", // LATIN SMALL LETTER X WITH DOT ABOVE
"\u1E8C":"\\\"{X}", // LATIN CAPITAL LETTER X WITH DIAERESIS
"\u1E8D":"\\\"{x}", // LATIN SMALL LETTER X WITH DIAERESIS
"\u1E8E":"\\.{Y}", // LATIN CAPITAL LETTER Y WITH DOT ABOVE
"\u1E8F":"\\.{y}", // LATIN SMALL LETTER Y WITH DOT ABOVE
"\u1E90":"\\^{Z}", // LATIN CAPITAL LETTER Z WITH CIRCUMFLEX
"\u1E91":"\\^{z}", // LATIN SMALL LETTER Z WITH CIRCUMFLEX
"\u1E92":"\\d{Z}", // LATIN CAPITAL LETTER Z WITH DOT BELOW
"\u1E93":"\\d{z}", // LATIN SMALL LETTER Z WITH DOT BELOW
"\u1E94":"\\b{Z}", // LATIN CAPITAL LETTER Z WITH LINE BELOW
"\u1E95":"\\b{z}", // LATIN SMALL LETTER Z WITH LINE BELOW
"\u1E96":"\\b{h}", // LATIN SMALL LETTER H WITH LINE BELOW
"\u1E97":"\\\"{t}", // LATIN SMALL LETTER T WITH DIAERESIS
"\u1EA0":"\\d{A}", // LATIN CAPITAL LETTER A WITH DOT BELOW
"\u1EA1":"\\d{a}", // LATIN SMALL LETTER A WITH DOT BELOW
"\u1EB8":"\\d{E}", // LATIN CAPITAL LETTER E WITH DOT BELOW
"\u1EB9":"\\d{e}", // LATIN SMALL LETTER E WITH DOT BELOW
"\u1EBC":"\\~{E}", // LATIN CAPITAL LETTER E WITH TILDE
"\u1EBD":"\\~{e}", // LATIN SMALL LETTER E WITH TILDE
"\u1ECA":"\\d{I}", // LATIN CAPITAL LETTER I WITH DOT BELOW
"\u1ECB":"\\d{i}", // LATIN SMALL LETTER I WITH DOT BELOW
"\u1ECC":"\\d{O}", // LATIN CAPITAL LETTER O WITH DOT BELOW
"\u1ECD":"\\d{o}", // LATIN SMALL LETTER O WITH DOT BELOW
"\u1EE4":"\\d{U}", // LATIN CAPITAL LETTER U WITH DOT BELOW
"\u1EE5":"\\d{u}", // LATIN SMALL LETTER U WITH DOT BELOW
"\u1EF2":"\\`{Y}", // LATIN CAPITAL LETTER Y WITH GRAVE
"\u1EF3":"\\`{y}", // LATIN SMALL LETTER Y WITH GRAVE
"\u1EF4":"\\d{Y}", // LATIN CAPITAL LETTER Y WITH DOT BELOW
"\u1EF5":"\\d{y}", // LATIN SMALL LETTER Y WITH DOT BELOW
"\u1EF8":"\\~{Y}", // LATIN CAPITAL LETTER Y WITH TILDE
"\u1EF9":"\\~{y}" // LATIN SMALL LETTER Y WITH TILDE
};
/* unfortunately the mapping isn't reversible - hence this second table - sigh! */
var reversemappingTable = {
"\\url" : "", // strip 'url'
"\\href" : "", // strip 'href'
"{\\textexclamdown}" : "\u00A1", // INVERTED EXCLAMATION MARK
"{\\textcent}" : "\u00A2", // CENT SIGN
"{\\textsterling}" : "\u00A3", // POUND SIGN
"{\\textyen}" : "\u00A5", // YEN SIGN
"{\\textbrokenbar}" : "\u00A6", // BROKEN BAR
"{\\textsection}" : "\u00A7", // SECTION SIGN
"{\\textasciidieresis}" : "\u00A8", // DIAERESIS
"{\\textcopyright}" : "\u00A9", // COPYRIGHT SIGN
"{\\textordfeminine}" : "\u00AA", // FEMININE ORDINAL INDICATOR
"{\\guillemotleft}" : "\u00AB", // LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
"{\\textlnot}" : "\u00AC", // NOT SIGN
"{\\textregistered}" : "\u00AE", // REGISTERED SIGN
"{\\textasciimacron}" : "\u00AF", // MACRON
"{\\textdegree}" : "\u00B0", // DEGREE SIGN
"{\\textpm}" : "\u00B1", // PLUS-MINUS SIGN
"{\\texttwosuperior}" : "\u00B2", // SUPERSCRIPT TWO
"{\\textthreesuperior}" : "\u00B3", // SUPERSCRIPT THREE
"{\\textasciiacute}" : "\u00B4", // ACUTE ACCENT
"{\\textmu}" : "\u00B5", // MICRO SIGN
"{\\textparagraph}" : "\u00B6", // PILCROW SIGN
"{\\textperiodcentered}" : "\u00B7", // MIDDLE DOT
"{\\c\\ }" : "\u00B8", // CEDILLA
"{\\textonesuperior}" : "\u00B9", // SUPERSCRIPT ONE
"{\\textordmasculine}" : "\u00BA", // MASCULINE ORDINAL INDICATOR
"{\\guillemotright}" : "\u00BB", // RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
"{\\textonequarter}" : "\u00BC", // VULGAR FRACTION ONE QUARTER
"{\\textonehalf}" : "\u00BD", // VULGAR FRACTION ONE HALF
"{\\textthreequarters}" : "\u00BE", // VULGAR FRACTION THREE QUARTERS
"{\\textquestiondown}" : "\u00BF", // INVERTED QUESTION MARK
"{\\AE}" : "\u00C6", // LATIN CAPITAL LETTER AE
"{\\DH}" : "\u00D0", // LATIN CAPITAL LETTER ETH
"{\\texttimes}" : "\u00D7", // MULTIPLICATION SIGN
"{\\O}" : "\U00D8", // LATIN SMALL LETTER O WITH STROKE
"{\\TH}" : "\u00DE", // LATIN CAPITAL LETTER THORN
"{\\ss}" : "\u00DF", // LATIN SMALL LETTER SHARP S
"{\\ae}" : "\u00E6", // LATIN SMALL LETTER AE
"{\\dh}" : "\u00F0", // LATIN SMALL LETTER ETH
"{\\textdiv}" : "\u00F7", // DIVISION SIGN
"{\\o}" : "\U00F8", // LATIN SMALL LETTER O WITH STROKE
"{\\th}" : "\u00FE", // LATIN SMALL LETTER THORN
"{\\i}" : "\u0131", // LATIN SMALL LETTER DOTLESS I
"'n" : "\u0149", // LATIN SMALL LETTER N PRECEDED BY APOSTROPHE
"{\\NG}" : "\u014A", // LATIN CAPITAL LETTER ENG
"{\\ng}" : "\u014B", // LATIN SMALL LETTER ENG
"{\\OE}" : "\u0152", // LATIN CAPITAL LIGATURE OE
"{\\oe}" : "\u0153", // LATIN SMALL LIGATURE OE
"{\\textasciicircum}" : "\u02C6", // MODIFIER LETTER CIRCUMFLEX ACCENT
// "\\~{}" : "\u02DC", // SMALL TILDE
"{\\textacutedbl}" : "\u02DD", // DOUBLE ACUTE ACCENT
// -- Tan -begin greek symbols
"$\\Gamma$" : "\u0393", // GREEK Gamma
"$\\Delta$" : "\u0394", // GREEK Delta
"$\\Theta$" : "\u0398", // GREEK Theta
"$\\Lambda$" : "\u039B", // GREEK Lambda
"$\\Xi$" : "\u039E", // GREEK Xi
"$\\Pi$" : "\u03A0", // GREEK Pi
"$\\Sigma$" : "\u03A3", // GREEK Sigma
"$\\Phi$" : "\u03A6", // GREEK Phi
"$\\Psi$" : "\u03A8", // GREEK Psi
"$\\Omega$" : "\u03A9", // GREEK Omega
"$\\alpha$" : "\u03B1", // GREEK alpha
"$\\beta$" : "\u03B2", // GREEK beta
"$\\gamma$" : "\u03B3", // GREEK gamma
"$\\delta$" : "\u03B4", // GREEK delta
"$\\varepsilon$": "\u03B5", // GREEK var-epsilon
"$\\zeta$" : "\u03B6", // GREEK zeta
"$\\eta$" : "\u03B7", // GREEK eta
"$\\theta$" : "\u03B8", // GREEK theta
"$\\iota$" : "\u03B9", // GREEK iota
"$\\kappa$" : "\u03BA", // GREEK kappa
"$\\lambda$" : "\u03BB", // GREEK lambda
"$\\mu$" : "\u03BC", // GREEK mu
"$\\nu$" : "\u03BD", // GREEK nu
"$\\xi$" : "\u03BE", // GREEK xi
"$\\pi$" : "\u03C0", // GREEK pi
"$\\rho$" : "\u03C1", // GREEK rho
"$\\varsigma$" : "\u03C2", // GREEK var-sigma
"$\\sigma$" : "\u03C3", // GREEK sigma
"$\\tau$" : "\u03C4", // GREEK tau
"$\\upsilon$" : "\u03C5", // GREEK upsilon
"$\\varphi$" : "\u03C6", // GREEK var-phi
"$\\chi$" : "\u03C7", // GREEK chi
"$\\psi$" : "\u03C8", // GREEK psi
"$\\omega$" : "\u03C9", // GREEK omega
"$\\vartheta$" : "\u03D1", // GREEK var-theta
"$\\Upsilon$" : "\u03D2", // GREEK Upsilon
"$\\phi$" : "\u03D5", // GREEK phi
"$\\varpi$" : "\u03D6", // GREEK var-pi
"$\\varrho$" : "\u03F1", // GREEK var-rho
"$\\epsilon$" : "\u03F5", // GREEK epsilon
// -- Tan -end greek symbols
"{\\textendash}" : "\u2013", // EN DASH
"{\\textemdash}" : "\u2014", // EM DASH
"---" : "\u2014", // EM DASH
"--" : "\u2013", // EN DASH
"{\\textbardbl}" : "\u2016", // DOUBLE VERTICAL LINE
"{\\textunderscore}" : "\u2017", // DOUBLE LOW LINE
"{\\textquoteleft}" : "\u2018", // LEFT SINGLE QUOTATION MARK
"{\\textquoteright}" : "\u2019", // RIGHT SINGLE QUOTATION MARK
"{\\quotesinglbase}" : "\u201A", // SINGLE LOW-9 QUOTATION MARK
"{\\textquotedblleft}" : "\u201C", // LEFT DOUBLE QUOTATION MARK
"{\\textquotedblright}" : "\u201D", // RIGHT DOUBLE QUOTATION MARK
"{\\quotedblbase}" : "\u201E", // DOUBLE LOW-9 QUOTATION MARK
// "{\\quotedblbase}" : "\u201F", // DOUBLE HIGH-REVERSED-9 QUOTATION MARK
"{\\textdagger}" : "\u2020", // DAGGER
"{\\textdaggerdbl}" : "\u2021", // DOUBLE DAGGER
"{\\textbullet}" : "\u2022", // BULLET
"{\\textellipsis}" : "\u2026", // HORIZONTAL ELLIPSIS
"{\\textperthousand}" : "\u2030", // PER MILLE SIGN
"'''" : "\u2034", // TRIPLE PRIME
"''" : "\u201D", // RIGHT DOUBLE QUOTATION MARK (could be a double prime)
"``" : "\u201C", // LEFT DOUBLE QUOTATION MARK (could be a reversed double prime)
"```" : "\u2037", // REVERSED TRIPLE PRIME
"{\\guilsinglleft}" : "\u2039", // SINGLE LEFT-POINTING ANGLE QUOTATION MARK
"{\\guilsinglright}" : "\u203A", // SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
"!!" : "\u203C", // DOUBLE EXCLAMATION MARK
"{\\textfractionsolidus}" : "\u2044", // FRACTION SLASH
"?!" : "\u2048", // QUESTION EXCLAMATION MARK
"!?" : "\u2049", // EXCLAMATION QUESTION MARK
"$^{0}$" : "\u2070", // SUPERSCRIPT ZERO
"$^{4}$" : "\u2074", // SUPERSCRIPT FOUR
"$^{5}$" : "\u2075", // SUPERSCRIPT FIVE
"$^{6}$" : "\u2076", // SUPERSCRIPT SIX
"$^{7}$" : "\u2077", // SUPERSCRIPT SEVEN
"$^{8}$" : "\u2078", // SUPERSCRIPT EIGHT
"$^{9}$" : "\u2079", // SUPERSCRIPT NINE
"$^{+}$" : "\u207A", // SUPERSCRIPT PLUS SIGN
"$^{-}$" : "\u207B", // SUPERSCRIPT MINUS
"$^{=}$" : "\u207C", // SUPERSCRIPT EQUALS SIGN
"$^{(}$" : "\u207D", // SUPERSCRIPT LEFT PARENTHESIS
"$^{)}$" : "\u207E", // SUPERSCRIPT RIGHT PARENTHESIS
"$^{n}$" : "\u207F", // SUPERSCRIPT LATIN SMALL LETTER N
"$_{0}$" : "\u2080", // SUBSCRIPT ZERO
"$_{1}$" : "\u2081", // SUBSCRIPT ONE
"$_{2}$" : "\u2082", // SUBSCRIPT TWO
"$_{3}$" : "\u2083", // SUBSCRIPT THREE
"$_{4}$" : "\u2084", // SUBSCRIPT FOUR
"$_{5}$" : "\u2085", // SUBSCRIPT FIVE
"$_{6}$" : "\u2086", // SUBSCRIPT SIX
"$_{7}$" : "\u2087", // SUBSCRIPT SEVEN
"$_{8}$" : "\u2088", // SUBSCRIPT EIGHT
"$_{9}$" : "\u2089", // SUBSCRIPT NINE
"$_{+}$" : "\u208A", // SUBSCRIPT PLUS SIGN
"$_{-}$" : "\u208B", // SUBSCRIPT MINUS
"$_{=}$" : "\u208C", // SUBSCRIPT EQUALS SIGN
"$_{(}$" : "\u208D", // SUBSCRIPT LEFT PARENTHESIS
"$_{)}$" : "\u208E", // SUBSCRIPT RIGHT PARENTHESIS
"{\\texteuro}" : "\u20AC", // EURO SIGN
"a/c" : "\u2100", // ACCOUNT OF
"a/s" : "\u2101", // ADDRESSED TO THE SUBJECT
"{\\textcelsius}" : "\u2103", // DEGREE CELSIUS
"c/o" : "\u2105", // CARE OF
"c/u" : "\u2106", // CADA UNA
"{\\textnumero}" : "\u2116", // NUMERO SIGN
"{\\textcircledP}" : "\u2117", // SOUND RECORDING COPYRIGHT
"{\\textservicemark}" : "\u2120", // SERVICE MARK
"{TEL}" : "\u2121", // TELEPHONE SIGN
"{\\texttrademark}" : "\u2122", // TRADE MARK SIGN
"{\\textohm}" : "\u2126", // OHM SIGN
"{\\textestimated}" : "\u212E", // ESTIMATED SYMBOL
" 1/3" : "\u2153", // VULGAR FRACTION ONE THIRD
" 2/3" : "\u2154", // VULGAR FRACTION TWO THIRDS
" 1/5" : "\u2155", // VULGAR FRACTION ONE FIFTH
" 2/5" : "\u2156", // VULGAR FRACTION TWO FIFTHS
" 3/5" : "\u2157", // VULGAR FRACTION THREE FIFTHS
" 4/5" : "\u2158", // VULGAR FRACTION FOUR FIFTHS
" 1/6" : "\u2159", // VULGAR FRACTION ONE SIXTH
" 5/6" : "\u215A", // VULGAR FRACTION FIVE SIXTHS
" 1/8" : "\u215B", // VULGAR FRACTION ONE EIGHTH
" 3/8" : "\u215C", // VULGAR FRACTION THREE EIGHTHS
" 5/8" : "\u215D", // VULGAR FRACTION FIVE EIGHTHS
" 7/8" : "\u215E", // VULGAR FRACTION SEVEN EIGHTHS
" 1/" : "\u215F", // FRACTION NUMERATOR ONE
"{\\textleftarrow}" : "\u2190", // LEFTWARDS ARROW
"{\\textuparrow}" : "\u2191", // UPWARDS ARROW
"{\\textrightarrow}" : "\u2192", // RIGHTWARDS ARROW
"{\\textdownarrow}" : "\u2193", // DOWNWARDS ARROW
"<->" : "\u2194", // LEFT RIGHT ARROW
"<=" : "\u21D0", // LEFTWARDS DOUBLE ARROW
"=>" : "\u21D2", // RIGHTWARDS DOUBLE ARROW
"<=>" : "\u21D4", // LEFT RIGHT DOUBLE ARROW
"$\\infty$" : "\u221E", // INFINITY
"||" : "\u2225", // PARALLEL TO
"/=" : "\u2260", // NOT EQUAL TO
// "<=" : "\u2264", // LESS-THAN OR EQUAL TO
">=" : "\u2265", // GREATER-THAN OR EQUAL TO
"<<" : "\u226A", // MUCH LESS-THAN
">>" : "\u226B", // MUCH GREATER-THAN
"(+)" : "\u2295", // CIRCLED PLUS
"(-)" : "\u2296", // CIRCLED MINUS
"(x)" : "\u2297", // CIRCLED TIMES
"(/)" : "\u2298", // CIRCLED DIVISION SLASH
"|-" : "\u22A2", // RIGHT TACK
"-|" : "\u22A3", // LEFT TACK
// "|-" : "\u22A6", // ASSERTION
"|=" : "\u22A7", // MODELS
// "|=" : "\u22A8", // TRUE
"||-" : "\u22A9", // FORCES
"$\\#$" : "\u22D5", // EQUAL AND PARALLEL TO
"<<<" : "\u22D8", // VERY MUCH LESS-THAN
">>>" : "\u22D9", // VERY MUCH GREATER-THAN
"{\\textlangle}" : "\u2329", // LEFT-POINTING ANGLE BRACKET
"{\\textrangle}" : "\u232A", // RIGHT-POINTING ANGLE BRACKET
"{\\textvisiblespace}" : "\u2423", // OPEN BOX
"///" : "\u2425", // SYMBOL FOR DELETE FORM TWO
"{\\textopenbullet}" : "\u25E6", // WHITE BULLET
":-(" : "\u2639", // WHITE FROWNING FACE
":-)" : "\u263A", // WHITE SMILING FACE
"(-: " : "\u263B", // BLACK SMILING FACE
// "$\\#$" : "\u266F", // MUSIC SHARP SIGN
"$\\%<$" : "\u2701", // UPPER BLADE SCISSORS
/* "$\\%<$" : "\u2702", // BLACK SCISSORS
"$\\%<$" : "\u2703", // LOWER BLADE SCISSORS
"$\\%<$" : "\u2704", // WHITE SCISSORS */
/* Derived accented characters */
"\\`{A}" : "\u00C0", // LATIN CAPITAL LETTER A WITH GRAVE
"\\'{A}" : "\u00C1", // LATIN CAPITAL LETTER A WITH ACUTE
"\\^{A}" : "\u00C2", // LATIN CAPITAL LETTER A WITH CIRCUMFLEX
"\\~{A}" : "\u00C3", // LATIN CAPITAL LETTER A WITH TILDE
"\\\"{A}" : "\u00C4", // LATIN CAPITAL LETTER A WITH DIAERESIS
"\\r{A}" : "\u00C5", // LATIN CAPITAL LETTER A WITH RING ABOVE
"\\c{C}" : "\u00C7", // LATIN CAPITAL LETTER C WITH CEDILLA
"\\`{E}" : "\u00C8", // LATIN CAPITAL LETTER E WITH GRAVE
"\\'{E}" : "\u00C9", // LATIN CAPITAL LETTER E WITH ACUTE
"\\^{E}" : "\u00CA", // LATIN CAPITAL LETTER E WITH CIRCUMFLEX
"\\\"{E}" : "\u00CB", // LATIN CAPITAL LETTER E WITH DIAERESIS
"\\`{I}" : "\u00CC", // LATIN CAPITAL LETTER I WITH GRAVE
"\\'{I}" : "\u00CD", // LATIN CAPITAL LETTER I WITH ACUTE
"\\^{I}" : "\u00CE", // LATIN CAPITAL LETTER I WITH CIRCUMFLEX
"\\\"{I}" : "\u00CF", // LATIN CAPITAL LETTER I WITH DIAERESIS
"\\~{N}" : "\u00D1", // LATIN CAPITAL LETTER N WITH TILDE
"\\`{O}" : "\u00D2", // LATIN CAPITAL LETTER O WITH GRAVE
"\\'{O}" : "\u00D3", // LATIN CAPITAL LETTER O WITH ACUTE
"\\^{O}" : "\u00D4", // LATIN CAPITAL LETTER O WITH CIRCUMFLEX
"\\~{O}" : "\u00D5", // LATIN CAPITAL LETTER O WITH TILDE
"\\\"{O}" : "\u00D6", // LATIN CAPITAL LETTER O WITH DIAERESIS
"\\`{U}" : "\u00D9", // LATIN CAPITAL LETTER U WITH GRAVE
"\\'{U}" : "\u00DA", // LATIN CAPITAL LETTER U WITH ACUTE
"\\^{U}" : "\u00DB", // LATIN CAPITAL LETTER U WITH CIRCUMFLEX
"\\\"{U}" : "\u00DC", // LATIN CAPITAL LETTER U WITH DIAERESIS
"\\'{Y}" : "\u00DD", // LATIN CAPITAL LETTER Y WITH ACUTE
"\\`{a}" : "\u00E0", // LATIN SMALL LETTER A WITH GRAVE
"\\'{a}" : "\u00E1", // LATIN SMALL LETTER A WITH ACUTE
"\\^{a}" : "\u00E2", // LATIN SMALL LETTER A WITH CIRCUMFLEX
"\\~{a}" : "\u00E3", // LATIN SMALL LETTER A WITH TILDE
"\\\"{a}" : "\u00E4", // LATIN SMALL LETTER A WITH DIAERESIS
"\\r{a}" : "\u00E5", // LATIN SMALL LETTER A WITH RING ABOVE
"\\c{c}" : "\u00E7", // LATIN SMALL LETTER C WITH CEDILLA
"\\`{e}" : "\u00E8", // LATIN SMALL LETTER E WITH GRAVE
"\\'{e}" : "\u00E9", // LATIN SMALL LETTER E WITH ACUTE
"\\^{e}" : "\u00EA", // LATIN SMALL LETTER E WITH CIRCUMFLEX
"\\\"{e}" : "\u00EB", // LATIN SMALL LETTER E WITH DIAERESIS
"\\`{i}" : "\u00EC", // LATIN SMALL LETTER I WITH GRAVE
"\\'{i}" : "\u00ED", // LATIN SMALL LETTER I WITH ACUTE
"\\^{i}" : "\u00EE", // LATIN SMALL LETTER I WITH CIRCUMFLEX
"\\\"{i}" : "\u00EF", // LATIN SMALL LETTER I WITH DIAERESIS
"\\~{n}" : "\u00F1", // LATIN SMALL LETTER N WITH TILDE
"\\`{o}" : "\u00F2", // LATIN SMALL LETTER O WITH GRAVE
"\\'{o}" : "\u00F3", // LATIN SMALL LETTER O WITH ACUTE
"\\^{o}" : "\u00F4", // LATIN SMALL LETTER O WITH CIRCUMFLEX
"\\~{o}" : "\u00F5", // LATIN SMALL LETTER O WITH TILDE
"\\\"{o}" : "\u00F6", // LATIN SMALL LETTER O WITH DIAERESIS
"\\`{u}" : "\u00F9", // LATIN SMALL LETTER U WITH GRAVE
"\\'{u}" : "\u00FA", // LATIN SMALL LETTER U WITH ACUTE
"\\^{u}" : "\u00FB", // LATIN SMALL LETTER U WITH CIRCUMFLEX
"\\\"{u}" : "\u00FC", // LATIN SMALL LETTER U WITH DIAERESIS
"\\'{y}" : "\u00FD", // LATIN SMALL LETTER Y WITH ACUTE
"\\\"{y}" : "\u00FF", // LATIN SMALL LETTER Y WITH DIAERESIS
"\\={A}" : "\u0100", // LATIN CAPITAL LETTER A WITH MACRON
"\\={a}" : "\u0101", // LATIN SMALL LETTER A WITH MACRON
"\\u{A}" : "\u0102", // LATIN CAPITAL LETTER A WITH BREVE
"\\u{a}" : "\u0103", // LATIN SMALL LETTER A WITH BREVE
"\\k{A}" : "\u0104", // LATIN CAPITAL LETTER A WITH OGONEK
"\\k{a}" : "\u0105", // LATIN SMALL LETTER A WITH OGONEK
"\\'{C}" : "\u0106", // LATIN CAPITAL LETTER C WITH ACUTE
"\\'{c}" : "\u0107", // LATIN SMALL LETTER C WITH ACUTE
"\\^{C}" : "\u0108", // LATIN CAPITAL LETTER C WITH CIRCUMFLEX
"\\^{c}" : "\u0109", // LATIN SMALL LETTER C WITH CIRCUMFLEX
"\\.{C}" : "\u010A", // LATIN CAPITAL LETTER C WITH DOT ABOVE
"\\.{c}" : "\u010B", // LATIN SMALL LETTER C WITH DOT ABOVE
"\\v{C}" : "\u010C", // LATIN CAPITAL LETTER C WITH CARON
"\\v{c}" : "\u010D", // LATIN SMALL LETTER C WITH CARON
"\\v{D}" : "\u010E", // LATIN CAPITAL LETTER D WITH CARON
"\\v{d}" : "\u010F", // LATIN SMALL LETTER D WITH CARON
"\\={E}" : "\u0112", // LATIN CAPITAL LETTER E WITH MACRON
"\\={e}" : "\u0113", // LATIN SMALL LETTER E WITH MACRON
"\\u{E}" : "\u0114", // LATIN CAPITAL LETTER E WITH BREVE
"\\u{e}" : "\u0115", // LATIN SMALL LETTER E WITH BREVE
"\\.{E}" : "\u0116", // LATIN CAPITAL LETTER E WITH DOT ABOVE
"\\.{e}" : "\u0117", // LATIN SMALL LETTER E WITH DOT ABOVE
"\\k{E}" : "\u0118", // LATIN CAPITAL LETTER E WITH OGONEK
"\\k{e}" : "\u0119", // LATIN SMALL LETTER E WITH OGONEK
"\\v{E}" : "\u011A", // LATIN CAPITAL LETTER E WITH CARON
"\\v{e}" : "\u011B", // LATIN SMALL LETTER E WITH CARON
"\\^{G}" : "\u011C", // LATIN CAPITAL LETTER G WITH CIRCUMFLEX
"\\^{g}" : "\u011D", // LATIN SMALL LETTER G WITH CIRCUMFLEX
"\\u{G}" : "\u011E", // LATIN CAPITAL LETTER G WITH BREVE
"\\u{g}" : "\u011F", // LATIN SMALL LETTER G WITH BREVE
"\\.{G}" : "\u0120", // LATIN CAPITAL LETTER G WITH DOT ABOVE
"\\.{g}" : "\u0121", // LATIN SMALL LETTER G WITH DOT ABOVE
"\\c{G}" : "\u0122", // LATIN CAPITAL LETTER G WITH CEDILLA
"\\c{g}" : "\u0123", // LATIN SMALL LETTER G WITH CEDILLA
"\\^{H}" : "\u0124", // LATIN CAPITAL LETTER H WITH CIRCUMFLEX
"\\^{h}" : "\u0125", // LATIN SMALL LETTER H WITH CIRCUMFLEX
"\\~{I}" : "\u0128", // LATIN CAPITAL LETTER I WITH TILDE
"\\~{i}" : "\u0129", // LATIN SMALL LETTER I WITH TILDE
"\\={I}" : "\u012A", // LATIN CAPITAL LETTER I WITH MACRON
"\\={i}" : "\u012B", // LATIN SMALL LETTER I WITH MACRON
"\\u{I}" : "\u012C", // LATIN CAPITAL LETTER I WITH BREVE
"\\u{i}" : "\u012D", // LATIN SMALL LETTER I WITH BREVE
"\\k{I}" : "\u012E", // LATIN CAPITAL LETTER I WITH OGONEK
"\\k{i}" : "\u012F", // LATIN SMALL LETTER I WITH OGONEK
"\\.{I}" : "\u0130", // LATIN CAPITAL LETTER I WITH DOT ABOVE
"\\^{J}" : "\u0134", // LATIN CAPITAL LETTER J WITH CIRCUMFLEX
"\\^{j}" : "\u0135", // LATIN SMALL LETTER J WITH CIRCUMFLEX
"\\c{K}" : "\u0136", // LATIN CAPITAL LETTER K WITH CEDILLA
"\\c{k}" : "\u0137", // LATIN SMALL LETTER K WITH CEDILLA
"\\'{L}" : "\u0139", // LATIN CAPITAL LETTER L WITH ACUTE
"\\'{l}" : "\u013A", // LATIN SMALL LETTER L WITH ACUTE
"\\c{L}" : "\u013B", // LATIN CAPITAL LETTER L WITH CEDILLA
"\\c{l}" : "\u013C", // LATIN SMALL LETTER L WITH CEDILLA
"\\v{L}" : "\u013D", // LATIN CAPITAL LETTER L WITH CARON
"\\v{l}" : "\u013E", // LATIN SMALL LETTER L WITH CARON
"\\L{}" : "\u0141", //LATIN CAPITAL LETTER L WITH STROKE
"\\l{}" : "\u0142", //LATIN SMALL LETTER L WITH STROKE
"\\'{N}" : "\u0143", // LATIN CAPITAL LETTER N WITH ACUTE
"\\'{n}" : "\u0144", // LATIN SMALL LETTER N WITH ACUTE
"\\c{N}" : "\u0145", // LATIN CAPITAL LETTER N WITH CEDILLA
"\\c{n}" : "\u0146", // LATIN SMALL LETTER N WITH CEDILLA
"\\v{N}" : "\u0147", // LATIN CAPITAL LETTER N WITH CARON
"\\v{n}" : "\u0148", // LATIN SMALL LETTER N WITH CARON
"\\={O}" : "\u014C", // LATIN CAPITAL LETTER O WITH MACRON
"\\={o}" : "\u014D", // LATIN SMALL LETTER O WITH MACRON
"\\u{O}" : "\u014E", // LATIN CAPITAL LETTER O WITH BREVE
"\\u{o}" : "\u014F", // LATIN SMALL LETTER O WITH BREVE
"\\H{O}" : "\u0150", // LATIN CAPITAL LETTER O WITH DOUBLE ACUTE
"\\H{o}" : "\u0151", // LATIN SMALL LETTER O WITH DOUBLE ACUTE
"\\'{R}" : "\u0154", // LATIN CAPITAL LETTER R WITH ACUTE
"\\'{r}" : "\u0155", // LATIN SMALL LETTER R WITH ACUTE
"\\c{R}" : "\u0156", // LATIN CAPITAL LETTER R WITH CEDILLA
"\\c{r}" : "\u0157", // LATIN SMALL LETTER R WITH CEDILLA
"\\v{R}" : "\u0158", // LATIN CAPITAL LETTER R WITH CARON
"\\v{r}" : "\u0159", // LATIN SMALL LETTER R WITH CARON
"\\'{S}" : "\u015A", // LATIN CAPITAL LETTER S WITH ACUTE
"\\'{s}" : "\u015B", // LATIN SMALL LETTER S WITH ACUTE
"\\^{S}" : "\u015C", // LATIN CAPITAL LETTER S WITH CIRCUMFLEX
"\\^{s}" : "\u015D", // LATIN SMALL LETTER S WITH CIRCUMFLEX
"\\c{S}" : "\u015E", // LATIN CAPITAL LETTER S WITH CEDILLA
"\\c{s}" : "\u015F", // LATIN SMALL LETTER S WITH CEDILLA
"\\v{S}" : "\u0160", // LATIN CAPITAL LETTER S WITH CARON
"\\v{s}" : "\u0161", // LATIN SMALL LETTER S WITH CARON
"\\c{T}" : "\u0162", // LATIN CAPITAL LETTER T WITH CEDILLA
"\\c{t}" : "\u0163", // LATIN SMALL LETTER T WITH CEDILLA
"\\v{T}" : "\u0164", // LATIN CAPITAL LETTER T WITH CARON
"\\v{t}" : "\u0165", // LATIN SMALL LETTER T WITH CARON
"\\~{U}" : "\u0168", // LATIN CAPITAL LETTER U WITH TILDE
"\\~{u}" : "\u0169", // LATIN SMALL LETTER U WITH TILDE
"\\={U}" : "\u016A", // LATIN CAPITAL LETTER U WITH MACRON
"\\={u}" : "\u016B", // LATIN SMALL LETTER U WITH MACRON
"\\u{U}" : "\u016C", // LATIN CAPITAL LETTER U WITH BREVE
"\\u{u}" : "\u016D", // LATIN SMALL LETTER U WITH BREVE
"\\H{U}" : "\u0170", // LATIN CAPITAL LETTER U WITH DOUBLE ACUTE
"\\H{u}" : "\u0171", // LATIN SMALL LETTER U WITH DOUBLE ACUTE
"\\k{U}" : "\u0172", // LATIN CAPITAL LETTER U WITH OGONEK
"\\k{u}" : "\u0173", // LATIN SMALL LETTER U WITH OGONEK
"\\^{W}" : "\u0174", // LATIN CAPITAL LETTER W WITH CIRCUMFLEX
"\\^{w}" : "\u0175", // LATIN SMALL LETTER W WITH CIRCUMFLEX
"\\^{Y}" : "\u0176", // LATIN CAPITAL LETTER Y WITH CIRCUMFLEX
"\\^{y}" : "\u0177", // LATIN SMALL LETTER Y WITH CIRCUMFLEX
"\\\"{Y}" : "\u0178", // LATIN CAPITAL LETTER Y WITH DIAERESIS
"\\'{Z}" : "\u0179", // LATIN CAPITAL LETTER Z WITH ACUTE
"\\'{z}" : "\u017A", // LATIN SMALL LETTER Z WITH ACUTE
"\\.{Z}" : "\u017B", // LATIN CAPITAL LETTER Z WITH DOT ABOVE
"\\.{z}" : "\u017C", // LATIN SMALL LETTER Z WITH DOT ABOVE
"\\v{Z}" : "\u017D", // LATIN CAPITAL LETTER Z WITH CARON
"\\v{z}" : "\u017E", // LATIN SMALL LETTER Z WITH CARON
"\\v{A}" : "\u01CD", // LATIN CAPITAL LETTER A WITH CARON
"\\v{a}" : "\u01CE", // LATIN SMALL LETTER A WITH CARON
"\\v{I}" : "\u01CF", // LATIN CAPITAL LETTER I WITH CARON
"\\v{i}" : "\u01D0", // LATIN SMALL LETTER I WITH CARON
"\\v{O}" : "\u01D1", // LATIN CAPITAL LETTER O WITH CARON
"\\v{o}" : "\u01D2", // LATIN SMALL LETTER O WITH CARON
"\\v{U}" : "\u01D3", // LATIN CAPITAL LETTER U WITH CARON
"\\v{u}" : "\u01D4", // LATIN SMALL LETTER U WITH CARON
"\\v{G}" : "\u01E6", // LATIN CAPITAL LETTER G WITH CARON
"\\v{g}" : "\u01E7", // LATIN SMALL LETTER G WITH CARON
"\\v{K}" : "\u01E8", // LATIN CAPITAL LETTER K WITH CARON
"\\v{k}" : "\u01E9", // LATIN SMALL LETTER K WITH CARON
"\\k{O}" : "\u01EA", // LATIN CAPITAL LETTER O WITH OGONEK
"\\k{o}" : "\u01EB", // LATIN SMALL LETTER O WITH OGONEK
"\\v{j}" : "\u01F0", // LATIN SMALL LETTER J WITH CARON
"\\'{G}" : "\u01F4", // LATIN CAPITAL LETTER G WITH ACUTE
"\\'{g}" : "\u01F5", // LATIN SMALL LETTER G WITH ACUTE
"\\.{B}" : "\u1E02", // LATIN CAPITAL LETTER B WITH DOT ABOVE
"\\.{b}" : "\u1E03", // LATIN SMALL LETTER B WITH DOT ABOVE
"\\d{B}" : "\u1E04", // LATIN CAPITAL LETTER B WITH DOT BELOW
"\\d{b}" : "\u1E05", // LATIN SMALL LETTER B WITH DOT BELOW
"\\b{B}" : "\u1E06", // LATIN CAPITAL LETTER B WITH LINE BELOW
"\\b{b}" : "\u1E07", // LATIN SMALL LETTER B WITH LINE BELOW
"\\.{D}" : "\u1E0A", // LATIN CAPITAL LETTER D WITH DOT ABOVE
"\\.{d}" : "\u1E0B", // LATIN SMALL LETTER D WITH DOT ABOVE
"\\d{D}" : "\u1E0C", // LATIN CAPITAL LETTER D WITH DOT BELOW
"\\d{d}" : "\u1E0D", // LATIN SMALL LETTER D WITH DOT BELOW
"\\b{D}" : "\u1E0E", // LATIN CAPITAL LETTER D WITH LINE BELOW
"\\b{d}" : "\u1E0F", // LATIN SMALL LETTER D WITH LINE BELOW
"\\c{D}" : "\u1E10", // LATIN CAPITAL LETTER D WITH CEDILLA
"\\c{d}" : "\u1E11", // LATIN SMALL LETTER D WITH CEDILLA
"\\.{F}" : "\u1E1E", // LATIN CAPITAL LETTER F WITH DOT ABOVE
"\\.{f}" : "\u1E1F", // LATIN SMALL LETTER F WITH DOT ABOVE
"\\={G}" : "\u1E20", // LATIN CAPITAL LETTER G WITH MACRON
"\\={g}" : "\u1E21", // LATIN SMALL LETTER G WITH MACRON
"\\.{H}" : "\u1E22", // LATIN CAPITAL LETTER H WITH DOT ABOVE
"\\.{h}" : "\u1E23", // LATIN SMALL LETTER H WITH DOT ABOVE
"\\d{H}" : "\u1E24", // LATIN CAPITAL LETTER H WITH DOT BELOW
"\\d{h}" : "\u1E25", // LATIN SMALL LETTER H WITH DOT BELOW
"\\\"{H}" : "\u1E26", // LATIN CAPITAL LETTER H WITH DIAERESIS
"\\\"{h}" : "\u1E27", // LATIN SMALL LETTER H WITH DIAERESIS
"\\c{H}" : "\u1E28", // LATIN CAPITAL LETTER H WITH CEDILLA
"\\c{h}" : "\u1E29", // LATIN SMALL LETTER H WITH CEDILLA
"\\'{K}" : "\u1E30", // LATIN CAPITAL LETTER K WITH ACUTE
"\\'{k}" : "\u1E31", // LATIN SMALL LETTER K WITH ACUTE
"\\d{K}" : "\u1E32", // LATIN CAPITAL LETTER K WITH DOT BELOW
"\\d{k}" : "\u1E33", // LATIN SMALL LETTER K WITH DOT BELOW
"\\b{K}" : "\u1E34", // LATIN CAPITAL LETTER K WITH LINE BELOW
"\\b{k}" : "\u1E35", // LATIN SMALL LETTER K WITH LINE BELOW
"\\d{L}" : "\u1E36", // LATIN CAPITAL LETTER L WITH DOT BELOW
"\\d{l}" : "\u1E37", // LATIN SMALL LETTER L WITH DOT BELOW
"\\b{L}" : "\u1E3A", // LATIN CAPITAL LETTER L WITH LINE BELOW
"\\b{l}" : "\u1E3B", // LATIN SMALL LETTER L WITH LINE BELOW
"\\'{M}" : "\u1E3E", // LATIN CAPITAL LETTER M WITH ACUTE
"\\'{m}" : "\u1E3F", // LATIN SMALL LETTER M WITH ACUTE
"\\.{M}" : "\u1E40", // LATIN CAPITAL LETTER M WITH DOT ABOVE
"\\.{m}" : "\u1E41", // LATIN SMALL LETTER M WITH DOT ABOVE
"\\d{M}" : "\u1E42", // LATIN CAPITAL LETTER M WITH DOT BELOW
"\\d{m}" : "\u1E43", // LATIN SMALL LETTER M WITH DOT BELOW
"\\.{N}" : "\u1E44", // LATIN CAPITAL LETTER N WITH DOT ABOVE
"\\.{n}" : "\u1E45", // LATIN SMALL LETTER N WITH DOT ABOVE
"\\d{N}" : "\u1E46", // LATIN CAPITAL LETTER N WITH DOT BELOW
"\\d{n}" : "\u1E47", // LATIN SMALL LETTER N WITH DOT BELOW
"\\b{N}" : "\u1E48", // LATIN CAPITAL LETTER N WITH LINE BELOW
"\\b{n}" : "\u1E49", // LATIN SMALL LETTER N WITH LINE BELOW
"\\'{P}" : "\u1E54", // LATIN CAPITAL LETTER P WITH ACUTE
"\\'{p}" : "\u1E55", // LATIN SMALL LETTER P WITH ACUTE
"\\.{P}" : "\u1E56", // LATIN CAPITAL LETTER P WITH DOT ABOVE
"\\.{p}" : "\u1E57", // LATIN SMALL LETTER P WITH DOT ABOVE
"\\.{R}" : "\u1E58", // LATIN CAPITAL LETTER R WITH DOT ABOVE
"\\.{r}" : "\u1E59", // LATIN SMALL LETTER R WITH DOT ABOVE
"\\d{R}" : "\u1E5A", // LATIN CAPITAL LETTER R WITH DOT BELOW
"\\d{r}" : "\u1E5B", // LATIN SMALL LETTER R WITH DOT BELOW
"\\b{R}" : "\u1E5E", // LATIN CAPITAL LETTER R WITH LINE BELOW
"\\b{r}" : "\u1E5F", // LATIN SMALL LETTER R WITH LINE BELOW
"\\.{S}" : "\u1E60", // LATIN CAPITAL LETTER S WITH DOT ABOVE
"\\.{s}" : "\u1E61", // LATIN SMALL LETTER S WITH DOT ABOVE
"\\d{S}" : "\u1E62", // LATIN CAPITAL LETTER S WITH DOT BELOW
"\\d{s}" : "\u1E63", // LATIN SMALL LETTER S WITH DOT BELOW
"\\.{T}" : "\u1E6A", // LATIN CAPITAL LETTER T WITH DOT ABOVE
"\\.{t}" : "\u1E6B", // LATIN SMALL LETTER T WITH DOT ABOVE
"\\d{T}" : "\u1E6C", // LATIN CAPITAL LETTER T WITH DOT BELOW
"\\d{t}" : "\u1E6D", // LATIN SMALL LETTER T WITH DOT BELOW
"\\b{T}" : "\u1E6E", // LATIN CAPITAL LETTER T WITH LINE BELOW
"\\b{t}" : "\u1E6F", // LATIN SMALL LETTER T WITH LINE BELOW
"\\~{V}" : "\u1E7C", // LATIN CAPITAL LETTER V WITH TILDE
"\\~{v}" : "\u1E7D", // LATIN SMALL LETTER V WITH TILDE
"\\d{V}" : "\u1E7E", // LATIN CAPITAL LETTER V WITH DOT BELOW
"\\d{v}" : "\u1E7F", // LATIN SMALL LETTER V WITH DOT BELOW
"\\`{W}" : "\u1E80", // LATIN CAPITAL LETTER W WITH GRAVE
"\\`{w}" : "\u1E81", // LATIN SMALL LETTER W WITH GRAVE
"\\'{W}" : "\u1E82", // LATIN CAPITAL LETTER W WITH ACUTE
"\\'{w}" : "\u1E83", // LATIN SMALL LETTER W WITH ACUTE
"\\\"{W}" : "\u1E84", // LATIN CAPITAL LETTER W WITH DIAERESIS
"\\\"{w}" : "\u1E85", // LATIN SMALL LETTER W WITH DIAERESIS
"\\.{W}" : "\u1E86", // LATIN CAPITAL LETTER W WITH DOT ABOVE
"\\.{w}" : "\u1E87", // LATIN SMALL LETTER W WITH DOT ABOVE
"\\d{W}" : "\u1E88", // LATIN CAPITAL LETTER W WITH DOT BELOW
"\\d{w}" : "\u1E89", // LATIN SMALL LETTER W WITH DOT BELOW
"\\.{X}" : "\u1E8A", // LATIN CAPITAL LETTER X WITH DOT ABOVE
"\\.{x}" : "\u1E8B", // LATIN SMALL LETTER X WITH DOT ABOVE
"\\\"{X}" : "\u1E8C", // LATIN CAPITAL LETTER X WITH DIAERESIS
"\\\"{x}" : "\u1E8D", // LATIN SMALL LETTER X WITH DIAERESIS
"\\.{Y}" : "\u1E8E", // LATIN CAPITAL LETTER Y WITH DOT ABOVE
"\\.{y}" : "\u1E8F", // LATIN SMALL LETTER Y WITH DOT ABOVE
"\\^{Z}" : "\u1E90", // LATIN CAPITAL LETTER Z WITH CIRCUMFLEX
"\\^{z}" : "\u1E91", // LATIN SMALL LETTER Z WITH CIRCUMFLEX
"\\d{Z}" : "\u1E92", // LATIN CAPITAL LETTER Z WITH DOT BELOW
"\\d{z}" : "\u1E93", // LATIN SMALL LETTER Z WITH DOT BELOW
"\\b{Z}" : "\u1E94", // LATIN CAPITAL LETTER Z WITH LINE BELOW
"\\b{z}" : "\u1E95", // LATIN SMALL LETTER Z WITH LINE BELOW
"\\b{h}" : "\u1E96", // LATIN SMALL LETTER H WITH LINE BELOW
"\\\"{t}" : "\u1E97", // LATIN SMALL LETTER T WITH DIAERESIS
"\\d{A}" : "\u1EA0", // LATIN CAPITAL LETTER A WITH DOT BELOW
"\\d{a}" : "\u1EA1", // LATIN SMALL LETTER A WITH DOT BELOW
"\\d{E}" : "\u1EB8", // LATIN CAPITAL LETTER E WITH DOT BELOW
"\\d{e}" : "\u1EB9", // LATIN SMALL LETTER E WITH DOT BELOW
"\\~{E}" : "\u1EBC", // LATIN CAPITAL LETTER E WITH TILDE
"\\~{e}" : "\u1EBD", // LATIN SMALL LETTER E WITH TILDE
"\\d{I}" : "\u1ECA", // LATIN CAPITAL LETTER I WITH DOT BELOW
"\\d{i}" : "\u1ECB", // LATIN SMALL LETTER I WITH DOT BELOW
"\\d{O}" : "\u1ECC", // LATIN CAPITAL LETTER O WITH DOT BELOW
"\\d{o}" : "\u1ECD", // LATIN SMALL LETTER O WITH DOT BELOW
"\\d{U}" : "\u1EE4", // LATIN CAPITAL LETTER U WITH DOT BELOW
"\\d{u}" : "\u1EE5", // LATIN SMALL LETTER U WITH DOT BELOW
"\\`{Y}" : "\u1EF2", // LATIN CAPITAL LETTER Y WITH GRAVE
"\\`{y}" : "\u1EF3", // LATIN SMALL LETTER Y WITH GRAVE
"\\d{Y}" : "\u1EF4", // LATIN CAPITAL LETTER Y WITH DOT BELOW
"\\d{y}" : "\u1EF5", // LATIN SMALL LETTER Y WITH DOT BELOW
"\\~{Y}" : "\u1EF8", // LATIN CAPITAL LETTER Y WITH TILDE
"\\~{y}" : "\u1EF9", // LATIN SMALL LETTER Y WITH TILDE
"\\~{}" : "\u223C", // TILDE OPERATOR
"~" : "\u00A0" // NO-BREAK SPACE
};
var alwaysMap = {
"|":"{\\textbar}",
"<":"{\\textless}",
">":"{\\textgreater}",
"~":"{\\textasciitilde}",
"^":"{\\textasciicircum}",
"\\":"{\\textbackslash}"
};
var strings = {};
var keyRe = /[a-zA-Z0-9\-]/;
function processField(item, field, value) {
if(Zotero.Utilities.trim(value) == '') return null;
if(fieldMap[field]) {
item[fieldMap[field]] = value;
} else if(inputFieldMap[field]) {
item[inputFieldMap[field]] = value;
} else if(field == "journal") {
if(item.publicationTitle) {
item.journalAbbreviation = value;
} else {
item.publicationTitle = value;
}
} else if(field == "fjournal") {
if(item.publicationTitle) {
// move publicationTitle to abbreviation
item.journalAbbreviation = value;
}
item.publicationTitle = value;
} else if(field == "author" || field == "editor" || field == "translator") {
// parse authors/editors/translators
var names = value.split(/ and /i); // now case insensitive
for(var i in names) {
var name = names[i];
// skip empty names
if (name.trim() == '') {
continue;
}
// Names in BibTeX can have three commas
pieces = name.split(',');
var creator = {};
if (pieces.length > 1) {
creator.firstName = pieces.pop().trim();
creator.lastName = pieces.join(',').trim();
creator.creatorType = field;
} else {
creator = Zotero.Utilities.cleanAuthor(name, field, false);
}
item.creators.push(creator);
}
} else if(field == "institution" || field == "organization") {
item.backupPublisher = value;
} else if(field == "number"){ // fix for techreport
if (item.itemType == "report") {
item.reportNumber = value;
} else if (item.itemType == "book" || item.itemType == "bookSection") {
item.seriesNumber = value;
} else {
item.issue = value;
}
} else if(field == "month") {
var monthIndex = months.indexOf(value.toLowerCase());
if(monthIndex != -1) {
value = Zotero.Utilities.formatDate({month:monthIndex});
} else {
value += " ";
}
if(item.date) {
if(value.indexOf(item.date) != -1) {
// value contains year and more
item.date = value;
} else {
item.date = value+item.date;
}
} else {
item.date = value;
}
} else if(field == "year") {
if(item.date) {
if(item.date.indexOf(value) == -1) {
// date does not already contain year
item.date += value;
}
} else {
item.date = value;
}
} else if(field == "pages") {
if (item.itemType == "book" || item.itemType == "thesis" || item.itemType == "manuscript") {
item.numPages = value;
}
else {
item.pages = value.replace(/--/g, "-");
}
} else if(field == "note") {
item.extra += "\n"+value;
} else if(field == "howpublished") {
if(value.length >= 7) {
var str = value.substr(0, 7);
if(str == "http://" || str == "https:/" || str == "mailto:") {
item.url = value;
} else {
item.extra += "\nPublished: "+value;
}
}
} else if(field == "keywords") {
if(value.indexOf(",") == -1) {
// keywords/tags
item.tags = value.split(" ");
} else {
item.tags = value.split(/, ?/g);
}
} else if (field == "comment" || field == "annote" || field == "review") {
item.notes.push({note:Zotero.Utilities.text2html(value)});
} else if (field == "pdf") {
if (/:\/\//.test(value)) { // a full uri is given
item.attachments = [{url:value, mimeType:"application/pdf", downloadable:true}];
} else { // if no uri is given, assume that it is an absolute path to the PDF
item.attachments = [{url:"file://"+value, mimeType:"application/pdf"}];
}
} else if (field == "sentelink") { // the reference manager 'Sente' has a unique file scheme in exported BibTeX
item.attachments = [{url:value.split(",")[0], mimeType:"application/pdf", downloadable:true}];
} else if (field == "file") {
var attachments = value.split(";");
for(var i in attachments){
var attachment = attachments[i];
var parts = attachment.split(":");
var filetitle = parts[0];
var filepath = parts[1];
if (filepath.trim() === '') continue; // skip empty entries
var filetype = parts[2];
if (filetitle.length == 0) {
filetitle = "Attachment";
}
if (filetype.match(/pdf/i)) {
item.attachments.push({url:"file://"+filepath, mimeType:"application/pdf", title:filetitle, downloadable:true});
} else {
item.attachments.push({url:"file://"+filepath, title:filetitle, downloadable:true});
}
}
}
}
function getFieldValue(read) {
var value = "";
// now, we have the first character of the field
if(read == "{") {
// character is a brace
var openBraces = 1;
while(read = Zotero.read(1)) {
if(read == "{" && value[value.length-1] != "\\") {
openBraces++;
value += "{";
} else if(read == "}" && value[value.length-1] != "\\") {
openBraces--;
if(openBraces == 0) {
break;
} else {
value += "}";
}
} else {
value += read;
}
}
} else if(read == '"') {
var openBraces = 0;
while(read = Zotero.read(1)) {
if(read == "{" && value[value.length-1] != "\\") {
openBraces++;
value += "{";
} else if(read == "}" && value[value.length-1] != "\\") {
openBraces--;
value += "}";
} else if(read == '"' && openBraces == 0) {
break;
} else {
value += read;
}
}
}
if(value.length > 1) {
// replace accented characters (yucky slow)
value = value.replace(/{?(\\[`"'^~=a-z]){?\\?([A-Za-z])}/g, "$1{$2}");
for (var mapped in reversemappingTable) { // really really slow!
var unicode = reversemappingTable[mapped];
if (value.indexOf(mapped) != -1) {
Zotero.debug("Replace " + mapped + " in " + value + " with " + unicode);
value = value.replace(mapped, unicode, "g");
}
mapped = mapped.replace(/[{}]/g, "");
if (value.indexOf(mapped) != -1) {
Zotero.debug("Replace(2) " + mapped + " in " + value + " with " + unicode);
value = value.replace(mapped, unicode, "g");
}
}
// kill braces
value = value.replace(/([^\\])[{}]+/g, "$1");
if(value[0] == "{") {
value = value.substr(1);
}
// chop off backslashes
value = value.replace(/([^\\])\\([#$%&~_^\\{}])/g, "$1$2");
value = value.replace(/([^\\])\\([#$%&~_^\\{}])/g, "$1$2");
if(value[0] == "\\" && "#$%&~_^\\{}".indexOf(value[1]) != -1) {
value = value.substr(1);
}
if(value[value.length-1] == "\\" && "#$%&~_^\\{}".indexOf(value[value.length-2]) != -1) {
value = value.substr(0, value.length-1);
}
value = value.replace(/\\\\/g, "\\");
value = value.replace(/\s+/g, " ");
}
return value;
}
function beginRecord(type, closeChar) {
type = Zotero.Utilities.trimInternal(type.toLowerCase());
if(type != "string") {
var zoteroType = bibtex2zoteroTypeMap[type];
if (!zoteroType) {
Zotero.debug("discarded item from BibTeX; type was "+type);
}
var item = new Zotero.Item(zoteroType);
item.extra = "";
}
var field = "";
// by setting dontRead to true, we can skip a read on the next iteration
// of this loop. this is useful after we read past the end of a string.
var dontRead = false;
while(dontRead || (read = Zotero.read(1))) {
dontRead = false;
if(read == "=") { // equals begin a field
// read whitespace
var read = Zotero.read(1);
while(" \n\r\t".indexOf(read) != -1) {
read = Zotero.read(1);
}
if(keyRe.test(read)) {
// read numeric data here, since we might get an end bracket
// that we should care about
value = "";
value += read;
// character is a number
while((read = Zotero.read(1)) && keyRe.test(read)) {
value += read;
}
// don't read the next char; instead, process the character
// we already read past the end of the string
dontRead = true;
// see if there's a defined string
if(strings[value]) value = strings[value];
} else {
var value = getFieldValue(read);
}
if(item) {
processField(item, field.toLowerCase(), value);
} else if(type == "string") {
strings[field] = value;
}
field = "";
} else if(read == ",") { // commas reset
field = "";
} else if(read == closeChar) {
if(item) {
if(item.extra) item.extra = item.extra.substr(1); // chop \n
item.complete();
}
return;
} else if(" \n\r\t".indexOf(read) == -1) { // skip whitespace
field += read;
}
}
}
function doImport() {
var read = "", text = "", recordCloseElement = false;
var type = false;
while(read = Zotero.read(1)) {
if(read == "@") {
type = "";
} else if(type !== false) {
if(type == "comment") {
type = false;
} else if(read == "{") { // possible open character
beginRecord(type, "}");
type = false;
} else if(read == "(") { // possible open character
beginRecord(type, ")");
type = false;
} else {
type += read;
}
}
}
}
// 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) {
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(!((field == "url") || (field == "doi") | (field == "file"))) {
// I hope these are all the escape characters!
// -- Tan --begin: preserve common latex markups ^,_,\,$ if users wish
if(preserveLatex) {
value = value.replace(/[|\<\>\~]/g, mapEscape).replace(/([\#\%\&])/g, "\\$1").replace(/([\s]+)([\$][0-9\.\,\-]+[\s]+)/g, "$1\\$2");
} else {
value = value.replace(/[|\<\>\~\^\\]/g, mapEscape).replace(/([\#\$\%\&\_])/g, "\\$1");
}
// -- Tan --end
// Case of words with uppercase characters in non-initial positions is preserved with braces.
if(!isMacro&&field != "pages") value = value.replace(/([^\s]+[A-Z][^\s,]*)/g, "{$1}");
}
if (Zotero.getOption("exportCharset") != "UTF-8") {
value = value.replace(/[\u0080-\uFFFF]/g, mapAccent);
}
Zotero.write(value);
if(!isMacro) Zotero.write("}");
}
function mapEscape(character) {
return alwaysMap[character];
}
function mapAccent(character) {
return (mappingTable[character] ? mappingTable[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();
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 citeKeyTitleBannedMoreRe = /\b(about|and|are|as|at|be|by|can|does|for|has|have|if|into|onto|is|it|its|or|that|these|this|those|via|was|were)(\s+|\b)/g; // -- Tan : more banned words
var citeKeyJournalBannedRe = /\b(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; // -- Tan: no 'a' for journal names
var citeKeyConversionsRe = /%([a-zA-Z]{2})([0-9]*)[\{]?([0-9]*)[\}]?/; // -- Tan: new key format string
var citeKeyCleanRe = /[^a-zA-Z0-9\!\$\&\*\+\-\.\/\:\;\<\>\?\[\]\^\_\`\|]+/g;
var citeKeyConversions = {
// -- Tan --begin: new 2-letter conversion functions
// for creators, title, journal, year, volume, pages. Do we need more?
"AU":function (label, maxlength, num, item) {
if(item.creators && item.creators[num] && item.creators[num].lastName) {
var auth = item.creators[num].lastName.toLowerCase().replace(/[\s\'\,]/g,"");
auth = tidyAccents(auth);
if(label == label.toUpperCase()) {
auth = auth.toUpperCase();
} else if(label[0] == label[0].toUpperCase()) {
auth = auth[0].toUpperCase() + auth.substr(1);
}
if (maxlength && auth.length > maxlength) {
return auth.substr(0,maxlength);
} else {
return auth;
}
}
return "";
},
"AA":function (label, maxlength, num, item) {
if(item.creators) {
var initials = "";
var len = item.creators.length;
len = (len > maxlength) ? maxlength : len;
for (var i=0; i<len; i++) {
var auth = item.creators[i].lastName.toLowerCase().replace(/[\s\'\,]/g,"");
auth = tidyAccents(auth);
initials = initials + auth[0];
}
if(label == label.toUpperCase()) {
initials = initials.toUpperCase();
}
return initials;
}
return "";
},
"TI":function (label, maxlength, num, item) {
if (item["title"]) {
var tit = tidyAccents(item["title"].toLowerCase().replace(citeKeyTitleBannedRe,"").replace(citeKeyTitleBannedMoreRe,"")).replace(/[^a-z\-\s]+/g,"").split(/\s+/g);
if (tit.length > num) {
var word = tit[num];
if(label == label.toUpperCase()) {
word = word.toUpperCase();
} else if(label[0] == label[0].toUpperCase()) {
word = word[0].toUpperCase() + word.substr(1);
}
if (maxlength && word.length > maxlength) {
return word.substr(0,maxlength);
} else {
return word;
}
}
}
return "";
},
"TT":function (label, maxlength, num, item) {
if (item["title"]) {
var tit = tidyAccents(item["title"].toLowerCase().replace(citeKeyTitleBannedRe,"").replace(citeKeyTitleBannedMoreRe,"")).replace(/[^a-z\s]+/g,"").replace(/\b([a-z])[a-z]+\b/g,"$1");
tit = tit.replace(/\s+/g,""); // first letter of each title word
if(label == label.toUpperCase()) {
tit = tit.toUpperCase();
}
if (maxlength && tit.length > maxlength) {
return tit.substr(0,maxlength);
} else {
return tit;
}
}
return "";
},
"YR":function (label, maxlength, num, item) {
if(item.date) {
var date = Zotero.Utilities.strToDate(item.date);
if(date.year && numberRe.test(date.year)) {
if(maxlength == 2) {
return date.year.toString().substr(2);
} else {
return date.year;
}
}
}
if(maxlength == 2) {
return "??";
} else {
return "????";
}
},
"JJ":function (label, maxlength, num, item) {
if (item.publicationTitle) {
var jou = tidyAccents(item.publicationTitle.toLowerCase().replace(citeKeyJournalBannedRe,"").replace(citeKeyTitleBannedMoreRe,"")).replace(/[^a-z\-\s]+/g,"").replace(/\b([a-z\-])[a-z\-]+\b/g,"$1");
jou = jou.replace(/\s+/g,""); // first letter of each journal word
if(label == label.toUpperCase()) {
jou = jou.toUpperCase();
}
if (maxlength && jou.length > maxlength) {
return jou.substr(0,maxlength);
} else {
return jou;
}
}
return "";
},
"VO":function (label, maxlength, num, item) {
if (item.volume) {
return item.volume;
}
return "";
},
"PG":function (label, maxlength, num, item) {
if (item.pages) {
if(num) { // last page number
return (item.pages.lastIndexOf("-") == -1) ? "" : item.pages.substr(item.pages.lastIndexOf("-")+1);
} else {
return item.pages.replace(/\-.*/g,""); // first page number
}
}
return "";
}
// -- Tan --end
}
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 label = m[1];
var maxlength = m[2] ? parseInt(m[2]) : 0;
var num = m[3] ? parseInt(m[3]) : 0;
var f = citeKeyConversions[label.toUpperCase()];
if (typeof(f) == "function") {
var value = f(label, maxlength, num, item);
Zotero.debug("Got value " + value + " for %" + m[1]);
//add conversion to basekey
basekey = basekey + value;
}
citeKeyFormatRemaining = citeKeyFormatRemaining.substr(m.index + m[0].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); // -- Tan: deal with in the individual matching
basekey = basekey.replace(citeKeyCleanRe, "");
var citekey = resolveCiteKeyCollision(basekey,citekeys); // -- Tan: separate the function
return citekey;
}
// -- Tan --begin: allow alphabetic suffix for key collisions
function resolveCiteKeyCollision(basekey,citekeys) {
var citekey = basekey;
var i = 0;
var ii = 0;
var iii = 0;
var suffix = citeKeyCollisionFormat.match(/([^\%]*)%([a-zA-Z0-9])/);
if(suffix) {
var sepmark = suffix[1].replace(citeKeyCleanRe, "");
while(citekeys[citekey]) {
i++;
if (i > 600) {
Zotero.debug("Pathological BibTeX key format: " + citeKeyFormat + " causing too many cite key collisions");
break;
}
if(suffix[2].toLowerCase() == "a") {
ii = Math.floor((i-1)/26);
iii = i - ii*26;
citekey = basekey + sepmark + (ii ? String.fromCharCode(96+ii) : "") + String.fromCharCode(96+iii);
} else {
citekey = basekey + sepmark + i;
}
}
} else {
Zotero.debug("Bad BibTeX key collision format: " + citeKeyCollisionFormat);
}
citekeys[citekey] = true;
return citekey;
}
// -- Tan --end
function doExport() {
//Zotero.write("% BibTeX export generated by Zotero "+Zotero.Utilities.getVersion());
// to make sure the BOM gets ignored
var first = true;
var citekeys = new Object();
var item;
while(item = Zotero.nextItem()) {
// create a unique citation key
// -- Tan --begin: user's own field for bibtex key (e.g., callNumber)
if (item[citeKeyField]) {
var citekey = resolveCiteKeyCollision(item[citeKeyField],citekeys);
} else {
var citekey = buildCiteKey(item, citekeys);
}
// -- Tan --end
// write citation key
Zotero.write((first ? "\\cite{" : ", ") + citekey); // -- Tan
first = false;
}
Zotero.write("}"); // -- Tan
}
/** BEGIN TEST CASES **/
var testCases = [
{
"type": "import",
"input": "@article{Adams2001,\u000aauthor = {Adams, Nancy K and DeSilva, Shanaka L and Self, Steven and Salas, Guido and Schubring, Steven and Permenter, Jason L and Arbesman, Kendra},\u000afile = {:Users/heatherwright/Documents/Scientific Papers/Adams\\_Huaynaputina.pdf:pdf;::},\u000ajournal = {Bulletin of Volcanology},\u000akeywords = {Vulcanian eruptions,breadcrust,plinian},\u000apages = {493--518},\u000atitle = {{The physical volcanology of the 1600 eruption of Huaynaputina, southern Peru}},\u000avolume = {62},\u000ayear = {2001}\u000a}",
"items": [
{
"itemType": "journalArticle",
"creators": [
{
"firstName": "Nancy K",
"lastName": "Adams",
"creatorType": "author"
},
{
"firstName": "Shanaka L",
"lastName": "DeSilva",
"creatorType": "author"
},
{
"firstName": "Steven",
"lastName": "Self",
"creatorType": "author"
},
{
"firstName": "Guido",
"lastName": "Salas",
"creatorType": "author"
},
{
"firstName": "Steven",
"lastName": "Schubring",
"creatorType": "author"
},
{
"firstName": "Jason L",
"lastName": "Permenter",
"creatorType": "author"
},
{
"firstName": "Kendra",
"lastName": "Arbesman",
"creatorType": "author"
}
],
"notes": [],
"tags": [
"Vulcanian eruptions",
"breadcrust",
"plinian"
],
"seeAlso": [],
"attachments": [
{
"url": "file://Users/heatherwright/Documents/Scientific Papers/Adams_Huaynaputina.pdf",
"mimeType": "application/pdf",
"title": "Attachment",
"downloadable": true
},
{
"url": "file://",
"title": "Attachment",
"downloadable": true
}
],
"publicationTitle": "Bulletin of Volcanology",
"pages": "493–518",
"title": "The physical volcanology of the 1600 eruption of Huaynaputina, southern Peru",
"volume": "62",
"date": "2001"
}
]
},
{
"type": "import",
"input": "@Book{abramowitz+stegun,\u000a author = \"Milton {Abramowitz} and Irene A. {Stegun}\",\u000a title = \"Handbook of Mathematical Functions with\u000a Formulas, Graphs, and Mathematical Tables\",\u000a publisher = \"Dover\",\u000a year = 1964,\u000a address = \"New York\",\u000a edition = \"ninth Dover printing, tenth GPO printing\"\u000a}\u000a\u000a@Book{Torre2008,\u000a author = \"Joe Torre and Tom Verducci\",\u000a publisher = \"Doubleday\",\u000a title = \"The Yankee Years\",\u000a year = 2008,\u000a isbn = \"0385527403\"\u000a}\u000a",
"items": [
{
"itemType": "book",
"creators": [
{
"firstName": "Milton",
"lastName": "Abramowitz",
"creatorType": "author"
},
{
"firstName": "Irene A.",
"lastName": "Stegun",
"creatorType": "author"
}
],
"notes": [],
"tags": [],
"seeAlso": [],
"attachments": [],
"title": "Handbook of Mathematical Functions with Formulas, Graphs, and Mathematical Tables",
"publisher": "Dover",
"date": "1964",
"place": "New York",
"edition": "ninth Dover printing, tenth GPO printing"
},
{
"itemType": "book",
"creators": [
{
"firstName": "Joe",
"lastName": "Torre",
"creatorType": "author"
},
{
"firstName": "Tom",
"lastName": "Verducci",
"creatorType": "author"
}
],
"notes": [],
"tags": [],
"seeAlso": [],
"attachments": [],
"publisher": "Doubleday",
"title": "The Yankee Years",
"date": "2008",
"ISBN": "0385527403"
}
]
},
{
"type": "import",
"input": "@INPROCEEDINGS {author:06,\u000a title = {Some publication title},\u000a author = {First Author and Second Author},\u000a crossref = {conference:06},\u000a pages = {330—331},\u000a}\u000a@PROCEEDINGS {conference:06,\u000a editor = {First Editor and Second Editor},\u000a title = {Proceedings of the Xth Conference on XYZ},\u000a booktitle = {Proceedings of the Xth Conference on XYZ},\u000a year = {2006},\u000a month = oct,\u000a}",
"items": [
{
"itemType": "conferencePaper",
"creators": [
{
"firstName": "First",
"lastName": "Author",
"creatorType": "author"
},
{
"firstName": "Second",
"lastName": "Author",
"creatorType": "author"
},
{
"firstName": "First",
"lastName": "Editor",
"creatorType": "editor"
},
{
"firstName": "Second",
"lastName": "Editor",
"creatorType": "editor"
}
],
"notes": [],
"tags": [],
"seeAlso": [],
"attachments": [],
"title": "Some publication title",
"date": "October 2006",
"proceedingsTitle": "Proceedings of the Xth Conference on XYZ",
"pages": "330—331"
},
{
"itemType": "book",
"creators": [
{
"firstName": "First",
"lastName": "Editor",
"creatorType": "editor"
},
{
"firstName": "Second",
"lastName": "Editor",
"creatorType": "editor"
}
],
"notes": [],
"tags": [],
"seeAlso": [],
"attachments": [],
"title": "Proceedings of the Xth Conference on XYZ",
"publicationTitle": "Proceedings of the Xth Conference on XYZ",
"date": "October 2006"
}
]
},
{
"type": "import",
"input": "@Book{hicks2001,\u000a author = \"von Hicks, III, Michael\",\u000a title = \"Design of a Carbon Fiber Composite Grid Structure for the GLAST\u000a Spacecraft Using a Novel Manufacturing Technique\",\u000a publisher = \"Stanford Press\",\u000a year = 2001,\u000a address = \"Palo Alto\",\u000a edition = \"1st,\",\u000a isbn = \"0-69-697269-4\"\u000a}",
"items": [
{
"itemType": "book",
"creators": [
{
"firstName": "Michael",
"lastName": "von Hicks, III",
"creatorType": "author"
}
],
"notes": [],
"tags": [],
"seeAlso": [],
"attachments": [],
"title": "Design of a Carbon Fiber Composite Grid Structure for the GLAST Spacecraft Using a Novel Manufacturing Technique",
"publisher": "Stanford Press",
"date": "2001",
"place": "Palo Alto",
"edition": "1st,",
"ISBN": "0-69-697269-4"
}
]
},
{
"type": "import",
"input": "@article{Oliveira_2009, title={USGS monitoring ecological impacts}, volume={107}, number={29}, journal={Oil & Gas Journal}, author={Oliveira, A}, year={2009}, pages={29}}",
"items": [
{
"itemType": "journalArticle",
"creators": [
{
"firstName": "A",
"lastName": "Oliveira",
"creatorType": "author"
}
],
"notes": [],
"tags": [],
"seeAlso": [],
"attachments": [],
"title": "USGS monitoring ecological impacts",
"volume": "107",
"issue": "29",
"publicationTitle": "Oil & Gas Journal",
"date": "2009",
"pages": "29"
}
]
},
{
"type": "import",
"input": "@article{test-ticket1661,\u000atitle={non-braking space: ~; accented characters: {\\~n} and \\~{n}; tilde operator: \\~},\u000a} ",
"items": [
{
"itemType": "journalArticle",
"creators": [],
"notes": [],
"tags": [],
"seeAlso": [],
"attachments": [],
"title": "non-braking space: ; accented characters: ñ and ñ; tilde operator: ∼"
}
]
}
]
/** END TEST CASES **/
{
"translatorID": "1234567",
"label": "BibTeX Tan-Revised",
"creator": "Simon Kornblith and Richard Karnesky with tweaks by Tan",
"target": "bib",
"minVersion": "2.1.9",
"maxVersion": "",
"priority": 200,
"displayOptions": {
"exportCharset": "ISO-8859-1",
"exportNotes": true,
"exportFileData": false
},
"inRepository": false,
"translatorType": 3,
"browserSupport": "gcs",
"lastUpdated": "2011-08-16 15:07:38"
}
// "exportCharset":"ISO-8859-1", unicode not working well with latex editor
// -- Tan --begin: read Key Format Strings and Field from prefs.
/*
1. A general matching element is % followed by a two-letter label: for
matching field and specifying the lower/upper case for 1st/remaining letters.
2. Then it can be optionally followed by a number for the maximum length in
number of characters. (default=0: means all characters)
3. Last it can be also optionally followed by a number within curly brackets
for selecting the n-th word of the field (start from 0-th, the default).
4. The special repitive 2-letter labels like %TT, %aa, and %JJ are to group
the first letters only of surnames/words in corresponding fields.
5. Separators/indicators including +,-,:,., etc, and all letters and numbers
can be used in between the elements.
Collision Format: %a for alphabetic suffix, %n for numeric suffix
Specified Key Field: e.g. callNumber for using the stored key
Some examples:
%au4%yr2%tt2 %AU_%yr_%TI %Au4-%Au4{1}:%JJ%yr:Vol%vo:Pg%pg-%pg{1}
%Au4{1} = first 4 letters of 2nd creator's surname (first letter capitalized)
%ti6{2} = first 6 letters of 3rd word in title (all lowercase)
%AA4 = initials of first 4 creators' surnames (uppercase)
%tt6 = first letters of first 6 words in title (lowercase)
%JJ5 = first letters of first 5 words in journal name (uppercase)
%yr = %yr4 = four-digit year, %yr2 = two-digit year
%vo = volume number
%pg = first page number
%pg{1} = last page number
*/
var citeKeyFormat = Zotero.getPrefs("bibtexKeyFormat") ? Zotero.getPrefs("bibtexKeyFormat") : "%au%yr%ti";
var citeKeyCollisionFormat = Zotero.getPrefs("bibtexKeyCollisionFormat") ? Zotero.getPrefs("bibtexKeyCollisionFormat") : "-%n";
var citeKeyField = Zotero.getPrefs("bibtexKeyField"); //e.g. callNumber
var exportLocalFilePath = Zotero.getPrefs("bibtexExportLocalFilePath"); // default=no
var preserveLatex = Zotero.getPrefs("bibtexPreserveLatex"); // default=no
// -- Tan --end
function detectImport() {
var maxChars = 1048576; // 1MB
var inComment = false;
var block = "";
var buffer = "";
var chr = "";
var charsRead = 0;
var re = /^\s*@[a-zA-Z]+[\(\{]/;
while((buffer = Zotero.read(4096)) && charsRead < maxChars) {
Zotero.debug("Scanning " + buffer.length + " characters for BibTeX");
charsRead += buffer.length;
for (var i=0; i<buffer.length; i++) {
chr = buffer[i];
if (inComment && chr != "\r" && chr != "\n") {
continue;
}
inComment = false;
if(chr == "%") {
// read until next newline
block = "";
inComment = true;
} else if((chr == "\n" || chr == "\r"
// allow one-line entries
|| i == (buffer.length - 1))
&& block) {
// check if this is a BibTeX entry
if(re.test(block)) {
return true;
}
block = "";
} else if(" \n\r\t".indexOf(chr) == -1) {
block += chr;
}
}
}
}
var fieldMap = {
address:"place",
chapter:"section",
edition:"edition",
type:"type",
series:"series",
title:"title",
volume:"volume",
copyright:"rights",
isbn:"ISBN",
issn:"ISSN",
lccn:"callNumber",
location:"archiveLocation",
shorttitle:"shortTitle",
url:"url",
doi:"DOI",
"abstract":"abstractNote"
};
var inputFieldMap = {
booktitle :"publicationTitle",
school:"publisher",
institution:"publisher",
publisher:"publisher",
issue:"issue"
};
var zotero2bibtexTypeMap = {
"book":"book",
"bookSection":"incollection",
"journalArticle":"article",
"magazineArticle":"article",
"newspaperArticle":"article",
"thesis":"phdthesis",
"letter":"misc",
"manuscript":"unpublished",
"interview":"misc",
"film":"misc",
"artwork":"misc",
"webpage":"misc",
"conferencePaper":"inproceedings",
"report":"techreport"
};
var bibtex2zoteroTypeMap = {
"book":"book", // or booklet, proceedings
"inbook":"bookSection",
"incollection":"bookSection",
"article":"journalArticle", // or magazineArticle or newspaperArticle
"phdthesis":"thesis",
"unpublished":"manuscript",
"inproceedings":"conferencePaper", // check for conference also
"conference":"conferencePaper",
"techreport":"report",
"booklet":"book",
"manual":"book",
"mastersthesis":"thesis",
"misc":"book",
"proceedings":"book"
};
/*
* three-letter month abbreviations. i assume these are the same ones that the
* docs say are defined in some appendix of the LaTeX book. (i don't have the
* LaTeX book.)
*/
var months = ["jan", "feb", "mar", "apr", "may", "jun",
"jul", "aug", "sep", "oct", "nov", "dec"];
/*
* new mapping table based on that from Matthias Steffens,
* then enhanced with some fields generated from the unicode table.
*/
var mappingTable = {
"\u00A0":"~", // NO-BREAK SPACE
"\u00A1":"{\\textexclamdown}", // INVERTED EXCLAMATION MARK
"\u00A2":"{\\textcent}", // CENT SIGN
"\u00A3":"{\\textsterling}", // POUND SIGN
"\u00A5":"{\\textyen}", // YEN SIGN
"\u00A6":"{\\textbrokenbar}", // BROKEN BAR
"\u00A7":"{\\textsection}", // SECTION SIGN
"\u00A8":"{\\textasciidieresis}", // DIAERESIS
"\u00A9":"{\\textcopyright}", // COPYRIGHT SIGN
"\u00AA":"{\\textordfeminine}", // FEMININE ORDINAL INDICATOR
"\u00AB":"{\\guillemotleft}", // LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
"\u00AC":"{\\textlnot}", // NOT SIGN
"\u00AD":"-", // SOFT HYPHEN
"\u00AE":"{\\textregistered}", // REGISTERED SIGN
"\u00AF":"{\\textasciimacron}", // MACRON
"\u00B0":"{\\textdegree}", // DEGREE SIGN
"\u00B1":"{\\textpm}", // PLUS-MINUS SIGN
"\u00B2":"{\\texttwosuperior}", // SUPERSCRIPT TWO
"\u00B3":"{\\textthreesuperior}", // SUPERSCRIPT THREE
"\u00B4":"{\\textasciiacute}", // ACUTE ACCENT
"\u00B5":"{\\textmu}", // MICRO SIGN
"\u00B6":"{\\textparagraph}", // PILCROW SIGN
"\u00B7":"{\\textperiodcentered}", // MIDDLE DOT
"\u00B8":"{\\c\\ }", // CEDILLA
"\u00B9":"{\\textonesuperior}", // SUPERSCRIPT ONE
"\u00BA":"{\\textordmasculine}", // MASCULINE ORDINAL INDICATOR
"\u00BB":"{\\guillemotright}", // RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
"\u00BC":"{\\textonequarter}", // VULGAR FRACTION ONE QUARTER
"\u00BD":"{\\textonehalf}", // VULGAR FRACTION ONE HALF
"\u00BE":"{\\textthreequarters}", // VULGAR FRACTION THREE QUARTERS
"\u00BF":"{\\textquestiondown}", // INVERTED QUESTION MARK
"\u00C6":"{\\AE}", // LATIN CAPITAL LETTER AE
"\u00D0":"{\\DH}", // LATIN CAPITAL LETTER ETH
"\u00D7":"{\\texttimes}", // MULTIPLICATION SIGN
"\U00D8":"{\\O}", // LATIN CAPITAL LETTER O WITH STROKE
"\u00DE":"{\\TH}", // LATIN CAPITAL LETTER THORN
"\u00DF":"{\\ss}", // LATIN SMALL LETTER SHARP S
"\u00E6":"{\\ae}", // LATIN SMALL LETTER AE
"\u00F0":"{\\dh}", // LATIN SMALL LETTER ETH
"\u00F7":"{\\textdiv}", // DIVISION SIGN
"\U00F8":"{\\o}", // LATIN SMALL LETTER O WITH STROKE
"\u00FE":"{\\th}", // LATIN SMALL LETTER THORN
"\u0131":"{\\i}", // LATIN SMALL LETTER DOTLESS I
"\u0132":"IJ", // LATIN CAPITAL LIGATURE IJ
"\u0133":"ij", // LATIN SMALL LIGATURE IJ
"\u0138":"k", // LATIN SMALL LETTER KRA
"\u0149":"'n", // LATIN SMALL LETTER N PRECEDED BY APOSTROPHE
"\u014A":"{\\NG}", // LATIN CAPITAL LETTER ENG
"\u014B":"{\\ng}", // LATIN SMALL LETTER ENG
"\u0152":"{\\OE}", // LATIN CAPITAL LIGATURE OE
"\u0153":"{\\oe}", // LATIN SMALL LIGATURE OE
"\u017F":"s", // LATIN SMALL LETTER LONG S
"\u02B9":"'", // MODIFIER LETTER PRIME
"\u02BB":"'", // MODIFIER LETTER TURNED COMMA
"\u02BC":"'", // MODIFIER LETTER APOSTROPHE
"\u02BD":"'", // MODIFIER LETTER REVERSED COMMA
"\u02C6":"{\\textasciicircum}", // MODIFIER LETTER CIRCUMFLEX ACCENT
"\u02C8":"'", // MODIFIER LETTER VERTICAL LINE
"\u02C9":"-", // MODIFIER LETTER MACRON
"\u02CC":",", // MODIFIER LETTER LOW VERTICAL LINE
"\u02D0":":", // MODIFIER LETTER TRIANGULAR COLON
"\u02DA":"o", // RING ABOVE
"\u02DC":"\\~{}", // SMALL TILDE
"\u02DD":"{\\textacutedbl}", // DOUBLE ACUTE ACCENT
"\u0374":"'", // GREEK NUMERAL SIGN
"\u0375":",", // GREEK LOWER NUMERAL SIGN
"\u037E":";", // GREEK QUESTION MARK
// -- Tan -begin greek symbols
"\u0393":"$\\Gamma$", // GREEK Gamma
"\u0394":"$\\Delta$", // GREEK Delta
"\u0398":"$\\Theta$", // GREEK Theta
"\u039B":"$\\Lambda$", // GREEK Lambda
"\u039E":"$\\Xi$", // GREEK Xi
"\u03A0":"$\\Pi$", // GREEK Pi
"\u03A3":"$\\Sigma$", // GREEK Sigma
"\u03A6":"$\\Phi$", // GREEK Phi
"\u03A8":"$\\Psi$", // GREEK Psi
"\u03A9":"$\\Omega$", // GREEK Omega
"\u03B1":"$\\alpha$", // GREEK alpha
"\u03B2":"$\\beta$", // GREEK beta
"\u03B3":"$\\gamma$", // GREEK gamma
"\u03B4":"$\\delta$", // GREEK delta
"\u03B5":"$\\varepsilon$", // GREEK var-epsilon
"\u03B6":"$\\zeta$", // GREEK zeta
"\u03B7":"$\\eta$", // GREEK eta
"\u03B8":"$\\theta$", // GREEK theta
"\u03B9":"$\\iota$", // GREEK iota
"\u03BA":"$\\kappa$", // GREEK kappa
"\u03BB":"$\\lambda$", // GREEK lambda
"\u03BC":"$\\mu$", // GREEK mu
"\u03BD":"$\\nu$", // GREEK nu
"\u03BE":"$\\xi$", // GREEK xi
"\u03C0":"$\\pi$", // GREEK pi
"\u03C1":"$\\rho$", // GREEK rho
"\u03C2":"$\\varsigma$", // GREEK var-sigma
"\u03C3":"$\\sigma$", // GREEK sigma
"\u03C4":"$\\tau$", // GREEK tau
"\u03C5":"$\\upsilon$", // GREEK upsilon
"\u03C6":"$\\varphi$", // GREEK var-phi
"\u03C7":"$\\chi$", // GREEK chi
"\u03C8":"$\\psi$", // GREEK psi
"\u03C9":"$\\omega$", // GREEK omega
"\u03D1":"$\\vartheta$", // GREEK var-theta
"\u03D2":"$\\Upsilon$", // GREEK Upsilon
"\u03D5":"$\\phi$", // GREEK phi
"\u03D6":"$\\varpi$", // GREEK var-pi
"\u03F1":"$\\varrho$", // GREEK var-rho
"\u03F5":"$\\epsilon$", // GREEK epsilon
// -- Tan -end greek symbols
"\u2000":" ", // EN QUAD
"\u2001":" ", // EM QUAD
"\u2002":" ", // EN SPACE
"\u2003":" ", // EM SPACE
"\u2004":" ", // THREE-PER-EM SPACE
"\u2005":" ", // FOUR-PER-EM SPACE
"\u2006":" ", // SIX-PER-EM SPACE
"\u2007":" ", // FIGURE SPACE
"\u2008":" ", // PUNCTUATION SPACE
"\u2009":" ", // THIN SPACE
"\u2010":"-", // HYPHEN
"\u2011":"-", // NON-BREAKING HYPHEN
"\u2012":"-", // FIGURE DASH
"\u2013":"{\\textendash}", // EN DASH
"\u2014":"{\\textemdash}", // EM DASH
"\u2015":"{\\textemdash}", // HORIZONTAL BAR or QUOTATION DASH (not in LaTeX -- use EM DASH)
"\u2016":"{\\textbardbl}", // DOUBLE VERTICAL LINE
"\u2017":"{\\textunderscore}", // DOUBLE LOW LINE
"\u2018":"{\\textquoteleft}", // LEFT SINGLE QUOTATION MARK
"\u2019":"{\\textquoteright}", // RIGHT SINGLE QUOTATION MARK
"`" : "\u2018", // LEFT SINGLE QUOTATION MARK
"'" : "\u2019", // RIGHT SINGLE QUOTATION MARK
"\u201A":"{\\quotesinglbase}", // SINGLE LOW-9 QUOTATION MARK
"\u201B":"'", // SINGLE HIGH-REVERSED-9 QUOTATION MARK
"\u201C":"{\\textquotedblleft}", // LEFT DOUBLE QUOTATION MARK
"\u201D":"{\\textquotedblright}", // RIGHT DOUBLE QUOTATION MARK
"\u201E":"{\\quotedblbase}", // DOUBLE LOW-9 QUOTATION MARK
"\u201F":"{\\quotedblbase}", // DOUBLE HIGH-REVERSED-9 QUOTATION MARK
"\u2020":"{\\textdagger}", // DAGGER
"\u2021":"{\\textdaggerdbl}", // DOUBLE DAGGER
"\u2022":"{\\textbullet}", // BULLET
"\u2023":">", // TRIANGULAR BULLET
"\u2024":".", // ONE DOT LEADER
"\u2025":"..", // TWO DOT LEADER
"\u2026":"{\\textellipsis}", // HORIZONTAL ELLIPSIS
"\u2027":"-", // HYPHENATION POINT
"\u202F":" ", // NARROW NO-BREAK SPACE
"\u2030":"{\\textperthousand}", // PER MILLE SIGN
"\u2032":"'", // PRIME
"\u2033":"'", // DOUBLE PRIME
"\u2034":"'''", // TRIPLE PRIME
"\u2035":"`", // REVERSED PRIME
"\u2036":"``", // REVERSED DOUBLE PRIME
"\u2037":"```", // REVERSED TRIPLE PRIME
"\u2039":"{\\guilsinglleft}", // SINGLE LEFT-POINTING ANGLE QUOTATION MARK
"\u203A":"{\\guilsinglright}", // SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
"\u203C":"!!", // DOUBLE EXCLAMATION MARK
"\u203E":"-", // OVERLINE
"\u2043":"-", // HYPHEN BULLET
"\u2044":"{\\textfractionsolidus}", // FRACTION SLASH
"\u2048":"?!", // QUESTION EXCLAMATION MARK
"\u2049":"!?", // EXCLAMATION QUESTION MARK
"\u204A":"7", // TIRONIAN SIGN ET
"\u2070":"$^{0}$", // SUPERSCRIPT ZERO
"\u2074":"$^{4}$", // SUPERSCRIPT FOUR
"\u2075":"$^{5}$", // SUPERSCRIPT FIVE
"\u2076":"$^{6}$", // SUPERSCRIPT SIX
"\u2077":"$^{7}$", // SUPERSCRIPT SEVEN
"\u2078":"$^{8}$", // SUPERSCRIPT EIGHT
"\u2079":"$^{9}$", // SUPERSCRIPT NINE
"\u207A":"$^{+}$", // SUPERSCRIPT PLUS SIGN
"\u207B":"$^{-}$", // SUPERSCRIPT MINUS
"\u207C":"$^{=}$", // SUPERSCRIPT EQUALS SIGN
"\u207D":"$^{(}$", // SUPERSCRIPT LEFT PARENTHESIS
"\u207E":"$^{)}$", // SUPERSCRIPT RIGHT PARENTHESIS
"\u207F":"$^{n}$", // SUPERSCRIPT LATIN SMALL LETTER N
"\u2080":"$_{0}$", // SUBSCRIPT ZERO
"\u2081":"$_{1}$", // SUBSCRIPT ONE
"\u2082":"$_{2}$", // SUBSCRIPT TWO
"\u2083":"$_{3}$", // SUBSCRIPT THREE
"\u2084":"$_{4}$", // SUBSCRIPT FOUR
"\u2085":"$_{5}$", // SUBSCRIPT FIVE
"\u2086":"$_{6}$", // SUBSCRIPT SIX
"\u2087":"$_{7}$", // SUBSCRIPT SEVEN
"\u2088":"$_{8}$", // SUBSCRIPT EIGHT
"\u2089":"$_{9}$", // SUBSCRIPT NINE
"\u208A":"$_{+}$", // SUBSCRIPT PLUS SIGN
"\u208B":"$_{-}$", // SUBSCRIPT MINUS
"\u208C":"$_{=}$", // SUBSCRIPT EQUALS SIGN
"\u208D":"$_{(}$", // SUBSCRIPT LEFT PARENTHESIS
"\u208E":"$_{)}$", // SUBSCRIPT RIGHT PARENTHESIS
"\u20AC":"{\\texteuro}", // EURO SIGN
"\u2100":"a/c", // ACCOUNT OF
"\u2101":"a/s", // ADDRESSED TO THE SUBJECT
"\u2103":"{\\textcelsius}", // DEGREE CELSIUS
"\u2105":"c/o", // CARE OF
"\u2106":"c/u", // CADA UNA
"\u2109":"F", // DEGREE FAHRENHEIT
"\u2113":"l", // SCRIPT SMALL L
"\u2116":"{\\textnumero}", // NUMERO SIGN
"\u2117":"{\\textcircledP}", // SOUND RECORDING COPYRIGHT
"\u2120":"{\\textservicemark}", // SERVICE MARK
"\u2121":"TEL", // TELEPHONE SIGN
"\u2122":"{\\texttrademark}", // TRADE MARK SIGN
"\u2126":"{\\textohm}", // OHM SIGN
"\u212A":"K", // KELVIN SIGN
"\u212B":"A", // ANGSTROM SIGN
"\u212E":"{\\textestimated}", // ESTIMATED SYMBOL
"\u2153":" 1/3", // VULGAR FRACTION ONE THIRD
"\u2154":" 2/3", // VULGAR FRACTION TWO THIRDS
"\u2155":" 1/5", // VULGAR FRACTION ONE FIFTH
"\u2156":" 2/5", // VULGAR FRACTION TWO FIFTHS
"\u2157":" 3/5", // VULGAR FRACTION THREE FIFTHS
"\u2158":" 4/5", // VULGAR FRACTION FOUR FIFTHS
"\u2159":" 1/6", // VULGAR FRACTION ONE SIXTH
"\u215A":" 5/6", // VULGAR FRACTION FIVE SIXTHS
"\u215B":" 1/8", // VULGAR FRACTION ONE EIGHTH
"\u215C":" 3/8", // VULGAR FRACTION THREE EIGHTHS
"\u215D":" 5/8", // VULGAR FRACTION FIVE EIGHTHS
"\u215E":" 7/8", // VULGAR FRACTION SEVEN EIGHTHS
"\u215F":" 1/", // FRACTION NUMERATOR ONE
"\u2160":"I", // ROMAN NUMERAL ONE
"\u2161":"II", // ROMAN NUMERAL TWO
"\u2162":"III", // ROMAN NUMERAL THREE
"\u2163":"IV", // ROMAN NUMERAL FOUR
"\u2164":"V", // ROMAN NUMERAL FIVE
"\u2165":"VI", // ROMAN NUMERAL SIX
"\u2166":"VII", // ROMAN NUMERAL SEVEN
"\u2167":"VIII", // ROMAN NUMERAL EIGHT
"\u2168":"IX", // ROMAN NUMERAL NINE
"\u2169":"X", // ROMAN NUMERAL TEN
"\u216A":"XI", // ROMAN NUMERAL ELEVEN
"\u216B":"XII", // ROMAN NUMERAL TWELVE
"\u216C":"L", // ROMAN NUMERAL FIFTY
"\u216D":"C", // ROMAN NUMERAL ONE HUNDRED
"\u216E":"D", // ROMAN NUMERAL FIVE HUNDRED
"\u216F":"M", // ROMAN NUMERAL ONE THOUSAND
"\u2170":"i", // SMALL ROMAN NUMERAL ONE
"\u2171":"ii", // SMALL ROMAN NUMERAL TWO
"\u2172":"iii", // SMALL ROMAN NUMERAL THREE
"\u2173":"iv", // SMALL ROMAN NUMERAL FOUR
"\u2174":"v", // SMALL ROMAN NUMERAL FIVE
"\u2175":"vi", // SMALL ROMAN NUMERAL SIX
"\u2176":"vii", // SMALL ROMAN NUMERAL SEVEN
"\u2177":"viii", // SMALL ROMAN NUMERAL EIGHT
"\u2178":"ix", // SMALL ROMAN NUMERAL NINE
"\u2179":"x", // SMALL ROMAN NUMERAL TEN
"\u217A":"xi", // SMALL ROMAN NUMERAL ELEVEN
"\u217B":"xii", // SMALL ROMAN NUMERAL TWELVE
"\u217C":"l", // SMALL ROMAN NUMERAL FIFTY
"\u217D":"c", // SMALL ROMAN NUMERAL ONE HUNDRED
"\u217E":"d", // SMALL ROMAN NUMERAL FIVE HUNDRED
"\u217F":"m", // SMALL ROMAN NUMERAL ONE THOUSAND
"\u2190":"{\\textleftarrow}", // LEFTWARDS ARROW
"\u2191":"{\\textuparrow}", // UPWARDS ARROW
"\u2192":"{\\textrightarrow}", // RIGHTWARDS ARROW
"\u2193":"{\\textdownarrow}", // DOWNWARDS ARROW
"\u2194":"<->", // LEFT RIGHT ARROW
"\u21D0":"<=", // LEFTWARDS DOUBLE ARROW
"\u21D2":"=>", // RIGHTWARDS DOUBLE ARROW
"\u21D4":"<=>", // LEFT RIGHT DOUBLE ARROW
"\u2212":"-", // MINUS SIGN
"\u2215":"/", // DIVISION SLASH
"\u2216":"\\", // SET MINUS
"\u2217":"*", // ASTERISK OPERATOR
"\u2218":"o", // RING OPERATOR
"\u2219":".", // BULLET OPERATOR
"\u221E":"$\\infty$", // INFINITY
"\u2223":"|", // DIVIDES
"\u2225":"||", // PARALLEL TO
"\u2236":":", // RATIO
"\u223C":"\\~{}", // TILDE OPERATOR
"\u2260":"/=", // NOT EQUAL TO
"\u2261":"=", // IDENTICAL TO
"\u2264":"<=", // LESS-THAN OR EQUAL TO
"\u2265":">=", // GREATER-THAN OR EQUAL TO
"\u226A":"<<", // MUCH LESS-THAN
"\u226B":">>", // MUCH GREATER-THAN
"\u2295":"(+)", // CIRCLED PLUS
"\u2296":"(-)", // CIRCLED MINUS
"\u2297":"(x)", // CIRCLED TIMES
"\u2298":"(/)", // CIRCLED DIVISION SLASH
"\u22A2":"|-", // RIGHT TACK
"\u22A3":"-|", // LEFT TACK
"\u22A6":"|-", // ASSERTION
"\u22A7":"|=", // MODELS
"\u22A8":"|=", // TRUE
"\u22A9":"||-", // FORCES
"\u22C5":".", // DOT OPERATOR
"\u22C6":"*", // STAR OPERATOR
"\u22D5":"$\\#$", // EQUAL AND PARALLEL TO
"\u22D8":"<<<", // VERY MUCH LESS-THAN
"\u22D9":">>>", // VERY MUCH GREATER-THAN
"\u2329":"{\\textlangle}", // LEFT-POINTING ANGLE BRACKET
"\u232A":"{\\textrangle}", // RIGHT-POINTING ANGLE BRACKET
"\u2400":"NUL", // SYMBOL FOR NULL
"\u2401":"SOH", // SYMBOL FOR START OF HEADING
"\u2402":"STX", // SYMBOL FOR START OF TEXT
"\u2403":"ETX", // SYMBOL FOR END OF TEXT
"\u2404":"EOT", // SYMBOL FOR END OF TRANSMISSION
"\u2405":"ENQ", // SYMBOL FOR ENQUIRY
"\u2406":"ACK", // SYMBOL FOR ACKNOWLEDGE
"\u2407":"BEL", // SYMBOL FOR BELL
"\u2408":"BS", // SYMBOL FOR BACKSPACE
"\u2409":"HT", // SYMBOL FOR HORIZONTAL TABULATION
"\u240A":"LF", // SYMBOL FOR LINE FEED
"\u240B":"VT", // SYMBOL FOR VERTICAL TABULATION
"\u240C":"FF", // SYMBOL FOR FORM FEED
"\u240D":"CR", // SYMBOL FOR CARRIAGE RETURN
"\u240E":"SO", // SYMBOL FOR SHIFT OUT
"\u240F":"SI", // SYMBOL FOR SHIFT IN
"\u2410":"DLE", // SYMBOL FOR DATA LINK ESCAPE
"\u2411":"DC1", // SYMBOL FOR DEVICE CONTROL ONE
"\u2412":"DC2", // SYMBOL FOR DEVICE CONTROL TWO
"\u2413":"DC3", // SYMBOL FOR DEVICE CONTROL THREE
"\u2414":"DC4", // SYMBOL FOR DEVICE CONTROL FOUR
"\u2415":"NAK", // SYMBOL FOR NEGATIVE ACKNOWLEDGE
"\u2416":"SYN", // SYMBOL FOR SYNCHRONOUS IDLE
"\u2417":"ETB", // SYMBOL FOR END OF TRANSMISSION BLOCK
"\u2418":"CAN", // SYMBOL FOR CANCEL
"\u2419":"EM", // SYMBOL FOR END OF MEDIUM
"\u241A":"SUB", // SYMBOL FOR SUBSTITUTE
"\u241B":"ESC", // SYMBOL FOR ESCAPE
"\u241C":"FS", // SYMBOL FOR FILE SEPARATOR
"\u241D":"GS", // SYMBOL FOR GROUP SEPARATOR
"\u241E":"RS", // SYMBOL FOR RECORD SEPARATOR
"\u241F":"US", // SYMBOL FOR UNIT SEPARATOR
"\u2420":"SP", // SYMBOL FOR SPACE
"\u2421":"DEL", // SYMBOL FOR DELETE
"\u2423":"{\\textvisiblespace}", // OPEN BOX
"\u2424":"NL", // SYMBOL FOR NEWLINE
"\u2425":"///", // SYMBOL FOR DELETE FORM TWO
"\u2426":"?", // SYMBOL FOR SUBSTITUTE FORM TWO
"\u2460":"(1)", // CIRCLED DIGIT ONE
"\u2461":"(2)", // CIRCLED DIGIT TWO
"\u2462":"(3)", // CIRCLED DIGIT THREE
"\u2463":"(4)", // CIRCLED DIGIT FOUR
"\u2464":"(5)", // CIRCLED DIGIT FIVE
"\u2465":"(6)", // CIRCLED DIGIT SIX
"\u2466":"(7)", // CIRCLED DIGIT SEVEN
"\u2467":"(8)", // CIRCLED DIGIT EIGHT
"\u2468":"(9)", // CIRCLED DIGIT NINE
"\u2469":"(10)", // CIRCLED NUMBER TEN
"\u246A":"(11)", // CIRCLED NUMBER ELEVEN
"\u246B":"(12)", // CIRCLED NUMBER TWELVE
"\u246C":"(13)", // CIRCLED NUMBER THIRTEEN
"\u246D":"(14)", // CIRCLED NUMBER FOURTEEN
"\u246E":"(15)", // CIRCLED NUMBER FIFTEEN
"\u246F":"(16)", // CIRCLED NUMBER SIXTEEN
"\u2470":"(17)", // CIRCLED NUMBER SEVENTEEN
"\u2471":"(18)", // CIRCLED NUMBER EIGHTEEN
"\u2472":"(19)", // CIRCLED NUMBER NINETEEN
"\u2473":"(20)", // CIRCLED NUMBER TWENTY
"\u2474":"(1)", // PARENTHESIZED DIGIT ONE
"\u2475":"(2)", // PARENTHESIZED DIGIT TWO
"\u2476":"(3)", // PARENTHESIZED DIGIT THREE
"\u2477":"(4)", // PARENTHESIZED DIGIT FOUR
"\u2478":"(5)", // PARENTHESIZED DIGIT FIVE
"\u2479":"(6)", // PARENTHESIZED DIGIT SIX
"\u247A":"(7)", // PARENTHESIZED DIGIT SEVEN
"\u247B":"(8)", // PARENTHESIZED DIGIT EIGHT
"\u247C":"(9)", // PARENTHESIZED DIGIT NINE
"\u247D":"(10)", // PARENTHESIZED NUMBER TEN
"\u247E":"(11)", // PARENTHESIZED NUMBER ELEVEN
"\u247F":"(12)", // PARENTHESIZED NUMBER TWELVE
"\u2480":"(13)", // PARENTHESIZED NUMBER THIRTEEN
"\u2481":"(14)", // PARENTHESIZED NUMBER FOURTEEN
"\u2482":"(15)", // PARENTHESIZED NUMBER FIFTEEN
"\u2483":"(16)", // PARENTHESIZED NUMBER SIXTEEN
"\u2484":"(17)", // PARENTHESIZED NUMBER SEVENTEEN
"\u2485":"(18)", // PARENTHESIZED NUMBER EIGHTEEN
"\u2486":"(19)", // PARENTHESIZED NUMBER NINETEEN
"\u2487":"(20)", // PARENTHESIZED NUMBER TWENTY
"\u2488":"1.", // DIGIT ONE FULL STOP
"\u2489":"2.", // DIGIT TWO FULL STOP
"\u248A":"3.", // DIGIT THREE FULL STOP
"\u248B":"4.", // DIGIT FOUR FULL STOP
"\u248C":"5.", // DIGIT FIVE FULL STOP
"\u248D":"6.", // DIGIT SIX FULL STOP
"\u248E":"7.", // DIGIT SEVEN FULL STOP
"\u248F":"8.", // DIGIT EIGHT FULL STOP
"\u2490":"9.", // DIGIT NINE FULL STOP
"\u2491":"10.", // NUMBER TEN FULL STOP
"\u2492":"11.", // NUMBER ELEVEN FULL STOP
"\u2493":"12.", // NUMBER TWELVE FULL STOP
"\u2494":"13.", // NUMBER THIRTEEN FULL STOP
"\u2495":"14.", // NUMBER FOURTEEN FULL STOP
"\u2496":"15.", // NUMBER FIFTEEN FULL STOP
"\u2497":"16.", // NUMBER SIXTEEN FULL STOP
"\u2498":"17.", // NUMBER SEVENTEEN FULL STOP
"\u2499":"18.", // NUMBER EIGHTEEN FULL STOP
"\u249A":"19.", // NUMBER NINETEEN FULL STOP
"\u249B":"20.", // NUMBER TWENTY FULL STOP
"\u249C":"(a)", // PARENTHESIZED LATIN SMALL LETTER A
"\u249D":"(b)", // PARENTHESIZED LATIN SMALL LETTER B
"\u249E":"(c)", // PARENTHESIZED LATIN SMALL LETTER C
"\u249F":"(d)", // PARENTHESIZED LATIN SMALL LETTER D
"\u24A0":"(e)", // PARENTHESIZED LATIN SMALL LETTER E
"\u24A1":"(f)", // PARENTHESIZED LATIN SMALL LETTER F
"\u24A2":"(g)", // PARENTHESIZED LATIN SMALL LETTER G
"\u24A3":"(h)", // PARENTHESIZED LATIN SMALL LETTER H
"\u24A4":"(i)", // PARENTHESIZED LATIN SMALL LETTER I
"\u24A5":"(j)", // PARENTHESIZED LATIN SMALL LETTER J
"\u24A6":"(k)", // PARENTHESIZED LATIN SMALL LETTER K
"\u24A7":"(l)", // PARENTHESIZED LATIN SMALL LETTER L
"\u24A8":"(m)", // PARENTHESIZED LATIN SMALL LETTER M
"\u24A9":"(n)", // PARENTHESIZED LATIN SMALL LETTER N
"\u24AA":"(o)", // PARENTHESIZED LATIN SMALL LETTER O
"\u24AB":"(p)", // PARENTHESIZED LATIN SMALL LETTER P
"\u24AC":"(q)", // PARENTHESIZED LATIN SMALL LETTER Q
"\u24AD":"(r)", // PARENTHESIZED LATIN SMALL LETTER R
"\u24AE":"(s)", // PARENTHESIZED LATIN SMALL LETTER S
"\u24AF":"(t)", // PARENTHESIZED LATIN SMALL LETTER T
"\u24B0":"(u)", // PARENTHESIZED LATIN SMALL LETTER U
"\u24B1":"(v)", // PARENTHESIZED LATIN SMALL LETTER V
"\u24B2":"(w)", // PARENTHESIZED LATIN SMALL LETTER W
"\u24B3":"(x)", // PARENTHESIZED LATIN SMALL LETTER X
"\u24B4":"(y)", // PARENTHESIZED LATIN SMALL LETTER Y
"\u24B5":"(z)", // PARENTHESIZED LATIN SMALL LETTER Z
"\u24B6":"(A)", // CIRCLED LATIN CAPITAL LETTER A
"\u24B7":"(B)", // CIRCLED LATIN CAPITAL LETTER B
"\u24B8":"(C)", // CIRCLED LATIN CAPITAL LETTER C
"\u24B9":"(D)", // CIRCLED LATIN CAPITAL LETTER D
"\u24BA":"(E)", // CIRCLED LATIN CAPITAL LETTER E
"\u24BB":"(F)", // CIRCLED LATIN CAPITAL LETTER F
"\u24BC":"(G)", // CIRCLED LATIN CAPITAL LETTER G
"\u24BD":"(H)", // CIRCLED LATIN CAPITAL LETTER H
"\u24BE":"(I)", // CIRCLED LATIN CAPITAL LETTER I
"\u24BF":"(J)", // CIRCLED LATIN CAPITAL LETTER J
"\u24C0":"(K)", // CIRCLED LATIN CAPITAL LETTER K
"\u24C1":"(L)", // CIRCLED LATIN CAPITAL LETTER L
"\u24C2":"(M)", // CIRCLED LATIN CAPITAL LETTER M
"\u24C3":"(N)", // CIRCLED LATIN CAPITAL LETTER N
"\u24C4":"(O)", // CIRCLED LATIN CAPITAL LETTER O
"\u24C5":"(P)", // CIRCLED LATIN CAPITAL LETTER P
"\u24C6":"(Q)", // CIRCLED LATIN CAPITAL LETTER Q
"\u24C7":"(R)", // CIRCLED LATIN CAPITAL LETTER R
"\u24C8":"(S)", // CIRCLED LATIN CAPITAL LETTER S
"\u24C9":"(T)", // CIRCLED LATIN CAPITAL LETTER T
"\u24CA":"(U)", // CIRCLED LATIN CAPITAL LETTER U
"\u24CB":"(V)", // CIRCLED LATIN CAPITAL LETTER V
"\u24CC":"(W)", // CIRCLED LATIN CAPITAL LETTER W
"\u24CD":"(X)", // CIRCLED LATIN CAPITAL LETTER X
"\u24CE":"(Y)", // CIRCLED LATIN CAPITAL LETTER Y
"\u24CF":"(Z)", // CIRCLED LATIN CAPITAL LETTER Z
"\u24D0":"(a)", // CIRCLED LATIN SMALL LETTER A
"\u24D1":"(b)", // CIRCLED LATIN SMALL LETTER B
"\u24D2":"(c)", // CIRCLED LATIN SMALL LETTER C
"\u24D3":"(d)", // CIRCLED LATIN SMALL LETTER D
"\u24D4":"(e)", // CIRCLED LATIN SMALL LETTER E
"\u24D5":"(f)", // CIRCLED LATIN SMALL LETTER F
"\u24D6":"(g)", // CIRCLED LATIN SMALL LETTER G
"\u24D7":"(h)", // CIRCLED LATIN SMALL LETTER H
"\u24D8":"(i)", // CIRCLED LATIN SMALL LETTER I
"\u24D9":"(j)", // CIRCLED LATIN SMALL LETTER J
"\u24DA":"(k)", // CIRCLED LATIN SMALL LETTER K
"\u24DB":"(l)", // CIRCLED LATIN SMALL LETTER L
"\u24DC":"(m)", // CIRCLED LATIN SMALL LETTER M
"\u24DD":"(n)", // CIRCLED LATIN SMALL LETTER N
"\u24DE":"(o)", // CIRCLED LATIN SMALL LETTER O
"\u24DF":"(p)", // CIRCLED LATIN SMALL LETTER P
"\u24E0":"(q)", // CIRCLED LATIN SMALL LETTER Q
"\u24E1":"(r)", // CIRCLED LATIN SMALL LETTER R
"\u24E2":"(s)", // CIRCLED LATIN SMALL LETTER S
"\u24E3":"(t)", // CIRCLED LATIN SMALL LETTER T
"\u24E4":"(u)", // CIRCLED LATIN SMALL LETTER U
"\u24E5":"(v)", // CIRCLED LATIN SMALL LETTER V
"\u24E6":"(w)", // CIRCLED LATIN SMALL LETTER W
"\u24E7":"(x)", // CIRCLED LATIN SMALL LETTER X
"\u24E8":"(y)", // CIRCLED LATIN SMALL LETTER Y
"\u24E9":"(z)", // CIRCLED LATIN SMALL LETTER Z
"\u24EA":"(0)", // CIRCLED DIGIT ZERO
"\u2500":"-", // BOX DRAWINGS LIGHT HORIZONTAL
"\u2501":"=", // BOX DRAWINGS HEAVY HORIZONTAL
"\u2502":"|", // BOX DRAWINGS LIGHT VERTICAL
"\u2503":"|", // BOX DRAWINGS HEAVY VERTICAL
"\u2504":"-", // BOX DRAWINGS LIGHT TRIPLE DASH HORIZONTAL
"\u2505":"=", // BOX DRAWINGS HEAVY TRIPLE DASH HORIZONTAL
"\u2506":"|", // BOX DRAWINGS LIGHT TRIPLE DASH VERTICAL
"\u2507":"|", // BOX DRAWINGS HEAVY TRIPLE DASH VERTICAL
"\u2508":"-", // BOX DRAWINGS LIGHT QUADRUPLE DASH HORIZONTAL
"\u2509":"=", // BOX DRAWINGS HEAVY QUADRUPLE DASH HORIZONTAL
"\u250A":"|", // BOX DRAWINGS LIGHT QUADRUPLE DASH VERTICAL
"\u250B":"|", // BOX DRAWINGS HEAVY QUADRUPLE DASH VERTICAL
"\u250C":"+", // BOX DRAWINGS LIGHT DOWN AND RIGHT
"\u250D":"+", // BOX DRAWINGS DOWN LIGHT AND RIGHT HEAVY
"\u250E":"+", // BOX DRAWINGS DOWN HEAVY AND RIGHT LIGHT
"\u250F":"+", // BOX DRAWINGS HEAVY DOWN AND RIGHT
"\u2510":"+", // BOX DRAWINGS LIGHT DOWN AND LEFT
"\u2511":"+", // BOX DRAWINGS DOWN LIGHT AND LEFT HEAVY
"\u2512":"+", // BOX DRAWINGS DOWN HEAVY AND LEFT LIGHT
"\u2513":"+", // BOX DRAWINGS HEAVY DOWN AND LEFT
"\u2514":"+", // BOX DRAWINGS LIGHT UP AND RIGHT
"\u2515":"+", // BOX DRAWINGS UP LIGHT AND RIGHT HEAVY
"\u2516":"+", // BOX DRAWINGS UP HEAVY AND RIGHT LIGHT
"\u2517":"+", // BOX DRAWINGS HEAVY UP AND RIGHT
"\u2518":"+", // BOX DRAWINGS LIGHT UP AND LEFT
"\u2519":"+", // BOX DRAWINGS UP LIGHT AND LEFT HEAVY
"\u251A":"+", // BOX DRAWINGS UP HEAVY AND LEFT LIGHT
"\u251B":"+", // BOX DRAWINGS HEAVY UP AND LEFT
"\u251C":"+", // BOX DRAWINGS LIGHT VERTICAL AND RIGHT
"\u251D":"+", // BOX DRAWINGS VERTICAL LIGHT AND RIGHT HEAVY
"\u251E":"+", // BOX DRAWINGS UP HEAVY AND RIGHT DOWN LIGHT
"\u251F":"+", // BOX DRAWINGS DOWN HEAVY AND RIGHT UP LIGHT
"\u2520":"+", // BOX DRAWINGS VERTICAL HEAVY AND RIGHT LIGHT
"\u2521":"+", // BOX DRAWINGS DOWN LIGHT AND RIGHT UP HEAVY
"\u2522":"+", // BOX DRAWINGS UP LIGHT AND RIGHT DOWN HEAVY
"\u2523":"+", // BOX DRAWINGS HEAVY VERTICAL AND RIGHT
"\u2524":"+", // BOX DRAWINGS LIGHT VERTICAL AND LEFT
"\u2525":"+", // BOX DRAWINGS VERTICAL LIGHT AND LEFT HEAVY
"\u2526":"+", // BOX DRAWINGS UP HEAVY AND LEFT DOWN LIGHT
"\u2527":"+", // BOX DRAWINGS DOWN HEAVY AND LEFT UP LIGHT
"\u2528":"+", // BOX DRAWINGS VERTICAL HEAVY AND LEFT LIGHT
"\u2529":"+", // BOX DRAWINGS DOWN LIGHT AND LEFT UP HEAVY
"\u252A":"+", // BOX DRAWINGS UP LIGHT AND LEFT DOWN HEAVY
"\u252B":"+", // BOX DRAWINGS HEAVY VERTICAL AND LEFT
"\u252C":"+", // BOX DRAWINGS LIGHT DOWN AND HORIZONTAL
"\u252D":"+", // BOX DRAWINGS LEFT HEAVY AND RIGHT DOWN LIGHT
"\u252E":"+", // BOX DRAWINGS RIGHT HEAVY AND LEFT DOWN LIGHT
"\u252F":"+", // BOX DRAWINGS DOWN LIGHT AND HORIZONTAL HEAVY
"\u2530":"+", // BOX DRAWINGS DOWN HEAVY AND HORIZONTAL LIGHT
"\u2531":"+", // BOX DRAWINGS RIGHT LIGHT AND LEFT DOWN HEAVY
"\u2532":"+", // BOX DRAWINGS LEFT LIGHT AND RIGHT DOWN HEAVY
"\u2533":"+", // BOX DRAWINGS HEAVY DOWN AND HORIZONTAL
"\u2534":"+", // BOX DRAWINGS LIGHT UP AND HORIZONTAL
"\u2535":"+", // BOX DRAWINGS LEFT HEAVY AND RIGHT UP LIGHT
"\u2536":"+", // BOX DRAWINGS RIGHT HEAVY AND LEFT UP LIGHT
"\u2537":"+", // BOX DRAWINGS UP LIGHT AND HORIZONTAL HEAVY
"\u2538":"+", // BOX DRAWINGS UP HEAVY AND HORIZONTAL LIGHT
"\u2539":"+", // BOX DRAWINGS RIGHT LIGHT AND LEFT UP HEAVY
"\u253A":"+", // BOX DRAWINGS LEFT LIGHT AND RIGHT UP HEAVY
"\u253B":"+", // BOX DRAWINGS HEAVY UP AND HORIZONTAL
"\u253C":"+", // BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL
"\u253D":"+", // BOX DRAWINGS LEFT HEAVY AND RIGHT VERTICAL LIGHT
"\u253E":"+", // BOX DRAWINGS RIGHT HEAVY AND LEFT VERTICAL LIGHT
"\u253F":"+", // BOX DRAWINGS VERTICAL LIGHT AND HORIZONTAL HEAVY
"\u2540":"+", // BOX DRAWINGS UP HEAVY AND DOWN HORIZONTAL LIGHT
"\u2541":"+", // BOX DRAWINGS DOWN HEAVY AND UP HORIZONTAL LIGHT
"\u2542":"+", // BOX DRAWINGS VERTICAL HEAVY AND HORIZONTAL LIGHT
"\u2543":"+", // BOX DRAWINGS LEFT UP HEAVY AND RIGHT DOWN LIGHT
"\u2544":"+", // BOX DRAWINGS RIGHT UP HEAVY AND LEFT DOWN LIGHT
"\u2545":"+", // BOX DRAWINGS LEFT DOWN HEAVY AND RIGHT UP LIGHT
"\u2546":"+", // BOX DRAWINGS RIGHT DOWN HEAVY AND LEFT UP LIGHT
"\u2547":"+", // BOX DRAWINGS DOWN LIGHT AND UP HORIZONTAL HEAVY
"\u2548":"+", // BOX DRAWINGS UP LIGHT AND DOWN HORIZONTAL HEAVY
"\u2549":"+", // BOX DRAWINGS RIGHT LIGHT AND LEFT VERTICAL HEAVY
"\u254A":"+", // BOX DRAWINGS LEFT LIGHT AND RIGHT VERTICAL HEAVY
"\u254B":"+", // BOX DRAWINGS HEAVY VERTICAL AND HORIZONTAL
"\u254C":"-", // BOX DRAWINGS LIGHT DOUBLE DASH HORIZONTAL
"\u254D":"=", // BOX DRAWINGS HEAVY DOUBLE DASH HORIZONTAL
"\u254E":"|", // BOX DRAWINGS LIGHT DOUBLE DASH VERTICAL
"\u254F":"|", // BOX DRAWINGS HEAVY DOUBLE DASH VERTICAL
"\u2550":"=", // BOX DRAWINGS DOUBLE HORIZONTAL
"\u2551":"|", // BOX DRAWINGS DOUBLE VERTICAL
"\u2552":"+", // BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE
"\u2553":"+", // BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE
"\u2554":"+", // BOX DRAWINGS DOUBLE DOWN AND RIGHT
"\u2555":"+", // BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE
"\u2556":"+", // BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE
"\u2557":"+", // BOX DRAWINGS DOUBLE DOWN AND LEFT
"\u2558":"+", // BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE
"\u2559":"+", // BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE
"\u255A":"+", // BOX DRAWINGS DOUBLE UP AND RIGHT
"\u255B":"+", // BOX DRAWINGS UP SINGLE AND LEFT DOUBLE
"\u255C":"+", // BOX DRAWINGS UP DOUBLE AND LEFT SINGLE
"\u255D":"+", // BOX DRAWINGS DOUBLE UP AND LEFT
"\u255E":"+", // BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE
"\u255F":"+", // BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE
"\u2560":"+", // BOX DRAWINGS DOUBLE VERTICAL AND RIGHT
"\u2561":"+", // BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE
"\u2562":"+", // BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE
"\u2563":"+", // BOX DRAWINGS DOUBLE VERTICAL AND LEFT
"\u2564":"+", // BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE
"\u2565":"+", // BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE
"\u2566":"+", // BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL
"\u2567":"+", // BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE
"\u2568":"+", // BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE
"\u2569":"+", // BOX DRAWINGS DOUBLE UP AND HORIZONTAL
"\u256A":"+", // BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE
"\u256B":"+", // BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE
"\u256C":"+", // BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL
"\u256D":"+", // BOX DRAWINGS LIGHT ARC DOWN AND RIGHT
"\u256E":"+", // BOX DRAWINGS LIGHT ARC DOWN AND LEFT
"\u256F":"+", // BOX DRAWINGS LIGHT ARC UP AND LEFT
"\u2570":"+", // BOX DRAWINGS LIGHT ARC UP AND RIGHT
"\u2571":"/", // BOX DRAWINGS LIGHT DIAGONAL UPPER RIGHT TO LOWER LEFT
"\u2572":"\\", // BOX DRAWINGS LIGHT DIAGONAL UPPER LEFT TO LOWER RIGHT
"\u2573":"X", // BOX DRAWINGS LIGHT DIAGONAL CROSS
"\u257C":"-", // BOX DRAWINGS LIGHT LEFT AND HEAVY RIGHT
"\u257D":"|", // BOX DRAWINGS LIGHT UP AND HEAVY DOWN
"\u257E":"-", // BOX DRAWINGS HEAVY LEFT AND LIGHT RIGHT
"\u257F":"|", // BOX DRAWINGS HEAVY UP AND LIGHT DOWN
"\u25CB":"o", // WHITE CIRCLE
"\u25E6":"{\\textopenbullet}", // WHITE BULLET
"\u2605":"*", // BLACK STAR
"\u2606":"*", // WHITE STAR
"\u2612":"X", // BALLOT BOX WITH X
"\u2613":"X", // SALTIRE
"\u2639":":-(", // WHITE FROWNING FACE
"\u263A":":-)", // WHITE SMILING FACE
"\u263B":"(-:", // BLACK SMILING FACE
"\u266D":"b", // MUSIC FLAT SIGN
"\u266F":"$\\#$", // MUSIC SHARP SIGN
"\u2701":"$\\%<$", // UPPER BLADE SCISSORS
"\u2702":"$\\%<$", // BLACK SCISSORS
"\u2703":"$\\%<$", // LOWER BLADE SCISSORS
"\u2704":"$\\%<$", // WHITE SCISSORS
"\u270C":"V", // VICTORY HAND
"\u2713":"v", // CHECK MARK
"\u2714":"V", // HEAVY CHECK MARK
"\u2715":"x", // MULTIPLICATION X
"\u2716":"x", // HEAVY MULTIPLICATION X
"\u2717":"X", // BALLOT X
"\u2718":"X", // HEAVY BALLOT X
"\u2719":"+", // OUTLINED GREEK CROSS
"\u271A":"+", // HEAVY GREEK CROSS
"\u271B":"+", // OPEN CENTRE CROSS
"\u271C":"+", // HEAVY OPEN CENTRE CROSS
"\u271D":"+", // LATIN CROSS
"\u271E":"+", // SHADOWED WHITE LATIN CROSS
"\u271F":"+", // OUTLINED LATIN CROSS
"\u2720":"+", // MALTESE CROSS
"\u2721":"*", // STAR OF DAVID
"\u2722":"+", // FOUR TEARDROP-SPOKED ASTERISK
"\u2723":"+", // FOUR BALLOON-SPOKED ASTERISK
"\u2724":"+", // HEAVY FOUR BALLOON-SPOKED ASTERISK
"\u2725":"+", // FOUR CLUB-SPOKED ASTERISK
"\u2726":"+", // BLACK FOUR POINTED STAR
"\u2727":"+", // WHITE FOUR POINTED STAR
"\u2729":"*", // STRESS OUTLINED WHITE STAR
"\u272A":"*", // CIRCLED WHITE STAR
"\u272B":"*", // OPEN CENTRE BLACK STAR
"\u272C":"*", // BLACK CENTRE WHITE STAR
"\u272D":"*", // OUTLINED BLACK STAR
"\u272E":"*", // HEAVY OUTLINED BLACK STAR
"\u272F":"*", // PINWHEEL STAR
"\u2730":"*", // SHADOWED WHITE STAR
"\u2731":"*", // HEAVY ASTERISK
"\u2732":"*", // OPEN CENTRE ASTERISK
"\u2733":"*", // EIGHT SPOKED ASTERISK
"\u2734":"*", // EIGHT POINTED BLACK STAR
"\u2735":"*", // EIGHT POINTED PINWHEEL STAR
"\u2736":"*", // SIX POINTED BLACK STAR
"\u2737":"*", // EIGHT POINTED RECTILINEAR BLACK STAR
"\u2738":"*", // HEAVY EIGHT POINTED RECTILINEAR BLACK STAR
"\u2739":"*", // TWELVE POINTED BLACK STAR
"\u273A":"*", // SIXTEEN POINTED ASTERISK
"\u273B":"*", // TEARDROP-SPOKED ASTERISK
"\u273C":"*", // OPEN CENTRE TEARDROP-SPOKED ASTERISK
"\u273D":"*", // HEAVY TEARDROP-SPOKED ASTERISK
"\u273E":"*", // SIX PETALLED BLACK AND WHITE FLORETTE
"\u273F":"*", // BLACK FLORETTE
"\u2740":"*", // WHITE FLORETTE
"\u2741":"*", // EIGHT PETALLED OUTLINED BLACK FLORETTE
"\u2742":"*", // CIRCLED OPEN CENTRE EIGHT POINTED STAR
"\u2743":"*", // HEAVY TEARDROP-SPOKED PINWHEEL ASTERISK
"\u2744":"*", // SNOWFLAKE
"\u2745":"*", // TIGHT TRIFOLIATE SNOWFLAKE
"\u2746":"*", // HEAVY CHEVRON SNOWFLAKE
"\u2747":"*", // SPARKLE
"\u2748":"*", // HEAVY SPARKLE
"\u2749":"*", // BALLOON-SPOKED ASTERISK
"\u274A":"*", // EIGHT TEARDROP-SPOKED PROPELLER ASTERISK
"\u274B":"*", // HEAVY EIGHT TEARDROP-SPOKED PROPELLER ASTERISK
"\uFB00":"ff", // LATIN SMALL LIGATURE FF
"\uFB01":"fi", // LATIN SMALL LIGATURE FI
"\uFB02":"fl", // LATIN SMALL LIGATURE FL
"\uFB03":"ffi", // LATIN SMALL LIGATURE FFI
"\uFB04":"ffl", // LATIN SMALL LIGATURE FFL
"\uFB05":"st", // LATIN SMALL LIGATURE LONG S T
"\uFB06":"st", // LATIN SMALL LIGATURE ST
/* Derived accented characters */
"\u00C0":"\\`{A}", // LATIN CAPITAL LETTER A WITH GRAVE
"\u00C1":"\\'{A}", // LATIN CAPITAL LETTER A WITH ACUTE
"\u00C2":"\\^{A}", // LATIN CAPITAL LETTER A WITH CIRCUMFLEX
"\u00C3":"\\~{A}", // LATIN CAPITAL LETTER A WITH TILDE
"\u00C4":"\\\"{A}", // LATIN CAPITAL LETTER A WITH DIAERESIS
"\u00C5":"\\r{A}", // LATIN CAPITAL LETTER A WITH RING ABOVE
"\u00C7":"\\c{C}", // LATIN CAPITAL LETTER C WITH CEDILLA
"\u00C8":"\\`{E}", // LATIN CAPITAL LETTER E WITH GRAVE
"\u00C9":"\\'{E}", // LATIN CAPITAL LETTER E WITH ACUTE
"\u00CA":"\\^{E}", // LATIN CAPITAL LETTER E WITH CIRCUMFLEX
"\u00CB":"\\\"{E}", // LATIN CAPITAL LETTER E WITH DIAERESIS
"\u00CC":"\\`{I}", // LATIN CAPITAL LETTER I WITH GRAVE
"\u00CD":"\\'{I}", // LATIN CAPITAL LETTER I WITH ACUTE
"\u00CE":"\\^{I}", // LATIN CAPITAL LETTER I WITH CIRCUMFLEX
"\u00CF":"\\\"{I}", // LATIN CAPITAL LETTER I WITH DIAERESIS
"\u00D1":"\\~{N}", // LATIN CAPITAL LETTER N WITH TILDE
"\u00D2":"\\`{O}", // LATIN CAPITAL LETTER O WITH GRAVE
"\u00D3":"\\'{O}", // LATIN CAPITAL LETTER O WITH ACUTE
"\u00D4":"\\^{O}", // LATIN CAPITAL LETTER O WITH CIRCUMFLEX
"\u00D5":"\\~{O}", // LATIN CAPITAL LETTER O WITH TILDE
"\u00D6":"\\\"{O}", // LATIN CAPITAL LETTER O WITH DIAERESIS
"\u00D9":"\\`{U}", // LATIN CAPITAL LETTER U WITH GRAVE
"\u00DA":"\\'{U}", // LATIN CAPITAL LETTER U WITH ACUTE
"\u00DB":"\\^{U}", // LATIN CAPITAL LETTER U WITH CIRCUMFLEX
"\u00DC":"\\\"{U}", // LATIN CAPITAL LETTER U WITH DIAERESIS
"\u00DD":"\\'{Y}", // LATIN CAPITAL LETTER Y WITH ACUTE
"\u00E0":"\\`{a}", // LATIN SMALL LETTER A WITH GRAVE
"\u00E1":"\\'{a}", // LATIN SMALL LETTER A WITH ACUTE
"\u00E2":"\\^{a}", // LATIN SMALL LETTER A WITH CIRCUMFLEX
"\u00E3":"\\~{a}", // LATIN SMALL LETTER A WITH TILDE
"\u00E4":"\\\"{a}", // LATIN SMALL LETTER A WITH DIAERESIS
"\u00E5":"\\r{a}", // LATIN SMALL LETTER A WITH RING ABOVE
"\u00E7":"\\c{c}", // LATIN SMALL LETTER C WITH CEDILLA
"\u00E8":"\\`{e}", // LATIN SMALL LETTER E WITH GRAVE
"\u00E9":"\\'{e}", // LATIN SMALL LETTER E WITH ACUTE
"\u00EA":"\\^{e}", // LATIN SMALL LETTER E WITH CIRCUMFLEX
"\u00EB":"\\\"{e}", // LATIN SMALL LETTER E WITH DIAERESIS
"\u00EC":"\\`{i}", // LATIN SMALL LETTER I WITH GRAVE
"\u00ED":"\\'{i}", // LATIN SMALL LETTER I WITH ACUTE
"\u00EE":"\\^{i}", // LATIN SMALL LETTER I WITH CIRCUMFLEX
"\u00EF":"\\\"{i}", // LATIN SMALL LETTER I WITH DIAERESIS
"\u00F1":"\\~{n}", // LATIN SMALL LETTER N WITH TILDE
"\u00F2":"\\`{o}", // LATIN SMALL LETTER O WITH GRAVE
"\u00F3":"\\'{o}", // LATIN SMALL LETTER O WITH ACUTE
"\u00F4":"\\^{o}", // LATIN SMALL LETTER O WITH CIRCUMFLEX
"\u00F5":"\\~{o}", // LATIN SMALL LETTER O WITH TILDE
"\u00F6":"\\\"{o}", // LATIN SMALL LETTER O WITH DIAERESIS
"\u00F9":"\\`{u}", // LATIN SMALL LETTER U WITH GRAVE
"\u00FA":"\\'{u}", // LATIN SMALL LETTER U WITH ACUTE
"\u00FB":"\\^{u}", // LATIN SMALL LETTER U WITH CIRCUMFLEX
"\u00FC":"\\\"{u}", // LATIN SMALL LETTER U WITH DIAERESIS
"\u00FD":"\\'{y}", // LATIN SMALL LETTER Y WITH ACUTE
"\u00FF":"\\\"{y}", // LATIN SMALL LETTER Y WITH DIAERESIS
"\u0100":"\\={A}", // LATIN CAPITAL LETTER A WITH MACRON
"\u0101":"\\={a}", // LATIN SMALL LETTER A WITH MACRON
"\u0102":"\\u{A}", // LATIN CAPITAL LETTER A WITH BREVE
"\u0103":"\\u{a}", // LATIN SMALL LETTER A WITH BREVE
"\u0104":"\\k{A}", // LATIN CAPITAL LETTER A WITH OGONEK
"\u0105":"\\k{a}", // LATIN SMALL LETTER A WITH OGONEK
"\u0106":"\\'{C}", // LATIN CAPITAL LETTER C WITH ACUTE
"\u0107":"\\'{c}", // LATIN SMALL LETTER C WITH ACUTE
"\u0108":"\\^{C}", // LATIN CAPITAL LETTER C WITH CIRCUMFLEX
"\u0109":"\\^{c}", // LATIN SMALL LETTER C WITH CIRCUMFLEX
"\u010A":"\\.{C}", // LATIN CAPITAL LETTER C WITH DOT ABOVE
"\u010B":"\\.{c}", // LATIN SMALL LETTER C WITH DOT ABOVE
"\u010C":"\\v{C}", // LATIN CAPITAL LETTER C WITH CARON
"\u010D":"\\v{c}", // LATIN SMALL LETTER C WITH CARON
"\u010E":"\\v{D}", // LATIN CAPITAL LETTER D WITH CARON
"\u010F":"\\v{d}", // LATIN SMALL LETTER D WITH CARON
"\u0112":"\\={E}", // LATIN CAPITAL LETTER E WITH MACRON
"\u0113":"\\={e}", // LATIN SMALL LETTER E WITH MACRON
"\u0114":"\\u{E}", // LATIN CAPITAL LETTER E WITH BREVE
"\u0115":"\\u{e}", // LATIN SMALL LETTER E WITH BREVE
"\u0116":"\\.{E}", // LATIN CAPITAL LETTER E WITH DOT ABOVE
"\u0117":"\\.{e}", // LATIN SMALL LETTER E WITH DOT ABOVE
"\u0118":"\\k{E}", // LATIN CAPITAL LETTER E WITH OGONEK
"\u0119":"\\k{e}", // LATIN SMALL LETTER E WITH OGONEK
"\u011A":"\\v{E}", // LATIN CAPITAL LETTER E WITH CARON
"\u011B":"\\v{e}", // LATIN SMALL LETTER E WITH CARON
"\u011C":"\\^{G}", // LATIN CAPITAL LETTER G WITH CIRCUMFLEX
"\u011D":"\\^{g}", // LATIN SMALL LETTER G WITH CIRCUMFLEX
"\u011E":"\\u{G}", // LATIN CAPITAL LETTER G WITH BREVE
"\u011F":"\\u{g}", // LATIN SMALL LETTER G WITH BREVE
"\u0120":"\\.{G}", // LATIN CAPITAL LETTER G WITH DOT ABOVE
"\u0121":"\\.{g}", // LATIN SMALL LETTER G WITH DOT ABOVE
"\u0122":"\\c{G}", // LATIN CAPITAL LETTER G WITH CEDILLA
"\u0123":"\\c{g}", // LATIN SMALL LETTER G WITH CEDILLA
"\u0124":"\\^{H}", // LATIN CAPITAL LETTER H WITH CIRCUMFLEX
"\u0125":"\\^{h}", // LATIN SMALL LETTER H WITH CIRCUMFLEX
"\u0128":"\\~{I}", // LATIN CAPITAL LETTER I WITH TILDE
"\u0129":"\\~{i}", // LATIN SMALL LETTER I WITH TILDE
"\u012A":"\\={I}", // LATIN CAPITAL LETTER I WITH MACRON
"\u012B":"\\={i}", // LATIN SMALL LETTER I WITH MACRON
"\u012C":"\\u{I}", // LATIN CAPITAL LETTER I WITH BREVE
"\u012D":"\\u{i}", // LATIN SMALL LETTER I WITH BREVE
"\u012E":"\\k{I}", // LATIN CAPITAL LETTER I WITH OGONEK
"\u012F":"\\k{i}", // LATIN SMALL LETTER I WITH OGONEK
"\u0130":"\\.{I}", // LATIN CAPITAL LETTER I WITH DOT ABOVE
"\u0134":"\\^{J}", // LATIN CAPITAL LETTER J WITH CIRCUMFLEX
"\u0135":"\\^{j}", // LATIN SMALL LETTER J WITH CIRCUMFLEX
"\u0136":"\\c{K}", // LATIN CAPITAL LETTER K WITH CEDILLA
"\u0137":"\\c{k}", // LATIN SMALL LETTER K WITH CEDILLA
"\u0139":"\\'{L}", // LATIN CAPITAL LETTER L WITH ACUTE
"\u013A":"\\'{l}", // LATIN SMALL LETTER L WITH ACUTE
"\u013B":"\\c{L}", // LATIN CAPITAL LETTER L WITH CEDILLA
"\u013C":"\\c{l}", // LATIN SMALL LETTER L WITH CEDILLA
"\u013D":"\\v{L}", // LATIN CAPITAL LETTER L WITH CARON
"\u013E":"\\v{l}", // LATIN SMALL LETTER L WITH CARON
"\u0141":"\\L{}", //LATIN CAPITAL LETTER L WITH STROKE
"\u0142":"\\l{}", //LATIN SMALL LETTER L WITH STROKE
"\u0143":"\\'{N}", // LATIN CAPITAL LETTER N WITH ACUTE
"\u0144":"\\'{n}", // LATIN SMALL LETTER N WITH ACUTE
"\u0145":"\\c{N}", // LATIN CAPITAL LETTER N WITH CEDILLA
"\u0146":"\\c{n}", // LATIN SMALL LETTER N WITH CEDILLA
"\u0147":"\\v{N}", // LATIN CAPITAL LETTER N WITH CARON
"\u0148":"\\v{n}", // LATIN SMALL LETTER N WITH CARON
"\u014C":"\\={O}", // LATIN CAPITAL LETTER O WITH MACRON
"\u014D":"\\={o}", // LATIN SMALL LETTER O WITH MACRON
"\u014E":"\\u{O}", // LATIN CAPITAL LETTER O WITH BREVE
"\u014F":"\\u{o}", // LATIN SMALL LETTER O WITH BREVE
"\u0150":"\\H{O}", // LATIN CAPITAL LETTER O WITH DOUBLE ACUTE
"\u0151":"\\H{o}", // LATIN SMALL LETTER O WITH DOUBLE ACUTE
"\u0154":"\\'{R}", // LATIN CAPITAL LETTER R WITH ACUTE
"\u0155":"\\'{r}", // LATIN SMALL LETTER R WITH ACUTE
"\u0156":"\\c{R}", // LATIN CAPITAL LETTER R WITH CEDILLA
"\u0157":"\\c{r}", // LATIN SMALL LETTER R WITH CEDILLA
"\u0158":"\\v{R}", // LATIN CAPITAL LETTER R WITH CARON
"\u0159":"\\v{r}", // LATIN SMALL LETTER R WITH CARON
"\u015A":"\\'{S}", // LATIN CAPITAL LETTER S WITH ACUTE
"\u015B":"\\'{s}", // LATIN SMALL LETTER S WITH ACUTE
"\u015C":"\\^{S}", // LATIN CAPITAL LETTER S WITH CIRCUMFLEX
"\u015D":"\\^{s}", // LATIN SMALL LETTER S WITH CIRCUMFLEX
"\u015E":"\\c{S}", // LATIN CAPITAL LETTER S WITH CEDILLA
"\u015F":"\\c{s}", // LATIN SMALL LETTER S WITH CEDILLA
"\u0160":"\\v{S}", // LATIN CAPITAL LETTER S WITH CARON
"\u0161":"\\v{s}", // LATIN SMALL LETTER S WITH CARON
"\u0162":"\\c{T}", // LATIN CAPITAL LETTER T WITH CEDILLA
"\u0163":"\\c{t}", // LATIN SMALL LETTER T WITH CEDILLA
"\u0164":"\\v{T}", // LATIN CAPITAL LETTER T WITH CARON
"\u0165":"\\v{t}", // LATIN SMALL LETTER T WITH CARON
"\u0168":"\\~{U}", // LATIN CAPITAL LETTER U WITH TILDE
"\u0169":"\\~{u}", // LATIN SMALL LETTER U WITH TILDE
"\u016A":"\\={U}", // LATIN CAPITAL LETTER U WITH MACRON
"\u016B":"\\={u}", // LATIN SMALL LETTER U WITH MACRON
"\u016C":"\\u{U}", // LATIN CAPITAL LETTER U WITH BREVE
"\u016D":"\\u{u}", // LATIN SMALL LETTER U WITH BREVE
"\u0170":"\\H{U}", // LATIN CAPITAL LETTER U WITH DOUBLE ACUTE
"\u0171":"\\H{u}", // LATIN SMALL LETTER U WITH DOUBLE ACUTE
"\u0172":"\\k{U}", // LATIN CAPITAL LETTER U WITH OGONEK
"\u0173":"\\k{u}", // LATIN SMALL LETTER U WITH OGONEK
"\u0174":"\\^{W}", // LATIN CAPITAL LETTER W WITH CIRCUMFLEX
"\u0175":"\\^{w}", // LATIN SMALL LETTER W WITH CIRCUMFLEX
"\u0176":"\\^{Y}", // LATIN CAPITAL LETTER Y WITH CIRCUMFLEX
"\u0177":"\\^{y}", // LATIN SMALL LETTER Y WITH CIRCUMFLEX
"\u0178":"\\\"{Y}", // LATIN CAPITAL LETTER Y WITH DIAERESIS
"\u0179":"\\'{Z}", // LATIN CAPITAL LETTER Z WITH ACUTE
"\u017A":"\\'{z}", // LATIN SMALL LETTER Z WITH ACUTE
"\u017B":"\\.{Z}", // LATIN CAPITAL LETTER Z WITH DOT ABOVE
"\u017C":"\\.{z}", // LATIN SMALL LETTER Z WITH DOT ABOVE
"\u017D":"\\v{Z}", // LATIN CAPITAL LETTER Z WITH CARON
"\u017E":"\\v{z}", // LATIN SMALL LETTER Z WITH CARON
"\u01CD":"\\v{A}", // LATIN CAPITAL LETTER A WITH CARON
"\u01CE":"\\v{a}", // LATIN SMALL LETTER A WITH CARON
"\u01CF":"\\v{I}", // LATIN CAPITAL LETTER I WITH CARON
"\u01D0":"\\v{i}", // LATIN SMALL LETTER I WITH CARON
"\u01D1":"\\v{O}", // LATIN CAPITAL LETTER O WITH CARON
"\u01D2":"\\v{o}", // LATIN SMALL LETTER O WITH CARON
"\u01D3":"\\v{U}", // LATIN CAPITAL LETTER U WITH CARON
"\u01D4":"\\v{u}", // LATIN SMALL LETTER U WITH CARON
"\u01E6":"\\v{G}", // LATIN CAPITAL LETTER G WITH CARON
"\u01E7":"\\v{g}", // LATIN SMALL LETTER G WITH CARON
"\u01E8":"\\v{K}", // LATIN CAPITAL LETTER K WITH CARON
"\u01E9":"\\v{k}", // LATIN SMALL LETTER K WITH CARON
"\u01EA":"\\k{O}", // LATIN CAPITAL LETTER O WITH OGONEK
"\u01EB":"\\k{o}", // LATIN SMALL LETTER O WITH OGONEK
"\u01F0":"\\v{j}", // LATIN SMALL LETTER J WITH CARON
"\u01F4":"\\'{G}", // LATIN CAPITAL LETTER G WITH ACUTE
"\u01F5":"\\'{g}", // LATIN SMALL LETTER G WITH ACUTE
"\u1E02":"\\.{B}", // LATIN CAPITAL LETTER B WITH DOT ABOVE
"\u1E03":"\\.{b}", // LATIN SMALL LETTER B WITH DOT ABOVE
"\u1E04":"\\d{B}", // LATIN CAPITAL LETTER B WITH DOT BELOW
"\u1E05":"\\d{b}", // LATIN SMALL LETTER B WITH DOT BELOW
"\u1E06":"\\b{B}", // LATIN CAPITAL LETTER B WITH LINE BELOW
"\u1E07":"\\b{b}", // LATIN SMALL LETTER B WITH LINE BELOW
"\u1E0A":"\\.{D}", // LATIN CAPITAL LETTER D WITH DOT ABOVE
"\u1E0B":"\\.{d}", // LATIN SMALL LETTER D WITH DOT ABOVE
"\u1E0C":"\\d{D}", // LATIN CAPITAL LETTER D WITH DOT BELOW
"\u1E0D":"\\d{d}", // LATIN SMALL LETTER D WITH DOT BELOW
"\u1E0E":"\\b{D}", // LATIN CAPITAL LETTER D WITH LINE BELOW
"\u1E0F":"\\b{d}", // LATIN SMALL LETTER D WITH LINE BELOW
"\u1E10":"\\c{D}", // LATIN CAPITAL LETTER D WITH CEDILLA
"\u1E11":"\\c{d}", // LATIN SMALL LETTER D WITH CEDILLA
"\u1E1E":"\\.{F}", // LATIN CAPITAL LETTER F WITH DOT ABOVE
"\u1E1F":"\\.{f}", // LATIN SMALL LETTER F WITH DOT ABOVE
"\u1E20":"\\={G}", // LATIN CAPITAL LETTER G WITH MACRON
"\u1E21":"\\={g}", // LATIN SMALL LETTER G WITH MACRON
"\u1E22":"\\.{H}", // LATIN CAPITAL LETTER H WITH DOT ABOVE
"\u1E23":"\\.{h}", // LATIN SMALL LETTER H WITH DOT ABOVE
"\u1E24":"\\d{H}", // LATIN CAPITAL LETTER H WITH DOT BELOW
"\u1E25":"\\d{h}", // LATIN SMALL LETTER H WITH DOT BELOW
"\u1E26":"\\\"{H}", // LATIN CAPITAL LETTER H WITH DIAERESIS
"\u1E27":"\\\"{h}", // LATIN SMALL LETTER H WITH DIAERESIS
"\u1E28":"\\c{H}", // LATIN CAPITAL LETTER H WITH CEDILLA
"\u1E29":"\\c{h}", // LATIN SMALL LETTER H WITH CEDILLA
"\u1E30":"\\'{K}", // LATIN CAPITAL LETTER K WITH ACUTE
"\u1E31":"\\'{k}", // LATIN SMALL LETTER K WITH ACUTE
"\u1E32":"\\d{K}", // LATIN CAPITAL LETTER K WITH DOT BELOW
"\u1E33":"\\d{k}", // LATIN SMALL LETTER K WITH DOT BELOW
"\u1E34":"\\b{K}", // LATIN CAPITAL LETTER K WITH LINE BELOW
"\u1E35":"\\b{k}", // LATIN SMALL LETTER K WITH LINE BELOW
"\u1E36":"\\d{L}", // LATIN CAPITAL LETTER L WITH DOT BELOW
"\u1E37":"\\d{l}", // LATIN SMALL LETTER L WITH DOT BELOW
"\u1E3A":"\\b{L}", // LATIN CAPITAL LETTER L WITH LINE BELOW
"\u1E3B":"\\b{l}", // LATIN SMALL LETTER L WITH LINE BELOW
"\u1E3E":"\\'{M}", // LATIN CAPITAL LETTER M WITH ACUTE
"\u1E3F":"\\'{m}", // LATIN SMALL LETTER M WITH ACUTE
"\u1E40":"\\.{M}", // LATIN CAPITAL LETTER M WITH DOT ABOVE
"\u1E41":"\\.{m}", // LATIN SMALL LETTER M WITH DOT ABOVE
"\u1E42":"\\d{M}", // LATIN CAPITAL LETTER M WITH DOT BELOW
"\u1E43":"\\d{m}", // LATIN SMALL LETTER M WITH DOT BELOW
"\u1E44":"\\.{N}", // LATIN CAPITAL LETTER N WITH DOT ABOVE
"\u1E45":"\\.{n}", // LATIN SMALL LETTER N WITH DOT ABOVE
"\u1E46":"\\d{N}", // LATIN CAPITAL LETTER N WITH DOT BELOW
"\u1E47":"\\d{n}", // LATIN SMALL LETTER N WITH DOT BELOW
"\u1E48":"\\b{N}", // LATIN CAPITAL LETTER N WITH LINE BELOW
"\u1E49":"\\b{n}", // LATIN SMALL LETTER N WITH LINE BELOW
"\u1E54":"\\'{P}", // LATIN CAPITAL LETTER P WITH ACUTE
"\u1E55":"\\'{p}", // LATIN SMALL LETTER P WITH ACUTE
"\u1E56":"\\.{P}", // LATIN CAPITAL LETTER P WITH DOT ABOVE
"\u1E57":"\\.{p}", // LATIN SMALL LETTER P WITH DOT ABOVE
"\u1E58":"\\.{R}", // LATIN CAPITAL LETTER R WITH DOT ABOVE
"\u1E59":"\\.{r}", // LATIN SMALL LETTER R WITH DOT ABOVE
"\u1E5A":"\\d{R}", // LATIN CAPITAL LETTER R WITH DOT BELOW
"\u1E5B":"\\d{r}", // LATIN SMALL LETTER R WITH DOT BELOW
"\u1E5E":"\\b{R}", // LATIN CAPITAL LETTER R WITH LINE BELOW
"\u1E5F":"\\b{r}", // LATIN SMALL LETTER R WITH LINE BELOW
"\u1E60":"\\.{S}", // LATIN CAPITAL LETTER S WITH DOT ABOVE
"\u1E61":"\\.{s}", // LATIN SMALL LETTER S WITH DOT ABOVE
"\u1E62":"\\d{S}", // LATIN CAPITAL LETTER S WITH DOT BELOW
"\u1E63":"\\d{s}", // LATIN SMALL LETTER S WITH DOT BELOW
"\u1E6A":"\\.{T}", // LATIN CAPITAL LETTER T WITH DOT ABOVE
"\u1E6B":"\\.{t}", // LATIN SMALL LETTER T WITH DOT ABOVE
"\u1E6C":"\\d{T}", // LATIN CAPITAL LETTER T WITH DOT BELOW
"\u1E6D":"\\d{t}", // LATIN SMALL LETTER T WITH DOT BELOW
"\u1E6E":"\\b{T}", // LATIN CAPITAL LETTER T WITH LINE BELOW
"\u1E6F":"\\b{t}", // LATIN SMALL LETTER T WITH LINE BELOW
"\u1E7C":"\\~{V}", // LATIN CAPITAL LETTER V WITH TILDE
"\u1E7D":"\\~{v}", // LATIN SMALL LETTER V WITH TILDE
"\u1E7E":"\\d{V}", // LATIN CAPITAL LETTER V WITH DOT BELOW
"\u1E7F":"\\d{v}", // LATIN SMALL LETTER V WITH DOT BELOW
"\u1E80":"\\`{W}", // LATIN CAPITAL LETTER W WITH GRAVE
"\u1E81":"\\`{w}", // LATIN SMALL LETTER W WITH GRAVE
"\u1E82":"\\'{W}", // LATIN CAPITAL LETTER W WITH ACUTE
"\u1E83":"\\'{w}", // LATIN SMALL LETTER W WITH ACUTE
"\u1E84":"\\\"{W}", // LATIN CAPITAL LETTER W WITH DIAERESIS
"\u1E85":"\\\"{w}", // LATIN SMALL LETTER W WITH DIAERESIS
"\u1E86":"\\.{W}", // LATIN CAPITAL LETTER W WITH DOT ABOVE
"\u1E87":"\\.{w}", // LATIN SMALL LETTER W WITH DOT ABOVE
"\u1E88":"\\d{W}", // LATIN CAPITAL LETTER W WITH DOT BELOW
"\u1E89":"\\d{w}", // LATIN SMALL LETTER W WITH DOT BELOW
"\u1E8A":"\\.{X}", // LATIN CAPITAL LETTER X WITH DOT ABOVE
"\u1E8B":"\\.{x}", // LATIN SMALL LETTER X WITH DOT ABOVE
"\u1E8C":"\\\"{X}", // LATIN CAPITAL LETTER X WITH DIAERESIS
"\u1E8D":"\\\"{x}", // LATIN SMALL LETTER X WITH DIAERESIS
"\u1E8E":"\\.{Y}", // LATIN CAPITAL LETTER Y WITH DOT ABOVE
"\u1E8F":"\\.{y}", // LATIN SMALL LETTER Y WITH DOT ABOVE
"\u1E90":"\\^{Z}", // LATIN CAPITAL LETTER Z WITH CIRCUMFLEX
"\u1E91":"\\^{z}", // LATIN SMALL LETTER Z WITH CIRCUMFLEX
"\u1E92":"\\d{Z}", // LATIN CAPITAL LETTER Z WITH DOT BELOW
"\u1E93":"\\d{z}", // LATIN SMALL LETTER Z WITH DOT BELOW
"\u1E94":"\\b{Z}", // LATIN CAPITAL LETTER Z WITH LINE BELOW
"\u1E95":"\\b{z}", // LATIN SMALL LETTER Z WITH LINE BELOW
"\u1E96":"\\b{h}", // LATIN SMALL LETTER H WITH LINE BELOW
"\u1E97":"\\\"{t}", // LATIN SMALL LETTER T WITH DIAERESIS
"\u1EA0":"\\d{A}", // LATIN CAPITAL LETTER A WITH DOT BELOW
"\u1EA1":"\\d{a}", // LATIN SMALL LETTER A WITH DOT BELOW
"\u1EB8":"\\d{E}", // LATIN CAPITAL LETTER E WITH DOT BELOW
"\u1EB9":"\\d{e}", // LATIN SMALL LETTER E WITH DOT BELOW
"\u1EBC":"\\~{E}", // LATIN CAPITAL LETTER E WITH TILDE
"\u1EBD":"\\~{e}", // LATIN SMALL LETTER E WITH TILDE
"\u1ECA":"\\d{I}", // LATIN CAPITAL LETTER I WITH DOT BELOW
"\u1ECB":"\\d{i}", // LATIN SMALL LETTER I WITH DOT BELOW
"\u1ECC":"\\d{O}", // LATIN CAPITAL LETTER O WITH DOT BELOW
"\u1ECD":"\\d{o}", // LATIN SMALL LETTER O WITH DOT BELOW
"\u1EE4":"\\d{U}", // LATIN CAPITAL LETTER U WITH DOT BELOW
"\u1EE5":"\\d{u}", // LATIN SMALL LETTER U WITH DOT BELOW
"\u1EF2":"\\`{Y}", // LATIN CAPITAL LETTER Y WITH GRAVE
"\u1EF3":"\\`{y}", // LATIN SMALL LETTER Y WITH GRAVE
"\u1EF4":"\\d{Y}", // LATIN CAPITAL LETTER Y WITH DOT BELOW
"\u1EF5":"\\d{y}", // LATIN SMALL LETTER Y WITH DOT BELOW
"\u1EF8":"\\~{Y}", // LATIN CAPITAL LETTER Y WITH TILDE
"\u1EF9":"\\~{y}" // LATIN SMALL LETTER Y WITH TILDE
};
/* unfortunately the mapping isn't reversible - hence this second table - sigh! */
var reversemappingTable = {
"\\url" : "", // strip 'url'
"\\href" : "", // strip 'href'
"{\\textexclamdown}" : "\u00A1", // INVERTED EXCLAMATION MARK
"{\\textcent}" : "\u00A2", // CENT SIGN
"{\\textsterling}" : "\u00A3", // POUND SIGN
"{\\textyen}" : "\u00A5", // YEN SIGN
"{\\textbrokenbar}" : "\u00A6", // BROKEN BAR
"{\\textsection}" : "\u00A7", // SECTION SIGN
"{\\textasciidieresis}" : "\u00A8", // DIAERESIS
"{\\textcopyright}" : "\u00A9", // COPYRIGHT SIGN
"{\\textordfeminine}" : "\u00AA", // FEMININE ORDINAL INDICATOR
"{\\guillemotleft}" : "\u00AB", // LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
"{\\textlnot}" : "\u00AC", // NOT SIGN
"{\\textregistered}" : "\u00AE", // REGISTERED SIGN
"{\\textasciimacron}" : "\u00AF", // MACRON
"{\\textdegree}" : "\u00B0", // DEGREE SIGN
"{\\textpm}" : "\u00B1", // PLUS-MINUS SIGN
"{\\texttwosuperior}" : "\u00B2", // SUPERSCRIPT TWO
"{\\textthreesuperior}" : "\u00B3", // SUPERSCRIPT THREE
"{\\textasciiacute}" : "\u00B4", // ACUTE ACCENT
"{\\textmu}" : "\u00B5", // MICRO SIGN
"{\\textparagraph}" : "\u00B6", // PILCROW SIGN
"{\\textperiodcentered}" : "\u00B7", // MIDDLE DOT
"{\\c\\ }" : "\u00B8", // CEDILLA
"{\\textonesuperior}" : "\u00B9", // SUPERSCRIPT ONE
"{\\textordmasculine}" : "\u00BA", // MASCULINE ORDINAL INDICATOR
"{\\guillemotright}" : "\u00BB", // RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
"{\\textonequarter}" : "\u00BC", // VULGAR FRACTION ONE QUARTER
"{\\textonehalf}" : "\u00BD", // VULGAR FRACTION ONE HALF
"{\\textthreequarters}" : "\u00BE", // VULGAR FRACTION THREE QUARTERS
"{\\textquestiondown}" : "\u00BF", // INVERTED QUESTION MARK
"{\\AE}" : "\u00C6", // LATIN CAPITAL LETTER AE
"{\\DH}" : "\u00D0", // LATIN CAPITAL LETTER ETH
"{\\texttimes}" : "\u00D7", // MULTIPLICATION SIGN
"{\\O}" : "\U00D8", // LATIN SMALL LETTER O WITH STROKE
"{\\TH}" : "\u00DE", // LATIN CAPITAL LETTER THORN
"{\\ss}" : "\u00DF", // LATIN SMALL LETTER SHARP S
"{\\ae}" : "\u00E6", // LATIN SMALL LETTER AE
"{\\dh}" : "\u00F0", // LATIN SMALL LETTER ETH
"{\\textdiv}" : "\u00F7", // DIVISION SIGN
"{\\o}" : "\U00F8", // LATIN SMALL LETTER O WITH STROKE
"{\\th}" : "\u00FE", // LATIN SMALL LETTER THORN
"{\\i}" : "\u0131", // LATIN SMALL LETTER DOTLESS I
"'n" : "\u0149", // LATIN SMALL LETTER N PRECEDED BY APOSTROPHE
"{\\NG}" : "\u014A", // LATIN CAPITAL LETTER ENG
"{\\ng}" : "\u014B", // LATIN SMALL LETTER ENG
"{\\OE}" : "\u0152", // LATIN CAPITAL LIGATURE OE
"{\\oe}" : "\u0153", // LATIN SMALL LIGATURE OE
"{\\textasciicircum}" : "\u02C6", // MODIFIER LETTER CIRCUMFLEX ACCENT
// "\\~{}" : "\u02DC", // SMALL TILDE
"{\\textacutedbl}" : "\u02DD", // DOUBLE ACUTE ACCENT
// -- Tan -begin greek symbols
"$\\Gamma$" : "\u0393", // GREEK Gamma
"$\\Delta$" : "\u0394", // GREEK Delta
"$\\Theta$" : "\u0398", // GREEK Theta
"$\\Lambda$" : "\u039B", // GREEK Lambda
"$\\Xi$" : "\u039E", // GREEK Xi
"$\\Pi$" : "\u03A0", // GREEK Pi
"$\\Sigma$" : "\u03A3", // GREEK Sigma
"$\\Phi$" : "\u03A6", // GREEK Phi
"$\\Psi$" : "\u03A8", // GREEK Psi
"$\\Omega$" : "\u03A9", // GREEK Omega
"$\\alpha$" : "\u03B1", // GREEK alpha
"$\\beta$" : "\u03B2", // GREEK beta
"$\\gamma$" : "\u03B3", // GREEK gamma
"$\\delta$" : "\u03B4", // GREEK delta
"$\\varepsilon$": "\u03B5", // GREEK var-epsilon
"$\\zeta$" : "\u03B6", // GREEK zeta
"$\\eta$" : "\u03B7", // GREEK eta
"$\\theta$" : "\u03B8", // GREEK theta
"$\\iota$" : "\u03B9", // GREEK iota
"$\\kappa$" : "\u03BA", // GREEK kappa
"$\\lambda$" : "\u03BB", // GREEK lambda
"$\\mu$" : "\u03BC", // GREEK mu
"$\\nu$" : "\u03BD", // GREEK nu
"$\\xi$" : "\u03BE", // GREEK xi
"$\\pi$" : "\u03C0", // GREEK pi
"$\\rho$" : "\u03C1", // GREEK rho
"$\\varsigma$" : "\u03C2", // GREEK var-sigma
"$\\sigma$" : "\u03C3", // GREEK sigma
"$\\tau$" : "\u03C4", // GREEK tau
"$\\upsilon$" : "\u03C5", // GREEK upsilon
"$\\varphi$" : "\u03C6", // GREEK var-phi
"$\\chi$" : "\u03C7", // GREEK chi
"$\\psi$" : "\u03C8", // GREEK psi
"$\\omega$" : "\u03C9", // GREEK omega
"$\\vartheta$" : "\u03D1", // GREEK var-theta
"$\\Upsilon$" : "\u03D2", // GREEK Upsilon
"$\\phi$" : "\u03D5", // GREEK phi
"$\\varpi$" : "\u03D6", // GREEK var-pi
"$\\varrho$" : "\u03F1", // GREEK var-rho
"$\\epsilon$" : "\u03F5", // GREEK epsilon
// -- Tan -end greek symbols
"{\\textendash}" : "\u2013", // EN DASH
"{\\textemdash}" : "\u2014", // EM DASH
"---" : "\u2014", // EM DASH
"--" : "\u2013", // EN DASH
"{\\textbardbl}" : "\u2016", // DOUBLE VERTICAL LINE
"{\\textunderscore}" : "\u2017", // DOUBLE LOW LINE
"{\\textquoteleft}" : "\u2018", // LEFT SINGLE QUOTATION MARK
"{\\textquoteright}" : "\u2019", // RIGHT SINGLE QUOTATION MARK
"{\\quotesinglbase}" : "\u201A", // SINGLE LOW-9 QUOTATION MARK
"{\\textquotedblleft}" : "\u201C", // LEFT DOUBLE QUOTATION MARK
"{\\textquotedblright}" : "\u201D", // RIGHT DOUBLE QUOTATION MARK
"{\\quotedblbase}" : "\u201E", // DOUBLE LOW-9 QUOTATION MARK
// "{\\quotedblbase}" : "\u201F", // DOUBLE HIGH-REVERSED-9 QUOTATION MARK
"{\\textdagger}" : "\u2020", // DAGGER
"{\\textdaggerdbl}" : "\u2021", // DOUBLE DAGGER
"{\\textbullet}" : "\u2022", // BULLET
"{\\textellipsis}" : "\u2026", // HORIZONTAL ELLIPSIS
"{\\textperthousand}" : "\u2030", // PER MILLE SIGN
"'''" : "\u2034", // TRIPLE PRIME
"''" : "\u201D", // RIGHT DOUBLE QUOTATION MARK (could be a double prime)
"``" : "\u201C", // LEFT DOUBLE QUOTATION MARK (could be a reversed double prime)
"```" : "\u2037", // REVERSED TRIPLE PRIME
"{\\guilsinglleft}" : "\u2039", // SINGLE LEFT-POINTING ANGLE QUOTATION MARK
"{\\guilsinglright}" : "\u203A", // SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
"!!" : "\u203C", // DOUBLE EXCLAMATION MARK
"{\\textfractionsolidus}" : "\u2044", // FRACTION SLASH
"?!" : "\u2048", // QUESTION EXCLAMATION MARK
"!?" : "\u2049", // EXCLAMATION QUESTION MARK
"$^{0}$" : "\u2070", // SUPERSCRIPT ZERO
"$^{4}$" : "\u2074", // SUPERSCRIPT FOUR
"$^{5}$" : "\u2075", // SUPERSCRIPT FIVE
"$^{6}$" : "\u2076", // SUPERSCRIPT SIX
"$^{7}$" : "\u2077", // SUPERSCRIPT SEVEN
"$^{8}$" : "\u2078", // SUPERSCRIPT EIGHT
"$^{9}$" : "\u2079", // SUPERSCRIPT NINE
"$^{+}$" : "\u207A", // SUPERSCRIPT PLUS SIGN
"$^{-}$" : "\u207B", // SUPERSCRIPT MINUS
"$^{=}$" : "\u207C", // SUPERSCRIPT EQUALS SIGN
"$^{(}$" : "\u207D", // SUPERSCRIPT LEFT PARENTHESIS
"$^{)}$" : "\u207E", // SUPERSCRIPT RIGHT PARENTHESIS
"$^{n}$" : "\u207F", // SUPERSCRIPT LATIN SMALL LETTER N
"$_{0}$" : "\u2080", // SUBSCRIPT ZERO
"$_{1}$" : "\u2081", // SUBSCRIPT ONE
"$_{2}$" : "\u2082", // SUBSCRIPT TWO
"$_{3}$" : "\u2083", // SUBSCRIPT THREE
"$_{4}$" : "\u2084", // SUBSCRIPT FOUR
"$_{5}$" : "\u2085", // SUBSCRIPT FIVE
"$_{6}$" : "\u2086", // SUBSCRIPT SIX
"$_{7}$" : "\u2087", // SUBSCRIPT SEVEN
"$_{8}$" : "\u2088", // SUBSCRIPT EIGHT
"$_{9}$" : "\u2089", // SUBSCRIPT NINE
"$_{+}$" : "\u208A", // SUBSCRIPT PLUS SIGN
"$_{-}$" : "\u208B", // SUBSCRIPT MINUS
"$_{=}$" : "\u208C", // SUBSCRIPT EQUALS SIGN
"$_{(}$" : "\u208D", // SUBSCRIPT LEFT PARENTHESIS
"$_{)}$" : "\u208E", // SUBSCRIPT RIGHT PARENTHESIS
"{\\texteuro}" : "\u20AC", // EURO SIGN
"a/c" : "\u2100", // ACCOUNT OF
"a/s" : "\u2101", // ADDRESSED TO THE SUBJECT
"{\\textcelsius}" : "\u2103", // DEGREE CELSIUS
"c/o" : "\u2105", // CARE OF
"c/u" : "\u2106", // CADA UNA
"{\\textnumero}" : "\u2116", // NUMERO SIGN
"{\\textcircledP}" : "\u2117", // SOUND RECORDING COPYRIGHT
"{\\textservicemark}" : "\u2120", // SERVICE MARK
"{TEL}" : "\u2121", // TELEPHONE SIGN
"{\\texttrademark}" : "\u2122", // TRADE MARK SIGN
"{\\textohm}" : "\u2126", // OHM SIGN
"{\\textestimated}" : "\u212E", // ESTIMATED SYMBOL
" 1/3" : "\u2153", // VULGAR FRACTION ONE THIRD
" 2/3" : "\u2154", // VULGAR FRACTION TWO THIRDS
" 1/5" : "\u2155", // VULGAR FRACTION ONE FIFTH
" 2/5" : "\u2156", // VULGAR FRACTION TWO FIFTHS
" 3/5" : "\u2157", // VULGAR FRACTION THREE FIFTHS
" 4/5" : "\u2158", // VULGAR FRACTION FOUR FIFTHS
" 1/6" : "\u2159", // VULGAR FRACTION ONE SIXTH
" 5/6" : "\u215A", // VULGAR FRACTION FIVE SIXTHS
" 1/8" : "\u215B", // VULGAR FRACTION ONE EIGHTH
" 3/8" : "\u215C", // VULGAR FRACTION THREE EIGHTHS
" 5/8" : "\u215D", // VULGAR FRACTION FIVE EIGHTHS
" 7/8" : "\u215E", // VULGAR FRACTION SEVEN EIGHTHS
" 1/" : "\u215F", // FRACTION NUMERATOR ONE
"{\\textleftarrow}" : "\u2190", // LEFTWARDS ARROW
"{\\textuparrow}" : "\u2191", // UPWARDS ARROW
"{\\textrightarrow}" : "\u2192", // RIGHTWARDS ARROW
"{\\textdownarrow}" : "\u2193", // DOWNWARDS ARROW
"<->" : "\u2194", // LEFT RIGHT ARROW
"<=" : "\u21D0", // LEFTWARDS DOUBLE ARROW
"=>" : "\u21D2", // RIGHTWARDS DOUBLE ARROW
"<=>" : "\u21D4", // LEFT RIGHT DOUBLE ARROW
"$\\infty$" : "\u221E", // INFINITY
"||" : "\u2225", // PARALLEL TO
"/=" : "\u2260", // NOT EQUAL TO
// "<=" : "\u2264", // LESS-THAN OR EQUAL TO
">=" : "\u2265", // GREATER-THAN OR EQUAL TO
"<<" : "\u226A", // MUCH LESS-THAN
">>" : "\u226B", // MUCH GREATER-THAN
"(+)" : "\u2295", // CIRCLED PLUS
"(-)" : "\u2296", // CIRCLED MINUS
"(x)" : "\u2297", // CIRCLED TIMES
"(/)" : "\u2298", // CIRCLED DIVISION SLASH
"|-" : "\u22A2", // RIGHT TACK
"-|" : "\u22A3", // LEFT TACK
// "|-" : "\u22A6", // ASSERTION
"|=" : "\u22A7", // MODELS
// "|=" : "\u22A8", // TRUE
"||-" : "\u22A9", // FORCES
"$\\#$" : "\u22D5", // EQUAL AND PARALLEL TO
"<<<" : "\u22D8", // VERY MUCH LESS-THAN
">>>" : "\u22D9", // VERY MUCH GREATER-THAN
"{\\textlangle}" : "\u2329", // LEFT-POINTING ANGLE BRACKET
"{\\textrangle}" : "\u232A", // RIGHT-POINTING ANGLE BRACKET
"{\\textvisiblespace}" : "\u2423", // OPEN BOX
"///" : "\u2425", // SYMBOL FOR DELETE FORM TWO
"{\\textopenbullet}" : "\u25E6", // WHITE BULLET
":-(" : "\u2639", // WHITE FROWNING FACE
":-)" : "\u263A", // WHITE SMILING FACE
"(-: " : "\u263B", // BLACK SMILING FACE
// "$\\#$" : "\u266F", // MUSIC SHARP SIGN
"$\\%<$" : "\u2701", // UPPER BLADE SCISSORS
/* "$\\%<$" : "\u2702", // BLACK SCISSORS
"$\\%<$" : "\u2703", // LOWER BLADE SCISSORS
"$\\%<$" : "\u2704", // WHITE SCISSORS */
/* Derived accented characters */
"\\`{A}" : "\u00C0", // LATIN CAPITAL LETTER A WITH GRAVE
"\\'{A}" : "\u00C1", // LATIN CAPITAL LETTER A WITH ACUTE
"\\^{A}" : "\u00C2", // LATIN CAPITAL LETTER A WITH CIRCUMFLEX
"\\~{A}" : "\u00C3", // LATIN CAPITAL LETTER A WITH TILDE
"\\\"{A}" : "\u00C4", // LATIN CAPITAL LETTER A WITH DIAERESIS
"\\r{A}" : "\u00C5", // LATIN CAPITAL LETTER A WITH RING ABOVE
"\\c{C}" : "\u00C7", // LATIN CAPITAL LETTER C WITH CEDILLA
"\\`{E}" : "\u00C8", // LATIN CAPITAL LETTER E WITH GRAVE
"\\'{E}" : "\u00C9", // LATIN CAPITAL LETTER E WITH ACUTE
"\\^{E}" : "\u00CA", // LATIN CAPITAL LETTER E WITH CIRCUMFLEX
"\\\"{E}" : "\u00CB", // LATIN CAPITAL LETTER E WITH DIAERESIS
"\\`{I}" : "\u00CC", // LATIN CAPITAL LETTER I WITH GRAVE
"\\'{I}" : "\u00CD", // LATIN CAPITAL LETTER I WITH ACUTE
"\\^{I}" : "\u00CE", // LATIN CAPITAL LETTER I WITH CIRCUMFLEX
"\\\"{I}" : "\u00CF", // LATIN CAPITAL LETTER I WITH DIAERESIS
"\\~{N}" : "\u00D1", // LATIN CAPITAL LETTER N WITH TILDE
"\\`{O}" : "\u00D2", // LATIN CAPITAL LETTER O WITH GRAVE
"\\'{O}" : "\u00D3", // LATIN CAPITAL LETTER O WITH ACUTE
"\\^{O}" : "\u00D4", // LATIN CAPITAL LETTER O WITH CIRCUMFLEX
"\\~{O}" : "\u00D5", // LATIN CAPITAL LETTER O WITH TILDE
"\\\"{O}" : "\u00D6", // LATIN CAPITAL LETTER O WITH DIAERESIS
"\\`{U}" : "\u00D9", // LATIN CAPITAL LETTER U WITH GRAVE
"\\'{U}" : "\u00DA", // LATIN CAPITAL LETTER U WITH ACUTE
"\\^{U}" : "\u00DB", // LATIN CAPITAL LETTER U WITH CIRCUMFLEX
"\\\"{U}" : "\u00DC", // LATIN CAPITAL LETTER U WITH DIAERESIS
"\\'{Y}" : "\u00DD", // LATIN CAPITAL LETTER Y WITH ACUTE
"\\`{a}" : "\u00E0", // LATIN SMALL LETTER A WITH GRAVE
"\\'{a}" : "\u00E1", // LATIN SMALL LETTER A WITH ACUTE
"\\^{a}" : "\u00E2", // LATIN SMALL LETTER A WITH CIRCUMFLEX
"\\~{a}" : "\u00E3", // LATIN SMALL LETTER A WITH TILDE
"\\\"{a}" : "\u00E4", // LATIN SMALL LETTER A WITH DIAERESIS
"\\r{a}" : "\u00E5", // LATIN SMALL LETTER A WITH RING ABOVE
"\\c{c}" : "\u00E7", // LATIN SMALL LETTER C WITH CEDILLA
"\\`{e}" : "\u00E8", // LATIN SMALL LETTER E WITH GRAVE
"\\'{e}" : "\u00E9", // LATIN SMALL LETTER E WITH ACUTE
"\\^{e}" : "\u00EA", // LATIN SMALL LETTER E WITH CIRCUMFLEX
"\\\"{e}" : "\u00EB", // LATIN SMALL LETTER E WITH DIAERESIS
"\\`{i}" : "\u00EC", // LATIN SMALL LETTER I WITH GRAVE
"\\'{i}" : "\u00ED", // LATIN SMALL LETTER I WITH ACUTE
"\\^{i}" : "\u00EE", // LATIN SMALL LETTER I WITH CIRCUMFLEX
"\\\"{i}" : "\u00EF", // LATIN SMALL LETTER I WITH DIAERESIS
"\\~{n}" : "\u00F1", // LATIN SMALL LETTER N WITH TILDE
"\\`{o}" : "\u00F2", // LATIN SMALL LETTER O WITH GRAVE
"\\'{o}" : "\u00F3", // LATIN SMALL LETTER O WITH ACUTE
"\\^{o}" : "\u00F4", // LATIN SMALL LETTER O WITH CIRCUMFLEX
"\\~{o}" : "\u00F5", // LATIN SMALL LETTER O WITH TILDE
"\\\"{o}" : "\u00F6", // LATIN SMALL LETTER O WITH DIAERESIS
"\\`{u}" : "\u00F9", // LATIN SMALL LETTER U WITH GRAVE
"\\'{u}" : "\u00FA", // LATIN SMALL LETTER U WITH ACUTE
"\\^{u}" : "\u00FB", // LATIN SMALL LETTER U WITH CIRCUMFLEX
"\\\"{u}" : "\u00FC", // LATIN SMALL LETTER U WITH DIAERESIS
"\\'{y}" : "\u00FD", // LATIN SMALL LETTER Y WITH ACUTE
"\\\"{y}" : "\u00FF", // LATIN SMALL LETTER Y WITH DIAERESIS
"\\={A}" : "\u0100", // LATIN CAPITAL LETTER A WITH MACRON
"\\={a}" : "\u0101", // LATIN SMALL LETTER A WITH MACRON
"\\u{A}" : "\u0102", // LATIN CAPITAL LETTER A WITH BREVE
"\\u{a}" : "\u0103", // LATIN SMALL LETTER A WITH BREVE
"\\k{A}" : "\u0104", // LATIN CAPITAL LETTER A WITH OGONEK
"\\k{a}" : "\u0105", // LATIN SMALL LETTER A WITH OGONEK
"\\'{C}" : "\u0106", // LATIN CAPITAL LETTER C WITH ACUTE
"\\'{c}" : "\u0107", // LATIN SMALL LETTER C WITH ACUTE
"\\^{C}" : "\u0108", // LATIN CAPITAL LETTER C WITH CIRCUMFLEX
"\\^{c}" : "\u0109", // LATIN SMALL LETTER C WITH CIRCUMFLEX
"\\.{C}" : "\u010A", // LATIN CAPITAL LETTER C WITH DOT ABOVE
"\\.{c}" : "\u010B", // LATIN SMALL LETTER C WITH DOT ABOVE
"\\v{C}" : "\u010C", // LATIN CAPITAL LETTER C WITH CARON
"\\v{c}" : "\u010D", // LATIN SMALL LETTER C WITH CARON
"\\v{D}" : "\u010E", // LATIN CAPITAL LETTER D WITH CARON
"\\v{d}" : "\u010F", // LATIN SMALL LETTER D WITH CARON
"\\={E}" : "\u0112", // LATIN CAPITAL LETTER E WITH MACRON
"\\={e}" : "\u0113", // LATIN SMALL LETTER E WITH MACRON
"\\u{E}" : "\u0114", // LATIN CAPITAL LETTER E WITH BREVE
"\\u{e}" : "\u0115", // LATIN SMALL LETTER E WITH BREVE
"\\.{E}" : "\u0116", // LATIN CAPITAL LETTER E WITH DOT ABOVE
"\\.{e}" : "\u0117", // LATIN SMALL LETTER E WITH DOT ABOVE
"\\k{E}" : "\u0118", // LATIN CAPITAL LETTER E WITH OGONEK
"\\k{e}" : "\u0119", // LATIN SMALL LETTER E WITH OGONEK
"\\v{E}" : "\u011A", // LATIN CAPITAL LETTER E WITH CARON
"\\v{e}" : "\u011B", // LATIN SMALL LETTER E WITH CARON
"\\^{G}" : "\u011C", // LATIN CAPITAL LETTER G WITH CIRCUMFLEX
"\\^{g}" : "\u011D", // LATIN SMALL LETTER G WITH CIRCUMFLEX
"\\u{G}" : "\u011E", // LATIN CAPITAL LETTER G WITH BREVE
"\\u{g}" : "\u011F", // LATIN SMALL LETTER G WITH BREVE
"\\.{G}" : "\u0120", // LATIN CAPITAL LETTER G WITH DOT ABOVE
"\\.{g}" : "\u0121", // LATIN SMALL LETTER G WITH DOT ABOVE
"\\c{G}" : "\u0122", // LATIN CAPITAL LETTER G WITH CEDILLA
"\\c{g}" : "\u0123", // LATIN SMALL LETTER G WITH CEDILLA
"\\^{H}" : "\u0124", // LATIN CAPITAL LETTER H WITH CIRCUMFLEX
"\\^{h}" : "\u0125", // LATIN SMALL LETTER H WITH CIRCUMFLEX
"\\~{I}" : "\u0128", // LATIN CAPITAL LETTER I WITH TILDE
"\\~{i}" : "\u0129", // LATIN SMALL LETTER I WITH TILDE
"\\={I}" : "\u012A", // LATIN CAPITAL LETTER I WITH MACRON
"\\={i}" : "\u012B", // LATIN SMALL LETTER I WITH MACRON
"\\u{I}" : "\u012C", // LATIN CAPITAL LETTER I WITH BREVE
"\\u{i}" : "\u012D", // LATIN SMALL LETTER I WITH BREVE
"\\k{I}" : "\u012E", // LATIN CAPITAL LETTER I WITH OGONEK
"\\k{i}" : "\u012F", // LATIN SMALL LETTER I WITH OGONEK
"\\.{I}" : "\u0130", // LATIN CAPITAL LETTER I WITH DOT ABOVE
"\\^{J}" : "\u0134", // LATIN CAPITAL LETTER J WITH CIRCUMFLEX
"\\^{j}" : "\u0135", // LATIN SMALL LETTER J WITH CIRCUMFLEX
"\\c{K}" : "\u0136", // LATIN CAPITAL LETTER K WITH CEDILLA
"\\c{k}" : "\u0137", // LATIN SMALL LETTER K WITH CEDILLA
"\\'{L}" : "\u0139", // LATIN CAPITAL LETTER L WITH ACUTE
"\\'{l}" : "\u013A", // LATIN SMALL LETTER L WITH ACUTE
"\\c{L}" : "\u013B", // LATIN CAPITAL LETTER L WITH CEDILLA
"\\c{l}" : "\u013C", // LATIN SMALL LETTER L WITH CEDILLA
"\\v{L}" : "\u013D", // LATIN CAPITAL LETTER L WITH CARON
"\\v{l}" : "\u013E", // LATIN SMALL LETTER L WITH CARON
"\\L{}" : "\u0141", //LATIN CAPITAL LETTER L WITH STROKE
"\\l{}" : "\u0142", //LATIN SMALL LETTER L WITH STROKE
"\\'{N}" : "\u0143", // LATIN CAPITAL LETTER N WITH ACUTE
"\\'{n}" : "\u0144", // LATIN SMALL LETTER N WITH ACUTE
"\\c{N}" : "\u0145", // LATIN CAPITAL LETTER N WITH CEDILLA
"\\c{n}" : "\u0146", // LATIN SMALL LETTER N WITH CEDILLA
"\\v{N}" : "\u0147", // LATIN CAPITAL LETTER N WITH CARON
"\\v{n}" : "\u0148", // LATIN SMALL LETTER N WITH CARON
"\\={O}" : "\u014C", // LATIN CAPITAL LETTER O WITH MACRON
"\\={o}" : "\u014D", // LATIN SMALL LETTER O WITH MACRON
"\\u{O}" : "\u014E", // LATIN CAPITAL LETTER O WITH BREVE
"\\u{o}" : "\u014F", // LATIN SMALL LETTER O WITH BREVE
"\\H{O}" : "\u0150", // LATIN CAPITAL LETTER O WITH DOUBLE ACUTE
"\\H{o}" : "\u0151", // LATIN SMALL LETTER O WITH DOUBLE ACUTE
"\\'{R}" : "\u0154", // LATIN CAPITAL LETTER R WITH ACUTE
"\\'{r}" : "\u0155", // LATIN SMALL LETTER R WITH ACUTE
"\\c{R}" : "\u0156", // LATIN CAPITAL LETTER R WITH CEDILLA
"\\c{r}" : "\u0157", // LATIN SMALL LETTER R WITH CEDILLA
"\\v{R}" : "\u0158", // LATIN CAPITAL LETTER R WITH CARON
"\\v{r}" : "\u0159", // LATIN SMALL LETTER R WITH CARON
"\\'{S}" : "\u015A", // LATIN CAPITAL LETTER S WITH ACUTE
"\\'{s}" : "\u015B", // LATIN SMALL LETTER S WITH ACUTE
"\\^{S}" : "\u015C", // LATIN CAPITAL LETTER S WITH CIRCUMFLEX
"\\^{s}" : "\u015D", // LATIN SMALL LETTER S WITH CIRCUMFLEX
"\\c{S}" : "\u015E", // LATIN CAPITAL LETTER S WITH CEDILLA
"\\c{s}" : "\u015F", // LATIN SMALL LETTER S WITH CEDILLA
"\\v{S}" : "\u0160", // LATIN CAPITAL LETTER S WITH CARON
"\\v{s}" : "\u0161", // LATIN SMALL LETTER S WITH CARON
"\\c{T}" : "\u0162", // LATIN CAPITAL LETTER T WITH CEDILLA
"\\c{t}" : "\u0163", // LATIN SMALL LETTER T WITH CEDILLA
"\\v{T}" : "\u0164", // LATIN CAPITAL LETTER T WITH CARON
"\\v{t}" : "\u0165", // LATIN SMALL LETTER T WITH CARON
"\\~{U}" : "\u0168", // LATIN CAPITAL LETTER U WITH TILDE
"\\~{u}" : "\u0169", // LATIN SMALL LETTER U WITH TILDE
"\\={U}" : "\u016A", // LATIN CAPITAL LETTER U WITH MACRON
"\\={u}" : "\u016B", // LATIN SMALL LETTER U WITH MACRON
"\\u{U}" : "\u016C", // LATIN CAPITAL LETTER U WITH BREVE
"\\u{u}" : "\u016D", // LATIN SMALL LETTER U WITH BREVE
"\\H{U}" : "\u0170", // LATIN CAPITAL LETTER U WITH DOUBLE ACUTE
"\\H{u}" : "\u0171", // LATIN SMALL LETTER U WITH DOUBLE ACUTE
"\\k{U}" : "\u0172", // LATIN CAPITAL LETTER U WITH OGONEK
"\\k{u}" : "\u0173", // LATIN SMALL LETTER U WITH OGONEK
"\\^{W}" : "\u0174", // LATIN CAPITAL LETTER W WITH CIRCUMFLEX
"\\^{w}" : "\u0175", // LATIN SMALL LETTER W WITH CIRCUMFLEX
"\\^{Y}" : "\u0176", // LATIN CAPITAL LETTER Y WITH CIRCUMFLEX
"\\^{y}" : "\u0177", // LATIN SMALL LETTER Y WITH CIRCUMFLEX
"\\\"{Y}" : "\u0178", // LATIN CAPITAL LETTER Y WITH DIAERESIS
"\\'{Z}" : "\u0179", // LATIN CAPITAL LETTER Z WITH ACUTE
"\\'{z}" : "\u017A", // LATIN SMALL LETTER Z WITH ACUTE
"\\.{Z}" : "\u017B", // LATIN CAPITAL LETTER Z WITH DOT ABOVE
"\\.{z}" : "\u017C", // LATIN SMALL LETTER Z WITH DOT ABOVE
"\\v{Z}" : "\u017D", // LATIN CAPITAL LETTER Z WITH CARON
"\\v{z}" : "\u017E", // LATIN SMALL LETTER Z WITH CARON
"\\v{A}" : "\u01CD", // LATIN CAPITAL LETTER A WITH CARON
"\\v{a}" : "\u01CE", // LATIN SMALL LETTER A WITH CARON
"\\v{I}" : "\u01CF", // LATIN CAPITAL LETTER I WITH CARON
"\\v{i}" : "\u01D0", // LATIN SMALL LETTER I WITH CARON
"\\v{O}" : "\u01D1", // LATIN CAPITAL LETTER O WITH CARON
"\\v{o}" : "\u01D2", // LATIN SMALL LETTER O WITH CARON
"\\v{U}" : "\u01D3", // LATIN CAPITAL LETTER U WITH CARON
"\\v{u}" : "\u01D4", // LATIN SMALL LETTER U WITH CARON
"\\v{G}" : "\u01E6", // LATIN CAPITAL LETTER G WITH CARON
"\\v{g}" : "\u01E7", // LATIN SMALL LETTER G WITH CARON
"\\v{K}" : "\u01E8", // LATIN CAPITAL LETTER K WITH CARON
"\\v{k}" : "\u01E9", // LATIN SMALL LETTER K WITH CARON
"\\k{O}" : "\u01EA", // LATIN CAPITAL LETTER O WITH OGONEK
"\\k{o}" : "\u01EB", // LATIN SMALL LETTER O WITH OGONEK
"\\v{j}" : "\u01F0", // LATIN SMALL LETTER J WITH CARON
"\\'{G}" : "\u01F4", // LATIN CAPITAL LETTER G WITH ACUTE
"\\'{g}" : "\u01F5", // LATIN SMALL LETTER G WITH ACUTE
"\\.{B}" : "\u1E02", // LATIN CAPITAL LETTER B WITH DOT ABOVE
"\\.{b}" : "\u1E03", // LATIN SMALL LETTER B WITH DOT ABOVE
"\\d{B}" : "\u1E04", // LATIN CAPITAL LETTER B WITH DOT BELOW
"\\d{b}" : "\u1E05", // LATIN SMALL LETTER B WITH DOT BELOW
"\\b{B}" : "\u1E06", // LATIN CAPITAL LETTER B WITH LINE BELOW
"\\b{b}" : "\u1E07", // LATIN SMALL LETTER B WITH LINE BELOW
"\\.{D}" : "\u1E0A", // LATIN CAPITAL LETTER D WITH DOT ABOVE
"\\.{d}" : "\u1E0B", // LATIN SMALL LETTER D WITH DOT ABOVE
"\\d{D}" : "\u1E0C", // LATIN CAPITAL LETTER D WITH DOT BELOW
"\\d{d}" : "\u1E0D", // LATIN SMALL LETTER D WITH DOT BELOW
"\\b{D}" : "\u1E0E", // LATIN CAPITAL LETTER D WITH LINE BELOW
"\\b{d}" : "\u1E0F", // LATIN SMALL LETTER D WITH LINE BELOW
"\\c{D}" : "\u1E10", // LATIN CAPITAL LETTER D WITH CEDILLA
"\\c{d}" : "\u1E11", // LATIN SMALL LETTER D WITH CEDILLA
"\\.{F}" : "\u1E1E", // LATIN CAPITAL LETTER F WITH DOT ABOVE
"\\.{f}" : "\u1E1F", // LATIN SMALL LETTER F WITH DOT ABOVE
"\\={G}" : "\u1E20", // LATIN CAPITAL LETTER G WITH MACRON
"\\={g}" : "\u1E21", // LATIN SMALL LETTER G WITH MACRON
"\\.{H}" : "\u1E22", // LATIN CAPITAL LETTER H WITH DOT ABOVE
"\\.{h}" : "\u1E23", // LATIN SMALL LETTER H WITH DOT ABOVE
"\\d{H}" : "\u1E24", // LATIN CAPITAL LETTER H WITH DOT BELOW
"\\d{h}" : "\u1E25", // LATIN SMALL LETTER H WITH DOT BELOW
"\\\"{H}" : "\u1E26", // LATIN CAPITAL LETTER H WITH DIAERESIS
"\\\"{h}" : "\u1E27", // LATIN SMALL LETTER H WITH DIAERESIS
"\\c{H}" : "\u1E28", // LATIN CAPITAL LETTER H WITH CEDILLA
"\\c{h}" : "\u1E29", // LATIN SMALL LETTER H WITH CEDILLA
"\\'{K}" : "\u1E30", // LATIN CAPITAL LETTER K WITH ACUTE
"\\'{k}" : "\u1E31", // LATIN SMALL LETTER K WITH ACUTE
"\\d{K}" : "\u1E32", // LATIN CAPITAL LETTER K WITH DOT BELOW
"\\d{k}" : "\u1E33", // LATIN SMALL LETTER K WITH DOT BELOW
"\\b{K}" : "\u1E34", // LATIN CAPITAL LETTER K WITH LINE BELOW
"\\b{k}" : "\u1E35", // LATIN SMALL LETTER K WITH LINE BELOW
"\\d{L}" : "\u1E36", // LATIN CAPITAL LETTER L WITH DOT BELOW
"\\d{l}" : "\u1E37", // LATIN SMALL LETTER L WITH DOT BELOW
"\\b{L}" : "\u1E3A", // LATIN CAPITAL LETTER L WITH LINE BELOW
"\\b{l}" : "\u1E3B", // LATIN SMALL LETTER L WITH LINE BELOW
"\\'{M}" : "\u1E3E", // LATIN CAPITAL LETTER M WITH ACUTE
"\\'{m}" : "\u1E3F", // LATIN SMALL LETTER M WITH ACUTE
"\\.{M}" : "\u1E40", // LATIN CAPITAL LETTER M WITH DOT ABOVE
"\\.{m}" : "\u1E41", // LATIN SMALL LETTER M WITH DOT ABOVE
"\\d{M}" : "\u1E42", // LATIN CAPITAL LETTER M WITH DOT BELOW
"\\d{m}" : "\u1E43", // LATIN SMALL LETTER M WITH DOT BELOW
"\\.{N}" : "\u1E44", // LATIN CAPITAL LETTER N WITH DOT ABOVE
"\\.{n}" : "\u1E45", // LATIN SMALL LETTER N WITH DOT ABOVE
"\\d{N}" : "\u1E46", // LATIN CAPITAL LETTER N WITH DOT BELOW
"\\d{n}" : "\u1E47", // LATIN SMALL LETTER N WITH DOT BELOW
"\\b{N}" : "\u1E48", // LATIN CAPITAL LETTER N WITH LINE BELOW
"\\b{n}" : "\u1E49", // LATIN SMALL LETTER N WITH LINE BELOW
"\\'{P}" : "\u1E54", // LATIN CAPITAL LETTER P WITH ACUTE
"\\'{p}" : "\u1E55", // LATIN SMALL LETTER P WITH ACUTE
"\\.{P}" : "\u1E56", // LATIN CAPITAL LETTER P WITH DOT ABOVE
"\\.{p}" : "\u1E57", // LATIN SMALL LETTER P WITH DOT ABOVE
"\\.{R}" : "\u1E58", // LATIN CAPITAL LETTER R WITH DOT ABOVE
"\\.{r}" : "\u1E59", // LATIN SMALL LETTER R WITH DOT ABOVE
"\\d{R}" : "\u1E5A", // LATIN CAPITAL LETTER R WITH DOT BELOW
"\\d{r}" : "\u1E5B", // LATIN SMALL LETTER R WITH DOT BELOW
"\\b{R}" : "\u1E5E", // LATIN CAPITAL LETTER R WITH LINE BELOW
"\\b{r}" : "\u1E5F", // LATIN SMALL LETTER R WITH LINE BELOW
"\\.{S}" : "\u1E60", // LATIN CAPITAL LETTER S WITH DOT ABOVE
"\\.{s}" : "\u1E61", // LATIN SMALL LETTER S WITH DOT ABOVE
"\\d{S}" : "\u1E62", // LATIN CAPITAL LETTER S WITH DOT BELOW
"\\d{s}" : "\u1E63", // LATIN SMALL LETTER S WITH DOT BELOW
"\\.{T}" : "\u1E6A", // LATIN CAPITAL LETTER T WITH DOT ABOVE
"\\.{t}" : "\u1E6B", // LATIN SMALL LETTER T WITH DOT ABOVE
"\\d{T}" : "\u1E6C", // LATIN CAPITAL LETTER T WITH DOT BELOW
"\\d{t}" : "\u1E6D", // LATIN SMALL LETTER T WITH DOT BELOW
"\\b{T}" : "\u1E6E", // LATIN CAPITAL LETTER T WITH LINE BELOW
"\\b{t}" : "\u1E6F", // LATIN SMALL LETTER T WITH LINE BELOW
"\\~{V}" : "\u1E7C", // LATIN CAPITAL LETTER V WITH TILDE
"\\~{v}" : "\u1E7D", // LATIN SMALL LETTER V WITH TILDE
"\\d{V}" : "\u1E7E", // LATIN CAPITAL LETTER V WITH DOT BELOW
"\\d{v}" : "\u1E7F", // LATIN SMALL LETTER V WITH DOT BELOW
"\\`{W}" : "\u1E80", // LATIN CAPITAL LETTER W WITH GRAVE
"\\`{w}" : "\u1E81", // LATIN SMALL LETTER W WITH GRAVE
"\\'{W}" : "\u1E82", // LATIN CAPITAL LETTER W WITH ACUTE
"\\'{w}" : "\u1E83", // LATIN SMALL LETTER W WITH ACUTE
"\\\"{W}" : "\u1E84", // LATIN CAPITAL LETTER W WITH DIAERESIS
"\\\"{w}" : "\u1E85", // LATIN SMALL LETTER W WITH DIAERESIS
"\\.{W}" : "\u1E86", // LATIN CAPITAL LETTER W WITH DOT ABOVE
"\\.{w}" : "\u1E87", // LATIN SMALL LETTER W WITH DOT ABOVE
"\\d{W}" : "\u1E88", // LATIN CAPITAL LETTER W WITH DOT BELOW
"\\d{w}" : "\u1E89", // LATIN SMALL LETTER W WITH DOT BELOW
"\\.{X}" : "\u1E8A", // LATIN CAPITAL LETTER X WITH DOT ABOVE
"\\.{x}" : "\u1E8B", // LATIN SMALL LETTER X WITH DOT ABOVE
"\\\"{X}" : "\u1E8C", // LATIN CAPITAL LETTER X WITH DIAERESIS
"\\\"{x}" : "\u1E8D", // LATIN SMALL LETTER X WITH DIAERESIS
"\\.{Y}" : "\u1E8E", // LATIN CAPITAL LETTER Y WITH DOT ABOVE
"\\.{y}" : "\u1E8F", // LATIN SMALL LETTER Y WITH DOT ABOVE
"\\^{Z}" : "\u1E90", // LATIN CAPITAL LETTER Z WITH CIRCUMFLEX
"\\^{z}" : "\u1E91", // LATIN SMALL LETTER Z WITH CIRCUMFLEX
"\\d{Z}" : "\u1E92", // LATIN CAPITAL LETTER Z WITH DOT BELOW
"\\d{z}" : "\u1E93", // LATIN SMALL LETTER Z WITH DOT BELOW
"\\b{Z}" : "\u1E94", // LATIN CAPITAL LETTER Z WITH LINE BELOW
"\\b{z}" : "\u1E95", // LATIN SMALL LETTER Z WITH LINE BELOW
"\\b{h}" : "\u1E96", // LATIN SMALL LETTER H WITH LINE BELOW
"\\\"{t}" : "\u1E97", // LATIN SMALL LETTER T WITH DIAERESIS
"\\d{A}" : "\u1EA0", // LATIN CAPITAL LETTER A WITH DOT BELOW
"\\d{a}" : "\u1EA1", // LATIN SMALL LETTER A WITH DOT BELOW
"\\d{E}" : "\u1EB8", // LATIN CAPITAL LETTER E WITH DOT BELOW
"\\d{e}" : "\u1EB9", // LATIN SMALL LETTER E WITH DOT BELOW
"\\~{E}" : "\u1EBC", // LATIN CAPITAL LETTER E WITH TILDE
"\\~{e}" : "\u1EBD", // LATIN SMALL LETTER E WITH TILDE
"\\d{I}" : "\u1ECA", // LATIN CAPITAL LETTER I WITH DOT BELOW
"\\d{i}" : "\u1ECB", // LATIN SMALL LETTER I WITH DOT BELOW
"\\d{O}" : "\u1ECC", // LATIN CAPITAL LETTER O WITH DOT BELOW
"\\d{o}" : "\u1ECD", // LATIN SMALL LETTER O WITH DOT BELOW
"\\d{U}" : "\u1EE4", // LATIN CAPITAL LETTER U WITH DOT BELOW
"\\d{u}" : "\u1EE5", // LATIN SMALL LETTER U WITH DOT BELOW
"\\`{Y}" : "\u1EF2", // LATIN CAPITAL LETTER Y WITH GRAVE
"\\`{y}" : "\u1EF3", // LATIN SMALL LETTER Y WITH GRAVE
"\\d{Y}" : "\u1EF4", // LATIN CAPITAL LETTER Y WITH DOT BELOW
"\\d{y}" : "\u1EF5", // LATIN SMALL LETTER Y WITH DOT BELOW
"\\~{Y}" : "\u1EF8", // LATIN CAPITAL LETTER Y WITH TILDE
"\\~{y}" : "\u1EF9", // LATIN SMALL LETTER Y WITH TILDE
"\\~{}" : "\u223C", // TILDE OPERATOR
"~" : "\u00A0" // NO-BREAK SPACE
};
var alwaysMap = {
"|":"{\\textbar}",
"<":"{\\textless}",
">":"{\\textgreater}",
"~":"{\\textasciitilde}",
"^":"{\\textasciicircum}",
"\\":"{\\textbackslash}"
};
var strings = {};
var keyRe = /[a-zA-Z0-9\-]/;
function processField(item, field, value) {
if(Zotero.Utilities.trim(value) == '') return null;
if(fieldMap[field]) {
item[fieldMap[field]] = value;
} else if(inputFieldMap[field]) {
item[inputFieldMap[field]] = value;
} else if(field == "journal") {
if(item.publicationTitle) {
item.journalAbbreviation = value;
} else {
item.publicationTitle = value;
}
} else if(field == "fjournal") {
if(item.publicationTitle) {
// move publicationTitle to abbreviation
item.journalAbbreviation = value;
}
item.publicationTitle = value;
} else if(field == "author" || field == "editor" || field == "translator") {
// parse authors/editors/translators
var names = value.split(/ and /i); // now case insensitive
for(var i in names) {
var name = names[i];
// skip empty names
if (name.trim() == '') {
continue;
}
// Names in BibTeX can have three commas
pieces = name.split(',');
var creator = {};
if (pieces.length > 1) {
creator.firstName = pieces.pop().trim();
creator.lastName = pieces.join(',').trim();
creator.creatorType = field;
} else {
creator = Zotero.Utilities.cleanAuthor(name, field, false);
}
item.creators.push(creator);
}
} else if(field == "institution" || field == "organization") {
item.backupPublisher = value;
} else if(field == "number"){ // fix for techreport
if (item.itemType == "report") {
item.reportNumber = value;
} else if (item.itemType == "book" || item.itemType == "bookSection") {
item.seriesNumber = value;
} else {
item.issue = value;
}
} else if(field == "month") {
var monthIndex = months.indexOf(value.toLowerCase());
if(monthIndex != -1) {
value = Zotero.Utilities.formatDate({month:monthIndex});
} else {
value += " ";
}
if(item.date) {
if(value.indexOf(item.date) != -1) {
// value contains year and more
item.date = value;
} else {
item.date = value+item.date;
}
} else {
item.date = value;
}
} else if(field == "year") {
if(item.date) {
if(item.date.indexOf(value) == -1) {
// date does not already contain year
item.date += value;
}
} else {
item.date = value;
}
} else if(field == "pages") {
if (item.itemType == "book" || item.itemType == "thesis" || item.itemType == "manuscript") {
item.numPages = value;
}
else {
item.pages = value.replace(/--/g, "-");
}
} else if(field == "note") {
item.extra += "\n"+value;
} else if(field == "howpublished") {
if(value.length >= 7) {
var str = value.substr(0, 7);
if(str == "http://" || str == "https:/" || str == "mailto:") {
item.url = value;
} else {
item.extra += "\nPublished: "+value;
}
}
} else if(field == "keywords") {
if(value.indexOf(",") == -1) {
// keywords/tags
item.tags = value.split(" ");
} else {
item.tags = value.split(/, ?/g);
}
} else if (field == "comment" || field == "annote" || field == "review") {
item.notes.push({note:Zotero.Utilities.text2html(value)});
} else if (field == "pdf") {
if (/:\/\//.test(value)) { // a full uri is given
item.attachments = [{url:value, mimeType:"application/pdf", downloadable:true}];
} else { // if no uri is given, assume that it is an absolute path to the PDF
item.attachments = [{url:"file://"+value, mimeType:"application/pdf"}];
}
} else if (field == "sentelink") { // the reference manager 'Sente' has a unique file scheme in exported BibTeX
item.attachments = [{url:value.split(",")[0], mimeType:"application/pdf", downloadable:true}];
} else if (field == "file") {
var attachments = value.split(";");
for(var i in attachments){
var attachment = attachments[i];
var parts = attachment.split(":");
var filetitle = parts[0];
var filepath = parts[1];
if (filepath.trim() === '') continue; // skip empty entries
var filetype = parts[2];
if (filetitle.length == 0) {
filetitle = "Attachment";
}
if (filetype.match(/pdf/i)) {
item.attachments.push({url:"file://"+filepath, mimeType:"application/pdf", title:filetitle, downloadable:true});
} else {
item.attachments.push({url:"file://"+filepath, title:filetitle, downloadable:true});
}
}
}
}
function getFieldValue(read) {
var value = "";
// now, we have the first character of the field
if(read == "{") {
// character is a brace
var openBraces = 1;
while(read = Zotero.read(1)) {
if(read == "{" && value[value.length-1] != "\\") {
openBraces++;
value += "{";
} else if(read == "}" && value[value.length-1] != "\\") {
openBraces--;
if(openBraces == 0) {
break;
} else {
value += "}";
}
} else {
value += read;
}
}
} else if(read == '"') {
var openBraces = 0;
while(read = Zotero.read(1)) {
if(read == "{" && value[value.length-1] != "\\") {
openBraces++;
value += "{";
} else if(read == "}" && value[value.length-1] != "\\") {
openBraces--;
value += "}";
} else if(read == '"' && openBraces == 0) {
break;
} else {
value += read;
}
}
}
if(value.length > 1) {
// replace accented characters (yucky slow)
value = value.replace(/{?(\\[`"'^~=a-z]){?\\?([A-Za-z])}/g, "$1{$2}");
for (var mapped in reversemappingTable) { // really really slow!
var unicode = reversemappingTable[mapped];
if (value.indexOf(mapped) != -1) {
Zotero.debug("Replace " + mapped + " in " + value + " with " + unicode);
value = value.replace(mapped, unicode, "g");
}
mapped = mapped.replace(/[{}]/g, "");
if (value.indexOf(mapped) != -1) {
Zotero.debug("Replace(2) " + mapped + " in " + value + " with " + unicode);
value = value.replace(mapped, unicode, "g");
}
}
// kill braces
value = value.replace(/([^\\])[{}]+/g, "$1");
if(value[0] == "{") {
value = value.substr(1);
}
// chop off backslashes
value = value.replace(/([^\\])\\([#$%&~_^\\{}])/g, "$1$2");
value = value.replace(/([^\\])\\([#$%&~_^\\{}])/g, "$1$2");
if(value[0] == "\\" && "#$%&~_^\\{}".indexOf(value[1]) != -1) {
value = value.substr(1);
}
if(value[value.length-1] == "\\" && "#$%&~_^\\{}".indexOf(value[value.length-2]) != -1) {
value = value.substr(0, value.length-1);
}
value = value.replace(/\\\\/g, "\\");
value = value.replace(/\s+/g, " ");
}
return value;
}
function beginRecord(type, closeChar) {
type = Zotero.Utilities.trimInternal(type.toLowerCase());
if(type != "string") {
var zoteroType = bibtex2zoteroTypeMap[type];
if (!zoteroType) {
Zotero.debug("discarded item from BibTeX; type was "+type);
}
var item = new Zotero.Item(zoteroType);
item.extra = "";
}
var field = "";
// by setting dontRead to true, we can skip a read on the next iteration
// of this loop. this is useful after we read past the end of a string.
var dontRead = false;
while(dontRead || (read = Zotero.read(1))) {
dontRead = false;
if(read == "=") { // equals begin a field
// read whitespace
var read = Zotero.read(1);
while(" \n\r\t".indexOf(read) != -1) {
read = Zotero.read(1);
}
if(keyRe.test(read)) {
// read numeric data here, since we might get an end bracket
// that we should care about
value = "";
value += read;
// character is a number
while((read = Zotero.read(1)) && keyRe.test(read)) {
value += read;
}
// don't read the next char; instead, process the character
// we already read past the end of the string
dontRead = true;
// see if there's a defined string
if(strings[value]) value = strings[value];
} else {
var value = getFieldValue(read);
}
if(item) {
processField(item, field.toLowerCase(), value);
} else if(type == "string") {
strings[field] = value;
}
field = "";
} else if(read == ",") { // commas reset
field = "";
} else if(read == closeChar) {
if(item) {
if(item.extra) item.extra = item.extra.substr(1); // chop \n
item.complete();
}
return;
} else if(" \n\r\t".indexOf(read) == -1) { // skip whitespace
field += read;
}
}
}
function doImport() {
var read = "", text = "", recordCloseElement = false;
var type = false;
while(read = Zotero.read(1)) {
if(read == "@") {
type = "";
} else if(type !== false) {
if(type == "comment") {
type = false;
} else if(read == "{") { // possible open character
beginRecord(type, "}");
type = false;
} else if(read == "(") { // possible open character
beginRecord(type, ")");
type = false;
} else {
type += read;
}
}
}
}
// 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) {
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(!((field == "url") || (field == "doi") | (field == "file"))) {
// I hope these are all the escape characters!
// -- Tan --begin: preserve common latex markups ^,_,\,$ if users wish
if(preserveLatex) {
value = value.replace(/[|\<\>\~]/g, mapEscape).replace(/([\#\%\&])/g, "\\$1").replace(/([\s]+)([\$][0-9\.\,\-]+[\s]+)/g, "$1\\$2");
} else {
value = value.replace(/[|\<\>\~\^\\]/g, mapEscape).replace(/([\#\$\%\&\_])/g, "\\$1");
}
// -- Tan --end
// Case of words with uppercase characters in non-initial positions is preserved with braces.
if(!isMacro&&field != "pages") value = value.replace(/([^\s]+[A-Z][^\s,]*)/g, "{$1}");
}
if (Zotero.getOption("exportCharset") != "UTF-8") {
value = value.replace(/[\u0080-\uFFFF]/g, mapAccent);
}
Zotero.write(value);
if(!isMacro) Zotero.write("}");
}
function mapEscape(character) {
return alwaysMap[character];
}
function mapAccent(character) {
return (mappingTable[character] ? mappingTable[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();
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 citeKeyTitleBannedMoreRe = /\b(about|and|are|as|at|be|by|can|does|for|has|have|if|into|onto|is|it|its|or|that|these|this|those|via|was|were)(\s+|\b)/g; // -- Tan : more banned words
var citeKeyJournalBannedRe = /\b(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; // -- Tan: no 'a' for journal names
var citeKeyConversionsRe = /%([a-zA-Z]{2})([0-9]*)[\{]?([0-9]*)[\}]?/; // -- Tan: new key format string
var citeKeyCleanRe = /[^a-zA-Z0-9\!\$\&\*\+\-\.\/\:\;\<\>\?\[\]\^\_\`\|]+/g;
var citeKeyConversions = {
// -- Tan --begin: new 2-letter conversion functions
// for creators, title, journal, year, volume, pages. Do we need more?
"AU":function (label, maxlength, num, item) {
if(item.creators && item.creators[num] && item.creators[num].lastName) {
var auth = item.creators[num].lastName.toLowerCase().replace(/[\s\'\,]/g,"");
auth = tidyAccents(auth);
if(label == label.toUpperCase()) {
auth = auth.toUpperCase();
} else if(label[0] == label[0].toUpperCase()) {
auth = auth[0].toUpperCase() + auth.substr(1);
}
if (maxlength && auth.length > maxlength) {
return auth.substr(0,maxlength);
} else {
return auth;
}
}
return "";
},
"AA":function (label, maxlength, num, item) {
if(item.creators) {
var initials = "";
var len = item.creators.length;
len = (len > maxlength) ? maxlength : len;
for (var i=0; i<len; i++) {
var auth = item.creators[i].lastName.toLowerCase().replace(/[\s\'\,]/g,"");
auth = tidyAccents(auth);
initials = initials + auth[0];
}
if(label == label.toUpperCase()) {
initials = initials.toUpperCase();
}
return initials;
}
return "";
},
"TI":function (label, maxlength, num, item) {
if (item["title"]) {
var tit = tidyAccents(item["title"].toLowerCase().replace(citeKeyTitleBannedRe,"").replace(citeKeyTitleBannedMoreRe,"")).replace(/[^a-z\-\s]+/g,"").split(/\s+/g);
if (tit.length > num) {
var word = tit[num];
if(label == label.toUpperCase()) {
word = word.toUpperCase();
} else if(label[0] == label[0].toUpperCase()) {
word = word[0].toUpperCase() + word.substr(1);
}
if (maxlength && word.length > maxlength) {
return word.substr(0,maxlength);
} else {
return word;
}
}
}
return "";
},
"TT":function (label, maxlength, num, item) {
if (item["title"]) {
var tit = tidyAccents(item["title"].toLowerCase().replace(citeKeyTitleBannedRe,"").replace(citeKeyTitleBannedMoreRe,"")).replace(/[^a-z\s]+/g,"").replace(/\b([a-z])[a-z]+\b/g,"$1");
tit = tit.replace(/\s+/g,""); // first letter of each title word
if(label == label.toUpperCase()) {
tit = tit.toUpperCase();
}
if (maxlength && tit.length > maxlength) {
return tit.substr(0,maxlength);
} else {
return tit;
}
}
return "";
},
"YR":function (label, maxlength, num, item) {
if(item.date) {
var date = Zotero.Utilities.strToDate(item.date);
if(date.year && numberRe.test(date.year)) {
if(maxlength == 2) {
return date.year.toString().substr(2);
} else {
return date.year;
}
}
}
if(maxlength == 2) {
return "??";
} else {
return "????";
}
},
"JJ":function (label, maxlength, num, item) {
if (item.publicationTitle) {
var jou = tidyAccents(item.publicationTitle.toLowerCase().replace(citeKeyJournalBannedRe,"").replace(citeKeyTitleBannedMoreRe,"")).replace(/[^a-z\-\s]+/g,"").replace(/\b([a-z\-])[a-z\-]+\b/g,"$1");
jou = jou.replace(/\s+/g,""); // first letter of each journal word
if(label == label.toUpperCase()) {
jou = jou.toUpperCase();
}
if (maxlength && jou.length > maxlength) {
return jou.substr(0,maxlength);
} else {
return jou;
}
}
return "";
},
"VO":function (label, maxlength, num, item) {
if (item.volume) {
return item.volume;
}
return "";
},
"PG":function (label, maxlength, num, item) {
if (item.pages) {
if(num) { // last page number
return (item.pages.lastIndexOf("-") == -1) ? "" : item.pages.substr(item.pages.lastIndexOf("-")+1);
} else {
return item.pages.replace(/\-.*/g,""); // first page number
}
}
return "";
}
// -- Tan --end
}
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 label = m[1];
var maxlength = m[2] ? parseInt(m[2]) : 0;
var num = m[3] ? parseInt(m[3]) : 0;
var f = citeKeyConversions[label.toUpperCase()];
if (typeof(f) == "function") {
var value = f(label, maxlength, num, item);
Zotero.debug("Got value " + value + " for %" + m[1]);
//add conversion to basekey
basekey = basekey + value;
}
citeKeyFormatRemaining = citeKeyFormatRemaining.substr(m.index + m[0].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); // -- Tan: deal with in the individual matching
basekey = basekey.replace(citeKeyCleanRe, "");
var citekey = resolveCiteKeyCollision(basekey,citekeys); // -- Tan: separate the function
return citekey;
}
// -- Tan --begin: allow alphabetic suffix for key collisions
function resolveCiteKeyCollision(basekey,citekeys) {
var citekey = basekey;
var i = 0;
var ii = 0;
var iii = 0;
var suffix = citeKeyCollisionFormat.match(/([^\%]*)%([a-zA-Z0-9])/);
if(suffix) {
var sepmark = suffix[1].replace(citeKeyCleanRe, "");
while(citekeys[citekey]) {
i++;
if (i > 600) {
Zotero.debug("Pathological BibTeX key format: " + citeKeyFormat + " causing too many cite key collisions");
break;
}
if(suffix[2].toLowerCase() == "a") {
ii = Math.floor((i-1)/26);
iii = i - ii*26;
citekey = basekey + sepmark + (ii ? String.fromCharCode(96+ii) : "") + String.fromCharCode(96+iii);
} else {
citekey = basekey + sepmark + i;
}
}
} else {
Zotero.debug("Bad BibTeX key collision format: " + citeKeyCollisionFormat);
}
citekeys[citekey] = true;
return citekey;
}
// -- Tan --end
function doExport() {
//Zotero.write("% BibTeX 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()) {
// determine type
var type = zotero2bibtexTypeMap[item.itemType];
if (typeof(type) == "function") { type = type(item); }
if(!type) type = "misc";
// create a unique citation key
// -- Tan --begin: user's own field for bibtex key (e.g., callNumber)
if (item[citeKeyField]) {
var citekey = resolveCiteKeyCollision(item[citeKeyField],citekeys);
} else {
var citekey = buildCiteKey(item, citekeys);
}
// -- Tan --end
// write citation key
Zotero.write((first ? "" : ",\n\n") + "@"+type+"{"+citekey);
first = false;
for(var field in fieldMap) {
if(item[fieldMap[field]]) {
writeField(field, item[fieldMap[field]]);
}
}
if(item.reportNumber || item.issue || item.seriesNumber) {
writeField("number", item.reportNumber || item.issue || item.seriesNumber);
}
if(item.publicationTitle) {
if(item.itemType == "bookSection" || item.itemType == "conferencePaper") {
writeField("booktitle", item.publicationTitle);
} else {
writeField("journal", item.publicationTitle);
}
}
if(item.publisher) {
if(item.itemType == "thesis") {
writeField("school", item.publisher);
} else if(item.itemType =="report") {
writeField("institution", item.publisher);
} else {
writeField("publisher", item.publisher);
}
}
if(item.creators && item.creators.length) {
// split creators into subcategories
var author = "";
var editor = "";
var translator = "";
for(var i in item.creators) {
var creator = item.creators[i];
var creatorString = creator.lastName;
if (creator.firstName) {
creatorString = creator.lastName + ", " + creator.firstName;
}
if (creator.creatorType == "editor") {
editor += " and "+creatorString;
} else if (creator.creatorType == "translator") {
translator += " and "+creatorString;
} else {
author += " and "+creatorString;
}
}
if(author) {
writeField("author", author.substr(5));
}
if(editor) {
writeField("editor", editor.substr(5));
}
if(translator) {
writeField("translator", translator.substr(5));
}
}
if(item.date) {
var date = Zotero.Utilities.strToDate(item.date);
// need to use non-localized abbreviation
if(typeof date.month == "number") {
writeField("month", months[date.month], true);
}
if(date.year) {
writeField("year", date.year);
}
}
if(item.extra) {
writeField("note", item.extra);
}
if(item.tags && item.tags.length) {
var tagString = "";
for(var i in item.tags) {
var tag = item.tags[i];
tagString += ", "+tag.tag;
}
writeField("keywords", tagString.substr(2));
}
if(item.pages) {
writeField("pages", item.pages.replace("-","--"));
}
// Commented out, because we don't want a books number of pages in the BibTeX "pages" field for books.
//if(item.numPages) {
// writeField("pages", item.numPages);
//}
if(item.itemType == "webpage") {
writeField("howpublished", item.url);
}
if (item.notes && Zotero.getOption("exportNotes")) {
for(var i in item.notes) {
var note = item.notes[i];
writeField("annote", Zotero.Utilities.unescapeHTML(note["note"]));
}
}
// -- Tan: export local file paths if users wish
if(exportLocalFilePath || Zotero.getOption("exportFileData")) {
if(item.attachments) {
var attachmentString = "";
for(var i in item.attachments) {
var attachment = item.attachments[i];
if(attachment.defaultPath && Zotero.getOption("exportFileData")) { // For Zotero 3.0
attachment.saveFile(attachment.defaultPath, true);
attachmentString += ";" + attachment.title + ":" + attachment.defaultPath + ":" + attachment.mimeType;
} else if(attachment.path) { // For Zotero 2.1
attachmentString += ";" + attachment.title + ":" + attachment.path + ":" + attachment.mimeType;
}
}
if(attachmentString) {
writeField("file", attachmentString.substr(1));
}
}
}
Zotero.write("\n}");
}
}
/** BEGIN TEST CASES **/
var testCases = [
{
"type": "import",
"input": "@article{Adams2001,\u000aauthor = {Adams, Nancy K and DeSilva, Shanaka L and Self, Steven and Salas, Guido and Schubring, Steven and Permenter, Jason L and Arbesman, Kendra},\u000afile = {:Users/heatherwright/Documents/Scientific Papers/Adams\\_Huaynaputina.pdf:pdf;::},\u000ajournal = {Bulletin of Volcanology},\u000akeywords = {Vulcanian eruptions,breadcrust,plinian},\u000apages = {493--518},\u000atitle = {{The physical volcanology of the 1600 eruption of Huaynaputina, southern Peru}},\u000avolume = {62},\u000ayear = {2001}\u000a}",
"items": [
{
"itemType": "journalArticle",
"creators": [
{
"firstName": "Nancy K",
"lastName": "Adams",
"creatorType": "author"
},
{
"firstName": "Shanaka L",
"lastName": "DeSilva",
"creatorType": "author"
},
{
"firstName": "Steven",
"lastName": "Self",
"creatorType": "author"
},
{
"firstName": "Guido",
"lastName": "Salas",
"creatorType": "author"
},
{
"firstName": "Steven",
"lastName": "Schubring",
"creatorType": "author"
},
{
"firstName": "Jason L",
"lastName": "Permenter",
"creatorType": "author"
},
{
"firstName": "Kendra",
"lastName": "Arbesman",
"creatorType": "author"
}
],
"notes": [],
"tags": [
"Vulcanian eruptions",
"breadcrust",
"plinian"
],
"seeAlso": [],
"attachments": [
{
"url": "file://Users/heatherwright/Documents/Scientific Papers/Adams_Huaynaputina.pdf",
"mimeType": "application/pdf",
"title": "Attachment",
"downloadable": true
},
{
"url": "file://",
"title": "Attachment",
"downloadable": true
}
],
"publicationTitle": "Bulletin of Volcanology",
"pages": "493–518",
"title": "The physical volcanology of the 1600 eruption of Huaynaputina, southern Peru",
"volume": "62",
"date": "2001"
}
]
},
{
"type": "import",
"input": "@Book{abramowitz+stegun,\u000a author = \"Milton {Abramowitz} and Irene A. {Stegun}\",\u000a title = \"Handbook of Mathematical Functions with\u000a Formulas, Graphs, and Mathematical Tables\",\u000a publisher = \"Dover\",\u000a year = 1964,\u000a address = \"New York\",\u000a edition = \"ninth Dover printing, tenth GPO printing\"\u000a}\u000a\u000a@Book{Torre2008,\u000a author = \"Joe Torre and Tom Verducci\",\u000a publisher = \"Doubleday\",\u000a title = \"The Yankee Years\",\u000a year = 2008,\u000a isbn = \"0385527403\"\u000a}\u000a",
"items": [
{
"itemType": "book",
"creators": [
{
"firstName": "Milton",
"lastName": "Abramowitz",
"creatorType": "author"
},
{
"firstName": "Irene A.",
"lastName": "Stegun",
"creatorType": "author"
}
],
"notes": [],
"tags": [],
"seeAlso": [],
"attachments": [],
"title": "Handbook of Mathematical Functions with Formulas, Graphs, and Mathematical Tables",
"publisher": "Dover",
"date": "1964",
"place": "New York",
"edition": "ninth Dover printing, tenth GPO printing"
},
{
"itemType": "book",
"creators": [
{
"firstName": "Joe",
"lastName": "Torre",
"creatorType": "author"
},
{
"firstName": "Tom",
"lastName": "Verducci",
"creatorType": "author"
}
],
"notes": [],
"tags": [],
"seeAlso": [],
"attachments": [],
"publisher": "Doubleday",
"title": "The Yankee Years",
"date": "2008",
"ISBN": "0385527403"
}
]
},
{
"type": "import",
"input": "@INPROCEEDINGS {author:06,\u000a title = {Some publication title},\u000a author = {First Author and Second Author},\u000a crossref = {conference:06},\u000a pages = {330—331},\u000a}\u000a@PROCEEDINGS {conference:06,\u000a editor = {First Editor and Second Editor},\u000a title = {Proceedings of the Xth Conference on XYZ},\u000a booktitle = {Proceedings of the Xth Conference on XYZ},\u000a year = {2006},\u000a month = oct,\u000a}",
"items": [
{
"itemType": "conferencePaper",
"creators": [
{
"firstName": "First",
"lastName": "Author",
"creatorType": "author"
},
{
"firstName": "Second",
"lastName": "Author",
"creatorType": "author"
},
{
"firstName": "First",
"lastName": "Editor",
"creatorType": "editor"
},
{
"firstName": "Second",
"lastName": "Editor",
"creatorType": "editor"
}
],
"notes": [],
"tags": [],
"seeAlso": [],
"attachments": [],
"title": "Some publication title",
"date": "October 2006",
"proceedingsTitle": "Proceedings of the Xth Conference on XYZ",
"pages": "330—331"
},
{
"itemType": "book",
"creators": [
{
"firstName": "First",
"lastName": "Editor",
"creatorType": "editor"
},
{
"firstName": "Second",
"lastName": "Editor",
"creatorType": "editor"
}
],
"notes": [],
"tags": [],
"seeAlso": [],
"attachments": [],
"title": "Proceedings of the Xth Conference on XYZ",
"publicationTitle": "Proceedings of the Xth Conference on XYZ",
"date": "October 2006"
}
]
},
{
"type": "import",
"input": "@Book{hicks2001,\u000a author = \"von Hicks, III, Michael\",\u000a title = \"Design of a Carbon Fiber Composite Grid Structure for the GLAST\u000a Spacecraft Using a Novel Manufacturing Technique\",\u000a publisher = \"Stanford Press\",\u000a year = 2001,\u000a address = \"Palo Alto\",\u000a edition = \"1st,\",\u000a isbn = \"0-69-697269-4\"\u000a}",
"items": [
{
"itemType": "book",
"creators": [
{
"firstName": "Michael",
"lastName": "von Hicks, III",
"creatorType": "author"
}
],
"notes": [],
"tags": [],
"seeAlso": [],
"attachments": [],
"title": "Design of a Carbon Fiber Composite Grid Structure for the GLAST Spacecraft Using a Novel Manufacturing Technique",
"publisher": "Stanford Press",
"date": "2001",
"place": "Palo Alto",
"edition": "1st,",
"ISBN": "0-69-697269-4"
}
]
},
{
"type": "import",
"input": "@article{Oliveira_2009, title={USGS monitoring ecological impacts}, volume={107}, number={29}, journal={Oil & Gas Journal}, author={Oliveira, A}, year={2009}, pages={29}}",
"items": [
{
"itemType": "journalArticle",
"creators": [
{
"firstName": "A",
"lastName": "Oliveira",
"creatorType": "author"
}
],
"notes": [],
"tags": [],
"seeAlso": [],
"attachments": [],
"title": "USGS monitoring ecological impacts",
"volume": "107",
"issue": "29",
"publicationTitle": "Oil & Gas Journal",
"date": "2009",
"pages": "29"
}
]
},
{
"type": "import",
"input": "@article{test-ticket1661,\u000atitle={non-braking space: ~; accented characters: {\\~n} and \\~{n}; tilde operator: \\~},\u000a} ",
"items": [
{
"itemType": "journalArticle",
"creators": [],
"notes": [],
"tags": [],
"seeAlso": [],
"attachments": [],
"title": "non-braking space: ; accented characters: ñ and ñ; tilde operator: ∼"
}
]
}
]
/** END TEST CASES **/
--- BibTeX.js 2012-03-15 16:38:11.000000000 -0400
+++ BibTeXTan.js 2012-03-15 18:32:45.000000000 -0400
@@ -1,21 +1,55 @@
{
- "translatorID": "9cb70025-a888-4a29-a210-93ec52da40d4",
- "label": "BibTeX",
- "creator": "Simon Kornblith and Richard Karnesky",
+ "translatorID": "1234567",
+ "label": "BibTeX Tan-Revised",
+ "creator": "Simon Kornblith and Richard Karnesky with tweaks by Tan",
"target": "bib",
"minVersion": "2.1.9",
"maxVersion": "",
"priority": 200,
"displayOptions": {
- "exportCharset": "UTF-8",
+ "exportCharset": "ISO-8859-1",
"exportNotes": true,
"exportFileData": false
},
- "inRepository": true,
+ "inRepository": false,
"translatorType": 3,
"browserSupport": "gcs",
"lastUpdated": "2011-08-16 15:07:38"
}
+// "exportCharset":"ISO-8859-1", unicode not working well with latex editor
+
+// -- Tan --begin: read Key Format Strings and Field from prefs.
+/*
+1. A general matching element is % followed by a two-letter label: for
+ matching field and specifying the lower/upper case for 1st/remaining letters.
+2. Then it can be optionally followed by a number for the maximum length in
+ number of characters. (default=0: means all characters)
+3. Last it can be also optionally followed by a number within curly brackets
+ for selecting the n-th word of the field (start from 0-th, the default).
+4. The special repitive 2-letter labels like %TT, %aa, and %JJ are to group
+ the first letters only of surnames/words in corresponding fields.
+5. Separators/indicators including +,-,:,., etc, and all letters and numbers
+ can be used in between the elements.
+Collision Format: %a for alphabetic suffix, %n for numeric suffix
+Specified Key Field: e.g. callNumber for using the stored key
+Some examples:
+ %au4%yr2%tt2 %AU_%yr_%TI %Au4-%Au4{1}:%JJ%yr:Vol%vo:Pg%pg-%pg{1}
+%Au4{1} = first 4 letters of 2nd creator's surname (first letter capitalized)
+%ti6{2} = first 6 letters of 3rd word in title (all lowercase)
+%AA4 = initials of first 4 creators' surnames (uppercase)
+%tt6 = first letters of first 6 words in title (lowercase)
+%JJ5 = first letters of first 5 words in journal name (uppercase)
+%yr = %yr4 = four-digit year, %yr2 = two-digit year
+%vo = volume number
+%pg = first page number
+%pg{1} = last page number
+*/
+var citeKeyFormat = Zotero.getPrefs("bibtexKeyFormat") ? Zotero.getPrefs("bibtexKeyFormat") : "%au%yr%ti";
+var citeKeyCollisionFormat = Zotero.getPrefs("bibtexKeyCollisionFormat") ? Zotero.getPrefs("bibtexKeyCollisionFormat") : "-%n";
+var citeKeyField = Zotero.getPrefs("bibtexKeyField"); //e.g. callNumber
+var exportLocalFilePath = Zotero.getPrefs("bibtexExportLocalFilePath"); // default=no
+var preserveLatex = Zotero.getPrefs("bibtexPreserveLatex"); // default=no
+// -- Tan --end
function detectImport() {
var maxChars = 1048576; // 1MB
@@ -59,11 +93,6 @@
}
}
-//%a = first author surname
-//%y = year
-//%t = first word of title
-var citeKeyFormat = "%a_%t_%y";
-
var fieldMap = {
address:"place",
chapter:"section",
@@ -206,6 +235,48 @@
"\u0374":"'", // GREEK NUMERAL SIGN
"\u0375":",", // GREEK LOWER NUMERAL SIGN
"\u037E":";", // GREEK QUESTION MARK
+// -- Tan -begin greek symbols
+ "\u0393":"$\\Gamma$", // GREEK Gamma
+ "\u0394":"$\\Delta$", // GREEK Delta
+ "\u0398":"$\\Theta$", // GREEK Theta
+ "\u039B":"$\\Lambda$", // GREEK Lambda
+ "\u039E":"$\\Xi$", // GREEK Xi
+ "\u03A0":"$\\Pi$", // GREEK Pi
+ "\u03A3":"$\\Sigma$", // GREEK Sigma
+ "\u03A6":"$\\Phi$", // GREEK Phi
+ "\u03A8":"$\\Psi$", // GREEK Psi
+ "\u03A9":"$\\Omega$", // GREEK Omega
+ "\u03B1":"$\\alpha$", // GREEK alpha
+ "\u03B2":"$\\beta$", // GREEK beta
+ "\u03B3":"$\\gamma$", // GREEK gamma
+ "\u03B4":"$\\delta$", // GREEK delta
+ "\u03B5":"$\\varepsilon$", // GREEK var-epsilon
+ "\u03B6":"$\\zeta$", // GREEK zeta
+ "\u03B7":"$\\eta$", // GREEK eta
+ "\u03B8":"$\\theta$", // GREEK theta
+ "\u03B9":"$\\iota$", // GREEK iota
+ "\u03BA":"$\\kappa$", // GREEK kappa
+ "\u03BB":"$\\lambda$", // GREEK lambda
+ "\u03BC":"$\\mu$", // GREEK mu
+ "\u03BD":"$\\nu$", // GREEK nu
+ "\u03BE":"$\\xi$", // GREEK xi
+ "\u03C0":"$\\pi$", // GREEK pi
+ "\u03C1":"$\\rho$", // GREEK rho
+ "\u03C2":"$\\varsigma$", // GREEK var-sigma
+ "\u03C3":"$\\sigma$", // GREEK sigma
+ "\u03C4":"$\\tau$", // GREEK tau
+ "\u03C5":"$\\upsilon$", // GREEK upsilon
+ "\u03C6":"$\\varphi$", // GREEK var-phi
+ "\u03C7":"$\\chi$", // GREEK chi
+ "\u03C8":"$\\psi$", // GREEK psi
+ "\u03C9":"$\\omega$", // GREEK omega
+ "\u03D1":"$\\vartheta$", // GREEK var-theta
+ "\u03D2":"$\\Upsilon$", // GREEK Upsilon
+ "\u03D5":"$\\phi$", // GREEK phi
+ "\u03D6":"$\\varpi$", // GREEK var-pi
+ "\u03F1":"$\\varrho$", // GREEK var-rho
+ "\u03F5":"$\\epsilon$", // GREEK epsilon
+// -- Tan -end greek symbols
"\u2000":" ", // EN QUAD
"\u2001":" ", // EM QUAD
"\u2002":" ", // EN SPACE
@@ -1115,6 +1186,48 @@
"{\\textasciicircum}" : "\u02C6", // MODIFIER LETTER CIRCUMFLEX ACCENT
// "\\~{}" : "\u02DC", // SMALL TILDE
"{\\textacutedbl}" : "\u02DD", // DOUBLE ACUTE ACCENT
+// -- Tan -begin greek symbols
+ "$\\Gamma$" : "\u0393", // GREEK Gamma
+ "$\\Delta$" : "\u0394", // GREEK Delta
+ "$\\Theta$" : "\u0398", // GREEK Theta
+ "$\\Lambda$" : "\u039B", // GREEK Lambda
+ "$\\Xi$" : "\u039E", // GREEK Xi
+ "$\\Pi$" : "\u03A0", // GREEK Pi
+ "$\\Sigma$" : "\u03A3", // GREEK Sigma
+ "$\\Phi$" : "\u03A6", // GREEK Phi
+ "$\\Psi$" : "\u03A8", // GREEK Psi
+ "$\\Omega$" : "\u03A9", // GREEK Omega
+ "$\\alpha$" : "\u03B1", // GREEK alpha
+ "$\\beta$" : "\u03B2", // GREEK beta
+ "$\\gamma$" : "\u03B3", // GREEK gamma
+ "$\\delta$" : "\u03B4", // GREEK delta
+ "$\\varepsilon$": "\u03B5", // GREEK var-epsilon
+ "$\\zeta$" : "\u03B6", // GREEK zeta
+ "$\\eta$" : "\u03B7", // GREEK eta
+ "$\\theta$" : "\u03B8", // GREEK theta
+ "$\\iota$" : "\u03B9", // GREEK iota
+ "$\\kappa$" : "\u03BA", // GREEK kappa
+ "$\\lambda$" : "\u03BB", // GREEK lambda
+ "$\\mu$" : "\u03BC", // GREEK mu
+ "$\\nu$" : "\u03BD", // GREEK nu
+ "$\\xi$" : "\u03BE", // GREEK xi
+ "$\\pi$" : "\u03C0", // GREEK pi
+ "$\\rho$" : "\u03C1", // GREEK rho
+ "$\\varsigma$" : "\u03C2", // GREEK var-sigma
+ "$\\sigma$" : "\u03C3", // GREEK sigma
+ "$\\tau$" : "\u03C4", // GREEK tau
+ "$\\upsilon$" : "\u03C5", // GREEK upsilon
+ "$\\varphi$" : "\u03C6", // GREEK var-phi
+ "$\\chi$" : "\u03C7", // GREEK chi
+ "$\\psi$" : "\u03C8", // GREEK psi
+ "$\\omega$" : "\u03C9", // GREEK omega
+ "$\\vartheta$" : "\u03D1", // GREEK var-theta
+ "$\\Upsilon$" : "\u03D2", // GREEK Upsilon
+ "$\\phi$" : "\u03D5", // GREEK phi
+ "$\\varpi$" : "\u03D6", // GREEK var-pi
+ "$\\varrho$" : "\u03F1", // GREEK var-rho
+ "$\\epsilon$" : "\u03F5", // GREEK epsilon
+// -- Tan -end greek symbols
"{\\textendash}" : "\u2013", // EN DASH
"{\\textemdash}" : "\u2014", // EM DASH
"---" : "\u2014", // EM DASH
@@ -1858,7 +1971,13 @@
// Other fields (DOI?) may need similar treatment
if(!((field == "url") || (field == "doi") | (field == "file"))) {
// I hope these are all the escape characters!
- value = value.replace(/[|\<\>\~\^\\]/g, mapEscape).replace(/([\#\$\%\&\_])/g, "\\$1");
+// -- Tan --begin: preserve common latex markups ^,_,\,$ if users wish
+ if(preserveLatex) {
+ value = value.replace(/[|\<\>\~]/g, mapEscape).replace(/([\#\%\&])/g, "\\$1").replace(/([\s]+)([\$][0-9\.\,\-]+[\s]+)/g, "$1\\$2");
+ } else {
+ value = value.replace(/[|\<\>\~\^\\]/g, mapEscape).replace(/([\#\$\%\&\_])/g, "\\$1");
+ }
+// -- Tan --end
// Case of words with uppercase characters in non-initial positions is preserved with braces.
if(!isMacro&&field != "pages") value = value.replace(/([^\s]+[A-Z][^\s,]*)/g, "{$1}");
}
@@ -1904,31 +2023,132 @@
// 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 citeKeyTitleBannedMoreRe = /\b(about|and|are|as|at|be|by|can|does|for|has|have|if|into|onto|is|it|its|or|that|these|this|those|via|was|were)(\s+|\b)/g; // -- Tan : more banned words
+var citeKeyJournalBannedRe = /\b(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; // -- Tan: no 'a' for journal names
+var citeKeyConversionsRe = /%([a-zA-Z]{2})([0-9]*)[\{]?([0-9]*)[\}]?/; // -- Tan: new key format string
+var citeKeyCleanRe = /[^a-zA-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,"");
+// -- Tan --begin: new 2-letter conversion functions
+// for creators, title, journal, year, volume, pages. Do we need more?
+ "AU":function (label, maxlength, num, item) {
+ if(item.creators && item.creators[num] && item.creators[num].lastName) {
+ var auth = item.creators[num].lastName.toLowerCase().replace(/[\s\'\,]/g,"");
+ auth = tidyAccents(auth);
+ if(label == label.toUpperCase()) {
+ auth = auth.toUpperCase();
+ } else if(label[0] == label[0].toUpperCase()) {
+ auth = auth[0].toUpperCase() + auth.substr(1);
+ }
+ if (maxlength && auth.length > maxlength) {
+ return auth.substr(0,maxlength);
+ } else {
+ return auth;
+ }
+ }
+ return "";
+ },
+ "AA":function (label, maxlength, num, item) {
+ if(item.creators) {
+ var initials = "";
+ var len = item.creators.length;
+ len = (len > maxlength) ? maxlength : len;
+ for (var i=0; i<len; i++) {
+ var auth = item.creators[i].lastName.toLowerCase().replace(/[\s\'\,]/g,"");
+ auth = tidyAccents(auth);
+ initials = initials + auth[0];
+ }
+ if(label == label.toUpperCase()) {
+ initials = initials.toUpperCase();
+ }
+ return initials;
+ }
+ return "";
+ },
+ "TI":function (label, maxlength, num, item) {
+ if (item["title"]) {
+ var tit = tidyAccents(item["title"].toLowerCase().replace(citeKeyTitleBannedRe,"").replace(citeKeyTitleBannedMoreRe,"")).replace(/[^a-z\-\s]+/g,"").split(/\s+/g);
+ if (tit.length > num) {
+ var word = tit[num];
+ if(label == label.toUpperCase()) {
+ word = word.toUpperCase();
+ } else if(label[0] == label[0].toUpperCase()) {
+ word = word[0].toUpperCase() + word.substr(1);
+ }
+ if (maxlength && word.length > maxlength) {
+ return word.substr(0,maxlength);
+ } else {
+ return word;
+ }
+ }
}
return "";
},
- "t":function (flags, item) {
+ "TT":function (label, maxlength, num, item) {
if (item["title"]) {
- return item["title"].toLowerCase().replace(citeKeyTitleBannedRe, "").split(/\s+/g)[0];
+ var tit = tidyAccents(item["title"].toLowerCase().replace(citeKeyTitleBannedRe,"").replace(citeKeyTitleBannedMoreRe,"")).replace(/[^a-z\s]+/g,"").replace(/\b([a-z])[a-z]+\b/g,"$1");
+ tit = tit.replace(/\s+/g,""); // first letter of each title word
+ if(label == label.toUpperCase()) {
+ tit = tit.toUpperCase();
+ }
+ if (maxlength && tit.length > maxlength) {
+ return tit.substr(0,maxlength);
+ } else {
+ return tit;
+ }
}
return "";
},
- "y":function (flags, item) {
+ "YR":function (label, maxlength, num, item) {
if(item.date) {
var date = Zotero.Utilities.strToDate(item.date);
if(date.year && numberRe.test(date.year)) {
- return date.year;
+ if(maxlength == 2) {
+ return date.year.toString().substr(2);
+ } else {
+ return date.year;
+ }
+
}
}
- return "????";
+ if(maxlength == 2) {
+ return "??";
+ } else {
+ return "????";
+ }
+ },
+ "JJ":function (label, maxlength, num, item) {
+ if (item.publicationTitle) {
+ var jou = tidyAccents(item.publicationTitle.toLowerCase().replace(citeKeyJournalBannedRe,"").replace(citeKeyTitleBannedMoreRe,"")).replace(/[^a-z\-\s]+/g,"").replace(/\b([a-z\-])[a-z\-]+\b/g,"$1");
+ jou = jou.replace(/\s+/g,""); // first letter of each journal word
+ if(label == label.toUpperCase()) {
+ jou = jou.toUpperCase();
+ }
+ if (maxlength && jou.length > maxlength) {
+ return jou.substr(0,maxlength);
+ } else {
+ return jou;
+ }
+ }
+ return "";
+ },
+ "VO":function (label, maxlength, num, item) {
+ if (item.volume) {
+ return item.volume;
+ }
+ return "";
+ },
+ "PG":function (label, maxlength, num, item) {
+ if (item.pages) {
+ if(num) { // last page number
+ return (item.pages.lastIndexOf("-") == -1) ? "" : item.pages.substr(item.pages.lastIndexOf("-")+1);
+ } else {
+ return item.pages.replace(/\-.*/g,""); // first page number
+ }
+ }
+ return "";
}
+// -- Tan --end
}
@@ -1946,15 +2166,18 @@
//add data before the conversion match to basekey
basekey = basekey + citeKeyFormatRemaining.substr(0, m.index);
}
- var flags = ""; // for now
- var f = citeKeyConversions[m[1]];
+
+ var label = m[1];
+ var maxlength = m[2] ? parseInt(m[2]) : 0;
+ var num = m[3] ? parseInt(m[3]) : 0;
+ var f = citeKeyConversions[label.toUpperCase()];
if (typeof(f) == "function") {
- var value = f(flags, item);
+ var value = f(label, maxlength, num, item);
Zotero.debug("Got value " + value + " for %" + m[1]);
//add conversion to basekey
basekey = basekey + value;
}
- citeKeyFormatRemaining = citeKeyFormatRemaining.substr(m.index + m.length);
+ citeKeyFormatRemaining = citeKeyFormatRemaining.substr(m.index + m[0].length);
counter++;
}
if (citeKeyFormatRemaining.length > 0) {
@@ -1969,17 +2192,42 @@
// " # % ' ( ) , = { } ~ and backslash
// however, we want to keep the base characters
- basekey = tidyAccents(basekey);
+// basekey = tidyAccents(basekey); // -- Tan: deal with in the individual matching
basekey = basekey.replace(citeKeyCleanRe, "");
+ var citekey = resolveCiteKeyCollision(basekey,citekeys); // -- Tan: separate the function
+ return citekey;
+}
+
+// -- Tan --begin: allow alphabetic suffix for key collisions
+function resolveCiteKeyCollision(basekey,citekeys) {
var citekey = basekey;
var i = 0;
- while(citekeys[citekey]) {
- i++;
- citekey = basekey + "-" + i;
+ var ii = 0;
+ var iii = 0;
+ var suffix = citeKeyCollisionFormat.match(/([^\%]*)%([a-zA-Z0-9])/);
+ if(suffix) {
+ var sepmark = suffix[1].replace(citeKeyCleanRe, "");
+ while(citekeys[citekey]) {
+ i++;
+ if (i > 600) {
+ Zotero.debug("Pathological BibTeX key format: " + citeKeyFormat + " causing too many cite key collisions");
+ break;
+ }
+ if(suffix[2].toLowerCase() == "a") {
+ ii = Math.floor((i-1)/26);
+ iii = i - ii*26;
+ citekey = basekey + sepmark + (ii ? String.fromCharCode(96+ii) : "") + String.fromCharCode(96+iii);
+ } else {
+ citekey = basekey + sepmark + i;
+ }
+ }
+ } else {
+ Zotero.debug("Bad BibTeX key collision format: " + citeKeyCollisionFormat);
}
citekeys[citekey] = true;
return citekey;
}
+// -- Tan --end
function doExport() {
//Zotero.write("% BibTeX export generated by Zotero "+Zotero.Utilities.getVersion());
@@ -1996,12 +2244,18 @@
if(!type) type = "misc";
// create a unique citation key
- var citekey = buildCiteKey(item, citekeys);
-
+// -- Tan --begin: user's own field for bibtex key (e.g., callNumber)
+ if (item[citeKeyField]) {
+ var citekey = resolveCiteKeyCollision(item[citeKeyField],citekeys);
+ } else {
+ var citekey = buildCiteKey(item, citekeys);
+ }
+// -- Tan --end
+
// write citation key
Zotero.write((first ? "" : ",\n\n") + "@"+type+"{"+citekey);
first = false;
-
+
for(var field in fieldMap) {
if(item[fieldMap[field]]) {
writeField(field, item[fieldMap[field]]);
@@ -2106,13 +2360,14 @@
}
}
- if(Zotero.getOption("exportFileData")) {
+// -- Tan: export local file paths if users wish
+ if(exportLocalFilePath || Zotero.getOption("exportFileData")) {
if(item.attachments) {
var attachmentString = "";
for(var i in item.attachments) {
var attachment = item.attachments[i];
- if(attachment.defaultPath) { // For Zotero 3.0
+ if(attachment.defaultPath && Zotero.getOption("exportFileData")) { // For Zotero 3.0
attachment.saveFile(attachment.defaultPath, true);
attachmentString += ";" + attachment.title + ":" + attachment.defaultPath + ":" + attachment.mimeType;
} else if(attachment.path) { // For Zotero 2.1
--- BibTeXTan.js 2012-03-15 18:32:45.000000000 -0400
+++ BibTeXKeyOnly.js 2012-03-16 16:31:37.000000000 -0400
@@ -1,22 +1,21 @@
{
- "translatorID": "1234567",
- "label": "BibTeX Tan-Revised",
+ "translatorID": "12345",
+ "label": "BibTeX CiteKey-only Exporter",
"creator": "Simon Kornblith and Richard Karnesky with tweaks by Tan",
"target": "bib",
"minVersion": "2.1.9",
"maxVersion": "",
"priority": 200,
- "displayOptions": {
- "exportCharset": "ISO-8859-1",
- "exportNotes": true,
- "exportFileData": false
- },
"inRepository": false,
"translatorType": 3,
"browserSupport": "gcs",
"lastUpdated": "2011-08-16 15:07:38"
}
-// "exportCharset":"ISO-8859-1", unicode not working well with latex editor
+/*
+A hack similar to what Andrew Leifer did so that Zotero will Drag & Drop
+citations in the latex form of "\cite{key1,key2,...}". The difference from
+the full version is to have the output of doExport() cleaned out.
+*/
// -- Tan --begin: read Key Format Strings and Field from prefs.
/*
@@ -2232,17 +2231,11 @@
function doExport() {
//Zotero.write("% BibTeX 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()) {
- // determine type
- var type = zotero2bibtexTypeMap[item.itemType];
- if (typeof(type) == "function") { type = type(item); }
- if(!type) type = "misc";
-
// create a unique citation key
// -- Tan --begin: user's own field for bibtex key (e.g., callNumber)
if (item[citeKeyField]) {
@@ -2253,136 +2246,10 @@
// -- Tan --end
// write citation key
- Zotero.write((first ? "" : ",\n\n") + "@"+type+"{"+citekey);
+ Zotero.write((first ? "\\cite{" : ", ") + citekey); // -- Tan
first = false;
-
- for(var field in fieldMap) {
- if(item[fieldMap[field]]) {
- writeField(field, item[fieldMap[field]]);
- }
- }
-
- if(item.reportNumber || item.issue || item.seriesNumber) {
- writeField("number", item.reportNumber || item.issue || item.seriesNumber);
- }
-
- if(item.publicationTitle) {
- if(item.itemType == "bookSection" || item.itemType == "conferencePaper") {
- writeField("booktitle", item.publicationTitle);
- } else {
- writeField("journal", item.publicationTitle);
- }
- }
-
- if(item.publisher) {
- if(item.itemType == "thesis") {
- writeField("school", item.publisher);
- } else if(item.itemType =="report") {
- writeField("institution", item.publisher);
- } else {
- writeField("publisher", item.publisher);
- }
- }
-
- if(item.creators && item.creators.length) {
- // split creators into subcategories
- var author = "";
- var editor = "";
- var translator = "";
- for(var i in item.creators) {
- var creator = item.creators[i];
- var creatorString = creator.lastName;
-
- if (creator.firstName) {
- creatorString = creator.lastName + ", " + creator.firstName;
- }
-
- if (creator.creatorType == "editor") {
- editor += " and "+creatorString;
- } else if (creator.creatorType == "translator") {
- translator += " and "+creatorString;
- } else {
- author += " and "+creatorString;
- }
- }
-
- if(author) {
- writeField("author", author.substr(5));
- }
- if(editor) {
- writeField("editor", editor.substr(5));
- }
- if(translator) {
- writeField("translator", translator.substr(5));
- }
- }
-
- if(item.date) {
- var date = Zotero.Utilities.strToDate(item.date);
- // need to use non-localized abbreviation
- if(typeof date.month == "number") {
- writeField("month", months[date.month], true);
- }
- if(date.year) {
- writeField("year", date.year);
- }
- }
-
- if(item.extra) {
- writeField("note", item.extra);
- }
-
- if(item.tags && item.tags.length) {
- var tagString = "";
- for(var i in item.tags) {
- var tag = item.tags[i];
- tagString += ", "+tag.tag;
- }
- writeField("keywords", tagString.substr(2));
- }
-
- if(item.pages) {
- writeField("pages", item.pages.replace("-","--"));
- }
-
- // Commented out, because we don't want a books number of pages in the BibTeX "pages" field for books.
- //if(item.numPages) {
- // writeField("pages", item.numPages);
- //}
-
- if(item.itemType == "webpage") {
- writeField("howpublished", item.url);
- }
- if (item.notes && Zotero.getOption("exportNotes")) {
- for(var i in item.notes) {
- var note = item.notes[i];
- writeField("annote", Zotero.Utilities.unescapeHTML(note["note"]));
- }
- }
-
-// -- Tan: export local file paths if users wish
- if(exportLocalFilePath || Zotero.getOption("exportFileData")) {
- if(item.attachments) {
- var attachmentString = "";
-
- for(var i in item.attachments) {
- var attachment = item.attachments[i];
- if(attachment.defaultPath && Zotero.getOption("exportFileData")) { // For Zotero 3.0
- attachment.saveFile(attachment.defaultPath, true);
- attachmentString += ";" + attachment.title + ":" + attachment.defaultPath + ":" + attachment.mimeType;
- } else if(attachment.path) { // For Zotero 2.1
- attachmentString += ";" + attachment.title + ":" + attachment.path + ":" + attachment.mimeType;
- }
- }
-
- if(attachmentString) {
- writeField("file", attachmentString.substr(1));
- }
- }
- }
-
- Zotero.write("\n}");
}
+ Zotero.write("}"); // -- Tan
}
/** BEGIN TEST CASES **/
/*
***** BEGIN LICENSE BLOCK *****
Copyright © 2009 Center for History and New Media
George Mason University, Fairfax, Virginia, USA
http://zotero.org
This file is part of Zotero.
Zotero is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Zotero is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
***** END LICENSE BLOCK *****
*/
/**
* @class
* Deprecated class for creating new Zotero.Translate instances<br/>
* <br/>
* New code should use Zotero.Translate.Web, Zotero.Translate.Import, Zotero.Translate.Export, or
* Zotero.Translate.Search
*/
Zotero.Translate = function(type) {
Zotero.debug("Translate: WARNING: new Zotero.Translate() is deprecated; please don't use this if you don't have to");
// hack
var translate = Zotero.Translate.newInstance(type);
for(var i in translate) {
this[i] = translate[i];
}
this.constructor = translate.constructor;
this.__proto__ = translate.__proto__;
}
/**
* Create a new translator by a string type
*/
Zotero.Translate.newInstance = function(type) {
return new Zotero.Translate[type.substr(0, 1).toUpperCase()+type.substr(1).toLowerCase()];
}
/**
* Namespace for Zotero sandboxes
* @namespace
*/
Zotero.Translate.Sandbox = {
/**
* Combines a sandbox with the base sandbox
*/
"_inheritFromBase":function(sandboxToMerge) {
var newSandbox = {};
for(var method in Zotero.Translate.Sandbox.Base) {
newSandbox[method] = Zotero.Translate.Sandbox.Base[method];
}
for(var method in sandboxToMerge) {
newSandbox[method] = sandboxToMerge[method];
}
return newSandbox;
},
/**
* Base sandbox. These methods are available to all translators.
* @namespace
*/
"Base": {
/**
* Called as {@link Zotero.Item#complete} from translators to save items to the database.
* @param {Zotero.Translate} translate
* @param {SandboxItem} An item created using the Zotero.Item class from the sandbox
*/
"_itemDone":function(translate, item) {
//Zotero.debug("Translate: Saving item");
// warn if itemDone called after translation completed
if(translate._complete) {
Zotero.debug("Translate: WARNING: Zotero.Item#complete() called after Zotero.done(); please fix your code", 2);
}
const allowedObjects = ["complete", "attachments", "seeAlso", "creators", "tags", "notes"];
for(var i in item) {
var val = item[i];
var type = typeof val;
if(!val && val !== 0) {
// remove null, undefined, and false properties, and convert objects to strings
delete item[i];
} else if(type === "string") {
// trim strings
item[i] = val.trim();
} else if((type === "object" || type === "xml") && allowedObjects.indexOf(i) === -1) {
// convert things that shouldn't be objecst to objects
translate._debug("Translate: WARNING: typeof "+i+" is "+type+"; converting to string");
item[i] = val.toString();
}
}
// if we're not supposed to save the item or we're in a child translator,
// just return the item array
if(translate._libraryID === false || translate._parentTranslator) {
translate.newItems.push(item);
translate._runHandler("itemDone", item, item);
return;
}
// We use this within the connector to keep track of items as they are saved
if(!item.id) item.id = Zotero.Utilities.randomString();
// don't save documents as documents in connector, since we can't pass them around
if(Zotero.isConnector) {
var attachments = item.attachments;
var nAttachments = attachments.length;
for(var j=0; j<nAttachments; j++) {
if(attachments[j].document) {
attachments[j].url = attachments[j].document.location.href;
delete attachments[j].document;
}
}
}
if(translate instanceof Zotero.Translate.Web) {
// For web translators, we queue saves
translate.saveQueue.push(item);
translate._runHandler("itemSaving", item);
} else {
var newItem;
translate._itemSaver.saveItems([item], function(returnValue, data) {
if(returnValue) {
newItem = data[0];
translate.newItems.push(newItem);
} else {
translate.complete(false, data);
throw data;
}
});
translate._runHandler("itemSaving", item);
// pass both the saved item and the original JS array item
translate._runHandler("itemDone", newItem, item);
}
},
/**
* Gets translator options that were defined in displayOptions in translator header
*
* @param {Zotero.Translate} translate
* @param {String} option Option to be retrieved
*/
"getOption":function(translate, option) {
if(typeof option !== "string") {
throw(new Error("getOption: option must be a string"));
return;
}
return translate._displayOptions[option];
},
"getPrefs":function(translate, pref) {
if(typeof pref !== "string") {
throw("Translate: getPrefs: pref must be a string");
return;
}
return Zotero.Prefs.get("translator."+pref);
},
/**
* For loading other translators and accessing their methods
*
* @param {Zotero.Translate} translate
* @param {String} type Translator type ("web", "import", "export", or "search")
* @returns {Object} A safeTranslator object, which operates mostly like Zotero.Translate
*/
"loadTranslator":function(translate, type) {
const setDefaultHandlers = function(translate, translation) {
if(Zotero.Utilities.isEmpty(translation._handlers)) {
if(type !== "export") {
translation.setHandler("itemDone", function(obj, item) {
translate.Sandbox._itemDone(translate, item);
});
}
translation.setHandler("selectItems", translate._handlers["selectItems"]);
}
}
if(typeof type !== "string") {
throw(new Error("loadTranslator: type must be a string"));
return;
}
Zotero.debug("Translate: Creating translate instance of type "+type+" in sandbox");
var translation = Zotero.Translate.newInstance(type);
translation._parentTranslator = translate;
if(translation instanceof Zotero.Translate.Export && !(translation instanceof Zotero.Translate.Export)) {
throw(new Error("Only export translators may call other export translators"));
}
/**
* @class Wrapper for {@link Zotero.Translate} for safely calling another translator
* from inside an existing translator
* @inner
*/
var safeTranslator = {};
safeTranslator.__exposedProps__ = {
"setSearch":"r",
"setDocument":"r",
"setHandler":"r",
"setString":"r",
"setTranslator":"r",
"getTranslators":"r",
"translate":"r",
"getTranslatorObject":"r"
};
safeTranslator.setSearch = function(arg) {
if(Zotero.isFx4 && !Zotero.isBookmarklet) arg = JSON.parse(JSON.stringify(arg));
return translation.setSearch(arg);
};
safeTranslator.setDocument = function(arg) { return translation.setDocument(arg) };
var errorHandlerSet = false;
safeTranslator.setHandler = function(arg1, arg2) {
if(arg1 === "error") errorHandlerSet = true;
translation.setHandler(arg1,
function(obj, item) {
try {
if(arg1 == "itemDone") {
if(Zotero.isFx && !Zotero.isBookmarklet
&& (translate instanceof Zotero.Translate.Web
|| translate instanceof Zotero.Translate.Search)) {
// Necessary to get around object wrappers in Firefox
var attachments = item.attachments;
item.attachments = [];
item = translate._sandboxManager.sandbox.Zotero._transferItem(JSON.stringify(item));
// Manually copy attachments in case there are documents, which
// can't be serialized and don't need to be
if(attachments) {
for(var i=0; i<attachments.length; i++) {
var attachment = attachments[i];
var doc = (attachment.document ? attachment.document : undefined);
delete attachment.document;
attachment = translate._sandboxManager.sandbox.Zotero._transferItem(JSON.stringify(attachment));
if(doc) attachment.document = doc;
item.attachments.push(attachment);
}
}
} else {
// otherwise, just use parent translator's complete function
item.complete = translate._sandboxManager.sandbox.Zotero.Item.prototype.complete;
}
}
arg2(obj, item);
} catch(e) {
translate.complete(false, e);
}
}
);
};
safeTranslator.setString = function(arg) { translation.setString(arg) };
safeTranslator.setTranslator = function(arg) {
var success = translation.setTranslator(arg);
if(!success) {
throw new Error("Translator "+translate.translator[0].translatorID+" attempted to call invalid translatorID "+arg);
}
};
var translatorsHandlerSet = false;
safeTranslator.getTranslators = function(callback) {
if(!translation._handlers["translators"] || !translation._handlers["translators"].length) {
if(Zotero.isConnector) {
throw new Error('Translator must register a "translators" handler to '+
'call getTranslators() in this translation environment.');
} else {
translate._debug('COMPAT WARNING: Translator must register a "translators" handler to '+
'call getTranslators() in connector');
}
}
if(!translatorsHandlerSet) {
translation.setHandler("translators", function() {
translate.decrementAsyncProcesses("safeTranslator#getTranslators()");
});
}
translate.incrementAsyncProcesses("safeTranslator#getTranslators()");
return translation.getTranslators();
};
var doneHandlerSet = false;
safeTranslator.translate = function() {
translate.incrementAsyncProcesses("safeTranslator#translate()");
setDefaultHandlers(translate, translation);
if(!doneHandlerSet) {
doneHandlerSet = true;
translation.setHandler("done", function() { translate.decrementAsyncProcesses("safeTranslator#translate()") });
}
if(!errorHandlerSet) {
errorHandlerSet = true;
translation.setHandler("error", function(obj, error) { translate.complete(false, error) });
}
return translation.translate(false);
};
safeTranslator.getTranslatorObject = function(callback) {
if(callback) {
translate.incrementAsyncProcesses("safeTranslator#getTranslatorObject()");
} else {
translate._debug("COMPAT WARNING: Translator must pass a callback to getTranslatorObject() to operate in connector");
}
var sandbox;
var haveTranslatorFunction = function(translator) {
translation.translator[0] = translator;
translation._loadTranslator(translator, function() {
if(Zotero.isFx && !Zotero.isBookmarklet) {
// do same origin check
var secMan = Components.classes["@mozilla.org/scriptsecuritymanager;1"]
.getService(Components.interfaces.nsIScriptSecurityManager);
var ioService = Components.classes["@mozilla.org/network/io-service;1"]
.getService(Components.interfaces.nsIIOService);
var outerSandboxURI = ioService.newURI(typeof translate._sandboxLocation === "object" ?
translate._sandboxLocation.location : translate._sandboxLocation, null, null);
var innerSandboxURI = ioService.newURI(typeof translation._sandboxLocation === "object" ?
translation._sandboxLocation.location : translation._sandboxLocation, null, null);
try {
secMan.checkSameOriginURI(outerSandboxURI, innerSandboxURI, false);
} catch(e) {
throw new Error("getTranslatorObject() may not be called from web or search "+
"translators to web or search translators from different origins.");
}
}
translation._prepareTranslation();
setDefaultHandlers(translate, translation);
sandbox = translation._sandboxManager.sandbox;
if(!Zotero.Utilities.isEmpty(sandbox.exports)) {
sandbox.exports.Zotero = sandbox.Zotero;
sandbox = sandbox.exports;
} else {
translate._debug("COMPAT WARNING: "+translation.translator[0].label+" does "+
"not export any properties. Only detect"+translation._entryFunctionSuffix+
" and do"+translation._entryFunctionSuffix+" will be available in "+
"connectors.");
}
if(callback) {
try {
callback(sandbox);
} catch(e) {
translate.complete(false, e);
return;
}
translate.decrementAsyncProcesses("safeTranslator#getTranslatorObject()");
}
});
};
if(typeof translation.translator[0] === "object") {
haveTranslatorFunction(translation.translator[0]);
return translation._sandboxManager.sandbox;
} else {
if(Zotero.isConnector && (!Zotero.isFx || Zotero.isBookmarklet) && !callback) {
throw new Error("Translator must pass a callback to getTranslatorObject() to "+
"operate in this translation environment.");
}
Zotero.Translators.get(translation.translator[0], haveTranslatorFunction);
if(Zotero.isConnector && Zotero.isFx && !callback) {
while(!sandbox && translate._currentState) {
// This processNextEvent call is used to handle a deprecated case
Zotero.mainThread.processNextEvent(true);
}
}
if(sandbox) return sandbox;
}
};
// TODO security is not super-tight here, as someone could pass something into arg
// that gets evaluated in the wrong scope in Fx < 4. We should wrap this.
return safeTranslator;
},
/**
* Enables asynchronous detection or translation
* @param {Zotero.Translate} translate
* @deprecated
*/
"wait":function(translate) {},
/**
* Sets the return value for detection
*
* @param {Zotero.Translate} translate
*/
"done":function(translate, returnValue) {
if(translate._currentState === "detect") {
translate._returnValue = returnValue;
}
},
/**
* Proxy for translator _debug function
*
* @param {Zotero.Translate} translate
* @param {String} string String to write to console
* @param {String} [level] Level to log as (1 to 5)
*/
"debug":function(translate, string, level) {
translate._debug(string, level);
}
},
/**
* Web functions exposed to sandbox
* @namespace
*/
"Web":{
/**
* Lets user pick which items s/he wants to put in his/her library
* @param {Zotero.Translate} translate
* @param {Object} items An set of id => name pairs in object format
*/
"selectItems":function(translate, items, callback) {
if(Zotero.Utilities.isEmpty(items)) {
throw new Error("Translator called select items with no items");
}
if(translate._selectedItems) {
// if we have a set of selected items for this translation, use them
return translate._selectedItems;
} else if(translate._handlers.select) {
// whether the translator supports asynchronous selectItems
var haveAsyncCallback = !!callback;
// whether the handler operates asynchronously
var haveAsyncHandler = false;
var returnedItems = null;
var callbackExecuted = false;
if(haveAsyncCallback) {
// if this translator provides an async callback for selectItems, rig things
// up to pop off the async process
var newCallback = function(selectedItems) {
callbackExecuted = true;
callback(selectedItems);
if(haveAsyncHandler) translate.decrementAsyncProcesses("Zotero.selectItems()");
};
} else {
// if this translator doesn't provide an async callback for selectItems, set things
// up so that we can wait to see if the select handler returns synchronously. If it
// doesn't, we will need to restart translation.
var newCallback = function(selectedItems) {
callbackExecuted = true;
if(haveAsyncHandler) {
translate.translate(this._libraryID, this._saveAttachments, selectedItems);
} else {
returnedItems = selectedItems;
}
};
}
var returnValue = translate._runHandler("select", items, newCallback);
if(returnValue !== undefined) {
// handler may have returned a value, which makes callback unnecessary
Zotero.debug("WARNING: Returning items from a select handler is deprecated. "+
"Please pass items as to the callback provided as the third argument to "+
"the handler.");
returnedItems = returnValue;
haveAsyncHandler = false;
} else {
// if we don't have returnedItems set already, the handler is asynchronous
haveAsyncHandler = !callbackExecuted;
}
if(haveAsyncCallback) {
if(haveAsyncHandler) {
// we are running asynchronously, so increment async processes
translate.incrementAsyncProcesses("Zotero.selectItems()");
} else if(!callbackExecuted) {
// callback didn't get called from handler, so call it here
callback(returnedItems);
}
return false;
} else {
translate._debug("COMPAT WARNING: No callback was provided for "+
"Zotero.selectItems(). When executed outside of Firefox, a selectItems() call "+
"will require that this translator to be called multiple times.", 1);
if(haveAsyncHandler) {
// The select handler is asynchronous, but this translator doesn't support
// asynchronous select. We return false to abort translation in this
// instance, and we will restart it later when the selectItems call is
// complete.
translate._aborted = true;
return false;
} else {
return returnedItems;
}
}
} else { // no handler defined; assume they want all of them
if(callback) callback(items);
return items;
}
},
/**
* Overloads {@link Zotero.Translate.Sandbox.Base._itemDone} to ensure that no standalone
* items are saved, that an item type is specified, and to add a libraryCatalog and
* shortTitle if relevant.
* @param {Zotero.Translate} translate
* @param {SandboxItem} An item created using the Zotero.Item class from the sandbox
*/
"_itemDone":function(translate, item) {
if(!item.itemType) {
item.itemType = "webpage";
translate._debug("WARNING: No item type specified");
}
if(item.type == "attachment" || item.type == "note") {
Zotero.debug("Translate: Discarding standalone "+item.type+" in non-import translator", 2);
return;
}
// store library catalog if this item was captured from a website, and
// libraryCatalog is truly undefined (not false or "")
if(item.repository !== undefined) {
Zotero.debug("Translate: 'repository' field is now 'libraryCatalog'; please fix your code", 2);
item.libraryCatalog = item.repository;
delete item.repository;
}
// automatically set library catalog
if(item.libraryCatalog === undefined) {
item.libraryCatalog = translate.translator[0].label;
}
// automatically set access date if URL is set
if(item.url && typeof item.accessDate == 'undefined') {
item.accessDate = "CURRENT_TIMESTAMP";
}
if(!item.title) {
throw new Error("No title specified for item");
}
// create short title
if(item.shortTitle === undefined && Zotero.Utilities.fieldIsValidForType("shortTitle", item.itemType)) {
// only set if changes have been made
var setShortTitle = false;
var title = item.title;
// shorten to before first colon
var index = title.indexOf(":");
if(index !== -1) {
title = title.substr(0, index);
setShortTitle = true;
}
// shorten to after first question mark
index = title.indexOf("?");
if(index !== -1) {
index++;
if(index != title.length) {
title = title.substr(0, index);
setShortTitle = true;
}
}
if(setShortTitle) item.shortTitle = title;
}
// call super
Zotero.Translate.Sandbox.Base._itemDone(translate, item);
}
},
/**
* Import functions exposed to sandbox
* @namespace
*/
"Import":{
/**
* Saves a collection to the DB
* Called as {@link Zotero.Collection#complete} from the sandbox
* @param {Zotero.Translate} translate
* @param {SandboxCollection} collection
*/
"_collectionDone":function(translate, collection) {
if(translate._libraryID == false) {
translate.newCollections.push(collection);
translate._runHandler("collectionDone", collection);
} else {
var newCollection = translate._itemSaver.saveCollection(collection);
translate.newCollections.push(newCollection);
translate._runHandler("collectionDone", newCollection);
}
},
/**
* Sets the value of the progress indicator associated with export as a percentage
* @param {Zotero.Translate} translate
* @param {Number} value
*/
"setProgress":function(translate, value) {
if(typeof value !== "number") {
translate._progress = null;
} else {
translate._progress = value;
}
}
},
/**
* Export functions exposed to sandbox
* @namespace
*/
"Export":{
/**
* Retrieves the next item to be exported
* @param {Zotero.Translate} translate
* @return {SandboxItem}
*/
"nextItem":function(translate) {
var item = translate._itemGetter.nextItem();
if(translate._displayOptions.hasOwnProperty("exportTags") && !translate._displayOptions["exportTags"]) {
item.tags = [];
}
translate._runHandler("itemDone", item);
return item;
},
/**
* Retrieves the next collection to be exported
* @param {Zotero.Translate} translate
* @return {SandboxCollection}
*/
"nextCollection":function(translate) {
if(!translate.translator[0].configOptions.getCollections) {
throw(new Error("getCollections configure option not set; cannot retrieve collection"));
}
return translate._itemGetter.nextCollection();
},
/**
* @borrows Zotero.Translate.Sandbox.Import.setProgress as this.setProgress
*/
"setProgress":function(translate, value) {
Zotero.Translate.Sandbox.Import.setProgress(translate, value);
}
},
/**
* Search functions exposed to sandbox
* @namespace
*/
"Search":{
/**
* @borrows Zotero.Translate.Sandbox.Web._itemDone as this._itemDone
*/
"_itemDone":function(translate, item) {
Zotero.Translate.Sandbox.Web._itemDone(translate, item);
}
}
}
/**
* @class Base class for all translation types
*
* @property {String} type The type of translator. This is deprecated; use instanceof instead.
* @property {Zotero.Translator[]} translator The translator currently in use. Usually, only the
* first entry of the Zotero.Translator array is populated; subsequent entries represent
* translators to be used if the first fails.
* @property {String} path The path or URI string of the target
* @property {String} newItems Items created when translate() was called
* @property {String} newCollections Collections created when translate() was called
* @property {Number} runningAsyncProcesses The number of async processes that are running. These
* need to terminate before Zotero.done() is called.
*/
Zotero.Translate.Base = function() {}
Zotero.Translate.Base.prototype = {
/**
* Initializes a Zotero.Translate instance
*/
"init":function() {
this._handlers = [];
this._currentState = null;
this.document = null;
this.location = null;
},
/**
* Sets the location to operate upon
*
* @param {String|nsIFile} location The URL to which the sandbox should be bound or path to local file
*/
"setLocation":function(location) {
this.location = location;
if(typeof this.location == "object") { // if a file
this.path = location.path;
} else { // if a url
this.path = location;
}
},
/**
* Sets the translator to be used for import/export
*
* @param {Zotero.Translator|string} Translator object or ID
*/
"setTranslator":function(translator) {
if(!translator) {
throw new Error("No translator specified");
}
this.translator = null;
this._setDisplayOptions = null;
if(typeof(translator) == "object") { // passed an object and not an ID
if(translator.translatorID) {
this.translator = [translator];
} else {
throw(new Error("No translatorID specified"));
}
} else {
this.translator = [translator];
}
return !!this.translator;
},
/**
* Registers a handler function to be called when translation is complete
*
* @param {String} type Type of handler to register. Legal values are:
* select
* valid: web
* called: when the user needs to select from a list of available items
* passed: an associative array in the form id => text
* returns: a numerically indexed array of ids, as extracted from the passed
* string
* itemDone
* valid: import, web, search
* called: when an item has been processed; may be called asynchronously
* passed: an item object (see Zotero.Item)
* returns: N/A
* collectionDone
* valid: import
* called: when a collection has been processed, after all items have been
* added; may be called asynchronously
* passed: a collection object (see Zotero.Collection)
* returns: N/A
* done
* valid: all
* called: when all processing is finished
* passed: true if successful, false if an error occurred
* returns: N/A
* debug
* valid: all
* called: when Zotero.debug() is called
* passed: string debug message
* returns: true if message should be logged to the console, false if not
* error
* valid: all
* called: when a fatal error occurs
* passed: error object (or string)
* returns: N/A
* translators
* valid: all
* called: when a translator search initiated with Zotero.Translate.getTranslators() is
* complete
* passed: an array of appropriate translators
* returns: N/A
* @param {Function} handler Callback function. All handlers will be passed the current
* translate instance as the first argument. The second argument is dependent on the handler.
*/
"setHandler":function(type, handler) {
if(!this._handlers[type]) {
this._handlers[type] = new Array();
}
this._handlers[type].push(handler);
},
/**
* Clears all handlers for a given function
* @param {String} type See {@link Zotero.Translate.Base#setHandler} for valid values
*/
"clearHandlers":function(type) {
this._handlers[type] = new Array();
},
/**
* Clears a single handler for a given function
* @param {String} type See {@link Zotero.Translate.Base#setHandler} for valid values
* @param {Function} handler Callback function to remove
*/
"removeHandler":function(type, handler) {
var handlerIndex = this._handlers[type].indexOf(handler);
if(handlerIndex !== -1) this._handlers[type].splice(handlerIndex, 1);
},
/**
* Indicates that a new async process is running
*/
"incrementAsyncProcesses":function(f) {
this._runningAsyncProcesses++;
if(this._parentTranslator) {
this._parentTranslator.incrementAsyncProcesses(f+" from child translator");
} else {
//Zotero.debug("Translate: Incremented asynchronous processes to "+this._runningAsyncProcesses+" for "+f, 4);
//Zotero.debug((new Error()).stack);
}
},
/**
* Indicates that a new async process is finished
*/
"decrementAsyncProcesses":function(f, by) {
this._runningAsyncProcesses -= (by ? by : 1);
if(!this._parentTranslator) {
//Zotero.debug("Translate: Decremented asynchronous processes to "+this._runningAsyncProcesses+" for "+f, 4);
//Zotero.debug((new Error()).stack);
}
if(this._runningAsyncProcesses === 0) {
this.complete();
}
if(this._parentTranslator) this._parentTranslator.decrementAsyncProcesses(f+" from child translator", by);
},
/**
* Clears all handlers for a given function
* @param {String} type See {@link Zotero.Translate.Base#setHandler} for valid values
* @param {Any} argument Argument to be passed to handler
*/
"_runHandler":function(type) {
var returnValue = undefined;
if(this._handlers[type]) {
// compile list of arguments
if(this._parentTranslator) {
// if there is a parent translator, make sure we don't the Zotero.Translate
// object, since it could open a security hole
var args = [null];
} else {
var args = [this];
}
for(var i=1; i<arguments.length; i++) {
args.push(arguments[i]);
}
var handlers = this._handlers[type].slice();
for(var i=0, n=handlers.length; i<n; i++) {
Zotero.debug("Translate: Running handler "+i+" for "+type, 5);
try {
returnValue = handlers[i].apply(null, args);
} catch(e) {
if(this._parentTranslator) {
// throw handler errors if they occur when a translator is
// called from another translator, so that the
// "Could Not Translate" dialog will appear if necessary
throw(e);
} else {
// otherwise, fail silently, so as not to interfere with
// interface cleanup
Zotero.debug("Translate: "+e+' in handler '+i+' for '+type, 5);
Zotero.logError(e);
}
}
}
}
return returnValue;
},
/**
* Gets all applicable translators of a given type
*
* For import, you should call this after setLocation; otherwise, you'll just get a list of all
* import filters, not filters equipped to handle a specific file
*
* @param {Boolean} [getAllTranslators] Whether all applicable translators should be returned,
* rather than just the first available.
* @return {Zotero.Translator[]} An array of {@link Zotero.Translator} objects
*/
"getTranslators":function(getAllTranslators) {
// do not allow simultaneous instances of getTranslators
if(this._currentState === "detect") throw new Error("getTranslators: detection is already running");
this._currentState = "detect";
this._getAllTranslators = getAllTranslators;
this._getTranslatorsGetPotentialTranslators();
// if detection returns immediately, return found translators
if(!this._currentState) return this._foundTranslators;
},
/**
* Get all potential translators
* @return {Zotero.Translator[]}
*/
"_getTranslatorsGetPotentialTranslators":function() {
var me = this;
Zotero.Translators.getAllForType(this.type,
function(translators) { me._getTranslatorsTranslatorsReceived(translators) });
},
/**
* Called on completion of {@link #_getTranslatorsGetPotentialTranslators} call
*/
"_getTranslatorsTranslatorsReceived":function(allPotentialTranslators, properToProxyFunctions) {
this._potentialTranslators = [];
this._foundTranslators = [];
// this gets passed out by Zotero.Translators.getWebTranslatorsForLocation() because it is
// specific for each translator, but we want to avoid making a copy of a translator whenever
// possible.
this._properToProxyFunctions = properToProxyFunctions ? properToProxyFunctions : null;
this._waitingForRPC = false;
for(var i=0, n=allPotentialTranslators.length; i<n; i++) {
var translator = allPotentialTranslators[i];
if(translator.runMode === Zotero.Translator.RUN_MODE_IN_BROWSER) {
this._potentialTranslators.push(translator);
} else if(this instanceof Zotero.Translate.Web && Zotero.Connector) {
this._waitingForRPC = true;
}
}
if(this._waitingForRPC) {
var me = this;
Zotero.Connector.callMethod("detect", {"uri":this.location.toString(),
"cookie":this.document.cookie,
"html":this.document.documentElement.innerHTML},
function(returnValue) { me._getTranslatorsRPCComplete(returnValue) });
}
this._detect();
},
/**
* Called on completion of detect RPC for
* {@link Zotero.Translate.Base#_getTranslatorsTranslatorsReceived}
*/
"_getTranslatorsRPCComplete":function(rpcTranslators) {
this._waitingForRPC = false;
// if there are translators, add them to the list of found translators
if(rpcTranslators) {
for(var i=0, n=rpcTranslators.length; i<n; i++) {
rpcTranslators[i].runMode = Zotero.Translator.RUN_MODE_ZOTERO_STANDALONE;
}
this._foundTranslators = this._foundTranslators.concat(rpcTranslators);
}
// call _detectTranslatorsCollected to return detected translators
if(this._currentState === null) {
this._detectTranslatorsCollected();
}
},
/**
* Begins the actual translation. At present, this returns immediately for import/export
* translators, but new code should use {@link Zotero.Translate.Base#setHandler} to register a
* "done" handler to determine when execution of web/search translators is complete.
*
* @param {NULL|Integer|FALSE} [libraryID=null] Library in which to save items,
* or NULL for default library;
* if FALSE, don't save items
* @param {Boolean} [saveAttachments=true] Exclude attachments (e.g., snapshots) on import
*/
"translate":function(libraryID, saveAttachments) { // initialize properties specific to each translation
this._currentState = "translate";
if(!this.translator || !this.translator.length) {
throw new Error("Failed: no translator specified");
}
this._libraryID = libraryID;
this._saveAttachments = saveAttachments === undefined || saveAttachments;
var me = this;
if(typeof this.translator[0] === "object") {
// already have a translator object, so use it
this._loadTranslator(this.translator[0], function() { me._translateTranslatorLoaded() });
} else {
// need to get translator first
Zotero.Translators.get(this.translator[0],
function(translator) {
me.translator[0] = translator;
me._loadTranslator(translator, function() { me._translateTranslatorLoaded() });
});
}
},
/**
* Called when translator has been retrieved and loaded
*/
"_translateTranslatorLoaded":function() {
if(!this.translator[0].code) {
this.complete(false,
new Error("Translator "+this.translator[0].label+" is unsupported within this environment"));
return;
}
// set display options to default if they don't exist
if(!this._displayOptions) this._displayOptions = this.translator[0].displayOptions;
// prepare translation
this._prepareTranslation();
Zotero.debug("Translate: Beginning translation with "+this.translator[0].label);
this.incrementAsyncProcesses("Zotero.Translate#translate()");
// translate
try {
this._sandboxManager.sandbox["do"+this._entryFunctionSuffix].apply(null, this._getParameters());
} catch(e) {
if(this._parentTranslator) {
throw(e);
} else {
this.complete(false, e);
return false;
}
}
this.decrementAsyncProcesses("Zotero.Translate#translate()");
},
/**
* Executed when items have been saved (which may happen asynchronously, if in connector)
*
* @param {Boolean} returnValue Whether saving was successful
* @param {Zotero.Item[]|Error} data If returnValue is true, this will be an array of
* Zotero.Item objects. If returnValue is false, this will
* be a string error message.
*/
"itemsSaved":function(returnValue, data) {
if(returnValue) {
// trigger deferred itemDone events
var nItems = data.length;
for(var i=0; i<nItems; i++) {
this._runHandler("itemDone", data[i], this.saveQueue[i]);
}
this.saveQueue = [];
} else {
Zotero.logError(data);
}
this._runHandler("done", returnValue);
},
/**
* Return the progress of the import operation, or null if progress cannot be determined
*/
"getProgress":function() { return null },
/**
* Executed on translator completion, either automatically from a synchronous scraper or as
* done() from an asynchronous scraper. Finishes things up and calls callback function(s).
* @param {Boolean|String} returnValue An item type or a boolean true or false
* @param {String|Exception} [error] An error that occurred during translation.
* @returm {String|NULL} The exception serialized to a string, or null if translation
* completed successfully.
*/
"complete":function(returnValue, error) {
// allow translation to be aborted for re-running after selecting items
if(this._aborted) return;
// Make sure this isn't called twice
if(this._currentState === null) {
var e = new Error();
Zotero.debug("Translate: WARNING: Zotero.done() called after translation completion. This should never happen. Please examine the stack below.");
Zotero.debug(e.stack);
return;
}
var oldState = this._currentState;
// reset async processes and propagate them to parent
if(this._parentTranslator && this._runningAsyncProcesses) {
this._parentTranslator.decrementAsyncProcesses("Zotero.Translate#complete", this._runningAsyncProcesses);
}
this._runningAsyncProcesses = 0;
if(!returnValue && this._returnValue) returnValue = this._returnValue;
var errorString = null;
if(!returnValue && error) errorString = this._generateErrorString(error);
if(oldState === "detect") {
if(this._potentialTranslators.length) {
var lastTranslator = this._potentialTranslators.shift();
var lastProperToProxyFunction = this._properToProxyFunctions ? this._properToProxyFunctions.shift() : null;
if(returnValue) {
var dupeTranslator = {"itemType":returnValue, "properToProxy":lastProperToProxyFunction};
for(var i in lastTranslator) dupeTranslator[i] = lastTranslator[i];
this._foundTranslators.push(dupeTranslator);
} else if(error) {
this._debug("Detect using "+lastTranslator.label+" failed: \n"+errorString, 2);
}
}
if(this._potentialTranslators.length && (this._getAllTranslators || !returnValue)) {
// more translators to try; proceed to next translator
this._detect();
} else {
this._currentState = null;
if(!this._waitingForRPC) this._detectTranslatorsCollected();
}
} else {
this._currentState = null;
// unset return value is equivalent to true
if(returnValue === undefined) returnValue = true;
if(returnValue) {
if(this.saveQueue.length) {
var me = this;
this._itemSaver.saveItems(this.saveQueue.slice(),
function(returnValue, data) { me.itemsSaved(returnValue, data) });
return;
} else {
this._debug("Translation successful");
}
} else {
if(error) {
// report error to console
Zotero.logError(error);
// report error to debug log
this._debug("Translation using "+(this.translator && this.translator[0] && this.translator[0].label ? this.translator[0].label : "no translator")+" failed: \n"+errorString, 2);
}
this._runHandler("error", error);
}
// call handlers
this._runHandler("done", returnValue);
}
return errorString;
},
/**
* Begins running detect code for a translator, first loading it
*/
"_detect":function() {
// there won't be any translators if we need an RPC call
if(!this._potentialTranslators.length) {
this.complete(true);
return;
}
var me = this;
this._loadTranslator(this._potentialTranslators[0],
function() { me._detectTranslatorLoaded() });
},
/**
* Runs detect code for a translator
*/
"_detectTranslatorLoaded":function() {
this._prepareDetection();
this.incrementAsyncProcesses("Zotero.Translate#getTranslators");
try {
var returnValue = this._sandboxManager.sandbox["detect"+this._entryFunctionSuffix].apply(null, this._getParameters());
} catch(e) {
this.complete(false, e);
return;
}
if(returnValue !== undefined) this._returnValue = returnValue;
this.decrementAsyncProcesses("Zotero.Translate#getTranslators");
},
/**
* Called when all translators have been collected for detection
*/
"_detectTranslatorsCollected":function() {
Zotero.debug("Translate: All translator detect calls and RPC calls complete");
this._foundTranslators.sort(function(a, b) { return a.priority-b.priority });
this._runHandler("translators", this._foundTranslators);
},
/**
* Loads the translator into its sandbox
* @param {Zotero.Translator} translator
* @return {Boolean} Whether the translator could be successfully loaded
*/
"_loadTranslator":function(translator, callback) {
var sandboxLocation = this._getSandboxLocation();
if(!this._sandboxLocation || sandboxLocation !== this._sandboxLocation) {
this._sandboxLocation = sandboxLocation;
this._generateSandbox();
}
this._runningAsyncProcesses = 0;
this._returnValue = undefined;
this._aborted = false;
this.saveQueue = [];
Zotero.debug("Translate: Parsing code for "+translator.label, 4);
try {
this._sandboxManager.eval("var exports = {}, ZOTERO_TRANSLATOR_INFO = "+translator.code,
["detect"+this._entryFunctionSuffix, "do"+this._entryFunctionSuffix, "exports",
"ZOTERO_TRANSLATOR_INFO"],
(translator.file ? translator.file.path : translator.label));
} catch(e) {
this.complete(false, e);
return;
}
if(callback) callback();
},
/**
* Generates a sandbox for scraping/scraper detection
*/
"_generateSandbox":function() {
Zotero.debug("Translate: Binding sandbox to "+(typeof this._sandboxLocation == "object" ? this._sandboxLocation.document.location : this._sandboxLocation), 4);
this._sandboxManager = new Zotero.Translate.SandboxManager(this._sandboxLocation);
const createArrays = "['creators', 'notes', 'tags', 'seeAlso', 'attachments']";
var src = "var Zotero = {};"+
"Zotero.Item = function (itemType) {"+
"const createArrays = "+createArrays+";"+
"this.itemType = itemType;"+
"for(var i=0, n=createArrays.length; i<n; i++) {"+
"this[createArrays[i]] = [];"+
"}"+
"};";
if(this instanceof Zotero.Translate.Export || this instanceof Zotero.Translate.Import) {
src += "Zotero.Collection = function () {};"+
"Zotero.Collection.prototype.complete = function() { Zotero._collectionDone(this); };";
if (this instanceof Zotero.Translate.Import) {
// https://bugzilla.mozilla.org/show_bug.cgi?id=609143 - can't pass E4X to sandbox in Fx4
src += "Zotero.getXML = function() {"+
"var xml = Zotero._getXML();"+
"if(typeof xml == 'string') return new XML(xml);"+
"};";
}
}
if(Zotero.isFx && !Zotero.isBookmarklet) {
// workaround for inadvertant attempts to pass E4X back from sandbox
src += "Zotero._transferItem = function(itemString) {"+
"var item = JSON.parse(itemString);"+
"item.complete = Zotero.Item.prototype.complete;"+
"return item;"+
"};"+
"Zotero.Item.prototype.complete = function() { "+
"for(var key in this) {"+
"if("+createArrays+".indexOf(key) !== -1) {"+
"for each(var item in this[key]) {"+
"for(var key2 in item[key2]) {"+
"if(typeof item[key2] === 'xml') {"+
"item[key2] = item[key2].toString();"+
"}"+
"}"+
"}"+
"} else if(typeof this[key] === 'xml') {"+
"this[key] = this[key].toString();"+
"}"+
"}";
} else {
src += "Zotero.Item.prototype.complete = function() { ";
}
src += "Zotero._itemDone(this);"+
"}";
this._sandboxManager.eval(src);
this._sandboxManager.importObject(this.Sandbox, this);
this._sandboxManager.importObject({"Utilities":new Zotero.Utilities.Translate(this)});
this._sandboxManager.sandbox.Zotero.Utilities.HTTP = this._sandboxManager.sandbox.Zotero.Utilities;
// create shortcuts
this._sandboxManager.sandbox.Z = this._sandboxManager.sandbox.Zotero;
this._sandboxManager.sandbox.ZU = this._sandboxManager.sandbox.Zotero.Utilities;
},
/**
* Logs a debugging message
* @param {String} string Debug string to log
* @param {Integer} level Log level (1-5, higher numbers are higher priority)
*/
"_debug":function(string, level) {
if(typeof string === "object" && Zotero.isFx36 && !Zotero.isBookmarklet) {
string = new XPCSafeJSObjectWrapper(string);
}
if(level !== undefined && typeof level !== "number") {
Zotero.debug("debug: level must be an integer");
return;
}
// if handler does not return anything explicitly false, show debug
// message in console
if(this._runHandler("debug", string) !== false) {
if(typeof string == "string") string = "Translate: "+string;
Zotero.debug(string, level);
}
},
/**
* Generates a string from an exception
* @param {String|Exception} error
*/
"_generateErrorString":function(error) {
var errorString = "";
if(typeof(error) == "string") {
errorString = "\nthrown exception => "+error;
} else {
for(var i in error) {
if(typeof(error[i]) != "object") {
errorString += "\n"+i+' => '+error[i];
}
}
if(error) {
errorString += "\nstring => "+error.toString();
}
}
errorString += "\nurl => "+this.path
+ "\ndownloadAssociatedFiles => "+Zotero.Prefs.get("downloadAssociatedFiles")
+ "\nautomaticSnapshots => "+Zotero.Prefs.get("automaticSnapshots");
return errorString.substr(1);
},
/**
* Determines the location where the sandbox should be bound
* @return {String|document} The location to which to bind the sandbox
*/
"_getSandboxLocation":function() {
return (this._parentTranslator ? this._parentTranslator._sandboxLocation : "http://www.example.com/");
},
/**
* Gets parameters to be passed to detect* and do* functions
* @return {Array} A list of parameters
*/
"_getParameters":function() { return []; },
/**
* No-op for preparing detection
*/
"_prepareDetection":function() {},
/**
* No-op for preparing translation
*/
"_prepareTranslation":function() {}
}
/**
* @class Web translation
*
* @property {Document} document The document object to be used for web scraping (set with setDocument)
* @property {Zotero.CookieSandbox} cookieSandbox A CookieSandbox to manage cookies for
* this Translate instance.
*/
Zotero.Translate.Web = function() {
this.init();
}
Zotero.Translate.Web.prototype = new Zotero.Translate.Base();
Zotero.Translate.Web.prototype.type = "web";
Zotero.Translate.Web.prototype._entryFunctionSuffix = "Web";
Zotero.Translate.Web.prototype.Sandbox = Zotero.Translate.Sandbox._inheritFromBase(Zotero.Translate.Sandbox.Web);
/**
* Sets the browser to be used for web translation
* @param {Document} doc An HTML document
*/
Zotero.Translate.Web.prototype.setDocument = function(doc) {
this.document = doc;
this.setLocation(doc.location.href);
}
/**
* Sets a Zotero.CookieSandbox to handle cookie management for XHRs initiated from this
* translate instance
*
* @param {Zotero.CookieSandbox} cookieSandbox
*/
Zotero.Translate.Web.prototype.setCookieSandbox = function(cookieSandbox) {
this.cookieSandbox = cookieSandbox;
}
/**
* Sets the location to operate upon
*
* @param {String} location The URL of the page to translate
*/
Zotero.Translate.Web.prototype.setLocation = function(location) {
this.location = location;
this.path = this.location;
}
/**
* Get potential web translators
*/
Zotero.Translate.Web.prototype._getTranslatorsGetPotentialTranslators = function() {
var me = this;
Zotero.Translators.getWebTranslatorsForLocation(this.location,
function(data) {
// data[0] = list of translators
// data[1] = list of functions to convert proper URIs to proxied URIs
me._getTranslatorsTranslatorsReceived(data[0], data[1]);
});
}
/**
* Bind sandbox to document being translated
*/
Zotero.Translate.Web.prototype._getSandboxLocation = function() {
return ("defaultView" in this.document ? this.document.defaultView : this.document.location.toString());
}
/**
* Pass document and location to detect* and do* functions
*/
Zotero.Translate.Web.prototype._getParameters = function() { return [this.document, this.location]; }
/**
* Prepare translation
*/
Zotero.Translate.Web.prototype._prepareTranslation = function() {
this._itemSaver = new Zotero.Translate.ItemSaver(this._libraryID,
Zotero.Translate.ItemSaver[(this._saveAttachments ? "ATTACHMENT_MODE_DOWNLOAD" : "ATTACHMENT_MODE_IGNORE")], 1,
this.document, this._cookieSandbox);
this.newItems = [];
}
/**
* Overload translate to set selectedItems
*/
Zotero.Translate.Web.prototype.translate = function(libraryID, saveAttachments, selectedItems) {
this._selectedItems = selectedItems;
Zotero.Translate.Base.prototype.translate.apply(this, [libraryID, saveAttachments]);
}
/**
* Overload _translateTranslatorLoaded to send an RPC call if necessary
*/
Zotero.Translate.Web.prototype._translateTranslatorLoaded = function() {
if(this.translator[0].runMode === Zotero.Translator.RUN_MODE_IN_BROWSER) {
// begin process to run translator in browser
Zotero.Translate.Base.prototype._translateTranslatorLoaded.apply(this);
} else {
// otherwise, ferry translator load to RPC
var me = this;
Zotero.Connector.callMethod("savePage", {
"uri":this.location.toString(),
"translatorID":(typeof this.translator[0] === "object"
? this.translator[0].translatorID : this.translator[0]),
"cookie":this.document.cookie,
"html":this.document.documentElement.innerHTML
}, function(obj) { me._translateRPCComplete(obj) });
}
}
/**
* Called when an RPC call for remote translation completes
*/
Zotero.Translate.Web.prototype._translateRPCComplete = function(obj, failureCode) {
if(!obj) this.complete(false, failureCode);
if(obj.selectItems) {
// if we have to select items, call the selectItems handler and do it
var me = this;
var items = this._runHandler("select", obj.selectItems,
function(selectedItems) {
Zotero.Connector.callMethod("selectItems",
{"instanceID":obj.instanceID, "selectedItems":selectedItems},
function(obj) { me._translateRPCComplete(obj) })
}
);
} else {
// if we don't have to select items, continue
for(var i=0, n=obj.items.length; i<n; i++) {
this._runHandler("itemDone", null, obj.items[i]);
}
this.newItems = obj.items;
this.complete(true);
}
}
/**
* Overload complete to report translation failure
*/
Zotero.Translate.Web.prototype.complete = function(returnValue, error) {
// call super
var oldState = this._currentState;
var errorString = Zotero.Translate.Base.prototype.complete.apply(this, [returnValue, error]);
// Report translation failure if we failed
if(oldState == "translate" && errorString && this.translator[0].inRepository && Zotero.Prefs.get("reportTranslationFailure")) {
// Don't report failure if in private browsing mode
if(Zotero.isFx && !Zotero.isBookmarklet && !Zotero.isStandalone) {
var pbs = Components.classes["@mozilla.org/privatebrowsing;1"]
.getService(Components.interfaces.nsIPrivateBrowsingService);
if (pbs.privateBrowsingEnabled) {
return;
}
}
var translator = this.translator[0];
Zotero.getSystemInfo(function(info) {
var postBody = "id=" + encodeURIComponent(translator.translatorID) +
"&lastUpdated=" + encodeURIComponent(translator.lastUpdated) +
"&diagnostic=" + encodeURIComponent(info) +
"&errorData=" + encodeURIComponent(errorString);
Zotero.HTTP.doPost("http://www.zotero.org/repo/report", postBody);
});
}
}
/**
* @class Import translation
*/
Zotero.Translate.Import = function() {
this.init();
}
Zotero.Translate.Import.prototype = new Zotero.Translate.Base();
Zotero.Translate.Import.prototype.type = "import";
Zotero.Translate.Import.prototype._entryFunctionSuffix = "Import";
Zotero.Translate.Import.prototype._io = false;
Zotero.Translate.Import.prototype.Sandbox = Zotero.Translate.Sandbox._inheritFromBase(Zotero.Translate.Sandbox.Import);
/**
* Sets string for translation and initializes string IO
*/
Zotero.Translate.Import.prototype.setString = function(string) {
this._string = string;
this._io = false;
}
/**
* Overload {@link Zotero.Translate.Base#complete} to close file
*/
Zotero.Translate.Import.prototype.complete = function(returnValue, error) {
if(this._io) {
this._progress = null;
this._io.close(false);
}
// call super
Zotero.Translate.Base.prototype.complete.apply(this, [returnValue, error]);
}
/**
* Get all potential import translators, ordering translators with the right file extension first
*/
Zotero.Translate.Import.prototype._getTranslatorsGetPotentialTranslators = function() {
if(this.location) {
var me = this;
Zotero.Translators.getImportTranslatorsForLocation(this.location,
function(translators) { me._getTranslatorsTranslatorsReceived(translators) });
} else {
Zotero.Translate.Base.prototype._getTranslatorsGetPotentialTranslators.call(this);
}
}
/**
* Overload {@link Zotero.Translate.Base#getTranslators} to return all translators immediately only
* if no string or location is set
*/
Zotero.Translate.Import.prototype.getTranslators = function() {
if(!this._string && !this.location) {
if(this._currentState === "detect") throw new Error("getTranslators: detection is already running");
this._currentState = "detect";
var me = this;
Zotero.Translators.getAllForType(this.type, function(translators) {
me._potentialTranslators = [];
me._foundTranslators = translators;
me.complete(true);
});
if(this._currentState === null) return this._foundTranslators;
} else {
return Zotero.Translate.Base.prototype.getTranslators.call(this);
}
}
/**
* Overload {@link Zotero.Translate.Base#_loadTranslator} to prepare translator IO
*/
Zotero.Translate.Import.prototype._loadTranslator = function(translator, callback) {
// call super
var me = this;
Zotero.Translate.Base.prototype._loadTranslator.call(this, translator, function() {
me._loadTranslatorPrepareIO(translator, callback);
});
}
/**
* Prepare translator IO
*/
Zotero.Translate.Import.prototype._loadTranslatorPrepareIO = function(translator, callback) {
var configOptions = this._sandboxManager.sandbox.ZOTERO_TRANSLATOR_INFO.configOptions;
var dataMode = configOptions ? configOptions["dataMode"] : "";
var me = this;
var initCallback = function(status, err) {
if(!status) {
me.complete(false, err);
} else {
me._sandboxManager.importObject(me._io);
if(callback) callback();
}
};
var err = false;
if(!this._io) {
if(Zotero.Translate.IO.Read && this.location && this.location instanceof Components.interfaces.nsIFile) {
try {
this._io = new Zotero.Translate.IO.Read(this.location);
} catch(e) {
err = e;
}
} else {
try {
this._io = new Zotero.Translate.IO.String(this._string, this.path ? this.path : "");
} catch(e) {
err = e;
}
}
if(err) {
this.complete(false, err);
return;
}
}
try {
this._io.init(dataMode, initCallback);
} catch(e) {
err = e;
}
if(err) {
this.complete(false, err);
return;
}
}
/**
* Prepare translation
*/
Zotero.Translate.Import.prototype._prepareTranslation = function() {
this._progress = undefined;
this._itemSaver = new Zotero.Translate.ItemSaver(this._libraryID,
Zotero.Translate.ItemSaver[(this._saveAttachments ? "ATTACHMENT_MODE_FILE" : "ATTACHMENT_MODE_IGNORE")]);
this.newItems = [];
this.newCollections = [];
}
/**
* Return the progress of the import operation, or null if progress cannot be determined
*/
Zotero.Translate.Import.prototype.getProgress = function() {
if(this._progress !== undefined) return this._progress;
if(Zotero.Translate.IO.rdfDataModes.indexOf(this._mode) !== -1 || this._mode === "xml/e4x" || this._mode == "xml/dom" || !this._io) {
return null;
}
return this._io.bytesRead/this._io.contentLength*100;
};
/**
* @class Export translation
*/
Zotero.Translate.Export = function() {
this.init();
}
Zotero.Translate.Export.prototype = new Zotero.Translate.Base();
Zotero.Translate.Export.prototype.type = "export";
Zotero.Translate.Export.prototype._entryFunctionSuffix = "Export";
Zotero.Translate.Export.prototype.Sandbox = Zotero.Translate.Sandbox._inheritFromBase(Zotero.Translate.Sandbox.Export);
/**
* Sets the items to be exported
* @param {Zotero.Item[]} items
*/
Zotero.Translate.Export.prototype.setItems = function(items) {
this._items = items;
delete this._collection;
}
/**
* Sets the collection to be exported (overrides setItems)
* @param {Zotero.Collection[]} collection
*/
Zotero.Translate.Export.prototype.setCollection = function(collection) {
this._collection = collection;
delete this._items;
}
/**
* Sets the translator to be used for export
*
* @param {Zotero.Translator|string} Translator object or ID. If this contains a displayOptions
* attribute, setDisplayOptions is automatically called with the specified value.
*/
Zotero.Translate.Export.prototype.setTranslator = function(translator) {
if(typeof translator == "object" && translator.displayOptions) {
this._displayOptions = translator.displayOptions;
}
return Zotero.Translate.Base.prototype.setTranslator.apply(this, [translator]);
}
/**
* Sets translator display options. you can also pass a translator (not ID) to
* setTranslator that includes a displayOptions argument
*/
Zotero.Translate.Export.prototype.setDisplayOptions = function(displayOptions) {
this._displayOptions = displayOptions;
}
/**
* Overload {@link Zotero.Translate.Base#complete} to close file and set complete
*/
Zotero.Translate.Export.prototype.complete = function(returnValue, error) {
if(this._io) {
this._progress = null;
this._io.close(true);
if(this._io instanceof Zotero.Translate.IO.String) {
this.string = this._io.string;
}
}
// call super
Zotero.Translate.Base.prototype.complete.apply(this, [returnValue, error]);
}
/**
* Overload {@link Zotero.Translate.Base#getTranslators} to return all translators immediately
*/
Zotero.Translate.Export.prototype.getTranslators = function() {
if(this._currentState === "detect") throw new Error("getTranslators: detection is already running");
this._currentState = "detect";
this._foundTranslators = Zotero.Translators.getAllForType(this.type);
this._potentialTranslators = [];
this.complete(true);
return this._foundTranslators;
}
/**
* Does the actual export, after code has been loaded and parsed
*/
Zotero.Translate.Export.prototype._prepareTranslation = function() {
this._progress = undefined;
// initialize ItemGetter
this._itemGetter = new Zotero.Translate.ItemGetter();
var getCollections = this.translator[0].configOptions.getCollections ? this.translator[0].configOptions.getCollections : false;
if(this._collection) {
this._itemGetter.setCollection(this._collection, getCollections);
delete this._collection;
} else if(this._items) {
this._itemGetter.setItems(this._items);
delete this._items;
} else {
this._itemGetter.setAll(getCollections);
}
// export file data, if requested
if(this._displayOptions["exportFileData"]) {
this.location = this._itemGetter.exportFiles(this.location, this.translator[0].target);
}
// initialize IO
// this is currently hackish since we pass null callbacks to the init function (they have
// callbacks to be consistent with import, but they are synchronous, so we ignore them)
if(!this.location) {
this._io = new Zotero.Translate.IO.String(null, this.path ? this.path : "");
this._io.init(this.translator[0].configOptions["dataMode"], function() {});
} else if(!Zotero.Translate.IO.Write) {
throw new Error("Writing to files is not supported in this build of Zotero.");
} else {
this._io = new Zotero.Translate.IO.Write(this.location);
this._io.init(this.translator[0].configOptions["dataMode"],
this._displayOptions["exportCharset"] ? this._displayOptions["exportCharset"] : null,
function() {});
}
this._sandboxManager.importObject(this._io);
}
/**
* Return the progress of the import operation, or null if progress cannot be determined
*/
Zotero.Translate.Export.prototype.getProgress = function() {
if(this._progress !== undefined) return this._progress;
if(!this._itemGetter) {
return null;
}
return (1-this._itemGetter.numItemsRemaining/this._itemGetter.numItems)*100;
};
/**
* @class Search translation
* @property {Array[]} search Item (in {@link Zotero.Item#serialize} format) to extrapolate data
* (set with setSearch)
*/
Zotero.Translate.Search = function() {
this.init();
};
Zotero.Translate.Search.prototype = new Zotero.Translate.Base();
Zotero.Translate.Search.prototype.type = "search";
Zotero.Translate.Search.prototype._entryFunctionSuffix = "Search";
Zotero.Translate.Search.prototype.Sandbox = Zotero.Translate.Sandbox._inheritFromBase(Zotero.Translate.Sandbox.Search);
/**
* @borrows Zotero.Translate.Web#setCookieSandbox
*/
Zotero.Translate.Search.prototype.setCookieSandbox = Zotero.Translate.Web.prototype.setCookieSandbox;
/**
* Sets the item to be used for searching
* @param {Object} item An item, with as many fields as desired, in the format returned by
* {@link Zotero.Item#serialize}
*/
Zotero.Translate.Search.prototype.setSearch = function(search) {
this.search = search;
}
/**
* Overloads {@link Zotero.Translate.Base#getTranslators} to always return all potential translators
*/
Zotero.Translate.Search.prototype.getTranslators = function() {
return Zotero.Translate.Base.prototype.getTranslators.call(this, true);
}
/**
* Sets the translator or translators to be used for search
*
* @param {Zotero.Translator|string} Translator object or ID
*/
Zotero.Translate.Search.prototype.setTranslator = function(translator) {
if(typeof translator == "object" && !translator.translatorID) {
// we have an array of translators
// accept a list of objects
this.translator = [];
for(var i=0, n=translator.length; i<n; i++) {
this.translator.push(translator[i]);
}
return true;
} else {
return Zotero.Translate.Base.prototype.setTranslator.apply(this, [translator]);
}
}
/**
* Overload Zotero.Translate.Base#complete to move onto the next translator if
* translation fails
*/
Zotero.Translate.Search.prototype.complete = function(returnValue, error) {
if(this._currentState == "translate" && (!this.newItems || !this.newItems.length)) {
Zotero.debug("Translate: Could not find a result using "+this.translator[0].label+": \n"
+this._generateErrorString(error), 3);
if(this.translator.length > 1) {
this.translator.shift();
this.translate(this._libraryID, this._saveAttachments);
return;
} else {
error = "No items returned from any translator";
returnValue = false;
}
}
// call super
Zotero.Translate.Base.prototype.complete.apply(this, [returnValue, error]);
}
/**
* Pass search item to detect* and do* functions
*/
Zotero.Translate.Search.prototype._getParameters = function() { return [this.search]; };
/**
* Extract sandbox location from translator target
*/
Zotero.Translate.Search.prototype._getSandboxLocation = function() {
// generate sandbox for search by extracting domain from translator target
if(this.translator && this.translator[0] && this.translator[0].target) {
// so that web translators work too
const searchSandboxRe = /^http:\/\/[\w.]+\//;
var tempURL = this.translator[0].target.replace(/\\/g, "").replace(/\^/g, "");
var m = searchSandboxRe.exec(tempURL);
if(m) return m[0];
}
return Zotero.Translate.Base.prototype._getSandboxLocation.call(this);
}
Zotero.Translate.Search.prototype._prepareTranslation = Zotero.Translate.Web.prototype._prepareTranslation;
/**
* IO-related functions
* @namespace
*/
Zotero.Translate.IO = {
/**
* Parses XML using DOMParser
*/
"parseDOMXML":function(input, charset, size) {
try {
var dp = new DOMParser();
} catch(e) {
try {
var dp = Components.classes["@mozilla.org/xmlextras/domparser;1"]
.createInstance(Components.interfaces.nsIDOMParser);
} catch(e) {
throw new Error("DOMParser not supported");
}
}
if(typeof input == "string") {
var nodes = dp.parseFromString(input, "text/xml");
} else {
var nodes = dp.parseFromStream(input, charset, size, "text/xml");
}
if(nodes.getElementsByTagName("parsererror").length) {
throw "DOMParser error: loading data into data store failed";
}
return nodes;
},
/**
* Names of RDF data modes
*/
"rdfDataModes":["rdf", "rdf/xml", "rdf/n3"]
};
/******* String support *******/
/**
* @class Translate backend for translating from a string
*/
Zotero.Translate.IO.String = function(string, uri, mode) {
if(string && typeof string === "string") {
this.string = string;
} else {
this.string = "";
}
this.contentLength = this.string.length;
this.bytesRead = 0;
this._uri = uri;
}
Zotero.Translate.IO.String.prototype = {
"__exposedProps__":{
"RDF":"r",
"read":"r",
"write":"r",
"setCharacterSet":"r",
"_getXML":"r"
},
"_initRDF":function(callback) {
Zotero.debug("Translate: Initializing RDF data store");
this._dataStore = new Zotero.RDF.AJAW.RDFIndexedFormula();
this.RDF = new Zotero.Translate.IO._RDFSandbox(this._dataStore);
if(this.contentLength) {
try {
var xml = Zotero.Translate.IO.parseDOMXML(this.string);
} catch(e) {
this._xmlInvalid = true;
throw e;
}
var parser = new Zotero.RDF.AJAW.RDFParser(this._dataStore);
parser.parse(xml, this._uri);
}
callback(true);
},
"setCharacterSet":function(charset) {},
"read":function(bytes) {
// if we are reading in RDF data mode and no string is set, serialize current RDF to the
// string
if(Zotero.Translate.IO.rdfDataModes.indexOf(this._mode) !== -1 && this.string === "") {
this.string = this.RDF.serialize();
}
// return false if string has been read
if(this.bytesRead >= this.contentLength) {
return false;
}
if(bytes !== undefined) {
if(this.bytesRead >= this.contentLength) return false;
var oldPointer = this.bytesRead;
this.bytesRead += bytes;
return this.string.substr(oldPointer, bytes);
} else {
// bytes not specified; read a line
var oldPointer = this.bytesRead;
var lfIndex = this.string.indexOf("\n", this.bytesRead);
if(lfIndex !== -1) {
// in case we have a CRLF
this.bytesRead = lfIndex+1;
if(this.contentLength > lfIndex && this.string[lfIndex-1] === "\r") {
lfIndex--;
}
return this.string.substr(oldPointer, lfIndex-oldPointer);
}
if(!this._noCR) {
var crIndex = this.string.indexOf("\r", this.bytesRead);
if(crIndex === -1) {
this._noCR = true;
} else {
this.bytesRead = crIndex+1;
return this.string.substr(oldPointer, crIndex-oldPointer-1);
}
}
this.bytesRead = this.contentLength;
return this.string.substr(oldPointer);
}
},
"write":function(data) {
this.string += data;
this.contentLength = this.string.length;
},
"_getXML":function() {
if(this._mode == "xml/dom") {
try {
return Zotero.Translate.IO.parseDOMXML(this.string);
} catch(e) {
this._xmlInvalid = true;
throw e;
}
} else {
return this.string.replace(/<\?xml[^>]+\?>/, "");
}
},
"init":function(newMode, callback) {
this.bytesRead = 0;
this._noCR = undefined;
this._mode = newMode;
if(newMode && (Zotero.Translate.IO.rdfDataModes.indexOf(newMode) !== -1
|| newMode.substr(0, 3) === "xml") && this._xmlInvalid) {
throw "XML known invalid";
} else if(Zotero.Translate.IO.rdfDataModes.indexOf(this._mode) !== -1) {
this._initRDF(callback);
} else {
callback(true);
}
},
"close":function(serialize) {
// if we are writing in RDF data mode and no string is set, serialize current RDF to the
// string
if(serialize && Zotero.Translate.IO.rdfDataModes.indexOf(this._mode) !== -1 && this.string === "") {
this.string = this.RDF.serialize();
}
}
}
/****** RDF DATA MODE ******/
/**
* @class An API for handling RDF from the sandbox. This is exposed to translators as Zotero.RDF.
*
* @property {Zotero.RDF.AJAW.RDFIndexedFormula} _dataStore
* @property {Integer[]} _containerCounts
* @param {Zotero.RDF.AJAW.RDFIndexedFormula} dataStore
*/
Zotero.Translate.IO._RDFSandbox = function(dataStore) {
this._dataStore = dataStore;
}
Zotero.Translate.IO._RDFSandbox.prototype = {
"_containerCounts":[],
"__exposedProps__":{
"addStatement":"r",
"newResource":"r",
"newContainer":"r",
"addContainerElement":"r",
"getContainerElements":"r",
"addNamespace":"r",
"getAllResources":"r",
"getResourceURI":"r",
"getArcsIn":"r",
"getArcsOut":"r",
"getSources":"r",
"getTargets":"r",
"getStatementsMatching":"r"
},
/**
* Gets a resource as a Zotero.RDF.AJAW.RDFSymbol, rather than a string
* @param {String|Zotero.RDF.AJAW.RDFSymbol} about
* @return {Zotero.RDF.AJAW.RDFSymbol}
*/
"_getResource":function(about) {
return (typeof about == "object" ? about : new Zotero.RDF.AJAW.RDFSymbol(about));
},
/**
* Runs a callback to initialize this RDF store
*/
"_init":function() {
if(this._prepFunction) {
this._dataStore = this._prepFunction();
delete this._prepFunction;
}
},
/**
* Serializes the current RDF to a string
*/
"serialize":function(dataMode) {
var serializer = Serializer();
for(var prefix in this._dataStore.namespaces) {
serializer.suggestPrefix(prefix, this._dataStore.namespaces[prefix]);
}
// serialize in appropriate format
if(dataMode == "rdf/n3") {
return serializer.statementsToN3(this._dataStore.statements);
}
return serializer.statementsToXML(this._dataStore.statements);
},
/**
* Adds an RDF triple
* @param {String|Zotero.RDF.AJAW.RDFSymbol} about
* @param {String|Zotero.RDF.AJAW.RDFSymbol} relation
* @param {String|Zotero.RDF.AJAW.RDFSymbol} value
* @param {Boolean} literal Whether value should be treated as a literal (true) or a resource
* (false)
*/
"addStatement":function(about, relation, value, literal) {
if(about === null || about === undefined) {
throw new Error("about must be defined in Zotero.RDF.addStatement");
}
if(relation === null || relation === undefined) {
throw new Error("relation must be defined in Zotero.RDF.addStatement");
}
if(value === null || value === undefined) {
throw new Error("value must be defined in Zotero.RDF.addStatement");
}
if(literal) {
// zap chars that Mozilla will mangle
value = value.toString().replace(/[\x00-\x08\x0B\x0C\x0E-\x1F]/g, '');
} else {
value = this._getResource(value);
}
this._dataStore.add(this._getResource(about), this._getResource(relation), value);
},
/**
* Creates a new anonymous resource
* @return {Zotero.RDF.AJAW.RDFSymbol}
*/
"newResource":function() {
return new Zotero.RDF.AJAW.RDFBlankNode();
},
/**
* Creates a new container resource
* @param {String} type The type of the container ("bag", "seq", or "alt")
* @param {String|Zotero.RDF.AJAW.RDFSymbol} about The URI of the resource
* @return {Zotero.Translate.RDF.prototype.newContainer
*/
"newContainer":function(type, about) {
const rdf = "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
const containerTypes = {"bag":"Bag", "seq":"Seq", "alt":"Alt"};
type = type.toLowerCase();
if(!containerTypes[type]) {
throw new Error("Invalid container type in Zotero.RDF.newContainer");
}
var about = this._getResource(about);
this.addStatement(about, rdf+"type", rdf+containerTypes[type], false);
this._containerCounts[about.toNT()] = 1;
return about;
},
/**
* Adds a new element to a container
* @param {String|Zotero.RDF.AJAW.RDFSymbol} about The container
* @param {String|Zotero.RDF.AJAW.RDFSymbol} element The element to add to the container
* @param {Boolean} literal Whether element should be treated as a literal (true) or a resource
* (false)
*/
"addContainerElement":function(about, element, literal) {
const rdf = "http://www.w3.org/1999/02/22-rdf-syntax-ns#";
var about = this._getResource(about);
this._dataStore.add(about, new Zotero.RDF.AJAW.RDFSymbol(rdf+"_"+(this._containerCounts[about.toNT()]++)), element, literal);
},
/**
* Gets all elements within a container
* @param {String|Zotero.RDF.AJAW.RDFSymbol} about The container
* @return {Zotero.RDF.AJAW.RDFSymbol[]}
*/
"getContainerElements":function(about) {
const liPrefix = "http://www.w3.org/1999/02/22-rdf-syntax-ns#_";
var about = this._getResource(about);
var statements = this._dataStore.statementsMatching(about);
var containerElements = [];
// loop over arcs out looking for list items
for(var i=0; i<statements.length; i++) {
var statement = statements[i];
if(statement.predicate.uri.substr(0, liPrefix.length) == liPrefix) {
var number = statement.predicate.uri.substr(liPrefix.length);
// make sure these are actually numeric list items
var intNumber = parseInt(number);
if(number == intNumber.toString()) {
// add to element array
containerElements[intNumber-1] = (statement.object.termType == "literal" ? statement.object.toString() : statement.object);
}
}
}
return containerElements;
},
/**
* Adds a namespace for a specific URI
* @param {String} prefix Namespace prefix
* @param {String} uri Namespace URI
*/
"addNamespace":function(prefix, uri) {
this._dataStore.setPrefixForURI(prefix, uri);
},
/**
* Gets the URI a specific resource
* @param {String|Zotero.RDF.AJAW.RDFSymbol} resource
* @return {String}
*/
"getResourceURI":function(resource) {
if(typeof(resource) == "string") return resource;
if(resource.uri) return resource.uri;
if(resource.toNT == undefined) throw new Error("Zotero.RDF: getResourceURI called on invalid resource");
return resource.toNT();
},
/**
* Gets all resources in the RDF data store
* @return {Zotero.RDF.AJAW.RDFSymbol[]}
*/
"getAllResources":function() {
var returnArray = [];
for(var i in this._dataStore.subjectIndex) {
returnArray.push(this._dataStore.subjectIndex[i][0].subject);
}
return returnArray;
},
/**
* Gets all arcs (predicates) into a resource
* @return {Zotero.RDF.AJAW.RDFSymbol[]}
* @deprecated Since 2.1. Use {@link Zotero.Translate.IO["rdf"]._RDFBase#getStatementsMatching}
*/
"getArcsIn":function(resource) {
var statements = this._dataStore.objectIndex[this._dataStore.canon(this._getResource(resource))];
if(!statements) return false;
var returnArray = [];
for(var i=0; i<statements.length; i++) {
returnArray.push(statements[i].predicate.uri);
}
return returnArray;
},
/**
* Gets all arcs (predicates) out of a resource
* @return {Zotero.RDF.AJAW.RDFSymbol[]}
* @deprecated Since 2.1. Use {@link Zotero.Translate.IO["rdf"]._RDFBase#getStatementsMatching}
*/
"getArcsOut":function(resource) {
var statements = this._dataStore.subjectIndex[this._dataStore.canon(this._getResource(resource))];
if(!statements) return false;
var returnArray = [];
for(var i=0; i<statements.length; i++) {
returnArray.push(statements[i].predicate.uri);
}
return returnArray;
},
/**
* Gets all subjects whose predicates point to a resource
* @param {String|Zotero.RDF.AJAW.RDFSymbol} resource Subject that predicates should point to
* @param {String|Zotero.RDF.AJAW.RDFSymbol} property Predicate
* @return {Zotero.RDF.AJAW.RDFSymbol[]}
* @deprecated Since 2.1. Use {@link Zotero.Translate.IO["rdf"]._RDFBase#getStatementsMatching}
*/
"getSources":function(resource, property) {
var statements = this._dataStore.statementsMatching(undefined, this._getResource(property), this._getResource(resource));
if(!statements.length) return false;
var returnArray = [];
for(var i=0; i<statements.length; i++) {
returnArray.push(statements[i].subject);
}
return returnArray;
},
/**
* Gets all objects of a given subject with a given predicate
* @param {String|Zotero.RDF.AJAW.RDFSymbol} resource Subject
* @param {String|Zotero.RDF.AJAW.RDFSymbol} property Predicate
* @return {Zotero.RDF.AJAW.RDFSymbol[]}
* @deprecated Since 2.1. Use {@link Zotero.Translate.IO["rdf"]._RDFBase#getStatementsMatching}
*/
"getTargets":function(resource, property) {
var statements = this._dataStore.statementsMatching(this._getResource(resource), this._getResource(property));
if(!statements.length) return false;
var returnArray = [];
for(var i=0; i<statements.length; i++) {
returnArray.push(statements[i].object.termType == "literal" ? statements[i].object.toString() : statements[i].object);
}
return returnArray;
},
/**
* Gets statements matching a certain pattern
*
* @param {String|Zotero.RDF.AJAW.RDFSymbol} subj Subject
* @param {String|Zotero.RDF.AJAW.RDFSymbol} predicate Predicate
* @param {String|Zotero.RDF.AJAW.RDFSymbol} obj Object
* @param {Boolean} objLiteral Whether the object is a literal (as
* opposed to a URI)
* @param {Boolean} justOne Whether to stop when a single result is
* retrieved
*/
"getStatementsMatching":function(subj, pred, obj, objLiteral, justOne) {
var statements = this._dataStore.statementsMatching(
(subj ? this._getResource(subj) : undefined),
(pred ? this._getResource(pred) : undefined),
(obj ? (objLiteral ? objLiteral : this._getResource(obj)) : undefined),
undefined, justOne);
if(!statements.length) return false;
var returnArray = [];
for(var i=0; i<statements.length; i++) {
returnArray.push([statements[i].subject, statements[i].predicate, (statements[i].object.termType == "literal" ? statements[i].object.toString() : statements[i].object)]);
}
return returnArray;
}
};
--- translate_original.js 2012-02-16 13:29:37.000000000 -0500
+++ translate.js 2012-03-15 16:52:15.000000000 -0400
@@ -165,6 +165,14 @@
return translate._displayOptions[option];
},
+
+ "getPrefs":function(translate, pref) {
+ if(typeof pref !== "string") {
+ throw("Translate: getPrefs: pref must be a string");
+ return;
+ }
+ return Zotero.Prefs.get("translator."+pref);
+ },
/**
* For loading other translators and accessing their methods
/*
***** BEGIN LICENSE BLOCK *****
Copyright © 2012 Center for History and New Media
George Mason University, Fairfax, Virginia, USA
http://zotero.org
This file is part of Zotero.
Zotero is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Zotero is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
***** END LICENSE BLOCK *****
*/
Zotero.Translate.ItemSaver = function(libraryID, attachmentMode, forceTagType, document,
cookieSandbox) {
// initialize constants
this.newItems = [];
this.newCollections = [];
this._IDMap = {};
// determine library ID
if(libraryID === false) {
this._libraryID = false;
} else if(libraryID === true || libraryID == undefined) {
this._libraryID = null;
} else {
this._libraryID = libraryID;
}
// determine whether to save files and attachments
if (attachmentMode == Zotero.Translate.ItemSaver.ATTACHMENT_MODE_DOWNLOAD) {
this._saveAttachment = this._saveAttachmentDownload;
} else if(attachmentMode == Zotero.Translate.ItemSaver.ATTACHMENT_MODE_FILE) {
this._saveAttachment = this._saveAttachmentFile;
} else {
this._saveAttachment = function() {};
}
this._saveFiles = !(attachmentMode === 0);
// If group filesEditable==false, don't save attachments
if (typeof this._libraryID == 'number') {
var type = Zotero.Libraries.getType(this._libraryID);
switch (type) {
case 'group':
var groupID = Zotero.Groups.getGroupIDFromLibraryID(this._libraryID);
var group = Zotero.Groups.get(groupID);
if (!group.filesEditable) {
this._saveFiles = false;
}
break;
}
}
// force tag types if requested
this._forceTagType = forceTagType;
this._cookieSandbox = cookieSandbox;
};
Zotero.Translate.ItemSaver.ATTACHMENT_MODE_IGNORE = 0;
Zotero.Translate.ItemSaver.ATTACHMENT_MODE_DOWNLOAD = 1;
Zotero.Translate.ItemSaver.ATTACHMENT_MODE_FILE = 2;
Zotero.Translate.ItemSaver.prototype = {
"saveItems":function(items, callback) {
// if no open transaction, open a transaction and add a timer call to close it
var openedTransaction = false;
if(!Zotero.DB.transactionInProgress()) {
Zotero.DB.beginTransaction();
openedTransaction = true;
}
try {
var newItems = [];
for each(var item in items) {
// Get typeID, defaulting to "webpage"
var newItem;
var type = (item.itemType ? item.itemType : "webpage");
if(type == "note") { // handle notes differently
newItem = new Zotero.Item('note');
newItem.libraryID = this._libraryID;
newItem.setNote(item.note);
var myID = newItem.save();
newItem = Zotero.Items.get(myID);
} else {
if(type == "attachment") { // handle attachments differently
newItem = this._saveAttachment(item);
if(!newItem) return;
var myID = newItem.id;
} else {
var typeID = Zotero.ItemTypes.getID(type);
newItem = new Zotero.Item(typeID);
newItem._libraryID = this._libraryID;
this._saveFields(item, newItem);
// handle creators
if(item.creators) {
this._saveCreators(item, newItem);
}
// save item
var myID = newItem.save();
newItem = Zotero.Items.get(myID);
// handle notes
if(item.notes) {
this._saveNotes(item, myID);
}
// handle attachments
if(item.attachments) {
for(var i=0; i<item.attachments.length; i++) {
var newAttachment = this._saveAttachment(item.attachments[i], myID);
if(newAttachment) this._saveTags(item.attachments[i], newAttachment);
}
}
}
}
if(item.itemID) this._IDMap[item.itemID] = myID;
// handle see also
this._saveTags(item, newItem);
// add to new item list
newItem = Zotero.Items.get(myID);
newItems.push(newItem);
}
if(openedTransaction) Zotero.DB.commitTransaction();
callback(true, newItems);
} catch(e) {
if(openedTransaction) Zotero.DB.rollbackTransaction();
callback(false, e);
}
},
"saveCollection":function(collection) {
var collectionsToProcess = [collection];
var parentIDs = [null];
var topLevelCollection;
while(collectionsToProcess.length) {
var collection = collectionsToProcess.shift();
var parentID = parentIDs.shift();
var newCollection = Zotero.Collections.add(collection.name, parentID);
if(parentID === null) topLevelCollection = newCollection;
this.newCollections.push(newCollection.id);
var toAdd = [];
for(var i=0; i<collection.children.length; i++) {
var child = collection.children[i];
if(child.type === "collection") {
// do recursive processing of collections
collectionsToProcess.push(child);
parentIDs.push(newCollection.id);
} else {
// add mapped items to collection
if(this._IDMap[child.id]) {
toAdd.push(this._IDMap[child.id]);
} else {
Zotero.debug("Translate: Could not map "+child.id+" to an imported item", 2);
}
}
}
if(toAdd.length) {
Zotero.debug("Translate: Adding " + toAdd, 5);
newCollection.addItems(toAdd);
}
}
return topLevelCollection;
},
"_saveAttachmentFile":function(attachment, parentID) {
const urlRe = /(([A-Za-z]+):\/\/[^\s]*)/i;
Zotero.debug("Translate: Adding attachment", 4);
if(!attachment.url && !attachment.path) {
Zotero.debug("Translate: Ignoring attachment: no path or URL specified", 2);
return;
}
if(!attachment.path) {
// see if this is actually a file URL
var m = urlRe.exec(attachment.url);
var protocol = m ? m[2].toLowerCase() : "";
if(protocol == "file") {
attachment.path = attachment.url;
attachment.url = false;
} else if(protocol != "http" && protocol != "https") {
Zotero.debug("Translate: Unrecognized protocol "+protocol, 2);
return;
}
}
if(!attachment.path) {
// create from URL
try {
var myID = Zotero.Attachments.linkFromURL(attachment.url, parentID,
(attachment.mimeType ? attachment.mimeType : undefined),
(attachment.title ? attachment.title : undefined));
} catch(e) {
Zotero.debug("Translate: Error adding attachment "+attachment.url, 2);
return;
}
Zotero.debug("Translate: Created attachment; id is "+myID, 4);
var newItem = Zotero.Items.get(myID);
} else {
var uri, file;
// generate nsIFile
var IOService = Components.classes["@mozilla.org/network/io-service;1"].
getService(Components.interfaces.nsIIOService);
try {
var uri = IOService.newURI(attachment.path, "", null);
}
catch (e) {
var msg = "Error parsing attachment path: " + attachment.path;
Zotero.logError(msg);
Zotero.debug("Translate: " + msg, 2);
return;
}
try {
var file = uri.QueryInterface(Components.interfaces.nsIFileURL).file;
if (file.path == '/') {
var msg = "Error parsing attachment path: " + attachment.path;
Zotero.logError(msg);
Zotero.debug("Translate: " + msg, 2);
return;
}
}
catch (e) {
var msg = "Error getting file from attachment path: " + attachment.path;
Zotero.logError(msg);
Zotero.debug("Translate: " + msg, 2);
return;
}
if (!file.exists()) {
// use attachment title if possible, or else file leaf name
var title = attachment.title;
if(!title) {
title = file.leafName;
}
var myID = Zotero.Attachments.createMissingAttachment(
attachment.url ? Zotero.Attachments.LINK_MODE_IMPORTED_URL
: Zotero.Attachments.LINK_MODE_IMPORTED_FILE,
file, attachment.url ? attachment.url : null, title,
attachment.mimeType, attachment.charset, parentID);
}
else if (attachment.url) {
var myID = Zotero.Attachments.importSnapshotFromFile(file,
attachment.url, attachment.title, attachment.mimeType, attachment.charset,
parentID);
}
else {
var myID = Zotero.Attachments.importFromFile(file, parentID);
}
}
var newItem = Zotero.Items.get(myID);
// save fields
attachment.itemType = "attachment";
this._saveFields(attachment, newItem);
// add note if necessary
if(attachment.note) {
newItem.setNote(attachment.note);
}
newItem.save();
return newItem;
},
"_saveAttachmentDownload":function(attachment, parentID) {
Zotero.debug("Translate: Adding attachment", 4);
// determine whether to save attachments at all
var automaticSnapshots = Zotero.Prefs.get("automaticSnapshots");
var downloadAssociatedFiles = Zotero.Prefs.get("downloadAssociatedFiles");
if(!attachment.url && !attachment.document) {
Zotero.debug("Translate: Not adding attachment: no URL specified", 2);
} else {
var shouldAttach = ((attachment.document
|| (attachment.mimeType && attachment.mimeType == "text/html")) && automaticSnapshots)
|| downloadAssociatedFiles;
if(!shouldAttach) return;
if(attachment.snapshot === false || !this._saveFiles) {
// if snapshot is explicitly set to false, attach as link
if(attachment.document) {
Zotero.Attachments.linkFromURL(attachment.document.location.href, parentID,
(attachment.mimeType ? attachment.mimeType : attachment.document.contentType),
(attachment.title ? attachment.title : attachment.document.title));
} else {
if(!attachment.mimeType || !attachment.title) {
Zotero.debug("Translate: Either mimeType or title is missing; attaching file will be slower", 3);
}
try {
Zotero.Attachments.linkFromURL(attachment.url, parentID,
(attachment.mimeType ? attachment.mimeType : undefined),
(attachment.title ? attachment.title : undefined));
} catch(e) {
Zotero.debug("Translate: Error adding attachment "+attachment.url, 2);
}
}
} else {
// if snapshot is not explicitly set to false, retrieve snapshot
if(attachment.document) {
if(automaticSnapshots) {
try {
Zotero.Attachments.importFromDocument(attachment.document, parentID, attachment.title);
} catch(e) {
Zotero.debug("Translate: Error attaching document", 2);
}
}
// Save attachment if snapshot pref enabled or not HTML
// (in which case downloadAssociatedFiles applies)
} else if(this._saveFiles && (automaticSnapshots || !attachment.mimeType
|| attachment.mimeType != "text/html")) {
var mimeType = (attachment.mimeType ? attachment.mimeType : null);
var title = (attachment.title ? attachment.title : null);
var fileBaseName = Zotero.Attachments.getFileBaseNameFromItem(parentID);
try {
Zotero.debug('Importing attachment from URL');
Zotero.Attachments.importFromURL(attachment.url, parentID, title,
fileBaseName, null, mimeType, this._libraryID, null, this._cookieSandbox);
} catch(e) {
Zotero.debug("Translate: Error adding attachment "+attachment.url, 2);
}
}
}
}
},
"_saveFields":function(item, newItem) {
// fields that should be handled differently
const skipFields = ["note", "notes", "itemID", "attachments", "tags", "seeAlso",
"itemType", "complete", "creators"];
var typeID = Zotero.ItemTypes.getID(item.itemType);
var fieldID;
for(var field in item) {
// loop through item fields
if(item[field] && skipFields.indexOf(field) === -1 && (fieldID = Zotero.ItemFields.getID(field))) {
// if field is in db and shouldn't be skipped
// try to map from base field
if(Zotero.ItemFields.isBaseField(fieldID)) {
fieldID = Zotero.ItemFields.getFieldIDFromTypeAndBase(typeID, fieldID);
if(fieldID) {
Zotero.debug("Translate: Mapping "+field+" to "+Zotero.ItemFields.getName(fieldID), 5);
}
}
// if field is valid for this type, set field
if(fieldID && Zotero.ItemFields.isValidForType(fieldID, typeID)) {
newItem.setField(fieldID, item[field]);
} else {
Zotero.debug("Translate: Discarded field "+field+" for item: field not valid for type "+item.itemType, 3);
}
}
}
},
"_saveCreators":function(item, newItem) {
for(var i=0; i<item.creators.length; i++) {
var creator = item.creators[i];
if(!creator.firstName && !creator.lastName) {
Zotero.debug("Translate: Silently dropping empty creator");
continue;
}
// try to assign correct creator type
var creatorTypeID = 1;
if(creator.creatorType) {
try {
var creatorTypeID = Zotero.CreatorTypes.getID(creator.creatorType);
} catch(e) {
Zotero.debug("Translate: Invalid creator type "+creator.creatorType+" for creator index "+j, 2);
}
}
// Single-field mode
if (creator.fieldMode && creator.fieldMode == 1) {
var fields = {
lastName: creator.lastName,
fieldMode: 1
};
}
// Two-field mode
else {
var fields = {
firstName: creator.firstName,
lastName: creator.lastName
};
}
var creator = null;
var creatorDataID = Zotero.Creators.getDataID(fields);
if(creatorDataID) {
var linkedCreators = Zotero.Creators.getCreatorsWithData(creatorDataID, this._libraryID);
if (linkedCreators) {
// TODO: support identical creators via popup? ugh...
var creatorID = linkedCreators[0];
creator = Zotero.Creators.get(creatorID);
}
}
if(!creator) {
creator = new Zotero.Creator;
creator.libraryID = this._libraryID;
creator.setFields(fields);
var creatorID = creator.save();
}
newItem.setCreator(i, creator, creatorTypeID);
}
},
"_saveNotes":function(item, parentID) {
for(var i=0; i<item.notes.length; i++) {
var note = item.notes[i];
var myNote = new Zotero.Item('note');
myNote.libraryID = this._libraryID;
myNote.setNote(typeof note == "object" ? note.note : note);
if(parentID) {
myNote.setSource(parentID);
}
var noteID = myNote.save();
if(typeof note == "object") {
// handle see also
myNote = Zotero.Items.get(noteID);
this._saveTags(note, myNote);
}
}
},
"_saveTags":function(item, newItem) {
// add to ID map
if(item.itemID) {
this._IDMap[item.itemID] = newItem.id;
}
// add see alsos
if(item.seeAlso) {
for(var i=0; i<item.seeAlso.length; i++) {
var seeAlso = item.seeAlso[i];
if(this._IDMap[seeAlso]) {
newItem.addRelatedItem(this._IDMap[seeAlso]);
}
}
newItem.save();
}
// if all tags are automatic and automatic tags pref is on, return immediately
var tagPref = Zotero.Prefs.get("automaticTags");
if(this._forceTagType == 1 && !tagPref) return;
// add tags
if(item.tags) {
var tagsToAdd = {};
tagsToAdd[0] = []; // user tags
tagsToAdd[1] = []; // automatic tags
for(var i=0; i<item.tags.length; i++) {
var tag = item.tags[i];
if(typeof(tag) == "string") {
// accept strings in tag array as automatic tags, or, if
// importing, as non-automatic tags
if(this._forceTagType) {
tagsToAdd[this._forceTagType].push(tag);
} else {
tagsToAdd[0].push(tag);
}
} else if(typeof(tag) == "object") {
// also accept objects
if(tag.tag || tag.name) {
if(this._forceTagType) {
var tagType = this._forceTagType;
} else if(tag.type) {
// skip automatic tags during import too (?)
if(tag.type == 1 && !tagPref) continue;
var tagType = tag.type;
} else {
var tagType = 0;
}
tagsToAdd[tagType].push(tag.tag ? tag.tag : tag.name);
}
}
}
for (var type in [0, 1]) {
if (tagsToAdd[type].length) {
newItem.addTags(tagsToAdd[type], type);
}
}
}
}
}
Zotero.Translate.ItemGetter = function() {
this._itemsLeft = null;
this._collectionsLeft = null;
this._exportFileDirectory = null;
};
Zotero.Translate.ItemGetter.prototype = {
"setItems":function(items) {
this._itemsLeft = items;
this.numItems = this._itemsLeft.length;
},
"setCollection":function(collection, getChildCollections) {
// get items in this collection
var haveItems = {};
this._itemsLeft = collection.getChildItems();
for each(var item in this._itemsLeft) haveItems[item.id] = true;
if(!this._itemsLeft) {
this._itemsLeft = [];
}
if(getChildCollections) {
// get child collections
this._collectionsLeft = Zotero.getCollections(collection.id, true);
// get items in child collections
for each(var collection in this._collectionsLeft) {
var childItems = collection.getChildItems();
if(childItems) {
for each(var item in childItems) {
if(!haveItems[item.id]) {
haveItems[item.id] = true;
this._itemsLeft.push(item);;
}
}
}
}
}
this.numItems = this._itemsLeft.length;
},
"setAll":function(getChildCollections) {
this._itemsLeft = Zotero.Items.getAll(true);
if(getChildCollections) {
this._collectionsLeft = Zotero.getCollections();
}
this.numItems = this._itemsLeft.length;
},
"exportFiles":function(dir, extension) {
// generate directory
this._exportFileDirectory = Components.classes["@mozilla.org/file/local;1"].
createInstance(Components.interfaces.nsILocalFile);
this._exportFileDirectory.initWithFile(dir.parent);
// delete this file if it exists
if(dir.exists()) {
dir.remove(true);
}
// get name
var name = dir.leafName;
this._exportFileDirectory.append(name);
// create directory
this._exportFileDirectory.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0700);
// generate a new location for the exported file, with the appropriate
// extension
var location = Components.classes["@mozilla.org/file/local;1"].
createInstance(Components.interfaces.nsILocalFile);
location.initWithFile(this._exportFileDirectory);
location.append(name+"."+extension);
return location;
},
/**
* Converts an attachment to array format and copies it to the export folder if desired
*/
"_attachmentToArray":function(attachment) {
var attachmentArray = this._itemToArray(attachment);
var linkMode = attachment.attachmentLinkMode;
// Get mime type
attachmentArray.mimeType = attachmentArray.uniqueFields.mimeType = attachment.attachmentMIMEType;
// Get charset
attachmentArray.charset = attachmentArray.uniqueFields.charset = attachment.attachmentCharset;
// get path
attachmentArray.path = attachmentArray.uniqueFields.path = attachment.getFile().persistentDescriptor;
if(linkMode != Zotero.Attachments.LINK_MODE_LINKED_URL && this._exportFileDirectory) {
var exportDir = this._exportFileDirectory;
// Add path and filename if not an internet link
var attachFile = attachment.getFile();
if(attachFile) {
attachmentArray.defaultPath = "files/" + attachmentArray.itemID + "/" + attachFile.leafName;
attachmentArray.filename = attachFile.leafName;
/**
* Copies the attachment file to the specified relative path from the
* export directory.
* @param {String} attachPath The path to which the file should be exported
* including the filename. If supporting files are included, they will be
* copied as well without any renaming.
* @param {Boolean} overwriteExisting Optional - If this is set to false, the
* function will throw an error when exporting a file would require an existing
* file to be overwritten. If true, the file will be silently overwritten.
* defaults to false if not provided.
*/
attachmentArray.saveFile = function(attachPath, overwriteExisting) {
// Ensure a valid path is specified
if(attachPath === undefined || attachPath == "") {
throw new Error("ERROR_EMPTY_PATH");
}
// Set the default value of overwriteExisting if it was not provided
if (overwriteExisting === undefined) {
overwriteExisting = false;
}
// Separate the path into a list of subdirectories and the attachment filename,
// and initialize the required file objects
var targetFile = Components.classes["@mozilla.org/file/local;1"].
createInstance(Components.interfaces.nsILocalFile);
targetFile.initWithFile(exportDir);
for each(var dir in attachPath.split("/")) targetFile.append(dir);
// First, check that we have not gone lower than exportDir in the hierarchy
var parent = targetFile, inExportFileDirectory;
while((parent = parent.parent)) {
if(exportDir.equals(parent)) {
inExportFileDirectory = true;
break;
}
}
if(!inExportFileDirectory) {
throw new Error("Invalid path; attachment cannot be placed above export "+
"directory in the file hirarchy");
}
// Create intermediate directories if they don't exist
parent = targetFile;
while((parent = parent.parent) && !parent.exists()) {
parent.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0700);
}
// Delete any existing file if overwriteExisting is set, or throw an exception
// if it is not
if(targetFile.exists()) {
if(overwriteExisting) {
targetFile.remove(false);
} else {
throw new Error("ERROR_FILE_EXISTS " + targetFile.leafName);
}
}
var directory = targetFile.parent;
// The only attachments that can have multiple supporting files are of mime type
// text/html (specified in Attachments.getNumFiles())
if(attachment.attachmentMIMEType == "text/html"
&& Zotero.Attachments.getNumFiles(attachment) > 1) {
// Attachment is a snapshot with supporting files. Check if any of the
// supporting files would cause a name conflict, and build a list of transfers
// that should be performed
var copySrcs = [];
var files = attachment.getFile().parent.directoryEntries;
while (files.hasMoreElements()) {
file = files.getNext();
file.QueryInterface(Components.interfaces.nsIFile);
// Ignore the main attachment file (has already been checked for name conflict)
if(attachFile.equals(file)) {
continue;
}
// Remove any existing files in the target destination if overwriteExisting
// is set, or throw an exception if it is not
var targetSupportFile = targetFile.parent.clone();
targetSupportFile.append(file.leafName);
if(targetSupportFile.exists()) {
if(overwriteExisting) {
targetSupportFile.remove(false);
} else {
throw new Error("ERROR_FILE_EXISTS " + targetSupportFile.leafName);
}
}
copySrcs.push(file.clone());
}
// No conflicts were detected or all conflicts were resolved, perform the copying
attachFile.copyTo(directory, targetFile.leafName);
for(var i = 0; i < copySrcs.length; i++) {
copySrcs[i].copyTo(directory, copySrcs[i].leafName);
}
} else {
// Attachment is a single file
// Copy the file to the specified location
attachFile.copyTo(directory, targetFile.leafName);
}
};
}
}
attachmentArray.itemType = "attachment";
return attachmentArray;
},
/**
* Converts an item to array format
*/
"_itemToArray":function(returnItem) {
// TODO use Zotero.Item#serialize()
var returnItemArray = returnItem.toArray();
// Remove SQL date from multipart dates
if (returnItemArray.date) {
returnItemArray.date = Zotero.Date.multipartToStr(returnItemArray.date);
}
var returnItemArray = Zotero.Utilities.itemToExportFormat(returnItemArray);
// TODO: Change tag.tag references in translators to tag.name
// once translators are 1.5-only
// TODO: Preserve tag type?
if (returnItemArray.tags) {
for (var i in returnItemArray.tags) {
returnItemArray.tags[i].tag = returnItemArray.tags[i].fields.name;
}
}
// add URI
returnItemArray.uri = Zotero.URI.getItemURI(returnItem);
return returnItemArray;
},
/**
* Retrieves the next available item
*/
"nextItem":function() {
while(this._itemsLeft.length != 0) {
var returnItem = this._itemsLeft.shift();
// export file data for single files
if(returnItem.isAttachment()) { // an independent attachment
var returnItemArray = this._attachmentToArray(returnItem);
if(returnItemArray) return returnItemArray;
} else {
var returnItemArray = this._itemToArray(returnItem);
// get attachments, although only urls will be passed if exportFileData is off
returnItemArray.attachments = new Array();
var attachments = returnItem.getAttachments();
for each(var attachmentID in attachments) {
var attachment = Zotero.Items.get(attachmentID);
var attachmentInfo = this._attachmentToArray(attachment);
if(attachmentInfo) {
returnItemArray.attachments.push(attachmentInfo);
}
}
return returnItemArray;
}
}
return false;
},
"nextCollection":function() {
if(!this._collectionsLeft || this._collectionsLeft.length == 0) return false;
var returnItem = this._collectionsLeft.shift();
var obj = returnItem.serialize(true);
obj.id = obj.primary.collectionID;
obj.name = obj.fields.name;
return obj;
}
}
Zotero.Translate.ItemGetter.prototype.__defineGetter__("numItemsRemaining", function() { return this._itemsLeft.length });
--- translate_item_original.js 2012-02-10 19:15:22.000000000 -0500
+++ translate_item.js 2012-03-15 17:03:54.000000000 -0400
@@ -618,6 +618,8 @@
attachmentArray.mimeType = attachmentArray.uniqueFields.mimeType = attachment.attachmentMIMEType;
// Get charset
attachmentArray.charset = attachmentArray.uniqueFields.charset = attachment.attachmentCharset;
+ // get path
+ attachmentArray.path = attachmentArray.uniqueFields.path = attachment.getFile().persistentDescriptor;
if(linkMode != Zotero.Attachments.LINK_MODE_LINKED_URL && this._exportFileDirectory) {
var exportDir = this._exportFileDirectory;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment