martijnversluis / ChordSheetJS

A JavaScript library for parsing and formatting chords and chord sheets
https://github.com/users/martijnversluis/projects/4
GNU General Public License v2.0
318 stars 51 forks source link

Using `delegates.grid` option with specifically `HtmlDivFormatter` seems to strip HTML content returned? #1448

Closed edonv closed 4 days ago

edonv commented 4 days ago

I'm having a weird issue with specifically HtmlDivFormatter's delegates.grid option. I've written a function that outputs HTML as a string to use for grid sections and it just ends up outputting the content of that HTML but without any of the HTML wrapping of it.

I've also tried swapping out the formatter with the HtmlTableFormatter and it actually works as expected.

Also weird: as this is in a browser, I've been inspecting what my function returns before returning it for the delegates.grid callback, and it does return the full HTML content. But oddly enough, when I don't use my function but just return something simple like:

grid(input) {
    return `<span>${input}</span>`;
}

it outputs exactly correct.

Example

Delegate function input -> |: E . | A F#m7 . :| 2x

My function's HTML string output:

<tbody>
    <td class="grid-barline">|:</td>
    <td class="grid-cell chord">E</td>
    <td class="grid-cell"></td>
    <td class="grid-barline">|</td>
    <td class="grid-cell chord">A</td>
    <td class="grid-cell chord">F#m7</td>
    <td class="grid-cell"></td>
    <td class="grid-barline">:|</td>
    <td class="grid-margin-text">2x</td>
</tbody>

ChordProJS's output:

<div class="literal">|:E|AF#m7:|2x</div>

Expected output (note that I give div.literal display: table CSS styling):

<div class="literal">
    <tbody>
        <td class="grid-barline">|:</td>
        <td class="grid-cell chord">E</td>
        <td class="grid-cell"></td>
        <td class="grid-barline">|</td>
        <td class="grid-cell chord">A</td>
        <td class="grid-cell chord">F#m7</td>
        <td class="grid-cell"></td>
        <td class="grid-barline">:|</td>
        <td class="grid-margin-text">2x</td>
    </tbody>
</div>

When I try the exact same thing using HtmlTableFormatter, it actually outputs the expected content.

Additionally, weirdly enough, during my testing I accidentally tried the following (processing my generated output):

grid(input) {
    const output = gridHTMLFromGridContent(input);
    return gridHTMLFromGridContent(output);
}

Of course, this doesn't work right either, but it actually results in something with real HTML content.

Any idea why this could be happening? I'm hoping I'm just really missing something.

edonv commented 4 days ago

Sorry, I found the issue. Weirdly, it's not necessarily an issue with ChordProJS or with my code.

It turns out that if you try to programmatically add an HTML string into the document (using something like .innerHTML = __ or .insertAdjacentHTML('beforeend', __), and the HTML string contains any <tbody> elements that aren't each wrapped in a <table> element, it just strips the HTML from the <tbody> content and replaces that part of the HTML string with the raw text. It literally just uses .textContent on the wrapping element (in my case <div class="literal">...</div>.

I didn't consider this as an possibility, as I figured it'd be enough to add display: table; to the enclosing <div>. Seems like a weird feature in JS/HTML. 🤷🏻 Sorry for the false alarm!