diff options
author | lonkaars <loek@pipeframe.xyz> | 2023-07-13 16:39:01 +0200 |
---|---|---|
committer | lonkaars <loek@pipeframe.xyz> | 2023-07-13 16:39:01 +0200 |
commit | 28fb362147358819afeb0f0a5fa7a4ad136499ac (patch) | |
tree | 4c4224f503f66fcea1e25b464daf0f9659a09bab /api | |
parent | 919cdce6bcf12f564901ea536dae4227d025b031 (diff) |
ignore terms
Diffstat (limited to 'api')
-rw-r--r-- | api/base.ts | 10 | ||||
-rw-r--r-- | api/sentence.ts | 44 | ||||
-rw-r--r-- | api/word.ts | 76 | ||||
-rw-r--r-- | api/yomikun.ts | 14 |
4 files changed, 104 insertions, 40 deletions
diff --git a/api/base.ts b/api/base.ts index e89e76b..28940ef 100644 --- a/api/base.ts +++ b/api/base.ts @@ -1,18 +1,12 @@ -import Core from "../core/api.ts"; import Yomikun from "./yomikun.ts"; /** @summary generic class that keeps a reference to parent API reference */ export default abstract class APIBase { private _resolveAPI: (api: Yomikun) => void = _ => {}; - - protected api: Promise<Yomikun>; - - constructor() { - this.api = new Promise<Yomikun>(res => this._resolveAPI = res); - } + protected api = new Promise<Yomikun>(res => this._resolveAPI = res); /** @summary set API reference and return self (for use directly after constructor) */ - withParent(api: Yomikun) { + withAPI(api: Yomikun) { this._resolveAPI(api); return this; } diff --git a/api/sentence.ts b/api/sentence.ts index 6b1a1e4..2311913 100644 --- a/api/sentence.ts +++ b/api/sentence.ts @@ -10,8 +10,8 @@ export default class Sentence extends APIBase { protected breaks: Array<number> = []; protected frozen = false; - public ready: Promise<void>; private _resolveReady: () => void = () => {}; + public ready = new Promise<void>(res => this._resolveReady = res); constructor(input: string) { super(); @@ -20,7 +20,7 @@ export default class Sentence extends APIBase { } first(searchValue: RegExp | string): Word | undefined { - return this.words[0]; // TODO: implement + return this.at(this.original.search(searchValue)); } private async fetch() { @@ -28,11 +28,15 @@ export default class Sentence extends APIBase { } private async updateWords() { - this.words.clear(); + this.words = []; let token = 0; let i = 0; while (i < this.original.length) { - this.words.push(new Word(this.query!.words[token]).withParent(await this.api)); + this.words.push( + new Word(this.query!.words[token]) + .withAPI(await this.api) + .withParent(this) + ); i += this.query!.words[token].source.length; if (i == this.original.length) break; @@ -42,7 +46,11 @@ export default class Sentence extends APIBase { if (this.query!.words[token]?.start == i) continue; var remainder = this.original.substring(i, this.query!.words[token]?.start); - this.words.push(new Word(remainder).withParent(await this.api)); + this.words.push( + new Word(remainder) + .withAPI(await this.api) + .withParent(this) + ); i += remainder.length; } } @@ -53,8 +61,7 @@ export default class Sentence extends APIBase { }, ""); } - public async update() { - if (this.frozen) return; + public async forceUpdate() { // unresolve ready this.ready = new Promise(res => this._resolveReady = res); @@ -65,12 +72,29 @@ export default class Sentence extends APIBase { // mark ready again this._resolveReady(); + } + + public async update() { + if (this.frozen) return; + await this.forceUpdate(); } - public at(term: string) { - return this.original.indexOf(term); + public indexOf(searchString: string, position: number = 0) { + return this.original.indexOf(searchString, position); } + public at(indentifier: number | string): Word | undefined { + var index = typeof indentifier === "number" ? indentifier : this.indexOf(indentifier); + if (index == -1) return; + let wordIndex = 0; + for (let i = 0; wordIndex < this.words.length; wordIndex++) { + var length = this.words[wordIndex].length; + if (i + length > index) break; + i += length; + } + return this.words[wordIndex]; + } + public async break(location: number) { this.breaks.push(location); await this.update(); @@ -82,6 +106,6 @@ export default class Sentence extends APIBase { public async unfreeze() { this.frozen = false; - await this.update(); + await this.forceUpdate(); } } diff --git a/api/word.ts b/api/word.ts index 2e07c98..b519789 100644 --- a/api/word.ts +++ b/api/word.ts @@ -6,33 +6,33 @@ import "../util/object.ts"; import { Tag, TagGroup, TokenTags } from "../search/tags.ts"; import { SearchWord } from "../search/types.ts"; import { recursiveValues } from "../util/object.ts"; +import Sentence from "./sentence.ts"; + +// TODO: better irregular reading handling (should also work for counter words / 入る) // irregular stems taken from <https://en.wikipedia.org/wiki/Japanese_irregular_verbs#suru_and_kuru> -function irregularSuruStem(tags: TokenTags): string { +function irregularSuru(tags: TokenTags, conjugation: string): string { for (let i = 0, tag = tags[i]; i < tags.length; i++, tag = tags[i]) { if (!recursiveValues(Tag.Inflection).includes(tag)) continue; if (recursiveValues(Tag.Inflection.Reason).includes(tag)) continue; if ([ Tag.Inflection.Polite.Masu, Tag.Inflection.Suffix.Te, - Tag.Inflection.Tense.Past, Tag.Inflection.Desirable.Itai, // part of Wikipedia's -ta form - Tag.Inflection.Negative, - Tag.Inflection.Desirable.Volitional, Tag.Inflection.Command, - ].includes(tag as any)) return "し"; + ].includes(tag as any)) return "し" + conjugation; if ([ Tag.Inflection.Passive, Tag.Inflection.Causative, - ].includes(tag as any)) return "さ"; + ].includes(tag as any)) return "さ" + conjugation; // wikipedia has できる as the potential form for する, but できる here // means it's already foobar'd break; } - return "す"; + return conjugation; } -function irregularKuruStem(tags: TokenTags): string { +function irregularKuru(tags: TokenTags, conjugation: string): string { for (let i = 0, tag = tags[i]; i < tags.length; i++, tag = tags[i]) { if (!recursiveValues(Tag.Inflection).includes(tag)) continue; if (recursiveValues(Tag.Inflection.Reason).includes(tag)) continue; @@ -41,7 +41,7 @@ function irregularKuruStem(tags: TokenTags): string { Tag.Inflection.Suffix.Te, Tag.Inflection.Tense.Past, Tag.Inflection.Desirable.Itai, // part of Wikipedia's -ta form - ].includes(tag as any)) return "き"; + ].includes(tag as any)) return "き" + conjugation; if ([ Tag.Inflection.Negative, Tag.Inflection.Desirable.Volitional, @@ -49,10 +49,10 @@ function irregularKuruStem(tags: TokenTags): string { Tag.Inflection.Causative, Tag.Inflection.Potential, Tag.Inflection.Command, - ].includes(tag as any)) return "こ"; + ].includes(tag as any)) return "こ" + conjugation; break; } - return "く"; + return "く" + conjugation; } export default class Word extends APIBase { @@ -60,11 +60,22 @@ export default class Word extends APIBase { protected base: Japanese; /** @prop word as written in parent sentence */ protected text: Japanese; - /** @prop this.furigana should output kanji with reading */ - protected outputKanji: boolean = true; /** @prop this word represents an unrecognized sentence part between recognized terms */ protected filler: boolean; + private _resolveParent: (sentence: Sentence) => void = _ => {}; + /** @prop parent sentence */ + protected parent = new Promise<Sentence>(res => this._resolveParent = res); + + /** @prop length of word in sentence */ + public length: number; + /** @prop (conjugated) writing of term (*may* contain kanji) */ + public writing: string; + /** @prop (conjugated) reading of term (kana-only) */ + public reading: string; + /** @prop dictionary id for term */ + public id: number = -1; + constructor(input: string | SearchWord) { super(); if (typeof input === "string") { @@ -72,7 +83,6 @@ export default class Word extends APIBase { input = input as string; this.base = new Japanese(input, input); this.text = this.base; - this.outputKanji = false; } else { this.filler = false; input = input as SearchWord; @@ -87,26 +97,50 @@ export default class Word extends APIBase { // special reading for irregular verbs var reading = input.reading; - if (input.writing == '来る') reading = irregularKuruStem(input.tags) + conjugation; - else if (input.writing == '為る') reading = irregularSuruStem(input.tags) + conjugation; + if (input.writing == '来る') reading = irregularKuru(input.tags, conjugation); + else if (input.writing == '為る') reading = irregularSuru(input.tags, conjugation); else reading = reading.replaceLast(base, conjugation); // generate conjugated version of verb with kanji - this.text = new Japanese(input.writing.replaceLast(base, conjugation), reading); + this.text = new Japanese(input.source, reading); } else { this.text = this.base; } - this.outputKanji = input.source.hasKanji(); // only output kanji if input also uses kanji + this.id = input.id; } + this.writing = this.text.writing; + this.length = this.text.writing.length; + this.reading = this.text.reading; } furigana(format: JapaneseFormatter) { - if (!this.outputKanji) return this.text.reading; - else return this.text.furigana(format); + return this.text.furigana(format); } async glossary() { // TODO: output nothing if this.filler == true - return new Glossary().withParent(await this.api); + return new Glossary().withAPI(await this.api); } + + /** @summary check if this word is written as ~ */ + public written(as: string) { + return this.text.writing == as || this.base.writing == as; + } + + /** @summary check if this word is read as ~ */ + public read(as: string) { + return this.text.reading == as || this.base.reading == as; + } + + /** @summary ignore this word for currently logged in user and refresh the sentence */ + async ignore() { + await (await this.api)["setTermPriority"](this.base.writing, this.base.reading, -1); + await (await this.parent).update(); + } + + /** @summary set parent sentence for this word */ + public withParent(parent: Sentence) { + this._resolveParent(parent); + return this; + } } diff --git a/api/yomikun.ts b/api/yomikun.ts index 696361f..2b102fe 100644 --- a/api/yomikun.ts +++ b/api/yomikun.ts @@ -4,6 +4,9 @@ import Sentence from "./sentence.ts"; export default class Yomikun { protected core: Core; + protected user: string = "root"; + protected uid: number = 0; + public ready: Promise<void>; constructor(core?: Core) { @@ -16,9 +19,18 @@ export default class Yomikun { } async sentence(input: string): Promise<Sentence> { - var sentence = new Sentence(input).withParent(this); + var sentence = new Sentence(input).withAPI(this); await sentence.ready; return sentence; } + + public su(user: string) { + this.user = user; + // TODO: set this.uid + } + + private async setTermPriority(expression: string, reading: string, priority: number) { + this.core.user.termPriority(this.uid, expression, reading, priority); + } } |