]> piware.de Git - chordpro-web.git/commitdiff
Render chorus sections
authorMartin Pitt <martin@piware.de>
Wed, 23 Sep 2026 21:28:17 +0000 (23:28 +0200)
committerMartin Pitt <martin@piware.de>
Wed, 23 Sep 2026 21:28:23 +0000 (23:28 +0200)
chordpro-web.js
chordpro.css

index 93a859aa95b70550150e879a9de84c55eb2cacef..a7914c193898d6b88b76f843671923a32cd91986 100644 (file)
@@ -86,17 +86,25 @@ directive_handlers.c = directive_handlers.comment;
 function renderChordpro(text) {
     const song = [];
     const chords = [];
+    let chorus = null; // content of the chorus being parsed, if any
     let verseLines = [];
     let verseHasChords = false;
 
     const flushVerse = () => {
         if (verseLines.length === 0)
             return;
-        song.push(html`<p class="verse${verseHasChords ? ' chords' : ''}">${verseLines}</p>`);
+        (chorus ?? song).push(html`<p class="verse${verseHasChords ? ' chords' : ''}">${verseLines}</p>`);
         verseLines = [];
         verseHasChords = false;
     };
 
+    const endChorus = () => {
+        if (chorus === null)
+            return;
+        song.push(html`<div class="chorus">${chorus}</div>`);
+        chorus = null;
+    };
+
     for (let line of text.split('\n')) {
         line = line.trim();
         if (line.startsWith('#'))
@@ -105,12 +113,20 @@ function renderChordpro(text) {
         const m = re_directive.exec(line);
         if (m) {
             flushVerse();
-            const [, directive, value] = m;
-            const handler = directive_handlers[directive];
-            if (handler)
-                song.push(handler(value ?? '', chords));
-            else
-                console.warn('unknown directive:', line);
+            const [, directive, value = ''] = m;
+            const target = chorus ?? song;
+            if (['start_of_chorus', 'soc'].includes(directive)) {
+                endChorus();
+                chorus = [];
+            } else if (['end_of_chorus', 'eoc'].includes(directive)) {
+                endChorus();
+            } else {
+                const handler = directive_handlers[directive];
+                if (handler)
+                    target.push(handler(value, chords));
+                else
+                    console.warn('unknown directive:', line);
+            }
         } else if (line === '') {
             flushVerse();
         } else {
@@ -134,6 +150,7 @@ function renderChordpro(text) {
         }
     }
     flushVerse();
+    endChorus();
     if (chords.length > 0)
         song.push(html`<div class="diagrams">${chords.map(chordDiagram)}</div>`);
 
index 628b0fd9629c63e8a1c277c980298653bf568825..09e370fa13df69f686c933b75ad6c7665254dbbc 100644 (file)
@@ -70,6 +70,11 @@ h2, .comment {
   white-space: pre-line;
 }
 
+.chorus {
+  border-left: 3px solid #39F;
+  padding-left: 0.7em;
+}
+
 /* A segment is one chord and the lyrics up to the next chord, stacked as two
    rows. Its width is the wider of the two, so chords can never overlap each
    other or the next segment. Line wrapping only happens between segments;