From ecaa7c3e1c07aceab645dffb901885043633add5 Mon Sep 17 00:00:00 2001 From: alikia2x Date: Sat, 27 Jul 2024 15:50:40 +0800 Subject: [PATCH] temp: debug --- bun.lockb | Bin 158500 -> 158500 bytes src/lib/lyrics/parser.ts | 125 ++++++++++++++++++++++----------- src/test/lrcParser.test.ts | 7 ++ src/test/resources/test-03.lrc | 77 ++++++++++++++++++++ 4 files changed, 169 insertions(+), 40 deletions(-) create mode 100644 src/test/resources/test-03.lrc diff --git a/bun.lockb b/bun.lockb index 570f2554d2852d9d48174ec86d591461388d9a03..383e35438a2601032d8d77bc2b3996534a1547dc 100755 GIT binary patch delta 25 hcmZ2-jdRI0&W0_F{p;8n;|%nS^-Q);TgTY92LOlG3K#$Y delta 25 dcmZ2-jdRI0&W0_F{p;A77{Flrv~`SqdjNX)2*>~c diff --git a/src/lib/lyrics/parser.ts b/src/lib/lyrics/parser.ts index 8803599..fed8188 100644 --- a/src/lib/lyrics/parser.ts +++ b/src/lib/lyrics/parser.ts @@ -4,24 +4,30 @@ import { buildLexer, expectEOF, fail, + kleft, kmid, + kright, opt_sc, + type Parser, rep, rep_sc, seq, str, tok, - type Parser, type Token } from 'typescript-parsec'; -export interface ScriptItem { + +interface ParserScriptItem { start: number; text: string; - end: number; - translation?: string; words?: ScriptWordsItem[]; - singer?: number; + translation?: string; + singer?: string; +} + +export interface ScriptItem extends ParserScriptItem{ + end: number; chorus?: string; } @@ -32,12 +38,24 @@ export interface ScriptWordsItem { endIndex: number; } -export interface LrcJsonData { +export interface LrcMetaData { ar?: string; ti?: string; al?: string; - scripts?: ScriptItem[]; + au?: string; + length?: string; + offset?: string; + tool?: string; + ve?: string; +} +export interface ParsedLrc extends LrcMetaData { + scripts?: ParserScriptItem[]; + [key: string]: any; +} + +export interface LrcJsonData extends LrcMetaData { + scripts?: ScriptItem[]; [key: string]: any; } @@ -46,10 +64,10 @@ interface IDTag { } function convertTimeToMs({ - mins, - secs, - decimals -}: { + mins, + secs, + decimals + }: { mins?: number | string; secs?: number | string; decimals?: string; @@ -84,7 +102,9 @@ const alpha = alt_sc( ); const alphaStr = apply(rep(alpha), (r) => r.join('')); -const spaces = rep_sc(str(' ')); +function spaces(): Parser[]> { + return rep_sc(str(' ')); +} const unicodeStr = rep(tok('char')); @@ -100,6 +120,10 @@ function trimmed(p: Parser[]>): Parser[]> { }); } +function padded(p: Parser): Parser { + return kmid(spaces(), p, spaces()); +} + function anythingTyped(types: string[]) { return types.map((t) => tok(t)).reduce((acc, cur) => alt_sc(cur, acc), fail('no alternatives')); } @@ -145,39 +169,60 @@ function tokenParserToText(p: Parser> | Parser[]>) }); } +const singerIndicator = kleft(tok('char'), str(':')); +const translateParser = kright(str('|'), unicodeStr); + function lrcLine( wordDiv = ' ', legacy = false -): Parser { +): Parser { return alt_sc( legacy ? apply(seq(squareTS, trimmed(rep_sc(anythingTyped(['char', '[', ']', '<', '>'])))), (r) => - ['script_item', { start: r[0], text: joinTokens(r[1]) } as any as ScriptItem] // TODO: Complete this - ) : apply(seq(squareTS, rep_sc(seq(opt_sc(angleTS), trimmed(rep_sc(anythingTyped(['char', '[', ']'])))))), (r) => { - const start = r[0]; + ['script_item', { start: r[0], text: joinTokens(r[1]) } as ParserScriptItem] // TODO: Complete this + ) : apply( + seq( + squareTS, + opt_sc(singerIndicator), + rep_sc( + seq( + opt_sc(angleTS), + trimmed(rep_sc(anythingTyped(['char', '[', ']']))) + ) + ), + opt_sc(trimmed(translateParser)) + ), (r) => { + const start = r[0]; + const singerPart = r[1]; + const mainPart = r[2]; + const translatePart = r[3]; - const text = r[1] - .map((s) => joinTokens(s[1])) - .filter((s) => s.trim().length > 0) - .join(wordDiv); + const text = mainPart + .map((s) => joinTokens(s[1])) + .filter((s) => s.trim().length > 0) + .join(wordDiv); - const words = r[1] - .filter((s) => joinTokens(s[1]).trim().length > 0) - .map((s) => { - const wordBegin = s[0]; - const word = s[1]; - let ret: Partial = { start: wordBegin }; - if (word[0]) { - ret.beginIndex = word[0].pos.columnBegin - 1; - } - if (word[word.length - 1]) { - ret.endIndex = word[word.length - 1].pos.columnEnd; - } - return ret as ScriptWordsItem; // TODO: Complete this - }); - return ['script_item', { start, text, words } as any as ScriptItem]; // TODO: Complete this - }), + const words = mainPart + .filter((s) => joinTokens(s[1]).trim().length > 0) + .map((s) => { + const wordBegin = s[0]; + const word = s[1]; + let ret: Partial = { start: wordBegin }; + if (word[0]) { + ret.beginIndex = word[0].pos.columnBegin - 1; + } + if (word[word.length - 1]) { + ret.endIndex = word[word.length - 1].pos.columnEnd; + } + return ret as ScriptWordsItem; // TODO: Complete this + }); + + const singer = singerPart?.text; + const translation = translatePart === undefined ? undefined : joinTokens(translatePart); + + return ['script_item', { start, text, words, singer, translation } as ParserScriptItem]; + }), apply(lrcTag, (r) => ['lrc_tag', r as IDTag]), - apply(seq(spaces, str('#'), unicodeStr), (cmt) => ['comment', cmt[2].join('')] as const), - apply(spaces, (_) => ['empty', null] as const) + apply(seq(spaces(), str('#'), unicodeStr), (cmt) => ['comment', cmt[2].join('')] as const), + apply(spaces(), (_) => ['empty', null] as const) ); } @@ -191,7 +236,7 @@ export function dumpToken(t: Token | undefined): string { export function parseLRC( input: string, { wordDiv, strict, legacy }: { wordDiv?: string; strict?: boolean; legacy?: boolean } = {} -): LrcJsonData { +): ParsedLrc { const tokenizer = buildLexer([ [true, /^\[/gu, '['], [true, /^\]/gu, ']'], @@ -231,5 +276,5 @@ export function parseLRC( default: return acc; } - }, {} as LrcJsonData); + }, {} as ParsedLrc); } diff --git a/src/test/lrcParser.test.ts b/src/test/lrcParser.test.ts index 01ae0af..27c1e3c 100644 --- a/src/test/lrcParser.test.ts +++ b/src/test/lrcParser.test.ts @@ -7,6 +7,8 @@ describe('LRC parser test', () => { const test01Text = test01Buffer.toString('utf-8'); const test02Buffer = fs.readFileSync('./src/test/resources/test-02.lrc'); const test02Text = test02Buffer.toString('utf-8'); + const test03Buffer = fs.readFileSync('./src/test/resources/test-03.lrc'); + const test03Text = test03Buffer.toString('utf-8'); it('Parses test-01.lrc', () => { const result = parseLRC(test01Text, { wordDiv: '', strict: true }); @@ -28,6 +30,11 @@ describe('LRC parser test', () => { expect(result.scripts!![0].words!![1].beginIndex).toBe("[00:00.00] <00:00.04> When <00:00.16> the".indexOf("the")); expect(result.scripts!![0].words!![1].start).toBe(160); }); + it('Parses test-03.lrc', () => { + const result = parseLRC(test03Text, { wordDiv: ' ', strict: true }); + console.log(result.scripts); + expect(result.scripts!![5].translation).toBe("བྲོ་ར་འདི་ལ་བྲོ་ཅིག་འཁྲབ།"); + }); it('Rejects some invalid LRCs', () => { const cases = [ "[<00:00.00>] <00:00.04> When <00:00.16> the", diff --git a/src/test/resources/test-03.lrc b/src/test/resources/test-03.lrc new file mode 100644 index 0000000..8edc547 --- /dev/null +++ b/src/test/resources/test-03.lrc @@ -0,0 +1,77 @@ +[ti: 雪山之眼] +[ar: 洛天依 & 旦增益西] +[al: 游四方] +[tool: 歌词滚动姬 https://lrc-maker.github.io] +[length: 04:17.400] +[00:34.280] 浸透了经卷 记忆的呼喊 +[00:37.800] 雪珠滚落山巅 栽下一个春天 +[00:47.390] 松石敲响玲珑清脆的银花 +[00:51.600] 穿过玛瑙的红霞 +[00:54.430] 在她眼中结编 亘久诗篇 +[01:05.440] བྲོ་ར་འདི་ལ་བྲོ་ཅིག་འཁྲབ། | 在舞池里舞一舞 +[01:08.780] 祝祷转过千年 五色经幡飘飞 +[01:12.040] 奏起悠扬巴叶 任岁月拨弦 +[01:19.130] གཞས་ར་འདི་ལ་གཞས་གཅིག་བཏང་། 我在歌坛献首歌 +[01:22.330] 宫殿 塔尖 彩绘 日月 同辉 +[01:25.810] 那层厚重壁垒化身 蝉翼一片 +[01:29.110] ང་ཚོ་འདི་ལ་འཛོམས་འཛོམས། 我们在此相聚 +[01:30.790] གཏན་དུ་འཛོམས་རྒྱུ་བྱུང་ན། 希望可以常聚 +[01:32.510] གཏན་དུ་འཛོམས་པའི་མི་ལ། 在此相聚的人们 +[01:34.120] སྙུན་གཞི་གོད་ཆགས་མ་གཏོང༌། 祝愿平安富足 +[01:35.920] ང་ཚོ་འདི་ལ་འཛོམས་འཛོམས། 我们在此相聚 +[01:37.630] གཏན་དུ་འཛོམས་རྒྱུ་བྱུང་ན། 希望可以常聚 +[01:39.350] གཏན་དུ་འཛོམས་པའི་མི་ལ། 在此相聚的人们 +[01:41.050] སྙུན་གཞི་གོད་ཆགས་མ་གཏོང༌། 祝愿平安富足 +[01:42.740] ང་ཚོ་འདི་ལ་འཛོམས་འཛོམས། 我们在此相聚 +[01:44.630] གཏན་དུ་འཛོམས་རྒྱུ་བྱུང་ན། 希望可以常聚 +[01:46.280] གཏན་དུ་འཛོམས་པའི་མི་ལ། 在此相聚的人们 +[01:48.010] སྙུན་གཞི་གོད་ཆགས་མ་གཏོང༌། 祝愿平安富足 +[01:49.600] ང་ཚོ་འདི་ལ་འཛོམས་འཛོམས། 我们在此相聚 +[01:51.380] གཏན་དུ་འཛོམས་རྒྱུ་བྱུང་ན། 希望可以常聚 +[01:53.070] གཏན་དུ་འཛོམས་པའི་མི་ལ། 在此相聚的人们 +[01:54.820] སྙུན་གཞི་གོད་ཆགས་མ་གཏོང༌། 祝愿平安富足 +[01:58.580] སྔོན་དང་པོ་གྲུབ་ཐོབ་ཐང་སྟོང་རྒྱལ་པོས་མཛད་པའི་མཛད་ཚུལ་དུ། དང་པོ་རྔོན་པའི་ས་སྦྱངས་ས་འདུལ། གཉིས་པ་རྒྱ་ལུའི་བྱིན་འབེབས། གསུམ་པ་ལྷ་མོའི་གླུ་གར་སོགས་རིན་ཆེན་གསུང་མགུར་གཞུང་བཟང་མང་པོ་འདུག་སྟེ། དེ་ཡང་མ་ཉུང་གི་ཚིག་ལ་དུམ་མཚམས་གཅིག་ཞུས་པ་བྱུང་བ་ཡིན་པ་ལགས་སོ། 如祖师唐东杰布所著,一有温巴净地,二有甲鲁祈福,三有仙女歌舞,所著繁多,在此简略献之。 +[02:24.240] 浸透了经卷 记忆的呼喊 +[02:27.450] 雪珠滚落山巅 栽下一个春天 +[02:37.090] 松石敲响玲珑清脆的银花 +[02:41.280] 穿过玛瑙的红霞 +[02:44.010] 在她眼中结编 亘久诗篇 +[02:55.250] བྲོ་ར་འདི་ལ་བྲོ་ཅིག་འཁྲབ། 在舞池里舞一舞 +[02:58.410] 祝祷转过千年 五色经幡飘飞 +[03:01.750] 奏起悠扬巴叶 任岁月拨弦 +[03:08.840] གཞས་ར་འདི་ལ་གཞས་གཅིག་བཏང་། 我在歌坛献首歌 +[03:12.050] 宫殿 塔尖 彩绘 日月 同辉 +[03:15.400] 那层厚重壁垒化身 蝉翼一片 +[03:18.850] ང་ཚོ་འདི་ལ་འཛོམས་འཛོམས། 我们在此相聚 +[03:20.480] གཏན་དུ་འཛོམས་རྒྱུ་བྱུང་ན། 希望可以常聚 +[03:22.210] གཏན་དུ་འཛོམས་པའི་མི་ལ། 在此相聚的人们 +[03:23.910] སྙུན་གཞི་གོད་ཆགས་མ་གཏོང༌། 祝愿平安富足 +[03:25.662] ང་ཚོ་འདི་ལ་འཛོམས་འཛོམས། 我们在此相聚 +[03:27.391] གཏན་དུ་འཛོམས་རྒྱུ་བྱུང་ན། 希望可以常聚 +[03:29.096] གཏན་དུ་འཛོམས་པའི་མི་ལ། 在此相聚的人们 +[03:30.789] སྙུན་གཞི་གོད་ཆགས་མ་གཏོང༌། 祝愿平安富足 +[03:32.496] ང་ཚོ་འདི་ལ་འཛོམས་འཛོམས། 我们在此相聚 +[03:34.175] གཏན་དུ་འཛོམས་རྒྱུ་བྱུང་ན། 希望可以常聚 +[03:35.876] གཏན་དུ་འཛོམས་པའི་མི་ལ། 在此相聚的人们 +[03:37.606] སྙུན་གཞི་གོད་ཆགས་མ་གཏོང༌། 祝愿平安富足 +[03:39.290] ང་ཚོ་འདི་ལ་འཛོམས་འཛོམས། 我们在此相聚 +[03:41.030] གཏན་དུ་འཛོམས་རྒྱུ་བྱུང་ན། 希望可以常聚 +[03:42.679] གཏན་དུ་འཛོམས་པའི་མི་ལ། 在此相聚的人们 +[03:44.455] སྙུན་གཞི་གོད་ཆགས་མ་གཏོང༌། 祝愿平安富足 +[03:46.176] ང་ཚོ་འདི་ལ་འཛོམས་འཛོམས། 我们在此相聚 +[03:47.910] གཏན་དུ་འཛོམས་རྒྱུ་བྱུང་ན། 希望可以常聚 +[03:49.625] གཏན་དུ་འཛོམས་པའི་མི་ལ། 在此相聚的人们 +[03:51.293] སྙུན་གཞི་གོད་ཆགས་མ་གཏོང༌། 祝愿平安富足 +[03:53.005] ང་ཚོ་འདི་ལ་འཛོམས་འཛོམས། 我们在此相聚 +[03:54.742] གཏན་དུ་འཛོམས་རྒྱུ་བྱུང་ན། 希望可以常聚 +[03:56.479] གཏན་དུ་འཛོམས་པའི་མི་ལ། 在此相聚的人们 +[03:58.159] སྙུན་གཞི་གོད་ཆགས་མ་གཏོང༌། 祝愿平安富足 +[03:59.859] ང་ཚོ་འདི་ལ་འཛོམས་འཛོམས། 我们在此相聚 +[04:01.548] གཏན་དུ་འཛོམས་རྒྱུ་བྱུང་ན། 希望可以常聚 +[04:03.312] གཏན་དུ་འཛོམས་པའི་མི་ལ། 在此相聚的人们 +[04:05.026] སྙུན་གཞི་གོད་ཆགས་མ་གཏོང༌། 祝愿平安富足 +[04:06.721] ང་ཚོ་འདི་ལ་འཛོམས་འཛོམས། 我们在此相聚 +[04:08.479] གཏན་དུ་འཛོམས་རྒྱུ་བྱུང་ན། 希望可以常聚 +[04:10.175] གཏན་དུ་འཛོམས་པའི་མི་ལ། 在此相聚的人们 +[04:11.923] སྙུན་གཞི་གོད་ཆགས་མ་གཏོང༌། 祝愿平安富足 +[04:17.400] \ No newline at end of file