UNPKG

openlyrics-parser

Version:

Parses and extracts data from OpenLyrics files, and creates them!

231 lines (230 loc) 8.17 kB
import { version } from './version'; export class Builder { overwriteMeta(obj, userMeta) { const defaultMeta = { createdIn: `openlyrics-parser ${version}`, modifiedIn: `openlyrics-parser ${version}`, lang: 'en', }; const mergedMeta = { ...defaultMeta, ...userMeta }; obj.song['@xml:lang'] = mergedMeta.lang; obj.song['@createdIn'] = mergedMeta.createdIn; obj.song['@modifiedIn'] = mergedMeta.modifiedIn; obj.song['@modifiedDate'] = new Date().toISOString().replace(/\.\d{3}Z$/, ''); if (mergedMeta.chordNotation != null) { obj.song['@chordNotation'] = mergedMeta.chordNotation; } } overwriteProperties(obj, userProps) { this.overwriteSpecialPropTitles(obj, userProps.titles); this.overwriteSpecialPropAuthors(obj, userProps.authors); this.overwriteSpecialPropComments(obj, userProps.comments); this.overwriteSpecialPropSongBooks(obj, userProps.songBooks); this.overwriteSpecialPropThemes(obj, userProps.themes); this.overwriteSpecialPropTempo(obj, userProps.tempo); const skipProps = ['authors', 'titles', 'tempo']; Object.keys(userProps).forEach((key) => { if (!skipProps.includes(key)) { const val = userProps[key]; if (typeof val === 'string' || typeof val === 'number') { obj.song.properties[key] = val.toString(); } } }); } overwriteFormats(obj, userFormat) { if (userFormat) { obj.song.format.tags = userFormat.map((f) => { return { '@application': f.application, tag: f.tags.map((t) => { return { '@name': t.name, open: this.encodeHtmlCarats(t.open), close: this.encodeHtmlCarats(t.close), }; }), }; }); } else { obj.song.format = undefined; } } overwriteVerses(obj, userVerses) { const versesXml = []; for (const verse of userVerses) { versesXml.push({ '@name': verse.name, '@break': verse.optionalBreak === true ? 'optional' : undefined, '@lang': verse.lang, '@transliteration': verse.transliteration, lines: this.getVerseLines(verse.lines), }); } obj.song.lyrics.verse = versesXml; } overwriteInstruments(obj, userInstruments) { if (userInstruments) { const instrumentsXml = []; for (const inst of userInstruments) { instrumentsXml.push({ '@name': inst.name, lines: this.getInstrumentLines(inst.lines), }); } obj.song.lyrics.instrument = instrumentsXml; } } overwriteSpecialPropTitles(obj, userTitles) { if (typeof userTitles === 'string') { obj.song.properties.titles.title = [{ '#text': userTitles }]; } else { obj.song.properties.titles.title = userTitles.map((t) => { return { '#text': t.value, '@lang': t.lang, '@translit': t.transliteration, '@original': t.original === true ? 'true' : undefined, }; }); } } overwriteSpecialPropAuthors(obj, userAuthors) { if (typeof userAuthors === 'string') { obj.song.properties.authors = { author: [{ '#text': userAuthors }] }; } else if (Array.isArray(userAuthors)) { obj.song.properties.authors = { author: userAuthors.map((t) => { return { '#text': t.value, '@lang': t.lang, '@type': t.type, }; }), }; } } overwriteSpecialPropComments(obj, userComments) { if (userComments) { obj.song.properties.comments = { comment: userComments, }; } } overwriteSpecialPropSongBooks(obj, userSongBooks) { if (userSongBooks) { obj.song.properties.songbooks = { songbook: userSongBooks.map((t) => { return { '@name': t.name, '@entry': t.entry, }; }), }; } } overwriteSpecialPropThemes(obj, userThemes) { if (userThemes) { obj.song.properties.themes = { theme: userThemes.map((t) => { return { '#text': t.value, '@lang': t.lang, }; }), }; } } overwriteSpecialPropTempo(obj, userTempo) { if (userTempo != null) { const tempoType = typeof userTempo === 'number' ? 'bpm' : 'text'; obj.song.properties.tempo = { '#text': userTempo, '@type': tempoType, }; } } getVerseLines(lines) { let verseLines = []; if (this.isStringArray(lines)) { verseLines = lines.map((l) => { return { '#text': this.convertToHtmlBreaks(l), }; }); } else { verseLines = lines.map((l) => { const lineContentArr = l.content.map((content) => { if (content.type === 'chord') { return this.getChord(content); } else if (content.type === 'tag') { return `<tag name="${content.name}">${content.value}</tag>`; } else if (content.type === 'comment') { return `<comment>${content.value}</comment>`; } return this.convertToHtmlBreaks(content.value); }); return { '#text': lineContentArr.join(''), '@part': l.part, '@break': l.optionalBreak === true ? 'optional' : undefined, '@repeat': l.repeat, }; }); } return verseLines; } getInstrumentLines(lines) { const linesXml = lines.map((l) => { const lineContentArr = l.content.map((content) => { if (content.type === 'chord') { return this.getChord(content); } return this.getBeat(content); }); return { '#text': lineContentArr.join(''), '@part': l.part, '@repeat': l.repeat, }; }); return linesXml; } getChord(chordObj) { let attrs = ''; if (chordObj.root != null) attrs += ` root="${chordObj.root}"`; if (chordObj.structure != null) attrs += ` structure="${chordObj.structure}"`; if (chordObj.upbeat === true) attrs += ` upbeat="true"`; if (chordObj.bass != null) attrs += ` bass="${chordObj.bass}"`; if (this.isVerseChord(chordObj)) { return `<chord${attrs}>${chordObj.value}</chord>`; } return `<chord${attrs}/>`; } getBeat(beatObj) { const chordsArr = beatObj.chords.map((c) => this.getChord(c)); return ` <beat>${chordsArr.join('')}</beat>\n`; } isStringArray(x) { return x.every((i) => typeof i === 'string'); } convertToHtmlBreaks(x) { return x.replace(/[\n\r]/g, '<br/>'); } encodeHtmlCarats(x) { return x.replace(/</g, '&lt;').replace(/>/g, '&gt;'); } isVerseChord(x) { return 'value' in x; } }