Simply-Static / simply-static

Convert your WordPress site into a static one with the free WordPress static site generator plugin, Simply Static.
https://simplystatic.com
GNU General Public License v2.0
200 stars 49 forks source link

exported HTML of <script> tags of type "text/html" or "text/template" are all missing closing </script> tag, since 3.1.7 #255

Closed omegabenefits closed 1 month ago

omegabenefits commented 2 months ago

I've just downloaded every version of simply-static (free) I could get my hands on to figure out where this broke - and I had to go all the way back to the 3.1.7 release to get HTML exports that weren't missing the closing ! (tried 3.1.8, 3.1.7.4, 3.1.7.2)

When an inline script using templates (underscore.js) like the block below is parsed by simply-static

<script type="text/html" id="tmpl-autocomplete-header">
    <div class="autocomplete-header">
        <div class="autocomplete-header-title">{{{ data.label }}}</div>
        <div class="clear"></div>
    </div>
</script>

the resulting exported HTML is missing the closing tag, breaking that script completely (but frustratingly NOT throwing any errors to the console, making the bug hard to track down!). A series of similar inline scripts then all get busted, as the first script is never closed and the rest are all treated as if they're nested (but none ever close)

<script type="text/html" id="tmpl-autocomplete-header">
    <div class="autocomplete-header">
        <div class="autocomplete-header-title">{{{ data.label }}}</div>
        <div class="clear"></div>
    </div>

This bug has been responsible for silently breaking our implementation of WP Search with Algolia plugin (I know SS complains it's not compatible, but we don't use the SS algolia integration, have been using the separate plugin for a long time with SS already). But I would imagine it's affecting any other templating scripts too.

Also found some Elementor inline scripts as well that use type="text/template" also have missing tags since 3.1.7, breaking some functionality I didn't even notice.

omegabenefits commented 2 months ago

since the only mention of parsing "text/html" scripts I could find in the source belonged to vendor/voku/simple_html_dom, and there appears to be a bump in composer.json from 4.8.8 to 4.8.9 (commit 5ba7de2) right around the time when simply-static didn't have this issue, curious if simple_html_dom is involved in the bug?

patrickposner commented 2 months ago

@omegabenefits thanks for the report!

Can you temporarily add the following code snippet, re-run the export, and check if the issue persists?

add_filter('ss_parse_inline_script', '__return_false' );

That should help getting a better idea if it's related to our changes or something associated with the underlying composer package.

omegabenefits commented 2 months ago

adding that filter did not fix the issue, still missing

patrickposner commented 2 months ago

Hey @omegabenefits,

thanks for the update!

Do you know how the script gets injected into the page? I just tried to replicate it by adding it to the footer of the page with:

`add_action( 'wp_footer', function () { ?>

<?php

} );`

When I then run the static export (ZIP/offline), the result looks fine (the closing tag is there, no invalid HTML):

Screenshot 2024-09-13 at 11 50 59

omegabenefits commented 1 month ago

I found a workaround that prevents the issue (and yes, the original problem is still happening on the latest 3.2.0 version of SS). I changed the type of the scripts to 'text/template' instead of 'text/html' - and the resulting SS exported HTML now has the proper closing tags! I would recommend this fix to anyone else using a templating library like underscore.js/handlebars/etc

These scripts are injected when template php files are included (this is from the WP Search with Algolia plugin) sample below:

<?php
/**
 * WP Search With Algolia autocomplete template file.
 *
 * @author  WebDevStudios <contact@webdevstudios.com>
 * @since   1.0.0
 *
 * @version 2.5.3
 * @package WebDevStudios\WPSWA
 */

?>

<script type="text/template" id="tmpl-autocomplete-header">
    <div class="autocomplete-header">
        <div class="autocomplete-header-title">{{{ data.label }}}</div>
        <div class="clear"></div>
    </div>
</script>

<script type="text/template" id="tmpl-autocomplete-post-suggestion">
    <a class="suggestion-link" href="{{ data.permalink }}" title="{{ data.post_title }}">
        <# if ( data.images.thumbnail ) { #>
            <img class="suggestion-post-thumbnail" src="{{ data.images.thumbnail.url }}" alt="{{ data.post_title }}">
        <# } #>
        <div class="suggestion-post-attributes">
            <span class="suggestion-post-title">{{{ data._highlightResult.post_title.value }}}</span>
            <# if ( data._snippetResult['content'] ) { #>
                <span class="suggestion-post-content">{{{ data._snippetResult['content'].value }}}</span>
            <# } #>
        </div>
        <?php
        do_action( 'algolia_autocomplete_after_hit' );
        ?>
    </a>
</script>

<script type="text/template" id="tmpl-autocomplete-term-suggestion">
    <a class="suggestion-link" href="{{ data.permalink }}" title="{{ data.name }}">
        <svg viewBox="0 0 21 21" width="21" height="21">
            <svg width="21" height="21" viewBox="0 0 21 21">
                <path
                    d="M4.662 8.72l-1.23 1.23c-.682.682-.68 1.792.004 2.477l5.135 5.135c.7.693 1.8.688 2.48.005l1.23-1.23 5.35-5.346c.31-.31.54-.92.51-1.36l-.32-4.29c-.09-1.09-1.05-2.06-2.15-2.14l-4.3-.33c-.43-.03-1.05.2-1.36.51l-.79.8-2.27 2.28-2.28 2.27zm9.826-.98c.69 0 1.25-.56 1.25-1.25s-.56-1.25-1.25-1.25-1.25.56-1.25 1.25.56 1.25 1.25 1.25z"
                    fill-rule="evenodd"></path>
            </svg>
        </svg>
        <span class="suggestion-post-title">{{{ data._highlightResult.name.value }}}</span>
    </a>
</script>
omegabenefits commented 1 month ago

note - I found this pull in voku/simple_html_dom that had me curious to try this workaround