openlyrics-parser
Version:
Parses and extracts data from OpenLyrics files, and creates them!
231 lines (230 loc) • 8.17 kB
JavaScript
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, '<').replace(/>/g, '>');
}
isVerseChord(x) {
return 'value' in x;
}
}