import { TokenTags, parseTags } from "../search/tags.ts"; import { Wrapper } from "./wrap.ts"; declare global { interface String { /** @summary get UnicodeRange for character at index 0 */ range(): UnicodeRange; /** @summary create a RangeTally object for counting used unicode ranges in string */ rangeTally(): RangeTally; /** @summary parse concatenated tag string to TokenTags */ parseTags(): TokenTags; /** * @summary Remove all instances of a substring in a string, using a regular expression or search string * @param searchValue A string to search for */ removeAll(searchValue: string | RegExp): string; /** * @summary parse string as JSON, with optional fallback value * * fallback is undefined by default. if fallback is specified, it will be * returned if JSON.parse throws any error. if fallback is not specified, * no errors will be caught. * * @argument fallback return this value if parsing fails */ json(fallback?: any): any; /** * @summary map each character of a string to another character using * `mapFn` */ map(mapFn: (char: string) => string): string; /** * @summary return length of the match of searchValue from startIndex (default: 0) * * Similar to String.prototype.startsWith, but returns the length of the * match instead of a boolean true or false. * * @param searchString string to search for * @param position index to search from (0 by default = start of string) */ cmpLen(searchString: string, position?: number): number; /** @summary remove `length` characters from end of string */ removeEnd(length: number): string; /** @summary replace last instance of `searchString` with `replaceValue` */ replaceLast(searchString: string, replaceValue: string): string; /** @summary wrap string using Wrapper */ wrap(wrapper: Wrapper): string; } } export enum UnicodeRange { BasicLatin = "latin", Whitespace = "any-whitespace", Punctuation = "any-punctuation", Unknown = "any-unknown", JapaneseFWPunctuation = "jp-full-width-punctuation", JapaneseHWPunctuation = "jp-half-width-punctuation", JapaneseFWHiragana = "jp-full-width-hiragana", JapaneseFWKatakana = "jp-full-width-katakana", JapaneseFWLatin = "jp-full-width-latin", JapaneseHWKatakana = "jp-half-width-katakana", JapaneseKanji = "jp-kanji", JapaneseKanjiRadicals = "jp-kanji-radicals", JapaneseAuxiliary = "jp-aux", } type RangeTally = Record; String.prototype.range = function() { var code = this.charCodeAt(0); if (0x09 == code) return UnicodeRange.Whitespace; // tab if (0x20 == code) return UnicodeRange.Whitespace; // space if (0x21 == code) return UnicodeRange.Punctuation; // exclamation mark if (0x2e == code) return UnicodeRange.Punctuation; // full stop if (0x3f == code) return UnicodeRange.Punctuation; // question mark // https://stackoverflow.com/a/53807563 if (0x0000 <= code && code <= 0x007f) return UnicodeRange.BasicLatin; if (0x2e80 <= code && code <= 0x2fd5) return UnicodeRange.JapaneseKanjiRadicals; if (0x3000 <= code && code <= 0x303f) return UnicodeRange.JapaneseFWPunctuation; if (0xff5f <= code && code <= 0xff60) return UnicodeRange.JapaneseFWPunctuation; if (0x3041 <= code && code <= 0x3096) return UnicodeRange.JapaneseFWHiragana; if (0x30a1 <= code && code <= 0x30ff) return UnicodeRange.JapaneseFWKatakana; if (0x3400 <= code && code <= 0x4db5) return UnicodeRange.JapaneseKanji; if (0x4e00 <= code && code <= 0x9fcb) return UnicodeRange.JapaneseKanji; if (0xf900 <= code && code <= 0xfa6a) return UnicodeRange.JapaneseKanji; if (0xff61 <= code && code <= 0xff65) return UnicodeRange.JapaneseHWPunctuation; if (0xff66 <= code && code <= 0xff9f) return UnicodeRange.JapaneseHWKatakana; if (0x31f0 <= code && code <= 0x31ff) return UnicodeRange.JapaneseAuxiliary; if (0x3220 <= code && code <= 0x3243) return UnicodeRange.JapaneseAuxiliary; if (0x3280 <= code && code <= 0x337f) return UnicodeRange.JapaneseAuxiliary; if (0xff01 <= code && code <= 0xff5e) return UnicodeRange.JapaneseFWLatin; return UnicodeRange.Unknown; } String.prototype.rangeTally = function() { var tally = Object.values(UnicodeRange).reduce((a: any,c) => (a[c] = 0, a), {}) as RangeTally; for (var char of this) tally[char.range()]++; return tally; }; String.prototype.parseTags = function() { return parseTags(this as string); } String.prototype.removeAll = function(searchValue) { return this.replaceAll(searchValue, ""); } String.prototype.json = function(fallback) { if (fallback) { try { return JSON.parse(this as string); } catch { return fallback; } } else { return JSON.parse(this as string); } } String.prototype.map = function(mapFn) { var out = ""; for (var char of this) out += mapFn(char); return out; } String.prototype.cmpLen = function(searchString, position = 0) { let len = 0; for (let i = 0; i < searchString.length; i++) { if (i + position >= this.length) break; if (this[i + position] == searchString[i]) len++; else break; } return len; } String.prototype.removeEnd = function(length) { return this.substring(0, this.length - length); } String.prototype.replaceLast = function(find, replace) { var i = this.lastIndexOf(find); if (i == -1) return this as string; // not found return this.substring(0, i) + replace + this.substring(i + find.length); } String.prototype.wrap = function(wrapper) { return wrapper[0] + this + wrapper[1]; }