14

I'm debugging a problem with a third party script of ours that wordpress users use by copy / pasting a snippet of script and html into their post's bodies like (non-real world example of course):

<script>
window.foobar = window.foobar || { hello: function(){ console.log('Hello World'); } };
window.foobar.hello();
</script>

I noticed that some installations of wordpress will wrap this in CDATA, some won't (probably by doing some sort of DOCTYPE checking - although all themes I tested this on were using an HTML5 doctype).

Yet, when wrapping the script in CDATA the users will get bitten by the following bug: https://core.trac.wordpress.org/ticket/3670 (the closing > is incorrectly replaced by &gt;) which leads to the browser ignoring the script content:

<script>// <![CDATA[  window.foobar = window.foobar || { hello: function(){ console.log('Hello World'); } }; window.foobar.hello();  // ]]&gt;</script>

I don't own too much WP-Fu myself and googling only led me to identifying the problem as is, so my question would be: when exactly does WordPress wrap inline scripts into CDATA sections? Can the user somehow prevent this behavior? Can the user somehow work around the above bug without modifying WP core?

3
  • 1
    When pasting inline JS in the editor, WP should do this behavior. I suggest enqueuing the JS using wp_head or wp_enqueue_script..
    – Ismail
    Commented Jul 28, 2015 at 13:28
  • Do you mean "post's bodies" as in the WYSIWYG editor? From what I can see, JS gets wrapped in CDATA tags when scripts are printed (which could be invoked in a number of ways) but aren't filterable. I would imagine, if you do mean the WYSIWYG of a post, it might be some filtering on the content done by the theme. Commented Mar 17, 2017 at 9:04
  • 1
    It's not recommended that you post javascript in the WYSIWYG editor. The editor has a number of filters to clean up your content that interact poorly with inline js. There are plugins that help in this type of scenario. Commented Jan 7, 2019 at 21:18

2 Answers 2

2

Actually, it is not WordPress that is inserting the CDATA tags, but the visual editor, TinyMCE. Details of TinyMCE are offtopic here, but you can read a solution to this on Stackoverflow.

That said, stopping TinyMCE may not be the full solution you want. WordPress itself also has a function for adding CDATA tags, wxr_cdata, which is used when outputting a valid xml-file, for instance if you want to export the file of use the content in a rss-feed. Themes and/or plugins could decide to attach this filter to the content if they want the document to be valid xhtml.

This is where you then run into the bug, which was first documented twelve years ago and remains unsolved. It's about these three lines in the_content:

$content = apply_filters( 'the_content', $content );
$content = str_replace( ']]>', ']]&gt;', $content );
echo $content;

As you can see, the str_replace is hardcoded, immediately followed by the echo. There's no way to intercept this replacement.

What you can do, however, if you control your theme, is buffer the_content and reverse the replacement. Like this:

ob_start();
the_content();
$content = ob_get_clean();
$content = str_replace( ']]&gt', ']]>', $content ); 
echo $content;
2
  • I am experiencing the same when using the Gravity forms Previewer. The script is being loaded by wp_localize_script function. In the default 2022 theme the script is not enclosed within CDATA tags however when using a custom theme the incline js is being enclosed within CDATA tags rendering the code inside useless. Can you please show how the above code is to be implemented in the function.php file. Commented Apr 6, 2022 at 10:14
  • @SarthakGupta Sorry, but I'm not an expert on Gravity Forms. You better ask on the forum of that plugin.
    – cjbj
    Commented Apr 8, 2022 at 10:27
1

WordPress will wrap scripts in CDATA if the active theme does not explicitly declare HTML5 support. To declare that the theme supports HTML5 add the line:

add_theme_support( 'html5', [ 'script', 'style' ] );

in functions.php or somewhere else suitable.

Note that this will not only only remove the CDATA wrap, it will also remove type="text/javascript" and type="text/css" from enqueued scripts and styles respectively.

For more information see https://developer.wordpress.org/reference/functions/add_theme_support/

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.