mirror of
https://github.com/johndoe6345789/low-code-react-app-b.git
synced 2026-04-24 13:44:54 +00:00
154 lines
7.3 KiB
JavaScript
154 lines
7.3 KiB
JavaScript
import fs from 'fs';
|
|
import path from 'path';
|
|
|
|
function createIconImportProxy() {
|
|
const packageName = '@phosphor-icons/react';
|
|
const fallbackIcon = 'Question';
|
|
const packagePath = 'node_modules/@phosphor-icons/react';
|
|
// Cache to avoid redundant filesystem checks
|
|
const existingExportsCache = new Set();
|
|
let hasLoadedExports = false;
|
|
const proxiedImports = new Map();
|
|
// Function to load all available exports from the package
|
|
const loadExports = () => {
|
|
if (hasLoadedExports)
|
|
return;
|
|
try {
|
|
const packageDir = path.resolve(packagePath);
|
|
console.log(`[icon-proxy] Checking for exports in directory: ${packageDir}`);
|
|
const filesToCheck = [
|
|
path.join(packageDir, 'dist', 'index.js'),
|
|
path.join(packageDir, 'dist', 'index.mjs'),
|
|
path.join(packageDir, 'dist', 'index.d.ts'),
|
|
path.join(packageDir, 'index.js'),
|
|
path.join(packageDir, 'index.d.ts'),
|
|
];
|
|
// Find the first file that exists
|
|
const existingFile = filesToCheck.find((file) => fs.existsSync(file));
|
|
if (existingFile) {
|
|
console.log(`[icon-proxy] Found package file: ${existingFile}`);
|
|
const content = fs.readFileSync(existingFile, 'utf-8');
|
|
// Extract export names with multiple regex patterns to catch different export styles
|
|
const exportPatterns = [
|
|
/export\s+\{\s*([^}]+)\s*\}/g, // export { Name1, Name2 }
|
|
/export\s+const\s+(\w+)/g, // export const Name
|
|
/export\s+function\s+(\w+)/g, // export function Name
|
|
/export\s+type\s+(\w+)/g, // export type Name
|
|
/export\s+\*\s+from\s+'.*\/csr\/(\w+)'/g, // export * from './csr/Name'
|
|
];
|
|
exportPatterns.forEach((pattern) => {
|
|
let match;
|
|
while ((match = pattern.exec(content)) !== null) {
|
|
if (pattern.source.includes('\\{')) {
|
|
// Multiple exports in braces
|
|
const exports$1 = match[1].split(',').map((e) => {
|
|
const parts = e.trim().split(/\s+as\s+/);
|
|
return parts[parts.length - 1].trim();
|
|
});
|
|
exports$1.forEach((name) => existingExportsCache.add(name));
|
|
}
|
|
else {
|
|
// Single export
|
|
existingExportsCache.add(match[1]);
|
|
}
|
|
}
|
|
});
|
|
console.log(`[icon-proxy] Loaded ${existingExportsCache.size} exports from ${existingFile}`);
|
|
}
|
|
else {
|
|
console.warn(`[icon-proxy] Could not find any index files for ${packageName}`);
|
|
}
|
|
hasLoadedExports = true;
|
|
}
|
|
catch (error) {
|
|
console.error(`[icon-proxy] Error analyzing package exports:`, error);
|
|
}
|
|
};
|
|
return {
|
|
name: 'vite-icon-import-proxy',
|
|
enforce: 'pre',
|
|
configResolved() {
|
|
loadExports();
|
|
},
|
|
transform(code, id) {
|
|
// Skip if not a JS/TS file or is in node_modules
|
|
if (!/\.(jsx?|tsx?)$/.test(id) || id.includes('node_modules')) {
|
|
return null;
|
|
}
|
|
// Ensure exports are loaded
|
|
if (!hasLoadedExports) {
|
|
loadExports();
|
|
}
|
|
if (!existingExportsCache.has(fallbackIcon)) {
|
|
// If we don't find the fallback icon, then there is no sense in trying to proxy icons to it.
|
|
// It's actually more likely that the icons *do* exist than not, so we should avoid proxying anything to prevent breaking the App's icons.
|
|
console.warn('[icon-proxy] Warning: Fallback icon not found. Not proxying any icons');
|
|
return null;
|
|
}
|
|
// No need to process files that don't import from our package
|
|
if (!code.includes(packageName)) {
|
|
return null;
|
|
}
|
|
// Regular expression to find imports from the package
|
|
// This matches both these patterns:
|
|
// import { IconA, IconB } from '@phosphor-icons/react';
|
|
// import { IconA as RenamedA, IconB } from '@phosphor-icons/react';
|
|
const importRegex = new RegExp(`import\\s+{([^}]+)}\\s+from\\s+['"]${packageName}['"]`, 'g');
|
|
let match;
|
|
let hasChanges = false;
|
|
let modifiedCode = code;
|
|
// Process each import statement
|
|
while ((match = importRegex.exec(code)) !== null) {
|
|
// Extract the imports section { IconA, IconB as AliasB, ... }
|
|
const importSection = match[1];
|
|
// Split into individual imports and process each
|
|
const imports = importSection
|
|
.split(',')
|
|
.map((item) => item.trim())
|
|
.filter((item) => item.length > 0);
|
|
let newImports = [...imports];
|
|
let needsQuestion = false;
|
|
// Process each imported icon
|
|
for (let i = 0; i < imports.length; i++) {
|
|
const importItem = imports[i];
|
|
// Handle aliased imports: IconName as AliasName
|
|
const parts = importItem.trim().split(/\s+as\s+/);
|
|
const iconName = parts[0].trim();
|
|
const aliasName = parts.length > 1 ? parts[1].trim() : iconName;
|
|
// Check if this icon exists in the package
|
|
if (!existingExportsCache.has(iconName)) {
|
|
console.log(`[icon-proxy] Proxying non-existent icon: ${iconName} -> ${fallbackIcon}`);
|
|
proxiedImports.set(iconName, fallbackIcon);
|
|
// Replace with Question as AliasName
|
|
newImports[i] = `${fallbackIcon} as ${aliasName}`;
|
|
needsQuestion = true;
|
|
hasChanges = true;
|
|
}
|
|
}
|
|
// Make sure Question is included if we need it
|
|
if (needsQuestion && !imports.some((imp) => imp === fallbackIcon || imp.startsWith(`${fallbackIcon} `))) {
|
|
newImports.push(fallbackIcon);
|
|
}
|
|
// Construct the new import statement
|
|
const originalImport = match[0];
|
|
const newImport = `import { ${newImports.join(', ')} } from '${packageName}'`;
|
|
// Replace in the code
|
|
modifiedCode = modifiedCode.replace(originalImport, newImport);
|
|
}
|
|
return hasChanges ? modifiedCode : null;
|
|
},
|
|
// At the end of the build, report which icons were proxied
|
|
closeBundle() {
|
|
if (proxiedImports.size > 0) {
|
|
console.log('\n[icon-proxy] Proxied imports:');
|
|
proxiedImports.forEach((fallback, original) => {
|
|
console.log(` - "${original}" -> "${fallback}"`);
|
|
});
|
|
}
|
|
},
|
|
};
|
|
}
|
|
|
|
export { createIconImportProxy as default };
|
|
//# sourceMappingURL=vitePhosphorIconProxyPlugin.js.map
|