local-svg 0.0.2 → 0.0.4
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/LICENSE +21 -0
- package/README.md +170 -0
- package/dist/index.d.mts +15 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +2 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +29 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Godswill Anwuli
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
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
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { SVGAttributes } from 'react';
|
|
3
|
+
|
|
4
|
+
type LocalSvgProps = SVGAttributes<SVGSVGElement> & {
|
|
5
|
+
name: string;
|
|
6
|
+
baseUrl?: string;
|
|
7
|
+
as?: React.ElementType;
|
|
8
|
+
};
|
|
9
|
+
declare const LocalSvg: react.NamedExoticComponent<SVGAttributes<SVGSVGElement> & {
|
|
10
|
+
name: string;
|
|
11
|
+
baseUrl?: string;
|
|
12
|
+
as?: React.ElementType;
|
|
13
|
+
} & react.RefAttributes<SVGSVGElement>>;
|
|
14
|
+
|
|
15
|
+
export { LocalSvg, type LocalSvgProps };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { SVGAttributes } from 'react';
|
|
3
|
+
|
|
4
|
+
type LocalSvgProps = SVGAttributes<SVGSVGElement> & {
|
|
5
|
+
name: string;
|
|
6
|
+
baseUrl?: string;
|
|
7
|
+
as?: React.ElementType;
|
|
8
|
+
};
|
|
9
|
+
declare const LocalSvg: react.NamedExoticComponent<SVGAttributes<SVGSVGElement> & {
|
|
10
|
+
name: string;
|
|
11
|
+
baseUrl?: string;
|
|
12
|
+
as?: React.ElementType;
|
|
13
|
+
} & react.RefAttributes<SVGSVGElement>>;
|
|
14
|
+
|
|
15
|
+
export { LocalSvg, type LocalSvgProps };
|
package/dist/index.js
ADDED
|
@@ -0,0 +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});
|
|
2
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +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"]}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +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};
|
|
2
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +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"]}
|
package/package.json
CHANGED
|
@@ -1,10 +1,36 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "local-svg",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.4",
|
|
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",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "https://github.com/g-anwuli/local-svg.git"
|
|
11
|
+
},
|
|
7
12
|
"author": "Godswill Anwuli",
|
|
8
13
|
"license": "MIT",
|
|
9
|
-
"private": false
|
|
14
|
+
"private": false,
|
|
15
|
+
"keywords": [
|
|
16
|
+
"svg",
|
|
17
|
+
"icon",
|
|
18
|
+
"local-svg"
|
|
19
|
+
],
|
|
20
|
+
"files": [
|
|
21
|
+
"dist"
|
|
22
|
+
],
|
|
23
|
+
"scripts": {
|
|
24
|
+
"build": "tsup"
|
|
25
|
+
},
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"@types/react": "^19.2.7",
|
|
28
|
+
"@types/react-dom": "^19.2.3",
|
|
29
|
+
"tsup": "^8.5.1",
|
|
30
|
+
"typescript": "^5.9.3"
|
|
31
|
+
},
|
|
32
|
+
"peerDependencies": {
|
|
33
|
+
"react": "^18.x || ^19.x",
|
|
34
|
+
"react-dom": "^18.x || ^19.x"
|
|
35
|
+
}
|
|
10
36
|
}
|