Files
feishin/vite.kuromoji-plugin.ts
T
York 62c1ac04e4 feat: support furigana and romaji generation on web (#2232)
* feat: support furigana and romaji generation on web
2026-07-15 22:26:05 -07:00

55 lines
1.7 KiB
TypeScript

import type { Connect, Plugin } from 'vite';
import fs from 'node:fs';
import { createRequire } from 'node:module';
import path from 'node:path';
const require = createRequire(import.meta.url);
const analyzerRequire = createRequire(require.resolve('kuroshiro-analyzer-kuromoji/package.json'));
const dictionaryDirectory = path.join(
path.dirname(analyzerRequire.resolve('kuromoji/package.json')),
'dict',
);
const dictionaryFiles = fs
.readdirSync(dictionaryDirectory)
.filter((fileName) => fileName.endsWith('.dat.gz'));
const serveDictionary: Connect.NextHandleFunction = (request, response, next) => {
const fileName = path.basename(new URL(request.url ?? '/', 'http://localhost').pathname);
if (!dictionaryFiles.includes(fileName)) {
next();
return;
}
response.setHeader('Content-Type', 'application/gzip');
fs.createReadStream(path.join(dictionaryDirectory, fileName)).pipe(response);
};
type KuromojiDictionaryPluginOptions = {
emitDictionary?: boolean;
};
export const kuromojiDictionaryPlugin = ({
emitDictionary = true,
}: KuromojiDictionaryPluginOptions = {}): Plugin => ({
configurePreviewServer(server) {
server.middlewares.use('/assets/kuromoji', serveDictionary);
},
configureServer(server) {
server.middlewares.use('/assets/kuromoji', serveDictionary);
},
generateBundle() {
if (!emitDictionary) return;
for (const fileName of dictionaryFiles) {
this.emitFile({
fileName: `assets/kuromoji/${fileName}`,
source: fs.readFileSync(path.join(dictionaryDirectory, fileName)),
type: 'asset',
});
}
},
name: 'kuromoji-dictionary',
});