Skip to content

Instantly share code, notes, and snippets.

@joshuatz
Last active March 29, 2022 17:24
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save joshuatz/3d37a01580645729e507837a4e0c3d4a to your computer and use it in GitHub Desktop.
Save joshuatz/3d37a01580645729e507837a4e0c3d4a to your computer and use it in GitHub Desktop.
<?php
/**
* @author Joshua Tzucker
* @license MIT
* @see https://joshuatz.com/posts/2020/adding-extra-attributes-to-style-and-script-tags-in-wordpress/
*/
/**
* These should stay global, so you can access them wherever
* you need to hack on an extra attribute
*
* @example
* ```php
* global $ARB_ATTRIB_PREFIX;
* wp_script_add_data($yourHandle, $ARB_ATTRIB_PREFIX . 'your_key', 'your_val');
* ```
*
* You can customize this prefix, but be careful about avoiding collisions, and escape any characters that will break building the regex pattern
*/
$ARB_ATTRIB_PREFIX = 'arb_att_&#';
$ARB_ATTRIB_PATTERN = '/' . $ARB_ATTRIB_PREFIX . '(.+)/';
/**
* Callback for WP to hit before echoing out an enqueued resource. This callback specifically checks for any key-value pairs that have been added through `add_data()` and are prefixed with a special value to indicate they should be injected into the final HTML
* @param {string} $tag - Will be the full string of the tag (`<link>` or `<script>`)
* @param {string} $handle - The handle that was specified for the resource when enqueuing it
* @param {string} $src - the URI of the resource
* @param {string|null} $media - if resources is style, should be the target media, else null
* @param {boolean} $isStyle - If the resource is a stylesheet
*/
function scriptAndStyleTagAttributeAdder($tag, $handle, $src, $media, $isStyle){
global $ARB_ATTRIB_PATTERN;
$extraAttrs = array();
$nodeName = '';
// Get the WP_Dependency instance for this handle, and grab any extra fields
if ($isStyle) {
$nodeName = 'link';
$extraAttrs = wp_styles()->registered[$handle]->extra;
} else {
$nodeName = 'script';
$extraAttrs = wp_scripts()->registered[$handle]->extra;
}
// Check stored properties on WP resource instance against our pattern
$attribsToAdd = array();
foreach ($extraAttrs as $fullAttrKey => $attrVal) {
$matches = array();
preg_match($ARB_ATTRIB_PATTERN, $fullAttrKey, $matches);
if (count($matches) > 1) {
$attrKey = $matches[1];
$attribsToAdd[$attrKey] = $attrVal;
}
}
// Actually do the work of adding attributes to $tag
if (count($attribsToAdd)) {
$dom = new DOMDocument();
@$dom->loadHTML($tag);
/** @var {DOMElement[]} */
$resourceTags = $dom->getElementsByTagName($nodeName);
foreach ($resourceTags as $resourceTagNode) {
foreach ($attribsToAdd as $attrKey => $attrVal) {
$resourceTagNode->setAttribute($attrKey, $attrVal);
}
}
$headStr = $dom->saveHTML($dom->getElementsByTagName('head')[0]);
// Capture content between <head></head>. Kind of hackish, but should be faster than preg_match
$content = substr($headStr, 7, (strlen($headStr) - 15));
return $content;
}
return $tag;
}
add_filter('script_loader_tag',function($tag, $handle, $src){
return scriptAndStyleTagAttributeAdder($tag, $handle, $src, null, false);
},10,4);
add_filter('style_loader_tag',function($tag, $handle, $src, $media){
return scriptAndStyleTagAttributeAdder($tag, $handle, $src, $media, true);
},10,4);
<?php
/**
* Including and using this is optional; a wrapper function around the add_data calls, so you don't have to remember to prefix with the special string
* @param {string} $handle
* @param {string} $attrKey
* @param {string} $attrVal
* @param {boolean} [$isScript = false]
*/
function add_attribute($handle, $key, $val, $isScript = false) {
global $ARB_ATTRIB_PREFIX;
$attrKey = $ARB_ATTRIB_PREFIX . $key;
if ($isScript) {
wp_script_add_data($handle, $attrKey, $val);
} else {
wp_style_add_data($handle, $attrKey, $val);
}
}
@dirad
Copy link

dirad commented Jan 25, 2022

Can you suggest how to achieve this when the script tags are not in the head, but late in the body?
Can you suggest how to add a tag to a localized script that gets output to inline script tags?

global $wp_query;
wp_localize_script( 'project-js', 'ajaxobj', array(
	'ajaxurl' => admin_url( 'admin-ajax.php' ),
	'some_vars' => json_encode( $wp_query->query )
));

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment