From 5f03ca99b9c765a3215f5d99ecabe6d46e559425 Mon Sep 17 00:00:00 2001 From: Lukince Date: Tue, 9 Nov 2021 15:45:02 +0900 Subject: [PATCH] New feature : Replacer Add override in assembler --- mod.ts | 4 +- src/entities/assembler.ts | 15 +++- src/entities/hangul.ts | 15 ++++ src/entities/replacer.ts | 154 ++++++++++++++++++++++++++++++++++++++ test/replacer.ts | 28 +++++++ 5 files changed, 212 insertions(+), 4 deletions(-) create mode 100644 src/entities/replacer.ts create mode 100644 test/replacer.ts diff --git a/mod.ts b/mod.ts index 2b97200..474abbc 100644 --- a/mod.ts +++ b/mod.ts @@ -1,8 +1,10 @@ export { Hangul } from "./src/entities/hangul.ts" export { Converter } from "./src/entities/converter.ts" export { Assembler } from "./src/entities/assembler.ts" -export { InteractLists, ComplexInteractionLists } from "./src/entities/interactList.ts" export { HangulBuilder } from "./src/entities/hangulBuilder.ts" +export { Replacer, Infection } from "./src/entities/replacer.ts" + +export { InteractLists, ComplexInteractionLists } from "./src/entities/interactList.ts" export { Range } from "./src/modules/random.ts" export type { StringType } from "./src/entities/stringType.ts" diff --git a/src/entities/assembler.ts b/src/entities/assembler.ts index c6c30b8..b3b1742 100644 --- a/src/entities/assembler.ts +++ b/src/entities/assembler.ts @@ -1,4 +1,5 @@ import { assemble, disassemble } from "../modules/assemble.ts" +import { Hangul } from "./hangul.ts" /** * Provide hangul assemble and disassemble function. @@ -14,13 +15,21 @@ export class Assembler { return assemble((str as string[]).reduce((p, c) => p + c)); } + /** + * This will disassemble hangul. + * @example Assembler.disassemble(new Hangul('안')) //['ㅇ','ㅏ','ㄴ'] + * @param han The hangul class to disassemble + * @returns Disassembled hangul + */ + static disassemble(han: Hangul): string[] /** * This will disassemble hangul. * @example Assembler.disassemble('안') // ['ㅇ','ㅏ','ㄴ'] - * @param str The string value which want to disassemble + * @param str The string value to disassemble * @returns Disassembled hangul */ - static disassemble(str: string): string[] { - return disassemble(str); + static disassemble(str: string): string[] + static disassemble(obj: Hangul | string): string[] { + return disassemble(obj instanceof Hangul ? obj.toString() : obj); } } diff --git a/src/entities/hangul.ts b/src/entities/hangul.ts index 1a44c1d..94d6535 100644 --- a/src/entities/hangul.ts +++ b/src/entities/hangul.ts @@ -5,6 +5,8 @@ import { StringType, import { random, RandomOption } from "../modules/random.ts" import { Converter } from "./converter.ts"; +import { Infection } from "./replacer.ts"; +import { Initial, Neutral, Final } from "./interactList.ts"; function insert(origin: string, ind: number, value: string): string { return [origin.slice(0, ind), value, origin.slice(ind)].join(''); @@ -20,10 +22,13 @@ export class Hangul { */ constructor(s: string) { this.content = s; + this.infection = new Infection(s, l => l); } private content: string; + private infection: Infection; + /** * Convert string of this class to Korean * @returns Korean string @@ -91,6 +96,16 @@ export class Hangul { return Hangul.getType(this.content); } + /** Refer `Replacer.infect` */ + infect(from: Initial | Neutral | Final, to: Initial | Neutral | Final): void { + this.infection.replacer = undefined; + this.infection.from = from; + this.infection.to = to; + this.infection.infect(); + + this.content = this.infection.toString(); + } + /** * Convert specific value to Korean. * @example Hangul.engToKor(new Hangul('dks')) // '안' diff --git a/src/entities/replacer.ts b/src/entities/replacer.ts new file mode 100644 index 0000000..e70b8ae --- /dev/null +++ b/src/entities/replacer.ts @@ -0,0 +1,154 @@ +import { Hangul } from "./hangul.ts" +import { Assembler } from "./assembler.ts" + +import { + Initial, + Neutral, + Final +} from "./interactList.ts" + +/** + * Provides static method replacing characters in disassembled korean + */ +export class Replacer { + /** + * Replace first character using replace function. + * @param input The string or Hangul class to replace + * @param replacer The replace function. The letter value will replace as return value. + */ + static infect(input: Hangul | string, replacer: (letter: T) => T): Hangul + /** + * Replace first character that match with `from` to `to`. + * @param input The string or Hangul class to replace + * @param from The korean character that you want to select. + * @param to The korean character to replace. + */ + static infect(input: Hangul | string, from: T, to: T): Hangul + /** + * Replace first character that included in `from` to `to`. + * @param input The string or Hangul class to replace + * @param from The korean character array that you want to select. + * @param to The korean character to replace. + */ + static infect(input: Hangul | string, from: T[], to: T): Hangul + static infect(input: Hangul | string, para1: any, para2?: T): Hangul { + const inf = + para1 instanceof Function + ? new Infection(input, para1) + : new Infection(input, para1, para2); + + inf.infect(); + return new Hangul(inf.toString()); + } + + /** + * Replace all characters using replace function. + * @param input The string or Hangul class to replace + * @param replacer The replace function. The letter value will replace as return value. + */ + static replaceAll(input: Hangul | string, replacer: (letter: T) => T): Hangul + /** + * Replace all characters that match with `from` to `to`. + * @param input The string or Hangul class to replace + * @param from The korean character that you want to select. + * @param to The korean character to replace. + */ + static replaceAll(input: Hangul | string, from: T, to: T): Hangul + /** + * Replace all characters that included in `from` to `to`. + * @param input The string or Hangul class to replace + * @param from The korean character array that you want to select. + * @param to The korean character to replace. + */ + static replaceAll(input: Hangul | string, from: T[], to: T): Hangul + static replaceAll(input: Hangul | string, para1: any, para2?: T): Hangul { + const inf = + para1 instanceof Function + ? new Infection(input, para1) + : new Infection(input, para1, para2); + + for (;!inf.isInfector;) inf.infect(); + + return new Hangul(inf.toString()); + } +} + +/** + * Provides that sequentially replace function for single object. + */ +export class Infection { + /** + * Declare new `Infection` class with replace function. + * @param str Original string or Hangul class + * @param replacer The replace function. The letter value will replace as return value. + */ + constructor(str: Hangul | string, replacer: (letter: T) => T) + /** + * Declare new `Infection` class with `from` and `to` + * @param str Original string or Hangul class + * @param from The korean character that you want to select. + * @param to The korean character to replace. + */ + constructor(str: Hangul | string, from: T, to: T) + /** + * Declare new `Infection` class with `from` and `to` + * @param str Original string or Hangul class + * @param from The korean character array that you want to select. + * @param to The korean character to replace. + */ + constructor(str: Hangul | string, from: T[], to: T) + constructor(str: Hangul | string, para1: T | T[] | Function, para2?: T) { + this.word = str instanceof Hangul ? str.toString() : str; + + if (para1 instanceof Function) { + this.replacer = para1 as (letter: T) => T; + } else { + this.from = para1; + this.to = para2 as T; + } + } + + private word: string; + + /** The replace function. The letter value will replace as return value. */ + replacer?: (letter: T) => T; + + /** The korean character or array that you want to select. */ + from?: T | T[]; + /** The korean character to replace. */ + to?: T; + + /** Whether all value that match with `from` replace to `to` */ + isInfector: boolean = false; + /** The count of how many values have been replaced. */ + infectCount: number = 0; + + /** Replace first value that match with `from` to `to` */ + infect(): void { + const w = Assembler.disassemble(this.word); + + if (this.replacer !== undefined) { + for(let i = 0; i < w.length; i++) { + if (!/[ㄱ-ㅣ]/.test(w[i])) continue; + if (this.replacer(w[i] as T) !== w[i]) { w[i] = this.replacer(w[i] as T); break; } + } + + if (w.map(l => this.replacer!(l as T)).every((v, ind) => v === w[ind])) this.isInfector = true; + } else { + for (let i = 0; i < w.length; i++) { + if (!/[ㄱ-ㅣ]/.test(w[i])) continue; + if ((this.from as T[]).includes(w[i] as T)) { w[i] = this.to!; break; } + } + + if (w.every(v => !this.from!.includes(v as T))) this.isInfector = true; + } + + this.infectCount++; + this.word = Assembler.assemble(w); + } + + /** return current string. */ + toString(): string { + return this.word; + } +} \ No newline at end of file diff --git a/test/replacer.ts b/test/replacer.ts new file mode 100644 index 0000000..d16e981 --- /dev/null +++ b/test/replacer.ts @@ -0,0 +1,28 @@ +import { + Hangul, + Replacer, + Infection +} from "../mod.ts" + +const word = new Hangul('안녕하세요'); + +console.log("word:", word.toString()); +console.log("replacerAll:", Replacer.replaceAll(word, k => { + if (k == 'ㅇ') return 'ㅁ'; + return k; +}).toString()); +console.log("replaceAll:", Replacer.replaceAll(word, 'ㅇ', 'ㅁ').toString()); +console.log("replaceAll:", Replacer.replaceAll(word, ['ㅇ', 'ㄴ'], 'ㅁ').toString()); +console.log("infect:", Replacer.infect(word, 'ㅇ', 'ㅁ').toString()); + +const inf = new Infection(word, 'ㅇ', 'ㅁ'); + +for (console.log(inf.toString(), inf.infectCount); !inf.isInfector; console.log(inf.toString(), inf.infectCount)) { + inf.infect(); +} + +console.log("infection:", inf); + +word.infect('ㅇ', 'ㅁ'); +word.infect('ㅇ', 'ㅁ'); +console.log("word:", word); \ No newline at end of file