temp: debug
This commit is contained in:
parent
9074f800d6
commit
ecaa7c3e1c
@ -4,24 +4,30 @@ import {
|
|||||||
buildLexer,
|
buildLexer,
|
||||||
expectEOF,
|
expectEOF,
|
||||||
fail,
|
fail,
|
||||||
|
kleft,
|
||||||
kmid,
|
kmid,
|
||||||
|
kright,
|
||||||
opt_sc,
|
opt_sc,
|
||||||
|
type Parser,
|
||||||
rep,
|
rep,
|
||||||
rep_sc,
|
rep_sc,
|
||||||
seq,
|
seq,
|
||||||
str,
|
str,
|
||||||
tok,
|
tok,
|
||||||
type Parser,
|
|
||||||
type Token
|
type Token
|
||||||
} from 'typescript-parsec';
|
} from 'typescript-parsec';
|
||||||
|
|
||||||
export interface ScriptItem {
|
|
||||||
|
interface ParserScriptItem {
|
||||||
start: number;
|
start: number;
|
||||||
text: string;
|
text: string;
|
||||||
end: number;
|
|
||||||
translation?: string;
|
|
||||||
words?: ScriptWordsItem[];
|
words?: ScriptWordsItem[];
|
||||||
singer?: number;
|
translation?: string;
|
||||||
|
singer?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ScriptItem extends ParserScriptItem{
|
||||||
|
end: number;
|
||||||
chorus?: string;
|
chorus?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,12 +38,24 @@ export interface ScriptWordsItem {
|
|||||||
endIndex: number;
|
endIndex: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface LrcJsonData {
|
export interface LrcMetaData {
|
||||||
ar?: string;
|
ar?: string;
|
||||||
ti?: string;
|
ti?: string;
|
||||||
al?: 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;
|
[key: string]: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,7 +67,7 @@ function convertTimeToMs({
|
|||||||
mins,
|
mins,
|
||||||
secs,
|
secs,
|
||||||
decimals
|
decimals
|
||||||
}: {
|
}: {
|
||||||
mins?: number | string;
|
mins?: number | string;
|
||||||
secs?: number | string;
|
secs?: number | string;
|
||||||
decimals?: string;
|
decimals?: string;
|
||||||
@ -84,7 +102,9 @@ const alpha = alt_sc(
|
|||||||
);
|
);
|
||||||
|
|
||||||
const alphaStr = apply(rep(alpha), (r) => r.join(''));
|
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'));
|
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[]) {
|
function anythingTyped(types: string[]) {
|
||||||
return types.map((t) => tok(t)).reduce((acc, cur) => alt_sc(cur, acc), fail('no alternatives'));
|
return types.map((t) => tok(t)).reduce((acc, cur) => alt_sc(cur, acc), fail('no alternatives'));
|
||||||
}
|
}
|
||||||
@ -145,21 +169,38 @@ 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(
|
function lrcLine(
|
||||||
wordDiv = ' ', legacy = false
|
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(
|
return alt_sc(
|
||||||
legacy ? apply(seq(squareTS, trimmed(rep_sc(anythingTyped(['char', '[', ']', '<', '>'])))), (r) =>
|
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
|
['script_item', { start: r[0], text: joinTokens(r[1]) } as ParserScriptItem] // TODO: Complete this
|
||||||
) : apply(seq(squareTS, rep_sc(seq(opt_sc(angleTS), trimmed(rep_sc(anythingTyped(['char', '[', ']'])))))), (r) => {
|
) : 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 start = r[0];
|
||||||
|
const singerPart = r[1];
|
||||||
|
const mainPart = r[2];
|
||||||
|
const translatePart = r[3];
|
||||||
|
|
||||||
const text = r[1]
|
const text = mainPart
|
||||||
.map((s) => joinTokens(s[1]))
|
.map((s) => joinTokens(s[1]))
|
||||||
.filter((s) => s.trim().length > 0)
|
.filter((s) => s.trim().length > 0)
|
||||||
.join(wordDiv);
|
.join(wordDiv);
|
||||||
|
|
||||||
const words = r[1]
|
const words = mainPart
|
||||||
.filter((s) => joinTokens(s[1]).trim().length > 0)
|
.filter((s) => joinTokens(s[1]).trim().length > 0)
|
||||||
.map((s) => {
|
.map((s) => {
|
||||||
const wordBegin = s[0];
|
const wordBegin = s[0];
|
||||||
@ -173,11 +214,15 @@ function lrcLine(
|
|||||||
}
|
}
|
||||||
return ret as ScriptWordsItem; // TODO: Complete this
|
return ret as ScriptWordsItem; // TODO: Complete this
|
||||||
});
|
});
|
||||||
return ['script_item', { start, text, words } as any as ScriptItem]; // 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(lrcTag, (r) => ['lrc_tag', r as IDTag]),
|
||||||
apply(seq(spaces, str('#'), unicodeStr), (cmt) => ['comment', cmt[2].join('')] as const),
|
apply(seq(spaces(), str('#'), unicodeStr), (cmt) => ['comment', cmt[2].join('')] as const),
|
||||||
apply(spaces, (_) => ['empty', null] as const)
|
apply(spaces(), (_) => ['empty', null] as const)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,7 +236,7 @@ export function dumpToken<T>(t: Token<T> | undefined): string {
|
|||||||
export function parseLRC(
|
export function parseLRC(
|
||||||
input: string,
|
input: string,
|
||||||
{ wordDiv, strict, legacy }: { wordDiv?: string; strict?: boolean; legacy?: boolean } = {}
|
{ wordDiv, strict, legacy }: { wordDiv?: string; strict?: boolean; legacy?: boolean } = {}
|
||||||
): LrcJsonData {
|
): ParsedLrc {
|
||||||
const tokenizer = buildLexer([
|
const tokenizer = buildLexer([
|
||||||
[true, /^\[/gu, '['],
|
[true, /^\[/gu, '['],
|
||||||
[true, /^\]/gu, ']'],
|
[true, /^\]/gu, ']'],
|
||||||
@ -231,5 +276,5 @@ export function parseLRC(
|
|||||||
default:
|
default:
|
||||||
return acc;
|
return acc;
|
||||||
}
|
}
|
||||||
}, {} as LrcJsonData);
|
}, {} as ParsedLrc);
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,8 @@ describe('LRC parser test', () => {
|
|||||||
const test01Text = test01Buffer.toString('utf-8');
|
const test01Text = test01Buffer.toString('utf-8');
|
||||||
const test02Buffer = fs.readFileSync('./src/test/resources/test-02.lrc');
|
const test02Buffer = fs.readFileSync('./src/test/resources/test-02.lrc');
|
||||||
const test02Text = test02Buffer.toString('utf-8');
|
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', () => {
|
it('Parses test-01.lrc', () => {
|
||||||
const result = parseLRC(test01Text, { wordDiv: '', strict: true });
|
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].beginIndex).toBe("[00:00.00] <00:00.04> When <00:00.16> the".indexOf("the"));
|
||||||
expect(result.scripts!![0].words!![1].start).toBe(160);
|
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', () => {
|
it('Rejects some invalid LRCs', () => {
|
||||||
const cases = [
|
const cases = [
|
||||||
"[<00:00.00>] <00:00.04> When <00:00.16> the",
|
"[<00:00.00>] <00:00.04> When <00:00.16> the",
|
||||||
|
77
src/test/resources/test-03.lrc
Normal file
77
src/test/resources/test-03.lrc
Normal 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]
|
Loading…
Reference in New Issue
Block a user