summaryrefslogtreecommitdiff
path: root/dev/dictionary-archive-util.js
diff options
context:
space:
mode:
Diffstat (limited to 'dev/dictionary-archive-util.js')
-rw-r--r--dev/dictionary-archive-util.js110
1 files changed, 110 insertions, 0 deletions
diff --git a/dev/dictionary-archive-util.js b/dev/dictionary-archive-util.js
new file mode 100644
index 00000000..ead5790b
--- /dev/null
+++ b/dev/dictionary-archive-util.js
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2024 Yomitan Authors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+import {BlobWriter, TextReader, TextWriter, Uint8ArrayReader, ZipReader, ZipWriter} from '@zip.js/zip.js';
+import {readFileSync, readdirSync} from 'fs';
+import {join} from 'path';
+import {parseJson} from './json.js';
+
+/**
+ * Creates a zip archive from the given dictionary directory.
+ * @param {string} dictionaryDirectory
+ * @param {string} [dictionaryName]
+ * @returns {Promise<ArrayBuffer>}
+ */
+export async function createDictionaryArchiveData(dictionaryDirectory, dictionaryName) {
+ const fileNames = readdirSync(dictionaryDirectory);
+ const zipFileWriter = new BlobWriter();
+ // Level 0 compression used since decompression in the node environment is not supported.
+ // See dev/lib/zip.js for more details.
+ const zipWriter = new ZipWriter(zipFileWriter, {
+ level: 0
+ });
+ for (const fileName of fileNames) {
+ if (/\.json$/.test(fileName)) {
+ const content = readFileSync(join(dictionaryDirectory, fileName), {encoding: 'utf8'});
+ /** @type {import('dictionary-data').Index} */
+ const json = parseJson(content);
+ if (fileName === 'index.json' && typeof dictionaryName === 'string') {
+ json.title = dictionaryName;
+ }
+ await zipWriter.add(fileName, new TextReader(JSON.stringify(json, null, 0)));
+ } else {
+ const content = readFileSync(join(dictionaryDirectory, fileName), {encoding: null});
+ await zipWriter.add(fileName, new Blob([content]).stream());
+ }
+ }
+ const blob = await zipWriter.close();
+ return await blob.arrayBuffer();
+}
+
+/**
+ * @param {import('@zip.js/zip.js').Entry} entry
+ * @returns {Promise<string>}
+ */
+export async function readArchiveEntryDataString(entry) {
+ if (typeof entry.getData === 'undefined') { throw new Error('Cannot get index data'); }
+ return await entry.getData(new TextWriter());
+}
+
+/**
+ * @template [T=unknown]
+ * @param {import('@zip.js/zip.js').Entry} entry
+ * @returns {Promise<T>}
+ */
+export async function readArchiveEntryDataJson(entry) {
+ const indexContent = await readArchiveEntryDataString(entry);
+ return parseJson(indexContent);
+}
+
+/**
+ * @param {ArrayBuffer} data
+ * @returns {Promise<import('@zip.js/zip.js').Entry[]>}
+ */
+export async function getDictionaryArchiveEntries(data) {
+ const zipFileReader = new Uint8ArrayReader(new Uint8Array(data));
+ const zipReader = new ZipReader(zipFileReader);
+ return await zipReader.getEntries();
+}
+
+/**
+ * @template T
+ * @param {import('@zip.js/zip.js').Entry[]} entries
+ * @param {string} fileName
+ * @returns {Promise<T>}
+ */
+export async function getDictionaryArchiveJson(entries, fileName) {
+ const entry = entries.find((item) => item.filename === fileName);
+ if (typeof entry === 'undefined') { throw new Error(`File not found: ${fileName}`); }
+ return await readArchiveEntryDataJson(entry);
+}
+
+/**
+ * @returns {string}
+ */
+export function getIndexFileName() {
+ return 'index.json';
+}
+
+/**
+ * @param {ArrayBuffer} data
+ * @returns {Promise<import('dictionary-data').Index>}
+ */
+export async function getDictionaryArchiveIndex(data) {
+ const entries = await getDictionaryArchiveEntries(data);
+ return await getDictionaryArchiveJson(entries, getIndexFileName());
+}