- Use jsdom in node.js for unescaping HTML
- Add itemToExportFormat and itemToServerJSON utility functions - Support asynchronous translator loading (this will only be used in node.js) - Fix cases where Safari/Chrome code was incorrectly applied in node.js - Add Zotero.ItemFields.getItemTypeFields() to connector cachedTypes.js
This commit is contained in:
parent
167806a5bd
commit
e2993b94a4
7 changed files with 303 additions and 260 deletions
|
@ -48,7 +48,7 @@ Zotero.Connector_Types = new function() {
|
|||
this[schemaType][entry.name] = entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Passes schema to a callback
|
||||
|
@ -56,24 +56,24 @@ Zotero.Connector_Types = new function() {
|
|||
*/
|
||||
this.getSchema = function(callback) {
|
||||
callback(Zotero.Connector_Types.schema);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Zotero.CachedTypes = function() {
|
||||
this.getID = function(idOrName) {
|
||||
if(!Zotero.Connector_Types[this.schemaType][idOrName]) return false;
|
||||
return Zotero.Connector_Types[this.schemaType][idOrName].id;
|
||||
}
|
||||
};
|
||||
|
||||
this.getName = function(idOrName) {
|
||||
if(!Zotero.Connector_Types[this.schemaType][idOrName]) return false;
|
||||
return Zotero.Connector_Types[this.schemaType][idOrName].name;
|
||||
}
|
||||
};
|
||||
|
||||
this.getLocalizedString = function(idOrName) {
|
||||
if(!Zotero.Connector_Types[this.schemaType][idOrName]) return false;
|
||||
return Zotero.Connector_Types[this.schemaType][idOrName].localizedString;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Zotero.ItemTypes = new function() {
|
||||
|
@ -90,7 +90,7 @@ Zotero.ItemTypes = new function() {
|
|||
} else if(Zotero.isSafari) {
|
||||
return safari.extension.baseURI+"images/itemTypes/"+Zotero.Connector_Types["itemTypes"][idOrName].icon;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Zotero.CreatorTypes = new function() {
|
||||
|
@ -105,7 +105,7 @@ Zotero.CreatorTypes = new function() {
|
|||
creatorTypes.push(Zotero.Connector_Types["creatorTypes"][itemType.creatorTypes[i]]);
|
||||
}
|
||||
return creatorTypes;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Zotero.ItemFields = new function() {
|
||||
|
@ -119,7 +119,7 @@ Zotero.ItemFields = new function() {
|
|||
|
||||
return Zotero.Connector_Types["itemTypes"][typeIdOrName].fields.indexOf(
|
||||
Zotero.Connector_Types["fields"][fieldIdOrName].id) !== -1;
|
||||
}
|
||||
};
|
||||
|
||||
this.getFieldIDFromTypeAndBase = function(itemType, baseField) {
|
||||
if(!Zotero.Connector_Types["fields"][baseField]
|
||||
|
@ -138,5 +138,9 @@ Zotero.ItemFields = new function() {
|
|||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
this.getItemTypeFields = function(idOrName) {
|
||||
return Zotero.Connector_Types["itemTypes"][typeIdOrName].fields.slice();
|
||||
};
|
||||
}
|
|
@ -56,120 +56,9 @@ Zotero.Translate.ItemSaver.prototype = {
|
|||
* Saves items to server
|
||||
*/
|
||||
"_saveToServer":function(items, callback) {
|
||||
const IGNORE_FIELDS = ["seeAlso", "attachments", "complete"];
|
||||
|
||||
var newItems = [];
|
||||
for(var i in items) {
|
||||
var item = items[i];
|
||||
|
||||
var newItem = {};
|
||||
newItems.push(newItem);
|
||||
|
||||
var typeID = Zotero.ItemTypes.getID(item.itemType);
|
||||
if(!typeID) {
|
||||
Zotero.debug("Translate: Invalid itemType "+item.itemType+"; saving as webpage");
|
||||
item.itemType = "webpage";
|
||||
typeID = Zotero.ItemTypes.getID(item.itemType);
|
||||
}
|
||||
|
||||
var fieldID;
|
||||
for(var field in item) {
|
||||
if(IGNORE_FIELDS.indexOf(field) !== -1) continue;
|
||||
|
||||
var val = item[field];
|
||||
|
||||
if(field === "itemType") {
|
||||
newItem[field] = val;
|
||||
} else if(field === "creators") {
|
||||
// normalize creators
|
||||
var newCreators = newItem.creators = [];
|
||||
for(var j in val) {
|
||||
var creator = val[j];
|
||||
|
||||
// Single-field mode
|
||||
if (!creator.firstName || (creator.fieldMode && creator.fieldMode == 1)) {
|
||||
var newCreator = {
|
||||
name: creator.lastName
|
||||
};
|
||||
}
|
||||
// Two-field mode
|
||||
else {
|
||||
var newCreator = {
|
||||
firstName: creator.firstName,
|
||||
lastName: creator.lastName
|
||||
};
|
||||
}
|
||||
|
||||
// ensure creatorType is present and valid
|
||||
newCreator.creatorType = "author";
|
||||
if(creator.creatorType) {
|
||||
if(Zotero.CreatorTypes.getID(creator.creatorType)) {
|
||||
newCreator.creatorType = creator.creatorType;
|
||||
} else {
|
||||
Zotero.debug("Translate: Invalid creator type "+creator.creatorType+"; falling back to author");
|
||||
}
|
||||
}
|
||||
|
||||
newCreators.push(newCreator);
|
||||
}
|
||||
} else if(field === "tags") {
|
||||
// normalize tags
|
||||
var newTags = newItem.tags = [];
|
||||
for(var j in val) {
|
||||
var tag = val[j];
|
||||
if(typeof tag === "object") {
|
||||
if(tag.tag) {
|
||||
tag = tag.tag;
|
||||
} else if(tag.name) {
|
||||
tag = tag.name;
|
||||
} else {
|
||||
Zotero.debug("Translate: Discarded invalid tag");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
newTags.push({"tag":tag.toString(), "type":1})
|
||||
}
|
||||
} else if(field === "notes") {
|
||||
// normalize notes
|
||||
var newNotes = newItem.notes = [];
|
||||
for(var j in val) {
|
||||
var note = val[j];
|
||||
if(typeof note === "object") {
|
||||
if(!note.note) {
|
||||
Zotero.debug("Translate: Discarded invalid note");
|
||||
continue;
|
||||
}
|
||||
note = note.note;
|
||||
}
|
||||
newNotes.push({"itemType":"note", "note":note.toString()});
|
||||
}
|
||||
} else if(fieldID = Zotero.ItemFields.getID(field)) {
|
||||
// if content is not a string, either stringify it or delete it
|
||||
if(typeof val !== "string") {
|
||||
if(val || val === 0) {
|
||||
val = val.toString();
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// map from base field if possible
|
||||
var itemFieldID = Zotero.ItemFields.getFieldIDFromTypeAndBase(typeID, fieldID);
|
||||
if(itemFieldID) {
|
||||
newItem[Zotero.ItemFields.getName(itemFieldID)] = val;
|
||||
continue; // already know this is valid
|
||||
}
|
||||
|
||||
// if field is valid for this type, set field
|
||||
if(Zotero.ItemFields.isValidForType(fieldID, typeID)) {
|
||||
newItem[field] = val;
|
||||
} else {
|
||||
Zotero.debug("Translate: Discarded field "+field+": field not valid for type "+item.itemType, 3);
|
||||
}
|
||||
} else if(field !== "complete") {
|
||||
Zotero.debug("Translate: Discarded unknown field "+field, 3);
|
||||
}
|
||||
}
|
||||
newItems.push(Zotero.Utilities.itemToServerJSON(items[i]));
|
||||
}
|
||||
|
||||
var url = 'users/%%USERID%%/items?key=%%APIKEY%%';
|
||||
|
|
|
@ -42,7 +42,7 @@ Zotero.Translators = new function() {
|
|||
this.init = function(translators) {
|
||||
if(!translators) {
|
||||
translators = [];
|
||||
if(!Zotero.isFx && localStorage["translatorMetadata"]) {
|
||||
if((Zotero.isChrome || Zotero.isSafari) && localStorage["translatorMetadata"]) {
|
||||
try {
|
||||
translators = JSON.parse(localStorage["translatorMetadata"]);
|
||||
if(typeof translators !== "object") {
|
||||
|
@ -186,17 +186,17 @@ Zotero.Translators = new function() {
|
|||
|
||||
if(j === 0) {
|
||||
converterFunctions.push(null);
|
||||
} else if(Zotero.isFx) {
|
||||
} else if(Zotero.isChrome || Zotero.isSafari) {
|
||||
// in Chrome/Safari, the converterFunction needs to be passed as JSON, so
|
||||
// just push an array with the proper and proxyHosts
|
||||
converterFunctions.push([properHosts[j-1], proxyHosts[j-1]]);
|
||||
} else {
|
||||
// in Firefox, push the converterFunction
|
||||
converterFunctions.push(new function() {
|
||||
var re = new RegExp('^https?://(?:[^/]\\.)?'+Zotero.Utilities.quotemeta(properHosts[j-1]), "gi");
|
||||
var proxyHost = proxyHosts[j-1].replace(/\$/g, "$$$$");
|
||||
return function(uri) { return uri.replace(re, "$&."+proxyHost) };
|
||||
});
|
||||
} else {
|
||||
// in Chrome/Safari, the converterFunction needs to be passed as JSON, so
|
||||
// just push an array with the proper and proxyHosts
|
||||
converterFunctions.push([properHosts[j-1], proxyHosts[j-1]]);
|
||||
}
|
||||
|
||||
// don't add translator more than once
|
||||
|
@ -244,17 +244,6 @@ Zotero.Translators = new function() {
|
|||
|
||||
if(reset) {
|
||||
var serializedTranslators = newMetadata;
|
||||
if(!Zotero.isFx) {
|
||||
// clear cached translatorCode
|
||||
Zotero.debug("Translators: Resetting translators");
|
||||
// XXX this is only to clear localStorage for people who installed yesterday and
|
||||
// should disappear soon
|
||||
for(var i in localStorage) {
|
||||
if(i.substr(0, TRANSLATOR_CODE_PREFIX.length) === TRANSLATOR_CODE_PREFIX) {
|
||||
delete localStorage[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var serializedTranslators = [];
|
||||
var hasChanged = false;
|
||||
|
@ -300,7 +289,7 @@ Zotero.Translators = new function() {
|
|||
}
|
||||
|
||||
// Store
|
||||
if(!Zotero.isFx) {
|
||||
if(Zotero.isChrome || Zotero.isSafari) {
|
||||
localStorage["translatorMetadata"] = JSON.stringify(serializedTranslators);
|
||||
}
|
||||
|
||||
|
@ -440,7 +429,7 @@ Zotero.Translator.prototype.init = function(info) {
|
|||
}
|
||||
|
||||
if(info.code) {
|
||||
this.code = preprocessCode(info.code);
|
||||
this.code = Zotero.Translators.preprocessCode(info.code);
|
||||
} else if(this.hasOwnProperty("code")) {
|
||||
delete this.code;
|
||||
}
|
||||
|
|
|
@ -283,48 +283,48 @@ Zotero.Translate.Sandbox = {
|
|||
var sandbox;
|
||||
var haveTranslatorFunction = function(translator) {
|
||||
translation.translator[0] = translator;
|
||||
if(!translation._loadTranslator(translator)) throw new Error("Translator could not be loaded");
|
||||
|
||||
if(Zotero.isFx) {
|
||||
// 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);
|
||||
|
||||
Zotero.debug(outerSandboxURI.spec);
|
||||
Zotero.debug(innerSandboxURI.spec);
|
||||
|
||||
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._loadTranslator(translator, function() {
|
||||
if(Zotero.isFx) {
|
||||
// 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);
|
||||
|
||||
Zotero.debug(outerSandboxURI.spec);
|
||||
Zotero.debug(innerSandboxURI.spec);
|
||||
|
||||
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(sandbox.Export) {
|
||||
sandbox.Export.Zotero = sandbox.Zotero;
|
||||
sandbox = sandbox.Export;
|
||||
} else {
|
||||
translate._debug("COMPAT WARNING: "+translate.translator[0].label+" does "+
|
||||
"not export any properties. Only detect"+translate._entryFunctionSuffix+
|
||||
" and do"+translate._entryFunctionSuffix+" will be available in "+
|
||||
"connectors.");
|
||||
}
|
||||
|
||||
if(callback) {
|
||||
callback(sandbox);
|
||||
translate.decrementAsyncProcesses();
|
||||
}
|
||||
|
||||
translation._prepareTranslation();
|
||||
setDefaultHandlers(translate, translation);
|
||||
sandbox = translation._sandboxManager.sandbox;
|
||||
if(sandbox.Export) {
|
||||
sandbox.Export.Zotero = sandbox.Zotero;
|
||||
sandbox = sandbox.Export;
|
||||
} else {
|
||||
translate._debug("COMPAT WARNING: "+translate.translator[0].label+" does "+
|
||||
"not export any properties. Only detect"+translate._entryFunctionSuffix+
|
||||
" and do"+translate._entryFunctionSuffix+" will be available in "+
|
||||
"connectors.");
|
||||
}
|
||||
|
||||
if(callback) {
|
||||
callback(sandbox);
|
||||
translate.decrementAsyncProcesses();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
if(typeof translation.translator[0] === "object") {
|
||||
|
@ -929,27 +929,24 @@ Zotero.Translate.Base.prototype = {
|
|||
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._translateHaveTranslator();
|
||||
this._loadTranslator(this.translator[0], function() { me._translateTranslatorLoaded() });
|
||||
} else {
|
||||
// need to get translator first
|
||||
var me = this;
|
||||
Zotero.Translators.get(this.translator[0],
|
||||
function(translator) {
|
||||
me.translator[0] = translator;
|
||||
me._translateHaveTranslator();
|
||||
me._loadTranslator(translator, function() { me._translateTranslatorLoaded() });
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Called when translator has been retrieved
|
||||
* Called when translator has been retrieved and loaded
|
||||
*/
|
||||
"_translateHaveTranslator":function() {
|
||||
// load translators
|
||||
if(!this._loadTranslator(this.translator[0])) return;
|
||||
|
||||
"_translateTranslatorLoaded":function() {
|
||||
// set display options to default if they don't exist
|
||||
if(!this._displayOptions) this._displayOptions = this.translator[0].displayOptions;
|
||||
|
||||
|
@ -1091,7 +1088,7 @@ Zotero.Translate.Base.prototype = {
|
|||
},
|
||||
|
||||
/**
|
||||
* Runs detect code for a translator
|
||||
* Begins running detect code for a translator, first loading it
|
||||
*/
|
||||
"_detect":function() {
|
||||
// there won't be any translators if we need an RPC call
|
||||
|
@ -1100,7 +1097,15 @@ Zotero.Translate.Base.prototype = {
|
|||
return;
|
||||
}
|
||||
|
||||
if(!this._loadTranslator(this._potentialTranslators[0])) return
|
||||
var me = this;
|
||||
this._loadTranslator(this._potentialTranslators[0],
|
||||
function() { me._detectTranslatorLoaded() });
|
||||
},
|
||||
|
||||
/**
|
||||
* Runs detect code for a translator
|
||||
*/
|
||||
"_detectTranslatorLoaded":function() {
|
||||
this._prepareDetection();
|
||||
|
||||
this.incrementAsyncProcesses();
|
||||
|
@ -1130,7 +1135,7 @@ Zotero.Translate.Base.prototype = {
|
|||
* @param {Zotero.Translator} translator
|
||||
* @return {Boolean} Whether the translator could be successfully loaded
|
||||
*/
|
||||
"_loadTranslator":function(translator) {
|
||||
"_loadTranslator":function(translator, callback) {
|
||||
var sandboxLocation = this._getSandboxLocation();
|
||||
if(!this._sandboxLocation || sandboxLocation != this._sandboxLocation) {
|
||||
this._sandboxLocation = sandboxLocation;
|
||||
|
@ -1155,10 +1160,9 @@ Zotero.Translate.Base.prototype = {
|
|||
}
|
||||
|
||||
this.complete(false, "parse error");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
if(callback) callback();
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -1494,9 +1498,13 @@ Zotero.Translate.Import.prototype.complete = function(returnValue, error) {
|
|||
* Get all potential import translators, ordering translators with the right file extension first
|
||||
*/
|
||||
Zotero.Translate.Import.prototype._getTranslatorsGetPotentialTranslators = function() {
|
||||
var me = this;
|
||||
Zotero.Translators.getImportTranslatorsForLocation(this.location,
|
||||
function(translators) { me._getTranslatorsTranslatorsReceived(translators) });
|
||||
if(this.location) {
|
||||
var me = this;
|
||||
Zotero.Translators.getImportTranslatorsForLocation(this.location,
|
||||
function(translators) { me._getTranslatorsTranslatorsReceived(translators) });
|
||||
} else {
|
||||
Zotero.Translate.Base.prototype._getTranslatorsGetPotentialTranslators.call(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1507,10 +1515,13 @@ 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";
|
||||
this._foundTranslators = Zotero.Translators.getAllForType(this.type);
|
||||
this._potentialTranslators = [];
|
||||
this.complete(true);
|
||||
return this._foundTranslators;
|
||||
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 {
|
||||
Zotero.Translate.Base.prototype.getTranslators.call(this);
|
||||
}
|
||||
|
@ -1519,46 +1530,61 @@ Zotero.Translate.Import.prototype.getTranslators = function() {
|
|||
/**
|
||||
* Overload {@link Zotero.Translate.Base#_loadTranslator} to prepare translator IO
|
||||
*/
|
||||
Zotero.Translate.Import.prototype._loadTranslator = function(translator) {
|
||||
Zotero.Translate.Import.prototype._loadTranslator = function(translator, callback) {
|
||||
// call super
|
||||
var returnVal = Zotero.Translate.Base.prototype._loadTranslator.call(this, translator);
|
||||
if(!returnVal) return returnVal;
|
||||
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 dataMode = (translator ? translator : this._potentialTranslators[0]).configOptions["dataMode"];
|
||||
|
||||
var err = false;
|
||||
if(this._io) {
|
||||
try {
|
||||
this._io.reset(dataMode);
|
||||
} catch(e) {
|
||||
err = e;
|
||||
var me = this;
|
||||
var initCallback = function(status, err) {
|
||||
if(!status) {
|
||||
me.complete(false, err);
|
||||
} else {
|
||||
me._sandboxManager.importObject(me._io);
|
||||
if(callback) callback();
|
||||
}
|
||||
} else {
|
||||
};
|
||||
|
||||
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, dataMode);
|
||||
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 : "", dataMode);
|
||||
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) {
|
||||
Zotero.debug("Translate: Preparing IO for "+translator.label+" failed: ");
|
||||
Zotero.debug(err);
|
||||
this.complete(false, err);
|
||||
return false;
|
||||
return;
|
||||
}
|
||||
|
||||
this._sandboxManager.importObject(this._io);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1853,10 +1879,6 @@ Zotero.Translate.IO.String = function(string, uri, mode) {
|
|||
}
|
||||
this._stringPointer = 0;
|
||||
this._uri = uri;
|
||||
|
||||
if(mode) {
|
||||
this.reset(mode);
|
||||
}
|
||||
}
|
||||
|
||||
Zotero.Translate.IO.String.prototype = {
|
||||
|
@ -1868,16 +1890,16 @@ Zotero.Translate.IO.String.prototype = {
|
|||
"_getXML":"r"
|
||||
},
|
||||
|
||||
"_initRDF":function() {
|
||||
"_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._string.length) {
|
||||
var parser = new Zotero.RDF.AJAW.RDFParser(this._dataStore);
|
||||
parser.parse(Zotero.Translate.IO.parseDOMXML(this._string), this._uri);
|
||||
callback(true);
|
||||
}
|
||||
|
||||
this.RDF = new Zotero.Translate.IO._RDFSandbox(this._dataStore);
|
||||
},
|
||||
|
||||
"setCharacterSet":function(charset) {},
|
||||
|
@ -1936,12 +1958,14 @@ Zotero.Translate.IO.String.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
"reset":function(newMode) {
|
||||
"init":function(newMode, callback) {
|
||||
this._stringPointer = 0;
|
||||
|
||||
this._mode = newMode;
|
||||
if(Zotero.Translate.IO.rdfDataModes.indexOf(this._mode) !== -1) {
|
||||
this._initRDF();
|
||||
this._initRDF(callback);
|
||||
} else {
|
||||
callback(true);
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
@ -325,9 +325,6 @@ Zotero.Translate.IO.Read = function(file, mode) {
|
|||
}
|
||||
|
||||
Zotero.debug("Translate: Detected file charset as "+this._charset);
|
||||
|
||||
// We know the charset now. Open a converter stream.
|
||||
if(mode) this.reset(mode);
|
||||
}
|
||||
|
||||
Zotero.Translate.IO.Read.prototype = {
|
||||
|
@ -437,7 +434,7 @@ Zotero.Translate.IO.Read.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
"reset":function(newMode) {
|
||||
"init":function(newMode, callback) {
|
||||
if(Zotero.Translate.IO.maintainedInstances.indexOf(this) === -1) {
|
||||
Zotero.Translate.IO.maintainedInstances.push(this);
|
||||
}
|
||||
|
@ -447,6 +444,8 @@ Zotero.Translate.IO.Read.prototype = {
|
|||
if(Zotero.Translate.IO.rdfDataModes.indexOf(this._mode) !== -1 && !this.RDF) {
|
||||
this._initRDF();
|
||||
}
|
||||
|
||||
callback(true);
|
||||
},
|
||||
|
||||
"close":function() {
|
||||
|
|
|
@ -664,33 +664,7 @@ Zotero.Translate.ItemGetter.prototype = {
|
|||
returnItemArray.date = Zotero.Date.multipartToStr(returnItemArray.date);
|
||||
}
|
||||
|
||||
returnItemArray.uniqueFields = {};
|
||||
|
||||
// get base fields, not just the type-specific ones
|
||||
var itemTypeID = returnItem.itemTypeID;
|
||||
var allFields = Zotero.ItemFields.getItemTypeFields(itemTypeID);
|
||||
for each(var field in allFields) {
|
||||
var fieldName = Zotero.ItemFields.getName(field);
|
||||
|
||||
if(returnItemArray[fieldName] !== undefined) {
|
||||
var baseField = Zotero.ItemFields.getBaseIDFromTypeAndField(itemTypeID, field);
|
||||
|
||||
var baseName = null;
|
||||
if(baseField && baseField != field) {
|
||||
baseName = Zotero.ItemFields.getName(baseField);
|
||||
}
|
||||
|
||||
if(baseName) {
|
||||
returnItemArray[baseName] = returnItemArray[fieldName];
|
||||
returnItemArray.uniqueFields[baseName] = returnItemArray[fieldName];
|
||||
} else {
|
||||
returnItemArray.uniqueFields[fieldName] = returnItemArray[fieldName];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// preserve notes
|
||||
if(returnItemArray.note) returnItemArray.uniqueFields.note = returnItemArray.note;
|
||||
var returnItemArray = Zotero.Utilities.itemToExportFormat(returnItemArray);
|
||||
|
||||
// TODO: Change tag.tag references in translators to tag.name
|
||||
// once translators are 1.5-only
|
||||
|
|
|
@ -222,6 +222,17 @@ Zotero.Utilities = {
|
|||
var nsISUHTML = Components.classes["@mozilla.org/feed-unescapehtml;1"]
|
||||
.getService(Components.interfaces.nsIScriptableUnescapeHTML);
|
||||
return nsISUHTML.unescape(str);
|
||||
} else if(Zotero.isNode) {
|
||||
var doc = require('jsdom').jsdom(str, null, {
|
||||
"features":{
|
||||
"FetchExternalResources":false,
|
||||
"ProcessExternalResources":false,
|
||||
"MutationEvents":false,
|
||||
"QuerySelector":false
|
||||
}
|
||||
});
|
||||
if(!doc.documentElement) return str;
|
||||
return doc.documentElement.textContent;
|
||||
} else {
|
||||
var node = document.createElement("div");
|
||||
node.innerHTML = str;
|
||||
|
@ -796,6 +807,159 @@ Zotero.Utilities = {
|
|||
dumped_text = "===>"+arr+"<===("+typeof(arr)+")";
|
||||
}
|
||||
return dumped_text;
|
||||
},
|
||||
|
||||
/**
|
||||
* Adds all fields to an item in toArray() format and adds a unique (base) fields to
|
||||
* uniqueFields array
|
||||
*/
|
||||
"itemToExportFormat":function(item) {
|
||||
item.uniqueFields = {};
|
||||
|
||||
// get base fields, not just the type-specific ones
|
||||
var itemTypeID = (item.itemTypeID ? item.itemTypeID : Zotero.ItemTypes.getID(item.itemType));
|
||||
var allFields = Zotero.ItemFields.getItemTypeFields(itemTypeID);
|
||||
for(var i in allFields) {
|
||||
var field = allFields[i];
|
||||
var fieldName = Zotero.ItemFields.getName(field);
|
||||
|
||||
if(item[fieldName] !== undefined) {
|
||||
var baseField = Zotero.ItemFields.getBaseIDFromTypeAndField(itemTypeID, field);
|
||||
|
||||
var baseName = null;
|
||||
if(baseField && baseField != field) {
|
||||
baseName = Zotero.ItemFields.getName(baseField);
|
||||
}
|
||||
|
||||
if(baseName) {
|
||||
item[baseName] = item[fieldName];
|
||||
item.uniqueFields[baseName] = item[fieldName];
|
||||
} else {
|
||||
item.uniqueFields[fieldName] = item[fieldName];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// preserve notes
|
||||
if(item.note) item.uniqueFields.note = item.note;
|
||||
|
||||
return item;
|
||||
},
|
||||
|
||||
/**
|
||||
* Converts an item from toArray() format to content=json format used by the server
|
||||
*/
|
||||
"itemToServerJSON":function(item) {
|
||||
const IGNORE_FIELDS = ["seeAlso", "attachments", "complete"];
|
||||
var newItem = {};
|
||||
|
||||
var typeID = Zotero.ItemTypes.getID(item.itemType);
|
||||
if(!typeID) {
|
||||
Zotero.debug("Translate: Invalid itemType "+item.itemType+"; saving as webpage");
|
||||
item.itemType = "webpage";
|
||||
typeID = Zotero.ItemTypes.getID(item.itemType);
|
||||
}
|
||||
|
||||
var fieldID;
|
||||
for(var field in item) {
|
||||
if(IGNORE_FIELDS.indexOf(field) !== -1) continue;
|
||||
|
||||
var val = item[field];
|
||||
|
||||
if(field === "itemType") {
|
||||
newItem[field] = val;
|
||||
} else if(field === "creators") {
|
||||
// normalize creators
|
||||
var newCreators = newItem.creators = [];
|
||||
for(var j in val) {
|
||||
var creator = val[j];
|
||||
|
||||
// Single-field mode
|
||||
if (!creator.firstName || (creator.fieldMode && creator.fieldMode == 1)) {
|
||||
var newCreator = {
|
||||
name: creator.lastName
|
||||
};
|
||||
}
|
||||
// Two-field mode
|
||||
else {
|
||||
var newCreator = {
|
||||
firstName: creator.firstName,
|
||||
lastName: creator.lastName
|
||||
};
|
||||
}
|
||||
|
||||
// ensure creatorType is present and valid
|
||||
newCreator.creatorType = "author";
|
||||
if(creator.creatorType) {
|
||||
if(Zotero.CreatorTypes.getID(creator.creatorType)) {
|
||||
newCreator.creatorType = creator.creatorType;
|
||||
} else {
|
||||
Zotero.debug("Translate: Invalid creator type "+creator.creatorType+"; falling back to author");
|
||||
}
|
||||
}
|
||||
|
||||
newCreators.push(newCreator);
|
||||
}
|
||||
} else if(field === "tags") {
|
||||
// normalize tags
|
||||
var newTags = newItem.tags = [];
|
||||
for(var j in val) {
|
||||
var tag = val[j];
|
||||
if(typeof tag === "object") {
|
||||
if(tag.tag) {
|
||||
tag = tag.tag;
|
||||
} else if(tag.name) {
|
||||
tag = tag.name;
|
||||
} else {
|
||||
Zotero.debug("Translate: Discarded invalid tag");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
newTags.push({"tag":tag.toString(), "type":1})
|
||||
}
|
||||
} else if(field === "notes") {
|
||||
// normalize notes
|
||||
var newNotes = newItem.notes = [];
|
||||
for(var j in val) {
|
||||
var note = val[j];
|
||||
if(typeof note === "object") {
|
||||
if(!note.note) {
|
||||
Zotero.debug("Translate: Discarded invalid note");
|
||||
continue;
|
||||
}
|
||||
note = note.note;
|
||||
}
|
||||
newNotes.push({"itemType":"note", "note":note.toString()});
|
||||
}
|
||||
} else if(fieldID = Zotero.ItemFields.getID(field)) {
|
||||
// if content is not a string, either stringify it or delete it
|
||||
if(typeof val !== "string") {
|
||||
if(val || val === 0) {
|
||||
val = val.toString();
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// map from base field if possible
|
||||
var itemFieldID = Zotero.ItemFields.getFieldIDFromTypeAndBase(typeID, fieldID);
|
||||
if(itemFieldID) {
|
||||
newItem[Zotero.ItemFields.getName(itemFieldID)] = val;
|
||||
continue; // already know this is valid
|
||||
}
|
||||
|
||||
// if field is valid for this type, set field
|
||||
if(Zotero.ItemFields.isValidForType(fieldID, typeID)) {
|
||||
newItem[field] = val;
|
||||
} else {
|
||||
Zotero.debug("Translate: Discarded field "+field+": field not valid for type "+item.itemType, 3);
|
||||
}
|
||||
} else if(field !== "complete") {
|
||||
Zotero.debug("Translate: Discarded unknown field "+field, 3);
|
||||
}
|
||||
}
|
||||
|
||||
return newItem;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue