Opened 3 years ago
Last modified 15 hours ago
#59444 new enhancement
Use HEREDOC/NOWDOC for embedded CSS/JS code in PHP
| Reported by: | westonruter | Owned by: | |
|---|---|---|---|
| Priority: | normal | Milestone: | 7.2 |
| Component: | General | Version: | 6.4 |
| Severity: | normal | Keywords: | |
| Cc: | Focuses: | javascript, css, coding-standards |
Description (last modified by )
As part of #4773 and #58775, many manually-constructed inline <script> and <style> tags were replaced with API calls to wp_print_inline_script_tag() and wp_add_inline_style(), respectively. While doing so comes with key runtime benefits, a downside is introduced in terms of the developer experience. In particular, when editing a PHP file that has an embedded <style> or <script> tag, IDEs will do syntax highlighting and other code intelligence features for the embedded language. These IDE features are particularly important since the JS/CSS code in question is not located in a .js or .css file, meaning it is not included in static analysis checks (e.g. JSHint). This means that the IDE is the first line of defense against developers accidentally making a typo or introducing a syntax error which, if it passes code review, would otherwise only get discovered at runtime in user testing. These IDE features are also important for developer productivity (e.g. autocompletion).
I understand PhpStorm to be the most popular IDE for WordPress core development, and it has a language injection feature. It involves using comments that precede the embedded language string, for example:
wp_print_inline_script_tag( /** @lang JavaScript */ "document.body.className = document.body.className.replace('no-js','js');" );
or
wp_add_inline_style( 'admin-bar', // language=CSS '@media print { #wpadminbar { display:none; } }' );
VSCode has an issue for Universal Language Injections, but it was closed for being too difficult. Apparently the scope was to go to the extent of detecting embedded languages even without the language injection comments that Jetbrains IDEs support. The feature was apparently relegated to the extension space (cf. Syntax Highlight Guide).
That being said, it does appear that VSCode does support method that PhpStorm supports: Inject a language inside a nowdoc/heredoc string. (I can't seem to find any VSCode documentation about this, but it seems to work locally.) This allows you to do:
wp_print_inline_script_tag( <<<'JS' document.body.className = document.body.className.replace('no-js','js'); JS );
Nevertheless, there are also issues with the ergonomics of heredoc strings, especially prior to PHP 7.3: the closing delimiter must always start at the beginning of the line, and it cannot have any comma following it on the same line. So that means you cannot do the following in PHP<7.3:
$scripts->add_inline_script( 'media-widgets', <<<'JS' wp.mediaWidgets.init(); JS, 'after' );
Since WordPress only now just bumped the minimum requirement to 7.0, this isn't yet an option.
I suggest that PhpStorm's syntax for language injection comments be adopted in WordPress core as a convention. Since PhpStorm is apparently the most popular IDE for WordPress core development, it will be useful for core contributors. For VSCode, an extension could potentially be written that adds support for the same syntax. Otherwise, we wait until PHP 7.3 is the minimum requirement and switch all existing JS/CSS string literals to heredocs.
Update: Now that PHP 7.4 is the minimum version supported by WordPress, we can move forward with using the flexible HEREDOC/NOWDOC syntax:
The closing marker for doc strings is no longer required to be followed by a semicolon or newline. Additionally the closing marker may be indented, in which case the indentation will be stripped from all lines in the doc string.
For delimiters, use JS for JavaScript code, and CSS for CSS code.
Try using NOWDOC whenever possible. See Plugin Check issue and comment. In some cases, it may make sense to continue to use wp_remove_surrounding_empty_script_tags().
This is closely related to #59446, where any manually-constructed <script> tags needs to be eliminated in core in favor of wp_print_inline_script_tag() for compatibility with CSP.
Previous conversations:
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)
One benefit of using the HEREDOC strings is that it should be a trivial update to indent them once the minimum supported version is 7.3, and they will work in both IDEs until then. That's where my vote lies, because I'd rather have syntax highlighting and IDE aids than avoid a dangling HEREDOC closer.
That being said I think this is good either way so I wouldn't want to block an update that has a positive impact. It would simply be a little more difficult to change later when embedding the comments inside the PHP strings.
There HEREDOC syntax has another benefit I personally like: it encourages normal formatting of JS inside PHP, using newlines properly, and aligning code. When a normal string is the example I feel like that puts pressure on people to fit everything in a single long line; if they do need multiple lines, then there are multiple ways they might approach that, whereas the HEREDOC conveys a single straightforward way.