|
| 1 | +import chalk from 'chalk'; |
| 2 | + |
| 3 | +import prompts from 'prompts'; |
| 4 | +import { spawn } from 'node:child_process'; |
| 5 | +import fs from 'node:fs/promises'; |
| 6 | +import path from 'node:path'; |
| 7 | +import { fileURLToPath } from 'node:url'; |
| 8 | + |
| 9 | +const __filename = fileURLToPath(import.meta.url); |
| 10 | +const __dirname = path.dirname(__filename); |
| 11 | + |
| 12 | +const projectDir = path.resolve(__dirname + '/../'); |
| 13 | +const themesDir = path.resolve(projectDir + '/src/lib/themes'); |
| 14 | +const carbonDir = path.resolve(themesDir + '/svelte/carbon'); |
| 15 | + |
| 16 | +// |
| 17 | +// main |
| 18 | +// |
| 19 | +(async () => { |
| 20 | + let themeType = ((process.argv[2] || '').trim() || await ask('Theme type? (svelte, react, vue)')).toLowerCase(); |
| 21 | + let themeName = ((process.argv[3] || '').trim() || await ask('What is the name of your new theme? (only lowercase letters and underscores)')).toLowerCase(); |
| 22 | + |
| 23 | + if (!themeName) { |
| 24 | + throw new Error('No theme name provided.'); |
| 25 | + } |
| 26 | + |
| 27 | + if (!themeType) { |
| 28 | + throw new Error('No theme type provided. Allowed: svelte, react, vue'); |
| 29 | + } |
| 30 | + if (!themeType.match(/^svelte|react|vue$/gi)) { |
| 31 | + throw new Error('Wrong template type provided. Allowed: svelte, react, vue'); |
| 32 | + } |
| 33 | + |
| 34 | + const newThemePath = carbonDir.replace(/\\/g, '/').replace(/\/svelte\/carbon$/g, `/${themeType}/${themeName}`).replace(/\//g, path.sep); |
| 35 | + |
| 36 | + const files = (await getAllFiles(carbonDir)); |
| 37 | + |
| 38 | + for (const file of files) { |
| 39 | + if (!file.match(/\.svelte$/gi)) { |
| 40 | + continue; |
| 41 | + } |
| 42 | + const newPath = path.resolve(file.replace(carbonDir, newThemePath)); |
| 43 | + const basename = newPath.replace(projectDir + path.sep, '').replace(new RegExp('\\\\', 'g'), '/'); |
| 44 | + const dir = path.dirname(newPath); |
| 45 | + await fs.mkdir(dir, {recursive: true}); |
| 46 | + await fs.writeFile(newPath, `TODO: Implement template "${basename}" for "${themeType}/${themeName}" theme.\n`); |
| 47 | + } |
| 48 | + |
| 49 | + await fs.copyFile(carbonDir+'/index.ts', newThemePath+'/index.ts'); |
| 50 | + |
| 51 | + const themesIndex = themesDir+'/'+themeType+'/index.ts'; |
| 52 | + let indexContent = (await fs.readFile(themesIndex)).toString(); |
| 53 | + if (!indexContent.match(new RegExp(`export *\\{ *default as ${themeName}`), 'gi')) { |
| 54 | + indexContent += `\nexport { default as ${themeName} } from './${themeName}';` |
| 55 | + } |
| 56 | + indexContent = indexContent.replace(/\n\n+/, "\n").trim()+"\n"; |
| 57 | + await fs.writeFile(themesIndex, indexContent); |
| 58 | +})(); |
| 59 | + |
| 60 | +async function ask(question) { |
| 61 | + let value = ''; |
| 62 | + |
| 63 | + const max = 3; |
| 64 | + let i = 0; |
| 65 | + while (!value || !value.trim()) { |
| 66 | + if (i >= max) { |
| 67 | + process.stderr.write(' [ERROR] No answer. Stopping.\n'); |
| 68 | + process.exit(1); |
| 69 | + } |
| 70 | + |
| 71 | + const answer = await prompts({ |
| 72 | + type: 'text', |
| 73 | + name: 'answer', |
| 74 | + message: question |
| 75 | + }); |
| 76 | + |
| 77 | + value = (answer.answer || '').trim(); |
| 78 | + |
| 79 | + i++; |
| 80 | + } |
| 81 | + |
| 82 | + return value; |
| 83 | +} |
| 84 | + |
| 85 | +async function getAllFiles(dirPath, arrayOfFiles = []) { |
| 86 | + const files = await fs.readdir(dirPath) |
| 87 | + |
| 88 | + arrayOfFiles = arrayOfFiles || [] |
| 89 | + |
| 90 | + for (const file of files) { |
| 91 | + const stat = await fs.stat(dirPath + path.sep + file); |
| 92 | + if (stat.isDirectory()) { |
| 93 | + arrayOfFiles = await getAllFiles(dirPath + path.sep + file, arrayOfFiles) |
| 94 | + } else { |
| 95 | + arrayOfFiles.push(path.join(dirPath, path.sep, file)) |
| 96 | + } |
| 97 | + } |
| 98 | + |
| 99 | + return arrayOfFiles |
| 100 | +} |
0 commit comments