commit 1ecc53b099bb96a5176843fe3a1f0f790e5d6924
parent 7b0c34a3ab176524c7c04d7d030a7128cd6a68e6
Author: Dan Stillman <dstillman@zotero.org>
Date: Thu, 6 Aug 2015 18:29:06 -0400
Merge pull request #820 from aurimasv/csl-json
Fix issues with computerProgram citations
Diffstat:
4 files changed, 112 insertions(+), 15 deletions(-)
diff --git a/chrome/content/zotero/xpcom/date.js b/chrome/content/zotero/xpcom/date.js
@@ -330,6 +330,8 @@ Zotero.Date = new function(){
}
if(date.month) date.month--; // subtract one for JS style
+ else delete date.month;
+
Zotero.debug("DATE: retrieved with algorithms: "+JSON.stringify(date));
parts.push(
@@ -369,7 +371,7 @@ Zotero.Date = new function(){
}
// MONTH
- if(!date.month) {
+ if(date.month === undefined) {
// compile month regular expression
var months = ['jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul',
'aug', 'sep', 'oct', 'nov', 'dec'];
diff --git a/chrome/content/zotero/xpcom/utilities.js b/chrome/content/zotero/xpcom/utilities.js
@@ -99,6 +99,7 @@ const CSL_DATE_MAPPINGS = {
/*
* Mappings for types
+ * Also see itemFromCSLJSON
*/
const CSL_TYPE_MAPPINGS = {
'book':"book",
@@ -1611,7 +1612,7 @@ Zotero.Utilities = {
cslItem[variable] = {"date-parts":[dateParts]};
// if no month, use season as month
- if(dateObj.part && !dateObj.month) {
+ if(dateObj.part && dateObj.month === undefined) {
cslItem[variable].season = dateObj.part;
}
} else {
@@ -1645,14 +1646,44 @@ Zotero.Utilities = {
* @param {Object} cslItem
*/
"itemFromCSLJSON":function(item, cslItem) {
- var isZoteroItem = item instanceof Zotero.Item, zoteroType;
-
- for(var type in CSL_TYPE_MAPPINGS) {
- if(CSL_TYPE_MAPPINGS[type] == cslItem.type) {
- zoteroType = type;
- break;
+ var isZoteroItem = item instanceof Zotero.Item,
+ zoteroType;
+
+ // Some special cases to help us map item types correctly
+ // This ensures that we don't lose data on import. The fields
+ // we check are incompatible with the alternative item types
+ if (cslItem.type == 'book') {
+ zoteroType = 'book';
+ if (cslItem.version) {
+ zoteroType = 'computerProgram';
+ }
+ } else if (cslItem.type == 'bill') {
+ zoteroType = 'bill';
+ if (cslItem.publisher || cslItem['number-of-volumes']) {
+ zoteroType = 'hearing';
+ }
+ } else if (cslItem.type == 'song') {
+ zoteroType = 'audioRecording';
+ if (cslItem.number) {
+ zoteroType = 'podcast';
+ }
+ } else if (cslItem.type == 'motion_picture') {
+ zoteroType = 'film';
+ if (cslItem['collection-title'] || cslItem['publisher-place']
+ || cslItem['event-place'] || cslItem.volume
+ || cslItem['number-of-volumes'] || cslItem.ISBN
+ ) {
+ zoteroType = 'videoRecording';
+ }
+ } else {
+ for(var type in CSL_TYPE_MAPPINGS) {
+ if(CSL_TYPE_MAPPINGS[type] == cslItem.type) {
+ zoteroType = type;
+ break;
+ }
}
}
+
if(!zoteroType) zoteroType = "document";
var itemTypeID = Zotero.ItemTypes.getID(zoteroType);
@@ -1667,9 +1698,14 @@ Zotero.Utilities = {
for(var variable in CSL_TEXT_MAPPINGS) {
if(variable in cslItem) {
var textMappings = CSL_TEXT_MAPPINGS[variable];
- for(var i in textMappings) {
- var field = textMappings[i],
- fieldID = Zotero.ItemFields.getID(field);
+ for(var i=0; i<textMappings.length; i++) {
+ var field = textMappings[i];
+
+ // Until 5.0, use version instead of versionNumber
+ if (field == 'versionNumber') field = 'version';
+
+ var fieldID = Zotero.ItemFields.getID(field);
+
if(Zotero.ItemFields.isBaseField(fieldID)) {
var newFieldID = Zotero.ItemFields.getFieldIDFromTypeAndBase(itemTypeID, fieldID);
if(newFieldID) fieldID = newFieldID;
@@ -1677,10 +1713,12 @@ Zotero.Utilities = {
if(Zotero.ItemFields.isValidForType(fieldID, itemTypeID)) {
if(isZoteroItem) {
- item.setField(fieldID, cslItem[variable], true);
+ item.setField(fieldID, cslItem[variable]);
} else {
item[field] = cslItem[variable];
}
+
+ break;
}
}
}
diff --git a/test/tests/data/citeProcJSExport.js b/test/tests/data/citeProcJSExport.js
@@ -1347,8 +1347,7 @@
1,
2
]
- ],
- "season": "2000-01-02"
+ ]
},
"title": "Title",
"type": "patent"
diff --git a/test/tests/utilities.js b/test/tests/utilities.js
@@ -221,7 +221,7 @@ describe("Zotero.Utilities", function() {
attachment.save();
- cslJSONAttachment = Zotero.Utilities.itemToCSLJSON(attachment);
+ let cslJSONAttachment = Zotero.Utilities.itemToCSLJSON(attachment);
assert.equal(cslJSONAttachment.type, 'article', 'attachment is exported as "article"');
assert.equal(cslJSONAttachment.title, 'Empty', 'attachment title is correct');
assert.deepEqual(cslJSONAttachment.accessed, {"date-parts":[["2001",2,3]]}, 'attachment access date is mapped correctly');
@@ -357,4 +357,62 @@ describe("Zotero.Utilities", function() {
assert.deepEqual(cslCreators[5], creators[5].expect, 'protected last name prevents parsing');
});
});
+ describe("itemFromCSLJSON", function() {
+ it("should stably perform itemToCSLJSON -> itemFromCSLJSON -> itemToCSLJSON", function() {
+ let data = loadSampleData('citeProcJSExport');
+
+ Zotero.DB.beginTransaction();
+
+ for (let i in data) {
+ let item = data[i];
+
+ let zItem = new Zotero.Item();
+ Zotero.Utilities.itemFromCSLJSON(zItem, item);
+ zItem = Zotero.Items.get(zItem.save());
+
+ let newItem = Zotero.Utilities.itemToCSLJSON(zItem);
+
+ delete newItem.id;
+ delete item.id;
+
+ assert.deepEqual(newItem, item, i + ' export -> import -> export is stable');
+ }
+
+ Zotero.DB.commitTransaction();
+
+ });
+ it("should import exported standalone note", function() {
+ let note = new Zotero.Item('note');
+ note.setNote('Some note longer than 50 characters, which will become the title.');
+ note = Zotero.Items.get(note.save());
+
+ let jsonNote = Zotero.Utilities.itemToCSLJSON(note);
+
+ let zItem = new Zotero.Item();
+ Zotero.Utilities.itemFromCSLJSON(zItem, jsonNote);
+ zItem = Zotero.Items.get(zItem.save());
+
+ assert.equal(zItem.getField('title'), jsonNote.title, 'title imported correctly');
+ });
+ it("should import exported standalone attachment", function() {
+ let file = getTestDataDirectory();
+ file.append("empty.pdf");
+
+ let attachment = Zotero.Items.get(Zotero.Attachments.importFromFile(file));
+ attachment.setField('title', 'Empty');
+ attachment.setField('accessDate', '2001-02-03 12:13:14');
+ attachment.setField('url', 'http://example.com');
+ attachment.setNote('Note');
+
+ attachment.save();
+
+ let jsonAttachment = Zotero.Utilities.itemToCSLJSON(attachment);
+
+ let zItem = new Zotero.Item();
+ Zotero.Utilities.itemFromCSLJSON(zItem, jsonAttachment);
+ zItem = Zotero.Items.get(zItem.save());
+
+ assert.equal(zItem.getField('title'), jsonAttachment.title, 'title imported correctly');
+ });
+ });
});