diff --git a/.nvmrc b/.nvmrc index 9a2a0e2..54c6511 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -v20 +v24 diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..6658883 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,2 @@ +package-lock.json +pandoc-zotxt.lua/ \ No newline at end of file diff --git a/Makefile b/Makefile index 4916595..11a66e5 100644 --- a/Makefile +++ b/Makefile @@ -2,11 +2,9 @@ VERSION=$(shell jq .version extension/manifest.json -r) -dist: test zotxt-$(VERSION).xpi ; +dist: unittest zotxt-$(VERSION).xpi ; -notest: zotxt-$(VERSION).xpi ; - -zotxt-$(VERSION).xpi: extension/*.js extension/resource/translators/EasyKeyExporter.js +zotxt-$(VERSION).xpi: extension/*.js extension/manifest.json extension/resource/translators/EasyKeyExporter.js cd extension && zip -r ../zotxt-$(VERSION).xpi * clean: @@ -17,3 +15,7 @@ unittest: test: unittest cd test && ruby test.rb + +format: + prettier -w . + rufo . diff --git a/README.md b/README.md index f0607c4..a4d4248 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,6 @@ For example: See [zotxt-emacs](https://github.com/egh/zotxt-emacs) -Zotxt API ---------- +## Zotxt API The Zotxt API is exposed via `http://127.0.0.1:23119/zotxt/`. To get an idea of what is possible, your best bet is probably to have a look at the `test/test.rb` file. diff --git a/extension/bootstrap.js b/extension/bootstrap.js index 9f8b054..543c268 100644 --- a/extension/bootstrap.js +++ b/extension/bootstrap.js @@ -13,90 +13,113 @@ // You should have received a copy of the GNU General Public License // along with Foobar. If not, see . -/* global Components, Set, FileUtils, NetUtil, Q, parseEasyKey, runSearch, buildRawSearch, buildEasyKeySearch, findByKey, cleanQuery, buildSearch, makeCslEngine, findByEasyKey, findByCitationKey, jsonStringify, item2key, makeClientError, ClientError, ensureLoaded */ -'use strict'; +/* global Components, Set, FileUtils, NetUtil, Q, runSearch, findByKey, cleanQuery, buildSearch, makeCslEngine, findByCitationKey, jsonStringify, item2key, ClientError, ensureLoaded, checkBBT */ +"use strict"; var uuidRe = /^[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12}/; -function makeEasyKeyExporterMetadata() { - return { - 'translatorID':'9d774afe-a51d-4055-a6c7-23bc96d19fe7', - 'label': 'Easy Citekey', - 'creator': 'Erik Hetzner', - 'target': 'txt', - 'minVersion': '2.1.9', - 'maxVersion': '', - 'priority': 200, - 'inRepository': false, - 'translatorType': 2, - 'browserSupport': 'gcs', - 'displayOptions': { - 'Alternate (@DoeTitle2000)': false - }, - 'lastUpdated':'2013-07-15 07:03:17' +const jsonMediaType = "application/json; charset=UTF-8"; +const textMediaType = "text/plain; charset=UTF-8"; +const badRequestCode = 400; +const okCode = 200; + +function loadZotero () { + let callback = function (resolve, reject) { + if (!Zotero) { + if (!("@zotero.org/Zotero;1" in Components.classes)) { + let timer = Components.classes["@mozilla.org/timer;1"].createInstanceComponents.interfaces.nsITimer; + return timer.initWithCallback(function () { + return callback(resolve, reject); + }, 10000, Components.interfaces.nsITimer.TYPE_ONE_SHOT); + } else { + Zotero = Components.classes["@zotero.org/Zotero;1"] + .getService(Components.interfaces.nsISupports).wrappedJSObject; + return resolve(Zotero); + } + } else { + return resolve(Zotero); + } }; + return new Promise(callback); +} + +function buildZoteroLink(item) { + // This is almost a direct copy from Zutilo + let libraryType = Zotero.Libraries.get(item.libraryID).libraryType; + var path = "undefined" + switch (libraryType) { + case 'group': + path = Zotero.URI.getLibraryPath(item.libraryID) + break; + case 'user': + path = 'library' + break; + default: + break; + } + return 'zotero://select/' + path + '/items/'+ item.key } -const jsonMediaType = 'application/json; charset=UTF-8'; -const textMediaType = 'text/plain; charset=UTF-8'; -const badRequestCode = 400; -const okCode = 200; function collectionSearch(name) { - let collections = Zotero.Collections.getByLibrary(Zotero.Libraries.userLibraryID, true); + let collections = Zotero.Collections.getByLibrary( + Zotero.Libraries.userLibraryID, + true, + ); for (let collection of collections) { if (collection.name === name) { - return Promise.resolve(collection.getChildItems()); + return collection.getChildItems(); } } - return makeClientError(`collection ${name} not found`); + throw new ClientError(`collection ${name} not found`); } -function processCitationItem (citation) { - let cloneButSetId = (item)=>{ +async function processCitationItem(citation) { + let cloneButSetId = (item) => { let retval = Object.assign({}, citation); retval.id = item.id; - delete(retval.easyKey); - delete(retval.key); + delete retval.easyKey; + delete retval.key; return retval; }; - if ('easyKey' in citation) { - return findByEasyKey(citation.easyKey, Zotero).then(cloneButSetId); - } else if ('key' in citation) { - return findByKey(citation.key, Zotero).then(cloneButSetId); + if ("easyKey" in citation) { + const item = await findByEasyKey(citation.easyKey, Zotero); + return cloneButSetId(item); + } else if ("key" in citation) { + const item = await findByKey(citation.key, Zotero); + return cloneButSetId(item); } else { - return Promise.resolve(citation); + return citation; } } /** * Map the easykeys in the citations to ids. */ -function processCitationsGroup (citationGroup) { +async function processCitationsGroup(citationGroup) { let citationItems = citationGroup.citationItems.map(processCitationItem); - return Promise.all(citationItems).then((items)=>{ - return { - 'properties': citationGroup.properties, - 'citationItems': items - }; - }); + const items = await Promise.all(citationItems); + return { + properties: citationGroup.properties, + citationItems: items, + }; } /** * Extract the ids from an array of citationGroups. */ -function extractIds (citationGroups) { +function extractIds(citationGroups) { let ids = []; - citationGroups.map (function(group) { - group.citationItems.map (function(citationItem) { + citationGroups.map(function (group) { + group.citationItems.map(function (citationItem) { ids.push(citationItem.id); }); }); return ids; } -function myExport (items, translatorId) { - let callback = function (resolve, reject) { +function myExport(items, translatorId) { + return new Promise((resolve, reject) => { let translation = new Zotero.Translate.Export(); translation.setItems(items); translation.setTranslator(translatorId); @@ -109,48 +132,51 @@ function myExport (items, translatorId) { reject(); } }); - if (translatorId === 'a515a220-6fef-45ea-9842-8025dfebcc8f') { - translation.setDisplayOptions({quickCopyMode: 'citekeys'}); + if (translatorId === "a515a220-6fef-45ea-9842-8025dfebcc8f") { + translation.setDisplayOptions({ quickCopyMode: "citekeys" }); } translation.translate(); - }; - let promise = new Promise(callback); - return promise; + }); } /** * Build a response based on items and a format parameter. */ -function buildResponse(items, format, style, locale) { - return ensureLoaded(items, Zotero).then((items)=>{ - if (format === 'key') { - return [okCode, 'application/json', jsonStringify(items.map(item2key))]; - } else if (format === 'easykey') { - return buildEasyKeyResponse(items); - } else if (format === 'betterbibtexkey' || format === 'citekey') { - return buildBBTKeyResponse(items); - } else if (format === 'bibtex') { - return buildBibTeXResponse(items); - } else if (format === 'bibliography') { - return buildBibliographyResponse(items, style, locale); - } else if (format === 'quickBib') { - return buildQuickBibResponse(items); - } else if (format === 'paths') { - return buildPathsResponse(items, style); - } else if (format && format.match(uuidRe)) { - return buildExportResponse(items, format); - } else { - return buildJsonResponse(items); - } - }); +async function buildResponse(items, format, style, locale) { + items = await ensureLoaded(items, Zotero); + if (format === "key") { + return [okCode, "application/json", jsonStringify(items.map(item2key))]; + } else if (format === "betterbibtexkey" || format === "citekey") { + return buildBBTKeyResponse(items); + } else if (format === "bibtex") { + return buildBibTeXResponse(items); + } else if (format === 'zoteroLink') { + return [okCode, 'application/json', jsonStringify(items.map(buildZoteroLink))]; + } else if (format === "bibliography") { + return buildBibliographyResponse(items, style, locale); + } else if (format === "quickBib") { + return buildQuickBibResponse(items); + } else if (format === "paths") { + return buildPathsResponse(items, style); + } else if (format && format.match(uuidRe)) { + return buildExportResponse(items, format); + } else { + return buildJsonResponse(items); + } } function buildJsonResponse(items) { /* Use BetterBibTeX JSON if available */ if (Zotero.BetterBibTeX) { - return buildExportResponse(items, 'f4b52ab0-f878-4556-85a0-c7aeedd09dfc'); + return buildExportResponse( + items, + "f4b52ab0-f878-4556-85a0-c7aeedd09dfc", + ); } else { - return buildExportResponse(items, 'bc03b4fe-436d-4a1f-ba59-de4d2d7a63f7'); + return buildExportResponse( + items, + "bc03b4fe-436d-4a1f-ba59-de4d2d7a63f7", + ); } } @@ -158,52 +184,47 @@ function buildJsonResponse(items) { * Build a response of a set of citation keys based on a set of items and a * translatorId via the Zotero export process. */ -function buildKeyResponse(items, translatorId) { +async function buildKeyResponse(items, translatorId) { if (items.length === 0) { - return [okCode, 'application/json', jsonStringify([])]; - } else { - return myExport(items, translatorId).then((rawKeys)=>{ - let keys = rawKeys.split(/[ ,]/); - // remove leading @ - let keys2 = keys.map(function(key) { return key.replace(/[\[\]@]/g, ''); }); - return [okCode, jsonMediaType, jsonStringify(keys2)]; - }); + return [okCode, "application/json", jsonStringify([])]; } -} - -function buildEasyKeyResponse(items) { - return buildKeyResponse(items, makeEasyKeyExporterMetadata().translatorID); + const rawKeys = await myExport(items, translatorId); + let keys = rawKeys.split(/[ ,]/); + // remove leading @ + let keys2 = keys.map(function (key) { + return key.replace(/[\[\]@]/g, ""); + }); + return [okCode, jsonMediaType, jsonStringify(keys2)]; } function buildBBTKeyResponse(items) { - if (!Zotero.BetterBibTeX) { - return makeClientError('BetterBibTex not installed.'); - } else { - return buildKeyResponse(items, 'a515a220-6fef-45ea-9842-8025dfebcc8f'); - } + checkBBT(); + return buildKeyResponse(items, "a515a220-6fef-45ea-9842-8025dfebcc8f"); } -function buildExportResponse(items, translatorId) { - return myExport(items, translatorId).then((data) => { - return [okCode, textMediaType, data]; - }); +async function buildExportResponse(items, translatorId) { + const data = await myExport(items, translatorId); + return [okCode, textMediaType, data]; } function buildBibTeXResponse(items) { - return buildExportResponse(items, '9cb70025-a888-4a29-a210-93ec52da40d4'); + return buildExportResponse(items, "9cb70025-a888-4a29-a210-93ec52da40d4"); } function buildBibliographyResponse(items, style, locale) { - let htmlCsl = makeCslEngine(style, locale, Zotero, 'html'); - let textCsl = makeCslEngine(style, locale, Zotero, 'text'); - let responseData = items.map ((item)=>{ + let htmlCsl = makeCslEngine(style, locale, Zotero, "html"); + let textCsl = makeCslEngine(style, locale, Zotero, "text"); + let responseData = items.map((item) => { htmlCsl.updateItems([item.id], true); textCsl.updateItems([item.id], true); return { - 'key': ((item.libraryID || '0') + '_' + item.key), - 'html': Zotero.Cite.makeFormattedBibliography(htmlCsl, 'html'), + key: (item.libraryID || "0") + "_" + item.key, + html: Zotero.Cite.makeFormattedBibliography(htmlCsl, "html"), // strip newlines - 'text': Zotero.Cite.makeFormattedBibliography(textCsl, 'text').replace(/(\r\n|\n|\r)/gm,'') + text: Zotero.Cite.makeFormattedBibliography( + textCsl, + "text", + ).replace(/(\r\n|\n|\r)/gm, ""), }; }); return [okCode, jsonMediaType, jsonStringify(responseData)]; @@ -215,25 +236,33 @@ function buildQuickBibResponse(items) { if (item.isRegularItem()) { let creators = item.getCreators(); let authors = []; - for (let i=0; i 0) { - let nameString = names[0].lastName + ', ' + names[0].firstName; + let nameString = names[0].lastName + ", " + names[0].firstName; if (names.length == 2) { - nameString += " & " + names[1].lastName + ', ' + names[1].firstName; + nameString += " & " + names[1].lastName + ", " + names[1].firstName; } else if (names.length > 1) { nameString += ", et al."; } @@ -241,257 +270,317 @@ function namesOrEtAl(names) { } } -function buildPathsResponse(items) { - let regularItems = items.filter((item)=>{ +async function buildPathsResponse(items) { + let regularItems = items.filter((item) => { return item.isRegularItem(); }); - let itemsWithPaths = regularItems.map((item)=>{ - let attachments = item.getAttachments(false).map((attachmentId)=>{ + let itemsWithPaths = regularItems.map(async (item) => { + let attachments = item.getAttachments(false).map((attachmentId) => { return Zotero.Items.get(attachmentId); }); - return Zotero.Promise.filter(attachments, (attachment)=>{ - return attachment.isFileAttachment(); - }).then ((attachments)=>{ - return attachments.map((a)=> { - return a.getFilePathAsync().then((path)=>{ - if (path) { - return path; - } else { - return Zotero.Sync.Runner.downloadFile(a).then((_)=>{ - return a.getFilePathAsync(); - }); - } - }); - }); - }).then((paths)=>{ - return Promise.all(paths).then((paths)=>{ - return { 'key': ((item.libraryID || '0') + '_' + item.key), 'paths': paths }; - }); - }); - }); - return Promise.all(itemsWithPaths).then((responseData)=>{ - return [okCode, jsonMediaType, jsonStringify(responseData)]; + + // Filter attachments to only file attachments + let fileAttachments = []; + for (let i = 0; i < attachments.length; i++) { + let attachment = attachments[i]; + if (attachment.isFileAttachment()) { + fileAttachments.push(attachment); + } + } + + let paths = await Promise.all( + fileAttachments.map(async (a) => { + const path = await a.getFilePathAsync(); + if (path) { + return path; + } else { + await Zotero.Sync.Runner.downloadFile(a); + return a.getFilePathAsync(); + } + }), + ); + + return { + key: (item.libraryID || "0") + "_" + item.key, + paths: paths, + }; }); + + const responseData = await Promise.all(itemsWithPaths); + return [okCode, jsonMediaType, jsonStringify(responseData)]; } -function handleErrors(f) { - return (...args)=>{ - return f(...args).catch((ex)=>{ - if (ex instanceof ClientError) { - return [badRequestCode, jsonMediaType, `"${ex.message}"`]; - } else { - return [500, textMediaType, (ex && (ex.message + ex.stack))]; +/** + * Handle errors from endpoint methods and return appropriate HTTP response. + */ +function handleEndpointError(ex) { + if (ex instanceof ClientError) { + return [badRequestCode, jsonMediaType, `"${ex.message}"`]; + } else { + return [500, textMediaType, ex && ex.message + ex.stack]; + } +} + +class VersionEndpoint { + supportedMethods = ["GET"]; + supportedDataTypes = ["application/x-www-form-urlencoded"]; + + init(request) { + try { + return [ + okCode, + jsonMediaType, + jsonStringify({ version: VersionEndpoint.version }), + ]; + } catch (ex) { + return handleEndpointError(ex); + } + } +} + +class CompleteEndpoint { + supportedMethods = ["GET"]; + supportedDataTypes = ["application/x-www-form-urlencoded"]; + + async init(request) { + try { + const prefix = request.searchParams.get("prefix"); + if (!prefix) { + throw new ClientError("Option prefix is required."); } - }); - }; + + const items = await searchByCitationKeyPrefix(prefix, Zotero); + return [ + okCode, + jsonMediaType, + jsonStringify( + items.map((item) => item.getField("citationKey")), + ), + ]; + } catch (ex) { + return handleEndpointError(ex); + } + } } -function bibliographyEndpoint(options) { - let cslEngine = makeCslEngine(options.data.styleId, options.data.locale, Zotero, 'html'); - if (!cslEngine) { - return makeClientError('No style found.'); - } else { - cslEngine.setOutputFormat('html'); - let groups = options.data.citationGroups.map(processCitationsGroup); - return Promise.all(groups).then((citationGroups)=>{ +class BibliographyEndpoint { + supportedMethods = ["POST"]; + supportedDataTypes = [ + "application/x-www-form-urlencoded", + "application/json", + ]; + + async init(request) { + try { + let cslEngine = makeCslEngine( + request.data.styleId, + request.data.locale, + Zotero, + "html", + ); + if (!cslEngine) { + throw new ClientError("No style found."); + } + + cslEngine.setOutputFormat("html"); + let groups = request.data.citationGroups.map(processCitationsGroup); + const citationGroups = await Promise.all(groups); + cslEngine.updateItems(extractIds(citationGroups)); let retval = {}; retval.bibliography = cslEngine.makeBibliography(); retval.citationClusters = []; - citationGroups.map (function (citationGroup) { - cslEngine.appendCitationCluster(citationGroup).map(function(updated) { - retval.citationClusters[updated[0]] = updated[1]; - }); - }); + citationGroups.map(function (citationGroup) { + cslEngine + .appendCitationCluster(citationGroup) + .map(function (updated) { + retval.citationClusters[updated[0]] = updated[1]; + }); + }); return [okCode, jsonMediaType, jsonStringify(retval)]; - }); + } catch (ex) { + return handleEndpointError(ex); + } } } -function makeVersionEndpoint(version) { - return (options)=>{ - let retval = {"version": version}; - return [okCode, jsonMediaType, jsonStringify(retval)]; +class SearchEndpoint { + supportedMethods = ["GET"]; + supportedDataTypes = ["application/x-www-form-urlencoded"]; + + async init(request) { + try { + const q = request.searchParams.get("q"); + const library = request.searchParams.get("library"); + const method = request.searchParams.get("method"); + const format = request.searchParams.get("format"); + const style = request.searchParams.get("style"); + const locale = request.searchParams.get("locale"); + if (!q) { + throw new ClientError("q param required."); + } + + let search = buildSearch(new Zotero.Search(), q, method); + if (!library) { + search.libraryID = Zotero.Libraries.userLibraryID; + } else if (library !== "all") { + search.libraryID = library; + } + const items = await runSearch(search, Zotero); + return await buildResponse(items, format, style, locale); + } catch (ex) { + return handleEndpointError(ex); + } } } -function completeEndpoint(options) { - const easykey = options.searchParams.get('easykey'); - if (!easykey) { - return makeClientError('Option easykey is required.'); - } else { - let search = buildEasyKeySearch(new Zotero.Search(), parseEasyKey(easykey, Zotero)); - return runSearch(search, Zotero).then((items)=>{ - if (!items) { - return makeClientError('EasyKey must be of the form DoeTitle2000 or doe:2000title'); +class SelectEndpoint { + supportedMethods = ["GET"]; + supportedDataTypes = ["application/x-www-form-urlencoded"]; + + async init(request) { + try { + let ZoteroPane = Components.classes[ + "@mozilla.org/appshell/window-mediator;1" + ] + .getService(Components.interfaces.nsIWindowMediator) + .getMostRecentWindow("navigator:browser").ZoteroPane; + const key = request.searchParams.get("key"); + const betterbibtexkey = request.searchParams.get("betterbibtexkey"); + const citekey = request.searchParams.get("citekey"); + + let item; + if (key) { + item = await findByKey(key, Zotero); + } else if (betterbibtexkey || citekey) { + item = await findByCitationKey( + betterbibtexkey || citekey, + Zotero, + ); } else { - return buildResponse(items, 'easykey'); + throw new ClientError("No param supplied!"); } - }); - } -} -function searchEndpoint(options) { - const q = options.searchParams.get('q'); - const library = options.searchParams.get('library'); - const method = options.searchParams.get('method'); - const format = options.searchParams.get('format'); - const style = options.searchParams.get('style'); - const locale = options.searchParams.get('locale'); - if (q) { - let search = buildSearch(new Zotero.Search(), q, method); - if (!library) { - search.libraryID = Zotero.Libraries.userLibraryID; - } else if (library !== "all") { - search.libraryID = library; + if (item === false) { + throw new ClientError("item with key " + key + " not found!"); + } + ZoteroPane.selectItem(item.id); + return [okCode, jsonMediaType, jsonStringify("success")]; + } catch (ex) { + return handleEndpointError(ex); } - return runSearch(search, Zotero).then((items)=>{ - return buildResponse(items, format, style, locale); - }); - } else { - return makeClientError('q param required.'); } } -function selectEndpoint(options) { - let ZoteroPane = Components.classes['@mozilla.org/appshell/window-mediator;1']. - getService(Components.interfaces.nsIWindowMediator).getMostRecentWindow('navigator:browser').ZoteroPane; - let promise = null; - const easykey = options.searchParams.get('easykey'); - const key = options.searchParams.get('key'); - const betterbibtexkey = options.searchParams.get('betterbibtexkey'); - const citekey = options.searchParams.get('citekey'); - if (easykey) { - promise = findByEasyKey(easykey, Zotero); - } else if (key) { - promise = findByKey(key, Zotero); - } else if (betterbibtexkey || citekey) { - promise = findByCitationKey(betterbibtexkey || citekey, Zotero); - } else { - return makeClientError('No param supplied!'); - } - return promise.then(function(item) { - if (item === false) { - return makeClientError('item with key ' + key + ' not found!'); +class ItemsEndpoint { + supportedMethods = ["GET"]; + supportedDataTypes = ["application/x-www-form-urlencoded"]; + + async init(request) { + try { + const selected = request.searchParams.get("selected"); + const key = request.searchParams.get("key"); + const betterbibtexkey = request.searchParams.get("betterbibtexkey"); + const citekey = request.searchParams.get("citekey"); + const collection = request.searchParams.get("collection"); + const all = request.searchParams.get("all"); + const format = request.searchParams.get("format"); + const style = request.searchParams.get("style"); + const locale = request.searchParams.get("locale"); + + let items; + if (selected) { + items = Zotero.getActiveZoteroPane().getSelectedItems(); + } else if (key) { + let keys = key.split(","); + items = await Promise.all( + keys.map((key) => { + return findByKey(key, Zotero); + }), + ); + } else if (betterbibtexkey || citekey) { + let keys = betterbibtexkey + ? betterbibtexkey.split(",") + : citekey.split(","); + items = await Promise.all( + keys.map((key) => { + return findByCitationKey(key, Zotero); + }), + ); + } else if (collection) { + items = await collectionSearch(collection); + } else if (all) { + items = await Zotero.Items.getAll( + Zotero.Libraries.userLibraryID, + ); + } else { + throw new ClientError("No param supplied!"); + } + + return await buildResponse(items, format, style, locale); + } catch (ex) { + return handleEndpointError(ex); } - ZoteroPane.selectItem(item.id); - return [okCode, jsonMediaType, jsonStringify('success')]; - }); + } } -function itemsEndpoint(options) { - const selected = options.searchParams.get('selected'); - const easykey = options.searchParams.get('easykey'); - const key = options.searchParams.get('key'); - const betterbibtexkey = options.searchParams.get('betterbibtexkey'); - const citekey = options.searchParams.get('citekey'); - const collection = options.searchParams.get('collection'); - const all = options.searchParams.get('all'); - const format = options.searchParams.get('format'); - const style = options.searchParams.get('style'); - const locale = options.searchParams.get('locale'); - let items = []; - let responder = (items) => { return buildResponse(items, format, style, locale); }; - if (selected) { - return responder(Zotero.getActiveZoteroPane().getSelectedItems()); - } else if (key) { - let keys = key.split(','); - return Promise.all( - keys.map((key)=>{ - return findByKey(key, Zotero); - })).then(responder); - } else if (easykey) { - let keys = easykey.split(','); - return Promise.all( - keys.map((key) => { - return findByEasyKey(key, Zotero); - })).then(responder); - } else if (betterbibtexkey || citekey) { - let keys = (betterbibtexkey ? betterbibtexkey.split(',') : citekey.split(',')); - return Promise.all( - keys.map((key) => { - return findByCitationKey(key, Zotero); - })).then(responder); - } else if (collection) - return collectionSearch(collection).then(responder); - else if (all) { - return Zotero.Items.getAll(Zotero.Libraries.userLibraryID).then(responder); - } else { - return makeClientError('No param supplied!'); +class StylesEndpoint { + supportedMethods = ["GET"]; + supportedDataTypes = ["application/x-www-form-urlencoded"]; + + init(request) { + return [ + okCode, + jsonMediaType, + jsonStringify(Zotero.Styles.getVisible()), + ]; } } -function stylesEndpoint(options) { - return [okCode, jsonMediaType, jsonStringify(Zotero.Styles.getVisible())]; -} +class LocalesEndpoint { + supportedMethods = ["GET"]; + supportedDataTypes = ["application/x-www-form-urlencoded"]; -function localesEndpoint(options) { - return [okCode, jsonMediaType, jsonStringify(Zotero.Locale.availableLocales)]; + init(request) { + return [ + okCode, + jsonMediaType, + jsonStringify(Zotero.Locale.availableLocales), + ]; + } } - + /** * Function to load our endpoints into the Zotero connector server. */ -function loadEndpoints (version) { - let endpoints = { - 'version': { - supportedMethods: ['GET'], - supportedDataType : ['application/x-www-form-urlencoded'], - init : makeVersionEndpoint(version) - }, - 'complete' : { - supportedMethods: ['GET'], - supportedDataType : ['application/x-www-form-urlencoded'], - init : handleErrors(completeEndpoint) - }, - 'bibliography' : { - supportedMethods: ['POST'], - supportedDataType: ['application/x-www-form-urlencoded'], - init: handleErrors(bibliographyEndpoint) - }, - 'search' : { - supportedMethods: ['GET'], - supportedDataType : ['application/x-www-form-urlencoded'], - init : handleErrors(searchEndpoint) - }, - 'select' : { - supportedMethods:['GET'], - supportedDataType : ['application/x-www-form-urlencoded'], - init : handleErrors(selectEndpoint) - }, - 'items' : { - supportedMethods:['GET'], - supportedDataType : ['application/x-www-form-urlencoded'], - init : handleErrors(itemsEndpoint) - }, - 'styles': { - supportedMethods:['GET'], - supportedDataType : ['application/x-www-form-urlencoded'], - init : stylesEndpoint - }, - 'locales': { - supportedMethods:['GET'], - supportedDataType : ['application/x-www-form-urlencoded'], - init : localesEndpoint - } - }; - for (let e in endpoints) { - let ep = Zotero.Server.Endpoints['/zotxt/' + e] = function() {}; - ep.prototype = endpoints[e]; - } +function loadEndpoints(version) { + // Register all endpoints + VersionEndpoint.version = version; + Zotero.Server.Endpoints["/zotxt/version"] = VersionEndpoint; + Zotero.Server.Endpoints["/zotxt/complete"] = CompleteEndpoint; + Zotero.Server.Endpoints["/zotxt/bibliography"] = BibliographyEndpoint; + Zotero.Server.Endpoints["/zotxt/search"] = SearchEndpoint; + Zotero.Server.Endpoints["/zotxt/select"] = SelectEndpoint; + Zotero.Server.Endpoints["/zotxt/items"] = ItemsEndpoint; + Zotero.Server.Endpoints["/zotxt/styles"] = StylesEndpoint; + Zotero.Server.Endpoints["/zotxt/locales"] = LocalesEndpoint; } -function startup({id, version, resourceURI, rootURI = resourceURI.spec}) { - Zotero.debug(rootURI + 'core.js'); - Services.scriptloader.loadSubScript(rootURI + 'core.js'); +function startup({ id, version, resourceURI, rootURI = resourceURI.spec }) { + Zotero.debug(rootURI + "core.js"); + Services.scriptloader.loadSubScript(rootURI + "core.js"); loadEndpoints(version); } -function shutdown () { +function shutdown() { + // Clean up all registered endpoints + for (const endpoint of Object.keys(Zotero.Server.Endpoints)) { + if (endpoint.startsWith("/zotxt/")) { + delete Zotero.Server.Endpoints[endpoint]; + } + } } -function uninstall() { -} +function uninstall() {} -function install() { -} +function install() {} diff --git a/extension/chrome.manifest b/extension/chrome.manifest deleted file mode 100644 index ca4d82c..0000000 --- a/extension/chrome.manifest +++ /dev/null @@ -1 +0,0 @@ -content zotxt content/ diff --git a/extension/core.js b/extension/core.js index a7ac726..e75f9ae 100644 --- a/extension/core.js +++ b/extension/core.js @@ -1,28 +1,8 @@ -/** - * Parses an easy key. Returns {creator: ..., title: ..., date: ...} or null if it - * did not parse correctly. - */ -function parseEasyKey(key, zotero) { - const easyKeyRe = zotero.Utilities.XRegExp('^(\\p{Lu}[\\p{Ll}_-]+)(\\p{Lu}\\p{Ll}+)?([0-9]{4})?'); - const alternateEasyKeyRe = zotero.Utilities.XRegExp('^([\\p{Ll}_-]+):([0-9]{4})?(\\p{Ll}+)?'); - let result = easyKeyRe.exec(key); - if (result) { - return {creator: result[1], title: result[2], date: result[3]}; - } else { - result = alternateEasyKeyRe.exec(key); - if (result) { - return {creator: result[1], title: result[3], date: result[2]}; - } else { - return null; - } - } -} - function fixStyleId(styleId) { if (!styleId) { - return 'http://www.zotero.org/styles/chicago-note-bibliography'; + return "http://www.zotero.org/styles/chicago-notes-bibliography"; } else if (!styleId.match(/^https?:/)) { - return 'http://www.zotero.org/styles/' + styleId; + return "http://www.zotero.org/styles/" + styleId; } else { return styleId; } @@ -34,53 +14,61 @@ function fixStyleId(styleId) { function cleanQuery(q) { let retval = {}; for (let key in q) { - retval[key] = q[key].replace('+', ' '); + retval[key] = q[key].replace("+", " "); } return retval; } /* Given a iterable of promises that return an item, return a deduped iterable * of promises (based on the id). */ -function dedupItems(items, zotero) { +async function dedupItems(items, zotero) { let seenIds = new Set([]); // To uniqify results - return zotero.Promise.filter(items, (item) => { - if (seenIds.has(item.id)) { - return false; - } else { + let resolvedItems = await Promise.all(items); + let dedupedItems = []; + for (let i = 0; i < resolvedItems.length; i++) { + let item = resolvedItems[i]; + if (!seenIds.has(item.id)) { seenIds.add(item.id); - return true; + dedupedItems.push(item); } - }); -}; + } + return dedupedItems; +} function ensureLoaded(items, zotero) { - return zotero.Promise.map(items, (item)=>{ - return item.loadAllData().then(()=> { + return Promise.all( + items.map(async (item) => { + await item.loadAllData(); return item; - }); - }); + }), + ); } function item2key(item) { - return ((item.libraryID || '1') + '_' + item.key); + return (item.libraryID || "1") + "_" + item.key; } -function findByKey(key, zotero) { - let rejectIfUndefined = (item)=>{ - if (!item) { - return makeClientError(`${key} not found`); - } else { - return item; - } - }; - if (key.indexOf('/') !== -1) { +async function findByKey(key, zotero) { + let item; + if (key.indexOf("/") !== -1) { let lkh = zotero.Items.parseLibraryKey(key); - return zotero.Items.getByLibraryAndKeyAsync(lkh.libraryID, lkh.key).then(rejectIfUndefined); - } else if (key.indexOf('_') !== -1) { - let [libraryId, key2] = key.split('_'); - return zotero.Items.getByLibraryAndKeyAsync(parseInt(libraryId), key2).then(rejectIfUndefined); + item = await zotero.Items.getByLibraryAndKeyAsync( + lkh.libraryID, + lkh.key, + ); + } else if (key.indexOf("_") !== -1) { + let [libraryId, key2] = key.split("_"); + item = await zotero.Items.getByLibraryAndKeyAsync( + parseInt(libraryId), + key2, + ); + } else { + item = await zotero.Items.getByLibraryAndKeyAsync(1, key); + } + if (!item) { + throw new ClientError(`${key} not found`); } else { - return zotero.Items.getByLibraryAndKeyAsync(1, key).then(rejectIfUndefined); + return item; } } @@ -92,7 +80,7 @@ function checkStyleId(styleId, zotero) { return styleId; } -function makeCslEngine (styleIdRaw, locale, zotero, format) { +function makeCslEngine(styleIdRaw, locale, zotero, format) { const styleId = fixStyleId(styleIdRaw); checkStyleId(styleId, zotero); let style = zotero.Styles.get(styleId); @@ -115,132 +103,83 @@ function getItemOrParent(item, zotero) { } } -/** - * Returns a promise resolving to an iterable. - */ -function runSearch(s, zotero) { - return s.search().then((ids) => { - let items = zotero.Items.getAsync(ids); - let items2 = zotero.Promise.map(items, (item)=>{ - return getItemOrParent(item, zotero) - }); - return dedupItems(items2, zotero); - }); -} - -function buildRawSearch(s, key) { - let str = '@' + key; - s.addCondition('joinMode', 'any'); - s.addCondition('tag', 'is', str); - s.addCondition('note', 'contains', str); - return s; -} - -/** - * Find many items by a (possibly incomplete) parsed easy key. - */ -function buildEasyKeySearch(s, parsedKey) { - /* allow multiple names separated by _ */ - var splitName = parsedKey.creator.split('_'); - for (let name of splitName) { - s.addCondition('creator', 'contains', name); - } - if (parsedKey.title != null) { - s.addCondition('title', 'contains', parsedKey.title); - } - if (parsedKey.date != null) { - s.addCondition('date', 'is', parsedKey.date); - } - return s; +async function runSearch(s, zotero) { + let results = await s.search(); + let items = await zotero.Items.getAsync(results); + let items2 = await Promise.all( + items.map((item) => { + return getItemOrParent(item, zotero); + }), + ); + return dedupItems(items2, zotero); } function buildSearch(s, query, method) { - if (!method) { method = 'titleCreatorYear'; } - s.addCondition('joinMode', 'all'); + if (!method) { + method = "titleCreatorYear"; + } + s.addCondition("joinMode", "all"); for (let word of query.split(/(?:\+|\s+)/)) { - s.addCondition('quicksearch-' + method, 'contains', word); + s.addCondition("quicksearch-" + method, "contains", word); } return s; } - -function ClientError(message) { - this.name = 'ClientError'; - this.message = message; - this.stack = (new Error()).stack; -} - -ClientError.prototype = new Error; - -function makeClientError(str) { - return Promise.reject(new ClientError(str)); -} - -/** - * Find a single item by its easy key, caching the result. - */ -function findByEasyKey(key, zotero) { - let parsedKey = parseEasyKey(key, zotero); - if (!parsedKey) { - return makeClientError(`${key} must be of the form DoeTitle2000 or doe:2000title`); - } else { - /* first try raw search */ - let search = buildRawSearch(new zotero.Search(), key); - return runSearch(search, zotero).then(function(items) { - if (items.length === 1) { - return items[0]; - } else if (items.length > 1) { - return makeClientError(`${key} returned multiple items`); - } else { - let search = buildEasyKeySearch(new zotero.Search(), parsedKey); - return runSearch(search, zotero).then (function (items) { - if (items.length > 1) { - // hack to ignore group library duplicates - // remove all items not in the local library - items = items.filter(function (item) { return item.libraryID === zotero.Libraries.userLibraryID; }); - } - if (items.length === 1) { - return items[0]; - } else if (items.length > 1) { - return makeClientError(`${key} returned multiple items`); - } else { - return makeClientError(`${key} had no results`); - } - }); - } - }); +class ClientError extends Error { + constructor(message) { + super(message); + this.name = "ClientError"; } } async function findByCitationKey(citekey, zotero) { const search = new zotero.Search(); - search.addCondition('libraryID', 'is', zotero.Libraries.userLibraryID); - search.addCondition('citationKey', 'is', citekey); + search.addCondition("libraryID", "is", zotero.Libraries.userLibraryID); + search.addCondition("citationKey", "is", citekey); const itemID = await search.search(); return itemID.length ? await zotero.Items.getAsync(itemID[0]) : undefined; } +async function searchByCitationKeyPrefix(prefix, zotero) { + checkBBT(); + const search = new zotero.Search(); + search.addCondition("libraryID", "is", zotero.Libraries.userLibraryID); + search.addCondition("citationKey", "contains", prefix); + const itemIDs = await search.search(); + const items = await zotero.Items.getAsync(itemIDs); + + return items.filter((item) => { + const key = item.getField("citationKey"); + return key && key.startsWith(prefix); + }); +} + function jsonStringify(json) { - return JSON.stringify(json, null, ' '); + return JSON.stringify(json, null, " "); +} + +function checkBBT() { + if (!Zotero.BetterBibTeX) { + throw new ClientError("BetterBibTeX not installed."); + } } /* Exported for tests in nodejs */ -if (typeof module !== 'undefined') { +if (typeof module !== "undefined") { module.exports = { - buildEasyKeySearch, - buildRawSearch, buildSearch, + checkBBT, checkStyleId, cleanQuery, dedupItems, findByCitationKey, - findByEasyKey, findByKey, fixStyleId, getItemOrParent, item2key, jsonStringify, makeCslEngine, - parseEasyKey - } + searchByCitationKeyPrefix, + ClientError, + }; } diff --git a/extension/manifest.json b/extension/manifest.json index 9404b8e..b6b4670 100644 --- a/extension/manifest.json +++ b/extension/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 2, "name": "zotxt", - "version": "7.0.0", + "version": "8.0.0.1", "description": "Plain text extensions for Zotero", "author": "Erik Hetzner", "applications": { @@ -9,7 +9,7 @@ "id": "zotxt@e6h.org", "update_url": "https://raw.githubusercontent.com/egh/zotxt/master/update.json", "strict_min_version": "6.999", - "strict_max_version": "7.0.*" + "strict_max_version": "8.*" } } } diff --git a/extension/resource/translators/EasyKeyExporter.js b/extension/resource/translators/EasyKeyExporter.js index e0f1fe2..c9b6a88 100644 --- a/extension/resource/translators/EasyKeyExporter.js +++ b/extension/resource/translators/EasyKeyExporter.js @@ -14,57 +14,2065 @@ // along with zotxt. If not, see . // from bibtex exporter -var citeKeyCleanRe = ZU.XRegExp('[^\\P{Lu}\\P{Ll}0-9\\!\\$\\&\\*\\+\\-\\.\\/\\:\\;\\<\\>\?\\[\\]\\^\\_\\`\\|]+', 'g'); +var citeKeyCleanRe = ZU.XRegExp( + "[^\\P{Lu}\\P{Ll}0-9\\!\\$\\&\\*\\+\\-\\.\\/\\:\\;\\<\\>\?\\[\\]\\^\\_\\`\\|]+", + "g", +); -function determineYear (item) { +function determineYear(item) { var year = ""; - var rawdate = item['date']; + var rawdate = item["date"]; if (rawdate) { var yearMd = rawdate.match(/[0-9]{4}/); if (yearMd && yearMd[0]) { year = yearMd[0]; - }; + } } return year; } function stripFormatting(str) { - return str.replace(new RegExp("(|||||]+>)", "g"), ""); + return str.replace( + new RegExp("(|||||]+>)", "g"), + "", + ); } function cleanString(string) { return ZU.XRegExp.replace(string.replace(/\s+/g, "_"), citeKeyCleanRe, ""); } -function determineAuthor (item) { +function determineAuthor(item) { var primaryCreatorType = ZU.getCreatorsForType(item.itemType)[0]; var primaryCreators = item.creators.filter(function (c) { - return (c.creatorType === primaryCreatorType); + return c.creatorType === primaryCreatorType; }); var creator = primaryCreators[0] || item.creators[0]; - var author = (creator && creator['lastName']) || "Anonymous"; + var author = (creator && creator["lastName"]) || "Anonymous"; return author; } -var stopwords = ["a", "aan", "abans", "aber", "acaba", "acerca", "ach", "aderton", "adertonde", "adesso", "adjö", "af", "agora", "ai", "aj", "al", "albo", "aldrig", "algmas", "algun", "alguna", "algunas", "algunes", "alguno", "algunos", "alguns", "algún", "ali", "alla", "allas", "alle", "allo", "allora", "allt", "alltid", "alltså", "alors", "als", "altmýþ", "altre", "altri", "altro", "altý", "am", "ama", "amb", "ambdós", "ambos", "ampleamos", "an", "anar", "anche", "andet", "andra", "andras", "andre", "annan", "annat", "ans", "ante", "antes", "apontar", "aquel", "aquela", "aquelas", "aquele", "aqueles", "aquell", "aquellas", "aquelles", "aquellos", "aquells", "aqui", "aquí", "arbeid", "arriba", "artonde", "artonn", "at", "atras", "atrás", "att", "au", "auch", "aucuns", "auf", "aus", "aussi", "autre", "av", "avant", "avec", "avere", "aveva", "avevano", "avoir", "az", "bajo", "bakom", "bana", "bara", "bardzo", "bastant", "bastante", "bazý", "be", "begge", "behöva", "behövas", "behövde", "behövt", "bei", "belki", "bem", "ben", "benden", "beni", "benim", "beslut", "beslutat", "beslutit", "bez", "beþ", "bien", "bij", "bin", "bir", "biri", "birkaç", "birkez", "birþey", "birþeyi", "bis", "bist", "biz", "bizden", "bizi", "bizim", "bland", "blev", "bli", "blir", "blivit", "bo", "bom", "bon", "bort", "borta", "bra", "bruke", "bu", "buna", "bunda", "bundan", "bunu", "bunun", "buono", "być", "bäst", "bättre", "båda", "bådas", "bé", "cada", "caminho", "car", "ce", "cela", "ces", "ceux", "chaque", "che", "chi", "ci", "ciebie", "cierta", "ciertas", "cierto", "ciertos", "cima", "cinque", "cię", "co", "com", "comme", "comment", "como", "comprare", "comprido", "con", "conhecido", "consecutivi", "consecutivo", "consegueixo", "conseguim", "conseguimos", "conseguir", "consigo", "consigue", "consigueix", "consigueixen", "consigueixes", "consiguen", "consigues", "corrente", "cosa", "csak", "cual", "cuando", "cui", "czy", "da", "dadurch", "dag", "dagar", "dagarna", "dagen", "daha", "daher", "dahi", "daleko", "dalt", "dan", "dans", "darum", "das", "dass", "dat", "daß", "de", "debaixo", "dedans", "defa", "dehors", "dein", "deine", "del", "delen", "della", "dello", "dem", "den", "denne", "dentro", "depuis", "der", "deras", "deres", "des", "desde", "deshalb", "desligado", "dess", "dessen", "det", "detta", "dette", "deve", "devem", "deverá", "devo", "devrait", "di", "die", "dies", "dieser", "dieses", "dig", "din", "dina", "dins", "direita", "disse", "dit", "ditt", "diye", "diz", "dizer", "dla", "dlaczego", "dlatego", "do", "dobrze", "doch", "dock", "dog", "dois", "doit", "doksan", "dokuz", "dokąd", "donc", "donde", "doppio", "dort", "dos", "dość", "droite", "du", "durch", "dużo", "dwa", "dwaj", "dwie", "dwoje", "dzisiaj", "dziś", "där", "därför", "då", "début", "dört", "e", "ecco", "een", "efter", "eftersom", "egy", "ein", "eine", "einem", "einen", "einer", "eines", "ej", "el", "ela", "ele", "eles", "elfte", "ellas", "elle", "eller", "elles", "elli", "ellos", "ells", "els", "elva", "em", "empleais", "emplean", "emplear", "empleas", "empleo", "en", "encima", "encore", "end", "ene", "eneste", "enhver", "enkel", "enkelt", "enkla", "enligt", "enn", "enquanto", "entonces", "entre", "então", "er", "eramos", "eran", "eras", "erem", "eren", "eres", "ert", "es", "essai", "est", "esta", "estaba", "estado", "estais", "estamos", "estan", "estar", "estará", "estat", "estava", "este", "estem", "estes", "esteu", "esteve", "estic", "estive", "estivemos", "estiveram", "estoy", "està", "está", "estão", "et", "ets", "ett", "ettusen", "eu", "euer", "eure", "fa", "faig", "fait", "faites", "fan", "fanns", "fare", "fará", "fas", "faz", "fazer", "fazia", "fel", "fem", "femte", "femtio", "femtionde", "femton", "femtonde", "fer", "feu", "fez", "fi", "fick", "fim", "fin", "fine", "finnas", "finns", "fino", "fire", "fjorton", "fjortonde", "fjärde", "fler", "flera", "flere", "flesta", "fleste", "foi", "fois", "for", "fora", "force", "fordi", "forrige", "forsÛke", "fra", "fram", "framför", "från", "fue", "fueron", "fui", "fuimos", "fyra", "fyrtio", "fyrtionde", "fÅ", "fÛr", "fÛrst", "få", "får", "fått", "följande", "för", "före", "förlåt", "förra", "första", "før", "für", "gdyby", "gdzie", "genast", "genom", "gente", "gibi", "gick", "giu", "gjorde", "gjort", "gjÛre", "goda", "godare", "godast", "gott", "gueno", "gÅ", "gälla", "gäller", "gällt", "gärna", "gå", "går", "gått", "gör", "göra", "ha", "hace", "haceis", "hacemos", "hacen", "hacer", "haces", "had", "hadde", "hade", "haft", "hago", "hai", "han", "hanno", "hans", "har", "hatte", "hatten", "hattest", "hattet", "haut", "haver", "heb", "heller", "hellre", "helst", "helt", "hem", "hendes", "henne", "hennes", "hep", "hepsi", "her", "het", "hier", "hij", "hinter", "hit", "hiç", "ho", "hoe", "hogy", "hon", "honom", "horas", "hors", "hun", "hundra", "hundraen", "hundraett", "hur", "hva", "hvad", "hvem", "hver", "hvilken", "hvis", "hvor", "hvordan", "hvorfor", "hvornår", "hát", "här", "hög", "höger", "högre", "högst", "i", "ibland", "ich", "ici", "idag", "ide", "igen", "igår", "ihr", "ihre", "ik", "iki", "ikke", "il", "ile", "ils", "im", "imorgon", "in", "incluso", "inclòs", "ind", "indietro", "inför", "inga", "ingen", "ingenting", "inget", "iniciar", "inicio", "innan", "inne", "innen", "inny", "inom", "inte", "intenta", "intentais", "intentamos", "intentan", "intentar", "intentas", "intento", "intet", "inuti", "invece", "io", "ir", "irá", "is", "ise", "ist", "ista", "iste", "isto", "için", "ja", "jag", "jak", "jakby", "jaki", "je", "jede", "jedem", "jeden", "jeder", "jedes", "jedna", "jedno", "jeg", "jego", "jej", "jemu", "jener", "jenes", "jeres", "jest", "jestem", "jetzt", "jeśli", "jeżeli", "jo", "juste", "już", "jämfört", "ją", "kan", "kann", "kannst", "kanske", "katrilyon", "każdy", "kez", "ki", "kiedy", "kierunku", "kim", "kimden", "kime", "kimi", "knappast", "kom", "komma", "kommer", "kommit", "kr", "kto", "ku", "kunde", "kunna", "kunnat", "kunne", "kvar", "können", "könnt", "kýrk", "la", "lage", "lang", "largo", "las", "lav", "lavoro", "le", "legat", "lei", "les", "lesz", "leur", "lidt", "ligado", "ligga", "ligger", "lik", "lika", "like", "likställd", "likställda", "lilla", "lille", "lite", "liten", "litet", "llarg", "llavors", "lo", "loro", "los", "lub", "lui", "lungo", "là", "länge", "längre", "längst", "lätt", "lättare", "lättast", "långsam", "långsammare", "långsammast", "långsamt", "långt", "ma", "machen", "maintenant", "maioria", "maiorias", "mais", "mają", "makt", "mam", "mand", "mange", "mas", "me", "med", "meg", "meget", "meglio", "mein", "meine", "mellan", "mentre", "mera", "mere", "mes", "mesmo", "mest", "meu", "mi", "mientras", "mig", "mij", "milyar", "milyon", "min", "mina", "mindre", "mine", "minst", "mio", "mit", "mitt", "mittemot", "mnie", "mną", "mode", "modo", "moi", "moins", "moja", "moje", "molt", "molta", "molti", "molto", "molts", "mon", "mot", "może", "mu", "muchos", "muito", "muitos", "musst", "muy", "muß", "mußt", "my", "mycket", "mye", "mÅ", "mÅte", "många", "måste", "même", "mój", "möjlig", "möjligen", "möjligt", "möjligtvis", "mü", "müssen", "müßt", "mý", "na", "nach", "nachdem", "nam", "nami", "nas", "nasi", "nasz", "nasza", "nasze", "nasýl", "natychmiast", "navn", "ne", "ned", "neden", "nederst", "nedersta", "nedre", "nei", "nein", "nej", "nella", "nem", "ner", "nerde", "nerede", "nereye", "ni", "nic", "nich", "nicht", "nie", "niego", "niej", "niemu", "nigdy", "nim", "nimi", "nio", "nionde", "nittio", "nittionde", "nitton", "nittonde", "niye", "niçin", "nią", "niż", "no", "nog", "nogen", "noget", "noi", "noll", "nome", "nommés", "nos", "nosaltres", "nosotros", "nosso", "nostro", "notre", "nous", "nouveaux", "nove", "novo", "nr", "nu", "nummer", "nun", "nuovi", "nuovo", "ny", "nyt", "nÅ", "nÅr", "não", "när", "nästa", "någon", "någonting", "något", "några", "nær", "næste", "næsten", "nós", "nödvändig", "nödvändiga", "nödvändigt", "nödvändigtvis", "o", "obok", "och", "också", "od", "oda", "oder", "of", "ofta", "oftast", "og", "ogsÅ", "około", "olika", "olikt", "oltre", "om", "on", "ona", "ondan", "onde", "one", "oni", "onlar", "onlardan", "onlari", "onlarýn", "ono", "ons", "onu", "ook", "op", "opp", "ora", "os", "oss", "otro", "otte", "otto", "otuz", "ou", "outro", "over", "owszem", "où", "par", "para", "parce", "parole", "part", "parte", "pas", "pegar", "peggio", "pelo", "per", "pero", "perquè", "persone", "personnes", "però", "pessoas", "peu", "peut", "piu", "pièce", "plupart", "po", "poco", "pod", "pode", "podeis", "podem", "podemos", "poden", "poder", "poderá", "podeu", "podia", "podria", "podriais", "podriamos", "podrian", "podrias", "ponieważ", "por", "porque", "potser", "pour", "pourquoi", "povo", "primer", "primero", "primo", "promeiro", "promesso", "przed", "przedtem", "puc", "puede", "pueden", "puedo", "punkt", "pÅ", "på", "qua", "qual", "qualquer", "quan", "quand", "quando", "quant", "quarto", "quasi", "quattro", "que", "quel", "quelle", "quelles", "quello", "quels", "quem", "questo", "qui", "quien", "quieto", "quindi", "quinto", "qué", "quê", "rakt", "redan", "rett", "riktig", "rispetto", "rá", "rätt", "sa", "sabe", "sabeis", "sabem", "sabemos", "saben", "saber", "sabes", "sabeu", "sade", "sagt", "sam", "sama", "samma", "samme", "sanki", "sans", "sant", "sap", "saps", "sara", "se", "secondo", "sedan", "sei", "seid", "sein", "seine", "sekiz", "seks", "seksen", "sem", "sembra", "sembrava", "sen", "senare", "senast", "senden", "seni", "senin", "sense", "sent", "senza", "ser", "ses", "sette", "seu", "seulement", "seus", "sex", "sextio", "sextionde", "sexton", "sextonde", "si", "sia", "siamo", "sich", "siden", "sie", "sien", "siendo", "siete", "sig", "sina", "sind", "sist", "sista", "siste", "sitt", "siz", "sizden", "sizi", "sizin", "się", "sju", "sjunde", "sjuttio", "sjuttionde", "sjutton", "sjuttonde", "sjätte", "ska", "skall", "skulle", "skąd", "slik", "slutligen", "slutt", "små", "smått", "snart", "sobre", "soc", "sois", "solament", "solamente", "soll", "sollen", "sollst", "sollt", "solo", "sols", "som", "somente", "somos", "son", "sono", "sonst", "sont", "sopra", "soprattutto", "sota", "sotto", "sous", "soweit", "sowie", "soy", "soyez", "start", "stati", "stato", "stesso", "stille", "stor", "stora", "store", "stort", "större", "störst", "su", "subito", "sujet", "sul", "sulla", "sur", "sus", "syv", "szét", "sÅ", "são", "säga", "säger", "sämre", "sämst", "så", "są", "ta", "tak", "taki", "tal", "tam", "también", "també", "também", "tandis", "tanto", "te", "tellement", "tels", "tem", "tempo", "ten", "tene", "teneis", "tenemos", "tener", "tengo", "tenho", "tenim", "tenir", "teniu", "tentar", "tentaram", "tente", "tentei", "terzo", "tes", "teu", "teve", "the", "ti", "tid", "tidig", "tidigare", "tidigast", "tidigt", "tiempo", "tiene", "tienen", "til", "tilbake", "till", "tills", "tillsammans", "tilstand", "tinc", "tio", "tionde", "tipo", "tive", "tjugo", "tjugoen", "tjugoett", "tjugonde", "tjugotre", "tjugotvå", "tjungo", "to", "tobie", "tobą", "todo", "todos", "tolfte", "tolv", "ton", "tot", "tous", "tout", "tra", "trabaja", "trabajais", "trabajamos", "trabajan", "trabajar", "trabajas", "trabajo", "trabalhar", "trabalho", "tras", "tre", "tredje", "trettio", "trettionde", "tretton", "trettonde", "trilyon", "triplo", "trop", "très", "tu", "tutaj", "tuyo", "två", "tvåhundra", "twoi", "twoja", "twoje", "twój", "ty", "têm", "tüm", "ud", "uit", "ultimo", "um", "uma", "umas", "un", "una", "unas", "und", "under", "unes", "uno", "unos", "uns", "unser", "unsere", "unter", "upp", "ur", "ursäkt", "usa", "usais", "usamos", "usan", "usar", "usas", "uso", "ut", "utan", "utanför", "ute", "uten", "va", "vad", "vagy", "vai", "vaig", "vais", "valeur", "valor", "vamos", "van", "var", "vara", "varför", "varifrån", "varit", "varken", "varsågod", "vart", "vaya", "ve", "ved", "veja", "vem", "vems", "ver", "verdad", "verdade", "verdadeiro", "verdadera", "verdadero", "verdi", "verkligen", "veya", "vi", "vid", "vidare", "viktig", "viktigare", "viktigast", "viktigt", "vil", "vilka", "vilken", "vilket", "vill", "ville", "vissza", "vite", "você", "voi", "voie", "voient", "volte", "vom", "von", "vont", "vor", "vosaltres", "vosotras", "vosotros", "vostro", "votre", "vous", "voy", "vu", "vÅr", "vÖre", "vÖrt", "vänster", "vänstra", "värre", "vår", "våra", "vårt", "wam", "wami", "wann", "warum", "was", "wasi", "wasz", "wasza", "wasze", "wat", "we", "weiter", "weitere", "wel", "wenn", "wer", "werde", "werden", "werdet", "weshalb", "wie", "wieder", "wieso", "wij", "wir", "wird", "wirst", "więc", "wo", "woher", "wohin", "wszystko", "wtedy", "wy", "ya", "yani", "yedi", "yetmiþ", "yirmi", "yo", "yüz", "zal", "zawsze", "ze", "zei", "zij", "zo", "zou", "zu", "zum", "zur", "Å", "át", "än", "ännu", "även", "åtminstone", "åtta", "åttio", "åttionde", "åttonde", "ça", "çok", "çünkü", "é", "én", "és", "éssent", "étaient", "état", "étions", "été", "être", "õ", "õk", "ön", "össze", "över", "övermorgon", "överst", "övre", "últim", "último", "ús", "über", "üç", "þey", "þeyden", "þeyi", "þeyler", "þu", "þuna", "þunda", "þundan", "þunu", "żaden", "że", "αὐτόσ", "γάρ", "γα^", "γε", "δέ", "δή", "δαί", "δαίσ", "διά", "δ’", "εἰ", "εἰμί", "εἰσ", "εἴμι", "καί", "κατά", "μέν", "μή", "μετά", "οἱ", "οὐ", "οὐδέ", "οὐδείσ", "οὐκ", "οὔτε", "οὕτωσ", "οὖν", "οὗτοσ", "παρά", "περί", "πρόσ", "σόσ", "σύ", "σύν", "τά", "τήν", "τί", "τίσ", "τε", "τι", "τισ", "τοί", "τοιοῦτοσ", "τούσ", "τοῦ", "τό", "τόν", "τῆσ", "τῇ", "τῶν", "τῷ", "а", "алло", "без", "близко", "более", "больше", "будем", "будет", "будете", "будешь", "будто", "буду", "будут", "будь", "бы", "бывает", "бывь", "был", "была", "были", "было", "быть", "в", "важная", "важное", "важные", "важный", "вам", "вами", "вас", "ваш", "ваша", "ваше", "ваши", "вверх", "вдали", "вдруг", "ведь", "везде", "весь", "вниз", "внизу", "во", "вокруг", "вон", "восемнадцатый", "восемнадцать", "восемь", "восьмой", "вот", "впрочем", "времени", "время", "все", "всегда", "всего", "всем", "всеми", "всему", "всех", "всею", "всю", "всюду", "вся", "всё", "второй", "вы", "г", "где", "говорил", "говорит", "год", "года", "году", "да", "давно", "даже", "далеко", "дальше", "даром", "два", "двадцатый", "двадцать", "две", "двенадцатый", "двенадцать", "двух", "девятнадцатый", "девятнадцать", "девятый", "девять", "действительно", "дел", "день", "десятый", "десять", "для", "до", "довольно", "долго", "должно", "другая", "другие", "других", "друго", "другое", "другой", "е", "его", "ее", "ей", "ему", "если", "есть", "еще", "ещё", "ею", "её", "ж", "же", "жизнь", "за", "занят", "занята", "занято", "заняты", "затем", "зато", "зачем", "здесь", "значит", "и", "из", "или", "им", "именно", "иметь", "ими", "имя", "иногда", "их", "к", "каждая", "каждое", "каждые", "каждый", "кажется", "как", "какая", "какой", "кем", "когда", "кого", "ком", "кому", "конечно", "которая", "которого", "которой", "которые", "который", "которых", "кроме", "кругом", "кто", "куда", "лет", "ли", "лишь", "лучше", "люди", "м", "мало", "между", "меля", "менее", "меньше", "меня", "миллионов", "мимо", "мира", "мне", "много", "многочисленная", "многочисленное", "многочисленные", "многочисленный", "мной", "мною", "мог", "могут", "мож", "может", "можно", "можхо", "мои", "мой", "мор", "мочь", "моя", "моё", "мы", "на", "наверху", "над", "надо", "назад", "наиболее", "наконец", "нам", "нами", "нас", "начала", "наш", "наша", "наше", "наши", "не", "него", "недавно", "недалеко", "нее", "ней", "нельзя", "нем", "немного", "нему", "непрерывно", "нередко", "несколько", "нет", "нею", "неё", "ни", "нибудь", "ниже", "низко", "никогда", "никуда", "ними", "них", "ничего", "но", "ну", "нужно", "нх", "о", "об", "оба", "обычно", "один", "одиннадцатый", "одиннадцать", "однажды", "однако", "одного", "одной", "около", "он", "она", "они", "оно", "опять", "особенно", "от", "отовсюду", "отсюда", "очень", "первый", "перед", "по", "под", "пожалуйста", "позже", "пока", "пор", "пора", "после", "посреди", "потом", "потому", "почему", "почти", "прекрасно", "при", "про", "просто", "против", "процентов", "пятнадцатый", "пятнадцать", "пятый", "пять", "раз", "разве", "рано", "раньше", "рядом", "с", "сам", "сама", "сами", "самим", "самими", "самих", "само", "самого", "самой", "самом", "самому", "саму", "свое", "своего", "своей", "свои", "своих", "свою", "сеаой", "себе", "себя", "сегодня", "седьмой", "сейчас", "семнадцатый", "семнадцать", "семь", "сих", "сказал", "сказала", "сказать", "сколько", "слишком", "сначала", "снова", "со", "собой", "собою", "совсем", "спасибо", "стал", "суть", "т", "та", "так", "такая", "также", "такие", "такое", "такой", "там", "твой", "твоя", "твоё", "те", "тебе", "тебя", "тем", "теми", "теперь", "тех", "то", "тобой", "тобою", "тогда", "того", "тоже", "только", "том", "тому", "тот", "тою", "третий", "три", "тринадцатый", "тринадцать", "ту", "туда", "тут", "ты", "тысяч", "у", "уж", "уже", "уметь", "хорошо", "хотеть", "хоть", "хотя", "хочешь", "часто", "чаще", "чего", "человек", "чем", "чему", "через", "четвертый", "четыре", "четырнадцатый", "четырнадцать", "что", "чтоб", "чтобы", "чуть", "шестнадцатый", "шестнадцать", "шестой", "шесть", "эта", "эти", "этим", "этими", "этих", "это", "этого", "этой", "этом", "этому", "этот", "эту", "я", "ἀλλά", "ἀλλ’", "ἀπό", "ἄλλοσ", "ἄν", "ἄρα", "ἐάν", "ἐγώ", "ἐκ", "ἐμόσ", "ἐν", "ἐπί", "ἑαυτοῦ", "ἔτι", "ἡ", "ἤ", "ὁ", "ὅδε", "ὅσ", "ὅστισ", "ὅτι", "ὑμόσ", "ὑπέρ", "ὑπό", "ὡσ", "ὥστε", "ὦ"]; +var stopwords = [ + "a", + "aan", + "abans", + "aber", + "acaba", + "acerca", + "ach", + "aderton", + "adertonde", + "adesso", + "adjö", + "af", + "agora", + "ai", + "aj", + "al", + "albo", + "aldrig", + "algmas", + "algun", + "alguna", + "algunas", + "algunes", + "alguno", + "algunos", + "alguns", + "algún", + "ali", + "alla", + "allas", + "alle", + "allo", + "allora", + "allt", + "alltid", + "alltså", + "alors", + "als", + "altmýþ", + "altre", + "altri", + "altro", + "altý", + "am", + "ama", + "amb", + "ambdós", + "ambos", + "ampleamos", + "an", + "anar", + "anche", + "andet", + "andra", + "andras", + "andre", + "annan", + "annat", + "ans", + "ante", + "antes", + "apontar", + "aquel", + "aquela", + "aquelas", + "aquele", + "aqueles", + "aquell", + "aquellas", + "aquelles", + "aquellos", + "aquells", + "aqui", + "aquí", + "arbeid", + "arriba", + "artonde", + "artonn", + "at", + "atras", + "atrás", + "att", + "au", + "auch", + "aucuns", + "auf", + "aus", + "aussi", + "autre", + "av", + "avant", + "avec", + "avere", + "aveva", + "avevano", + "avoir", + "az", + "bajo", + "bakom", + "bana", + "bara", + "bardzo", + "bastant", + "bastante", + "bazý", + "be", + "begge", + "behöva", + "behövas", + "behövde", + "behövt", + "bei", + "belki", + "bem", + "ben", + "benden", + "beni", + "benim", + "beslut", + "beslutat", + "beslutit", + "bez", + "beþ", + "bien", + "bij", + "bin", + "bir", + "biri", + "birkaç", + "birkez", + "birþey", + "birþeyi", + "bis", + "bist", + "biz", + "bizden", + "bizi", + "bizim", + "bland", + "blev", + "bli", + "blir", + "blivit", + "bo", + "bom", + "bon", + "bort", + "borta", + "bra", + "bruke", + "bu", + "buna", + "bunda", + "bundan", + "bunu", + "bunun", + "buono", + "być", + "bäst", + "bättre", + "båda", + "bådas", + "bé", + "cada", + "caminho", + "car", + "ce", + "cela", + "ces", + "ceux", + "chaque", + "che", + "chi", + "ci", + "ciebie", + "cierta", + "ciertas", + "cierto", + "ciertos", + "cima", + "cinque", + "cię", + "co", + "com", + "comme", + "comment", + "como", + "comprare", + "comprido", + "con", + "conhecido", + "consecutivi", + "consecutivo", + "consegueixo", + "conseguim", + "conseguimos", + "conseguir", + "consigo", + "consigue", + "consigueix", + "consigueixen", + "consigueixes", + "consiguen", + "consigues", + "corrente", + "cosa", + "csak", + "cual", + "cuando", + "cui", + "czy", + "da", + "dadurch", + "dag", + "dagar", + "dagarna", + "dagen", + "daha", + "daher", + "dahi", + "daleko", + "dalt", + "dan", + "dans", + "darum", + "das", + "dass", + "dat", + "daß", + "de", + "debaixo", + "dedans", + "defa", + "dehors", + "dein", + "deine", + "del", + "delen", + "della", + "dello", + "dem", + "den", + "denne", + "dentro", + "depuis", + "der", + "deras", + "deres", + "des", + "desde", + "deshalb", + "desligado", + "dess", + "dessen", + "det", + "detta", + "dette", + "deve", + "devem", + "deverá", + "devo", + "devrait", + "di", + "die", + "dies", + "dieser", + "dieses", + "dig", + "din", + "dina", + "dins", + "direita", + "disse", + "dit", + "ditt", + "diye", + "diz", + "dizer", + "dla", + "dlaczego", + "dlatego", + "do", + "dobrze", + "doch", + "dock", + "dog", + "dois", + "doit", + "doksan", + "dokuz", + "dokąd", + "donc", + "donde", + "doppio", + "dort", + "dos", + "dość", + "droite", + "du", + "durch", + "dużo", + "dwa", + "dwaj", + "dwie", + "dwoje", + "dzisiaj", + "dziś", + "där", + "därför", + "då", + "début", + "dört", + "e", + "ecco", + "een", + "efter", + "eftersom", + "egy", + "ein", + "eine", + "einem", + "einen", + "einer", + "eines", + "ej", + "el", + "ela", + "ele", + "eles", + "elfte", + "ellas", + "elle", + "eller", + "elles", + "elli", + "ellos", + "ells", + "els", + "elva", + "em", + "empleais", + "emplean", + "emplear", + "empleas", + "empleo", + "en", + "encima", + "encore", + "end", + "ene", + "eneste", + "enhver", + "enkel", + "enkelt", + "enkla", + "enligt", + "enn", + "enquanto", + "entonces", + "entre", + "então", + "er", + "eramos", + "eran", + "eras", + "erem", + "eren", + "eres", + "ert", + "es", + "essai", + "est", + "esta", + "estaba", + "estado", + "estais", + "estamos", + "estan", + "estar", + "estará", + "estat", + "estava", + "este", + "estem", + "estes", + "esteu", + "esteve", + "estic", + "estive", + "estivemos", + "estiveram", + "estoy", + "està", + "está", + "estão", + "et", + "ets", + "ett", + "ettusen", + "eu", + "euer", + "eure", + "fa", + "faig", + "fait", + "faites", + "fan", + "fanns", + "fare", + "fará", + "fas", + "faz", + "fazer", + "fazia", + "fel", + "fem", + "femte", + "femtio", + "femtionde", + "femton", + "femtonde", + "fer", + "feu", + "fez", + "fi", + "fick", + "fim", + "fin", + "fine", + "finnas", + "finns", + "fino", + "fire", + "fjorton", + "fjortonde", + "fjärde", + "fler", + "flera", + "flere", + "flesta", + "fleste", + "foi", + "fois", + "for", + "fora", + "force", + "fordi", + "forrige", + "forsÛke", + "fra", + "fram", + "framför", + "från", + "fue", + "fueron", + "fui", + "fuimos", + "fyra", + "fyrtio", + "fyrtionde", + "fÅ", + "fÛr", + "fÛrst", + "få", + "får", + "fått", + "följande", + "för", + "före", + "förlåt", + "förra", + "första", + "før", + "für", + "gdyby", + "gdzie", + "genast", + "genom", + "gente", + "gibi", + "gick", + "giu", + "gjorde", + "gjort", + "gjÛre", + "goda", + "godare", + "godast", + "gott", + "gueno", + "gÅ", + "gälla", + "gäller", + "gällt", + "gärna", + "gå", + "går", + "gått", + "gör", + "göra", + "ha", + "hace", + "haceis", + "hacemos", + "hacen", + "hacer", + "haces", + "had", + "hadde", + "hade", + "haft", + "hago", + "hai", + "han", + "hanno", + "hans", + "har", + "hatte", + "hatten", + "hattest", + "hattet", + "haut", + "haver", + "heb", + "heller", + "hellre", + "helst", + "helt", + "hem", + "hendes", + "henne", + "hennes", + "hep", + "hepsi", + "her", + "het", + "hier", + "hij", + "hinter", + "hit", + "hiç", + "ho", + "hoe", + "hogy", + "hon", + "honom", + "horas", + "hors", + "hun", + "hundra", + "hundraen", + "hundraett", + "hur", + "hva", + "hvad", + "hvem", + "hver", + "hvilken", + "hvis", + "hvor", + "hvordan", + "hvorfor", + "hvornår", + "hát", + "här", + "hög", + "höger", + "högre", + "högst", + "i", + "ibland", + "ich", + "ici", + "idag", + "ide", + "igen", + "igår", + "ihr", + "ihre", + "ik", + "iki", + "ikke", + "il", + "ile", + "ils", + "im", + "imorgon", + "in", + "incluso", + "inclòs", + "ind", + "indietro", + "inför", + "inga", + "ingen", + "ingenting", + "inget", + "iniciar", + "inicio", + "innan", + "inne", + "innen", + "inny", + "inom", + "inte", + "intenta", + "intentais", + "intentamos", + "intentan", + "intentar", + "intentas", + "intento", + "intet", + "inuti", + "invece", + "io", + "ir", + "irá", + "is", + "ise", + "ist", + "ista", + "iste", + "isto", + "için", + "ja", + "jag", + "jak", + "jakby", + "jaki", + "je", + "jede", + "jedem", + "jeden", + "jeder", + "jedes", + "jedna", + "jedno", + "jeg", + "jego", + "jej", + "jemu", + "jener", + "jenes", + "jeres", + "jest", + "jestem", + "jetzt", + "jeśli", + "jeżeli", + "jo", + "juste", + "już", + "jämfört", + "ją", + "kan", + "kann", + "kannst", + "kanske", + "katrilyon", + "każdy", + "kez", + "ki", + "kiedy", + "kierunku", + "kim", + "kimden", + "kime", + "kimi", + "knappast", + "kom", + "komma", + "kommer", + "kommit", + "kr", + "kto", + "ku", + "kunde", + "kunna", + "kunnat", + "kunne", + "kvar", + "können", + "könnt", + "kýrk", + "la", + "lage", + "lang", + "largo", + "las", + "lav", + "lavoro", + "le", + "legat", + "lei", + "les", + "lesz", + "leur", + "lidt", + "ligado", + "ligga", + "ligger", + "lik", + "lika", + "like", + "likställd", + "likställda", + "lilla", + "lille", + "lite", + "liten", + "litet", + "llarg", + "llavors", + "lo", + "loro", + "los", + "lub", + "lui", + "lungo", + "là", + "länge", + "längre", + "längst", + "lätt", + "lättare", + "lättast", + "långsam", + "långsammare", + "långsammast", + "långsamt", + "långt", + "ma", + "machen", + "maintenant", + "maioria", + "maiorias", + "mais", + "mają", + "makt", + "mam", + "mand", + "mange", + "mas", + "me", + "med", + "meg", + "meget", + "meglio", + "mein", + "meine", + "mellan", + "mentre", + "mera", + "mere", + "mes", + "mesmo", + "mest", + "meu", + "mi", + "mientras", + "mig", + "mij", + "milyar", + "milyon", + "min", + "mina", + "mindre", + "mine", + "minst", + "mio", + "mit", + "mitt", + "mittemot", + "mnie", + "mną", + "mode", + "modo", + "moi", + "moins", + "moja", + "moje", + "molt", + "molta", + "molti", + "molto", + "molts", + "mon", + "mot", + "może", + "mu", + "muchos", + "muito", + "muitos", + "musst", + "muy", + "muß", + "mußt", + "my", + "mycket", + "mye", + "mÅ", + "mÅte", + "många", + "måste", + "même", + "mój", + "möjlig", + "möjligen", + "möjligt", + "möjligtvis", + "mü", + "müssen", + "müßt", + "mý", + "na", + "nach", + "nachdem", + "nam", + "nami", + "nas", + "nasi", + "nasz", + "nasza", + "nasze", + "nasýl", + "natychmiast", + "navn", + "ne", + "ned", + "neden", + "nederst", + "nedersta", + "nedre", + "nei", + "nein", + "nej", + "nella", + "nem", + "ner", + "nerde", + "nerede", + "nereye", + "ni", + "nic", + "nich", + "nicht", + "nie", + "niego", + "niej", + "niemu", + "nigdy", + "nim", + "nimi", + "nio", + "nionde", + "nittio", + "nittionde", + "nitton", + "nittonde", + "niye", + "niçin", + "nią", + "niż", + "no", + "nog", + "nogen", + "noget", + "noi", + "noll", + "nome", + "nommés", + "nos", + "nosaltres", + "nosotros", + "nosso", + "nostro", + "notre", + "nous", + "nouveaux", + "nove", + "novo", + "nr", + "nu", + "nummer", + "nun", + "nuovi", + "nuovo", + "ny", + "nyt", + "nÅ", + "nÅr", + "não", + "när", + "nästa", + "någon", + "någonting", + "något", + "några", + "nær", + "næste", + "næsten", + "nós", + "nödvändig", + "nödvändiga", + "nödvändigt", + "nödvändigtvis", + "o", + "obok", + "och", + "också", + "od", + "oda", + "oder", + "of", + "ofta", + "oftast", + "og", + "ogsÅ", + "około", + "olika", + "olikt", + "oltre", + "om", + "on", + "ona", + "ondan", + "onde", + "one", + "oni", + "onlar", + "onlardan", + "onlari", + "onlarýn", + "ono", + "ons", + "onu", + "ook", + "op", + "opp", + "ora", + "os", + "oss", + "otro", + "otte", + "otto", + "otuz", + "ou", + "outro", + "over", + "owszem", + "où", + "par", + "para", + "parce", + "parole", + "part", + "parte", + "pas", + "pegar", + "peggio", + "pelo", + "per", + "pero", + "perquè", + "persone", + "personnes", + "però", + "pessoas", + "peu", + "peut", + "piu", + "pièce", + "plupart", + "po", + "poco", + "pod", + "pode", + "podeis", + "podem", + "podemos", + "poden", + "poder", + "poderá", + "podeu", + "podia", + "podria", + "podriais", + "podriamos", + "podrian", + "podrias", + "ponieważ", + "por", + "porque", + "potser", + "pour", + "pourquoi", + "povo", + "primer", + "primero", + "primo", + "promeiro", + "promesso", + "przed", + "przedtem", + "puc", + "puede", + "pueden", + "puedo", + "punkt", + "pÅ", + "på", + "qua", + "qual", + "qualquer", + "quan", + "quand", + "quando", + "quant", + "quarto", + "quasi", + "quattro", + "que", + "quel", + "quelle", + "quelles", + "quello", + "quels", + "quem", + "questo", + "qui", + "quien", + "quieto", + "quindi", + "quinto", + "qué", + "quê", + "rakt", + "redan", + "rett", + "riktig", + "rispetto", + "rá", + "rätt", + "sa", + "sabe", + "sabeis", + "sabem", + "sabemos", + "saben", + "saber", + "sabes", + "sabeu", + "sade", + "sagt", + "sam", + "sama", + "samma", + "samme", + "sanki", + "sans", + "sant", + "sap", + "saps", + "sara", + "se", + "secondo", + "sedan", + "sei", + "seid", + "sein", + "seine", + "sekiz", + "seks", + "seksen", + "sem", + "sembra", + "sembrava", + "sen", + "senare", + "senast", + "senden", + "seni", + "senin", + "sense", + "sent", + "senza", + "ser", + "ses", + "sette", + "seu", + "seulement", + "seus", + "sex", + "sextio", + "sextionde", + "sexton", + "sextonde", + "si", + "sia", + "siamo", + "sich", + "siden", + "sie", + "sien", + "siendo", + "siete", + "sig", + "sina", + "sind", + "sist", + "sista", + "siste", + "sitt", + "siz", + "sizden", + "sizi", + "sizin", + "się", + "sju", + "sjunde", + "sjuttio", + "sjuttionde", + "sjutton", + "sjuttonde", + "sjätte", + "ska", + "skall", + "skulle", + "skąd", + "slik", + "slutligen", + "slutt", + "små", + "smått", + "snart", + "sobre", + "soc", + "sois", + "solament", + "solamente", + "soll", + "sollen", + "sollst", + "sollt", + "solo", + "sols", + "som", + "somente", + "somos", + "son", + "sono", + "sonst", + "sont", + "sopra", + "soprattutto", + "sota", + "sotto", + "sous", + "soweit", + "sowie", + "soy", + "soyez", + "start", + "stati", + "stato", + "stesso", + "stille", + "stor", + "stora", + "store", + "stort", + "större", + "störst", + "su", + "subito", + "sujet", + "sul", + "sulla", + "sur", + "sus", + "syv", + "szét", + "sÅ", + "são", + "säga", + "säger", + "sämre", + "sämst", + "så", + "są", + "ta", + "tak", + "taki", + "tal", + "tam", + "también", + "també", + "também", + "tandis", + "tanto", + "te", + "tellement", + "tels", + "tem", + "tempo", + "ten", + "tene", + "teneis", + "tenemos", + "tener", + "tengo", + "tenho", + "tenim", + "tenir", + "teniu", + "tentar", + "tentaram", + "tente", + "tentei", + "terzo", + "tes", + "teu", + "teve", + "the", + "ti", + "tid", + "tidig", + "tidigare", + "tidigast", + "tidigt", + "tiempo", + "tiene", + "tienen", + "til", + "tilbake", + "till", + "tills", + "tillsammans", + "tilstand", + "tinc", + "tio", + "tionde", + "tipo", + "tive", + "tjugo", + "tjugoen", + "tjugoett", + "tjugonde", + "tjugotre", + "tjugotvå", + "tjungo", + "to", + "tobie", + "tobą", + "todo", + "todos", + "tolfte", + "tolv", + "ton", + "tot", + "tous", + "tout", + "tra", + "trabaja", + "trabajais", + "trabajamos", + "trabajan", + "trabajar", + "trabajas", + "trabajo", + "trabalhar", + "trabalho", + "tras", + "tre", + "tredje", + "trettio", + "trettionde", + "tretton", + "trettonde", + "trilyon", + "triplo", + "trop", + "très", + "tu", + "tutaj", + "tuyo", + "två", + "tvåhundra", + "twoi", + "twoja", + "twoje", + "twój", + "ty", + "têm", + "tüm", + "ud", + "uit", + "ultimo", + "um", + "uma", + "umas", + "un", + "una", + "unas", + "und", + "under", + "unes", + "uno", + "unos", + "uns", + "unser", + "unsere", + "unter", + "upp", + "ur", + "ursäkt", + "usa", + "usais", + "usamos", + "usan", + "usar", + "usas", + "uso", + "ut", + "utan", + "utanför", + "ute", + "uten", + "va", + "vad", + "vagy", + "vai", + "vaig", + "vais", + "valeur", + "valor", + "vamos", + "van", + "var", + "vara", + "varför", + "varifrån", + "varit", + "varken", + "varsågod", + "vart", + "vaya", + "ve", + "ved", + "veja", + "vem", + "vems", + "ver", + "verdad", + "verdade", + "verdadeiro", + "verdadera", + "verdadero", + "verdi", + "verkligen", + "veya", + "vi", + "vid", + "vidare", + "viktig", + "viktigare", + "viktigast", + "viktigt", + "vil", + "vilka", + "vilken", + "vilket", + "vill", + "ville", + "vissza", + "vite", + "você", + "voi", + "voie", + "voient", + "volte", + "vom", + "von", + "vont", + "vor", + "vosaltres", + "vosotras", + "vosotros", + "vostro", + "votre", + "vous", + "voy", + "vu", + "vÅr", + "vÖre", + "vÖrt", + "vänster", + "vänstra", + "värre", + "vår", + "våra", + "vårt", + "wam", + "wami", + "wann", + "warum", + "was", + "wasi", + "wasz", + "wasza", + "wasze", + "wat", + "we", + "weiter", + "weitere", + "wel", + "wenn", + "wer", + "werde", + "werden", + "werdet", + "weshalb", + "wie", + "wieder", + "wieso", + "wij", + "wir", + "wird", + "wirst", + "więc", + "wo", + "woher", + "wohin", + "wszystko", + "wtedy", + "wy", + "ya", + "yani", + "yedi", + "yetmiþ", + "yirmi", + "yo", + "yüz", + "zal", + "zawsze", + "ze", + "zei", + "zij", + "zo", + "zou", + "zu", + "zum", + "zur", + "Å", + "át", + "än", + "ännu", + "även", + "åtminstone", + "åtta", + "åttio", + "åttionde", + "åttonde", + "ça", + "çok", + "çünkü", + "é", + "én", + "és", + "éssent", + "étaient", + "état", + "étions", + "été", + "être", + "õ", + "õk", + "ön", + "össze", + "över", + "övermorgon", + "överst", + "övre", + "últim", + "último", + "ús", + "über", + "üç", + "þey", + "þeyden", + "þeyi", + "þeyler", + "þu", + "þuna", + "þunda", + "þundan", + "þunu", + "żaden", + "że", + "αὐτόσ", + "γάρ", + "γα^", + "γε", + "δέ", + "δή", + "δαί", + "δαίσ", + "διά", + "δ’", + "εἰ", + "εἰμί", + "εἰσ", + "εἴμι", + "καί", + "κατά", + "μέν", + "μή", + "μετά", + "οἱ", + "οὐ", + "οὐδέ", + "οὐδείσ", + "οὐκ", + "οὔτε", + "οὕτωσ", + "οὖν", + "οὗτοσ", + "παρά", + "περί", + "πρόσ", + "σόσ", + "σύ", + "σύν", + "τά", + "τήν", + "τί", + "τίσ", + "τε", + "τι", + "τισ", + "τοί", + "τοιοῦτοσ", + "τούσ", + "τοῦ", + "τό", + "τόν", + "τῆσ", + "τῇ", + "τῶν", + "τῷ", + "а", + "алло", + "без", + "близко", + "более", + "больше", + "будем", + "будет", + "будете", + "будешь", + "будто", + "буду", + "будут", + "будь", + "бы", + "бывает", + "бывь", + "был", + "была", + "были", + "было", + "быть", + "в", + "важная", + "важное", + "важные", + "важный", + "вам", + "вами", + "вас", + "ваш", + "ваша", + "ваше", + "ваши", + "вверх", + "вдали", + "вдруг", + "ведь", + "везде", + "весь", + "вниз", + "внизу", + "во", + "вокруг", + "вон", + "восемнадцатый", + "восемнадцать", + "восемь", + "восьмой", + "вот", + "впрочем", + "времени", + "время", + "все", + "всегда", + "всего", + "всем", + "всеми", + "всему", + "всех", + "всею", + "всю", + "всюду", + "вся", + "всё", + "второй", + "вы", + "г", + "где", + "говорил", + "говорит", + "год", + "года", + "году", + "да", + "давно", + "даже", + "далеко", + "дальше", + "даром", + "два", + "двадцатый", + "двадцать", + "две", + "двенадцатый", + "двенадцать", + "двух", + "девятнадцатый", + "девятнадцать", + "девятый", + "девять", + "действительно", + "дел", + "день", + "десятый", + "десять", + "для", + "до", + "довольно", + "долго", + "должно", + "другая", + "другие", + "других", + "друго", + "другое", + "другой", + "е", + "его", + "ее", + "ей", + "ему", + "если", + "есть", + "еще", + "ещё", + "ею", + "её", + "ж", + "же", + "жизнь", + "за", + "занят", + "занята", + "занято", + "заняты", + "затем", + "зато", + "зачем", + "здесь", + "значит", + "и", + "из", + "или", + "им", + "именно", + "иметь", + "ими", + "имя", + "иногда", + "их", + "к", + "каждая", + "каждое", + "каждые", + "каждый", + "кажется", + "как", + "какая", + "какой", + "кем", + "когда", + "кого", + "ком", + "кому", + "конечно", + "которая", + "которого", + "которой", + "которые", + "который", + "которых", + "кроме", + "кругом", + "кто", + "куда", + "лет", + "ли", + "лишь", + "лучше", + "люди", + "м", + "мало", + "между", + "меля", + "менее", + "меньше", + "меня", + "миллионов", + "мимо", + "мира", + "мне", + "много", + "многочисленная", + "многочисленное", + "многочисленные", + "многочисленный", + "мной", + "мною", + "мог", + "могут", + "мож", + "может", + "можно", + "можхо", + "мои", + "мой", + "мор", + "мочь", + "моя", + "моё", + "мы", + "на", + "наверху", + "над", + "надо", + "назад", + "наиболее", + "наконец", + "нам", + "нами", + "нас", + "начала", + "наш", + "наша", + "наше", + "наши", + "не", + "него", + "недавно", + "недалеко", + "нее", + "ней", + "нельзя", + "нем", + "немного", + "нему", + "непрерывно", + "нередко", + "несколько", + "нет", + "нею", + "неё", + "ни", + "нибудь", + "ниже", + "низко", + "никогда", + "никуда", + "ними", + "них", + "ничего", + "но", + "ну", + "нужно", + "нх", + "о", + "об", + "оба", + "обычно", + "один", + "одиннадцатый", + "одиннадцать", + "однажды", + "однако", + "одного", + "одной", + "около", + "он", + "она", + "они", + "оно", + "опять", + "особенно", + "от", + "отовсюду", + "отсюда", + "очень", + "первый", + "перед", + "по", + "под", + "пожалуйста", + "позже", + "пока", + "пор", + "пора", + "после", + "посреди", + "потом", + "потому", + "почему", + "почти", + "прекрасно", + "при", + "про", + "просто", + "против", + "процентов", + "пятнадцатый", + "пятнадцать", + "пятый", + "пять", + "раз", + "разве", + "рано", + "раньше", + "рядом", + "с", + "сам", + "сама", + "сами", + "самим", + "самими", + "самих", + "само", + "самого", + "самой", + "самом", + "самому", + "саму", + "свое", + "своего", + "своей", + "свои", + "своих", + "свою", + "сеаой", + "себе", + "себя", + "сегодня", + "седьмой", + "сейчас", + "семнадцатый", + "семнадцать", + "семь", + "сих", + "сказал", + "сказала", + "сказать", + "сколько", + "слишком", + "сначала", + "снова", + "со", + "собой", + "собою", + "совсем", + "спасибо", + "стал", + "суть", + "т", + "та", + "так", + "такая", + "также", + "такие", + "такое", + "такой", + "там", + "твой", + "твоя", + "твоё", + "те", + "тебе", + "тебя", + "тем", + "теми", + "теперь", + "тех", + "то", + "тобой", + "тобою", + "тогда", + "того", + "тоже", + "только", + "том", + "тому", + "тот", + "тою", + "третий", + "три", + "тринадцатый", + "тринадцать", + "ту", + "туда", + "тут", + "ты", + "тысяч", + "у", + "уж", + "уже", + "уметь", + "хорошо", + "хотеть", + "хоть", + "хотя", + "хочешь", + "часто", + "чаще", + "чего", + "человек", + "чем", + "чему", + "через", + "четвертый", + "четыре", + "четырнадцатый", + "четырнадцать", + "что", + "чтоб", + "чтобы", + "чуть", + "шестнадцатый", + "шестнадцать", + "шестой", + "шесть", + "эта", + "эти", + "этим", + "этими", + "этих", + "это", + "этого", + "этой", + "этом", + "этому", + "этот", + "эту", + "я", + "ἀλλά", + "ἀλλ’", + "ἀπό", + "ἄλλοσ", + "ἄν", + "ἄρα", + "ἐάν", + "ἐγώ", + "ἐκ", + "ἐμόσ", + "ἐν", + "ἐπί", + "ἑαυτοῦ", + "ἔτι", + "ἡ", + "ἤ", + "ὁ", + "ὅδε", + "ὅσ", + "ὅστισ", + "ὅτι", + "ὑμόσ", + "ὑπέρ", + "ὑπό", + "ὡσ", + "ὥστε", + "ὦ", +]; // Based on http://www.ranks.nl/stopwords/ function determineTitleWord(item) { - var cleanTitle = stripFormatting(item['title'].toLowerCase()); + var cleanTitle = stripFormatting(item["title"].toLowerCase()); var words = ZU.XRegExp.split(cleanTitle, ZU.XRegExp("\\s+|\\p{P}")); var filteredWords = words.filter(function (word) { - return (stopwords.indexOf(word) == -1 && - word.length > 1 && - !ZU.XRegExp.test(word, ZU.XRegExp('^\\p{P}+$')) && - !ZU.XRegExp.test(word, ZU.XRegExp('^[0-9]+$'))); + return ( + stopwords.indexOf(word) == -1 && + word.length > 1 && + !ZU.XRegExp.test(word, ZU.XRegExp("^\\p{P}+$")) && + !ZU.XRegExp.test(word, ZU.XRegExp("^[0-9]+$")) + ); }); return filteredWords[0] || "unknown"; } -function doExport () { +function doExport() { var item; var first = true; - while((item = Zotero.nextItem())) { + while ((item = Zotero.nextItem())) { // only write spaces after the first export if (!first) { Zotero.write(" "); @@ -75,9 +2083,20 @@ function doExport () { var author = determineAuthor(item); var titleword = determineTitleWord(item); if (Zotero.getOption("alternate")) { - Zotero.write("@" + ZU.capitalizeTitle(author, true) + ZU.capitalizeTitle(titleword, true) + year); + Zotero.write( + "@" + + ZU.capitalizeTitle(author, true) + + ZU.capitalizeTitle(titleword, true) + + year, + ); } else { - Zotero.write("@" + cleanString(author.toLowerCase()) + ":" + year + cleanString(titleword.toLowerCase())); + Zotero.write( + "@" + + cleanString(author.toLowerCase()) + + ":" + + year + + cleanString(titleword.toLowerCase()), + ); } } } diff --git a/package-lock.json b/package-lock.json index 40776c4..5306283 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,1296 +1,1298 @@ { - "name": "zotxt", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "dependencies": { - "bluebird": "^3.5.1", - "mocha": "^11.0.1", - "sinon": "^4.0.2", - "xregexp": "^3.2.0" - } - }, - "node_modules/@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" - }, - "node_modules/@isaacs/cliui/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "optional": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/@sinonjs/commons": { - "version": "1.8.6", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz", - "integrity": "sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==", - "license": "BSD-3-Clause", - "dependencies": { - "type-detect": "4.0.8" - } - }, - "node_modules/@sinonjs/commons/node_modules/type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/@sinonjs/formatio": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-2.0.0.tgz", - "integrity": "sha512-ls6CAMA6/5gG+O/IdsBcblvnd8qcO/l1TYoNeAzp3wcISOxlPXQEus0mLcdwazEkWjaBdaJ3TaxmNgCLWwvWzg==", - "license": "BSD-3-Clause", - "dependencies": { - "samsam": "1.3.0" - } - }, - "node_modules/@sinonjs/samsam": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-3.3.3.tgz", - "integrity": "sha512-bKCMKZvWIjYD0BLGnNrxVuw4dkWCYsLqFOUWw8VgKF/+5Y+mE7LfHWPIYoDXowH+3a9LsWDMo0uAP8YDosPvHQ==", - "license": "BSD-3-Clause", - "dependencies": { - "@sinonjs/commons": "^1.3.0", - "array-from": "^2.1.1", - "lodash": "^4.17.15" - } - }, - "node_modules/@sinonjs/text-encoding": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.3.tgz", - "integrity": "sha512-DE427ROAphMQzU4ENbliGYrBSYPXF+TtLg9S8vzeA+OF4ZKzoDdzfL8sxuMUGS/lgRhM6j1URSk9ghf7Xo1tyA==", - "license": "(Unlicense OR Apache-2.0)" - }, - "node_modules/ansi-colors": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", - "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", - "engines": { - "node": ">=6" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "license": "ISC", - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "license": "Python-2.0" - }, - "node_modules/array-from": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/array-from/-/array-from-2.1.1.tgz", - "integrity": "sha512-GQTc6Uupx1FCavi5mPzBvVT7nEOeWMmUA9P95wpfpW1XwMSKs+KaymD5C2Up7KAUKg/mYwbsUYzdZWcoajlNZg==", - "license": "MIT" - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "node_modules/binary-extensions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", - "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "license": "MIT" - }, - "node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "license": "MIT", - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "license": "ISC" - }, - "node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/chalk/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "license": "MIT", - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "license": "MIT" - }, - "node_modules/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/debug": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/decamelize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/diff": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", - "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "license": "MIT" - }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "license": "MIT", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "license": "MIT", - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "license": "BSD-3-Clause", - "bin": { - "flat": "cli.js" - } - }, - "node_modules/foreground-child": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", - "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", - "dependencies": { - "cross-spawn": "^7.0.0", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "license": "ISC", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/glob/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "license": "MIT", - "bin": { - "he": "bin/he" - } - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "license": "MIT", - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "license": "MIT", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", - "license": "MIT" - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" - }, - "node_modules/jackspeak": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", - "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" - } - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/just-extend": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz", - "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==", - "license": "MIT" - }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "license": "MIT", - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "license": "MIT" - }, - "node_modules/lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", - "license": "MIT" - }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "license": "MIT", - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lolex": { - "version": "2.7.5", - "resolved": "https://registry.npmjs.org/lolex/-/lolex-2.7.5.tgz", - "integrity": "sha512-l9x0+1offnKKIzYVjyXU2SiwhXDLekRzKyhnbyldPHvC7BvLPVpdNUNR2KeMAiCN2D/kLNttZgQD5WjSxuBx3Q==", - "license": "BSD-3-Clause" - }, - "node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==" - }, - "node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/mocha": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.0.1.tgz", - "integrity": "sha512-+3GkODfsDG71KSCQhc4IekSW+ItCK/kiez1Z28ksWvYhKXV/syxMlerR/sC7whDp7IyreZ4YxceMLdTs5hQE8A==", - "dependencies": { - "ansi-colors": "^4.1.3", - "browser-stdout": "^1.3.1", - "chokidar": "^3.5.3", - "debug": "^4.3.5", - "diff": "^5.2.0", - "escape-string-regexp": "^4.0.0", - "find-up": "^5.0.0", - "glob": "^10.4.5", - "he": "^1.2.0", - "js-yaml": "^4.1.0", - "log-symbols": "^4.1.0", - "minimatch": "^5.1.6", - "ms": "^2.1.3", - "serialize-javascript": "^6.0.2", - "strip-json-comments": "^3.1.1", - "supports-color": "^8.1.1", - "workerpool": "^6.5.1", - "yargs": "^16.2.0", - "yargs-parser": "^20.2.9", - "yargs-unparser": "^2.0.0" - }, - "bin": { - "_mocha": "bin/_mocha", - "mocha": "bin/mocha.js" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "license": "MIT" - }, - "node_modules/nise": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/nise/-/nise-1.5.3.tgz", - "integrity": "sha512-Ymbac/94xeIrMf59REBPOv0thr+CJVFMhrlAkW/gjCIE58BGQdCj0x7KRCb3yz+Ga2Rz3E9XXSvUyyxqqhjQAQ==", - "license": "BSD-3-Clause", - "dependencies": { - "@sinonjs/formatio": "^3.2.1", - "@sinonjs/text-encoding": "^0.7.1", - "just-extend": "^4.0.2", - "lolex": "^5.0.1", - "path-to-regexp": "^1.7.0" - } - }, - "node_modules/nise/node_modules/@sinonjs/formatio": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-3.2.2.tgz", - "integrity": "sha512-B8SEsgd8gArBLMD6zpRw3juQ2FVSsmdd7qlevyDqzS9WTCtvF55/gAL+h6gue8ZvPYcdiPdvueM/qm//9XzyTQ==", - "license": "BSD-3-Clause", - "dependencies": { - "@sinonjs/commons": "^1", - "@sinonjs/samsam": "^3.1.0" - } - }, - "node_modules/nise/node_modules/lolex": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/lolex/-/lolex-5.1.2.tgz", - "integrity": "sha512-h4hmjAvHTmd+25JSwrtTIuwbKdwg5NzZVRMLn9saij4SZaepCrTCxPr35H/3bjwfMJtN+t3CX8672UIkglz28A==", - "license": "BSD-3-Clause", - "dependencies": { - "@sinonjs/commons": "^1.7.0" - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "license": "MIT", - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "license": "MIT", - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/package-json-from-dist": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", - "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==" - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-scurry": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", - "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", - "dependencies": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - }, - "engines": { - "node": ">=16 || 14 >=14.18" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/path-to-regexp": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.9.0.tgz", - "integrity": "sha512-xIp7/apCFJuUHdDLWe8O1HIkb0kQrOMb/0u6FXQjemHn/ii5LrIzU6bdECnsiTF/GjZkMEKg1xdiZwNqDYlZ6g==", - "license": "MIT", - "dependencies": { - "isarray": "0.0.1" - } - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "license": "MIT", - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/samsam": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.3.0.tgz", - "integrity": "sha512-1HwIYD/8UlOtFS3QO3w7ey+SdSDFE4HRNLZoZRYVQefrOY3l17epswImeB1ijgJFQJodIaHcwkp3r/myBjFVbg==", - "deprecated": "This package has been deprecated in favour of @sinonjs/samsam", - "license": "BSD-3-Clause" - }, - "node_modules/serialize-javascript": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", - "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "engines": { - "node": ">=8" - } - }, - "node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/sinon": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-4.5.0.tgz", - "integrity": "sha512-trdx+mB0VBBgoYucy6a9L7/jfQOmvGeaKZT4OOJ+lPAtI8623xyGr8wLiE4eojzBS8G9yXbhx42GHUOVLr4X2w==", - "deprecated": "16.1.1", - "hasInstallScript": true, - "license": "BSD-3-Clause", - "dependencies": { - "@sinonjs/formatio": "^2.0.0", - "diff": "^3.1.0", - "lodash.get": "^4.4.2", - "lolex": "^2.2.0", - "nise": "^1.2.0", - "supports-color": "^5.1.0", - "type-detect": "^4.0.5" - } - }, - "node_modules/sinon/node_modules/diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/sinon/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/sinon/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "license": "MIT", - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width-cjs": { - "name": "string-width", - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi-cjs": { - "name": "strip-ansi", - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "license": "MIT", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/type-detect": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz", - "integrity": "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==", - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/workerpool": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz", - "integrity": "sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==" - }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs": { - "name": "wrap-ansi", - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/xregexp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-3.2.0.tgz", - "integrity": "sha512-tWodXkrdYZPGadukpkmhKAbyp37CV5ZiFHacIVPhRZ4/sSt7qtOYHLv2dAqcPN0mBsViY2Qai9JkO7v2TBP6hg==", - "license": "MIT" - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "license": "MIT", - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-unparser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", - "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", - "license": "MIT", - "dependencies": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } + "name": "zotxt", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "bluebird": "^3.5.1", + "mocha": "^11.0.1", + "sinon": "^4.0.2", + "xregexp": "^3.2.0" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@sinonjs/commons": { + "version": "1.8.6", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz", + "integrity": "sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==", + "license": "BSD-3-Clause", + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/commons/node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/@sinonjs/formatio": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-2.0.0.tgz", + "integrity": "sha512-ls6CAMA6/5gG+O/IdsBcblvnd8qcO/l1TYoNeAzp3wcISOxlPXQEus0mLcdwazEkWjaBdaJ3TaxmNgCLWwvWzg==", + "license": "BSD-3-Clause", + "dependencies": { + "samsam": "1.3.0" + } + }, + "node_modules/@sinonjs/samsam": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-3.3.3.tgz", + "integrity": "sha512-bKCMKZvWIjYD0BLGnNrxVuw4dkWCYsLqFOUWw8VgKF/+5Y+mE7LfHWPIYoDXowH+3a9LsWDMo0uAP8YDosPvHQ==", + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^1.3.0", + "array-from": "^2.1.1", + "lodash": "^4.17.15" + } + }, + "node_modules/@sinonjs/text-encoding": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.3.tgz", + "integrity": "sha512-DE427ROAphMQzU4ENbliGYrBSYPXF+TtLg9S8vzeA+OF4ZKzoDdzfL8sxuMUGS/lgRhM6j1URSk9ghf7Xo1tyA==", + "license": "(Unlicense OR Apache-2.0)" + }, + "node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "license": "Python-2.0" + }, + "node_modules/array-from": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/array-from/-/array-from-2.1.1.tgz", + "integrity": "sha512-GQTc6Uupx1FCavi5mPzBvVT7nEOeWMmUA9P95wpfpW1XwMSKs+KaymD5C2Up7KAUKg/mYwbsUYzdZWcoajlNZg==", + "license": "MIT" + }, + "node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.3.tgz", + "integrity": "sha512-fy6KJm2RawA5RcHkLa1z/ScpBeA762UF9KmZQxwIbDtRJrgLzM10depAiEQ+CXYcoiqW1/m96OAAoke2nE9EeA==", + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/browser-stdout": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "license": "ISC" + }, + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "license": "MIT", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/cliui/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/cliui/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/diff": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-7.0.0.tgz", + "integrity": "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "license": "MIT" + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "license": "MIT" + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", + "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "license": "BSD-3-Clause", + "bin": { + "flat": "cli.js" + } + }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/glob": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "license": "MIT", + "bin": { + "he": "bin/he" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "license": "ISC" + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/just-extend": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.2.1.tgz", + "integrity": "sha512-g3UB796vUFIY90VIv/WX3L2c8CS2MdWUww3CNrYmqza1Fg0DURc2K/O4YrnklBdQarSJ/y8JnJYDGc+1iumQjg==", + "license": "MIT" + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.23", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz", + "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==", + "license": "MIT" + }, + "node_modules/lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", + "deprecated": "This package is deprecated. Use the optional chaining (?.) operator instead.", + "license": "MIT" + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "license": "MIT", + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lolex": { + "version": "2.7.5", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-2.7.5.tgz", + "integrity": "sha512-l9x0+1offnKKIzYVjyXU2SiwhXDLekRzKyhnbyldPHvC7BvLPVpdNUNR2KeMAiCN2D/kLNttZgQD5WjSxuBx3Q==", + "license": "BSD-3-Clause" + }, + "node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "license": "ISC" + }, + "node_modules/minimatch": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.7.tgz", + "integrity": "sha512-MOwgjc8tfrpn5QQEvjijjmDVtMw2oL88ugTevzxQnzRLm6l3fVEF2gzU0kYeYYKD8C66+IdGX6peJ4MyUlUnPg==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^5.0.2" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/mocha": { + "version": "11.7.5", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.7.5.tgz", + "integrity": "sha512-mTT6RgopEYABzXWFx+GcJ+ZQ32kp4fMf0xvpZIIfSq9Z8lC/++MtcCnQ9t5FP2veYEP95FIYSvW+U9fV4xrlig==", + "license": "MIT", + "dependencies": { + "browser-stdout": "^1.3.1", + "chokidar": "^4.0.1", + "debug": "^4.3.5", + "diff": "^7.0.0", + "escape-string-regexp": "^4.0.0", + "find-up": "^5.0.0", + "glob": "^10.4.5", + "he": "^1.2.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "log-symbols": "^4.1.0", + "minimatch": "^9.0.5", + "ms": "^2.1.3", + "picocolors": "^1.1.1", + "serialize-javascript": "^6.0.2", + "strip-json-comments": "^3.1.1", + "supports-color": "^8.1.1", + "workerpool": "^9.2.0", + "yargs": "^17.7.2", + "yargs-parser": "^21.1.1", + "yargs-unparser": "^2.0.0" + }, + "bin": { + "_mocha": "bin/_mocha", + "mocha": "bin/mocha.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/nise": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/nise/-/nise-1.5.3.tgz", + "integrity": "sha512-Ymbac/94xeIrMf59REBPOv0thr+CJVFMhrlAkW/gjCIE58BGQdCj0x7KRCb3yz+Ga2Rz3E9XXSvUyyxqqhjQAQ==", + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/formatio": "^3.2.1", + "@sinonjs/text-encoding": "^0.7.1", + "just-extend": "^4.0.2", + "lolex": "^5.0.1", + "path-to-regexp": "^1.7.0" + } + }, + "node_modules/nise/node_modules/@sinonjs/formatio": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-3.2.2.tgz", + "integrity": "sha512-B8SEsgd8gArBLMD6zpRw3juQ2FVSsmdd7qlevyDqzS9WTCtvF55/gAL+h6gue8ZvPYcdiPdvueM/qm//9XzyTQ==", + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^1", + "@sinonjs/samsam": "^3.1.0" + } + }, + "node_modules/nise/node_modules/lolex": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/lolex/-/lolex-5.1.2.tgz", + "integrity": "sha512-h4hmjAvHTmd+25JSwrtTIuwbKdwg5NzZVRMLn9saij4SZaepCrTCxPr35H/3bjwfMJtN+t3CX8672UIkglz28A==", + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^1.7.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "license": "BlueOak-1.0.0" + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-to-regexp": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.9.0.tgz", + "integrity": "sha512-xIp7/apCFJuUHdDLWe8O1HIkb0kQrOMb/0u6FXQjemHn/ii5LrIzU6bdECnsiTF/GjZkMEKg1xdiZwNqDYlZ6g==", + "license": "MIT", + "dependencies": { + "isarray": "0.0.1" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "license": "MIT", + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "license": "MIT", + "engines": { + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" } + ], + "license": "MIT" + }, + "node_modules/samsam": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.3.0.tgz", + "integrity": "sha512-1HwIYD/8UlOtFS3QO3w7ey+SdSDFE4HRNLZoZRYVQefrOY3l17epswImeB1ijgJFQJodIaHcwkp3r/myBjFVbg==", + "deprecated": "This package has been deprecated in favour of @sinonjs/samsam", + "license": "BSD-3-Clause" + }, + "node_modules/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "license": "BSD-3-Clause", + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/sinon": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-4.5.0.tgz", + "integrity": "sha512-trdx+mB0VBBgoYucy6a9L7/jfQOmvGeaKZT4OOJ+lPAtI8623xyGr8wLiE4eojzBS8G9yXbhx42GHUOVLr4X2w==", + "deprecated": "16.1.1", + "hasInstallScript": true, + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/formatio": "^2.0.0", + "diff": "^3.1.0", + "lodash.get": "^4.4.2", + "lolex": "^2.2.0", + "nise": "^1.2.0", + "supports-color": "^5.1.0", + "type-detect": "^4.0.5" + } + }, + "node_modules/sinon/node_modules/diff": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.1.tgz", + "integrity": "sha512-Z3u54A8qGyqFOSr2pk0ijYs8mOE9Qz8kTvtKeBI+upoG9j04Sq+oI7W8zAJiQybDcESET8/uIdHzs0p3k4fZlw==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/sinon/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/sinon/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/type-detect": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz", + "integrity": "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/workerpool": { + "version": "9.3.4", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-9.3.4.tgz", + "integrity": "sha512-TmPRQYYSAnnDiEB0P/Ytip7bFGvqnSU6I2BcuSw7Hx+JSg/DsUi5ebYfc8GYaSdpuvOcEs6dXxPurOYpe9QFwg==", + "license": "Apache-2.0" + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/xregexp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-3.2.0.tgz", + "integrity": "sha512-tWodXkrdYZPGadukpkmhKAbyp37CV5ZiFHacIVPhRZ4/sSt7qtOYHLv2dAqcPN0mBsViY2Qai9JkO7v2TBP6hg==", + "license": "MIT" + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-unparser": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", + "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", + "license": "MIT", + "dependencies": { + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/yargs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } } + } } diff --git a/package.json b/package.json index a6a2d39..69e2b57 100644 --- a/package.json +++ b/package.json @@ -1,12 +1,12 @@ { - "scripts": { - "test": "mocha" - }, - "type": "commonjs", - "dependencies": { - "bluebird": "^3.5.1", - "mocha": "^11.0.1", - "sinon": "^4.0.2", - "xregexp": "^3.2.0" - } + "scripts": { + "test": "mocha" + }, + "type": "commonjs", + "dependencies": { + "bluebird": "^3.5.1", + "mocha": "^11.0.1", + "sinon": "^4.0.2", + "xregexp": "^3.2.0" + } } diff --git a/test/Gemfile.lock b/test/Gemfile.lock index 4135799..28e0bbd 100644 --- a/test/Gemfile.lock +++ b/test/Gemfile.lock @@ -1,9 +1,13 @@ GEM remote: https://rubygems.org/ specs: - httpclient (2.8.3) - json (2.6.3) - minitest (5.18.1) + httpclient (2.9.0) + mutex_m + json (2.18.1) + minitest (6.0.1) + prism (~> 1.5) + mutex_m (0.3.0) + prism (1.9.0) PLATFORMS ruby @@ -14,4 +18,4 @@ DEPENDENCIES minitest BUNDLED WITH - 2.2.22 + 2.7.2 diff --git a/test/test.js b/test/test.js index 70e4ef0..0481a18 100644 --- a/test/test.js +++ b/test/test.js @@ -1,306 +1,254 @@ /* global require describe it */ -const assert = require('assert'); -const sinon = require('sinon'); -const xregexp = require('xregexp'); -const bluebird = require('bluebird'); +const assert = require("assert"); +const sinon = require("sinon"); +const xregexp = require("xregexp"); +const bluebird = require("bluebird"); -const core = require('../extension/core.js'); +const core = require("../extension/core.js"); -describe('#core.fixStyleId()', () => { - it('should return chicago as default', ()=>{ - assert.equal('http://www.zotero.org/styles/chicago-note-bibliography', core.fixStyleId()); +describe("#core.fixStyleId()", () => { + it("should return chicago as default", () => { + assert.equal( + "http://www.zotero.org/styles/chicago-notes-bibliography", + core.fixStyleId(), + ); }); - it('should append the prefix if necessary', ()=>{ - assert.equal('http://www.zotero.org/styles/foobar', core.fixStyleId('foobar')); + it("should append the prefix if necessary", () => { + assert.equal( + "http://www.zotero.org/styles/foobar", + core.fixStyleId("foobar"), + ); }); - it('should return the full url otherwise', ()=>{ - const url = 'http://example.org/foo'; + it("should return the full url otherwise", () => { + const url = "http://example.org/foo"; assert.equal(url, core.fixStyleId(url)); }); }); - -describe('#core.checkStyleId()', () => { - const styleId = "http://example.org/chicago" - beforeEach(()=>{ - getAll = sinon.stub().returns({[styleId]: {"styleID": styleId}}); - zotero = { Styles : { getAll } }; +describe("#core.checkStyleId()", () => { + const styleId = "http://example.org/chicago"; + beforeEach(() => { + getAll = sinon.stub().returns({ [styleId]: { styleID: styleId } }); + zotero = { Styles: { getAll } }; }); - it('should do nothing for good styles', ()=>{ + it("should do nothing for good styles", () => { assert.equal(styleId, core.checkStyleId(styleId, zotero)); }); - it('should throw an exception for a bad style', ()=>{ - assert.throws( - ()=> { - core.checkStyleId('http://example.org/bad', zotero); - }, - /Style .*bad is not installed/); - }); -}); - - -describe('#core.parseEasyKey()', () => { - const zotero = { Utilities: { XRegExp: xregexp } }; - const altRes = { - creator: 'foo', - date: '2016', - title: 'bar' - }; - - const res = { - creator: 'Foo', - date: '2016', - title: 'Bar' - }; - - it('should parse an alternative easykey', ()=>{ - assert.deepEqual(altRes, core.parseEasyKey('foo:2016bar', zotero)); - }); - - it('should parse a normal easykey', ()=>{ - assert.deepEqual(res, core.parseEasyKey('FooBar2016', zotero)); + it("should throw an exception for a bad style", () => { + assert.throws(() => { + core.checkStyleId("http://example.org/bad", zotero); + }, /Style .*bad is not installed/); }); }); -describe('#core.cleanQuery()', () => { - it('should replace all + with space', ()=>{ - assert.deepEqual({foo: 'foo bar'}, core.cleanQuery({foo: 'foo+bar'})); +describe("#core.cleanQuery()", () => { + it("should replace all + with space", () => { + assert.deepEqual( + { foo: "foo bar" }, + core.cleanQuery({ foo: "foo+bar" }), + ); }); }); -describe('#core.dedupItems()', () => { - const item1 = {id: 1}; - const item2 = {id: 2}; - const item3 = {id: 3}; +describe("#core.dedupItems()", () => { + const item1 = { id: 1 }; + const item2 = { id: 2 }; + const item3 = { id: 3 }; const zotero = { Promise: { filter: bluebird.filter } }; - const mkPromises = (...rest)=>{ return rest.map(bluebird.resolve); }; - it('should return an Promise that resolves to an iterable', ()=>{ - return core.dedupItems(mkPromises(item1), zotero).then((items)=>{ - assert.equal(1, items.length); - assert.deepEqual(item1, items[0]); - }); + const mkPromises = (...rest) => { + return rest.map(bluebird.resolve); + }; + it("should return an Promise that resolves to an iterable", async () => { + const items = await core.dedupItems(mkPromises(item1), zotero); + assert.equal(1, items.length); + assert.deepEqual(item1, items[0]); }); - it('should dedup with the same id', ()=>{ - return core.dedupItems(mkPromises(item1, item1), zotero).then((items)=>{ - assert.equal(1, items.length); - assert.deepEqual(item1, items[0]); - }); + it("should dedup with the same id", async () => { + const items = await core.dedupItems(mkPromises(item1, item1), zotero); + assert.equal(1, items.length); + assert.deepEqual(item1, items[0]); }); - it('should dedup and return in order', ()=>{ - return core.dedupItems(mkPromises(item1, item2, item1, item3, item1), zotero).then((items)=>{ - assert.equal(3, items.length); - assert.deepEqual(item1, items[0]); - assert.deepEqual(item2, items[1]); - assert.deepEqual(item3, items[2]); - }); + it("should dedup and return in order", async () => { + const items = await core.dedupItems( + mkPromises(item1, item2, item1, item3, item1), + zotero, + ); + assert.equal(3, items.length); + assert.deepEqual(item1, items[0]); + assert.deepEqual(item2, items[1]); + assert.deepEqual(item3, items[2]); }); }); -describe('#core.item2key()', () => { - it('builds a key', ()=>{ - const item = { libraryID: '2', key: 'foo' }; - assert('2_foo', core.item2key(item)); +describe("#core.item2key()", () => { + it("builds a key", () => { + const item = { libraryID: "2", key: "foo" }; + assert("2_foo", core.item2key(item)); }); - it('defaults to librar 1', ()=>{ - const item = { key: 'foo' }; - assert('1_foo', core.item2key(item)); + it("defaults to librar 1", () => { + const item = { key: "foo" }; + assert("1_foo", core.item2key(item)); }); }); -describe('#core.findByKey()', () => { +describe("#core.findByKey()", () => { let getByLibraryAndKeyAsync, parseLibraryKey, zotero; - beforeEach(()=>{ + beforeEach(() => { getByLibraryAndKeyAsync = sinon.stub().returns(Promise.resolve(true)); - parseLibraryKey = sinon.stub().returns({ libraryID: 2, key: 'bar' }); - zotero = { Items : { getByLibraryAndKeyAsync, parseLibraryKey } }; + parseLibraryKey = sinon.stub().returns({ libraryID: 2, key: "bar" }); + zotero = { Items: { getByLibraryAndKeyAsync, parseLibraryKey } }; }); - it("calls getByLibraryAndKeyAsync when a key without a / is passed in", ()=>{ - const key = 'foo-bar'; + it("calls getByLibraryAndKeyAsync when a key without a / is passed in", () => { + const key = "foo-bar"; core.findByKey(key, zotero); assert(parseLibraryKey.notCalled); assert(getByLibraryAndKeyAsync.calledOnce); assert(getByLibraryAndKeyAsync.calledWith(1, key)); }); - it("calls getByLibraryAndKeyAsync when a key with a _ is passed in", ()=>{ - const key = '3_bar'; + it("calls getByLibraryAndKeyAsync when a key with a _ is passed in", () => { + const key = "3_bar"; core.findByKey(key, zotero); assert(parseLibraryKey.notCalled); assert(getByLibraryAndKeyAsync.calledOnce); - assert(getByLibraryAndKeyAsync.calledWith(3, 'bar')); + assert(getByLibraryAndKeyAsync.calledWith(3, "bar")); }); - it("fetches the library id and calls getByLibraryAndKeyAsync when a key with a / is used", ()=>{ - const key = 'foo/bar'; + it("fetches the library id and calls getByLibraryAndKeyAsync when a key with a / is used", () => { + const key = "foo/bar"; core.findByKey(key, zotero); assert(parseLibraryKey.calledOnce); assert(parseLibraryKey.calledWith(key)); assert(getByLibraryAndKeyAsync.calledOnce); - assert(getByLibraryAndKeyAsync.calledWith(2, 'bar')); + assert(getByLibraryAndKeyAsync.calledWith(2, "bar")); }); }); - -describe('#core.makeCslEngine()', () => { - let opt, getCiteProc, style, get, zotero, styleName, locale, styleId, getAll; - - beforeEach(()=>{ +describe("#core.makeCslEngine()", () => { + let opt, + getCiteProc, + style, + get, + zotero, + styleName, + locale, + styleId, + getAll; + + beforeEach(() => { opt = { development_extensions: { wrap_url_and_doi: false } }; getCiteProc = sinon.stub().returns({ opt }); style = { getCiteProc }; - styleName = 'foo'; - locale = 'en-US'; + styleName = "foo"; + locale = "en-US"; styleId = `http://www.zotero.org/styles/${styleName}`; get = sinon.stub().returns(style); - getAll = sinon.stub().returns({[styleId]: {"styleID": styleId}}); - zotero = { Styles : { get, getAll } }; + getAll = sinon.stub().returns({ [styleId]: { styleID: styleId } }); + zotero = { Styles: { get, getAll } }; }); - it("sets wrap_url_and_dio", ()=>{ - core.makeCslEngine(styleName, locale, zotero, 'html'); + it("sets wrap_url_and_dio", () => { + core.makeCslEngine(styleName, locale, zotero, "html"); assert.equal(true, opt.development_extensions.wrap_url_and_doi); }); - it("sets calls Styles.get", ()=>{ - core.makeCslEngine(styleName, locale, zotero, 'text'); + it("sets calls Styles.get", () => { + core.makeCslEngine(styleName, locale, zotero, "text"); sinon.assert.calledOnce(get); sinon.assert.calledWith(get, styleId); }); - it("sets calls getCiteProc with locale", ()=>{ - core.makeCslEngine(styleName, locale, zotero, 'html'); + it("sets calls getCiteProc with locale", () => { + core.makeCslEngine(styleName, locale, zotero, "html"); sinon.assert.calledOnce(getCiteProc); - sinon.assert.calledWith(getCiteProc, 'en-US', 'html'); + sinon.assert.calledWith(getCiteProc, "en-US", "html"); }); }); -describe('#core.getItemOrParent()', () => { - it("returns item when item is a regularItem", ()=>{ +describe("#core.getItemOrParent()", () => { + it("returns item when item is a regularItem", async () => { const isRegularItem = sinon.stub().returns(true); const item = { isRegularItem }; assert.equal(item, core.getItemOrParent(item, undefined)); }); - it("returns item when item is not a regularItem but the parentKey is falsey", ()=>{ + it("returns item when item is not a regularItem but the parentKey is falsey", async () => { const isRegularItem = sinon.stub().returns(false); const parentKey = undefined; const item = { isRegularItem, parentKey }; - assert.equal(item, core.getItemOrParent(item, undefined)); + assert.equal(item, await core.getItemOrParent(item, undefined)); }); - it("returns item when item is not a regularItem but the parentKey is falsey", ()=>{ - const retval = 'foo'; + it("returns item when item is not a regularItem but the parentKey is falsey", async () => { + const retval = "foo"; const isRegularItem = sinon.stub().returns(false); const parentKey = "foo_bar"; const item = { isRegularItem, parentKey }; - const getByLibraryAndKeyAsync = sinon.stub().returns(Promise.resolve(retval)); + const getByLibraryAndKeyAsync = sinon + .stub() + .returns(Promise.resolve(retval)); const Items = { getByLibraryAndKeyAsync }; const zotero = { Items }; - core.getItemOrParent(item, zotero).then((item)=> { assert.equal(retval, item); }); - }); -}); - -describe('#core.buildSearch()', () => { - let addCondition, search; - - beforeEach(()=>{ - addCondition = sinon.stub(); - search = { addCondition }; - }); - - it("sets joinMode to all ", ()=>{ - core.buildSearch(search, 'foo', null); - sinon.assert.calledWith(addCondition, 'joinMode', 'all'); - }); - - it("searches titleCreatorYear by default", ()=>{ - core.buildSearch(search, 'foo', null); - sinon.assert.calledWith(addCondition, 'quicksearch-titleCreatorYear', 'contains', 'foo'); - }); - - it("uses the method if passed in by default", ()=>{ - core.buildSearch(search, 'foo', 'test'); - sinon.assert.calledWith(addCondition, 'quicksearch-test', 'contains', 'foo'); - }); - - it("splits words for search", ()=>{ - core.buildSearch(search, 'foo bar', null); - sinon.assert.calledWith(addCondition, 'quicksearch-titleCreatorYear', 'contains', 'foo'); - sinon.assert.calledWith(addCondition, 'quicksearch-titleCreatorYear', 'contains', 'bar'); - }); -}); - -describe('#core.buildRawSearch()', () => { - let addCondition, search; - - beforeEach(()=>{ - addCondition = sinon.stub(); - search = { addCondition }; - }); - - it("sets up the search as expected ", ()=>{ - core.buildRawSearch(search, 'foo:2016bar'); - sinon.assert.calledWith(addCondition, 'joinMode', 'any'); - sinon.assert.calledWith(addCondition, 'tag', 'is', '@foo:2016bar'); - sinon.assert.calledWith(addCondition, 'note', 'contains', '@foo:2016bar'); + assert.equal(retval, await core.getItemOrParent(item, zotero)); }); }); - -describe('#core.buildEasyKeySearch()', () => { +describe("#core.buildSearch()", () => { let addCondition, search; - const zotero = { Utilities: { XRegExp: xregexp } }; - beforeEach(()=>{ + beforeEach(() => { addCondition = sinon.stub(); search = { addCondition }; }); - it("adds all fields if provided", ()=>{ - const key = core.parseEasyKey('foo:2016bar', zotero); - core.buildEasyKeySearch(search, key); - sinon.assert.calledWith(addCondition, 'creator', 'contains', 'foo'); - sinon.assert.calledWith(addCondition, 'title', 'contains', 'bar'); - sinon.assert.calledWith(addCondition, 'date', 'is', '2016'); - }); - - it("splits names", ()=>{ - const key = core.parseEasyKey('foo_bar:2016baz', zotero); - core.buildEasyKeySearch(search, key); - sinon.assert.calledWith(addCondition, 'creator', 'contains', 'foo'); - sinon.assert.calledWith(addCondition, 'creator', 'contains', 'bar'); - }); - - it("works when date not provided", ()=>{ - const key = core.parseEasyKey('foo:bar', zotero); - core.buildEasyKeySearch(search, key); - sinon.assert.calledWith(addCondition, 'creator', 'contains', 'foo'); - sinon.assert.calledWith(addCondition, 'title', 'contains', 'bar'); - sinon.assert.calledTwice(addCondition); - }); - - it("works when title not provided", ()=>{ - const key = core.parseEasyKey('foo:2016', zotero); - core.buildEasyKeySearch(search, key); - sinon.assert.calledWith(addCondition, 'creator', 'contains', 'foo'); - sinon.assert.calledWith(addCondition, 'date', 'is', '2016'); - sinon.assert.calledTwice(addCondition); - }); - - it("works when date title not provided", ()=>{ - const key = core.parseEasyKey('foo:', zotero); - core.buildEasyKeySearch(search, key); - sinon.assert.calledWith(addCondition, 'creator', 'contains', 'foo'); - sinon.assert.calledOnce(addCondition); + it("sets joinMode to all ", () => { + core.buildSearch(search, "foo", null); + sinon.assert.calledWith(addCondition, "joinMode", "all"); + }); + + it("searches titleCreatorYear by default", () => { + core.buildSearch(search, "foo", null); + sinon.assert.calledWith( + addCondition, + "quicksearch-titleCreatorYear", + "contains", + "foo", + ); + }); + + it("uses the method if passed in by default", () => { + core.buildSearch(search, "foo", "test"); + sinon.assert.calledWith( + addCondition, + "quicksearch-test", + "contains", + "foo", + ); + }); + + it("splits words for search", () => { + core.buildSearch(search, "foo bar", null); + sinon.assert.calledWith( + addCondition, + "quicksearch-titleCreatorYear", + "contains", + "foo", + ); + sinon.assert.calledWith( + addCondition, + "quicksearch-titleCreatorYear", + "contains", + "bar", + ); }); }); diff --git a/test/test.rb b/test/test.rb index 51b28c9..e74e22a 100644 --- a/test/test.rb +++ b/test/test.rb @@ -5,7 +5,7 @@ require "json" require "open3" -class ZotxtTest < MiniTest::Test +class ZotxtTest < Minitest::Test def setup @client = HTTPClient.new @base_url = "http://127.0.0.1:23119/zotxt" @@ -33,109 +33,6 @@ def test_items_nothing assert_equal 400, resp.status end - def test_items_easykey - resp = @client.get(@item_url, { "easykey" => "DoeBook2005" }) - assert_equal 200, resp.status - i = JSON.parse(resp.body) - assert_equal "book", i[0]["type"] - assert_equal "First Book", i[0]["title"] - assert_equal "Doe", i[0]["author"][0]["family"] - end - - def test_items_easykey_key_format - resp = @client.get(@item_url, { "easykey" => "DoeBook2005", "format" => "key" }) - assert_equal 200, resp.status - i = JSON.parse(resp.body) - assert_equal @doe_first_book_key, i[0] - end - - def test_items_easykey_json_format - resp = @client.get(@item_url, { "easykey" => "DoeBook2005", "format" => "json" }) - assert_equal 200, resp.status - i = JSON.parse(resp.body) - i[0].delete("id") - assert_equal({ "citation-key" => "doe:2005first", - "type" => "book", - "title" => "First Book", - "publisher" => "Cambridge University Press", - "author" => [{ "family" => "Doe", "given" => "John" }], - "issued" => { "date-parts" => [["2005"]] }, - "publisher-place" => "Cambridge", - "event-place" => "Cambridge" }, i[0]) - end - - def test_items_easykey_paths_format - resp = @client.get(@item_url, { "easykey" => "doe:2006article", "format" => "paths" }) - assert_equal 200, resp.status - i = JSON.parse(resp.body) - assert_equal(@doe_article_key, i[0]["key"]) - assert(i[0]["paths"][0] =~ %r{storage/[A-Z0-9]{8}/doe$}) - end - - def test_items_easykey_paths_format_after_deletion - skip("requires sync setup") - resp = @client.get(@item_url, { "easykey" => "doe:2006article", "format" => "paths" }) - i = JSON.parse(resp.body) - - # should be fetched afer deletion - File.unlink(i[0]["paths"][0]) - resp = @client.get(@item_url, { "easykey" => "doe:2006article", "format" => "paths" }) - assert_equal 200, resp.status - i = JSON.parse(resp.body) - assert_equal(@doe_article_key, i[0]["key"]) - # assert_match not working? - assert(i[0]["paths"][0] =~ %r{storage/[A-Z0-9]{8}/doe$}) - end - - def test_items_easykey_two_word - key = find_item_key("united nations wonderful") - resp = @client.get(@item_url, { "easykey" => "united_nations:2005book", "format" => "key" }) - assert_equal 200, resp.status - i = JSON.parse(resp.body) - assert_equal key, i[0] - end - - def test_items_easykey_double_name - key = find_item_key("roe doe double") - resp = @client.get(@item_url, { "easykey" => "roe_doe:2015double", "format" => "key" }) - assert_equal 200, resp.status - i = JSON.parse(resp.body) - assert_equal key, i[0] - end - - def test_items_easykey_hyphenated_name - resp = @client.get(@item_url, { "easykey" => "roe-doe:2015hyphens", "format" => "key" }) - assert_equal 200, resp.status - i = JSON.parse(resp.body) - assert_equal @roe_doe_hyphens_key, i[0] - end - - def test_items_easykey_alternate_key_format - resp = @client.get(@item_url, { "easykey" => "doe:2005book", "format" => "key" }) - assert_equal 200, resp.status - i = JSON.parse(resp.body) - assert_equal @doe_first_book_key, i[0] - end - - def test_items_easykey_two_items - resp = @client.get(@item_url, { "easykey" => "doe:2005book,roe-doe:2015hyphens", "format" => "key" }) - assert_equal 200, resp.status - i = JSON.parse(resp.body) - assert_equal [@doe_first_book_key, @roe_doe_hyphens_key].sort, i.sort - end - - def test_items_easykey_ambiguous - resp = @client.get(@item_url, { "easykey" => "doe:2005ambiguous" }) - assert_equal 400, resp.status - assert_equal '"doe:2005ambiguous returned multiple items"', resp.body - end - - def test_items_easykey_bad - resp = @client.get(@item_url, { "easykey" => "doe:2005foobar" }) - assert_equal 400, resp.status - assert_equal '"doe:2005foobar had no results"', resp.body - end - def test_betterbibtexkey %w[betterbibtexkey citekey].each do |name| resp = @client.get(@item_url, { name => "doe:2005first", "format" => "key" }) @@ -162,29 +59,6 @@ def test_betterbibtexkey_two_items # assert_equal ["xyz"], i # end - def test_items_easykey_bibliography_format - resp = @client.get(@item_url, { "easykey" => "DoeBook2005", "format" => "bibliography" }) - assert_equal 200, resp.status - i = JSON.parse(resp.body) - assert(i[0].key?("html")) - - # with style - resp = @client.get(@item_url, - { "easykey" => "DoeBook2005", "format" => "bibliography", - "style" => "http://www.zotero.org/styles/chicago-note-bibliography" }) - assert_equal 200, resp.status - i = JSON.parse(resp.body) - assert(i[0].key?("html")) - - # with short style - resp = @client.get(@item_url, - { "easykey" => "DoeBook2005", "format" => "bibliography", - "style" => "chicago-note-bibliography" }) - assert_equal 200, resp.status - i = JSON.parse(resp.body) - assert(i[0].key?("html")) - end - def test_items_key resp = @client.get(@item_url, { "key" => @doe_first_book_key, "format" => "key" }) assert_equal 200, resp.status @@ -205,13 +79,6 @@ def test_items_bad_key assert_equal '"1_ZBZQ4KMXXXX not found"', resp.body end - def test_items_multiple_easykeys - resp = @client.get(@item_url, { "easykey" => "DoeBook2005,Doe2006article", "format" => "key" }) - assert_equal 200, resp.status - i = JSON.parse(resp.body) - assert_equal 2, i.length - end - def test_items_multiple_keys resp = @client.get(@item_url, { "key" => "#{@doe_first_book_key},#{@doe_article_key}", "format" => "key" }) assert_equal 200, resp.status @@ -224,54 +91,6 @@ def test_selected assert_equal 200, resp.status end - def test_bibliography - r = { - "styleId" => "chicago-author-date", - "citationGroups" => [ - { "citationItems" => [{ "easyKey" => "DoeBook2005" }], - "properties" => { "noteIndex" => 0 } }, - ], - } - header = { "Content-Type" => "application/json" } - resp = @client.post(@bibliography_url, header: header, body: JSON.dump(r)) - assert_equal 200, resp.status - i = JSON.parse(resp.body) - assert_equal ["(Doe 2005)"], i["citationClusters"] - end - - def test_bibliography_error - r = { - "styleId" => "chicago-author-date", - "citationGroups" => [ - { "citationItems" => [{ "easyKey" => "doe:2005ambiguous" }], - "properties" => { "noteIndex" => 0 } }, - { "citationItems" => [{ "easyKey" => "doe:2005first" }], - "properties" => { "noteIndex" => 0 } }, - ], - } - header = { "Content-Type" => "application/json" } - resp = @client.post(@bibliography_url, header: header, body: JSON.dump(r)) - assert_equal 400, resp.status - assert_equal '"doe:2005ambiguous returned multiple items"', resp.body - end - - def test_ambiguous_bibliography - r = { - "styleId" => "chicago-author-date", - "citationGroups" => [ - { "citationItems" => [{ "easyKey" => "jenkins:2011jesus" }], - "properties" => { "index" => 0, "noteIndex" => 0 } }, - { "citationItems" => [{ "easyKey" => "jenkins:2009lost" }], - "properties" => { "index" => 1, "noteIndex" => 0 } }, - ], - } - header = { "Content-Type" => "application/json" } - resp = @client.post(@bibliography_url, header: header, body: JSON.dump(r)) - assert_equal 200, resp.status - i = JSON.parse(resp.body) - assert_equal ["(J. P. Jenkins 2011)", "(P. Jenkins 2009)"], i["citationClusters"] - end - def test_bibliography_key key = find_item_key("doe 2005 first book") r = { @@ -288,19 +107,6 @@ def test_bibliography_key assert_equal ["(Doe 2005)"], i["citationClusters"] end - def test_bad_bibliography - r = { - "styleId" => "chicago-author-date", - "citationGroups" => [ - { "citationItems" => [{ "easyKey" => "FooBar0000" }], - "properties" => { "noteIndex" => 0 } }, - ], - } - header = { "Content-Type" => "application/json" } - resp = @client.post(@bibliography_url, header: header, body: JSON.dump(r)) - assert_equal 400, resp.status - end - def test_no_param resp = @client.get(@item_url) assert_equal 400, resp.status @@ -312,51 +118,6 @@ def test_all assert_equal 200, resp.status end - def test_bad_easykey - resp = @client.get(@item_url, { "easykey" => "XXX" }) - assert_equal 400, resp.status - end - - def test_unicode_easykey - resp = @client.get(@item_url, { "easykey" => "HüningWortbildung2012" }) - assert_equal 200, resp.status - end - - def test_bad_easykey - resp = @client.get(@item_url, { "easykey" => "XXX" }) - assert_equal 400, resp.status - end - - def test_custom_key - skip("this seems broken") - resp = @client.get(@item_url, { "easykey" => "hüning:2012foo" }) - assert_equal 200, resp.status - end - - def test_accent_easykey_export - skip("easykey is deprecated") - key = find_item_key("acćénts") - resp = @client.get(@item_url, { "key" => key, "format" => "easykey" }) - assert_equal 200, resp.status - results = JSON.parse(resp.body) - assert_equal "hüáéèñ:2015acćénts", results[0] - end - - def test_accent_easykey_fetch - key = find_item_key("acćénts") - resp = @client.get(@item_url, { "easykey" => "hüáéèñ:2015acćénts", "format" => "key" }) - assert_equal 200, resp.status - results = JSON.parse(resp.body) - assert_equal key, results[0] - end - - def test_duplicate_in_group_library - resp = @client.get(@item_url, { "easykey" => "doe:2015duplicated", "format" => "key" }) - assert_equal 200, resp.status - results = JSON.parse(resp.body) - assert_equal @doe_duplicated, results[0] - end - def test_collection_search resp = @client.get(@item_url, { "collection" => "zotxt test" }) assert_equal 200, resp.status @@ -423,29 +184,6 @@ def test_format_quickbib assert_equal({ "key" => @doe_article_key, "quickBib" => "Doe, John - 2006 - Article" }, results[0]) end - def test_format_easykey - skip("easykey is deprecated") - resp = @client.get(@item_url, { "key" => @doe_article_key, "format" => "easykey" }) - assert_equal 200, resp.status - results = JSON.parse(resp.body) - assert_equal "doe:2006article", results[0] - end - - def test_format_easykey_clean_html - skip("easykey is deprecated") - resp = @client.get(@item_url, { "easykey" => "doe:2007why", "format" => "easykey" }) - assert_equal 200, resp.status - results = JSON.parse(resp.body) - assert_equal "doe:2007why", results[0] - end - - def test_select - resp = @client.get(@item_url, { "selected" => "t", "format" => "easykey" }) - assert_equal 200, resp.status - results = JSON.parse(resp.body) - assert [[], ["doe:2006article"]].include?(results) - end - def test_format_betterbibtex %w[betterbibtexkey citekey].each do |name| resp = @client.get(@item_url, { "key" => @doe_article_key, "format" => name }) @@ -479,33 +217,23 @@ def test_format_json assert_equal 200, resp.status results = JSON.parse(resp.body) results[0].delete("id") - assert_equal({ "citation-key" => "doe:2006article", - "type" => "article-journal", - "title" => "Article", + assert_equal({ "author" => [{ "family" => "Doe", "given" => "John" }], + "citation-key" => "doe:2006article", "container-title" => "Journal of Generic Studies", - "page" => "33-34", - "volume" => "6", - "author" => [{ "family" => "Doe", "given" => "John" }], - "issued" => { "date-parts" => [["2006"]] } }, results[0]) + "issued" => { "date-parts" => [["2006"]] }, + "page" => "33–34", + "title" => "Article", + "type" => "article-journal", + "volume" => "6" }, + results[0]) end - def test_completion - skip("easykey is deprecated") - resp = @client.get(@complete_url, { "citekey" => "doe:" }) - results = JSON.parse(resp.body) - assert(results.size > 4) - - resp = @client.get(@complete_url, { "easykey" => "doe:20" }) - results = JSON.parse(resp.body) - assert(results.size > 4) - - resp = @client.get(@complete_url, { "easykey" => "doe:2006" }) - results = JSON.parse(resp.body) - assert_equal ["doe:2006article"], results - - resp = @client.get(@complete_url, { "easykey" => "doe:2006art" }) + def test_citationkey_prefix_completion + resp = @client.get(@complete_url, { "prefix" => "doe" }) + assert_equal 200, resp.status results = JSON.parse(resp.body) - assert_equal ["doe:2006article"], results + assert results.is_a?(Array) + assert results.all? { |key| key.start_with?("doe") } end def test_search @@ -532,19 +260,15 @@ def test_search_everything_standalone_note def test_select resp = @client.get(@select_url, { "key" => @doe_article_key }) assert_equal 200, resp.status - resp = @client.get(@select_url, { "easykey" => "doe:2006article" }) - assert_equal 200, resp.status # bad key resp = @client.get(@select_url, { "key" => "1_4T8MCITQXXX" }) assert_equal 400, resp.status - resp = @client.get(@select_url, { "easykey" => "XXX" }) - assert_equal 400, resp.status end def test_version resp = @client.get(@version_url) assert_equal 200, resp.status - assert_match(/^7.0/, JSON.parse(resp.body)["version"]) + assert_match(/^8.0/, JSON.parse(resp.body)["version"]) end def test_locales @@ -557,9 +281,9 @@ def test_styles resp = @client.get(@styles_url) assert_equal 200, resp.status style = JSON.parse(resp.body).find do |value| - value["styleID"] == "http://www.zotero.org/styles/chicago-fullnote-bibliography" + value["styleID"] == "http://www.zotero.org/styles/modern-language-association" end - assert_equal "note", style["categories"] - assert_equal "Chicago Manual of Style 17th edition (full note)", style["title"] + assert_equal "author", style["categories"] + assert_equal "MLA Handbook 9th edition (in-text citations)", style["title"] end end diff --git a/update.json b/update.json index da8b202..5c2a70f 100644 --- a/update.json +++ b/update.json @@ -4,7 +4,7 @@ "updates": [ { "version": "6.0.3", - "update_link": "https://github.com/egh/zotxt/releases/download/v6.0.3/zotxt-6.0.3.xpi" + "update_link": "https://github.com/egh/zotxt/releases/download/v6.0.3/zotxt-6.0.3.xpi", "update_hash": "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", "applications": { "gecko": { @@ -14,19 +14,18 @@ } }, { - "version": "7.0.0", - "update_link": "https://github.com/egh/zotxt/releases/download/v7.0.0/zotxt-7.0.0.xpi" + "version": "7.0.2", + "update_link": "https://github.com/egh/zotxt/releases/download/v7.0.2/zotxt-7.0.2.xpi", "update_hash": "sha256:4a6dd04c197629a02a9c6beaa9ebd52a69bb683f8400243bcdf95847f0ee254a", "applications": { "gecko": { "strict_min_version": "60.9", "strict_max_version": "60.9" }, - "zotero": { + "zotero": { "strict_min_version": "6.999", "strict_max_version": "7.0.*" } - } } ]