ether-code 0.3.8 → 0.4.0

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.
@@ -103,209 +103,86 @@ class CSSGenerator {
103
103
 
104
104
  translateProperty(prop) {
105
105
  const lower = prop.toLowerCase()
106
- return this.propertyMap[lower] || this.translateGeneric(prop)
106
+ if (this.propertyMap && this.propertyMap[lower]) {
107
+ return this.propertyMap[lower]
108
+ }
109
+ return this.translateGeneric(prop)
107
110
  }
108
111
 
109
112
  translateValue(val) {
110
113
  if (typeof val !== 'string') return val
111
- const lower = val.toLowerCase()
112
114
 
113
- if (this.colorMap[lower]) {
114
- return this.colorMap[lower]
115
- }
115
+ let result = val
116
+ result = this.translateFunctions(result)
117
+ result = this.translateColors(result)
118
+ result = this.translateKeywords(result)
119
+
120
+ return result
121
+ }
122
+
123
+ translateFunctions(val) {
124
+ let result = val
125
+
126
+ result = result.replace(/utiliser:\s*([\w\u00C0-\u024F\-]+)/gi, (match, varName) => {
127
+ return `var(--${varName})`
128
+ })
116
129
 
117
- if (this.valueMap[lower]) {
118
- const mapped = this.valueMap[lower]
119
- if (typeof mapped === 'object' && mapped.type === 'animation') {
120
- return mapped
130
+ result = result.replace(/dégradé linéaire:\s*/gi, 'linear-gradient(')
131
+ result = result.replace(/degrade lineaire:\s*/gi, 'linear-gradient(')
132
+ result = result.replace(/dégradé radial:\s*/gi, 'radial-gradient(')
133
+ result = result.replace(/degrade radial:\s*/gi, 'radial-gradient(')
134
+ result = result.replace(/dégradé conique:\s*/gi, 'conic-gradient(')
135
+ result = result.replace(/degrade conique:\s*/gi, 'conic-gradient(')
136
+
137
+ result = result.replace(/rgba:\s*(\d+),\s*(\d+),\s*(\d+),\s*([\d.]+)/gi, 'rgba($1, $2, $3, $4)')
138
+ result = result.replace(/rgb:\s*(\d+),\s*(\d+),\s*(\d+)/gi, 'rgb($1, $2, $3)')
139
+ result = result.replace(/hsl:\s*(\d+),\s*([\d.]+%?),\s*([\d.]+%?)/gi, 'hsl($1, $2, $3)')
140
+ result = result.replace(/hsla:\s*(\d+),\s*([\d.]+%?),\s*([\d.]+%?),\s*([\d.]+)/gi, 'hsla($1, $2, $3, $4)')
141
+
142
+ result = result.replace(/flou:\s*([\d.]+\w*)/gi, 'blur($1)')
143
+ result = result.replace(/luminosité:\s*([\d.]+%?)/gi, 'brightness($1)')
144
+ result = result.replace(/luminosite:\s*([\d.]+%?)/gi, 'brightness($1)')
145
+ result = result.replace(/contraste:\s*([\d.]+%?)/gi, 'contrast($1)')
146
+ result = result.replace(/niveaux-gris:\s*([\d.]+%?)/gi, 'grayscale($1)')
147
+ result = result.replace(/niveaux gris:\s*([\d.]+%?)/gi, 'grayscale($1)')
148
+ result = result.replace(/inverser:\s*([\d.]+%?)/gi, 'invert($1)')
149
+ result = result.replace(/saturation:\s*([\d.]+%?)/gi, 'saturate($1)')
150
+ result = result.replace(/sépia:\s*([\d.]+%?)/gi, 'sepia($1)')
151
+ result = result.replace(/sepia:\s*([\d.]+%?)/gi, 'sepia($1)')
152
+ result = result.replace(/teinte:\s*([\d.]+\w*)/gi, 'hue-rotate($1)')
153
+
154
+ result = result.replace(/déplacer-y:\s*([\d.\-]+\w*)/gi, 'translateY($1)')
155
+ result = result.replace(/deplacer-y:\s*([\d.\-]+\w*)/gi, 'translateY($1)')
156
+ result = result.replace(/déplacer-x:\s*([\d.\-]+\w*)/gi, 'translateX($1)')
157
+ result = result.replace(/deplacer-x:\s*([\d.\-]+\w*)/gi, 'translateX($1)')
158
+ result = result.replace(/déplacer:\s*([\d.\-]+\w*),?\s*([\d.\-]+\w*)?/gi, (match, x, y) => {
159
+ if (y) return `translate(${x}, ${y})`
160
+ return `translate(${x})`
161
+ })
162
+ result = result.replace(/rotation:\s*([\d.\-]+\w*)/gi, 'rotate($1)')
163
+ result = result.replace(/échelle:\s*([\d.]+)/gi, 'scale($1)')
164
+ result = result.replace(/echelle:\s*([\d.]+)/gi, 'scale($1)')
165
+
166
+ result = result.replace(/répéter:\s*([^,]+),\s*minmax:\s*([^,]+),\s*([^\s\)]+)/gi, 'repeat($1, minmax($2, $3))')
167
+ result = result.replace(/repeter:\s*([^,]+),\s*minmax:\s*([^,]+),\s*([^\s\)]+)/gi, 'repeat($1, minmax($2, $3))')
168
+ result = result.replace(/minmax:\s*([^,]+),\s*([^\s\)]+)/gi, 'minmax($1, $2)')
169
+
170
+ result = result.replace(/calcul:\s*(.+)/gi, 'calc($1)')
171
+ result = result.replace(/minimum:\s*([^,]+),\s*([^\s\)]+)/gi, 'min($1, $2)')
172
+ result = result.replace(/maximum:\s*([^,]+),\s*([^\s\)]+)/gi, 'max($1, $2)')
173
+ result = result.replace(/borner:\s*([^,]+),\s*([^,]+),\s*([^\s\)]+)/gi, 'clamp($1, $2, $3)')
174
+
175
+ if (result.includes('linear-gradient(') || result.includes('radial-gradient(') || result.includes('conic-gradient(')) {
176
+ if (!result.endsWith(')')) {
177
+ result = result + ')'
121
178
  }
122
- return mapped
123
179
  }
124
180
 
125
- return this.translateGeneric(val)
181
+ return result
126
182
  }
127
183
 
128
- translateGeneric(text) {
129
- const translations = {
130
- 'couleur-fond': 'background-color',
131
- 'couleur-texte': 'color',
132
- 'couleur-bordure': 'border-color',
133
- 'couleur-primaire': '--color-primary',
134
- 'couleur-secondaire': '--color-secondary',
135
- 'couleur-accent': '--color-accent',
136
- 'couleur-surface': '--color-surface',
137
- 'couleur-texte-pale': '--color-text-muted',
138
- 'famille-police': 'font-family',
139
- 'taille-police': 'font-size',
140
- 'poids-police': 'font-weight',
141
- 'style-police': 'font-style',
142
- 'hauteur-ligne': 'line-height',
143
- 'espacement-lettres': 'letter-spacing',
144
- 'espacement-mots': 'word-spacing',
145
- 'texte-aligne': 'text-align',
146
- 'alignement-texte': 'text-align',
147
- 'decoration-texte': 'text-decoration',
148
- 'transformation-texte': 'text-transform',
149
- 'retrait-texte': 'text-indent',
150
- 'ombre-texte': 'text-shadow',
151
- 'debordement-texte': 'text-overflow',
152
- 'coupure-mot': 'word-break',
153
- 'retour-ligne': 'word-wrap',
154
- 'espace-blanc': 'white-space',
155
- 'marge-haut': 'margin-top',
156
- 'marge-bas': 'margin-bottom',
157
- 'marge-gauche': 'margin-left',
158
- 'marge-droite': 'margin-right',
159
- 'marge-bloc': 'margin-block',
160
- 'marge-en-ligne': 'margin-inline',
161
- 'remplissage-haut': 'padding-top',
162
- 'remplissage-bas': 'padding-bottom',
163
- 'remplissage-gauche': 'padding-left',
164
- 'remplissage-droite': 'padding-right',
165
- 'remplissage-bloc': 'padding-block',
166
- 'remplissage-en-ligne': 'padding-inline',
167
- 'bordure-haut': 'border-top',
168
- 'bordure-bas': 'border-bottom',
169
- 'bordure-gauche': 'border-left',
170
- 'bordure-droite': 'border-right',
171
- 'largeur-bordure': 'border-width',
172
- 'style-bordure': 'border-style',
173
- 'rayon-bordure': 'border-radius',
174
- 'rayon-haut-gauche': 'border-top-left-radius',
175
- 'rayon-haut-droite': 'border-top-right-radius',
176
- 'rayon-bas-gauche': 'border-bottom-left-radius',
177
- 'rayon-bas-droite': 'border-bottom-right-radius',
178
- 'ombre-boite': 'box-shadow',
179
- 'modele-boite': 'box-sizing',
180
- 'max-largeur': 'max-width',
181
- 'min-largeur': 'min-width',
182
- 'max-hauteur': 'max-height',
183
- 'min-hauteur': 'min-height',
184
- 'ajustement-objet': 'object-fit',
185
- 'position-objet': 'object-position',
186
- 'debordement-x': 'overflow-x',
187
- 'debordement-y': 'overflow-y',
188
- 'comportement-defilement': 'scroll-behavior',
189
- 'justifier-contenu': 'justify-content',
190
- 'aligner-elements': 'align-items',
191
- 'aligner-contenu': 'align-content',
192
- 'aligner-soi': 'align-self',
193
- 'justifier-soi': 'justify-self',
194
- 'justifier-elements': 'justify-items',
195
- 'direction-flex': 'flex-direction',
196
- 'enveloppe-flex': 'flex-wrap',
197
- 'flux-flex': 'flex-flow',
198
- 'croissance-flex': 'flex-grow',
199
- 'retrecissement-flex': 'flex-shrink',
200
- 'base-flex': 'flex-basis',
201
- 'ordre': 'order',
202
- 'colonnes-grille': 'grid-template-columns',
203
- 'lignes-grille': 'grid-template-rows',
204
- 'zones-grille': 'grid-template-areas',
205
- 'colonne-grille': 'grid-column',
206
- 'ligne-grille': 'grid-row',
207
- 'zone-grille': 'grid-area',
208
- 'ecart-grille': 'grid-gap',
209
- 'ecart-colonnes': 'column-gap',
210
- 'ecart-lignes': 'row-gap',
211
- 'flux-auto-grille': 'grid-auto-flow',
212
- 'colonnes-auto-grille': 'grid-auto-columns',
213
- 'lignes-auto-grille': 'grid-auto-rows',
214
- 'z-index': 'z-index',
215
- 'index-z': 'z-index',
216
- 'liste-style': 'list-style',
217
- 'type-liste': 'list-style-type',
218
- 'position-liste': 'list-style-position',
219
- 'image-liste': 'list-style-image',
220
- 'duree-transition': 'transition-duration',
221
- 'delai-transition': 'transition-delay',
222
- 'propriete-transition': 'transition-property',
223
- 'fonction-transition': 'transition-timing-function',
224
- 'nom-animation': 'animation-name',
225
- 'duree-animation': 'animation-duration',
226
- 'delai-animation': 'animation-delay',
227
- 'fonction-animation': 'animation-timing-function',
228
- 'iteration-animation': 'animation-iteration-count',
229
- 'direction-animation': 'animation-direction',
230
- 'remplissage-animation': 'animation-fill-mode',
231
- 'etat-animation': 'animation-play-state',
232
- 'origine-transformation': 'transform-origin',
233
- 'style-transformation': 'transform-style',
234
- 'perspective': 'perspective',
235
- 'origine-perspective': 'perspective-origin',
236
- 'face-arriere': 'backface-visibility',
237
- 'flou-fond': 'backdrop-filter',
238
- 'mode-melange': 'mix-blend-mode',
239
- 'mode-melange-fond': 'background-blend-mode',
240
- 'image-fond': 'background-image',
241
- 'position-fond': 'background-position',
242
- 'taille-fond': 'background-size',
243
- 'repetition-fond': 'background-repeat',
244
- 'attachement-fond': 'background-attachment',
245
- 'origine-fond': 'background-origin',
246
- 'decoupe-fond': 'background-clip',
247
- 'selection-utilisateur': 'user-select',
248
- 'evenements-pointeur': 'pointer-events',
249
- 'accrochage-defilement': 'scroll-snap-type',
250
- 'alignement-accrochage': 'scroll-snap-align',
251
- 'redimensionnement': 'resize',
252
- 'apparence': 'appearance',
253
- 'contour': 'outline',
254
- 'largeur-contour': 'outline-width',
255
- 'style-contour': 'outline-style',
256
- 'couleur-contour': 'outline-color',
257
- 'decalage-contour': 'outline-offset',
258
- 'compteur-reset': 'counter-reset',
259
- 'compteur-increment': 'counter-increment',
260
- 'guillemets': 'quotes',
261
- 'coupure-colonne': 'break-inside',
262
- 'orphelins': 'orphans',
263
- 'veuves': 'widows',
264
- 'fond': 'background',
265
- 'couleur': 'color',
266
- 'police': 'font-family',
267
- 'taille': 'font-size',
268
- 'poids': 'font-weight',
269
- 'style': 'font-style',
270
- 'alignement': 'text-align',
271
- 'decoration': 'text-decoration',
272
- 'transformation': 'transform',
273
- 'debordement': 'overflow',
274
- 'largeur': 'width',
275
- 'hauteur': 'height',
276
- 'marge': 'margin',
277
- 'remplissage': 'padding',
278
- 'bordure': 'border',
279
- 'arrondi': 'border-radius',
280
- 'ombre': 'box-shadow',
281
- 'affichage': 'display',
282
- 'position': 'position',
283
- 'haut': 'top',
284
- 'bas': 'bottom',
285
- 'gauche': 'left',
286
- 'droite': 'right',
287
- 'z': 'z-index',
288
- 'opacite': 'opacity',
289
- 'curseur': 'cursor',
290
- 'transition': 'transition',
291
- 'animation': 'animation',
292
- 'filtre': 'filter',
293
- 'ajustement': 'object-fit',
294
- 'selection': 'user-select',
295
- 'redimensionner': 'resize',
296
- 'visibilite': 'visibility',
297
- 'flex': 'flex',
298
- 'grille': 'grid',
299
- 'colonnes': 'grid-template-columns',
300
- 'lignes': 'grid-template-rows',
301
- 'zone': 'grid-area',
302
- 'ecart': 'gap',
303
- 'espace': 'gap',
304
- 'direction': 'flex-direction',
305
- 'envelopper': 'flex-wrap',
306
- 'justifier': 'justify-content',
307
- 'aligner': 'align-items',
308
- 'contenu': 'content',
184
+ translateColors(val) {
185
+ const colorMap = {
309
186
  'blanc': 'white',
310
187
  'noir': 'black',
311
188
  'rouge': 'red',
@@ -316,55 +193,301 @@ class CSSGenerator {
316
193
  'violet': 'purple',
317
194
  'rose': 'pink',
318
195
  'gris': 'gray',
319
- 'transparent': 'transparent',
320
- 'heriter': 'inherit',
321
- 'initial': 'initial',
196
+ 'cyan': 'cyan',
197
+ 'magenta': 'magenta',
198
+ 'turquoise': 'turquoise',
199
+ 'beige': 'beige',
200
+ 'or': 'gold',
201
+ 'argent': 'silver',
202
+ 'corail': 'coral',
203
+ 'saumon': 'salmon',
204
+ 'olive': 'olive',
205
+ 'marine': 'navy',
206
+ 'bordeaux': 'maroon',
207
+ 'kaki': 'khaki',
208
+ 'ivoire': 'ivory',
209
+ 'indigo': 'indigo',
210
+ 'lavande': 'lavender',
211
+ 'prune': 'plum',
212
+ 'chocolat': 'chocolate',
213
+ 'transparent': 'transparent'
214
+ }
215
+
216
+ let result = val
217
+ for (const [fr, en] of Object.entries(colorMap)) {
218
+ const regex = new RegExp(`\\b${fr}\\b`, 'gi')
219
+ result = result.replace(regex, en)
220
+ }
221
+ return result
222
+ }
223
+
224
+ translateKeywords(val) {
225
+ const keywords = {
322
226
  'aucun': 'none',
227
+ 'aucune': 'none',
323
228
  'auto': 'auto',
229
+ 'hériter': 'inherit',
230
+ 'heriter': 'inherit',
231
+ 'initial': 'initial',
232
+ 'caché': 'hidden',
324
233
  'cache': 'hidden',
325
234
  'visible': 'visible',
235
+ 'défiler': 'scroll',
326
236
  'defiler': 'scroll',
327
237
  'fixe': 'fixed',
238
+ 'fixée': 'fixed',
239
+ 'fixee': 'fixed',
240
+ 'absolue': 'absolute',
328
241
  'absolu': 'absolute',
242
+ 'relative': 'relative',
329
243
  'relatif': 'relative',
330
244
  'statique': 'static',
331
245
  'collant': 'sticky',
246
+ 'collante': 'sticky',
332
247
  'centre': 'center',
248
+ 'centré': 'center',
249
+ 'début': 'flex-start',
333
250
  'debut': 'flex-start',
334
251
  'fin': 'flex-end',
335
- 'entre': 'space-between',
336
- 'autour': 'space-around',
337
- 'egal': 'space-evenly',
252
+ 'espace-entre': 'space-between',
253
+ 'espace entre': 'space-between',
254
+ 'espace-autour': 'space-around',
255
+ 'espace autour': 'space-around',
256
+ 'espace-égal': 'space-evenly',
257
+ 'espace egal': 'space-evenly',
258
+ 'étirer': 'stretch',
338
259
  'etirer': 'stretch',
339
260
  'ligne': 'row',
340
261
  'colonne': 'column',
341
- 'inverser': 'reverse',
262
+ 'ligne-inverse': 'row-reverse',
263
+ 'ligne inverse': 'row-reverse',
264
+ 'colonne-inverse': 'column-reverse',
265
+ 'colonne inverse': 'column-reverse',
266
+ 'envelopper': 'wrap',
267
+ 'sans-retour': 'nowrap',
268
+ 'sans retour': 'nowrap',
342
269
  'gras': 'bold',
343
270
  'normal': 'normal',
344
271
  'italique': 'italic',
272
+ 'souligné': 'underline',
345
273
  'souligne': 'underline',
274
+ 'barré': 'line-through',
346
275
  'barre': 'line-through',
347
276
  'majuscules': 'uppercase',
348
277
  'minuscules': 'lowercase',
349
278
  'capitaliser': 'capitalize',
350
279
  'pointeur': 'pointer',
351
280
  'attente': 'wait',
352
- 'texte': 'text',
353
281
  'interdit': 'not-allowed',
354
282
  'couvrir': 'cover',
355
283
  'contenir': 'contain',
356
284
  'remplir': 'fill',
357
285
  'bloc': 'block',
358
286
  'en-ligne': 'inline',
287
+ 'en ligne': 'inline',
359
288
  'bloc-en-ligne': 'inline-block',
289
+ 'bloc en ligne': 'inline-block',
360
290
  'flex-en-ligne': 'inline-flex',
291
+ 'flex en ligne': 'inline-flex',
292
+ 'grille': 'grid',
361
293
  'grille-en-ligne': 'inline-grid',
362
- 'espace-blanc': 'white-space',
363
- 'blanc-espace': 'white-space',
364
- 'pre': 'pre',
294
+ 'grille en ligne': 'inline-grid',
295
+ 'préservé': 'pre',
296
+ 'preserve': 'pre',
297
+ 'pré-ligne': 'pre-line',
365
298
  'pre-ligne': 'pre-line',
299
+ 'pré-enveloppe': 'pre-wrap',
366
300
  'pre-enveloppe': 'pre-wrap',
367
- 'sans-retour': 'nowrap'
301
+ 'solide': 'solid',
302
+ 'pointillée': 'dotted',
303
+ 'pointillee': 'dotted',
304
+ 'tirets': 'dashed',
305
+ 'double': 'double',
306
+ 'tout': 'all',
307
+ 'ease': 'ease',
308
+ 'ease-in': 'ease-in',
309
+ 'ease-out': 'ease-out',
310
+ 'ease-in-out': 'ease-in-out',
311
+ 'linéaire': 'linear',
312
+ 'lineaire': 'linear'
313
+ }
314
+
315
+ let result = val
316
+
317
+ const varPlaceholders = []
318
+ result = result.replace(/var\(--[\w\u00C0-\u024F\-]+\)/gi, (match) => {
319
+ varPlaceholders.push(match)
320
+ return `__VAR_PLACEHOLDER_${varPlaceholders.length - 1}__`
321
+ })
322
+
323
+ for (const [fr, en] of Object.entries(keywords)) {
324
+ const regex = new RegExp(`\\b${fr}\\b`, 'gi')
325
+ result = result.replace(regex, en)
326
+ }
327
+
328
+ if (result === val) {
329
+ const lower = val.toLowerCase()
330
+ if (lower === 'texte') return 'text'
331
+ }
332
+
333
+ for (let i = 0; i < varPlaceholders.length; i++) {
334
+ result = result.replace(`__VAR_PLACEHOLDER_${i}__`, varPlaceholders[i])
335
+ }
336
+
337
+ return result
338
+ }
339
+
340
+ translateGeneric(text) {
341
+ const translations = {
342
+ 'couleur': 'color',
343
+ 'fond': 'background',
344
+ 'police': 'font-family',
345
+ 'taille police': 'font-size',
346
+ 'taille-police': 'font-size',
347
+ 'poids police': 'font-weight',
348
+ 'poids-police': 'font-weight',
349
+ 'style police': 'font-style',
350
+ 'style-police': 'font-style',
351
+ 'hauteur ligne': 'line-height',
352
+ 'hauteur-ligne': 'line-height',
353
+ 'espacement-lettres': 'letter-spacing',
354
+ 'espacement lettres': 'letter-spacing',
355
+ 'alignement-texte': 'text-align',
356
+ 'alignement texte': 'text-align',
357
+ 'décoration-texte': 'text-decoration',
358
+ 'décoration texte': 'text-decoration',
359
+ 'decoration-texte': 'text-decoration',
360
+ 'decoration texte': 'text-decoration',
361
+ 'transformation-texte': 'text-transform',
362
+ 'transformation texte': 'text-transform',
363
+ 'ombre-texte': 'text-shadow',
364
+ 'ombre texte': 'text-shadow',
365
+ 'marge': 'margin',
366
+ 'marge haut': 'margin-top',
367
+ 'marge-haut': 'margin-top',
368
+ 'marge bas': 'margin-bottom',
369
+ 'marge-bas': 'margin-bottom',
370
+ 'marge gauche': 'margin-left',
371
+ 'marge-gauche': 'margin-left',
372
+ 'marge droite': 'margin-right',
373
+ 'marge-droite': 'margin-right',
374
+ 'marge dedans': 'padding',
375
+ 'marge-dedans': 'padding',
376
+ 'marge dedans haut': 'padding-top',
377
+ 'marge-dedans-haut': 'padding-top',
378
+ 'marge dedans bas': 'padding-bottom',
379
+ 'marge-dedans-bas': 'padding-bottom',
380
+ 'marge dedans gauche': 'padding-left',
381
+ 'marge-dedans-gauche': 'padding-left',
382
+ 'marge dedans droite': 'padding-right',
383
+ 'marge-dedans-droite': 'padding-right',
384
+ 'bordure': 'border',
385
+ 'bordure haut': 'border-top',
386
+ 'bordure-haut': 'border-top',
387
+ 'bordure bas': 'border-bottom',
388
+ 'bordure-bas': 'border-bottom',
389
+ 'bordure gauche': 'border-left',
390
+ 'bordure-gauche': 'border-left',
391
+ 'bordure droite': 'border-right',
392
+ 'bordure-droite': 'border-right',
393
+ 'couleur-bordure': 'border-color',
394
+ 'couleur bordure': 'border-color',
395
+ 'arrondi': 'border-radius',
396
+ 'largeur': 'width',
397
+ 'hauteur': 'height',
398
+ 'largeur minimum': 'min-width',
399
+ 'largeur-minimum': 'min-width',
400
+ 'largeur maximum': 'max-width',
401
+ 'largeur-maximum': 'max-width',
402
+ 'hauteur minimum': 'min-height',
403
+ 'hauteur-minimum': 'min-height',
404
+ 'hauteur maximum': 'max-height',
405
+ 'hauteur-maximum': 'max-height',
406
+ 'affichage': 'display',
407
+ 'position': 'position',
408
+ 'haut': 'top',
409
+ 'bas': 'bottom',
410
+ 'gauche': 'left',
411
+ 'droite': 'right',
412
+ 'index-z': 'z-index',
413
+ 'z-index': 'z-index',
414
+ 'débordement': 'overflow',
415
+ 'debordement': 'overflow',
416
+ 'débordement-x': 'overflow-x',
417
+ 'debordement-x': 'overflow-x',
418
+ 'débordement-y': 'overflow-y',
419
+ 'debordement-y': 'overflow-y',
420
+ 'opacité': 'opacity',
421
+ 'opacite': 'opacity',
422
+ 'curseur': 'cursor',
423
+ 'transition': 'transition',
424
+ 'animation': 'animation',
425
+ 'transformation': 'transform',
426
+ 'filtre': 'filter',
427
+ 'filtre-fond': 'backdrop-filter',
428
+ 'filtre fond': 'backdrop-filter',
429
+ 'ombre-boîte': 'box-shadow',
430
+ 'ombre-boite': 'box-shadow',
431
+ 'ombre boîte': 'box-shadow',
432
+ 'ombre boite': 'box-shadow',
433
+ 'modèle-boîte': 'box-sizing',
434
+ 'modele-boite': 'box-sizing',
435
+ 'modèle boîte': 'box-sizing',
436
+ 'modele boite': 'box-sizing',
437
+ 'espace': 'gap',
438
+ 'espace ligne': 'row-gap',
439
+ 'espace-ligne': 'row-gap',
440
+ 'espace colonne': 'column-gap',
441
+ 'espace-colonne': 'column-gap',
442
+ 'justifier-contenu': 'justify-content',
443
+ 'justifier contenu': 'justify-content',
444
+ 'aligner-éléments': 'align-items',
445
+ 'aligner-elements': 'align-items',
446
+ 'aligner éléments': 'align-items',
447
+ 'aligner elements': 'align-items',
448
+ 'aligner-contenu': 'align-content',
449
+ 'aligner contenu': 'align-content',
450
+ 'direction-flex': 'flex-direction',
451
+ 'direction flex': 'flex-direction',
452
+ 'enveloppe-flex': 'flex-wrap',
453
+ 'enveloppe flex': 'flex-wrap',
454
+ 'flex': 'flex',
455
+ 'grille': 'display',
456
+ 'colonnes-grille': 'grid-template-columns',
457
+ 'colonnes grille': 'grid-template-columns',
458
+ 'lignes-grille': 'grid-template-rows',
459
+ 'lignes grille': 'grid-template-rows',
460
+ 'style-liste': 'list-style',
461
+ 'style liste': 'list-style',
462
+ 'contenu': 'content',
463
+ 'évènements-pointeur': 'pointer-events',
464
+ 'evenements-pointeur': 'pointer-events',
465
+ 'évènements pointeur': 'pointer-events',
466
+ 'evenements pointeur': 'pointer-events',
467
+ 'découpe-fond': 'background-clip',
468
+ 'decoupe-fond': 'background-clip',
469
+ 'découpe fond': 'background-clip',
470
+ 'decoupe fond': 'background-clip',
471
+ 'couleur-remplissage-texte': '-webkit-text-fill-color',
472
+ 'couleur remplissage texte': '-webkit-text-fill-color',
473
+ 'espace-blanc': 'white-space',
474
+ 'espace blanc': 'white-space',
475
+ 'taille': 'font-size',
476
+ 'poids': 'font-weight',
477
+ 'style': 'font-style',
478
+ 'alignement': 'text-align',
479
+ 'decoration': 'text-decoration',
480
+ 'ombre': 'box-shadow',
481
+ 'ecart': 'gap',
482
+ 'direction': 'flex-direction',
483
+ 'envelopper': 'flex-wrap',
484
+ 'justifier': 'justify-content',
485
+ 'aligner': 'align-items',
486
+ 'visibilite': 'visibility',
487
+ 'visibilité': 'visibility',
488
+ 'redimensionnement': 'resize',
489
+ 'apparence': 'appearance',
490
+ 'contour': 'outline'
368
491
  }
369
492
 
370
493
  const lower = text.toLowerCase()
@@ -374,30 +497,91 @@ class CSSGenerator {
374
497
  translateSelector(selector) {
375
498
  let result = selector
376
499
 
377
- result = result.replace(/au survol/gi, ':hover')
378
- result = result.replace(/au clic/gi, ':active')
379
- result = result.replace(/au focus/gi, ':focus')
380
- result = result.replace(/au focus dans/gi, ':focus-within')
381
- result = result.replace(/visite/gi, ':visited')
382
- result = result.replace(/premier enfant/gi, ':first-child')
383
- result = result.replace(/dernier enfant/gi, ':last-child')
384
- result = result.replace(/enfant impair/gi, ':nth-child(odd)')
385
- result = result.replace(/enfant pair/gi, ':nth-child(even)')
386
- result = result.replace(/avant/gi, '::before')
387
- result = result.replace(/apres/gi, '::after')
388
- result = result.replace(/selection/gi, '::selection')
389
- result = result.replace(/placeholder/gi, '::placeholder')
390
- result = result.replace(/premiere lettre/gi, '::first-letter')
391
- result = result.replace(/premiere ligne/gi, '::first-line')
392
- result = result.replace(/coche/gi, ':checked')
393
- result = result.replace(/desactive/gi, ':disabled')
394
- result = result.replace(/active/gi, ':enabled')
395
- result = result.replace(/requis/gi, ':required')
396
- result = result.replace(/optionnel/gi, ':optional')
397
- result = result.replace(/valide/gi, ':valid')
398
- result = result.replace(/invalide/gi, ':invalid')
399
- result = result.replace(/vide/gi, ':empty')
400
- result = result.replace(/racine/gi, ':root')
500
+ result = result.replace(/:racine\b/gi, ':root')
501
+ result = result.replace(/::avant\b/gi, '::before')
502
+ result = result.replace(/::après\b/gi, '::after')
503
+ result = result.replace(/::apres\b/gi, '::after')
504
+ result = result.replace(/::première-lettre\b/gi, '::first-letter')
505
+ result = result.replace(/::premiere-lettre\b/gi, '::first-letter')
506
+ result = result.replace(/::première-ligne\b/gi, '::first-line')
507
+ result = result.replace(/::premiere-ligne\b/gi, '::first-line')
508
+ result = result.replace(/::sélection\b/gi, '::selection')
509
+ result = result.replace(/::selection\b/gi, '::selection')
510
+ result = result.replace(/::marqueur\b/gi, '::marker')
511
+
512
+ result = result.replace(/\bau survol\b/gi, ':hover')
513
+ result = result.replace(/\bquand survolé\b/gi, ':hover')
514
+ result = result.replace(/\bquand survole\b/gi, ':hover')
515
+ result = result.replace(/\ben survol\b/gi, ':hover')
516
+ result = result.replace(/\bau clic\b/gi, ':active')
517
+ result = result.replace(/\bquand cliqué\b/gi, ':active')
518
+ result = result.replace(/\bquand clique\b/gi, ':active')
519
+ result = result.replace(/\ben clic\b/gi, ':active')
520
+ result = result.replace(/\bactif\b/gi, ':active')
521
+ result = result.replace(/\bau focus\b/gi, ':focus')
522
+ result = result.replace(/\bquand focalisé\b/gi, ':focus')
523
+ result = result.replace(/\bquand focalise\b/gi, ':focus')
524
+ result = result.replace(/\ben focus\b/gi, ':focus')
525
+ result = result.replace(/\bau focus dans\b/gi, ':focus-within')
526
+ result = result.replace(/\bvisité\b/gi, ':visited')
527
+ result = result.replace(/\bvisite\b/gi, ':visited')
528
+
529
+ result = result.replace(/\s+(:hover|:active|:focus|:focus-within|:visited|:checked|:disabled|:enabled|:required|:optional|:valid|:invalid|:empty|:target)/gi, '$1')
530
+ result = result.replace(/\bpremier enfant\b/gi, ':first-child')
531
+ result = result.replace(/\bdernier enfant\b/gi, ':last-child')
532
+ result = result.replace(/\benfant impair\b/gi, ':nth-child(odd)')
533
+ result = result.replace(/\benfant pair\b/gi, ':nth-child(even)')
534
+ result = result.replace(/\bpremier de type\b/gi, ':first-of-type')
535
+ result = result.replace(/\bdernier de type\b/gi, ':last-of-type')
536
+ result = result.replace(/\benfant unique\b/gi, ':only-child')
537
+ result = result.replace(/\bunique de type\b/gi, ':only-of-type')
538
+ result = result.replace(/\bvide\b/gi, ':empty')
539
+ result = result.replace(/\bcible\b/gi, ':target')
540
+ result = result.replace(/\bcoché\b/gi, ':checked')
541
+ result = result.replace(/\bcoche\b/gi, ':checked')
542
+ result = result.replace(/\bdésactivé\b/gi, ':disabled')
543
+ result = result.replace(/\bdesactive\b/gi, ':disabled')
544
+ result = result.replace(/\bactivé\b/gi, ':enabled')
545
+ result = result.replace(/\brequis\b/gi, ':required')
546
+ result = result.replace(/\boptionnel\b/gi, ':optional')
547
+ result = result.replace(/\bvalide\b/gi, ':valid')
548
+ result = result.replace(/\binvalide\b/gi, ':invalid')
549
+
550
+ result = result.replace(/\bcorps\b/gi, 'body')
551
+ result = result.replace(/\btête\b/gi, 'head')
552
+ result = result.replace(/\btete\b/gi, 'head')
553
+ result = result.replace(/\btitre1\b/gi, 'h1')
554
+ result = result.replace(/\btitre2\b/gi, 'h2')
555
+ result = result.replace(/\btitre3\b/gi, 'h3')
556
+ result = result.replace(/\btitre4\b/gi, 'h4')
557
+ result = result.replace(/\btitre5\b/gi, 'h5')
558
+ result = result.replace(/\btitre6\b/gi, 'h6')
559
+ result = result.replace(/\bparagraphe\b/gi, 'p')
560
+ result = result.replace(/\blien\b/gi, 'a')
561
+ result = result.replace(/\bimage\b/gi, 'img')
562
+ result = result.replace(/\bbouton\b/gi, 'button')
563
+ result = result.replace(/\bformulaire\b/gi, 'form')
564
+ result = result.replace(/\bchamp\b/gi, 'input')
565
+ result = result.replace(/\bliste\b/gi, 'ul')
566
+ result = result.replace(/\bliste-ordonnée\b/gi, 'ol')
567
+ result = result.replace(/\bliste-ordonnee\b/gi, 'ol')
568
+ result = result.replace(/\bélément-liste\b/gi, 'li')
569
+ result = result.replace(/\belement-liste\b/gi, 'li')
570
+ result = result.replace(/\btableau\b/gi, 'table')
571
+ result = result.replace(/\bligne-tableau\b/gi, 'tr')
572
+ result = result.replace(/\bcellule\b/gi, 'td')
573
+ result = result.replace(/\bentête\b/gi, 'header')
574
+ result = result.replace(/\bentete\b/gi, 'header')
575
+ result = result.replace(/\bpied\b/gi, 'footer')
576
+ result = result.replace(/\bnavigation\b/gi, 'nav')
577
+ result = result.replace(/\bsection\b/gi, 'section')
578
+ result = result.replace(/\barticle\b/gi, 'article')
579
+ result = result.replace(/\bcôté\b/gi, 'aside')
580
+ result = result.replace(/\bcote\b/gi, 'aside')
581
+ result = result.replace(/\bprincipal\b/gi, 'main')
582
+ result = result.replace(/\bdivision\b/gi, 'div')
583
+ result = result.replace(/\bportée\b/gi, 'span')
584
+ result = result.replace(/\bportee\b/gi, 'span')
401
585
 
402
586
  return result
403
587
  }
@@ -427,12 +611,13 @@ class CSSGenerator {
427
611
  'fr': 'fr'
428
612
  }
429
613
 
614
+ let result = value
430
615
  for (const [fr, css] of Object.entries(unitMap)) {
431
616
  const regex = new RegExp(`(\\d+(?:\\.\\d+)?)\\s*${fr}\\b`, 'gi')
432
- value = value.replace(regex, `$1${css}`)
617
+ result = result.replace(regex, `$1${css}`)
433
618
  }
434
619
 
435
- return value
620
+ return result
436
621
  }
437
622
 
438
623
  generate(ast) {
@@ -482,6 +667,10 @@ class CSSGenerator {
482
667
  case 'mediaQuery':
483
668
  this.generateMediaQuery(node)
484
669
  break
670
+ case 'Condition':
671
+ case 'condition':
672
+ this.generateCondition(node)
673
+ break
485
674
  case 'FontFace':
486
675
  case 'fontFace':
487
676
  this.generateFontFace(node)
@@ -537,7 +726,7 @@ class CSSGenerator {
537
726
  let value = decl.value
538
727
 
539
728
  if (isRoot) {
540
- property = '--' + property.toLowerCase()
729
+ property = '--' + property.toLowerCase().replace(/\s+/g, '-')
541
730
  } else {
542
731
  property = this.translateProperty(property)
543
732
  }
@@ -554,6 +743,18 @@ class CSSGenerator {
554
743
  value += ' !important'
555
744
  }
556
745
 
746
+ const needsWebkitPrefix = [
747
+ 'background-clip',
748
+ 'box-decoration-break',
749
+ 'text-stroke',
750
+ 'text-stroke-width',
751
+ 'text-stroke-color'
752
+ ]
753
+
754
+ if (needsWebkitPrefix.includes(property) && !property.startsWith('-webkit-')) {
755
+ this.writeLine(`-webkit-${property}: ${value};`)
756
+ }
757
+
557
758
  this.writeLine(`${property}: ${value};`)
558
759
  }
559
760
 
@@ -620,27 +821,79 @@ class CSSGenerator {
620
821
  generateMediaQuery(node) {
621
822
  let query = node.query || node.condition || ''
622
823
 
623
- query = query.replace(/ecran/gi, 'screen')
624
- query = query.replace(/imprimante/gi, 'print')
625
- query = query.replace(/tous/gi, 'all')
626
- query = query.replace(/largeur-min/gi, 'min-width')
627
- query = query.replace(/largeur min/gi, 'min-width')
628
- query = query.replace(/largeur-max/gi, 'max-width')
629
- query = query.replace(/largeur max/gi, 'max-width')
630
- query = query.replace(/max-largeur/gi, 'max-width')
631
- query = query.replace(/min-largeur/gi, 'min-width')
632
- query = query.replace(/hauteur-min/gi, 'min-height')
633
- query = query.replace(/hauteur min/gi, 'min-height')
634
- query = query.replace(/hauteur-max/gi, 'max-height')
635
- query = query.replace(/hauteur max/gi, 'max-height')
636
- query = query.replace(/max-hauteur/gi, 'max-height')
637
- query = query.replace(/min-hauteur/gi, 'min-height')
638
- query = query.replace(/orientation/gi, 'orientation')
639
- query = query.replace(/paysage/gi, 'landscape')
640
- query = query.replace(/portrait/gi, 'portrait')
641
- query = query.replace(/et/gi, 'and')
642
- query = query.replace(/ou/gi, 'or')
643
- query = query.replace(/pas/gi, 'not')
824
+ query = this.translateMediaQuery(query)
825
+
826
+ this.writeLine(`@media ${query} {`)
827
+ this.indent++
828
+
829
+ const rules = node.rules || node.children || []
830
+ for (const rule of rules) {
831
+ this.generateNode(rule)
832
+ }
833
+
834
+ this.indent--
835
+ this.writeLine('}')
836
+ this.writeLine('')
837
+ }
838
+
839
+ translateMediaQuery(query) {
840
+ let result = query
841
+
842
+ result = result.replace(/écran/gi, 'screen')
843
+ result = result.replace(/ecran/gi, 'screen')
844
+ result = result.replace(/imprimante/gi, 'print')
845
+ result = result.replace(/tous/gi, 'all')
846
+ result = result.replace(/largeur-min/gi, 'min-width')
847
+ result = result.replace(/largeur min/gi, 'min-width')
848
+ result = result.replace(/largeur-max/gi, 'max-width')
849
+ result = result.replace(/largeur max/gi, 'max-width')
850
+ result = result.replace(/max-largeur/gi, 'max-width')
851
+ result = result.replace(/min-largeur/gi, 'min-width')
852
+ result = result.replace(/hauteur-min/gi, 'min-height')
853
+ result = result.replace(/hauteur min/gi, 'min-height')
854
+ result = result.replace(/hauteur-max/gi, 'max-height')
855
+ result = result.replace(/hauteur max/gi, 'max-height')
856
+ result = result.replace(/max-hauteur/gi, 'max-height')
857
+ result = result.replace(/min-hauteur/gi, 'min-height')
858
+ result = result.replace(/orientation/gi, 'orientation')
859
+ result = result.replace(/paysage/gi, 'landscape')
860
+ result = result.replace(/portrait/gi, 'portrait')
861
+ result = result.replace(/\bet\b/gi, 'and')
862
+ result = result.replace(/\bou\b/gi, 'or')
863
+ result = result.replace(/\bpas\b/gi, 'not')
864
+
865
+ return result
866
+ }
867
+
868
+ generateCondition(node) {
869
+ let condition = node.condition || ''
870
+ let query = ''
871
+
872
+ const plusPetitMatch = condition.match(/plus petit que\s+([\d.]+\w*)/i)
873
+ const plusGrandMatch = condition.match(/plus grand que\s+([\d.]+\w*)/i)
874
+ const inferieurMatch = condition.match(/inférieur[e]?\s+à\s+([\d.]+\w*)/i) || condition.match(/inferieur[e]?\s+a\s+([\d.]+\w*)/i)
875
+ const superieurMatch = condition.match(/supérieur[e]?\s+à\s+([\d.]+\w*)/i) || condition.match(/superieur[e]?\s+a\s+([\d.]+\w*)/i)
876
+ const egalMatch = condition.match(/égal[e]?\s+à\s+([\d.]+\w*)/i) || condition.match(/egal[e]?\s+a\s+([\d.]+\w*)/i)
877
+ const simpleInfMatch = condition.match(/<\s*([\d.]+\w*)/i)
878
+ const simpleSupMatch = condition.match(/>\s*([\d.]+\w*)/i)
879
+
880
+ if (plusPetitMatch) {
881
+ query = `(max-width: ${plusPetitMatch[1]})`
882
+ } else if (plusGrandMatch) {
883
+ query = `(min-width: ${plusGrandMatch[1]})`
884
+ } else if (inferieurMatch) {
885
+ query = `(max-width: ${inferieurMatch[1]})`
886
+ } else if (superieurMatch) {
887
+ query = `(min-width: ${superieurMatch[1]})`
888
+ } else if (egalMatch) {
889
+ query = `(width: ${egalMatch[1]})`
890
+ } else if (simpleInfMatch) {
891
+ query = `(max-width: ${simpleInfMatch[1]})`
892
+ } else if (simpleSupMatch) {
893
+ query = `(min-width: ${simpleSupMatch[1]})`
894
+ } else {
895
+ query = this.translateMediaQuery(condition)
896
+ }
644
897
 
645
898
  this.writeLine(`@media ${query} {`)
646
899
  this.indent++