From ae139fffb27d3dbdb8d252129918420a40e0f9db Mon Sep 17 00:00:00 2001 From: Donnie D'Amato Date: Tue, 16 Jun 2020 14:46:20 -0400 Subject: [PATCH] Update the docs --- README.md | 18 ++++++++++++++++++ docs/index.html | 16 ++++++++++++++-- docs/index.md | 28 ++++++++++++++++++++++++++++ docs/savager/savager.esm.js | 2 +- docs/savager/savager.umd.js | 2 +- docs/styles.css | 7 ++++++- 6 files changed, 68 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 0c73a27..79e1210 100644 --- a/README.md +++ b/README.md @@ -129,6 +129,24 @@ const { injectionFn } = require('savager'); --- +### `getAssets(assetNames, options)` + +This is a slimmer version of the `prepareAssets()` method on the `Savager` instance. It can be helpful when you've prepared your reference sheet in one part of the app lifecycle but need to generate the assets at another time without needing to import the `symbols` and instanciate another instance. + +This function will not provide a reference sheet, only the `assets` and `inject` (if requested). + +The `consolidate` and `autoAppend` options do nothing here as there is no reference sheet to work with. + +```js +const { getAssets } = require('savager'); + +const { assets } = getAssets(['balloon', 'paperclip'], { externalPath: 'path/to/assets' }); +console.log(assets.balloon); // +console.log(assets.paperclip); // +``` + +--- + ### `createSymbols(pathOrObject)` This method takes a single argument, either a path to SVG files or an object where the keys are asset names (used for look up) and the value is a SVG XML string (``). When using the directory path, the file name will become the asset name. diff --git a/docs/index.html b/docs/index.html index c95fd56..4c2e96d 100644 --- a/docs/index.html +++ b/docs/index.html @@ -1,4 +1,4 @@ -Savager Example Page

Savager

Getting Started

Install the package into your project

npm i savager
+Savager Example Page

Savager

Getting Started

Install the package into your project

npm i savager
 

Run the create-symbols script against your SVG files.

create-symbols -i svg -o assets -t esm
 

Then import Savager and the symbols into your build script. The assets output will contain your new SVG markup!

import Savager from 'savager';
 import symbols from './manifest.js';
@@ -30,7 +30,19 @@
 const savager = new Savager(symbols, { attemptInject: true });
 const { assets, inject } = savager.prepareAssets('balloon');
 

If you need the inject function in a different context from where you prepare assets, you can export it directly from the package. Be sure that when preparing assets, that attemptInject option was set to true. Otherwise, executing the function will do nothing.

import { injectionFn } from 'savager';
-

Examples

Each one of the examples shows the code after initializing an instance of Savager as well as the output to this page with an SVG.

Reference sheets are automatically consolidated under the savager-primarysheet Element by default using consolidate option. This consolidates multiple reference sheets found on the page into a single sheet. For the purposes of example, this option has been set to false so sheets can be inspected within the page. Consolidation is normally an important step to ensure no id is duplicated.


Assets as innerHTML

Creating these assets will return strings. You can export the strings to a render function for templating or just write them as HTML. Remember to add the sheet to the page if the assets are not hosted.

const { assets, sheet } = savager.prepareAssets('bang-triangle');
+

Organization

One method of organizing is to create a savager.config.js which you may maintain as your source of truth for SVG assets.

// savager.config.js
+import Savager from 'savager';
+import symbols from './manifest.js';
+
+export default new Savager(symbols);
+

Then you can prepare assets as needed.

import { prepareAssets } from './savager.config.js';
+
+const { assets, sheet } = prepareAssets('balloon');
+

You may also apply the reference sheet earlier and use the getAssets export from the package to render your assets. This function is independent from the symbols entered into a Savager instance; it just assumes these assets are included in the correct location given the options you provide.

// Assume the reference sheet is on the page
+import { getAssets } from 'savager';
+
+const { assets } = getAssets('balloon');
+

Options related to reference sheet management (consolidate, autoAppend) do not affect these assets.

Examples

Each one of the examples shows the code after initializing an instance of Savager as well as the output to this page with an SVG.

Reference sheets are automatically consolidated under the savager-primarysheet Element by default using consolidate option. This consolidates multiple reference sheets found on the page into a single sheet. For the purposes of example, this option has been set to false so sheets can be inspected within the page. Consolidation is normally an important step to ensure no id is duplicated.


Assets as innerHTML

Creating these assets will return strings. You can export the strings to a render function for templating or just write them as HTML. Remember to add the sheet to the page if the assets are not hosted.

const { assets, sheet } = savager.prepareAssets('bang-triangle');
 
 /* Add the reference sheet to the page */
 const sheetContainer = document.createElement('div');
diff --git a/docs/index.md b/docs/index.md
index 10c08a3..6928d3c 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -88,6 +88,34 @@ If you need the `inject` function in a different context from where you prepare
 import { injectionFn } from 'savager';
 ```
 
+## Organization
+One method of organizing is to create a `savager.config.js` which you may maintain as your source of truth for SVG assets.
+
+```js
+// savager.config.js
+import Savager from 'savager';
+import symbols from './manifest.js';
+
+export default new Savager(symbols);
+```
+
+Then you can prepare assets as needed.
+
+```js
+import { prepareAssets } from './savager.config.js';
+
+const { assets, sheet } = prepareAssets('balloon');
+```
+
+You may also apply the reference sheet earlier and use the `getAssets` export from the package to render your assets. This function is independent from the `symbols` entered into a `Savager` instance; it just assumes these assets are included in the correct location given the options you provide.
+
+```js
+// Assume the reference sheet is on the page
+import { getAssets } from 'savager';
+
+const { assets } = getAssets('balloon');
+```
+Options related to reference sheet management (`consolidate`, `autoAppend`) do not affect these assets.
 
 ## Examples
 
diff --git a/docs/savager/savager.esm.js b/docs/savager/savager.esm.js
index b391745..f2ef0ab 100644
--- a/docs/savager/savager.esm.js
+++ b/docs/savager/savager.esm.js
@@ -1 +1 @@
-function e(e,t){const r=document.getElementById(e);if(!r)return;t||(t="savager-primarysheet");let n=document.getElementById(t);n||(n=document.createElementNS("http://www.w3.org/2000/svg","svg"),n.id=t,n.style.display="none",document.body.appendChild(n)),Array.prototype.slice.call(r.querySelectorAll("symbol")).forEach(e=>{!n.getElementById(e.id)&&n.appendChild(e)}),r.remove()}var t="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};var r=function(e,t,r){return e(r={path:t,exports:{},require:function(e,t){return function(){throw new Error("Dynamic requires are not currently supported by @rollup/plugin-commonjs")}(null==t&&r.path)}},r.exports),r.exports}((function(e){var r,n;r=t,n=function(){function e(e){var t=[];if(0===e.length)return"";if("string"!=typeof e[0])throw new TypeError("Url must be a string. Received "+e[0]);if(e[0].match(/^[^/:]+:\/*$/)&&e.length>1){var r=e.shift();e[0]=r+e[0]}e[0].match(/^file:\/\/\//)?e[0]=e[0].replace(/^([^/:]+):\/*/,"$1:///"):e[0]=e[0].replace(/^([^/:]+):\/*/,"$1://");for(var n=0;n0&&(o=o.replace(/^[\/]+/,"")),o=n0?"?":"")+i.join("&")}return function(){return e("object"==typeof arguments[0]?arguments[0]:[].slice.call(arguments))}},e.exports?e.exports=n():r.urljoin=n()}));class n{constructor(){this._registrar={}}get(e){return this._registrar[e]}replace(e){const{url:t,exposure:r,id:n}=this._parseNode(e);if(this.get(n))return Promise.resolve(this._replace(e,n));if("internal"===r){return e.getRootNode().getElementById(n)?Promise.resolve("Reference found in root, replacement halted."):this._embedInternal(e,{id:n})}return"external"===r?this._embedExternal(e,{id:n,url:t}):Promise.reject("Could not find asset reference. Ensure the reference sheet or external url exist before executing this script")}_replace(e,t){const r=this.get(t).cloneNode(!0);r.removeAttribute("id"),r.setAttribute("replaced","");const n=e.parentNode;return[...n.attributes].forEach(({name:e,value:t})=>r.setAttribute(e,t)),n.replaceWith(r),r}register(e,t,r){return this._registrar[t]=r,this._replace(e,t)}_embedInternal(e,{id:t}){const r=document.getElementById(t);if(r){const n=r.cloneNode(!0);return Promise.resolve(this.register(e,t,this._transformSymbol(n)))}return Promise.reject(`Symbol "${t}" not found in document.`)}_embedExternal(e,{id:t,url:r}){return window.fetch(r).then(e=>e.text()).then(r=>{const n=(new DOMParser).parseFromString(r,"image/svg+xml").querySelector("symbol");if(n)return this.register(e,t,this._transformSymbol(n));throw new Error("Malformed external reference, please ensure '' assets.")}).catch(e=>console.error(e))}_parseNode(e){const t=e.getAttribute("href");if(!t)return{};const[r,n]=t.split("#");let o=e.getAttribute("exposure");return o||(o=Boolean(r)?"external":"internal"),{url:t,exposure:o,id:n}}_transformSymbol(e){const t=document.createElementNS("http://www.w3.org/2000/svg","svg");return e.children&&[...e.children].forEach(e=>t.appendChild(e)),e.hasAttributes()&&[...e.attributes].forEach(({name:e,value:r})=>t.setAttribute(e,r)),t}}const o="window.svgInjectionManager && window.svgInjectionManager.replace(this)",s={style:"animation: nodeDetected .1ms",onanimationstart:o,onerror:o},i=()=>{if("undefined"!=typeof window)return window.svgInjectionManager=new n,window.svgInjectionManager};class a{constructor(e,t){this._symbols={},this._options=Object.assign({},t),this.storeSymbols(e)}prepareAssets(t,n){const{externalPath:o,attemptInject:a,classNames:l,toSvgElement:d,consolidate:p,autoAppend:m}=Object.assign(n||{},this._options),g={xmlns:"http://www.w3.org/2000/svg"},f={prepareConsolidation:void 0===p||Boolean(p)};f.prepareConsolidation&&(f.primarySheetId="string"==typeof p?p.toString():"savager-primarysheet");const h={};a&&(h.inject=i),l&&(g.class=[].concat(l).filter(Boolean).join(" "));let y=e=>e;d&&(y="function"==typeof d?d:u);const w=[].concat(t).reduce((function(e,t){const n=Object.assign({exposure:"internal"},g);let i={href:"#"+t};"string"==typeof o&&(n.exposure="external",i.href=r(o,t+".svg",i.href));let l="";a&&(l="",i=Object.assign(i,s));const u=`${l}`;return Object.assign(e,{[t]:u})}),{}),b=this._symbols;let v=Object.keys(w).reduce((function(e,t){return b&&b[t]?e+b[t].replace(/<\/?svg ?[^>]*>/gim,""):e}),"");if(h.assets=Object.entries(w).reduce((function(e,[t,r]){return Object.assign(e,{[t]:y(r)})}),{}),v&&!o){const{sheet:t}=function(t,r){const{prepareConsolidation:n,primarySheetId:o}=r,s="savager-"+Math.random().toString(36).substr(2,9),i=`id="${s}" xmlns="http://www.w3.org/2000/svg" style="display:none;"`;let a="";if(n){const t=`(${e.toString()})('${s}', '${o}')`.replace(/\"/g,"'");a=``}return{sheet:`${a}${t}`}}(v,f);h.sheet=y(t),m&&function(e){if("undefined"==typeof document||!document.createElement)throw new Error("Attempted to autoAppend without browser context");document.body.appendChild(u(e))}(t)}return h}storeSymbols(e){return this._symbols=Object.assign({},this._symbols,e),this}}function c(e){return Object.entries(e).map(([e,t])=>`${e}="${t}"`).join(" ")}let l;function u(e){if("undefined"!=typeof document&&document.createElement){l||(l=document.createElement("div")),l.innerHTML=e;const t=document.createDocumentFragment();return[...l.children].forEach(e=>t.appendChild(e)),t}return e}async function d(e){if("string"!=typeof e){if("object"==typeof e)return Object.entries(e).reduce((e,[t,r])=>Object.assign(e,{[t]:p(r,t)}),{});throw new Error("Unknown argument provided. Must be an object or path to files.",e)}{if("undefined"!=typeof window||!require)throw new Error("Can only create symbols using path within node environment.");const t=require("path"),r=require("fs");try{const n=await r.promises.readdir(e),o=await Promise.all(n.map(async n=>({[t.parse(n).name]:(await r.promises.readFile(t.resolve(e,n))).toString()})));return d(o.reduce((e,t)=>Object.assign(e,t),{}))}catch(e){throw new Error(e)}}}function p(e,t){let r='xmlns="http://www.w3.org/2000/svg"';const n=e.replace(/(xmlns=.[^"']+)./gim,e=>(r=e,"")).replace(/(<\/?)svg/gim,"$1symbol").replace(/${n}`.replace(/\r?\n|\r|/g,"").replace(/ {2,}/g," ")}const m=a;export default a;export{m as Savager,d as createSymbols,i as injectionFn};
+var e="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};var t=function(e,t,r){return e(r={path:t,exports:{},require:function(e,t){return function(){throw new Error("Dynamic requires are not currently supported by @rollup/plugin-commonjs")}(null==t&&r.path)}},r.exports),r.exports}((function(t){var r,n;r=e,n=function(){function e(e){var t=[];if(0===e.length)return"";if("string"!=typeof e[0])throw new TypeError("Url must be a string. Received "+e[0]);if(e[0].match(/^[^/:]+:\/*$/)&&e.length>1){var r=e.shift();e[0]=r+e[0]}e[0].match(/^file:\/\/\//)?e[0]=e[0].replace(/^([^/:]+):\/*/,"$1:///"):e[0]=e[0].replace(/^([^/:]+):\/*/,"$1://");for(var n=0;n0&&(o=o.replace(/^[\/]+/,"")),o=n0?"?":"")+i.join("&")}return function(){return e("object"==typeof arguments[0]?arguments[0]:[].slice.call(arguments))}},t.exports?t.exports=n():r.urljoin=n()}));let r;function n(e){if("undefined"!=typeof document&&document.createElement){r||(r=document.createElement("div")),r.innerHTML=e;const t=document.createDocumentFragment();return[...r.children].forEach(e=>t.appendChild(e)),t}return e}class o{constructor(){this._registrar={}}get(e){return this._registrar[e]}replace(e){const{url:t,exposure:r,id:n}=this._parseNode(e);if(this.get(n))return Promise.resolve(this._replace(e,n));if("internal"===r){return e.getRootNode().getElementById(n)?Promise.resolve("Reference found in root, replacement halted."):this._embedInternal(e,{id:n})}return"external"===r?this._embedExternal(e,{id:n,url:t}):Promise.reject("Could not find asset reference. Ensure the reference sheet or external url exist before executing this script")}_replace(e,t){const r=this.get(t).cloneNode(!0);r.removeAttribute("id"),r.setAttribute("replaced","");const n=e.parentNode;return[...n.attributes].forEach(({name:e,value:t})=>r.setAttribute(e,t)),n.replaceWith(r),r}register(e,t,r){return this._registrar[t]=r,this._replace(e,t)}_embedInternal(e,{id:t}){const r=document.getElementById(t);if(r){const n=r.cloneNode(!0);return Promise.resolve(this.register(e,t,this._transformSymbol(n)))}return Promise.reject(`Symbol "${t}" not found in document.`)}_embedExternal(e,{id:t,url:r}){return window.fetch(r).then(e=>e.text()).then(r=>{const n=(new DOMParser).parseFromString(r,"image/svg+xml").querySelector("symbol");if(n)return this.register(e,t,this._transformSymbol(n));throw new Error("Malformed external reference, please ensure '' assets.")}).catch(e=>console.error(e))}_parseNode(e){const t=e.getAttribute("href");if(!t)return{};const[r,n]=t.split("#");let o=e.getAttribute("exposure");return o||(o=Boolean(r)?"external":"internal"),{url:t,exposure:o,id:n}}_transformSymbol(e){const t=document.createElementNS("http://www.w3.org/2000/svg","svg");return e.children&&[...e.children].forEach(e=>t.appendChild(e)),e.hasAttributes()&&[...e.attributes].forEach(({name:e,value:r})=>t.setAttribute(e,r)),t}}const s="window.svgInjectionManager && window.svgInjectionManager.replace(this)",i={style:"animation: nodeDetected .1ms",onanimationstart:s,onerror:s},a=()=>{if("undefined"!=typeof window)return window.svgInjectionManager=new o,window.svgInjectionManager};function c(e,r){const{externalPath:o,attemptInject:s,classNames:c,toSvgElement:u}=r||{},d={xmlns:"http://www.w3.org/2000/svg"},p={};s&&(p.inject=a),c&&(d.class=[].concat(c).filter(Boolean).join(" "));let m=e=>e;u&&(m="function"==typeof u?u:n);const g=[].concat(e).reduce((function(e,r){const n=Object.assign({exposure:"internal"},d);let a={href:"#"+r};"string"==typeof o&&(n.exposure="external",a.href=t(o,r+".svg",a.href));let c="";s&&(c="",a=Object.assign(a,i));const u=`${c}`;return Object.assign(e,{[r]:u})}),{});return p.assets=Object.entries(g).reduce((function(e,[t,r]){return Object.assign(e,{[t]:m(r)})}),{}),p}function l(e){return Object.entries(e).map(([e,t])=>`${e}="${t}"`).join(" ")}function u(e,t){const r=document.getElementById(e);if(!r)return;t||(t="savager-primarysheet");let n=document.getElementById(t);n||(n=document.createElementNS("http://www.w3.org/2000/svg","svg"),n.id=t,n.style.display="none",document.body.appendChild(n)),Array.prototype.slice.call(r.querySelectorAll("symbol")).forEach(e=>{!n.getElementById(e.id)&&n.appendChild(e)}),r.remove()}class d{constructor(e,t){this._symbols={},this._options=Object.assign({},t),this.storeSymbols(e)}prepareAssets(e,t){const{consolidate:r,autoAppend:o,...s}=Object.assign(t||{},this._options);let i=e=>e;s.toSvgElement&&(i="function"==typeof s.toSvgElement?s.toSvgElement:n);const a=c(e,s),l={prepareConsolidation:void 0===r||Boolean(r)};l.prepareConsolidation&&(l.primarySheetId="string"==typeof r?r.toString():"savager-primarysheet");const d=this._symbols;let p=Object.keys(a.assets).reduce((function(e,t){return d&&d[t]?e+d[t].replace(/<\/?svg ?[^>]*>/gim,""):e}),"");if(p&&!s.externalPath){const{sheet:e}=function(e,t){const{prepareConsolidation:r,primarySheetId:n}=t,o="savager-"+Math.random().toString(36).substr(2,9),s=`id="${o}" xmlns="http://www.w3.org/2000/svg" style="display:none;"`;let i="";if(r){const e=`(${u.toString()})('${o}', '${n}')`.replace(/\"/g,"'");i=``}return{sheet:`${i}${e}`}}(p,l);a.sheet=i(e),o&&function(e){if("undefined"==typeof document||!document.createElement)throw new Error("Attempted to autoAppend without browser context");document.body.appendChild(n(e))}(e)}return a}storeSymbols(e){return this._symbols=Object.assign({},this._symbols,e),this}}async function p(e){if("string"!=typeof e){if("object"==typeof e)return Object.entries(e).reduce((e,[t,r])=>Object.assign(e,{[t]:m(r,t)}),{});throw new Error("Unknown argument provided. Must be an object or path to files.",e)}{if("undefined"!=typeof window||!require)throw new Error("Can only create symbols using path within node environment.");const t=require("path"),r=require("fs");try{const n=await r.promises.readdir(e),o=await Promise.all(n.map(async n=>({[t.parse(n).name]:(await r.promises.readFile(t.resolve(e,n))).toString()})));return p(o.reduce((e,t)=>Object.assign(e,t),{}))}catch(e){throw new Error(e)}}}function m(e,t){let r='xmlns="http://www.w3.org/2000/svg"';const n=e.replace(/(xmlns=.[^"']+)./gim,e=>(r=e,"")).replace(/(<\/?)svg/gim,"$1symbol").replace(/${n}`.replace(/\r?\n|\r|/g,"").replace(/ {2,}/g," ")}const g=d;export default d;export{g as Savager,p as createSymbols,c as getAssets,a as injectionFn};
diff --git a/docs/savager/savager.umd.js b/docs/savager/savager.umd.js
index 8a886ba..27539fa 100644
--- a/docs/savager/savager.umd.js
+++ b/docs/savager/savager.umd.js
@@ -1 +1 @@
-!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e=e||self).Savager={})}(this,(function(e){"use strict";function t(e,t){const r=document.getElementById(e);if(!r)return;t||(t="savager-primarysheet");let n=document.getElementById(t);n||(n=document.createElementNS("http://www.w3.org/2000/svg","svg"),n.id=t,n.style.display="none",document.body.appendChild(n)),Array.prototype.slice.call(r.querySelectorAll("symbol")).forEach(e=>{!n.getElementById(e.id)&&n.appendChild(e)}),r.remove()}var r="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};var n=function(e,t,r){return e(r={path:t,exports:{},require:function(e,t){return function(){throw new Error("Dynamic requires are not currently supported by @rollup/plugin-commonjs")}(null==t&&r.path)}},r.exports),r.exports}((function(e){var t,n;t=r,n=function(){function e(e){var t=[];if(0===e.length)return"";if("string"!=typeof e[0])throw new TypeError("Url must be a string. Received "+e[0]);if(e[0].match(/^[^/:]+:\/*$/)&&e.length>1){var r=e.shift();e[0]=r+e[0]}e[0].match(/^file:\/\/\//)?e[0]=e[0].replace(/^([^/:]+):\/*/,"$1:///"):e[0]=e[0].replace(/^([^/:]+):\/*/,"$1://");for(var n=0;n0&&(o=o.replace(/^[\/]+/,"")),o=n0?"?":"")+i.join("&")}return function(){return e("object"==typeof arguments[0]?arguments[0]:[].slice.call(arguments))}},e.exports?e.exports=n():t.urljoin=n()}));class o{constructor(){this._registrar={}}get(e){return this._registrar[e]}replace(e){const{url:t,exposure:r,id:n}=this._parseNode(e);if(this.get(n))return Promise.resolve(this._replace(e,n));if("internal"===r){return e.getRootNode().getElementById(n)?Promise.resolve("Reference found in root, replacement halted."):this._embedInternal(e,{id:n})}return"external"===r?this._embedExternal(e,{id:n,url:t}):Promise.reject("Could not find asset reference. Ensure the reference sheet or external url exist before executing this script")}_replace(e,t){const r=this.get(t).cloneNode(!0);r.removeAttribute("id"),r.setAttribute("replaced","");const n=e.parentNode;return[...n.attributes].forEach(({name:e,value:t})=>r.setAttribute(e,t)),n.replaceWith(r),r}register(e,t,r){return this._registrar[t]=r,this._replace(e,t)}_embedInternal(e,{id:t}){const r=document.getElementById(t);if(r){const n=r.cloneNode(!0);return Promise.resolve(this.register(e,t,this._transformSymbol(n)))}return Promise.reject(`Symbol "${t}" not found in document.`)}_embedExternal(e,{id:t,url:r}){return window.fetch(r).then(e=>e.text()).then(r=>{const n=(new DOMParser).parseFromString(r,"image/svg+xml").querySelector("symbol");if(n)return this.register(e,t,this._transformSymbol(n));throw new Error("Malformed external reference, please ensure '' assets.")}).catch(e=>console.error(e))}_parseNode(e){const t=e.getAttribute("href");if(!t)return{};const[r,n]=t.split("#");let o=e.getAttribute("exposure");return o||(o=Boolean(r)?"external":"internal"),{url:t,exposure:o,id:n}}_transformSymbol(e){const t=document.createElementNS("http://www.w3.org/2000/svg","svg");return e.children&&[...e.children].forEach(e=>t.appendChild(e)),e.hasAttributes()&&[...e.attributes].forEach(({name:e,value:r})=>t.setAttribute(e,r)),t}}const s="window.svgInjectionManager && window.svgInjectionManager.replace(this)",i={style:"animation: nodeDetected .1ms",onanimationstart:s,onerror:s},a=()=>{if("undefined"!=typeof window)return window.svgInjectionManager=new o,window.svgInjectionManager};class c{constructor(e,t){this._symbols={},this._options=Object.assign({},t),this.storeSymbols(e)}prepareAssets(e,r){const{externalPath:o,attemptInject:s,classNames:c,toSvgElement:u,consolidate:p,autoAppend:f}=Object.assign(r||{},this._options),m={xmlns:"http://www.w3.org/2000/svg"},g={prepareConsolidation:void 0===p||Boolean(p)};g.prepareConsolidation&&(g.primarySheetId="string"==typeof p?p.toString():"savager-primarysheet");const h={};s&&(h.inject=a),c&&(m.class=[].concat(c).filter(Boolean).join(" "));let y=e=>e;u&&(y="function"==typeof u?u:d);const w=[].concat(e).reduce((function(e,t){const r=Object.assign({exposure:"internal"},m);let a={href:"#"+t};"string"==typeof o&&(r.exposure="external",a.href=n(o,t+".svg",a.href));let c="";s&&(c="",a=Object.assign(a,i));const u=`${c}`;return Object.assign(e,{[t]:u})}),{}),b=this._symbols;let v=Object.keys(w).reduce((function(e,t){return b&&b[t]?e+b[t].replace(/<\/?svg ?[^>]*>/gim,""):e}),"");if(h.assets=Object.entries(w).reduce((function(e,[t,r]){return Object.assign(e,{[t]:y(r)})}),{}),v&&!o){const{sheet:e}=function(e,r){const{prepareConsolidation:n,primarySheetId:o}=r,s="savager-"+Math.random().toString(36).substr(2,9),i=`id="${s}" xmlns="http://www.w3.org/2000/svg" style="display:none;"`;let a="";if(n){const e=`(${t.toString()})('${s}', '${o}')`.replace(/\"/g,"'");a=``}return{sheet:`${a}${e}`}}(v,g);h.sheet=y(e),f&&function(e){if("undefined"==typeof document||!document.createElement)throw new Error("Attempted to autoAppend without browser context");document.body.appendChild(d(e))}(e)}return h}storeSymbols(e){return this._symbols=Object.assign({},this._symbols,e),this}}function l(e){return Object.entries(e).map(([e,t])=>`${e}="${t}"`).join(" ")}let u;function d(e){if("undefined"!=typeof document&&document.createElement){u||(u=document.createElement("div")),u.innerHTML=e;const t=document.createDocumentFragment();return[...u.children].forEach(e=>t.appendChild(e)),t}return e}function p(e,t){let r='xmlns="http://www.w3.org/2000/svg"';const n=e.replace(/(xmlns=.[^"']+)./gim,e=>(r=e,"")).replace(/(<\/?)svg/gim,"$1symbol").replace(/${n}`.replace(/\r?\n|\r|/g,"").replace(/ {2,}/g," ")}const f=c;e.Savager=f,e.createSymbols=async function e(t){if("string"!=typeof t){if("object"==typeof t)return Object.entries(t).reduce((e,[t,r])=>Object.assign(e,{[t]:p(r,t)}),{});throw new Error("Unknown argument provided. Must be an object or path to files.",t)}{if("undefined"!=typeof window||!require)throw new Error("Can only create symbols using path within node environment.");const r=require("path"),n=require("fs");try{const o=await n.promises.readdir(t),s=await Promise.all(o.map(async e=>({[r.parse(e).name]:(await n.promises.readFile(r.resolve(t,e))).toString()})));return e(s.reduce((e,t)=>Object.assign(e,t),{}))}catch(e){throw new Error(e)}}},e.default=c,e.injectionFn=a,Object.defineProperty(e,"__esModule",{value:!0})}));
+!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e=e||self).Savager={})}(this,(function(e){"use strict";var t="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};var r=function(e,t,r){return e(r={path:t,exports:{},require:function(e,t){return function(){throw new Error("Dynamic requires are not currently supported by @rollup/plugin-commonjs")}(null==t&&r.path)}},r.exports),r.exports}((function(e){var r,n;r=t,n=function(){function e(e){var t=[];if(0===e.length)return"";if("string"!=typeof e[0])throw new TypeError("Url must be a string. Received "+e[0]);if(e[0].match(/^[^/:]+:\/*$/)&&e.length>1){var r=e.shift();e[0]=r+e[0]}e[0].match(/^file:\/\/\//)?e[0]=e[0].replace(/^([^/:]+):\/*/,"$1:///"):e[0]=e[0].replace(/^([^/:]+):\/*/,"$1://");for(var n=0;n0&&(o=o.replace(/^[\/]+/,"")),o=n0?"?":"")+i.join("&")}return function(){return e("object"==typeof arguments[0]?arguments[0]:[].slice.call(arguments))}},e.exports?e.exports=n():r.urljoin=n()}));let n;function o(e){if("undefined"!=typeof document&&document.createElement){n||(n=document.createElement("div")),n.innerHTML=e;const t=document.createDocumentFragment();return[...n.children].forEach(e=>t.appendChild(e)),t}return e}class s{constructor(){this._registrar={}}get(e){return this._registrar[e]}replace(e){const{url:t,exposure:r,id:n}=this._parseNode(e);if(this.get(n))return Promise.resolve(this._replace(e,n));if("internal"===r){return e.getRootNode().getElementById(n)?Promise.resolve("Reference found in root, replacement halted."):this._embedInternal(e,{id:n})}return"external"===r?this._embedExternal(e,{id:n,url:t}):Promise.reject("Could not find asset reference. Ensure the reference sheet or external url exist before executing this script")}_replace(e,t){const r=this.get(t).cloneNode(!0);r.removeAttribute("id"),r.setAttribute("replaced","");const n=e.parentNode;return[...n.attributes].forEach(({name:e,value:t})=>r.setAttribute(e,t)),n.replaceWith(r),r}register(e,t,r){return this._registrar[t]=r,this._replace(e,t)}_embedInternal(e,{id:t}){const r=document.getElementById(t);if(r){const n=r.cloneNode(!0);return Promise.resolve(this.register(e,t,this._transformSymbol(n)))}return Promise.reject(`Symbol "${t}" not found in document.`)}_embedExternal(e,{id:t,url:r}){return window.fetch(r).then(e=>e.text()).then(r=>{const n=(new DOMParser).parseFromString(r,"image/svg+xml").querySelector("symbol");if(n)return this.register(e,t,this._transformSymbol(n));throw new Error("Malformed external reference, please ensure '' assets.")}).catch(e=>console.error(e))}_parseNode(e){const t=e.getAttribute("href");if(!t)return{};const[r,n]=t.split("#");let o=e.getAttribute("exposure");return o||(o=Boolean(r)?"external":"internal"),{url:t,exposure:o,id:n}}_transformSymbol(e){const t=document.createElementNS("http://www.w3.org/2000/svg","svg");return e.children&&[...e.children].forEach(e=>t.appendChild(e)),e.hasAttributes()&&[...e.attributes].forEach(({name:e,value:r})=>t.setAttribute(e,r)),t}}const i="window.svgInjectionManager && window.svgInjectionManager.replace(this)",a={style:"animation: nodeDetected .1ms",onanimationstart:i,onerror:i},c=()=>{if("undefined"!=typeof window)return window.svgInjectionManager=new s,window.svgInjectionManager};function l(e,t){const{externalPath:n,attemptInject:s,classNames:i,toSvgElement:l}=t||{},d={xmlns:"http://www.w3.org/2000/svg"},p={};s&&(p.inject=c),i&&(d.class=[].concat(i).filter(Boolean).join(" "));let f=e=>e;l&&(f="function"==typeof l?l:o);const m=[].concat(e).reduce((function(e,t){const o=Object.assign({exposure:"internal"},d);let i={href:"#"+t};"string"==typeof n&&(o.exposure="external",i.href=r(n,t+".svg",i.href));let c="";s&&(c="",i=Object.assign(i,a));const l=`${c}`;return Object.assign(e,{[t]:l})}),{});return p.assets=Object.entries(m).reduce((function(e,[t,r]){return Object.assign(e,{[t]:f(r)})}),{}),p}function u(e){return Object.entries(e).map(([e,t])=>`${e}="${t}"`).join(" ")}function d(e,t){const r=document.getElementById(e);if(!r)return;t||(t="savager-primarysheet");let n=document.getElementById(t);n||(n=document.createElementNS("http://www.w3.org/2000/svg","svg"),n.id=t,n.style.display="none",document.body.appendChild(n)),Array.prototype.slice.call(r.querySelectorAll("symbol")).forEach(e=>{!n.getElementById(e.id)&&n.appendChild(e)}),r.remove()}class p{constructor(e,t){this._symbols={},this._options=Object.assign({},t),this.storeSymbols(e)}prepareAssets(e,t){const{consolidate:r,autoAppend:n,...s}=Object.assign(t||{},this._options);let i=e=>e;s.toSvgElement&&(i="function"==typeof s.toSvgElement?s.toSvgElement:o);const a=l(e,s),c={prepareConsolidation:void 0===r||Boolean(r)};c.prepareConsolidation&&(c.primarySheetId="string"==typeof r?r.toString():"savager-primarysheet");const u=this._symbols;let p=Object.keys(a.assets).reduce((function(e,t){return u&&u[t]?e+u[t].replace(/<\/?svg ?[^>]*>/gim,""):e}),"");if(p&&!s.externalPath){const{sheet:e}=function(e,t){const{prepareConsolidation:r,primarySheetId:n}=t,o="savager-"+Math.random().toString(36).substr(2,9),s=`id="${o}" xmlns="http://www.w3.org/2000/svg" style="display:none;"`;let i="";if(r){const e=`(${d.toString()})('${o}', '${n}')`.replace(/\"/g,"'");i=``}return{sheet:`${i}${e}`}}(p,c);a.sheet=i(e),n&&function(e){if("undefined"==typeof document||!document.createElement)throw new Error("Attempted to autoAppend without browser context");document.body.appendChild(o(e))}(e)}return a}storeSymbols(e){return this._symbols=Object.assign({},this._symbols,e),this}}function f(e,t){let r='xmlns="http://www.w3.org/2000/svg"';const n=e.replace(/(xmlns=.[^"']+)./gim,e=>(r=e,"")).replace(/(<\/?)svg/gim,"$1symbol").replace(/${n}`.replace(/\r?\n|\r|/g,"").replace(/ {2,}/g," ")}const m=p;e.Savager=m,e.createSymbols=async function e(t){if("string"!=typeof t){if("object"==typeof t)return Object.entries(t).reduce((e,[t,r])=>Object.assign(e,{[t]:f(r,t)}),{});throw new Error("Unknown argument provided. Must be an object or path to files.",t)}{if("undefined"!=typeof window||!require)throw new Error("Can only create symbols using path within node environment.");const r=require("path"),n=require("fs");try{const o=await n.promises.readdir(t),s=await Promise.all(o.map(async e=>({[r.parse(e).name]:(await n.promises.readFile(r.resolve(t,e))).toString()})));return e(s.reduce((e,t)=>Object.assign(e,t),{}))}catch(e){throw new Error(e)}}},e.default=p,e.getAssets=l,e.injectionFn=c,Object.defineProperty(e,"__esModule",{value:!0})}));
diff --git a/docs/styles.css b/docs/styles.css
index af97d25..052ded6 100644
--- a/docs/styles.css
+++ b/docs/styles.css
@@ -62,8 +62,13 @@ pre {
 }
 
 :not(pre) > code {
-  font-size: 1.3em;
+  font-size: 1em;
   color: var(--accentColor);
+  vertical-align: 0.2em;
+  border: 1px solid rgba(255, 255, 255, .1);
+  background: rgba(0, 0, 0, .1);
+  padding: 2px 4px;
+  border-radius: 4px;
 }
 
 .token.string,