✨ Full EsCSS Support#22
Conversation
|
@codedgar is attempting to deploy a commit to the OSS Program EsJS Team on Vercel. A member of the Team first needs to authorize it. |
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughSe añaden recursos y paquetes para soportar EsCSS: demo Vite, generadores de diccionarios, compilador bidireccional EsCSS↔CSS, plugins (Vite, Prettier), herramientas de lenguaje (TextMate/config), integración en esvue, múltiples tests y configuraciones de build/TypeScript. Changes
Estimated code review effort🎯 4 (Complejo) | ⏱️ ~60 minutos Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 24
🤖 Fix all issues with AI agents
In `@demos/demo-escss/package.json`:
- Around line 1-26: El package.json no declara el tipo de módulo y Vite está
usando ESM en vite.config.js, lo que provoca errores al Node interpretar .js;
fix: add "type": "module" at the top-level of package.json (next to
name/version) so Node treats .js files as ESM, or alternatively rename
vite.config.js to vite.config.mjs; update package.json (the file shown)
accordingly and ensure any tooling or import statements in vite.config.js remain
unchanged.
In `@packages/escss-generator/src/generate-at-rules.ts`:
- Around line 23-68: The generated getDictionary currently calls
invertMap(dictionary) on every inverted request; modify the generator
(generateAtRulesCode) so the emitted module stores a lazily-initialized cached
Map (e.g., a module-scoped variable like invertedDictionary: Map<string,string>
| undefined) and in getDictionary(inverted = false) return dictionary when false
and if inverted return the cached invertedDictionary if set or compute
invertMap(dictionary), assign it to invertedDictionary, and then return it;
reference the existing symbols dictionary, getDictionary, invertMap and
generateAtRulesCode when making this change.
In `@packages/escss-generator/src/generate-properties.ts`:
- Around line 322-356: The generated properties code currently lets duplicate
EsCSS names overwrite entries and breaks bijectivity; in
generatePropertiesCode() (which uses generatePropertiesMapping() and
translateProperty()), validate the mappings before building the dictionary by
scanning the generated [css, escss] pairs for duplicate escss keys, collect
conflicts (escss -> list of css names) and throw a clear error (or fail the
build) listing the duplicated escss names and their original CSS properties so
the author can resolve collisions; ensure this validation runs prior to
constructing the entries and that getDictionary()/dictionary remain unchanged
once the check passes.
In `@packages/escss-generator/src/generate-values.ts`:
- Around line 196-200: Hay una entrada duplicada para la clave 'both' en la
lista que construye el Map (aparece en "Animation values" y otra vez en "Resize
values" como ['both','ambos']); elimina la segunda aparición en el bloque
"Resize values" (la tupla ['both','ambos']) para evitar confusión y dejar una
única definición, asegurándote de actualizar cualquier comentario cercano si es
necesario y conservar la consistencia con las claves usadas por la función que
crea el Map en generate-values.ts.
- Around line 412-428: The generated transformValue implementation (function
transformValue) incorrectly uses value.split(/\s+/) which breaks CSS functions
(e.g., calc(), rgb(), url()) and results in dead/incorrect generated code; fix
the generator to either emit the correct implementation that preserves function
contents by tokenizing/splitting on whitespace while tracking parenthesis depth
(mirroring the working logic in packages/escss/src/utils/transformValue.ts) or
stop generating this function and import/reuse the existing transformValue
implementation; ensure no leftover dead code remains in the generated output and
update references to the symbol transformValue accordingly.
In `@packages/escss-generator/src/index.ts`:
- Around line 1-54: This module currently runs generate() during import causing
side effects; remove the top-level generate() invocation and instead export the
generate function so callers can invoke it, and add a guarded runner that only
calls generate() when the file is executed as the entrypoint (use
fileURLToPath(import.meta.url) vs process.argv[1] check). Keep ensureDir,
outputDir and all generator imports unchanged; ensure no other top-level file
writes occur so importing this module no longer writes files automatically.
In `@packages/escss/package.json`:
- Around line 24-32: Mover "@es-js/core" de devDependencies a dependencies en
package.json porque las exportaciones reexportadas desde index.ts (módulos
properties, values, at-rules, pseudo, selectors) usan invertMap de
`@es-js/core/utils` en las funciones runtime getDictionary(),
getPseudoClassesDictionary() y getPseudoElementsDictionary(); además
build.config.ts lo marca como external (no se bundlea), por lo que los
consumidores deben recibirlo al instalar escss. Actualiza package.json para
colocar "@es-js/core" bajo "dependencies" y publica/rebuild para que las
dependencias runtime estén disponibles para los consumidores.
In `@packages/escss/src/index.ts`:
- Around line 41-56: El problema: la función compile está mutando el objeto
options recibido; evita mutar argumentos de entrada. Solución: en la función
compile crea un nuevo objeto local (por ejemplo const opts = { from: 'escss',
to: 'css', ...options } o usando Object.assign) y usa ese objeto (opts) para las
comprobaciones y retorno en lugar de modificar options; actualiza las
referencias a options.from/options.to para usar opts.from/opts.to y mantiene la
firma y el tipo CompileOptions sin mutar el parámetro original.
In `@packages/escss/src/utils/transformSelector.ts`:
- Around line 20-29: The current regex in transformSelector.ts used in the
result.replace call includes '[' in the lookbehind, so attribute selectors like
[time] get treated as element names and translated; update the regex to avoid
matching when inside attribute selectors by removing '\[' from the lookbehind
(or add a negative lookbehind for '['), e.g. change
/(?<=^|[\s,>+~\[]|\))\b([a-z][a-z0-9-]*)\b(?![([])/gi to a pattern that does not
allow '[' (for example /(?<=^|[\s,>+~]|\))\b([a-z][a-z0-9-]*)\b(?![([])/gi or
equivalently add (?<!\[) before \b), and keep the replacement logic with
selectorsDict.get(element.toLowerCase()) unchanged.
In `@packages/escss/src/utils/transformValue.ts`:
- Around line 40-69: The splitter splitValuePreservingFunctions currently
ignores quotes and escapes so it wrongly splits on spaces inside quoted strings
(e.g., content: "a b", font-family: "Open Sans"); update
splitValuePreservingFunctions to track quote state and escape sequences: add
variables for currentQuote (single/double/none) and isEscaped, toggle them when
encountering backslashes or quote chars and only treat a space as a split when
depth === 0 and currentQuote is null (not inside a string); ensure closing
quotes are preserved in current and that escapes inside strings are not consumed
or lost so original literal spacing/escapes remain intact.
In `@packages/escss/vite.config.ts`:
- Around line 1-7: La configuración de Vitest declara globals: true pero los
tests en compile.test.ts importan explícitamente describe, it y expect; cambiad
la configuración para que refleje el patrón actual: en
packages/escss/vite.config.ts actualizad defineConfig -> test -> globals: false;
alternativamente, si preferís usar APIs globales, eliminad los imports de
describe/it/expect en packages/escss/test/compile.test.ts y dejad globals: true.
Aseguraos de mantener la opción coherente con el archivo de test para evitar
redundancia.
In `@packages/esvue/package.json`:
- Around line 20-23: El paquete '@es-js/escss' se está importando en tiempo de
ejecución (ver import { compile as EsCSSCompile } from '@es-js/escss' en
packages/esvue/src/index.ts) pero actualmente figura en devDependencies; mueve
'@es-js/escss' desde devDependencies a dependencies (o a peerDependencies if you
expect consumers to provide it) en packages/esvue/package.json y actualiza la
instalación/lockfile para que los consumidores de `@es-js/esvue` tengan la
dependencia disponible en producción.
In `@packages/language-tools/package.json`:
- Line 27: package.json is missing a "files" field so the generated artifacts
under dist (including escss.tmLanguage.json and
escss-language-configuration.json) won't be included in published packages; add
a "files": ["dist"] entry to package.json and ensure the package.json exports
remain correct, and also verify that the dependency "@es-js/escss" (referenced
from src/generate-escss-syntax.js) is declared in dependencies (not just
devDependencies) since it's required at runtime by source code.
In `@packages/language-tools/src/generate-escss-language-configurations.js`:
- Around line 7-13: The file currently relies on implicit Buffer-to-string
coercion when reading/writing JSON; update the readFileSync and writeFileSync
calls to use explicit UTF-8 encoding to avoid implicit Buffer conversion: call
readFileSync('./assets/css-language-configuration.json', 'utf8') so variable
data is a string before JSON.parse, and call
writeFileSync('dist/escss-language-configuration.json', output, 'utf8') when
writing the output; reference the existing symbols readFileSync, writeFileSync,
data, jsonData, and output when making the change.
In `@packages/language-tools/src/generate-escss-syntax.js`:
- Around line 14-17: The current keyword extraction via getEscssKeywords() can
produce regex patterns with unescaped special characters; update the code that
builds the regex pattern (use the array from getEscssKeywords and the code that
joins them into a pattern) to escape regex metacharacters in each keyword (e.g.,
replace characters like . * + ? ^ $ { } ( ) | [ ] \ / with escaped versions)
before joining, so the generated pattern is always valid and matches the literal
keywords; locate and modify the pattern construction that consumes
getEscssKeywords() and apply an escape function to each keyword.
In `@packages/prettier-plugin-escss/package.json`:
- Around line 26-35: The package.json currently lists "@es-js/escss" under
"devDependencies" but it is required at runtime by the Prettier plugin; move the
entry "@es-js/escss": "workspace:*" from the "devDependencies" object into the
top-level "dependencies" object (preserving the version specifier) so the
runtime bundle/install will include it; update any package.json
ordering/formatting as needed.
- Line 2: Actualizar el campo "name" en package.json que actualmente es
"prettier-plugin-escss" para usar el scope del monorepo, cambiándolo a
"@es-js/prettier-plugin-escss"; busca el valor "prettier-plugin-escss" en
package.json del paquete y reemplázalo por "@es-js/prettier-plugin-escss", y
luego verifica que cualquier referencia a ese nombre (por ejemplo en la
configuración de publicación o en dependencias internas) se actualice en caso de
ser necesario.
In `@packages/prettier-plugin-escss/src/index.ts`:
- Around line 61-67: El acceso a la API interna de Prettier mediante
Symbol.for('comments') es frágil y puede romperse en futuras versiones; update
el bloque donde se lee options[Symbol.for('comments')] (la variable comments)
para añadir un comentario claro explicando que esto usa una API interna no
documentada de Prettier, por qué se hizo (compatibilidad con otros plugins), los
riesgos asociados y que debe ser revisado/monitoreado en upgrades de Prettier
(añadir un TODO con referencia a versión/issue tracking si procede).
- Around line 69-81: El printer actualmente toma options.originalText (EsCSS) y
lo pasa a format(parser: 'css'), lo cual es incorrecto; en lugar de usar
options.originalText en la llamada a format() dentro de la función que hace el
formateo, utiliza el CSS compilado que devuelve preprocess (la variable que
contiene el CSS generado por EsCSSCompile/preprocess) como entrada a format(), y
luego convierte el resultado formateado de nuevo a EsCSS con
EsCSSCompile(formatted, { from: 'css', to: 'escss' }); ajusta las referencias en
la función del printer para reemplazar options.originalText por la variable del
CSS compilado (no cambiar EsCSSCompile ni format() firmas).
In `@packages/prettier-plugin-escss/vite.config.ts`:
- Around line 1-7: Remove the unnecessary globals setting from the Vitest
configuration: update the object passed to defineConfig by removing the globals:
true property inside the test configuration (the test key may remain if you plan
to add tests later), so eliminate the unused globals flag referenced as globals
in the test object to avoid enabling Vitest globals when no tests/imports are
present.
In `@packages/vite-plugin-escss/package.json`:
- Around line 22-30: Mover "vite" de "dependencies" a "peerDependencies" para
indicar que el plugin debe usar la instancia de Vite del consumidor, y mover
"@es-js/escss" de "devDependencies" a "dependencies" porque su función compile
se utiliza en tiempo de ejecución dentro de los hooks configureServer y
transform; actualiza package.json para reflejar estos cambios y asegúrate de
ajustar semver si es necesario (por ejemplo mantener "^5.0.0" para vite en
peerDependencies y "workspace:*" o la versión adecuada para `@es-js/escss` en
dependencies) para evitar romper la resolución de paquetes.
In `@packages/vite-plugin-escss/src/index.ts`:
- Around line 64-68: El middleware usa readFileSync(filePath, 'utf-8') que
bloquea el event loop; reemplázalo por la API asíncrona (fs/promises) para leer
el archivo sin bloquear: importar readFile desde 'fs/promises', await
readFile(filePath, 'utf-8') dentro del try/catch del handler que llama a
compile(raw, { from: 'escss', to: 'css' }) y luego usar
res.setHeader('Content-Type', 'text/css') y res.end(compiled) exactamente como
ahora; asegúrate de marcar la función que contiene este código como async y de
manejar errores correctamente en el catch.
- Around line 77-81: The transform hook currently returns compiled CSS but omits
moduleType, so update the transform(raw: string, id: string) function to return
an object including moduleType: 'css' (e.g., return { code: compiled, map: null,
moduleType: 'css' }) so Vite treats .escss imports as CSS modules and enables
CSS pipeline/HMR when importing .escss from JS/TS; keep the existing compiled
value and map handling.
In `@packages/vscode-esjs/scripts/generate-grammars-configurations.ts`:
- Line 6: The grammars list (const grammars) includes escss.tmLanguage.json but
`@es-js/language-tools` does not publish escss.tmLanguage.json or
escss-language-configuration.json; either publish those two files in the
`@es-js/language-tools` package build so the script can download them, or
remove/guard the escss entries from the grammars and any corresponding
configuration lists (escss.tmLanguage.json and
escss-language-configuration.json) and add error handling to skip missing files
when fetching from unpkg.com; update the grammars array (and any configuration
arrays) or the package build accordingly to resolve the axios download failures.
There was a problem hiding this comment.
Actionable comments posted: 17
🤖 Fix all issues with AI agents
In `@packages/escss-generator/src/generate-properties.ts`:
- Around line 345-393: La plantilla generada exporta el identificador export
const cssProperties, que puede colisionar con el mismo nombre en consumidores;
en generatePropertiesCode cambia la línea que emite "export const cssProperties
= [" por un nombre no conflictivo (por ejemplo "export const allCssProperties" o
similar) y actualiza cualquier referencia interna del archivo generado (y la
documentación en el mismo template) para usar ese nuevo identificador; asegúrate
además de actualizar donde sea consumido fuera del generador para importar el
nuevo nombre o mantener un re-export explícito si se requiere compatibilidad.
In `@packages/escss-generator/src/generate-pseudo.ts`:
- Around line 107-204: generatePseudoCode currently injects raw strings into the
template (e.g., in classEntries, elementEntries and the various list mappings
like cssPseudoClassesList, escssPseudoClassesList, cssPseudoElementsList,
escssPseudoElementsList) using `'${escss}'` / `'${css}'` which breaks if values
contain single quotes or backslashes; fix by escaping values before
interpolation (create/inline an escape function used when building classEntries
and elementEntries and when mapping keys/values for the lists — e.g., replace
backslashes and single quotes with escaped versions or use JSON.stringify and
strip its surrounding quotes) so every injected string is safely escaped in
generatePseudoCode and all occurrences of direct `'${...}'` interpolation are
replaced with the escaped variant.
In `@packages/escss-generator/src/generate-selectors.ts`:
- Line 77: La entrada ['source', 'fuente'] en generate-selectors.ts puede
confundirse con la traducción de la propiedad font en word-dictionary.ts; cambia
la segunda elemento de ese par a 'origen' (o a otro término no ambigua como
'origen-source') para desambiguar el selector <source> de la fuente tipográfica,
actualiza cualquier prueba o comentario que asuma 'fuente' y mantén consistencia
con la traducción 'source' → 'origen' usada en word-dictionary.ts.
- Around line 5-96: The cssElementTranslations map in generate-selectors.ts
lacks duplicate-target detection like generatePropertiesMapping in
generate-properties.ts, so add collision validation in generateSelectorsCode:
iterate cssElementTranslations (or during codegen) and build a reverse map/set
of target names (the EsCSS names), and if a target is already present throw or
surface a clear error (including the conflicting source keys and the target) to
prevent two CSS keys mapping to the same EsCSS name; mirror the validation
behavior and error format used by generatePropertiesMapping so future additions
are caught consistently.
In `@packages/escss-generator/src/generate-values.ts`:
- Around line 374-376: The array contains duplicate mappings ['currentcolor',
'color-actual'] and ['currentColor', 'color-actual'] which are redundant because
the generated Map for the EsCSS→CSS direction will only keep the last entry
(resulting in 'color-actual' → 'currentColor'); remove the lowercase
'currentcolor' entry or add an inline comment next to the ['currentcolor',
'color-actual'] element explaining that the duplicate is intentional to show
canonical casing and that the Map will normalize to 'currentColor'.
- Around line 229-230: Las entradas de alias ['gray','gris'] y ['grey','gris']
producen claves duplicadas en el Map y la última definición vence, imponiendo la
grafía británica; arregla esto haciendo explícita la canonización: en el array
de pares de alias (p. ej. donde están ['gray','gris'], ['grey','gris'] y
similares) elimina uno de los alias o reemplaza ambos pares por un único par que
use la grafía preferida (por ejemplo ['gray','gris'] si quieres emitir "gray"),
o bien deduplica/normaliza antes de construir el Map (convertir ambos alias a la
misma clave canónica). Aplica el mismo cambio a las otras ocurrencias señaladas
(líneas similares con dark/light/slate/dim) para evitar que la última entrada
del Map sobrescriba la grafía deseada.
In `@packages/escss-generator/src/index.ts`:
- Around line 54-56: La guardia de entry-point usando direct comparación de
process.argv[1] con fileURLToPath(import.meta.url) es frágil; en la
función/archivo que contiene generate(), sustituye esa comparación por una
comparación de rutas resueltas usando fs.realpathSync para normalizar ambos
extremos (resolver realpath de fileURLToPath(import.meta.url) y, si existe,
realpathSync(process.argv[1])) y sólo invoca generate() cuando ambas rutas
resueltas coincidan; además defensivamente comprueba que process.argv[1] existe
antes de llamar a realpathSync para evitar errores en entornos sin ese índice.
- Around line 21-52: The generate() function calls writeFileSync multiple times
(for properties.ts, values.ts, at-rules.ts, pseudo.ts, selectors.ts) without
error handling; wrap the sequence of file writes in a try/catch (or implement an
atomic/temp-file + rename strategy) so failures don’t leave outputDir in a
partially-written state: capture exceptions around the calls to writeFileSync,
log a clear error via console.error (including the filename and the caught
error), and if using a multi-step approach, ensure cleanup/rollback of any temp
files; reference generate(), writeFileSync, outputDir and the helpers
generatePropertiesCode(), generateValuesCode(), generateAtRulesCode(),
generatePseudoCode(), generateSelectorsCode() when locating the changes.
In `@packages/escss-generator/src/word-dictionary.ts`:
- Line 179: Remove the duplicate ['stretch', 'estirar'] tuple from the list of
word pairs in packages/escss-generator/src/word-dictionary.ts so the pair only
appears once; locate the array of translation pairs used to build the Map (the
list of ['english','spanish'] entries that feed the Map construction) and delete
the second occurrence (the one at line ~179) to avoid unnecessary duplication
while leaving the original entry (line ~60) intact.
- Around line 5-230: The issue: cssWordTranslations contains duplicate target
values (e.g., "espacio", "relleno", "origen") so createInvertedWordDictionary()
silently overwrites keys when inverting; fix by changing
createInvertedWordDictionary() to accumulate an array of source keys per
translated value (Map<string, string[]>), emit a warning when collisions are
detected (use console.warn or processLogger), update any callers expecting the
old Map<string,string> to handle arrays, and remove the duplicate
['stretch','estirar'] entry from cssWordTranslations; keep function name
createInvertedWordDictionary and map cssWordTranslations as the referenced
symbols.
In `@packages/escss/src/index.ts`:
- Around line 91-94: The catch block currently logs the error as console.error({
error }), which wraps the Error in an object and hides the stack; replace that
call so the error is logged directly with context (e.g., a descriptive string
plus the error) in the catch that returns content — locate the catch where
console.error({ error }) is used in packages/escss/src/index.ts and change it to
log the message and the error variable itself (preserving the stack) before
returning content.
In `@packages/escss/src/utils/transformSelector.ts`:
- Around line 43-59: The current replace call on result (the result.replace(...)
that matches /:([a-zñ-]+)(?:\(([^)]*)\))?/gi) can wrongly match the second colon
of a pseudo-element already transformed; change the match logic so pseudo-class
matches are not preceded by another colon (e.g. use a negative lookbehind like
(?<!:):([a-zñ-]+)(?:\(([^)]*)\))? or a preceding-char check inside the replace
callback) before consulting pseudoClassDict; update the replace invocation in
transformSelector (the result.replace block) to use that regex or check so
pseudo-elements (double-colon) are excluded reliably.
- Around line 20-29: La expresión regular usada en la llamada a result.replace
en transformSelector.ts no transforma nombres de elemento seguidos por '[' (p.
ej. div[class]) porque el lookahead negativo contiene '['; elimina el carácter
'[' del conjunto dentro del lookahead negativo (la parte (?![([\]=])) para que
pase a excluir sólo los demás caracteres pero no '['), dejando el lookbehind
(?<!\[) intacto; busca la llamada que usa result.replace con la regex
/(?<=^|[\s,>+~]|\))(?<!\[)\b([a-zñ][a-zñ0-9-]*)\b(?![([\]=])/gi y actualiza solo
el lookahead negativo para permitir transformar elementos antes de '[' mientras
que sigue evitando coincidencias dentro de corchetes (variables relevantes:
result, selectorsDict).
In `@packages/escss/test/compile.test.ts`:
- Around line 203-250: The CSS→EsCSS suite ("describe('CSS to EsCSS')") lacks
coverage compared to the reverse direction; add tests calling compile(input, {
from: 'css', to: 'escss' }) that assert translations for missing cases: semantic
value mappings (e.g., block→bloque and common color names/hex), `@keyframes`
rules, pseudo-elements (::before/::after → their EsCSS tokens), border
shorthand/individual border properties, and grid/flex properties (e.g., display:
grid/flex, grid-template, justify-content). For each case add a focused it(...)
using the same pattern as existing tests and assert with
expect(output).toContain(...) referencing the expected EsCSS tokens so
bidirectional parity is validated.
- Around line 34-43: La prueba "should transform background properties" es
insuficiente porque solo verifica la presencia de 'background-color'; actualiza
el test que llama a compile(input, { from: 'escss', to: 'css' }) para verificar
además que ambos mapeos de EsCSS ('color-fondo' y 'fondo-color') aparecen como
'background-color' con los valores traducidos ('azul' → 'blue' y 'rojo' →
'red'); es decir, comprueba que la salida contenga "background-color: blue" y
"background-color: red" (o las cadenas equivalentes en la salida) para asegurar
que ambos nombres de propiedad y ambos valores se transformaron correctamente.
- Around line 252-303: Add a bidirectional round-trip test that uses the
compile(...) helper to convert EsCSS→CSS and then compile the resulting CSS back
to EsCSS (and a separate case CSS→EsCSS→CSS), asserting the final string equals
the original (or a normalized form e.g., trimmed/consistent whitespace). Locate
tests near the existing "Edge cases" block and add two it(...) cases referencing
the compile function: one that starts with an EsCSS input, compiles to CSS and
back to EsCSS and asserts equality, and one that starts with CSS and round-trips
to CSS; ensure any normalization used for comparison is applied consistently to
both original and round-tripped outputs.
- Around line 158-174: The test is asserting an invalid CSS value: change the
expectation in compile.test.ts from 'empty-cells: hidden' to 'empty-cells:
hide'; then update the translation dictionary (the value mapping that currently
maps 'oculto' -> 'hidden') to include a 'hide' target and add a
property-specific rule so transformValue() can return 'hide' when the property
is 'empty-cells' (leave general mapping for other properties as 'hidden' if
needed); locate and modify transformValue() to accept property context (or add a
small conditional branch keyed on the property name) so the compile(input, ...)
path produces 'empty-cells: hide'.
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/vscode-esjs/scripts/generate-grammars-configurations.ts (1)
20-28:⚠️ Potential issue | 🟠 MajorLas llamadas a
downloadFileno están siendo esperadas (await).
downloadFilees una funciónasync, pero se invoca sinawaitni manejo de la promesa resultante. Esto causa dos problemas:
- El script puede terminar antes de que las descargas se completen.
- Los errores de las promesas rechazadas no se propagan (unhandled promise rejections).
🔧 Corrección propuesta
Envolver la lógica en una función
asyncprincipal:-for (const grammar of grammars) { - downloadFile(`${BASE_URL}${grammar}`, `./syntaxes/${grammar}`) -} -for (const conf of configurations) { - downloadFile(`${BASE_URL}${conf}`, `./languages/${conf}`) -} -for (const snippet of snippets) { - downloadFile(`${BASE_URL}${snippet}`, `./snippets/${snippet}`) -} +async function main() { + const downloads = [ + ...grammars.map(g => downloadFile(`${BASE_URL}${g}`, `./syntaxes/${g}`)), + ...configurations.map(c => downloadFile(`${BASE_URL}${c}`, `./languages/${c}`)), + ...snippets.map(s => downloadFile(`${BASE_URL}${s}`, `./snippets/${s}`)), + ] + await Promise.all(downloads) +} + +main().catch((err) => { + console.error(err) + process.exit(1) +})
🤖 Fix all issues with AI agents
In `@packages/vscode-esjs/scripts/generate-grammars-configurations.ts`:
- Around line 37-39: El catch actual que solo hace console.error para errores al
descargar (referencia a la variable url en generate-grammars-configurations.ts)
silencia fallos críticos; modifica la lógica alrededor del bloque try/catch que
descarga gramáticas para distinguir entre archivos obligatorios (por ejemplo
esjs.tmLanguage.json) y opcionales (por ejemplo EsCSS), y en el catch vuelve a
lanzar el error o llama a process.exit(1) cuando la descarga de un archivo
obligatorio falla, mientras que para archivos opcionales solo registras el error
y continúas; identifica el sitio donde se descarga (la función/loop que usa url)
y añade una lista/condición requiredFiles para decidir si relanzar el error o
tolerarlo.
|
@codedgar si! perdon, vengo revisandolo de a poco... aún tengo unos cuantos comentarios de CodeRabbit por revisar y ya lo mergeamos/lanzamos la |
There was a problem hiding this comment.
Actionable comments posted: 9
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@packages/escss-generator/src/generate-selectors.ts`:
- Around line 96-98: El import de validateNoDuplicateEscssValues está declarado
después de la definición de cssElementTranslations; muévelo al bloque de imports
al inicio del archivo (antes de la declaración de cssElementTranslations) para
seguir la convención del proyecto y mantener consistencia con otros generadores,
o si la colocación posterior es intencional documenta en un comentario junto a
cssElementTranslations la razón; referencia: función/const
validateNoDuplicateEscssValues y la constante cssElementTranslations.
- Line 75: The selector array entry ['figcaption', 'leyendafigura'] is
inconsistent with the hyphenated naming used elsewhere; change 'leyendafigura'
to 'leyenda-figura' in the selectors definition (the array containing
['figcaption', 'leyendafigura'] in generate-selectors.ts) and update any other
occurrences of the non-hyphenated 'leyendafigura' to the hyphenated form to keep
naming consistent with entries like 'areadetexto'/'area-texto' and
'conjuntocampos'/'conjunto-campos'.
- Around line 63-65: In the selector translations array in generate-selectors.ts
(the entries ['textarea','areadetexto'] and ['fieldset','conjuntocampos']),
normalize composed Spanish names to use hyphens to match the rest of the
dictionary: change 'areadetexto' to 'area-de-texto' and 'conjuntocampos' to
'conjunto-campos' (or 'conjunto-de-campos' if you prefer the extra particle),
update those string literals in the mapping, and run the test/validation that
checks selector translation consistency.
In `@packages/escss/src/index.ts`:
- Around line 76-83: root.walkAtRules currently calls transformMediaParams for
every at-rule; restrict this so transformMediaParams runs only for at-rules that
accept CSS media-like parameters (e.g., "media" and "supports" and any other
project-relevant at-rules), by checking atRule.name before calling
transformMediaParams. Update the block that iterates (root.walkAtRules and the
atRule handling) to only set atRule.params = transformMediaParams(...) when
atRule.name matches the allowed set (use explicit names like "media" and
"supports" or a small configurable whitelist) and leave params untouched for
others such as "keyframes" or "font-face".
In `@packages/escss/src/utils/transformValue.ts`:
- Around line 10-14: The current direct-match check in transformValue.ts uses
"if (directMatch)" which incorrectly treats mapped empty strings as no match;
change the check to explicitly detect presence by using "if (directMatch !==
undefined)" or "if (dictionary.has(value))" after calling dictionary.get(value)
so that empty-string mappings are returned correctly; update the conditional
around the directMatch variable in the transformValue function to use one of
these explicit existence checks.
In `@packages/escss/test/transformSelector.test.ts`:
- Around line 1-64: Add tests to exercise element-name mappings in
transformSelector: add cases that transform element names from CSS→EsCSS and
back (e.g., transformSelector('body:hover', true) -> 'cuerpo:encima' and the
reverse transformSelector('cuerpo:encima', false) -> 'body:hover'), and include
cases with combinators to ensure element mapping works in context (e.g., 'div >
span' and 'header + nav' both directions). Locate tests near existing
transformSelector specs (the describe blocks for pseudo-classes) and use the
same boolean flag pattern to assert both CSS→EsCSS and EsCSS→CSS behavior.
In `@packages/prettier-plugin-escss/src/index.ts`:
- Around line 72-75: The call that builds formatted via format(css, {
...options, parser: 'css' }) can propagate options.plugins (which may include
EsCSSPlugin or future plugins that register a 'css' parser) and risk recursive
parser invocation; fix by passing a sanitized options object to format: clone
options but remove or filter out plugins that register/override the 'css' parser
(or set plugins to undefined) before calling format so the local EsCSSPlugin
(and any plugin that registers 'css') is not re-registered; update the code
around the formatted assignment and the use of format/options/css/EsCSSPlugin to
use the sanitized options.
- Around line 28-47: The EsCSS→CSS compilation inside preprocess (remove the
EsCSSCompile call) is unnecessary because the printer uses options.originalText
(EsCSS) and the CSS AST isn't consumed; change preprocess to trim the input, set
options.originalText = text, and return the trimmed text directly instead of
compiled CSS; also update the printer (the printer function that currently
re-compiles or expects CSS) to stop re-running EsCSSCompile—rename any variables
like css/originalText to reflect that the printer receives EsCSS source and
delete the redundant EsCSSCompile usage there so no double compilation occurs.
In `@packages/vscode-esjs/package.json`:
- Around line 93-107: The package.json language entry for id "escss" points to
missing resources; either add the referenced language configuration and syntax
files or remove/disable the "escss" language entry. Specifically, create and
commit the two files referenced by the "escss" entry (the language configuration
file referenced as ./languages/escss-language-configuration.json and the syntax
grammar referenced as ./syntaxes/escss.tmLanguage.json) with valid VSCode
language-configuration and tmLanguage JSON, or if EsCSS is not ready, remove the
"escss" block from package.json so the extension no longer references
non-existent files.
---
Duplicate comments:
In `@packages/escss-generator/src/generate-properties.ts`:
- Around line 333-381: The generator defines a local constant cssProperties and
also emits an exported const with the same name into the generated file, which
can confuse consumers; update generatePropertiesCode to export a different
identifier (e.g., exportedCssProperties or generatedCssProperties) in the
template instead of "export const cssProperties = [...]" and keep the template
interpolation using the local cssProperties variable (i.e., change the emitted
line to `export const generatedCssProperties =
[${cssProperties.map(...).join(...) }]`), then search for any code that imports
the generated file and update those imports to the new exported name.
In `@packages/escss-generator/src/generate-pseudo.ts`:
- Around line 109-209: Remove the stray placeholder "[duplicate_comment]" left
in the review comment; locate the generatePseudoCode function (export function
generatePseudoCode) and ensure the generated string/template and any surrounding
review/comment text do not contain the "[duplicate_comment]" token so it isn't
left in the codebase or in generated output.
In `@packages/escss-generator/src/generate-selectors.ts`:
- Line 77: La entrada de traducción ['source','fuente'] es ambigua entre la
etiqueta HTML <source> y la "fuente" tipográfica; reemplaza esa pareja por dos
identificadores claros y no ambivalentes (por ejemplo cambiar 'fuente' a
'fuente-tipografica' para la traducción de font-related "source" o usar
'source-media' / 'fuente-multimedia' para la etiqueta HTML) dentro del mismo
archivo generate-selectors.ts donde se define esa lista (busca la matriz/const
que contiene ['source','fuente']) y actualiza cualquier referencia consumidora
en el código o tests para usar el nuevo identificador para evitar la colisión
semántica.
In `@packages/escss-generator/src/word-dictionary.ts`:
- Around line 243-249: La función createInvertedWordDictionary está
sobrescribiendo silenciosamente claves cuando dos entradas de
cssWordTranslations comparten el mismo valor; antes de hacer inverted.set(value,
key) detecta colisiones usando inverted.has(value) y maneja el conflicto (por
ejemplo lanzando un Error que incluya value, la key entrante y la key existente,
o acumulando todos los duplicados y lanzando al final). Asegúrate de referenciar
cssWordTranslations y createInvertedWordDictionary al implementar la
comprobación para evitar sobrescrituras silenciosas y proporcionar un mensaje
claro sobre la colisión.
In `@packages/escss/src/utils/transformSelector.ts`:
- Around line 17-26: The regex used in the result.replace call in
transformSelector.ts is preventing element selectors followed by `[` (e.g.,
div[class]) from being transformed because the negative lookahead (?![([\]=])
includes `[`; remove `[` from that negative lookahead so the pattern becomes
(?![(\]=]) while keeping the existing (?<!\[) lookbehind to avoid matching
inside brackets; update the regex literal passed to result.replace (the one that
currently includes
/(?<=^|[\s,>+~]|\))(?<!\[)\b([a-zñ][a-zñ0-9-]*)\b(?![([\]=])/gi) accordingly and
leave the selector lookup via selectorsDict.get(element.toLowerCase())
unchanged.
In `@packages/escss/src/utils/transformValue.ts`:
- Around line 76-78: En transformValue.ts la variable depth se decrementa sin
comprobar, lo que permite valores negativos si hay paréntesis de cierre
sobrantes; cambia la lógica dentro del bloque que maneja char === ')' para no
decrementar depth por debajo de 0 (p. ej. sólo hacer depth-- cuando depth > 0) y
seguir agregando el carácter a current; así la condición depth === 0 usada al
hacer split seguirá funcionando y evitará producir un token gigante.
In `@packages/escss/test/compile.test.ts`:
- Around line 34-43: El test 'should transform background properties' no
verifica la traducción de los valores de color; modifica la prueba en
packages/escss/test/compile.test.ts para usar la función compile(input, { from:
'escss', to: 'css' }) y además de comprobar que aparece 'background-color',
aserciona explícitamente las traducciones de los valores textuales: espera que
la salida contenga 'background-color: blue' para `color-fondo: azul` y
'background-color: red' para `fondo-color: rojo` (o ajusta la expectativa según
la semántica de sobrescritura si solo debe quedar uno); referencia la función
compile y el nombre del test para localizar el cambio.
- Around line 204-220: The test is asserting an invalid CSS value because the
translation dictionary maps the Spanish token "oculto" to "hidden" globally; for
the CSS property empty-cells the correct translated value is "hide". Update the
translation logic used by compile (the translation map or the function that
applies property-specific translations, e.g., the map object and the translator
function invoked by compile) to return "hide" when the target property is
"empty-cells" (or add a small conditional in the property/value translation
routine to map "oculto" -> "hide" when propName === "empty-cells"), keeping the
global mapping for other contexts unchanged.
In `@packages/esvue/package.json`:
- Around line 20-23: La dependencia `@es-js/escss` se está importando en tiempo de
ejecución desde packages/esvue/src/index.ts pero permanece listada en
devDependencies; mueve `@es-js/escss` de "devDependencies" a "dependencies" (o a
"peerDependencies" si prefieres exigir que el consumidor la provea) en
package.json para que esté disponible para los consumidores publicados;
actualiza la sección correspondiente en package.json y asegúrate de probar la
construcción/instalación para validar que la importación desde
packages/esvue/src/index.ts resuelva correctamente.
In `@packages/language-tools/package.json`:
- Around line 25-27: Agregar el campo "files" al package.json para asegurar que
los artefactos compilados en dist/ se incluyan al publicar; en el archivo
package.json del paquete (paquete identificado por "exports" que referencia
escss.tmLanguage.json y escss-language-configuration.json) añade "files":
["dist"] en la raíz del objeto JSON para forzar la inclusión de los ficheros
generados en dist/, de modo que los archivos referenciados por "exports" siempre
se publiquen incluso si .npmignore excluye otros archivos.
In `@packages/language-tools/src/generate-escss-syntax.js`:
- Around line 14-17: The keys returned by getEscssKeywords are later
interpolated into TextMate regexes and must be escaped; update getEscssKeywords
(or add a helper like escapeRegex) to map dictionary.keys() to escaped versions
by replacing/escaping all regex-special characters (e.g., . * + ? ^ $ { } ( ) |
[ ] \ /) before returning the array so generated grammar patterns remain valid.
- Around line 92-137: The grammar's rule-list pattern doesn't allow nested rules
because 'rule-list' currently only includes '#comment' and '#property'; update
the 'rule-list' patterns to also include recursive and surrounding rule patterns
(e.g., include '#rule-list' and '#selector' and '#at-rule' or whatever
selector/at-rule scopes exist) so that nested `{ ... }` blocks are parsed—modify
the 'rule-list' entry (symbol 'rule-list') to add includes for '#rule-list',
'#selector', and '#at-rule' alongside '#comment' and '#property' so nested rules
are recognized.
In `@packages/prettier-plugin-escss/src/index.ts`:
- Around line 69-81: El código está formateando el texto EsCSS original
(options.originalText) como si fuera CSS, lo que es frágil y engañoso; en lugar
de pasar options.originalText directo a format() con parser 'css', primero
transpila EsCSS a CSS usando EsCSSCompile(..., {from: 'escss', to: 'css'}),
luego pasa ese CSS resultante a format(css, { ..., parser: 'css' }), y por
último reconvierte el CSS formateado a EsCSS con EsCSSCompile(..., {from: 'css',
to: 'escss'}); actualiza la sección donde se usan format() y EsCSSCompile() (y
renombra la variable css si procede) para reflejar este flujo correcto, y
mantiene referencias a options.originalText and preprocess donde corresponda.
There was a problem hiding this comment.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/core/test/fixtures.test.ts (1)
148-151:⚠️ Potential issue | 🟡 MinorEl bloque
catchno retorna valor, causandoTypeErroren los callers en lugar del error real.Si
testCompilelanza una excepción, elcatchhaceconsole.errorpero retornaundefined. Los callers acceden aresult.generated(ej. línea 158), lo que produce unTypeError: Cannot read properties of undefinedque oculta el error original de compilación. Aunque es pre-existente, la lógica circundante ha cambiado y el riesgo afecta directamente a la depuración de fallos en estos tests.🐛 Propuesta: re-lanzar el error para preservar el diagnóstico
} catch (error) { console.error(`Error in ${fixture}`, error) + throw error }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/core/test/fixtures.test.ts` around lines 148 - 151, The catch block swallows exceptions causing callers that expect a result (e.g., code that reads result.generated) to get undefined and a misleading TypeError; modify the catch in the fixture runner to re-throw the caught error (or return a well-typed error result) so the original compilation error from testCompile is propagated to callers (locate the try/catch around testCompile and the code that accesses result.generated to apply the change).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@packages/core/test/compilers.test.ts`:
- Around line 37-42: Extract the duplicated string assigned to expectedEsbabel
into a module-level constant (similar to expectedJs) and replace the two local
expectedEsbabel definitions in the tests with that shared constant; locate the
occurrences by looking for the identifier expectedEsbabel in the test file
(packages/core/test/compilers.test.ts) and update both test blocks to reference
the new top-level constant instead of re-declaring the same literal.
In `@packages/core/test/testUtils.ts`:
- Around line 29-32: The helper normalizeJsForCompare currently passes
PRETTIER_OPTIONS redundantly into formatWithPrettier; change
normalizeJsForCompare to call formatWithPrettier(code) only, leaving
PRETTIER_OPTIONS to be applied by formatWithPrettier's internal spread logic
(refer to function names normalizeJsForCompare and formatWithPrettier and the
constant PRETTIER_OPTIONS).
- Around line 34-47: The tests assertCompile and assertJSToESJS call
compile(jsCode, { ...options, to: 'esjs' }) without specifying from, which
causes the compiler to default to 'esjs' and misinterpret plain JS; update every
compile invocation that passes jsCode (in assertCompile and assertJSToESJS) to
include from: 'js' in the options (e.g., compile(jsCode, { ...options, from:
'js', to: 'esjs' })) so the compile function is explicitly told the input
language; ensure corresponding round-trip compile calls that transform back to
'js' remain correct and keep use of normalizeJsForCompare unchanged.
---
Outside diff comments:
In `@packages/core/test/fixtures.test.ts`:
- Around line 148-151: The catch block swallows exceptions causing callers that
expect a result (e.g., code that reads result.generated) to get undefined and a
misleading TypeError; modify the catch in the fixture runner to re-throw the
caught error (or return a well-typed error result) so the original compilation
error from testCompile is propagated to callers (locate the try/catch around
testCompile and the code that accesses result.generated to apply the change).
702bed2 to
bc2b5e1
Compare
…sCSS values in translation maps
bc2b5e1 to
a4f864e
Compare

EsCSS: CSS con sintaxis en Español 🎨
Descripción
Este PR introduce EsCSS, un nuevo añadido al proyecto que permite escribir CSS usando propiedades, valores y selectores en español. Sigue los mismos patrones establecidos por EsJS, EsHTML y EsVue.
Ejemplo
¿Qué se agregó?
Nuevos paquetes
@es-js/escss@es-js/escss-generator@es-js/vite-plugin-escss.escss@es-js/prettier-plugin-escss.escssActualizaciones a paquetes existentes
@es-js/language-tools.escss(highlighting)@es-js/vscode-esjs.escssen VSCode@es-js/esvue<estilo>con EsCSSNueva demo
demos/demo-escss/- Proyecto de ejemplo con Vite¿Cómo funciona?
Arquitectura
Sistema de traducción
El generador usa un diccionario basado en palabras que traduce fragmentos de propiedades CSS:
Compilación bidireccional
¿Cómo probarlo?
1. Instalar dependencias
2. Construir los paquetes
3. Ejecutar la demo
cd demos/demo-escss pnpm devAbrir http://localhost:5173 en el navegador.
4. Ejecutar tests
Uso en un proyecto
Instalación
Configuración de Vite
Crear archivo .escss
Importar en HTML o JS
Características soportadas
Propiedades (300+)
mostrar,posicion,flex-direccion,cuadricula-plantilla-columnasmargen,relleno,borde,ancho,altofuente-familia,fuente-tamanio,texto-alinearcolor,fondo-color,borde-colorValores (370+)
ninguno,bloque,flex,cuadricularelativo,absoluto,fijo,pegajosofila,columna,centro,espacio-entrerojo,azul,verde-oscuro,azul-cielo-claro(140 colores)At-rules
@medios@media@fotogramas@keyframes@importar@import@fuente-cara@font-face@soporta@supportsPseudo-clases
:encima:hover:activo:active:enfoque:focus:primer-hijo:first-child:hijo-n():nth-child()Pseudo-elementos
::antes::before::despues::after::primera-linea::first-line::seleccion::selectionSelectores de elementos
cuerpobodybotonbuttonentradainputformularioformencabezadoheaderExports del paquete @es-js/escss
Checklist
<estilo>)Próximos pasos (fuera de este PR)
repetir(),trasladarY())Summary by CodeRabbit
Nuevas Características
Integraciones
Demo
Tests
Chores