pure-glyf 0.1.0 → 1.0.0
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 +2 -0
- package/dist/index.cjs +2 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.js +22 -13
- package/dist/inject.d.ts +8 -1
- package/dist/plugin.cjs +5 -5
- package/dist/plugin.js +51 -51
- package/package.json +6 -4
package/README.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# pure-glyf
|
|
2
2
|
|
|
3
|
+
[](https://badge.fury.io/js/pure-glyf)
|
|
4
|
+
|
|
3
5
|
**Vite plugin and runtime to compile SVG icons into tree-shakeable CSS masks for modern web applications.**
|
|
4
6
|
|
|
5
7
|
`pure-glyf` takes a different approach to icon management. Instead of inlining SVGs (bloating your DOM) or using sprites (complexity), it converts your SVGs into CSS classes that inject their styles on demand. The result? Zero runtime overhead for unused icons, perfect tree-shaking, and a developer experience that feels like magic.
|
package/dist/index.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const c=new Map,a=new Set;let t=null;const r=`
|
|
2
2
|
.pure-glyf-icon {
|
|
3
3
|
display: inline-block;
|
|
4
4
|
width: 1em;
|
|
@@ -10,4 +10,4 @@
|
|
|
10
10
|
-webkit-mask-repeat: no-repeat;
|
|
11
11
|
-webkit-mask-position: center;
|
|
12
12
|
-webkit-mask-size: contain;
|
|
13
|
-
}`;
|
|
13
|
+
}`;exports.sheet=r;function s(){typeof document>"u"||t||(t=document.createElement("style"),t.textContent=exports.sheet,document.head.appendChild(t))}function l(e){a.add(e)}function u(e){const n=e.match(/^\.([\w-]+)/),o=n?n[1]:e;c.has(o)||(c.set(o,e),exports.sheet+=e,t&&(t.textContent=exports.sheet),a.forEach(i=>i(e)))}function m(e){const n=new Set;for(const[o,i]of c.entries())e.includes(o)&&n.add(i);return r+Array.from(n).join("")}exports.extractCriticalCSS=m;exports.injectCSS=u;exports.mount=s;exports.onInject=l;
|
package/dist/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { injectCSS, sheet, mount, onInject } from './inject';
|
|
1
|
+
export { injectCSS, sheet, mount, onInject, extractCriticalCSS } from './inject';
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
const
|
|
2
|
-
let
|
|
1
|
+
const a = /* @__PURE__ */ new Map(), r = /* @__PURE__ */ new Set();
|
|
2
|
+
let t = null;
|
|
3
|
+
const s = `
|
|
3
4
|
.pure-glyf-icon {
|
|
4
5
|
display: inline-block;
|
|
5
6
|
width: 1em;
|
|
@@ -11,20 +12,28 @@ let n = `
|
|
|
11
12
|
-webkit-mask-repeat: no-repeat;
|
|
12
13
|
-webkit-mask-position: center;
|
|
13
14
|
-webkit-mask-size: contain;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
}`;
|
|
16
|
+
let c = s;
|
|
17
|
+
function l() {
|
|
18
|
+
typeof document > "u" || t || (t = document.createElement("style"), t.textContent = c, document.head.appendChild(t));
|
|
17
19
|
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
20
|
+
function u(e) {
|
|
21
|
+
r.add(e);
|
|
22
|
+
}
|
|
23
|
+
function m(e) {
|
|
24
|
+
const n = e.match(/^\.([\w-]+)/), o = n ? n[1] : e;
|
|
25
|
+
a.has(o) || (a.set(o, e), c += e, t && (t.textContent = c), r.forEach((i) => i(e)));
|
|
21
26
|
}
|
|
22
27
|
function d(e) {
|
|
23
|
-
|
|
28
|
+
const n = /* @__PURE__ */ new Set();
|
|
29
|
+
for (const [o, i] of a.entries())
|
|
30
|
+
e.includes(o) && n.add(i);
|
|
31
|
+
return s + Array.from(n).join("");
|
|
24
32
|
}
|
|
25
33
|
export {
|
|
26
|
-
d as
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
34
|
+
d as extractCriticalCSS,
|
|
35
|
+
m as injectCSS,
|
|
36
|
+
l as mount,
|
|
37
|
+
u as onInject,
|
|
38
|
+
c as sheet
|
|
30
39
|
};
|
package/dist/inject.d.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
/**
|
|
9
9
|
* Accumulated CSS string for Server-Side Rendering (SSR).
|
|
10
|
-
*
|
|
10
|
+
* Contains all injected styles.
|
|
11
11
|
*/
|
|
12
12
|
export declare let sheet: string;
|
|
13
13
|
/**
|
|
@@ -18,3 +18,10 @@ export declare let sheet: string;
|
|
|
18
18
|
export declare function mount(): void;
|
|
19
19
|
export declare function onInject(callback: (css: string) => void): void;
|
|
20
20
|
export declare function injectCSS(css: string): void;
|
|
21
|
+
/**
|
|
22
|
+
* Scans the provided HTML for usage of injected icons and returns
|
|
23
|
+
* a critical CSS string containing only the necessary styles.
|
|
24
|
+
*
|
|
25
|
+
* @param html The full HTML string to scan
|
|
26
|
+
*/
|
|
27
|
+
export declare function extractCriticalCSS(html: string): string;
|
package/dist/plugin.cjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const d=require("node:fs"),p=require("node:path");function C(
|
|
2
|
-
injectCSS(\`${
|
|
3
|
-
return "pure-glyf-icon ${
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const d=require("node:fs"),p=require("node:path");function C(o){return o.replace(/[-_./\\]+(.)/g,(c,s)=>s.toUpperCase()).replace(/^./,c=>c.toUpperCase())}function I(o){return`data:image/svg+xml,${o.replace(/"/g,"'").replace(/%/g,"%25").replace(/#/g,"%23").replace(/{/g,"%7B").replace(/}/g,"%7D").replace(/</g,"%3C").replace(/>/g,"%3E").replace(/\s+/g," ")}`}function v(o,c){let s=[];return d.existsSync(o)&&d.readdirSync(o).forEach(i=>{const a=p.join(o,i),l=d.statSync(a);l&&l.isDirectory()?s=s.concat(v(a,c)):i.endsWith(".svg")&&s.push(p.relative(c,a))}),s}function P(o,c=!1){const s=[];for(const[t,e]of Object.entries(o)){const n=p.resolve(process.cwd(),e);if(!d.existsSync(n)){console.warn(`[pure-glyf] Warning: Icon directory not found: ${n}`);continue}v(n,n).forEach(g=>{const y=p.join(n,g),S=d.readFileSync(y,"utf-8"),m=g.replace(/\.svg$/,""),$=C(m),j=t+$,x=`glyf-${t.toLowerCase()}-${m.replace(/[^a-zA-Z0-9-]/g,"-")}`,h=I(S),w=`.${x}{mask-image:url("${h}");-webkit-mask-image:url("${h}");}`;s.push({name:j,css:w})})}const u=["import { injectCSS, mount, sheet, onInject } from 'pure-glyf';","export { mount, sheet, onInject };",""];let i="",a;c?(u.unshift("import 'pure-glyf/icons.css';"),i=s.map(t=>t.css).join(""),a=s.map(t=>{const e=t.css.match(/^\s*\.(\S+)\{/),n=e?e[1]:"error-class";return`export const ${t.name} = "pure-glyf-icon ${n}";`})):a=s.map(t=>{const e=t.css.match(/^\s*\.(\S+)\{/),n=e?e[1]:"error-class";return`export const ${t.name} = /*#__PURE__*/ (() => {
|
|
2
|
+
injectCSS(\`${t.css}\`);
|
|
3
|
+
return "pure-glyf-icon ${n}";
|
|
4
4
|
})();`});const l=u.concat(a).join(`
|
|
5
|
-
`),
|
|
6
|
-
`);return{code:l,css:i,dts:f}}function b(
|
|
5
|
+
`),r=["declare module 'pure-glyf/icons' {"," export function mount(): void;"," export const sheet: string;"," export function onInject(callback: (css: string) => void): void;"];s.forEach(t=>{r.push(` export const ${t.name}: string;`)}),r.push("}");const f=r.join(`
|
|
6
|
+
`);return{code:l,css:i,dts:f}}function b(o){const c="pure-glyf/icons",s="\0"+c,u="pure-glyf/icons.css",i="\0"+u,a=o.dts||"pure-glyf.d.ts";let l=null,r=null,f=!1;function t(){try{if(l=P(o.icons,f),d.writeFileSync(p.resolve(process.cwd(),a),l.dts),r){const e=r.moduleGraph.getModuleById(s);e&&(r.moduleGraph.invalidateModule(e),r.ws.send({type:"full-reload",path:"*"}))}}catch(e){console.error("[pure-glyf] Generation failed:",e)}}return{name:"vite-plugin-pure-glyf",enforce:"pre",configResolved(e){f=e.command==="serve"},configureServer(e){r=e,Object.values(o.icons).forEach(n=>{r?.watcher.add(p.resolve(n))}),r?.watcher.on("change",n=>{n.endsWith(".svg")&&t()}),r?.watcher.on("add",n=>{n.endsWith(".svg")&&t()}),r?.watcher.on("unlink",n=>{n.endsWith(".svg")&&t()})},buildStart(){t()},resolveId(e){if(e===c)return s;if(e===u)return i},load(e){if(e===s)return l.code;if(e===i)return l.css}}}exports.pureGlyfPlugin=b;
|
package/dist/plugin.js
CHANGED
|
@@ -1,29 +1,29 @@
|
|
|
1
1
|
import p from "node:fs";
|
|
2
2
|
import d from "node:path";
|
|
3
|
-
function C(
|
|
4
|
-
return
|
|
3
|
+
function C(o) {
|
|
4
|
+
return o.replace(/[-_./\\]+(.)/g, (c, s) => s.toUpperCase()).replace(/^./, (c) => c.toUpperCase());
|
|
5
5
|
}
|
|
6
|
-
function I(
|
|
7
|
-
return `data:image/svg+xml,${
|
|
6
|
+
function I(o) {
|
|
7
|
+
return `data:image/svg+xml,${o.replace(/"/g, "'").replace(/%/g, "%25").replace(/#/g, "%23").replace(/{/g, "%7B").replace(/}/g, "%7D").replace(/</g, "%3C").replace(/>/g, "%3E").replace(/\s+/g, " ")}`;
|
|
8
8
|
}
|
|
9
|
-
function
|
|
10
|
-
let
|
|
11
|
-
return p.existsSync(
|
|
12
|
-
const a = d.join(
|
|
13
|
-
l && l.isDirectory() ?
|
|
14
|
-
}),
|
|
9
|
+
function v(o, c) {
|
|
10
|
+
let s = [];
|
|
11
|
+
return p.existsSync(o) && p.readdirSync(o).forEach((i) => {
|
|
12
|
+
const a = d.join(o, i), l = p.statSync(a);
|
|
13
|
+
l && l.isDirectory() ? s = s.concat(v(a, c)) : i.endsWith(".svg") && s.push(d.relative(c, a));
|
|
14
|
+
}), s;
|
|
15
15
|
}
|
|
16
|
-
function P(
|
|
17
|
-
const
|
|
18
|
-
for (const [
|
|
19
|
-
const
|
|
20
|
-
if (!p.existsSync(
|
|
21
|
-
console.warn(`[pure-glyf] Warning: Icon directory not found: ${
|
|
16
|
+
function P(o, c = !1) {
|
|
17
|
+
const s = [];
|
|
18
|
+
for (const [t, e] of Object.entries(o)) {
|
|
19
|
+
const n = d.resolve(process.cwd(), e);
|
|
20
|
+
if (!p.existsSync(n)) {
|
|
21
|
+
console.warn(`[pure-glyf] Warning: Icon directory not found: ${n}`);
|
|
22
22
|
continue;
|
|
23
23
|
}
|
|
24
|
-
|
|
25
|
-
const
|
|
26
|
-
|
|
24
|
+
v(n, n).forEach((g) => {
|
|
25
|
+
const y = d.join(n, g), S = p.readFileSync(y, "utf-8"), m = g.replace(/\.svg$/, ""), $ = C(m), x = t + $, j = `glyf-${t.toLowerCase()}-${m.replace(/[^a-zA-Z0-9-]/g, "-")}`, h = I(S), w = `.${j}{mask-image:url("${h}");-webkit-mask-image:url("${h}");}`;
|
|
26
|
+
s.push({ name: x, css: w });
|
|
27
27
|
});
|
|
28
28
|
}
|
|
29
29
|
const u = [
|
|
@@ -32,38 +32,38 @@ function P(c, r = !1) {
|
|
|
32
32
|
""
|
|
33
33
|
];
|
|
34
34
|
let i = "", a;
|
|
35
|
-
|
|
36
|
-
const e =
|
|
37
|
-
return `export const ${
|
|
38
|
-
})) : a =
|
|
39
|
-
const e =
|
|
40
|
-
return `export const ${
|
|
41
|
-
injectCSS(\`${
|
|
42
|
-
return "pure-glyf-icon ${
|
|
35
|
+
c ? (u.unshift("import 'pure-glyf/icons.css';"), i = s.map((t) => t.css).join(""), a = s.map((t) => {
|
|
36
|
+
const e = t.css.match(/^\s*\.(\S+)\{/), n = e ? e[1] : "error-class";
|
|
37
|
+
return `export const ${t.name} = "pure-glyf-icon ${n}";`;
|
|
38
|
+
})) : a = s.map((t) => {
|
|
39
|
+
const e = t.css.match(/^\s*\.(\S+)\{/), n = e ? e[1] : "error-class";
|
|
40
|
+
return `export const ${t.name} = /*#__PURE__*/ (() => {
|
|
41
|
+
injectCSS(\`${t.css}\`);
|
|
42
|
+
return "pure-glyf-icon ${n}";
|
|
43
43
|
})();`;
|
|
44
44
|
});
|
|
45
45
|
const l = u.concat(a).join(`
|
|
46
|
-
`),
|
|
46
|
+
`), r = [
|
|
47
47
|
"declare module 'pure-glyf/icons' {",
|
|
48
48
|
" export function mount(): void;",
|
|
49
49
|
" export const sheet: string;",
|
|
50
50
|
" export function onInject(callback: (css: string) => void): void;"
|
|
51
51
|
];
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
}),
|
|
55
|
-
const f =
|
|
52
|
+
s.forEach((t) => {
|
|
53
|
+
r.push(` export const ${t.name}: string;`);
|
|
54
|
+
}), r.push("}");
|
|
55
|
+
const f = r.join(`
|
|
56
56
|
`);
|
|
57
57
|
return { code: l, css: i, dts: f };
|
|
58
58
|
}
|
|
59
|
-
function _(
|
|
60
|
-
const
|
|
61
|
-
let l = null,
|
|
62
|
-
function
|
|
59
|
+
function _(o) {
|
|
60
|
+
const c = "pure-glyf/icons", s = "\0" + c, u = "pure-glyf/icons.css", i = "\0" + u, a = o.dts || "pure-glyf.d.ts";
|
|
61
|
+
let l = null, r = null, f = !1;
|
|
62
|
+
function t() {
|
|
63
63
|
try {
|
|
64
|
-
if (l = P(
|
|
65
|
-
const e =
|
|
66
|
-
e && (
|
|
64
|
+
if (l = P(o.icons, f), p.writeFileSync(d.resolve(process.cwd(), a), l.dts), r) {
|
|
65
|
+
const e = r.moduleGraph.getModuleById(s);
|
|
66
|
+
e && (r.moduleGraph.invalidateModule(e), r.ws.send({
|
|
67
67
|
type: "full-reload",
|
|
68
68
|
path: "*"
|
|
69
69
|
}));
|
|
@@ -79,27 +79,27 @@ function _(c) {
|
|
|
79
79
|
f = e.command === "serve";
|
|
80
80
|
},
|
|
81
81
|
configureServer(e) {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
}),
|
|
85
|
-
|
|
86
|
-
}),
|
|
87
|
-
|
|
88
|
-
}),
|
|
89
|
-
|
|
82
|
+
r = e, Object.values(o.icons).forEach((n) => {
|
|
83
|
+
r?.watcher.add(d.resolve(n));
|
|
84
|
+
}), r?.watcher.on("change", (n) => {
|
|
85
|
+
n.endsWith(".svg") && t();
|
|
86
|
+
}), r?.watcher.on("add", (n) => {
|
|
87
|
+
n.endsWith(".svg") && t();
|
|
88
|
+
}), r?.watcher.on("unlink", (n) => {
|
|
89
|
+
n.endsWith(".svg") && t();
|
|
90
90
|
});
|
|
91
91
|
},
|
|
92
92
|
buildStart() {
|
|
93
|
-
|
|
93
|
+
t();
|
|
94
94
|
},
|
|
95
95
|
resolveId(e) {
|
|
96
|
-
if (e ===
|
|
97
|
-
return
|
|
96
|
+
if (e === c)
|
|
97
|
+
return s;
|
|
98
98
|
if (e === u)
|
|
99
99
|
return i;
|
|
100
100
|
},
|
|
101
101
|
load(e) {
|
|
102
|
-
if (e ===
|
|
102
|
+
if (e === s)
|
|
103
103
|
return l.code;
|
|
104
104
|
if (e === i)
|
|
105
105
|
return l.css;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pure-glyf",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "Vite plugin and runtime for compiling SVGs into tree-shakeable CSS masks",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"keywords": [
|
|
@@ -38,7 +38,9 @@
|
|
|
38
38
|
"types": "./dist/inject.d.ts",
|
|
39
39
|
"import": "./dist/inject.js",
|
|
40
40
|
"require": "./dist/inject.cjs"
|
|
41
|
-
}
|
|
41
|
+
},
|
|
42
|
+
"./src": "./src/index.ts",
|
|
43
|
+
"./src/*": "./src/*"
|
|
42
44
|
},
|
|
43
45
|
"files": [
|
|
44
46
|
"dist"
|
|
@@ -50,10 +52,10 @@
|
|
|
50
52
|
"preview": "vite preview"
|
|
51
53
|
},
|
|
52
54
|
"devDependencies": {
|
|
53
|
-
"@types/node": "
|
|
55
|
+
"@types/node": "25.0.10",
|
|
54
56
|
"tsx": "^4.21.0",
|
|
55
57
|
"typescript": "^5.7.0",
|
|
56
|
-
"vite": "
|
|
58
|
+
"vite": "7.3.1",
|
|
57
59
|
"vite-plugin-dts": "^4.0.0"
|
|
58
60
|
},
|
|
59
61
|
"license": "MIT",
|