]> piware.de Git - chordpro-web.git/blob - chordpro-web.js
Add loading via URL
[chordpro-web.git] / chordpro-web.js
1 import { html, render } from 'https://cdn.pika.dev/lit';
2
3 const re_directive = /^{(\w+):\s*([^}]+)}$/;
4
5 const el_song = document.getElementById('song');
6 const song = [];
7
8 const directive_handlers = {
9     title: value => {
10         document.getElementById('title').textContent = value;
11         document.title = `${value} - ChordPro Web`;
12     },
13     subtitle: value => document.getElementById('artist').textContent = value,
14     comment: value => song.push(html`<p class="comment">${value}</p>`),
15 };
16
17 function renderChordpro(text) {
18     let verseLines = null;
19     let verseHasChords = false;
20     song.length = 0;
21
22     for (let line of text.split('\n')) {
23         line = line.trim();
24         if (line.startsWith('#'))
25             continue;
26
27         let m;
28         if ((m = re_directive.exec(line)) !== null) {
29             const [_, directive, value] = m;
30             const handler = directive_handlers[directive];
31             if (handler)
32                 handler(value);
33             else
34                 console.warn('unknown directive:', line);
35         } else if (line === '') {
36             if (verseLines == null)
37                 continue;
38             song.push(html`<p class="verse${verseHasChords ? ' chords' : ''}">${verseLines}</p>`);
39             verseLines = null;
40             verseHasChords = false;
41         } else {
42             if (verseLines == null)
43                 verseLines = [];
44
45             // split line into parts on chords
46             const parts = [];
47             line.split(/(\[[^\]]+\])/).forEach(part => parts.push(part[0] == '['
48                 ? html`<span class="chord">${part.slice(1, -1)}</span>`
49                 : (part ? html`<span class="text">${part}</span>` : null)
50             ));
51             verseHasChords ||= parts.length > 1;
52             parts.push('\n')
53             verseLines.push(parts);
54         }
55     }
56
57     render(song, el_song);
58 }
59
60 async function main() {
61     document.getElementById('open').addEventListener('change', async ev => renderChordpro(await ev.target.files[0].text()));
62
63     const params = new URLSearchParams(document.location.search);
64     const loadURL = params.get('l');
65     if (loadURL) {
66         try {
67             const response = await fetch(loadURL);
68             if (response.ok) {
69                 renderChordpro(await response.text());
70             } else {
71                 console.warn('Failed to fetch', loadURL, ':', response.status, response.statusText);
72             }
73         } catch (error) {
74             console.warn('Failed to fetch', loadURL, ':', error);
75         }
76     }
77 }
78
79 main();