Skip to content

Fix: Update Raw <script> tags with wp_inline_script_tag() for bundled themes. #9416

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: trunk
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 113 additions & 1 deletion src/wp-content/themes/twentyfifteen/functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -412,7 +412,7 @@ function twentyfifteen_fonts_url() {
* @since Twenty Fifteen 1.1
*/
function twentyfifteen_javascript_detection() {
echo "<script>(function(html){html.className = html.className.replace(/\bno-js\b/,'js')})(document.documentElement);</script>\n";
wp_print_inline_script_tag( "(function(html){html.className = html.className.replace(/\bno-js\b/,'js')})(document.documentElement);" );
}
add_action( 'wp_head', 'twentyfifteen_javascript_detection', 0 );

Expand Down Expand Up @@ -666,3 +666,115 @@ function twentyfifteen_register_block_patterns() {
}

add_action( 'init', 'twentyfifteen_register_block_patterns' );

if ( ! function_exists( 'wp_get_inline_script_tag' ) ) {
/**
* Constructs an inline script tag.
*
* It is possible to inject attributes in the `<script>` tag via the {@see 'wp_inline_script_attributes'} filter.
* Automatically injects type attribute if needed.
*
* Added for backward compatibility to support pre-5.7.0 WordPress versions.
*
* @since 5.7.0
*
* @param string $data Data for script tag: JavaScript, importmap, speculationrules, etc.
* @param array $attributes Optional. Key-value pairs representing `<script>` tag attributes.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should add a breathing space between 2 doc annotations. @param and @return.

* @return string String containing inline JavaScript code wrapped around `<script>` tag.
*/
function wp_get_inline_script_tag( $data, $attributes = array() ) {
$is_html5 = current_theme_supports( 'html5', 'script' ) || is_admin();
if ( ! isset( $attributes['type'] ) && ! $is_html5 ) {
// Keep the type attribute as the first for legacy reasons (it has always been this way in core).
$attributes = array_merge(
array( 'type' => 'text/javascript' ),
$attributes
);
}

/*
* XHTML extracts the contents of the SCRIPT element and then the XML parser
* decodes character references and other syntax elements. This can lead to
* misinterpretation of the script contents or invalid XHTML documents.
*
* Wrapping the contents in a CDATA section instructs the XML parser not to
* transform the contents of the SCRIPT element before passing them to the
* JavaScript engine.
*
* Example:
*
* <script>console.log('&hellip;');</script>
*
* In an HTML document this would print "&hellip;" to the console,
* but in an XHTML document it would print "…" to the console.
*
* <script>console.log('An image is <img> in HTML');</script>
*
* In an HTML document this would print "An image is <img> in HTML",
* but it's an invalid XHTML document because it interprets the `<img>`
* as an empty tag missing its closing `/`.
*
* @see https://www.w3.org/TR/xhtml1/#h-4.8
*/
if (
! $is_html5 &&
(
! isset( $attributes['type'] ) ||
'module' === $attributes['type'] ||
str_contains( $attributes['type'], 'javascript' ) ||
str_contains( $attributes['type'], 'ecmascript' ) ||
str_contains( $attributes['type'], 'jscript' ) ||
str_contains( $attributes['type'], 'livescript' )
)
) {
/*
* If the string `]]>` exists within the JavaScript it would break
* out of any wrapping CDATA section added here, so to start, it's
* necessary to escape that sequence which requires splitting the
* content into two CDATA sections wherever it's found.
*
* Note: it's only necessary to escape the closing `]]>` because
* an additional `<![CDATA[` leaves the contents unchanged.
*/
$data = str_replace( ']]>', ']]]]><![CDATA[>', $data );

// Wrap the entire escaped script inside a CDATA section.
$data = sprintf( "/* <![CDATA[ */\n%s\n/* ]]> */", $data );
}

$data = "\n" . trim( $data, "\n\r " ) . "\n";

/**
* Filters attributes to be added to a script tag.
*
* Added for backward compatibility to support pre-5.7.0 WordPress versions.
*
* @since 5.7.0
*
* @param array $attributes Key-value pairs representing `<script>` tag attributes.
* Only the attribute name is added to the `<script>` tag for
* entries with a boolean value, and that are true.
* @param string $data Inline data.
*/
$attributes = apply_filters( 'wp_inline_script_attributes', $attributes, $data );

return sprintf( "<script%s>%s</script>\n", wp_sanitize_script_attributes( $attributes ), $data );
}
}

if ( ! function_exists( 'wp_print_inline_script_tag' ) ) {
/**
* Prints an inline script tag.
*
* It is possible to inject attributes in the `<script>` tag via the {@see 'wp_inline_script_attributes'} filter.
* Automatically injects type attribute if needed.
*
* @since 5.7.0
*
* @param string $data Data for script tag: JavaScript, importmap, speculationrules, etc.
* @param array $attributes Optional. Key-value pairs representing `<script>` tag attributes.
*/
function wp_print_inline_script_tag( $data, $attributes = array() ) {
echo wp_get_inline_script_tag( $data, $attributes );
}
}
123 changes: 118 additions & 5 deletions src/wp-content/themes/twentynineteen/functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -303,11 +303,12 @@ function twentynineteen_scripts() {
*/
function twentynineteen_skip_link_focus_fix() {
// The following is minified via `terser --compress --mangle -- js/skip-link-focus-fix.js`.
?>
<script>
/(trident|msie)/i.test(navigator.userAgent)&&document.getElementById&&window.addEventListener&&window.addEventListener("hashchange",function(){var t,e=location.hash.substring(1);/^[A-z0-9_-]+$/.test(e)&&(t=document.getElementById(e))&&(/^(?:a|select|input|button|textarea)$/i.test(t.tagName)||(t.tabIndex=-1),t.focus())},!1);
</script>
<?php
wp_print_inline_script_tag(
'/(trident|msie)/i.test(navigator.userAgent) && document.getElementById && window.addEventListener && window.addEventListener("hashchange", function() {
var t, e = location.hash.substring(1);
/^[A-z0-9_-]+$/.test(e) && (t = document.getElementById(e)) && (/^(?:a|select|input|button|textarea)$/i.test(t.tagName) || (t.tabIndex = -1), t.focus());
}, false);'
);
}

/**
Expand Down Expand Up @@ -395,3 +396,115 @@ function twentynineteen_register_block_patterns() {
}

add_action( 'init', 'twentynineteen_register_block_patterns' );

if ( ! function_exists( 'wp_get_inline_script_tag' ) ) {
/**
* Constructs an inline script tag.
*
* It is possible to inject attributes in the `<script>` tag via the {@see 'wp_inline_script_attributes'} filter.
* Automatically injects type attribute if needed.
*
* Added for backward compatibility to support pre-5.7.0 WordPress versions.
*
* @since 5.7.0
*
* @param string $data Data for script tag: JavaScript, importmap, speculationrules, etc.
* @param array $attributes Optional. Key-value pairs representing `<script>` tag attributes.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same goes here.

* @return string String containing inline JavaScript code wrapped around `<script>` tag.
*/
function wp_get_inline_script_tag( $data, $attributes = array() ) {
$is_html5 = current_theme_supports( 'html5', 'script' ) || is_admin();
if ( ! isset( $attributes['type'] ) && ! $is_html5 ) {
// Keep the type attribute as the first for legacy reasons (it has always been this way in core).
$attributes = array_merge(
array( 'type' => 'text/javascript' ),
$attributes
);
}

/*
* XHTML extracts the contents of the SCRIPT element and then the XML parser
* decodes character references and other syntax elements. This can lead to
* misinterpretation of the script contents or invalid XHTML documents.
*
* Wrapping the contents in a CDATA section instructs the XML parser not to
* transform the contents of the SCRIPT element before passing them to the
* JavaScript engine.
*
* Example:
*
* <script>console.log('&hellip;');</script>
*
* In an HTML document this would print "&hellip;" to the console,
* but in an XHTML document it would print "…" to the console.
*
* <script>console.log('An image is <img> in HTML');</script>
*
* In an HTML document this would print "An image is <img> in HTML",
* but it's an invalid XHTML document because it interprets the `<img>`
* as an empty tag missing its closing `/`.
*
* @see https://www.w3.org/TR/xhtml1/#h-4.8
*/
if (
! $is_html5 &&
(
! isset( $attributes['type'] ) ||
'module' === $attributes['type'] ||
str_contains( $attributes['type'], 'javascript' ) ||
str_contains( $attributes['type'], 'ecmascript' ) ||
str_contains( $attributes['type'], 'jscript' ) ||
str_contains( $attributes['type'], 'livescript' )
)
) {
/*
* If the string `]]>` exists within the JavaScript it would break
* out of any wrapping CDATA section added here, so to start, it's
* necessary to escape that sequence which requires splitting the
* content into two CDATA sections wherever it's found.
*
* Note: it's only necessary to escape the closing `]]>` because
* an additional `<![CDATA[` leaves the contents unchanged.
*/
$data = str_replace( ']]>', ']]]]><![CDATA[>', $data );

// Wrap the entire escaped script inside a CDATA section.
$data = sprintf( "/* <![CDATA[ */\n%s\n/* ]]> */", $data );
}

$data = "\n" . trim( $data, "\n\r " ) . "\n";

/**
* Filters attributes to be added to a script tag.
*
* Added for backward compatibility to support pre-5.7.0 WordPress versions.
*
* @since 5.7.0
*
* @param array $attributes Key-value pairs representing `<script>` tag attributes.
* Only the attribute name is added to the `<script>` tag for
* entries with a boolean value, and that are true.
* @param string $data Inline data.
*/
$attributes = apply_filters( 'wp_inline_script_attributes', $attributes, $data );

return sprintf( "<script%s>%s</script>\n", wp_sanitize_script_attributes( $attributes ), $data );
}
}

if ( ! function_exists( 'wp_print_inline_script_tag' ) ) {
/**
* Prints an inline script tag.
*
* It is possible to inject attributes in the `<script>` tag via the {@see 'wp_inline_script_attributes'} filter.
* Automatically injects type attribute if needed.
*
* @since 5.7.0
*
* @param string $data Data for script tag: JavaScript, importmap, speculationrules, etc.
* @param array $attributes Optional. Key-value pairs representing `<script>` tag attributes.
*/
function wp_print_inline_script_tag( $data, $attributes = array() ) {
echo wp_get_inline_script_tag( $data, $attributes );
}
}
114 changes: 113 additions & 1 deletion src/wp-content/themes/twentyseventeen/functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -406,7 +406,7 @@ function twentyseventeen_excerpt_more( $link ) {
* @since Twenty Seventeen 1.0
*/
function twentyseventeen_javascript_detection() {
echo "<script>(function(html){html.className = html.className.replace(/\bno-js\b/,'js')})(document.documentElement);</script>\n";
wp_print_inline_script_tag( "(function(html){html.className = html.className.replace(/\bno-js\b/,'js')})(document.documentElement);" );
}
add_action( 'wp_head', 'twentyseventeen_javascript_detection', 0 );

Expand Down Expand Up @@ -758,3 +758,115 @@ function twentyseventeen_register_block_patterns() {
}

add_action( 'init', 'twentyseventeen_register_block_patterns' );

if ( ! function_exists( 'wp_get_inline_script_tag' ) ) {
/**
* Constructs an inline script tag.
*
* It is possible to inject attributes in the `<script>` tag via the {@see 'wp_inline_script_attributes'} filter.
* Automatically injects type attribute if needed.
*
* Added for backward compatibility to support pre-5.7.0 WordPress versions.
*
* @since 5.7.0
*
* @param string $data Data for script tag: JavaScript, importmap, speculationrules, etc.
* @param array $attributes Optional. Key-value pairs representing `<script>` tag attributes.
* @return string String containing inline JavaScript code wrapped around `<script>` tag.
*/
function wp_get_inline_script_tag( $data, $attributes = array() ) {
$is_html5 = current_theme_supports( 'html5', 'script' ) || is_admin();
if ( ! isset( $attributes['type'] ) && ! $is_html5 ) {
// Keep the type attribute as the first for legacy reasons (it has always been this way in core).
$attributes = array_merge(
array( 'type' => 'text/javascript' ),
$attributes
);
}

/*
* XHTML extracts the contents of the SCRIPT element and then the XML parser
* decodes character references and other syntax elements. This can lead to
* misinterpretation of the script contents or invalid XHTML documents.
*
* Wrapping the contents in a CDATA section instructs the XML parser not to
* transform the contents of the SCRIPT element before passing them to the
* JavaScript engine.
*
* Example:
*
* <script>console.log('&hellip;');</script>
*
* In an HTML document this would print "&hellip;" to the console,
* but in an XHTML document it would print "…" to the console.
*
* <script>console.log('An image is <img> in HTML');</script>
*
* In an HTML document this would print "An image is <img> in HTML",
* but it's an invalid XHTML document because it interprets the `<img>`
* as an empty tag missing its closing `/`.
*
* @see https://www.w3.org/TR/xhtml1/#h-4.8
*/
if (
! $is_html5 &&
(
! isset( $attributes['type'] ) ||
'module' === $attributes['type'] ||
str_contains( $attributes['type'], 'javascript' ) ||
str_contains( $attributes['type'], 'ecmascript' ) ||
str_contains( $attributes['type'], 'jscript' ) ||
str_contains( $attributes['type'], 'livescript' )
)
) {
/*
* If the string `]]>` exists within the JavaScript it would break
* out of any wrapping CDATA section added here, so to start, it's
* necessary to escape that sequence which requires splitting the
* content into two CDATA sections wherever it's found.
*
* Note: it's only necessary to escape the closing `]]>` because
* an additional `<![CDATA[` leaves the contents unchanged.
*/
$data = str_replace( ']]>', ']]]]><![CDATA[>', $data );

// Wrap the entire escaped script inside a CDATA section.
$data = sprintf( "/* <![CDATA[ */\n%s\n/* ]]> */", $data );
}

$data = "\n" . trim( $data, "\n\r " ) . "\n";

/**
* Filters attributes to be added to a script tag.
*
* Added for backward compatibility to support pre-5.7.0 WordPress versions.
*
* @since 5.7.0
*
* @param array $attributes Key-value pairs representing `<script>` tag attributes.
* Only the attribute name is added to the `<script>` tag for
* entries with a boolean value, and that are true.
* @param string $data Inline data.
*/
$attributes = apply_filters( 'wp_inline_script_attributes', $attributes, $data );

return sprintf( "<script%s>%s</script>\n", wp_sanitize_script_attributes( $attributes ), $data );
}
}

if ( ! function_exists( 'wp_print_inline_script_tag' ) ) {
/**
* Prints an inline script tag.
*
* It is possible to inject attributes in the `<script>` tag via the {@see 'wp_inline_script_attributes'} filter.
* Automatically injects type attribute if needed.
*
* @since 5.7.0
*
* @param string $data Data for script tag: JavaScript, importmap, speculationrules, etc.
* @param array $attributes Optional. Key-value pairs representing `<script>` tag attributes.
*/
function wp_print_inline_script_tag( $data, $attributes = array() ) {
echo wp_get_inline_script_tag( $data, $attributes );
}
}
Loading
Loading