zotero/translators/RIS.js
Dan Stillman af36412a11 Closes #1275, Map RIS ED tag to editor
Mapping both import and export. The spec doesn't actually give any indication that ED is for editors (and, given that AB isn't actually abstract, you can't really make assumptions when it comes to RIS), but other apps seem to put editors in ED

A forum user suggested that mixing and matching A1/A2 and ED caused creator data to be skipped altogether on import to EndNote. I haven't checked this, but I'm adding editor export to ED on the grounds that more data is better than less, and users can update other import filters if necessary.
2010-02-04 02:34:04 +00:00

527 lines
No EOL
13 KiB
JavaScript

{
"translatorID":"32d59d2d-b65a-4da4-b0a3-bdd3cfb979e7",
"translatorType":3,
"label":"RIS",
"creator":"Simon Kornblith",
"target":"ris",
"minVersion":"1.0.2",
"maxVersion":"",
"priority":100,
"inRepository":true,
"lastUpdated":"2010-02-04 02:24:27"
}
Zotero.configure("dataMode", "line");
Zotero.addOption("exportNotes", true);
Zotero.addOption("exportCharset", "UTF-8");
function detectImport() {
var line;
var i = 0;
while((line = Zotero.read()) !== false) {
line = line.replace(/^\s+/, "");
if(line != "") {
if(line.substr(0, 6).match(/^TY {1,2}- /)) {
return true;
} else {
if(i++ > 3) {
return false;
}
}
}
}
}
var fieldMap = {
ID:"itemID",
T1:"title",
T3:"series",
JF:"publicationTitle",
CY:"place",
JA:"journalAbbreviation",
M3:"DOI"
};
var inputFieldMap = {
TI:"title",
CT:"title",
CY:"place"
};
// TODO: figure out if these are the best types for letter, interview, webpage
var typeMap = {
book:"BOOK",
bookSection:"CHAP",
journalArticle:"JOUR",
magazineArticle:"MGZN",
newspaperArticle:"NEWS",
thesis:"THES",
letter:"PCOMM",
manuscript:"PAMP",
interview:"PCOMM",
film:"MPCT",
artwork:"ART",
report:"RPRT",
bill:"BILL",
case:"CASE",
hearing:"HEAR",
patent:"PAT",
statute:"STAT",
map:"MAP",
blogPost:"ELEC",
webpage:"ELEC",
instantMessage:"ICOMM",
forumPost:"ICOMM",
email:"ICOMM",
audioRecording:"SOUND",
presentation:"GEN",
videoRecording:"VIDEO",
tvBroadcast:"GEN",
radioBroadcast:"GEN",
podcast:"GEN",
computerProgram:"COMP",
conferencePaper:"CONF",
document:"GEN"
};
// supplements outputTypeMap for importing
// TODO: DATA, MUSIC
var inputTypeMap = {
ABST:"journalArticle",
ADVS:"film",
CTLG:"magazineArticle",
INPR:"manuscript",
JFULL:"journalArticle",
PAMP:"manuscript",
SER:"book",
SLIDE:"artwork",
UNBILL:"manuscript"
};
function processTag(item, tag, value) {
if (Zotero.Utilities.unescapeHTML) {
value = Zotero.Utilities.unescapeHTML(value.replace("\n", "<br>", "g"));
}
if(fieldMap[tag]) {
item[fieldMap[tag]] = value;
} else if(inputFieldMap[tag]) {
item[inputFieldMap[tag]] = value;
} else if(tag == "TY") {
// look for type
// first check typeMap
for(var i in typeMap) {
if(value == typeMap[i]) {
item.itemType = i;
}
}
// then check inputTypeMap
if(!item.itemType) {
if(inputTypeMap[value]) {
item.itemType = inputTypeMap[value];
} else {
// default to generic from inputTypeMap
item.itemType = inputTypeMap["GEN"];
}
}
} else if(tag == "JO") {
if (item.itemType == "conferencePaper"){
item.conferenceName = value;
} else {
item.publicationTitle = value;
}
} else if(tag == "BT") {
// ignore, unless this is a book or unpublished work, as per spec
if(item.itemType == "book" || item.itemType == "manuscript") {
item.title = value;
} else {
item.backupPublicationTitle = value;
}
} else if(tag == "T2") {
item.backupPublicationTitle = value;
} else if(tag == "A1" || tag == "AU") {
// primary author (patent: inventor)
// store Zotero "creator type" in temporary variable
var tempType;
if (item.itemType == "patent") {
tempType = "inventor";
} else {
tempType = "author";
}
var names = value.split(/, ?/);
item.creators.push({lastName:names[0], firstName:names[1], creatorType:tempType});
} else if(tag == "ED") {
var names = value.split(/, ?/);
item.creators.push({lastName:names[0], firstName:names[1], creatorType:"editor"});
} else if(tag == "A2") {
// contributing author (patent: assignee)
if (item.itemType == "patent") {
if (item.assignee) {
// Patents can have multiple assignees (applicants) but Zotero only allows a single
// assignee field, so we have to concatenate them together
item.assignee += ", "+value;
} else {
item.assignee = value;
}
} else {
var names = value.split(/, ?/);
item.creators.push({lastName:names[0], firstName:names[1], creatorType:"contributor"});
}
} else if(tag == "Y1" || tag == "PY") {
// year or date
var dateParts = value.split("/");
if(dateParts.length == 1) {
// technically, if there's only one date part, the file isn't valid
// RIS, but EndNote writes this, so we have to too
// Nick: RIS spec example records also only contain a single part
// even though it says the slashes are not optional (?)
item.date = value;
} else {
// in the case that we have a year and other data, format that way
var month = parseInt(dateParts[1]);
if(month) {
month--;
} else {
month = undefined;
}
item.date = Zotero.Utilities.formatDate({year:dateParts[0],
month:month,
day:dateParts[2],
part:dateParts[3]});
}
} else if(tag == "Y2") {
// the secondary date field can mean two things, a secondary date, or an
// invalid EndNote-style date. let's see which one this is.
// patent: application (filing) date -- do not append to date field
// for now. Zotero needs a filing date field added to make use of this.
var dateParts = value.split("/");
if(dateParts.length != 4 && item.itemType != "patent") {
// an invalid date and not a patent.
// It's from EndNote or Delphion (YYYY-MM-DD)
if(item.date && value.indexOf(item.date) == -1) {
// append existing year
value += " " + item.date;
}
item.date = value;
}
// ToDo: Handle correctly formatted Y2 fields (secondary date)
} else if(tag == "N1" || tag == "AB") {
// notes
if(value != item.title) { // why does EndNote do this!?
item.notes.push({note:value});
}
} else if(tag == "N2") {
// abstract
item.abstractNote = value;
} else if(tag == "KW") {
// keywords/tags
// technically, treating newlines as new tags breaks the RIS spec, but
// it's required to work with EndNote
item.tags = item.tags.concat(value.split("\n"));
} else if(tag == "SP") {
// start page
if(!item.pages) {
item.pages = value;
} else if(item.pages[0] == "-") { // already have ending page
item.pages = value + item.pages;
} else { // multiple ranges? hey, it's a possibility
item.pages += ", "+value;
}
} else if(tag == "EP") {
// end page
if(value) {
if(!item.pages) {
item.pages = value;
} else if(value != item.pages) {
item.pages += "-"+value;
}
}
} else if(tag == "SN") {
// ISSN/ISBN - just add both
if(!item.ISBN) {
item.ISBN = value;
}
if(!item.ISSN) {
item.ISSN = value;
}
} else if(tag == "UR" || tag == "L1" || tag == "L2" || tag == "L4") {
// URL
if(!item.url) {
item.url = value;
}
if(tag == "UR") {
item.attachments.push({url:value});
} else if(tag == "L1") {
item.attachments.push({url:value, mimeType:"application/pdf",
title:"Full Text (PDF)", downloadable:true});
} else if(tag == "L2") {
item.attachments.push({url:value, mimeType:"text/html",
title:"Full Text (HTML)", downloadable:true});
} else if(tag == "L4") {
item.attachments.push({url:value,
title:"Image", downloadable:true});
}
} else if (tag == "IS") {
// Issue Number (patent: patentNumber)
if (item.itemType == "patent") {
item.patentNumber = value;
} else {
item.issue = value;
}
} else if (tag == "VL") {
// Volume Number (patent: applicationNumber)
if (item.itemType == "patent") {
item.applicationNumber = value;
} else {
item.volume = value;
}
} else if (tag == "PB") {
// publisher (patent: references)
if (item.itemType == "patent") {
item.references = value;
} else {
item.publisher = value;
}
} else if (tag == "M1" || tag == "M2") {
// Miscellaneous fields
if (!item.extra) {
item.extra = value;
} else {
item.extra += "; "+value;
}
}
}
function completeItem(item) {
// if backup publication title exists but not proper, use backup
// (hack to get newspaper titles from EndNote)
if(item.backupPublicationTitle) {
if(!item.publicationTitle) {
item.publicationTitle = item.backupPublicationTitle;
}
item.backupPublicationTitle = undefined;
}
// hack for sites like Nature, which only use JA, journal abbreviation
if(item.journalAbbreviation && !item.publicationTitle){
item.publicationTitle = item.journalAbbreviation;
}
item.complete();
}
function doImport(attachments) {
var line = true;
var tag = data = false;
do { // first valid line is type
line = Zotero.read();
line = line.replace(/^\s+/, "");
} while(line !== false && !line.substr(0, 6).match(/^TY {1,2}- /));
var item = new Zotero.Item();
var i = 0;
if(attachments && attachments[i]) {
item.attachments = attachments[i];
}
var tag = "TY";
// Handle out-of-spec old EndNote exports
if (line.substr(0, 5) == "TY - ") {
var data = line.substr(5);
}
else {
var data = line.substr(6);
}
var rawLine;
while((rawLine = Zotero.read()) !== false) { // until EOF
// trim leading space if this line is not part of a note
line = rawLine.replace(/^\s+/, "");
if(line.substr(2, 4) == " - " || line == "ER -" || line.substr(0, 5) == "TY - ") {
// if this line is a tag, take a look at the previous line to map
// its tag
if(tag) {
Zotero.debug("tag: '"+tag+"'; data: '"+data+"'");
processTag(item, tag, data);
}
// then fetch the tag and data from this line
tag = line.substr(0,2);
// Handle out-of-spec old EndNote exports
if (line.substr(0, 5) == "TY - ") {
data = line.substr(5);
}
else {
data = line.substr(6);
}
if(tag == "ER") { // ER signals end of reference
// unset info
tag = data = false;
// new item
completeItem(item);
item = new Zotero.Item();
i++;
if(attachments && attachments[i]) {
item.attachments = attachments[i];
}
}
} else {
// otherwise, assume this is data from the previous line continued
if(tag == "N1" || tag == "N2" || tag == "AB" || tag == "KW") {
// preserve line endings for N1/N2/AB fields, for EndNote
// compatibility
data += "\n"+rawLine;
} else if(tag) {
// otherwise, follow the RIS spec
if(data[data.length-1] == " ") {
data += rawLine;
} else {
data += " "+rawLine;
}
}
}
}
if(tag && tag != "ER") { // save any unprocessed tags
Zotero.debug(tag);
processTag(item, tag, data);
completeItem(item);
}
}
function addTag(tag, value) {
if(value) {
Zotero.write(tag+" - "+value+"\r\n");
}
}
function doExport() {
var item;
while(item = Zotero.nextItem()) {
// can't store independent notes in RIS
if(item.itemType == "note" || item.itemType == "attachment") {
continue;
}
// type
addTag("TY", typeMap[item.itemType] ? typeMap[item.itemType] : "GEN");
// use field map
for(var j in fieldMap) {
if(item[fieldMap[j]]) addTag(j, item[fieldMap[j]]);
}
// creators
for(var j in item.creators) {
// only two types, primary and secondary
var risTag;
// authors and inventors are primary creators
if (item.creators[j].creatorType == "author" || item.creators[j].creatorType == "inventor") {
risTag = "A1";
} else if (item.creators[j].creatorType == "editor") {
risTag = "ED";
} else {
risTag = "A2";
}
addTag(risTag, item.creators[j].lastName+","+item.creators[j].firstName);
}
// assignee (patent)
if(item.assignee) {
addTag("A2", item.assignee);
}
// volume (patent: applicationNumber)
if(item.volume || item.applicationNumber) {
var value = (item.volume) ? item.volume : item.applicationNumber;
addTag("VL", value);
}
// issue (patent: patentNumber)
if(item.issue || item.patentNumber) {
var value = (item.issue) ? item.issue : item.patentNumber;
addTag("IS", value);
}
// publisher (patent: references)
if(item.publisher || item.references) {
var value = (item.publisher) ? item.publisher : item.references;
addTag("PB", value);
}
// date
if(item.date) {
var date = Zotero.Utilities.strToDate(item.date);
var string = date.year+"/";
if(date.month != undefined) {
// deal with javascript months
date.month++;
if(date.month < 10) string += "0";
string += date.month;
}
string += "/";
if(date.day != undefined) {
if(date.day < 10) string += "0";
string += date.day;
}
string += "/";
if(date.part != undefined) {
string += date.part;
}
addTag("PY", string);
}
// notes
if(Zotero.getOption("exportNotes")) {
for(var j in item.notes) {
addTag("N1", item.notes[j].note.replace(/(?:\r\n?|\n)/g, "\r\n"));
}
}
if(item.abstractNote) {
addTag("N2", item.abstractNote.replace(/(?:\r\n?|\n)/g, "\r\n"));
}
else if(item.abstract) {
// patent type has abstract
addTag("N2", item.abstract.replace(/(?:\r\n?|\n)/g, "\r\n"));
}
// tags
for each(var tag in item.tags) {
addTag("KW", tag.tag);
}
// pages
if(item.pages) {
if(item.itemType == "book") {
addTag("EP", item.pages);
} else {
var range = Zotero.Utilities.getPageRange(item.pages);
addTag("SP", range[0]);
addTag("EP", range[1]);
}
}
// ISBN/ISSN
addTag("SN", item.ISBN);
addTag("SN", item.ISSN);
// URL
if(item.url) {
addTag("UR", item.url);
} else if(item.source && item.source.substr(0, 7) == "http://") {
addTag("UR", item.source);
}
Zotero.write("ER - \r\n\r\n");
}
}