#!/usr/bin/env node /** * Copy Astro build assets to WordPress plugin structure * and generate PHP-readable manifest */ import fs from 'fs'; import path from 'path'; import { fileURLToPath } from 'url'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); class WordPressAssetCopier { constructor() { this.projectRoot = path.resolve(__dirname, '..'); this.astroDistDir = path.join(this.projectRoot, 'admin/assets/dist'); this.wpAdminDir = path.join(this.projectRoot, 'admin'); this.manifest = {}; this.stats = { filesCopied: 0, errors: 0 }; } async run() { console.log('🚀 Starting WordPress asset integration...'); try { // Ensure directories exist await this.ensureDirectories(); // Parse Astro build output await this.parseAstroOutput(); // Generate WordPress manifest await this.generateManifest(); // Copy additional assets await this.copyStaticAssets(); // Generate asset loader await this.generateAssetLoader(); console.log(`✅ Successfully processed ${this.stats.filesCopied} files`); if (this.stats.errors > 0) { console.warn(`⚠️ ${this.stats.errors} errors encountered`); } } catch (error) { console.error('❌ Asset integration failed:', error.message); process.exit(1); } } async ensureDirectories() { const dirs = [ path.join(this.wpAdminDir, 'js'), path.join(this.wpAdminDir, 'css'), path.join(this.wpAdminDir, 'images') ]; for (const dir of dirs) { if (!fs.existsSync(dir)) { fs.mkdirSync(dir, { recursive: true }); } } } async parseAstroOutput() { if (!fs.existsSync(this.astroDistDir)) { throw new Error(`Astro dist directory not found: ${this.astroDistDir}`); } // Read all files from dist directory const files = await this.getAllFiles(this.astroDistDir); for (const file of files) { const relativePath = path.relative(this.astroDistDir, file); const ext = path.extname(file).toLowerCase(); // Categorize and process files if (ext === '.html') { await this.processHtmlFile(file, relativePath); } else if (ext === '.js') { await this.processJsFile(file, relativePath); } else if (ext === '.css') { await this.processCssFile(file, relativePath); } else if (['.png', '.jpg', '.jpeg', '.svg', '.gif'].includes(ext)) { await this.processImageFile(file, relativePath); } } } async processHtmlFile(file, relativePath) { const content = fs.readFileSync(file, 'utf-8'); const pageName = path.basename(relativePath, '.html'); // Extract CSS and JS references const cssMatches = content.match(/]*href="([^"]*\.css)"[^>]*>/g) || []; const jsMatches = content.match(/]*src="([^"]*\.js)"[^>]*>/g) || []; const assets = { css: cssMatches.map(match => { const href = match.match(/href="([^"]*)"/)[1]; return href.startsWith('./') ? href.substring(2) : href; }), js: jsMatches.map(match => { const src = match.match(/src="([^"]*)"/)[1]; return src.startsWith('./') ? src.substring(2) : src; }), html: relativePath }; this.manifest[pageName] = assets; // Copy HTML file to admin templates const templateDir = path.join(this.wpAdminDir, 'templates'); if (!fs.existsSync(templateDir)) { fs.mkdirSync(templateDir, { recursive: true }); } const destPath = path.join(templateDir, `${pageName}.html`); fs.copyFileSync(file, destPath); this.stats.filesCopied++; } async processJsFile(file, relativePath) { const destPath = path.join(this.wpAdminDir, relativePath); const destDir = path.dirname(destPath); if (!fs.existsSync(destDir)) { fs.mkdirSync(destDir, { recursive: true }); } // Process JavaScript for WordPress compatibility let content = fs.readFileSync(file, 'utf-8'); // Replace placeholder variables with WordPress equivalents content = content.replace(/__WP_NONCE__/g, 'window.tigerStyleLife9.nonce'); content = content.replace(/__WP_AJAX_URL__/g, 'window.tigerStyleLife9.ajaxUrl'); content = content.replace(/__WP_REST_URL__/g, 'window.tigerStyleLife9.restUrl'); content = content.replace(/__PLUGIN_URL__/g, 'window.tigerStyleLife9.pluginUrl'); fs.writeFileSync(destPath, content); this.stats.filesCopied++; } async processCssFile(file, relativePath) { const destPath = path.join(this.wpAdminDir, relativePath); const destDir = path.dirname(destPath); if (!fs.existsSync(destDir)) { fs.mkdirSync(destDir, { recursive: true }); } // Process CSS for WordPress admin compatibility let content = fs.readFileSync(file, 'utf-8'); // Ensure all styles are scoped to plugin container if (!content.includes('.tigerstyle-life9-container')) { console.warn(`CSS file ${relativePath} may not be properly scoped`); } fs.writeFileSync(destPath, content); this.stats.filesCopied++; } async processImageFile(file, relativePath) { const destPath = path.join(this.wpAdminDir, relativePath); const destDir = path.dirname(destPath); if (!fs.existsSync(destDir)) { fs.mkdirSync(destDir, { recursive: true }); } fs.copyFileSync(file, destPath); this.stats.filesCopied++; } async generateManifest() { // Generate PHP manifest file const phpManifest = this.generatePhpManifest(); const manifestPath = path.join(this.wpAdminDir, 'assets-manifest.php'); fs.writeFileSync(manifestPath, phpManifest); // Generate JSON manifest for development const jsonManifest = JSON.stringify(this.manifest, null, 2); const jsonPath = path.join(this.wpAdminDir, 'assets-manifest.json'); fs.writeFileSync(jsonPath, jsonManifest); console.log(`📝 Generated manifest with ${Object.keys(this.manifest).length} pages`); } generatePhpManifest() { return ` `${spaces} ${this.phpStringify(item, indent + 1)}` ).join(',\n'); return `[\n${items}\n${spaces}]`; } if (typeof obj === 'object' && obj !== null) { const keys = Object.keys(obj); if (keys.length === 0) return '[]'; const items = keys.map(key => `${spaces} '${key}' => ${this.phpStringify(obj[key], indent + 1)}` ).join(',\n'); return `[\n${items}\n${spaces}]`; } if (typeof obj === 'string') { return `'${obj.replace(/'/g, "\\'")}'`; } if (typeof obj === 'boolean') { return obj ? 'true' : 'false'; } if (typeof obj === 'number') { return obj.toString(); } return 'null'; } async copyStaticAssets() { const publicDir = path.join(this.projectRoot, 'src/astro/public'); if (fs.existsSync(publicDir)) { const files = await this.getAllFiles(publicDir); for (const file of files) { const relativePath = path.relative(publicDir, file); const destPath = path.join(this.wpAdminDir, 'static', relativePath); const destDir = path.dirname(destPath); if (!fs.existsSync(destDir)) { fs.mkdirSync(destDir, { recursive: true }); } fs.copyFileSync(file, destPath); this.stats.filesCopied++; } } } async generateAssetLoader() { const loaderContent = ` $css_file) { wp_enqueue_style( "tigerstyle-life9-{$page_name}-{$index}", $plugin_url . 'admin/' . $css_file, [], TIGERSTYLE_LIFE9_VERSION ); } } // Enqueue JavaScript files if (!empty($assets['js'])) { foreach ($assets['js'] as $index => $js_file) { $handle = "tigerstyle-life9-{$page_name}-{$index}"; wp_enqueue_script( $handle, $plugin_url . 'admin/' . $js_file, ['jquery', 'wp-api'], TIGERSTYLE_LIFE9_VERSION, true ); // Localize script data on the first JS file if ($index === 0) { $localize_data = array_merge([ 'nonce' => wp_create_nonce('tigerstyle_life9_nonce'), 'ajaxUrl' => admin_url('admin-ajax.php'), 'restUrl' => rest_url('tigerstyle-life9/v1/'), 'pluginUrl' => $plugin_url, 'currentUser' => get_current_user_id(), 'capabilities' => [ 'manage_backups' => current_user_can('manage_options'), 'download_backups' => current_user_can('manage_options') ], 'strings' => [ 'backupStarted' => __('Backup Started', 'tigerstyle-life9'), 'backupComplete' => __('Backup Complete', 'tigerstyle-life9'), 'error' => __('Error', 'tigerstyle-life9'), 'confirm' => __('Are you sure?', 'tigerstyle-life9') ] ], $extra_data); wp_localize_script($handle, 'tigerStyleLife9', $localize_data); } } } return true; }`; const loaderPath = path.join(this.wpAdminDir, 'asset-loader.php'); fs.writeFileSync(loaderPath, loaderContent); console.log('🔧 Generated WordPress asset loader'); } async getAllFiles(dir) { const files = []; const entries = fs.readdirSync(dir, { withFileTypes: true }); for (const entry of entries) { const fullPath = path.join(dir, entry.name); if (entry.isDirectory()) { files.push(...await this.getAllFiles(fullPath)); } else { files.push(fullPath); } } return files; } } // Run the copier const copier = new WordPressAssetCopier(); copier.run().catch(console.error);