ether-code 0.6.1 → 0.6.3

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.
@@ -12,6 +12,8 @@ class HTMLGenerator {
12
12
  'area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input',
13
13
  'link', 'meta', 'param', 'source', 'track', 'wbr'
14
14
  ]
15
+ this.multiWordTags = []
16
+ this.multiWordAttrs = []
15
17
 
16
18
  if (i18nPath) {
17
19
  this.loadI18n(i18nPath)
@@ -28,86 +30,154 @@ class HTMLGenerator {
28
30
  this.tagMap = {}
29
31
  this.attrMap = {}
30
32
  this.eventMap = {}
33
+ this.multiWordTags = []
34
+ this.multiWordAttrs = []
31
35
 
32
36
  if (!this.i18n) return
33
37
 
34
- const addToMap = (map, section, targetKey = 'html') => {
38
+ const addToTagMap = (section) => {
35
39
  if (!section) return
36
40
  for (const [key, translations] of Object.entries(section)) {
37
- if (translations && translations.fr && translations[targetKey]) {
38
- map[translations.fr.toLowerCase()] = translations[targetKey]
41
+ if (translations && translations.fr && translations.html) {
42
+ const frTerm = translations.fr.toLowerCase()
43
+ this.tagMap[frTerm] = translations.html
44
+ if (frTerm.includes(' ')) {
45
+ this.multiWordTags.push(frTerm)
46
+ }
47
+ }
48
+ }
49
+ }
50
+
51
+ const addToAttrMap = (section) => {
52
+ if (!section) return
53
+ for (const [key, translations] of Object.entries(section)) {
54
+ if (translations && translations.fr && translations.html) {
55
+ const frTerm = translations.fr.toLowerCase()
56
+ this.attrMap[frTerm] = translations.html
57
+ if (frTerm.includes(' ')) {
58
+ this.multiWordAttrs.push(frTerm)
59
+ }
39
60
  }
40
61
  }
41
62
  }
42
63
 
43
- addToMap(this.tagMap, this.i18n.rootElements)
44
- addToMap(this.tagMap, this.i18n.metadata)
45
- addToMap(this.tagMap, this.i18n.semanticSections)
46
- addToMap(this.tagMap, this.i18n.headings)
47
- addToMap(this.tagMap, this.i18n.textContent)
48
- addToMap(this.tagMap, this.i18n.inlineSemantics)
49
- addToMap(this.tagMap, this.i18n.lists)
50
- addToMap(this.tagMap, this.i18n.textFormatting)
51
- addToMap(this.tagMap, this.i18n.codeAndData)
52
- addToMap(this.tagMap, this.i18n.images)
53
- addToMap(this.tagMap, this.i18n.media)
54
- addToMap(this.tagMap, this.i18n.embeddedContent)
55
- addToMap(this.tagMap, this.i18n.graphics)
56
- addToMap(this.tagMap, this.i18n.tableStructure)
57
- addToMap(this.tagMap, this.i18n.formStructure)
58
- addToMap(this.tagMap, this.i18n.formInputs)
59
- addToMap(this.tagMap, this.i18n.interactive)
60
- addToMap(this.tagMap, this.i18n.genericContainers)
61
-
62
- addToMap(this.attrMap, this.i18n.globalAttributes)
63
- addToMap(this.attrMap, this.i18n.linkAttributes)
64
- addToMap(this.attrMap, this.i18n.imageAttributes)
65
- addToMap(this.attrMap, this.i18n.formAttributes)
66
- addToMap(this.attrMap, this.i18n.inputAttributes)
67
- addToMap(this.attrMap, this.i18n.textareaAttributes)
68
- addToMap(this.attrMap, this.i18n.mediaAttributes)
69
- addToMap(this.attrMap, this.i18n.tableAttributes)
70
- addToMap(this.attrMap, this.i18n.metaAttributes)
71
- addToMap(this.attrMap, this.i18n.ariaStates)
72
- addToMap(this.attrMap, this.i18n.ariaProperties)
73
-
74
- addToMap(this.eventMap, this.i18n.windowEvents)
75
- addToMap(this.eventMap, this.i18n.mouseEvents)
76
- addToMap(this.eventMap, this.i18n.keyboardEvents)
77
- addToMap(this.eventMap, this.i18n.formEvents)
78
- addToMap(this.eventMap, this.i18n.mediaEvents)
79
- addToMap(this.eventMap, this.i18n.dragEvents)
80
- addToMap(this.eventMap, this.i18n.clipboardEvents)
81
- addToMap(this.eventMap, this.i18n.touchEvents)
82
- addToMap(this.eventMap, this.i18n.pointerEvents)
64
+ addToTagMap(this.i18n.rootElements)
65
+ addToTagMap(this.i18n.metadata)
66
+ addToTagMap(this.i18n.semanticSections)
67
+ addToTagMap(this.i18n.headings)
68
+ addToTagMap(this.i18n.textContent)
69
+ addToTagMap(this.i18n.inlineSemantics)
70
+ addToTagMap(this.i18n.lists)
71
+ addToTagMap(this.i18n.textFormatting)
72
+ addToTagMap(this.i18n.codeAndData)
73
+ addToTagMap(this.i18n.editAnnotations)
74
+ addToTagMap(this.i18n.asianText)
75
+ addToTagMap(this.i18n.bidirectional)
76
+ addToTagMap(this.i18n.otherInline)
77
+ addToTagMap(this.i18n.images)
78
+ addToTagMap(this.i18n.audioVideo)
79
+ addToTagMap(this.i18n.embeddedContent)
80
+ addToTagMap(this.i18n.graphics)
81
+ addToTagMap(this.i18n.tableStructure)
82
+ addToTagMap(this.i18n.formStructure)
83
+ addToTagMap(this.i18n.formInputs)
84
+ addToTagMap(this.i18n.interactive)
85
+ addToTagMap(this.i18n.scripting)
86
+ addToTagMap(this.i18n.genericContainers)
87
+
88
+ addToAttrMap(this.i18n.globalAttributes)
89
+ addToAttrMap(this.i18n.linkAttributes)
90
+ addToAttrMap(this.i18n.imageAttributes)
91
+ addToAttrMap(this.i18n.formAttributes)
92
+ addToAttrMap(this.i18n.inputAttributes)
93
+ addToAttrMap(this.i18n.textareaAttributes)
94
+ addToAttrMap(this.i18n.mediaAttributes)
95
+ addToAttrMap(this.i18n.tableAttributes)
96
+ addToAttrMap(this.i18n.metaAttributes)
97
+ addToAttrMap(this.i18n.iframeAttributes)
98
+ addToAttrMap(this.i18n.scriptAttributes)
99
+ addToAttrMap(this.i18n.objectAttributes)
100
+ addToAttrMap(this.i18n.areaAttributes)
101
+ addToAttrMap(this.i18n.ariaStates)
102
+ addToAttrMap(this.i18n.ariaProperties)
103
+
104
+ addToAttrMap(this.i18n.windowEvents)
105
+ addToAttrMap(this.i18n.mouseEvents)
106
+ addToAttrMap(this.i18n.keyboardEvents)
107
+ addToAttrMap(this.i18n.formEvents)
108
+ addToAttrMap(this.i18n.mediaEvents)
109
+ addToAttrMap(this.i18n.dragEvents)
110
+ addToAttrMap(this.i18n.clipboardEvents)
111
+ addToAttrMap(this.i18n.touchEvents)
112
+ addToAttrMap(this.i18n.pointerEvents)
113
+ addToAttrMap(this.i18n.focusEvents)
114
+ addToAttrMap(this.i18n.animationEvents)
115
+
116
+ this.multiWordTags.sort((a, b) => b.length - a.length)
117
+ this.multiWordAttrs.sort((a, b) => b.length - a.length)
83
118
  }
84
119
 
85
120
  translateTag(tag) {
86
121
  const lower = tag.toLowerCase()
87
122
  const withSpaces = lower.replace(/-/g, ' ')
88
- let result = this.tagMap[lower] || this.tagMap[withSpaces] || this.translateGenericTag(tag)
123
+
124
+ let result = this.tagMap[lower] || this.tagMap[withSpaces]
125
+
126
+ if (!result) {
127
+ for (const multiWord of this.multiWordTags) {
128
+ if (lower === multiWord || withSpaces === multiWord) {
129
+ result = this.tagMap[multiWord]
130
+ break
131
+ }
132
+ }
133
+ }
134
+
135
+ if (!result) {
136
+ result = this.translateGenericTag(tag)
137
+ }
138
+
89
139
  result = result.replace(/^<|>$/g, '').trim()
90
140
  return result
91
141
  }
92
142
 
93
143
  translateAttribute(attr) {
94
144
  const lower = attr.toLowerCase()
95
- return this.attrMap[lower] || this.eventMap[lower] || this.translateGenericAttr(attr)
145
+
146
+ let result = this.attrMap[lower]
147
+
148
+ if (!result) {
149
+ for (const multiWord of this.multiWordAttrs) {
150
+ if (lower === multiWord) {
151
+ result = this.attrMap[multiWord]
152
+ break
153
+ }
154
+ }
155
+ }
156
+
157
+ if (!result) {
158
+ result = this.translateGenericAttr(attr)
159
+ }
160
+
161
+ return result
96
162
  }
97
163
 
98
164
  translateGenericTag(tag) {
99
165
  const translations = {
100
166
  'document': 'html',
167
+ 'tête': 'head',
101
168
  'tete': 'head',
102
169
  'corps': 'body',
103
170
  'titre': 'title',
171
+ 'méta': 'meta',
104
172
  'meta': 'meta',
105
173
  'lien': 'a',
106
174
  'liaison': 'link',
107
175
  'style': 'style',
108
176
  'script': 'script',
177
+ 'base': 'base',
178
+ 'entête': 'header',
109
179
  'entete': 'header',
110
- 'piedpage': 'footer',
180
+ 'pied de page': 'footer',
111
181
  'pied': 'footer',
112
182
  'navigation': 'nav',
113
183
  'nav': 'nav',
@@ -115,106 +185,165 @@ class HTMLGenerator {
115
185
  'section': 'section',
116
186
  'article': 'article',
117
187
  'aside': 'aside',
188
+ 'côté': 'aside',
118
189
  'cote': 'aside',
119
190
  'recherche': 'search',
120
191
  'adresse': 'address',
121
- 'titre1': 'h1',
122
- 'titre2': 'h2',
123
- 'titre3': 'h3',
124
- 'titre4': 'h4',
125
- 'titre5': 'h5',
126
- 'titre6': 'h6',
192
+ 'groupe titres': 'hgroup',
193
+ 'titre 1': 'h1',
194
+ 'titre 2': 'h2',
195
+ 'titre 3': 'h3',
196
+ 'titre 4': 'h4',
197
+ 'titre 5': 'h5',
198
+ 'titre 6': 'h6',
127
199
  'paragraphe': 'p',
128
200
  'division': 'div',
129
201
  'div': 'div',
202
+ 'étendue': 'span',
203
+ 'etendue': 'span',
130
204
  'span': 'span',
131
- 'portee': 'span',
132
205
  'image': 'img',
206
+ 'image réactive': 'picture',
207
+ 'image reactive': 'picture',
133
208
  'figure': 'figure',
134
- 'legende': 'figcaption',
135
- 'liste': 'ul',
209
+ 'légende figure': 'figcaption',
210
+ 'legende figure': 'figcaption',
211
+ 'liste ordonnée': 'ol',
136
212
  'liste ordonnee': 'ol',
213
+ 'liste non ordonnée': 'ul',
137
214
  'liste non ordonnee': 'ul',
138
- 'element': 'li',
215
+ 'liste': 'ul',
216
+ 'élément liste': 'li',
139
217
  'element liste': 'li',
140
- 'definition': 'dl',
218
+ 'élément': 'li',
219
+ 'element': 'li',
220
+ 'liste description': 'dl',
141
221
  'terme': 'dt',
142
- 'description': 'dd',
222
+ 'définition': 'dd',
223
+ 'definition': 'dd',
224
+ 'menu': 'menu',
143
225
  'tableau': 'table',
144
- 'ligne': 'tr',
145
- 'cellule': 'td',
146
- 'entete cellule': 'th',
226
+ 'légende tableau': 'caption',
227
+ 'legende tableau': 'caption',
228
+ 'entête tableau': 'thead',
147
229
  'entete tableau': 'thead',
148
230
  'corps tableau': 'tbody',
149
231
  'pied tableau': 'tfoot',
232
+ 'groupe colonnes': 'colgroup',
233
+ 'colonne': 'col',
234
+ 'ligne': 'tr',
235
+ 'cellule entête': 'th',
236
+ 'cellule entete': 'th',
237
+ 'cellule': 'td',
150
238
  'formulaire': 'form',
239
+ 'ensemble champs': 'fieldset',
240
+ 'groupe champs': 'fieldset',
241
+ 'légende': 'legend',
242
+ 'legende': 'legend',
243
+ 'legende groupe': 'legend',
244
+ 'étiquette': 'label',
151
245
  'etiquette': 'label',
246
+ 'entrée': 'input',
247
+ 'entree': 'input',
152
248
  'champ': 'input',
153
249
  'zone texte': 'textarea',
250
+ 'sélection': 'select',
154
251
  'selection': 'select',
155
- 'option': 'option',
156
252
  'groupe options': 'optgroup',
253
+ 'option': 'option',
254
+ 'liste données': 'datalist',
255
+ 'liste donnees': 'datalist',
157
256
  'bouton': 'button',
158
- 'groupe champs': 'fieldset',
159
- 'legende groupe': 'legend',
160
- 'video': 'video',
257
+ 'résultat': 'output',
258
+ 'resultat': 'output',
259
+ 'sortie': 'output',
260
+ 'progression': 'progress',
261
+ 'mesure': 'meter',
262
+ 'metre': 'meter',
161
263
  'audio': 'audio',
264
+ 'vidéo': 'video',
265
+ 'video': 'video',
162
266
  'source': 'source',
163
267
  'piste': 'track',
268
+ 'cadre en ligne': 'iframe',
164
269
  'cadre': 'iframe',
165
- 'objet': 'object',
270
+ 'intégrer': 'embed',
166
271
  'integrer': 'embed',
272
+ 'objet': 'object',
273
+ 'canevas': 'canvas',
167
274
  'canvas': 'canvas',
168
275
  'toile': 'canvas',
169
276
  'svg': 'svg',
170
277
  'math': 'math',
171
- 'gras': 'strong',
172
- 'fort': 'strong',
173
- 'italique': 'em',
278
+ 'carte image': 'map',
279
+ 'carte': 'map',
280
+ 'zone': 'area',
281
+ 'zone cliquable': 'area',
174
282
  'emphase': 'em',
283
+ 'fort': 'strong',
284
+ 'gras': 'b',
285
+ 'petit': 'small',
286
+ 'citation': 'q',
287
+ 'citation bloc': 'blockquote',
288
+ 'citation courte': 'q',
289
+ 'référence citation': 'cite',
290
+ 'reference citation': 'cite',
291
+ 'abréviation': 'abbr',
292
+ 'abreviation': 'abbr',
293
+ 'définition': 'dfn',
294
+ 'italique': 'i',
295
+ 'souligné': 'u',
175
296
  'souligne': 'u',
297
+ 'barré': 's',
176
298
  'barre': 's',
177
- 'supprime': 'del',
178
- 'insere': 'ins',
179
- 'petit': 'small',
299
+ 'marqué': 'mark',
180
300
  'marque': 'mark',
301
+ 'indice': 'sub',
302
+ 'exposant': 'sup',
181
303
  'code': 'code',
182
- 'pre': 'pre',
183
- 'preformate': 'pre',
184
- 'citation': 'blockquote',
185
- 'citation courte': 'q',
186
- 'abreviation': 'abbr',
187
- 'temps': 'time',
188
304
  'variable': 'var',
189
- 'clavier': 'kbd',
305
+ 'sortie exemple': 'samp',
190
306
  'exemple': 'samp',
191
- 'indice': 'sub',
192
- 'exposant': 'sup',
193
- 'ligne horizontale': 'hr',
194
- 'saut ligne': 'br',
307
+ 'entrée clavier': 'kbd',
308
+ 'entree clavier': 'kbd',
309
+ 'clavier': 'kbd',
310
+ 'donnée': 'data',
311
+ 'donnee': 'data',
312
+ 'donnees': 'data',
313
+ 'temps': 'time',
314
+ 'inséré': 'ins',
315
+ 'insere': 'ins',
316
+ 'supprimé': 'del',
317
+ 'supprime': 'del',
318
+ 'ruby': 'ruby',
319
+ 'annotation ruby': 'rt',
320
+ 'parenthèses ruby': 'rp',
321
+ 'parentheses ruby': 'rp',
322
+ 'isolation bidi': 'bdi',
323
+ 'remplacement bidi': 'bdo',
324
+ 'retour ligne possible': 'wbr',
325
+ 'césure': 'wbr',
326
+ 'cesure': 'wbr',
327
+ 'wbr': 'wbr',
328
+ 'préformaté': 'pre',
329
+ 'preformate': 'pre',
330
+ 'pre': 'pre',
195
331
  'retour ligne': 'br',
332
+ 'saut ligne': 'br',
196
333
  'br': 'br',
334
+ 'ligne horizontale': 'hr',
197
335
  'hr': 'hr',
336
+ 'détails': 'details',
198
337
  'details': 'details',
338
+ 'résumé': 'summary',
199
339
  'resume': 'summary',
200
340
  'dialogue': 'dialog',
201
- 'menu': 'menu',
341
+ 'modèle': 'template',
202
342
  'modele': 'template',
203
- 'slot': 'slot',
204
343
  'emplacement': 'slot',
205
- 'donnees': 'data',
206
- 'metre': 'meter',
207
- 'progression': 'progress',
208
- 'sortie': 'output',
209
- 'carte': 'map',
210
- 'zone cliquable': 'area',
211
- 'groupe colonnes': 'colgroup',
212
- 'colonne': 'col',
213
- 'legende tableau': 'caption',
214
- 'wbr': 'wbr',
215
- 'cesure': 'wbr',
216
- 'noscript': 'noscript',
217
- 'sans script': 'noscript'
344
+ 'slot': 'slot',
345
+ 'sans script': 'noscript',
346
+ 'noscript': 'noscript'
218
347
  }
219
348
 
220
349
  const lower = tag.toLowerCase()
@@ -229,157 +358,191 @@ class HTMLGenerator {
229
358
  'titre': 'title',
230
359
  'langue': 'lang',
231
360
  'direction': 'dir',
361
+ 'caché': 'hidden',
232
362
  'cache': 'hidden',
233
363
  'tabindex': 'tabindex',
364
+ 'ordre tabulation': 'tabindex',
234
365
  'index tabulation': 'tabindex',
366
+ 'éditable': 'contenteditable',
235
367
  'editable': 'contenteditable',
236
- 'draggable': 'draggable',
368
+ 'glissable': 'draggable',
369
+ 'déplaçable': 'draggable',
237
370
  'deplacable': 'draggable',
371
+ 'inerte': 'inert',
372
+ 'popover': 'popover',
373
+ 'rôle': 'role',
238
374
  'role': 'role',
375
+ 'href': 'href',
239
376
  'adresse': 'href',
240
377
  'cible': 'target',
241
- 'nouvelle fenetre': '_blank',
378
+ 'relation': 'rel',
379
+ 'téléchargement': 'download',
380
+ 'telechargement': 'download',
242
381
  'source': 'src',
382
+ 'src': 'src',
383
+ 'srcset': 'srcset',
384
+ 'sources réactives': 'srcset',
385
+ 'sources reactives': 'srcset',
386
+ 'média': 'media',
387
+ 'media': 'media',
388
+ 'alternative': 'alt',
389
+ 'texte alternatif': 'alt',
243
390
  'alt': 'alt',
244
391
  'alternatif': 'alt',
245
- 'texte alternatif': 'alt',
246
392
  'largeur': 'width',
247
393
  'hauteur': 'height',
248
394
  'chargement': 'loading',
249
- 'paresseux': 'lazy',
395
+ 'décodage': 'decoding',
396
+ 'decodage': 'decoding',
397
+ 'tailles': 'sizes',
398
+ 'usemap': 'usemap',
399
+ 'forme': 'shape',
400
+ 'coords': 'coords',
401
+ 'coordonnées': 'coords',
402
+ 'coordonnees': 'coords',
250
403
  'action': 'action',
404
+ 'méthode': 'method',
251
405
  'methode': 'method',
406
+ 'enctype': 'enctype',
407
+ 'type encodage': 'enctype',
408
+ 'cible formulaire': 'formtarget',
409
+ 'novalidate': 'novalidate',
410
+ 'sans validation': 'novalidate',
411
+ 'autocomplétion': 'autocomplete',
412
+ 'autocompletion': 'autocomplete',
252
413
  'type': 'type',
253
414
  'nom': 'name',
254
- 'contenu': 'content',
255
415
  'valeur': 'value',
256
- 'valeur min': 'min',
257
- 'valeur max': 'max',
258
416
  'placeholder': 'placeholder',
259
417
  'indicateur': 'placeholder',
260
418
  'requis': 'required',
261
419
  'obligatoire': 'required',
420
+ 'aria-required': 'aria-required',
421
+ 'désactivé': 'disabled',
262
422
  'desactive': 'disabled',
263
423
  'lecture seule': 'readonly',
264
- 'coche': 'checked',
265
- 'selectionne': 'selected',
266
- 'multiple': 'multiple',
267
- 'minimum': 'min',
424
+ 'autofocus': 'autofocus',
425
+ 'longueur max': 'maxlength',
426
+ 'longueur min': 'minlength',
427
+ 'valeur max': 'max',
428
+ 'max': 'max',
268
429
  'maximum': 'max',
430
+ 'valeur min': 'min',
431
+ 'min': 'min',
432
+ 'minimum': 'min',
269
433
  'pas': 'step',
270
434
  'motif': 'pattern',
271
- 'longueur min': 'minlength',
272
- 'longueur max': 'maxlength',
273
- 'autocomplete': 'autocomplete',
274
- 'autofocus': 'autofocus',
275
- 'focus auto': 'autofocus',
276
- 'lignes': 'rows',
435
+ 'taille': 'size',
436
+ 'liste': 'list',
437
+ 'multiple': 'multiple',
438
+ 'accepter': 'accept',
439
+ 'accept': 'accept',
440
+ 'capture': 'capture',
441
+ 'coché': 'checked',
442
+ 'coche': 'checked',
443
+ 'sélectionné': 'selected',
444
+ 'selectionne': 'selected',
277
445
  'colonnes': 'cols',
446
+ 'cols': 'cols',
447
+ 'rangées': 'rows',
448
+ 'rangees': 'rows',
449
+ 'lignes': 'rows',
450
+ 'rows': 'rows',
451
+ 'retour à la ligne': 'wrap',
452
+ 'retour a la ligne': 'wrap',
453
+ 'contrôles': 'controls',
278
454
  'controles': 'controls',
279
455
  'lecture auto': 'autoplay',
280
456
  'boucle': 'loop',
281
457
  'muet': 'muted',
282
- 'affiche': 'poster',
458
+ 'préchargement': 'preload',
283
459
  'prechargement': 'preload',
284
- 'fusion lignes': 'rowspan',
285
- 'fusion colonnes': 'colspan',
286
- 'portee': 'scope',
287
- 'pour': 'for',
460
+ 'affiche': 'poster',
461
+ 'poster': 'poster',
462
+ 'lecture en ligne': 'playsinline',
463
+ 'kind': 'kind',
464
+ 'srclang': 'srclang',
465
+ 'étiquette': 'label',
288
466
  'etiquette': 'label',
289
- 'accept': 'accept',
290
- 'accepter': 'accept',
291
- 'enctype': 'enctype',
292
- 'encodage': 'enctype',
293
- 'rel': 'rel',
294
- 'relation': 'rel',
295
- 'media': 'media',
296
- 'type media': 'media',
467
+ 'défaut': 'default',
468
+ 'defaut': 'default',
469
+ 'allow': 'allow',
470
+ 'allowfullscreen': 'allowfullscreen',
471
+ 'plein écran': 'allowfullscreen',
472
+ 'plein ecran': 'allowfullscreen',
473
+ 'sandbox': 'sandbox',
474
+ 'données': 'data',
475
+ 'donnees': 'data',
476
+ 'portée': 'scope',
477
+ 'portee': 'scope',
478
+ 'colspan': 'colspan',
479
+ 'fusion colonnes': 'colspan',
480
+ 'rowspan': 'rowspan',
481
+ 'fusion lignes': 'rowspan',
482
+ 'étendue': 'span',
483
+ 'etendue': 'span',
484
+ 'span': 'span',
485
+ 'contenu': 'content',
486
+ 'jeu caractères': 'charset',
487
+ 'jeu caracteres': 'charset',
297
488
  'charset': 'charset',
298
- 'encodage caracteres': 'charset',
489
+ 'http-equiv': 'http-equiv',
490
+ 'équivalent http': 'http-equiv',
491
+ 'equivalent http': 'http-equiv',
492
+ 'ouvert': 'open',
493
+ 'différé': 'defer',
494
+ 'differe': 'defer',
495
+ 'defer': 'defer',
299
496
  'async': 'async',
300
497
  'asynchrone': 'async',
301
- 'defer': 'defer',
302
- 'differer': 'defer',
303
- 'crossorigin': 'crossorigin',
304
- 'origine croisee': 'crossorigin',
305
- 'integrite': 'integrity',
306
- 'referrerpolicy': 'referrerpolicy',
307
- 'politique referent': 'referrerpolicy',
308
- 'sandbox': 'sandbox',
309
- 'bac a sable': 'sandbox',
310
- 'allow': 'allow',
311
- 'autoriser': 'allow',
312
- 'donnees': 'data',
313
- 'accesskey': 'accesskey',
314
- 'touche acces': 'accesskey',
315
- 'translate': 'translate',
316
- 'traduire': 'translate',
317
- 'spellcheck': 'spellcheck',
318
- 'orthographe': 'spellcheck',
319
- 'enterkeyhint': 'enterkeyhint',
320
- 'indice entree': 'enterkeyhint',
321
- 'inputmode': 'inputmode',
322
- 'mode saisie': 'inputmode',
323
- 'is': 'is',
324
- 'est': 'is',
325
- 'part': 'part',
326
- 'partie': 'part',
327
- 'exportparts': 'exportparts',
328
- 'exporter parties': 'exportparts',
329
- 'nonce': 'nonce',
330
- 'jeton': 'nonce'
498
+ 'pour': 'for',
499
+ 'datetime': 'datetime',
500
+ 'cite': 'cite',
501
+ 'nouvelle fenêtre': '_blank',
502
+ 'nouvelle fenetre': '_blank',
503
+ 'même fenêtre': '_self',
504
+ 'meme fenetre': '_self',
505
+ 'low': 'low',
506
+ 'bas': 'low',
507
+ 'high': 'high',
508
+ 'haut': 'high',
509
+ 'optimum': 'optimum',
510
+ 'start': 'start',
511
+ 'début': 'start',
512
+ 'debut': 'start',
513
+ 'reversed': 'reversed',
514
+ 'inversé': 'reversed',
515
+ 'inverse': 'reversed',
516
+ 'aria-label': 'aria-label',
517
+ 'aria-describedby': 'aria-describedby',
518
+ 'décrit par': 'aria-describedby',
519
+ 'decrit par': 'aria-describedby',
520
+ 'aria-labelledby': 'aria-labelledby',
521
+ 'étiqueté par': 'aria-labelledby',
522
+ 'etiquete par': 'aria-labelledby',
523
+ 'aria-hidden': 'aria-hidden',
524
+ 'aria-expanded': 'aria-expanded',
525
+ 'étendu': 'aria-expanded',
526
+ 'aria-controls': 'aria-controls',
527
+ 'aria-live': 'aria-live',
528
+ 'en direct': 'aria-live',
529
+ 'aria-atomic': 'aria-atomic'
331
530
  }
332
531
 
333
532
  const lower = attr.toLowerCase()
334
533
  return translations[lower] || attr
335
534
  }
336
535
 
337
- translateInputType(type) {
338
- const types = {
339
- 'texte': 'text',
340
- 'mot de passe': 'password',
341
- 'email': 'email',
342
- 'courriel': 'email',
343
- 'nombre': 'number',
344
- 'telephone': 'tel',
345
- 'url': 'url',
346
- 'recherche': 'search',
347
- 'date': 'date',
348
- 'heure': 'time',
349
- 'datetime': 'datetime-local',
350
- 'date heure': 'datetime-local',
351
- 'mois': 'month',
352
- 'semaine': 'week',
353
- 'couleur': 'color',
354
- 'fichier': 'file',
355
- 'cache': 'hidden',
356
- 'case a cocher': 'checkbox',
357
- 'bouton radio': 'radio',
358
- 'intervalle': 'range',
359
- 'soumettre': 'submit',
360
- 'reinitialiser': 'reset',
361
- 'bouton': 'button',
362
- 'image': 'image'
363
- }
364
-
365
- const lower = type.toLowerCase()
366
- return types[lower] || type
367
- }
368
-
369
536
  generate(ast) {
370
537
  this.output = ''
371
538
  this.indent = 0
372
539
 
373
- if (Array.isArray(ast)) {
374
- for (const node of ast) {
375
- this.generateNode(node)
376
- }
377
- } else if (ast && ast.type) {
378
- this.generateNode(ast)
379
- } else if (ast && ast.children) {
380
- for (const child of ast.children) {
540
+ if (ast.type === 'document' || ast.type === 'root') {
541
+ for (const child of ast.children || []) {
381
542
  this.generateNode(child)
382
543
  }
544
+ } else {
545
+ this.generateNode(ast)
383
546
  }
384
547
 
385
548
  return this.output.trim()
@@ -389,36 +552,24 @@ class HTMLGenerator {
389
552
  if (!node) return
390
553
 
391
554
  switch (node.type) {
392
- case 'Document':
393
- case 'document':
394
- this.output += '<!DOCTYPE html>\n'
395
- if (node.children) {
396
- for (const child of node.children) {
397
- this.generateNode(child)
398
- }
399
- }
555
+ case 'doctype':
556
+ this.generateDoctype(node)
400
557
  break
401
- case 'Element':
402
558
  case 'element':
559
+ case 'tag':
403
560
  this.generateElement(node)
404
561
  break
405
- case 'Text':
406
562
  case 'text':
407
563
  this.generateText(node)
408
564
  break
409
- case 'Comment':
410
565
  case 'comment':
411
566
  this.generateComment(node)
412
567
  break
413
- case 'Doctype':
414
- case 'doctype':
415
- this.generateDoctype(node)
416
- break
417
- case 'Include':
568
+ case 'include':
418
569
  this.generateInclude(node)
419
570
  break
420
571
  default:
421
- if (node.tag || node.tagName) {
572
+ if (node.tag || node.tagName || node.name) {
422
573
  this.generateElement(node)
423
574
  } else if (node.text || node.content) {
424
575
  this.generateText(node)
@@ -437,6 +588,14 @@ class HTMLGenerator {
437
588
  }
438
589
  }
439
590
 
591
+ if (tag === 'a' && attrs.relation) {
592
+ const rel = this.translateAttribute(attrs.relation)
593
+ const linkRels = ['stylesheet', 'icon', 'preconnect', 'prefetch', 'preload', 'dns-prefetch', 'canonical', 'alternate', 'manifest', 'apple-touch-icon']
594
+ if (linkRels.some(r => rel.includes(r))) {
595
+ tag = 'link'
596
+ }
597
+ }
598
+
440
599
  const attributes = this.generateAttributes(attrs)
441
600
  const isVoid = this.voidElements.includes(tag.toLowerCase())
442
601
 
@@ -484,7 +643,7 @@ class HTMLGenerator {
484
643
  for (const [key, value] of Object.entries(attrs)) {
485
644
  let attrName = this.translateAttribute(key)
486
645
 
487
- if (attrName.startsWith('au ') || attrName.startsWith('a la ')) {
646
+ if (attrName.startsWith('au ') || attrName.startsWith('à la ') || attrName.startsWith('a la ')) {
488
647
  attrName = this.translateEvent(key)
489
648
  }
490
649
 
@@ -499,6 +658,10 @@ class HTMLGenerator {
499
658
  attrValue = this.translateInputType(value)
500
659
  }
501
660
 
661
+ if (attrName === 'target' && this.isTargetValue(value)) {
662
+ attrValue = this.translateTargetValue(value)
663
+ }
664
+
502
665
  parts.push(`${attrName}="${this.escapeAttr(attrValue)}"`)
503
666
  }
504
667
  }
@@ -512,53 +675,100 @@ class HTMLGenerator {
512
675
  'au double clic': 'ondblclick',
513
676
  'au survol': 'onmouseover',
514
677
  'au survol fin': 'onmouseout',
678
+ 'souris entrée': 'onmouseenter',
515
679
  'souris entree': 'onmouseenter',
680
+ 'entrée souris': 'onmouseenter',
681
+ 'entree souris': 'onmouseenter',
516
682
  'souris sortie': 'onmouseleave',
517
- 'souris bas': 'onmousedown',
518
- 'souris haut': 'onmouseup',
519
- 'souris mouvement': 'onmousemove',
683
+ 'sortie souris': 'onmouseleave',
684
+ 'bouton enfoncé': 'onmousedown',
685
+ 'bouton enfonce': 'onmousedown',
686
+ 'bouton relâché': 'onmouseup',
687
+ 'bouton relache': 'onmouseup',
688
+ 'mouvement souris': 'onmousemove',
520
689
  'au focus': 'onfocus',
521
- 'au focus perdu': 'onblur',
690
+ 'à la perte focus': 'onblur',
691
+ 'a la perte focus': 'onblur',
522
692
  'perte focus': 'onblur',
693
+ 'au focus perdu': 'onblur',
523
694
  'au changement': 'onchange',
695
+ 'à la saisie': 'oninput',
524
696
  'a la saisie': 'oninput',
697
+ 'touche enfoncée': 'onkeydown',
698
+ 'touche enfoncee': 'onkeydown',
525
699
  'touche bas': 'onkeydown',
700
+ 'touche relâchée': 'onkeyup',
701
+ 'touche relachee': 'onkeyup',
526
702
  'touche haut': 'onkeyup',
527
- 'touche presse': 'onkeypress',
703
+ 'à la soumission': 'onsubmit',
528
704
  'a la soumission': 'onsubmit',
705
+ 'à la réinitialisation': 'onreset',
529
706
  'a la reinitialisation': 'onreset',
530
707
  'au chargement': 'onload',
708
+ 'au déchargement': 'onunload',
709
+ 'au dechargement': 'onunload',
531
710
  'a la fermeture': 'onunload',
711
+ 'avant déchargement': 'onbeforeunload',
712
+ 'avant dechargement': 'onbeforeunload',
532
713
  'au redimensionnement': 'onresize',
714
+ 'au défilement': 'onscroll',
533
715
  'au defilement': 'onscroll',
716
+ 'à l\'erreur': 'onerror',
717
+ 'a l\'erreur': 'onerror',
534
718
  'erreur': 'onerror',
719
+ 'en ligne': 'ononline',
720
+ 'hors ligne': 'onoffline',
535
721
  'lecture': 'onplay',
536
722
  'pause': 'onpause',
537
723
  'fin': 'onended',
724
+ 'début glissement': 'ondragstart',
725
+ 'debut glissement': 'ondragstart',
538
726
  'glisser debut': 'ondragstart',
727
+ 'glissement': 'ondrag',
539
728
  'glisser': 'ondrag',
729
+ 'fin glissement': 'ondragend',
540
730
  'glisser fin': 'ondragend',
731
+ 'entrée zone': 'ondragenter',
732
+ 'entree zone': 'ondragenter',
541
733
  'glisser entree': 'ondragenter',
734
+ 'sortie zone': 'ondragleave',
542
735
  'glisser sortie': 'ondragleave',
736
+ 'survol zone': 'ondragover',
543
737
  'glisser survol': 'ondragover',
738
+ 'dépôt': 'ondrop',
739
+ 'depot': 'ondrop',
544
740
  'deposer': 'ondrop',
545
741
  'copier': 'oncopy',
546
742
  'couper': 'oncut',
547
743
  'coller': 'onpaste',
744
+ 'début toucher': 'ontouchstart',
745
+ 'debut toucher': 'ontouchstart',
548
746
  'toucher debut': 'ontouchstart',
747
+ 'mouvement toucher': 'ontouchmove',
549
748
  'toucher mouvement': 'ontouchmove',
749
+ 'fin toucher': 'ontouchend',
550
750
  'toucher fin': 'ontouchend',
751
+ 'annulation toucher': 'ontouchcancel',
551
752
  'toucher annuler': 'ontouchcancel',
552
- 'pointeur bas': 'onpointerdown',
553
- 'pointeur haut': 'onpointerup',
554
- 'pointeur mouvement': 'onpointermove',
555
- 'pointeur entree': 'onpointerenter',
556
- 'pointeur sortie': 'onpointerleave',
753
+ 'molette': 'onwheel',
557
754
  'roue': 'onwheel',
558
755
  'menu contextuel': 'oncontextmenu',
756
+ 'début animation': 'onanimationstart',
757
+ 'debut animation': 'onanimationstart',
559
758
  'animation debut': 'onanimationstart',
759
+ 'fin animation': 'onanimationend',
560
760
  'animation fin': 'onanimationend',
561
- 'transition fin': 'ontransitionend'
761
+ 'itération animation': 'onanimationiteration',
762
+ 'iteration animation': 'onanimationiteration',
763
+ 'début transition': 'ontransitionstart',
764
+ 'debut transition': 'ontransitionstart',
765
+ 'fin transition': 'ontransitionend',
766
+ 'transition fin': 'ontransitionend',
767
+ 'pointeur bas': 'onpointerdown',
768
+ 'pointeur haut': 'onpointerup',
769
+ 'pointeur mouvement': 'onpointermove',
770
+ 'pointeur entree': 'onpointerenter',
771
+ 'pointeur sortie': 'onpointerleave'
562
772
  }
563
773
 
564
774
  const lower = event.toLowerCase()
@@ -568,16 +778,70 @@ class HTMLGenerator {
568
778
  isInputType(value) {
569
779
  const types = [
570
780
  'texte', 'text', 'mot de passe', 'password', 'email', 'courriel',
571
- 'nombre', 'number', 'telephone', 'tel', 'url', 'recherche', 'search',
572
- 'date', 'heure', 'time', 'datetime', 'date heure', 'mois', 'month',
573
- 'semaine', 'week', 'couleur', 'color', 'fichier', 'file', 'cache',
574
- 'hidden', 'case a cocher', 'checkbox', 'bouton radio', 'radio',
575
- 'intervalle', 'range', 'soumettre', 'submit', 'reinitialiser', 'reset',
576
- 'bouton', 'button', 'image'
781
+ 'nombre', 'number', 'téléphone', 'telephone', 'tel', 'url',
782
+ 'recherche', 'search', 'date', 'heure', 'time', 'datetime-local',
783
+ 'date et heure locale', 'mois', 'month', 'semaine', 'week',
784
+ 'couleur', 'color', 'fichier', 'file', 'caché', 'cache', 'hidden',
785
+ 'case à cocher', 'case a cocher', 'checkbox', 'bouton radio', 'radio',
786
+ 'intervalle', 'range', 'soumettre', 'submit', 'réinitialiser',
787
+ 'reinitialiser', 'reset', 'bouton', 'button', 'image'
577
788
  ]
578
789
  return types.includes(value.toLowerCase())
579
790
  }
580
791
 
792
+ translateInputType(type) {
793
+ const types = {
794
+ 'texte': 'text',
795
+ 'mot de passe': 'password',
796
+ 'courriel': 'email',
797
+ 'nombre': 'number',
798
+ 'téléphone': 'tel',
799
+ 'telephone': 'tel',
800
+ 'recherche': 'search',
801
+ 'heure': 'time',
802
+ 'date et heure locale': 'datetime-local',
803
+ 'mois': 'month',
804
+ 'semaine': 'week',
805
+ 'couleur': 'color',
806
+ 'fichier': 'file',
807
+ 'caché': 'hidden',
808
+ 'cache': 'hidden',
809
+ 'case à cocher': 'checkbox',
810
+ 'case a cocher': 'checkbox',
811
+ 'bouton radio': 'radio',
812
+ 'intervalle': 'range',
813
+ 'soumettre': 'submit',
814
+ 'réinitialiser': 'reset',
815
+ 'reinitialiser': 'reset',
816
+ 'bouton': 'button'
817
+ }
818
+
819
+ return types[type.toLowerCase()] || type
820
+ }
821
+
822
+ isTargetValue(value) {
823
+ const targets = [
824
+ 'même fenêtre', 'meme fenetre', '_self',
825
+ 'nouvelle fenêtre', 'nouvelle fenetre', '_blank',
826
+ 'parent', '_parent',
827
+ 'haut', '_top'
828
+ ]
829
+ return targets.includes(value.toLowerCase())
830
+ }
831
+
832
+ translateTargetValue(value) {
833
+ const targets = {
834
+ 'même fenêtre': '_self',
835
+ 'meme fenetre': '_self',
836
+ 'nouvelle fenêtre': '_blank',
837
+ 'nouvelle fenetre': '_blank',
838
+ 'parent': '_parent',
839
+ 'haut': '_top'
840
+ }
841
+
842
+ return targets[value.toLowerCase()] || value
843
+ }
844
+
581
845
  generateText(node) {
582
846
  const text = node.text || node.content || node.value || ''
583
847
  if (text.trim()) {