alleyinteractive/wp-asset-manager

Asset Manager is a toolkit for managing front-end assets and more tightly controlling where, when, and how they're loaded.

Installs: 32 353

Dependents: 2

Suggesters: 0

Security: 0

Stars: 24

Watchers: 40

Forks: 5

Open Issues: 4

Type:wordpress-plugin

v1.3.6 2023-12-18 19:51 UTC

README

Asset Manager is a toolkit for managing front-end assets and more tightly controlling where, when, and how they're loaded.

Using Asset Manager in your WordPress Project

To get started, simply download and install this plugin into your plugins directory and activate it on the plugins screen.

Enqueue Functions

The am_enqueue_* functions will enqueue an asset with additional attributes based upon its load_method value. Options can be passed in as an array or individual parameters.

am_enqueue_script

// Enqueue a JavaScript asset.
am_enqueue_script(
  [
    'handle'      => 'footer-script',
    'src'         => 'js/script.js',
    'deps'        => [],
    'condition'   => 'global',
    'load_method' => 'sync', // 'sync', 'inline', 'async', 'defer', 'async-defer'
    'version'     => '1.0.0',
    'load_hook'   => 'wp_footer',
  ]
);

Use am_modify_load_method to modify the load method of an already-enqueued script.

// Defer an enqueued JavaScript asset.
am_modify_load_method(
  [
    'handle'      => 'footer-script', 
    'load_method' => 'defer',
  ]
);

am_enqueue_style

// Load a CSS asset asynchronously.
am_enqueue_style(
  [
    'handle'      => 'site-styles',
    'src'         => 'css/styles.css',
    'deps'        => [],
    'condition'   => 'global',
    'load_method' => 'async', // 'sync', 'inline', 'async', 'defer', 'preload'
    'version'     => '1.0.0',
    'load_hook'   => 'wp_head',
    'media'       => 'all', // 'print', 'screen', or any valid media query
  ]
);

Conditions

The condition parameter determines under which condition(s) the asset should load.

include

string|array

Requires that all conditions be truthy in order for the asset to load.

The include property is implied if the condition parameter is a string or array of strings; otherwise the condition parameter must contain the include property.

include_any

string|array

Allows for any condition to be truthy, instead of requiring that all conditions be.

exclude

string|array

Requires that all conditions be falsey in order for the asset to load. This is skipped if neither include nor include_any are truthy.

Custom Conditions

There are a few default conditions included out-of-the-box:

Name Condition
'global' true
'single' is_single()
'search' is_search()

Use the am_asset_conditions filter to add or replace conditions.

function asset_conditions( $conditions ) {
  return array_merge(
    $conditions,
    [
      'home'    => ( is_home() || is_front_page() ),
      'archive' => is_archive(),
      'page'    => is_page(),
    ]
  );
}

add_filter( 'am_asset_conditions', 'asset_conditions', 10 );

Inline Assets

Use load_method => inline with an absolute src path for either enqueue function to print the contents of the file to the document head.

Print the contents of a file

// Print the contents of this CSS asset into a <style> tag.
// Also works with `am_enqueue_script` for printing a JavaScript asset into a <script> tag.
am_enqueue_style(
  [
    'handle'      => 'inline-styles',
    'src'         => 'css/styles.css',
    'condition'   => 'global',
    'load_method' => 'inline',
  ]
);

Print inline global variables

Pass an array of values as the src to print global JavaScript variables to the document head.

// Add JavaScript values to a property on the `window.amScripts` object.
am_enqueue_script(
  [
    'handle'      => 'inline-vars',
    'src'         => [
      'myGlobalVar' => true,
    ],
    'load_method' => 'inline',
  ]
);

The result will be an object added to the window.amScripts[$handle] object:

<script class="wp-asset-manager inline-vars" type="text/javascript">window.amScripts = window.amScripts || {}; window.amScripts["inline-vars"] = {"myGlobalVar":true}</script>

Use the am_inline_script_context filter to change the global object name.

add_filter(
  'am_inline_script_context',
  function() {
    return 'myContext'; // window.myContext[$handle]
  }
);

Enqueue Options

The am_enqueue_* functions use the same parameters as their core WordPress enqueue equivelant, with the exception of the $in_footer parameter for scripts; use 'load_hook' (details below) instead.

Additional options:

Name Description Default
condition The condition for which this asset should load 'global'
load_hook 'wp_head'
  — wp_head Load this asset via wp_head
  — wp_footer Load this asset via wp_footer
load_method 'sync'
  — sync Use the corewp_enqueue function
  — async Adds the async attribute to the enqueue
  — defer Adds the defer attribute to the enqueue
  — async-defer Adds the async and defer attributes (scripts only)
  — inline Prints the asset inline in the document head

Preload Function

Use am_preload for preloading assets of any supported type.

// `as` and `mime_type` options will be automatically added for CSS, but are included here for clarity.
am_preload(
  [
    'handle'    => 'preload-styles',
    'src'       => 'css/styles.css',
    'condition' => 'global',
    'version'   => '1.0.0',
    'as'        => 'style'
    'mime_type' => 'text/css',
  ]
);

Result:

<link rel="preload" href="http://client/css/test.css?ver=1.0.0" class="wp-asset-manager preload-styles" as="style" media="all" type="text/css" />

The am_preload function patches the as and mime_type option values for common use-cases (CSS, JavaScript and WOFF2 fonts), but will throw an error if the as option is missing for any other file type.

From the spec:

The [as] attribute is necessary to guarantee correct prioritization, request matching, application of the correct Content Security Policy policy, and setting of the appropriate Accept request header.

This function will also automatically add the crossorigin attribute for fonts, which is required when preloading fonts, even if they're not actually cross-origin requests.

Preload Options

Name Description Required Default
handle The handle for the asset
src The URI for the asset
condition The condition for which this asset should load 'global'
version The asset version '1.0.0'
as The as attribute's value (info)
mime_type The type attribute's value (info)
media The media attribute value used to conditionally preload the asset 'all'

SVG Sprite

Allows for fine-grained control over SVG assets in WordPress templates by creating a sprite of registered symbols and providing helper functions for displaying them.

Asset Manager will add an SVG file's contents to the sprite if:

  1. The symbol is registered via am_register_symbol with a unique handle and valid file path
  2. The symbol's condition is truthy

See Conditions for more about Asset Manager's conditions and how to update them.

Setup

The sprite is printed via the wp_body_open hook, so be sure your templates have the wp_body_open() function at the top of the document's <body> element.

Admin pages

Prints the sprite to admin pages via the in_admin_header hook, which is the most similar admin hook to wp_body_open. Symbols registered with condition(s) not matching admin pages will not be added to the sprite.

/**
 * Add SVG symbols to the admin page content.
 */
function print_admin_sprite() {
  if ( class_exists( 'Asset_Manager_SVG_Sprite' ) ) {
    Asset_Manager_SVG_Sprite::instance()->print_sprite_sheet();
  }
}
add_action( 'in_admin_header', 'print_admin_sprite' );

Registering Symbols

Use the am_register_symbol function to add a symbol to the sprite. Like wp_register_script and wp_register_style, an attempt to re-register a symbol with an existing handle will be ignored.

Symbols should be registered via an action that fires before wp_body_open.

am_register_symbol(
  [
    'handle'    => 'logomark',
    'src'       => 'svg/logomark.svg',
    'condition' => 'global',
  ]
);

Options can be passed in as an array or individual parameters.

$handle

string

Handle for the asset. Should be unique.

$src

string

Absolute path to the SVG file, or a relative path based on the current theme root. Use the am_modify_svg_directory filter to update the directory from which relative paths will be completed.

$condition

string|array

Loading condition(s) that, when matched, will allow the asset to be added to the sprite.

$attributes

array

An array of HTML attribute names and values to add to the resulting <svg> everywhere it is rendered.

Verifying a symbol is registered

am_symbol_is_registered( $handle = '' );

$handle

string

The handle with which the symbol should be registered.

Return

bool

Whether the symbol has been registered.

Changing the SVG directory

Use the am_modify_svg_directory filter to update the directory from which relative paths will be completed.

Default: The current theme root.

add_filter(
  'am_modify_svg_directory',
  function( $theme_root ) {
    return $theme_root . '/svg/';
  }
);

Setting Global Attributes

Use the am_global_svg_attributes filter to add global attributes that will apply to all symbols.

Default: []

add_filter(
  'am_global_svg_attributes',
  function() {
    return [
      'aria-hidden' => 'true',
      'focusable'   => 'false',
    ];
  }
);

Update $sprite_allowed_tags

Use the am_sprite_allowed_tags to filter elements and attributes used in escaping the sprite, such as certain deprecated attributes, script tags, and event handlers.

add_filter(
  'am_sprite_allowed_tags',
  function( $sprite_allowed_tags ) {
    $sprite_allowed_tags['path']['onclick'] = true;

    return $sprite_allowed_tags;
  }
);

Removing a Symbol

Use am_deregister_symbol to remove a registered a symbol.

This should be added via an action that fires after, or at a lower priority, than the action used for am_register_symbol.

am_deregister_symbol( $handle = '' );

$handle

string

The handle with which the symbol was registered.

Return

bool

Whether the symbol has been deregistered and removed from the sprite. true on success, or if the symbol hadn't been previously registered; false on failure.

Replacing a symbol

Prior to re-registering a symbol, verify the symbol to be replaced is not registered.

if ( am_deregister_symbol( 'logomark' ) ) {
  am_register_symbol(
    [
      'handle'    => 'logomark',
      'src'       => 'svg/logomark-alt.svg',
      'condition' => 'global',
    ]
  );
}

Displaying a Symbol

am_use_symbol prints an <svg> element with the specified attributes.

am_use_symbol( $handle = '', $attributes = [] );

$handle

string

The handle with which the symbol was registered.

$attributes

array

An array of attribute-value pairs to add to the resulting SVG markup.

Override global attributes, or those defined via am_register_symbol, by declaring a new value here; remove it entirely by passing a falsy value.

Notes on SVG sizing

Asset Manager will attempt to establish a default size for each SVG, which will be used to calculate the dimensions if only one, or neither, of height or width is passed to am_use_symbol.

The default size is based on (in order):

  1. The values set in the symbol's am_register_symbol attributes array
  2. The height and width attributes from the SVG
  3. The viewBox attribute values

If Asset Manager cannot determine a symbol's dimensions, both height and width will need to be declared in the attributes array passed to am_use_symbol.

The simplest way to ensure SVGs are sized as expected is to verify each file's <svg> element either has both height and width attributes or a viewBox attribute.

Example:

am_use_symbol(
  'logomark',
  [
    'width' => 200,
    'class' => 'header-logo',
  ]
);

Output:

<svg width="200" height="27.67" class="header-logo" aria-hidden="true" focusable="false">
  <use href="#am-symbol-logomark"></use>
</svg>

Getting a Symbol

am_get_symbol returns a string containing the <svg> element with the specified attributes.

$symbol_markup = am_get_symbol( $handle = '', $attributes = [] );

This function uses the same arguments as am_use_symbol.

Example:

$logomark_svg_markup = am_get_symbol(
  'logomark',
  [
    'width' => 200,
    'class' => 'header-logo',
  ]
);

Requirements

  • WordPress: 5.2.0+
  • PHP: 7.4+

Downloads and Versioning.

You can view Asset Manager's official releases here.

The develop branch on GitHub contains the "bleeding edge" releases (alpha, beta, RC). The production branch is the latest stable release.

Contributing to Development

Development of Asset Manager happens on Github. Bugs with Asset Manager should be addressed in the Github issue queue, and enhancements or bug fixes should be submitted as pull requests, which are always welcome.