The item badge still showed Planning Center's raw "Bb" and "F#m" while the Song Key tile beside it showed B♭ and F♯m. One module should not spell the same thing two ways. The notation moves into key-notation.js and both tiles import it, rather than each keeping its own copy of the parse: the day one of them changes, they all should. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
26 lines
1004 B
JavaScript
26 lines
1004 B
JavaScript
/* PCO Plan — how a song key is written.
|
|
|
|
Planning Center stores keys as typed: "Bb", "F#m", "Ab". Every tile in this
|
|
module shows them as notes instead — B♭, F♯m, A♭ — so the plan, the badge
|
|
on an item and the Song Key tile all agree. Shared rather than repeated
|
|
because the day one of them changes, they all should. */
|
|
|
|
/** "F#m" → { note: 'F', accidental: '♯', quality: 'm' }; anything odd → null. */
|
|
export function parseKey(raw) {
|
|
const match = /^([A-G])\s*([#b♯♭]?)\s*(.*)$/.exec(String(raw || '').trim());
|
|
if (!match) return null;
|
|
const [, note, accidental, quality] = match;
|
|
return {
|
|
note,
|
|
accidental: accidental === '#' ? '♯' : accidental === 'b' ? '♭' : accidental,
|
|
quality: quality.trim(),
|
|
};
|
|
}
|
|
|
|
/** The same thing as one string, for a badge or a caption. */
|
|
export function prettyKey(raw) {
|
|
const parts = parseKey(raw);
|
|
if (!parts) return String(raw || '').trim();
|
|
return `${parts.note}${parts.accidental}${parts.quality}`;
|
|
}
|