local-svg 0.0.7 → 0.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +2 -3
- package/dist/index.d.ts +2 -3
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -4
package/dist/index.d.mts
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { SVGAttributes } from 'react';
|
|
3
3
|
|
|
4
|
-
type LocalSvgNames = string;
|
|
5
4
|
type LocalSvgProps = SVGAttributes<SVGSVGElement> & {
|
|
6
|
-
name: LocalSvgNames;
|
|
5
|
+
name: LocalSvg.LocalSvgNames;
|
|
7
6
|
baseUrl?: string;
|
|
8
7
|
as?: React.ElementType;
|
|
9
8
|
};
|
|
10
9
|
declare const LocalSvg: react.NamedExoticComponent<SVGAttributes<SVGSVGElement> & {
|
|
11
|
-
name: LocalSvgNames;
|
|
10
|
+
name: LocalSvg.LocalSvgNames;
|
|
12
11
|
baseUrl?: string;
|
|
13
12
|
as?: React.ElementType;
|
|
14
13
|
} & react.RefAttributes<SVGSVGElement>>;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
2
|
import { SVGAttributes } from 'react';
|
|
3
3
|
|
|
4
|
-
type LocalSvgNames = string;
|
|
5
4
|
type LocalSvgProps = SVGAttributes<SVGSVGElement> & {
|
|
6
|
-
name: LocalSvgNames;
|
|
5
|
+
name: LocalSvg.LocalSvgNames;
|
|
7
6
|
baseUrl?: string;
|
|
8
7
|
as?: React.ElementType;
|
|
9
8
|
};
|
|
10
9
|
declare const LocalSvg: react.NamedExoticComponent<SVGAttributes<SVGSVGElement> & {
|
|
11
|
-
name: LocalSvgNames;
|
|
10
|
+
name: LocalSvg.LocalSvgNames;
|
|
12
11
|
baseUrl?: string;
|
|
13
12
|
as?: React.ElementType;
|
|
14
13
|
} & react.RefAttributes<SVGSVGElement>>;
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var S=Object.defineProperty,z=Object.defineProperties,U=Object.getOwnPropertyDescriptor,V=Object.getOwnPropertyDescriptors,M=Object.getOwnPropertyNames,T=Object.getOwnPropertySymbols;var A=Object.prototype.hasOwnProperty,b=Object.prototype.propertyIsEnumerable;var v=(t,e,r)=>e in t?S(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r,d=(t,e)=>{for(var r in e||(e={}))A.call(e,r)&&v(t,r,e[r]);if(T)for(var r of T(e))b.call(e,r)&&v(t,r,e[r]);return t},I=(t,e)=>z(t,V(e));var R=(t,e)=>{var r={};for(var n in t)A.call(t,n)&&e.indexOf(n)<0&&(r[n]=t[n]);if(t!=null&&T)for(var n of T(t))e.indexOf(n)<0&&b.call(t,n)&&(r[n]=t[n]);return r};var Z=(t,e)=>{for(var r in e)S(t,r,{get:e[r],enumerable:!0})},X=(t,e,r,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of M(e))!A.call(t,s)&&s!==r&&S(t,s,{get:()=>e[s],enumerable:!(n=U(e,s))||n.enumerable});return t};var W=t=>X(S({},"__esModule",{value:!0}),t);var l=(t,e,r)=>new Promise((n,s)=>{var c=a=>{try{o(r.next(a))}catch(
|
|
1
|
+
var S=Object.defineProperty,z=Object.defineProperties,U=Object.getOwnPropertyDescriptor,V=Object.getOwnPropertyDescriptors,M=Object.getOwnPropertyNames,T=Object.getOwnPropertySymbols;var A=Object.prototype.hasOwnProperty,b=Object.prototype.propertyIsEnumerable;var v=(t,e,r)=>e in t?S(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r,d=(t,e)=>{for(var r in e||(e={}))A.call(e,r)&&v(t,r,e[r]);if(T)for(var r of T(e))b.call(e,r)&&v(t,r,e[r]);return t},I=(t,e)=>z(t,V(e));var R=(t,e)=>{var r={};for(var n in t)A.call(t,n)&&e.indexOf(n)<0&&(r[n]=t[n]);if(t!=null&&T)for(var n of T(t))e.indexOf(n)<0&&b.call(t,n)&&(r[n]=t[n]);return r};var Z=(t,e)=>{for(var r in e)S(t,r,{get:e[r],enumerable:!0})},X=(t,e,r,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of M(e))!A.call(t,s)&&s!==r&&S(t,s,{get:()=>e[s],enumerable:!(n=U(e,s))||n.enumerable});return t};var W=t=>X(S({},"__esModule",{value:!0}),t);var l=(t,e,r)=>new Promise((n,s)=>{var c=a=>{try{o(r.next(a))}catch(u){s(u)}},i=a=>{try{o(r.throw(a))}catch(u){s(u)}},o=a=>a.done?n(a.value):Promise.resolve(a.value).then(c,i);o((r=r.apply(t,e)).next())});var Y={};Z(Y,{LocalSvg:()=>O});module.exports=W(Y);var g=require("react");var C=require("react");function N(t,e=null,r={},n="0"){return typeof t=="string"?t:(0,C.createElement)(t.type,I(d(d({},t.props),r),{ref:e,key:n}),...t.children.map((s,c)=>N(s,null,{},`${n}-${c}`)))}function P(t){if(!t)return"";let e=t.replace(/\n|\r|\t/g,"").replace(/\s{2,}/g," ").replace(/\s*(=)\s*"/g,'="').replace(/class="[^"]+"/g,"").replace(/<!--.*?-->/g,"").replace(/\sxmlns(?::[a-zA-Z0-9_-]+)?="[^"]*"/g,"").replace(/<\?xml[^>]*>/g,"").replace(/<metadata>.*?<\/metadata>/g,"").replace(/<(\w+)([^>]*)><\/\1>/g,"<$1$2/>").trim(),r=/id="([^"]{8,})"/g,n,s={},c=0;for(;(n=r.exec(e))!==null;){let i=n[1];s[i]||(s[i]=c.toString(),c++)}for(let i in s){let[o,a]=[i,s[i]],u=new RegExp(`id="${o}"`,"g");e=e.replace(u,`id="${a}"`);let m=new RegExp(`url\\(#${o}\\)`,"g");e=e.replace(m,`url(#${a})`)}return s={},e}var y=class{constructor(e,r){this.name=e;this.value=r}},F=[[/^\s+/,null],[/^<\?xml[^]*\?>/,null],[/^<!--[\s\S]*?-->/,null],[/^<[a-zA-Z_][\w\-.]*(?::[a-zA-Z_][\w\-.]*)?(?=[\s>/>])/,"BEGIN_TAG"],[/^[a-zA-Z_][\w\-.]*(?::[a-zA-Z_][\w\-.]*)?=["|'][^"']*["|']/,"ATTRIBUTE"],[/^>/,"END_TAG"],[/^<\/[a-zA-Z_][\w\-.]*(?::[a-zA-Z_][\w\-.]*)?>/,"CLOSE_TAG"],[/^\/>/,"END_CLOSE_TAG"],[/^.+(?=<\/)/,"TEXT"]],E=class{constructor(){this._cursor=0;this._string=""}init(e){this._string=e}isEOF(){return this._cursor===this._string.length}hasMoreTokens(){return this._cursor<this._string.length}getNextToken(){if(!this.hasMoreTokens())return null;let e=this._string.slice(this._cursor);for(let[r,n]of F){let s=this._match(r,e);if(s!=null)return n==null?this.getNextToken():new y(n,s)}throw new SyntaxError(`Unknown token type ${e.slice(0,10)}`)}_match(e,r){let n=e.exec(r);return n===null?null:(this._cursor+=n[0].length,n[0])}};var G={"xlink:actuate":"xlinkActuate","xlink:arcrole":"xlinkArcrole","xlink:href":"xlinkHref","xlink:role":"xlinkRole","xlink:show":"xlinkShow","xlink:title":"xlinkTitle","xlink:type":"xlinkType","xml:lang":"xmlLang","xml:space":"xmlSpace","xml:base":"xmlBase","xmlns:xlink":"xmlnsXlink",class:"className"};var w=class{constructor(e,r={}){this.type=e;this.props=r;this.children=[]}addChild(e){this.children.push(e)}addProp(e,r){this.props[e]=r}},j={BEGIN_TAG:{ATTRIBUTE:!0,END_TAG:!0,END_CLOSE_TAG:!0},ATTRIBUTE:{ATTRIBUTE:!0,END_TAG:!0,END_CLOSE_TAG:!0},END_TAG:{BEGIN_TAG:!0,CLOSE_TAG:!0,TEXT:!0},CLOSE_TAG:{BEGIN_TAG:!0,CLOSE_TAG:!0},END_CLOSE_TAG:{BEGIN_TAG:!0,CLOSE_TAG:!0},TEXT:{CLOSE_TAG:!0}};function H(t){return t.startsWith("aria-")?t:G[t]?G[t]:t.startsWith("rdf:")||t.startsWith("cc:")||t.startsWith("dc:")||t.startsWith("xmlns:")?t.toLowerCase():t.replace(/-([a-zA-Z])/g,(e,r)=>r.toUpperCase())}var x=class{constructor(){this.tokenizer=new E}parse(e){var c;this.tokenizer.init(e);let r=new w("ROOT"),n=[r],s=this.tokenizer.getNextToken();for(;s;){let i=s;if(s=this.tokenizer.getNextToken(),!i)throw new SyntaxError("Not Token found where expected");if(s&&!((c=j[i.name])!=null&&c[s.name]))throw new SyntaxError(`Unexpected token ${s.name} after ${i.name}`);switch(i.name){case"BEGIN_TAG":let o=new w(i.value.slice(1));n[n.length-1].addChild(o),n.push(o);break;case"ATTRIBUTE":let[a,u]=i.value.split("=");n[n.length-1].addProp(H(a),u.slice(1,-1));break;case"END_TAG":break;case"CLOSE_TAG":if(n.length<=1)throw new SyntaxError("Unexpected closing tag");let m=n.pop();if(m.type!==i.value.slice(2,-1))throw new SyntaxError(`Mismatched tag: expected </${m.type}>, got ${i.value}`);break;case"END_CLOSE_TAG":if(n.length<=1)throw new SyntaxError("Unexpected closing tag");n.pop();break;case"TEXT":n[n.length-1].addChild(i.value);break;default:throw new SyntaxError(`Unknown token type: ${i.name}`)}}if(n.length>1)throw new SyntaxError(`Invalid SVG structure: Missing </${n[n.length-1].type}>`);return r.children[0]}};var f=class{getItem(e){return l(this,null,function*(){let r=localStorage.getItem(e);return r?JSON.parse(r):null})}setItem(e,r){return l(this,null,function*(){localStorage.setItem(e,r)})}},k=class{constructor(){this.dbName="LOCAL_SVG_DB";this.storeName="svgs";this.version=1;this.dbPromise=this.openDB()}openDB(){return new Promise((e,r)=>{if(!(window.indexedDB||window.mozIndexedDB||window.webkitIndexedDB||window.msIndexedDB)){r(new Error("IndexedDB is not supported in this environment."));return}let s=indexedDB.open(this.dbName,this.version);s.onupgradeneeded=()=>{let c=s.result;c.objectStoreNames.contains(this.storeName)||c.createObjectStore(this.storeName)},s.onsuccess=()=>e(s.result),s.onerror=()=>r(s.error)})}getItem(e){return l(this,null,function*(){let r=yield this.dbPromise;return new Promise((n,s)=>{let o=r.transaction(this.storeName,"readonly").objectStore(this.storeName).get(e);o.onsuccess=()=>{n(o.result||null)},o.onerror=()=>{s(o.error)}})})}setItem(e,r){return l(this,null,function*(){let n=yield this.dbPromise;return new Promise((s,c)=>{let a=n.transaction(this.storeName,"readwrite").objectStore(this.storeName).put(r,e);a.onsuccess=()=>s(),a.onerror=()=>c(a.error)})})}},B=t=>{if(typeof window=="undefined")return console.warn("Store can only be created in a browser environment."),null;try{return t==="localstorage"?new f:new k}catch(e){return new f}},_=class{constructor(){this.cache=new Map}get(e){return this.cache.get(e)}set(e,r){this.cache.set(e,r)}};var p=B(),D=new _,J=(t,e="/")=>e+t+".svg",K=t=>l(null,null,function*(){try{return yield(yield fetch(t)).text()}catch(e){return console.error(e),null}}),Q=t=>l(null,null,function*(){try{return new x().parse(t)}catch(e){console.error(e)}}),L=(t,e="/")=>l(null,null,function*(){let r=J(t,e),n=D.get(r);if(n)return n;let s=new Promise((c,i)=>l(null,null,function*(){try{let o=yield p==null?void 0:p.getItem(r);if(o||(o=yield K(r),o&&setTimeout(()=>{try{let a=P(o);p==null||p.setItem(r,a)}catch(a){console.warn("Storage is full, cannot cache SVG.")}})),o){let a=yield Q(o);c(a)}i(`Error occured processing Svg ${r}`)}catch(o){i(o)}}));return D.set(r,s),s});var $=require("react/jsx-runtime"),O=(0,g.memo)((0,g.forwardRef)((c,s)=>{var i=c,{name:t,baseUrl:e="/",as:r="span"}=i,n=R(i,["name","baseUrl","as"]);let[o,a]=(0,g.useState)(null);return(0,g.useEffect)(()=>{let m=!0;return L(t,e).then(h=>{m&&h&&a(h)}).catch(h=>console.error(h)),()=>{m=!1}},[t,e]),o?N(o,s,n):(0,$.jsx)(r,{className:n.className,style:d({width:n.width,height:n.height,display:"inline-block"},n.style)})}));0&&(module.exports={LocalSvg});
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/LocalSvg.tsx","../src/tree.ts","../src/minification.ts","../src/tokenizer.ts","../src/namespace.ts","../src/parser.ts","../src/store.ts","../src/query.ts"],"sourcesContent":["export { LocalSvg, type LocalSvgProps } from \"./LocalSvg\";\n","import { forwardRef, memo, SVGAttributes, useEffect, useState } from \"react\";\nimport { SvgNode } from \"./parser\";\nimport { buildSvgReactTree } from \"./tree\";\nimport { createSvg } from \"./query\";\n\nexport type LocalSvgNames = string;\nexport type LocalSvgProps = SVGAttributes<SVGSVGElement> & {\n name: LocalSvgNames;\n baseUrl?: string;\n as?: React.ElementType;\n};\n\nexport const LocalSvg = memo(\n forwardRef<SVGSVGElement, LocalSvgProps>(\n ({ name, baseUrl = \"/\", as = \"span\", ...props }, ref) => {\n const [node, setNode] = useState<SvgNode | null>(null);\n\n useEffect(() => {\n let alive = true;\n\n createSvg(name, baseUrl)\n .then((node) => {\n if (alive && node) setNode(node);\n })\n .catch((err) => console.error(err));\n\n return () => {\n alive = false;\n };\n }, [name, baseUrl]);\n\n const Com = as;\n\n return node ? (\n buildSvgReactTree(node, ref, props)\n ) : (\n <Com\n className={props.className}\n style={{\n width: props.width,\n height: props.height,\n display: \"inline-block\",\n ...props.style,\n }}\n />\n );\n }\n )\n);\n","import { createElement, Ref } from \"react\";\nimport { SvgNode } from \"./parser\";\n\nexport function buildSvgReactTree(\n node: SvgNode | string,\n ref: Ref<SVGSVGElement> | null = null,\n props: Record<string, any> = {},\n keyPath: string = \"0\"\n): React.ReactElement | string {\n if (typeof node === \"string\") return node;\n\n return createElement(\n node.type,\n { ...node.props, ...props, ref, key: keyPath },\n ...node.children.map((child, i) =>\n buildSvgReactTree(child, null, {}, `${keyPath}-${i}`)\n )\n );\n}\n","/**\n * Minifies an SVG string for more efficient usage in the browser or inline.\n *\n * Features:\n * 1. Removes unnecessary whitespace, line breaks, tabs, and extra spaces.\n * 2. Strips XML declarations, comments, metadata, `class` attributes, and `xmlns` attributes.\n * 3. Collapses empty tags into self-closing tags.\n * 4. Shortens long IDs (8+ characters) to sequential numeric IDs and updates all corresponding `url(#ID)` references.\n *\n * @param {string} svg - The raw SVG string to minify.\n * @returns {string} The minified SVG string with optimized IDs and whitespace removed.\n *\n * @example\n * const raw = `<svg xmlns=\"http://www.w3.org/2000/svg\">\n * <defs>\n * <linearGradient id=\"longGradient12345678\"><stop offset=\"0%\" /></linearGradient>\n * </defs>\n * <rect fill=\"url(#longGradient12345678)\" width=\"100\" height=\"100\"/>\n * </svg>`;\n *\n * const minified = minifySVG(raw);\n * console.log(minified);\n */\nexport function minifySVG(svg: string) {\n if (!svg) return \"\";\n\n // 1️⃣ Remove newlines, tabs, multiple spaces\n let min = svg\n .replace(/\\n|\\r|\\t/g, \"\")\n .replace(/\\s{2,}/g, \" \")\n .replace(/\\s*(=)\\s*\"/g, '=\"')\n .replace(/class=\"[^\"]+\"/g, \"\")\n .replace(/<!--.*?-->/g, \"\") // Remove comments\n .replace(/\\sxmlns(?::[a-zA-Z0-9_-]+)?=\"[^\"]*\"/g, \"\") // Remove xmlns attribute\n .replace(/<\\?xml[^>]*>/g, \"\") // Remove XML declaration\n .replace(/<metadata>.*?<\\/metadata>/g, \"\") // Remove metadata\n .replace(/<(\\w+)([^>]*)><\\/\\1>/g, \"<$1$2/>\") // 4️⃣ Collapse self-closing tags (optional)\n .trim();\n\n // 2️⃣ Collect all IDs that look like IconifyId* or long random IDs\n const idRegex = /id=\"([^\"]{8,})\"/g;\n let match;\n let idMap: Record<string, string> = {};\n let counter = 0;\n\n while ((match = idRegex.exec(min)) !== null) {\n const longId = match[1];\n if (!idMap[longId]) {\n idMap[longId] = counter.toString();\n counter++;\n }\n }\n\n // 3️⃣ Replace IDs and corresponding url(#ID) references\n for (const key in idMap) {\n const [longId, shortId] = [key, idMap[key]];\n const idPattern = new RegExp(`id=\"${longId}\"`, \"g\");\n min = min.replace(idPattern, `id=\"${shortId}\"`);\n const urlPattern = new RegExp(`url\\\\(#${longId}\\\\)`, \"g\");\n min = min.replace(urlPattern, `url(#${shortId})`);\n }\n\n idMap = {};\n\n return min;\n}\n","import { TOKEN_TYPE } from \"./enums\";\n\nexport class Token {\n constructor(public name: TOKEN_TYPE, public value: string) {}\n}\n\nconst Spec: [RegExp, TOKEN_TYPE | null][] = [\n [/^\\s+/, null],\n [/^<\\?xml[^]*\\?>/, null],\n [/^<!--[\\s\\S]*?-->/, null],\n [\n /^<[a-zA-Z_][\\w\\-.]*(?::[a-zA-Z_][\\w\\-.]*)?(?=[\\s>/>])/,\n TOKEN_TYPE.BEGIN_TAG,\n ],\n [\n /^[a-zA-Z_][\\w\\-.]*(?::[a-zA-Z_][\\w\\-.]*)?=[\"|'][^\"']*[\"|']/,\n TOKEN_TYPE.ATTRIBUTE,\n ],\n [/^>/, TOKEN_TYPE.END_TAG],\n [/^<\\/[a-zA-Z_][\\w\\-.]*(?::[a-zA-Z_][\\w\\-.]*)?>/, TOKEN_TYPE.CLOSE_TAG],\n [/^\\/>/, TOKEN_TYPE.END_CLOSE_TAG],\n [/^.+(?=<\\/)/, TOKEN_TYPE.TEXT],\n];\n\nclass Tokenizer {\n private _cursor = 0;\n private _string = \"\";\n\n init(str: string) {\n this._string = str;\n }\n\n isEOF() {\n return this._cursor === this._string.length;\n }\n\n hasMoreTokens() {\n return this._cursor < this._string.length;\n }\n\n getNextToken(): Token | null {\n if (!this.hasMoreTokens()) {\n return null;\n }\n\n const string = this._string.slice(this._cursor);\n\n for (const [regexp, tokenType] of Spec) {\n const tokenValue = this._match(regexp, string);\n\n if (tokenValue == null) {\n continue;\n }\n\n if (tokenType == null) {\n return this.getNextToken();\n }\n\n return new Token(tokenType, tokenValue);\n }\n\n throw new SyntaxError(`Unknown token type ${string.slice(0, 10)}`);\n }\n\n _match(reg: RegExp, string: string) {\n let matched = reg.exec(string);\n\n if (matched === null) {\n return null;\n }\n\n this._cursor += matched[0].length;\n return matched[0];\n }\n}\n\nexport { Tokenizer };\n","export const REACT_NAMESPACE_ATTRS: Record<string, string> = {\n \"xlink:actuate\": \"xlinkActuate\",\n \"xlink:arcrole\": \"xlinkArcrole\",\n \"xlink:href\": \"xlinkHref\",\n \"xlink:role\": \"xlinkRole\",\n \"xlink:show\": \"xlinkShow\",\n \"xlink:title\": \"xlinkTitle\",\n \"xlink:type\": \"xlinkType\",\n \"xml:lang\": \"xmlLang\",\n \"xml:space\": \"xmlSpace\",\n \"xml:base\": \"xmlBase\",\n \"xmlns:xlink\": \"xmlnsXlink\",\n class: \"className\",\n};\n","import { TOKEN_TYPE } from \"./enums\";\nimport { Tokenizer } from \"./tokenizer\";\nimport { REACT_NAMESPACE_ATTRS } from \"./namespace\";\n\nclass SvgNode {\n public children: (SvgNode | string)[] = [];\n constructor(\n public type: string,\n public props: { [key: string]: string } = {}\n ) {}\n\n addChild(node: SvgNode | string) {\n this.children.push(node);\n }\n\n addProp(key: string, value: string) {\n this.props[key] = value;\n }\n}\n\nconst AllowedLookAhead: Record<\n TOKEN_TYPE,\n Partial<Record<TOKEN_TYPE, boolean>>\n> = {\n [TOKEN_TYPE.BEGIN_TAG]: {\n [TOKEN_TYPE.ATTRIBUTE]: true,\n [TOKEN_TYPE.END_TAG]: true,\n [TOKEN_TYPE.END_CLOSE_TAG]: true,\n },\n [TOKEN_TYPE.ATTRIBUTE]: {\n [TOKEN_TYPE.ATTRIBUTE]: true,\n [TOKEN_TYPE.END_TAG]: true,\n [TOKEN_TYPE.END_CLOSE_TAG]: true,\n },\n [TOKEN_TYPE.END_TAG]: {\n [TOKEN_TYPE.BEGIN_TAG]: true,\n [TOKEN_TYPE.CLOSE_TAG]: true,\n [TOKEN_TYPE.TEXT]: true,\n },\n [TOKEN_TYPE.CLOSE_TAG]: {\n [TOKEN_TYPE.BEGIN_TAG]: true,\n [TOKEN_TYPE.CLOSE_TAG]: true,\n },\n [TOKEN_TYPE.END_CLOSE_TAG]: {\n [TOKEN_TYPE.BEGIN_TAG]: true,\n [TOKEN_TYPE.CLOSE_TAG]: true,\n },\n [TOKEN_TYPE.TEXT]: {\n [TOKEN_TYPE.CLOSE_TAG]: true,\n },\n};\n\nfunction formatAttributeName(name: string) {\n // 1. ARIA → passthrough\n if (name.startsWith(\"aria-\")) {\n return name;\n }\n\n // 2. Explicit React namespace mapping\n if (REACT_NAMESPACE_ATTRS[name]) {\n return REACT_NAMESPACE_ATTRS[name];\n }\n\n // 3. Unsupported XML namespaces → bail out\n if (\n name.startsWith(\"rdf:\") ||\n name.startsWith(\"cc:\") ||\n name.startsWith(\"dc:\") ||\n name.startsWith(\"xmlns:\")\n ) {\n return name.toLowerCase();\n }\n\n // 4. Standard HTML/SVG attribute\n return name.replace(/-([a-zA-Z])/g, (_, char) => char.toUpperCase());\n}\n\nclass Parser {\n tokenizer: Tokenizer;\n\n constructor() {\n this.tokenizer = new Tokenizer();\n }\n\n parse(str: string) {\n this.tokenizer.init(str);\n const root = new SvgNode(\"ROOT\");\n let tags: SvgNode[] = [root];\n let lookAhead = this.tokenizer.getNextToken();\n\n while (lookAhead) {\n const token = lookAhead;\n lookAhead = this.tokenizer.getNextToken();\n\n if (!token) {\n throw new SyntaxError(`Not Token found where expected`);\n }\n\n if (lookAhead && !AllowedLookAhead[token.name]?.[lookAhead.name]) {\n throw new SyntaxError(\n `Unexpected token ${lookAhead.name} after ${token.name}`\n );\n }\n\n switch (token.name) {\n case TOKEN_TYPE.BEGIN_TAG:\n const node = new SvgNode(token.value.slice(1));\n tags[tags.length - 1].addChild(node);\n tags.push(node);\n break;\n\n case TOKEN_TYPE.ATTRIBUTE:\n const [name, value] = token.value.split(\"=\");\n\n tags[tags.length - 1].addProp(\n formatAttributeName(name),\n value.slice(1, -1)\n );\n break;\n\n case TOKEN_TYPE.END_TAG:\n //Do nothing\n break;\n\n case TOKEN_TYPE.CLOSE_TAG:\n if (tags.length <= 1) {\n // ✅ NOW in the right place\n throw new SyntaxError(\"Unexpected closing tag\");\n }\n const current = tags.pop()!;\n if (current.type !== token.value.slice(2, -1)) {\n throw new SyntaxError(\n `Mismatched tag: expected </${current.type}>, got ${token.value}`\n );\n }\n break;\n\n case TOKEN_TYPE.END_CLOSE_TAG:\n if (tags.length <= 1) {\n // ✅ NOW in the right place\n throw new SyntaxError(\"Unexpected closing tag\");\n }\n tags.pop();\n break;\n\n case TOKEN_TYPE.TEXT:\n tags[tags.length - 1].addChild(token.value);\n break;\n\n default:\n throw new SyntaxError(`Unknown token type: ${token.name}`);\n }\n }\n\n if (tags.length > 1) {\n throw new SyntaxError(\n `Invalid SVG structure: Missing </${tags[tags.length - 1].type}>`\n );\n }\n\n return root.children[0] as SvgNode;\n }\n}\n\nexport { Parser, SvgNode };\n","interface Store {\n getItem(key: string): Promise<string | null>;\n setItem(key: string, content:string): Promise<void>;\n}\n\nclass LocalStorageStore implements Store {\n async getItem(key: string): Promise<string | null> {\n const item = localStorage.getItem(key);\n return item ? (JSON.parse(item) as string) : null;\n }\n\n async setItem(key: string, value: string) {\n localStorage.setItem(key, value);\n }\n}\n\nclass IndexedDBStore implements Store {\n private dbName = \"LOCAL_SVG_DB\";\n private storeName = \"svgs\";\n private dbPromise: Promise<IDBDatabase>;\n private version = 1;\n\n constructor() {\n this.dbPromise = this.openDB();\n }\n\n private openDB(): Promise<IDBDatabase> {\n return new Promise((resolve, reject) => {\n const idb: IDBFactory | null =\n window.indexedDB ||\n (window as any).mozIndexedDB ||\n (window as any).webkitIndexedDB ||\n (window as any).msIndexedDB;\n if (!idb) {\n reject(new Error(\"IndexedDB is not supported in this environment.\"));\n return;\n }\n const request = indexedDB.open(this.dbName, this.version);\n request.onupgradeneeded = () => {\n const db = request.result;\n if (!db.objectStoreNames.contains(this.storeName)) {\n db.createObjectStore(this.storeName);\n }\n };\n request.onsuccess = () => resolve(request.result);\n request.onerror = () => reject(request.error);\n });\n }\n\n async getItem(key: string): Promise<string | null> {\n const db = await this.dbPromise;\n return new Promise((resolve, reject) => {\n const transaction = db.transaction(this.storeName, \"readonly\");\n const store = transaction.objectStore(this.storeName);\n const request = store.get(key);\n request.onsuccess = () => {\n resolve((request.result as string) || null);\n };\n request.onerror = () => {\n reject(request.error);\n };\n });\n }\n\n async setItem(key: string, value: string): Promise<void> {\n const db = await this.dbPromise;\n return new Promise((resolve, reject) => {\n const transaction = db.transaction(this.storeName, \"readwrite\");\n const store = transaction.objectStore(this.storeName);\n const request = store.put(value, key);\n request.onsuccess = () => resolve();\n request.onerror = () => reject(request.error);\n });\n }\n}\n\nexport const createStore = (storage?: \"localstorage\" | \"indexdb\"): Store => {\n if (typeof window === \"undefined\") {\n console.warn(\"Store can only be created in a browser environment.\");\n return null;\n }\n try {\n if (storage === \"localstorage\") {\n return new LocalStorageStore();\n }\n return new IndexedDBStore();\n } catch (error) {\n return new LocalStorageStore();\n }\n};\n\nexport class PromiseCache<T> {\n private cache: Map<string, Promise<T>>;\n\n constructor() {\n this.cache = new Map();\n }\n\n get(key: string): Promise<T> | undefined {\n return this.cache.get(key);\n }\n\n set(key: string, promise: Promise<T>): void {\n this.cache.set(key, promise);\n }\n}","import { minifySVG } from \"./minification\";\nimport { Parser, SvgNode } from \"./parser\";\nimport { createStore, PromiseCache } from \"./store\";\n\nconst store = createStore();\nconst promiseCache = new PromiseCache<SvgNode>();\n\nconst composeUrl = (name: string, baseUrl = \"/\") => {\n return baseUrl + name + \".svg\";\n};\n\nconst _fetch = async (url: string) => {\n try {\n const response = await fetch(url);\n return await response.text();\n } catch (error) {\n console.error(error);\n return null;\n }\n};\n\nconst processSvgText = async (text: string) => {\n try {\n const parser = new Parser();\n return parser.parse(text);\n } catch (error) {\n console.error(error);\n }\n};\n\nexport const createSvg = async (name: string, baseUrl = \"/\") => {\n const fullUrl = composeUrl(name, baseUrl);\n const promise = promiseCache.get(fullUrl);\n\n if (promise) {\n return promise;\n }\n\n const newPromise = new Promise<SvgNode>(async (resolve, reject) => {\n try {\n let text = await store?.getItem(fullUrl);\n\n if (!text) {\n text = await _fetch(fullUrl);\n\n if (text) {\n setTimeout(() => {\n try {\n const minified = minifySVG(text);\n store?.setItem(fullUrl, minified);\n } catch (error) {\n console.warn(\"Storage is full, cannot cache SVG.\");\n }\n });\n }\n }\n\n if (text) {\n const node = await processSvgText(text);\n resolve(node);\n }\n\n reject(`Error occured processing Svg ${fullUrl}`);\n } catch (error) {\n reject(error);\n }\n });\n\n promiseCache.set(fullUrl, newPromise);\n\n return newPromise;\n};\n"],"mappings":"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","names":["index_exports","__export","LocalSvg","__toCommonJS","import_react","import_react","buildSvgReactTree","node","ref","props","keyPath","__spreadProps","__spreadValues","child","i","minifySVG","svg","min","idRegex","match","idMap","counter","longId","key","shortId","idPattern","urlPattern","Token","name","value","Spec","Tokenizer","str","string","regexp","tokenType","tokenValue","reg","matched","REACT_NAMESPACE_ATTRS","SvgNode","type","props","node","key","value","AllowedLookAhead","formatAttributeName","name","REACT_NAMESPACE_ATTRS","_","char","Parser","Tokenizer","str","_a","root","tags","lookAhead","token","current","LocalStorageStore","key","__async","item","value","IndexedDBStore","resolve","reject","request","db","createStore","storage","error","PromiseCache","promise","store","createStore","promiseCache","PromiseCache","composeUrl","name","baseUrl","_fetch","url","__async","error","processSvgText","text","Parser","createSvg","fullUrl","promise","newPromise","resolve","reject","minified","minifySVG","node","import_jsx_runtime","LocalSvg","_a","ref","_b","name","baseUrl","as","props","__objRest","node","setNode","alive","createSvg","err","buildSvgReactTree","__spreadValues"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/LocalSvg.tsx","../src/tree.ts","../src/minification.ts","../src/tokenizer.ts","../src/namespace.ts","../src/parser.ts","../src/store.ts","../src/query.ts"],"sourcesContent":["export { LocalSvg, type LocalSvgProps } from \"./LocalSvg\";\n","import { forwardRef, memo, SVGAttributes, useEffect, useState } from \"react\";\nimport { SvgNode } from \"./parser\";\nimport { buildSvgReactTree } from \"./tree\";\nimport { createSvg } from \"./query\";\n\nexport type LocalSvgProps = SVGAttributes<SVGSVGElement> & {\n name: LocalSvg.LocalSvgNames;\n baseUrl?: string;\n as?: React.ElementType;\n};\n\nexport const LocalSvg = memo(\n forwardRef<SVGSVGElement, LocalSvgProps>(\n ({ name, baseUrl = \"/\", as = \"span\", ...props }, ref) => {\n const [node, setNode] = useState<SvgNode | null>(null);\n\n useEffect(() => {\n let alive = true;\n\n createSvg(name, baseUrl)\n .then((node) => {\n if (alive && node) setNode(node);\n })\n .catch((err) => console.error(err));\n\n return () => {\n alive = false;\n };\n }, [name, baseUrl]);\n\n const Com = as;\n\n return node ? (\n buildSvgReactTree(node, ref, props)\n ) : (\n <Com\n className={props.className}\n style={{\n width: props.width,\n height: props.height,\n display: \"inline-block\",\n ...props.style,\n }}\n />\n );\n }\n )\n);\n","import { createElement, Ref } from \"react\";\nimport { SvgNode } from \"./parser\";\n\nexport function buildSvgReactTree(\n node: SvgNode | string,\n ref: Ref<SVGSVGElement> | null = null,\n props: Record<string, any> = {},\n keyPath: string = \"0\"\n): React.ReactElement | string {\n if (typeof node === \"string\") return node;\n\n return createElement(\n node.type,\n { ...node.props, ...props, ref, key: keyPath },\n ...node.children.map((child, i) =>\n buildSvgReactTree(child, null, {}, `${keyPath}-${i}`)\n )\n );\n}\n","/**\n * Minifies an SVG string for more efficient usage in the browser or inline.\n *\n * Features:\n * 1. Removes unnecessary whitespace, line breaks, tabs, and extra spaces.\n * 2. Strips XML declarations, comments, metadata, `class` attributes, and `xmlns` attributes.\n * 3. Collapses empty tags into self-closing tags.\n * 4. Shortens long IDs (8+ characters) to sequential numeric IDs and updates all corresponding `url(#ID)` references.\n *\n * @param {string} svg - The raw SVG string to minify.\n * @returns {string} The minified SVG string with optimized IDs and whitespace removed.\n *\n * @example\n * const raw = `<svg xmlns=\"http://www.w3.org/2000/svg\">\n * <defs>\n * <linearGradient id=\"longGradient12345678\"><stop offset=\"0%\" /></linearGradient>\n * </defs>\n * <rect fill=\"url(#longGradient12345678)\" width=\"100\" height=\"100\"/>\n * </svg>`;\n *\n * const minified = minifySVG(raw);\n * console.log(minified);\n */\nexport function minifySVG(svg: string) {\n if (!svg) return \"\";\n\n // 1️⃣ Remove newlines, tabs, multiple spaces\n let min = svg\n .replace(/\\n|\\r|\\t/g, \"\")\n .replace(/\\s{2,}/g, \" \")\n .replace(/\\s*(=)\\s*\"/g, '=\"')\n .replace(/class=\"[^\"]+\"/g, \"\")\n .replace(/<!--.*?-->/g, \"\") // Remove comments\n .replace(/\\sxmlns(?::[a-zA-Z0-9_-]+)?=\"[^\"]*\"/g, \"\") // Remove xmlns attribute\n .replace(/<\\?xml[^>]*>/g, \"\") // Remove XML declaration\n .replace(/<metadata>.*?<\\/metadata>/g, \"\") // Remove metadata\n .replace(/<(\\w+)([^>]*)><\\/\\1>/g, \"<$1$2/>\") // 4️⃣ Collapse self-closing tags (optional)\n .trim();\n\n // 2️⃣ Collect all IDs that look like IconifyId* or long random IDs\n const idRegex = /id=\"([^\"]{8,})\"/g;\n let match;\n let idMap: Record<string, string> = {};\n let counter = 0;\n\n while ((match = idRegex.exec(min)) !== null) {\n const longId = match[1];\n if (!idMap[longId]) {\n idMap[longId] = counter.toString();\n counter++;\n }\n }\n\n // 3️⃣ Replace IDs and corresponding url(#ID) references\n for (const key in idMap) {\n const [longId, shortId] = [key, idMap[key]];\n const idPattern = new RegExp(`id=\"${longId}\"`, \"g\");\n min = min.replace(idPattern, `id=\"${shortId}\"`);\n const urlPattern = new RegExp(`url\\\\(#${longId}\\\\)`, \"g\");\n min = min.replace(urlPattern, `url(#${shortId})`);\n }\n\n idMap = {};\n\n return min;\n}\n","import { TOKEN_TYPE } from \"./enums\";\n\nexport class Token {\n constructor(public name: TOKEN_TYPE, public value: string) {}\n}\n\nconst Spec: [RegExp, TOKEN_TYPE | null][] = [\n [/^\\s+/, null],\n [/^<\\?xml[^]*\\?>/, null],\n [/^<!--[\\s\\S]*?-->/, null],\n [\n /^<[a-zA-Z_][\\w\\-.]*(?::[a-zA-Z_][\\w\\-.]*)?(?=[\\s>/>])/,\n TOKEN_TYPE.BEGIN_TAG,\n ],\n [\n /^[a-zA-Z_][\\w\\-.]*(?::[a-zA-Z_][\\w\\-.]*)?=[\"|'][^\"']*[\"|']/,\n TOKEN_TYPE.ATTRIBUTE,\n ],\n [/^>/, TOKEN_TYPE.END_TAG],\n [/^<\\/[a-zA-Z_][\\w\\-.]*(?::[a-zA-Z_][\\w\\-.]*)?>/, TOKEN_TYPE.CLOSE_TAG],\n [/^\\/>/, TOKEN_TYPE.END_CLOSE_TAG],\n [/^.+(?=<\\/)/, TOKEN_TYPE.TEXT],\n];\n\nclass Tokenizer {\n private _cursor = 0;\n private _string = \"\";\n\n init(str: string) {\n this._string = str;\n }\n\n isEOF() {\n return this._cursor === this._string.length;\n }\n\n hasMoreTokens() {\n return this._cursor < this._string.length;\n }\n\n getNextToken(): Token | null {\n if (!this.hasMoreTokens()) {\n return null;\n }\n\n const string = this._string.slice(this._cursor);\n\n for (const [regexp, tokenType] of Spec) {\n const tokenValue = this._match(regexp, string);\n\n if (tokenValue == null) {\n continue;\n }\n\n if (tokenType == null) {\n return this.getNextToken();\n }\n\n return new Token(tokenType, tokenValue);\n }\n\n throw new SyntaxError(`Unknown token type ${string.slice(0, 10)}`);\n }\n\n _match(reg: RegExp, string: string) {\n let matched = reg.exec(string);\n\n if (matched === null) {\n return null;\n }\n\n this._cursor += matched[0].length;\n return matched[0];\n }\n}\n\nexport { Tokenizer };\n","export const REACT_NAMESPACE_ATTRS: Record<string, string> = {\n \"xlink:actuate\": \"xlinkActuate\",\n \"xlink:arcrole\": \"xlinkArcrole\",\n \"xlink:href\": \"xlinkHref\",\n \"xlink:role\": \"xlinkRole\",\n \"xlink:show\": \"xlinkShow\",\n \"xlink:title\": \"xlinkTitle\",\n \"xlink:type\": \"xlinkType\",\n \"xml:lang\": \"xmlLang\",\n \"xml:space\": \"xmlSpace\",\n \"xml:base\": \"xmlBase\",\n \"xmlns:xlink\": \"xmlnsXlink\",\n class: \"className\",\n};\n","import { TOKEN_TYPE } from \"./enums\";\nimport { Tokenizer } from \"./tokenizer\";\nimport { REACT_NAMESPACE_ATTRS } from \"./namespace\";\n\nclass SvgNode {\n public children: (SvgNode | string)[] = [];\n constructor(\n public type: string,\n public props: { [key: string]: string } = {}\n ) {}\n\n addChild(node: SvgNode | string) {\n this.children.push(node);\n }\n\n addProp(key: string, value: string) {\n this.props[key] = value;\n }\n}\n\nconst AllowedLookAhead: Record<\n TOKEN_TYPE,\n Partial<Record<TOKEN_TYPE, boolean>>\n> = {\n [TOKEN_TYPE.BEGIN_TAG]: {\n [TOKEN_TYPE.ATTRIBUTE]: true,\n [TOKEN_TYPE.END_TAG]: true,\n [TOKEN_TYPE.END_CLOSE_TAG]: true,\n },\n [TOKEN_TYPE.ATTRIBUTE]: {\n [TOKEN_TYPE.ATTRIBUTE]: true,\n [TOKEN_TYPE.END_TAG]: true,\n [TOKEN_TYPE.END_CLOSE_TAG]: true,\n },\n [TOKEN_TYPE.END_TAG]: {\n [TOKEN_TYPE.BEGIN_TAG]: true,\n [TOKEN_TYPE.CLOSE_TAG]: true,\n [TOKEN_TYPE.TEXT]: true,\n },\n [TOKEN_TYPE.CLOSE_TAG]: {\n [TOKEN_TYPE.BEGIN_TAG]: true,\n [TOKEN_TYPE.CLOSE_TAG]: true,\n },\n [TOKEN_TYPE.END_CLOSE_TAG]: {\n [TOKEN_TYPE.BEGIN_TAG]: true,\n [TOKEN_TYPE.CLOSE_TAG]: true,\n },\n [TOKEN_TYPE.TEXT]: {\n [TOKEN_TYPE.CLOSE_TAG]: true,\n },\n};\n\nfunction formatAttributeName(name: string) {\n // 1. ARIA → passthrough\n if (name.startsWith(\"aria-\")) {\n return name;\n }\n\n // 2. Explicit React namespace mapping\n if (REACT_NAMESPACE_ATTRS[name]) {\n return REACT_NAMESPACE_ATTRS[name];\n }\n\n // 3. Unsupported XML namespaces → bail out\n if (\n name.startsWith(\"rdf:\") ||\n name.startsWith(\"cc:\") ||\n name.startsWith(\"dc:\") ||\n name.startsWith(\"xmlns:\")\n ) {\n return name.toLowerCase();\n }\n\n // 4. Standard HTML/SVG attribute\n return name.replace(/-([a-zA-Z])/g, (_, char) => char.toUpperCase());\n}\n\nclass Parser {\n tokenizer: Tokenizer;\n\n constructor() {\n this.tokenizer = new Tokenizer();\n }\n\n parse(str: string) {\n this.tokenizer.init(str);\n const root = new SvgNode(\"ROOT\");\n let tags: SvgNode[] = [root];\n let lookAhead = this.tokenizer.getNextToken();\n\n while (lookAhead) {\n const token = lookAhead;\n lookAhead = this.tokenizer.getNextToken();\n\n if (!token) {\n throw new SyntaxError(`Not Token found where expected`);\n }\n\n if (lookAhead && !AllowedLookAhead[token.name]?.[lookAhead.name]) {\n throw new SyntaxError(\n `Unexpected token ${lookAhead.name} after ${token.name}`\n );\n }\n\n switch (token.name) {\n case TOKEN_TYPE.BEGIN_TAG:\n const node = new SvgNode(token.value.slice(1));\n tags[tags.length - 1].addChild(node);\n tags.push(node);\n break;\n\n case TOKEN_TYPE.ATTRIBUTE:\n const [name, value] = token.value.split(\"=\");\n\n tags[tags.length - 1].addProp(\n formatAttributeName(name),\n value.slice(1, -1)\n );\n break;\n\n case TOKEN_TYPE.END_TAG:\n //Do nothing\n break;\n\n case TOKEN_TYPE.CLOSE_TAG:\n if (tags.length <= 1) {\n // ✅ NOW in the right place\n throw new SyntaxError(\"Unexpected closing tag\");\n }\n const current = tags.pop()!;\n if (current.type !== token.value.slice(2, -1)) {\n throw new SyntaxError(\n `Mismatched tag: expected </${current.type}>, got ${token.value}`\n );\n }\n break;\n\n case TOKEN_TYPE.END_CLOSE_TAG:\n if (tags.length <= 1) {\n // ✅ NOW in the right place\n throw new SyntaxError(\"Unexpected closing tag\");\n }\n tags.pop();\n break;\n\n case TOKEN_TYPE.TEXT:\n tags[tags.length - 1].addChild(token.value);\n break;\n\n default:\n throw new SyntaxError(`Unknown token type: ${token.name}`);\n }\n }\n\n if (tags.length > 1) {\n throw new SyntaxError(\n `Invalid SVG structure: Missing </${tags[tags.length - 1].type}>`\n );\n }\n\n return root.children[0] as SvgNode;\n }\n}\n\nexport { Parser, SvgNode };\n","interface Store {\n getItem(key: string): Promise<string | null>;\n setItem(key: string, content:string): Promise<void>;\n}\n\nclass LocalStorageStore implements Store {\n async getItem(key: string): Promise<string | null> {\n const item = localStorage.getItem(key);\n return item ? (JSON.parse(item) as string) : null;\n }\n\n async setItem(key: string, value: string) {\n localStorage.setItem(key, value);\n }\n}\n\nclass IndexedDBStore implements Store {\n private dbName = \"LOCAL_SVG_DB\";\n private storeName = \"svgs\";\n private dbPromise: Promise<IDBDatabase>;\n private version = 1;\n\n constructor() {\n this.dbPromise = this.openDB();\n }\n\n private openDB(): Promise<IDBDatabase> {\n return new Promise((resolve, reject) => {\n const idb: IDBFactory | null =\n window.indexedDB ||\n (window as any).mozIndexedDB ||\n (window as any).webkitIndexedDB ||\n (window as any).msIndexedDB;\n if (!idb) {\n reject(new Error(\"IndexedDB is not supported in this environment.\"));\n return;\n }\n const request = indexedDB.open(this.dbName, this.version);\n request.onupgradeneeded = () => {\n const db = request.result;\n if (!db.objectStoreNames.contains(this.storeName)) {\n db.createObjectStore(this.storeName);\n }\n };\n request.onsuccess = () => resolve(request.result);\n request.onerror = () => reject(request.error);\n });\n }\n\n async getItem(key: string): Promise<string | null> {\n const db = await this.dbPromise;\n return new Promise((resolve, reject) => {\n const transaction = db.transaction(this.storeName, \"readonly\");\n const store = transaction.objectStore(this.storeName);\n const request = store.get(key);\n request.onsuccess = () => {\n resolve((request.result as string) || null);\n };\n request.onerror = () => {\n reject(request.error);\n };\n });\n }\n\n async setItem(key: string, value: string): Promise<void> {\n const db = await this.dbPromise;\n return new Promise((resolve, reject) => {\n const transaction = db.transaction(this.storeName, \"readwrite\");\n const store = transaction.objectStore(this.storeName);\n const request = store.put(value, key);\n request.onsuccess = () => resolve();\n request.onerror = () => reject(request.error);\n });\n }\n}\n\nexport const createStore = (storage?: \"localstorage\" | \"indexdb\"): Store => {\n if (typeof window === \"undefined\") {\n console.warn(\"Store can only be created in a browser environment.\");\n return null;\n }\n try {\n if (storage === \"localstorage\") {\n return new LocalStorageStore();\n }\n return new IndexedDBStore();\n } catch (error) {\n return new LocalStorageStore();\n }\n};\n\nexport class PromiseCache<T> {\n private cache: Map<string, Promise<T>>;\n\n constructor() {\n this.cache = new Map();\n }\n\n get(key: string): Promise<T> | undefined {\n return this.cache.get(key);\n }\n\n set(key: string, promise: Promise<T>): void {\n this.cache.set(key, promise);\n }\n}","import { minifySVG } from \"./minification\";\nimport { Parser, SvgNode } from \"./parser\";\nimport { createStore, PromiseCache } from \"./store\";\n\nconst store = createStore();\nconst promiseCache = new PromiseCache<SvgNode>();\n\nconst composeUrl = (name: string, baseUrl = \"/\") => {\n return baseUrl + name + \".svg\";\n};\n\nconst _fetch = async (url: string) => {\n try {\n const response = await fetch(url);\n return await response.text();\n } catch (error) {\n console.error(error);\n return null;\n }\n};\n\nconst processSvgText = async (text: string) => {\n try {\n const parser = new Parser();\n return parser.parse(text);\n } catch (error) {\n console.error(error);\n }\n};\n\nexport const createSvg = async (name: string, baseUrl = \"/\") => {\n const fullUrl = composeUrl(name, baseUrl);\n const promise = promiseCache.get(fullUrl);\n\n if (promise) {\n return promise;\n }\n\n const newPromise = new Promise<SvgNode>(async (resolve, reject) => {\n try {\n let text = await store?.getItem(fullUrl);\n\n if (!text) {\n text = await _fetch(fullUrl);\n\n if (text) {\n setTimeout(() => {\n try {\n const minified = minifySVG(text);\n store?.setItem(fullUrl, minified);\n } catch (error) {\n console.warn(\"Storage is full, cannot cache SVG.\");\n }\n });\n }\n }\n\n if (text) {\n const node = await processSvgText(text);\n resolve(node);\n }\n\n reject(`Error occured processing Svg ${fullUrl}`);\n } catch (error) {\n reject(error);\n }\n });\n\n promiseCache.set(fullUrl, newPromise);\n\n return newPromise;\n};\n"],"mappings":"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","names":["index_exports","__export","LocalSvg","__toCommonJS","import_react","import_react","buildSvgReactTree","node","ref","props","keyPath","__spreadProps","__spreadValues","child","i","minifySVG","svg","min","idRegex","match","idMap","counter","longId","key","shortId","idPattern","urlPattern","Token","name","value","Spec","Tokenizer","str","string","regexp","tokenType","tokenValue","reg","matched","REACT_NAMESPACE_ATTRS","SvgNode","type","props","node","key","value","AllowedLookAhead","formatAttributeName","name","REACT_NAMESPACE_ATTRS","_","char","Parser","Tokenizer","str","_a","root","tags","lookAhead","token","current","LocalStorageStore","key","__async","item","value","IndexedDBStore","resolve","reject","request","db","createStore","storage","error","PromiseCache","promise","store","createStore","promiseCache","PromiseCache","composeUrl","name","baseUrl","_fetch","url","__async","error","processSvgText","text","Parser","createSvg","fullUrl","promise","newPromise","resolve","reject","minified","minifySVG","node","import_jsx_runtime","LocalSvg","_a","ref","_b","name","baseUrl","as","props","__objRest","node","setNode","alive","createSvg","err","buildSvgReactTree","__spreadValues"]}
|
package/dist/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var B=Object.defineProperty,D=Object.defineProperties;var L=Object.getOwnPropertyDescriptors;var h=Object.getOwnPropertySymbols;var G=Object.prototype.hasOwnProperty,k=Object.prototype.propertyIsEnumerable;var y=(t,e,r)=>e in t?B(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r,p=(t,e)=>{for(var r in e||(e={}))G.call(e,r)&&y(t,r,e[r]);if(h)for(var r of h(e))k.call(e,r)&&y(t,r,e[r]);return t},v=(t,e)=>D(t,L(e));var b=(t,e)=>{var r={};for(var n in t)G.call(t,n)&&e.indexOf(n)<0&&(r[n]=t[n]);if(t!=null&&h)for(var n of h(t))e.indexOf(n)<0&&k.call(t,n)&&(r[n]=t[n]);return r};var l=(t,e,r)=>new Promise((n,s)=>{var c=a=>{try{o(r.next(a))}catch(
|
|
1
|
+
var B=Object.defineProperty,D=Object.defineProperties;var L=Object.getOwnPropertyDescriptors;var h=Object.getOwnPropertySymbols;var G=Object.prototype.hasOwnProperty,k=Object.prototype.propertyIsEnumerable;var y=(t,e,r)=>e in t?B(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r,p=(t,e)=>{for(var r in e||(e={}))G.call(e,r)&&y(t,r,e[r]);if(h)for(var r of h(e))k.call(e,r)&&y(t,r,e[r]);return t},v=(t,e)=>D(t,L(e));var b=(t,e)=>{var r={};for(var n in t)G.call(t,n)&&e.indexOf(n)<0&&(r[n]=t[n]);if(t!=null&&h)for(var n of h(t))e.indexOf(n)<0&&k.call(t,n)&&(r[n]=t[n]);return r};var l=(t,e,r)=>new Promise((n,s)=>{var c=a=>{try{o(r.next(a))}catch(u){s(u)}},i=a=>{try{o(r.throw(a))}catch(u){s(u)}},o=a=>a.done?n(a.value):Promise.resolve(a.value).then(c,i);o((r=r.apply(t,e)).next())});import{forwardRef as W,memo as q,useEffect as F,useState as j}from"react";import{createElement as O}from"react";function f(t,e=null,r={},n="0"){return typeof t=="string"?t:O(t.type,v(p(p({},t.props),r),{ref:e,key:n}),...t.children.map((s,c)=>f(s,null,{},`${n}-${c}`)))}function I(t){if(!t)return"";let e=t.replace(/\n|\r|\t/g,"").replace(/\s{2,}/g," ").replace(/\s*(=)\s*"/g,'="').replace(/class="[^"]+"/g,"").replace(/<!--.*?-->/g,"").replace(/\sxmlns(?::[a-zA-Z0-9_-]+)?="[^"]*"/g,"").replace(/<\?xml[^>]*>/g,"").replace(/<metadata>.*?<\/metadata>/g,"").replace(/<(\w+)([^>]*)><\/\1>/g,"<$1$2/>").trim(),r=/id="([^"]{8,})"/g,n,s={},c=0;for(;(n=r.exec(e))!==null;){let i=n[1];s[i]||(s[i]=c.toString(),c++)}for(let i in s){let[o,a]=[i,s[i]],u=new RegExp(`id="${o}"`,"g");e=e.replace(u,`id="${a}"`);let g=new RegExp(`url\\(#${o}\\)`,"g");e=e.replace(g,`url(#${a})`)}return s={},e}var _=class{constructor(e,r){this.name=e;this.value=r}},z=[[/^\s+/,null],[/^<\?xml[^]*\?>/,null],[/^<!--[\s\S]*?-->/,null],[/^<[a-zA-Z_][\w\-.]*(?::[a-zA-Z_][\w\-.]*)?(?=[\s>/>])/,"BEGIN_TAG"],[/^[a-zA-Z_][\w\-.]*(?::[a-zA-Z_][\w\-.]*)?=["|'][^"']*["|']/,"ATTRIBUTE"],[/^>/,"END_TAG"],[/^<\/[a-zA-Z_][\w\-.]*(?::[a-zA-Z_][\w\-.]*)?>/,"CLOSE_TAG"],[/^\/>/,"END_CLOSE_TAG"],[/^.+(?=<\/)/,"TEXT"]],T=class{constructor(){this._cursor=0;this._string=""}init(e){this._string=e}isEOF(){return this._cursor===this._string.length}hasMoreTokens(){return this._cursor<this._string.length}getNextToken(){if(!this.hasMoreTokens())return null;let e=this._string.slice(this._cursor);for(let[r,n]of z){let s=this._match(r,e);if(s!=null)return n==null?this.getNextToken():new _(n,s)}throw new SyntaxError(`Unknown token type ${e.slice(0,10)}`)}_match(e,r){let n=e.exec(r);return n===null?null:(this._cursor+=n[0].length,n[0])}};var A={"xlink:actuate":"xlinkActuate","xlink:arcrole":"xlinkArcrole","xlink:href":"xlinkHref","xlink:role":"xlinkRole","xlink:show":"xlinkShow","xlink:title":"xlinkTitle","xlink:type":"xlinkType","xml:lang":"xmlLang","xml:space":"xmlSpace","xml:base":"xmlBase","xmlns:xlink":"xmlnsXlink",class:"className"};var S=class{constructor(e,r={}){this.type=e;this.props=r;this.children=[]}addChild(e){this.children.push(e)}addProp(e,r){this.props[e]=r}},U={BEGIN_TAG:{ATTRIBUTE:!0,END_TAG:!0,END_CLOSE_TAG:!0},ATTRIBUTE:{ATTRIBUTE:!0,END_TAG:!0,END_CLOSE_TAG:!0},END_TAG:{BEGIN_TAG:!0,CLOSE_TAG:!0,TEXT:!0},CLOSE_TAG:{BEGIN_TAG:!0,CLOSE_TAG:!0},END_CLOSE_TAG:{BEGIN_TAG:!0,CLOSE_TAG:!0},TEXT:{CLOSE_TAG:!0}};function V(t){return t.startsWith("aria-")?t:A[t]?A[t]:t.startsWith("rdf:")||t.startsWith("cc:")||t.startsWith("dc:")||t.startsWith("xmlns:")?t.toLowerCase():t.replace(/-([a-zA-Z])/g,(e,r)=>r.toUpperCase())}var E=class{constructor(){this.tokenizer=new T}parse(e){var c;this.tokenizer.init(e);let r=new S("ROOT"),n=[r],s=this.tokenizer.getNextToken();for(;s;){let i=s;if(s=this.tokenizer.getNextToken(),!i)throw new SyntaxError("Not Token found where expected");if(s&&!((c=U[i.name])!=null&&c[s.name]))throw new SyntaxError(`Unexpected token ${s.name} after ${i.name}`);switch(i.name){case"BEGIN_TAG":let o=new S(i.value.slice(1));n[n.length-1].addChild(o),n.push(o);break;case"ATTRIBUTE":let[a,u]=i.value.split("=");n[n.length-1].addProp(V(a),u.slice(1,-1));break;case"END_TAG":break;case"CLOSE_TAG":if(n.length<=1)throw new SyntaxError("Unexpected closing tag");let g=n.pop();if(g.type!==i.value.slice(2,-1))throw new SyntaxError(`Mismatched tag: expected </${g.type}>, got ${i.value}`);break;case"END_CLOSE_TAG":if(n.length<=1)throw new SyntaxError("Unexpected closing tag");n.pop();break;case"TEXT":n[n.length-1].addChild(i.value);break;default:throw new SyntaxError(`Unknown token type: ${i.name}`)}}if(n.length>1)throw new SyntaxError(`Invalid SVG structure: Missing </${n[n.length-1].type}>`);return r.children[0]}};var w=class{getItem(e){return l(this,null,function*(){let r=localStorage.getItem(e);return r?JSON.parse(r):null})}setItem(e,r){return l(this,null,function*(){localStorage.setItem(e,r)})}},N=class{constructor(){this.dbName="LOCAL_SVG_DB";this.storeName="svgs";this.version=1;this.dbPromise=this.openDB()}openDB(){return new Promise((e,r)=>{if(!(window.indexedDB||window.mozIndexedDB||window.webkitIndexedDB||window.msIndexedDB)){r(new Error("IndexedDB is not supported in this environment."));return}let s=indexedDB.open(this.dbName,this.version);s.onupgradeneeded=()=>{let c=s.result;c.objectStoreNames.contains(this.storeName)||c.createObjectStore(this.storeName)},s.onsuccess=()=>e(s.result),s.onerror=()=>r(s.error)})}getItem(e){return l(this,null,function*(){let r=yield this.dbPromise;return new Promise((n,s)=>{let o=r.transaction(this.storeName,"readonly").objectStore(this.storeName).get(e);o.onsuccess=()=>{n(o.result||null)},o.onerror=()=>{s(o.error)}})})}setItem(e,r){return l(this,null,function*(){let n=yield this.dbPromise;return new Promise((s,c)=>{let a=n.transaction(this.storeName,"readwrite").objectStore(this.storeName).put(r,e);a.onsuccess=()=>s(),a.onerror=()=>c(a.error)})})}},R=t=>{if(typeof window=="undefined")return console.warn("Store can only be created in a browser environment."),null;try{return t==="localstorage"?new w:new N}catch(e){return new w}},x=class{constructor(){this.cache=new Map}get(e){return this.cache.get(e)}set(e,r){this.cache.set(e,r)}};var m=R(),C=new x,M=(t,e="/")=>e+t+".svg",Z=t=>l(null,null,function*(){try{return yield(yield fetch(t)).text()}catch(e){return console.error(e),null}}),X=t=>l(null,null,function*(){try{return new E().parse(t)}catch(e){console.error(e)}}),P=(t,e="/")=>l(null,null,function*(){let r=M(t,e),n=C.get(r);if(n)return n;let s=new Promise((c,i)=>l(null,null,function*(){try{let o=yield m==null?void 0:m.getItem(r);if(o||(o=yield Z(r),o&&setTimeout(()=>{try{let a=I(o);m==null||m.setItem(r,a)}catch(a){console.warn("Storage is full, cannot cache SVG.")}})),o){let a=yield X(o);c(a)}i(`Error occured processing Svg ${r}`)}catch(o){i(o)}}));return C.set(r,s),s});import{jsx as J}from"react/jsx-runtime";var H=q(W((c,s)=>{var i=c,{name:t,baseUrl:e="/",as:r="span"}=i,n=b(i,["name","baseUrl","as"]);let[o,a]=j(null);return F(()=>{let g=!0;return P(t,e).then(d=>{g&&d&&a(d)}).catch(d=>console.error(d)),()=>{g=!1}},[t,e]),o?f(o,s,n):J(r,{className:n.className,style:p({width:n.width,height:n.height,display:"inline-block"},n.style)})}));export{H as LocalSvg};
|
|
2
2
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/LocalSvg.tsx","../src/tree.ts","../src/minification.ts","../src/tokenizer.ts","../src/namespace.ts","../src/parser.ts","../src/store.ts","../src/query.ts"],"sourcesContent":["import { forwardRef, memo, SVGAttributes, useEffect, useState } from \"react\";\nimport { SvgNode } from \"./parser\";\nimport { buildSvgReactTree } from \"./tree\";\nimport { createSvg } from \"./query\";\n\nexport type LocalSvgNames = string;\nexport type LocalSvgProps = SVGAttributes<SVGSVGElement> & {\n name: LocalSvgNames;\n baseUrl?: string;\n as?: React.ElementType;\n};\n\nexport const LocalSvg = memo(\n forwardRef<SVGSVGElement, LocalSvgProps>(\n ({ name, baseUrl = \"/\", as = \"span\", ...props }, ref) => {\n const [node, setNode] = useState<SvgNode | null>(null);\n\n useEffect(() => {\n let alive = true;\n\n createSvg(name, baseUrl)\n .then((node) => {\n if (alive && node) setNode(node);\n })\n .catch((err) => console.error(err));\n\n return () => {\n alive = false;\n };\n }, [name, baseUrl]);\n\n const Com = as;\n\n return node ? (\n buildSvgReactTree(node, ref, props)\n ) : (\n <Com\n className={props.className}\n style={{\n width: props.width,\n height: props.height,\n display: \"inline-block\",\n ...props.style,\n }}\n />\n );\n }\n )\n);\n","import { createElement, Ref } from \"react\";\nimport { SvgNode } from \"./parser\";\n\nexport function buildSvgReactTree(\n node: SvgNode | string,\n ref: Ref<SVGSVGElement> | null = null,\n props: Record<string, any> = {},\n keyPath: string = \"0\"\n): React.ReactElement | string {\n if (typeof node === \"string\") return node;\n\n return createElement(\n node.type,\n { ...node.props, ...props, ref, key: keyPath },\n ...node.children.map((child, i) =>\n buildSvgReactTree(child, null, {}, `${keyPath}-${i}`)\n )\n );\n}\n","/**\n * Minifies an SVG string for more efficient usage in the browser or inline.\n *\n * Features:\n * 1. Removes unnecessary whitespace, line breaks, tabs, and extra spaces.\n * 2. Strips XML declarations, comments, metadata, `class` attributes, and `xmlns` attributes.\n * 3. Collapses empty tags into self-closing tags.\n * 4. Shortens long IDs (8+ characters) to sequential numeric IDs and updates all corresponding `url(#ID)` references.\n *\n * @param {string} svg - The raw SVG string to minify.\n * @returns {string} The minified SVG string with optimized IDs and whitespace removed.\n *\n * @example\n * const raw = `<svg xmlns=\"http://www.w3.org/2000/svg\">\n * <defs>\n * <linearGradient id=\"longGradient12345678\"><stop offset=\"0%\" /></linearGradient>\n * </defs>\n * <rect fill=\"url(#longGradient12345678)\" width=\"100\" height=\"100\"/>\n * </svg>`;\n *\n * const minified = minifySVG(raw);\n * console.log(minified);\n */\nexport function minifySVG(svg: string) {\n if (!svg) return \"\";\n\n // 1️⃣ Remove newlines, tabs, multiple spaces\n let min = svg\n .replace(/\\n|\\r|\\t/g, \"\")\n .replace(/\\s{2,}/g, \" \")\n .replace(/\\s*(=)\\s*\"/g, '=\"')\n .replace(/class=\"[^\"]+\"/g, \"\")\n .replace(/<!--.*?-->/g, \"\") // Remove comments\n .replace(/\\sxmlns(?::[a-zA-Z0-9_-]+)?=\"[^\"]*\"/g, \"\") // Remove xmlns attribute\n .replace(/<\\?xml[^>]*>/g, \"\") // Remove XML declaration\n .replace(/<metadata>.*?<\\/metadata>/g, \"\") // Remove metadata\n .replace(/<(\\w+)([^>]*)><\\/\\1>/g, \"<$1$2/>\") // 4️⃣ Collapse self-closing tags (optional)\n .trim();\n\n // 2️⃣ Collect all IDs that look like IconifyId* or long random IDs\n const idRegex = /id=\"([^\"]{8,})\"/g;\n let match;\n let idMap: Record<string, string> = {};\n let counter = 0;\n\n while ((match = idRegex.exec(min)) !== null) {\n const longId = match[1];\n if (!idMap[longId]) {\n idMap[longId] = counter.toString();\n counter++;\n }\n }\n\n // 3️⃣ Replace IDs and corresponding url(#ID) references\n for (const key in idMap) {\n const [longId, shortId] = [key, idMap[key]];\n const idPattern = new RegExp(`id=\"${longId}\"`, \"g\");\n min = min.replace(idPattern, `id=\"${shortId}\"`);\n const urlPattern = new RegExp(`url\\\\(#${longId}\\\\)`, \"g\");\n min = min.replace(urlPattern, `url(#${shortId})`);\n }\n\n idMap = {};\n\n return min;\n}\n","import { TOKEN_TYPE } from \"./enums\";\n\nexport class Token {\n constructor(public name: TOKEN_TYPE, public value: string) {}\n}\n\nconst Spec: [RegExp, TOKEN_TYPE | null][] = [\n [/^\\s+/, null],\n [/^<\\?xml[^]*\\?>/, null],\n [/^<!--[\\s\\S]*?-->/, null],\n [\n /^<[a-zA-Z_][\\w\\-.]*(?::[a-zA-Z_][\\w\\-.]*)?(?=[\\s>/>])/,\n TOKEN_TYPE.BEGIN_TAG,\n ],\n [\n /^[a-zA-Z_][\\w\\-.]*(?::[a-zA-Z_][\\w\\-.]*)?=[\"|'][^\"']*[\"|']/,\n TOKEN_TYPE.ATTRIBUTE,\n ],\n [/^>/, TOKEN_TYPE.END_TAG],\n [/^<\\/[a-zA-Z_][\\w\\-.]*(?::[a-zA-Z_][\\w\\-.]*)?>/, TOKEN_TYPE.CLOSE_TAG],\n [/^\\/>/, TOKEN_TYPE.END_CLOSE_TAG],\n [/^.+(?=<\\/)/, TOKEN_TYPE.TEXT],\n];\n\nclass Tokenizer {\n private _cursor = 0;\n private _string = \"\";\n\n init(str: string) {\n this._string = str;\n }\n\n isEOF() {\n return this._cursor === this._string.length;\n }\n\n hasMoreTokens() {\n return this._cursor < this._string.length;\n }\n\n getNextToken(): Token | null {\n if (!this.hasMoreTokens()) {\n return null;\n }\n\n const string = this._string.slice(this._cursor);\n\n for (const [regexp, tokenType] of Spec) {\n const tokenValue = this._match(regexp, string);\n\n if (tokenValue == null) {\n continue;\n }\n\n if (tokenType == null) {\n return this.getNextToken();\n }\n\n return new Token(tokenType, tokenValue);\n }\n\n throw new SyntaxError(`Unknown token type ${string.slice(0, 10)}`);\n }\n\n _match(reg: RegExp, string: string) {\n let matched = reg.exec(string);\n\n if (matched === null) {\n return null;\n }\n\n this._cursor += matched[0].length;\n return matched[0];\n }\n}\n\nexport { Tokenizer };\n","export const REACT_NAMESPACE_ATTRS: Record<string, string> = {\n \"xlink:actuate\": \"xlinkActuate\",\n \"xlink:arcrole\": \"xlinkArcrole\",\n \"xlink:href\": \"xlinkHref\",\n \"xlink:role\": \"xlinkRole\",\n \"xlink:show\": \"xlinkShow\",\n \"xlink:title\": \"xlinkTitle\",\n \"xlink:type\": \"xlinkType\",\n \"xml:lang\": \"xmlLang\",\n \"xml:space\": \"xmlSpace\",\n \"xml:base\": \"xmlBase\",\n \"xmlns:xlink\": \"xmlnsXlink\",\n class: \"className\",\n};\n","import { TOKEN_TYPE } from \"./enums\";\nimport { Tokenizer } from \"./tokenizer\";\nimport { REACT_NAMESPACE_ATTRS } from \"./namespace\";\n\nclass SvgNode {\n public children: (SvgNode | string)[] = [];\n constructor(\n public type: string,\n public props: { [key: string]: string } = {}\n ) {}\n\n addChild(node: SvgNode | string) {\n this.children.push(node);\n }\n\n addProp(key: string, value: string) {\n this.props[key] = value;\n }\n}\n\nconst AllowedLookAhead: Record<\n TOKEN_TYPE,\n Partial<Record<TOKEN_TYPE, boolean>>\n> = {\n [TOKEN_TYPE.BEGIN_TAG]: {\n [TOKEN_TYPE.ATTRIBUTE]: true,\n [TOKEN_TYPE.END_TAG]: true,\n [TOKEN_TYPE.END_CLOSE_TAG]: true,\n },\n [TOKEN_TYPE.ATTRIBUTE]: {\n [TOKEN_TYPE.ATTRIBUTE]: true,\n [TOKEN_TYPE.END_TAG]: true,\n [TOKEN_TYPE.END_CLOSE_TAG]: true,\n },\n [TOKEN_TYPE.END_TAG]: {\n [TOKEN_TYPE.BEGIN_TAG]: true,\n [TOKEN_TYPE.CLOSE_TAG]: true,\n [TOKEN_TYPE.TEXT]: true,\n },\n [TOKEN_TYPE.CLOSE_TAG]: {\n [TOKEN_TYPE.BEGIN_TAG]: true,\n [TOKEN_TYPE.CLOSE_TAG]: true,\n },\n [TOKEN_TYPE.END_CLOSE_TAG]: {\n [TOKEN_TYPE.BEGIN_TAG]: true,\n [TOKEN_TYPE.CLOSE_TAG]: true,\n },\n [TOKEN_TYPE.TEXT]: {\n [TOKEN_TYPE.CLOSE_TAG]: true,\n },\n};\n\nfunction formatAttributeName(name: string) {\n // 1. ARIA → passthrough\n if (name.startsWith(\"aria-\")) {\n return name;\n }\n\n // 2. Explicit React namespace mapping\n if (REACT_NAMESPACE_ATTRS[name]) {\n return REACT_NAMESPACE_ATTRS[name];\n }\n\n // 3. Unsupported XML namespaces → bail out\n if (\n name.startsWith(\"rdf:\") ||\n name.startsWith(\"cc:\") ||\n name.startsWith(\"dc:\") ||\n name.startsWith(\"xmlns:\")\n ) {\n return name.toLowerCase();\n }\n\n // 4. Standard HTML/SVG attribute\n return name.replace(/-([a-zA-Z])/g, (_, char) => char.toUpperCase());\n}\n\nclass Parser {\n tokenizer: Tokenizer;\n\n constructor() {\n this.tokenizer = new Tokenizer();\n }\n\n parse(str: string) {\n this.tokenizer.init(str);\n const root = new SvgNode(\"ROOT\");\n let tags: SvgNode[] = [root];\n let lookAhead = this.tokenizer.getNextToken();\n\n while (lookAhead) {\n const token = lookAhead;\n lookAhead = this.tokenizer.getNextToken();\n\n if (!token) {\n throw new SyntaxError(`Not Token found where expected`);\n }\n\n if (lookAhead && !AllowedLookAhead[token.name]?.[lookAhead.name]) {\n throw new SyntaxError(\n `Unexpected token ${lookAhead.name} after ${token.name}`\n );\n }\n\n switch (token.name) {\n case TOKEN_TYPE.BEGIN_TAG:\n const node = new SvgNode(token.value.slice(1));\n tags[tags.length - 1].addChild(node);\n tags.push(node);\n break;\n\n case TOKEN_TYPE.ATTRIBUTE:\n const [name, value] = token.value.split(\"=\");\n\n tags[tags.length - 1].addProp(\n formatAttributeName(name),\n value.slice(1, -1)\n );\n break;\n\n case TOKEN_TYPE.END_TAG:\n //Do nothing\n break;\n\n case TOKEN_TYPE.CLOSE_TAG:\n if (tags.length <= 1) {\n // ✅ NOW in the right place\n throw new SyntaxError(\"Unexpected closing tag\");\n }\n const current = tags.pop()!;\n if (current.type !== token.value.slice(2, -1)) {\n throw new SyntaxError(\n `Mismatched tag: expected </${current.type}>, got ${token.value}`\n );\n }\n break;\n\n case TOKEN_TYPE.END_CLOSE_TAG:\n if (tags.length <= 1) {\n // ✅ NOW in the right place\n throw new SyntaxError(\"Unexpected closing tag\");\n }\n tags.pop();\n break;\n\n case TOKEN_TYPE.TEXT:\n tags[tags.length - 1].addChild(token.value);\n break;\n\n default:\n throw new SyntaxError(`Unknown token type: ${token.name}`);\n }\n }\n\n if (tags.length > 1) {\n throw new SyntaxError(\n `Invalid SVG structure: Missing </${tags[tags.length - 1].type}>`\n );\n }\n\n return root.children[0] as SvgNode;\n }\n}\n\nexport { Parser, SvgNode };\n","interface Store {\n getItem(key: string): Promise<string | null>;\n setItem(key: string, content:string): Promise<void>;\n}\n\nclass LocalStorageStore implements Store {\n async getItem(key: string): Promise<string | null> {\n const item = localStorage.getItem(key);\n return item ? (JSON.parse(item) as string) : null;\n }\n\n async setItem(key: string, value: string) {\n localStorage.setItem(key, value);\n }\n}\n\nclass IndexedDBStore implements Store {\n private dbName = \"LOCAL_SVG_DB\";\n private storeName = \"svgs\";\n private dbPromise: Promise<IDBDatabase>;\n private version = 1;\n\n constructor() {\n this.dbPromise = this.openDB();\n }\n\n private openDB(): Promise<IDBDatabase> {\n return new Promise((resolve, reject) => {\n const idb: IDBFactory | null =\n window.indexedDB ||\n (window as any).mozIndexedDB ||\n (window as any).webkitIndexedDB ||\n (window as any).msIndexedDB;\n if (!idb) {\n reject(new Error(\"IndexedDB is not supported in this environment.\"));\n return;\n }\n const request = indexedDB.open(this.dbName, this.version);\n request.onupgradeneeded = () => {\n const db = request.result;\n if (!db.objectStoreNames.contains(this.storeName)) {\n db.createObjectStore(this.storeName);\n }\n };\n request.onsuccess = () => resolve(request.result);\n request.onerror = () => reject(request.error);\n });\n }\n\n async getItem(key: string): Promise<string | null> {\n const db = await this.dbPromise;\n return new Promise((resolve, reject) => {\n const transaction = db.transaction(this.storeName, \"readonly\");\n const store = transaction.objectStore(this.storeName);\n const request = store.get(key);\n request.onsuccess = () => {\n resolve((request.result as string) || null);\n };\n request.onerror = () => {\n reject(request.error);\n };\n });\n }\n\n async setItem(key: string, value: string): Promise<void> {\n const db = await this.dbPromise;\n return new Promise((resolve, reject) => {\n const transaction = db.transaction(this.storeName, \"readwrite\");\n const store = transaction.objectStore(this.storeName);\n const request = store.put(value, key);\n request.onsuccess = () => resolve();\n request.onerror = () => reject(request.error);\n });\n }\n}\n\nexport const createStore = (storage?: \"localstorage\" | \"indexdb\"): Store => {\n if (typeof window === \"undefined\") {\n console.warn(\"Store can only be created in a browser environment.\");\n return null;\n }\n try {\n if (storage === \"localstorage\") {\n return new LocalStorageStore();\n }\n return new IndexedDBStore();\n } catch (error) {\n return new LocalStorageStore();\n }\n};\n\nexport class PromiseCache<T> {\n private cache: Map<string, Promise<T>>;\n\n constructor() {\n this.cache = new Map();\n }\n\n get(key: string): Promise<T> | undefined {\n return this.cache.get(key);\n }\n\n set(key: string, promise: Promise<T>): void {\n this.cache.set(key, promise);\n }\n}","import { minifySVG } from \"./minification\";\nimport { Parser, SvgNode } from \"./parser\";\nimport { createStore, PromiseCache } from \"./store\";\n\nconst store = createStore();\nconst promiseCache = new PromiseCache<SvgNode>();\n\nconst composeUrl = (name: string, baseUrl = \"/\") => {\n return baseUrl + name + \".svg\";\n};\n\nconst _fetch = async (url: string) => {\n try {\n const response = await fetch(url);\n return await response.text();\n } catch (error) {\n console.error(error);\n return null;\n }\n};\n\nconst processSvgText = async (text: string) => {\n try {\n const parser = new Parser();\n return parser.parse(text);\n } catch (error) {\n console.error(error);\n }\n};\n\nexport const createSvg = async (name: string, baseUrl = \"/\") => {\n const fullUrl = composeUrl(name, baseUrl);\n const promise = promiseCache.get(fullUrl);\n\n if (promise) {\n return promise;\n }\n\n const newPromise = new Promise<SvgNode>(async (resolve, reject) => {\n try {\n let text = await store?.getItem(fullUrl);\n\n if (!text) {\n text = await _fetch(fullUrl);\n\n if (text) {\n setTimeout(() => {\n try {\n const minified = minifySVG(text);\n store?.setItem(fullUrl, minified);\n } catch (error) {\n console.warn(\"Storage is full, cannot cache SVG.\");\n }\n });\n }\n }\n\n if (text) {\n const node = await processSvgText(text);\n resolve(node);\n }\n\n reject(`Error occured processing Svg ${fullUrl}`);\n } catch (error) {\n reject(error);\n }\n });\n\n promiseCache.set(fullUrl, newPromise);\n\n return newPromise;\n};\n"],"mappings":"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","names":["forwardRef","memo","useEffect","useState","createElement","buildSvgReactTree","node","ref","props","keyPath","createElement","__spreadProps","__spreadValues","child","i","minifySVG","svg","min","idRegex","match","idMap","counter","longId","key","shortId","idPattern","urlPattern","Token","name","value","Spec","Tokenizer","str","string","regexp","tokenType","tokenValue","reg","matched","REACT_NAMESPACE_ATTRS","SvgNode","type","props","node","key","value","AllowedLookAhead","formatAttributeName","name","REACT_NAMESPACE_ATTRS","_","char","Parser","Tokenizer","str","_a","root","tags","lookAhead","token","current","LocalStorageStore","key","__async","item","value","IndexedDBStore","resolve","reject","request","db","createStore","storage","error","PromiseCache","promise","store","createStore","promiseCache","PromiseCache","composeUrl","name","baseUrl","_fetch","url","__async","error","processSvgText","text","Parser","createSvg","fullUrl","promise","newPromise","resolve","reject","minified","minifySVG","node","jsx","LocalSvg","memo","forwardRef","_a","ref","_b","name","baseUrl","as","props","__objRest","node","setNode","useState","useEffect","alive","createSvg","err","buildSvgReactTree","__spreadValues"]}
|
|
1
|
+
{"version":3,"sources":["../src/LocalSvg.tsx","../src/tree.ts","../src/minification.ts","../src/tokenizer.ts","../src/namespace.ts","../src/parser.ts","../src/store.ts","../src/query.ts"],"sourcesContent":["import { forwardRef, memo, SVGAttributes, useEffect, useState } from \"react\";\nimport { SvgNode } from \"./parser\";\nimport { buildSvgReactTree } from \"./tree\";\nimport { createSvg } from \"./query\";\n\nexport type LocalSvgProps = SVGAttributes<SVGSVGElement> & {\n name: LocalSvg.LocalSvgNames;\n baseUrl?: string;\n as?: React.ElementType;\n};\n\nexport const LocalSvg = memo(\n forwardRef<SVGSVGElement, LocalSvgProps>(\n ({ name, baseUrl = \"/\", as = \"span\", ...props }, ref) => {\n const [node, setNode] = useState<SvgNode | null>(null);\n\n useEffect(() => {\n let alive = true;\n\n createSvg(name, baseUrl)\n .then((node) => {\n if (alive && node) setNode(node);\n })\n .catch((err) => console.error(err));\n\n return () => {\n alive = false;\n };\n }, [name, baseUrl]);\n\n const Com = as;\n\n return node ? (\n buildSvgReactTree(node, ref, props)\n ) : (\n <Com\n className={props.className}\n style={{\n width: props.width,\n height: props.height,\n display: \"inline-block\",\n ...props.style,\n }}\n />\n );\n }\n )\n);\n","import { createElement, Ref } from \"react\";\nimport { SvgNode } from \"./parser\";\n\nexport function buildSvgReactTree(\n node: SvgNode | string,\n ref: Ref<SVGSVGElement> | null = null,\n props: Record<string, any> = {},\n keyPath: string = \"0\"\n): React.ReactElement | string {\n if (typeof node === \"string\") return node;\n\n return createElement(\n node.type,\n { ...node.props, ...props, ref, key: keyPath },\n ...node.children.map((child, i) =>\n buildSvgReactTree(child, null, {}, `${keyPath}-${i}`)\n )\n );\n}\n","/**\n * Minifies an SVG string for more efficient usage in the browser or inline.\n *\n * Features:\n * 1. Removes unnecessary whitespace, line breaks, tabs, and extra spaces.\n * 2. Strips XML declarations, comments, metadata, `class` attributes, and `xmlns` attributes.\n * 3. Collapses empty tags into self-closing tags.\n * 4. Shortens long IDs (8+ characters) to sequential numeric IDs and updates all corresponding `url(#ID)` references.\n *\n * @param {string} svg - The raw SVG string to minify.\n * @returns {string} The minified SVG string with optimized IDs and whitespace removed.\n *\n * @example\n * const raw = `<svg xmlns=\"http://www.w3.org/2000/svg\">\n * <defs>\n * <linearGradient id=\"longGradient12345678\"><stop offset=\"0%\" /></linearGradient>\n * </defs>\n * <rect fill=\"url(#longGradient12345678)\" width=\"100\" height=\"100\"/>\n * </svg>`;\n *\n * const minified = minifySVG(raw);\n * console.log(minified);\n */\nexport function minifySVG(svg: string) {\n if (!svg) return \"\";\n\n // 1️⃣ Remove newlines, tabs, multiple spaces\n let min = svg\n .replace(/\\n|\\r|\\t/g, \"\")\n .replace(/\\s{2,}/g, \" \")\n .replace(/\\s*(=)\\s*\"/g, '=\"')\n .replace(/class=\"[^\"]+\"/g, \"\")\n .replace(/<!--.*?-->/g, \"\") // Remove comments\n .replace(/\\sxmlns(?::[a-zA-Z0-9_-]+)?=\"[^\"]*\"/g, \"\") // Remove xmlns attribute\n .replace(/<\\?xml[^>]*>/g, \"\") // Remove XML declaration\n .replace(/<metadata>.*?<\\/metadata>/g, \"\") // Remove metadata\n .replace(/<(\\w+)([^>]*)><\\/\\1>/g, \"<$1$2/>\") // 4️⃣ Collapse self-closing tags (optional)\n .trim();\n\n // 2️⃣ Collect all IDs that look like IconifyId* or long random IDs\n const idRegex = /id=\"([^\"]{8,})\"/g;\n let match;\n let idMap: Record<string, string> = {};\n let counter = 0;\n\n while ((match = idRegex.exec(min)) !== null) {\n const longId = match[1];\n if (!idMap[longId]) {\n idMap[longId] = counter.toString();\n counter++;\n }\n }\n\n // 3️⃣ Replace IDs and corresponding url(#ID) references\n for (const key in idMap) {\n const [longId, shortId] = [key, idMap[key]];\n const idPattern = new RegExp(`id=\"${longId}\"`, \"g\");\n min = min.replace(idPattern, `id=\"${shortId}\"`);\n const urlPattern = new RegExp(`url\\\\(#${longId}\\\\)`, \"g\");\n min = min.replace(urlPattern, `url(#${shortId})`);\n }\n\n idMap = {};\n\n return min;\n}\n","import { TOKEN_TYPE } from \"./enums\";\n\nexport class Token {\n constructor(public name: TOKEN_TYPE, public value: string) {}\n}\n\nconst Spec: [RegExp, TOKEN_TYPE | null][] = [\n [/^\\s+/, null],\n [/^<\\?xml[^]*\\?>/, null],\n [/^<!--[\\s\\S]*?-->/, null],\n [\n /^<[a-zA-Z_][\\w\\-.]*(?::[a-zA-Z_][\\w\\-.]*)?(?=[\\s>/>])/,\n TOKEN_TYPE.BEGIN_TAG,\n ],\n [\n /^[a-zA-Z_][\\w\\-.]*(?::[a-zA-Z_][\\w\\-.]*)?=[\"|'][^\"']*[\"|']/,\n TOKEN_TYPE.ATTRIBUTE,\n ],\n [/^>/, TOKEN_TYPE.END_TAG],\n [/^<\\/[a-zA-Z_][\\w\\-.]*(?::[a-zA-Z_][\\w\\-.]*)?>/, TOKEN_TYPE.CLOSE_TAG],\n [/^\\/>/, TOKEN_TYPE.END_CLOSE_TAG],\n [/^.+(?=<\\/)/, TOKEN_TYPE.TEXT],\n];\n\nclass Tokenizer {\n private _cursor = 0;\n private _string = \"\";\n\n init(str: string) {\n this._string = str;\n }\n\n isEOF() {\n return this._cursor === this._string.length;\n }\n\n hasMoreTokens() {\n return this._cursor < this._string.length;\n }\n\n getNextToken(): Token | null {\n if (!this.hasMoreTokens()) {\n return null;\n }\n\n const string = this._string.slice(this._cursor);\n\n for (const [regexp, tokenType] of Spec) {\n const tokenValue = this._match(regexp, string);\n\n if (tokenValue == null) {\n continue;\n }\n\n if (tokenType == null) {\n return this.getNextToken();\n }\n\n return new Token(tokenType, tokenValue);\n }\n\n throw new SyntaxError(`Unknown token type ${string.slice(0, 10)}`);\n }\n\n _match(reg: RegExp, string: string) {\n let matched = reg.exec(string);\n\n if (matched === null) {\n return null;\n }\n\n this._cursor += matched[0].length;\n return matched[0];\n }\n}\n\nexport { Tokenizer };\n","export const REACT_NAMESPACE_ATTRS: Record<string, string> = {\n \"xlink:actuate\": \"xlinkActuate\",\n \"xlink:arcrole\": \"xlinkArcrole\",\n \"xlink:href\": \"xlinkHref\",\n \"xlink:role\": \"xlinkRole\",\n \"xlink:show\": \"xlinkShow\",\n \"xlink:title\": \"xlinkTitle\",\n \"xlink:type\": \"xlinkType\",\n \"xml:lang\": \"xmlLang\",\n \"xml:space\": \"xmlSpace\",\n \"xml:base\": \"xmlBase\",\n \"xmlns:xlink\": \"xmlnsXlink\",\n class: \"className\",\n};\n","import { TOKEN_TYPE } from \"./enums\";\nimport { Tokenizer } from \"./tokenizer\";\nimport { REACT_NAMESPACE_ATTRS } from \"./namespace\";\n\nclass SvgNode {\n public children: (SvgNode | string)[] = [];\n constructor(\n public type: string,\n public props: { [key: string]: string } = {}\n ) {}\n\n addChild(node: SvgNode | string) {\n this.children.push(node);\n }\n\n addProp(key: string, value: string) {\n this.props[key] = value;\n }\n}\n\nconst AllowedLookAhead: Record<\n TOKEN_TYPE,\n Partial<Record<TOKEN_TYPE, boolean>>\n> = {\n [TOKEN_TYPE.BEGIN_TAG]: {\n [TOKEN_TYPE.ATTRIBUTE]: true,\n [TOKEN_TYPE.END_TAG]: true,\n [TOKEN_TYPE.END_CLOSE_TAG]: true,\n },\n [TOKEN_TYPE.ATTRIBUTE]: {\n [TOKEN_TYPE.ATTRIBUTE]: true,\n [TOKEN_TYPE.END_TAG]: true,\n [TOKEN_TYPE.END_CLOSE_TAG]: true,\n },\n [TOKEN_TYPE.END_TAG]: {\n [TOKEN_TYPE.BEGIN_TAG]: true,\n [TOKEN_TYPE.CLOSE_TAG]: true,\n [TOKEN_TYPE.TEXT]: true,\n },\n [TOKEN_TYPE.CLOSE_TAG]: {\n [TOKEN_TYPE.BEGIN_TAG]: true,\n [TOKEN_TYPE.CLOSE_TAG]: true,\n },\n [TOKEN_TYPE.END_CLOSE_TAG]: {\n [TOKEN_TYPE.BEGIN_TAG]: true,\n [TOKEN_TYPE.CLOSE_TAG]: true,\n },\n [TOKEN_TYPE.TEXT]: {\n [TOKEN_TYPE.CLOSE_TAG]: true,\n },\n};\n\nfunction formatAttributeName(name: string) {\n // 1. ARIA → passthrough\n if (name.startsWith(\"aria-\")) {\n return name;\n }\n\n // 2. Explicit React namespace mapping\n if (REACT_NAMESPACE_ATTRS[name]) {\n return REACT_NAMESPACE_ATTRS[name];\n }\n\n // 3. Unsupported XML namespaces → bail out\n if (\n name.startsWith(\"rdf:\") ||\n name.startsWith(\"cc:\") ||\n name.startsWith(\"dc:\") ||\n name.startsWith(\"xmlns:\")\n ) {\n return name.toLowerCase();\n }\n\n // 4. Standard HTML/SVG attribute\n return name.replace(/-([a-zA-Z])/g, (_, char) => char.toUpperCase());\n}\n\nclass Parser {\n tokenizer: Tokenizer;\n\n constructor() {\n this.tokenizer = new Tokenizer();\n }\n\n parse(str: string) {\n this.tokenizer.init(str);\n const root = new SvgNode(\"ROOT\");\n let tags: SvgNode[] = [root];\n let lookAhead = this.tokenizer.getNextToken();\n\n while (lookAhead) {\n const token = lookAhead;\n lookAhead = this.tokenizer.getNextToken();\n\n if (!token) {\n throw new SyntaxError(`Not Token found where expected`);\n }\n\n if (lookAhead && !AllowedLookAhead[token.name]?.[lookAhead.name]) {\n throw new SyntaxError(\n `Unexpected token ${lookAhead.name} after ${token.name}`\n );\n }\n\n switch (token.name) {\n case TOKEN_TYPE.BEGIN_TAG:\n const node = new SvgNode(token.value.slice(1));\n tags[tags.length - 1].addChild(node);\n tags.push(node);\n break;\n\n case TOKEN_TYPE.ATTRIBUTE:\n const [name, value] = token.value.split(\"=\");\n\n tags[tags.length - 1].addProp(\n formatAttributeName(name),\n value.slice(1, -1)\n );\n break;\n\n case TOKEN_TYPE.END_TAG:\n //Do nothing\n break;\n\n case TOKEN_TYPE.CLOSE_TAG:\n if (tags.length <= 1) {\n // ✅ NOW in the right place\n throw new SyntaxError(\"Unexpected closing tag\");\n }\n const current = tags.pop()!;\n if (current.type !== token.value.slice(2, -1)) {\n throw new SyntaxError(\n `Mismatched tag: expected </${current.type}>, got ${token.value}`\n );\n }\n break;\n\n case TOKEN_TYPE.END_CLOSE_TAG:\n if (tags.length <= 1) {\n // ✅ NOW in the right place\n throw new SyntaxError(\"Unexpected closing tag\");\n }\n tags.pop();\n break;\n\n case TOKEN_TYPE.TEXT:\n tags[tags.length - 1].addChild(token.value);\n break;\n\n default:\n throw new SyntaxError(`Unknown token type: ${token.name}`);\n }\n }\n\n if (tags.length > 1) {\n throw new SyntaxError(\n `Invalid SVG structure: Missing </${tags[tags.length - 1].type}>`\n );\n }\n\n return root.children[0] as SvgNode;\n }\n}\n\nexport { Parser, SvgNode };\n","interface Store {\n getItem(key: string): Promise<string | null>;\n setItem(key: string, content:string): Promise<void>;\n}\n\nclass LocalStorageStore implements Store {\n async getItem(key: string): Promise<string | null> {\n const item = localStorage.getItem(key);\n return item ? (JSON.parse(item) as string) : null;\n }\n\n async setItem(key: string, value: string) {\n localStorage.setItem(key, value);\n }\n}\n\nclass IndexedDBStore implements Store {\n private dbName = \"LOCAL_SVG_DB\";\n private storeName = \"svgs\";\n private dbPromise: Promise<IDBDatabase>;\n private version = 1;\n\n constructor() {\n this.dbPromise = this.openDB();\n }\n\n private openDB(): Promise<IDBDatabase> {\n return new Promise((resolve, reject) => {\n const idb: IDBFactory | null =\n window.indexedDB ||\n (window as any).mozIndexedDB ||\n (window as any).webkitIndexedDB ||\n (window as any).msIndexedDB;\n if (!idb) {\n reject(new Error(\"IndexedDB is not supported in this environment.\"));\n return;\n }\n const request = indexedDB.open(this.dbName, this.version);\n request.onupgradeneeded = () => {\n const db = request.result;\n if (!db.objectStoreNames.contains(this.storeName)) {\n db.createObjectStore(this.storeName);\n }\n };\n request.onsuccess = () => resolve(request.result);\n request.onerror = () => reject(request.error);\n });\n }\n\n async getItem(key: string): Promise<string | null> {\n const db = await this.dbPromise;\n return new Promise((resolve, reject) => {\n const transaction = db.transaction(this.storeName, \"readonly\");\n const store = transaction.objectStore(this.storeName);\n const request = store.get(key);\n request.onsuccess = () => {\n resolve((request.result as string) || null);\n };\n request.onerror = () => {\n reject(request.error);\n };\n });\n }\n\n async setItem(key: string, value: string): Promise<void> {\n const db = await this.dbPromise;\n return new Promise((resolve, reject) => {\n const transaction = db.transaction(this.storeName, \"readwrite\");\n const store = transaction.objectStore(this.storeName);\n const request = store.put(value, key);\n request.onsuccess = () => resolve();\n request.onerror = () => reject(request.error);\n });\n }\n}\n\nexport const createStore = (storage?: \"localstorage\" | \"indexdb\"): Store => {\n if (typeof window === \"undefined\") {\n console.warn(\"Store can only be created in a browser environment.\");\n return null;\n }\n try {\n if (storage === \"localstorage\") {\n return new LocalStorageStore();\n }\n return new IndexedDBStore();\n } catch (error) {\n return new LocalStorageStore();\n }\n};\n\nexport class PromiseCache<T> {\n private cache: Map<string, Promise<T>>;\n\n constructor() {\n this.cache = new Map();\n }\n\n get(key: string): Promise<T> | undefined {\n return this.cache.get(key);\n }\n\n set(key: string, promise: Promise<T>): void {\n this.cache.set(key, promise);\n }\n}","import { minifySVG } from \"./minification\";\nimport { Parser, SvgNode } from \"./parser\";\nimport { createStore, PromiseCache } from \"./store\";\n\nconst store = createStore();\nconst promiseCache = new PromiseCache<SvgNode>();\n\nconst composeUrl = (name: string, baseUrl = \"/\") => {\n return baseUrl + name + \".svg\";\n};\n\nconst _fetch = async (url: string) => {\n try {\n const response = await fetch(url);\n return await response.text();\n } catch (error) {\n console.error(error);\n return null;\n }\n};\n\nconst processSvgText = async (text: string) => {\n try {\n const parser = new Parser();\n return parser.parse(text);\n } catch (error) {\n console.error(error);\n }\n};\n\nexport const createSvg = async (name: string, baseUrl = \"/\") => {\n const fullUrl = composeUrl(name, baseUrl);\n const promise = promiseCache.get(fullUrl);\n\n if (promise) {\n return promise;\n }\n\n const newPromise = new Promise<SvgNode>(async (resolve, reject) => {\n try {\n let text = await store?.getItem(fullUrl);\n\n if (!text) {\n text = await _fetch(fullUrl);\n\n if (text) {\n setTimeout(() => {\n try {\n const minified = minifySVG(text);\n store?.setItem(fullUrl, minified);\n } catch (error) {\n console.warn(\"Storage is full, cannot cache SVG.\");\n }\n });\n }\n }\n\n if (text) {\n const node = await processSvgText(text);\n resolve(node);\n }\n\n reject(`Error occured processing Svg ${fullUrl}`);\n } catch (error) {\n reject(error);\n }\n });\n\n promiseCache.set(fullUrl, newPromise);\n\n return newPromise;\n};\n"],"mappings":"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","names":["forwardRef","memo","useEffect","useState","createElement","buildSvgReactTree","node","ref","props","keyPath","createElement","__spreadProps","__spreadValues","child","i","minifySVG","svg","min","idRegex","match","idMap","counter","longId","key","shortId","idPattern","urlPattern","Token","name","value","Spec","Tokenizer","str","string","regexp","tokenType","tokenValue","reg","matched","REACT_NAMESPACE_ATTRS","SvgNode","type","props","node","key","value","AllowedLookAhead","formatAttributeName","name","REACT_NAMESPACE_ATTRS","_","char","Parser","Tokenizer","str","_a","root","tags","lookAhead","token","current","LocalStorageStore","key","__async","item","value","IndexedDBStore","resolve","reject","request","db","createStore","storage","error","PromiseCache","promise","store","createStore","promiseCache","PromiseCache","composeUrl","name","baseUrl","_fetch","url","__async","error","processSvgText","text","Parser","createSvg","fullUrl","promise","newPromise","resolve","reject","minified","minifySVG","node","jsx","LocalSvg","memo","forwardRef","_a","ref","_b","name","baseUrl","as","props","__objRest","node","setNode","useState","useEffect","alive","createSvg","err","buildSvgReactTree","__spreadValues"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "local-svg",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.9",
|
|
4
4
|
"description": "LocalSvg - A lightweight React component for loading local or remote SVGs. Skip bloated icon sets and streamline your custom icon workflow.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -11,7 +11,6 @@
|
|
|
11
11
|
},
|
|
12
12
|
"author": "Godswill Anwuli",
|
|
13
13
|
"license": "MIT",
|
|
14
|
-
"private": false,
|
|
15
14
|
"keywords": [
|
|
16
15
|
"svg",
|
|
17
16
|
"icon",
|
|
@@ -23,8 +22,7 @@
|
|
|
23
22
|
"dist"
|
|
24
23
|
],
|
|
25
24
|
"scripts": {
|
|
26
|
-
"build": "tsup"
|
|
27
|
-
"publish": "npm publish --access public"
|
|
25
|
+
"build": "tsup"
|
|
28
26
|
},
|
|
29
27
|
"devDependencies": {
|
|
30
28
|
"@types/node": "^25.0.8",
|