diff --git a/chrome/content/scaffold/scaffold.js b/chrome/content/scaffold/scaffold.js
index faf4435fc5..0682440f67 100644
--- a/chrome/content/scaffold/scaffold.js
+++ b/chrome/content/scaffold/scaffold.js
@@ -269,7 +269,7 @@ var Scaffold = new function() {
}
//Strip JSON metadata
- var code = yield translator.getCode();
+ var code = yield _translatorProvider.getCodeForTranslator(translator);
var lastUpdatedIndex = code.indexOf('"lastUpdated"');
var header = code.substr(0, lastUpdatedIndex + 50);
var m = /^\s*{[\S\s]*?}\s*?[\r\n]+/.exec(header);
@@ -747,10 +747,6 @@ var Scaffold = new function() {
translator[props[i]] = metadata[props[i]];
}
- translator.getCode = function () {
- return Zotero.Promise.resolve(this.code);
- };
-
if(!translator.configOptions) translator.configOptions = {};
if(!translator.displayOptions) translator.displayOptions = {};
if(!translator.browserSupport) translator.browserSupport = "g";
diff --git a/chrome/content/scaffold/scaffold.xul b/chrome/content/scaffold/scaffold.xul
index 927d6feba7..ecc7d6e450 100644
--- a/chrome/content/scaffold/scaffold.xul
+++ b/chrome/content/scaffold/scaffold.xul
@@ -34,7 +34,7 @@
title="Scaffold"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
-
+
diff --git a/chrome/content/scaffold/translators.js b/chrome/content/scaffold/translators.js
index 606e6579e1..fcb7b31312 100644
--- a/chrome/content/scaffold/translators.js
+++ b/chrome/content/scaffold/translators.js
@@ -107,6 +107,17 @@ var Scaffold_Translators = {
return translator ? translator.translator : false;
}.bind(this),
+ getCodeForTranslator: async function (translator) {
+ if (translator.code) return translator.code;
+ return Zotero.File.getContentsAsync(translator.path).then(function(code) {
+ if (translator.cacheCode) {
+ // See Translator.init() for cache rules
+ translator.code = code;
+ }
+ return code;
+ });
+ }.bind(this),
+
getAllForType: async function (type) {
if (!this._translators.size) {
await this.load();
diff --git a/chrome/content/zotero/tools/testTranslators/testTranslators.css b/chrome/content/zotero/tools/testTranslators/testTranslators.css
deleted file mode 100644
index 035ec0a740..0000000000
--- a/chrome/content/zotero/tools/testTranslators/testTranslators.css
+++ /dev/null
@@ -1,86 +0,0 @@
-body {
- font-family: Helvetica, sans;
- font-size: 12px;
-}
-
-table {
- border-color: black;
- border-width: 0 0 1px 1px;
- border-style: solid;
- border-collapse: collapse;
- width: 100%;
-}
-
-td, th {
- border-color: black;
- border-width: 1px 1px 0 0;
- border-style: solid;
- padding: 2px;
-}
-
-.th-translator {
-}
-
-.th-status {
- width: 100px;
- max-width: 100px;
-}
-
-.th-pending, .th-supported, .th-succeeded, .th-failed, .th-mismatch {
- width: 75px;
- max-width: 75px;
-}
-
-.th-issues {
-}
-
-.status-succeeded, .supported-yes {
- background-color: #90ff90;
-}
-
-.status-failed, .supported-no {
- background-color: #ff9090;
-}
-
-.status-mismatch {
- background-color: #FFB;
-}
-
-.status-untested {
- background-color: #ececec;
-}
-
-.status-pending, .status-running {
- background-color: #9FF;
-}
-
-.status-partial-failure {
- background-color: rgb(249, 180, 98);
-}
-
-tr.output-displayed > td {
- background-color: #b4d5ff !important;
-}
-
-#translator-box {
- position: absolute;
- top: 0;
- bottom: 25%;
- left: 0;
- right: 0;
- padding: 5px;
- overflow: scroll;
-}
-
-#output-box {
- position: absolute;
- top: 75%;
- bottom: 0;
- left: 0;
- right: 0;
- padding: 5px;
- white-space: pre;
- overflow: scroll;
- font-family: Monaco, Courier, monospace;
- font-size: 10px;
-}
\ No newline at end of file
diff --git a/chrome/content/zotero/tools/testTranslators/testTranslators.html b/chrome/content/zotero/tools/testTranslators/testTranslators.html
deleted file mode 100644
index d2449288e1..0000000000
--- a/chrome/content/zotero/tools/testTranslators/testTranslators.html
+++ /dev/null
@@ -1,37 +0,0 @@
-
-
-
-
-
-
-
-
-
- Zotero Translator Tester
-
-
-
-
\ No newline at end of file
diff --git a/chrome/content/zotero/tools/testTranslators/testTranslators.js b/chrome/content/zotero/tools/testTranslators/testTranslators.js
deleted file mode 100644
index c5e822df52..0000000000
--- a/chrome/content/zotero/tools/testTranslators/testTranslators.js
+++ /dev/null
@@ -1,653 +0,0 @@
-/*
- ***** BEGIN LICENSE BLOCK *****
-
- Copyright © 2011 Center for History and New Media
- George Mason University, Fairfax, Virginia, USA
- http://zotero.org
-
- This file is part of Zotero.
-
- Zotero is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- Zotero is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with Zotero. If not, see .
-
- ***** END LICENSE BLOCK *****
-*/
-
-const NUM_CONCURRENT_TESTS = 6;
-const TABLE_COLUMNS = ["Translator", "Supported", "Status", "Pending", "Succeeded", "Failed", "Mismatch", "Issues"];
-// Not using const to prevent const collisions in connectors
-var TRANSLATOR_TYPES = ["Web", "Import", "Export", "Search"];
-var translatorTables = {},
- translatorTestViews = {},
- translatorTestViewsToRun = {},
- translatorTestStats = {},
- translatorBox,
- outputBox,
- allOutputView,
- currentOutputView,
- seleniumOutput = {},
- viewerMode = true;
-
-/**
- * Fetches issue information from GitHub
- */
-var Issues = new function() {
- var _executeWhenRetrieved = [];
- var githubInfo;
-
- /**
- * Gets issues for a specific translator
- * @param {String} translatorLabel Gets issues starting with translatorLabel
- * @param {Function} callback Function to call when issue information is available
- */
- this.getFor = function(translatorLabel, callback) {
- translatorLabel = translatorLabel.toLowerCase();
-
- var whenRetrieved = function() {
- var issues = [];
- for(var i=0; i {
- let translatorType = displayType.toLowerCase();
-
- translatorTestViews[translatorType] = [];
-
- // create header
- var h1 = document.createElement("h1");
- h1.appendChild(document.createTextNode(displayType+" Translators "));
-
- if(!viewerMode) {
- // create "run all"
- var runAll = document.createElement("a");
- runAll.href = "#";
- runAll.appendChild(document.createTextNode("(Run)"));
- runAll.addEventListener("click", new function() {
- var type = translatorType;
- return function(e) {
- e.preventDefault();
- runTranslatorTests(type);
- }
- }, false);
- h1.appendChild(runAll);
- }
-
- translatorBox.appendChild(h1);
-
- // create table
- var translatorTable = document.createElement("table");
- translatorTables[translatorType] = translatorTable;
-
- translatorTestStats[translatorType] = new TranslatorTestStats(translatorType);
- translatorBox.appendChild(translatorTestStats[translatorType].node);
-
- // add headings to table
- var headings = document.createElement("tr");
- for(var j in TABLE_COLUMNS) {
- var th = document.createElement("th");
- th.className = "th-"+TABLE_COLUMNS[j].toLowerCase();
- th.appendChild(document.createTextNode(TABLE_COLUMNS[j]));
- headings.appendChild(th);
- }
-
- // append to document
- translatorTable.appendChild(headings);
- translatorBox.appendChild(translatorTable);
-
- // get translators, with code for unsupported translators
- if(!viewerMode) {
- let translators = await Zotero.Translators.getAllForType(translatorType, true);
- haveTranslators(translators, translatorType);
- }
- }));
-
- if(viewerMode) {
- // if no Zotero object, try to unserialize data
- var req = new XMLHttpRequest();
- var loc = "testResults.json";
- if(window.location.hash) {
- var hashVars = {};
- var hashVarsSplit = window.location.hash.substr(1).split("&");
- for(var i=0; i {
- translatorTestView.runTests(resolve);
- });
- }
- var elem = document.createElement('p');
- elem.setAttribute('id', 'translator-tests-complete');
- document.body.appendChild(elem);
-}
-
-/**
- * Begin running all translator tests of a given type
- */
-function runTranslatorTests(type, callback) {
- for(var i in translatorTestViewsToRun[type]) {
- var testView = translatorTestViewsToRun[type][i];
- testView.updateStatus(testView._translatorTester, "pending");
- }
- for(var i=0; i.
-
- ***** END LICENSE BLOCK *****
-*/
-
-// Timeout for test to complete
-var TEST_RUN_TIMEOUT = 15000;
-var EXPORTED_SYMBOLS = ["Zotero_TranslatorTesters"];
-
-// For debugging specific translators by label
-var includeTranslators = [];
-
-if (typeof window != "undefined") {
- window.Zotero = window.Zotero;
-} else if (typeof global != 'undefined') {
- global.Zotero = global.Zotero;
-} else if (typeof this != 'undefined') {
- this.Zotero = this.Zotero;
-}
-
-var Zotero_TranslatorTesters = new function() {
- const TEST_TYPES = ["web", "import", "export", "search"];
- var collectedResults = {};
-
- /**
- * Runs all tests
- */
- this.runAllTests = function (numConcurrentTests, skipTranslators, writeDataCallback) {
- var id = Math.random() * (100000000 - 1) + 1;
-
- if (!(typeof process === 'object' && process + '' === '[object process]')){
- waitForDialog();
-
- if(!Zotero) {
- Zotero = Components.classes["@zotero.org/Zotero;1"]
- .getService(Components.interfaces.nsISupports).wrappedJSObject;
- }
- }
-
- var testers = [];
- var waitingForTranslators = TEST_TYPES.length;
- for(var i=0; i translators[i].label.includes(x))) continue;
- if (skipTranslators && skipTranslators[translators[i].translatorID]) continue;
- testers.push(new Zotero_TranslatorTester(translators[i], type));
- };
-
- if(!(--waitingForTranslators)) {
- runTesters(testers, numConcurrentTests, id, writeDataCallback);
- }
- } catch(e) {
- Zotero.debug(e);
- Zotero.logError(e);
- }
- };
- });
- };
- };
-
- /**
- * Runs a specific set of tests
- */
- function runTesters(testers, numConcurrentTests, id, writeDataCallback) {
- var testersRunning = 0;
- var results = []
-
- var testerDoneCallback = function(tester) {
- try {
- if(tester.pending.length) return;
-
- Zotero.debug("Done testing "+tester.translator.label);
-
- // Done translating, so serialize test results
- testersRunning--;
- let results = tester.serialize();
- let last = !testers.length && !testersRunning;
- collectData(id, results, last, writeDataCallback);
-
- if(testers.length) {
- // Run next tester if one is available
- runNextTester();
- }
- } catch(e) {
- Zotero.debug(e);
- Zotero.logError(e);
- }
- };
-
- var runNextTester = function() {
- if (!testers.length) {
- return;
- }
- testersRunning++;
- Zotero.debug("Testing "+testers[0].translator.label);
- testers.shift().runTests(testerDoneCallback);
- };
-
- for(var i=0; i {
- if (a.tag < b.tag) return -1;
- if (b.tag < a.tag) return 1;
- return 0;
- });
- }
-
- return item;
-};
-/**
- * Serializes translator tester results to JSON
- */
-Zotero_TranslatorTester.prototype.serialize = function() {
- return {
- "translatorID":this.translator.translatorID,
- "type":this.type,
- "output":this.output,
- "label":this.translator.label,
- "isSupported":this.isSupported,
- "pending":this.pending,
- "failed":this.failed,
- "succeeded":this.succeeded,
- "unknown":this.unknown
- };
-};
-
-/**
- * Sets tests for this translatorTester
- */
-Zotero_TranslatorTester.prototype.setTests = function(tests) {
- this.tests = tests.slice(0);
- this.pending = tests.slice(0);
- this.succeeded = [];
- this.failed = [];
- this.unknown = [];
-};
-
-/**
- * Executes tests for this translator
- * @param {Function} testDoneCallback A callback to be executed each time a test is complete
- */
-Zotero_TranslatorTester.prototype.runTests = function(testDoneCallback, recursiveRun) {
- if(!recursiveRun) {
- var w = (this.pending.length === 1) ? "test" : "tests";
- this._debug(this, "TranslatorTester: Running "+this.pending.length+" "+w+" for "+this.translator.label);
- }
-
- if(!this.pending.length) {
- // always call testDoneCallback once if there are no tests
- if(!recursiveRun && testDoneCallback) testDoneCallback(this, null, "unknown", "No tests present\n");
- return;
- }
-
- this._runTestsRecursively(testDoneCallback);
-};
-
-/**
- * Executes tests for this translator, without checks or a debug message
- * @param {Function} testDoneCallback A callback to be executed each time a test is complete
- */
-Zotero_TranslatorTester.prototype._runTestsRecursively = function(testDoneCallback) {
- var test = this.pending.shift();
- var testNumber = this.tests.length-this.pending.length;
- var me = this;
-
- this._debug(this, "TranslatorTester: Running "+this.translator.label+" Test "+testNumber);
-
- var executedCallback = false;
- var callback = function(obj, test, status, message) {
- if(executedCallback) return;
- executedCallback = true;
-
- me._debug(this, "TranslatorTester: "+me.translator.label+" Test "+testNumber+": "+status+" ("+message+")");
- me[status].push(test);
- test.message = message;
- if(testDoneCallback) testDoneCallback(me, test, status, message);
- me.runTests(testDoneCallback, true);
- };
-
- if(this.type === "web") {
- this.fetchPageAndRunTest(test, callback);
- } else {
- (Zotero.setTimeout ? Zotero : window).setTimeout(function() {
- me.runTest(test, null, callback);
- }, 0);
- }
-
- (Zotero.setTimeout ? Zotero : window).setTimeout(function() {
- callback(me, test, "failed", "Test timed out after "+TEST_RUN_TIMEOUT/1000+" seconds");
- }, TEST_RUN_TIMEOUT);
-};
-
-/**
- * Fetches the page for a given test and runs it
- *
- * This function is only applicable in Firefox; it is overridden in translator_global.js in Chrome
- * and Safari.
- *
- * @param {Object} test - Test to execute
- * @param {Function} testDoneCallback - A callback to be executed when test is complete
- */
-Zotero_TranslatorTester.prototype.fetchPageAndRunTest = function (test, testDoneCallback) {
- // Scaffold
- if (Zotero.isFx) {
- let browser = Zotero.HTTP.loadDocuments(
- test.url,
- (doc) => {
- if (test.defer) {
- Zotero.debug("Waiting " + (Zotero_TranslatorTester.DEFER_DELAY / 1000)
- + " second(s) for page content to settle");
- }
- setTimeout(() => {
- // Use cookies from document in translator HTTP requests
- this._cookieSandbox = new Zotero.CookieSandbox(null, test.url, doc.cookie);
-
- this.runTest(test, doc, function (obj, test, status, message) {
- Zotero.Browser.deleteHiddenBrowser(browser);
- testDoneCallback(obj, test, status, message);
- });
- }, test.defer ? Zotero_TranslatorTester.DEFER_DELAY : 0);
- },
- null,
- (e) => {
- Zotero.Browser.deleteHiddenBrowser(browser);
- testDoneCallback(this, test, "failed", "Translation failed to initialize: " + e);
- },
- true
- );
- browser.docShell.allowMetaRedirects = true;
- return
- }
-
- if (typeof process === 'object' && process + '' === '[object process]'){
- this._cookieSandbox = require('request').jar();
- }
- Zotero.HTTP.processDocuments(
- test.url,
- (doc) => {
- this.runTest(test, doc, function (obj, test, status, message) {
- testDoneCallback(obj, test, status, message);
- });
- },
- {
- cookieSandbox: this._cookieSandbox
- }
- )
- .catch(function (e) {
- testDoneCallback(this, test, "failed", "Translation failed to initialize: " + e);
- }.bind(this))
-};
-
-/**
- * Executes a test for a translator, given the document to test upon
- * @param {Object} test Test to execute
- * @param {Document} data DOM document to test against
- * @param {Function} testDoneCallback A callback to be executed when test is complete
- */
-Zotero_TranslatorTester.prototype.runTest = function(test, doc, testDoneCallback) {
- this._debug(this, "TranslatorTester: Translating"+(test.url ? " "+test.url : ""));
-
- var me = this;
- var translate = Zotero.Translate.newInstance(this.type);
- if (this.translatorProvider) {
- translate.setTranslatorProvider(this.translatorProvider);
- }
- if(this.type === "web") {
- translate.setDocument(doc);
- } else if(this.type === "import") {
- translate.setString(test.input);
- } else if(this.type === "search") {
- translate.setSearch(test.input);
- }
- if (translate.setCookieSandbox && this._cookieSandbox) {
- translate.setCookieSandbox(this._cookieSandbox);
- }
-
- translate.setHandler("translators", function(obj, translators) {
- me._runTestTranslate(translate, translators, test, testDoneCallback);
- });
- translate.setHandler("debug", this._debug);
- var errorReturned;
- translate.setHandler("error", function(obj, err) {
- errorReturned = err;
- });
- translate.setHandler("done", function(obj, returnValue) {
- me._checkResult(test, obj, returnValue, errorReturned, testDoneCallback);
- });
- var selectCalled = false;
- translate.setHandler("select", function(obj, items, callback) {
- if(test.items !== "multiple" && test.items.length <= 1) {
- testDoneCallback(me, test, "failed", "Zotero.selectItems() called, but only one item defined in test");
- callback({});
- return;
- } else if(selectCalled) {
- testDoneCallback(me, test, "failed", "Zotero.selectItems() called multiple times");
- callback({});
- return;
- }
-
- selectCalled = true;
- var newItems = {};
- var haveItems = false;
- for(var i in items) {
- if(items[i] && typeof(items[i]) == "object" && items[i].title !== undefined) {
- newItems[i] = items[i].title;
- } else {
- newItems[i] = items[i];
- }
- haveItems = true;
-
- // only save one item if "items":"multiple" (as opposed to an array of items)
- if(test.items === "multiple") break;
- }
-
- if(!haveItems) {
- testDoneCallback(me, test, "failed", "No items defined");
- callback({});
- }
-
- callback(newItems);
- });
- translate.capitalizeTitles = false;
-
- // internal hack to call detect on this translator
- translate._potentialTranslators = [this.translator];
- translate._foundTranslators = [];
- translate._currentState = "detect";
- translate._detect();
-}
-
-/**
- * Runs translation for a translator, given a document to test against
- */
-Zotero_TranslatorTester.prototype._runTestTranslate = function(translate, translators, test, testDoneCallback) {
- if(!translators.length) {
- testDoneCallback(this, test, "failed", "Detection failed");
- return;
- } else if(this.type === "web" && translators[0].itemType !== Zotero.Translator.RUN_MODE_ZOTERO_SERVER
- && (translators[0].itemType !== "multiple" && test.items.length > 1 ||
- test.items.length === 1 && translators[0].itemType !== test.items[0].itemType)) {
- // this handles "items":"multiple" too, since the string has length 8
- testDoneCallback(this, test, "failed", "Detection returned wrong item type");
- return;
- }
-
- translate.setTranslator(this.translator);
- translate.translate({
- libraryID: false
- });
-};
-
-/**
- * Checks whether the results of translation match what is expected by the test
- * @param {Object} test Test that was executed
- * @param {Zotero.Translate} translate The Zotero.Translate instance
- * @param {Boolean} returnValue Whether translation completed successfully
- * @param {Error} error Error code, if one was specified
- * @param {Function} testDoneCallback A callback to be executed when test is complete
- */
-Zotero_TranslatorTester.prototype._checkResult = function(test, translate, returnValue, error, testDoneCallback) {
- if(error) {
- var errorString = "Translation failed: "+error.toString();
- if(typeof error === "object") {
- for(var i in error) {
- if(typeof(error[i]) != "object") {
- errorString += "\n"+i+' => '+error[i];
- }
- }
- }
- testDoneCallback(this, test, "failed", errorString);
- return;
- }
-
- if(!returnValue) {
- testDoneCallback(this, test, "failed", "Translation failed; examine debug output for errors");
- return;
- }
-
- if(!translate.newItems.length) {
- testDoneCallback(this, test, "failed", "Translation failed: no items returned");
- return;
- }
-
- if(test.items !== "multiple") {
- if(translate.newItems.length !== test.items.length) {
- testDoneCallback(this, test, "unknown", "Expected "+test.items.length+" items; got "+translate.newItems.length);
- return;
- }
-
- for(var i=0, n=test.items.length; i