From 7ebde9b9649d3fb3aeb579ed52f7e1a33ee5f73f Mon Sep 17 00:00:00 2001 From: MarvNC Date: Thu, 11 Jul 2024 14:45:51 -0700 Subject: [PATCH 01/26] Refactor files --- src/convertWikipedia.js | 17 ++++++----------- src/{ => parse}/parseLine.js | 0 src/{ => parse}/readingParse.js | 0 src/{test.js => parse/readingParse.test.js} | 2 +- src/util/getVersion.js | 8 ++++++++ 5 files changed, 15 insertions(+), 12 deletions(-) rename src/{ => parse}/parseLine.js (100%) rename src/{ => parse}/readingParse.js (100%) rename src/{test.js => parse/readingParse.test.js} (99%) create mode 100644 src/util/getVersion.js diff --git a/src/convertWikipedia.js b/src/convertWikipedia.js index 6122ab6..e263aa2 100644 --- a/src/convertWikipedia.js +++ b/src/convertWikipedia.js @@ -5,6 +5,7 @@ import { Dictionary, TermEntry } from 'yomichan-dict-builder'; import { parseLine } from './parseLine.js'; import { languagesAllowed } from './constants.js'; +import { getVersion } from './util/getVersion.js'; const linkCharacter = '⧉'; /** @@ -80,7 +81,7 @@ div.gloss-sc-div[data-sc-wikipedia=term-specifier] { function processLine(line, dict, lang) { const { term, termSlug, termSpecifier, reading, definition } = parseLine( line, - lang, + lang ); const termEntry = new TermEntry(term); @@ -132,8 +133,8 @@ function processLine(line, dict, lang) { lang === languagesAllowed.ja ? '続きを読む' : lang === languagesAllowed.zh - ? '查看更多' - : 'Read more'; + ? '查看更多' + : 'Read more'; /** * @type {import('yomichan-dict-builder/dist/types/yomitan/termbank').StructuredContentNode} */ @@ -175,8 +176,8 @@ function readArgs() { if (!languagesAllowed[langInput.toLowerCase()]) { throw new Error( `Language ${langInput} is not allowed. Allowed languages: ${Object.keys( - languagesAllowed, - ).join(', ')}`, + languagesAllowed + ).join(', ')}` ); } @@ -189,9 +190,3 @@ function readArgs() { } return { lang, date: dateInput }; } - -function getVersion() { - const packageJsonPath = path.join(process.cwd(), 'package.json'); - const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8')); - return packageJson.version; -} diff --git a/src/parseLine.js b/src/parse/parseLine.js similarity index 100% rename from src/parseLine.js rename to src/parse/parseLine.js diff --git a/src/readingParse.js b/src/parse/readingParse.js similarity index 100% rename from src/readingParse.js rename to src/parse/readingParse.js diff --git a/src/test.js b/src/parse/readingParse.test.js similarity index 99% rename from src/test.js rename to src/parse/readingParse.test.js index 2fa8781..3db8af0 100644 --- a/src/test.js +++ b/src/parse/readingParse.test.js @@ -2,7 +2,7 @@ import test from 'ava'; import { parseLine } from './parseLine.js'; -import { languagesAllowed } from './constants.js'; +import { languagesAllowed } from '../constants.js'; /** * @typedef {Object} TestCase diff --git a/src/util/getVersion.js b/src/util/getVersion.js new file mode 100644 index 0000000..eebb130 --- /dev/null +++ b/src/util/getVersion.js @@ -0,0 +1,8 @@ +import fs from 'fs'; +import path from 'path'; + +export function getVersion() { + const packageJsonPath = path.join(process.cwd(), 'package.json'); + const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8')); + return packageJson.version; +} From 910dc8169b96c39dbcfe937145020d41c561c98e Mon Sep 17 00:00:00 2001 From: MarvNC Date: Thu, 11 Jul 2024 14:50:04 -0700 Subject: [PATCH 02/26] Init bun --- bun.lockb | Bin 0 -> 76326 bytes package-lock.json | 2271 --------------------------------------------- package.json | 9 +- tsconfig.json | 27 + 4 files changed, 34 insertions(+), 2273 deletions(-) create mode 100644 bun.lockb delete mode 100644 package-lock.json create mode 100644 tsconfig.json diff --git a/bun.lockb b/bun.lockb new file mode 100644 index 0000000000000000000000000000000000000000..d9741afed4b5a3b4c84f778fe8f8285ea6dc5077 GIT binary patch literal 76326 zcmeF3c{oETe5+X8>C7Ci4%9JTG&+|NmiYQZslw>Gl#>!BXnMj6A4W^

S~z+# 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 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@rollup/pluginutils": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.2.1.tgz", - "integrity": "sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==", - "dev": true, - "dependencies": { - "estree-walker": "^2.0.1", - "picomatch": "^2.2.2" - }, - "engines": { - "node": ">= 8.0.0" - } - }, - "node_modules/@rollup/pluginutils/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/@sindresorhus/merge-streams": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-1.0.0.tgz", - "integrity": "sha512-rUV5WyJrJLoloD4NDN1V1+LDMDWOa4OTsT4yYJwQNpTU6FWxkxHpL7eu4w+DmiH8x/EAM1otkPE1+LaspIbplw==", - "dev": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@vercel/nft": { - "version": "0.24.4", - "resolved": "https://registry.npmjs.org/@vercel/nft/-/nft-0.24.4.tgz", - "integrity": "sha512-KjYAZty7boH5fi5udp6p+lNu6nawgs++pHW+3koErMgbRkkHuToGX/FwjN5clV1FcaM3udfd4zW/sUapkMgpZw==", - "dev": true, - "dependencies": { - "@mapbox/node-pre-gyp": "^1.0.5", - "@rollup/pluginutils": "^4.0.0", - "acorn": "^8.6.0", - "async-sema": "^3.1.1", - "bindings": "^1.4.0", - "estree-walker": "2.0.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "micromatch": "^4.0.2", - "node-gyp-build": "^4.2.2", - "resolve-from": "^5.0.0" - }, - "bin": { - "nft": "out/cli.js" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true - }, - "node_modules/acorn": { - "version": "8.11.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz", - "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-walk": { - "version": "8.3.1", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.1.tgz", - "integrity": "sha512-TgUZgYvqZprrl7YldZNoa9OciCAyZR+Ejm9eXzKCmjsF5IKp/wgQ7Z/ZpjpGTIUPwrHQIcYeI8qDh4PsEwxMbw==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dev": true, - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "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==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/aproba": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", - "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", - "dev": true - }, - "node_modules/are-we-there-yet": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", - "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", - "dev": true, - "dependencies": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/are-we-there-yet/node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/array-find-index": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", - "integrity": "sha512-M1HQyIXcBGtVywBt8WVdim+lrNaK7VHp99Qt5pSNziXznKHViIBbXWtfRTpEFpF/c4FdfxNAsCCwPp5phBYJtw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/arrgv": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/arrgv/-/arrgv-1.0.2.tgz", - "integrity": "sha512-a4eg4yhp7mmruZDQFqVMlxNRFGi/i1r87pt8SDHy0/I8PqSXoUTlWZRdAZo0VXgvEARcujbtTk8kiZRi1uDGRw==", - "dev": true, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/arrify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-3.0.0.tgz", - "integrity": "sha512-tLkvA81vQG/XqE2mjDkGQHoOINtMHtysSnemrmoGe6PydDPMRbVugqyk4A6V/WDWEfm3l+0d8anA9r8cv/5Jaw==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/async-sema": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/async-sema/-/async-sema-3.1.1.tgz", - "integrity": "sha512-tLRNUXati5MFePdAk8dw7Qt7DpxPB60ofAgn8WRhW6a2rcimZnYBP9oxHiv0OHy+Wz7kPMG+t4LGdt31+4EmGg==", - "dev": true - }, - "node_modules/ava": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ava/-/ava-6.0.1.tgz", - "integrity": "sha512-9zR0wOwlcJdOWwHOKnpi0GrPRLTlxDFapGalP4rGD0oQRKxDVoucBBWvxVQ/2cPv10Hx1PkDXLJH5iUzhPn0/g==", - "dev": true, - "dependencies": { - "@vercel/nft": "^0.24.4", - "acorn": "^8.11.2", - "acorn-walk": "^8.3.0", - "ansi-styles": "^6.2.1", - "arrgv": "^1.0.2", - "arrify": "^3.0.0", - "callsites": "^4.1.0", - "cbor": "^9.0.1", - "chalk": "^5.3.0", - "chunkd": "^2.0.1", - "ci-info": "^4.0.0", - "ci-parallel-vars": "^1.0.1", - "cli-truncate": "^4.0.0", - "code-excerpt": "^4.0.0", - "common-path-prefix": "^3.0.0", - "concordance": "^5.0.4", - "currently-unhandled": "^0.4.1", - "debug": "^4.3.4", - "emittery": "^1.0.1", - "figures": "^6.0.1", - "globby": "^14.0.0", - "ignore-by-default": "^2.1.0", - "indent-string": "^5.0.0", - "is-plain-object": "^5.0.0", - "is-promise": "^4.0.0", - "matcher": "^5.0.0", - "memoize": "^10.0.0", - "ms": "^2.1.3", - "p-map": "^6.0.0", - "package-config": "^5.0.0", - "picomatch": "^3.0.1", - "plur": "^5.1.0", - "pretty-ms": "^8.0.0", - "resolve-cwd": "^3.0.0", - "stack-utils": "^2.0.6", - "strip-ansi": "^7.1.0", - "supertap": "^3.0.1", - "temp-dir": "^3.0.0", - "write-file-atomic": "^5.0.1", - "yargs": "^17.7.2" - }, - "bin": { - "ava": "entrypoints/cli.mjs" - }, - "engines": { - "node": "^18.18 || ^20.8 || ^21" - }, - "peerDependencies": { - "@ava/typescript": "*" - }, - "peerDependenciesMeta": { - "@ava/typescript": { - "optional": true - } - } - }, - "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==", - "dev": true - }, - "node_modules/bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "dev": true, - "dependencies": { - "file-uri-to-path": "1.0.0" - } - }, - "node_modules/blueimp-md5": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/blueimp-md5/-/blueimp-md5-2.19.0.tgz", - "integrity": "sha512-DRQrD6gJyy8FbiE4s+bDoXS9hiW3Vbx5uCdwvcCf3zLHL+Iv7LtGHLpr+GZV8rHG8tK766FGYBwRbu8pELTt+w==", - "dev": true - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/callsites": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-4.1.0.tgz", - "integrity": "sha512-aBMbD1Xxay75ViYezwT40aQONfr+pSXTHwNKvIXhXD6+LY3F1dLIcceoC5OZKBVHbXcysz1hL9D2w0JJIMXpUw==", - "dev": true, - "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cbor": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/cbor/-/cbor-9.0.1.tgz", - "integrity": "sha512-/TQOWyamDxvVIv+DY9cOLNuABkoyz8K/F3QE56539pGVYohx0+MEA1f4lChFTX79dBTBS7R1PF6ovH7G+VtBfQ==", - "dev": true, - "dependencies": { - "nofilter": "^3.1.0" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/chalk": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", - "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", - "dev": true, - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/chunkd": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/chunkd/-/chunkd-2.0.1.tgz", - "integrity": "sha512-7d58XsFmOq0j6el67Ug9mHf9ELUXsQXYJBkyxhH/k+6Ke0qXRnv0kbemx+Twc6fRJ07C49lcbdgm9FL1Ei/6SQ==", - "dev": true - }, - "node_modules/ci-info": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.0.0.tgz", - "integrity": "sha512-TdHqgGf9odd8SXNuxtUBVx8Nv+qZOejE6qyqiy5NtbYYQOeFa6zmHkxlPzmaLxWWHsU6nJmB7AETdVPi+2NBUg==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], - "engines": { - "node": ">=8" - } - }, - "node_modules/ci-parallel-vars": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ci-parallel-vars/-/ci-parallel-vars-1.0.1.tgz", - "integrity": "sha512-uvzpYrpmidaoxvIQHM+rKSrigjOe9feHYbw4uOI2gdfe1C3xIlxO+kVXq83WQWNniTf8bAxVpy+cQeFQsMERKg==", - "dev": true - }, - "node_modules/cli-truncate": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz", - "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==", - "dev": true, - "dependencies": { - "slice-ansi": "^5.0.0", - "string-width": "^7.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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==", - "dev": true, - "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==", - "dev": true, - "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==", - "dev": true - }, - "node_modules/cliui/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==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "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==", - "dev": true, - "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==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/code-excerpt": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/code-excerpt/-/code-excerpt-4.0.0.tgz", - "integrity": "sha512-xxodCmBen3iy2i0WtAK8FlFNrRzjUqjRsMfho58xT/wvZU1YTM3fCnRjcy1gJPMepaRlgm/0e6w8SpWHpn3/cA==", - "dev": true, - "dependencies": { - "convert-to-spaces": "^2.0.1" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "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==", - "dev": true - }, - "node_modules/color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "dev": true, - "bin": { - "color-support": "bin.js" - } - }, - "node_modules/common-path-prefix": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/common-path-prefix/-/common-path-prefix-3.0.0.tgz", - "integrity": "sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==", - "dev": true - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "node_modules/concordance": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/concordance/-/concordance-5.0.4.tgz", - "integrity": "sha512-OAcsnTEYu1ARJqWVGwf4zh4JDfHZEaSNlNccFmt8YjB2l/n19/PF2viLINHc57vO4FKIAFl2FWASIGZZWZ2Kxw==", - "dev": true, - "dependencies": { - "date-time": "^3.1.0", - "esutils": "^2.0.3", - "fast-diff": "^1.2.0", - "js-string-escape": "^1.0.1", - "lodash": "^4.17.15", - "md5-hex": "^3.0.1", - "semver": "^7.3.2", - "well-known-symbols": "^2.0.0" - }, - "engines": { - "node": ">=10.18.0 <11 || >=12.14.0 <13 || >=14" - } - }, - "node_modules/console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", - "dev": true - }, - "node_modules/convert-to-spaces": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/convert-to-spaces/-/convert-to-spaces-2.0.1.tgz", - "integrity": "sha512-rcQ1bsQO9799wq24uE5AM2tAILy4gXGIK/njFWcVQkGNZ96edlpY+A7bjwvzjYvLDyzmG1MmMLZhpcsb+klNMQ==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - } - }, - "node_modules/core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" - }, - "node_modules/currently-unhandled": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", - "integrity": "sha512-/fITjgjGU50vjQ4FH6eUoYu+iUoUKIXws2hL15JJpIR+BbTxaXQsMuuyjtNh2WqsSBS5nsaZHFsFecyw5CCAng==", - "dev": true, - "dependencies": { - "array-find-index": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/date-time": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/date-time/-/date-time-3.1.0.tgz", - "integrity": "sha512-uqCUKXE5q1PNBXjPqvwhwJf9SwMoAHBgWJ6DcrnS5o+W2JOiIILl0JEdVD8SGujrNS02GGxgwAg2PN2zONgtjg==", - "dev": true, - "dependencies": { - "time-zone": "^1.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/debug/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", - "dev": true - }, - "node_modules/detect-libc": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.2.tgz", - "integrity": "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/emittery": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/emittery/-/emittery-1.0.1.tgz", - "integrity": "sha512-2ID6FdrMD9KDLldGesP6317G78K7km/kMcwItRtVFva7I/cSEOIaLpewaUb+YLXVwdAp3Ctfxh/V5zIl1sj7dQ==", - "dev": true, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sindresorhus/emittery?sponsor=1" - } - }, - "node_modules/emoji-regex": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", - "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", - "dev": true - }, - "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-string-regexp": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", - "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "dev": true - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/fast-diff": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", - "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", - "dev": true - }, - "node_modules/fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fastq": { - "version": "1.16.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.16.0.tgz", - "integrity": "sha512-ifCoaXsDrsdkWTtiNJX5uzHDsrck5TzfKKDcuFFTIrrc/BS076qgEIfoIy1VeZqViznfKiysPYTh/QeHtnIsYA==", - "dev": true, - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/figures": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/figures/-/figures-6.0.1.tgz", - "integrity": "sha512-0oY/olScYD4IhQ8u//gCPA4F3mlTn2dacYmiDm/mbDQvpmLjV4uH+zhsQ5IyXRyvqkvtUkXkNdGvg5OFJTCsuQ==", - "dev": true, - "dependencies": { - "is-unicode-supported": "^2.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "dev": true - }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/find-up-simple": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/find-up-simple/-/find-up-simple-1.0.0.tgz", - "integrity": "sha512-q7Us7kcjj2VMePAa02hDAF6d+MzsdsAWEwYyOpwUtlerRBkOEPBCRZrAV4XfcSN8fHAgaD0hP7miwoay6DCprw==", - "dev": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/fs-minipass/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, - "node_modules/gauge": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", - "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", - "dev": true, - "dependencies": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.2", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.1", - "object-assign": "^4.1.1", - "signal-exit": "^3.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/gauge/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==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/gauge/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==", - "dev": true - }, - "node_modules/gauge/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==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/gauge/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==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/gauge/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==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "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==", - "dev": true, - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-east-asian-width": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.2.0.tgz", - "integrity": "sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==", - "dev": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/globby": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-14.0.0.tgz", - "integrity": "sha512-/1WM/LNHRAOH9lZta77uGbq0dAEQM+XjNesWwhlERDVenqothRbnzTrL3/LrIoEPPjeUHC3vrS6TwoyxeHs7MQ==", - "dev": true, - "dependencies": { - "@sindresorhus/merge-streams": "^1.0.0", - "fast-glob": "^3.3.2", - "ignore": "^5.2.4", - "path-type": "^5.0.0", - "slash": "^5.1.0", - "unicorn-magic": "^0.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true - }, - "node_modules/has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", - "dev": true - }, - "node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "dev": true, - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/ignore": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz", - "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/ignore-by-default": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-2.1.0.tgz", - "integrity": "sha512-yiWd4GVmJp0Q6ghmM2B/V3oZGRmjrKLXvHR3TE1nfoXsmoggllfZUQe74EN0fJdPFZu2NIvNdrMMLm3OsV7Ohw==", - "dev": true, - "engines": { - "node": ">=10 <11 || >=12 <13 || >=14" - } - }, - "node_modules/immediate": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.0.6.tgz", - "integrity": "sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==" - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/indent-string": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", - "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/irregular-plurals": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/irregular-plurals/-/irregular-plurals-3.5.0.tgz", - "integrity": "sha512-1ANGLZ+Nkv1ptFb2pa8oG8Lem4krflKuX/gINiHJHjJUKaJHk/SXk5x6K3J+39/p0h1RQ2saROclJJ+QLvETCQ==", - "dev": true, - "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==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", - "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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==", - "dev": true, - "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==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-plain-object": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-promise": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", - "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", - "dev": true - }, - "node_modules/is-unicode-supported": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-2.0.0.tgz", - "integrity": "sha512-FRdAyx5lusK1iHG0TWpVtk9+1i+GjrzRffhDg4ovQ7mcidMQ6mj+MhKPmvh7Xwyv5gIS06ns49CA7Sqg7lC22Q==", - "dev": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" - }, - "node_modules/js-string-escape": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/js-string-escape/-/js-string-escape-1.0.1.tgz", - "integrity": "sha512-Smw4xcfIQ5LVjAOuJCvN/zIodzA/BBSsluuoSykP+lUvScIi4U6RJLfwHet5cxFnCswUjISV8oAXaqaJDY3chg==", - "dev": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jszip": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/jszip/-/jszip-3.10.1.tgz", - "integrity": "sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==", - "dependencies": { - "lie": "~3.3.0", - "pako": "~1.0.2", - "readable-stream": "~2.3.6", - "setimmediate": "^1.0.5" - } - }, - "node_modules/lie": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/lie/-/lie-3.3.0.tgz", - "integrity": "sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==", - "dependencies": { - "immediate": "~3.0.5" - } - }, - "node_modules/load-json-file": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-7.0.1.tgz", - "integrity": "sha512-Gnxj3ev3mB5TkVBGad0JM6dmLiQL+o0t23JPBZ9sd+yvSLk05mFoqKBw5N8gbbkU4TNXyqCgIrl/VM17OgUIgQ==", - "dev": true, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "dependencies": { - "semver": "^6.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/make-dir/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/matcher": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/matcher/-/matcher-5.0.0.tgz", - "integrity": "sha512-s2EMBOWtXFc8dgqvoAzKJXxNHibcdJMV0gwqKUaw9E2JBJuGUK7DrNKrA6g/i+v72TT16+6sVm5mS3thaMLQUw==", - "dev": true, - "dependencies": { - "escape-string-regexp": "^5.0.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/md5-hex": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/md5-hex/-/md5-hex-3.0.1.tgz", - "integrity": "sha512-BUiRtTtV39LIJwinWBjqVsU9xhdnz7/i889V859IBFpuqGAj6LuOvHv5XLbgZ2R7ptJoJaEcxkv88/h25T7Ciw==", - "dev": true, - "dependencies": { - "blueimp-md5": "^2.10.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/memoize": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/memoize/-/memoize-10.0.0.tgz", - "integrity": "sha512-H6cBLgsi6vMWOcCpvVCdFFnl3kerEXbrYh9q+lY6VXvQSmM6CkmV08VOwT+WE2tzIEqRPFfAq3fm4v/UIW6mSA==", - "dev": true, - "dependencies": { - "mimic-function": "^5.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sindresorhus/memoize?sponsor=1" - } - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dev": true, - "dependencies": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/micromatch/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/mimic-function": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.0.tgz", - "integrity": "sha512-RBfQ+9X9DpXdEoK7Bu+KeEU6vFhumEIiXKWECPzRBmDserEq4uR2b/VCm0LwpMSosoq2k+Zuxj/GzOr0Fn6h/g==", - "dev": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/minizlib/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "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==", - "dev": true - }, - "node_modules/node-fetch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", - "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", - "dev": true, - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/node-gyp-build": { - "version": "4.7.1", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.7.1.tgz", - "integrity": "sha512-wTSrZ+8lsRRa3I3H8Xr65dLWSgCvY2l4AOnaeKdPA9TB/WYMPaTcrzf3rXvFoVvjKNVnu0CcWSx54qq9GKRUYg==", - "dev": true, - "bin": { - "node-gyp-build": "bin.js", - "node-gyp-build-optional": "optional.js", - "node-gyp-build-test": "build-test.js" - } - }, - "node_modules/nofilter": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/nofilter/-/nofilter-3.1.0.tgz", - "integrity": "sha512-l2NNj07e9afPnhAhvgVrCD/oy2Ai1yfLpuo3EpiO1jFTsB4sFz6oIfAfSZyQzVpkZQ9xS8ZS5g1jCBgq4Hwo0g==", - "dev": true, - "engines": { - "node": ">=12.19" - } - }, - "node_modules/nopt": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", - "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", - "dev": true, - "dependencies": { - "abbrev": "1" - }, - "bin": { - "nopt": "bin/nopt.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/npmlog": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", - "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", - "dev": true, - "dependencies": { - "are-we-there-yet": "^2.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^3.0.0", - "set-blocking": "^2.0.0" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/p-map": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-6.0.0.tgz", - "integrity": "sha512-T8BatKGY+k5rU+Q/GTYgrEf2r4xRMevAN5mtXc2aPc4rS1j3s+vWTaO2Wag94neXuCAUAs8cxBL9EeB5EA6diw==", - "dev": true, - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/package-config": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/package-config/-/package-config-5.0.0.tgz", - "integrity": "sha512-GYTTew2slBcYdvRHqjhwaaydVMvn/qrGC323+nKclYioNSLTDUM/lGgtGTgyHVtYcozb+XkE8CNhwcraOmZ9Mg==", - "dev": true, - "dependencies": { - "find-up-simple": "^1.0.0", - "load-json-file": "^7.0.1" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pako": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", - "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" - }, - "node_modules/parse-ms": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-3.0.0.tgz", - "integrity": "sha512-Tpb8Z7r7XbbtBTrM9UhpkzzaMrqA2VXMT3YChzYltwV3P3pM6t8wl7TvpMnSTosz1aQAdVib7kdoys7vYOPerw==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-type": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-5.0.0.tgz", - "integrity": "sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==", - "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/picomatch": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-3.0.1.tgz", - "integrity": "sha512-I3EurrIQMlRc9IaAZnqRR044Phh2DXY+55o7uJ0V+hYZAcQYSuFWsc9q5PvyDHUSCe1Qxn/iBz+78s86zWnGag==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pinyin-pro": { - "version": "3.18.5", - "resolved": "https://registry.npmjs.org/pinyin-pro/-/pinyin-pro-3.18.5.tgz", - "integrity": "sha512-WNnVRkNj+SLkSLL+zUqWgs2t9RuEaCZFTNPyjwBqbgJYu6VSX5bZMP/hmKiUD0n21VJSQTBQHrW8plQQvK8b0A==" - }, - "node_modules/plur": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/plur/-/plur-5.1.0.tgz", - "integrity": "sha512-VP/72JeXqak2KiOzjgKtQen5y3IZHn+9GOuLDafPv0eXa47xq0At93XahYBs26MsifCQ4enGKwbjBTKgb9QJXg==", - "dev": true, - "dependencies": { - "irregular-plurals": "^3.3.0" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pretty-ms": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-8.0.0.tgz", - "integrity": "sha512-ASJqOugUF1bbzI35STMBUpZqdfYKlJugy6JBziGi2EE+AL5JPJGSzvpeVXojxrr0ViUYoToUjb5kjSEGf7Y83Q==", - "dev": true, - "dependencies": { - "parse-ms": "^3.0.0" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/readable-stream": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", - "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "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==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/resolve-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", - "dev": true, - "dependencies": { - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - }, - "node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/serialize-error": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", - "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", - "dev": true, - "dependencies": { - "type-fest": "^0.13.1" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", - "dev": true - }, - "node_modules/setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==" - }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "node_modules/slash": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", - "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", - "dev": true, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/slice-ansi": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", - "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^6.0.0", - "is-fullwidth-code-point": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true - }, - "node_modules/stack-utils": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", - "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", - "dev": true, - "dependencies": { - "escape-string-regexp": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/stack-utils/node_modules/escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/string-width": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.0.0.tgz", - "integrity": "sha512-GPQHj7row82Hjo9hKZieKcHIhaAIKOJvFSIZXuCU9OASVZrMNUaZuz++SPVrBjnLsnk4k+z9f2EIypgxf2vNFw==", - "dev": true, - "dependencies": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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==", - "dev": true, - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/supertap": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/supertap/-/supertap-3.0.1.tgz", - "integrity": "sha512-u1ZpIBCawJnO+0QePsEiOknOfCRq0yERxiAchT0i4li0WHNUJbf0evXXSXOcCAR4M8iMDoajXYmstm/qO81Isw==", - "dev": true, - "dependencies": { - "indent-string": "^5.0.0", - "js-yaml": "^3.14.1", - "serialize-error": "^7.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - } - }, - "node_modules/tar": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", - "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==", - "dev": true, - "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/temp-dir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-3.0.0.tgz", - "integrity": "sha512-nHc6S/bwIilKHNRgK/3jlhDoIHcp45YgyiwcAk46Tr0LfEqGBVpmiAyuiuxeVE44m3mXnEeVhaipLOEWmH+Njw==", - "dev": true, - "engines": { - "node": ">=14.16" - } - }, - "node_modules/time-zone": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/time-zone/-/time-zone-1.0.0.tgz", - "integrity": "sha512-TIsDdtKo6+XrPtiTm1ssmMngN1sAhyKnTO2kunQWqNPWIVvCm15Wmw4SWInwTVgJ5u/Tr04+8Ei9TNcw4x4ONA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "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==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "dev": true - }, - "node_modules/type-fest": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", - "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/unicorn-magic": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.1.0.tgz", - "integrity": "sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==", - "dev": true, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" - }, - "node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "dev": true - }, - "node_modules/well-known-symbols": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/well-known-symbols/-/well-known-symbols-2.0.0.tgz", - "integrity": "sha512-ZMjC3ho+KXo0BfJb7JgtQ5IBuvnShdlACNkKkdsqBmYw3bPAaJfPeYUo6tLUaT5tG/Gkh7xkpBhKRQ9e7pyg9Q==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "dev": true, - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "node_modules/wide-align": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", - "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", - "dev": true, - "dependencies": { - "string-width": "^1.0.2 || 2 || 3 || 4" - } - }, - "node_modules/wide-align/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==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/wide-align/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==", - "dev": true - }, - "node_modules/wide-align/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==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/wide-align/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==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wide-align/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==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "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==", - "dev": true, - "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/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==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi/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==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/wrap-ansi/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==", - "dev": true - }, - "node_modules/wrap-ansi/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==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi/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==", - "dev": true, - "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/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==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true - }, - "node_modules/write-file-atomic": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", - "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", - "dev": true, - "dependencies": { - "imurmurhash": "^0.1.4", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, - "node_modules/write-file-atomic/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==", - "dev": true, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, - "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==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "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==", - "dev": true, - "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==", - "dev": true - }, - "node_modules/yargs/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==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "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==", - "dev": true, - "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==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/yomichan-dict-builder": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/yomichan-dict-builder/-/yomichan-dict-builder-1.3.2.tgz", - "integrity": "sha512-dYjfXxYK/pBHv5eYEBPHAo8FvH/LuxPn4MocRmGJ8cYLRcgSSHUVf1zzMjH36ZWz9U0Dnb1vhkFz4pqgHztSfQ==", - "dependencies": { - "jszip": "^3.10.1" - } - } - } -} diff --git a/package.json b/package.json index e8b7aba..b8a0eee 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,11 @@ }, "type": "module", "devDependencies": { - "ava": "^6.0.1" + "ava": "^6.0.1", + "@types/bun": "latest" + }, + "name": "wikipedia-yomitan", + "peerDependencies": { + "typescript": "^5.0.0" } -} +} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..238655f --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,27 @@ +{ + "compilerOptions": { + // Enable latest features + "lib": ["ESNext", "DOM"], + "target": "ESNext", + "module": "ESNext", + "moduleDetection": "force", + "jsx": "react-jsx", + "allowJs": true, + + // Bundler mode + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "verbatimModuleSyntax": true, + "noEmit": true, + + // Best practices + "strict": true, + "skipLibCheck": true, + "noFallthroughCasesInSwitch": true, + + // Some stricter flags (disabled by default) + "noUnusedLocals": false, + "noUnusedParameters": false, + "noPropertyAccessFromIndexSignature": false + } +} From a95eb6e4fddcbec06318fc71da10d283cc5b7e31 Mon Sep 17 00:00:00 2001 From: MarvNC Date: Thu, 11 Jul 2024 15:02:50 -0700 Subject: [PATCH 03/26] Convert helpers to TS --- src/parse/{parseLine.js => parseLine.ts} | 27 ++++++++++--------- ...dingParse.test.js => readingParse.test.ts} | 24 ++++++----------- .../{readingParse.js => readingParse.ts} | 20 +++++--------- 3 files changed, 28 insertions(+), 43 deletions(-) rename src/parse/{parseLine.js => parseLine.ts} (72%) rename src/parse/{readingParse.test.js => readingParse.test.ts} (97%) rename src/parse/{readingParse.js => readingParse.ts} (83%) diff --git a/src/parse/parseLine.js b/src/parse/parseLine.ts similarity index 72% rename from src/parse/parseLine.js rename to src/parse/parseLine.ts index f6f7bd1..be42579 100644 --- a/src/parse/parseLine.js +++ b/src/parse/parseLine.ts @@ -1,16 +1,14 @@ import { pinyin } from 'pinyin-pro'; -import { languagesAllowed } from './constants.js'; -import { getReadingFromDefinition } from './readingParse.js'; +import { languagesAllowed } from '../constants'; +import { getReadingFromDefinition } from './readingParse'; -/** - * @typedef {Object} ParsedLine - * @property {string} term - * @property {string} termSlug - * @property {string} termSpecifier - * @property {string} reading - * @property {string} definition - * - */ +type ParsedLine = { + term: string; + termSlug: string; + termSpecifier: string; + reading: string; + definition: string; +}; /** * @@ -18,11 +16,14 @@ import { getReadingFromDefinition } from './readingParse.js'; * @param {typeof languagesAllowed[keyof typeof languagesAllowed]} lang * @returns {ParsedLine} */ -function parseLine(line, lang) { +function parseLine( + line: string, + lang: (typeof languagesAllowed)[keyof typeof languagesAllowed] +): ParsedLine { // remove last 6 characters line = line.slice(0, -6); const [resource, definition] = line.split( - '> "', + '> "' ); let termSlug = resource.split('.dbpedia.org/resource/').pop(); if (!termSlug) { diff --git a/src/parse/readingParse.test.js b/src/parse/readingParse.test.ts similarity index 97% rename from src/parse/readingParse.test.js rename to src/parse/readingParse.test.ts index 3db8af0..acfa26f 100644 --- a/src/parse/readingParse.test.js +++ b/src/parse/readingParse.test.ts @@ -4,22 +4,14 @@ import { parseLine } from './parseLine.js'; import { languagesAllowed } from '../constants.js'; -/** - * @typedef {Object} TestCase - * @property {string} line - * @property {string} term - * @property {string} expectedReading - */ -/** - * @typedef {Object} TestCases - * @property {typeof languagesAllowed[keyof typeof languagesAllowed]} lang - * @property {TestCase[]} cases - */ - -/** - * @type {TestCases[]} - */ -const testCases = [ +const testCases: { + lang: (typeof languagesAllowed)[keyof typeof languagesAllowed]; + cases: { + line: string; + term: string; + expectedReading: string; + }[]; +}[] = [ { lang: languagesAllowed.ja, cases: [ diff --git a/src/parse/readingParse.js b/src/parse/readingParse.ts similarity index 83% rename from src/parse/readingParse.js rename to src/parse/readingParse.ts index ec9326a..03ef5b5 100644 --- a/src/parse/readingParse.js +++ b/src/parse/readingParse.ts @@ -1,12 +1,7 @@ const leewayAfterTerm = 2; -/** - * @param {string} definition - * @param {string} term - * @returns {string} - */ -function getReadingFromDefinition(definition, term) { - const normalizeText = (text) => text.replace(/ /g, '').toLowerCase(); +function getReadingFromDefinition(definition: string, term: string): string { + const normalizeText = (text: string) => text.replace(/ /g, '').toLowerCase(); // Remove spaces from definition and term definition = normalizeText(definition); term = normalizeText(term); @@ -15,7 +10,6 @@ function getReadingFromDefinition(definition, term) { for (const matchArr of bracketMatches) { if (matchArr && matchArr.length >= 3) { - // @ts-ignore const outerBracketContent = matchArr[1]; const bracketContent = matchArr[2]; const bracketIndex = definition.indexOf(outerBracketContent); @@ -35,12 +29,10 @@ function getReadingFromDefinition(definition, term) { return ''; } -/** - * @param {string} bracketContent - * @param {string} term - * @returns {string} - */ -function parseReadingFromBrackets(bracketContent, term) { +function parseReadingFromBrackets( + bracketContent: string, + term: string +): string { if (!bracketContent) return ''; const commaRegex = /,|、/g; From b08cbce9d30bce771e86fd1d399950a2f9a42244 Mon Sep 17 00:00:00 2001 From: MarvNC Date: Thu, 11 Jul 2024 15:04:05 -0700 Subject: [PATCH 04/26] Convert getVersion.js to TypeScript --- src/util/{getVersion.js => getVersion.ts} | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) rename src/util/{getVersion.js => getVersion.ts} (62%) diff --git a/src/util/getVersion.js b/src/util/getVersion.ts similarity index 62% rename from src/util/getVersion.js rename to src/util/getVersion.ts index eebb130..d7ea6b5 100644 --- a/src/util/getVersion.js +++ b/src/util/getVersion.ts @@ -1,8 +1,11 @@ import fs from 'fs'; import path from 'path'; -export function getVersion() { +export function getVersion(): string { const packageJsonPath = path.join(process.cwd(), 'package.json'); const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8')); + if (!packageJson.version) { + throw new Error('Could not get version from package.json'); + } return packageJson.version; } From 11064afc39f9125c6f06e5e8db953a8eda593249 Mon Sep 17 00:00:00 2001 From: MarvNC Date: Thu, 11 Jul 2024 15:08:15 -0700 Subject: [PATCH 05/26] Convert to TS --- src/{constants.js => constants.ts} | 0 ...onvertWikipedia.js => convertWikipedia.ts} | 56 +++++++------------ 2 files changed, 20 insertions(+), 36 deletions(-) rename src/{constants.js => constants.ts} (100%) rename src/{convertWikipedia.js => convertWikipedia.ts} (77%) diff --git a/src/constants.js b/src/constants.ts similarity index 100% rename from src/constants.js rename to src/constants.ts diff --git a/src/convertWikipedia.js b/src/convertWikipedia.ts similarity index 77% rename from src/convertWikipedia.js rename to src/convertWikipedia.ts index e263aa2..f18d504 100644 --- a/src/convertWikipedia.js +++ b/src/convertWikipedia.ts @@ -3,25 +3,23 @@ import path from 'path'; import readline from 'readline'; import { Dictionary, TermEntry } from 'yomichan-dict-builder'; -import { parseLine } from './parseLine.js'; -import { languagesAllowed } from './constants.js'; -import { getVersion } from './util/getVersion.js'; +import { parseLine } from './parse/parseLine'; +import { languagesAllowed } from './constants'; +import { getVersion } from './util/getVersion'; +import type { + StructuredContent, + StructuredContentNode, +} from 'yomichan-dict-builder/dist/types/yomitan/termbank'; const linkCharacter = '⧉'; -/** - * - * @param {string} lang - * @param {string} date - * @param {string} version - * @returns - */ -const outputZipName = (lang, date, version) => + +const outputZipName = (lang: string, date: string, version: string) => `${lang} Wikipedia [${date}] (v${version}).zip`; -const shortAbstractFile = (lang) => +const shortAbstractFile = (lang: string) => `short-abstracts_lang=${lang.toLowerCase()}.ttl`; (async () => { - const version = await getVersion(); + const version = getVersion(); console.log(`Using version ${version}`); @@ -74,11 +72,8 @@ div.gloss-sc-div[data-sc-wikipedia=term-specifier] { /** * Reads a line and adds that term entry to the dictionary - * @param {string} line - * @param {Dictionary} dict - * @param {string} lang */ -function processLine(line, dict, lang) { +function processLine(line: string, dict: Dictionary, lang: string) { const { term, termSlug, termSpecifier, reading, definition } = parseLine( line, lang @@ -87,17 +82,11 @@ function processLine(line, dict, lang) { const termEntry = new TermEntry(term); termEntry.setReading(reading); - /** - * @type {import('yomichan-dict-builder/dist/types/yomitan/termbank').StructuredContent[]} - */ - const structuredContentList = []; + const structuredContentList: StructuredContent[] = []; // Add term specifier heading if exists if (termSpecifier) { - /** - * @type {import('yomichan-dict-builder/dist/types/yomitan/termbank').StructuredContentNode} - */ - const specifierSCNode = { + const specifierSCNode: StructuredContentNode = { tag: 'div', content: `«${termSpecifier}»`, data: { @@ -112,10 +101,7 @@ function processLine(line, dict, lang) { } const definitionStrings = definition.split('\\n').map((line) => line.trim()); - /** - * @type {import('yomichan-dict-builder/dist/types/yomitan/termbank').StructuredContentNode} - */ - const definitionUList = { + const definitionUList: StructuredContentNode = { tag: 'ul', content: definitionStrings.map((definitionString) => ({ tag: 'li', @@ -135,10 +121,7 @@ function processLine(line, dict, lang) { : lang === languagesAllowed.zh ? '查看更多' : 'Read more'; - /** - * @type {import('yomichan-dict-builder/dist/types/yomitan/termbank').StructuredContentNode} - */ - const linkSC = { + const linkSC: StructuredContentNode = { tag: 'ul', content: [ { @@ -171,9 +154,10 @@ function processLine(line, dict, lang) { function readArgs() { // Read arguments: node convertWikipedia.js [language] [date of dump] - const langInput = process.argv[2]; + const langInput = + process.argv[2].toLowerCase() as keyof typeof languagesAllowed; // Assert language is valid - if (!languagesAllowed[langInput.toLowerCase()]) { + if (!languagesAllowed[langInput]) { throw new Error( `Language ${langInput} is not allowed. Allowed languages: ${Object.keys( languagesAllowed @@ -181,7 +165,7 @@ function readArgs() { ); } - const lang = languagesAllowed[langInput.toLowerCase()]; + const lang = languagesAllowed[langInput]; const dateInput = process.argv[3]; // Assert date is valid in format YYYY-MM-DD From 74df800c0be29db1bb7a87f334012276c73a0a6d Mon Sep 17 00:00:00 2001 From: MarvNC Date: Thu, 11 Jul 2024 15:26:22 -0700 Subject: [PATCH 06/26] More TS updates --- src/constants.ts | 2 +- src/{convertWikipedia.ts => index.ts} | 14 +++++++------- src/parse/parseLine.ts | 10 +++++----- src/parse/readingParse.test.ts | 8 ++++---- 4 files changed, 17 insertions(+), 17 deletions(-) rename src/{convertWikipedia.ts => index.ts} (93%) diff --git a/src/constants.ts b/src/constants.ts index f126b01..24399b0 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -1,4 +1,4 @@ -export const languagesAllowed = { +export const languages = { ja: 'JA', zh: 'ZH', }; diff --git a/src/convertWikipedia.ts b/src/index.ts similarity index 93% rename from src/convertWikipedia.ts rename to src/index.ts index f18d504..d2b9c0d 100644 --- a/src/convertWikipedia.ts +++ b/src/index.ts @@ -4,7 +4,7 @@ import readline from 'readline'; import { Dictionary, TermEntry } from 'yomichan-dict-builder'; import { parseLine } from './parse/parseLine'; -import { languagesAllowed } from './constants'; +import { languages } from './constants'; import { getVersion } from './util/getVersion'; import type { StructuredContent, @@ -116,9 +116,9 @@ function processLine(line: string, dict: Dictionary, lang: string) { // Read more const articleLink = `https://${lang.toLowerCase()}.wikipedia.org/wiki/${termSlug}`; const readTheRest = - lang === languagesAllowed.ja + lang === languages.ja ? '続きを読む' - : lang === languagesAllowed.zh + : lang === languages.zh ? '查看更多' : 'Read more'; const linkSC: StructuredContentNode = { @@ -155,17 +155,17 @@ function processLine(line: string, dict: Dictionary, lang: string) { function readArgs() { // Read arguments: node convertWikipedia.js [language] [date of dump] const langInput = - process.argv[2].toLowerCase() as keyof typeof languagesAllowed; + process.argv[2].toLowerCase() as keyof typeof languages; // Assert language is valid - if (!languagesAllowed[langInput]) { + if (!languages[langInput]) { throw new Error( `Language ${langInput} is not allowed. Allowed languages: ${Object.keys( - languagesAllowed + languages ).join(', ')}` ); } - const lang = languagesAllowed[langInput]; + const lang = languages[langInput]; const dateInput = process.argv[3]; // Assert date is valid in format YYYY-MM-DD diff --git a/src/parse/parseLine.ts b/src/parse/parseLine.ts index be42579..6fdeee7 100644 --- a/src/parse/parseLine.ts +++ b/src/parse/parseLine.ts @@ -1,5 +1,5 @@ import { pinyin } from 'pinyin-pro'; -import { languagesAllowed } from '../constants'; +import { languages } from '../constants'; import { getReadingFromDefinition } from './readingParse'; type ParsedLine = { @@ -13,12 +13,12 @@ type ParsedLine = { /** * * @param {string} line - * @param {typeof languagesAllowed[keyof typeof languagesAllowed]} lang + * @param {typeof languages[keyof typeof languages]} lang * @returns {ParsedLine} */ function parseLine( line: string, - lang: (typeof languagesAllowed)[keyof typeof languagesAllowed] + lang: (typeof languages)[keyof typeof languages] ): ParsedLine { // remove last 6 characters line = line.slice(0, -6); @@ -41,9 +41,9 @@ function parseLine( term = term.replace(/_/g, ' '); let reading = ''; - if (lang === languagesAllowed.ja) { + if (lang === languages.ja) { reading = getReadingFromDefinition(definition, term); - } else if (lang === languagesAllowed.zh) { + } else if (lang === languages.zh) { reading = pinyin(term, { mode: 'surname' }); reading = reading.replace(/ /g, ''); } diff --git a/src/parse/readingParse.test.ts b/src/parse/readingParse.test.ts index acfa26f..f18c96f 100644 --- a/src/parse/readingParse.test.ts +++ b/src/parse/readingParse.test.ts @@ -2,10 +2,10 @@ import test from 'ava'; import { parseLine } from './parseLine.js'; -import { languagesAllowed } from '../constants.js'; +import { languages } from '../constants.js'; const testCases: { - lang: (typeof languagesAllowed)[keyof typeof languagesAllowed]; + lang: (typeof languages)[keyof typeof languages]; cases: { line: string; term: string; @@ -13,7 +13,7 @@ const testCases: { }[]; }[] = [ { - lang: languagesAllowed.ja, + lang: languages.ja, cases: [ { line: ` "みぞおちとは、人間の腹の上方中央にある窪んだ部位のこと。鳩尾(きゅうび、みぞおち)、水月(すいげつ)、心窩(しんか、しんわ)とも呼ばれる。みぞおちの内部背中側には腹腔神経叢(ふっくうしんけいそう、英:celiac plexus, solar plexus. 独:solarplexus)という (en:nerve plexus) がある。"@ja .`, @@ -95,7 +95,7 @@ const testCases: { ], }, { - lang: languagesAllowed.zh, + lang: languages.zh, cases: [ { line: ` "《!HERO》(直译“!英雄”)是一部有关耶稣的。这部歌剧基于“如果耶稣出生在宾夕法尼亚州伯利恒将会怎样?”这个问题。2003年首次巡演后,《!HERO》也通过DVD和CD发行。此歌剧也被写成一部小说三部曲和一系列漫画。"@zh .`, From 848c5d24a082acdefb24f8e217ebb3d0ed93faff Mon Sep 17 00:00:00 2001 From: MarvNC Date: Thu, 11 Jul 2024 15:27:25 -0700 Subject: [PATCH 07/26] Make tests run --- .gitignore | 2 ++ bun.lockb | Bin 76326 -> 92039 bytes package.json | 16 +++++++++++++--- tsconfig.json | 18 ++---------------- 4 files changed, 17 insertions(+), 19 deletions(-) diff --git a/.gitignore b/.gitignore index 3144fc3..929e9d1 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,8 @@ *.bz2 *.zip +.tsimp + # Created by https://www.toptal.com/developers/gitignore/api/node # Edit at https://www.toptal.com/developers/gitignore?templates=node diff --git a/bun.lockb b/bun.lockb index d9741afed4b5a3b4c84f778fe8f8285ea6dc5077..0cbe8e2ad013ba1fc06208da831e4ba13db95aec 100644 GIT binary patch delta 23014 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 Q?2SgUR~Sp-0f$%oH*U@OEC2ui diff --git a/package.json b/package.json index b8a0eee..808437f 100644 --- a/package.json +++ b/package.json @@ -2,19 +2,29 @@ "version": "1.4.0", "scripts": { "test": "ava", - "buildja": "node .\\src\\convertWikipedia.js ja 2022-12-01" + "start": "bun run src/index.ts" }, "dependencies": { "pinyin-pro": "^3.18.5", + "tsimp": "^2.0.11", "yomichan-dict-builder": "^1.3.2" }, "type": "module", "devDependencies": { - "ava": "^6.0.1", - "@types/bun": "latest" + "@ava/typescript": "^5.0.0", + "@types/bun": "latest", + "ava": "^6.0.1" }, "name": "wikipedia-yomitan", "peerDependencies": { "typescript": "^5.0.0" + }, + "ava": { + "extensions": { + "ts": "module" + }, + "nodeArguments": [ + "--import=tsimp" + ] } } \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index 238655f..3ad96b4 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,27 +1,13 @@ { "compilerOptions": { - // Enable latest features "lib": ["ESNext", "DOM"], "target": "ESNext", "module": "ESNext", - "moduleDetection": "force", "jsx": "react-jsx", "allowJs": true, - - // Bundler mode - "moduleResolution": "bundler", - "allowImportingTsExtensions": true, - "verbatimModuleSyntax": true, - "noEmit": true, - - // Best practices + "moduleResolution": "node", "strict": true, "skipLibCheck": true, - "noFallthroughCasesInSwitch": true, - - // Some stricter flags (disabled by default) - "noUnusedLocals": false, - "noUnusedParameters": false, - "noPropertyAccessFromIndexSignature": false + "noFallthroughCasesInSwitch": true } } From 16bce4104494131f9c177c7623c287dd4443ebf0 Mon Sep 17 00:00:00 2001 From: MarvNC Date: Thu, 11 Jul 2024 15:42:17 -0700 Subject: [PATCH 08/26] Test with bun --- .github/workflows/test-readings.yaml | 10 +++++----- bun.lockb | Bin 92039 -> 8523 bytes package.json | 6 +----- src/parse/readingParse.test.ts | 6 +++--- 4 files changed, 9 insertions(+), 13 deletions(-) diff --git a/.github/workflows/test-readings.yaml b/.github/workflows/test-readings.yaml index 08e641c..ffca8ed 100644 --- a/.github/workflows/test-readings.yaml +++ b/.github/workflows/test-readings.yaml @@ -1,4 +1,4 @@ -name: Node.js CI +name: Test on: [push, pull_request] @@ -8,8 +8,8 @@ jobs: steps: - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 + - uses: oven-sh/setup-bun@v2 with: - node-version: 18 - - run: npm ci - - run: npm test + bun-version-file: package.json + - run: bun install --frozen-lockfile + - run: bun test diff --git a/bun.lockb b/bun.lockb index 0cbe8e2ad013ba1fc06208da831e4ba13db95aec..4976cef975f055ba17b233c072eabfea2d92b721 100644 GIT binary patch delta 1381 zcmb_cYe-a45I*O2SJ%hpy6W1xQCdDruDfn-E7oo$l(d=l%g2w(aJ45I6=*_jVD!); zo8qJuMHKa;AJtM8CKX{(+d~L~4WfdIUP3`XdST7ny_fn?P|$&y@65g5%sn%6=WM%g z2+!H06r2oq&%bvn{z-eo)HO*(9lMWuzJIt|_V=TCG-NqHIxW9>#i1tOqB*eX(v9XAq8nz=QpdIMBmR?(j29aAER<$6XtzHoz zVAsbm7KhJMaUYL}qGFpIeLjRpLE;Tj|I6BQ@+CejH?|oczchs(B|pCh!%6wZBRRps zsapffpxRu)UC?Xx@vRU+{QzvqKAr+~sEgNzaoewsPFRn>qtQrGK(BSnzuf@mT zK?HR+*iwAF5$aIyhhEfoAd=#fVr1yc^h)Ijey_AehDQj)GGr|9N>&5ZBh(n64?&=n z>V~Cec{3iKkzg?xCZz5$dvy`UqL`zmio{FS?0-S>vuJ+5;AZv1Dfj}DrCzGG-e^K{ zOh?hz|2=SRH0RNAcv}NOL9U`tH(Yo6Ir?Fdh$!Yee`>DQ36!A zs~RaaoryAu=Ro3UVii@I3PuH{|Cu@*gF;<3qL3ryPMxOz9RF*Y31&jU!J#2yv$X0T ziU!Uykds-gm3a9?@};=+9r_00u*T2LU?MM;&vVjH+>R+2^gFhEG;*inRNP3@$4j3S zi7$33PLEQ;CWw((-fY*0I6Pvgot=BdE%8moii>=2iWVcc@j9`?$SdsuY!n6yhRf!b ziH;LhD$k)f7;6_Fh}S6+;<(MOUk1lq4;LOe@p(G(oQgwnYCLNxdg!zNv8zcAFL7K# zjte;@jOo+g@viyqcFWsIlA4HfI%Ah*u{fKLbL;m)Pf`7@-19R_=^PloSn=pLMO@2_ z8*di%4d9y+rP!@ZV?(kyjlK!38CVfqXRv12;TC(BcDZzVO78Hsv7=8lLMW37e;#-A k@66+0$A}jNe7v~j;aS4a$jA3bmhnO^(hGS7WDOqp0ZwrKp8x;= literal 92039 zcmeEvcUTok_V!gk5y_I1L?ve>3z9)VNs_6%rtvMC%;XD);K~UU6w1aA3 z0{4{i+qws52P;-=cK|I6X5-gi3|g^0 zrV9sy*#mK&4ld9RECisQio2!A?C)eO}z~u zA)kwbtAo3Rr{{T4rvmi=Z2N8y0_guKAff+fuW+=O_2Aff)B@x%aS=*RDQwrbZK!~^<$8<0TzzV;4Q z_8=Y(o;H3k!ZV;9_O}N7fquDLc-iwg+4#FVcvyJZcw$_ftQ|Z+;B5g9)H4JU`ojjW z(0>ab3-Aep@wf1>^8|7y7zEgVe<5*K*#4OugCPU;Q6M4S#?#8e*}~e!%Gtr&0o>ne zKhm*0^&oj*KfG*Q-1&fOp5E>@9$psiK_D3+eh z4^Nv#Fxb# z2NK3bfNoQ=V5K{siv`SE7Z@BUZCud8(|FQ4#2^9IC%2?nmW_qKJ@1XXoq=ZYvJj22H5qm@%D7E^~bogY|c9& z*3EbY0}1`Uh}9PX{(!EA**e&HdjJQLLE^wT+qgJ*dD(dQTiaNA+W|f#K1`s$Acew) z*f;I%19j+6G6x0&K8AVPxcGo@VUT(3Z{h6h;OT{Nu|C9SZ{vp}LHdK#>3k z{SE;V#>vLh+snb(6XT7oYjJM2?*QbG|0@XguldWh8TUzS9huiVxi|es=Ho-42jhdx z_cuTv+Ou-tb8xkF!&upSyE<88fV6OS0{yhIbOYXFFs^Q3xds8~0Q%4`uo}W}f;{!G z^8xo8K|AENuyXT&6R8^1VH`O4H^+?*NLWYKHxYqNyKb&lHjv-f!@}Ji@cn*Wa~Is? z118_W$~*!zpWE+ zT@7${ute5ZL`sNk+Cl18_HMqe0E(>BuI?_*ZXgkO4sFKY&cfRcc4QFLp?xI&zh5tq zxFh57`}+v)_j<@a(FyorzZ-#sai9PauG^2W?H2AHZkAw)!v%FXuE_qjSA28aT;1Hg zV7x6XEj?_&!0iD2g#OA(Y|02AVP1K8h#rP|E*4HUzt$~m9xn)Q=GiOBP5qCc4*j47 zx{&9b)TW(wAbUtl&y4C$l+DB0$1^9Rw2QGqSGJW9wuucB>ivG_{(##|Q0`UOqgMD+E%yMa1Bbc4;ac!oz0 z)EvGg(x;V?vnE#EHEx;jSr*CiPQdJ-8Ox_;DP^hTz?|dz27_z5tt80FQl_YBhI;HO zBC{SUxkcr+bJ4$>P)!-{_EOzx7c|zq6m5&!d|L3)p=2M|3s;42WN?J>@EnmN3*!C6iN?H*0j#aAP> zbR4^?Pn!?t`~Pqg$)rD;UJyS`McEah-#x<~;6`f1$U4GSyNC6W@s6~2$}1V}8_qlK zxw9(1EpihobDpzGpRqR9e=l9Ds3q|17Hv~Kh2X)M&x-MCRA51W5 zz$lw}`CFG~&5vFk={=!y)Be)xR2envwpBh)GYTm!B^$i@Jj1Q`GF){%rh4uDI8pOk zvJY*}IF5vs1YbVJO^+6ch0U$Y*mYP3MLM!8F78;2Zq9;@M#8&%3#8D%y*ePHmK!R_%|7z(}Lyh@fA)YD0o<`Y%2DUo2 zGcx6blkV|H>d2+Op4NzOj(rnNvUa;@XMMt>yB0@rhjx<8^`3k-*qCrKZ-;8mj>naJ zI5{Nk^^5Pb^$ByVxzb{@9_Vibx9ev)ij}`u3-~#+YWe>3K73K)gB|&!p>7eG4Dxir zHdLP<-K$AqzTi%GL#AFCzWL10Z&xgq2YlQ_B|rGpsa>LsB|KMysjnh^&pkaw zEh5HQP*5S5on7|4x4b`2b=)_7#9D4>F5+@ElUvQF=pV(#okORzaS{7C1urax!|ffJ zjhZ|uoK2+M;!QdXKG9x@eQh4f==!tgR0Hn>ZSX;@*_(SPxNKtDiU+D^SUh>@rgR!# zy|&496q3#62s%$jH|_E~)$o&cGvZ$@#p_*F^`G|3e5t+PM0&^`*HBombyqOQ0D-GW*% zrX=i2da_Bpr&oWTcPD&WZp2vue&^0w8@yS-Uxm4g=J;b+sum4OLmCiG# z@X~wj%rw2!=TAC{EI*@E`*@Nlo_!3N$BW7L`sjjK7FXWgSv=oxgu-giH)WdTK=s;D zADNpHT0Ol}Yqg_S>l6d-9Szr#&eHee9;OefeeT-+xms^ocWmFrb6!){Qtkbua*e*h zT4e-d3B{W4BGz#3hnV+H%|*VP@!|}Si005l=Cxi)Mkg=n@B}g+kDiuQ!7WUkN9KD0 zCEs}$*Z#JnID5Z4&J+{hxYYV>?Uk5T``B4Q4XRVG!w;S#$d#{`v>!RwWfjwgKTXI? zyZ0Q2u!Jvp9d*>5#J)YagO4LFx3D~>_;h?+HuKF&oOM;^htIpX-}$nPnSEsIyHuBz z9po#n-ZUqiO6P~HZw<{;qnWx z`)qo&qX+L((qY%@#e~m7wMN{As?CxMQeS%dEa8XwO!pY5AO3zdKl6^_l^cuo{faYZ zKLxTQ`4l9|_rYFHqAp+ZhOMc5X9BWLq|J#}@6ey(MAlbCPR}MMI;}YGMC!5){b%HG z_--NVbkF{-rj+dP6NF}I%;UT#_uqcynbXU<(-MjQ@7D_??#Ouj{yu{H zy&kep=v?e8W-?SK$gA36b#qryNnBp2Xt;3T#A~8+nF-NWUG?dv^Uh5C-F9696(1tV zypjD)t&snO&x2s*M+6~C+|3sKVr^6B7q4;8URln`tYXADM@HL_Ow%FWm(4vG?XAY8 zE@?aR`bK%ULc)gklxWAaFOtXE)~ADSX}IayY!pf|N`!v3UkeJul`U6k+Qs$cnBdu^ zz!|&NDDr96s{+O`2g+q6_P9wmPHCr9-)_F{pW)c$a6;3IvPyq?BiP7@(R?X^!Ck-I z@RNZ@XwJ3t89Zk5qdo@0j4?r4O~|_5j6ZomU8|{u^Yh@mC-p*QpO$joblixjfn?$7 z7_uG7C8mmOdy~_qb|4%5UzG4I11$33(gEiP$Oj(TF-SZ3_=g42O9Wcr=oALA@JzE+ zzYzQ=z{p|kgO3?JX4qpAGQfQR!FyZq+t4fZ*Q&5O@Umg@^6n zwbPagg69AMgYyTeZ`c1)fCrBjzw!s>&{q3^*qaAx840F1)?g*Z6&NIUrW zhXv7tj%#7@5U^eU+pzYb?XCI_?I89E!GMVZ`!IH}fM=>L6$CE_@G$@2+6R3=c>at8 z!Dj=!EVln}?6=wn1ix!H1_K@`f3v^c_#Fj!IDdioWgFq$s{j4~sE76c&oJowh@Dn| zhw}%C`*!0;1r~f|fJgYY8$U;YS48=b@SuJDcb^fxVt_~HKOFz<#vc!KTprkmHnuwV zp)O)y1>m85WZy&Dq0S!_L~k!hT!@F`zny~MPXIhze?S`lD%*|!H7p((_wC}l0A3E* zhp~q~Z8!d+Am}Fneyg}&oy6LLpDzJCT>p^xBlrJIBJq2P#cwBfAUA^F2VN4%1N%sQ zyYV{>@NoPf4qniYtrWywD!?Q8w^iGaAHnxx?IY{YR&1m3WZ-4l-^o8sfR_XPhxrHn zNBn{|{-_{&sQ|AC@K6_N`y(83578Y0c$hzM{ex{tJEHfWB%;SiyorbN54LS}3=sVP z=I`H|za}95s$l%!`teudUyL0;Wc}UhI)scLCHT??ym}5p>WKVLd4segdMdxeBlrJI zB6xp*NAJIXhC}Wn_!fYd$Hou2w-t%tiNVW#cz%I#gSo%m{8t8e`22&cd&oZaXFeeI z;{YC>ACYm}uKjv|N6ydCCgR6d?e75JFCptU#BA5T48Vi05`Otl4)Dl6yjA-#0M8Hb zNZht-zXTYC&p&_$1Lpt|*R9$o-iN^)1$asTfVQ`5|2V)40zA_1t?uK9pP>M+4)C!4 zSM0w6c=Y^1{Mc&$Nhtna{;L2yTtAS0Z#RDb+dux^{^1Ye5Az2Z_wB~N4dCJW0rLf7 zx4V82f{BBypO9m#1<8NK-{H6Ge>A|u{73e`?c(18JbeCzeuJabw&y<^6$T>)@NoSG zTk*E>=K&tQe{9$PM*t7LY7Rqi;BjV41&RN6fJd+Y$UgLEBnVy{d}%HZ>?8U2XE@|O zf)4{$KT<2K?Xv*}sq++KzoAfQRc3w7;DkK>WWA@UZ`g|6BC|!M_K1#lI1M z8M;mUUtK@WV)0w`8;LFAe*?h7{d22%|9kuj!1Dq;^Z~Iy3h;3L|5dy&!{++8)qU^x{dWa;xc~fB`(*$R=MOS| z2>+i+r2jtv{t&>!y=OZG!Mia2u(^KCDCgTa6)t7X`oP6vg@v{YBd0 z=RYclo(I4~|NrXx_ZZ;O^MAYk?_u7IKVtund`90x{8s>Y*nemjj=^^A`vUwCfJgEd z;RRHGSP;E(=6^oFZ8ZlG{8xa7@rQNj`*!^oV)@7SKac}?4g(+mupsu&1H1?}ex!eh z_~)Alz5?Lk`i=OF%!7Z{{?{6Up8OBL2Ar!HckO?jJC3aKN?Q{ILOe^!W$j{by_cT0``%0=yRRA8J6`+x34Q z;8jumM|dIM9~DGTjN>2c57dV~Y^5OhI{>c%>?8H9V4)78zw^N6`U%%xn7iAxe;DB5 z{)yxtpxQ8DhHxZ!TFE#(^h?l{vmh+EPgv!H2x~U z!~EZ>-$-l_`|kl>?r-EDKi5Cb?~r?|{Xp#d0sP;w{|t-Y4UKQ3Aoi)a|FQodZCjy1 zbZr41&L8;vxScUT@Hqev&p%t;Hxb_u{0P9G{2SvZ#`E{)Uns!;o%O36;Nkfd>Cbla zXA22W`W)t&SstR}lDn z^EVpcp?%ozt;P=a53yej@G$?7xFPLO=Z^}aHxKa0`v=H@wEqzn-b3`bfb%L?`w+j~ z_y+(yTz?@aEJ!~#YybH#V!s05(dYlIo&yp59Kgfp@2%QJJVNliLjU~xC8QnE`%ez^~^Aq)-28%+T$Kt`@+f=igT6FoHh^@NoQL9mWo6N89>$pAo$(EFO*@ytbSF zi&*@2au520*yjeFhw}&VAKu$aLGXXqe|umb#vkF^ifyQa=%-=v$hwcT{}~UW*MY?& z@!M|xi-DKta(}~rUx0__hrjCo1i-`j5B-K0(vPk7|L^{O_5b?!7ysA4pZ&k?|KACwDONU$pUzJZ2XXWTak$WV*oFQ#c#(4 z1kVOGUpRla`rL!~hTu&A9@`cegE{}p&T$}NffDkZfE7@-BB8$aFYQeUV;cZ2IPPb$?OT!1 zpKx$Nz6dN1O4uHSt)nIE$0ck#TEhH`1sCLr!`_Dy>R-jyp@jG2v30bB?Fra+C}BMj zTZal?_gyCkg%X7)GGuRlttiz1xm6!MuC{ zE?CeK-hcJ0b!!sxH(~X+BliMKFBXTEFfZO=+o6Q~1K2v0u>Kxg(9a=o!2%_$kH88j zXbJU4f3^Ozg!&(_?NIIk*DSc8{V(8x1xl#*6_EbJ@xjL5 zN!Y}XZT}+)RRpklkYhLYf=zG^!tsIoJ1kJb`}<%86eyt{1+0Lw9SL!izfk|%=asN= zKuZ`OWo$c?FrU@1b+m+e@V|Y2GY`@GI}8=9!#F0u3Mf#*dLpcV0wt^`!3ro)!a90? zhwZQq{N}mffBXFZ_WA#R`}_}* zA8;c6Hw)m~f!X9mQ{#F^4V|VU_;E$0Ciyz)z85>=@E(UYSMU2Y+{B=4aq)BGUZt1h zs@{~Lr@jaatxP7Be$~Xe`NZwQQP0to%>7b2!6;t11|tQx!F}GpB_Z2#I^TFczMT9v z!)f+dx&7tR?F=sZuN>|l(;z6`qu}Pn7l$!PmZIA;y%9ITGu|Oob?NP$y9oiBqbOdu zw;}~s5cidLO3=Nk^T|IR^DP~4{wcz_*m210EK3UhxoQRq(Id*uP2U;Jh;TBS$uHev z6#n_rcUO*58uyhSyF>0yM4dwM!m|@na2Ic4bhN0&#qk4iZ*`r<&6PSrX4Dr|+?pwj zORKp%TKocc`igWMPUxLGe!7=3j_@xn7TQgHPivancbOvrb%#eR8a$K3HI!GPnErPNEm zcCjW&uR7B18*0-c#ovQ>4RF#)W|&_jHRWwPTl160d`&pVsa+19&5>~jq2y{{F)4S zs2+Mp-e4g}uS4;|y#pz@HW;_)69d`lyNGl1Vn5No_FJh{c$9Oc>r2N;R~4Qo1J?Ia zcpVc*^_ zw^Ht%{JBW;TEB-j=#a#@LbGoJzL(yO2$iqaKe% z$u2Cey0zlmEKy?f6ALwc?v9U+12LM{)H9-z`~2mOS_R6}R`d~bB&x}a^u`W3@t!CivU(2Qf{5A0qTCA=aXFaEhLT8tcL ziQl1t7sX48=KVo8`106odq%C11gQ(ew{2y14UZpeAurs`&q{Fy#Y=|f{d!Se;CmjAd&0G{t3}dAPn3%V1bJ&0 z3h!rTUNVjd_)3#ALe;&|<*xeH$)Db2Y3Uq|HTl!=nopClcfMMk2Y<)jdurWzdakmv|>szRpCx$Id({0Jn(%K-4VR(G%$nA4LBG7g?nnFgn^?pKTW~Pag?>Lo-k}tW;-x_Q>n44pcV4=_yF9APgxfRc zN%*wk!pE`O<<2fR?>!FI%)4Cq_PJcoe5%WLO?H6{+e#4+u9=ostNl@I^h zr-;9lXx>5ocMG3*>$J}09LJ4ocYJtdRceUUw`^9gO>ej*HL^|QsIL>1dGoE0XGxXM zZ|rUx#MB3chS8k3aG&WzI$=i|ikAw_J463n(Ug6fW@2^_^ZmOaU-{19r)g`(rtj9y zzGGKNnvvpoYC-0Aj^uS}(A+}qan{inB|Mo883GnF%Jd?kGw>Y(;x9Ft*R+_Z-mKwR z2bY{qaFyjK2R~<#{rGI!g3e>Q8+BJ6dX*hO)&3&E*&CA{)V$(29FnCzca?VOdB#5v+Xzwc{*RbG=3V4L)4X!*(jL99Z zJ-{;-B~>l))ptg@Au><%HYTOhp}Uh-DnJe8FD;rkf2{PF!46GZykWBM!3J@J`(l^5 zU4+jhlBE%Ot`Hh~^}h8!W>;>1$by7PnW6QHXwF;A?3;kV`^Tm;>`wPoIH7py(7ax_ z^LxfMf3}d`bG{cSW7`s_o48T2zdk(ZTd!cL)7Z)dr-|ETkA6y9Tq>(+9hbqj>4jy!6>iHX+iD1R^h<2FA4SIZsv(CXbZKIRs-e=)Ec# zFBc~|nBdaM?&M%$*%J{VA&cT=Li36{7|EwCzgo`1Su*X7+v(dAMc!0mCf}RIE9*hX zl1`>UR82}bZkQP#=zQVmv5r%YHdHIQMTKjVGESKyA5Oq`e~7>P(Y)*W)-fGRa^&q< zorN4K1&;T>>+KYf8-D4AA8eMec8s$qw1QK9?;g%CO1BE4D3Ff z2X^9l9}f4nc^(<}&OIFyN@@Ch-IQr9M(=~9>49CtczjJm4bk_$PNH~O(Y#inlrk&> z1xK9-uG%TQn^W^IsG45O^1PI7moS-CSP~#c+b)-MvWlI$M|C*QjqHN;>6)%f_%j9V zj}%MGRrEffc-hdr1*0d-^tw)1F7t-!Xa`6e?4=oPqD!aYoG8^vZNu%kcWPg=n3M*W z54-29{hk}w)P!}ZYC@*O$2W4iY=n*yz;~g@xUr*oYm2TZ5m+5OhM#vg{O$o$x|b~+ zPIP%GWQRFbF3eq+Nz(fH`sMB%;ef>-<$jd{W8;w5Ho{%InOO{9R9zgR7alUSCh!H1Zs@*Z!t{{|i*6kVbgE&4-`XHBpOQqAX zlmu~|NA^tjf4)#Tkv7Px+e(64?e$*7jNEBYuZ~6d1d8_{nz!{{a1pEAapQNf913ps zj-1-9=8w%QjuUA!7!6!-Cpi;vc)-Loac8>Mt)53ht6>un-5;rLR=mTLdpaRoD~y`rfEy1Pdi;mu8pJ#@EYX-tLt? z|3q^SikAn?d#N~GUq^D(i&T?}`*oq>c{`s+TFvB!x(D~}9=ZIIF_op!kT#`#fu)Ty zQ*>XV+sh|9Jh)k96WnjoZ*tc>v__w!c+tEW3DTdEo7}96f}XKb7*iHuRM-Vb%YrCh zOhy`RbhxXZWsFKsKVr(r$>v5c-)TW>8tqqC`>m}EH&JASYTP^sP3`b{%$=H7(WTd4 z9k+L+I;uD-Q(iln>7rg_XMb$o%2`|M`#6cV8G%@-vgTPMzc=EMc|I}>!b*p_rJJKilTY{i|gbeH1B_L zoji=@mGP!{SyiZF^UN?Tqoy!BH(_Jyg;JeuE4lA;;lZ)P&&V$~3)q)hrtN4Yx?GaL zaYXHE1)gZ?@dPXS={FAy8qv=!;Af-172J!Y?d&-udI}1&o$XRhADk!K^OzUU);5&e zPx@QQpBJE#b?o<~Z2m08uJnOpVyf=7>yHyDZ_l+l_Fr}NZfl%I<(c?ztRT;DABbt0 z>Y8}YCqLmB;;ytRW?d`dstYKhp`waczg*$df36f~opZgIvMhcC=Y_Db#hKe=uJ&gO z)J5wEL|=|Nqj)9Iyox~@{24ZBS&fXe!(Vq;D6-L;@21QRdGf&eg2&yVp(3lZ`X{w$ zRts*u(|F`K%fq&?KZAux@gd7DHV5@mb|y9yuOyoHN|4jL!w#1Hwngt9i6y5`FMHo* zw5G59{A~{xkM=`<{}Qv71MZp@n&u}hG(O(V73}|hBQKYqD0bcQ-8(TATl9HS3e7t| zf0K&-)QjM?!C~XV+Ip4quFt9O?iQ@J!O6NIil26dak8w?^mTZ%UNnT<*h+=?vSOu66b1{E-38U~6WNLIxC39b2?5cgJh(1Tjp#8mnYi56Wy2bfX64ztI zqn%1|qw863WiEZA*G)`(zj15egPOE@`grG8iqFSFn-XsF_7Ppw+Tm`5>1etk|7j@_ z{?A2`a|!bMo?rg1z7y7#qa}8fw9x({u+G=OQ(4(Z-p6HijkgkydHPhw`}kmWi#KI4hsdr^=Z13(-#qgt^0df&_2A1p zmPcb=3HAFlmX@0G1B4Z9SewQd38J_hU(+&=kI%6+zZEOm&!YN>_Hv6JidPQJJ9jkg zVCO*Z5AGa6E)$uVda8!6d%udFZfqQzHT^JIUd{YCp7YVt&940t!*6TeJeKY-lkdAY zL$w3H`$kBi%EKBI?@=_b;hSD%1*u+oo}Wmfw%n_ub5!sIQ~BduJ<`V|^c^T(c{J~es8{U_hkLS?$&NPe0Lu=? zcEz%f&xMS$ZF6KVHIk^4Di$f6j84O)ENRe_eN#W*fAn+D8qTQ)D&rg?;cH9i^P~cr zcebarmEy=MYo2J_hoU>LmCRmo-tIY7$1-igY44G_?AS-n&|pkv_x!tZ^4t@58LjHO z&-y*}q`Agfn&$I)E~D26MKo`@u``Ejy^mPhP8J8}Fz>*C`z(8LC*G2HW(;b+ediqZ zFjBtvzP(-6-QjO8ksc>htAxIkQu*m6$*tP(d%88FpNEj|i6K31S8_w^1QU^^3VYZA zjk4pfrFX}4`jYGer3m7go9 z3HO{|ezPN0Y3-2e6<^7p;i}x#x7JYOrhp|Jh(DWXLVtRpQ^7uOBD^L?mLysBv41eLtYC3YY9P&7g5W225 zd(~?cHf$Ej87N-l`*lcJp1PLTyi=n#x6@U) ziE-(S{S_-$?-a`);gs`!c6ud6Ds#v6_c5+YuA|?ls-yk=FP=-__y0)2{V$$NG!RlC zasP|w5=}JkfAL(Rh35S)o=c9SdDrj`w+_Z?$Wj}glXqEpdvSNSivB!4@jE$S}nN7AC*T6ZugrkvThM^>bKv0 zQD+V$4`jF9u1elvlC`mm{v5lzZTO*%tArAlPx>#;wW-{T+P$ZupquFO%Ty^^m{pNw7+S-lE;=8Sh>_0ddzt?#;%c0F#B?iU1M(IW!R}Dsr6)UkopBYW7{ag z;!87TdRpSC{>f=7NfG&Xct@zNhsMOA{MAA8R-bfWCQYfm(YCJ0bfk_|QmrkB-Lad6 ztdW@^LWXtJu*}d?kE3!a;A_8{XBs}PpUBJ0#20RxUM#9`o04i(Ek*I_qInnM_QklW z3yv1q;LhKsnNz(`9TFxeV-Z`?UUj>gIqt}zAGdM7>g^_#wwzdS<8km3@;-1UEhb0) z>2aqM4p|)NeMk?@I}{$sDACyIvB#Yv@1viB@1s_VrBkNiMn$APQugn;bBT!!bXrKc z+Zyt1E(rKc3eN}HTL?T?FFO8IZs@xywJ^$GeKhYah21kB`wv#|h;?TVEhQHRKD-#} zA$h!FJRo_LEByyJcDRCWSDcp58Xzas23?6dB{m{m&iW_mOt;taJnp7-=P_9c_~N#MN!sg%b5h`h7K+yp%}dfxa_(4jlIiTg<>n3<8vf5= zOZe8qD*^_1^kOPHbWef9N#zP_FDc@k6>o?@;l=BzlR9<)0T(yhdo= z)GWE%>s%=f6+50}=!U3iUgi_et$0aDeGH#XeM9%4xSuf7_+Ecc%*SK9Qr^wm%xFDi zCynNqz0@FzfBqtkD*Af{V>GXs5!I8$1Cz8x#@%W!rVGk$b$yM_4DacdmX>+IG1@&<%#YctH(k)uOmi%l~Degpm}xD26#Cpl9bX8 E_ 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 { + test(`parseLine ${langTestCases.lang}: ${testCase.term}`, () => { const { reading } = parseLine(testCase.line, langTestCases.lang); - t.is(reading, testCase.expectedReading); + expect(reading).toBe(testCase.expectedReading); }); } } From 37d7c09f3e05856368823d0ed006446bf132b1db Mon Sep 17 00:00:00 2001 From: MarvNC Date: Thu, 11 Jul 2024 16:05:08 -0700 Subject: [PATCH 09/26] Fix build for bun --- bun.lockb | Bin 8523 -> 8523 bytes readme.md | 19 +++++++++++++++++++ src/index.ts | 38 +++++++++++++++++++++++--------------- 3 files changed, 42 insertions(+), 15 deletions(-) diff --git a/bun.lockb b/bun.lockb index 4976cef975f055ba17b233c072eabfea2d92b721..011943596393ba86c7b4622b95319f5f5347eba2 100644 GIT binary patch delta 20 bcmX@@blPddZ*g{}oWzpU;*!lw5}up@T-gVb delta 20 bcmX@@blPddZ*g`;Lp?)1GltDf5}up@PtXPU diff --git a/readme.md b/readme.md index 023eb09..65e32f0 100644 --- a/readme.md +++ b/readme.md @@ -55,3 +55,22 @@ div.gloss-sc-div[data-sc-wikipedia='term-specifier'] { ## License The code in this repository is licensed under the MIT license. + +## Dev + +This project uses bun. + +To download the abstracts for a language, run: + +```sh +/src/downloadDump.sh ja 2022.12.01 +``` + +To build a dictionary, run: + +```sh +bun run start ja 2022-12-01 +``` + +where `ja` is the language code and `2022.12.01` is the date of the dump (there +are no newer DBPedia versions). diff --git a/src/index.ts b/src/index.ts index d2b9c0d..ac71f01 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,6 +1,4 @@ -import fs from 'fs'; -import path from 'path'; -import readline from 'readline'; +import { file } from 'bun'; import { Dictionary, TermEntry } from 'yomichan-dict-builder'; import { parseLine } from './parse/parseLine'; @@ -27,11 +25,9 @@ const shortAbstractFile = (lang: string) => console.log(`Converting ${lang} Wikipedia dump from ${date}...`); const filePath = shortAbstractFile(lang); - const fileStream = fs.createReadStream(filePath); - const lineReader = readline.createInterface({ - input: fileStream, - crlfDelay: Infinity, - }); + const fileHandle = file(filePath); + const fileReader = fileHandle.stream(); + const lineReader = fileReader.getReader(); const dict = new Dictionary({ // @ts-ignore @@ -39,11 +35,24 @@ const shortAbstractFile = (lang: string) => }); let processedLines = 0; - for await (const line of lineReader) { - await processLine(line, dict, lang); - processedLines++; - if (processedLines % 1000 === 0) { - console.log(`Processed ${processedLines} lines`); + let buffer = ''; + + while (true) { + const { done, value } = await lineReader.read(); + if (done) break; + + buffer += new TextDecoder().decode(value); + let lineEnd; + + while ((lineEnd = buffer.indexOf('\n')) !== -1) { + const line = buffer.slice(0, lineEnd); + await processLine(line.trim(), dict, lang); + buffer = buffer.slice(lineEnd + 1); + processedLines++; + + if (processedLines % 1000 === 0) { + console.log(`Processed ${processedLines} lines`); + } } } @@ -154,8 +163,7 @@ function processLine(line: string, dict: Dictionary, lang: string) { function readArgs() { // Read arguments: node convertWikipedia.js [language] [date of dump] - const langInput = - process.argv[2].toLowerCase() as keyof typeof languages; + const langInput = process.argv[2].toLowerCase() as keyof typeof languages; // Assert language is valid if (!languages[langInput]) { throw new Error( From 93ae2248b8f147ab1deb83e1c9ffc90fcf44499d Mon Sep 17 00:00:00 2001 From: MarvNC Date: Thu, 11 Jul 2024 16:08:03 -0700 Subject: [PATCH 10/26] Bump yomichan-dict-builder --- bun.lockb | Bin 8523 -> 8523 bytes package.json | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/bun.lockb b/bun.lockb index 011943596393ba86c7b4622b95319f5f5347eba2..8bc8485db4a520d0c7cfbaf895d2015354201afb 100644 GIT binary patch delta 152 zcmV;J0B8TpLd!ysE+7au)f_WYP4xE}wz@SSVQtIf))F1@s&w?VN~kMOM?0}j;sFH$ z00006li>j?vtRNK>DMKP?b5nn z`IX18g!$0aRxj;vtR+3BnEs0bVgKGcGc-HW(%Y12HZ$ MlRzCIvw$1R1&oV9NdN!< diff --git a/package.json b/package.json index 0063eef..bccb28c 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ }, "dependencies": { "pinyin-pro": "^3.18.5", - "yomichan-dict-builder": "^1.3.2" + "yomichan-dict-builder": "^2.6.0" }, "type": "module", "devDependencies": { From 9a8ede8e8c5cce6aa9ef071a33603e01afe37382 Mon Sep 17 00:00:00 2001 From: MarvNC Date: Thu, 11 Jul 2024 16:27:45 -0700 Subject: [PATCH 11/26] Update getVersion for bun --- src/util/getVersion.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/util/getVersion.ts b/src/util/getVersion.ts index d7ea6b5..ed44417 100644 --- a/src/util/getVersion.ts +++ b/src/util/getVersion.ts @@ -1,9 +1,8 @@ -import fs from 'fs'; -import path from 'path'; +import { file } from 'bun'; -export function getVersion(): string { - const packageJsonPath = path.join(process.cwd(), 'package.json'); - const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8')); +export async function getVersion(): Promise { + const packageJsonPath = `${import.meta.dir}/../package.json`; + const packageJson = await file(packageJsonPath).json(); if (!packageJson.version) { throw new Error('Could not get version from package.json'); } From 919a97ca63bf8314ebbb79538cac4a24d2d7387b Mon Sep 17 00:00:00 2001 From: MarvNC Date: Thu, 11 Jul 2024 16:41:06 -0700 Subject: [PATCH 12/26] Use bun args --- readme.md | 2 +- src/index.ts | 41 +++++++++++++++++++++++++++++++---------- src/util/getVersion.ts | 18 +++++++++++++----- 3 files changed, 45 insertions(+), 16 deletions(-) diff --git a/readme.md b/readme.md index 65e32f0..5c8c440 100644 --- a/readme.md +++ b/readme.md @@ -69,7 +69,7 @@ To download the abstracts for a language, run: To build a dictionary, run: ```sh -bun run start ja 2022-12-01 +bun run start -l ja -d 2022-12-01 ``` where `ja` is the language code and `2022.12.01` is the date of the dump (there diff --git a/src/index.ts b/src/index.ts index ac71f01..58358bf 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,5 +1,6 @@ import { file } from 'bun'; import { Dictionary, TermEntry } from 'yomichan-dict-builder'; +import { parseArgs } from 'util'; import { parseLine } from './parse/parseLine'; import { languages } from './constants'; @@ -17,7 +18,7 @@ const shortAbstractFile = (lang: string) => `short-abstracts_lang=${lang.toLowerCase()}.ttl`; (async () => { - const version = getVersion(); + const version = await getVersion(); console.log(`Using version ${version}`); @@ -60,7 +61,7 @@ const shortAbstractFile = (lang: string) => await dict.setIndex({ title: `${lang} Wikipedia [${date}] (v${version})`, - revision: `wikipedia_${new Date().toISOString()}`, + revision: `wikipedia_${version}`, format: 3, url: 'https://github.com/MarvNC/wikipedia-yomitan', description: `Wikipedia short abstracts from the DBPedia dataset available at https://databus.dbpedia.org/dbpedia/text/short-abstracts. @@ -162,23 +163,43 @@ function processLine(line: string, dict: Dictionary, lang: string) { } function readArgs() { - // Read arguments: node convertWikipedia.js [language] [date of dump] - const langInput = process.argv[2].toLowerCase() as keyof typeof languages; + const { values } = parseArgs({ + options: { + lang: { + type: 'string', + short: 'l', + }, + date: { + type: 'string', + short: 'd', + }, + }, + strict: true, + allowPositionals: false, + }); + + const langInput = ( + values.lang as string + )?.toLowerCase() as keyof typeof languages; + const dateInput = values.date as string; + // Assert language is valid - if (!languages[langInput]) { + if (!langInput || !languages[langInput]) { throw new Error( - `Language ${langInput} is not allowed. Allowed languages: ${Object.keys( + `Language ${langInput} is not allowed or not provided. Allowed languages: ${Object.keys( languages ).join(', ')}` ); } - const lang = languages[langInput]; + const lang = languages[langInput] as keyof typeof languages; - const dateInput = process.argv[3]; // Assert date is valid in format YYYY-MM-DD - if (!/^\d{4}-\d{2}-\d{2}$/.test(dateInput)) { - throw new Error(`Date ${dateInput} is not valid. Format: YYYY-MM-DD`); + if (!dateInput || !/^\d{4}-\d{2}-\d{2}$/.test(dateInput)) { + throw new Error( + `Date ${dateInput} is not valid or not provided. Format: YYYY-MM-DD` + ); } + return { lang, date: dateInput }; } diff --git a/src/util/getVersion.ts b/src/util/getVersion.ts index ed44417..e7c8d94 100644 --- a/src/util/getVersion.ts +++ b/src/util/getVersion.ts @@ -1,10 +1,18 @@ import { file } from 'bun'; +import { join } from 'path'; export async function getVersion(): Promise { - const packageJsonPath = `${import.meta.dir}/../package.json`; - const packageJson = await file(packageJsonPath).json(); - if (!packageJson.version) { - throw new Error('Could not get version from package.json'); + const packageJsonPath = join(process.cwd(), 'package.json'); + try { + const packageJson = await file(packageJsonPath).json(); + if (!packageJson.version) { + throw new Error('Version not found in package.json'); + } + return packageJson.version; + } catch (error) { + if (error instanceof Error) { + throw new Error(`Failed to read package.json: ${error.message}`); + } + throw error; } - return packageJson.version; } From ea6b02774902756324b7afe057abe2b81e9f455f Mon Sep 17 00:00:00 2001 From: MarvNC Date: Thu, 11 Jul 2024 17:13:40 -0700 Subject: [PATCH 13/26] Use progress bar --- bun.lockb | Bin 8523 -> 11137 bytes package.json | 4 +++- src/constants.ts | 1 + src/index.ts | 19 +++++++++++++------ 4 files changed, 17 insertions(+), 7 deletions(-) diff --git a/bun.lockb b/bun.lockb index 8bc8485db4a520d0c7cfbaf895d2015354201afb..c2b86d4d117e1701990d8bbb4ebc2a163f11f256 100644 GIT binary patch delta 2834 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 diff --git a/package.json b/package.json index bccb28c..17b286e 100644 --- a/package.json +++ b/package.json @@ -4,12 +4,14 @@ "start": "bun run src/index.ts" }, "dependencies": { + "cli-progress": "^3.12.0", "pinyin-pro": "^3.18.5", "yomichan-dict-builder": "^2.6.0" }, "type": "module", "devDependencies": { - "@types/bun": "latest" + "@types/bun": "latest", + "@types/cli-progress": "^3.11.6" }, "name": "wikipedia-yomitan", "peerDependencies": { diff --git a/src/constants.ts b/src/constants.ts index 24399b0..ad78fdf 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -2,3 +2,4 @@ export const languages = { ja: 'JA', zh: 'ZH', }; +export const linkCharacter = '⧉'; diff --git a/src/index.ts b/src/index.ts index 58358bf..7173d37 100644 --- a/src/index.ts +++ b/src/index.ts @@ -3,14 +3,14 @@ import { Dictionary, TermEntry } from 'yomichan-dict-builder'; import { parseArgs } from 'util'; import { parseLine } from './parse/parseLine'; -import { languages } from './constants'; +import { languages, linkCharacter } from './constants'; import { getVersion } from './util/getVersion'; import type { StructuredContent, StructuredContentNode, } from 'yomichan-dict-builder/dist/types/yomitan/termbank'; -const linkCharacter = '⧉'; +import * as cliProgress from 'cli-progress'; const outputZipName = (lang: string, date: string, version: string) => `${lang} Wikipedia [${date}] (v${version}).zip`; @@ -37,6 +37,13 @@ const shortAbstractFile = (lang: string) => let processedLines = 0; let buffer = ''; + const progressBar = new cliProgress.SingleBar({ + format: `{value} lines | {file}`, + }); + + progressBar.start(0, 0, { + file: filePath, + }); while (true) { const { done, value } = await lineReader.read(); @@ -51,16 +58,16 @@ const shortAbstractFile = (lang: string) => buffer = buffer.slice(lineEnd + 1); processedLines++; - if (processedLines % 1000 === 0) { - console.log(`Processed ${processedLines} lines`); - } + progressBar.update(processedLines); } } + progressBar.stop(); + console.log(`Processed ${processedLines} lines, exporting zip...`); await dict.setIndex({ - title: `${lang} Wikipedia [${date}] (v${version})`, + title: `${lang.toUpperCase()} Wikipedia [${date}] (v${version})`, revision: `wikipedia_${version}`, format: 3, url: 'https://github.com/MarvNC/wikipedia-yomitan', From d3b3df2a949ddf81ea1f71a6a789ef35a35e10be Mon Sep 17 00:00:00 2001 From: MarvNC Date: Thu, 11 Jul 2024 18:08:51 -0700 Subject: [PATCH 14/26] Move downloads to ts --- .gitignore | 2 +- readme.md | 10 +++----- src/downloadDump.sh | 23 ------------------- src/index.ts | 9 ++++---- src/util/downloadDumps.ts | 48 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 57 insertions(+), 35 deletions(-) delete mode 100755 src/downloadDump.sh create mode 100644 src/util/downloadDumps.ts diff --git a/.gitignore b/.gitignore index 929e9d1..3b44fc6 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,7 @@ *.bz2 *.zip -.tsimp +/download # Created by https://www.toptal.com/developers/gitignore/api/node # Edit at https://www.toptal.com/developers/gitignore?templates=node diff --git a/readme.md b/readme.md index 5c8c440..2fadfed 100644 --- a/readme.md +++ b/readme.md @@ -60,13 +60,7 @@ The code in this repository is licensed under the MIT license. This project uses bun. -To download the abstracts for a language, run: - -```sh -/src/downloadDump.sh ja 2022.12.01 -``` - -To build a dictionary, run: +To download and build a dictionary, run: ```sh bun run start -l ja -d 2022-12-01 @@ -74,3 +68,5 @@ bun run start -l ja -d 2022-12-01 where `ja` is the language code and `2022.12.01` is the date of the dump (there are no newer DBPedia versions). + +You must be running this in linux with `bzip2` installed. diff --git a/src/downloadDump.sh b/src/downloadDump.sh deleted file mode 100755 index 3af78c2..0000000 --- a/src/downloadDump.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/bash - -# Check for two arguments: language (en, de, fr, ...) and date (yyyy.mm.dd) -if [ $# -ne 2 ]; then - echo "Usage: $0 " - exit 1 -fi - -ARCHIVE="short-abstracts_lang=$1.ttl.bz2" -URL="https://databus.dbpedia.org/dbpedia/text/short-abstracts/$2/$ARCHIVE" -FILE="short-abstracts_lang=$1.ttl" - -# Download the archive if neither the file nor archive exists -if [ ! -f "$FILE" ] && [ ! -f "$ARCHIVE" ]; then - echo "Downloading $URL" - wget "$URL" -fi - -# Extract the archive if it does not exist -if [ ! -f "$FILE" ]; then - echo "Extracting $ARCHIVE" - bzip2 -dc "$ARCHIVE" >"$FILE" -fi diff --git a/src/index.ts b/src/index.ts index 7173d37..b0a0769 100644 --- a/src/index.ts +++ b/src/index.ts @@ -11,11 +11,10 @@ import type { } from 'yomichan-dict-builder/dist/types/yomitan/termbank'; import * as cliProgress from 'cli-progress'; +import { downloadDumps } from './util/downloadDumps'; const outputZipName = (lang: string, date: string, version: string) => `${lang} Wikipedia [${date}] (v${version}).zip`; -const shortAbstractFile = (lang: string) => - `short-abstracts_lang=${lang.toLowerCase()}.ttl`; (async () => { const version = await getVersion(); @@ -23,9 +22,11 @@ const shortAbstractFile = (lang: string) => console.log(`Using version ${version}`); const { lang, date } = readArgs(); - console.log(`Converting ${lang} Wikipedia dump from ${date}...`); - const filePath = shortAbstractFile(lang); + + console.log(`Converting ${lang} Wikipedia dump from ${date}...`); + + const filePath = await downloadDumps(lang, date); const fileHandle = file(filePath); const fileReader = fileHandle.stream(); const lineReader = fileReader.getReader(); diff --git a/src/util/downloadDumps.ts b/src/util/downloadDumps.ts new file mode 100644 index 0000000..06112d3 --- /dev/null +++ b/src/util/downloadDumps.ts @@ -0,0 +1,48 @@ +import { $ } from 'bun'; +import { exists } from 'node:fs/promises'; +import { join } from 'path'; + +const ARCHIVE = (lang: string) => + `short-abstracts_lang=${lang.toLowerCase()}.ttl.bz2`; +const FILE = (lang: string) => `short-abstracts_lang=${lang.toLowerCase()}.ttl`; +const URL = (lang: string, date: string) => + `https://databus.dbpedia.org/dbpedia/text/short-abstracts/${date}/${ARCHIVE( + lang + )}`; +const DOWNLOAD_DIR = './download'; + +export async function downloadDumps(lang: string, date: string) { + // Replace - with . in date + date = date.replace(/-/g, '.'); + // Check if lang is in format YYYY.MM.DD + if (!/^\d{4}\.\d{2}\.\d{2}$/.test(date)) { + throw new Error(`Invalid date format: ${date}`); + } + + // TODO: Check lang + + // Check if download directory exists + if (!(await exists(DOWNLOAD_DIR))) { + await $`mkdir ${DOWNLOAD_DIR}`; + } + + const archivePath = join(DOWNLOAD_DIR, ARCHIVE(lang)); + const filePath = join(DOWNLOAD_DIR, FILE(lang)); + const archiveExists = await exists(archivePath); + const fileExists = await exists(filePath); + + // Download the archive if neither the file nor archive exists + if (!fileExists && !archiveExists) { + const url = URL(lang, date); + console.log(`Downloading ${url}`); + await $`wget ${url} -O ${archivePath}`; + } + + // Extract the archive if it does not exist + if (!fileExists) { + console.log(`Extracting ${archivePath}`); + await $`bzip2 -dc ${archivePath} >${filePath}`; + } + + return filePath; +} From 2a0bc519b3c8b3b76afc5d8167b974fb3ae6c39e Mon Sep 17 00:00:00 2001 From: MarvNC Date: Thu, 11 Jul 2024 18:20:26 -0700 Subject: [PATCH 15/26] Comments --- src/index.ts | 3 +-- src/parse/parseLine.ts | 5 +---- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/index.ts b/src/index.ts index b0a0769..c4cf74f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -23,9 +23,8 @@ const outputZipName = (lang: string, date: string, version: string) => const { lang, date } = readArgs(); - console.log(`Converting ${lang} Wikipedia dump from ${date}...`); - + const filePath = await downloadDumps(lang, date); const fileHandle = file(filePath); const fileReader = fileHandle.stream(); diff --git a/src/parse/parseLine.ts b/src/parse/parseLine.ts index 6fdeee7..641a854 100644 --- a/src/parse/parseLine.ts +++ b/src/parse/parseLine.ts @@ -11,10 +11,7 @@ type ParsedLine = { }; /** - * - * @param {string} line - * @param {typeof languages[keyof typeof languages]} lang - * @returns {ParsedLine} + * Parses a line of text and extracts relevant information. */ function parseLine( line: string, From 1afc4a446380e8355101ec19269a8716d3502a1a Mon Sep 17 00:00:00 2001 From: MarvNC Date: Thu, 11 Jul 2024 18:21:18 -0700 Subject: [PATCH 16/26] move readArgs --- src/index.ts | 44 +------------------------------------------- src/util/readArgs.ts | 44 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 43 deletions(-) create mode 100644 src/util/readArgs.ts diff --git a/src/index.ts b/src/index.ts index c4cf74f..e4fde48 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,6 +1,5 @@ import { file } from 'bun'; import { Dictionary, TermEntry } from 'yomichan-dict-builder'; -import { parseArgs } from 'util'; import { parseLine } from './parse/parseLine'; import { languages, linkCharacter } from './constants'; @@ -12,6 +11,7 @@ import type { import * as cliProgress from 'cli-progress'; import { downloadDumps } from './util/downloadDumps'; +import { readArgs } from './util/readArgs'; const outputZipName = (lang: string, date: string, version: string) => `${lang} Wikipedia [${date}] (v${version}).zip`; @@ -168,45 +168,3 @@ function processLine(line: string, dict: Dictionary, lang: string) { dict.addTerm(termEntry.build()); } - -function readArgs() { - const { values } = parseArgs({ - options: { - lang: { - type: 'string', - short: 'l', - }, - date: { - type: 'string', - short: 'd', - }, - }, - strict: true, - allowPositionals: false, - }); - - const langInput = ( - values.lang as string - )?.toLowerCase() as keyof typeof languages; - const dateInput = values.date as string; - - // Assert language is valid - if (!langInput || !languages[langInput]) { - throw new Error( - `Language ${langInput} is not allowed or not provided. Allowed languages: ${Object.keys( - languages - ).join(', ')}` - ); - } - - const lang = languages[langInput] as keyof typeof languages; - - // Assert date is valid in format YYYY-MM-DD - if (!dateInput || !/^\d{4}-\d{2}-\d{2}$/.test(dateInput)) { - throw new Error( - `Date ${dateInput} is not valid or not provided. Format: YYYY-MM-DD` - ); - } - - return { lang, date: dateInput }; -} diff --git a/src/util/readArgs.ts b/src/util/readArgs.ts new file mode 100644 index 0000000..ae12174 --- /dev/null +++ b/src/util/readArgs.ts @@ -0,0 +1,44 @@ +import { parseArgs } from "util"; +import { languages } from "../constants"; + +export function readArgs() { + const { values } = parseArgs({ + options: { + lang: { + type: 'string', + short: 'l', + }, + date: { + type: 'string', + short: 'd', + }, + }, + strict: true, + allowPositionals: false, + }); + + const langInput = ( + values.lang as string + )?.toLowerCase() as keyof typeof languages; + const dateInput = values.date as string; + + // Assert language is valid + if (!langInput || !languages[langInput]) { + throw new Error( + `Language ${langInput} is not allowed or not provided. Allowed languages: ${Object.keys( + languages + ).join(', ')}` + ); + } + + const lang = languages[langInput] as keyof typeof languages; + + // Assert date is valid in format YYYY-MM-DD + if (!dateInput || !/^\d{4}-\d{2}-\d{2}$/.test(dateInput)) { + throw new Error( + `Date ${dateInput} is not valid or not provided. Format: YYYY-MM-DD` + ); + } + + return { lang, date: dateInput }; +} From 51293855136876df8693b02f801fe7766e9f12eb Mon Sep 17 00:00:00 2001 From: MarvNC Date: Thu, 11 Jul 2024 18:32:39 -0700 Subject: [PATCH 17/26] Split out processLine --- src/index.ts | 87 ++----------------------------------- src/yomitan/processLine.ts | 89 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 93 insertions(+), 83 deletions(-) create mode 100644 src/yomitan/processLine.ts diff --git a/src/index.ts b/src/index.ts index e4fde48..9fd9b7b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -12,6 +12,7 @@ import type { import * as cliProgress from 'cli-progress'; import { downloadDumps } from './util/downloadDumps'; import { readArgs } from './util/readArgs'; +import { processLine } from './yomitan/processLine'; const outputZipName = (lang: string, date: string, version: string) => `${lang} Wikipedia [${date}] (v${version}).zip`; @@ -54,7 +55,9 @@ const outputZipName = (lang: string, date: string, version: string) => while ((lineEnd = buffer.indexOf('\n')) !== -1) { const line = buffer.slice(0, lineEnd); - await processLine(line.trim(), dict, lang); + + processLine(line.trim(), dict, lang); + buffer = buffer.slice(lineEnd + 1); processedLines++; @@ -86,85 +89,3 @@ div.gloss-sc-div[data-sc-wikipedia=term-specifier] { })().catch((e) => { console.error(e); }); - -/** - * Reads a line and adds that term entry to the dictionary - */ -function processLine(line: string, dict: Dictionary, lang: string) { - const { term, termSlug, termSpecifier, reading, definition } = parseLine( - line, - lang - ); - - const termEntry = new TermEntry(term); - termEntry.setReading(reading); - - const structuredContentList: StructuredContent[] = []; - - // Add term specifier heading if exists - if (termSpecifier) { - const specifierSCNode: StructuredContentNode = { - tag: 'div', - content: `«${termSpecifier}»`, - data: { - wikipedia: 'term-specifier', - }, - style: { - fontSize: '1.5em', - }, - }; - - structuredContentList.push(specifierSCNode); - } - - const definitionStrings = definition.split('\\n').map((line) => line.trim()); - const definitionUList: StructuredContentNode = { - tag: 'ul', - content: definitionStrings.map((definitionString) => ({ - tag: 'li', - content: definitionString, - })), - data: { - wikipedia: 'abstract', - }, - }; - structuredContentList.push(definitionUList); - - // Read more - const articleLink = `https://${lang.toLowerCase()}.wikipedia.org/wiki/${termSlug}`; - const readTheRest = - lang === languages.ja - ? '続きを読む' - : lang === languages.zh - ? '查看更多' - : 'Read more'; - const linkSC: StructuredContentNode = { - tag: 'ul', - content: [ - { - tag: 'li', - content: [ - { - tag: 'a', - href: articleLink, - content: readTheRest, - }, - ], - }, - ], - data: { - wikipedia: 'continue-reading', - }, - style: { - listStyleType: `"${linkCharacter}"`, - }, - }; - structuredContentList.push(linkSC); - - termEntry.addDetailedDefinition({ - type: 'structured-content', - content: structuredContentList, - }); - - dict.addTerm(termEntry.build()); -} diff --git a/src/yomitan/processLine.ts b/src/yomitan/processLine.ts new file mode 100644 index 0000000..86f22aa --- /dev/null +++ b/src/yomitan/processLine.ts @@ -0,0 +1,89 @@ +import { Dictionary, TermEntry } from 'yomichan-dict-builder'; +import { parseLine } from '../parse/parseLine'; +import { + StructuredContent, + StructuredContentNode, +} from 'yomichan-dict-builder/dist/types/yomitan/termbank'; +import { languages, linkCharacter } from '../constants'; + +/** + * Reads a line and adds that term entry to the dictionary + */ +export function processLine(line: string, dict: Dictionary, lang: string) { + const { term, termSlug, termSpecifier, reading, definition } = parseLine( + line, + lang + ); + + const termEntry = new TermEntry(term); + termEntry.setReading(reading); + + const structuredContentList: StructuredContent[] = []; + + // Add term specifier heading if exists + if (termSpecifier) { + const specifierSCNode: StructuredContentNode = { + tag: 'div', + content: `«${termSpecifier}»`, + data: { + wikipedia: 'term-specifier', + }, + style: { + fontSize: '1.5em', + }, + }; + + structuredContentList.push(specifierSCNode); + } + + const definitionStrings = definition.split('\\n').map((line) => line.trim()); + const definitionUList: StructuredContentNode = { + tag: 'ul', + content: definitionStrings.map((definitionString) => ({ + tag: 'li', + content: definitionString, + })), + data: { + wikipedia: 'abstract', + }, + }; + structuredContentList.push(definitionUList); + + // Read more + const articleLink = `https://${lang.toLowerCase()}.wikipedia.org/wiki/${termSlug}`; + const readTheRest = + lang === languages.ja + ? '続きを読む' + : lang === languages.zh + ? '查看更多' + : 'Read more'; + const linkSC: StructuredContentNode = { + tag: 'ul', + content: [ + { + tag: 'li', + content: [ + { + tag: 'a', + href: articleLink, + content: readTheRest, + }, + ], + }, + ], + data: { + wikipedia: 'continue-reading', + }, + style: { + listStyleType: `"${linkCharacter}"`, + }, + }; + structuredContentList.push(linkSC); + + termEntry.addDetailedDefinition({ + type: 'structured-content', + content: structuredContentList, + }); + + dict.addTerm(termEntry.build()); +} From 64abcd4fe9c03dcc8bccc34d5ca08194a39e1f2d Mon Sep 17 00:00:00 2001 From: MarvNC Date: Thu, 11 Jul 2024 18:48:23 -0700 Subject: [PATCH 18/26] Separate out `readAndProcessLines` function --- src/index.ts | 64 ++++++++++++++++++++++---------------- src/yomitan/processLine.ts | 1 + 2 files changed, 39 insertions(+), 26 deletions(-) diff --git a/src/index.ts b/src/index.ts index 9fd9b7b..ac10242 100644 --- a/src/index.ts +++ b/src/index.ts @@ -16,8 +16,10 @@ import { processLine } from './yomitan/processLine'; const outputZipName = (lang: string, date: string, version: string) => `${lang} Wikipedia [${date}] (v${version}).zip`; +const OUT_DIRECTORY = './out'; (async () => { + const dev = process.env.NODE_ENV === 'dev'; const version = await getVersion(); console.log(`Using version ${version}`); @@ -27,15 +29,42 @@ const outputZipName = (lang: string, date: string, version: string) => console.log(`Converting ${lang} Wikipedia dump from ${date}...`); const filePath = await downloadDumps(lang, date); - const fileHandle = file(filePath); - const fileReader = fileHandle.stream(); - const lineReader = fileReader.getReader(); const dict = new Dictionary({ // @ts-ignore fileName: outputZipName(lang, date, version), }); + const processedLines = await readAndProcessLines(filePath, dict, lang, dev); + + console.log(`Processed ${processedLines} lines, exporting zip...`); + + await dict.setIndex({ + title: `${lang.toUpperCase()} Wikipedia [${date}] (v${version})`, + revision: `wikipedia_${version}`, + format: 3, + url: 'https://github.com/MarvNC/wikipedia-yomitan', + description: `Wikipedia short abstracts from the DBPedia dataset available at https://databus.dbpedia.org/dbpedia/text/short-abstracts.`, + author: 'Marv', + attribution: `https://${lang.toLowerCase()}.wikipedia.org/`, + }); + + await dict.export(OUT_DIRECTORY); + console.log(`Exported to ${outputZipName(lang, date, version)}`); + process.exit(0); +})().catch((e) => { + console.error(e); +}); + +async function readAndProcessLines( + filePath: string, + dict: Dictionary, + lang: string, + dev: boolean +) { + const fileHandle = file(filePath); + const fileReader = fileHandle.stream(); + const lineReader = fileReader.getReader(); let processedLines = 0; let buffer = ''; const progressBar = new cliProgress.SingleBar({ @@ -62,30 +91,13 @@ const outputZipName = (lang: string, date: string, version: string) => processedLines++; progressBar.update(processedLines); + + if (processedLines >= 1000 && dev) { + return processedLines; + } } } progressBar.stop(); - - console.log(`Processed ${processedLines} lines, exporting zip...`); - - await dict.setIndex({ - title: `${lang.toUpperCase()} Wikipedia [${date}] (v${version})`, - revision: `wikipedia_${version}`, - format: 3, - url: 'https://github.com/MarvNC/wikipedia-yomitan', - description: `Wikipedia short abstracts from the DBPedia dataset available at https://databus.dbpedia.org/dbpedia/text/short-abstracts. - -Recommended custom CSS: -div.gloss-sc-div[data-sc-wikipedia=term-specifier] { - color: #e5007f; -}`, - author: 'Wikipedians, DBPedia, Marv', - attribution: `https://${lang.toLowerCase()}.wikipedia.org/`, - }); - - await dict.export('./'); - console.log(`Exported to ${outputZipName(lang, date, version)}`); -})().catch((e) => { - console.error(e); -}); + return processedLines; +} diff --git a/src/yomitan/processLine.ts b/src/yomitan/processLine.ts index 86f22aa..6c16d42 100644 --- a/src/yomitan/processLine.ts +++ b/src/yomitan/processLine.ts @@ -30,6 +30,7 @@ export function processLine(line: string, dict: Dictionary, lang: string) { }, style: { fontSize: '1.5em', + color: '#e5007f', }, }; From 2f622df5d5775a6006091620a78cd8437a10de2d Mon Sep 17 00:00:00 2001 From: MarvNC Date: Thu, 11 Jul 2024 18:49:07 -0700 Subject: [PATCH 19/26] Readme mention dev env --- readme.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/readme.md b/readme.md index 2fadfed..eb17cf1 100644 --- a/readme.md +++ b/readme.md @@ -70,3 +70,10 @@ where `ja` is the language code and `2022.12.01` is the date of the dump (there are no newer DBPedia versions). You must be running this in linux with `bzip2` installed. + +If you want to export a minimal dictionary with 1000 lines for testing, set an +environment variable: + +```sh +NODE_ENV=dev +``` From 593dc2bfe01631c3c429b8458aab78049a90c01a Mon Sep 17 00:00:00 2001 From: MarvNC Date: Thu, 11 Jul 2024 18:54:15 -0700 Subject: [PATCH 20/26] Refactor `processLine` --- src/index.ts | 8 +--- src/yomitan/processLine.ts | 95 +++++++++++++++++++++++++------------- 2 files changed, 65 insertions(+), 38 deletions(-) diff --git a/src/index.ts b/src/index.ts index ac10242..64961dc 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,13 +1,7 @@ import { file } from 'bun'; -import { Dictionary, TermEntry } from 'yomichan-dict-builder'; +import { Dictionary } from 'yomichan-dict-builder'; -import { parseLine } from './parse/parseLine'; -import { languages, linkCharacter } from './constants'; import { getVersion } from './util/getVersion'; -import type { - StructuredContent, - StructuredContentNode, -} from 'yomichan-dict-builder/dist/types/yomitan/termbank'; import * as cliProgress from 'cli-progress'; import { downloadDumps } from './util/downloadDumps'; diff --git a/src/yomitan/processLine.ts b/src/yomitan/processLine.ts index 6c16d42..f1780b6 100644 --- a/src/yomitan/processLine.ts +++ b/src/yomitan/processLine.ts @@ -14,31 +14,63 @@ export function processLine(line: string, dict: Dictionary, lang: string) { line, lang ); + const termEntry = createTermEntry(term, reading); + const structuredContentList = createStructuredContentList( + termSpecifier, + definition, + termSlug, + lang + ); + termEntry.addDetailedDefinition({ + type: 'structured-content', + content: structuredContentList, + }); + + dict.addTerm(termEntry.build()); +} + +// Helper functions +function createTermEntry(term: string, reading: string): TermEntry { const termEntry = new TermEntry(term); termEntry.setReading(reading); + return termEntry; +} +function createStructuredContentList( + termSpecifier: string | null, + definition: string, + termSlug: string, + lang: string +): StructuredContent[] { const structuredContentList: StructuredContent[] = []; - // Add term specifier heading if exists if (termSpecifier) { - const specifierSCNode: StructuredContentNode = { - tag: 'div', - content: `«${termSpecifier}»`, - data: { - wikipedia: 'term-specifier', - }, - style: { - fontSize: '1.5em', - color: '#e5007f', - }, - }; - - structuredContentList.push(specifierSCNode); + structuredContentList.push(createTermSpecifierNode(termSpecifier)); } + structuredContentList.push(createDefinitionNode(definition)); + structuredContentList.push(createReadMoreNode(termSlug, lang)); + + return structuredContentList; +} + +function createTermSpecifierNode(termSpecifier: string): StructuredContentNode { + return { + tag: 'div', + content: `«${termSpecifier}»`, + data: { + wikipedia: 'term-specifier', + }, + style: { + fontSize: '1.5em', + }, + }; +} + +function createDefinitionNode(definition: string): StructuredContentNode { const definitionStrings = definition.split('\\n').map((line) => line.trim()); - const definitionUList: StructuredContentNode = { + return { tag: 'ul', content: definitionStrings.map((definitionString) => ({ tag: 'li', @@ -48,17 +80,15 @@ export function processLine(line: string, dict: Dictionary, lang: string) { wikipedia: 'abstract', }, }; - structuredContentList.push(definitionUList); +} - // Read more +function createReadMoreNode( + termSlug: string, + lang: string +): StructuredContentNode { const articleLink = `https://${lang.toLowerCase()}.wikipedia.org/wiki/${termSlug}`; - const readTheRest = - lang === languages.ja - ? '続きを読む' - : lang === languages.zh - ? '查看更多' - : 'Read more'; - const linkSC: StructuredContentNode = { + const readTheRest = getReadMoreText(lang); + return { tag: 'ul', content: [ { @@ -79,12 +109,15 @@ export function processLine(line: string, dict: Dictionary, lang: string) { listStyleType: `"${linkCharacter}"`, }, }; - structuredContentList.push(linkSC); - - termEntry.addDetailedDefinition({ - type: 'structured-content', - content: structuredContentList, - }); +} - dict.addTerm(termEntry.build()); +function getReadMoreText(lang: string): string { + switch (lang) { + case languages.ja: + return '続きを読む'; + case languages.zh: + return '查看更多'; + default: + return 'Read more'; + } } From 783ee88723f20911444f1715514422dddd68ecfc Mon Sep 17 00:00:00 2001 From: MarvNC Date: Thu, 11 Jul 2024 18:57:45 -0700 Subject: [PATCH 21/26] Update header color --- src/yomitan/processLine.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/yomitan/processLine.ts b/src/yomitan/processLine.ts index f1780b6..b3fd74a 100644 --- a/src/yomitan/processLine.ts +++ b/src/yomitan/processLine.ts @@ -64,6 +64,7 @@ function createTermSpecifierNode(termSpecifier: string): StructuredContentNode { }, style: { fontSize: '1.5em', + color: '#e5007f', }, }; } From 8944b1f2419f82c86526f3aef2b050ff7cab95c7 Mon Sep 17 00:00:00 2001 From: MarvNC Date: Thu, 11 Jul 2024 18:57:54 -0700 Subject: [PATCH 22/26] Separate out `readAndProcessLines` --- src/index.ts | 50 +-------------------------------- src/util/readAndProcessLines.ts | 50 +++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 49 deletions(-) create mode 100644 src/util/readAndProcessLines.ts diff --git a/src/index.ts b/src/index.ts index 64961dc..41c4381 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,12 +1,10 @@ -import { file } from 'bun'; import { Dictionary } from 'yomichan-dict-builder'; import { getVersion } from './util/getVersion'; -import * as cliProgress from 'cli-progress'; import { downloadDumps } from './util/downloadDumps'; import { readArgs } from './util/readArgs'; -import { processLine } from './yomitan/processLine'; +import { readAndProcessLines } from './util/readAndProcessLines'; const outputZipName = (lang: string, date: string, version: string) => `${lang} Wikipedia [${date}] (v${version}).zip`; @@ -49,49 +47,3 @@ const OUT_DIRECTORY = './out'; })().catch((e) => { console.error(e); }); - -async function readAndProcessLines( - filePath: string, - dict: Dictionary, - lang: string, - dev: boolean -) { - const fileHandle = file(filePath); - const fileReader = fileHandle.stream(); - const lineReader = fileReader.getReader(); - let processedLines = 0; - let buffer = ''; - const progressBar = new cliProgress.SingleBar({ - format: `{value} lines | {file}`, - }); - - progressBar.start(0, 0, { - file: filePath, - }); - - while (true) { - const { done, value } = await lineReader.read(); - if (done) break; - - buffer += new TextDecoder().decode(value); - let lineEnd; - - while ((lineEnd = buffer.indexOf('\n')) !== -1) { - const line = buffer.slice(0, lineEnd); - - processLine(line.trim(), dict, lang); - - buffer = buffer.slice(lineEnd + 1); - processedLines++; - - progressBar.update(processedLines); - - if (processedLines >= 1000 && dev) { - return processedLines; - } - } - } - - progressBar.stop(); - return processedLines; -} diff --git a/src/util/readAndProcessLines.ts b/src/util/readAndProcessLines.ts new file mode 100644 index 0000000..ef95f96 --- /dev/null +++ b/src/util/readAndProcessLines.ts @@ -0,0 +1,50 @@ +import { file } from 'bun'; +import { Dictionary } from 'yomichan-dict-builder'; +import * as cliProgress from 'cli-progress'; +import { processLine } from '../yomitan/processLine'; + +export async function readAndProcessLines( + filePath: string, + dict: Dictionary, + lang: string, + dev: boolean +) { + const fileHandle = file(filePath); + const fileReader = fileHandle.stream(); + const lineReader = fileReader.getReader(); + let processedLines = 0; + let buffer = ''; + const progressBar = new cliProgress.SingleBar({ + format: `{value} lines | {file}`, + }); + + progressBar.start(0, 0, { + file: filePath, + }); + + while (true) { + const { done, value } = await lineReader.read(); + if (done) break; + + buffer += new TextDecoder().decode(value); + let lineEnd; + + while ((lineEnd = buffer.indexOf('\n')) !== -1) { + const line = buffer.slice(0, lineEnd); + + processLine(line.trim(), dict, lang); + + buffer = buffer.slice(lineEnd + 1); + processedLines++; + + progressBar.update(processedLines); + + if (processedLines >= 1000 && dev) { + return processedLines; + } + } + } + + progressBar.stop(); + return processedLines; +} From b5a0bc4cad2f770a0fca44c84f62754d314bb5e1 Mon Sep 17 00:00:00 2001 From: MarvNC Date: Thu, 11 Jul 2024 19:10:32 -0700 Subject: [PATCH 23/26] Rework footer --- assets/wikipedia-icon.png | Bin 0 -> 555 bytes src/constants.ts | 9 ++++++++- src/index.ts | 3 +++ src/yomitan/processLine.ts | 36 ++++++++++++++++++------------------ 4 files changed, 29 insertions(+), 19 deletions(-) create mode 100644 assets/wikipedia-icon.png diff --git a/assets/wikipedia-icon.png b/assets/wikipedia-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..4405b8d59ae181a457145da259ce983102029fdb GIT binary patch literal 555 zcmV+`0@VG9P)U2ueha-E1+&(^&v0cY`^|IV%wrkeqXIZreFmE;x>(v89w00F;?E zrF1&GZCi0%-wpLkA%x;!-}locIp+fCoNH|RzE95?01=%6gWiFqa#@z)Mc#WwL`B5r zGG^9wU5953JcMwv!N|e0ELf?$_a%BnJe8%sa}@m$z-SS18d0AGW^M%AZz4LCYzkoY zG6y3;)mgB2NAK0znAwK_DWw81i_A)eh|}mqzFT~j$ti${=(?`O!Kik1sb&DjaVR2A zJL3|-garUaY@^yD;#6SHxoI~&1+etZ92lVOzQrsi(wyeVY5|Q%Yq713&{wM8m=JGC+*6q}kGG(f5KiNCO<{;$?t(JTvpKuWLPo5OiJF z%hr4eK%|{~v)N#Rwa%Fhp0@z%o}W#y5V&4&%*!!002ovPDHLkV1nmA14aM< literal 0 HcmV?d00001 diff --git a/src/constants.ts b/src/constants.ts index ad78fdf..fea2f31 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -1,5 +1,12 @@ +import * as path from 'path'; export const languages = { ja: 'JA', zh: 'ZH', }; -export const linkCharacter = '⧉'; + +export const ASSETS_FOLDER = './assets'; +export const WIKIPEDIA_ICON_FILENAME = 'wikipedia-icon.png'; +export const WIKIPEDIA_ICON_FILEPATH = path.join( + ASSETS_FOLDER, + WIKIPEDIA_ICON_FILENAME +); diff --git a/src/index.ts b/src/index.ts index 41c4381..a907852 100644 --- a/src/index.ts +++ b/src/index.ts @@ -5,6 +5,7 @@ import { getVersion } from './util/getVersion'; import { downloadDumps } from './util/downloadDumps'; import { readArgs } from './util/readArgs'; import { readAndProcessLines } from './util/readAndProcessLines'; +import { WIKIPEDIA_ICON_FILEPATH } from './constants'; const outputZipName = (lang: string, date: string, version: string) => `${lang} Wikipedia [${date}] (v${version}).zip`; @@ -27,6 +28,8 @@ const OUT_DIRECTORY = './out'; fileName: outputZipName(lang, date, version), }); + dict.addFile(WIKIPEDIA_ICON_FILEPATH, WIKIPEDIA_ICON_FILEPATH); + const processedLines = await readAndProcessLines(filePath, dict, lang, dev); console.log(`Processed ${processedLines} lines, exporting zip...`); diff --git a/src/yomitan/processLine.ts b/src/yomitan/processLine.ts index b3fd74a..ee22651 100644 --- a/src/yomitan/processLine.ts +++ b/src/yomitan/processLine.ts @@ -4,7 +4,8 @@ import { StructuredContent, StructuredContentNode, } from 'yomichan-dict-builder/dist/types/yomitan/termbank'; -import { languages, linkCharacter } from '../constants'; +import * as path from 'path'; +import { WIKIPEDIA_ICON_FILEPATH } from '../constants'; /** * Reads a line and adds that term entry to the dictionary @@ -88,37 +89,36 @@ function createReadMoreNode( lang: string ): StructuredContentNode { const articleLink = `https://${lang.toLowerCase()}.wikipedia.org/wiki/${termSlug}`; - const readTheRest = getReadMoreText(lang); return { - tag: 'ul', + tag: 'div', content: [ { - tag: 'li', + tag: 'span', content: [ + { + tag: 'img', + path: WIKIPEDIA_ICON_FILEPATH, + collapsed: false, + collapsible: false, + height: 1, + width: 1, + sizeUnits: 'em', + verticalAlign: 'middle', + }, + ' ', { tag: 'a', href: articleLink, - content: readTheRest, + content: `Wikipedia`, }, ], }, ], data: { - wikipedia: 'continue-reading', + wikipedia: 'footer', }, style: { - listStyleType: `"${linkCharacter}"`, + textAlign: 'end', }, }; } - -function getReadMoreText(lang: string): string { - switch (lang) { - case languages.ja: - return '続きを読む'; - case languages.zh: - return '查看更多'; - default: - return 'Read more'; - } -} From f17ef4921267707f23e301888df233fad53a8d3f Mon Sep 17 00:00:00 2001 From: MarvNC Date: Thu, 11 Jul 2024 19:36:43 -0700 Subject: [PATCH 24/26] More modularized language types --- src/constants.ts | 22 +++++++++++++++++++--- src/parse/parseLine.ts | 15 +++------------ src/parse/readingParse.test.ts | 8 ++++---- src/util/downloadDumps.ts | 7 +++---- src/util/readAndProcessLines.ts | 3 ++- src/util/readArgs.ts | 16 ++++++---------- src/yomitan/processLine.ts | 24 +++++++++++------------- 7 files changed, 48 insertions(+), 47 deletions(-) diff --git a/src/constants.ts b/src/constants.ts index fea2f31..85a0760 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -1,7 +1,23 @@ import * as path from 'path'; -export const languages = { - ja: 'JA', - zh: 'ZH', +import { getReadingFromDefinition } from './parse/readingParse'; +import { pinyin } from 'pinyin-pro'; + +export const LANGUAGE_CODES = ['ja', 'zh'] as const; +export type LanguageCode = (typeof LANGUAGE_CODES)[number]; + +export const languageUtils: { + [key in LanguageCode]: { + getReading: (definition: string, term: string) => string; + }; +} = { + ja: { + getReading: (definition, term) => + getReadingFromDefinition(definition, term), + }, + zh: { + getReading: (definition, term) => + pinyin(term, { mode: 'surname' }).replace(/ /g, ''), + }, }; export const ASSETS_FOLDER = './assets'; diff --git a/src/parse/parseLine.ts b/src/parse/parseLine.ts index 641a854..d817639 100644 --- a/src/parse/parseLine.ts +++ b/src/parse/parseLine.ts @@ -1,5 +1,5 @@ import { pinyin } from 'pinyin-pro'; -import { languages } from '../constants'; +import { LanguageCode, languageUtils } from '../constants'; import { getReadingFromDefinition } from './readingParse'; type ParsedLine = { @@ -13,10 +13,7 @@ type ParsedLine = { /** * Parses a line of text and extracts relevant information. */ -function parseLine( - line: string, - lang: (typeof languages)[keyof typeof languages] -): ParsedLine { +function parseLine(line: string, lang: LanguageCode): ParsedLine { // remove last 6 characters line = line.slice(0, -6); const [resource, definition] = line.split( @@ -37,13 +34,7 @@ function parseLine( } term = term.replace(/_/g, ' '); - let reading = ''; - if (lang === languages.ja) { - reading = getReadingFromDefinition(definition, term); - } else if (lang === languages.zh) { - reading = pinyin(term, { mode: 'surname' }); - reading = reading.replace(/ /g, ''); - } + const reading = languageUtils[lang].getReading(definition, term); return { term, diff --git a/src/parse/readingParse.test.ts b/src/parse/readingParse.test.ts index c0fa4b7..24fa993 100644 --- a/src/parse/readingParse.test.ts +++ b/src/parse/readingParse.test.ts @@ -2,10 +2,10 @@ import { test, expect } from 'bun:test'; import { parseLine } from './parseLine.js'; -import { languages } from '../constants.js'; +import { LanguageCode } from '../constants.js'; const testCases: { - lang: (typeof languages)[keyof typeof languages]; + lang: LanguageCode; cases: { line: string; term: string; @@ -13,7 +13,7 @@ const testCases: { }[]; }[] = [ { - lang: languages.ja, + lang: 'ja', cases: [ { line: ` "みぞおちとは、人間の腹の上方中央にある窪んだ部位のこと。鳩尾(きゅうび、みぞおち)、水月(すいげつ)、心窩(しんか、しんわ)とも呼ばれる。みぞおちの内部背中側には腹腔神経叢(ふっくうしんけいそう、英:celiac plexus, solar plexus. 独:solarplexus)という (en:nerve plexus) がある。"@ja .`, @@ -95,7 +95,7 @@ const testCases: { ], }, { - lang: languages.zh, + lang: 'zh', cases: [ { line: ` "《!HERO》(直译“!英雄”)是一部有关耶稣的。这部歌剧基于“如果耶稣出生在宾夕法尼亚州伯利恒将会怎样?”这个问题。2003年首次巡演后,《!HERO》也通过DVD和CD发行。此歌剧也被写成一部小说三部曲和一系列漫画。"@zh .`, diff --git a/src/util/downloadDumps.ts b/src/util/downloadDumps.ts index 06112d3..efc91cf 100644 --- a/src/util/downloadDumps.ts +++ b/src/util/downloadDumps.ts @@ -1,6 +1,7 @@ import { $ } from 'bun'; import { exists } from 'node:fs/promises'; import { join } from 'path'; +import { LanguageCode, languageUtils } from '../constants'; const ARCHIVE = (lang: string) => `short-abstracts_lang=${lang.toLowerCase()}.ttl.bz2`; @@ -11,16 +12,14 @@ const URL = (lang: string, date: string) => )}`; const DOWNLOAD_DIR = './download'; -export async function downloadDumps(lang: string, date: string) { +export async function downloadDumps(lang: LanguageCode, date: string) { // Replace - with . in date date = date.replace(/-/g, '.'); - // Check if lang is in format YYYY.MM.DD + // Check if date is in format YYYY.MM.DD if (!/^\d{4}\.\d{2}\.\d{2}$/.test(date)) { throw new Error(`Invalid date format: ${date}`); } - // TODO: Check lang - // Check if download directory exists if (!(await exists(DOWNLOAD_DIR))) { await $`mkdir ${DOWNLOAD_DIR}`; diff --git a/src/util/readAndProcessLines.ts b/src/util/readAndProcessLines.ts index ef95f96..f3a611c 100644 --- a/src/util/readAndProcessLines.ts +++ b/src/util/readAndProcessLines.ts @@ -2,11 +2,12 @@ import { file } from 'bun'; import { Dictionary } from 'yomichan-dict-builder'; import * as cliProgress from 'cli-progress'; import { processLine } from '../yomitan/processLine'; +import { LanguageCode } from '../constants'; export async function readAndProcessLines( filePath: string, dict: Dictionary, - lang: string, + lang: LanguageCode, dev: boolean ) { const fileHandle = file(filePath); diff --git a/src/util/readArgs.ts b/src/util/readArgs.ts index ae12174..9cc51e0 100644 --- a/src/util/readArgs.ts +++ b/src/util/readArgs.ts @@ -1,5 +1,5 @@ -import { parseArgs } from "util"; -import { languages } from "../constants"; +import { parseArgs } from 'util'; +import { LanguageCode, languageUtils } from '../constants'; export function readArgs() { const { values } = parseArgs({ @@ -17,22 +17,18 @@ export function readArgs() { allowPositionals: false, }); - const langInput = ( - values.lang as string - )?.toLowerCase() as keyof typeof languages; + const langInput = (values.lang as string)?.toLowerCase() as LanguageCode; const dateInput = values.date as string; // Assert language is valid - if (!langInput || !languages[langInput]) { + if (!langInput || !languageUtils[langInput]) { throw new Error( `Language ${langInput} is not allowed or not provided. Allowed languages: ${Object.keys( - languages + languageUtils ).join(', ')}` ); } - const lang = languages[langInput] as keyof typeof languages; - // Assert date is valid in format YYYY-MM-DD if (!dateInput || !/^\d{4}-\d{2}-\d{2}$/.test(dateInput)) { throw new Error( @@ -40,5 +36,5 @@ export function readArgs() { ); } - return { lang, date: dateInput }; + return { lang: langInput, date: dateInput }; } diff --git a/src/yomitan/processLine.ts b/src/yomitan/processLine.ts index ee22651..df9d268 100644 --- a/src/yomitan/processLine.ts +++ b/src/yomitan/processLine.ts @@ -4,18 +4,23 @@ import { StructuredContent, StructuredContentNode, } from 'yomichan-dict-builder/dist/types/yomitan/termbank'; -import * as path from 'path'; -import { WIKIPEDIA_ICON_FILEPATH } from '../constants'; +import { LanguageCode, WIKIPEDIA_ICON_FILEPATH } from '../constants'; /** * Reads a line and adds that term entry to the dictionary */ -export function processLine(line: string, dict: Dictionary, lang: string) { +export function processLine( + line: string, + dict: Dictionary, + lang: LanguageCode +) { const { term, termSlug, termSpecifier, reading, definition } = parseLine( line, lang ); - const termEntry = createTermEntry(term, reading); + const termEntry = new TermEntry(term); + termEntry.setReading(reading); + const structuredContentList = createStructuredContentList( termSpecifier, definition, @@ -31,18 +36,11 @@ export function processLine(line: string, dict: Dictionary, lang: string) { dict.addTerm(termEntry.build()); } -// Helper functions -function createTermEntry(term: string, reading: string): TermEntry { - const termEntry = new TermEntry(term); - termEntry.setReading(reading); - return termEntry; -} - function createStructuredContentList( termSpecifier: string | null, definition: string, termSlug: string, - lang: string + lang: LanguageCode ): StructuredContent[] { const structuredContentList: StructuredContent[] = []; @@ -86,7 +84,7 @@ function createDefinitionNode(definition: string): StructuredContentNode { function createReadMoreNode( termSlug: string, - lang: string + lang: LanguageCode ): StructuredContentNode { const articleLink = `https://${lang.toLowerCase()}.wikipedia.org/wiki/${termSlug}`; return { From 6288be58e4d46a974700bba2b1d13d6faeb66a64 Mon Sep 17 00:00:00 2001 From: MarvNC Date: Thu, 11 Jul 2024 20:56:54 -0700 Subject: [PATCH 25/26] Expand language codes --- src/constants.ts | 116 +++++++++++++++++++++++++++++++++++++- src/util/downloadDumps.ts | 2 +- src/util/readArgs.ts | 10 ++-- 3 files changed, 120 insertions(+), 8 deletions(-) diff --git a/src/constants.ts b/src/constants.ts index 85a0760..d1768c4 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -2,21 +2,133 @@ import * as path from 'path'; import { getReadingFromDefinition } from './parse/readingParse'; import { pinyin } from 'pinyin-pro'; -export const LANGUAGE_CODES = ['ja', 'zh'] as const; +export const LANGUAGE_CODES = [ + 'hu', + 'eu', + 'pt', + 'ga', + 'el', + 'de', + 'eo', + 'ar', + 'id', + 'pl', + 'cs', + 'ca', + 'sv', + 'ru', + 'nl', + 'uk', + 'en', + 'ko', + 'es', + 'ja', + 'zh', + 'fr', + 'it', +] as const; + export type LanguageCode = (typeof LANGUAGE_CODES)[number]; export const languageUtils: { - [key in LanguageCode]: { + [key: string]: { getReading: (definition: string, term: string) => string; + fullName: string; }; } = { + hu: { + getReading: (definition, term) => '', + fullName: 'Hungarian', + }, + eu: { + getReading: (definition, term) => '', + fullName: 'Basque', + }, + pt: { + getReading: (definition, term) => '', + fullName: 'Portuguese', + }, + ga: { + getReading: (definition, term) => '', + fullName: 'Irish', + }, + el: { + getReading: (definition, term) => '', + fullName: 'Greek', + }, + de: { + getReading: (definition, term) => '', + fullName: 'German', + }, + eo: { + getReading: (definition, term) => '', + fullName: 'Esperanto', + }, + ar: { + getReading: (definition, term) => '', + fullName: 'Arabic', + }, + id: { + getReading: (definition, term) => '', + fullName: 'Indonesian', + }, + pl: { + getReading: (definition, term) => '', + fullName: 'Polish', + }, + cs: { + getReading: (definition, term) => '', + fullName: 'Czech', + }, + ca: { + getReading: (definition, term) => '', + fullName: 'Catalan', + }, + sv: { + getReading: (definition, term) => '', + fullName: 'Swedish', + }, + ru: { + getReading: (definition, term) => '', + fullName: 'Russian', + }, + nl: { + getReading: (definition, term) => '', + fullName: 'Dutch', + }, + uk: { + getReading: (definition, term) => '', + fullName: 'Ukrainian', + }, + en: { + getReading: (definition, term) => '', + fullName: 'English', + }, + ko: { + getReading: (definition, term) => '', + fullName: 'Korean', + }, + es: { + getReading: (definition, term) => '', + fullName: 'Spanish', + }, ja: { getReading: (definition, term) => getReadingFromDefinition(definition, term), + fullName: 'Japanese', }, zh: { getReading: (definition, term) => pinyin(term, { mode: 'surname' }).replace(/ /g, ''), + fullName: 'Chinese', + }, + fr: { + getReading: (definition, term) => '', + fullName: 'French', + }, + it: { + getReading: (definition, term) => '', + fullName: 'Italian', }, }; diff --git a/src/util/downloadDumps.ts b/src/util/downloadDumps.ts index efc91cf..ece6582 100644 --- a/src/util/downloadDumps.ts +++ b/src/util/downloadDumps.ts @@ -1,7 +1,7 @@ import { $ } from 'bun'; import { exists } from 'node:fs/promises'; import { join } from 'path'; -import { LanguageCode, languageUtils } from '../constants'; +import { LanguageCode } from '../constants'; const ARCHIVE = (lang: string) => `short-abstracts_lang=${lang.toLowerCase()}.ttl.bz2`; diff --git a/src/util/readArgs.ts b/src/util/readArgs.ts index 9cc51e0..df34e42 100644 --- a/src/util/readArgs.ts +++ b/src/util/readArgs.ts @@ -1,5 +1,5 @@ import { parseArgs } from 'util'; -import { LanguageCode, languageUtils } from '../constants'; +import { LANGUAGE_CODES, LanguageCode, languageUtils } from '../constants'; export function readArgs() { const { values } = parseArgs({ @@ -21,11 +21,11 @@ export function readArgs() { const dateInput = values.date as string; // Assert language is valid - if (!langInput || !languageUtils[langInput]) { + if (!langInput || !LANGUAGE_CODES.includes(langInput)) { throw new Error( - `Language ${langInput} is not allowed or not provided. Allowed languages: ${Object.keys( - languageUtils - ).join(', ')}` + `Language ${langInput} is not allowed or not provided. Allowed languages: ${LANGUAGE_CODES.join( + ', ' + )}` ); } From 3b03e6971d7948872f9b35fb1baab978f95833be Mon Sep 17 00:00:00 2001 From: MarvNC Date: Thu, 11 Jul 2024 21:16:33 -0700 Subject: [PATCH 26/26] Add -a flag to process all langs --- src/constants.ts | 2 ++ src/index.ts | 33 +++++++++++++++++++++++++++------ src/util/downloadDumps.ts | 10 ++++++++-- src/util/readArgs.ts | 10 +++++++--- 4 files changed, 44 insertions(+), 11 deletions(-) diff --git a/src/constants.ts b/src/constants.ts index d1768c4..0fad892 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -2,6 +2,8 @@ import * as path from 'path'; import { getReadingFromDefinition } from './parse/readingParse'; import { pinyin } from 'pinyin-pro'; +export const DBPEDIA_DATE = '2022-12-01'; + export const LANGUAGE_CODES = [ 'hu', 'eu', diff --git a/src/index.ts b/src/index.ts index a907852..1688378 100644 --- a/src/index.ts +++ b/src/index.ts @@ -5,7 +5,12 @@ import { getVersion } from './util/getVersion'; import { downloadDumps } from './util/downloadDumps'; import { readArgs } from './util/readArgs'; import { readAndProcessLines } from './util/readAndProcessLines'; -import { WIKIPEDIA_ICON_FILEPATH } from './constants'; +import { + LanguageCode, + WIKIPEDIA_ICON_FILEPATH, + DBPEDIA_DATE, + LANGUAGE_CODES, +} from './constants'; const outputZipName = (lang: string, date: string, version: string) => `${lang} Wikipedia [${date}] (v${version}).zip`; @@ -17,8 +22,27 @@ const OUT_DIRECTORY = './out'; console.log(`Using version ${version}`); - const { lang, date } = readArgs(); + const { lang, date, all } = readArgs(); + if (!all) { + await processWikipediaDataForLang(version, dev, lang, date); + } else { + for (const lang of LANGUAGE_CODES) { + await processWikipediaDataForLang(version, dev, lang, DBPEDIA_DATE); + } + } + + process.exit(0); +})().catch((e) => { + console.error(e); +}); + +async function processWikipediaDataForLang( + version: string, + dev: boolean, + lang: LanguageCode, + date: string +) { console.log(`Converting ${lang} Wikipedia dump from ${date}...`); const filePath = await downloadDumps(lang, date); @@ -46,7 +70,4 @@ const OUT_DIRECTORY = './out'; await dict.export(OUT_DIRECTORY); console.log(`Exported to ${outputZipName(lang, date, version)}`); - process.exit(0); -})().catch((e) => { - console.error(e); -}); +} diff --git a/src/util/downloadDumps.ts b/src/util/downloadDumps.ts index ece6582..9b34846 100644 --- a/src/util/downloadDumps.ts +++ b/src/util/downloadDumps.ts @@ -1,5 +1,5 @@ import { $ } from 'bun'; -import { exists } from 'node:fs/promises'; +import { exists, mkdir } from 'node:fs/promises'; import { join } from 'path'; import { LanguageCode } from '../constants'; @@ -22,13 +22,17 @@ export async function downloadDumps(lang: LanguageCode, date: string) { // Check if download directory exists if (!(await exists(DOWNLOAD_DIR))) { - await $`mkdir ${DOWNLOAD_DIR}`; + console.log(`Creating download directory ${DOWNLOAD_DIR}`); + await mkdir(DOWNLOAD_DIR); } const archivePath = join(DOWNLOAD_DIR, ARCHIVE(lang)); const filePath = join(DOWNLOAD_DIR, FILE(lang)); const archiveExists = await exists(archivePath); const fileExists = await exists(filePath); + console.log( + `${lang}: archiveExists=${archiveExists}, fileExists=${fileExists}` + ); // Download the archive if neither the file nor archive exists if (!fileExists && !archiveExists) { @@ -43,5 +47,7 @@ export async function downloadDumps(lang: LanguageCode, date: string) { await $`bzip2 -dc ${archivePath} >${filePath}`; } + console.log(`Finished downloading and extracting ${lang} dump`); + return filePath; } diff --git a/src/util/readArgs.ts b/src/util/readArgs.ts index df34e42..d2cca64 100644 --- a/src/util/readArgs.ts +++ b/src/util/readArgs.ts @@ -12,6 +12,10 @@ export function readArgs() { type: 'string', short: 'd', }, + all: { + type: 'boolean', + short: 'a', + }, }, strict: true, allowPositionals: false, @@ -21,7 +25,7 @@ export function readArgs() { const dateInput = values.date as string; // Assert language is valid - if (!langInput || !LANGUAGE_CODES.includes(langInput)) { + if (langInput != null && !LANGUAGE_CODES.includes(langInput)) { throw new Error( `Language ${langInput} is not allowed or not provided. Allowed languages: ${LANGUAGE_CODES.join( ', ' @@ -30,11 +34,11 @@ export function readArgs() { } // Assert date is valid in format YYYY-MM-DD - if (!dateInput || !/^\d{4}-\d{2}-\d{2}$/.test(dateInput)) { + if (dateInput != null && !/^\d{4}-\d{2}-\d{2}$/.test(dateInput)) { throw new Error( `Date ${dateInput} is not valid or not provided. Format: YYYY-MM-DD` ); } - return { lang: langInput, date: dateInput }; + return { lang: langInput, date: dateInput, all: !!values.all }; }