Keys read as notes on the Plan tile's badge too

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>
This commit is contained in:
Waters Church
2026-09-29 14:57:43 -04:00
co-authored by Claude Opus 5
parent 4e5b60e82b
commit 06066529bc
4 changed files with 49 additions and 23 deletions
+13 -18
View File
@@ -4,6 +4,8 @@
streamed state the Plan tile does, so it needs no connection of its own;
which item is current comes from the ProPresenter module, as ever. */
import { parseKey, prettyKey } from "./key-notation.js";
export default function createKey({ root, moduleApi }) {
let state = null;
let stream = null;
@@ -69,13 +71,7 @@ export default function createKey({ root, moduleApi }) {
}
if (!state.live.ppReachable) return moduleApi.setStatus('error', 'ProPresenter unreachable — showing the last item');
if (!item) return moduleApi.setStatus('ok', 'Waiting for an item to go live');
moduleApi.setStatus('ok', `${titleOf(item)}${item.keyName ? ` — ${item.keyName}` : ' — no key in the plan'}`);
}
/** "Bb" → "B♭", "F#m" → "F♯m" — for the plain-text line under the key. */
function prettyKey(text) {
const match = /^([A-G])([#b])(.*)$/.exec(String(text || '').trim());
return match ? `${match[1]}${match[2] === '#' ? '♯' : '♭'}${match[3]}` : String(text || '');
moduleApi.setStatus('ok', `${titleOf(item)}${item.keyName ? ` — ${prettyKey(item.keyName)}` : ' — no key in the plan'}`);
}
/**
@@ -84,23 +80,22 @@ export default function createKey({ root, moduleApi }) {
*/
function drawKey(text) {
keyEl.innerHTML = '';
const match = /^([A-G])([#b♯♭]?)(.*)$/.exec(String(text).trim());
if (!match) {
const parts = parseKey(text);
if (!parts) {
keyEl.textContent = text;
return;
}
const [, note, accidental, rest] = match;
keyEl.appendChild(document.createTextNode(note));
if (accidental) {
const sup = document.createElement('span');
sup.className = 'pk-accidental';
sup.textContent = accidental === '#' ? '♯' : accidental === 'b' ? '♭' : accidental;
keyEl.appendChild(sup);
keyEl.appendChild(document.createTextNode(parts.note));
if (parts.accidental) {
const acc = document.createElement('span');
acc.className = 'pk-accidental';
acc.textContent = parts.accidental;
keyEl.appendChild(acc);
}
if (rest) {
if (parts.quality) {
const tail = document.createElement('span');
tail.className = 'pk-quality';
tail.textContent = rest;
tail.textContent = parts.quality;
keyEl.appendChild(tail);
}
}