local-svg 0.0.3 → 0.0.5

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/README.md CHANGED
@@ -0,0 +1,170 @@
1
+ # LocalSvg
2
+
3
+ A lightweight, performant React component for loading and rendering local or remote SVG files directly as React components. Skip bloated icon libraries and streamline your custom icon workflow.
4
+
5
+ ## Why LocalSvg?
6
+
7
+ - **No Icon Set Bloat**: Use only the SVGs you need without including massive icon library dependencies
8
+ - **Smart Caching**: Automatic localStorage caching with in-memory promise caching for optimal performance
9
+ - **Automatic Minification**: SVG files are automatically minified to reduce bandwidth and storage
10
+ - **Pure React Components**: SVGs are parsed and rendered as native React components with full TypeScript support
11
+ - **Flexible Loading**: Load SVGs from any URL or local path
12
+ - **Namespace Aware**: Automatically handles XML/SVG namespaces and converts them to React-compatible attributes
13
+ - **Lightweight**: No external dependencies (except React)
14
+
15
+ ## Installation
16
+
17
+ ```bash
18
+ npm install local-svg
19
+ ```
20
+
21
+ Or with yarn:
22
+
23
+ ```bash
24
+ yarn add local-svg
25
+ ```
26
+
27
+ ## Quick Start
28
+
29
+ ```tsx
30
+ import { LocalSvg } from 'local-svg';
31
+
32
+ export default function App() {
33
+ return (
34
+ <LocalSvg
35
+ name="icon-name"
36
+ width={24}
37
+ height={24}
38
+ />
39
+ );
40
+ }
41
+ ```
42
+
43
+ ## Props
44
+
45
+ ### LocalSvgProps
46
+
47
+ Extends `SVGAttributes<SVGSVGElement>`, so you can use any standard SVG element props.
48
+
49
+ | Prop | Type | Default | Description |
50
+ |------|------|---------|-------------|
51
+ | `name` | `string` | Required | The name of the SVG file (without `.svg` extension) |
52
+ | `baseUrl` | `string` | `"/"` | The base URL or path where SVG files are located |
53
+ | `as` | `React.ElementType` | `"span"` | The wrapper component to use while loading |
54
+ | `ref` | `RefObject<SVGSVGElement>` | - | Forward ref to the SVG element |
55
+ | `...rest` | `SVGAttributes` | - | Any standard SVG attributes (className, style, onClick, etc.) |
56
+
57
+ ## Usage Examples
58
+
59
+ ### Basic Icon
60
+
61
+ ```tsx
62
+ <LocalSvg name="star" width={24} height={24} />
63
+ ```
64
+
65
+ ### With Custom Styling
66
+
67
+ ```tsx
68
+ <LocalSvg
69
+ name="logo"
70
+ width={100}
71
+ height={100}
72
+ className="logo-icon"
73
+ style={{ color: '#007bff', filter: 'drop-shadow(0 2px 4px rgba(0,0,0,0.1))' }}
74
+ />
75
+ ```
76
+
77
+ ### Custom Base URL
78
+
79
+ ```tsx
80
+ <LocalSvg
81
+ name="icon"
82
+ baseUrl="/static/icons/"
83
+ />
84
+ ```
85
+
86
+ ### With Event Handlers
87
+
88
+ ```tsx
89
+ <LocalSvg
90
+ name="button-icon"
91
+ width={20}
92
+ height={20}
93
+ onClick={() => console.log('Clicked!')}
94
+ style={{ cursor: 'pointer' }}
95
+ />
96
+ ```
97
+
98
+ ### With Loading Placeholder
99
+
100
+ ```tsx
101
+ <LocalSvg
102
+ name="spinner"
103
+ width={24}
104
+ height={24}
105
+ as="div"
106
+ className="loading-placeholder"
107
+ />
108
+ ```
109
+
110
+ The `as` prop specifies what to render while the SVG is loading (defaults to `span`).
111
+
112
+ ## How It Works
113
+
114
+ 1. **Fetching**: Loads the SVG file from the URL when the component mounts
115
+ 2. **Parsing**: Converts the SVG text into a React-friendly structure
116
+ 3. **Minification**: Removes unnecessary data from the SVG (whitespace, comments, etc.) to save space
117
+ 4. **Caching**:
118
+ - Stores the minified SVG in browser localStorage so it doesn't need to be fetched again
119
+ - Uses in-memory cache to prevent duplicate requests in the same session
120
+ 5. **Rendering**: Displays the SVG as native React elements
121
+
122
+ ## Performance Optimizations
123
+
124
+ LocalSvg is built for speed:
125
+
126
+ - **Smart Caching**: localStorage persists minified SVGs across page reloads, reducing bandwidth on return visits by 99%
127
+ - **Size Reduction**: SVGs are automatically cleaned up, saving 40-60% of file size on average
128
+ - **React Optimized**: Prevents unnecessary re-renders and avoids duplicate fetch requests
129
+
130
+ ## TypeScript Support
131
+
132
+ Full TypeScript support is built-in:
133
+
134
+ ```tsx
135
+ import { LocalSvg, type LocalSvgProps } from 'local-svg';
136
+
137
+ const IconWrapper: React.FC<LocalSvgProps> = (props) => {
138
+ return <LocalSvg {...props} />;
139
+ };
140
+ ```
141
+
142
+ ## Browser Support
143
+
144
+ Works in all modern browsers that support:
145
+ - ES6+ JavaScript
146
+ - React 18+
147
+ - localStorage API
148
+
149
+ ## API Reference
150
+
151
+ ### LocalSvg
152
+
153
+ The main React component for rendering SVGs.
154
+
155
+ ```tsx
156
+ <LocalSvg
157
+ name="icon-name"
158
+ baseUrl="/"
159
+ as="span"
160
+ width={24}
161
+ height={24}
162
+ className="my-icon"
163
+ // ... any SVG attributes
164
+ ref={svgRef}
165
+ />
166
+ ```
167
+
168
+ ## License
169
+
170
+ MIT © Godswill Anwuli
package/dist/index.d.mts CHANGED
@@ -1,13 +1,14 @@
1
1
  import * as react from 'react';
2
2
  import { SVGAttributes } from 'react';
3
3
 
4
+ type LocalSvgNames = string;
4
5
  type LocalSvgProps = SVGAttributes<SVGSVGElement> & {
5
- name: string;
6
+ name: LocalSvgNames;
6
7
  baseUrl?: string;
7
8
  as?: React.ElementType;
8
9
  };
9
10
  declare const LocalSvg: react.NamedExoticComponent<SVGAttributes<SVGSVGElement> & {
10
- name: string;
11
+ name: LocalSvgNames;
11
12
  baseUrl?: string;
12
13
  as?: React.ElementType;
13
14
  } & react.RefAttributes<SVGSVGElement>>;
package/dist/index.d.ts CHANGED
@@ -1,13 +1,14 @@
1
1
  import * as react from 'react';
2
2
  import { SVGAttributes } from 'react';
3
3
 
4
+ type LocalSvgNames = string;
4
5
  type LocalSvgProps = SVGAttributes<SVGSVGElement> & {
5
- name: string;
6
+ name: LocalSvgNames;
6
7
  baseUrl?: string;
7
8
  as?: React.ElementType;
8
9
  };
9
10
  declare const LocalSvg: react.NamedExoticComponent<SVGAttributes<SVGSVGElement> & {
10
- name: string;
11
+ name: LocalSvgNames;
11
12
  baseUrl?: string;
12
13
  as?: React.ElementType;
13
14
  } & react.RefAttributes<SVGSVGElement>>;
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- var d=Object.defineProperty,I=Object.defineProperties,O=Object.getOwnPropertyDescriptor,$=Object.getOwnPropertyDescriptors,B=Object.getOwnPropertyNames,E=Object.getOwnPropertySymbols;var _=Object.prototype.hasOwnProperty,N=Object.prototype.propertyIsEnumerable;var k=(t,e,r)=>e in t?d(t,e,{enumerable:!0,configurable:!0,writable:!0,value:r}):t[e]=r,T=(t,e)=>{for(var r in e||(e={}))_.call(e,r)&&k(t,r,e[r]);if(E)for(var r of E(e))N.call(e,r)&&k(t,r,e[r]);return t},y=(t,e)=>I(t,$(e));var R=(t,e)=>{var r={};for(var n in t)_.call(t,n)&&e.indexOf(n)<0&&(r[n]=t[n]);if(t!=null&&E)for(var n of E(t))e.indexOf(n)<0&&N.call(t,n)&&(r[n]=t[n]);return r};var U=(t,e)=>{for(var r in e)d(t,r,{get:e[r],enumerable:!0})},z=(t,e,r,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of B(e))!_.call(t,o)&&o!==r&&d(t,o,{get:()=>e[o],enumerable:!(n=O(e,o))||n.enumerable});return t};var D=t=>z(d({},"__esModule",{value:!0}),t);var u=(t,e,r)=>new Promise((n,o)=>{var s=c=>{try{l(r.next(c))}catch(a){o(a)}},i=c=>{try{l(r.throw(c))}catch(a){o(a)}},l=c=>c.done?n(c.value):Promise.resolve(c.value).then(s,i);l((r=r.apply(t,e)).next())});var H={};U(H,{LocalSvg:()=>L});module.exports=D(H);var g=require("react");var v=require("react");function A(t,e=null,r={},n="0"){return typeof t=="string"?t:(0,v.createElement)(t.type,y(T(T({},t.props),r),{ref:e,key:n}),...t.children.map((o,s)=>A(o,null,{},`${n}-${s}`)))}var w=class{constructor(e,r){this.name=e;this.value=r}},V=[[/^\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"]],S=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 V){let o=this._match(r,e);if(o!=null)return n==null?this.getNextToken():new w(n,o)}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 m=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}},M={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 X(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 f=class{constructor(){this.tokenizer=new S}parse(e){var s;this.tokenizer.init(e);let r=new m("ROOT"),n=[r],o=this.tokenizer.getNextToken();for(;o;){let i=o;if(o=this.tokenizer.getNextToken(),!i)throw new SyntaxError("Not Token found where expected");if(o&&!((s=M[i.name])!=null&&s[o.name]))throw new SyntaxError(`Unexpected token ${o.name} after ${i.name}`);switch(i.name){case"BEGIN_TAG":let l=new m(i.value.slice(1));n[n.length-1].addChild(l),n.push(l);break;case"ATTRIBUTE":let[c,a]=i.value.split("=");n[n.length-1].addProp(X(c),a.slice(1,-1));break;case"END_TAG":break;case"CLOSE_TAG":if(n.length<=1)throw new SyntaxError("Unexpected closing tag");let p=n.pop();if(p.type!==i.value.slice(2,-1))throw new SyntaxError(`Mismatched tag: expected </${p.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 x={},Z=(t,e="/")=>e+t+".svg",W=t=>u(null,null,function*(){try{return yield(yield fetch(t)).text()}catch(e){return console.error(e),null}}),F=t=>u(null,null,function*(){try{return new f().parse(t)}catch(e){console.log(e)}});function q(t){if(!t)return"";let e=t.replace(/\n|\r|\t/g,"").replace(/\s{2,}/g," ").replace(/\s*(=)\s*"/g,'="').trim(),r=/id="([^"]{8,})"/g,n,o={},s=0,i="abcdefghijklmnopqrstuvwxyz";for(;(n=r.exec(e))!==null;){let l=n[1];o[l]||(o[l]=i[s]||`id${s}`,s++)}for(let l in o){let[c,a]=[l,o[l]],p=new RegExp(`id="${c}"`,"g");e=e.replace(p,`id="${a}"`);let h=new RegExp(`url\\(#${c}\\)`,"g");e=e.replace(h,`url(#${a})`)}return e=e.replace(/<(\w+)([^>]*)><\/\1>/g,"<$1$2/>"),e}var C=(t,e="/")=>u(null,null,function*(){let r=Z(t,e);return x[r]||(x[r]=new Promise((n,o)=>u(null,null,function*(){try{let s=localStorage.getItem(r);if(!s&&(s=yield W(r),s))try{localStorage.setItem(r,s)}catch(i){console.warn("LocalStorage is full, cannot cache SVG.")}if(s){setTimeout(()=>{let l=s.length-q(s).length;console.log(s.length,s.length-l,`SVG Minification saved ${l} bytes for ${t}, percentage: ${(l/s.length*100).toFixed(2)}%`)});let i=yield F(s);n(i)}n(void 0)}catch(s){o(s)}}))),x[r]});var b=require("react/jsx-runtime"),L=(0,g.memo)((0,g.forwardRef)((s,o)=>{var i=s,{name:t,baseUrl:e="/",as:r="span"}=i,n=R(i,["name","baseUrl","as"]);let[l,c]=(0,g.useState)(null);return(0,g.useEffect)(()=>{u(null,null,function*(){let h=yield C(t,e);h&&c(h)})},[]),l?A(l,o,n):(0,b.jsx)(r,{className:n.className,style:T({width:n.width,height:n.height,display:"inline-block"},n.style)})}));0&&(module.exports={LocalSvg});
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(g){s(g)}},i=a=>{try{o(r.throw(a))}catch(g){s(g)}},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 u=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]],g=new RegExp(`id="${o}"`,"g");e=e.replace(g,`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,g]=i.value.split("=");n[n.length-1].addProp(H(a),g.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,u.memo)((0,u.forwardRef)((c,s)=>{var i=c,{name:t,baseUrl:e="/",as:r="span"}=i,n=R(i,["name","baseUrl","as"]);let[o,a]=(0,u.useState)(null);return(0,u.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/tokenizer.ts","../src/namespace.ts","../src/parser.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: string;\n baseUrl?: string;\n as?: React.ElementType;\n};\n\nconst 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 const loadSvg = async () => {\n const node = await createSvg(name, baseUrl);\n if (node) {\n setNode(node);\n }\n };\n\n loadSvg();\n }, []);\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\nexport { LocalSvg };\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","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","import { Parser, SvgNode } from \"./parser\";\n\ntype ResultPromise = Promise<SvgNode | undefined>;\nconst promiseCache: Record<string, ResultPromise | null> = {};\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\n// const fullUrl = composeUrl(name, baseUrl);\n\nconst processSvgText = async (text: string) => {\n try {\n const parser = new Parser();\n return parser.parse(text);\n } catch (error) {\n console.log(error);\n }\n};\n\n/**\n * Minify SVG string dynamically\n * - Removes whitespace, line breaks\n * - Collapses multiple spaces\n * - Shortens linearGradient and other IDs\n * @param {string} svg\n * @returns {string} minified SVG\n */\n\nfunction 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 .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 const idMap: Record<string, string> = {};\n let counter = 0;\n const letters = \"abcdefghijklmnopqrstuvwxyz\";\n\n while ((match = idRegex.exec(min)) !== null) {\n const longId = match[1];\n if (!idMap[longId]) {\n idMap[longId] = letters[counter] || `id${counter}`;\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 // 4️⃣ Collapse self-closing tags (optional)\n min = min.replace(/<(\\w+)([^>]*)><\\/\\1>/g, \"<$1$2/>\");\n\n return min;\n}\n\nexport const createSvg = async (name: string, baseUrl = \"/\") => {\n const fullUrl = composeUrl(name, baseUrl);\n\n if (promiseCache[fullUrl]) {\n return promiseCache[fullUrl];\n }\n\n promiseCache[fullUrl] = new Promise(async (resolve, reject) => {\n try {\n let text = localStorage.getItem(fullUrl);\n\n if (!text) {\n text = await _fetch(fullUrl);\n\n if (text) {\n try {\n localStorage.setItem(fullUrl, text);\n } catch (error) {\n console.warn(\"LocalStorage is full, cannot cache SVG.\");\n }\n }\n }\n\n if (text) {\n setTimeout(() => {\n const diff = text.length - minifySVG(text).length;\n console.log(\n text.length,\n text.length - diff,\n `SVG Minification saved ${diff} bytes for ${name}, percentage: ${(\n (diff / text.length) *\n 100\n ).toFixed(2)}%`\n );\n });\n\n const node = await processSvgText(text);\n resolve(node);\n }\n resolve(undefined);\n } catch (error) {\n reject(error);\n }\n });\n\n return promiseCache[fullUrl]!;\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","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","promiseCache","composeUrl","name","baseUrl","_fetch","url","__async","error","processSvgText","text","Parser","minifySVG","svg","min","idRegex","match","idMap","counter","letters","longId","key","shortId","idPattern","urlPattern","createSvg","fullUrl","resolve","reject","diff","node","import_jsx_runtime","LocalSvg","_a","ref","_b","name","baseUrl","as","props","__objRest","node","setNode","__async","createSvg","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 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"]}
package/dist/index.mjs CHANGED
@@ -1,2 +1,2 @@
1
- var R=Object.defineProperty,v=Object.defineProperties;var C=Object.getOwnPropertyDescriptors;var h=Object.getOwnPropertySymbols;var w=Object.prototype.hasOwnProperty,G=Object.prototype.propertyIsEnumerable;var A=(t,e,n)=>e in t?R(t,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[e]=n,p=(t,e)=>{for(var n in e||(e={}))w.call(e,n)&&A(t,n,e[n]);if(h)for(var n of h(e))G.call(e,n)&&A(t,n,e[n]);return t},k=(t,e)=>v(t,C(e));var N=(t,e)=>{var n={};for(var r in t)w.call(t,r)&&e.indexOf(r)<0&&(n[r]=t[r]);if(t!=null&&h)for(var r of h(t))e.indexOf(r)<0&&G.call(t,r)&&(n[r]=t[r]);return n};var g=(t,e,n)=>new Promise((r,s)=>{var o=c=>{try{l(n.next(c))}catch(a){s(a)}},i=c=>{try{l(n.throw(c))}catch(a){s(a)}},l=c=>c.done?r(c.value):Promise.resolve(c.value).then(o,i);l((n=n.apply(t,e)).next())});import{forwardRef as P,memo as V,useEffect as M,useState as X}from"react";import{createElement as L}from"react";function f(t,e=null,n={},r="0"){return typeof t=="string"?t:L(t.type,k(p(p({},t.props),n),{ref:e,key:r}),...t.children.map((s,o)=>f(s,null,{},`${r}-${o}`)))}var x=class{constructor(e,n){this.name=e;this.value=n}},I=[[/^\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[n,r]of I){let s=this._match(n,e);if(s!=null)return r==null?this.getNextToken():new x(r,s)}throw new SyntaxError(`Unknown token type ${e.slice(0,10)}`)}_match(e,n){let r=e.exec(n);return r===null?null:(this._cursor+=r[0].length,r[0])}};var _={"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 d=class{constructor(e,n={}){this.type=e;this.props=n;this.children=[]}addChild(e){this.children.push(e)}addProp(e,n){this.props[e]=n}},O={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 $(t){return t.startsWith("aria-")?t:_[t]?_[t]:t.startsWith("rdf:")||t.startsWith("cc:")||t.startsWith("dc:")||t.startsWith("xmlns:")?t.toLowerCase():t.replace(/-([a-zA-Z])/g,(e,n)=>n.toUpperCase())}var S=class{constructor(){this.tokenizer=new E}parse(e){var o;this.tokenizer.init(e);let n=new d("ROOT"),r=[n],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&&!((o=O[i.name])!=null&&o[s.name]))throw new SyntaxError(`Unexpected token ${s.name} after ${i.name}`);switch(i.name){case"BEGIN_TAG":let l=new d(i.value.slice(1));r[r.length-1].addChild(l),r.push(l);break;case"ATTRIBUTE":let[c,a]=i.value.split("=");r[r.length-1].addProp($(c),a.slice(1,-1));break;case"END_TAG":break;case"CLOSE_TAG":if(r.length<=1)throw new SyntaxError("Unexpected closing tag");let u=r.pop();if(u.type!==i.value.slice(2,-1))throw new SyntaxError(`Mismatched tag: expected </${u.type}>, got ${i.value}`);break;case"END_CLOSE_TAG":if(r.length<=1)throw new SyntaxError("Unexpected closing tag");r.pop();break;case"TEXT":r[r.length-1].addChild(i.value);break;default:throw new SyntaxError(`Unknown token type: ${i.name}`)}}if(r.length>1)throw new SyntaxError(`Invalid SVG structure: Missing </${r[r.length-1].type}>`);return n.children[0]}};var m={},B=(t,e="/")=>e+t+".svg",U=t=>g(null,null,function*(){try{return yield(yield fetch(t)).text()}catch(e){return console.error(e),null}}),z=t=>g(null,null,function*(){try{return new S().parse(t)}catch(e){console.log(e)}});function D(t){if(!t)return"";let e=t.replace(/\n|\r|\t/g,"").replace(/\s{2,}/g," ").replace(/\s*(=)\s*"/g,'="').trim(),n=/id="([^"]{8,})"/g,r,s={},o=0,i="abcdefghijklmnopqrstuvwxyz";for(;(r=n.exec(e))!==null;){let l=r[1];s[l]||(s[l]=i[o]||`id${o}`,o++)}for(let l in s){let[c,a]=[l,s[l]],u=new RegExp(`id="${c}"`,"g");e=e.replace(u,`id="${a}"`);let T=new RegExp(`url\\(#${c}\\)`,"g");e=e.replace(T,`url(#${a})`)}return e=e.replace(/<(\w+)([^>]*)><\/\1>/g,"<$1$2/>"),e}var y=(t,e="/")=>g(null,null,function*(){let n=B(t,e);return m[n]||(m[n]=new Promise((r,s)=>g(null,null,function*(){try{let o=localStorage.getItem(n);if(!o&&(o=yield U(n),o))try{localStorage.setItem(n,o)}catch(i){console.warn("LocalStorage is full, cannot cache SVG.")}if(o){setTimeout(()=>{let l=o.length-D(o).length;console.log(o.length,o.length-l,`SVG Minification saved ${l} bytes for ${t}, percentage: ${(l/o.length*100).toFixed(2)}%`)});let i=yield z(o);r(i)}r(void 0)}catch(o){s(o)}}))),m[n]});import{jsx as W}from"react/jsx-runtime";var Z=V(P((o,s)=>{var i=o,{name:t,baseUrl:e="/",as:n="span"}=i,r=N(i,["name","baseUrl","as"]);let[l,c]=X(null);return M(()=>{g(null,null,function*(){let T=yield y(t,e);T&&c(T)})},[]),l?f(l,s,r):W(n,{className:r.className,style:p({width:r.width,height:r.height,display:"inline-block"},r.style)})}));export{Z as LocalSvg};
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(g){s(g)}},i=a=>{try{o(r.throw(a))}catch(g){s(g)}},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]],g=new RegExp(`id="${o}"`,"g");e=e.replace(g,`id="${a}"`);let u=new RegExp(`url\\(#${o}\\)`,"g");e=e.replace(u,`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,g]=i.value.split("=");n[n.length-1].addProp(V(a),g.slice(1,-1));break;case"END_TAG":break;case"CLOSE_TAG":if(n.length<=1)throw new SyntaxError("Unexpected closing tag");let u=n.pop();if(u.type!==i.value.slice(2,-1))throw new SyntaxError(`Mismatched tag: expected </${u.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 u=!0;return P(t,e).then(d=>{u&&d&&a(d)}).catch(d=>console.error(d)),()=>{u=!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
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/LocalSvg.tsx","../src/tree.ts","../src/tokenizer.ts","../src/namespace.ts","../src/parser.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: string;\n baseUrl?: string;\n as?: React.ElementType;\n};\n\nconst 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 const loadSvg = async () => {\n const node = await createSvg(name, baseUrl);\n if (node) {\n setNode(node);\n }\n };\n\n loadSvg();\n }, []);\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\nexport { LocalSvg };\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","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","import { Parser, SvgNode } from \"./parser\";\n\ntype ResultPromise = Promise<SvgNode | undefined>;\nconst promiseCache: Record<string, ResultPromise | null> = {};\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\n// const fullUrl = composeUrl(name, baseUrl);\n\nconst processSvgText = async (text: string) => {\n try {\n const parser = new Parser();\n return parser.parse(text);\n } catch (error) {\n console.log(error);\n }\n};\n\n/**\n * Minify SVG string dynamically\n * - Removes whitespace, line breaks\n * - Collapses multiple spaces\n * - Shortens linearGradient and other IDs\n * @param {string} svg\n * @returns {string} minified SVG\n */\n\nfunction 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 .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 const idMap: Record<string, string> = {};\n let counter = 0;\n const letters = \"abcdefghijklmnopqrstuvwxyz\";\n\n while ((match = idRegex.exec(min)) !== null) {\n const longId = match[1];\n if (!idMap[longId]) {\n idMap[longId] = letters[counter] || `id${counter}`;\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 // 4️⃣ Collapse self-closing tags (optional)\n min = min.replace(/<(\\w+)([^>]*)><\\/\\1>/g, \"<$1$2/>\");\n\n return min;\n}\n\nexport const createSvg = async (name: string, baseUrl = \"/\") => {\n const fullUrl = composeUrl(name, baseUrl);\n\n if (promiseCache[fullUrl]) {\n return promiseCache[fullUrl];\n }\n\n promiseCache[fullUrl] = new Promise(async (resolve, reject) => {\n try {\n let text = localStorage.getItem(fullUrl);\n\n if (!text) {\n text = await _fetch(fullUrl);\n\n if (text) {\n try {\n localStorage.setItem(fullUrl, text);\n } catch (error) {\n console.warn(\"LocalStorage is full, cannot cache SVG.\");\n }\n }\n }\n\n if (text) {\n setTimeout(() => {\n const diff = text.length - minifySVG(text).length;\n console.log(\n text.length,\n text.length - diff,\n `SVG Minification saved ${diff} bytes for ${name}, percentage: ${(\n (diff / text.length) *\n 100\n ).toFixed(2)}%`\n );\n });\n\n const node = await processSvgText(text);\n resolve(node);\n }\n resolve(undefined);\n } catch (error) {\n reject(error);\n }\n });\n\n return promiseCache[fullUrl]!;\n};\n"],"mappings":"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","names":["forwardRef","memo","useEffect","useState","createElement","buildSvgReactTree","node","ref","props","keyPath","createElement","__spreadProps","__spreadValues","child","i","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","promiseCache","composeUrl","name","baseUrl","_fetch","url","__async","error","processSvgText","text","Parser","minifySVG","svg","min","idRegex","match","idMap","counter","letters","longId","key","shortId","idPattern","urlPattern","createSvg","fullUrl","resolve","reject","diff","node","jsx","LocalSvg","memo","forwardRef","_a","ref","_b","name","baseUrl","as","props","__objRest","node","setNode","useState","useEffect","__async","createSvg","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 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"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "local-svg",
3
- "version": "0.0.3",
3
+ "version": "0.0.5",
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",
@@ -21,9 +21,11 @@
21
21
  "dist"
22
22
  ],
23
23
  "scripts": {
24
- "build": "tsup"
24
+ "build": "tsup",
25
+ "publish": "npm publish --access public "
25
26
  },
26
27
  "devDependencies": {
28
+ "@types/node": "^25.0.8",
27
29
  "@types/react": "^19.2.7",
28
30
  "@types/react-dom": "^19.2.3",
29
31
  "tsup": "^8.5.1",