2019-08-02 10:09:36 +00:00
|
|
|
var Scaffold_Translators = {
|
|
|
|
// Keep in sync with translator.js
|
|
|
|
TRANSLATOR_TYPES: { import: 1, export: 2, web: 4, search: 8 },
|
|
|
|
|
|
|
|
_provider: null,
|
|
|
|
_translators: new Map(),
|
|
|
|
_translatorFiles: new Map(),
|
2021-12-29 01:32:56 +00:00
|
|
|
_onLoadBeginListener: null,
|
|
|
|
_onLoadCompleteListener: null,
|
2019-08-02 10:09:36 +00:00
|
|
|
|
2021-12-29 01:32:56 +00:00
|
|
|
load: Zotero.serial(async function (reload) {
|
2019-08-02 10:09:36 +00:00
|
|
|
if (this._translators.size && !reload) {
|
|
|
|
Zotero.debug("Scaffold: Translators already loaded");
|
2021-12-29 01:32:56 +00:00
|
|
|
return { numLoaded: 0, numDeleted: 0 };
|
2019-08-02 10:09:36 +00:00
|
|
|
}
|
2021-12-29 01:32:56 +00:00
|
|
|
|
|
|
|
if (this._onLoadBeginListener) this._onLoadBeginListener();
|
2019-08-02 10:09:36 +00:00
|
|
|
|
|
|
|
var t = new Date();
|
|
|
|
var dir = this.getDirectory();
|
|
|
|
var numLoaded = 0;
|
|
|
|
var deletedTranslators = new Set(this._translatorFiles.keys());
|
2019-08-28 11:44:35 +00:00
|
|
|
await Zotero.File.iterateDirectory(dir, async function (entry) {
|
|
|
|
if (entry.isDir || entry.name.startsWith('.') || !entry.name.endsWith('.js')) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
deletedTranslators.delete(entry.name);
|
|
|
|
|
|
|
|
try {
|
|
|
|
let fmtime;
|
|
|
|
if ('winLastWriteDate' in entry) {
|
|
|
|
fmtime = entry.winLastWriteDate.getTime();
|
|
|
|
}
|
|
|
|
else {
|
2023-12-04 10:05:34 +00:00
|
|
|
fmtime = (await IOUtils.stat(entry.path)).lastModified;
|
2019-08-28 11:44:35 +00:00
|
|
|
}
|
|
|
|
let translatorID = this._translatorFiles.get(entry.name);
|
|
|
|
let loadFile = true;
|
|
|
|
// If translator is already loaded, see if mtime has changed
|
|
|
|
if (translatorID) {
|
|
|
|
let mtime = this._translators.get(translatorID).mtime;
|
|
|
|
if (mtime == fmtime) {
|
|
|
|
loadFile = false;
|
2019-08-02 10:09:36 +00:00
|
|
|
}
|
2019-08-28 11:44:35 +00:00
|
|
|
}
|
|
|
|
if (loadFile) {
|
|
|
|
let translator = await Zotero.Translators.loadFromFile(entry.path);
|
|
|
|
this._translators.set(
|
|
|
|
translator.translatorID,
|
|
|
|
{
|
|
|
|
translator,
|
|
|
|
filename: entry.name,
|
|
|
|
mtime: fmtime,
|
2019-08-02 10:09:36 +00:00
|
|
|
}
|
2019-08-28 11:44:35 +00:00
|
|
|
);
|
|
|
|
this._translatorFiles.set(entry.name, translator.translatorID);
|
|
|
|
numLoaded++;
|
2019-08-02 10:09:36 +00:00
|
|
|
}
|
|
|
|
}
|
2019-08-28 11:44:35 +00:00
|
|
|
catch (e) {
|
|
|
|
Zotero.logError(e);
|
|
|
|
}
|
2019-08-02 10:09:36 +00:00
|
|
|
}.bind(this));
|
|
|
|
|
|
|
|
Zotero.debug(`Scaffold: Loaded ${numLoaded} ${Zotero.Utilities.pluralize(numLoaded, 'translator')} `
|
|
|
|
+ `in ${new Date() - t} ms`);
|
|
|
|
|
|
|
|
for (let filename of deletedTranslators) {
|
|
|
|
let id = this._translatorFiles.get(filename);
|
|
|
|
let translator = this._translators.get(id);
|
|
|
|
this._translatorFiles.delete(filename);
|
|
|
|
// Filename won't match if translator was renamed
|
|
|
|
if (translator.filename == filename) {
|
|
|
|
this._translators.delete(id);
|
|
|
|
}
|
|
|
|
}
|
2021-12-29 01:32:56 +00:00
|
|
|
|
|
|
|
if (this._onLoadCompleteListener) this._onLoadCompleteListener();
|
|
|
|
|
|
|
|
return {
|
|
|
|
numLoaded,
|
|
|
|
numDeleted: deletedTranslators.size
|
|
|
|
};
|
2019-08-02 10:09:36 +00:00
|
|
|
}),
|
|
|
|
|
|
|
|
deleteByID: async function (translatorID) {
|
|
|
|
var translator = this._translators.get(translatorID);
|
|
|
|
if (!translator) {
|
|
|
|
Zotero.debug("Scaffold: Can't delete missing translator");
|
|
|
|
return;
|
|
|
|
}
|
2023-12-04 10:05:34 +00:00
|
|
|
await IOUtils.remove(PathUtils.join(this.getDirectory(), translator.filename));
|
2019-08-02 10:09:36 +00:00
|
|
|
this._translators.delete(translatorID);
|
|
|
|
this._translatorFiles.delete(translator.filename);
|
|
|
|
},
|
|
|
|
|
|
|
|
getDirectory: function () {
|
|
|
|
return Zotero.Prefs.get('scaffold.translatorsDir');
|
|
|
|
},
|
2021-12-29 01:32:56 +00:00
|
|
|
|
|
|
|
getModifiedTime: function (translatorID) {
|
|
|
|
return this._translators.get(translatorID)?.mtime;
|
|
|
|
},
|
2019-08-02 10:09:36 +00:00
|
|
|
|
|
|
|
getProvider: function () {
|
|
|
|
if (this._provider) {
|
|
|
|
return this._provider;
|
|
|
|
}
|
|
|
|
this._provider = Zotero.Translators.makeTranslatorProvider({
|
|
|
|
get: function (translatorID) {
|
|
|
|
if (!this._translators.size) {
|
|
|
|
throw new Error("Scaffold: Translators not loaded");
|
|
|
|
}
|
|
|
|
var translator = this._translators.get(translatorID);
|
|
|
|
return translator ? translator.translator : false;
|
|
|
|
}.bind(this),
|
|
|
|
|
2021-07-28 12:32:13 +00:00
|
|
|
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),
|
|
|
|
|
2019-08-02 10:09:36 +00:00
|
|
|
getAllForType: async function (type) {
|
|
|
|
if (!this._translators.size) {
|
|
|
|
await this.load();
|
|
|
|
}
|
|
|
|
return [...this._translators.values()]
|
|
|
|
.map(x => x.translator)
|
|
|
|
.filter(translator => translator.translatorType & this.TRANSLATOR_TYPES[type]);
|
|
|
|
}.bind(this),
|
|
|
|
|
|
|
|
getTranslatorsDirectory: function () {
|
|
|
|
return this.getDirectory();
|
|
|
|
}.bind(this),
|
|
|
|
|
|
|
|
reinit: async function (options = {}) {
|
|
|
|
return this.load(
|
|
|
|
true,
|
|
|
|
options.filenames
|
|
|
|
);
|
|
|
|
}.bind(this)
|
|
|
|
});
|
|
|
|
return this._provider;
|
2021-12-29 01:32:56 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
setLoadListener({ onLoadBegin, onLoadComplete }) {
|
|
|
|
this._onLoadBeginListener = onLoadBegin;
|
|
|
|
this._onLoadCompleteListener = onLoadComplete;
|
2019-08-02 10:09:36 +00:00
|
|
|
}
|
2021-12-29 01:32:56 +00:00
|
|
|
};
|