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:
parent
c982155f21
commit
3c8ed5b273
2 changed files with 217 additions and 103 deletions
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in a new issue