@aippy/vite-plugins 0.2.0 → 0.2.2

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.
@@ -0,0 +1,26 @@
1
+ /**
2
+ * HTML processing utilities for aippy preload plugin
3
+ */
4
+ /**
5
+ * Generate meta tags for asset preloading
6
+ * @param assets - Array of asset URLs
7
+ * @returns HTML meta tags string
8
+ */
9
+ export declare function generateMetaTags(assets: string[]): string;
10
+ /**
11
+ * Inject meta tags into HTML content
12
+ * @param htmlContent - Original HTML content
13
+ * @param metaTags - Meta tags to inject
14
+ * @returns Modified HTML content
15
+ */
16
+ export declare function injectMetaTags(htmlContent: string, metaTags: string): string;
17
+ /**
18
+ * Log scan results to console
19
+ * @param assets - Array of found assets
20
+ */
21
+ export declare function logScanResults(assets: string[]): void;
22
+ /**
23
+ * Log injection result to console
24
+ * @param count - Number of meta tags injected
25
+ */
26
+ export declare function logInjectionResult(count: number): void;
@@ -1,11 +1,12 @@
1
1
  import { Plugin } from 'vite';
2
- interface AssetPreloadOptions {
3
- extensions?: string[];
4
- includeFiles?: string[];
5
- exclude?: string[];
6
- outDir?: string;
7
- includeSubdirs?: boolean;
8
- deepScan?: boolean;
9
- }
2
+ import { AssetPreloadOptions } from './types';
3
+ /**
4
+ * Aippy preload plugin - scans source files for assets and injects preload meta tags
5
+ *
6
+ * This plugin scans source files (not build output) to avoid including third-party libraries
7
+ *
8
+ * @param options - Plugin options
9
+ * @returns Vite plugin
10
+ */
10
11
  export declare function aippyPreloadPlugin(options?: AssetPreloadOptions): Plugin;
11
12
  export default aippyPreloadPlugin;
@@ -1,146 +1,121 @@
1
- var f = Object.defineProperty;
2
- var g = (e, s, t) => s in e ? f(e, s, { enumerable: !0, configurable: !0, writable: !0, value: t }) : e[s] = t;
3
- var p = (e, s, t) => g(e, typeof s != "symbol" ? s + "" : s, t);
4
- import r from "fs/promises";
5
- import a from "path";
6
- import { glob as l } from "glob";
7
- import { extractAssetsFromContent as c } from "../utils/index.js";
8
- class F {
9
- constructor(s = {}) {
10
- p(this, "options");
11
- this.options = {
12
- extensions: [".js", ".css", ".png", ".jpg", ".jpeg", ".gif", ".svg", ".woff", ".woff2", ".ttf", ".eot"],
13
- includeFiles: [],
14
- exclude: ["*.map"],
15
- outDir: "dist",
16
- includeSubdirs: !0,
17
- deepScan: !0,
18
- ...s
19
- };
20
- }
21
- /**
22
- * Scan external file resources
23
- */
24
- async scanExternalFiles() {
25
- const s = [], t = this.options.extensions.map(
26
- (i) => this.options.includeSubdirs ? a.join(this.options.outDir, "**", `*${i}`) : a.join(this.options.outDir, `*${i}`)
27
- ), n = await l(t, {
28
- ignore: this.options.exclude,
29
- absolute: !0
30
- });
31
- if (s.push(...n), this.options.includeFiles.length > 0) {
32
- const i = this.options.includeFiles.map((h) => this.options.includeSubdirs ? a.join(this.options.outDir, "**", h) : a.join(this.options.outDir, h)), u = await l(i, {
33
- ignore: this.options.exclude,
34
- absolute: !0
35
- });
36
- s.push(...u);
1
+ import { promises as i } from "fs";
2
+ import u from "path";
3
+ import { extractAssetsFromContent as r } from "../utils/index.js";
4
+ import { g as l } from "../file-scanner-DHkDSQm8.js";
5
+ async function d(s) {
6
+ const t = [], n = [u.join(process.cwd(), "index.html")];
7
+ for (const c of n)
8
+ try {
9
+ const e = await i.readFile(c, "utf-8"), o = r(e, "html", s);
10
+ t.push(...o);
11
+ } catch {
12
+ console.warn("⚠️ No index.html found in project root");
37
13
  }
38
- return [...new Set(s)].map((i) => `/${a.relative(this.options.outDir, i).replace(/\\/g, "/")}`);
39
- }
40
- /**
41
- * Scan HTML files
42
- */
43
- async scanHtmlFiles() {
44
- const s = [], t = await l("**/*.html", { cwd: this.options.outDir, absolute: !0 });
45
- for (const n of t)
46
- try {
47
- const o = await r.readFile(n, "utf-8"), i = c(o, "html", this.options.extensions);
48
- s.push(...i);
49
- } catch (o) {
50
- console.warn(`⚠️ Failed to read HTML file: ${n}`, o);
51
- }
52
- return s;
53
- }
54
- /**
55
- * Scan JS files
56
- */
57
- async scanJsFiles() {
58
- const s = [], t = await l("**/*.js", { cwd: this.options.outDir, absolute: !0 });
59
- for (const n of t)
60
- try {
61
- const o = await r.readFile(n, "utf-8"), i = c(o, "js", this.options.extensions);
62
- s.push(...i);
63
- } catch (o) {
64
- console.warn(`⚠️ Failed to read JS file: ${n}`, o);
65
- }
66
- return s;
67
- }
68
- /**
69
- * Scan CSS files
70
- */
71
- async scanCssFiles() {
72
- const s = [], t = await l("**/*.css", { cwd: this.options.outDir, absolute: !0 });
73
- for (const n of t)
74
- try {
75
- const o = await r.readFile(n, "utf-8"), i = c(o, "css", this.options.extensions);
76
- s.push(...i);
77
- } catch (o) {
78
- console.warn(`⚠️ Failed to read CSS file: ${n}`, o);
79
- }
80
- return s;
81
- }
82
- /**
83
- * Execute complete asset scanning
84
- */
85
- async scanAllAssets() {
86
- console.log("🔍 Scanning for static assets...");
87
- const s = [], t = await this.scanExternalFiles();
88
- if (s.push(...t), this.options.deepScan) {
89
- console.log("🔍 Deep scanning file contents...");
90
- const [n, o, i] = await Promise.all([
91
- this.scanHtmlFiles(),
92
- this.scanJsFiles(),
93
- this.scanCssFiles()
94
- ]);
95
- s.push(...n, ...o, ...i);
14
+ return t;
15
+ }
16
+ async function g(s, t) {
17
+ const n = [], c = await l(s, [".ts", ".tsx", ".js", ".jsx"]);
18
+ for (const e of c)
19
+ try {
20
+ const o = await i.readFile(e, "utf-8"), a = r(o, "js", t);
21
+ n.push(...a);
22
+ } catch (o) {
23
+ console.warn(`⚠️ Failed to read JS file: ${e}`, o);
24
+ }
25
+ return n;
26
+ }
27
+ async function h(s, t) {
28
+ const n = [], c = await l(s, [".css", ".scss", ".sass", ".less"]);
29
+ for (const e of c)
30
+ try {
31
+ const o = await i.readFile(e, "utf-8"), a = r(o, "css", t);
32
+ n.push(...a);
33
+ } catch (o) {
34
+ console.warn(`⚠️ Failed to read CSS file: ${e}`, o);
96
35
  }
97
- return [...new Set(s)];
36
+ return n;
37
+ }
38
+ async function m(s, t) {
39
+ const n = [], c = await l(s, [".json"]);
40
+ for (const e of c)
41
+ try {
42
+ const o = await i.readFile(e, "utf-8"), a = r(o, "js", t);
43
+ n.push(...a);
44
+ } catch (o) {
45
+ console.warn(`⚠️ Failed to read JSON file: ${e}`, o);
46
+ }
47
+ return n;
48
+ }
49
+ async function j(s, t, n) {
50
+ console.log("🔍 Scanning source files for static assets...");
51
+ const c = [];
52
+ if (n) {
53
+ console.log("🔍 Deep scanning source file contents...");
54
+ const [e, o, a, p] = await Promise.all([
55
+ d(t),
56
+ g(s, t),
57
+ h(s, t),
58
+ m(s, t)
59
+ ]);
60
+ c.push(...e, ...o, ...a, ...p);
98
61
  }
62
+ return [...new Set(c)];
99
63
  }
100
- function m(e) {
101
- return e.map((s) => ` <meta content="${s}" name="aippy:preload">`).join(`
64
+ const f = "<head>", F = f.length;
65
+ function w(s) {
66
+ return s.map((t) => ` <meta content="${t}" name="aippy:preload">`).join(`
102
67
  `);
103
68
  }
104
- const d = "<head>", w = d.length;
105
- function j(e, s) {
106
- const t = e.indexOf(d);
107
- if (t === -1)
69
+ function y(s, t) {
70
+ const n = s.indexOf(f);
71
+ if (n === -1)
108
72
  throw new Error("Could not find <head> tag in HTML");
109
- const n = t + w;
110
- return e.slice(0, n) + `
111
- ` + s + `
112
- ` + e.slice(n);
73
+ const c = n + F;
74
+ return s.slice(0, c) + `
75
+ ` + t + `
76
+ ` + s.slice(c);
113
77
  }
114
- function x(e) {
115
- if (console.log(`📁 Found ${e.length} static assets`), e.length === 0) {
116
- console.log("⚠️ No static assets found. This might be because all assets are inlined.");
78
+ function A(s) {
79
+ if (console.log(`📁 Found ${s.length} static assets in source files`), s.length === 0) {
80
+ console.log("⚠️ No static assets found in source files.");
117
81
  return;
118
82
  }
119
- console.log("📋 Assets found:"), e.forEach((s) => console.log(` - ${s}`));
83
+ console.log("📋 Assets found:"), s.forEach((t) => console.log(` - ${t}`));
120
84
  }
121
- function A(e) {
122
- console.log(`✅ Injected ${e} preload meta tags into index.html`);
85
+ function x(s) {
86
+ console.log(`✅ Injected ${s} preload meta tags into index.html`);
123
87
  }
124
- function P(e = {}) {
88
+ function C(s = {}) {
89
+ const t = {
90
+ extensions: [".png", ".jpg", ".jpeg", ".gif", ".svg", ".mp4", ".mp3", ".wav", ".ogg", ".webm"],
91
+ srcDir: "src",
92
+ outDir: "dist",
93
+ deepScan: !0,
94
+ ...s
95
+ };
125
96
  return {
126
97
  name: "vite-plugin-aippy-preload",
127
98
  apply: "build",
128
99
  async closeBundle() {
129
100
  try {
130
- const t = await new F(e).scanAllAssets();
131
- if (x(t), t.length === 0)
101
+ const n = await j(
102
+ t.srcDir,
103
+ t.extensions,
104
+ t.deepScan
105
+ );
106
+ if (A(n), n.length === 0)
132
107
  return;
133
- const n = a.join(e.outDir || "dist", "index.html");
134
- let o = await r.readFile(n, "utf-8");
135
- const i = m(t);
136
- o = j(o, i), await r.writeFile(n, o, "utf-8"), A(t.length);
137
- } catch (s) {
138
- console.error("❌ Error in asset preload plugin:", s);
108
+ const c = u.join(t.outDir, "index.html");
109
+ let e = await i.readFile(c, "utf-8");
110
+ const o = w(n);
111
+ e = y(e, o), await i.writeFile(c, e, "utf-8"), x(n.length);
112
+ } catch (n) {
113
+ console.error("❌ Error in aippy preload plugin:", n);
139
114
  }
140
115
  }
141
116
  };
142
117
  }
143
118
  export {
144
- P as aippyPreloadPlugin,
145
- P as default
119
+ C as aippyPreloadPlugin,
120
+ C as default
146
121
  };
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Source file scanning utilities for aippy preload plugin
3
+ */
4
+ /**
5
+ * Scan HTML files in project root directory
6
+ * @param extensions - Asset extensions to look for
7
+ * @returns Array of asset URLs
8
+ */
9
+ export declare function scanHtmlFiles(extensions: string[]): Promise<string[]>;
10
+ /**
11
+ * Scan TypeScript/JavaScript files in source directory
12
+ * @param srcDir - Source directory
13
+ * @param extensions - Asset extensions to look for
14
+ * @returns Array of asset URLs
15
+ */
16
+ export declare function scanJsFiles(srcDir: string, extensions: string[]): Promise<string[]>;
17
+ /**
18
+ * Scan CSS files in source directory
19
+ * @param srcDir - Source directory
20
+ * @param extensions - Asset extensions to look for
21
+ * @returns Array of asset URLs
22
+ */
23
+ export declare function scanCssFiles(srcDir: string, extensions: string[]): Promise<string[]>;
24
+ /**
25
+ * Scan JSON files in source directory for asset URLs
26
+ * @param srcDir - Source directory
27
+ * @param extensions - Asset extensions to look for
28
+ * @returns Array of asset URLs
29
+ */
30
+ export declare function scanJsonFiles(srcDir: string, extensions: string[]): Promise<string[]>;
31
+ /**
32
+ * Scan all source files for asset references
33
+ * @param srcDir - Source directory
34
+ * @param extensions - Asset extensions to look for
35
+ * @param deepScan - Whether to deep scan file contents
36
+ * @returns Array of unique asset URLs
37
+ */
38
+ export declare function scanAllSourceAssets(srcDir: string, extensions: string[], deepScan: boolean): Promise<string[]>;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Type definitions for aippy preload plugin
3
+ */
4
+ export interface AssetPreloadOptions {
5
+ extensions?: string[];
6
+ srcDir?: string;
7
+ outDir?: string;
8
+ deepScan?: boolean;
9
+ }
@@ -0,0 +1,22 @@
1
+ import { AssetInfo } from './types';
2
+ /**
3
+ * Generate assets.json file content from asset info
4
+ * @param assets - Map of assets
5
+ * @param existingAssets - Map of existing assets from previous runs
6
+ * @returns JSON string
7
+ */
8
+ export declare function generateAssetsFileContent(assets: Map<string, AssetInfo>, existingAssets: Map<string, string>): string;
9
+ /**
10
+ * Parse existing assets.json file
11
+ * @param content - File content
12
+ * @returns Map of URI to constant name
13
+ */
14
+ export declare function parseExistingAssetsContent(content: string): Map<string, string>;
15
+ /**
16
+ * Log generation statistics
17
+ * @param totalAssets - Total number of assets
18
+ * @param existingAssets - Map of existing assets
19
+ * @param assets - Map of current assets
20
+ * @param outputFile - Output file path
21
+ */
22
+ export declare function logGenerationStats(totalAssets: number, existingAssets: Map<string, string>, assets: Map<string, AssetInfo>, outputFile: string): void;
@@ -1,9 +1,4 @@
1
1
  import { Plugin } from 'vite';
2
- interface AssetConstantsOptions {
3
- extensions?: string[];
4
- srcDir?: string;
5
- outputFile?: string;
6
- devMode?: boolean;
7
- }
2
+ import { AssetConstantsOptions } from './types';
8
3
  export declare function assetConstantsPlugin(options?: AssetConstantsOptions): Plugin;
9
4
  export default assetConstantsPlugin;
@@ -1,19 +1,50 @@
1
- var v = Object.defineProperty;
2
- var $ = (l, s, t) => s in l ? v(l, s, { enumerable: !0, configurable: !0, writable: !0, value: t }) : l[s] = t;
3
- var g = (l, s, t) => $(l, typeof s != "symbol" ? s + "" : s, t);
4
- import { promises as f } from "fs";
5
- import p from "path";
6
- import { parse as F } from "@babel/parser";
7
- import d from "@babel/traverse";
1
+ var C = Object.defineProperty;
2
+ var v = (a, s, t) => s in a ? C(a, s, { enumerable: !0, configurable: !0, writable: !0, value: t }) : a[s] = t;
3
+ var f = (a, s, t) => v(a, typeof s != "symbol" ? s + "" : s, t);
4
+ import { promises as g } from "fs";
5
+ import d from "path";
6
+ import { parse as N } from "@babel/parser";
7
+ import h from "@babel/traverse";
8
8
  import * as u from "@babel/types";
9
9
  import m from "@babel/generator";
10
- import { generateConstantName as j, extractAssetsFromContent as N, processAssetURL as C } from "../utils/index.js";
11
- const A = typeof d == "function" ? d : d.default, U = typeof m == "function" ? m : m.default;
12
- class E {
10
+ import { generateConstantName as U, extractAssetsFromContent as $, processAssetURL as j } from "../utils/index.js";
11
+ import { F as E, g as A, a as b } from "../file-scanner-DHkDSQm8.js";
12
+ function D(a, s) {
13
+ const t = {};
14
+ for (const [i, o] of s.entries())
15
+ t[o] = i;
16
+ return Array.from(a.values()).forEach((i) => {
17
+ t[i.constantName] = i.originalUri;
18
+ }), JSON.stringify(t, null, 2) + `
19
+ `;
20
+ }
21
+ function I(a) {
22
+ const s = /* @__PURE__ */ new Map();
23
+ try {
24
+ if (!a.trim())
25
+ return s;
26
+ const t = JSON.parse(a);
27
+ for (const [e, i] of Object.entries(t))
28
+ typeof i == "string" && s.set(i, e);
29
+ s.size > 0 && console.log(`📋 Found ${s.size} existing constants in assets.json`);
30
+ } catch (t) {
31
+ console.warn("Warning: Failed to parse existing assets.json:", t);
32
+ }
33
+ return s;
34
+ }
35
+ function S(a, s, t, e) {
36
+ const i = Array.from(t.values()).filter(
37
+ (n) => s.has(n.originalUri)
38
+ ).length, o = a - i;
39
+ o > 0 ? console.log(`✅ Generated ${a} asset constants (${o} new, ${i} reused) in ${e}`) : a > 0 ? console.log(`✅ Generated ${a} asset constants (all reused from existing) in ${e}`) : console.log("✅ No asset constants found");
40
+ }
41
+ const x = typeof h == "function" ? h : h.default, W = typeof m == "function" ? m : m.default;
42
+ class R {
13
43
  constructor(s = {}) {
14
- g(this, "options");
15
- g(this, "assets", /* @__PURE__ */ new Map());
16
- g(this, "existingAssets", /* @__PURE__ */ new Map());
44
+ f(this, "options");
45
+ f(this, "assets", /* @__PURE__ */ new Map());
46
+ f(this, "existingAssets", /* @__PURE__ */ new Map());
47
+ f(this, "fileCache", new E());
17
48
  this.options = {
18
49
  extensions: [".png", ".jpg", ".jpeg", ".gif", ".svg", ".mp4", ".mp3", ".wav", ".ogg", ".webm"],
19
50
  srcDir: "src",
@@ -22,157 +53,115 @@ class E {
22
53
  ...s
23
54
  };
24
55
  }
56
+ clearCache() {
57
+ this.fileCache.clear();
58
+ }
25
59
  generateConstantName(s) {
26
60
  const t = /* @__PURE__ */ new Set([
27
61
  ...Array.from(this.assets.values()).map((e) => e.constantName),
28
62
  ...Array.from(this.existingAssets.values())
29
63
  ]);
30
- return j(s, t);
64
+ return U(s, t);
31
65
  }
32
66
  async scanTsFile(s) {
33
67
  try {
34
- const t = await f.readFile(s, "utf-8");
35
- F(t, {
36
- sourceType: "module",
37
- plugins: ["typescript", "jsx", "decorators-legacy"]
38
- });
39
- const e = [];
40
- return N(t, "js", this.options.extensions).forEach((i) => {
41
- const n = this.generateConstantName(i), a = t.split(`
42
- `).findIndex((h) => h.includes(i)) + 1;
68
+ const t = await this.fileCache.read(s), e = [], i = $(t, "js", this.options.extensions), o = t.split(`
69
+ `);
70
+ return i.forEach((n) => {
71
+ const r = this.generateConstantName(n), c = o.findIndex((p) => p.includes(n)) + 1;
43
72
  e.push({
44
- originalUri: i,
45
- constantName: n,
73
+ originalUri: n,
74
+ constantName: r,
46
75
  filePath: s,
47
- line: a,
76
+ line: c,
48
77
  column: 1
49
78
  });
50
79
  }), e;
51
80
  } catch (t) {
52
- return console.warn(`Warning: Failed to parse ${s}:`, t), [];
81
+ return console.warn(`Warning: Failed to scan ${s}:`, t), [];
53
82
  }
54
83
  }
55
84
  async scanAllTsFiles() {
56
85
  const s = this.options.srcDir;
57
86
  try {
58
- const t = await this.getAllTsFiles(s);
87
+ const t = await A(s, [".ts", ".tsx"]);
59
88
  for (const e of t) {
60
89
  if (e.endsWith("assets.json") || e.endsWith("assets.ts"))
61
90
  continue;
62
- (await this.scanTsFile(e)).forEach((i) => {
63
- this.existingAssets.has(i.originalUri) && (i.constantName = this.existingAssets.get(i.originalUri));
64
- const n = i.originalUri;
65
- this.assets.has(n) || this.assets.set(n, i);
91
+ (await this.scanTsFile(e)).forEach((o) => {
92
+ this.existingAssets.has(o.originalUri) && (o.constantName = this.existingAssets.get(o.originalUri));
93
+ const n = o.originalUri;
94
+ this.assets.has(n) || this.assets.set(n, o);
66
95
  });
67
96
  }
68
97
  } catch (t) {
69
98
  console.error("Error scanning TypeScript files:", t);
70
99
  }
71
100
  }
72
- async getAllTsFiles(s) {
73
- const t = [];
74
- try {
75
- const e = await f.readdir(s, { withFileTypes: !0 });
76
- for (const o of e) {
77
- const i = p.join(s, o.name);
78
- if (o.isDirectory()) {
79
- const n = await this.getAllTsFiles(i);
80
- t.push(...n);
81
- } else o.isFile() && /\.(ts|tsx)$/.test(o.name) && t.push(i);
82
- }
83
- } catch (e) {
84
- console.warn(`Warning: Failed to read directory ${s}:`, e);
85
- }
86
- return t;
87
- }
88
- generateAssetsFileContent() {
89
- const s = Array.from(this.assets.values()), t = {};
90
- return s.forEach((e) => {
91
- t[e.constantName] = e.originalUri;
92
- }), JSON.stringify(t, null, 2) + `
93
- `;
94
- }
95
101
  async readExistingAssetsFile() {
96
102
  try {
97
- return await f.readFile(this.options.outputFile, "utf-8");
103
+ return await g.readFile(this.options.outputFile, "utf-8");
98
104
  } catch {
99
105
  return "";
100
106
  }
101
107
  }
102
108
  async parseExistingAssets() {
103
- try {
104
- const s = await this.readExistingAssetsFile();
105
- if (!s.trim())
106
- return;
107
- const t = JSON.parse(s);
108
- for (const [e, o] of Object.entries(t))
109
- typeof o == "string" && this.existingAssets.set(o, e);
110
- this.existingAssets.size > 0 && console.log(`📋 Found ${this.existingAssets.size} existing constants in assets.json`);
111
- } catch (s) {
112
- console.warn("Warning: Failed to parse existing assets.json:", s);
113
- }
109
+ const s = await this.readExistingAssetsFile();
110
+ this.existingAssets = I(s);
114
111
  }
115
112
  async generateAssetsFile() {
116
113
  await this.parseExistingAssets(), await this.scanAllTsFiles();
117
- const s = this.generateAssetsFileContent(), t = p.dirname(this.options.outputFile);
118
- await f.mkdir(t, { recursive: !0 }), await f.writeFile(this.options.outputFile, s, "utf-8");
119
- const e = Array.from(this.assets.values()).filter(
120
- (i) => this.existingAssets.has(i.originalUri)
121
- ).length, o = this.assets.size - e;
122
- o > 0 ? console.log(`✅ Generated ${this.assets.size} asset constants (${o} new, ${e} reused) in ${this.options.outputFile}`) : this.assets.size > 0 ? console.log(`✅ Generated ${this.assets.size} asset constants (all reused from existing) in ${this.options.outputFile}`) : console.log("✅ No asset constants found");
114
+ const s = D(this.assets, this.existingAssets), t = d.dirname(this.options.outputFile);
115
+ await g.mkdir(t, { recursive: !0 }), await g.writeFile(this.options.outputFile, s, "utf-8"), S(this.assets.size, this.existingAssets, this.assets, this.options.outputFile);
123
116
  }
124
117
  getAssets() {
125
118
  return Array.from(this.assets.values());
126
119
  }
127
120
  async replaceUrisInFile(s, t) {
128
121
  try {
129
- const e = await f.readFile(s, "utf-8"), o = F(e, {
122
+ const e = await this.fileCache.read(s), i = N(e, {
130
123
  sourceType: "module",
131
124
  plugins: ["typescript", "jsx", "decorators-legacy"]
132
125
  });
133
- let i = !1;
134
- if (A(o, {
126
+ let o = !1;
127
+ if (x(i, {
135
128
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
136
- StringLiteral: (c) => {
137
- const h = c.node.value, w = C(h);
129
+ StringLiteral: (l) => {
130
+ const p = l.node.value, w = j(p);
138
131
  if (t.has(w)) {
139
- const x = t.get(w), y = u.memberExpression(
132
+ const F = t.get(w), y = u.memberExpression(
140
133
  u.identifier("assetsData"),
141
- u.identifier(x)
134
+ u.identifier(F)
142
135
  );
143
- c.parent && u.isJSXAttribute(c.parent) ? c.replaceWith(u.jsxExpressionContainer(y)) : c.replaceWith(y), i = !0;
136
+ l.parent && u.isJSXAttribute(l.parent) ? l.replaceWith(u.jsxExpressionContainer(y)) : l.replaceWith(y), o = !0;
144
137
  }
145
138
  }
146
- }), !i)
139
+ }), !o)
147
140
  return;
148
- const n = this.getRelativeImportPath(s, this.options.outputFile) + ".json";
141
+ const n = b(s, this.options.outputFile) + ".json";
149
142
  let r = !1;
150
- if (A(o, {
143
+ if (x(i, {
151
144
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
152
- ImportDeclaration: (c) => {
153
- c.node.source.value === n && (r = !0, c.stop());
145
+ ImportDeclaration: (l) => {
146
+ l.node.source.value === n && (r = !0, l.stop());
154
147
  }
155
148
  }), !r) {
156
- const c = u.importDeclaration(
149
+ const l = u.importDeclaration(
157
150
  [u.importDefaultSpecifier(u.identifier("assetsData"))],
158
151
  u.stringLiteral(n)
159
152
  );
160
- o.program.body.unshift(c);
153
+ i.program.body.unshift(l);
161
154
  }
162
- const a = U(o, {
155
+ const c = W(i, {
163
156
  retainLines: !1,
164
157
  comments: !0,
165
158
  compact: !1
166
159
  }, e);
167
- await f.writeFile(s, a.code, "utf-8"), console.log(` ✓ Replaced URIs in ${p.relative(process.cwd(), s)}`);
160
+ await g.writeFile(s, c.code, "utf-8"), this.fileCache.invalidate(s), console.log(` ✓ Replaced URIs in ${d.relative(process.cwd(), s)}`);
168
161
  } catch (e) {
169
162
  console.warn(`Warning: Failed to replace URIs in ${s}:`, e);
170
163
  }
171
164
  }
172
- getRelativeImportPath(s, t) {
173
- const o = p.relative(p.dirname(s), t).replace(/\.(ts|json)$/, "");
174
- return o.startsWith(".") ? o : `./${o}`;
175
- }
176
165
  async replaceAllUris() {
177
166
  const s = /* @__PURE__ */ new Map(), t = /* @__PURE__ */ new Set();
178
167
  for (const e of this.assets.values())
@@ -188,35 +177,35 @@ class E {
188
177
  const t = /* @__PURE__ */ new Map();
189
178
  try {
190
179
  const n = JSON.parse(s);
191
- for (const [r, a] of Object.entries(n))
192
- typeof a == "string" && t.set(r, a);
180
+ for (const [r, c] of Object.entries(n))
181
+ typeof c == "string" && t.set(r, c);
193
182
  } catch (n) {
194
183
  console.warn("Warning: Failed to parse assets.json:", n);
195
184
  return;
196
185
  }
197
186
  if (t.size === 0)
198
187
  return;
199
- const e = /* @__PURE__ */ new Set(), o = await this.getAllTsFiles(this.options.srcDir);
200
- for (const n of o)
188
+ const e = /* @__PURE__ */ new Set(), i = await A(this.options.srcDir, [".ts", ".tsx"]);
189
+ for (const n of i)
201
190
  if (!(n.endsWith("assets.json") || n.endsWith("assets.ts")))
202
191
  try {
203
- const r = await f.readFile(n, "utf-8");
204
- for (const a of t.keys())
205
- r.includes(a) && e.add(a);
192
+ const r = await this.fileCache.read(n);
193
+ for (const c of t.keys())
194
+ r.includes(c) && e.add(c);
206
195
  } catch (r) {
207
196
  console.warn(`Warning: Failed to read ${n}:`, r);
208
197
  }
209
- const i = [];
198
+ const o = [];
210
199
  for (const n of t.keys())
211
- e.has(n) || i.push(n);
212
- if (i.length > 0) {
213
- console.log(`🧹 Removing ${i.length} unused constant(s):`), i.forEach((r) => {
200
+ e.has(n) || o.push(n);
201
+ if (o.length > 0) {
202
+ console.log(`🧹 Removing ${o.length} unused constant(s):`), o.forEach((r) => {
214
203
  console.log(` - ${r}`);
215
204
  });
216
205
  const n = [];
217
- for (const r of i) {
218
- const a = t.get(r);
219
- a && n.push(a);
206
+ for (const r of o) {
207
+ const c = t.get(r);
208
+ c && n.push(c);
220
209
  }
221
210
  for (const r of n)
222
211
  this.assets.delete(r);
@@ -227,22 +216,22 @@ class E {
227
216
  }
228
217
  }
229
218
  }
230
- function z(l = {}) {
219
+ function q(a = {}) {
231
220
  return {
232
221
  name: "vite-plugin-asset-constants",
233
222
  apply: "build",
234
223
  async buildStart() {
235
- if (l.devMode)
224
+ if (a.devMode)
236
225
  try {
237
- const s = new E(l);
226
+ const s = new R(a);
238
227
  await s.generateAssetsFile();
239
228
  const t = s.getAssets();
240
229
  t.length > 0 && (console.log(`📦 Found ${t.length} asset references:`), t.forEach((e) => {
241
- console.log(` ${e.constantName} = '${e.originalUri}' (${p.relative(process.cwd(), e.filePath)}:${e.line})`);
230
+ console.log(` ${e.constantName} = '${e.originalUri}' (${d.relative(process.cwd(), e.filePath)}:${e.line})`);
242
231
  }), console.log(`
243
232
  🔄 Replacing URIs with constants...`), await s.replaceAllUris(), console.log("✅ URI replacement completed!")), console.log(`
244
233
  🧹 Checking for unused constants...`), await s.cleanupUnusedConstants(), await s.generateAssetsFile(), console.log(`✅ Asset constants finalized!
245
- `);
234
+ `), s.clearCache();
246
235
  } catch (s) {
247
236
  console.error("❌ Error in asset constants plugin:", s);
248
237
  }
@@ -250,6 +239,6 @@ function z(l = {}) {
250
239
  };
251
240
  }
252
241
  export {
253
- z as assetConstantsPlugin,
254
- z as default
242
+ q as assetConstantsPlugin,
243
+ q as default
255
244
  };
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Type definitions for asset constants plugin
3
+ */
4
+ export interface AssetConstantsOptions {
5
+ extensions?: string[];
6
+ srcDir?: string;
7
+ outputFile?: string;
8
+ devMode?: boolean;
9
+ }
10
+ export interface AssetInfo {
11
+ originalUri: string;
12
+ constantName: string;
13
+ filePath: string;
14
+ line: number;
15
+ column: number;
16
+ }
@@ -0,0 +1,50 @@
1
+ var l = Object.defineProperty;
2
+ var u = (e, t, a) => t in e ? l(e, t, { enumerable: !0, configurable: !0, writable: !0, value: a }) : e[t] = a;
3
+ var o = (e, t, a) => u(e, typeof t != "symbol" ? t + "" : t, a);
4
+ import { promises as h } from "fs";
5
+ import i from "path";
6
+ async function f(e, t) {
7
+ const a = [];
8
+ try {
9
+ const s = await h.readdir(e, { withFileTypes: !0 });
10
+ for (const r of s) {
11
+ const c = i.join(e, r.name);
12
+ if (r.isDirectory()) {
13
+ const n = await f(c, t);
14
+ a.push(...n);
15
+ } else if (r.isFile()) {
16
+ const n = i.extname(r.name);
17
+ t.includes(n) && a.push(c);
18
+ }
19
+ }
20
+ } catch (s) {
21
+ console.warn(`Warning: Failed to read directory ${e}:`, s);
22
+ }
23
+ return a;
24
+ }
25
+ function y(e, t) {
26
+ const s = i.relative(i.dirname(e), t).replace(/\.(ts|tsx|js|jsx|json)$/, "");
27
+ return s.startsWith(".") ? s : `./${s}`;
28
+ }
29
+ class F {
30
+ constructor() {
31
+ o(this, "cache", /* @__PURE__ */ new Map());
32
+ }
33
+ async read(t) {
34
+ if (this.cache.has(t))
35
+ return this.cache.get(t);
36
+ const a = await h.readFile(t, "utf-8");
37
+ return this.cache.set(t, a), a;
38
+ }
39
+ invalidate(t) {
40
+ this.cache.delete(t);
41
+ }
42
+ clear() {
43
+ this.cache.clear();
44
+ }
45
+ }
46
+ export {
47
+ F,
48
+ y as a,
49
+ f as g
50
+ };
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Common file scanning utilities for vite plugins
3
+ */
4
+ /**
5
+ * Recursively get all files in a directory matching specified extensions
6
+ * @param dir - Directory to scan
7
+ * @param extensions - File extensions to match (e.g., ['.ts', '.tsx', '.js'])
8
+ * @returns Array of file paths
9
+ */
10
+ export declare function getFilesByExtension(dir: string, extensions: string[]): Promise<string[]>;
11
+ /**
12
+ * Get relative import path from one file to another
13
+ * @param fromFile - Source file path
14
+ * @param toFile - Target file path
15
+ * @returns Relative import path (without extension)
16
+ */
17
+ export declare function getRelativeImportPath(fromFile: string, toFile: string): string;
18
+ /**
19
+ * Read file with caching support
20
+ */
21
+ export declare class FileContentCache {
22
+ private cache;
23
+ read(filePath: string): Promise<string>;
24
+ invalidate(filePath: string): void;
25
+ clear(): void;
26
+ }
@@ -3,8 +3,9 @@
3
3
  */
4
4
  /**
5
5
  * Process asset URL to ensure it's properly formatted
6
+ * Keep the original path format to preserve context-dependent paths
6
7
  * @param url - The asset URL to process
7
- * @returns Processed URL
8
+ * @returns Processed URL (trimmed and cleaned)
8
9
  */
9
10
  export declare function processAssetURL(url: string): string;
10
11
  /**
@@ -1,89 +1,96 @@
1
- import { existsSync as l } from "fs";
2
- import g from "path";
3
- const h = [".png", ".jpg", ".jpeg", ".gif", ".svg", ".webp"], m = [".mp4", ".webm", ".mov", ".avi"], w = [".mp3", ".wav", ".ogg", ".m4a"];
4
- function p(e) {
5
- return e.match(/^https?:\/\//) || e.match(/^data:/) || e.match(/^blob:/) || e.startsWith("/") ? e : `/${e}`;
1
+ import { existsSync as g } from "fs";
2
+ import f from "path";
3
+ const u = [".png", ".jpg", ".jpeg", ".gif", ".svg", ".webp"], d = [".mp4", ".webm", ".mov", ".avi"], w = [".mp3", ".wav", ".ogg", ".m4a"];
4
+ function m(t) {
5
+ return t = t.trim(), t.match(/^https?:\/\//) || t.match(/^data:/) || t.match(/^blob:/), t;
6
6
  }
7
- function E(e) {
8
- return !(e.includes("node_modules") || e.length < 4 || e.startsWith("./") && e.length < 10);
7
+ function h(t) {
8
+ if (!t || t.length < 4 || t.includes("node_modules") || t.startsWith("./") && t.length < 10)
9
+ return !1;
10
+ let e;
11
+ if (t.match(/^https?:\/\//)) {
12
+ const r = t.split("/");
13
+ e = r[r.length - 1];
14
+ } else {
15
+ const r = t.split("/");
16
+ e = r[r.length - 1];
17
+ }
18
+ if (e = e.split("?")[0].split("#")[0], !e || e.startsWith("."))
19
+ return !1;
20
+ const s = e.split(".");
21
+ return !(s.length < 2 || s[0].length === 0 || s[s.length - 1].toLowerCase() === "json");
9
22
  }
10
- function R(e, t = /* @__PURE__ */ new Set()) {
11
- let r = "ASSET";
12
- h.some((n) => e.endsWith(n)) ? r = "IMAGE" : m.some((n) => e.endsWith(n)) ? r = "VIDEO" : w.some((n) => e.endsWith(n)) && (r = "AUDIO");
23
+ function C(t, e = /* @__PURE__ */ new Set()) {
24
+ let s = "ASSET";
25
+ u.some((n) => t.endsWith(n)) ? s = "IMAGE" : d.some((n) => t.endsWith(n)) ? s = "VIDEO" : w.some((n) => t.endsWith(n)) && (s = "AUDIO");
13
26
  let o;
14
- const s = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
27
+ const r = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
15
28
  do {
16
29
  let n = "";
17
- for (let c = 0; c < 4; c++)
18
- n += s[Math.floor(Math.random() * s.length)];
19
- o = `${r}_${n}`;
20
- } while (t.has(o));
30
+ for (let i = 0; i < 4; i++)
31
+ n += r[Math.floor(Math.random() * r.length)];
32
+ o = `${s}_${n}`;
33
+ } while (e.has(o));
21
34
  return o;
22
35
  }
23
- function d(e, t, r = [".js", ".css", ".png", ".jpg", ".jpeg", ".gif", ".svg", ".woff", ".woff2", ".ttf", ".eot"]) {
24
- const o = /* @__PURE__ */ new Set(), s = r.map((n) => n.replace(/^\./, "")).join("|");
25
- if (t === "html")
36
+ function E(t) {
37
+ return t.replace(
38
+ /(["'])(?:(?=(\\?))\2.)*?\1|\/\*[\s\S]*?\*\/|\/\/.*/g,
39
+ (s) => s.startsWith('"') || s.startsWith("'") ? s : ""
40
+ );
41
+ }
42
+ function S(t) {
43
+ return t.replace(/\/\*[\s\S]*?\*\//g, "");
44
+ }
45
+ function j(t, e, s = [".js", ".css", ".png", ".jpg", ".jpeg", ".gif", ".svg", ".woff", ".woff2", ".ttf", ".eot"]) {
46
+ const o = /* @__PURE__ */ new Set();
47
+ let r = t;
48
+ e === "js" ? r = E(t) : e === "css" && (r = S(t));
49
+ const n = s.map((i) => i.replace(/^\./, "")).join("|");
50
+ if (e === "html")
26
51
  [
27
52
  // src/href attributes for img, script, link, video, audio tags
28
- new RegExp(`(?:src|href)=["']([^"']*\\.(?:${s}))["']`, "g"),
53
+ new RegExp(`(?:src|href)=["']([^"']*\\.(?:${n}))["']`, "g"),
29
54
  // url() in CSS
30
- new RegExp(`url\\(["']?([^"']*\\.(?:${s}))["']?\\)`, "g")
31
- ].forEach((a) => {
32
- let i;
33
- for (; (i = a.exec(e)) !== null; )
34
- i[1] && o.add(p(i[1]));
35
- }), (e.match(/<script[^>]*>[\s\S]*?<\/script>/g) || []).forEach((a) => {
36
- const i = a.replace(/<script[^>]*>/, "").replace(/<\/script>/, "");
37
- d(i, "js", r).forEach((f) => o.add(f));
38
- });
39
- else if (t === "js")
40
- [
41
- // Dynamic import()
42
- new RegExp(`import\\(["']([^"']*\\.(?:${s}))["']\\)`, "g"),
43
- // fetch() requests
44
- new RegExp(`fetch\\(["']([^"']*\\.(?:${s}))["']\\)`, "g"),
45
- // new Image() creation
46
- new RegExp(`new\\s+Image\\(\\)\\.src\\s*=\\s*["']([^"']*\\.(?:${s}))["']`, "g"),
47
- // Direct src assignment
48
- new RegExp(`\\.src\\s*=\\s*["']([^"']*\\.(?:${s}))["']`, "g"),
49
- // Resource paths in variable assignments
50
- new RegExp(`=\\s*["']([^"']*\\.(?:${s}))["']`, "g"),
51
- // Resource paths in variable declarations
52
- new RegExp(`const\\s+\\w+\\s*=\\s*["']([^"']*\\.(?:${s}))["']`, "g"),
53
- // Variable assignments in minified code
54
- new RegExp(`\\w+\\s*=\\s*["']([^"']*\\.(?:${s}))["']`, "g"),
55
- // Resource paths in string literals (more precise matching)
56
- new RegExp(`["']([^"']*\\.(?:${s}))["']`, "g")
57
- ].forEach((c) => {
55
+ new RegExp(`url\\(["']?([^"']*\\.(?:${n}))["']?\\)`, "g")
56
+ ].forEach((l) => {
58
57
  let a;
59
- for (; (a = c.exec(e)) !== null; )
60
- a[1] && E(a[1]) && o.add(p(a[1]));
58
+ for (; (a = l.exec(r)) !== null; )
59
+ a[1] && h(a[1]) && o.add(m(a[1]));
60
+ }), (r.match(/<script[^>]*>[\s\S]*?<\/script>/g) || []).forEach((l) => {
61
+ const a = l.replace(/<script[^>]*>/, "").replace(/<\/script>/, "");
62
+ j(a, "js", s).forEach((p) => o.add(p));
61
63
  });
62
- else if (t === "css") {
63
- const n = new RegExp(`url\\(["']?([^"']*\\.(?:${s}))["']?\\)`, "g");
64
+ else if (e === "js") {
65
+ const i = new RegExp(`["']([^"']*\\.(?:${n}))["']`, "g");
66
+ let c;
67
+ for (; (c = i.exec(r)) !== null; )
68
+ c[1] && h(c[1]) && o.add(m(c[1]));
69
+ } else if (e === "css") {
70
+ const i = new RegExp(`url\\(["']?([^"']*\\.(?:${n}))["']?\\)`, "g");
64
71
  let c;
65
- for (; (c = n.exec(e)) !== null; )
66
- c[1] && o.add(p(c[1]));
72
+ for (; (c = i.exec(r)) !== null; )
73
+ c[1] && h(c[1]) && o.add(m(c[1]));
67
74
  }
68
75
  return Array.from(o);
69
76
  }
70
- function S(e = process.cwd()) {
77
+ function N(t = process.cwd()) {
71
78
  try {
72
- let t = e, r = 0;
73
- for (; t !== g.parse(t).root && r < 20; ) {
74
- if (l(g.join(t, "package.json")))
75
- return t;
76
- t = g.dirname(t), r++;
79
+ let e = t, s = 0;
80
+ for (; e !== f.parse(e).root && s < 20; ) {
81
+ if (g(f.join(e, "package.json")))
82
+ return e;
83
+ e = f.dirname(e), s++;
77
84
  }
78
85
  return process.cwd();
79
- } catch (t) {
80
- return console.error("Error finding project root:", t), process.cwd();
86
+ } catch (e) {
87
+ return console.error("Error finding project root:", e), process.cwd();
81
88
  }
82
89
  }
83
90
  export {
84
- d as extractAssetsFromContent,
85
- S as findProjectRoot,
86
- R as generateConstantName,
87
- E as isValidAsset,
88
- p as processAssetURL
91
+ j as extractAssetsFromContent,
92
+ N as findProjectRoot,
93
+ C as generateConstantName,
94
+ h as isValidAsset,
95
+ m as processAssetURL
89
96
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aippy/vite-plugins",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "Vite plugins for Aippy projects - Asset management and component tagging",
5
5
  "private": false,
6
6
  "type": "module",