From aa7dbf2ba46ec1541ea7af0ca290d72b87129b36 Mon Sep 17 00:00:00 2001 From: Cashew Date: Sun, 14 Jan 2024 11:35:35 +0700 Subject: [PATCH 1/7] improve dictionary validation --- dev/dictionary-validate.js | 63 +++++++++++++----------- ext/js/dictionary/dictionary-importer.js | 16 +++--- types/dev/dictionary-validate.d.ts | 5 ++ types/ext/dictionary-importer.d.ts | 2 +- 4 files changed, 47 insertions(+), 39 deletions(-) diff --git a/dev/dictionary-validate.js b/dev/dictionary-validate.js index 51edcc50a5..f05522b511 100644 --- a/dev/dictionary-validate.js +++ b/dev/dictionary-validate.js @@ -39,35 +39,33 @@ function readSchema(relativeFileName) { /** * @param {import('dev/schema-validate').ValidateMode} mode * @param {import('jszip')} zip - * @param {string} fileNameFormat - * @param {import('dev/dictionary-validate').Schema} schema + * @param {import('dev/dictionary-validate').SchemasDetails} schemasDetails */ -async function validateDictionaryBanks(mode, zip, fileNameFormat, schema) { - let jsonSchema; - try { - jsonSchema = createJsonSchema(mode, schema); - } catch (e) { - const e2 = e instanceof Error ? e : new Error(`${e}`); - e2.message += `\n(in file ${fileNameFormat})}`; - throw e2; - } - let index = 1; - while (true) { - const fileName = fileNameFormat.replace(/\?/, `${index}`); +async function validateDictionaryBanks(mode, zip, schemasDetails) { + for (const [fileName, file] of Object.entries(zip.files)) { + for (const [fileNameFormat, schema] of schemasDetails) { + if (!fileNameFormat.test(fileName)) { continue; } - const file = zip.files[fileName]; - if (!file) { break; } + let jsonSchema; + try { + jsonSchema = createJsonSchema(mode, schema); + } catch (e) { + const e2 = e instanceof Error ? e : new Error(`${e}`); + e2.message += `\n(in file ${fileName})}`; + throw e2; + } - const data = parseJson(await file.async('string')); - try { - jsonSchema.validate(data); - } catch (e) { - const e2 = e instanceof Error ? e : new Error(`${e}`); - e2.message += `\n(in file ${fileName})}`; - throw e2; - } + const data = parseJson(await file.async('string')); - ++index; + try { + jsonSchema.validate(data); + } catch (e) { + const e2 = e instanceof Error ? e : new Error(`${e}`); + e2.message += `\n(in file ${fileName})}`; + throw e2; + } + break; + } } } @@ -97,11 +95,16 @@ export async function validateDictionary(mode, archive, schemas) { throw e2; } - await validateDictionaryBanks(mode, archive, 'term_bank_?.json', version === 1 ? schemas.termBankV1 : schemas.termBankV3); - await validateDictionaryBanks(mode, archive, 'term_meta_bank_?.json', schemas.termMetaBankV3); - await validateDictionaryBanks(mode, archive, 'kanji_bank_?.json', version === 1 ? schemas.kanjiBankV1 : schemas.kanjiBankV3); - await validateDictionaryBanks(mode, archive, 'kanji_meta_bank_?.json', schemas.kanjiMetaBankV3); - await validateDictionaryBanks(mode, archive, 'tag_bank_?.json', schemas.tagBankV3); + /** @type {import('dev/dictionary-validate').SchemasDetails} */ + const schemasDetails = [ + [/^term_bank_(\d+)\.json$/, version === 1 ? schemas.termBankV1 : schemas.termBankV3], + [/^term_meta_bank_(\d+)\.json$/, schemas.termMetaBankV3], + [/^kanji_bank_(\d+)\.json$/, version === 1 ? schemas.kanjiBankV1 : schemas.kanjiBankV3], + [/^kanji_meta_bank_(\d+)\.json$/, schemas.kanjiMetaBankV3], + [/^tag_bank_(\d+)\.json$/, schemas.tagBankV3] + ]; + + await validateDictionaryBanks(mode, archive, schemasDetails); } /** diff --git a/ext/js/dictionary/dictionary-importer.js b/ext/js/dictionary/dictionary-importer.js index 2c0c7e9c2e..d81cb29945 100644 --- a/ext/js/dictionary/dictionary-importer.js +++ b/ext/js/dictionary/dictionary-importer.js @@ -114,13 +114,13 @@ export class DictionaryImporter { // Files /** @type {import('dictionary-importer').QueryDetails} */ - const queryDetails = new Map([ + const queryDetails = [ ['termFiles', /^term_bank_(\d+)\.json$/], ['termMetaFiles', /^term_meta_bank_(\d+)\.json$/], ['kanjiFiles', /^kanji_bank_(\d+)\.json$/], ['kanjiMetaFiles', /^kanji_meta_bank_(\d+)\.json$/], ['tagFiles', /^tag_bank_(\d+)\.json$/] - ]); + ]; const {termFiles, termMetaFiles, kanjiFiles, kanjiMetaFiles, tagFiles} = Object.fromEntries(this._getArchiveFiles(fileMap, queryDetails)); // Load data @@ -691,18 +691,18 @@ export class DictionaryImporter { _getArchiveFiles(fileMap, queryDetails) { /** @type {import('dictionary-importer').QueryResult} */ const results = new Map(); - for (const [name, value] of fileMap.entries()) { - for (const [fileType, fileNameFormat] of queryDetails.entries()) { + for (const [fileName, fileEntry] of fileMap.entries()) { + for (const [fileType, fileNameFormat] of queryDetails) { + if (!fileNameFormat.test(fileName)) { continue; } + let entries = results.get(fileType); if (typeof entries === 'undefined') { entries = []; results.set(fileType, entries); } - if (fileNameFormat.test(name)) { - entries.push(value); - break; - } + entries.push(fileEntry); + break; } } return results; diff --git a/types/dev/dictionary-validate.d.ts b/types/dev/dictionary-validate.d.ts index c39f4335c2..b10a74ee06 100644 --- a/types/dev/dictionary-validate.d.ts +++ b/types/dev/dictionary-validate.d.ts @@ -29,3 +29,8 @@ export type Schemas = { termBankV3: Schema; termMetaBankV3: Schema; }; + +/** + * A map of regular expression identifiers of file types inside a dictionary and its corresponding schemas. + */ +export type SchemasDetails = [RegExp, unknown][]; diff --git a/types/ext/dictionary-importer.d.ts b/types/ext/dictionary-importer.d.ts index 2d16dc5e62..6c23605fb8 100644 --- a/types/ext/dictionary-importer.d.ts +++ b/types/ext/dictionary-importer.d.ts @@ -115,7 +115,7 @@ export type ArchiveFileMap = Map; /** * A map of file types inside a dictionary and its corresponding regular expressions. */ -export type QueryDetails = Map; +export type QueryDetails = [string, RegExp][]; /** * A map of file types inside a dictionary and its matching entries. From 7e90cd137d8ebc026083f986dc82621b6d6b2e03 Mon Sep 17 00:00:00 2001 From: Cashew Date: Sun, 14 Jan 2024 11:48:09 +0700 Subject: [PATCH 2/7] fix --- ext/js/dictionary/dictionary-importer.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ext/js/dictionary/dictionary-importer.js b/ext/js/dictionary/dictionary-importer.js index d81cb29945..8b20dfee55 100644 --- a/ext/js/dictionary/dictionary-importer.js +++ b/ext/js/dictionary/dictionary-importer.js @@ -693,16 +693,16 @@ export class DictionaryImporter { const results = new Map(); for (const [fileName, fileEntry] of fileMap.entries()) { for (const [fileType, fileNameFormat] of queryDetails) { - if (!fileNameFormat.test(fileName)) { continue; } - let entries = results.get(fileType); if (typeof entries === 'undefined') { entries = []; results.set(fileType, entries); } - entries.push(fileEntry); - break; + if (fileNameFormat.test(fileName)) { + entries.push(fileEntry); + break; + } } } return results; From 749f33737530bffaf30bae48a080fba146137d7e Mon Sep 17 00:00:00 2001 From: Cashew Date: Sun, 14 Jan 2024 12:08:13 +0700 Subject: [PATCH 3/7] improve performance --- ext/js/dictionary/dictionary-importer.js | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/ext/js/dictionary/dictionary-importer.js b/ext/js/dictionary/dictionary-importer.js index 8b20dfee55..110590503b 100644 --- a/ext/js/dictionary/dictionary-importer.js +++ b/ext/js/dictionary/dictionary-importer.js @@ -691,18 +691,19 @@ export class DictionaryImporter { _getArchiveFiles(fileMap, queryDetails) { /** @type {import('dictionary-importer').QueryResult} */ const results = new Map(); + + for (const [fileType] of queryDetails) { + results.set(fileType, []); + } + for (const [fileName, fileEntry] of fileMap.entries()) { for (const [fileType, fileNameFormat] of queryDetails) { - let entries = results.get(fileType); - if (typeof entries === 'undefined') { - entries = []; - results.set(fileType, entries); - } + if (!fileNameFormat.test(fileName)) { continue; } + const entries = results.get(fileType); - if (fileNameFormat.test(fileName)) { - entries.push(fileEntry); - break; - } + // @ts-expect-error - entries should be initialized + entries.push(fileEntry); + break; } } return results; From 290279718be6b9321416225c35d90600c1d12ce7 Mon Sep 17 00:00:00 2001 From: Cashew Date: Tue, 16 Jan 2024 16:30:35 +0700 Subject: [PATCH 4/7] add undefined check --- ext/js/dictionary/dictionary-importer.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/ext/js/dictionary/dictionary-importer.js b/ext/js/dictionary/dictionary-importer.js index 110590503b..fa8af614e5 100644 --- a/ext/js/dictionary/dictionary-importer.js +++ b/ext/js/dictionary/dictionary-importer.js @@ -701,9 +701,10 @@ export class DictionaryImporter { if (!fileNameFormat.test(fileName)) { continue; } const entries = results.get(fileType); - // @ts-expect-error - entries should be initialized - entries.push(fileEntry); - break; + if (typeof entries !== 'undefined') { + entries.push(fileEntry); + break; + } } } return results; From f7ae56f9a202574a66536c762b5766d2207ed44f Mon Sep 17 00:00:00 2001 From: Cashew Date: Wed, 17 Jan 2024 09:14:49 +0700 Subject: [PATCH 5/7] rename types --- dev/dictionary-validate.js | 2 +- ext/js/dictionary/dictionary-importer.js | 4 ++-- types/dev/dictionary-validate.d.ts | 4 ++-- types/ext/dictionary-importer.d.ts | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/dev/dictionary-validate.js b/dev/dictionary-validate.js index f05522b511..010d843b2b 100644 --- a/dev/dictionary-validate.js +++ b/dev/dictionary-validate.js @@ -39,7 +39,7 @@ function readSchema(relativeFileName) { /** * @param {import('dev/schema-validate').ValidateMode} mode * @param {import('jszip')} zip - * @param {import('dev/dictionary-validate').SchemasDetails} schemasDetails + * @param {import('dev/dictionary-validate').SchemasDetail[]} schemasDetails */ async function validateDictionaryBanks(mode, zip, schemasDetails) { for (const [fileName, file] of Object.entries(zip.files)) { diff --git a/ext/js/dictionary/dictionary-importer.js b/ext/js/dictionary/dictionary-importer.js index fa8af614e5..16df379fe4 100644 --- a/ext/js/dictionary/dictionary-importer.js +++ b/ext/js/dictionary/dictionary-importer.js @@ -113,7 +113,7 @@ export class DictionaryImporter { const dataBankSchemas = this._getDataBankSchemas(version); // Files - /** @type {import('dictionary-importer').QueryDetails} */ + /** @type {import('dictionary-importer').QueryDetail[]} */ const queryDetails = [ ['termFiles', /^term_bank_(\d+)\.json$/], ['termMetaFiles', /^term_meta_bank_(\d+)\.json$/], @@ -685,7 +685,7 @@ export class DictionaryImporter { /** * @param {import('dictionary-importer').ArchiveFileMap} fileMap - * @param {import('dictionary-importer').QueryDetails} queryDetails + * @param {import('dictionary-importer').QueryDetail[]} queryDetails * @returns {import('dictionary-importer').QueryResult} */ _getArchiveFiles(fileMap, queryDetails) { diff --git a/types/dev/dictionary-validate.d.ts b/types/dev/dictionary-validate.d.ts index b10a74ee06..0a69f56aba 100644 --- a/types/dev/dictionary-validate.d.ts +++ b/types/dev/dictionary-validate.d.ts @@ -31,6 +31,6 @@ export type Schemas = { }; /** - * A map of regular expression identifiers of file types inside a dictionary and its corresponding schemas. + * A tuple of a regular expression identifier of file types inside a dictionary and its corresponding schema. */ -export type SchemasDetails = [RegExp, unknown][]; +export type SchemasDetail = [RegExp, unknown]; diff --git a/types/ext/dictionary-importer.d.ts b/types/ext/dictionary-importer.d.ts index 6c23605fb8..645e9a42f6 100644 --- a/types/ext/dictionary-importer.d.ts +++ b/types/ext/dictionary-importer.d.ts @@ -113,9 +113,9 @@ export type ImportRequirementContext = { export type ArchiveFileMap = Map; /** - * A map of file types inside a dictionary and its corresponding regular expressions. + * A tuple of a file type inside a dictionary and its corresponding regular expression. */ -export type QueryDetails = [string, RegExp][]; +export type QueryDetail = [string, RegExp]; /** * A map of file types inside a dictionary and its matching entries. From 413679f847a14d12dceeaa8381a42193e342e6fd Mon Sep 17 00:00:00 2001 From: Cashew Date: Wed, 17 Jan 2024 09:15:49 +0700 Subject: [PATCH 6/7] rename types --- dev/dictionary-validate.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/dictionary-validate.js b/dev/dictionary-validate.js index 010d843b2b..ec4621bd36 100644 --- a/dev/dictionary-validate.js +++ b/dev/dictionary-validate.js @@ -95,7 +95,7 @@ export async function validateDictionary(mode, archive, schemas) { throw e2; } - /** @type {import('dev/dictionary-validate').SchemasDetails} */ + /** @type {import('dev/dictionary-validate').SchemasDetail[]} */ const schemasDetails = [ [/^term_bank_(\d+)\.json$/, version === 1 ? schemas.termBankV1 : schemas.termBankV3], [/^term_meta_bank_(\d+)\.json$/, schemas.termMetaBankV3], From e16f0f17d458bf0b3fc867801edb242dce9e8852 Mon Sep 17 00:00:00 2001 From: Cashew Date: Wed, 17 Jan 2024 09:32:55 +0700 Subject: [PATCH 7/7] rename --- dev/dictionary-validate.js | 4 ++-- ext/js/dictionary/dictionary-importer.js | 4 ++-- types/dev/dictionary-validate.d.ts | 4 ++-- types/ext/dictionary-importer.d.ts | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/dev/dictionary-validate.js b/dev/dictionary-validate.js index ec4621bd36..f05522b511 100644 --- a/dev/dictionary-validate.js +++ b/dev/dictionary-validate.js @@ -39,7 +39,7 @@ function readSchema(relativeFileName) { /** * @param {import('dev/schema-validate').ValidateMode} mode * @param {import('jszip')} zip - * @param {import('dev/dictionary-validate').SchemasDetail[]} schemasDetails + * @param {import('dev/dictionary-validate').SchemasDetails} schemasDetails */ async function validateDictionaryBanks(mode, zip, schemasDetails) { for (const [fileName, file] of Object.entries(zip.files)) { @@ -95,7 +95,7 @@ export async function validateDictionary(mode, archive, schemas) { throw e2; } - /** @type {import('dev/dictionary-validate').SchemasDetail[]} */ + /** @type {import('dev/dictionary-validate').SchemasDetails} */ const schemasDetails = [ [/^term_bank_(\d+)\.json$/, version === 1 ? schemas.termBankV1 : schemas.termBankV3], [/^term_meta_bank_(\d+)\.json$/, schemas.termMetaBankV3], diff --git a/ext/js/dictionary/dictionary-importer.js b/ext/js/dictionary/dictionary-importer.js index 16df379fe4..fa8af614e5 100644 --- a/ext/js/dictionary/dictionary-importer.js +++ b/ext/js/dictionary/dictionary-importer.js @@ -113,7 +113,7 @@ export class DictionaryImporter { const dataBankSchemas = this._getDataBankSchemas(version); // Files - /** @type {import('dictionary-importer').QueryDetail[]} */ + /** @type {import('dictionary-importer').QueryDetails} */ const queryDetails = [ ['termFiles', /^term_bank_(\d+)\.json$/], ['termMetaFiles', /^term_meta_bank_(\d+)\.json$/], @@ -685,7 +685,7 @@ export class DictionaryImporter { /** * @param {import('dictionary-importer').ArchiveFileMap} fileMap - * @param {import('dictionary-importer').QueryDetail[]} queryDetails + * @param {import('dictionary-importer').QueryDetails} queryDetails * @returns {import('dictionary-importer').QueryResult} */ _getArchiveFiles(fileMap, queryDetails) { diff --git a/types/dev/dictionary-validate.d.ts b/types/dev/dictionary-validate.d.ts index 0a69f56aba..118954cb81 100644 --- a/types/dev/dictionary-validate.d.ts +++ b/types/dev/dictionary-validate.d.ts @@ -31,6 +31,6 @@ export type Schemas = { }; /** - * A tuple of a regular expression identifier of file types inside a dictionary and its corresponding schema. + * An array of tuples of a regular expression for file types inside a dictionary and its corresponding schema. */ -export type SchemasDetail = [RegExp, unknown]; +export type SchemasDetails = [fileNameFormat: RegExp, schema: unknown][]; diff --git a/types/ext/dictionary-importer.d.ts b/types/ext/dictionary-importer.d.ts index 645e9a42f6..070adbdac8 100644 --- a/types/ext/dictionary-importer.d.ts +++ b/types/ext/dictionary-importer.d.ts @@ -113,9 +113,9 @@ export type ImportRequirementContext = { export type ArchiveFileMap = Map; /** - * A tuple of a file type inside a dictionary and its corresponding regular expression. + * An array of tuples of a file type inside a dictionary and its corresponding regular expression. */ -export type QueryDetail = [string, RegExp]; +export type QueryDetails = [fileType: string, fileNameFormat: RegExp][]; /** * A map of file types inside a dictionary and its matching entries.