Skip to content

Commit

Permalink
Replace custom parser with ChordSheetJS parser
Browse files Browse the repository at this point in the history
  • Loading branch information
woshibiantai committed Jul 21, 2024
1 parent 4303c9b commit ab53200
Show file tree
Hide file tree
Showing 8 changed files with 219 additions and 70 deletions.
17 changes: 17 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"format": "prettier --write src/"
},
"dependencies": {
"chordsheetjs": "10.1.0",
"vue": "^3.4.29",
"vue-router": "^4.3.3"
},
Expand Down
96 changes: 26 additions & 70 deletions src/components/ChordChart.vue
Original file line number Diff line number Diff line change
Expand Up @@ -26,24 +26,19 @@
class="chordchart-body"
:style="{ '--chordchart-columns': columns }"
>
<div
class="chordchart-body-stanza"
v-for="(stanza, index) in stanzas"
<ChordChartBodyParagraph
v-for="(paragraph, index) in bodyParagraphs"
:key="index"
>
<ChordChartBodyLine
v-for="(line, index) in stanza"
:key="index"
:line="line"
/>
</div>
:paragraph="paragraph"
/>
</div>
</section>
</template>

<script setup>
import { computed, inject } from 'vue';
import ChordChartBodyLine from './ChordChartBodyLine.vue';
import { computed, inject, ref, watch } from 'vue';
import { ChordProParser, Song } from 'chordsheetjs';
import ChordChartBodyParagraph from './ChordChartBodyParagraph.vue';
defineProps({
columns: {
Expand All @@ -52,60 +47,26 @@ defineProps({
},
});
const chordProInput = inject('chordProInput');
const lines = computed(() => chordProInput.value.split('\n'));
const artist = computed(computeArtist);
const bodyLines = computed(computeBodyLines);
const key = computed(computeKey);
const stanzas = computed(computeStanzas);
const tempo = computed(computeTempo);
const time = computed(computeTime);
const title = computed(computeTitle);
function computeArtist() {
const artistLine = lines.value.find(line => line.startsWith('{artist:')) || '';
return artistLine.replace('{artist:', '').replace('}', '');
}
function computeBodyLines() {
return lines.value.filter(line => (!line.startsWith('{') || line.startsWith('{comment:')));
}
function computeKey() {
const keyLine = lines.value.find(line => line.startsWith('{key:')) || '';
return keyLine.replace('{key:', '').replace('}', '');
}
function computeStanzas() {
return bodyLines.value.reduce((acc, line, index) => {
if (index === 0) {
acc.push(line.trim() === '' ? [] : [line]); // Start first stanza
} else if (line.trim() === '') {
if (acc[acc.length - 1].length === 0) {
return acc; // Skip if previous stanza was empty
}
acc.push([]); // Start new stanza
} else {
acc[acc.length - 1].push(line); // Add line to current stanza
}
return acc;
}, []);
}
function computeTempo() {
const tempoLine = lines.value.find(line => line.startsWith('{tempo:')) || '';
return tempoLine.replace('{tempo:', '').replace('}', '');
}
function computeTime() {
const timeLine = lines.value.find(line => line.startsWith('{time:')) || '';
return timeLine.replace('{time:', '').replace('}', '');
}
function computeTitle() {
const titleLine = lines.value.find(line => line.startsWith('{title:')) || '';
return titleLine.replace('{title:', '').replace('}', '');
}
const chordProInput = inject('chordProInput');
const parser = new ChordProParser();
const song = ref(new Song());
const metadata = computed(() => song.value.metadata);
const artist = computed(() => metadata.value.get('artist'));
const bodyParagraphs = computed(() => song.value.bodyParagraphs);
const key = computed(() => metadata.value.get('key'));
const tempo = computed(() => metadata.value.get('tempo'));
const time = computed(() => metadata.value.get('time'));
const title = computed(() => metadata.value.get('title'));
watch(chordProInput, (newValue) => {
try {
song.value = parser.parse(newValue);
} catch(err) {
console.error(err);
}
}, { immediate: true });
</script>

<style scoped>
Expand Down Expand Up @@ -140,9 +101,4 @@ h1 {
.chordchart-body {
column-count: var(--chordchart-columns);
}
.chordchart-body-stanza {
break-inside: avoid;
padding-top: 1em;
}
</style>
28 changes: 28 additions & 0 deletions src/components/ChordChartBodyParagraph.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<template>
<div class="chordchart-body-paragraph">
<ChordChartLine
v-for="(line, index) in props.paragraph.lines"
:key="index"
:line="line"
/>
</div>
</template>

<script setup>
import { Paragraph } from 'chordsheetjs';
import ChordChartLine from './ChordChartLine.vue';
const props = defineProps({
paragraph: {
type: Paragraph,
required: true,
}
});
</script>

<style scoped>
.chordchart-body-paragraph {
break-inside: avoid;
padding-top: 1em;
}
</style>
50 changes: 50 additions & 0 deletions src/components/ChordChartChordLyricsPair.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<template>
<span class="chordchart-chord-lyrics-pair">
<code class="chordchart-chords">
{{ pair.chords }}
</code>
<span class="chordchart-lyrics">
{{ pair.lyrics }}
</span>
</span>
</template>

<script setup>
import { ChordLyricsPair } from 'chordsheetjs';
defineProps({
pair: {
type: ChordLyricsPair,
required: true,
}
});
</script>

<style scoped>
.chordchart-chord-lyrics-pair {
align-items: flex-start;
display: inline-flex;
flex-direction: column;
margin-top: .2em;
&:first-of-type {
margin-left: 2em;
}
}
.chordchart-chords {
font-family: inherit;
font-size: 1em;
font-weight: bold;
height: 1.1em;
line-height: 1.1em;
padding-right: .4em;
white-space: pre-wrap;
}
.chordchart-lyrics {
font-size: 1em;
height: 1.1em;
line-height: 1.1em;
}
</style>
33 changes: 33 additions & 0 deletions src/components/ChordChartLine.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<template>
<p class="chordchart-body-paragraph-line">
<ChordChartLineItem
v-for="(item, index) in line.items"
:key="index"
:item="item"
/>
</p>
</template>

<script setup>
import { Line } from 'chordsheetjs';
import ChordChartLineItem from './ChordChartLineItem.vue';
defineProps({
line: {
type: Line,
required: true,
}
});
</script>

<style scoped>
.chordchart-body-paragraph-line {
display: flex;
flex-wrap: wrap;
gap: .4em;
}
.chordchart-body-paragraph-line-verse {
margin-left: 2em;
}
</style>
25 changes: 25 additions & 0 deletions src/components/ChordChartLineItem.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<template>
<ChordChartTag
v-if="isTag"
:tag="item"
/>
<ChordChartChordLyricsPair
v-else
:pair="item"
/>
</template>

<script setup>
import { ChordLyricsPair, Tag } from 'chordsheetjs';
import ChordChartChordLyricsPair from './ChordChartChordLyricsPair.vue';
import ChordChartTag from './ChordChartTag.vue';
const props = defineProps({
item: {
type: [ChordLyricsPair, Tag],
required: true,
}
});
const isTag = props.item instanceof Tag && props.item.hasValue();
</script>
39 changes: 39 additions & 0 deletions src/components/ChordChartTag.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<template>
<span
v-if="isKeychange"
class="chordchart-tag chordchart-keychange"
>
Key - {{ tag.value }}
</span>
<span
v-else
class="chordchart-tag"
>
{{ tag.value }}
</span>
</template>

<script setup>
import { Tag } from 'chordsheetjs';
const props = defineProps({
tag: {
type: Tag,
required: true,
}
});
const isKeychange = props.tag.name === 'keychange';
</script>

<style scoped>
.chordchart-tag {
font-size: 1em;
font-weight: bold;
line-height: 2;
}
.chordchart-keychange {
display: block;
margin-left: auto;
}
</style>

0 comments on commit ab53200

Please sign in to comment.