tailjng 0.1.0 → 0.1.1
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.
- package/README.md +3 -2
- package/cli/execute/init-app.js +38 -5
- package/cli/settings/project-utils.js +70 -0
- package/package.json +1 -1
- package/tailjng-0.1.1.tgz +0 -0
- package/tailjng-0.1.0.tgz +0 -0
package/README.md
CHANGED
|
@@ -41,9 +41,10 @@ El CLI instala **dependencias transitivas** automáticamente (ej. `button` → `
|
|
|
41
41
|
|
|
42
42
|
## Requisitos
|
|
43
43
|
|
|
44
|
-
- Angular **19.2+**
|
|
45
|
-
- Tailwind CSS **4.x**
|
|
44
|
+
- Angular **19.2+** (19.x dentro del mismo major; no Angular 20/21 aún)
|
|
45
|
+
- Tailwind CSS **4.x** (incluido si eliges Tailwind al crear el proyecto con `ng new`)
|
|
46
46
|
- Peers: `lucide-angular`, `date-fns`, `exceljs`, `xlsx` (el CLI los instala con `init:app` si faltan)
|
|
47
|
+
- Estilos globales en **CSS o SCSS** — `init:app` detecta cuál usa tu app
|
|
47
48
|
|
|
48
49
|
---
|
|
49
50
|
|
package/cli/execute/init-app.js
CHANGED
|
@@ -20,11 +20,13 @@ const {
|
|
|
20
20
|
patchAppConfig,
|
|
21
21
|
patchAppComponentForAlerts,
|
|
22
22
|
getMissingPackages,
|
|
23
|
+
resolveRuntimePackages,
|
|
24
|
+
resolveDevPackages,
|
|
25
|
+
hasTailwindSetup,
|
|
23
26
|
fileExists,
|
|
24
27
|
} = require('../settings/project-utils');
|
|
25
28
|
|
|
26
29
|
const RUNTIME_PACKAGES = {
|
|
27
|
-
'@angular/animations': '^19.2.0',
|
|
28
30
|
'lucide-angular': '^0.525.0',
|
|
29
31
|
'@ng-icons/lucide': '>=32.0.0',
|
|
30
32
|
'date-fns': '^4.1.0',
|
|
@@ -82,10 +84,19 @@ function installPackages(workspaceRoot, packages, isDev = false) {
|
|
|
82
84
|
const flag = isDev ? '--save-dev' : '--save';
|
|
83
85
|
console.log(`${COLORS.blue}[tailjng CLI] Installing ${isDev ? 'dev ' : ''}dependencies...${COLORS.reset}`);
|
|
84
86
|
|
|
87
|
+
const run = (extra = '') => {
|
|
88
|
+
execSync(`npm install ${flag} ${extra} ${spec}`.replace(/\s+/g, ' ').trim(), {
|
|
89
|
+
cwd: workspaceRoot,
|
|
90
|
+
stdio: 'inherit',
|
|
91
|
+
shell: true,
|
|
92
|
+
});
|
|
93
|
+
};
|
|
94
|
+
|
|
85
95
|
try {
|
|
86
|
-
|
|
96
|
+
run();
|
|
87
97
|
} catch {
|
|
88
|
-
|
|
98
|
+
console.log(`${COLORS.yellow}[tailjng CLI] Retrying with --legacy-peer-deps...${COLORS.reset}`);
|
|
99
|
+
run('--legacy-peer-deps');
|
|
89
100
|
}
|
|
90
101
|
}
|
|
91
102
|
|
|
@@ -158,6 +169,7 @@ async function runInitApp() {
|
|
|
158
169
|
|
|
159
170
|
const packageJsonPath = path.join(workspaceRoot, 'package.json');
|
|
160
171
|
const packageJson = fileExists(packageJsonPath) ? readJson(packageJsonPath) : { dependencies: {}, devDependencies: {} };
|
|
172
|
+
const tailwindReady = hasTailwindSetup(workspaceRoot, packageJson, primaryStylePath);
|
|
161
173
|
|
|
162
174
|
if (!packageJson.dependencies?.tailjng) {
|
|
163
175
|
console.log(`${COLORS.yellow}[tailjng CLI] WARNING: tailjng is not in package.json dependencies.${COLORS.reset}`);
|
|
@@ -165,8 +177,19 @@ async function runInitApp() {
|
|
|
165
177
|
}
|
|
166
178
|
|
|
167
179
|
if (installDeps) {
|
|
168
|
-
|
|
169
|
-
|
|
180
|
+
if (tailwindReady) {
|
|
181
|
+
console.log(`${COLORS.cyan}[tailjng CLI] Tailwind already configured — skipping Tailwind/PostCSS packages and .postcssrc.json${COLORS.reset}`);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
const runtimePackages = resolveRuntimePackages(packageJson, RUNTIME_PACKAGES);
|
|
185
|
+
const devPackages = resolveDevPackages(packageJson, DEV_PACKAGES, tailwindReady);
|
|
186
|
+
const missingRuntime = Object.fromEntries(getMissingPackages(packageJson, runtimePackages));
|
|
187
|
+
const missingDev = Object.fromEntries(getMissingPackages(packageJson, devPackages));
|
|
188
|
+
|
|
189
|
+
if (missingRuntime['@angular/animations']) {
|
|
190
|
+
console.log(`${COLORS.dim}[tailjng CLI] Adding @angular/animations aligned with @angular/core${COLORS.reset}`);
|
|
191
|
+
}
|
|
192
|
+
|
|
170
193
|
installPackages(workspaceRoot, missingRuntime, false);
|
|
171
194
|
installPackages(workspaceRoot, missingDev, true);
|
|
172
195
|
}
|
|
@@ -192,6 +215,12 @@ async function runInitApp() {
|
|
|
192
215
|
}
|
|
193
216
|
|
|
194
217
|
for (const file of files) {
|
|
218
|
+
if (tailwindReady && file.relativePath === '.postcssrc.json') {
|
|
219
|
+
skipped += 1;
|
|
220
|
+
console.log(`${COLORS.yellow}↷ Skipped (Tailwind already configured) ${file.relativePath}${COLORS.reset}`);
|
|
221
|
+
continue;
|
|
222
|
+
}
|
|
223
|
+
|
|
195
224
|
const targetPath = resolveTargetPath(workspaceRoot, selectedApp, file.relativePath, file.appRootRelative);
|
|
196
225
|
const isPrimaryStyles = file.relativePath === primaryStylePath;
|
|
197
226
|
const forceWrite = isPrimaryStyles && shouldWriteStyles(targetPath);
|
|
@@ -236,6 +265,10 @@ async function runInitApp() {
|
|
|
236
265
|
}
|
|
237
266
|
}
|
|
238
267
|
|
|
268
|
+
if (tailwindReady && !shouldWriteStyles(path.join(workspaceRoot, primaryStylePath))) {
|
|
269
|
+
console.log(`${COLORS.yellow}[tailjng CLI] Tip: add tailjng @theme tokens to your existing styles if components look unstyled.${COLORS.reset}`);
|
|
270
|
+
}
|
|
271
|
+
|
|
239
272
|
console.log(`\n${COLORS.greenBright}${COLORS.bright}[tailjng CLI] init:app completed.${COLORS.reset}`);
|
|
240
273
|
console.log(`${COLORS.dim}Created: ${created} | Skipped: ${skipped}${COLORS.reset}`);
|
|
241
274
|
console.log(`\n${COLORS.cyan}Project ready. Install components when you need them:${COLORS.reset}`);
|
|
@@ -201,6 +201,72 @@ function getMissingPackages(packageJson, packages) {
|
|
|
201
201
|
return Object.entries(packages).filter(([name]) => !deps[name]);
|
|
202
202
|
}
|
|
203
203
|
|
|
204
|
+
function getMergedDependencies(packageJson) {
|
|
205
|
+
return { ...packageJson.dependencies, ...packageJson.devDependencies };
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/** Alinea @angular/animations con la línea de @angular/core del proyecto (evita ERESOLVE 19.2.0 vs 19.2.25). */
|
|
209
|
+
function resolveRuntimePackages(packageJson, basePackages) {
|
|
210
|
+
const packages = { ...basePackages };
|
|
211
|
+
const deps = getMergedDependencies(packageJson);
|
|
212
|
+
|
|
213
|
+
if (deps['@angular/animations']) {
|
|
214
|
+
delete packages['@angular/animations'];
|
|
215
|
+
} else if (deps['@angular/core']) {
|
|
216
|
+
packages['@angular/animations'] = deps['@angular/core'];
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
return packages;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
function resolveDevPackages(packageJson, basePackages, tailwindReady) {
|
|
223
|
+
const packages = { ...basePackages };
|
|
224
|
+
if (!tailwindReady) return packages;
|
|
225
|
+
|
|
226
|
+
for (const name of ['tailwindcss', '@tailwindcss/postcss', 'postcss', 'autoprefixer']) {
|
|
227
|
+
if (getMergedDependencies(packageJson)[name]) {
|
|
228
|
+
delete packages[name];
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
return packages;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
function hasTailwindSetup(workspaceRoot, packageJson, primaryStylePath) {
|
|
235
|
+
const deps = getMergedDependencies(packageJson);
|
|
236
|
+
if (deps.tailwindcss || deps['@tailwindcss/postcss']) {
|
|
237
|
+
return true;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
const postcssConfigs = [
|
|
241
|
+
'.postcssrc.json',
|
|
242
|
+
'postcss.config.js',
|
|
243
|
+
'postcss.config.mjs',
|
|
244
|
+
'postcss.config.cjs',
|
|
245
|
+
];
|
|
246
|
+
|
|
247
|
+
for (const configName of postcssConfigs) {
|
|
248
|
+
const configPath = path.join(workspaceRoot, configName);
|
|
249
|
+
if (!fs.existsSync(configPath)) continue;
|
|
250
|
+
const content = fs.readFileSync(configPath, 'utf8');
|
|
251
|
+
if (/tailwindcss|@tailwindcss\/postcss/.test(content)) {
|
|
252
|
+
return true;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
const stylePath = path.isAbsolute(primaryStylePath)
|
|
257
|
+
? primaryStylePath
|
|
258
|
+
: path.join(workspaceRoot, primaryStylePath);
|
|
259
|
+
|
|
260
|
+
if (fs.existsSync(stylePath)) {
|
|
261
|
+
const content = fs.readFileSync(stylePath, 'utf8');
|
|
262
|
+
if (/tailwindcss/.test(content)) {
|
|
263
|
+
return true;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
return false;
|
|
268
|
+
}
|
|
269
|
+
|
|
204
270
|
module.exports = {
|
|
205
271
|
findAngularWorkspace,
|
|
206
272
|
readJson,
|
|
@@ -216,5 +282,9 @@ module.exports = {
|
|
|
216
282
|
patchAppConfig,
|
|
217
283
|
patchAppComponentForAlerts,
|
|
218
284
|
getMissingPackages,
|
|
285
|
+
getMergedDependencies,
|
|
286
|
+
resolveRuntimePackages,
|
|
287
|
+
resolveDevPackages,
|
|
288
|
+
hasTailwindSetup,
|
|
219
289
|
fileExists,
|
|
220
290
|
};
|
package/package.json
CHANGED
|
Binary file
|
package/tailjng-0.1.0.tgz
DELETED
|
Binary file
|