temp: debug

This commit is contained in:
alikia2x 2024-07-27 15:50:40 +08:00
parent 9074f800d6
commit ecaa7c3e1c
4 changed files with 169 additions and 40 deletions

BIN
bun.lockb

Binary file not shown.

View File

@ -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<K>(): Parser<K, Token<K>[]> {
return rep_sc(str(' '));
}
const unicodeStr = rep(tok('char'));
@ -100,6 +120,10 @@ function trimmed<K, T>(p: Parser<K, Token<T>[]>): Parser<K, Token<T>[]> {
});
}
function padded<K, T>(p: Parser<K, T>): Parser<K, T> {
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<K, T>(p: Parser<K, Token<T>> | Parser<K, Token<T>[]>)
});
}
const singerIndicator = kleft(tok('char'), str(':'));
const translateParser = kright(str('|'), unicodeStr);
function lrcLine(
wordDiv = ' ', legacy = false
): Parser<unknown, ['script_item', ScriptItem] | ['lrc_tag', IDTag] | ['comment', string] | ['empty', null]> {
): Parser<unknown, ['script_item', ParserScriptItem] | ['lrc_tag', IDTag] | ['comment', string] | ['empty', null]> {
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<ScriptWordsItem> = { 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<ScriptWordsItem> = { 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>(t: Token<T> | 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);
}

View File

@ -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",

View File

@ -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]