Merge pull request #1104 from adomasven/feature/connector-targetAll-support

Connector targetAll support
This commit is contained in:
Dan Stillman 2016-10-04 02:59:11 -04:00 committed by GitHub
commit cfc1b56ca6
3 changed files with 96 additions and 70 deletions

View file

@ -141,66 +141,47 @@ Zotero.Translators = new function() {
* @return {Promise<Array[]>} - A promise for a 2-item array containing an array of translators and
* an array of functions for converting URLs from proper to proxied forms
*/
this.getWebTranslatorsForLocation = Zotero.Promise.method(function (uri) {
this.getWebTranslatorsForLocation = Zotero.Promise.method(function (URI, rootURI) {
var isFrame = URI !== rootURI;
if(!_initialized) Zotero.Translators.init();
var allTranslators = _cache["web"];
var potentialTranslators = [];
var searchURIs = [uri];
Zotero.debug("Translators: Looking for translators for "+uri);
// if there is a subdomain that is also a TLD, also test against URI with the domain
// dropped after the TLD
// (i.e., www.nature.com.mutex.gmu.edu => www.nature.com)
var m = /^(https?:\/\/)([^\/]+)/i.exec(uri);
var properHosts = [];
var proxyHosts = [];
if(m) {
// First, drop the 0- if it exists (this is an III invention)
var host = m[2];
if(host.substr(0, 2) === "0-") host = host.substr(2);
var hostnames = host.split(".");
for(var i=1; i<hostnames.length-2; i++) {
if(TLDS[hostnames[i].toLowerCase()]) {
var properHost = hostnames.slice(0, i+1).join(".");
searchURIs.push(m[1]+properHost+uri.substr(m[0].length));
properHosts.push(properHost);
proxyHosts.push(hostnames.slice(i+1).join("."));
}
}
}
var converterFunctions = [];
var rootSearchURIs = this.getSearchURIs(rootURI);
var frameSearchURIs = isFrame ? this.getSearchURIs(URI) : rootSearchURIs;
Zotero.debug("Translators: Looking for translators for "+Object.keys(frameSearchURIs).join(', '));
for(var i=0; i<allTranslators.length; i++) {
for(var j=0; j<searchURIs.length; j++) {
// don't attempt to use translators with no target that can't be run in this browser
var translator = allTranslators[i];
if (isFrame && !translator.webRegexp.all) {
continue;
}
rootURIsLoop:
for(var rootSearchURI in rootSearchURIs) {
var isGeneric = !allTranslators[i].webRegexp.root;
// don't attempt to use generic translators that can't be run in this browser
// since that would require transmitting every page to Zotero host
if(!allTranslators[i].webRegexp
&& allTranslators[i].runMode !== Zotero.Translator.RUN_MODE_IN_BROWSER) {
if(isGeneric && allTranslators[i].runMode !== Zotero.Translator.RUN_MODE_IN_BROWSER) {
continue;
}
if(!allTranslators[i].webRegexp
|| (uri.length < 8192 && allTranslators[i].webRegexp.test(searchURIs[j]))) {
// add translator to list
potentialTranslators.push(allTranslators[i]);
if(j === 0) {
converterFunctions.push(null);
} else if(Zotero.isBrowserExt || 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) };
});
var rootURIMatches = isGeneric || rootSearchURI.length < 8192 && translator.webRegexp.root.test(rootSearchURI);
if (translator.webRegexp.all && rootURIMatches) {
for (var frameSearchURI in frameSearchURIs) {
var frameURIMatches = frameSearchURI.length < 8192 && translator.webRegexp.all.test(frameSearchURI);
if (frameURIMatches) {
potentialTranslators.push(translator);
converterFunctions.push(frameSearchURIs[frameSearchURI]);
// prevent adding the translator multiple times
break rootURIsLoop;
}
}
// don't add translator more than once
} else if(!isFrame && (isGeneric || rootURIMatches)) {
potentialTranslators.push(translator);
converterFunctions.push(rootSearchURIs[rootSearchURI]);
break;
}
}
@ -212,6 +193,47 @@ Zotero.Translators = new function() {
});
});
/**
* Get the array of searchURIs and related proxy converter functions
*
* @param {String} URI to get searchURIs and converterFunctions for
*/
this.getSearchURIs = function(URI) {
var searchURIs = {};
searchURIs[URI] = null;
// if there is a subdomain that is also a TLD, also test against URI with the domain
// dropped after the TLD
// (i.e., www.nature.com.mutex.gmu.edu => www.nature.com)
var m = /^(https?:\/\/)([^\/]+)/i.exec(URI);
if (m) {
// First, drop the 0- if it exists (this is an III invention)
var host = m[2];
if(host.substr(0, 2) === "0-") host = host.substr(2);
var hostnames = host.split(".");
for (var i=1; i<hostnames.length-2; i++) {
if (TLDS[hostnames[i].toLowerCase()]) {
var properHost = hostnames.slice(0, i+1).join(".");
var proxyHost = hostnames.slice(i+1).join(".");
var searchURI = m[1]+properHost+URI.substr(m[0].length);
if(Zotero.isBrowserExt || Zotero.isSafari) {
// in Chrome/Safari, the converterFunction needs to be passed as JSON, so
// just push an array with the proper and proxyHosts
searchURIs[searchURI] = [properHost, proxyHost];
} else {
// in Firefox, add a converterFunction
searchURIs[searchURI] = new function() {
var re = new RegExp('^https?://(?:[^/]+\\.)?'+Zotero.Utilities.quotemeta(properHost)+'(?=/)', "gi");
var _proxyHost = proxyHost.replace(/\$/g, "$$$$");
return function(uri) { return uri.replace(re, "$&."+_proxyHost) };
};
}
}
}
}
return searchURIs;
};
/**
* Converts translators to JSON-serializable objects
*/
@ -361,9 +383,12 @@ Zotero.Translators.CodeGetter.prototype.getAll = function () {
var TRANSLATOR_REQUIRED_PROPERTIES = ["translatorID", "translatorType", "label", "creator", "target",
"priority", "lastUpdated"];
var TRANSLATOR_OPTIONAL_PROPERTIES = ["targetAll", "browserSupport", "minVersion", "maxVersion",
"inRepository", "configOptions", "displayOptions",
"hiddenPrefs", "itemType"];
var TRANSLATOR_PASSING_PROPERTIES = TRANSLATOR_REQUIRED_PROPERTIES
.concat(["targetAll", "browserSupport", "code", "runMode", "itemType"]);
var TRANSLATOR_SAVE_PROPERTIES = TRANSLATOR_REQUIRED_PROPERTIES.concat(["browserSupport"]);
var TRANSLATOR_SAVE_PROPERTIES = TRANSLATOR_REQUIRED_PROPERTIES.concat(["browserSupport", "targetAll"]);
/**
* @class Represents an individual translator
* @constructor
@ -407,6 +432,12 @@ Zotero.Translator.prototype.init = function(info) {
this[property] = info[property];
}
}
for(var i=0; i<TRANSLATOR_OPTIONAL_PROPERTIES.length; i++) {
var property = TRANSLATOR_OPTIONAL_PROPERTIES[i];
if(info[property] !== undefined) {
this[property] = info[property];
}
}
this.browserSupport = info["browserSupport"] ? info["browserSupport"] : "g";

View file

@ -89,7 +89,7 @@ Zotero.Server.Connector.GetTranslators.prototype = {
// Translator data
var me = this;
if(data.url) {
Zotero.Translators.getWebTranslatorsForLocation(data.url).then(function(data) {
Zotero.Translators.getWebTranslatorsForLocation(data.url, data.rootUrl).then(function(data) {
sendResponseCallback(200, "application/json",
JSON.stringify(me._serializeTranslators(data[0])));
});
@ -106,13 +106,10 @@ Zotero.Server.Connector.GetTranslators.prototype = {
"_serializeTranslators":function(translators) {
var responseData = [];
for each(var translator in translators) {
let serializableTranslator = {};
for (let key of ["translatorID", "translatorType", "label", "creator", "target",
"minVersion", "maxVersion", "priority", "browserSupport", "inRepository", "lastUpdated"]) {
serializableTranslator[key] = translator[key];
}
responseData.push(serializableTranslator);
let properties = ["translatorID", "translatorType", "label", "creator", "target", "targetAll",
"minVersion", "maxVersion", "priority", "browserSupport", "inRepository", "lastUpdated"];
for (var translator of translators) {
responseData.push(translator.serialize(properties));
}
return responseData;
}

View file

@ -278,7 +278,7 @@ Zotero.Translators = new function() {
return this.getAllForType(type).then(function(allTranslators) {
var potentialTranslators = [];
var translatorConverterFunctions = [];
var converterFunctions = [];
var rootSearchURIs = this.getSearchURIs(rootURI);
var frameSearchURIs = isFrame ? this.getSearchURIs(URI) : rootSearchURIs;
@ -286,12 +286,10 @@ Zotero.Translators = new function() {
Zotero.debug("Translators: Looking for translators for "+Object.keys(frameSearchURIs).join(', '));
for (let translator of allTranslators) {
translatorLoop:
rootURIsLoop:
for (let rootSearchURI in rootSearchURIs) {
let isGeneric = (!translator.webRegexp.root && translator.runMode === Zotero.Translator.RUN_MODE_IN_BROWSER);
if (!isGeneric && !translator.webRegexp.root) {
continue;
}
let isGeneric = !translator.webRegexp.root;
let rootURIMatches = isGeneric || rootSearchURI.length < 8192 && translator.webRegexp.root.test(rootSearchURI);
if (translator.webRegexp.all && rootURIMatches) {
for (let frameSearchURI in frameSearchURIs) {
@ -299,21 +297,21 @@ Zotero.Translators = new function() {
if (frameURIMatches) {
potentialTranslators.push(translator);
translatorConverterFunctions.push(frameSearchURIs[frameSearchURI]);
converterFunctions.push(frameSearchURIs[frameSearchURI]);
// prevent adding the translator multiple times
break translatorLoop;
break rootURIsLoop;
}
}
}
else if(!isFrame && (isGeneric || rootURIMatches)) {
potentialTranslators.push(translator);
translatorConverterFunctions.push(rootSearchURIs[rootSearchURI]);
converterFunctions.push(rootSearchURIs[rootSearchURI]);
break;
}
}
}
return [potentialTranslators, translatorConverterFunctions];
return [potentialTranslators, converterFunctions];
}.bind(this));
},