lyric-romanizer 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +40 -0
- package/README.md +97 -31
- package/dist/detector.d.ts +74 -0
- package/dist/detector.d.ts.map +1 -1
- package/dist/detector.js +73 -23
- package/dist/detector.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/romanizer.d.ts +7 -2
- package/dist/romanizer.d.ts.map +1 -1
- package/dist/romanizer.js +173 -115
- package/dist/romanizer.js.map +1 -1
- package/dist/types.d.ts +25 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/docs/README.hi.md +296 -0
- package/docs/README.ja.md +296 -0
- package/docs/README.ko.md +296 -0
- package/docs/README.ru.md +296 -0
- package/docs/README.ta.md +296 -0
- package/docs/README.th.md +296 -0
- package/docs/README.zh-CN.md +296 -0
- package/docs/README.zh-yue.md +306 -0
- package/docs/adr/0001-outputs-are-a-contract.md +21 -0
- package/docs/adr/0002-whole-array-script-pinning.md +26 -0
- package/docs/adr/0003-zero-api-default-injectable-engines.md +22 -0
- package/docs/adr/0004-no-unified-variant-seam.md +23 -0
- package/docs/adr/0005-always-latest-dependencies.md +23 -0
- package/package.json +13 -6
- package/src/detector.ts +127 -0
- package/src/index.ts +18 -0
- package/src/romanizer.ts +240 -0
- package/src/shims.d.ts +3 -0
- package/src/types.ts +75 -0
package/dist/romanizer.js
CHANGED
|
@@ -1,137 +1,195 @@
|
|
|
1
|
-
import
|
|
2
|
-
import KuromojiAnalyzer from '@sglkc/kuroshiro-analyzer-kuromoji';
|
|
3
|
-
import { pinyin } from 'pinyin-pro';
|
|
4
|
-
import CyrillicToTranslit from 'cyrillic-to-translit-js';
|
|
5
|
-
import Sanscript from '@indic-transliteration/sanscript';
|
|
6
|
-
import { romanize as romanizeKorean } from '@romanize/korean';
|
|
7
|
-
import romanizeThai from '@dehoist/romanize-thai';
|
|
8
|
-
import { romanize as romanizeTamil } from 'tamil-romanizer';
|
|
9
|
-
import { transliterate } from 'transliteration';
|
|
10
|
-
import { detectScript } from './detector.js';
|
|
1
|
+
import { NON_LATIN_SCRIPT_RE, detectScript } from './detector.js';
|
|
11
2
|
import { UnsupportedRomanizationError } from './types.js';
|
|
12
3
|
const DEFAULT_JAPANESE_DICT_PATH = 'https://cdn.jsdelivr.net/npm/kuromoji/dict';
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
|
|
4
|
+
const HAS_LETTER_RE = /\p{L}/u;
|
|
5
|
+
const ASCII_LETTER_RE = /[A-Za-z]/;
|
|
6
|
+
/**
|
|
7
|
+
* Memoizes an async load; a failed load clears the cache so the next call
|
|
8
|
+
* retries instead of caching the rejection.
|
|
9
|
+
*/
|
|
10
|
+
function lazy(load) {
|
|
11
|
+
let cached = null;
|
|
12
|
+
return () => {
|
|
13
|
+
if (!cached) {
|
|
14
|
+
cached = load().catch((error) => {
|
|
15
|
+
cached = null;
|
|
16
|
+
throw error;
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
return cached;
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
/** Rejects the load when interop resolution finds nothing callable. */
|
|
23
|
+
function resolved(value, what) {
|
|
24
|
+
if (value === undefined)
|
|
25
|
+
throw new Error(`Failed to resolve ${what} from its module.`);
|
|
26
|
+
return value;
|
|
27
|
+
}
|
|
28
|
+
// Every engine loads on first use so that importing this module costs nothing
|
|
29
|
+
// until a line of the matching script is romanized. The `?? default` chains
|
|
30
|
+
// bridge module shapes: bundlers surface these CJS packages' named exports,
|
|
31
|
+
// while plain Node ESM surfaces them only on `default`.
|
|
32
|
+
const loadPinyin = lazy(async () => {
|
|
33
|
+
const mod = await import('pinyin-pro');
|
|
34
|
+
return resolved(mod.pinyin ?? mod.default?.pinyin, 'pinyin');
|
|
35
|
+
});
|
|
36
|
+
const loadJyutping = lazy(() => import('to-jyutping'));
|
|
37
|
+
const loadKorean = lazy(async () => {
|
|
38
|
+
const mod = await import('@romanize/korean');
|
|
39
|
+
return resolved(mod.romanize ?? mod.default?.romanize, 'korean romanize');
|
|
40
|
+
});
|
|
41
|
+
const loadThai = lazy(async () => {
|
|
42
|
+
const mod = await import('@dehoist/romanize-thai');
|
|
43
|
+
return resolved(mod.default ?? mod.romanize, 'thai romanize');
|
|
44
|
+
});
|
|
45
|
+
const loadTamil = lazy(async () => {
|
|
46
|
+
const mod = await import('tamil-romanizer');
|
|
47
|
+
return resolved(mod.romanize ?? mod.default?.romanize, 'tamil romanize');
|
|
48
|
+
});
|
|
49
|
+
const loadSanscript = lazy(async () => {
|
|
50
|
+
const mod = await import('@indic-transliteration/sanscript');
|
|
51
|
+
return resolved(mod.default ?? mod.Sanscript, 'Sanscript');
|
|
52
|
+
});
|
|
53
|
+
const loadTransliterate = lazy(async () => {
|
|
54
|
+
const mod = await import('transliteration');
|
|
55
|
+
return resolved(mod.transliterate ?? mod.default?.transliterate, 'transliterate');
|
|
56
|
+
});
|
|
57
|
+
const loadCyrillicTranslit = lazy(async () => {
|
|
58
|
+
const mod = await import('cyrillic-to-translit-js');
|
|
59
|
+
const factory = resolved(mod.default ?? mod, 'CyrillicToTranslit');
|
|
60
|
+
return { ru: factory({ preset: 'ru' }), uk: factory({ preset: 'uk' }) };
|
|
61
|
+
});
|
|
62
|
+
/**
|
|
63
|
+
* Ukrainian-specific characters pick the Ukrainian preset; all other Cyrillic
|
|
64
|
+
* romanizes as Russian. Applied per line, so a mixed-language song switches
|
|
65
|
+
* preset line by line.
|
|
66
|
+
*/
|
|
67
|
+
export function selectCyrillicPreset(line) {
|
|
68
|
+
return /[іїєґ]/i.test(line) ? 'uk' : 'ru';
|
|
32
69
|
}
|
|
33
70
|
class DefaultRomanizer {
|
|
34
71
|
japaneseDictPath;
|
|
35
|
-
|
|
36
|
-
|
|
72
|
+
engines;
|
|
73
|
+
loadKuroshiro = lazy(async () => {
|
|
74
|
+
const [kuroshiroModule, analyzerModule] = await Promise.all([
|
|
75
|
+
import('@sglkc/kuroshiro'),
|
|
76
|
+
import('@sglkc/kuroshiro-analyzer-kuromoji'),
|
|
77
|
+
]);
|
|
78
|
+
const KuroshiroCtor = kuroshiroModule.default ?? kuroshiroModule;
|
|
79
|
+
const KuromojiAnalyzer = analyzerModule.default ?? analyzerModule;
|
|
80
|
+
const instance = new KuroshiroCtor();
|
|
81
|
+
await instance.init(new KuromojiAnalyzer({ dictPath: this.japaneseDictPath }));
|
|
82
|
+
return instance;
|
|
83
|
+
});
|
|
37
84
|
constructor(options) {
|
|
38
85
|
this.japaneseDictPath = options?.japaneseDictPath ?? DEFAULT_JAPANESE_DICT_PATH;
|
|
86
|
+
// Null-prototype: an out-of-contract script name from an untyped caller
|
|
87
|
+
// (e.g. 'toString') must miss the lookup rather than resolve to an
|
|
88
|
+
// inherited Object.prototype method and be invoked as an engine.
|
|
89
|
+
const engines = Object.assign(Object.create(null), this.buildDefaultEngines());
|
|
90
|
+
for (const [script, engine] of Object.entries(options?.engines ?? {})) {
|
|
91
|
+
if (engine)
|
|
92
|
+
engines[script] = engine;
|
|
93
|
+
}
|
|
94
|
+
this.engines = engines;
|
|
39
95
|
}
|
|
40
96
|
async romanizeLine(line, options) {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
const script = options?.script ?? detectScript([line]);
|
|
44
|
-
if (script === 'latin')
|
|
45
|
-
return line;
|
|
46
|
-
if (requiresExternalRomanization(script)) {
|
|
47
|
-
throw new UnsupportedRomanizationError(script);
|
|
48
|
-
}
|
|
49
|
-
try {
|
|
50
|
-
switch (script) {
|
|
51
|
-
case 'japanese': {
|
|
52
|
-
const k = await this.getKuroshiro();
|
|
53
|
-
return k.convert(line, { to: 'romaji', mode: 'spaced' });
|
|
54
|
-
}
|
|
55
|
-
case 'chinese': {
|
|
56
|
-
if (options?.dialect === 'cantonese') {
|
|
57
|
-
try {
|
|
58
|
-
const jyutping = await this.getJyutpingModule();
|
|
59
|
-
const result = jyutping.getJyutpingText(line);
|
|
60
|
-
if (result)
|
|
61
|
-
return result;
|
|
62
|
-
}
|
|
63
|
-
catch {
|
|
64
|
-
// fall through to pinyin
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
return pinyin(line, { toneType: 'symbol', type: 'string' });
|
|
68
|
-
}
|
|
69
|
-
case 'korean':
|
|
70
|
-
return romanizeKorean(line);
|
|
71
|
-
case 'cyrillic':
|
|
72
|
-
return /[іїєґ]/i.test(line)
|
|
73
|
-
? cyrillicTranslitUk.transform(line)
|
|
74
|
-
: cyrillicTranslitRu.transform(line);
|
|
75
|
-
case 'devanagari':
|
|
76
|
-
case 'gujarati':
|
|
77
|
-
case 'gurmukhi':
|
|
78
|
-
case 'telugu':
|
|
79
|
-
case 'kannada':
|
|
80
|
-
case 'odia': {
|
|
81
|
-
const scheme = SANSCRIPT_SCHEME[script];
|
|
82
|
-
if (!scheme)
|
|
83
|
-
throw new Error(`Missing Sanscript scheme mapping for '${script}'.`);
|
|
84
|
-
if (!Sanscript.schemes?.[scheme]) {
|
|
85
|
-
throw new Error(`Sanscript does not support scheme '${scheme}' for '${script}'.`);
|
|
86
|
-
}
|
|
87
|
-
return Sanscript.t(line, scheme, 'iast');
|
|
88
|
-
}
|
|
89
|
-
case 'tamil':
|
|
90
|
-
return romanizeTamil(line);
|
|
91
|
-
case 'thai':
|
|
92
|
-
return romanizeThai(line);
|
|
93
|
-
default:
|
|
94
|
-
return transliterate(line);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
catch {
|
|
98
|
-
return transliterate(line);
|
|
99
|
-
}
|
|
97
|
+
const { text } = await this.resolveLine(line, options?.script, options);
|
|
98
|
+
return text;
|
|
100
99
|
}
|
|
101
100
|
async romanizeLines(lines, options) {
|
|
102
101
|
const script = options?.script ?? detectScript(lines);
|
|
103
|
-
if (
|
|
102
|
+
if (script !== 'latin' && !this.engines[script]) {
|
|
104
103
|
throw new UnsupportedRomanizationError(script);
|
|
105
104
|
}
|
|
106
105
|
if (script === 'latin') {
|
|
107
|
-
return { script, lines: [...lines] };
|
|
106
|
+
return { script, lines: [...lines], fallbacks: lines.map(() => false) };
|
|
108
107
|
}
|
|
109
|
-
const
|
|
110
|
-
return {
|
|
108
|
+
const resolved = await Promise.all(lines.map((line) => this.resolveLine(line, script, options)));
|
|
109
|
+
return {
|
|
110
|
+
script,
|
|
111
|
+
lines: resolved.map((r) => r.text),
|
|
112
|
+
fallbacks: resolved.map((r) => r.fallback),
|
|
113
|
+
};
|
|
111
114
|
}
|
|
112
|
-
async
|
|
113
|
-
if (!
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
115
|
+
async resolveLine(line, script, options) {
|
|
116
|
+
if (!line.trim() || !HAS_LETTER_RE.test(line))
|
|
117
|
+
return { text: line, fallback: false };
|
|
118
|
+
const resolved = script ?? detectScript([line]);
|
|
119
|
+
if (resolved === 'latin')
|
|
120
|
+
return { text: line, fallback: false };
|
|
121
|
+
// Checked before the latin guard below so that a script with no engine
|
|
122
|
+
// throws regardless of what the line contains — matching romanizeLines,
|
|
123
|
+
// which rejects such a script before looking at any line.
|
|
124
|
+
const engine = this.engines[resolved];
|
|
125
|
+
if (!engine)
|
|
126
|
+
throw new UnsupportedRomanizationError(resolved);
|
|
127
|
+
// A pinned script (romanizeLines, or an explicit option) skips per-line
|
|
128
|
+
// detection, so re-apply the latin no-op here: a line with ASCII letters
|
|
129
|
+
// and no character of any detectable script has nothing the pinned engine
|
|
130
|
+
// could romanize — without this, engines mangle it (pinyin-pro spaces
|
|
131
|
+
// "Hello" into "H e l l o").
|
|
132
|
+
if (ASCII_LETTER_RE.test(line) && !NON_LATIN_SCRIPT_RE.test(line)) {
|
|
133
|
+
return { text: line, fallback: false };
|
|
124
134
|
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
if (!this.jyutpingReady) {
|
|
129
|
-
this.jyutpingReady = import('to-jyutping').catch((e) => {
|
|
130
|
-
this.jyutpingReady = null;
|
|
131
|
-
throw e;
|
|
132
|
-
});
|
|
135
|
+
const context = { dialect: options?.dialect ?? 'mandarin' };
|
|
136
|
+
try {
|
|
137
|
+
return { text: await engine(line, context), fallback: false };
|
|
133
138
|
}
|
|
134
|
-
|
|
139
|
+
catch {
|
|
140
|
+
// Universal-fallback policy: a failed engine (or engine load) must not
|
|
141
|
+
// keep lyrics from rendering. Degrade to plain transliteration and
|
|
142
|
+
// report it via RomanizeResult.fallbacks.
|
|
143
|
+
try {
|
|
144
|
+
const transliterate = await loadTransliterate();
|
|
145
|
+
return { text: transliterate(line), fallback: true };
|
|
146
|
+
}
|
|
147
|
+
catch {
|
|
148
|
+
// Even the universal engine is unavailable. Render the line as-is
|
|
149
|
+
// rather than failing the whole batch; the flag reports the degradation.
|
|
150
|
+
return { text: line, fallback: true };
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
// Total over EngineScript: adding a local script to ScriptType (or
|
|
155
|
+
// reclassifying one in SCRIPT_METADATA) is a compile error here until the
|
|
156
|
+
// engine row exists — there is no default arm to fall through silently.
|
|
157
|
+
buildDefaultEngines() {
|
|
158
|
+
const sanscriptEngine = (scheme) => async (line) => (await loadSanscript()).t(line, scheme, 'iast');
|
|
159
|
+
return {
|
|
160
|
+
japanese: async (line) => {
|
|
161
|
+
const kuroshiro = await this.loadKuroshiro();
|
|
162
|
+
return kuroshiro.convert(line, { to: 'romaji', mode: 'spaced' });
|
|
163
|
+
},
|
|
164
|
+
chinese: async (line, context) => {
|
|
165
|
+
if (context.dialect === 'cantonese') {
|
|
166
|
+
try {
|
|
167
|
+
const jyutping = await loadJyutping();
|
|
168
|
+
const result = jyutping.getJyutpingText(line);
|
|
169
|
+
if (result)
|
|
170
|
+
return result;
|
|
171
|
+
}
|
|
172
|
+
catch {
|
|
173
|
+
// fall through to pinyin
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
const pinyin = await loadPinyin();
|
|
177
|
+
return pinyin(line, { toneType: 'symbol', type: 'string' });
|
|
178
|
+
},
|
|
179
|
+
korean: async (line) => (await loadKorean())(line),
|
|
180
|
+
cyrillic: async (line) => {
|
|
181
|
+
const translit = await loadCyrillicTranslit();
|
|
182
|
+
return translit[selectCyrillicPreset(line)].transform(line);
|
|
183
|
+
},
|
|
184
|
+
devanagari: sanscriptEngine('devanagari'),
|
|
185
|
+
gujarati: sanscriptEngine('gujarati'),
|
|
186
|
+
gurmukhi: sanscriptEngine('gurmukhi'),
|
|
187
|
+
telugu: sanscriptEngine('telugu'),
|
|
188
|
+
kannada: sanscriptEngine('kannada'),
|
|
189
|
+
odia: sanscriptEngine('oriya'),
|
|
190
|
+
tamil: async (line) => (await loadTamil())(line),
|
|
191
|
+
thai: async (line) => (await loadThai())(line),
|
|
192
|
+
};
|
|
135
193
|
}
|
|
136
194
|
}
|
|
137
195
|
export function createRomanizer(options) {
|
package/dist/romanizer.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"romanizer.js","sourceRoot":"","sources":["../src/romanizer.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"romanizer.js","sourceRoot":"","sources":["../src/romanizer.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,14 +1,39 @@
|
|
|
1
1
|
export type ScriptType = 'japanese' | 'chinese' | 'korean' | 'cyrillic' | 'devanagari' | 'gujarati' | 'gurmukhi' | 'telugu' | 'kannada' | 'odia' | 'tamil' | 'malayalam' | 'bengali' | 'arabic' | 'hebrew' | 'thai' | 'latin' | 'other';
|
|
2
|
+
export type RomanizeEngineContext = {
|
|
3
|
+
/** Chinese romanization system. Every other built-in engine ignores it. */
|
|
4
|
+
dialect: 'mandarin' | 'cantonese';
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* An engine adapter: romanizes one line of its script. May be synchronous or
|
|
8
|
+
* asynchronous. Throwing (or rejecting) triggers the universal transliteration
|
|
9
|
+
* fallback, reported per line via `RomanizeResult.fallbacks`.
|
|
10
|
+
*/
|
|
11
|
+
export type RomanizeEngine = (line: string, context: RomanizeEngineContext) => string | Promise<string>;
|
|
2
12
|
export type RomanizerOptions = {
|
|
3
13
|
japaneseDictPath?: string;
|
|
14
|
+
/**
|
|
15
|
+
* Override the built-in engine for a script, or plug an engine for a script
|
|
16
|
+
* that has none built in (arabic, hebrew, malayalam, bengali, other).
|
|
17
|
+
* Scripts without an engine — built-in or injected — throw
|
|
18
|
+
* `UnsupportedRomanizationError`. Entries with an `undefined` value are
|
|
19
|
+
* ignored, as is a `latin` entry: latin text is always returned unchanged.
|
|
20
|
+
*/
|
|
21
|
+
engines?: Partial<Record<ScriptType, RomanizeEngine>>;
|
|
4
22
|
};
|
|
5
23
|
export type RomanizeOptions = {
|
|
6
24
|
script?: ScriptType;
|
|
25
|
+
/** Only honored for `chinese`; every other script ignores it. */
|
|
7
26
|
dialect?: 'mandarin' | 'cantonese';
|
|
8
27
|
};
|
|
9
28
|
export type RomanizeResult = {
|
|
10
29
|
script: ScriptType;
|
|
11
30
|
lines: string[];
|
|
31
|
+
/**
|
|
32
|
+
* Aligned with `lines`: `true` where the script engine failed and the line
|
|
33
|
+
* was universally transliterated as a last resort. Always populated by this
|
|
34
|
+
* library; optional so existing code constructing results keeps compiling.
|
|
35
|
+
*/
|
|
36
|
+
fallbacks?: boolean[];
|
|
12
37
|
};
|
|
13
38
|
export interface Romanizer {
|
|
14
39
|
romanizeLine(line: string, options?: RomanizeOptions): Promise<string>;
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GAClB,UAAU,GACV,SAAS,GACT,QAAQ,GACR,UAAU,GACV,YAAY,GACZ,UAAU,GACV,UAAU,GACV,QAAQ,GACR,SAAS,GACT,MAAM,GACN,OAAO,GACP,WAAW,GACX,SAAS,GACT,QAAQ,GACR,QAAQ,GACR,MAAM,GACN,OAAO,GACP,OAAO,CAAC;AAEZ,MAAM,MAAM,gBAAgB,GAAG;IAC7B,gBAAgB,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GAClB,UAAU,GACV,SAAS,GACT,QAAQ,GACR,UAAU,GACV,YAAY,GACZ,UAAU,GACV,UAAU,GACV,QAAQ,GACR,SAAS,GACT,MAAM,GACN,OAAO,GACP,WAAW,GACX,SAAS,GACT,QAAQ,GACR,QAAQ,GACR,MAAM,GACN,OAAO,GACP,OAAO,CAAC;AAEZ,MAAM,MAAM,qBAAqB,GAAG;IAClC,2EAA2E;IAC3E,OAAO,EAAE,UAAU,GAAG,WAAW,CAAC;CACnC,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,qBAAqB,KAAK,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;AAExG,MAAM,MAAM,gBAAgB,GAAG;IAC7B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,UAAU,EAAE,cAAc,CAAC,CAAC,CAAC;CACvD,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,iEAAiE;IACjE,OAAO,CAAC,EAAE,UAAU,GAAG,WAAW,CAAC;CACpC,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,MAAM,EAAE,UAAU,CAAC;IACnB,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,EAAE,CAAC;CACvB,CAAC;AAEF,MAAM,WAAW,SAAS;IACxB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACvE,aAAa,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;CAC7F;AAED,qBAAa,4BAA6B,SAAQ,KAAK;IACrD,SAAgB,MAAM,EAAE,UAAU,CAAC;IAEnC,YAAY,MAAM,EAAE,UAAU,EAI7B;CACF"}
|
package/dist/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAkEA,MAAM,OAAO,4BAA6B,SAAQ,KAAK;IACrC,MAAM,CAAa;IAEnC,YAAY,MAAkB;QAC5B,KAAK,CAAC,WAAW,MAAM,mCAAmC,CAAC,CAAC;QAC5D,IAAI,CAAC,IAAI,GAAG,8BAA8B,CAAC;QAC3C,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;CACF"}
|