From 84a3a61c0068a77e1d57d220883bb3dccfd58ead Mon Sep 17 00:00:00 2001 From: Trenton Schulz Date: Tue, 7 Mar 2023 22:01:05 +0100 Subject: [PATCH 01/29] Add a function for getting the non-deprecated link. This is mostly just adapted from Zutilo, but it seems to be considered the "blessed" version, so I'm keeping it for now. --- extension/bootstrap.js | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/extension/bootstrap.js b/extension/bootstrap.js index 9f8b054..933520d 100644 --- a/extension/bootstrap.js +++ b/extension/bootstrap.js @@ -42,6 +42,44 @@ 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 +} + + function collectionSearch(name) { let collections = Zotero.Collections.getByLibrary(Zotero.Libraries.userLibraryID, true); for (let collection of collections) { @@ -127,6 +165,8 @@ function buildResponse(items, format, style, locale) { return [okCode, 'application/json', jsonStringify(items.map(item2key))]; } else if (format === 'easykey') { return buildEasyKeyResponse(items); + } else if (format === 'zoteroLink') { + return [okCode, 'application/json', jsonStringify(items.map(buildZoteroLink))]; } else if (format === 'betterbibtexkey' || format === 'citekey') { return buildBBTKeyResponse(items); } else if (format === 'bibtex') { From ae89e9cee49ed6ca96bc16305ee216dd802ed67d Mon Sep 17 00:00:00 2001 From: Erik Hetzner Date: Thu, 27 Feb 2025 10:46:41 -0800 Subject: [PATCH 02/29] update for latest ruby --- test/test.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test.rb b/test/test.rb index 51b28c9..1164669 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" From 5a760c4d4629e0827c2f395da5037b912b66bccd Mon Sep 17 00:00:00 2001 From: Erik Hetzner Date: Thu, 27 Feb 2025 11:48:39 -0800 Subject: [PATCH 03/29] Support any 7.x version of Zotero --- extension/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extension/manifest.json b/extension/manifest.json index 9404b8e..b552e67 100644 --- a/extension/manifest.json +++ b/extension/manifest.json @@ -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": "7.*" } } } From 55daf9448d49d7d54a2a8304d2aaa2532531d5c7 Mon Sep 17 00:00:00 2001 From: Erik Hetzner Date: Thu, 27 Feb 2025 11:48:52 -0800 Subject: [PATCH 04/29] Bump version to 7.0.1 --- extension/manifest.json | 2 +- update.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/extension/manifest.json b/extension/manifest.json index b552e67..4f37bbe 100644 --- a/extension/manifest.json +++ b/extension/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 2, "name": "zotxt", - "version": "7.0.0", + "version": "7.0.1", "description": "Plain text extensions for Zotero", "author": "Erik Hetzner", "applications": { diff --git a/update.json b/update.json index da8b202..d59dd23 100644 --- a/update.json +++ b/update.json @@ -14,8 +14,8 @@ } }, { - "version": "7.0.0", - "update_link": "https://github.com/egh/zotxt/releases/download/v7.0.0/zotxt-7.0.0.xpi" + "version": "7.0.1", + "update_link": "https://github.com/egh/zotxt/releases/download/v7.0.1/zotxt-7.0.1.xpi" "update_hash": "sha256:4a6dd04c197629a02a9c6beaa9ebd52a69bb683f8400243bcdf95847f0ee254a", "applications": { "gecko": { From 94eb8abb886e7094c279f41f097df4e0b87e4636 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 11 Jun 2025 20:56:06 +0000 Subject: [PATCH 05/29] Bump brace-expansion from 2.0.1 to 2.0.2 Bumps [brace-expansion](https://github.com/juliangruber/brace-expansion) from 2.0.1 to 2.0.2. - [Release notes](https://github.com/juliangruber/brace-expansion/releases) - [Commits](https://github.com/juliangruber/brace-expansion/compare/v2.0.1...v2.0.2) --- updated-dependencies: - dependency-name: brace-expansion dependency-version: 2.0.2 dependency-type: indirect ... Signed-off-by: dependabot[bot] --- package-lock.json | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 40776c4..c4fd41b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -234,9 +234,10 @@ "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==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } From c7b09eeca428a6a02eca88c3321419702ef351f0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 19 Nov 2025 01:32:34 +0000 Subject: [PATCH 06/29] Bump glob from 10.4.5 to 10.5.0 Bumps [glob](https://github.com/isaacs/node-glob) from 10.4.5 to 10.5.0. - [Changelog](https://github.com/isaacs/node-glob/blob/main/changelog.md) - [Commits](https://github.com/isaacs/node-glob/compare/v10.4.5...v10.5.0) --- updated-dependencies: - dependency-name: glob dependency-version: 10.5.0 dependency-type: indirect ... Signed-off-by: dependabot[bot] --- package-lock.json | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index c4fd41b..939f487 100644 --- a/package-lock.json +++ b/package-lock.json @@ -513,9 +513,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==", + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "license": "ISC", "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", From 160c875e2ce8df81b4fc631340bf7fcf126af151 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 19 Nov 2025 18:06:59 +0000 Subject: [PATCH 07/29] Bump js-yaml from 4.1.0 to 4.1.1 Bumps [js-yaml](https://github.com/nodeca/js-yaml) from 4.1.0 to 4.1.1. - [Changelog](https://github.com/nodeca/js-yaml/blob/master/CHANGELOG.md) - [Commits](https://github.com/nodeca/js-yaml/compare/4.1.0...4.1.1) --- updated-dependencies: - dependency-name: js-yaml dependency-version: 4.1.1 dependency-type: indirect ... Signed-off-by: dependabot[bot] --- package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 939f487..e10f732 100644 --- a/package-lock.json +++ b/package-lock.json @@ -674,9 +674,9 @@ } }, "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==", + "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" From 1509e20ebdd51b7608e33c28a668dde95873aaaf Mon Sep 17 00:00:00 2001 From: Erik Hetzner Date: Mon, 24 Nov 2025 09:50:41 -0800 Subject: [PATCH 08/29] fix default style name --- extension/core.js | 2 +- test/test.js | 2 +- test/test.rb | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/extension/core.js b/extension/core.js index a7ac726..7bc9e4f 100644 --- a/extension/core.js +++ b/extension/core.js @@ -20,7 +20,7 @@ function parseEasyKey(key, zotero) { 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; } else { diff --git a/test/test.js b/test/test.js index 70e4ef0..51d1dc3 100644 --- a/test/test.js +++ b/test/test.js @@ -9,7 +9,7 @@ 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()); + assert.equal('http://www.zotero.org/styles/chicago-notes-bibliography', core.fixStyleId()); }); it('should append the prefix if necessary', ()=>{ diff --git a/test/test.rb b/test/test.rb index 1164669..0893bac 100644 --- a/test/test.rb +++ b/test/test.rb @@ -179,7 +179,7 @@ def test_items_easykey_bibliography_format # with short style resp = @client.get(@item_url, { "easykey" => "DoeBook2005", "format" => "bibliography", - "style" => "chicago-note-bibliography" }) + "style" => "chicago-notes-bibliography" }) assert_equal 200, resp.status i = JSON.parse(resp.body) assert(i[0].key?("html")) From bbeb46cbfec7792c8e64a138b41d6313c4b75ebe Mon Sep 17 00:00:00 2001 From: Erik Hetzner Date: Mon, 24 Nov 2025 11:12:10 -0800 Subject: [PATCH 09/29] bundle update --- test/Gemfile.lock | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/test/Gemfile.lock b/test/Gemfile.lock index 4135799..7afa026 100644 --- a/test/Gemfile.lock +++ b/test/Gemfile.lock @@ -1,9 +1,11 @@ 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.16.0) + minitest (5.26.2) + mutex_m (0.3.0) PLATFORMS ruby @@ -14,4 +16,4 @@ DEPENDENCIES minitest BUNDLED WITH - 2.2.22 + 2.7.2 From 521f7db05195c37e3c7b19ca6aa2ee683d67a8cf Mon Sep 17 00:00:00 2001 From: Erik Hetzner Date: Mon, 24 Nov 2025 11:15:26 -0800 Subject: [PATCH 10/29] bump version to 7.0.2 --- extension/manifest.json | 2 +- update.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/extension/manifest.json b/extension/manifest.json index 4f37bbe..1648d9e 100644 --- a/extension/manifest.json +++ b/extension/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 2, "name": "zotxt", - "version": "7.0.1", + "version": "7.0.2", "description": "Plain text extensions for Zotero", "author": "Erik Hetzner", "applications": { diff --git a/update.json b/update.json index d59dd23..041c74d 100644 --- a/update.json +++ b/update.json @@ -14,8 +14,8 @@ } }, { - "version": "7.0.1", - "update_link": "https://github.com/egh/zotxt/releases/download/v7.0.1/zotxt-7.0.1.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": { From 475a21262dc1a159c76671efdebe77456856f2a0 Mon Sep 17 00:00:00 2001 From: Erik Hetzner Date: Thu, 5 Feb 2026 21:51:44 -0800 Subject: [PATCH 11/29] bundle update --- test/Gemfile.lock | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/Gemfile.lock b/test/Gemfile.lock index 7afa026..28e0bbd 100644 --- a/test/Gemfile.lock +++ b/test/Gemfile.lock @@ -3,9 +3,11 @@ GEM specs: httpclient (2.9.0) mutex_m - json (2.16.0) - minitest (5.26.2) + json (2.18.1) + minitest (6.0.1) + prism (~> 1.5) mutex_m (0.3.0) + prism (1.9.0) PLATFORMS ruby From 1c23fe67d9d2fc7ece98593a7b64f3e103b4238b Mon Sep 17 00:00:00 2001 From: Erik Hetzner Date: Thu, 5 Feb 2026 21:52:52 -0800 Subject: [PATCH 12/29] bump node --- .nvmrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.nvmrc b/.nvmrc index 9a2a0e2..54c6511 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -v20 +v24 From c4ad5ace9da4cca4fab9a7b9c4d6a64c3a2a6c2c Mon Sep 17 00:00:00 2001 From: Erik Hetzner Date: Thu, 5 Feb 2026 21:53:00 -0800 Subject: [PATCH 13/29] npm update --- package-lock.json | 678 +++++++++++++++++++++++----------------------- 1 file changed, 336 insertions(+), 342 deletions(-) diff --git a/package-lock.json b/package-lock.json index e10f732..3fe0590 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,6 +15,7 @@ "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", @@ -27,83 +28,11 @@ "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==", + "license": "MIT", "optional": true, "engines": { "node": ">=14" @@ -153,21 +82,16 @@ "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==", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", "license": "MIT", "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, "node_modules/ansi-styles": { @@ -185,19 +109,6 @@ "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", @@ -213,19 +124,8 @@ "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" - } + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT" }, "node_modules/bluebird": { "version": "3.7.2", @@ -242,18 +142,6 @@ "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", @@ -301,41 +189,90 @@ } }, "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/" - } - ], + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", "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" + "readdirp": "^4.0.1" }, "engines": { - "node": ">= 8.10.0" + "node": ">= 14.16.0" }, - "optionalDependencies": { - "fsevents": "~2.3.2" + "funding": { + "url": "https://paulmillr.com/funding/" } }, "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==", + "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.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": { @@ -360,6 +297,7 @@ "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", @@ -370,9 +308,10 @@ } }, "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==", + "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" }, @@ -398,9 +337,10 @@ } }, "node_modules/diff": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", - "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", + "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" } @@ -408,12 +348,13 @@ "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "license": "MIT" }, "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==", + "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": { @@ -437,18 +378,6 @@ "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", @@ -475,11 +404,12 @@ } }, "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==", + "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.0", + "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" }, "engines": { @@ -489,20 +419,6 @@ "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", @@ -516,6 +432,7 @@ "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", @@ -532,32 +449,6 @@ "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", @@ -576,27 +467,6 @@ "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", @@ -606,25 +476,13 @@ "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==", + "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": ">=0.12.0" + "node": ">=8" } }, "node_modules/is-plain-obj": { @@ -657,12 +515,14 @@ "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + "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" }, @@ -707,15 +567,16 @@ } }, "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "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": { @@ -743,51 +604,59 @@ "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==" + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "license": "ISC" }, "node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, "engines": { - "node": ">=10" + "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.0.1", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.0.1.tgz", - "integrity": "sha512-+3GkODfsDG71KSCQhc4IekSW+ItCK/kiez1Z28ksWvYhKXV/syxMlerR/sC7whDp7IyreZ4YxceMLdTs5hQE8A==", + "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": { - "ansi-colors": "^4.1.3", "browser-stdout": "^1.3.1", - "chokidar": "^3.5.3", + "chokidar": "^4.0.1", "debug": "^4.3.5", - "diff": "^5.2.0", + "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": "^5.1.6", + "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": "^6.5.1", - "yargs": "^16.2.0", - "yargs-parser": "^20.2.9", + "workerpool": "^9.2.0", + "yargs": "^17.7.2", + "yargs-parser": "^21.1.1", "yargs-unparser": "^2.0.0" }, "bin": { @@ -836,15 +705,6 @@ "@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", @@ -878,7 +738,8 @@ "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==" + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "license": "BlueOak-1.0.0" }, "node_modules/path-exists": { "version": "4.0.0", @@ -893,6 +754,7 @@ "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" } @@ -901,6 +763,7 @@ "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" @@ -921,36 +784,32 @@ "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/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": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", "license": "MIT", - "dependencies": { - "picomatch": "^2.2.1" - }, "engines": { - "node": ">=8.10.0" + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" } }, "node_modules/require-directory": { @@ -979,7 +838,8 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/samsam": { "version": "1.3.0", @@ -992,6 +852,7 @@ "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" } @@ -1000,6 +861,7 @@ "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" }, @@ -1011,6 +873,7 @@ "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" } @@ -1019,6 +882,7 @@ "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" }, @@ -1044,9 +908,9 @@ } }, "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==", + "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" @@ -1074,17 +938,20 @@ } }, "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==", + "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": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" }, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/string-width-cjs": { @@ -1092,6 +959,7 @@ "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", @@ -1101,7 +969,22 @@ "node": ">=8" } }, - "node_modules/strip-ansi": { + "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==", @@ -1113,11 +996,27 @@ "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" }, @@ -1125,6 +1024,15 @@ "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", @@ -1152,18 +1060,6 @@ "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", @@ -1177,6 +1073,7 @@ "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" }, @@ -1188,22 +1085,23 @@ } }, "node_modules/workerpool": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz", - "integrity": "sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==" + "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": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "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": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" }, "engines": { - "node": ">=10" + "node": ">=12" }, "funding": { "url": "https://github.com/chalk/wrap-ansi?sponsor=1" @@ -1214,6 +1112,7 @@ "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", @@ -1226,6 +1125,59 @@ "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", @@ -1242,29 +1194,30 @@ } }, "node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "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": "^7.0.2", + "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", - "string-width": "^4.2.0", + "string-width": "^4.2.3", "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" + "yargs-parser": "^21.1.1" }, "engines": { - "node": ">=10" + "node": ">=12" } }, "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==", + "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": ">=10" + "node": ">=12" } }, "node_modules/yargs-unparser": { @@ -1282,6 +1235,47 @@ "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", From 33f9b942babe5ffb06ad497640886893caa4c9be Mon Sep 17 00:00:00 2001 From: Erik Hetzner Date: Thu, 5 Feb 2026 21:58:43 -0800 Subject: [PATCH 14/29] syntax fix --- update.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/update.json b/update.json index 041c74d..bcbf5c5 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": { From b48d3e30e960e23b158033c3ec2096f7f3e6f21d Mon Sep 17 00:00:00 2001 From: Erik Hetzner Date: Thu, 5 Feb 2026 21:59:05 -0800 Subject: [PATCH 15/29] syntax fix --- update.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/update.json b/update.json index bcbf5c5..33bd56f 100644 --- a/update.json +++ b/update.json @@ -15,7 +15,7 @@ }, { "version": "7.0.2", - "update_link": "https://github.com/egh/zotxt/releases/download/v7.0.2/zotxt-7.0.2.xpi" + "update_link": "https://github.com/egh/zotxt/releases/download/v7.0.2/zotxt-7.0.2.xpi", "update_hash": "sha256:4a6dd04c197629a02a9c6beaa9ebd52a69bb683f8400243bcdf95847f0ee254a", "applications": { "gecko": { From 65b99c633a5449d8db2411366b69b2c1a61849bb Mon Sep 17 00:00:00 2001 From: Erik Hetzner Date: Thu, 5 Feb 2026 21:59:39 -0800 Subject: [PATCH 16/29] prettier --- .prettierignore | 2 + README.md | 3 +- extension/bootstrap.js | 463 ++-- extension/core.js | 116 +- .../resource/translators/EasyKeyExporter.js | 2055 ++++++++++++++++- package.json | 20 +- test/test.js | 350 +-- update.json | 3 +- 8 files changed, 2578 insertions(+), 434 deletions(-) create mode 100644 .prettierignore 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/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 933520d..2cd44fc 100644 --- a/extension/bootstrap.js +++ b/extension/bootstrap.js @@ -14,31 +14,31 @@ // 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'; +"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 + 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' + lastUpdated: "2013-07-15 07:03:17", }; } -const jsonMediaType = 'application/json; charset=UTF-8'; -const textMediaType = 'text/plain; charset=UTF-8'; +const jsonMediaType = "application/json; charset=UTF-8"; +const textMediaType = "text/plain; charset=UTF-8"; const badRequestCode = 400; const okCode = 200; @@ -81,7 +81,10 @@ function buildZoteroLink(item) { 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()); @@ -90,17 +93,17 @@ function collectionSearch(name) { return makeClientError(`collection ${name} not found`); } -function processCitationItem (citation) { - let cloneButSetId = (item)=>{ +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) { + if ("easyKey" in citation) { return findByEasyKey(citation.easyKey, Zotero).then(cloneButSetId); - } else if ('key' in citation) { + } else if ("key" in citation) { return findByKey(citation.key, Zotero).then(cloneButSetId); } else { return Promise.resolve(citation); @@ -110,12 +113,12 @@ function processCitationItem (citation) { /** * Map the easykeys in the citations to ids. */ -function processCitationsGroup (citationGroup) { +function processCitationsGroup(citationGroup) { let citationItems = citationGroup.citationItems.map(processCitationItem); - return Promise.all(citationItems).then((items)=>{ + return Promise.all(citationItems).then((items) => { return { - 'properties': citationGroup.properties, - 'citationItems': items + properties: citationGroup.properties, + citationItems: items, }; }); } @@ -123,17 +126,17 @@ function processCitationsGroup (citationGroup) { /** * 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) { +function myExport(items, translatorId) { let callback = function (resolve, reject) { let translation = new Zotero.Translate.Export(); translation.setItems(items); @@ -147,8 +150,8 @@ 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(); }; @@ -160,22 +163,26 @@ function myExport (items, translatorId) { * 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 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 === 'zoteroLink') { return [okCode, 'application/json', jsonStringify(items.map(buildZoteroLink))]; - } else if (format === 'betterbibtexkey' || format === 'citekey') { + } else if (format === "betterbibtexkey" || format === "citekey") { return buildBBTKeyResponse(items); - } else if (format === 'bibtex') { + } else if (format === "bibtex") { return buildBibTeXResponse(items); - } else if (format === 'bibliography') { + } else if (format === "bibliography") { return buildBibliographyResponse(items, style, locale); - } else if (format === 'quickBib') { + } else if (format === "quickBib") { return buildQuickBibResponse(items); - } else if (format === 'paths') { + } else if (format === "paths") { return buildPathsResponse(items, style); } else if (format && format.match(uuidRe)) { return buildExportResponse(items, format); @@ -188,9 +195,15 @@ function buildResponse(items, format, style, locale) { 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", + ); } } @@ -200,12 +213,14 @@ function buildJsonResponse(items) { */ function buildKeyResponse(items, translatorId) { if (items.length === 0) { - return [okCode, 'application/json', jsonStringify([])]; + return [okCode, "application/json", jsonStringify([])]; } else { - return myExport(items, translatorId).then((rawKeys)=>{ + return myExport(items, translatorId).then((rawKeys) => { let keys = rawKeys.split(/[ ,]/); // remove leading @ - let keys2 = keys.map(function(key) { return key.replace(/[\[\]@]/g, ''); }); + let keys2 = keys.map(function (key) { + return key.replace(/[\[\]@]/g, ""); + }); return [okCode, jsonMediaType, jsonStringify(keys2)]; }); } @@ -217,9 +232,9 @@ function buildEasyKeyResponse(items) { function buildBBTKeyResponse(items) { if (!Zotero.BetterBibTeX) { - return makeClientError('BetterBibTex not installed.'); + return makeClientError("BetterBibTex not installed."); } else { - return buildKeyResponse(items, 'a515a220-6fef-45ea-9842-8025dfebcc8f'); + return buildKeyResponse(items, "a515a220-6fef-45ea-9842-8025dfebcc8f"); } } @@ -230,20 +245,23 @@ function buildExportResponse(items, translatorId) { } 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)]; @@ -255,25 +273,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."; } @@ -282,102 +308,121 @@ function namesOrEtAl(names) { } function buildPathsResponse(items) { - let regularItems = items.filter((item)=>{ + let regularItems = items.filter((item) => { return item.isRegularItem(); }); - let itemsWithPaths = regularItems.map((item)=>{ - let attachments = item.getAttachments(false).map((attachmentId)=>{ + let itemsWithPaths = regularItems.map((item) => { + let attachments = item.getAttachments(false).map((attachmentId) => { return Zotero.Items.get(attachmentId); }); - return Zotero.Promise.filter(attachments, (attachment)=>{ + 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((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, + }; }); }); - }).then((paths)=>{ - return Promise.all(paths).then((paths)=>{ - return { 'key': ((item.libraryID || '0') + '_' + item.key), 'paths': paths }; - }); - }); }); - return Promise.all(itemsWithPaths).then((responseData)=>{ + return Promise.all(itemsWithPaths).then((responseData) => { return [okCode, jsonMediaType, jsonStringify(responseData)]; }); } function handleErrors(f) { - return (...args)=>{ - return f(...args).catch((ex)=>{ + 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))]; + return [500, textMediaType, ex && ex.message + ex.stack]; } }); }; } function bibliographyEndpoint(options) { - let cslEngine = makeCslEngine(options.data.styleId, options.data.locale, Zotero, 'html'); + let cslEngine = makeCslEngine( + options.data.styleId, + options.data.locale, + Zotero, + "html", + ); if (!cslEngine) { - return makeClientError('No style found.'); + return makeClientError("No style found."); } else { - cslEngine.setOutputFormat('html'); + cslEngine.setOutputFormat("html"); let groups = options.data.citationGroups.map(processCitationsGroup); - return Promise.all(groups).then((citationGroups)=>{ + return Promise.all(groups).then((citationGroups) => { 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)]; }); } } -function makeVersionEndpoint(version) { - return (options)=>{ - let retval = {"version": version}; +function makeVersionEndpoint(version) { + return (options) => { + let retval = { version: version }; return [okCode, jsonMediaType, jsonStringify(retval)]; - } + }; } function completeEndpoint(options) { - const easykey = options.searchParams.get('easykey'); + const easykey = options.searchParams.get("easykey"); if (!easykey) { - return makeClientError('Option easykey is required.'); + return makeClientError("Option easykey is required."); } else { - let search = buildEasyKeySearch(new Zotero.Search(), parseEasyKey(easykey, Zotero)); - return runSearch(search, Zotero).then((items)=>{ + 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'); + return makeClientError( + "EasyKey must be of the form DoeTitle2000 or doe:2000title", + ); } else { - return buildResponse(items, 'easykey'); + return buildResponse(items, "easykey"); } }); } } 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'); + 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) { @@ -385,22 +430,25 @@ function searchEndpoint(options) { } else if (library !== "all") { search.libraryID = library; } - return runSearch(search, Zotero).then((items)=>{ + return runSearch(search, Zotero).then((items) => { return buildResponse(items, format, style, locale); }); } else { - return makeClientError('q param required.'); + 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 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'); + 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) { @@ -408,56 +456,64 @@ function selectEndpoint(options) { } else if (betterbibtexkey || citekey) { promise = findByCitationKey(betterbibtexkey || citekey, Zotero); } else { - return makeClientError('No param supplied!'); + return makeClientError("No param supplied!"); } - return promise.then(function(item) { + return promise.then(function (item) { if (item === false) { - return makeClientError('item with key ' + key + ' not found!'); + return makeClientError("item with key " + key + " not found!"); } ZoteroPane.selectItem(item.id); - return [okCode, jsonMediaType, jsonStringify('success')]; + 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'); + 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); }; + let responder = (items) => { + return buildResponse(items, format, style, locale); + }; if (selected) { return responder(Zotero.getActiveZoteroPane().getSelectedItems()); } else if (key) { - let keys = key.split(','); + let keys = key.split(","); return Promise.all( - keys.map((key)=>{ + keys.map((key) => { return findByKey(key, Zotero); - })).then(responder); + }), + ).then(responder); } else if (easykey) { - let keys = easykey.split(','); + let keys = easykey.split(","); return Promise.all( keys.map((key) => { return findByEasyKey(key, Zotero); - })).then(responder); + }), + ).then(responder); } else if (betterbibtexkey || citekey) { - let keys = (betterbibtexkey ? betterbibtexkey.split(',') : citekey.split(',')); + 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); + }), + ).then(responder); + } else if (collection) return collectionSearch(collection).then(responder); else if (all) { - return Zotero.Items.getAll(Zotero.Libraries.userLibraryID).then(responder); + return Zotero.Items.getAll(Zotero.Libraries.userLibraryID).then( + responder, + ); } else { - return makeClientError('No param supplied!'); + return makeClientError("No param supplied!"); } } @@ -466,72 +522,73 @@ function stylesEndpoint(options) { } function localesEndpoint(options) { - return [okCode, jsonMediaType, jsonStringify(Zotero.Locale.availableLocales)]; + 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) { + 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 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() {} -function uninstall() { -} +function uninstall() {} -function install() { -} +function install() {} diff --git a/extension/core.js b/extension/core.js index 7bc9e4f..f7896df 100644 --- a/extension/core.js +++ b/extension/core.js @@ -3,15 +3,19 @@ * 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}+)?'); + 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]}; + 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]}; + return { creator: result[1], title: result[3], date: result[2] }; } else { return null; } @@ -20,9 +24,9 @@ function parseEasyKey(key, zotero) { function fixStyleId(styleId) { if (!styleId) { - return 'http://www.zotero.org/styles/chicago-notes-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,7 +38,7 @@ 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; } @@ -51,36 +55,44 @@ function dedupItems(items, zotero) { return true; } }); -}; +} function ensureLoaded(items, zotero) { - return zotero.Promise.map(items, (item)=>{ - return item.loadAllData().then(()=> { + return zotero.Promise.map(items, (item) => { + return item.loadAllData().then(() => { return item; }); }); } function item2key(item) { - return ((item.libraryID || '1') + '_' + item.key); + return (item.libraryID || "1") + "_" + item.key; } function findByKey(key, zotero) { - let rejectIfUndefined = (item)=>{ + let rejectIfUndefined = (item) => { if (!item) { return makeClientError(`${key} not found`); } else { return item; } }; - if (key.indexOf('/') !== -1) { + 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); + 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); } else { - return zotero.Items.getByLibraryAndKeyAsync(1, key).then(rejectIfUndefined); + return zotero.Items.getByLibraryAndKeyAsync(1, key).then( + rejectIfUndefined, + ); } } @@ -92,7 +104,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); @@ -121,18 +133,18 @@ function getItemOrParent(item, zotero) { 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) + 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); + let str = "@" + key; + s.addCondition("joinMode", "any"); + s.addCondition("tag", "is", str); + s.addCondition("note", "contains", str); return s; } @@ -141,36 +153,37 @@ function buildRawSearch(s, key) { */ function buildEasyKeySearch(s, parsedKey) { /* allow multiple names separated by _ */ - var splitName = parsedKey.creator.split('_'); + var splitName = parsedKey.creator.split("_"); for (let name of splitName) { - s.addCondition('creator', 'contains', name); + s.addCondition("creator", "contains", name); } if (parsedKey.title != null) { - s.addCondition('title', 'contains', parsedKey.title); + s.addCondition("title", "contains", parsedKey.title); } if (parsedKey.date != null) { - s.addCondition('date', 'is', parsedKey.date); + s.addCondition("date", "is", parsedKey.date); } return s; } 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.name = "ClientError"; this.message = message; - this.stack = (new Error()).stack; + this.stack = new Error().stack; } -ClientError.prototype = new Error; +ClientError.prototype = new Error(); function makeClientError(str) { return Promise.reject(new ClientError(str)); @@ -182,27 +195,36 @@ function makeClientError(str) { function findByEasyKey(key, zotero) { let parsedKey = parseEasyKey(key, zotero); if (!parsedKey) { - return makeClientError(`${key} must be of the form DoeTitle2000 or doe:2000title`); + 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) { + 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) { + 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; }); + 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`); + return makeClientError( + `${key} returned multiple items`, + ); } else { return makeClientError(`${key} had no results`); } @@ -214,18 +236,18 @@ function findByEasyKey(key, zotero) { 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; } function jsonStringify(json) { - return JSON.stringify(json, null, ' '); + return JSON.stringify(json, null, " "); } /* Exported for tests in nodejs */ -if (typeof module !== 'undefined') { +if (typeof module !== "undefined") { module.exports = { buildEasyKeySearch, buildRawSearch, @@ -241,6 +263,6 @@ if (typeof module !== 'undefined') { item2key, jsonStringify, makeCslEngine, - parseEasyKey - } + parseEasyKey, + }; } 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.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/test.js b/test/test.js index 51d1dc3..116b5f4 100644 --- a/test/test.js +++ b/test/test.js @@ -1,306 +1,352 @@ /* 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-notes-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/); + 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()', () => { +describe("#core.parseEasyKey()", () => { const zotero = { Utilities: { XRegExp: xregexp } }; const altRes = { - creator: 'foo', - date: '2016', - title: 'bar' + creator: "foo", + date: "2016", + title: "bar", }; const res = { - creator: 'Foo', - date: '2016', - title: 'Bar' + creator: "Foo", + date: "2016", + title: "Bar", }; - it('should parse an alternative easykey', ()=>{ - assert.deepEqual(altRes, core.parseEasyKey('foo:2016bar', zotero)); + 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 parse a normal easykey", () => { + assert.deepEqual(res, core.parseEasyKey("FooBar2016", zotero)); }); }); -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)=>{ + 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]); }); }); - 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", () => { + return core + .dedupItems(mkPromises(item1, item1), zotero) + .then((items) => { + 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", () => { + 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]); + }); }); }); -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", () => { 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", () => { const isRegularItem = sinon.stub().returns(false); const parentKey = undefined; const item = { isRegularItem, parentKey }; assert.equal(item, 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", () => { + 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); }); + core.getItemOrParent(item, zotero).then((item) => { + assert.equal(retval, item); + }); }); }); -describe('#core.buildSearch()', () => { +describe("#core.buildSearch()", () => { let addCondition, search; - beforeEach(()=>{ + 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'); + 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()', () => { +describe("#core.buildRawSearch()", () => { let addCondition, search; - beforeEach(()=>{ + 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'); + 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", + ); }); }); - -describe('#core.buildEasyKeySearch()', () => { +describe("#core.buildEasyKeySearch()", () => { 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); + 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'); + 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); + 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'); + 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); + 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.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); + 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.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); + 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.calledWith(addCondition, "creator", "contains", "foo"); sinon.assert.calledOnce(addCondition); }); }); diff --git a/update.json b/update.json index 33bd56f..5c2a70f 100644 --- a/update.json +++ b/update.json @@ -22,11 +22,10 @@ "strict_min_version": "60.9", "strict_max_version": "60.9" }, - "zotero": { + "zotero": { "strict_min_version": "6.999", "strict_max_version": "7.0.*" } - } } ] From 208a77d1e68d6b059894ae9755fb03ad146b7d25 Mon Sep 17 00:00:00 2001 From: Erik Hetzner Date: Thu, 5 Feb 2026 23:41:10 -0800 Subject: [PATCH 17/29] upgrade for zotero 8 --- Makefile | 2 +- extension/bootstrap.js | 603 ++++++++++++++++++++------------------ extension/chrome.manifest | 1 - extension/core.js | 65 ++-- extension/manifest.json | 4 +- test/test.js | 58 ++-- test/test.rb | 2 +- 7 files changed, 381 insertions(+), 354 deletions(-) delete mode 100644 extension/chrome.manifest diff --git a/Makefile b/Makefile index 4916595..8f317d4 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ dist: test 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: diff --git a/extension/bootstrap.js b/extension/bootstrap.js index 2cd44fc..ab6e7a4 100644 --- a/extension/bootstrap.js +++ b/extension/bootstrap.js @@ -13,7 +13,7 @@ // 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 */ +/* global Components, Set, FileUtils, NetUtil, Q, parseEasyKey, runSearch, buildRawSearch, buildEasyKeySearch, findByKey, cleanQuery, buildSearch, makeCslEngine, findByEasyKey, findByCitationKey, jsonStringify, item2key, ClientError, ensureLoaded */ "use strict"; var uuidRe = /^[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12}/; @@ -87,13 +87,13 @@ function collectionSearch(name) { ); 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) { +async function processCitationItem(citation) { let cloneButSetId = (item) => { let retval = Object.assign({}, citation); retval.id = item.id; @@ -102,25 +102,26 @@ function processCitationItem(citation) { return retval; }; if ("easyKey" in citation) { - return findByEasyKey(citation.easyKey, Zotero).then(cloneButSetId); + const item = await findByEasyKey(citation.easyKey, Zotero); + return cloneButSetId(item); } else if ("key" in citation) { - return findByKey(citation.key, Zotero).then(cloneButSetId); + 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, + }; } /** @@ -137,7 +138,7 @@ function extractIds(citationGroups) { } function myExport(items, translatorId) { - let callback = function (resolve, reject) { + return new Promise((resolve, reject) => { let translation = new Zotero.Translate.Export(); translation.setItems(items); translation.setTranslator(translatorId); @@ -154,42 +155,35 @@ function myExport(items, translatorId) { 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 === 'zoteroLink') { - return [okCode, 'application/json', jsonStringify(items.map(buildZoteroLink))]; - } 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 === "easykey") { + return buildEasyKeyResponse(items); + } 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) { @@ -211,19 +205,17 @@ 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)]; - }); } + 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 buildEasyKeyResponse(items) { @@ -232,16 +224,15 @@ function buildEasyKeyResponse(items) { function buildBBTKeyResponse(items) { if (!Zotero.BetterBibTeX) { - return makeClientError("BetterBibTex not installed."); + throw new ClientError("BetterBibTex not installed."); } else { 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) { @@ -307,71 +298,126 @@ function namesOrEtAl(names) { } } -function buildPathsResponse(items) { +async function buildPathsResponse(items) { let regularItems = items.filter((item) => { return item.isRegularItem(); }); - let itemsWithPaths = regularItems.map((item) => { + 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"]; + + async 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 easykey = request.searchParams.get("easykey"); + if (!easykey) { + throw new ClientError("Option easykey is required."); } - }); - }; + + let search = buildEasyKeySearch( + new Zotero.Search(), + parseEasyKey(easykey, Zotero), + ); + const items = await runSearch(search, Zotero); + + if (!items) { + throw new ClientError( + "EasyKey must be of the form DoeTitle2000 or doe:2000title", + ); + } + return buildResponse(items, "easykey"); + } 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(); @@ -384,201 +430,183 @@ function bibliographyEndpoint(options) { }); }); 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 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 easykey = request.searchParams.get("easykey"); + const key = request.searchParams.get("key"); + const betterbibtexkey = request.searchParams.get("betterbibtexkey"); + const citekey = request.searchParams.get("citekey"); + + let item; + if (easykey) { + item = await findByEasyKey(easykey, Zotero); + } else 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 easykey = request.searchParams.get("easykey"); + 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 (easykey) { + let keys = easykey.split(","); + items = await Promise.all( + keys.map((key) => { + return findByEasyKey(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 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]; - } + // 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 }) { @@ -587,7 +615,14 @@ function startup({ id, version, resourceURI, rootURI = resourceURI.spec }) { 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() {} 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 f7896df..b6b1436 100644 --- a/extension/core.js +++ b/extension/core.js @@ -45,24 +45,27 @@ function cleanQuery(q) { /* 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) { @@ -72,7 +75,7 @@ function item2key(item) { function findByKey(key, zotero) { let rejectIfUndefined = (item) => { if (!item) { - return makeClientError(`${key} not found`); + throw new ClientError(`${key} not found`); } else { return item; } @@ -131,11 +134,13 @@ 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 s.search().then(async (ids) => { + let items = await zotero.Items.getAsync(ids); + let items2 = await Promise.all( + items.map((item) => { + return getItemOrParent(item, zotero); + }), + ); return dedupItems(items2, zotero); }); } @@ -177,16 +182,11 @@ function buildSearch(s, query, method) { 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)); +class ClientError extends Error { + constructor(message) { + super(message); + this.name = "ClientError"; + } } /** @@ -195,7 +195,7 @@ function makeClientError(str) { function findByEasyKey(key, zotero) { let parsedKey = parseEasyKey(key, zotero); if (!parsedKey) { - return makeClientError( + throw new ClientError( `${key} must be of the form DoeTitle2000 or doe:2000title`, ); } else { @@ -205,7 +205,7 @@ function findByEasyKey(key, zotero) { if (items.length === 1) { return items[0]; } else if (items.length > 1) { - return makeClientError(`${key} returned multiple items`); + throw new ClientError(`${key} returned multiple items`); } else { let search = buildEasyKeySearch(new zotero.Search(), parsedKey); return runSearch(search, zotero).then(function (items) { @@ -222,11 +222,9 @@ function findByEasyKey(key, zotero) { if (items.length === 1) { return items[0]; } else if (items.length > 1) { - return makeClientError( - `${key} returned multiple items`, - ); + throw new ClientError(`${key} returned multiple items`); } else { - return makeClientError(`${key} had no results`); + throw new ClientError(`${key} had no results`); } }); } @@ -264,5 +262,6 @@ if (typeof module !== "undefined") { jsonStringify, makeCslEngine, parseEasyKey, + ClientError, }; } diff --git a/extension/manifest.json b/extension/manifest.json index 1648d9e..5ae31d1 100644 --- a/extension/manifest.json +++ b/extension/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 2, "name": "zotxt", - "version": "7.0.2", + "version": "8.0.0", "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.*" + "strict_max_version": "8.*" } } } diff --git a/test/test.js b/test/test.js index 116b5f4..3fd6da5 100644 --- a/test/test.js +++ b/test/test.js @@ -86,31 +86,27 @@ describe("#core.dedupItems()", () => { 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]); - }); - }); - - 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 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 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", 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", 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]); }); }); @@ -203,20 +199,20 @@ describe("#core.makeCslEngine()", () => { }); describe("#core.getItemOrParent()", () => { - it("returns item when item is a regularItem", () => { + 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", () => { + 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"; @@ -226,9 +222,7 @@ describe("#core.getItemOrParent()", () => { .returns(Promise.resolve(retval)); const Items = { getByLibraryAndKeyAsync }; const zotero = { Items }; - core.getItemOrParent(item, zotero).then((item) => { - assert.equal(retval, item); - }); + assert.equal(retval, await core.getItemOrParent(item, zotero)); }); }); diff --git a/test/test.rb b/test/test.rb index 0893bac..e76f889 100644 --- a/test/test.rb +++ b/test/test.rb @@ -544,7 +544,7 @@ def test_select 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 From e776b7ff8a0eb14cf82510b0aa255f19152240a7 Mon Sep 17 00:00:00 2001 From: Erik Hetzner Date: Fri, 6 Feb 2026 11:30:59 -0800 Subject: [PATCH 18/29] support bbt key completion --- extension/bootstrap.js | 37 +++++++++++++++---------------------- extension/core.js | 22 ++++++++++++++++++++++ test/test.rb | 10 +++++++++- 3 files changed, 46 insertions(+), 23 deletions(-) diff --git a/extension/bootstrap.js b/extension/bootstrap.js index ab6e7a4..d56da70 100644 --- a/extension/bootstrap.js +++ b/extension/bootstrap.js @@ -13,7 +13,7 @@ // 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, ClientError, ensureLoaded */ +/* global Components, Set, FileUtils, NetUtil, Q, parseEasyKey, runSearch, buildRawSearch, buildEasyKeySearch, findByKey, cleanQuery, buildSearch, makeCslEngine, findByEasyKey, findByCitationKey, searchByCitationKeyPrefix, jsonStringify, item2key, ClientError, ensureLoaded, checkBBT */ "use strict"; var uuidRe = /^[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12}/; @@ -223,11 +223,8 @@ function buildEasyKeyResponse(items) { } function buildBBTKeyResponse(items) { - if (!Zotero.BetterBibTeX) { - throw new ClientError("BetterBibTex not installed."); - } else { - return buildKeyResponse(items, "a515a220-6fef-45ea-9842-8025dfebcc8f"); - } + checkBBT(); + return buildKeyResponse(items, "a515a220-6fef-45ea-9842-8025dfebcc8f"); } async function buildExportResponse(items, translatorId) { @@ -353,7 +350,7 @@ class VersionEndpoint { supportedMethods = ["GET"]; supportedDataTypes = ["application/x-www-form-urlencoded"]; - async init(request) { + init(request) { try { return [ okCode, @@ -372,23 +369,19 @@ class CompleteEndpoint { async init(request) { try { - const easykey = request.searchParams.get("easykey"); - if (!easykey) { - throw new ClientError("Option easykey is required."); + const prefix = request.searchParams.get("prefix"); + if (!prefix) { + throw new ClientError("Option prefix is required."); } - let search = buildEasyKeySearch( - new Zotero.Search(), - parseEasyKey(easykey, Zotero), - ); - const items = await runSearch(search, Zotero); - - if (!items) { - throw new ClientError( - "EasyKey must be of the form DoeTitle2000 or doe:2000title", - ); - } - return buildResponse(items, "easykey"); + const items = await searchByCitationKeyPrefix(prefix, Zotero); + return [ + okCode, + jsonMediaType, + jsonStringify( + items.map((item) => item.getField("citationKey")), + ), + ]; } catch (ex) { return handleEndpointError(ex); } diff --git a/extension/core.js b/extension/core.js index b6b1436..d3bafaa 100644 --- a/extension/core.js +++ b/extension/core.js @@ -240,16 +240,37 @@ async function findByCitationKey(citekey, zotero) { 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, " "); } +function checkBBT() { + if (!Zotero.BetterBibTeX) { + throw new ClientError("BetterBibTex not installed."); + } +} + /* Exported for tests in nodejs */ if (typeof module !== "undefined") { module.exports = { buildEasyKeySearch, buildRawSearch, buildSearch, + checkBBT, checkStyleId, cleanQuery, dedupItems, @@ -262,6 +283,7 @@ if (typeof module !== "undefined") { jsonStringify, makeCslEngine, parseEasyKey, + searchByCitationKeyPrefix, ClientError, }; } diff --git a/test/test.rb b/test/test.rb index e76f889..c845ad1 100644 --- a/test/test.rb +++ b/test/test.rb @@ -508,6 +508,14 @@ def test_completion assert_equal ["doe:2006article"], results end + def test_citationkey_prefix_completion + resp = @client.get(@complete_url, { "prefix" => "doe" }) + assert_equal 200, resp.status + results = JSON.parse(resp.body) + assert results.is_a?(Array) + assert results.all? { |key| key.start_with?("doe") } + end + def test_search resp = @client.get(@search_url, { "q" => "doe article", "format" => "key" }) assert_equal 200, resp.status @@ -557,7 +565,7 @@ 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"] From cdfcc12e5b2f5220669339ac630cbdd9401aef41 Mon Sep 17 00:00:00 2001 From: Erik Hetzner Date: Fri, 6 Feb 2026 11:45:20 -0800 Subject: [PATCH 19/29] drop easykey --- extension/bootstrap.js | 40 +----- extension/core.js | 97 -------------- test/test.js | 91 ------------- test/test.rb | 285 ----------------------------------------- 4 files changed, 2 insertions(+), 511 deletions(-) diff --git a/extension/bootstrap.js b/extension/bootstrap.js index d56da70..5fa7efb 100644 --- a/extension/bootstrap.js +++ b/extension/bootstrap.js @@ -13,30 +13,11 @@ // 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, searchByCitationKeyPrefix, jsonStringify, item2key, ClientError, ensureLoaded, checkBBT */ +/* 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; @@ -165,8 +146,6 @@ 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 === "easykey") { - return buildEasyKeyResponse(items); } else if (format === "betterbibtexkey" || format === "citekey") { return buildBBTKeyResponse(items); } else if (format === "bibtex") { @@ -218,10 +197,6 @@ async function buildKeyResponse(items, translatorId) { return [okCode, jsonMediaType, jsonStringify(keys2)]; } -function buildEasyKeyResponse(items) { - return buildKeyResponse(items, makeEasyKeyExporterMetadata().translatorID); -} - function buildBBTKeyResponse(items) { checkBBT(); return buildKeyResponse(items, "a515a220-6fef-45ea-9842-8025dfebcc8f"); @@ -470,15 +445,12 @@ class SelectEndpoint { ] .getService(Components.interfaces.nsIWindowMediator) .getMostRecentWindow("navigator:browser").ZoteroPane; - const easykey = request.searchParams.get("easykey"); const key = request.searchParams.get("key"); const betterbibtexkey = request.searchParams.get("betterbibtexkey"); const citekey = request.searchParams.get("citekey"); let item; - if (easykey) { - item = await findByEasyKey(easykey, Zotero); - } else if (key) { + if (key) { item = await findByKey(key, Zotero); } else if (betterbibtexkey || citekey) { item = await findByCitationKey( @@ -507,7 +479,6 @@ class ItemsEndpoint { async init(request) { try { const selected = request.searchParams.get("selected"); - const easykey = request.searchParams.get("easykey"); const key = request.searchParams.get("key"); const betterbibtexkey = request.searchParams.get("betterbibtexkey"); const citekey = request.searchParams.get("citekey"); @@ -527,13 +498,6 @@ class ItemsEndpoint { return findByKey(key, Zotero); }), ); - } else if (easykey) { - let keys = easykey.split(","); - items = await Promise.all( - keys.map((key) => { - return findByEasyKey(key, Zotero); - }), - ); } else if (betterbibtexkey || citekey) { let keys = betterbibtexkey ? betterbibtexkey.split(",") diff --git a/extension/core.js b/extension/core.js index d3bafaa..0f68c75 100644 --- a/extension/core.js +++ b/extension/core.js @@ -1,27 +1,3 @@ -/** - * 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-notes-bibliography"; @@ -145,32 +121,6 @@ function runSearch(s, 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; -} - function buildSearch(s, query, method) { if (!method) { method = "titleCreatorYear"; @@ -189,49 +139,6 @@ class ClientError extends Error { } } -/** - * Find a single item by its easy key, caching the result. - */ -function findByEasyKey(key, zotero) { - let parsedKey = parseEasyKey(key, zotero); - if (!parsedKey) { - throw new ClientError( - `${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) { - throw new ClientError(`${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) { - throw new ClientError(`${key} returned multiple items`); - } else { - throw new ClientError(`${key} had no results`); - } - }); - } - }); - } -} - async function findByCitationKey(citekey, zotero) { const search = new zotero.Search(); search.addCondition("libraryID", "is", zotero.Libraries.userLibraryID); @@ -267,22 +174,18 @@ function checkBBT() { /* Exported for tests in nodejs */ 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/test/test.js b/test/test.js index 3fd6da5..49f4406 100644 --- a/test/test.js +++ b/test/test.js @@ -46,29 +46,6 @@ describe("#core.checkStyleId()", () => { }); }); -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)); - }); -}); - describe("#core.cleanQuery()", () => { it("should replace all + with space", () => { assert.deepEqual( @@ -276,71 +253,3 @@ describe("#core.buildSearch()", () => { }); }); -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", - ); - }); -}); - -describe("#core.buildEasyKeySearch()", () => { - let addCondition, search; - const zotero = { Utilities: { XRegExp: xregexp } }; - - 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); - }); -}); diff --git a/test/test.rb b/test/test.rb index c845ad1..eddf968 100644 --- a/test/test.rb +++ b/test/test.rb @@ -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-notes-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 }) @@ -489,25 +227,6 @@ def test_format_json "issued" => { "date-parts" => [["2006"]] } }, 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" }) - results = JSON.parse(resp.body) - assert_equal ["doe:2006article"], results - end - def test_citationkey_prefix_completion resp = @client.get(@complete_url, { "prefix" => "doe" }) assert_equal 200, resp.status @@ -540,13 +259,9 @@ 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 From e05f164f6d747a9711a5ae6e15ecaf8c7fcffaea Mon Sep 17 00:00:00 2001 From: Erik Hetzner Date: Fri, 6 Feb 2026 11:45:40 -0800 Subject: [PATCH 20/29] makefile updates --- Makefile | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 8f317d4..11a66e5 100644 --- a/Makefile +++ b/Makefile @@ -2,9 +2,7 @@ VERSION=$(shell jq .version extension/manifest.json -r) -dist: test zotxt-$(VERSION).xpi ; - -notest: zotxt-$(VERSION).xpi ; +dist: unittest zotxt-$(VERSION).xpi ; zotxt-$(VERSION).xpi: extension/*.js extension/manifest.json extension/resource/translators/EasyKeyExporter.js cd extension && zip -r ../zotxt-$(VERSION).xpi * @@ -17,3 +15,7 @@ unittest: test: unittest cd test && ruby test.rb + +format: + prettier -w . + rufo . From d6a2af524ee1074c91a798cb4527aa8b88ba9e9f Mon Sep 17 00:00:00 2001 From: Erik Hetzner Date: Fri, 6 Feb 2026 11:49:02 -0800 Subject: [PATCH 21/29] lint --- test/test.js | 1 - 1 file changed, 1 deletion(-) diff --git a/test/test.js b/test/test.js index 49f4406..0481a18 100644 --- a/test/test.js +++ b/test/test.js @@ -252,4 +252,3 @@ describe("#core.buildSearch()", () => { ); }); }); - From 5baf6d13b47914d48eca62f56236552b6c70fc98 Mon Sep 17 00:00:00 2001 From: Erik Hetzner Date: Fri, 6 Feb 2026 11:51:23 -0800 Subject: [PATCH 22/29] fix test --- test/test.rb | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/test/test.rb b/test/test.rb index eddf968..ff48a1c 100644 --- a/test/test.rb +++ b/test/test.rb @@ -217,14 +217,15 @@ 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_citationkey_prefix_completion From 1b7a36a13f07a665aedb1464c995a0e8466818b8 Mon Sep 17 00:00:00 2001 From: Erik Hetzner Date: Fri, 6 Feb 2026 11:59:47 -0800 Subject: [PATCH 23/29] fix findByKey --- extension/core.js | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/extension/core.js b/extension/core.js index 0f68c75..93cb383 100644 --- a/extension/core.js +++ b/extension/core.js @@ -48,30 +48,27 @@ function item2key(item) { return (item.libraryID || "1") + "_" + item.key; } -function findByKey(key, zotero) { - let rejectIfUndefined = (item) => { - if (!item) { - throw new ClientError(`${key} not found`); - } else { - return item; - } - }; +async function findByKey(key, zotero) { + let item; if (key.indexOf("/") !== -1) { let lkh = zotero.Items.parseLibraryKey(key); - return zotero.Items.getByLibraryAndKeyAsync( + item = await zotero.Items.getByLibraryAndKeyAsync( lkh.libraryID, lkh.key, - ).then(rejectIfUndefined); + ); } else if (key.indexOf("_") !== -1) { let [libraryId, key2] = key.split("_"); - return zotero.Items.getByLibraryAndKeyAsync( + item = await zotero.Items.getByLibraryAndKeyAsync( parseInt(libraryId), key2, - ).then(rejectIfUndefined); - } else { - return zotero.Items.getByLibraryAndKeyAsync(1, key).then( - rejectIfUndefined, ); + } else { + item = await zotero.Items.getByLibraryAndKeyAsync(1, key); + } + if (!item) { + throw new ClientError(`${key} not found`); + } else { + return item; } } From f1b516b9d702accaf7c206f411fb65300b8b00ff Mon Sep 17 00:00:00 2001 From: Erik Hetzner Date: Fri, 6 Feb 2026 12:15:19 -0800 Subject: [PATCH 24/29] fix style check --- extension/bootstrap.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extension/bootstrap.js b/extension/bootstrap.js index 5fa7efb..543c268 100644 --- a/extension/bootstrap.js +++ b/extension/bootstrap.js @@ -427,7 +427,7 @@ class SearchEndpoint { search.libraryID = library; } const items = await runSearch(search, Zotero); - return buildResponse(items, format, style, locale); + return await buildResponse(items, format, style, locale); } catch (ex) { return handleEndpointError(ex); } @@ -517,7 +517,7 @@ class ItemsEndpoint { throw new ClientError("No param supplied!"); } - return buildResponse(items, format, style, locale); + return await buildResponse(items, format, style, locale); } catch (ex) { return handleEndpointError(ex); } From db3f339d9aedb562a5e580b428a045c830f6bd6d Mon Sep 17 00:00:00 2001 From: Erik Hetzner Date: Fri, 6 Feb 2026 12:16:17 -0800 Subject: [PATCH 25/29] improve async code --- extension/core.js | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/extension/core.js b/extension/core.js index 93cb383..ec4cff0 100644 --- a/extension/core.js +++ b/extension/core.js @@ -103,19 +103,15 @@ function getItemOrParent(item, zotero) { } } -/** - * Returns a promise resolving to an iterable. - */ -function runSearch(s, zotero) { - return s.search().then(async (ids) => { - let items = await zotero.Items.getAsync(ids); - let items2 = await Promise.all( - items.map((item) => { - return getItemOrParent(item, zotero); - }), - ); - return dedupItems(items2, zotero); - }); +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) { From 785d90f158094a822f901f5fec70efd9c8919e9d Mon Sep 17 00:00:00 2001 From: Erik Hetzner Date: Fri, 6 Feb 2026 12:16:26 -0800 Subject: [PATCH 26/29] fix test --- test/test.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test.rb b/test/test.rb index ff48a1c..e74e22a 100644 --- a/test/test.rb +++ b/test/test.rb @@ -283,7 +283,7 @@ def test_styles style = JSON.parse(resp.body).find do |value| 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 From 6ff6d94159f2bfe0c310a5bd49fa4ebbbd7fab9b Mon Sep 17 00:00:00 2001 From: Erik Hetzner Date: Fri, 6 Feb 2026 12:21:40 -0800 Subject: [PATCH 27/29] capitalize --- extension/core.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extension/core.js b/extension/core.js index ec4cff0..e75f9ae 100644 --- a/extension/core.js +++ b/extension/core.js @@ -160,7 +160,7 @@ function jsonStringify(json) { function checkBBT() { if (!Zotero.BetterBibTeX) { - throw new ClientError("BetterBibTex not installed."); + throw new ClientError("BetterBibTeX not installed."); } } From 3ca6004f4e4dff6f8add83a1ba8cbd5d26afd8b8 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 25 Feb 2026 07:52:30 +0000 Subject: [PATCH 28/29] Bump minimatch from 9.0.5 to 9.0.7 Bumps [minimatch](https://github.com/isaacs/minimatch) from 9.0.5 to 9.0.7. - [Changelog](https://github.com/isaacs/minimatch/blob/main/changelog.md) - [Commits](https://github.com/isaacs/minimatch/compare/v9.0.5...v9.0.7) --- updated-dependencies: - dependency-name: minimatch dependency-version: 9.0.7 dependency-type: indirect ... Signed-off-by: dependabot[bot] --- package-lock.json | 2582 +++++++++++++++++++++++---------------------- 1 file changed, 1294 insertions(+), 1288 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3fe0590..5306283 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,1292 +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==", - "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": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "license": "MIT" - }, - "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.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "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.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "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" - } + "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" + } } + } } From 8048f8a6c4c12f8d954bac6fe6dfa3f31795e27d Mon Sep 17 00:00:00 2001 From: Trenton Schulz Date: Thu, 7 May 2026 16:53:48 +0200 Subject: [PATCH 29/29] Merge. --- extension/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extension/manifest.json b/extension/manifest.json index 5ae31d1..b6b4670 100644 --- a/extension/manifest.json +++ b/extension/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 2, "name": "zotxt", - "version": "8.0.0", + "version": "8.0.0.1", "description": "Plain text extensions for Zotero", "author": "Erik Hetzner", "applications": {