JSFiddle - React, Tailwind, and code Playground
by Ryan Duffy
HTML
<!--
verse 1
D Bm Em7 A9 Em7 D Bm7 Em7
At last my love has come along,
A7+ A7 D Bm7 Em7
My lonely days are over
Gdim A7 D Bm Gdim A9
And life is like a song.
verse 2
A7 D Bm Em7 A9 Em7 D Bm7 Em7
At last the skies above are blue;
A7+ A7 D Bm7 Em7
My heart was wrapped in clover
Gdim A7 D Gm Gdim D
The night I looked at you.
Bridge
A7 D7 G7+ Gdim DM7 D6
I found a dream that I can speak to,
C+ Bm6 Fdim F#m
A dream that I can call my own,
Bm6 Dm6 E7 AM7 A6
I found a thrill to press my cheek to,
D Bm7 Cdim A Em7 A7
A thrill I've never known.
verse 3
A7 D Bm Em7 A9 Em7 D Bm7 Em7
You smiled and then the spell was cast,
A7+ A7 D Bm7 Em7
And here we are in heaven,
Gdim A7 D Bm Em Gdim (A7)
For you are mine at last.
Gdim A7 D6 Gm Gdim D6
(last time) For you are mine at last.
-->
CSS
textarea {
height:200px;
width:300px;
}
JavaScript
enyo.kind({
name:"com.tiqtech.accord.Parser",
kind:"Component",
parseDelay:null,
re:{
chord:/([A-G][#b]?(add|aug|dim|m|maj|min|sus)?\d{0,2}\+?(\/[A-G][#b]?)?)/ig,
chords:/^\s*([A-G][#b]?(add|aug|dim|m|maj|min|sus)?\d{0,2}\+?(\/[A-G][#b]?)?\s*)+(\(.*\))?$/ig,
section:/^(chorus|intro|introduction|bridge|pre\-?chorus|verse(\s+\d)?|break|instrumental)\s*(\(.*\))?$/ig
},
published:{
value:""
},
events:{
onParseComplete:""
},
valueChanged:function() {
if(this.parseDelay) clearTimeout(this.parseDelay);
this.parseDelay = setTimeout(enyo.bind(this, "parse"), 400);
},
parse:function() {
this.parseDelay = undefined;
var lines = this.value.split("\n");
this.nextLine(lines);
},
nextLine:function(remaining, parsed) {
if(this.parseDelay) return; // kick out if user has typed
parsed = parsed || [];
if(remaining.length === 0) {
this.parseComplete(parsed);
} else {
enyo.asyncMethod(this, "processLine", remaining, parsed);
}
},
parseComplete:function(parsed) {
if(!parsed || parsed.length === 0) return;
var song = [],
sections = [],
buffer = null;
for(var i in parsed) {
var p = parsed[i];
if(!(p.type && p.value)) continue;
switch(p.type) {
case "section":
song.push({name:p.value, content:[]});
break;
case "chord":
if(buffer) {
song[song.length-1].content.push(this.multiplex("", buffer));
}
buffer = p.value;
break;
case "text":
song[song.length-1].content.push(this.multiplex(p.value, buffer));
buffer = null;
...