UNPKG

paroles

Version:

A library for parsing, making, modifying and playing LRC format lyrics

4 lines (3 loc) 6.34 kB
"use strict";var C=Object.defineProperty;var I=(r,e,t)=>e in r?C(r,e,{enumerable:!0,configurable:!0,writable:!0,value:t}):r[e]=t;var h=(r,e,t)=>(I(r,typeof e!="symbol"?e+"":e,t),t);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const g=` `,S=`\r `;function A(r){const e=Array.from(r.matchAll(/\n/g)).length;return e===0?g:Array.from(r.matchAll(/\r\n/g)).length===e?S:g}const y=(r,e)=>{const[t,i]=r.toString().split(".");return t.length<e?new Array(e-t.length).fill("0").join("")+t+(i?"."+i:""):t+(i?"."+i:"")},$=/^\[[^:]+:[^\]]*\]/,x=/\[(\d+):(\d+)(?:.(\d+))?\]/g,p=/\[([a-z]+):([^\]]*)\]/,E={resolveConflict:"merge"},j={eol:g,resolveConflict:"merge"};class a{constructor(e,t){h(this,"_offset");h(this,"_option");h(this,"eol");h(this,"info");h(this,"lines");if(this._option={...E,...t||{}},typeof e=="string"){this.eol=A(e);const i=a.parse(e,{eol:this.eol,resolveConflict:this._option.resolveConflict});this.info=i.info,this.lines=i.lines,this._offset=i.info.offset||0}else if(typeof e>"u")this.eol=g,this.info={},this.lines=[],this._offset=0;else{const i=e.clone();this.eol=i.eol,this.info=i.info,this.lines=i.lines,this._offset=i.info.offset||0,this._option=i._option}}clone(){return new a(this.toString())}toString(){return a.stringify(this)}at(e){return this.lines.at(e)}getIndexByTime(e){const t=this.lines.findIndex(i=>i.time-this._offset>e);return t<=0?t:t-1}atTime(e){const t=this.getIndexByTime(e);return this.lines.at(t)}setOffset(e){this._offset=e}merge(e,t){const i=new a(e);t!=null&&t.resolveInfo?this.info=t.resolveInfo(this.info,i.info):t!=null&&t.override?this.info={...this.info,...i.info}:this.info={...i.info,...this.info};for(const s of i.lines){let n=this.getIndexByTime(s.time);if(n=n===-1?this.lines.length-1:n,this.lines[n].time===s.time)if(t!=null&&t.resolveConflict)this.lines[n]={time:s.time,text:t.resolveConflict(this.lines[n].text,s.text)};else if(t!=null&&t.override)this.lines[n]={time:s.time,text:s.text};else continue;else n===this.lines.length-1?this.lines.push(s):n===0&&s.time<this.lines[n].time?this.lines.unshift(s):this.lines.splice(n+1,0,s)}return this}insert(e){const t=Array.isArray(e)?e:[e];for(const i of t){let s=this.getIndexByTime(i.time);s=s===-1?this.lines.length-1:s,this.lines[s].time===i.time?this.lines[s]=i:s===this.lines.length-1?this.lines.push(i):s===0&&i.time<this.lines[s].time?this.lines.unshift(i):this.lines.splice(s+1,0,i)}return this}remove(e){if(typeof e=="string")this.lines=this.lines.filter(t=>t.text!==e);else if(e instanceof RegExp)this.lines=this.lines.filter(t=>!e.test(t.text));else{let t=this.getIndexByTime(e.time);t=t===-1?this.lines.length-1:t,this.lines[t].time===e.time&&this.lines[t].text===e.text?this.lines.splice(t,1):console.error("lyrics line not existed")}return this}replace(e,t){if((typeof e=="string"||e instanceof RegExp)&&typeof t=="string"){const i=this.lines.filter(s=>typeof e=="string"?s.text===e:e.test(s.text));i.length&&i.forEach(s=>{typeof e=="string"?s.text=t:s.text=s.text.replace(e,t)})}else if(d(e)&&d(t)){const i=[];this.lines.forEach((s,n)=>{s.text===e.text&&s.time===e.time&&i.push(n)}),i.forEach(s=>{this.lines[s]=t})}return this}setInfo(e){return this.info={...this.info,...e},this}static stringify(e){const t=[];for(const[n,f]of Object.entries(e.info)){const c=z(n);t.push(`[${c}:${f}]`)}const i={};for(const n of e.lines)i[n.text]?i[n.text].push(n.time):i[n.text]=[n.time];const s=Object.entries(i).map(([n,f])=>({text:n,time:f})).sort((n,f)=>n.time[0]-f.time[0]).map(n=>`${n.time.map(c=>`[${B(c)}]`).join("")}${n.text}`);return t.push(...s),t.join(e.eol)}static parse(e,t){const i={...j,...t||{}},s=e.split(i.eol).map(c=>c.trim()).filter(c=>$.test(c)),n={},f=[];for(const c of s)if(x.test(c)){const o=c.replace(x,"").trim();Array.from(c.matchAll(x)).forEach(u=>{const m=+u[1],b=+u[2],v=(u[3]?+`0.${u[3]}`:0).toFixed(2),T=(m*60+b).toString(),_=v.slice(1);f.push({time:Number(T+_),text:o})})}else if(p.test(c)){const o=c.match(p)||["",""],l=O(o[1].trim()),u=o[2].trim();if(l)if(l!=="offset")n[l]=u||"";else{const m=+u;n[l]=isNaN(m)?0:+(m/1e3).toFixed(2)}}return f.sort(function(c,o){return c.time-o.time}),f.forEach((c,o,l)=>{!l[o+1]||c.time!==l[o+1].time||(i.resolveConflict==="merge"?l[o].text=`${l[o].text}${i.eol}${l[o+1].text}`:i.resolveConflict==="overwrite"?l[o].text=l[o+1].text:typeof i.resolveConflict=="function"&&(l[o].text=i.resolveConflict(l[o].text,l[o+1].text)),l.splice(o+1,1))}),{info:n,lines:f}}}function O(r){switch(r){case"al":return"album";case"ar":return"artist";case"au":return"author";case"ti":return"title";case"by":return"creator";case"offset":return"offset";case"length":return"length";case"re":return"editor";case"ve":return"version";default:return}}function z(r){switch(r){case"album":return"al";case"artist":return"ar";case"author":return"au";case"title":return"ti";case"creator":return"by";case"offset":return"offset";case"length":return"length";case"editor":return"re";case"version":return"ve";default:return""}}function B(r){const e=y(Math.floor(r/60),2),t=y((r%60).toFixed(2),2);return`${e}:${t}`}function d(r){return!!r&&typeof r=="object"&&"text"in r&&"time"in r}class R{constructor(e){h(this,"lyrics");h(this,"currentTime");h(this,"_currentLine");h(this,"_subscriptions");this.lyrics=e,this.currentTime=0,this._subscriptions={linechange:[],lyricschange:[]}}updateTime(e){this.currentTime=e,this._currentLine!==this.getCurrentLine()&&(this._currentLine=this.getCurrentLine(),this._subscriptions.linechange.forEach(t=>{const i=this.getCurrentIndex(),s=this.lyrics.lines.at(i);t((s==null?void 0:s.text)||"",i===-1?this.lyrics.lines.length-1:i)}))}getCurrentLine(){var e;return((e=this.lyrics.atTime(this.currentTime))==null?void 0:e.text)||""}getCurrentIndex(){return this.lyrics.getIndexByTime(this.currentTime)}on(...[e,t]){e==="linechange"?this._subscriptions.linechange.push(t):e==="lyricschange"&&this._subscriptions.lyricschange.push(t)}off(e,t){if(!e){this._subscriptions={linechange:[],lyricschange:[]};return}const i=this._subscriptions[e].findIndex(s=>s===t);i>-1?this._subscriptions.linechange.splice(i,1):t?console.error("LyricsPlayer.off(): handler not correct."):this._subscriptions.linechange=[]}rewind(e){this.currentTime=0,this._currentLine=void 0,e&&(this.lyrics=e,this._subscriptions.lyricschange.forEach(t=>t()))}}exports.Lyrics=a;exports.LyricsPlayer=R;