From 152b25e620627e3a178c7772025cf60dd1764ddb Mon Sep 17 00:00:00 2001 From: Mehdi ZAYANI Date: Tue, 22 Jul 2025 18:13:50 +0200 Subject: [PATCH] fix(js-template): support JavaScript templates in project generation --- README.md | 2 +- src/generators/projectGenerator.js | 38 +++++++++------- src/index.js | 2 +- src/ui/cliWelcome.mjs | 2 +- src/utils/copyTemplateFiles.js | 30 ++++++++++--- templates/{ => js}/postcss.config.js | 0 .../src/components/Hero/Hero.jsx} | 0 .../src/components/Hero/index.jsx} | 0 templates/js/src/pages/_app.jsx | 5 +++ templates/js/src/pages/index.jsx | 9 ++++ templates/{ => js}/src/styles/global.css | 0 templates/{ => js}/tailwind.config.js | 0 templates/ts/postcss.config.js | 6 +++ templates/ts/src/components/Hero/Hero.tsx | 43 +++++++++++++++++++ templates/ts/src/components/Hero/index.tsx | 1 + templates/{ => ts}/src/pages/_app.tsx | 0 templates/{ => ts}/src/pages/index.tsx | 0 templates/ts/src/styles/global.css | 11 +++++ templates/ts/tailwind.config.js | 25 +++++++++++ 19 files changed, 149 insertions(+), 25 deletions(-) rename templates/{ => js}/postcss.config.js (100%) rename templates/{src/components/Hero/Hero.tsx => js/src/components/Hero/Hero.jsx} (100%) rename templates/{src/components/Hero/index.tsx => js/src/components/Hero/index.jsx} (100%) create mode 100644 templates/js/src/pages/_app.jsx create mode 100644 templates/js/src/pages/index.jsx rename templates/{ => js}/src/styles/global.css (100%) rename templates/{ => js}/tailwind.config.js (100%) create mode 100644 templates/ts/postcss.config.js create mode 100644 templates/ts/src/components/Hero/Hero.tsx create mode 100644 templates/ts/src/components/Hero/index.tsx rename templates/{ => ts}/src/pages/_app.tsx (100%) rename templates/{ => ts}/src/pages/index.tsx (100%) create mode 100644 templates/ts/src/styles/global.css create mode 100644 templates/ts/tailwind.config.js diff --git a/README.md b/README.md index bfeb2f5..9875173 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ ![CI](https://github.com/msz-tech/create-nexter/actions/workflows/ci.yaml/badge.svg?branch=main&style=flat-square) -![npm version](https://img.shields.io/npm/v/create-nexter) +[![npm version](https://img.shields.io/npm/v/create-nexter?style=flat-square)](https://www.npmjs.com/package/create-nexter) [![MIT License](https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square)](LICENSE) ## Table of Contents diff --git a/src/generators/projectGenerator.js b/src/generators/projectGenerator.js index 9f7b9c6..7af15a1 100644 --- a/src/generators/projectGenerator.js +++ b/src/generators/projectGenerator.js @@ -1,17 +1,16 @@ import path from 'path'; -import { fileURLToPath } from 'url'; import spawn from 'cross-spawn'; +import { copyTemplateFiles } from '../utils/copyTemplateFiles.js'; -// Pour __dirname avec ESModules -const __dirname = path.dirname(fileURLToPath(import.meta.url)); export default function generateProject(language, projectName) { return new Promise((resolve, reject) => { + const args = [ 'create-next-app@15.4.1', projectName, language === 'ts' ? '--typescript' : '--javascript', - '--no-tailwind', // Ne pas installer tailwind par défaut + '--no-tailwind', '--eslint', '--src-dir', '--no-app', @@ -20,6 +19,8 @@ export default function generateProject(language, projectName) { '--yes', ]; + console.log(`🚀 Creating Next.js project (${language}) named '${projectName}'...`); + const cmd = 'npx'; const child = spawn(cmd, args, { stdio: 'inherit' }); @@ -30,25 +31,30 @@ export default function generateProject(language, projectName) { console.log('📦 Installing TailwindCSS and PostCSS plugins...'); - // Installer tailwindcss + plugins PostCSS obligatoires - const extraDeps = [ - 'tailwindcss@3.3.2', - 'postcss@8.4.21', - 'autoprefixer@10.4.14', - 'lucide-react' - ]; + const extraDeps = [ + 'tailwindcss@3.3.2', + 'postcss@8.4.21', + 'autoprefixer@10.4.14', + 'lucide-react', + ]; const install = spawn('npm', ['install', '-D', ...extraDeps], { cwd: path.resolve(projectName), stdio: 'inherit', }); - install.on('close', (installCode) => { - if (installCode === 0) { - console.log('✅ TailwindCSS and PostCSS plugins installed.'); + install.on('close', async (installCode) => { + if (installCode !== 0) { + return reject(new Error('❌ Failed to install TailwindCSS/PostCSS plugins.')); + } + + try { + console.log(`📁 Copying template files for language: ${language}...`); + await copyTemplateFiles(path.resolve(projectName), language); + console.log('✅ Project generation complete!'); resolve(); - } else { - reject(new Error('❌ Failed to install TailwindCSS/PostCSS plugins.')); + } catch (error) { + reject(new Error(`❌ Error copying template files: ${error.message}`)); } }); }); diff --git a/src/index.js b/src/index.js index 964a6a4..2862ade 100644 --- a/src/index.js +++ b/src/index.js @@ -22,7 +22,7 @@ export default async function main() { await cleanProject(projectName, language); - await copyTemplateFiles(projectName); + await copyTemplateFiles(projectName, language); diff --git a/src/ui/cliWelcome.mjs b/src/ui/cliWelcome.mjs index 622eb3b..7d69366 100644 --- a/src/ui/cliWelcome.mjs +++ b/src/ui/cliWelcome.mjs @@ -13,5 +13,5 @@ export function displayWelcome() { console.log(gradient.pastel.multiline(msg)); console.log(chalk.cyanBright('Welcome to create-nexter CLI!\n')); -console.log(chalk.white('Effortless Next.js project scaffolding, built for scalable and maintainable applications.\n')); + console.log(chalk.white('Effortless Next.js project scaffolding, built for scalable and maintainable applications.\n')); } diff --git a/src/utils/copyTemplateFiles.js b/src/utils/copyTemplateFiles.js index 9ca6a7f..18af14c 100644 --- a/src/utils/copyTemplateFiles.js +++ b/src/utils/copyTemplateFiles.js @@ -1,20 +1,38 @@ import path from 'path'; import fsExtra from 'fs-extra'; -const { copy, readdir } = fsExtra; +const { copy, readdir, pathExists } = fsExtra; import { fileURLToPath } from 'url'; const __dirname = path.dirname(fileURLToPath(import.meta.url)); -export async function copyTemplateFiles(targetDir) { - const templateDir = path.join(__dirname, '../../templates'); - console.log('Template dir:', templateDir); - console.log('Target dir:', targetDir); +/** + * Copy template files based on the selected language (ts or js) + * @param {string} targetDir - The directory where the template files will be copied + * @param {string} language - 'ts' or 'js' to select the appropriate template folder + */ +export async function copyTemplateFiles(targetDir, language) { + if (!['ts', 'js'].includes(language)) { + throw new Error(`Invalid language '${language}'. Expected 'ts' or 'js'.`); + } + + const templateDir = path.join(__dirname, '../../templates', language); + + const exists = await pathExists(templateDir); + if (!exists) { + throw new Error(`Template directory does not exist: ${templateDir}`); + } + + console.log(`[copyTemplateFiles] Copying template for language: ${language}`); + console.log(`[copyTemplateFiles] From: ${templateDir}`); + console.log(`[copyTemplateFiles] To: ${targetDir}`); const files = await readdir(templateDir); - console.log('Files in templateDir:', files); + console.log(`[copyTemplateFiles] Files to copy: ${files.join(', ')}`); await copy(templateDir, targetDir, { overwrite: true, recursive: true, }); + + console.log(`[copyTemplateFiles] Copy completed successfully.`); } diff --git a/templates/postcss.config.js b/templates/js/postcss.config.js similarity index 100% rename from templates/postcss.config.js rename to templates/js/postcss.config.js diff --git a/templates/src/components/Hero/Hero.tsx b/templates/js/src/components/Hero/Hero.jsx similarity index 100% rename from templates/src/components/Hero/Hero.tsx rename to templates/js/src/components/Hero/Hero.jsx diff --git a/templates/src/components/Hero/index.tsx b/templates/js/src/components/Hero/index.jsx similarity index 100% rename from templates/src/components/Hero/index.tsx rename to templates/js/src/components/Hero/index.jsx diff --git a/templates/js/src/pages/_app.jsx b/templates/js/src/pages/_app.jsx new file mode 100644 index 0000000..d7109cf --- /dev/null +++ b/templates/js/src/pages/_app.jsx @@ -0,0 +1,5 @@ +import "../styles/global.css"; + +export default function App({ Component, pageProps }) { + return ; +} diff --git a/templates/js/src/pages/index.jsx b/templates/js/src/pages/index.jsx new file mode 100644 index 0000000..208f731 --- /dev/null +++ b/templates/js/src/pages/index.jsx @@ -0,0 +1,9 @@ +import { Hero } from "../components/Hero"; + +export default function Home() { + return ( +
+ +
+ ); +} diff --git a/templates/src/styles/global.css b/templates/js/src/styles/global.css similarity index 100% rename from templates/src/styles/global.css rename to templates/js/src/styles/global.css diff --git a/templates/tailwind.config.js b/templates/js/tailwind.config.js similarity index 100% rename from templates/tailwind.config.js rename to templates/js/tailwind.config.js diff --git a/templates/ts/postcss.config.js b/templates/ts/postcss.config.js new file mode 100644 index 0000000..a1b36d2 --- /dev/null +++ b/templates/ts/postcss.config.js @@ -0,0 +1,6 @@ +module.exports = { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +}; diff --git a/templates/ts/src/components/Hero/Hero.tsx b/templates/ts/src/components/Hero/Hero.tsx new file mode 100644 index 0000000..b1de566 --- /dev/null +++ b/templates/ts/src/components/Hero/Hero.tsx @@ -0,0 +1,43 @@ +import { Github, BookOpen } from "lucide-react"; + +export default function Hero() { + return ( +
+ {/* Background Blur Circles */} +
+
+ + {/* Main Content */} +
+
+ NX +
+ +

+ Create Nexter +

+ +

+ Kickstart your next project with Next.js 15 and Tailwind CSS 3.3.2. No config, just code. +

+ +
+ + + Get Started + + + + View on GitHub + +
+
+
+ ); +} diff --git a/templates/ts/src/components/Hero/index.tsx b/templates/ts/src/components/Hero/index.tsx new file mode 100644 index 0000000..6d8d5f2 --- /dev/null +++ b/templates/ts/src/components/Hero/index.tsx @@ -0,0 +1 @@ +export { default as Hero } from './Hero'; diff --git a/templates/src/pages/_app.tsx b/templates/ts/src/pages/_app.tsx similarity index 100% rename from templates/src/pages/_app.tsx rename to templates/ts/src/pages/_app.tsx diff --git a/templates/src/pages/index.tsx b/templates/ts/src/pages/index.tsx similarity index 100% rename from templates/src/pages/index.tsx rename to templates/ts/src/pages/index.tsx diff --git a/templates/ts/src/styles/global.css b/templates/ts/src/styles/global.css new file mode 100644 index 0000000..f2ea320 --- /dev/null +++ b/templates/ts/src/styles/global.css @@ -0,0 +1,11 @@ +/* Import Google Fonts Poppins */ +@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;600&display=swap'); + +@tailwind base; +@tailwind components; +@tailwind utilities; + + +body { + font-family: 'Poppins', ui-sans-serif, system-ui, sans-serif; +} diff --git a/templates/ts/tailwind.config.js b/templates/ts/tailwind.config.js new file mode 100644 index 0000000..66a186f --- /dev/null +++ b/templates/ts/tailwind.config.js @@ -0,0 +1,25 @@ +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: [ + "./src/pages/**/*.{js,ts,jsx,tsx}", + "./src/components/**/*.{js,ts,jsx,tsx}", + ], + theme: { + extend: { + colors: { + primary: { + light: '#E0F2FE', + dark: '#0F172A', + accent: '#38BDF8', + }, + }, + backgroundImage: { + 'hero-gradient': 'linear-gradient(135deg, #e0f2fe 0%, #bae6fd 50%, #f0f9ff 100%)', + }, + fontFamily: { + sans: ['Poppins', 'ui-sans-serif', 'system-ui'], + }, + }, + }, + plugins: [], +};