ideasonpurpose / wp-svg-lib
Utilities for collecting and reusing inline SVG components
Requires
- doctrine/inflector: ^2.0
- kint-php/kint: ^5
Requires (Dev)
- ideasonpurpose/wp-test-stubs: dev-main@dev
- php-stubs/acf-pro-stubs: ^6
- php-stubs/wordpress-stubs: ^6
- phpunit/phpunit: ^10.2
This package is auto-updated.
Last update: 2024-11-20 17:45:53 UTC
README
Version 3.0.0
A powerful utility library for including SVG files in WordPress sites.
What it does
This helper library reads SVG files from a directory then provides helper functions for embedding the files into WordPress templates. Files can be embedded inline or converted to symbols to help conserve bandwidth.
The library also enables SVG shortcodes, which can directly place SVGs into the block editor.
Note: Version 2.0.0 changed the namespace from IdeasOnPurpose\SVG
to IdeasOnPurpose\WP\SVG
.
Instructions
Initialize the library from a theme's functions.php file. Starting with version 3, the library looks for SVG files in the theme's dist/images/svg
directory by default, so instantiation can look like this:
new IdeasOnPurpose\WP\SVG; // or use a custom path new IdeasOnPurpose\WP\SVG(get_theme_directory() . '/icons/svg');
All SVG files below the directory will be registered and available to template files. The library will inject an $SVG
query var so SVGs can be accessed from inside get_template_part()
includes with no additional code.
Install from Packagist, require it in composer.json or tell Composer to load the package:
$ composer require ideasonpurpose/wp-svg-lib
Embedding SVGs
Embedding images is the same as pasting the SVG files into the HTML source. Most registered SVG files can be inserted using just their name, so a file named logo.svg can embedded like this:
<div><?= $SVG->logo ?></div>
That code outputs something like this:
<div><svg viewBox="0 0 25 10">...</svg></div>
The library normalizes all file names to camelCase to help with embedding. Directory separators will be replaced with double-underscores. Some examples:
// the file 'icons/email-circle.svg' can be embedded as: $SVG->icons__emailCircle;
For SVG files whose names aren't compatible with PHP's property syntax, there's also an embed command which also works with nested directories:
<li><?= $SVG->embed('arrow-left') ?></li> <li><?= $SVG->embed('icons/email') ?></li>
For convenience, SVG files can be embedded with or without their file extension. So the previous embeds could also work like this:
<li><?= $SVG->embed('arrow-left.svg') ?></li> <li><?= $SVG->embed('icons/email.svg') ?></li>
Note that name resolution is bi-directional. An SVG file named dash-case.svg can be embedded by either dash-case
or dashCase
. Likewise, a file named camelCase.svg will be accessible by either camelCase
or camel-case
.
Inlining SVG Symbols
SVGs can also be injected as linked symbols, where most all of the markup only appears once. This can be useful for simple elements which appear repeatedly:
<a href="#"><?= $SVG->use('arrow') ?>Go!</a>
The library keeps a record of which files have been included like this, then injects a symbol reference from the wp_footer
hook. Together, the above code and symbol library look like this:
<a href="#"><svg class="arrow"><use xlink:href="#arrow" href="#arrow" /></svg>Go!</a> <svg xmlns='http://www.w3.org/2000/svg' style='display: none;'> <symbol id="arrow" viewBox="0 0 50 50">...</symbol> </svg> </body>
REST API
This library adds the /ideasonpurpose/v1/svg
endpoint to the WP-JSON API.
Files can be requested by name like this:
- https://example.com/wp-json/ideasonpurpose/v1/svg/arrowLeft
- https://example.com/wp-json/ideasonpurpose/v1/svg/icons__email
Dimensions, classes and IDs can be injected using query vars:
- https://example.com/wp-json/ideasonpurpose/v1/svg/arrowLeft?width=200&height=auto
- https://example.com/wp-json/ideasonpurpose/v1/svg/icons__email&class=social+blue
A listing of all registered SVGs is here:
If either height or width are 'auto' then that value will be calculated from the aspect ratio and the opposite dimension.
Well-formed SVG files should return a data object like this:
{ "svg": "<svg viewBox=\"0 0 25 10\" xmlns=\"http://www.w3.org/2000/svg\"><path fill-rule=\"evenodd\" d=\"M0 5.57.01 4.4c12.59.08 18.84.08 18.77 0V0L25 4.99 18.77 10l.01-4.43H0Z\"/>\n</svg>", "innerContent": "<path fill-rule=\"evenodd\" d=\"M0 5.57.01 4.4c12.59.08 18.84.08 18.77 0V0L25 4.99 18.77 10l.01-4.43H0Z\"/>\n", "width": 25, "height": 10, "aspect": 2.5, "attributes": { "viewBox": "0 0 25 10" }, "__srcPath": "/var/www/html/wp-content/themes/example/dist/images/svg/arrow.svg", "_links": { "self": "https://example.com/wp-json/ideasonpurpose/v1/svg/arrow", "collection": "https://example.com/wp-json/ideasonpurpose/v1/svg", "svg": "https://example.com/wp-json/ideasonpurpose/v1/svg/arrow?svg=1", "src": "https://example.com/wp-content/themes/example/dist/images/svg/arrow.svg" } }
Properties:
svg
- A rewrapped SVG with a cleaned subset of attributesinnerContent
- The contents of the SVG with enclosing tags stripped off. Used in the Block Editor in place of pre-processed SVGR objects.width
- Derived width of the file, either extracted from viewBox or read from attributes.height
- Derived height of the file, either extracted from viewBox or read from attributes.aspect
- Convenience value, derived width divided by derived height.attributes
- Array of attributes to appear in the<svg>
tag. Valid attributes include:id
,class
,height
,width
andviewBox
_links
- Array of related URLs:self
collection
(all available SVGs)svg
- Returns withContent-type: image/svg+xml
headers and can be used to display the SVG file directly in the browser.src
- Direct link to the unmodified source SVG file
original_attributes
- The unmodified array of cleaned attributes. Only appears for requests with modified attributes.__srcPath
- Filesystem path of the source SVG. [Debug only]
Removed Attributes and Optimization
All attributes except viewBox
and xmlns
are removed fromclean
valid SVG files, but the unmodified src
files are also available.
Invalid SVGs pass through to src
without modification. Error details will be added to the JSON data object.
Other than the opening <svg>
tag, vector data is not optimized in any way. Please use something like svgo to optimize SVG files.
Shortcodes
In Progress
SVGs can be included by authors and for Full Site Editing using shortcodes.
[svg file-slug]
[svg file-slug height="23" width="auto"]
[svg src="fileSlug" height="23" width="auto" class="hello there"]
A single bare attribute will be treated as the source, but the shortcode prefers named attributes and if a shortcode contains both, the named src
attribute will override the positional info.
In this example, the square
SVG will be shown instead of circle
:
[svg circle src="square"]
Notes
- using
svg
as the Shortcode name may come back to haunt us. But I'd rather keep the shortcode simple and memorable. - Is it necessary to quote shortcode attributes?
-
What happens to invalid SVGs?
- A. No idea? Pass through unchanged? There should be some notification, no quiet failures. (Is that a failure? -- Yes, any deviation from expected behavior should be explained)
-
What happens if there's no viewBox?
- ViewBox will be added if it can be derived from supplied
height
andwidth
attributes. If there are no dimensions and no viewBox, nothing will be added to the opening<svg>
tag.
- ViewBox will be added if it can be derived from supplied
Cleaning Quirks
<svg></svg
is a valid, though useless SVG document. Internally, the cleaner will returned zero for width and height, with an aspect ratio of 1.