ChordSheetJS icon indicating copy to clipboard operation
ChordSheetJS copied to clipboard

Custom HtmlFormatter

Open hkfuertes opened this issue 10 months ago • 2 comments

Hello I just want to extend the functionality to create a custom formatter... can I do that without monkey patching? Or should I create a pr? (maybe when I have this running I will).

I run (and made) this website (spanish catholic songbook, doceacordes.es) and I started with a hand made tables formatter, but a year ago I found a more "elegant" way of doing this.

<!-- [c]esto es un[d]a pru[em]eba. -->
<div class="position-relative pt-3">
  <span class="lyric chord none" data-chord="C">esto </span>
  <span class="none"> es un </span>
  <span class="lyric chord none" data-chord="D">a </span>
  <span class="none"> pru </span>
  <span class="lyric chord none" data-chord="em">eba.</span>
  <br>
</div>

And the matching styles:

.chorus { font-weight: bold; }
.lyric { line-height: 2.7; white-space: pre;  }

.chord {
  position: relative;
  display: inline-block;
}

.chord:before {
  content: attr(data-chord); /*<---- this is the key element!*/
  position: absolute;
  top: -1rem;
  color: #001f3f;
}

Again I was doing all the key changes and parsing and everyting myself, but I just came across this awesome library and I plan on using it. I already have a proof of concept preact component using this library and "my" formatter... but I wanted to follow your conventions and thats why I asked if I can do that or if I need to open a PR (wich eventually I think I will...)

I also posted my solution here for if it can help anyone or if any admin wants to make the formatter.

hkfuertes avatar Apr 23 '24 05:04 hkfuertes

Hey @hkfuertes. Yes, it's actually quite easy to have your own custom formatter without issuing a PR. You can, for example, extend from HtmlDivFormatter.

To render the HTML, you can create a template based on the html_div_formatter template, use your own templating engine, or use basic logic.

The template function of your formatter needs return a function thats accepts a single argument of the type HtmlTemplateArgs and returns the rendered string.

import { ChordProParser, HtmlDivFormatter } from 'chordsheetjs';

function customTemplate({ configuration, song, renderBlankLines, bodyParagraphs }) {
  return '<div>...</div>';
}

class CustomFormatter extends HtmlDivFormatter {
  get template() {
    return customTemplate;
  }
}

const chordPro = '...';
const song = new ChordProParser().parse(chordPro);
const html = new CustomFormatter().format(song);

Please let me know if this answers your question. Feel free to follow up with any more questions!

martijnversluis avatar Apr 23 '24 06:04 martijnversluis

Oh thank you for the quick response. I will try to do that... first I copied over the HtmlDivFormatter to start modifying but by pulling the thread I saw that most (if not all) of the imports where relative.... and so I thought... there has to be an easier way... that's why I opened the issue..... and there is! hahahahaha, thank you!

I will try to get inspiration on what you already did to not use jsx for the templating.

Thank you again!

One other unrelated question or problem that I encounter is... as I'm an spanish site, all my chordpro are stored in European Notation, and also bad normalized ('DO' instead of 'Do' or 'do'), my bad... I will convert them to english as a laravel task in the backend.... anyway when I to a test with [Do]esto es un[Re]a pru[mim]eba. It gets rendered, but If I try to transpose it I get key errors.... I will investigate on my own :) If I have any specific issue I will open an issue then.

Thank you again for this awesome work!

hkfuertes avatar Apr 23 '24 07:04 hkfuertes