vtex-css-sanitizer-cli 1.0.2 → 1.0.5
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/.github/workflows/release.yml +75 -0
- package/dist/commands/fix.js +17 -9
- package/dist/utils/file-finder.js +8 -2
- package/docs/assets/cli-mockup.png +0 -0
- package/docs/assets/gui-mockup.png +0 -0
- package/docs/favicon.svg +5 -0
- package/docs/index.html +336 -0
- package/docs/script.js +64 -0
- package/docs/styles.css +745 -0
- package/gui/electron-builder.yml +24 -0
- package/gui/electron.vite.config.ts +21 -0
- package/gui/out/main/index.js +536 -0
- package/gui/out/preload/index.js +98 -0
- package/gui/out/renderer/assets/index-B4Zg_1V2.js +7540 -0
- package/gui/out/renderer/assets/index-BUoLJXor.css +1320 -0
- package/gui/out/renderer/index.html +13 -0
- package/gui/package.json +40 -0
- package/gui/tsconfig.node.json +26 -0
- package/gui/tsconfig.web.json +30 -0
- package/gui/yarn.lock +3574 -0
- package/package.json +2 -2
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# Workflow: Build & Release
|
|
2
|
+
# Se dispara cuando se hace push de un tag con formato v*.*.*
|
|
3
|
+
# Compila la GUI para Windows y Linux y crea un GitHub Release con los binarios.
|
|
4
|
+
|
|
5
|
+
name: Build & Release
|
|
6
|
+
|
|
7
|
+
on:
|
|
8
|
+
push:
|
|
9
|
+
tags:
|
|
10
|
+
- 'v*.*.*'
|
|
11
|
+
|
|
12
|
+
permissions:
|
|
13
|
+
contents: write
|
|
14
|
+
|
|
15
|
+
jobs:
|
|
16
|
+
build:
|
|
17
|
+
strategy:
|
|
18
|
+
matrix:
|
|
19
|
+
include:
|
|
20
|
+
- os: ubuntu-latest
|
|
21
|
+
platform: linux
|
|
22
|
+
build_script: build:linux
|
|
23
|
+
- os: windows-latest
|
|
24
|
+
platform: win
|
|
25
|
+
build_script: build:win
|
|
26
|
+
|
|
27
|
+
runs-on: ${{ matrix.os }}
|
|
28
|
+
|
|
29
|
+
steps:
|
|
30
|
+
- name: Checkout
|
|
31
|
+
uses: actions/checkout@v4
|
|
32
|
+
|
|
33
|
+
- name: Setup Node.js
|
|
34
|
+
uses: actions/setup-node@v4
|
|
35
|
+
with:
|
|
36
|
+
node-version: 20
|
|
37
|
+
|
|
38
|
+
- name: Install dependencies
|
|
39
|
+
working-directory: gui
|
|
40
|
+
run: yarn install --frozen-lockfile
|
|
41
|
+
|
|
42
|
+
- name: Build & Package
|
|
43
|
+
working-directory: gui
|
|
44
|
+
run: yarn ${{ matrix.build_script }}
|
|
45
|
+
|
|
46
|
+
- name: Upload artifacts
|
|
47
|
+
uses: actions/upload-artifact@v4
|
|
48
|
+
with:
|
|
49
|
+
name: release-${{ matrix.platform }}
|
|
50
|
+
path: |
|
|
51
|
+
gui/release/*.exe
|
|
52
|
+
gui/release/*.AppImage
|
|
53
|
+
if-no-files-found: warn
|
|
54
|
+
|
|
55
|
+
release:
|
|
56
|
+
needs: build
|
|
57
|
+
runs-on: ubuntu-latest
|
|
58
|
+
|
|
59
|
+
steps:
|
|
60
|
+
- name: Download all artifacts
|
|
61
|
+
uses: actions/download-artifact@v4
|
|
62
|
+
with:
|
|
63
|
+
path: artifacts
|
|
64
|
+
merge-multiple: true
|
|
65
|
+
|
|
66
|
+
- name: List artifacts
|
|
67
|
+
run: find artifacts -type f | head -20
|
|
68
|
+
|
|
69
|
+
- name: Create GitHub Release
|
|
70
|
+
uses: softprops/action-gh-release@v2
|
|
71
|
+
with:
|
|
72
|
+
generate_release_notes: true
|
|
73
|
+
files: |
|
|
74
|
+
artifacts/**/*.exe
|
|
75
|
+
artifacts/**/*.AppImage
|
package/dist/commands/fix.js
CHANGED
|
@@ -41,13 +41,16 @@ async function fixCommand(projectPath) {
|
|
|
41
41
|
if (candidates.length === 0) {
|
|
42
42
|
continue;
|
|
43
43
|
}
|
|
44
|
+
// Arreglos temporales para los cambios del archivo actual
|
|
45
|
+
const fileDeletedRules = [];
|
|
46
|
+
const fileKeptRules = [];
|
|
44
47
|
let rulesRemovedInFile = 0;
|
|
48
|
+
let userCancelled = false;
|
|
45
49
|
for (let i = 0; i < candidates.length; i++) {
|
|
46
50
|
const rule = candidates[i];
|
|
47
51
|
const relativePath = path_1.default.relative(projectPath, filePath);
|
|
48
52
|
const ruleAsString = rule.toString();
|
|
49
53
|
console.clear();
|
|
50
|
-
// Se muestra el progreso general y el del archivo actual
|
|
51
54
|
console.log(`[ Progreso: Archivo ${fileIndex + 1} de ${totalFiles} ]`);
|
|
52
55
|
console.log(`------------------------------------------------------------------`);
|
|
53
56
|
console.log(`Revisando Archivo: ${relativePath}`);
|
|
@@ -63,25 +66,28 @@ async function fixCommand(projectPath) {
|
|
|
63
66
|
});
|
|
64
67
|
if (response.shouldDelete === undefined) {
|
|
65
68
|
console.log('\n🛑 Proceso de limpieza cancelado por el usuario.');
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
await (0, report_generator_1.generateFixReport)(projectPath, deletedRules, keptRules);
|
|
69
|
-
console.log(`\n📄 Informe parcial de limpieza guardado.`);
|
|
70
|
-
}
|
|
71
|
-
return;
|
|
69
|
+
userCancelled = true;
|
|
70
|
+
break;
|
|
72
71
|
}
|
|
73
72
|
if (response.shouldDelete) {
|
|
73
|
+
fileDeletedRules.push({ rule: ruleAsString, filePath });
|
|
74
74
|
rule.remove();
|
|
75
75
|
rulesRemovedInFile++;
|
|
76
|
-
deletedRules.push({ rule: ruleAsString, filePath });
|
|
77
76
|
console.log('\x1b[31m%s\x1b[0m', '🗑️ Regla eliminada.');
|
|
78
77
|
}
|
|
79
78
|
else {
|
|
80
|
-
|
|
79
|
+
fileKeptRules.push({ rule: ruleAsString, filePath });
|
|
81
80
|
console.log('\x1b[32m%s\x1b[0m', '👍 Regla conservada.');
|
|
82
81
|
}
|
|
83
82
|
console.log('------------------------------------------------------------------');
|
|
84
83
|
}
|
|
84
|
+
if (userCancelled) {
|
|
85
|
+
if (deletedRules.length > 0 || keptRules.length > 0) {
|
|
86
|
+
await (0, report_generator_1.generateFixReport)(projectPath, deletedRules, keptRules);
|
|
87
|
+
console.log(`\n📄 Informe parcial de limpieza guardado con los cambios de los archivos **anteriores**.`);
|
|
88
|
+
}
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
85
91
|
if (rulesRemovedInFile > 0) {
|
|
86
92
|
const newContent = root.toString();
|
|
87
93
|
await promises_1.default.writeFile(filePath, newContent, 'utf-8');
|
|
@@ -89,6 +95,8 @@ async function fixCommand(projectPath) {
|
|
|
89
95
|
totalRulesRemoved += rulesRemovedInFile;
|
|
90
96
|
await (0, prompts_1.default)({ type: 'invisible', name: 'continue', message: 'Presiona Enter para continuar con el siguiente archivo...' });
|
|
91
97
|
}
|
|
98
|
+
deletedRules.push(...fileDeletedRules);
|
|
99
|
+
keptRules.push(...fileKeptRules);
|
|
92
100
|
}
|
|
93
101
|
console.clear();
|
|
94
102
|
if (totalRulesRemoved > 0) {
|
|
@@ -7,12 +7,18 @@ exports.findJsonFiles = findJsonFiles;
|
|
|
7
7
|
exports.findCssFiles = findCssFiles;
|
|
8
8
|
const glob_1 = require("glob");
|
|
9
9
|
const path_1 = __importDefault(require("path"));
|
|
10
|
+
/**
|
|
11
|
+
* Normaliza una ruta para que use forward slashes (/), requerido por glob en Windows.
|
|
12
|
+
*/
|
|
13
|
+
function toGlobPath(p) {
|
|
14
|
+
return p.split(path_1.default.sep).join('/');
|
|
15
|
+
}
|
|
10
16
|
/**
|
|
11
17
|
* Encuentra todos los archivos .json y .jsonc en la carpeta /store.
|
|
12
18
|
*/
|
|
13
19
|
function findJsonFiles(projectPath) {
|
|
14
20
|
const storePath = path_1.default.join(projectPath, 'store');
|
|
15
|
-
return (0, glob_1.sync)(`${storePath}/**/*.{json,jsonc}`);
|
|
21
|
+
return (0, glob_1.sync)(`${toGlobPath(storePath)}/**/*.{json,jsonc}`);
|
|
16
22
|
}
|
|
17
23
|
/**
|
|
18
24
|
* Encuentra todos los archivos .css DE APPS NATIVAS (vtex.*) en la carpeta /styles/css.
|
|
@@ -20,7 +26,7 @@ function findJsonFiles(projectPath) {
|
|
|
20
26
|
*/
|
|
21
27
|
function findCssFiles(projectPath) {
|
|
22
28
|
const stylesPath = path_1.default.join(projectPath, 'styles/css');
|
|
23
|
-
const allCssFiles = (0, glob_1.sync)(`${stylesPath}/**/*.css`);
|
|
29
|
+
const allCssFiles = (0, glob_1.sync)(`${toGlobPath(stylesPath)}/**/*.css`);
|
|
24
30
|
const nativeVtexCssFiles = allCssFiles.filter(filePath => {
|
|
25
31
|
const fileName = path_1.default.basename(filePath);
|
|
26
32
|
return fileName.startsWith('vtex.');
|
|
Binary file
|
|
Binary file
|
package/docs/favicon.svg
ADDED
package/docs/index.html
ADDED
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="es">
|
|
3
|
+
|
|
4
|
+
<head>
|
|
5
|
+
<meta charset="UTF-8">
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
7
|
+
<title>VTEX CSS Sanitizer — Limpiá tu CSS en VTEX IO</title>
|
|
8
|
+
<meta name="description"
|
|
9
|
+
content="Herramienta para detectar y eliminar CSS y blockClass no utilizados en proyectos VTEX IO. Disponible como CLI y aplicación de escritorio.">
|
|
10
|
+
<meta name="keywords" content="vtex, vtex io, css, sanitizer, cleanup, blockclass, developer tools">
|
|
11
|
+
<meta name="author" content="Elias Daniel Emanuele">
|
|
12
|
+
|
|
13
|
+
<!-- Open Graph -->
|
|
14
|
+
<meta property="og:title" content="VTEX CSS Sanitizer">
|
|
15
|
+
<meta property="og:description" content="Detectá y eliminá CSS y blockClass no utilizados en proyectos VTEX IO.">
|
|
16
|
+
<meta property="og:type" content="website">
|
|
17
|
+
<meta property="og:url" content="https://emanueleelias.github.io/vtex-css-sanitizer/">
|
|
18
|
+
|
|
19
|
+
<!-- Fonts -->
|
|
20
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
21
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
22
|
+
<link
|
|
23
|
+
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap"
|
|
24
|
+
rel="stylesheet">
|
|
25
|
+
|
|
26
|
+
<!-- Favicon -->
|
|
27
|
+
<link rel="icon" href="favicon.svg" type="image/svg+xml">
|
|
28
|
+
|
|
29
|
+
<link rel="stylesheet" href="styles.css">
|
|
30
|
+
</head>
|
|
31
|
+
|
|
32
|
+
<body>
|
|
33
|
+
<!-- ============ NAV ============ -->
|
|
34
|
+
<nav class="nav" id="nav">
|
|
35
|
+
<div class="nav__container">
|
|
36
|
+
<a href="#" class="nav__logo">
|
|
37
|
+
<svg class="nav__icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"
|
|
38
|
+
stroke-linecap="round" stroke-linejoin="round">
|
|
39
|
+
<path d="M12 2L2 7l10 5 10-5-10-5z" />
|
|
40
|
+
<path d="M2 17l10 5 10-5" />
|
|
41
|
+
<path d="M2 12l10 5 10-5" />
|
|
42
|
+
</svg>
|
|
43
|
+
<span>VTEX CSS Sanitizer</span>
|
|
44
|
+
</a>
|
|
45
|
+
<div class="nav__links">
|
|
46
|
+
<a href="#features">Features</a>
|
|
47
|
+
<a href="#versions">Versiones</a>
|
|
48
|
+
<a href="#downloads">Descargas</a>
|
|
49
|
+
<a href="https://github.com/emanueleelias/vtex-css-sanitizer" target="_blank" rel="noopener" class="nav__github"
|
|
50
|
+
aria-label="GitHub">
|
|
51
|
+
<svg viewBox="0 0 24 24" fill="currentColor" width="22" height="22">
|
|
52
|
+
<path
|
|
53
|
+
d="M12 0C5.37 0 0 5.37 0 12c0 5.31 3.435 9.795 8.205 11.385.6.105.825-.255.825-.57 0-.285-.015-1.23-.015-2.235-3.015.555-3.795-.735-4.035-1.41-.135-.345-.72-1.41-1.23-1.695-.42-.225-1.02-.78-.015-.795.945-.015 1.62.87 1.845 1.23 1.08 1.815 2.805 1.305 3.495.99.105-.78.42-1.305.765-1.605-2.67-.3-5.46-1.335-5.46-5.925 0-1.305.465-2.385 1.23-3.225-.12-.3-.54-1.53.12-3.18 0 0 1.005-.315 3.3 1.23.96-.27 1.98-.405 3-.405s2.04.135 3 .405c2.295-1.56 3.3-1.23 3.3-1.23.66 1.65.24 2.88.12 3.18.765.84 1.23 1.905 1.23 3.225 0 4.605-2.805 5.625-5.475 5.925.435.375.81 1.095.81 2.22 0 1.605-.015 2.895-.015 3.3 0 .315.225.69.825.57A12.02 12.02 0 0024 12c0-6.63-5.37-12-12-12z" />
|
|
54
|
+
</svg>
|
|
55
|
+
</a>
|
|
56
|
+
</div>
|
|
57
|
+
</div>
|
|
58
|
+
</nav>
|
|
59
|
+
|
|
60
|
+
<!-- ============ HERO ============ -->
|
|
61
|
+
<header class="hero" id="hero">
|
|
62
|
+
<div class="hero__glow"></div>
|
|
63
|
+
<div class="container">
|
|
64
|
+
<div class="hero__badges">
|
|
65
|
+
<a href="https://www.npmjs.com/package/vtex-css-sanitizer-cli" target="_blank" rel="noopener" class="badge">
|
|
66
|
+
<span class="badge__dot badge__dot--npm"></span>npm v1.0.3
|
|
67
|
+
</a>
|
|
68
|
+
<a href="https://github.com/emanueleelias/vtex-css-sanitizer" target="_blank" rel="noopener" class="badge">
|
|
69
|
+
<span class="badge__dot badge__dot--gh"></span>Open Source
|
|
70
|
+
</a>
|
|
71
|
+
</div>
|
|
72
|
+
<h1 class="hero__title">
|
|
73
|
+
Limpiá el CSS<br>
|
|
74
|
+
de tus proyectos<br>
|
|
75
|
+
<span class="hero__highlight">VTEX IO</span>
|
|
76
|
+
</h1>
|
|
77
|
+
<p class="hero__subtitle">
|
|
78
|
+
Detectá reglas CSS huérfanas y <code>blockClass</code> sin uso.<br>
|
|
79
|
+
Mantené tu proyecto limpio, performante y fácil de mantener.
|
|
80
|
+
</p>
|
|
81
|
+
<div class="hero__actions">
|
|
82
|
+
<a href="#downloads" class="btn btn--primary">
|
|
83
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
|
|
84
|
+
stroke-linejoin="round" width="18" height="18">
|
|
85
|
+
<path d="M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4" />
|
|
86
|
+
<polyline points="7 10 12 15 17 10" />
|
|
87
|
+
<line x1="12" y1="15" x2="12" y2="3" />
|
|
88
|
+
</svg>
|
|
89
|
+
Descargar
|
|
90
|
+
</a>
|
|
91
|
+
<a href="https://github.com/emanueleelias/vtex-css-sanitizer" target="_blank" rel="noopener"
|
|
92
|
+
class="btn btn--outline">
|
|
93
|
+
Ver en GitHub
|
|
94
|
+
</a>
|
|
95
|
+
</div>
|
|
96
|
+
</div>
|
|
97
|
+
</header>
|
|
98
|
+
|
|
99
|
+
<!-- ============ FEATURES ============ -->
|
|
100
|
+
<section class="features" id="features">
|
|
101
|
+
<div class="container">
|
|
102
|
+
<span class="section__label">Características</span>
|
|
103
|
+
<h2 class="section__title">Todo lo que necesitás</h2>
|
|
104
|
+
<div class="features__grid">
|
|
105
|
+
<article class="feature-card reveal">
|
|
106
|
+
<div class="feature-card__icon">
|
|
107
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
|
|
108
|
+
stroke-linejoin="round">
|
|
109
|
+
<circle cx="11" cy="11" r="8" />
|
|
110
|
+
<line x1="21" y1="21" x2="16.65" y2="16.65" />
|
|
111
|
+
</svg>
|
|
112
|
+
</div>
|
|
113
|
+
<h3>Análisis Bidireccional</h3>
|
|
114
|
+
<p>Encuentra CSS sin <code>blockClass</code> y <code>blockClass</code> sin CSS. Doble chequeo para no dejar
|
|
115
|
+
nada suelto.</p>
|
|
116
|
+
</article>
|
|
117
|
+
<article class="feature-card reveal">
|
|
118
|
+
<div class="feature-card__icon">
|
|
119
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
|
|
120
|
+
stroke-linejoin="round">
|
|
121
|
+
<path d="M12 20h9" />
|
|
122
|
+
<path d="M16.5 3.5a2.121 2.121 0 013 3L7 19l-4 1 1-4L16.5 3.5z" />
|
|
123
|
+
</svg>
|
|
124
|
+
</div>
|
|
125
|
+
<h3>Limpieza Interactiva</h3>
|
|
126
|
+
<p>El comando <code>fix</code> te guía regla por regla. Vos decidís qué se elimina y qué se conserva.</p>
|
|
127
|
+
</article>
|
|
128
|
+
<article class="feature-card reveal">
|
|
129
|
+
<div class="feature-card__icon">
|
|
130
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
|
|
131
|
+
stroke-linejoin="round">
|
|
132
|
+
<path d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z" />
|
|
133
|
+
<polyline points="14 2 14 8 20 8" />
|
|
134
|
+
<line x1="16" y1="13" x2="8" y2="13" />
|
|
135
|
+
<line x1="16" y1="17" x2="8" y2="17" />
|
|
136
|
+
</svg>
|
|
137
|
+
</div>
|
|
138
|
+
<h3>Informes Detallados</h3>
|
|
139
|
+
<p>Genera reportes en Markdown con cada análisis y sesión de limpieza para un registro histórico.</p>
|
|
140
|
+
</article>
|
|
141
|
+
<article class="feature-card reveal">
|
|
142
|
+
<div class="feature-card__icon">
|
|
143
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
|
|
144
|
+
stroke-linejoin="round">
|
|
145
|
+
<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" />
|
|
146
|
+
</svg>
|
|
147
|
+
</div>
|
|
148
|
+
<h3>Seguro</h3>
|
|
149
|
+
<p>Ignora automáticamente los archivos CSS de componentes React custom para evitar falsos positivos.</p>
|
|
150
|
+
</article>
|
|
151
|
+
<article class="feature-card reveal">
|
|
152
|
+
<div class="feature-card__icon">
|
|
153
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
|
|
154
|
+
stroke-linejoin="round">
|
|
155
|
+
<polyline points="16 18 22 12 16 6" />
|
|
156
|
+
<polyline points="8 6 2 12 8 18" />
|
|
157
|
+
</svg>
|
|
158
|
+
</div>
|
|
159
|
+
<h3>Inteligente</h3>
|
|
160
|
+
<p>Reconoce clases de estado dinámicas de VTEX como <code>--isActive</code> y solo valida el
|
|
161
|
+
<code>blockClass</code> principal.</p>
|
|
162
|
+
</article>
|
|
163
|
+
<article class="feature-card reveal">
|
|
164
|
+
<div class="feature-card__icon">
|
|
165
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
|
|
166
|
+
stroke-linejoin="round">
|
|
167
|
+
<rect x="2" y="3" width="20" height="14" rx="2" ry="2" />
|
|
168
|
+
<line x1="8" y1="21" x2="16" y2="21" />
|
|
169
|
+
<line x1="12" y1="17" x2="12" y2="21" />
|
|
170
|
+
</svg>
|
|
171
|
+
</div>
|
|
172
|
+
<h3>CLI + GUI</h3>
|
|
173
|
+
<p>Usalo desde la terminal o con la aplicación de escritorio. Elegí la que mejor se adapte a tu workflow.</p>
|
|
174
|
+
</article>
|
|
175
|
+
</div>
|
|
176
|
+
</div>
|
|
177
|
+
</section>
|
|
178
|
+
|
|
179
|
+
<!-- ============ VERSIONS ============ -->
|
|
180
|
+
<section class="versions" id="versions">
|
|
181
|
+
<div class="container">
|
|
182
|
+
<span class="section__label">Versiones</span>
|
|
183
|
+
<h2 class="section__title">Dos formas de usarlo</h2>
|
|
184
|
+
<div class="versions__grid">
|
|
185
|
+
<!-- CLI -->
|
|
186
|
+
<div class="version-card reveal">
|
|
187
|
+
<div class="version-card__header">
|
|
188
|
+
<span class="version-card__tag">CLI</span>
|
|
189
|
+
<h3>Línea de Comandos</h3>
|
|
190
|
+
<p>Ideal para integrar en tu workflow de desarrollo.</p>
|
|
191
|
+
</div>
|
|
192
|
+
<div class="version-card__preview">
|
|
193
|
+
<img src="assets/cli-mockup.png" alt="VTEX CSS Sanitizer CLI en acción" loading="lazy">
|
|
194
|
+
</div>
|
|
195
|
+
<div class="version-card__install">
|
|
196
|
+
<div class="copy-block" id="copyBlock">
|
|
197
|
+
<code>npm install -g vtex-css-sanitizer-cli</code>
|
|
198
|
+
<button class="copy-block__btn" id="copyBtn" aria-label="Copiar comando">
|
|
199
|
+
<svg class="copy-block__icon copy-block__icon--copy" viewBox="0 0 24 24" fill="none"
|
|
200
|
+
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
201
|
+
<rect x="9" y="9" width="13" height="13" rx="2" ry="2" />
|
|
202
|
+
<path d="M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1" />
|
|
203
|
+
</svg>
|
|
204
|
+
<svg class="copy-block__icon copy-block__icon--check" viewBox="0 0 24 24" fill="none"
|
|
205
|
+
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
206
|
+
<polyline points="20 6 9 17 4 12" />
|
|
207
|
+
</svg>
|
|
208
|
+
</button>
|
|
209
|
+
</div>
|
|
210
|
+
</div>
|
|
211
|
+
</div>
|
|
212
|
+
<!-- GUI -->
|
|
213
|
+
<div class="version-card reveal">
|
|
214
|
+
<div class="version-card__header">
|
|
215
|
+
<span class="version-card__tag version-card__tag--gui">GUI</span>
|
|
216
|
+
<h3>Aplicación de Escritorio</h3>
|
|
217
|
+
<p>Interfaz visual intuitiva para analizar y limpiar tu proyecto sin tocar la terminal.</p>
|
|
218
|
+
</div>
|
|
219
|
+
<div class="version-card__preview">
|
|
220
|
+
<img src="assets/gui-mockup.png" alt="VTEX CSS Sanitizer GUI" loading="lazy">
|
|
221
|
+
</div>
|
|
222
|
+
<div class="version-card__platforms">
|
|
223
|
+
<span class="platform-chip">
|
|
224
|
+
<svg viewBox="0 0 24 24" fill="currentColor" width="16" height="16">
|
|
225
|
+
<path
|
|
226
|
+
d="M0 3.449L9.75 2.1v9.451H0m10.949-9.602L24 0v11.4H10.949M0 12.6h9.75v9.451L0 20.699M10.949 12.6H24V24l-12.9-1.801" />
|
|
227
|
+
</svg>
|
|
228
|
+
Windows
|
|
229
|
+
</span>
|
|
230
|
+
<span class="platform-chip">
|
|
231
|
+
<svg viewBox="0 0 24 24" fill="currentColor" width="16" height="16">
|
|
232
|
+
<path
|
|
233
|
+
d="M12.504 0c-.155 0-.311.005-.466.014C8.752.233 5.937 2.158 4.702 5.024c-1.058 2.451-.996 5.333.172 7.678.364.732.834 1.425 1.396 2.048.485.541.979 1.076 1.3 1.722.298.597.462 1.246.557 1.903.146 1.009.159 2.032.159 3.049v.456c0 .627.225 1.2.6 1.646.45.534 1.131.874 1.884.874h2.461c.754 0 1.434-.34 1.884-.874.375-.446.6-1.019.6-1.646v-.456c0-1.017.013-2.04.159-3.049.095-.657.259-1.306.557-1.903.321-.646.815-1.181 1.3-1.722.562-.623 1.032-1.316 1.396-2.048 1.168-2.345 1.23-5.227.172-7.678C18.063 2.158 15.248.233 11.962.014 11.81.005 11.659 0 11.504 0h1z" />
|
|
234
|
+
</svg>
|
|
235
|
+
Linux
|
|
236
|
+
</span>
|
|
237
|
+
</div>
|
|
238
|
+
</div>
|
|
239
|
+
</div>
|
|
240
|
+
</div>
|
|
241
|
+
</section>
|
|
242
|
+
|
|
243
|
+
<!-- ============ DOWNLOADS ============ -->
|
|
244
|
+
<section class="downloads" id="downloads">
|
|
245
|
+
<div class="container">
|
|
246
|
+
<span class="section__label">Descargas</span>
|
|
247
|
+
<h2 class="section__title">Empezá ahora</h2>
|
|
248
|
+
<p class="section__desc">Elegí la versión que mejor se adapte a tu necesidad.</p>
|
|
249
|
+
<div class="downloads__grid">
|
|
250
|
+
<!-- npm -->
|
|
251
|
+
<div class="download-card reveal">
|
|
252
|
+
<div class="download-card__icon download-card__icon--npm">
|
|
253
|
+
<svg viewBox="0 0 24 24" fill="currentColor" width="32" height="32">
|
|
254
|
+
<path
|
|
255
|
+
d="M0 7.334v8h6.666v1.332H12v-1.332h12v-8H0zm6.666 6.664H5.334v-4H3.999v4H1.335V8.667h5.331v5.331zm4 0v1.336H8.001V8.667h5.334v5.331h-2.669zm12.001 0h-1.33v-4h-1.336v4h-1.335v-4h-1.33v4h-2.671V8.667h8.002v5.331zM10.665 10H12v2.667h-1.335V10z" />
|
|
256
|
+
</svg>
|
|
257
|
+
</div>
|
|
258
|
+
<h3>npm (CLI)</h3>
|
|
259
|
+
<p>Instalá globalmente con un solo comando.</p>
|
|
260
|
+
<div class="copy-block copy-block--small" id="copyBlockDl">
|
|
261
|
+
<code>npm i -g vtex-css-sanitizer-cli</code>
|
|
262
|
+
<button class="copy-block__btn" id="copyBtnDl" aria-label="Copiar comando">
|
|
263
|
+
<svg class="copy-block__icon copy-block__icon--copy" viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
|
264
|
+
stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
265
|
+
<rect x="9" y="9" width="13" height="13" rx="2" ry="2" />
|
|
266
|
+
<path d="M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1" />
|
|
267
|
+
</svg>
|
|
268
|
+
<svg class="copy-block__icon copy-block__icon--check" viewBox="0 0 24 24" fill="none"
|
|
269
|
+
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
270
|
+
<polyline points="20 6 9 17 4 12" />
|
|
271
|
+
</svg>
|
|
272
|
+
</button>
|
|
273
|
+
</div>
|
|
274
|
+
</div>
|
|
275
|
+
<!-- Windows -->
|
|
276
|
+
<div class="download-card reveal">
|
|
277
|
+
<div class="download-card__icon download-card__icon--win">
|
|
278
|
+
<svg viewBox="0 0 24 24" fill="currentColor" width="32" height="32">
|
|
279
|
+
<path
|
|
280
|
+
d="M0 3.449L9.75 2.1v9.451H0m10.949-9.602L24 0v11.4H10.949M0 12.6h9.75v9.451L0 20.699M10.949 12.6H24V24l-12.9-1.801" />
|
|
281
|
+
</svg>
|
|
282
|
+
</div>
|
|
283
|
+
<h3>Windows</h3>
|
|
284
|
+
<p>Descargá el instalador .exe para Windows.</p>
|
|
285
|
+
<a href="https://github.com/emanueleelias/vtex-css-sanitizer/releases/latest" target="_blank" rel="noopener"
|
|
286
|
+
class="btn btn--download">
|
|
287
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
|
|
288
|
+
stroke-linejoin="round" width="18" height="18">
|
|
289
|
+
<path d="M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4" />
|
|
290
|
+
<polyline points="7 10 12 15 17 10" />
|
|
291
|
+
<line x1="12" y1="15" x2="12" y2="3" />
|
|
292
|
+
</svg>
|
|
293
|
+
Descargar .exe
|
|
294
|
+
</a>
|
|
295
|
+
</div>
|
|
296
|
+
<!-- Linux -->
|
|
297
|
+
<div class="download-card reveal">
|
|
298
|
+
<div class="download-card__icon download-card__icon--linux">
|
|
299
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 15 15"><!-- Icon from Teenyicons by smhmd - https://github.com/teenyicons/teenyicons/blob/master/LICENSE --><path fill="currentColor" d="m.5 14.5l-.354-.354A.5.5 0 0 0 .5 15zm.656-.656l-.353-.354zM14.5 14.5v.5a.5.5 0 0 0 .354-.854zm-11-4l-.224-.447a.5.5 0 0 0-.13.8zm.87-.435l.223.447zm6.26 0l-.223.447zm.87.435l.354.354a.5.5 0 0 0-.13-.801zm-7.414.586l.353-.354zM.854 14.854l.656-.657l-.707-.707l-.657.656zM2 13.014V6.5H1v6.514zM13 6.5v6.514h1V6.5zm.49 7.697l.656.657l.708-.708l-.657-.656zM14.5 14H.5v1h14zm-1.5-.986c0 .444.176.87.49 1.183l.707-.707a.67.67 0 0 1-.197-.476zM7.5 1A5.5 5.5 0 0 1 13 6.5h1A6.5 6.5 0 0 0 7.5 0zM2 6.5A5.5 5.5 0 0 1 7.5 1V0A6.5 6.5 0 0 0 1 6.5zm-.49 7.697c.314-.314.49-.74.49-1.183H1c0 .179-.07.35-.197.476zm2.214-3.25l.87-.434l-.448-.895l-.87.435zm6.683-.434l.87.434l.447-.894l-.87-.435zm.74-.367l-.586.586l.707.707l.586-.585zm-6.708.586l-.585-.586l-.708.708l.586.585zM7.5 12a4.33 4.33 0 0 1-3.06-1.268l-.708.707c1 1 2.355 1.561 3.768 1.561zm3.06-1.268A4.33 4.33 0 0 1 7.5 12v1a5.33 5.33 0 0 0 3.768-1.56zm-5.967-.22a6.5 6.5 0 0 1 5.814 0l.447-.894a7.5 7.5 0 0 0-6.708 0zM7 6.5v1h1v-1zm-3 1v-1H3v1zM5.5 9A1.5 1.5 0 0 1 4 7.5H3A2.5 2.5 0 0 0 5.5 10zM7 7.5A1.5 1.5 0 0 1 5.5 9v1A2.5 2.5 0 0 0 8 7.5zM5.5 5A1.5 1.5 0 0 1 7 6.5h1A2.5 2.5 0 0 0 5.5 4zm0-1A2.5 2.5 0 0 0 3 6.5h1A1.5 1.5 0 0 1 5.5 5zM11 6.5v1h1v-1zM9.5 9A1.5 1.5 0 0 1 8 7.5H7A2.5 2.5 0 0 0 9.5 10zM11 7.5A1.5 1.5 0 0 1 9.5 9v1A2.5 2.5 0 0 0 12 7.5zM9.5 5A1.5 1.5 0 0 1 11 6.5h1A2.5 2.5 0 0 0 9.5 4zm0-1A2.5 2.5 0 0 0 7 6.5h1A1.5 1.5 0 0 1 9.5 5zM5 7v1h1V7zm4 0v1h1V7z"/></svg>
|
|
300
|
+
</div>
|
|
301
|
+
<h3>Linux</h3>
|
|
302
|
+
<p>Descargá el AppImage para distribuciones Linux.</p>
|
|
303
|
+
<a href="https://github.com/emanueleelias/vtex-css-sanitizer/releases/latest" target="_blank" rel="noopener"
|
|
304
|
+
class="btn btn--download">
|
|
305
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
|
|
306
|
+
stroke-linejoin="round" width="18" height="18">
|
|
307
|
+
<path d="M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4" />
|
|
308
|
+
<polyline points="7 10 12 15 17 10" />
|
|
309
|
+
<line x1="12" y1="15" x2="12" y2="3" />
|
|
310
|
+
</svg>
|
|
311
|
+
Descargar .AppImage
|
|
312
|
+
</a>
|
|
313
|
+
</div>
|
|
314
|
+
</div>
|
|
315
|
+
</div>
|
|
316
|
+
</section>
|
|
317
|
+
|
|
318
|
+
<!-- ============ FOOTER ============ -->
|
|
319
|
+
<footer class="footer">
|
|
320
|
+
<div class="container footer__inner">
|
|
321
|
+
<div class="footer__left">
|
|
322
|
+
<span class="footer__brand">VTEX CSS Sanitizer</span>
|
|
323
|
+
<span class="footer__copy">© 2025 Elias Daniel Emanuele · MIT License</span>
|
|
324
|
+
</div>
|
|
325
|
+
<div class="footer__links">
|
|
326
|
+
<a href="https://github.com/emanueleelias/vtex-css-sanitizer" target="_blank" rel="noopener">GitHub</a>
|
|
327
|
+
<a href="https://www.npmjs.com/package/vtex-css-sanitizer-cli" target="_blank" rel="noopener">npm</a>
|
|
328
|
+
<a href="https://github.com/emanueleelias/vtex-css-sanitizer/issues" target="_blank" rel="noopener">Issues</a>
|
|
329
|
+
</div>
|
|
330
|
+
</div>
|
|
331
|
+
</footer>
|
|
332
|
+
|
|
333
|
+
<script src="script.js"></script>
|
|
334
|
+
</body>
|
|
335
|
+
|
|
336
|
+
</html>
|
package/docs/script.js
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/* ========================================
|
|
2
|
+
VTEX CSS Sanitizer — Landing Page JS
|
|
3
|
+
======================================== */
|
|
4
|
+
|
|
5
|
+
document.addEventListener('DOMContentLoaded', () => {
|
|
6
|
+
// -- Copy to clipboard --
|
|
7
|
+
function setupCopyButton(blockId, btnId) {
|
|
8
|
+
const block = document.getElementById(blockId);
|
|
9
|
+
const btn = document.getElementById(btnId);
|
|
10
|
+
if (!block || !btn) return;
|
|
11
|
+
|
|
12
|
+
btn.addEventListener('click', () => {
|
|
13
|
+
const code = block.querySelector('code');
|
|
14
|
+
if (!code) return;
|
|
15
|
+
|
|
16
|
+
const text = code.textContent.trim();
|
|
17
|
+
navigator.clipboard.writeText(text).then(() => {
|
|
18
|
+
block.classList.add('copied');
|
|
19
|
+
setTimeout(() => block.classList.remove('copied'), 2000);
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
setupCopyButton('copyBlock', 'copyBtn');
|
|
25
|
+
setupCopyButton('copyBlockDl', 'copyBtnDl');
|
|
26
|
+
|
|
27
|
+
// -- Scroll reveal --
|
|
28
|
+
const reveals = document.querySelectorAll('.reveal');
|
|
29
|
+
|
|
30
|
+
if ('IntersectionObserver' in window) {
|
|
31
|
+
const observer = new IntersectionObserver(
|
|
32
|
+
(entries) => {
|
|
33
|
+
entries.forEach((entry) => {
|
|
34
|
+
if (entry.isIntersecting) {
|
|
35
|
+
entry.target.classList.add('visible');
|
|
36
|
+
observer.unobserve(entry.target);
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
},
|
|
40
|
+
{ threshold: 0.15, rootMargin: '0px 0px -40px 0px' }
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
reveals.forEach((el) => observer.observe(el));
|
|
44
|
+
} else {
|
|
45
|
+
// Fallback: show all
|
|
46
|
+
reveals.forEach((el) => el.classList.add('visible'));
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// -- Smooth scroll for anchor links --
|
|
50
|
+
document.querySelectorAll('a[href^="#"]').forEach((link) => {
|
|
51
|
+
link.addEventListener('click', (e) => {
|
|
52
|
+
const targetId = link.getAttribute('href');
|
|
53
|
+
if (targetId === '#') return;
|
|
54
|
+
|
|
55
|
+
const target = document.querySelector(targetId);
|
|
56
|
+
if (target) {
|
|
57
|
+
e.preventDefault();
|
|
58
|
+
const navHeight = document.querySelector('.nav')?.offsetHeight || 64;
|
|
59
|
+
const top = target.getBoundingClientRect().top + window.scrollY - navHeight;
|
|
60
|
+
window.scrollTo({ top, behavior: 'smooth' });
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
});
|