import glob from 'fast-glob';
|
|
import { FastifyPluginAsync } from 'fastify';
|
|
import yaml from 'js-yaml';
|
|
import S from 'jsonschema-definer';
|
|
import sanitize from 'sanitize-filename';
|
|
|
|
import { oItem, readYAML } from '../shared';
|
|
|
|
export const kanjiRouter: FastifyPluginAsync = async (f) => {
|
|
f.get<{
|
|
Params: {
|
|
entry: string;
|
|
};
|
|
}>(':entry.md', async (req) => {
|
|
const { entry } = req.params;
|
|
|
|
const m = getEntry(entry);
|
|
if (!m) {
|
|
throw { statusCode: 404 };
|
|
}
|
|
|
|
const { data, content } = m;
|
|
if (content.trim()) return content;
|
|
|
|
let md = '';
|
|
if (data.meanings) {
|
|
md += data.meanings
|
|
.map((v, i) => {
|
|
const out = [`${i + 1}. ${v.meaning.join('; ')}`];
|
|
if (v.examples) {
|
|
out.push(
|
|
...v.examples.map(
|
|
(ex) => ' - ' + ex.ja + (ex.en ? `\n - ` + ex.en : ''),
|
|
),
|
|
);
|
|
}
|
|
|
|
return out.join('\n');
|
|
})
|
|
.join('\n');
|
|
}
|
|
|
|
return (
|
|
md ||
|
|
yaml
|
|
.dump(data)
|
|
.split('\n')
|
|
.map((ln) => (ln ? ' ' + ln : ln))
|
|
.join('\n')
|
|
);
|
|
});
|
|
|
|
f.get<{
|
|
Params: {
|
|
entry: string;
|
|
};
|
|
}>(':entry', async (req): Promise<typeof sEntry.type> => {
|
|
const { entry } = req.params;
|
|
|
|
const m = getEntry(entry);
|
|
if (!m) {
|
|
throw { statusCode: 404 };
|
|
}
|
|
|
|
return m.data;
|
|
});
|
|
};
|
|
|
|
export default kanjiRouter;
|
|
|
|
const sEntry = S.shape({
|
|
readings: S.list(
|
|
S.shape({
|
|
reading: S.string(),
|
|
type: S.string(),
|
|
...oItem,
|
|
}).additionalProperties(true),
|
|
).optional(),
|
|
meanings: S.list(
|
|
S.shape({
|
|
meaning: S.list(S.string()),
|
|
...oItem,
|
|
}).additionalProperties(true),
|
|
).optional(),
|
|
}).additionalProperties(true);
|
|
|
|
function getEntry(entry: string) {
|
|
const filepath = glob.sync(`assets/kanji/**/${sanitize(entry)}.md`).sort()[0];
|
|
|
|
if (!filepath) return null;
|
|
|
|
const { data, content } = readYAML(filepath);
|
|
|
|
return {
|
|
data: sEntry.ensure(data),
|
|
content,
|
|
};
|
|
}
|