compile from wk

This commit is contained in:
polv committed 2022-04-03 08:41:43 +07:00
1 parent 14c722c529
commit 693b742c9e
12 files changed
+888

No files matched your search

@@ -0,0 +1,154 @@
import fs from 'fs'
import yaml from 'js-yaml'
import { toKatakana } from 'wanakana'
import { subjects } from './dump-subjects'
import { IKanji, IRadical } from './shared'
interface IItem {
document_url: string
level: number
meaning: string
reading?: string
components: {
[source: string]: string[]
}
similar: string[]
image?: {
src: string
content_type: string
width: string | undefined
height: string | undefined
}
}
interface IBeautifiedRadicals {
[id: string]: IItem
}
export const radicals = {
data: {} as IBeautifiedRadicals,
filename: 'radicals.yaml',
load() {
this.data = yaml.load(
fs.readFileSync(this.filename, 'utf-8')
) as IBeautifiedRadicals
return this.data
},
dump(d: IBeautifiedRadicals) {
this.data = d
this.finalize()
},
finalize() {
fs.writeFileSync(
this.filename,
yaml.dump(this.data, {
skipInvalid: true
})
)
}
}
async function main() {
const rs = subjects.load()
const idMap = new Map<number, string>()
radicals.data = {}
rs.filter((r) => r.object === 'radical').map((r0) => {
const r = r0 as IRadical
const d = {
document_url: r.data.document_url,
level: r.data.level,
meaning: r.data.meanings.filter((m) => m.primary)[0]!.meaning,
components: {},
sup: r.data.amalgamation_subject_ids.map((it) => it.toString()),
similar: []
}
let id = r.data.characters
if (id) {
radicals.data[id] = d
} else {
id = d.meaning
const st = (im: {
content_type: string
metadata: { dimensions?: string }
}) =>
im.content_type === 'image/svg+xml'
? 5000
: im.metadata.dimensions
? Math.min(...im.metadata.dimensions.split('x').map(Number))
: 0
const im = r.data.character_images.sort((a, b) => st(a) - st(b))[0]!
const dim = im.metadata.dimensions?.split('x') || []
radicals.data[id] = {
...d,
image: {
src: im.url,
content_type: im.content_type,
width: dim[0],
height: dim[1]
}
}
}
idMap.set(r.id, id)
})
rs.filter((r) => r.object === 'kanji').map((r0) => {
const r = r0 as IKanji
const reading = r.data.readings.filter((m) => m.primary)[0]!
const d = {
document_url: r.data.document_url,
level: r.data.level,
meaning: r.data.meanings.filter((m) => m.primary)[0]!.meaning,
reading:
reading.type === 'onyomi'
? toKatakana(reading.reading)
: reading.reading,
components: {
wanikani: r.data.component_subject_ids.map((it) => it.toString())
},
similar: r.data.visually_similar_subject_ids.map((it) => it.toString())
}
const id = r.data.characters
idMap.set(r.id, id)
// const prev = radicals.data[id]
// if (prev) {
// radicals.data[id] = {
// ...d,
// sup: prev.sup
// }
// } else {
// radicals.data[id] = {
// ...d,
// sup: []
// }
// }
radicals.data[id] = d
})
for (const [k, v] of Object.entries(radicals.data)) {
if (v.components?.['wanikani']) {
v.components['wanikani'] = v.components['wanikani']
.map((s) => idMap.get(Number(s)) || s)
.filter((s) => s !== k)
}
v.similar = v.similar.map((s) => idMap.get(Number(s)) || s)
// v.sup = v.sup.map((s) => idMap.get(Number(s)) || s)
}
radicals.finalize()
}
if (require.main === module) {
main()
}
@@ -0,0 +1,39 @@
import fs from 'fs'
import { radicals } from './beautify-radicals'
async function main() {
const map = radicals.load()
fs.writeFileSync(
'../../_radicals.md',
Object.entries(map)
.map(([k, v]) => {
const headers = [k]
if (v.meaning !== k) {
headers.push(v.meaning)
}
if (v.reading) {
headers.push(v.reading)
}
headers.push(String(v.level))
const rows = [`## ${headers.join(', ')}`, '']
if (v.image) {
rows.push(
`<img src="${v.image.src}" alt="${k}"${
v.image.width ? ` width="${v.image.width}"` : ''
}${v.image.height ? ` height="${v.image.height}"` : ''} />`,
''
)
}
return rows.join('\n')
})
.join('\n\n')
)
}
if (require.main === module) {
main()
}
+53
View File
@@ -0,0 +1,53 @@
import fs from 'fs'
import axios from 'axios'
import { IKanji, IRadical } from './shared'
export const subjects = {
data: [] as (IKanji | IRadical)[],
filename: 'wanikani.json',
load() {
this.data = JSON.parse(fs.readFileSync(this.filename, 'utf-8'))
return this.data
},
dump(d: (IKanji | IRadical)[]) {
this.data = d
this.finalize()
},
finalize() {
fs.writeFileSync(this.filename, JSON.stringify(this.data))
}
}
async function main() {
const wk = axios.create({
baseURL: 'https://api.wanikani.com/v2/',
headers: {
Authorization: `Bearer ${process.env['WANIKANI_API_KEY']}`
}
})
const data: (IKanji | IRadical)[] = []
let nextURL = '/subjects?types=radical,kanji'
while (nextURL) {
const r = await wk
.get<{
pages: {
next_url?: string
}
data: (IKanji | IRadical)[]
}>(nextURL)
.then((r) => r.data)
data.push(...r.data)
console.info(r.pages.next_url)
nextURL = r.pages.next_url || ''
}
subjects.dump(data)
}
if (require.main === module) {
main()
}
+49
View File
@@ -0,0 +1,49 @@
export interface IKanji {
id: number
/** Actual type */
object: 'kanji'
url: string
data_updated_at: string
data: {
level: number
document_url: string
characters: string
meanings: {
meaning: string
primary: boolean
}[]
readings: {
reading: string
primary: boolean
type: 'kunyomi' | 'onyomi'
}[]
component_subject_ids: number[]
visually_similar_subject_ids: number[]
}
}
export interface IRadical {
id: number
/** Actual type */
object: 'radical'
url: string
data_updated_at: string
data: {
level: number
document_url: string
characters: string | null
character_images: {
url: string
metadata: {
inline_styles?: boolean
dimensions?: string
}
content_type: string
}[]
meanings: {
meaning: string
primary: boolean
}[]
amalgamation_subject_ids: number[]
}
}