UNPKG

chordsong

Version:

ChordSong is a simple text format for the notation of lyrics with guitar chords, and an application that renders them to portable HTML pages.

174 lines 6.25 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Diagram = exports.fretStringsRegEx = exports.stringsFretsRegEx = void 0; exports.stringsFretsRegEx = /^([oOxX\d]{6}|(?:(?:[xXoO]|\d{1,2}),){5}(?:[xXoO]|\d{1,2}))$/; exports.fretStringsRegEx = /^(([12]?\d):([1-6](-[1-6])?)(,[1-6](-[1-6])?){0,5})(\/([12]?\d):([1-6](-[1-6])?)(,[1-6](-[1-6])?){0,5}){1,3}$/; class Diagram { constructor(parsedDiagram, chordName, chordVariant, chordRenderName) { this._stringFrets = []; this.fretStrings = {}; this._fingersAndBarres = []; this.chordName = chordName; this.chordVariant = chordVariant; this.chordRenderName = chordRenderName ?? chordName; try { this.fromStringFrets(parsedDiagram); } catch (error) { this.fromFingersAndBarres(parsedDiagram); } } get stringFrets() { return this._stringFrets; } set stringFrets(arr) { this._stringFrets = arr; this._computeFretStrings(); this._computeFingersAndBarrels(); } get fingersAndBarrels() { return this._fingersAndBarres; } set fingersAndBarrels(arr) { this._fingersAndBarres = arr; this._computeStringFrets(); this._computeFretStrings(); } get minFret() { return Math.min(...this.stringFrets.filter(fret => fret > 0)); } get maxFret() { return Math.max(...this.stringFrets); } fromStringFrets(parsedDiagram) { if (!exports.stringsFretsRegEx.test(parsedDiagram)) { throw new Error(`invalid stringFrets format for ${parsedDiagram}`); } parsedDiagram = parsedDiagram .replace(/\|/g, '') .replace(/[Oo]/g, '0') .replace(/[Xx]/g, 'x'); this.stringFrets = (parsedDiagram.match(/[x0-9]{6}/) != null ? parsedDiagram.split('') : parsedDiagram.split(',')).map((str) => str === 'x' ? -1 : Number(str)); } fromFingersAndBarres(parsedDiagram) { if (!exports.fretStringsRegEx.test(parsedDiagram)) { throw new Error(`invalid format for ${parsedDiagram}`); } const fingersAndBarres = []; parsedDiagram.split('/').forEach(item => { const parsed = []; let fret; item.split(':').forEach((value, index) => { if (index === 0) { fret = Number(value); } else if (index === 1) { value.split(',').forEach(range => { let a = Number(range[0]); a = 6 - a; let b = Number(range[range.length - 1]); b = 6 - b; parsed.push({ fret, stringFrom: (a < b) ? a : b, stringTo: (a >= b) ? a : b }); }); } else { throw new Error(`Invalid diagram ${parsedDiagram}`); } }); parsed.forEach(item => { fingersAndBarres.push(item); }); }); this.fingersAndBarrels = fingersAndBarres; } _computeBarrel() { const fingeredFrets = this.stringFrets.filter((item) => item > 0); if (fingeredFrets.length < 5 || (fingeredFrets.length === 5 && this.stringFrets[0] > 0)) { return null; } const barrels = {}; for (const [fretPos, strings] of Object.entries(this.fretStrings)) { if (Number(fretPos) <= 0) continue; const from = Math.min(...strings); let to = from; for (let i = from + 1; i < 6; i++) { if (!strings.includes(i) && this.stringFrets[i] >= 0 && this.stringFrets[i] < Number(fretPos)) { break; } else { to++; } } barrels[fretPos] = { from, to }; } let fret = 0; let stringFrom = 0; let stringTo = 0; for (const [fretPos, fromTo] of Object.entries(barrels)) { if (fromTo.to - fromTo.from + 1 > stringTo - stringFrom) { fret = Number(fretPos); stringFrom = fromTo.from; stringTo = fromTo.to; } } return { fret, stringFrom, stringTo }; } _computeStringFrets() { this._stringFrets = [-1, -1, -1, -1, -1, -1]; this._fingersAndBarres.forEach(item => { const fret = item.fret; const strings = range(item.stringTo, item.stringFrom); strings.forEach(item => { if (fret > this._stringFrets[item]) { this._stringFrets[item] = fret; } }); }); } _computeFretStrings() { this._stringFrets.forEach((fret, string) => { if (String(fret) in this.fretStrings) { this.fretStrings[String(fret)].push(string); } else { this.fretStrings[String(fret)] = [string]; } }); } _computeFingersAndBarrels() { const barrel = this._computeBarrel(); if (barrel != null) { this._fingersAndBarres.push(barrel); } for (const [fretPos, strings] of Object.entries(this.fretStrings)) { if (Number(fretPos) <= 0) continue; if (barrel === null || Number(fretPos) !== barrel.fret) { strings.forEach((fretStr) => this._fingersAndBarres.push({ fret: Number(fretPos), stringFrom: fretStr, stringTo: fretStr })); } } } toString() { return this.stringFrets.join(',').replace(/-1/g, 'x').replace(/0/g, 'o'); } } exports.Diagram = Diagram; function range(max, min = 0, step = 1) { const arr = []; for (let i = min; i <= max; i += step) { arr.push(i); } return arr; } //# sourceMappingURL=Diagram.js.map