From 6274d68d3da81a544ab9fc5de374dd39b4c0f34b Mon Sep 17 00:00:00 2001 From: Chris <26607885+chrisglein@users.noreply.github.com> Date: Sat, 11 Jul 2026 22:56:52 -0700 Subject: [PATCH 1/3] Add lean songbook UI, move ABC editing behind Advanced (#46) Redesign the home page for a songbook+ audience: a tight top toolbar now leads with a song picker (labeled with the current title), compact icon toggles for lyrics/trumpet/tab, and a transpose control that's a key dropdown showing the current key with each destination key's semitone offset. The ABC textarea, "No errors" indicator, ABC-notation link, GitHub "add a song" link, PDF/QR block, and commit-hash link move into a hidden #advanced panel, revealed by a gear toggle or ?advanced=true. Also fix a latent bug where trumpet fingering never displayed (filter checked #show-trumpt instead of #show-trumpet). --- src/index.pug | 211 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 145 insertions(+), 66 deletions(-) diff --git a/src/index.pug b/src/index.pug index b1a9f16..696656b 100644 --- a/src/index.pug +++ b/src/index.pug @@ -15,66 +15,101 @@ append head } body { padding: 1em } #paper { width: 100% } - .item { - margin-left: 1em; + .item { white-space: nowrap } + + /* lean toolbar */ + #toolbar { gap: .45rem; margin-top: .6rem } + #toolbar .btn .bi { vertical-align: -.15em } + #toolbar .btn .bi + span, + #toolbar .btn .bi + * { margin-left: .35em } + #toolbar .btn-group-toggle .btn .bi { margin-right: .35em } + #toolbar #songLabel { + display: inline-block; + max-width: 45vw; + overflow: hidden; + text-overflow: ellipsis; + vertical-align: bottom; white-space: nowrap; } + #toolbar .dropdown-menu { max-height: 60vh; overflow-y: auto } + #key-menu { min-width: 7rem } - button { margin-right: 1ex } + /* advanced panel (power-user / editing) */ + #advanced { display: none; margin-top: 1rem } + #advanced > * { margin-bottom: .8rem } @media print { .noprint { display: none !important } } append body + //- inline Bootstrap-icons style glyph (no extra deps): pass an array of {d, fr?} + mixin bi(paths) + svg.bi(xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true" focusable="false") + each p in paths + if p.fr + path(fill-rule=p.fr d=p.d) + else + path(d=p.d) + + #toolbar.noprint.d-flex.flex-wrap.align-items-center + //- Song picker (primary action) + .dropdown + button.btn.btn-primary.dropdown-toggle#songFile(type="button" data-toggle="dropdown" title="Choose a song") + +bi([{d:'M6 13c0 1.105-1.12 2-2.5 2S1 14.105 1 13c0-1.104 1.12-2 2.5-2s2.5.896 2.5 2zm9-2c0 1.105-1.12 2-2.5 2S10 12.105 10 11c0-1.104 1.12-2 2.5-2s2.5.896 2.5 2z'},{fr:'evenodd',d:'M14 11V2h1v9h-1zM6 3v10H5V3h1z'},{d:'M5 2.905a1 1 0 0 1 .9-.995l8-.8a1 1 0 0 1 1.1.995V3L5 4V2.905z'}]) + span#songLabel Pick a song + .dropdown-menu#song-menu(aria-labelledby="songFile") + - var keys = Object.keys(src['by-title.json']) + - keys.sort() + each k in keys + a.dropdown-item(href="#")= k + + //- View toggles + .btn-group.btn-group-toggle.btn-group-sm#viewToggles(data-toggle="buttons") + label.btn.btn-outline-secondary.active(title="Show lyrics") + input#show-lyrics(type="checkbox" checked autocomplete="off") + +bi([{d:'M14.5 3a.5.5 0 0 1 .5.5v9a.5.5 0 0 1-.5.5h-13a.5.5 0 0 1-.5-.5v-9a.5.5 0 0 1 .5-.5h13zm-13-1A1.5 1.5 0 0 0 0 3.5v9A1.5 1.5 0 0 0 1.5 14h13a1.5 1.5 0 0 0 1.5-1.5v-9A1.5 1.5 0 0 0 14.5 2h-13z'},{d:'M3 5.5a.5.5 0 0 1 .5-.5h9a.5.5 0 0 1 0 1h-9a.5.5 0 0 1-.5-.5zM3 8a.5.5 0 0 1 .5-.5h9a.5.5 0 0 1 0 1h-9A.5.5 0 0 1 3 8zm0 2.5a.5.5 0 0 1 .5-.5h6a.5.5 0 0 1 0 1h-6a.5.5 0 0 1-.5-.5z'}]) + | Lyrics + label.btn.btn-outline-secondary(title="Show trumpet fingering") + input#show-trumpet(type="checkbox" autocomplete="off") + svg.bi(xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true" focusable="false") + circle(cx="3.6" cy="8" r="2.1") + circle(cx="8" cy="8" r="2.1") + circle(cx="12.4" cy="8" r="2.1") + | Trumpet + label.btn.btn-outline-secondary(title="Show guitar tab") + input#show-gtab(type="checkbox" autocomplete="off") + svg.bi(xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.3" viewBox="0 0 16 16" aria-hidden="true" focusable="false") + path(d="M1 3.5h14M1 6.5h14M1 9.5h14M1 12.5h14") + | Tab + + //- Transpose: pick the destination key (offset shown) + .dropdown + button.btn.btn-outline-secondary.btn-sm.dropdown-toggle#keyBtn(type="button" data-toggle="dropdown" title="Transpose: choose a key") + +bi([{fr:'evenodd',d:'M11.5 15a.5.5 0 0 0 .5-.5V2.707l3.146 3.147a.5.5 0 0 0 .708-.708l-4-4a.5.5 0 0 0-.708 0l-4 4a.5.5 0 1 0 .708.708L11 2.707V14.5a.5.5 0 0 0 .5.5zm-7-14a.5.5 0 0 1 .5.5v11.793l3.146-3.147a.5.5 0 0 1 .708.708l-4 4a.5.5 0 0 1-.708 0l-4-4a.5.5 0 0 1 .708-.708L4 13.293V1.5a.5.5 0 0 1 .5-.5z'}]) + span#keyLabel – + .dropdown-menu.dropdown-menu-right#key-menu(aria-labelledby="keyBtn") + + //- Advanced / edit ABC (power users) + button.btn.btn-outline-secondary.btn-sm.ml-auto#advancedToggle(type="button" title="Advanced / edit ABC" aria-pressed="false") + +bi([{d:'M8 4.754a3.246 3.246 0 1 0 0 6.492 3.246 3.246 0 0 0 0-6.492zM5.754 8a2.246 2.246 0 1 1 4.492 0 2.246 2.246 0 0 1-4.492 0z'},{d:'M9.796 1.343c-.527-1.79-3.065-1.79-3.592 0l-.094.319a.873.873 0 0 1-1.255.52l-.292-.16c-1.64-.892-3.433.902-2.54 2.541l.159.292a.873.873 0 0 1-.52 1.255l-.319.094c-1.79.527-1.79 3.065 0 3.592l.319.094a.873.873 0 0 1 .52 1.255l-.16.292c-.892 1.64.901 3.434 2.541 2.54l.292-.159a.873.873 0 0 1 1.255.52l.094.319c.527 1.79 3.065 1.79 3.592 0l.094-.319a.873.873 0 0 1 1.255-.52l.292.16c1.64.893 3.434-.902 2.54-2.541l-.159-.292a.873.873 0 0 1 .52-1.255l.319-.094c1.79-.527 1.79-3.065 0-3.592l-.319-.094a.873.873 0 0 1-.52-1.255l.16-.292c.893-1.64-.902-3.434-2.541-2.54l-.292.159a.873.873 0 0 1-1.255-.52l-.094-.319zm-2.633.283c.246-.835 1.428-.835 1.674 0l.094.319a1.873 1.873 0 0 0 2.693 1.115l.291-.16c.764-.415 1.6.42 1.184 1.185l-.159.292a1.873 1.873 0 0 0 1.116 2.692l.318.094c.835.246.835 1.428 0 1.674l-.319.094a1.873 1.873 0 0 0-1.115 2.693l.16.291c.415.764-.42 1.6-1.185 1.184l-.291-.159a1.873 1.873 0 0 0-2.693 1.116l-.094.318c-.246.835-1.428.835-1.674 0l-.094-.319a1.873 1.873 0 0 0-2.692-1.115l-.292.16c-.764.415-1.6-.42-1.184-1.185l.159-.291A1.873 1.873 0 0 0 1.945 8.93l-.319-.094c-.835-.246-.835-1.428 0-1.674l.319-.094A1.873 1.873 0 0 0 3.06 4.377l-.16-.292c-.415-.764.42-1.6 1.185-1.184l.292.159a1.873 1.873 0 0 0 2.692-1.115l.094-.319z'}]) + #paper - .noprint.d-flex.flex-wrap.align-items-center + + #advanced.noprint .item - span Enter some   + span Enter some a(href="https://github.com/brewingcode/shanties/blob/master/README.md" target="_blank") ABC notation - .item - span or   - .dropdown.d-inline-block - button.btn.dropdown-toggle(type="button" id="songFile" data-toggle="dropdown") Pick a song - .dropdown-menu(aria-labelledby="songFile") - - var keys = Object.keys(src['by-title.json']) - - keys.sort() - each k in keys - a.dropdown-item(href="#")= k - .item - span or   + span , or a(href="https://github.com/brewingcode/shanties/tree/master/songs") - svg(xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16") - path(d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.012 8.012 0 0 0 16 8c0-4.42-3.58-8-8-8z") - span  add a song - - .noprint: textarea#abc(spellcheck="false") - .noprint: #warnings - .noprint#settings - label - span Show lyrics - input#show-lyrics(type="checkbox" checked) - span     - label - span Show trumpet fingering - input#show-trumpet(type="checkbox") - span     - label - span Show guitar tab - input#show-gtab(type="checkbox") - span     - label - span Transpose: - input#transpose(type="number" min="-24" max="24" step="1" value="0") - span   - span#fromKey - span  ->  - span#toKey - .noprint + +bi([{d:'M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.012 8.012 0 0 0 16 8c0-4.42-3.58-8-8-8z'}]) + span add a song + textarea#abc(spellcheck="false") + #warnings p The Songbook PDF can be found at this link, or via this QR code: img(src="qr-code.svg" alt="https://brewingcode.github.io/shanties/Songbook.pdf" width="200" height="200") - .noprint - a(href="https://github.com/brewingcode/shanties/commit/" + src['GIT_HEAD'])= src['GIT_HEAD'] + div + a(href="https://github.com/brewingcode/shanties/commit/" + src['GIT_HEAD'])= src['GIT_HEAD'] script. var songs = !{JSON.stringify(src['songs.json'])}; var byTitle = !{JSON.stringify(src['by-title.json'])}; @@ -96,6 +131,39 @@ append body else k.root + CHROMATIC = ['C', 'D♭', 'D', 'E♭', 'E', 'F', 'G♭', 'G', 'A♭', 'A', 'B♭', 'B'] + prevStep = 0 + origPc = null + + keyToPc = (name) -> + return null unless name + base = { C: 0, D: 2, E: 4, F: 5, G: 7, A: 9, B: 11 } + pc = base[name.charAt(0)] + return null unless pc? + pc += 1 if name.indexOf('#') >= 0 or name.indexOf('♯') >= 0 + pc -= 1 if name.indexOf('♭') >= 0 + ((pc % 12) + 12) % 12 + + updateKeyLabel = -> + k = displayKey() or '–' + k += " (#{if prevStep > 0 then '+' else ''}#{prevStep})" unless prevStep is 0 + $('#keyLabel').text k + $('#key-menu .dropdown-item').each -> + $(this).toggleClass 'active', +$(this).attr('data-offset') is prevStep + + buildKeyMenu = -> + menu = $('#key-menu').empty() + return unless origPc? + for d in [-5..6] + pc = (((origPc + d) % 12) + 12) % 12 + label = CHROMATIC[pc] + label += " (#{if d > 0 then '+' else ''}#{d})" unless d is 0 + $('') + .attr('data-offset', d) + .text(label) + .appendTo menu + updateKeyLabel() + setSong = (song) -> s = song .split /\n/ @@ -104,7 +172,7 @@ append body lyrics = m[1] if lyrics.match /^[\s\d\?]+$/ # all digits are trumpet fingering, keep those - return $('#show-trumpt').is(':checked') + return $('#show-trumpet').is(':checked') else return $('#show-lyrics').is(':checked') else @@ -114,10 +182,10 @@ append body document.title = Object.entries(byTitle) .find ([k,v]) -> v is song ?.at(0) or 'YEEAAARGH' + prevStep = 0 setTimeout -> - k = displayKey() - $('#fromKey').text(k) - $('#toKey').text(k) + origPc = keyToPc displayKey() + buildKeyMenu() , 500 updateUrl = (title) -> @@ -126,37 +194,38 @@ append body window.history.replaceState {}, '', "#{window.location.pathname}?#{params}" addEditButton = -> - $('#settings > button').remove() - $('#settings').prepend """ - """ - $('#settings > button').on 'click', (e) -> - $(e.target).remove() + $('#advanced > .edit-btn').remove() + btn = $('') + btn.on 'click', -> + btn.remove() $('#abc').prop('disabled', false) .focus() - .on 'blur', (e) -> + .on 'blur', -> $('#abc').prop 'disabled', true addEditButton() + $('#advanced').prepend btn window.onload = -> - prevStep = 0 window.editor = new ABCJS.Editor 'abc', canvas_id: 'paper', warnings_id: 'warnings' abcjsParams: abcjsParams - $('.dropdown-menu a').click -> - setSong byTitle[$(this).text()] - updateUrl $(this).text() + $('#song-menu a.dropdown-item').click (e) -> + e.preventDefault() + title = $(this).text() + setSong byTitle[title] + $('#songLabel').text title + updateUrl title - $('#transpose').on 'change', -> - tv = +$('#transpose').val() - $('#fromKey').text $('#toKey').text() + $('#key-menu').on 'click', '.dropdown-item', (e) -> + e.preventDefault() + tv = +$(this).attr('data-offset') + return if tv is prevStep newTunes = ABCJS.strTranspose $('#abc').val(), window.editor.tunes, tv - prevStep - window.editor.editarea.setString(newTunes) + window.editor.editarea.setString newTunes prevStep = tv - setTimeout -> - $('#toKey').text displayKey() - , 500 + setTimeout updateKeyLabel, 500 $('#show-lyrics, #show-trumpet').on 'change', -> setSong byTitle[document.title] @@ -172,16 +241,26 @@ append body }] } + $('#advancedToggle').on 'click', -> + shown = $('#advanced').toggle().is(':visible') + $(this).toggleClass('active', shown).attr 'aria-pressed', shown + params = new URLSearchParams(window.location.search) file = params.get('file') title = params.get('title') if file and songs[file] setSong songs[file] + $('#songLabel').text(document.title) unless document.title is 'YEEAAARGH' else if title and byTitle[title] setSong byTitle[title] + $('#songLabel').text title else setSong "%%notelabels 1\nB c d e | ff | c'd' | EE E | =D^D" + if params.get('advanced') is 'true' + $('#advanced').show() + $('#advancedToggle').addClass('active').attr 'aria-pressed', true + if navigator.userAgent.match /i(Pad|Phone)/i $('#abc').prop 'disabled', true addEditButton() From 7b8ecacc4da0d544746668d4ec89b58044395161 Mon Sep 17 00:00:00 2001 From: Chris <26607885+chrisglein@users.noreply.github.com> Date: Sun, 12 Jul 2026 06:41:23 -0700 Subject: [PATCH 2/3] Add Staff toggle & note-render toggles, emoji icons, songbook dialog (#46, #27) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Refine the lean home UI: - New Staff toggle: hides the whole notation image (abcjs couples staff/notes/lyrics/tab and can't reflow), surfacing the song's extended W: verses as text. Pure-CSS via body.no-staff, overriding abcjs's inline padding-bottom so width is kept and the staff re-renders crisply when shown again. Color/Labels auto-disable when the staff is hidden. - Note color & note labels are now UI toggles (issue #27): removed the hardcoded %%notecolors/%%notelabels from all 26 songs/*.txt and the default snippet; they're injected before rendering based on the Color/Labels toggles (default on, so the look is unchanged). - Icons switched to emoji (song 🎶, staff 🎼, color 🎨, labels 🔤, lyrics 🗣️, trumpet 🎺, guitar 🎸, songbook 📄, edit 🖊️). - Rename "Tab" -> "Guitar"; Key control now reads "Key: E♭ (+2)". - Edit button is a pen (was a gear); the advanced panel is now ABC-only (links, textarea, warnings). - Songbook PDF + QR moved into a modal launched by 📄, with the commit hash relocated to its footer as the version, separating it from the ABC-editing controls. --- songs/all-for-me-grog.txt | 2 - songs/ballad-of-the-mer.txt | 2 - songs/barretts-privateers.txt | 1 - songs/bosun-bill.txt | 2 - songs/bully-boys.txt | 2 - songs/bully-in-the-alley.txt | 2 - songs/deck-the-halls.txt | 2 - songs/drunken-sailor.txt | 2 - songs/health-to-the-company.txt | 2 - songs/joli-rouge.txt | 2 - songs/leave-her-johnny.txt | 2 - songs/lifeboat-prayer.txt | 1 - songs/mario.txt | 2 - songs/mercy-mercy-mercy.txt | 2 - songs/mingulay-boat-song.txt | 2 - songs/old-maui.txt | 1 - songs/randy-dandy-o.txt | 2 - songs/roll-the-old-chariot-along.txt | 2 - songs/skipper-jan-rebec.txt | 1 - songs/song-of-storms.txt | 2 - songs/south-australia.txt | 2 - songs/the-last-shanty.txt | 2 - songs/toss-a-coin-to-your-witcher.txt | 2 - songs/we-wish-you-a-merry-xmas.txt | 2 - songs/wellerman.txt | 2 - songs/whiskey-johnny.txt | 2 - src/index.pug | 126 ++++++++++++++++++++------ 27 files changed, 99 insertions(+), 75 deletions(-) diff --git a/songs/all-for-me-grog.txt b/songs/all-for-me-grog.txt index 03c57a2..629a6e8 100644 --- a/songs/all-for-me-grog.txt +++ b/songs/all-for-me-grog.txt @@ -1,8 +1,6 @@ X: 1 T: All For Me Grog %%vocalfont times 10 -%%notecolors 1 -%%notelabels 1 M: 4/4 L: 1/8 K: C diff --git a/songs/ballad-of-the-mer.txt b/songs/ballad-of-the-mer.txt index 7891d93..0f6a0bd 100644 --- a/songs/ballad-of-the-mer.txt +++ b/songs/ballad-of-the-mer.txt @@ -1,7 +1,5 @@ T: Ballad of the Mer %%vocalfont times 10 -%%notecolors 1 -%%notelabels 1 L:1/4 K: Eb M: 3/4 diff --git a/songs/barretts-privateers.txt b/songs/barretts-privateers.txt index 10c6501..3ebf0ef 100644 --- a/songs/barretts-privateers.txt +++ b/songs/barretts-privateers.txt @@ -1,7 +1,6 @@ T: Barrett's Privateers K: C L: 1/8 -%%notelabels 1 P: Verse C3 E | "C" G2 G2 "F" FF E2 | "G"DD D2 "C"C2 GG | GG3 "F"A2 A2 | "C"G2 G2 | "G"D4 z2 A2 | w: Oh, the year was se-ven-teen sev-en-ty eight, how I wish I was in Sher-brooke now! A diff --git a/songs/bosun-bill.txt b/songs/bosun-bill.txt index 2e558ff..6f5c3f4 100644 --- a/songs/bosun-bill.txt +++ b/songs/bosun-bill.txt @@ -1,8 +1,6 @@ X: 1 T: Bosun Bill %%vocalfont times 10 -%%notecolors 1 -%%notelabels 1 M: 2/4 L: 1/16 K: Eb diff --git a/songs/bully-boys.txt b/songs/bully-boys.txt index a938f4d..8559f67 100644 --- a/songs/bully-boys.txt +++ b/songs/bully-boys.txt @@ -1,8 +1,6 @@ X: 1 T: Bully Boys %%vocalfont times 10 -%%notecolors 1 -%%notelabels 1 M: 6/8 K: C Q: 1/4=140 diff --git a/songs/bully-in-the-alley.txt b/songs/bully-in-the-alley.txt index 2722bd6..2e8523c 100644 --- a/songs/bully-in-the-alley.txt +++ b/songs/bully-in-the-alley.txt @@ -1,8 +1,6 @@ X: 1 T: Bully in the Alley %%vocalfont times 10 -%%notecolors 1 -%%notelabels 1 K: G M: 4/4 Q: 1/4=150 diff --git a/songs/deck-the-halls.txt b/songs/deck-the-halls.txt index 221c527..b869459 100644 --- a/songs/deck-the-halls.txt +++ b/songs/deck-the-halls.txt @@ -1,6 +1,4 @@ T: Deck the Halls -%%notecolors 1 -%%notelabels 1 K: D L: 1/8 "D"A3 G "A"F2 E2 | "D"D2 E2 "D_"F2 D2 | "A7"EFGE "D"F3 E | "A7"D2 C2 "D"D4 | diff --git a/songs/drunken-sailor.txt b/songs/drunken-sailor.txt index 650fa72..d9cfadb 100644 --- a/songs/drunken-sailor.txt +++ b/songs/drunken-sailor.txt @@ -1,7 +1,5 @@ T: Drunken Sailor %%vocalfont times 10 -%%notecolors 1 -%%notelabels 1 K: Dm M: 4/4 "Dm"a2 aa a2 aa | a2 d2 f2 a2 | "C"g2 gg g2 gg | g2 c2 e2 g2 | diff --git a/songs/health-to-the-company.txt b/songs/health-to-the-company.txt index 8a4d149..03b1696 100644 --- a/songs/health-to-the-company.txt +++ b/songs/health-to-the-company.txt @@ -1,7 +1,5 @@ T: Health to the Company %%vocalfont times 10 -%%notecolors 1 -%%notelabels 1 M: 3/4 L: 1/8 Q: 1/4=110 diff --git a/songs/joli-rouge.txt b/songs/joli-rouge.txt index 79accfd..1fb48d3 100644 --- a/songs/joli-rouge.txt +++ b/songs/joli-rouge.txt @@ -1,8 +1,6 @@ X: 1 T: Joli Rouge %%vocalfont times 10 -%%notecolors 1 -%%notelabels 1 M: 6/8 K: Dm "Dm" D3 [F2A] [FA] | "Am" A,3 [C3E] | "Dm" D3 [F2A] [FA] | "Am" A,3 [C3E] | "Dm" D3 [F2A] [FA] | "Am" A,3 [C3EG] | diff --git a/songs/leave-her-johnny.txt b/songs/leave-her-johnny.txt index 598e904..bf6d574 100644 --- a/songs/leave-her-johnny.txt +++ b/songs/leave-her-johnny.txt @@ -1,7 +1,5 @@ T: Leave Her Johnny %%vocalfont times 10 -%%notecolors 1 -%%notelabels 1 K: C M: 4/4 cd | "C"e2 e2 e2 cd | e2 d2 c4 | "G"d2 d2 d3 c | "C"e2 g4 diff --git a/songs/lifeboat-prayer.txt b/songs/lifeboat-prayer.txt index fcfdb7c..1d18611 100644 --- a/songs/lifeboat-prayer.txt +++ b/songs/lifeboat-prayer.txt @@ -1,7 +1,6 @@ T: Lifeboat Prayer K: D L: 1/8 -%%notelabels 1 "D" A3A F3 D "G" G3 A "D" F3 D "G" G3 A "D" FE D "A" E3 F E3 w: Those who ven-ture on the sea to ply their trade _ up-on the deep w: When the call for res-cue comes, from those in per- _ il on this day diff --git a/songs/mario.txt b/songs/mario.txt index 0b3959d..dbd1ca8 100644 --- a/songs/mario.txt +++ b/songs/mario.txt @@ -1,7 +1,5 @@ X: 1 T: Mario Bros. Theme -%%notecolors 1 -%%notelabels 1 M: 4/4 L: 1/16 K: G diff --git a/songs/mercy-mercy-mercy.txt b/songs/mercy-mercy-mercy.txt index aec5bed..eb349ed 100644 --- a/songs/mercy-mercy-mercy.txt +++ b/songs/mercy-mercy-mercy.txt @@ -1,7 +1,5 @@ T: Mercy, Mercy, Mercy %%vocalfont times 10 -%%notecolors 1 -%%notelabels 1 K: F M: 4/4 "C7" z2 A G2 "C7/E" EEC | "F" DCCA, "G7sus" C2 D2 diff --git a/songs/mingulay-boat-song.txt b/songs/mingulay-boat-song.txt index e97e91a..b39b579 100644 --- a/songs/mingulay-boat-song.txt +++ b/songs/mingulay-boat-song.txt @@ -1,7 +1,5 @@ T: Mingulay Boat Song %%vocalfont times 10 -%%notecolors 1 -%%notelabels 1 M: 3/4 Q: 1/4=140 K: G diff --git a/songs/old-maui.txt b/songs/old-maui.txt index 1fe3110..d9a3d95 100644 --- a/songs/old-maui.txt +++ b/songs/old-maui.txt @@ -1,6 +1,5 @@ T: Old Maui K: G -%%notelabels 1 P: Verse BB | "Em"e2 e2 "B"^d2 BB | "G"g2 fe "D"f2 (ba) | "Em"(gf) e2 "B"f2 de | "Em"e4 BB | w:It's a damn tough life full of toil and ~ strife we ~ wha-ler-men un-der - go, and we diff --git a/songs/randy-dandy-o.txt b/songs/randy-dandy-o.txt index 8797680..1c07669 100644 --- a/songs/randy-dandy-o.txt +++ b/songs/randy-dandy-o.txt @@ -1,7 +1,5 @@ T: Randy Dandy-O %%vocalfont times 10 -%%notecolors 1 -%%notelabels 1 K: C M: 6/8 L: 1/16 diff --git a/songs/roll-the-old-chariot-along.txt b/songs/roll-the-old-chariot-along.txt index c92910e..6c9b04a 100644 --- a/songs/roll-the-old-chariot-along.txt +++ b/songs/roll-the-old-chariot-along.txt @@ -1,7 +1,5 @@ T: Roll the Old Chariot Along %%vocalfont times 10 -%%notecolors 1 -%%notelabels 1 K: Dm M: 4/4 Q: 1/4=140 diff --git a/songs/skipper-jan-rebec.txt b/songs/skipper-jan-rebec.txt index 93ecd70..f1f52b8 100644 --- a/songs/skipper-jan-rebec.txt +++ b/songs/skipper-jan-rebec.txt @@ -1,5 +1,4 @@ T: Skipper Jan Rebec -%%notelabels 1 K: Eb "Eb"GGGEB,"Bb"CE "Eb"E EE"F"DEF "Eb"GGEE"Bb"AAA| A"Eb"GE"F"FD"Eb"E EFGEB,EEE | GE"F"FFF | "Eb"GE"Bb"AAAA | "Eb"GE"F"FD"Eb"E \ No newline at end of file diff --git a/songs/song-of-storms.txt b/songs/song-of-storms.txt index b5cd15d..7a5ef91 100644 --- a/songs/song-of-storms.txt +++ b/songs/song-of-storms.txt @@ -1,6 +1,4 @@ T: Song of Storms -%%notecolors 1 -%%notelabels 1 K: Dm L: 1/4 M: 6/8 diff --git a/songs/south-australia.txt b/songs/south-australia.txt index 8033e76..ab53f11 100644 --- a/songs/south-australia.txt +++ b/songs/south-australia.txt @@ -1,7 +1,5 @@ T: South Australia %%vocalfont times 10 -%%notecolors 1 -%%notelabels 1 M: 4/4 K: E P: Part A diff --git a/songs/the-last-shanty.txt b/songs/the-last-shanty.txt index 5cb1a72..562cec2 100644 --- a/songs/the-last-shanty.txt +++ b/songs/the-last-shanty.txt @@ -1,8 +1,6 @@ X: 1 T: The Last Shanty %%vocalfont times 10 -%%notecolors 1 -%%notelabels 1 K: A F E "D"D D D E D A, A, D D D E D w: Well me fa-ther oft-en told me when I was just a lad diff --git a/songs/toss-a-coin-to-your-witcher.txt b/songs/toss-a-coin-to-your-witcher.txt index a01807a..fa28d88 100644 --- a/songs/toss-a-coin-to-your-witcher.txt +++ b/songs/toss-a-coin-to-your-witcher.txt @@ -1,7 +1,5 @@ T: Toss a Coin to Your Witcher %%vocalfont times 10 -%%notecolors 1 -%%notelabels 1 K: Db M:4/4 "Bbm" z4 DCB,A, | "Eb" B,4 DEDC | diff --git a/songs/we-wish-you-a-merry-xmas.txt b/songs/we-wish-you-a-merry-xmas.txt index 2161ce4..2c9ea24 100644 --- a/songs/we-wish-you-a-merry-xmas.txt +++ b/songs/we-wish-you-a-merry-xmas.txt @@ -1,6 +1,4 @@ T: We Wish You a Merry Christmas -%%notelabels 1 -%%notecolors 1 L: 1/8 G2 | "C"c2 cd cB | "F"A2 A2 A2 | "D7"d2 de dc | "G"B2 G2 G2 | "E"e2 ef ed | "Am"c2 A2 "C"GG | "F"A2 d2 "G"B2 | "C"c4 G2 | diff --git a/songs/wellerman.txt b/songs/wellerman.txt index b928aad..b49e5a5 100644 --- a/songs/wellerman.txt +++ b/songs/wellerman.txt @@ -1,8 +1,6 @@ X: 1 T: Wellerman %%vocalfont times 10 -%%notecolors 1 -%%notelabels 1 M: 4/4 L: 1/8 K: Eb diff --git a/songs/whiskey-johnny.txt b/songs/whiskey-johnny.txt index 4915a57..ff9976a 100644 --- a/songs/whiskey-johnny.txt +++ b/songs/whiskey-johnny.txt @@ -1,8 +1,6 @@ X: 1 T: Whiskey Johnny %%vocalfont times 10 -%%notecolors 1 -%%notelabels 1 M: 4/4 L: 1/4 K: A diff --git a/src/index.pug b/src/index.pug index 696656b..5a46ad6 100644 --- a/src/index.pug +++ b/src/index.pug @@ -19,10 +19,15 @@ append head /* lean toolbar */ #toolbar { gap: .45rem; margin-top: .6rem } + #toolbar .ico { + font-style: normal; + font-size: 1.05em; + line-height: 1; + vertical-align: -.05em; + } #toolbar .btn .bi { vertical-align: -.15em } - #toolbar .btn .bi + span, - #toolbar .btn .bi + * { margin-left: .35em } - #toolbar .btn-group-toggle .btn .bi { margin-right: .35em } + #toolbar .btn > .ico, + #toolbar .btn > .bi { margin-right: .3em } #toolbar #songLabel { display: inline-block; max-width: 45vw; @@ -34,7 +39,14 @@ append head #toolbar .dropdown-menu { max-height: 60vh; overflow-y: auto } #key-menu { min-width: 7rem } - /* advanced panel (power-user / editing) */ + /* staff hidden: keep #paper width (abcjs is responsive) but collapse its height. + abcjs sets an inline padding-bottom aspect-ratio, so override it with !important. */ + body.no-staff #paper { height: 0 !important; padding-bottom: 0 !important; overflow: hidden } + #verses { display: none; margin-top: 1rem } + #verses p { margin-bottom: .8rem } + body.no-staff #verses { display: block } + + /* advanced panel (ABC editing) */ #advanced { display: none; margin-top: 1rem } #advanced > * { margin-bottom: .8rem } @@ -56,7 +68,7 @@ append body //- Song picker (primary action) .dropdown button.btn.btn-primary.dropdown-toggle#songFile(type="button" data-toggle="dropdown" title="Choose a song") - +bi([{d:'M6 13c0 1.105-1.12 2-2.5 2S1 14.105 1 13c0-1.104 1.12-2 2.5-2s2.5.896 2.5 2zm9-2c0 1.105-1.12 2-2.5 2S10 12.105 10 11c0-1.104 1.12-2 2.5-2s2.5.896 2.5 2z'},{fr:'evenodd',d:'M14 11V2h1v9h-1zM6 3v10H5V3h1z'},{d:'M5 2.905a1 1 0 0 1 .9-.995l8-.8a1 1 0 0 1 1.1.995V3L5 4V2.905z'}]) + span.ico 🎶 span#songLabel Pick a song .dropdown-menu#song-menu(aria-labelledby="songFile") - var keys = Object.keys(src['by-title.json']) @@ -64,38 +76,55 @@ append body each k in keys a.dropdown-item(href="#")= k - //- View toggles + //- Staff + note options + .btn-group.btn-group-toggle.btn-group-sm#staffToggles(data-toggle="buttons") + label.btn.btn-outline-secondary.active(title="Show the music staff") + input#show-staff(type="checkbox" checked autocomplete="off") + span.ico 🎼 + | Staff + label.btn.btn-outline-secondary.active(title="Color notes by pitch") + input#show-notecolors(type="checkbox" checked autocomplete="off") + span.ico 🎨 + | Color + label.btn.btn-outline-secondary.active(title="Label notes with letter names") + input#show-notelabels(type="checkbox" checked autocomplete="off") + span.ico 🔤 + | Labels + + //- Lyrics & instrument layers .btn-group.btn-group-toggle.btn-group-sm#viewToggles(data-toggle="buttons") label.btn.btn-outline-secondary.active(title="Show lyrics") input#show-lyrics(type="checkbox" checked autocomplete="off") - +bi([{d:'M14.5 3a.5.5 0 0 1 .5.5v9a.5.5 0 0 1-.5.5h-13a.5.5 0 0 1-.5-.5v-9a.5.5 0 0 1 .5-.5h13zm-13-1A1.5 1.5 0 0 0 0 3.5v9A1.5 1.5 0 0 0 1.5 14h13a1.5 1.5 0 0 0 1.5-1.5v-9A1.5 1.5 0 0 0 14.5 2h-13z'},{d:'M3 5.5a.5.5 0 0 1 .5-.5h9a.5.5 0 0 1 0 1h-9a.5.5 0 0 1-.5-.5zM3 8a.5.5 0 0 1 .5-.5h9a.5.5 0 0 1 0 1h-9A.5.5 0 0 1 3 8zm0 2.5a.5.5 0 0 1 .5-.5h6a.5.5 0 0 1 0 1h-6a.5.5 0 0 1-.5-.5z'}]) + span.ico 🗣️ | Lyrics label.btn.btn-outline-secondary(title="Show trumpet fingering") input#show-trumpet(type="checkbox" autocomplete="off") - svg.bi(xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" viewBox="0 0 16 16" aria-hidden="true" focusable="false") - circle(cx="3.6" cy="8" r="2.1") - circle(cx="8" cy="8" r="2.1") - circle(cx="12.4" cy="8" r="2.1") + span.ico 🎺 | Trumpet label.btn.btn-outline-secondary(title="Show guitar tab") input#show-gtab(type="checkbox" autocomplete="off") - svg.bi(xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.3" viewBox="0 0 16 16" aria-hidden="true" focusable="false") - path(d="M1 3.5h14M1 6.5h14M1 9.5h14M1 12.5h14") - | Tab + span.ico 🎸 + | Guitar //- Transpose: pick the destination key (offset shown) .dropdown button.btn.btn-outline-secondary.btn-sm.dropdown-toggle#keyBtn(type="button" data-toggle="dropdown" title="Transpose: choose a key") +bi([{fr:'evenodd',d:'M11.5 15a.5.5 0 0 0 .5-.5V2.707l3.146 3.147a.5.5 0 0 0 .708-.708l-4-4a.5.5 0 0 0-.708 0l-4 4a.5.5 0 1 0 .708.708L11 2.707V14.5a.5.5 0 0 0 .5.5zm-7-14a.5.5 0 0 1 .5.5v11.793l3.146-3.147a.5.5 0 0 1 .708.708l-4 4a.5.5 0 0 1-.708 0l-4-4a.5.5 0 0 1 .708-.708L4 13.293V1.5a.5.5 0 0 1 .5-.5z'}]) - span#keyLabel – + span#keyLabel Key: – .dropdown-menu.dropdown-menu-right#key-menu(aria-labelledby="keyBtn") - //- Advanced / edit ABC (power users) - button.btn.btn-outline-secondary.btn-sm.ml-auto#advancedToggle(type="button" title="Advanced / edit ABC" aria-pressed="false") - +bi([{d:'M8 4.754a3.246 3.246 0 1 0 0 6.492 3.246 3.246 0 0 0 0-6.492zM5.754 8a2.246 2.246 0 1 1 4.492 0 2.246 2.246 0 0 1-4.492 0z'},{d:'M9.796 1.343c-.527-1.79-3.065-1.79-3.592 0l-.094.319a.873.873 0 0 1-1.255.52l-.292-.16c-1.64-.892-3.433.902-2.54 2.541l.159.292a.873.873 0 0 1-.52 1.255l-.319.094c-1.79.527-1.79 3.065 0 3.592l.319.094a.873.873 0 0 1 .52 1.255l-.16.292c-.892 1.64.901 3.434 2.541 2.54l.292-.159a.873.873 0 0 1 1.255.52l.094.319c.527 1.79 3.065 1.79 3.592 0l.094-.319a.873.873 0 0 1 1.255-.52l.292.16c1.64.893 3.434-.902 2.54-2.541l-.159-.292a.873.873 0 0 1 .52-1.255l.319-.094c1.79-.527 1.79-3.065 0-3.592l-.319-.094a.873.873 0 0 1-.52-1.255l.16-.292c.893-1.64-.902-3.434-2.541-2.54l-.292.159a.873.873 0 0 1-1.255-.52l-.094-.319zm-2.633.283c.246-.835 1.428-.835 1.674 0l.094.319a1.873 1.873 0 0 0 2.693 1.115l.291-.16c.764-.415 1.6.42 1.184 1.185l-.159.292a1.873 1.873 0 0 0 1.116 2.692l.318.094c.835.246.835 1.428 0 1.674l-.319.094a1.873 1.873 0 0 0-1.115 2.693l.16.291c.415.764-.42 1.6-1.185 1.184l-.291-.159a1.873 1.873 0 0 0-2.693 1.116l-.094.318c-.246.835-1.428.835-1.674 0l-.094-.319a1.873 1.873 0 0 0-2.692-1.115l-.292.16c-.764.415-1.6-.42-1.184-1.185l.159-.291A1.873 1.873 0 0 0 1.945 8.93l-.319-.094c-.835-.246-.835-1.428 0-1.674l.319-.094A1.873 1.873 0 0 0 3.06 4.377l-.16-.292c-.415-.764.42-1.6 1.185-1.184l.292.159a1.873 1.873 0 0 0 2.692-1.115l.094-.319z'}]) + //- Songbook PDF / QR (document dialog) + button.btn.btn-outline-secondary.btn-sm.ml-auto#songbookBtn(type="button" data-toggle="modal" data-target="#songbookModal" title="Songbook PDF & QR code") + span.ico 📄 + + //- Edit the ABC source + button.btn.btn-outline-secondary.btn-sm#advancedToggle(type="button" title="Edit ABC notation" aria-pressed="false") + span.ico 🖊️ #paper + #verses + #advanced.noprint .item span Enter some @@ -106,10 +135,23 @@ append body span add a song textarea#abc(spellcheck="false") #warnings - p The Songbook PDF can be found at this link, or via this QR code: - img(src="qr-code.svg" alt="https://brewingcode.github.io/shanties/Songbook.pdf" width="200" height="200") - div - a(href="https://github.com/brewingcode/shanties/commit/" + src['GIT_HEAD'])= src['GIT_HEAD'] + + //- Songbook PDF + QR code dialog + #songbookModal.modal.fade.noprint(tabindex="-1" role="dialog" aria-labelledby="songbookModalLabel" aria-hidden="true") + .modal-dialog.modal-dialog-centered(role="document") + .modal-content + .modal-header + h5.modal-title#songbookModalLabel Songbook + button.close(type="button" data-dismiss="modal" aria-label="Close") + span(aria-hidden="true") × + .modal-body.text-center + p Download the printable songbook: Songbook.pdf + p.text-muted or scan to open it on another device: + img(src="qr-code.svg" alt="Songbook.pdf QR code" width="200" height="200") + .modal-footer.justify-content-center + small.text-muted + span version + a(href="https://github.com/brewingcode/shanties/commit/" + src['GIT_HEAD'])= src['GIT_HEAD'] script. var songs = !{JSON.stringify(src['songs.json'])}; var byTitle = !{JSON.stringify(src['by-title.json'])}; @@ -134,6 +176,7 @@ append body CHROMATIC = ['C', 'D♭', 'D', 'E♭', 'E', 'F', 'G♭', 'G', 'A♭', 'A', 'B♭', 'B'] prevStep = 0 origPc = null + currentSong = '' keyToPc = (name) -> return null unless name @@ -147,7 +190,7 @@ append body updateKeyLabel = -> k = displayKey() or '–' k += " (#{if prevStep > 0 then '+' else ''}#{prevStep})" unless prevStep is 0 - $('#keyLabel').text k + $('#keyLabel').text "Key: #{k}" $('#key-menu .dropdown-item').each -> $(this).toggleClass 'active', +$(this).attr('data-offset') is prevStep @@ -164,7 +207,25 @@ append body .appendTo menu updateKeyLabel() + esc = (s) -> $('
').text(s).html() + + renderVerses = (song) -> + para = [] + html = '' + flush = -> + if para.length + html += "

#{para.join('
')}

" + para = [] + for line in song.split(/\n/) + m = line.match /^\s*W:(.*)$/ + continue unless m + text = m[1].replace(/^\s/, '').replace(/\s+$/, '') + if text is '' then flush() else para.push esc(text) + flush() + $('#verses').html html + setSong = (song) -> + currentSong = song s = song .split /\n/ .filter (line) -> @@ -178,7 +239,11 @@ append body else return true .join('\n') - window.editor.editarea.setString s + directives = '' + directives += '%%notecolors 1\n' if $('#show-notecolors').is(':checked') + directives += '%%notelabels 1\n' if $('#show-notelabels').is(':checked') + window.editor.editarea.setString directives + s + renderVerses song document.title = Object.entries(byTitle) .find ([k,v]) -> v is song ?.at(0) or 'YEEAAARGH' @@ -227,8 +292,15 @@ append body prevStep = tv setTimeout updateKeyLabel, 500 - $('#show-lyrics, #show-trumpet').on 'change', -> - setSong byTitle[document.title] + $('#show-lyrics, #show-trumpet, #show-notecolors, #show-notelabels').on 'change', -> + setSong currentSong + + $('#show-staff').on 'change', -> + on_ = $(this).is(':checked') + $('body').toggleClass 'no-staff', not on_ + $('#show-notecolors, #show-notelabels') + .prop('disabled', not on_) + .closest('label').toggleClass 'disabled', not on_ $('#show-gtab').on 'change', -> window.editor.paramChanged { @@ -255,7 +327,7 @@ append body setSong byTitle[title] $('#songLabel').text title else - setSong "%%notelabels 1\nB c d e | ff | c'd' | EE E | =D^D" + setSong "B c d e | ff | c'd' | EE E | =D^D" if params.get('advanced') is 'true' $('#advanced').show() From 1fc960c84e5d45bfccfaac7100f41e79e0a9627d Mon Sep 17 00:00:00 2001 From: Chris <26607885+chrisglein@users.noreply.github.com> Date: Sun, 12 Jul 2026 10:15:06 -0700 Subject: [PATCH 3/3] Add color themes, line-art icons, docked bars; inject vocalfont MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rework the home-page graphic design based on a treatment sampler: - Two selectable color themes — "Soft" (off-white/blue, default) and "Nautical" (navy/brass-gold) — driven by CSS variables and a body class. A theme switcher (contrast icon) persists the choice in localStorage and applies it pre-render to avoid a flash. - Replace emoji with a monochrome line-art SVG icon sprite (+ an `icon` mixin); keep the GitHub logo as the only bitmapped glyph. - Docked bars instead of floating: a sticky full-width top bar, and a docked, collapsible bottom "Edit ABC" bar (its header toggles the editor) — removing the floating action button and the iPad disable-textarea dance. - Segmented toggle groups: a soft-grey track with pill segments — active pops (blue / gold), off segments take the standard button background, disabled ones fade. The edit bar shares the top bar's background. - Inject `%%vocalfont times 10` into every render (like the note color/label directives, but unconditional) and remove the hardcoded copies from the 19 songs that had it, so all songs share the serif lyric font. - Move the version/commit link out of the Songbook dialog into the ABC edit bar, and ignore the local `.temp/` scratch folder. --- songs/all-for-me-grog.txt | 1 - songs/ballad-of-the-mer.txt | 1 - songs/bosun-bill.txt | 1 - songs/bully-boys.txt | 1 - songs/bully-in-the-alley.txt | 1 - songs/drunken-sailor.txt | 1 - songs/health-to-the-company.txt | 1 - songs/joli-rouge.txt | 1 - songs/leave-her-johnny.txt | 1 - songs/mercy-mercy-mercy.txt | 1 - songs/mingulay-boat-song.txt | 1 - songs/randy-dandy-o.txt | 1 - songs/roll-the-old-chariot-along.txt | 1 - songs/row-your-boat.txt | 1 - songs/south-australia.txt | 1 - songs/the-last-shanty.txt | 1 - songs/toss-a-coin-to-your-witcher.txt | 1 - songs/wellerman.txt | 1 - songs/whiskey-johnny.txt | 1 - src/index.pug | 385 +++++++++++++++++++------- 20 files changed, 286 insertions(+), 118 deletions(-) diff --git a/songs/all-for-me-grog.txt b/songs/all-for-me-grog.txt index 629a6e8..44b5a45 100644 --- a/songs/all-for-me-grog.txt +++ b/songs/all-for-me-grog.txt @@ -1,6 +1,5 @@ X: 1 T: All For Me Grog -%%vocalfont times 10 M: 4/4 L: 1/8 K: C diff --git a/songs/ballad-of-the-mer.txt b/songs/ballad-of-the-mer.txt index 0f6a0bd..3ef6632 100644 --- a/songs/ballad-of-the-mer.txt +++ b/songs/ballad-of-the-mer.txt @@ -1,5 +1,4 @@ T: Ballad of the Mer -%%vocalfont times 10 L:1/4 K: Eb M: 3/4 diff --git a/songs/bosun-bill.txt b/songs/bosun-bill.txt index 6f5c3f4..72bbfa4 100644 --- a/songs/bosun-bill.txt +++ b/songs/bosun-bill.txt @@ -1,6 +1,5 @@ X: 1 T: Bosun Bill -%%vocalfont times 10 M: 2/4 L: 1/16 K: Eb diff --git a/songs/bully-boys.txt b/songs/bully-boys.txt index 8559f67..8007fe9 100644 --- a/songs/bully-boys.txt +++ b/songs/bully-boys.txt @@ -1,6 +1,5 @@ X: 1 T: Bully Boys -%%vocalfont times 10 M: 6/8 K: C Q: 1/4=140 diff --git a/songs/bully-in-the-alley.txt b/songs/bully-in-the-alley.txt index 2e8523c..0ad9e42 100644 --- a/songs/bully-in-the-alley.txt +++ b/songs/bully-in-the-alley.txt @@ -1,6 +1,5 @@ X: 1 T: Bully in the Alley -%%vocalfont times 10 K: G M: 4/4 Q: 1/4=150 diff --git a/songs/drunken-sailor.txt b/songs/drunken-sailor.txt index d9cfadb..2ab4883 100644 --- a/songs/drunken-sailor.txt +++ b/songs/drunken-sailor.txt @@ -1,5 +1,4 @@ T: Drunken Sailor -%%vocalfont times 10 K: Dm M: 4/4 "Dm"a2 aa a2 aa | a2 d2 f2 a2 | "C"g2 gg g2 gg | g2 c2 e2 g2 | diff --git a/songs/health-to-the-company.txt b/songs/health-to-the-company.txt index 03b1696..f7a273d 100644 --- a/songs/health-to-the-company.txt +++ b/songs/health-to-the-company.txt @@ -1,5 +1,4 @@ T: Health to the Company -%%vocalfont times 10 M: 3/4 L: 1/8 Q: 1/4=110 diff --git a/songs/joli-rouge.txt b/songs/joli-rouge.txt index 1fb48d3..d7d43ea 100644 --- a/songs/joli-rouge.txt +++ b/songs/joli-rouge.txt @@ -1,6 +1,5 @@ X: 1 T: Joli Rouge -%%vocalfont times 10 M: 6/8 K: Dm "Dm" D3 [F2A] [FA] | "Am" A,3 [C3E] | "Dm" D3 [F2A] [FA] | "Am" A,3 [C3E] | "Dm" D3 [F2A] [FA] | "Am" A,3 [C3EG] | diff --git a/songs/leave-her-johnny.txt b/songs/leave-her-johnny.txt index bf6d574..d2880af 100644 --- a/songs/leave-her-johnny.txt +++ b/songs/leave-her-johnny.txt @@ -1,5 +1,4 @@ T: Leave Her Johnny -%%vocalfont times 10 K: C M: 4/4 cd | "C"e2 e2 e2 cd | e2 d2 c4 | "G"d2 d2 d3 c | "C"e2 g4 diff --git a/songs/mercy-mercy-mercy.txt b/songs/mercy-mercy-mercy.txt index eb349ed..2d9b41c 100644 --- a/songs/mercy-mercy-mercy.txt +++ b/songs/mercy-mercy-mercy.txt @@ -1,5 +1,4 @@ T: Mercy, Mercy, Mercy -%%vocalfont times 10 K: F M: 4/4 "C7" z2 A G2 "C7/E" EEC | "F" DCCA, "G7sus" C2 D2 diff --git a/songs/mingulay-boat-song.txt b/songs/mingulay-boat-song.txt index b39b579..b49e5d2 100644 --- a/songs/mingulay-boat-song.txt +++ b/songs/mingulay-boat-song.txt @@ -1,5 +1,4 @@ T: Mingulay Boat Song -%%vocalfont times 10 M: 3/4 Q: 1/4=140 K: G diff --git a/songs/randy-dandy-o.txt b/songs/randy-dandy-o.txt index 1c07669..4e8605b 100644 --- a/songs/randy-dandy-o.txt +++ b/songs/randy-dandy-o.txt @@ -1,5 +1,4 @@ T: Randy Dandy-O -%%vocalfont times 10 K: C M: 6/8 L: 1/16 diff --git a/songs/roll-the-old-chariot-along.txt b/songs/roll-the-old-chariot-along.txt index 6c9b04a..711e479 100644 --- a/songs/roll-the-old-chariot-along.txt +++ b/songs/roll-the-old-chariot-along.txt @@ -1,5 +1,4 @@ T: Roll the Old Chariot Along -%%vocalfont times 10 K: Dm M: 4/4 Q: 1/4=140 diff --git a/songs/row-your-boat.txt b/songs/row-your-boat.txt index ba32e2c..de15f82 100644 --- a/songs/row-your-boat.txt +++ b/songs/row-your-boat.txt @@ -1,5 +1,4 @@ T: Row Row Row Your Boat -%%vocalfont times 10 K: C M: 6/8 | C3 C3 | C2 D E3 | E2 D E2 F | G6 | diff --git a/songs/south-australia.txt b/songs/south-australia.txt index ab53f11..660ecdc 100644 --- a/songs/south-australia.txt +++ b/songs/south-australia.txt @@ -1,5 +1,4 @@ T: South Australia -%%vocalfont times 10 M: 4/4 K: E P: Part A diff --git a/songs/the-last-shanty.txt b/songs/the-last-shanty.txt index 562cec2..7af4500 100644 --- a/songs/the-last-shanty.txt +++ b/songs/the-last-shanty.txt @@ -1,6 +1,5 @@ X: 1 T: The Last Shanty -%%vocalfont times 10 K: A F E "D"D D D E D A, A, D D D E D w: Well me fa-ther oft-en told me when I was just a lad diff --git a/songs/toss-a-coin-to-your-witcher.txt b/songs/toss-a-coin-to-your-witcher.txt index fa28d88..4f5e112 100644 --- a/songs/toss-a-coin-to-your-witcher.txt +++ b/songs/toss-a-coin-to-your-witcher.txt @@ -1,5 +1,4 @@ T: Toss a Coin to Your Witcher -%%vocalfont times 10 K: Db M:4/4 "Bbm" z4 DCB,A, | "Eb" B,4 DEDC | diff --git a/songs/wellerman.txt b/songs/wellerman.txt index b49e5a5..54a902e 100644 --- a/songs/wellerman.txt +++ b/songs/wellerman.txt @@ -1,6 +1,5 @@ X: 1 T: Wellerman -%%vocalfont times 10 M: 4/4 L: 1/8 K: Eb diff --git a/songs/whiskey-johnny.txt b/songs/whiskey-johnny.txt index ff9976a..29e9dad 100644 --- a/songs/whiskey-johnny.txt +++ b/songs/whiskey-johnny.txt @@ -1,6 +1,5 @@ X: 1 T: Whiskey Johnny -%%vocalfont times 10 M: 4/4 L: 1/4 K: A diff --git a/src/index.pug b/src/index.pug index 5a46ad6..7cda8fa 100644 --- a/src/index.pug +++ b/src/index.pug @@ -7,51 +7,171 @@ append head script: include bootstrap.bundle.min.js style: include bootstrap.min.css style. - #abc { - resize: both; - height: 10em; - width: 100%; - font-family: monospace; + :root { --radius: 8px } + * { box-sizing: border-box } + body { + margin: 0; + color: #212529; + background: var(--page-bg); + /* ---- theme: soft (default) ---- */ + --bar-bg: #f1f3f5; + --bar-border: #dfe3e9; + --bar-shadow: 0 1px 3px rgba(16,24,40,.10), 0 1px 2px rgba(16,24,40,.06); + --track-bg: #e4e6ec; + --seg-fg: #5b636f; + --seg-active-bg: #1a73e8; + --seg-active-fg: #ffffff; + --seg-active-shadow: 0 1px 2px rgba(26,115,232,.35); + --btn-bg: #ffffff; + --btn-fg: #495159; + --btn-border: #d3d8de; + --btn-hover-bg: #f1f3f6; + --accent: #1a73e8; + --primary-fg: #ffffff; + --page-bg: #ffffff; + --edit-bg: #f1f3f5; + --edit-fg: #2a2f36; + --ta-bg: #ffffff; + --ta-fg: #24292f; + --ta-border: #d3d8de; + --link: #1a63d6; + --muted: #6b727c; + } + body.theme-nautical { + --bar-bg: #12314f; + --bar-border: #0f2a45; + --bar-shadow: 0 2px 8px rgba(0,0,0,.30); + --track-bg: #1b466c; + --seg-fg: #cdd9e5; + --seg-active-bg: #e7b24a; + --seg-active-fg: #14293d; + --seg-active-shadow: none; + --btn-bg: #173d61; + --btn-fg: #cdd9e5; + --btn-border: #2a557d; + --btn-hover-bg: #1d4a70; + --accent: #e7b24a; + --primary-fg: #14293d; + --page-bg: #ffffff; + --edit-bg: #12314f; + --edit-fg: #cdd9e5; + --ta-bg: #0a1f33; + --ta-fg: #e8eef4; + --ta-border: #2a557d; + --link: #8fc0ff; + --muted: #9fb3c6; } - body { padding: 1em } + + /* ---- docked top bar ---- */ + #toolbar { + position: sticky; top: 0; z-index: 1020; + display: flex; flex-wrap: wrap; align-items: center; gap: .45rem; + padding: .5rem .8rem; + background: var(--bar-bg); + border-bottom: 1px solid var(--bar-border); + box-shadow: var(--bar-shadow); + } + #stage { padding: 1rem .9rem 4rem } #paper { width: 100% } .item { white-space: nowrap } + #verses { display: none; margin-top: 1rem } + #verses p { margin-bottom: .8rem } + /* staff hidden: keep #paper width (abcjs is responsive) but collapse its + height. abcjs sets an inline padding-bottom aspect-ratio -> !important. */ + body.no-staff #paper { height: 0 !important; padding-bottom: 0 !important; overflow: hidden } + body.no-staff #verses { display: block } - /* lean toolbar */ - #toolbar { gap: .45rem; margin-top: .6rem } - #toolbar .ico { - font-style: normal; - font-size: 1.05em; - line-height: 1; - vertical-align: -.05em; + /* ---- buttons ---- */ + #toolbar .btn { + display: inline-flex; align-items: center; gap: .35rem; + font-size: .82rem; line-height: 1; + padding: .36rem .6rem; + color: var(--btn-fg); + background: var(--btn-bg); + border: 1px solid var(--btn-border); + border-radius: var(--radius); + box-shadow: none; } - #toolbar .btn .bi { vertical-align: -.15em } - #toolbar .btn > .ico, - #toolbar .btn > .bi { margin-right: .3em } + #toolbar .btn:hover:not(.active):not(.disabled) { background: var(--btn-hover-bg); color: var(--btn-fg) } + #toolbar .btn:focus, #toolbar .btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; box-shadow: none } + #toolbar .btn-primary { + color: var(--primary-fg); background: var(--accent); + border-color: var(--accent); font-weight: 600; + } + #toolbar .btn-primary:hover { color: var(--primary-fg); background: var(--accent); filter: brightness(.96) } #toolbar #songLabel { - display: inline-block; - max-width: 45vw; - overflow: hidden; - text-overflow: ellipsis; - vertical-align: bottom; - white-space: nowrap; + display: inline-block; max-width: 42vw; + overflow: hidden; text-overflow: ellipsis; + white-space: nowrap; vertical-align: bottom; } + + /* ---- segmented toggle groups (soft grey track) ---- */ + #toolbar .btn-group-toggle { + background: var(--track-bg); + border-radius: var(--radius); + padding: 3px; + gap: 3px; + } + #toolbar .btn-group-toggle .btn { + border: none !important; + margin: 0 !important; + border-radius: calc(var(--radius) - 3px) !important; + background: var(--btn-bg); + color: var(--seg-fg); + } + #toolbar .btn-group-toggle .btn:hover:not(.active):not(.disabled) { background: var(--btn-hover-bg); color: var(--seg-fg) } + #toolbar .btn-group-toggle .btn.active { + background: var(--seg-active-bg); + color: var(--seg-active-fg); + box-shadow: var(--seg-active-shadow); + } + #toolbar .btn-group-toggle .btn.disabled { opacity: .4 } + #toolbar .dropdown-menu { max-height: 60vh; overflow-y: auto } #key-menu { min-width: 7rem } - /* staff hidden: keep #paper width (abcjs is responsive) but collapse its height. - abcjs sets an inline padding-bottom aspect-ratio, so override it with !important. */ - body.no-staff #paper { height: 0 !important; padding-bottom: 0 !important; overflow: hidden } - #verses { display: none; margin-top: 1rem } - #verses p { margin-bottom: .8rem } - body.no-staff #verses { display: block } + /* ---- line-art icons ---- */ + .ico { + width: 18px; height: 18px; flex: 0 0 auto; + fill: none; stroke: currentColor; stroke-width: 1.7; + stroke-linecap: round; stroke-linejoin: round; + vertical-align: -3px; + } - /* advanced panel (ABC editing) */ - #advanced { display: none; margin-top: 1rem } - #advanced > * { margin-bottom: .8rem } + /* ---- docked, collapsible bottom edit bar ---- */ + #advanced { + position: fixed; left: 0; right: 0; bottom: 0; z-index: 1030; + background: var(--edit-bg); color: var(--edit-fg); + border-top: 2px solid var(--accent); + box-shadow: 0 -4px 18px rgba(16,24,40,.16); + max-height: 80vh; overflow-y: auto; + } + #advanced .adv-header { + display: flex; align-items: center; justify-content: space-between; + gap: .5rem; padding: .5rem .9rem; + cursor: pointer; user-select: none; + font-size: .85rem; font-weight: 600; + } + #advanced .adv-title { display: inline-flex; align-items: center; gap: .45rem } + #advanced .adv-chevron { transition: transform .18s ease; opacity: .8 } + #advanced.open .adv-chevron { transform: rotate(180deg) } + #advBody { display: none; padding: 0 .9rem .9rem } + #advanced.open #advBody { display: block } + #advBody > * { margin-bottom: .7rem } + #advBody a { color: var(--link) } + #advBody #warnings { color: var(--muted); font-family: monospace; font-size: .85rem; margin-bottom: 0 } + #advBody .adv-version { color: var(--muted); font-size: .8rem; margin: .2rem 0 0 } + #abc { + resize: vertical; height: 9em; width: 100%; + font-family: monospace; font-size: .85rem; + background: var(--ta-bg); color: var(--ta-fg); + border: 1px solid var(--ta-border); border-radius: 6px; + padding: .5rem .6rem; + } @media print { .noprint { display: none !important } + #stage { padding: 0 } } append body @@ -64,11 +184,68 @@ append body else path(d=p.d) + //- monochrome line-art icon referencing the sprite below + mixin icon(id) + svg.ico(viewBox="0 0 24 24" aria-hidden="true" focusable="false") + use(href="#i-" + id) + + //- apply the saved colour theme early to avoid a flash of the default + script. + try { document.body.classList.add('theme-' + (localStorage.getItem('shanties-theme') || 'soft')); } catch (e) {} + + //- line-art icon sprite + svg(width="0" height="0" style="position:absolute" aria-hidden="true") + defs + symbol#i-note(viewBox="0 0 24 24") + path(d="M9 18V5l12-2v13") + circle(cx="6" cy="18" r="3") + circle(cx="18" cy="16" r="3") + symbol#i-book(viewBox="0 0 24 24") + path(d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20") + path(d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z") + symbol#i-staff(viewBox="0 0 24 24") + path(d="M3 6h18M3 10h18M3 14h18M3 18h18") + circle(cx="8" cy="10" r="1.5" fill="currentColor" stroke="none") + circle(cx="15" cy="14" r="1.5" fill="currentColor" stroke="none") + symbol#i-palette(viewBox="0 0 24 24") + path(d="M12 2a10 10 0 1 0 0 20 1.7 1.7 0 0 0 1.7-1.7 1.7 1.7 0 0 0-.45-1.15 1.7 1.7 0 0 1 1.25-2.85H17a5 5 0 0 0 5-5c0-4.42-4.48-8-10-8z") + circle(cx="7.5" cy="11" r="1.15" fill="currentColor" stroke="none") + circle(cx="12" cy="7.5" r="1.15" fill="currentColor" stroke="none") + circle(cx="16.5" cy="11" r="1.15" fill="currentColor" stroke="none") + symbol#i-type(viewBox="0 0 24 24") + path(d="M4 7V4h16v3") + path(d="M9 20h6") + path(d="M12 4v16") + symbol#i-mic(viewBox="0 0 24 24") + rect(x="9" y="2" width="6" height="12" rx="3") + path(d="M5 10v2a7 7 0 0 0 14 0v-2") + path(d="M12 19v3") + path(d="M8 22h8") + symbol#i-trumpet(viewBox="0 0 24 24") + path(d="M2 10.5h13l5-3v9l-5-3H2z") + path(d="M6 10.5V8M9.5 10.5V8M13 10.5V8") + symbol#i-guitar(viewBox="0 0 24 24") + circle(cx="8" cy="16" r="5.3") + circle(cx="8" cy="16" r="1.5" fill="currentColor" stroke="none") + path(d="M11.9 12.2 18 6.1") + path(d="M16.4 4.3l3.3 3.3-1.7 1.7-3.3-3.3z") + symbol#i-arrows(viewBox="0 0 24 24") + path(d="M8 21V4M4 8l4-4 4 4") + path(d="M16 3v17M12 16l4 4 4-4") + symbol#i-contrast(viewBox="0 0 24 24") + circle(cx="12" cy="12" r="9") + path(d="M12 3a9 9 0 0 1 0 18z" fill="currentColor" stroke="none") + symbol#i-pencil(viewBox="0 0 24 24") + path(d="M12 20h9") + path(d="M16.5 3.5a2.12 2.12 0 0 1 3 3L7 19l-4 1 1-4 12.5-12.5z") + symbol#i-chevron(viewBox="0 0 24 24") + path(d="M6 15l6-6 6 6") + #toolbar.noprint.d-flex.flex-wrap.align-items-center //- Song picker (primary action) .dropdown button.btn.btn-primary.dropdown-toggle#songFile(type="button" data-toggle="dropdown" title="Choose a song") - span.ico 🎶 + +icon('note') span#songLabel Pick a song .dropdown-menu#song-menu(aria-labelledby="songFile") - var keys = Object.keys(src['by-title.json']) @@ -76,65 +253,79 @@ append body each k in keys a.dropdown-item(href="#")= k + //- Songbook PDF / QR (grouped with song selection) + button.btn.btn-sm#songbookBtn(type="button" data-toggle="modal" data-target="#songbookModal" title="Songbook PDF & QR code") + +icon('book') + //- Staff + note options .btn-group.btn-group-toggle.btn-group-sm#staffToggles(data-toggle="buttons") - label.btn.btn-outline-secondary.active(title="Show the music staff") + label.btn.active(title="Show the music staff") input#show-staff(type="checkbox" checked autocomplete="off") - span.ico 🎼 - | Staff - label.btn.btn-outline-secondary.active(title="Color notes by pitch") + +icon('staff') + span Staff + label.btn.active(title="Color notes by pitch") input#show-notecolors(type="checkbox" checked autocomplete="off") - span.ico 🎨 - | Color - label.btn.btn-outline-secondary.active(title="Label notes with letter names") + +icon('palette') + span Color + label.btn.active(title="Label notes with letter names") input#show-notelabels(type="checkbox" checked autocomplete="off") - span.ico 🔤 - | Labels + +icon('type') + span Labels //- Lyrics & instrument layers .btn-group.btn-group-toggle.btn-group-sm#viewToggles(data-toggle="buttons") - label.btn.btn-outline-secondary.active(title="Show lyrics") + label.btn.active(title="Show lyrics") input#show-lyrics(type="checkbox" checked autocomplete="off") - span.ico 🗣️ - | Lyrics - label.btn.btn-outline-secondary(title="Show trumpet fingering") + +icon('mic') + span Lyrics + label.btn(title="Show trumpet fingering") input#show-trumpet(type="checkbox" autocomplete="off") - span.ico 🎺 - | Trumpet - label.btn.btn-outline-secondary(title="Show guitar tab") + +icon('trumpet') + span Trumpet + label.btn(title="Show guitar tab") input#show-gtab(type="checkbox" autocomplete="off") - span.ico 🎸 - | Guitar + +icon('guitar') + span Guitar //- Transpose: pick the destination key (offset shown) - .dropdown - button.btn.btn-outline-secondary.btn-sm.dropdown-toggle#keyBtn(type="button" data-toggle="dropdown" title="Transpose: choose a key") - +bi([{fr:'evenodd',d:'M11.5 15a.5.5 0 0 0 .5-.5V2.707l3.146 3.147a.5.5 0 0 0 .708-.708l-4-4a.5.5 0 0 0-.708 0l-4 4a.5.5 0 1 0 .708.708L11 2.707V14.5a.5.5 0 0 0 .5.5zm-7-14a.5.5 0 0 1 .5.5v11.793l3.146-3.147a.5.5 0 0 1 .708.708l-4 4a.5.5 0 0 1-.708 0l-4-4a.5.5 0 0 1 .708-.708L4 13.293V1.5a.5.5 0 0 1 .5-.5z'}]) + .dropdown.ml-auto + button.btn.btn-sm.dropdown-toggle#keyBtn(type="button" data-toggle="dropdown" title="Transpose: choose a key") + +icon('arrows') span#keyLabel Key: – .dropdown-menu.dropdown-menu-right#key-menu(aria-labelledby="keyBtn") - //- Songbook PDF / QR (document dialog) - button.btn.btn-outline-secondary.btn-sm.ml-auto#songbookBtn(type="button" data-toggle="modal" data-target="#songbookModal" title="Songbook PDF & QR code") - span.ico 📄 + //- Colour theme + .dropdown#themeWrap + button.btn.btn-sm.dropdown-toggle#themeBtn(type="button" data-toggle="dropdown" title="Color theme") + +icon('contrast') + .dropdown-menu.dropdown-menu-right#theme-menu(aria-labelledby="themeBtn") + a.dropdown-item(href="#" data-theme="soft") Soft + a.dropdown-item(href="#" data-theme="nautical") Nautical - //- Edit the ABC source - button.btn.btn-outline-secondary.btn-sm#advancedToggle(type="button" title="Edit ABC notation" aria-pressed="false") - span.ico 🖊️ - - #paper - - #verses + #stage + #paper + #verses #advanced.noprint - .item - span Enter some - a(href="https://github.com/brewingcode/shanties/blob/master/README.md" target="_blank") ABC notation - span , or - a(href="https://github.com/brewingcode/shanties/tree/master/songs") - +bi([{d:'M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.012 8.012 0 0 0 16 8c0-4.42-3.58-8-8-8z'}]) - span add a song - textarea#abc(spellcheck="false") - #warnings + .adv-header#advToggle + span.adv-title + +icon('pencil') + span Edit ABC notation + svg.ico.adv-chevron(viewBox="0 0 24 24" aria-hidden="true" focusable="false") + use(href="#i-chevron") + #advBody + .item + span Enter some + a(href="https://github.com/brewingcode/shanties/blob/master/README.md" target="_blank") ABC notation + span , or + a(href="https://github.com/brewingcode/shanties/tree/master/songs") + +bi([{d:'M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.012 8.012 0 0 0 16 8c0-4.42-3.58-8-8-8z'}]) + span add a song + textarea#abc(spellcheck="false") + #warnings + .adv-version + span version + a(href="https://github.com/brewingcode/shanties/commit/" + src['GIT_HEAD'])= src['GIT_HEAD'] //- Songbook PDF + QR code dialog #songbookModal.modal.fade.noprint(tabindex="-1" role="dialog" aria-labelledby="songbookModalLabel" aria-hidden="true") @@ -148,10 +339,7 @@ append body p Download the printable songbook: Songbook.pdf p.text-muted or scan to open it on another device: img(src="qr-code.svg" alt="Songbook.pdf QR code" width="200" height="200") - .modal-footer.justify-content-center - small.text-muted - span version - a(href="https://github.com/brewingcode/shanties/commit/" + src['GIT_HEAD'])= src['GIT_HEAD'] + script. var songs = !{JSON.stringify(src['songs.json'])}; var byTitle = !{JSON.stringify(src['by-title.json'])}; @@ -239,7 +427,7 @@ append body else return true .join('\n') - directives = '' + directives = '%%vocalfont times 10\n' directives += '%%notecolors 1\n' if $('#show-notecolors').is(':checked') directives += '%%notelabels 1\n' if $('#show-notelabels').is(':checked') window.editor.editarea.setString directives + s @@ -258,18 +446,6 @@ append body params.set 'title', title window.history.replaceState {}, '', "#{window.location.pathname}?#{params}" - addEditButton = -> - $('#advanced > .edit-btn').remove() - btn = $('') - btn.on 'click', -> - btn.remove() - $('#abc').prop('disabled', false) - .focus() - .on 'blur', -> - $('#abc').prop 'disabled', true - addEditButton() - $('#advanced').prepend btn - window.onload = -> window.editor = new ABCJS.Editor 'abc', canvas_id: 'paper', @@ -308,14 +484,30 @@ append body tablature: if $(this).is(':checked') [{ instrument: "guitar", - label: "Guitar (%T)", + label: "", tuning: ["E,", "A,", "D", "G", "B", "e"], }] } - $('#advancedToggle').on 'click', -> - shown = $('#advanced').toggle().is(':visible') - $(this).toggleClass('active', shown).attr 'aria-pressed', shown + $('#advToggle').on 'click', -> + $('#advanced').toggleClass 'open' + + applyTheme = (name) -> + name = if name is 'nautical' then 'nautical' else 'soft' + $('body').removeClass('theme-soft theme-nautical').addClass "theme-#{name}" + try + localStorage.setItem 'shanties-theme', name + $('#theme-menu .dropdown-item').each -> + $(this).toggleClass 'active', $(this).attr('data-theme') is name + + saved = 'soft' + try + saved = localStorage.getItem('shanties-theme') or 'soft' + applyTheme saved + + $('#theme-menu a.dropdown-item').click (e) -> + e.preventDefault() + applyTheme $(this).attr('data-theme') params = new URLSearchParams(window.location.search) file = params.get('file') @@ -330,9 +522,4 @@ append body setSong "B c d e | ff | c'd' | EE E | =D^D" if params.get('advanced') is 'true' - $('#advanced').show() - $('#advancedToggle').addClass('active').attr 'aria-pressed', true - - if navigator.userAgent.match /i(Pad|Phone)/i - $('#abc').prop 'disabled', true - addEditButton() + $('#advanced').addClass 'open'