Add itemToCSLJSON utility function. At the moment, this differs from the implementation used by Word integration, but it uses the same mapping table. When we have unit tests, they will be unified.

This commit is contained in:
Simon Kornblith 2011-09-26 01:20:12 +00:00
parent c982155f21
commit 3c8ed5b273
2 changed files with 217 additions and 103 deletions

View file

@ -1,107 +1,12 @@
Zotero.Cite = function(){} Zotero.Cite = function(){}
Zotero.Cite.System = function(){}; Zotero.Cite.System = function(){};
/**
* Mappings for names
* Note that this is the reverse of the text variable map, since all mappings should be one to one
* and it makes the code cleaner
*/
Zotero.Cite.System._zoteroNameMap = {
"author":"author",
"bookAuthor":"container-author",
"composer":"composer",
"editor":"editor",
"interviewer":"interviewer",
"recipient":"recipient",
"seriesEditor":"collection-editor",
"translator":"translator"
}
/**
* Mappings for text variables
*/
Zotero.Cite.System._zoteroFieldMap = {
"title":["title"],
"container-title":["publicationTitle", "reporter", "code"], /* reporter and code should move to SQL mapping tables */
"collection-title":["seriesTitle", "series"],
"collection-number":["seriesNumber"],
"publisher":["publisher", "distributor"], /* distributor should move to SQL mapping tables */
"publisher-place":["place"],
"authority":["court"],
"page":["pages"],
"volume":["volume"],
"issue":["issue"],
"number-of-volumes":["numberOfVolumes"],
"number-of-pages":["numPages"],
"edition":["edition"],
"version":["version"],
"section":["section"],
"genre":["type", "artworkSize"], /* artworkSize should move to SQL mapping tables, or added as a CSL variable */
"medium":["medium", "system"],
"archive":["archive"],
"archive_location":["archiveLocation"],
"event":["meetingName", "conferenceName"], /* these should be mapped to the same base field in SQL mapping tables */
"event-place":["place"],
"abstract":["abstractNote"],
"URL":["url"],
"DOI":["DOI"],
"ISBN":["ISBN"],
"call-number":["callNumber"],
"note":["extra"],
"number":["number"],
"references":["history"],
"shortTitle":["shortTitle"],
"journalAbbreviation":["journalAbbreviation"],
"language":["language"]
}
Zotero.Cite.System._zoteroDateMap = {
"issued":"date",
"accessed":"accessDate"
}
Zotero.Cite.System._zoteroTypeMap = {
'book':"book",
'bookSection':'chapter',
'journalArticle':"article-journal",
'magazineArticle':"article-magazine",
'newspaperArticle':"article-newspaper",
'thesis':"thesis",
'encyclopediaArticle':"entry-encyclopedia",
'dictionaryEntry':"entry-dictionary",
'conferencePaper':"paper-conference",
'letter':"personal_communication",
'manuscript':"manuscript",
'interview':"interview",
'film':"motion_picture",
'artwork':"graphic",
'webpage':"webpage",
'report':"report",
'bill':"bill",
'case':"legal_case",
'hearing':"bill", // ??
'patent':"patent",
'statute':"bill", // ??
'email':"personal_communication",
'map':"map",
'blogPost':"webpage",
'instantMessage':"personal_communication",
'forumPost':"webpage",
'audioRecording':"song", // ??
'presentation':"speech",
'videoRecording':"motion_picture",
'tvBroadcast':"broadcast",
'radioBroadcast':"broadcast",
'podcast':"song", // ??
'computerProgram':"book" // ??
};
Zotero.Cite.System._quotedRegexp = /^".+"$/; Zotero.Cite.System._quotedRegexp = /^".+"$/;
// TODO: Clear this cache from time to time // TODO: Clear this cache from time to time
Zotero.Cite.System._cache = new Object(); Zotero.Cite.System._cache = new Object();
Zotero.Cite.System.retrieveItem = function(item){ Zotero.Cite.System.retrieveItem = function(item) {
var zoteroItem, slashIndex; var zoteroItem, slashIndex;
if(item instanceof Zotero.Item) { if(item instanceof Zotero.Item) {
//if(this._cache[item.id]) return this._cache[item.id]; //if(this._cache[item.id]) return this._cache[item.id];
@ -127,13 +32,13 @@ Zotero.Cite.System.retrieveItem = function(item){
} }
if(!zoteroItem) { if(!zoteroItem) {
throw "Zotero.Cite.getCSLItem called to wrap a non-item"; throw "Zotero.Cite.getCSLItem called to wrap a non-item "+item;
} }
// don't return URL or accessed information for journal articles if a // don't return URL or accessed information for journal articles if a
// pages field exists // pages field exists
var itemType = Zotero.ItemTypes.getName(zoteroItem.itemTypeID); var itemType = Zotero.ItemTypes.getName(zoteroItem.itemTypeID);
var cslType = Zotero.Cite.System._zoteroTypeMap[itemType]; var cslType = CSL_TYPE_MAPPINGS[itemType];
if(!cslType) cslType = "article"; if(!cslType) cslType = "article";
var ignoreURL = ((zoteroItem.getField("accessDate", true, true) || zoteroItem.getField("url", true, true)) && var ignoreURL = ((zoteroItem.getField("accessDate", true, true) || zoteroItem.getField("url", true, true)) &&
["journalArticle", "newspaperArticle", "magazineArticle"].indexOf(itemType) !== -1 ["journalArticle", "newspaperArticle", "magazineArticle"].indexOf(itemType) !== -1
@ -147,8 +52,8 @@ Zotero.Cite.System.retrieveItem = function(item){
// get all text variables (there must be a better way) // get all text variables (there must be a better way)
// TODO: does citeproc-js permit short forms? // TODO: does citeproc-js permit short forms?
for(var variable in Zotero.Cite.System._zoteroFieldMap) { for(var variable in CSL_TEXT_MAPPINGS) {
var fields = Zotero.Cite.System._zoteroFieldMap[variable]; var fields = CSL_TEXT_MAPPINGS[variable];
if(variable == "URL" && ignoreURL) continue; if(variable == "URL" && ignoreURL) continue;
for each(var field in fields) { for each(var field in fields) {
var value = zoteroItem.getField(field, false, true).toString(); var value = zoteroItem.getField(field, false, true).toString();
@ -173,7 +78,7 @@ Zotero.Cite.System.retrieveItem = function(item){
var creatorType = Zotero.CreatorTypes.getName(creator.creatorTypeID); var creatorType = Zotero.CreatorTypes.getName(creator.creatorTypeID);
} }
var creatorType = Zotero.Cite.System._zoteroNameMap[creatorType]; var creatorType = CSL_NAMES_MAPPINGS[creatorType];
if(!creatorType) continue; if(!creatorType) continue;
var nameObj = {'family':creator.ref.lastName, 'given':creator.ref.firstName}; var nameObj = {'family':creator.ref.lastName, 'given':creator.ref.firstName};
@ -186,8 +91,8 @@ Zotero.Cite.System.retrieveItem = function(item){
} }
// get date variables // get date variables
for(var variable in Zotero.Cite.System._zoteroDateMap) { for(var variable in CSL_DATE_MAPPINGS) {
var date = zoteroItem.getField(Zotero.Cite.System._zoteroDateMap[variable], false, true); var date = zoteroItem.getField(CSL_DATE_MAPPINGS[variable], false, true);
if(date) { if(date) {
var dateObj = Zotero.Date.strToDate(date); var dateObj = Zotero.Date.strToDate(date);
// otherwise, use date-parts // otherwise, use date-parts

View file

@ -26,6 +26,107 @@
***** END LICENSE BLOCK ***** ***** END LICENSE BLOCK *****
*/ */
/*
* Mappings for names
* Note that this is the reverse of the text variable map, since all mappings should be one to one
* and it makes the code cleaner
*/
const CSL_NAMES_MAPPINGS = {
"author":"author",
"bookAuthor":"container-author",
"composer":"composer",
"editor":"editor",
"interviewer":"interviewer",
"recipient":"recipient",
"seriesEditor":"collection-editor",
"translator":"translator"
}
/*
* Mappings for text variables
*/
const CSL_TEXT_MAPPINGS = {
"title":["title"],
"container-title":["publicationTitle", "reporter", "code"], /* reporter and code should move to SQL mapping tables */
"collection-title":["seriesTitle", "series"],
"collection-number":["seriesNumber"],
"publisher":["publisher", "distributor"], /* distributor should move to SQL mapping tables */
"publisher-place":["place"],
"authority":["court"],
"page":["pages"],
"volume":["volume"],
"issue":["issue"],
"number-of-volumes":["numberOfVolumes"],
"number-of-pages":["numPages"],
"edition":["edition"],
"version":["version"],
"section":["section"],
"genre":["type", "artworkSize"], /* artworkSize should move to SQL mapping tables, or added as a CSL variable */
"medium":["medium", "system"],
"archive":["archive"],
"archive_location":["archiveLocation"],
"event":["meetingName", "conferenceName"], /* these should be mapped to the same base field in SQL mapping tables */
"event-place":["place"],
"abstract":["abstractNote"],
"URL":["url"],
"DOI":["DOI"],
"ISBN":["ISBN"],
"call-number":["callNumber"],
"note":["extra"],
"number":["number"],
"references":["history"],
"shortTitle":["shortTitle"],
"journalAbbreviation":["journalAbbreviation"],
"language":["language"]
}
/*
* Mappings for dates
*/
const CSL_DATE_MAPPINGS = {
"issued":"date",
"accessed":"accessDate"
}
/*
* Mappings for types
*/
const CSL_TYPE_MAPPINGS = {
'book':"book",
'bookSection':'chapter',
'journalArticle':"article-journal",
'magazineArticle':"article-magazine",
'newspaperArticle':"article-newspaper",
'thesis':"thesis",
'encyclopediaArticle':"entry-encyclopedia",
'dictionaryEntry':"entry-dictionary",
'conferencePaper':"paper-conference",
'letter':"personal_communication",
'manuscript':"manuscript",
'interview':"interview",
'film':"motion_picture",
'artwork':"graphic",
'webpage':"webpage",
'report':"report",
'bill':"bill",
'case':"legal_case",
'hearing':"bill", // ??
'patent':"patent",
'statute':"bill", // ??
'email':"personal_communication",
'map':"map",
'blogPost':"webpage",
'instantMessage':"personal_communication",
'forumPost':"webpage",
'audioRecording':"song", // ??
'presentation':"speech",
'videoRecording':"motion_picture",
'tvBroadcast':"broadcast",
'radioBroadcast':"broadcast",
'podcast':"song", // ??
'computerProgram':"book" // ??
};
/** /**
* @class Functions for text manipulation and other miscellaneous purposes * @class Functions for text manipulation and other miscellaneous purposes
*/ */
@ -1085,5 +1186,113 @@ Zotero.Utilities = {
} }
return newItem; return newItem;
},
/**
* Converts an item from toArray() format to citeproc-js JSON
*/
"itemToCSLJSON":function(item) {
if(item instanceof Zotero.Item) {
item = item.toArray();
}
var itemType = item.itemType;
var cslType = CSL_TYPE_MAPPINGS[itemType];
if(!cslType) cslType = "article";
var cslItem = {
'id':item.itemID,
'type':cslType
};
// Map text fields
var itemTypeID = Zotero.ItemTypes.getID(itemType);
for(var variable in CSL_TEXT_MAPPINGS) {
var fields = CSL_TEXT_MAPPINGS[variable];
for(var i=0, n=fields.length; i<n; i++) {
var field = fields[i], value = undefined;
if(field in item) {
value = item[field];
} else {
var fieldID = Zotero.ItemFields.getID(field),
baseMapping
if(Zotero.ItemFields.isValidForType(fieldID, itemTypeID)
&& (baseMapping = Zotero.ItemFields.getBaseIDFromTypeAndField(itemTypeID, fieldID))) {
value = item[Zotero.ItemTypes.getName(baseMapping)];
}
}
if(!value) continue;
var valueLength = value.length;
if(valueLength) {
// Strip enclosing quotes
if(value[0] === '"' && value[valueLength-1] === '"') {
value = value.substr(1, valueLength-2);
}
}
cslItem[variable] = value;
break;
}
}
// separate name variables
var authorID = Zotero.CreatorTypes.getPrimaryIDForType(item.itemType);
var creators = item.creators;
if(creators) {
for(var i=0, n=creators.length; i<n; i++) {
var creator = creators[i];
if(creator.creatorTypeID == authorID) {
var creatorType = "author";
} else {
var creatorType = CSL_NAMES_MAPPINGS[creator.creatorType]
}
if(!creatorType) continue;
var nameObj = {'family':creator.lastName, 'given':creator.firstName};
if(cslItem[creatorType]) {
cslItem[creatorType].push(nameObj);
} else {
cslItem[creatorType] = [nameObj];
}
}
}
// get date variables
for(var variable in CSL_DATE_MAPPINGS) {
var date = item[CSL_DATE_MAPPINGS[variable]];
if(date) {
var dateObj = Zotero.Date.strToDate(date);
// otherwise, use date-parts
var dateParts = [];
if(dateObj.year) {
// add year, month, and day, if they exist
dateParts.push(dateObj.year);
if(dateObj.month !== undefined) {
dateParts.push(dateObj.month+1);
if(dateObj.day) {
dateParts.push(dateObj.day);
}
}
cslItem[variable] = {"date-parts":[dateParts]};
// if no month, use season as month
if(dateObj.part && !dateObj.month) {
cslItem[variable].season = dateObj.part;
}
} else {
// if no year, pass date literally
cslItem[variable] = {"literal":date};
}
}
}
//this._cache[item.id] = cslItem;
return cslItem;
} }
} }