turbo-editors/turbo-jspublic Fork 0
main
Commits
Clone
git clone https://git.rickub.com/turbo-editors/turbo-js.git
git clone ssh://git@rickub.com/turbo-editors/turbo-js.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

📦 Turbo JS 91999d1 · on main · k33g · 9h ago
languages.md · 296 lines · 21.2 KBmarkdown
Blame HistoryOpen raw

Référence : langages colorés

Description neutre des fichiers que Turbo JS colore, de la façon dont il décide, et de ce que chaque scanner reconnaît.

Reconnaissance

L'extension d'un fichier décide dès qu'elle est l'une de celles-ci :

Extension Langage
.js, .mjs, .cjs JavaScript
.json, .jsonc JSON
.toml TOML
.yaml, .yml YAML
.md, .markdown Markdown
.html, .htm HTML
.xml, .xsd, .xsl, .xslt, .svg, .plist, .csproj, .pom XML
.sh, .bash, .zsh Shell
.dockerfile, .containerfile Dockerfile

Les extensions sont comparées sans tenir compte de la casse, et seule la dernière compte : notes.js.md est du Markdown, main.js.backup n'est pas du JavaScript, et main.test.js est du JavaScript.

Un fichier dont l'extension ne décide rien est ensuite cherché par son nom. Seuls les fichiers sans extension utile en ont besoin :

Nom Langage
Dockerfile, Containerfile Dockerfile

Un nom correspond sur sa totalité ou sur la partie avant le premier point, sans tenir compte de la casse — Dockerfile, dockerfile et Dockerfile.dev sont donc tous reconnus, tandis que Dockerfile.md est du Markdown, parce que l'extension est consultée d'abord.

Un fichier que ni l'une ni l'autre table ne réclame est lu par sa première ligne. Un shebang nommant node en fait du JavaScript : un outil en ligne de commande écrit en JavaScript est un fichier sans extension dont la première ligne est #!/usr/bin/env node, et Node retire cette ligne avant de parser. Un shebang nommant un shell — sh, bash, zsh, dash ou ksh — en fait un script shell. L'interpréteur est reconnu comme élément de chemin ou comme argument d'env.

Première ligne Résultat
#!/usr/bin/env node JavaScript
#!/usr/local/bin/node JavaScript
#!/usr/bin/env -S node --no-warnings JavaScript
#!/bin/sh Shell
#!/usr/bin/env bash Shell
#!/usr/bin/env python3 Non coloré
Tout ce qui ne commence pas par #! Non coloré

L'ordre est fixe — extension, puis nom, puis première ligne — et le premier qui décide l'emporte.

Tout le reste est affiché en texte brut. Ce n'est pas une erreur — ouvrir un PNG dans l'éditeur n'est pas une faute, c'est juste non coloré. En particulier, TypeScript (.ts, .tsx), JSX (.jsx) et CSS ne sont pas colorés : le serveur de langage sert les fichiers .ts quand même, mais le scanner ici est pour JavaScript.

Classes

Chaque scanner produit le même vocabulaire de classes, et chacune correspond à une clé de thème.

Classe Clé de thème Produite par
identifier syntax.identifier JavaScript, JSON (un mot nu, qui n'est pas du JSON), TOML, shell, YAML, Dockerfile
keyword syntax.keyword JavaScript, shell, HTML (doctype), XML, Dockerfile
type syntax.type JavaScript (noms de classes et noms capitalisés), TOML (en-têtes de table), YAML (tags)
builtin syntax.builtin JavaScript (les globales de la bibliothèque standard et de Node), shell (builtins et expansions), YAML (ancres et alias), Dockerfile (variables)
constant syntax.constant JavaScript, JSON, TOML, shell, YAML, HTML et XML (entités)
function syntax.function JavaScript, shell (la commande)
string syntax.string tous
char syntax.char JavaScript (littéraux d'expressions régulières)
number syntax.number JavaScript, JSON, TOML, shell, YAML, Dockerfile
comment syntax.comment JavaScript, JSON, TOML, shell, HTML, YAML, XML, Dockerfile
operator syntax.operator JavaScript, TOML, shell, HTML, YAML (en-têtes de scalaires bloc), XML, Dockerfile
punctuation syntax.punctuation JavaScript, JSON, TOML, shell, Markdown, YAML, Dockerfile
heading syntax.heading Markdown
tag syntax.tag HTML, XML
attribute syntax.attribute JSON (clés), JavaScript (décorateurs), HTML, XML, Dockerfile (options)
emphasis syntax.emphasis Markdown
link syntax.link Markdown

JavaScript ne produit aucune portée heading, tag, emphasis ou link. Dans turbo-classic, syntax.number et syntax.constant sont tous deux magenta et syntax.char a le vert de syntax.string, si bien que 42 et true partagent une couleur là, et /re/ et "re" aussi ; d'autres thèmes les séparent. Voir écrire son propre thème pour changer cela.

JavaScript

Écrit à la main, dans internal/jslang, et enregistré sous le même nom que le scanner que turbo-core livre pour JavaScript, qu'il remplace. Ce qu'il ajoute à celui de la bibliothèque : les littéraux d'expressions régulières, la ligne de hashbang, les globales de Node, le nom après function et class, les noms privés, les décorateurs, et une majuscule initiale lue comme un nom de classe.

Deux constructions franchissent une ligne, et sont portées à la ligne suivante : un commentaire bloc /* … */ jusqu'à son */ fermant, et un littéral de gabarit `…` jusqu'à son accent grave fermant. Aucune des deux ne s'imbrique. Une chaîne ordinaire '…' ou "…" ne franchit pas une ligne : une chaîne non terminée est colorée jusqu'à la fin de sa ligne, et la ligne suivante est de nouveau du code.

Reconnu Comme
as, async, await, break, case, catch, class, const, continue, debugger, default, delete, do, else, export, extends, finally, for, from, function, get, if, import, in, instanceof, let, new, of, return, set, static, super, switch, throw, try, typeof, var, void, while, with, yield, et les réservés enum, implements, interface, package, private, protected, public mot-clé
true, false, null, undefined, NaN, Infinity, this constante
les globales de la bibliothèque standard — Array, Object, Promise, Math, JSON, Map, Set, Symbol, BigInt, Error, TypeError, parseInt, setTimeout, structuredClone, fetch, URL, … builtin
les globales de Node — process, Buffer, console, require, module, exports, __dirname, __filename, setImmediate, performance, crypto — et document et window du navigateur builtin
le nom après function, function* ou async functionparse dans function parse(input) {} fonction
le nom après classwidget dans class widget extends Base {} type
tout autre nom commençant par une majuscule ASCII — Greeter, EventEmitter, MyError — même devant un ( type
tout autre nom immédiatement avant (compute(3), obj.method(), this.#reset() fonction
tout mot après . ou ?., quelle que soit son orthographe — map.get(k) une fonction, options.default un nom, user?.class un nom propriété, jamais un mot-clé
get, set, static, of, from et as devant un (get(key) fonction
#count, un membre privé, # compris identifiant, ou fonction devant (
@decorator, @observable.ref, chemin pointé compris attribut
tout autre nom : une lettre Unicode, _ ou $, puis des lettres, des chiffres et les mêmes — x, $el, _, café, 名前 identifiant
"…", '…' avec les échappements par barre oblique inverse, sur une ligne chaîne
`…`, interpolations ${…} comprises, sur plusieurs lignes chaîne
/…/gi, un littéral d'expression régulière, drapeaux compris, là où le token précédent en permet un et qu'un / fermant existe sur la ligne caractère
42, 1_000, 0xFF, 0o17, 0b1010, 1.5e-3, 2E+10, .5, 10n, 0xFFn nombre
// jusqu'à la fin de la ligne ; /* … */ et /** … */ sur plusieurs lignes commentaire
#! sur la première ligne du fichier, jusqu'à sa fin commentaire
... ponctuation, en une seule portée
?. opérateur, en une seule portée
les suites de +-*/%=<>!&|^~?: — dont =>, ??, ===, **, >>>= opérateur
()[]{},; et un . seul ponctuation

Une barre oblique divise après une valeur et ouvre une expression régulière partout ailleurs. Après un nom, un nombre, une chaîne, un gabarit, une expression régulière, ) ou ], un / est une division. Après un opérateur, (, [, {, }, ,, ;, :, un mot-clé, ou en début de ligne, il ouvre une expression régulière — à condition qu'un / fermant existe sur la même ligne ; sinon il divise, quoi qu'il y ait avant. Une expression régulière ne peut pas franchir une ligne, cette borne limite donc une mauvaise supposition à une ligne.

Un point rejoint un nombre seulement quand un chiffre le suit, 1.toString() est donc le nombre 1, un point et une méthode. Le signe après un e fait partie du nombre, sauf dans un littéral hexadécimal, où 0xE+1 est une somme.

Un nom capitalisé est une classe par convention, pas par règle. JavaScript vous laisse écrire const Count = 1, et il est coloré comme une classe quand même, tout comme MAX_SIZE. Les classes et les constructeurs sont ce que les gens capitalisent, et la couleur suit les gens.

Non reconnu, chacun pour une raison énoncée :

Non reconnu Parce que
Le code dans ${…} d'un gabarit Le colorer signifie que le scanner rentre en lui-même avec une profondeur d'imbrication à porter, pour une construction qui est d'habitude une courte expression ; tout le littéral est une chaîne
Un accent grave dans ${…} Pour la même raison : il termine le gabarit trop tôt, et le code qui suit est coloré comme du code jusqu'à l'accent grave suivant
Une expression régulière sans barre oblique fermante sur sa ligne Elle ne peut pas en être une — le langage interdit un saut de ligne dans le littéral — la barre oblique divise donc
JSX <div> est lu comme un opérateur, un nom et un opérateur ; il n'y a pas de HTML dans le JavaScript ici
Les annotations et les types de TypeScript Un autre langage ; les fichiers .ts ne sont pas colorés du tout
Les commentaires bloc imbriqués JavaScript termine un commentaire bloc au premier */ ; une profondeur serait une affirmation sur un autre langage
Une chaîne continuée par une barre oblique inverse finale La chaîne s'arrête à sa ligne et la ligne suivante est du code ; la continuation est assez rare pour ne pas valoir d'être portée
Si un nom en SCREAMING_SNAKE_CASE est une constante La majuscule initiale dit classe, et rien dans l'orthographe ne sépare les deux conventions
# comme commentaire Il n'en est un que dans le hashbang, sur la première ligne ; partout ailleurs # commence un nom privé ou est enjambé
Si un nom est lié dans cette portée Rien ici ne lit plus d'une ligne à la fois ; c'est la question du serveur de langage, et F1 y répond

JSON

Écrit à la main, dans internal/jslang/json.go, trente lignes, parce que le langage fait trente lignes : des chaînes, des nombres, trois mots, six signes de ponctuation. C'est le langage dans lequel est écrit le manifeste de chaque projet Node, et turbo-core ne le colore pas.

Reconnu Comme
"name" suivi d'un deux-points — une clé attribut
"demo" partout ailleurs — une valeur chaîne
-12.5e+3, 42, 0.5 nombre
true, false, null constante
{, }, [, ], ,, : ponctuation
// jusqu'à la fin de la ligne ; /* … */ sur plusieurs lignes commentaire
tout mot nu — undefined, NaN, une clé sans guillemets identifiant

Une chaîne est une clé quand un deux-points la suit, au-delà des espaces éventuels, et une valeur sinon. {"a" 1} colore "a" comme une valeur : ce n'est pas encore une clé.

Les commentaires sont tolérés, pas approuvés. Le JSON strict n'en a pas ; tsconfig.json, les fichiers .jsonc et le fichier de réglages de chaque éditeur en ont, et un scanner qui les peindrait comme cassés aurait tort exactement dans les fichiers les plus susceptibles d'en contenir un.

Non reconnu Parce que
Si le document est du JSON valide Le scanner colore des tokens ; un mot nu sort comme un identifiant plutôt que d'arrêter la ligne, et une clé dupliquée ressemble à n'importe quelle autre
Les chaînes entre apostrophes, les virgules finales et le reste de JSON5 Pas du JSON ; un ' est enjambé sans couleur
Une chaîne non terminée qui s'arrête ailleurs qu'à sa ligne Elle est colorée jusqu'à la fin de la ligne, comme une valeur, et la ligne suivante est de nouveau du JSON

TOML

Reconnu Comme
# commentaire commentaire
[table], [[tableau]] le nom comme type, les crochets comme ponctuation
clé = identifiant, puis opérateur
"basique", 'littérale', """multiligne""", '''multiligne''' chaîne
true, false constante
nombres, dates, heures, inf, nan nombre

YAML

Un fichier compose, un manifeste Kubernetes et un workflow de CI sont tous cela : il n'y a pas de dialecte séparé, parce qu'un dialecte serait le schéma de quelqu'un d'autre à maintenir en phase.

Reconnu Comme
# commentaire commentaire
clé: avant un espace ou la fin de ligne la clé comme identifiant, le deux-points comme ponctuation
"citée": 1, 'citée': 1 la clé citée comme identifiant
- ouvrant un élément de séquence ponctuation
"…", '…' chaîne
true, false, yes, no, on, off, null constante, quelle que soit la casse
nombres, dates et heures écrits sans guillemets nombre
&ancre, *alias builtin
!!str, !Custom type
---, ... toute la ligne comme ponctuation
{, }, [, ], , ponctuation
|, >, avec leurs indicateurs de troncature et d'indentation l'en-tête comme opérateur, le corps comme chaîne

Un deux-points n'est un séparateur que si un espace ou la fin de ligne le suit. image: node:24-alpine est une clé et une valeur, et url: http://example.com/x est une clé et une URL — colorer les deux-points intérieurs comme séparateurs mettrait chaque tag d'image et chaque URL en trois couleurs.

L'étendue d'un scalaire bloc est décidée par l'indentation, pas par un délimiteur. La première ligne de contenu après | ou > fixe l'indentation du bloc ; chaque ligne indentée au moins autant lui appartient, et la première qui ne l'est pas le termine. Une ligne vide dans un bloc reste dans le bloc : un scalaire littéral garde ses lignes vides, et terminer le bloc au premier saut de paragraphe couperait en deux un script shell dans un fichier de CI.

Un # a besoin d'un espace devant pour ouvrir un commentaire, colour: ff#00aa est donc un seul scalaire.

Non reconnu Parce que
Le schéma d'un fichier compose, d'un manifeste ou d'un workflow Colorer services: autrement que n'importe quelle clé signifie porter le schéma de quelqu'un d'autre, et il vieillit le jour où ils ajoutent une clé
Les flux multi-documents comme documents séparés --- est coloré, mais rien n'est réinitialisé ; rien dans la coloration ne dépend des frontières de documents
Si un mot nu est une chaîne ou un nombre pour un parseur 1.2.3 est une version pour un lecteur et une chaîne pour YAML ; le scanner colore ce à quoi cela ressemble

Markdown

Reconnu Comme
# Titre###### Titre toute la ligne comme titre
**gras**, __gras__, *italique*, _italique_ emphase
`code` chaîne
[texte](cible), ![alt](src) le tout comme lien
- , * , + , 1. , 1) le marqueur comme ponctuation
> ponctuation
---, ***, ___ ponctuation
les clôtures ``` et ~~~ tout le bloc, lignes d'ouverture et de fermeture comprises, comme chaîne

Un bloc clôturé est d'une seule couleur quel que soit le langage annoncé : ```javascript ne colore pas son contenu comme du JavaScript dans un fichier Markdown. La suite de marqueurs qui ouvre un bloc doit être fermée par le même caractère, une clôture en accents graves n'est donc pas fermée par une en tildes. Une clôture non fermée colore jusqu'à la fin du fichier.

La suite de marqueurs ouvrant une emphase doit être fermée par une suite de même longueur, **gras** est donc une portée plutôt que deux italiques.

HTML

Reconnu Comme
<tag, </tag, >, /> balise
les noms d'attributs, dont data-*, xlink:href, @click, v-bind.prop attribut
= opérateur
"…", '…' chaîne
<!-- … -->, sur plusieurs lignes commentaire
&amp;, &#169; constante
<!DOCTYPE …> et les autres déclarations mot-clé

Le texte entre les balises n'est pas coloré. Un & nu sans ; dans les 32 caractères est laissé tranquille, parce que c'est du texte légal.

Le contenu de <script> et <style> n'est pas coloré comme du JavaScript et du CSS, même dans cet éditeur : le scanner HTML est celui de turbo-core, et il ne confie pas une région d'une ligne à un autre scanner.

XML

Son propre scanner plutôt que celui de HTML, pour une raison qui compte : CDATA. Tout l'intérêt de <![CDATA[ … ]]> est que son contenu n'est pas du balisage, et colorer les balises qu'il contient comme des balises est exactement à l'envers.

Reconnu Comme
<?xml version="1.0"?> et les autres instructions de traitement la cible et ?> comme mot-clé, les paires entre elles comme attributs et chaînes
<!DOCTYPE …> et les autres formes <! mot-clé
<!-- … -->, sur plusieurs lignes commentaire
<![CDATA[ … ]]>, sur plusieurs lignes chaîne
<tag, </tag, >, /> balise
<ns:tag>, xsi:type le préfixe et le nom local en une portée
les noms d'attributs attribut
= opérateur
"…", '…' chaîne
&amp;, &#169; constante

Un commentaire et une section CDATA se ferment sur des délimiteurs différents, et sont portés séparément : un --> dans une section CDATA ne la termine pas.

Un & nu sans point-virgule dans les 32 caractères est laissé tranquille, parce que c'est du texte légal dans bien des documents et qu'avaler le reste de la ligne serait la plus grosse erreur.

Le texte entre les balises n'est pas coloré.

Shell

Vaut pour sh, bash et zsh : les mots-clés reconnus sont ceux qu'ils partagent.

Reconnu Comme
if, then, fi, for, while, case, esac, function, return, … mot-clé
true, false constante
echo, printf, export, local, read, cd, set, source, … builtin
$NAME, ${…}, $(…), $1, $?, $@ builtin
le premier mot nu d'une ligne fonction
chaque mot nu suivant, et NAME dans NAME=valeur identifiant
'…', sans rien d'échappé ni de développé dedans chaîne
"…", avec les expansions dedans colorées comme des expansions chaîne
# jusqu'à la fin de ligne commentaire

$(a $(b) c) est une seule portée : l'imbrication est comptée. Une option comme -euo est un seul mot, pas un moins et un mot.

Les heredocs ne sont pas reconnus. <<EOF et le texte qui suit sont colorés comme du shell ordinaire.

Dockerfile

Reconnu Comme
FROM, RUN, COPY, ADD, ARG, ENV, CMD, ENTRYPOINT, EXPOSE, LABEL, USER, VOLUME, WORKDIR, HEALTHCHECK, ONBUILD, SHELL, STOPSIGNAL, MAINTAINER mot-clé, quelle que soit la casse
AS, NONE mot-clé
# commentaire, y compris les directives # syntax= et # escape= commentaire
--from=builder, --chown=me:me le nom de l'option comme attribut
$NAME, ${NAME}, ${NAME:-default} builtin, en une portée jusqu'à l'accolade fermante
"…", '…' chaîne
un \ final opérateur
les nombres nombre
les chemins et références d'images — /usr/local/bin, node:24-alpine identifiant, en une portée

Seul le premier mot d'une ligne peut être une instruction, et un mot qui n'en est pas une est un argument — ce qui garde le premier mot d'une ligne de continuation hors de la couleur des mots-clés.

Rien ne franchit une ligne. Un \ joint deux lignes pour Docker, mais chaque moitié se lit toujours comme une commande et est colorée seule.

Non reconnu Parce que
Le shell dans un RUN Il faudrait lancer le scanner shell sur une partie de ligne et reporter ses colonnes, et RUN peut contenir n'importe quel langage
Les heredocs dans un RUN La même raison que pour le scanner shell
Quelle étape un --from nomme Rien ici ne lit le reste du fichier

Voir aussi

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
# Référence : langages colorés

> Description neutre des fichiers que Turbo JS colore, de la façon dont il décide, et de ce que chaque scanner reconnaît.

## Reconnaissance

L'**extension** d'un fichier décide dès qu'elle est l'une de celles-ci :

| Extension | Langage |
| --- | --- |
| `.js`, `.mjs`, `.cjs` | JavaScript |
| `.json`, `.jsonc` | JSON |
| `.toml` | TOML |
| `.yaml`, `.yml` | YAML |
| `.md`, `.markdown` | Markdown |
| `.html`, `.htm` | HTML |
| `.xml`, `.xsd`, `.xsl`, `.xslt`, `.svg`, `.plist`, `.csproj`, `.pom` | XML |
| `.sh`, `.bash`, `.zsh` | Shell |
| `.dockerfile`, `.containerfile` | Dockerfile |

Les extensions sont comparées sans tenir compte de la casse, et seule la dernière compte : `notes.js.md` est du Markdown, `main.js.backup` n'est pas du JavaScript, et `main.test.js` est du JavaScript.

Un fichier dont l'extension ne décide rien est ensuite cherché par son **nom**. Seuls les fichiers sans extension utile en ont besoin :

| Nom | Langage |
| --- | --- |
| `Dockerfile`, `Containerfile` | Dockerfile |

Un nom correspond sur sa totalité ou sur la partie avant le premier point, sans tenir compte de la casse — `Dockerfile`, `dockerfile` et `Dockerfile.dev` sont donc tous reconnus, tandis que `Dockerfile.md` est du Markdown, parce que l'extension est consultée d'abord.

Un fichier que ni l'une ni l'autre table ne réclame est lu par sa **première ligne**. Un shebang nommant `node` en fait du JavaScript : un outil en ligne de commande écrit en JavaScript est un fichier sans extension dont la première ligne est `#!/usr/bin/env node`, et Node retire cette ligne avant de parser. Un shebang nommant un shell — `sh`, `bash`, `zsh`, `dash` ou `ksh` — en fait un script shell. L'interpréteur est reconnu comme élément de chemin ou comme argument d'`env`.

| Première ligne | Résultat |
| --- | --- |
| `#!/usr/bin/env node` | JavaScript |
| `#!/usr/local/bin/node` | JavaScript |
| `#!/usr/bin/env -S node --no-warnings` | JavaScript |
| `#!/bin/sh` | Shell |
| `#!/usr/bin/env bash` | Shell |
| `#!/usr/bin/env python3` | Non coloré |
| Tout ce qui ne commence pas par `#!` | Non coloré |

L'ordre est fixe — extension, puis nom, puis première ligne — et le premier qui décide l'emporte.

Tout le reste est affiché en texte brut. Ce n'est pas une erreur — ouvrir un PNG dans l'éditeur n'est pas une faute, c'est juste non coloré. En particulier, **TypeScript (`.ts`, `.tsx`), JSX (`.jsx`) et CSS ne sont pas colorés** : le serveur de langage sert les fichiers `.ts` quand même, mais le scanner ici est pour JavaScript.

## Classes

Chaque scanner produit le même vocabulaire de classes, et chacune correspond à une clé de thème.

| Classe | Clé de thème | Produite par |
| --- | --- | --- |
| `identifier` | `syntax.identifier` | JavaScript, JSON (un mot nu, qui n'est pas du JSON), TOML, shell, YAML, Dockerfile |
| `keyword` | `syntax.keyword` | JavaScript, shell, HTML (doctype), XML, Dockerfile |
| `type` | `syntax.type` | JavaScript (noms de classes et noms capitalisés), TOML (en-têtes de table), YAML (tags) |
| `builtin` | `syntax.builtin` | JavaScript (les globales de la bibliothèque standard et de Node), shell (builtins et expansions), YAML (ancres et alias), Dockerfile (variables) |
| `constant` | `syntax.constant` | JavaScript, JSON, TOML, shell, YAML, HTML et XML (entités) |
| `function` | `syntax.function` | JavaScript, shell (la commande) |
| `string` | `syntax.string` | tous |
| `char` | `syntax.char` | JavaScript (littéraux d'expressions régulières) |
| `number` | `syntax.number` | JavaScript, JSON, TOML, shell, YAML, Dockerfile |
| `comment` | `syntax.comment` | JavaScript, JSON, TOML, shell, HTML, YAML, XML, Dockerfile |
| `operator` | `syntax.operator` | JavaScript, TOML, shell, HTML, YAML (en-têtes de scalaires bloc), XML, Dockerfile |
| `punctuation` | `syntax.punctuation` | JavaScript, JSON, TOML, shell, Markdown, YAML, Dockerfile |
| `heading` | `syntax.heading` | Markdown |
| `tag` | `syntax.tag` | HTML, XML |
| `attribute` | `syntax.attribute` | JSON (clés), JavaScript (décorateurs), HTML, XML, Dockerfile (options) |
| `emphasis` | `syntax.emphasis` | Markdown |
| `link` | `syntax.link` | Markdown |

JavaScript ne produit aucune portée `heading`, `tag`, `emphasis` ou `link`. Dans `turbo-classic`, `syntax.number` et `syntax.constant` sont tous deux magenta et `syntax.char` a le vert de `syntax.string`, si bien que `42` et `true` partagent une couleur là, et `/re/` et `"re"` aussi ; d'autres thèmes les séparent. Voir [écrire son propre thème](../how-to/write-a-theme.md) pour changer cela.

## JavaScript

Écrit à la main, dans `internal/jslang`, et enregistré sous le même nom que le scanner que turbo-core livre pour JavaScript, qu'il remplace. Ce qu'il ajoute à celui de la bibliothèque : les littéraux d'expressions régulières, la ligne de hashbang, les globales de Node, le nom après `function` et `class`, les noms privés, les décorateurs, et une majuscule initiale lue comme un nom de classe.

**Deux constructions franchissent une ligne**, et sont portées à la ligne suivante : un commentaire bloc `/* … */` jusqu'à son `*/` fermant, et un littéral de gabarit `` `` `` jusqu'à son accent grave fermant. Aucune des deux ne s'imbrique. Une chaîne ordinaire `'…'` ou `"…"` ne franchit **pas** une ligne : une chaîne non terminée est colorée jusqu'à la fin de sa ligne, et la ligne suivante est de nouveau du code.

| Reconnu | Comme |
| --- | --- |
| `as`, `async`, `await`, `break`, `case`, `catch`, `class`, `const`, `continue`, `debugger`, `default`, `delete`, `do`, `else`, `export`, `extends`, `finally`, `for`, `from`, `function`, `get`, `if`, `import`, `in`, `instanceof`, `let`, `new`, `of`, `return`, `set`, `static`, `super`, `switch`, `throw`, `try`, `typeof`, `var`, `void`, `while`, `with`, `yield`, et les réservés `enum`, `implements`, `interface`, `package`, `private`, `protected`, `public` | mot-clé |
| `true`, `false`, `null`, `undefined`, `NaN`, `Infinity`, `this` | constante |
| les globales de la bibliothèque standard — `Array`, `Object`, `Promise`, `Math`, `JSON`, `Map`, `Set`, `Symbol`, `BigInt`, `Error`, `TypeError`, `parseInt`, `setTimeout`, `structuredClone`, `fetch`, `URL`, … | builtin |
| les globales de Node — `process`, `Buffer`, `console`, `require`, `module`, `exports`, `__dirname`, `__filename`, `setImmediate`, `performance`, `crypto` — et `document` et `window` du navigateur | builtin |
| le nom après `function`, `function*` ou `async function` — `parse` dans `function parse(input) {}` | fonction |
| le nom après `class` — `widget` dans `class widget extends Base {}` | type |
| tout autre nom commençant par une majuscule ASCII — `Greeter`, `EventEmitter`, `MyError` — même devant un `(` | type |
| tout autre nom immédiatement avant `(` — `compute(3)`, `obj.method()`, `this.#reset()` | fonction |
| tout mot après `.` ou `?.`, quelle que soit son orthographe — `map.get(k)` une fonction, `options.default` un nom, `user?.class` un nom | propriété, jamais un mot-clé |
| `get`, `set`, `static`, `of`, `from` et `as` devant un `(` — `get(key)` | fonction |
| `#count`, un membre privé, `#` compris | identifiant, ou fonction devant `(` |
| `@decorator`, `@observable.ref`, chemin pointé compris | attribut |
| tout autre nom : une lettre Unicode, `_` ou `$`, puis des lettres, des chiffres et les mêmes — `x`, `$el`, `_`, `café`, `名前` | identifiant |
| `"…"`, `'…'` avec les échappements par barre oblique inverse, sur une ligne | chaîne |
| `` `` ``, interpolations `${…}` comprises, sur plusieurs lignes | chaîne |
| `/…/gi`, un littéral d'expression régulière, drapeaux compris, là où le token précédent en permet un et qu'un `/` fermant existe sur la ligne | caractère |
| `42`, `1_000`, `0xFF`, `0o17`, `0b1010`, `1.5e-3`, `2E+10`, `.5`, `10n`, `0xFFn` | nombre |
| `//` jusqu'à la fin de la ligne ; `/* … */` et `/** … */` sur plusieurs lignes | commentaire |
| `#!` sur la première ligne du fichier, jusqu'à sa fin | commentaire |
| `...` | ponctuation, en une seule portée |
| `?.` | opérateur, en une seule portée |
| les suites de `+-*/%=<>!&\|^~?:` — dont `=>`, `??`, `===`, `**`, `>>>=` | opérateur |
| `()[]{},;` et un `.` seul | ponctuation |

**Une barre oblique divise après une valeur et ouvre une expression régulière partout ailleurs.** Après un nom, un nombre, une chaîne, un gabarit, une expression régulière, `)` ou `]`, un `/` est une division. Après un opérateur, `(`, `[`, `{`, `}`, `,`, `;`, `:`, un mot-clé, ou en début de ligne, il ouvre une expression régulière — **à condition qu'un `/` fermant existe sur la même ligne** ; sinon il divise, quoi qu'il y ait avant. Une expression régulière ne peut pas franchir une ligne, cette borne limite donc une mauvaise supposition à une ligne.

**Un point rejoint un nombre seulement quand un chiffre le suit**, `1.toString()` est donc le nombre `1`, un point et une méthode. **Le signe après un `e` fait partie du nombre**, sauf dans un littéral hexadécimal, où `0xE+1` est une somme.

**Un nom capitalisé est une classe par convention, pas par règle.** JavaScript vous laisse écrire `const Count = 1`, et il est coloré comme une classe quand même, tout comme `MAX_SIZE`. Les classes et les constructeurs sont ce que les gens capitalisent, et la couleur suit les gens.

**Non reconnu**, chacun pour une raison énoncée :

| Non reconnu | Parce que |
| --- | --- |
| Le code dans `${…}` d'un gabarit | Le colorer signifie que le scanner rentre en lui-même avec une profondeur d'imbrication à porter, pour une construction qui est d'habitude une courte expression ; tout le littéral est une chaîne |
| Un accent grave dans `${…}` | Pour la même raison : il termine le gabarit trop tôt, et le code qui suit est coloré comme du code jusqu'à l'accent grave suivant |
| Une expression régulière sans barre oblique fermante sur sa ligne | Elle ne peut pas en être une — le langage interdit un saut de ligne dans le littéral — la barre oblique divise donc |
| JSX | `<div>` est lu comme un opérateur, un nom et un opérateur ; il n'y a pas de HTML dans le JavaScript ici |
| Les annotations et les types de TypeScript | Un autre langage ; les fichiers `.ts` ne sont pas colorés du tout |
| Les commentaires bloc imbriqués | JavaScript termine un commentaire bloc au premier `*/` ; une profondeur serait une affirmation sur un autre langage |
| Une chaîne continuée par une barre oblique inverse finale | La chaîne s'arrête à sa ligne et la ligne suivante est du code ; la continuation est assez rare pour ne pas valoir d'être portée |
| Si un nom en `SCREAMING_SNAKE_CASE` est une constante | La majuscule initiale dit classe, et rien dans l'orthographe ne sépare les deux conventions |
| `#` comme commentaire | Il n'en est un que dans le hashbang, sur la première ligne ; partout ailleurs `#` commence un nom privé ou est enjambé |
| Si un nom est lié dans cette portée | Rien ici ne lit plus d'une ligne à la fois ; c'est la question du serveur de langage, et [F1 y répond](../how-to/ask-about-code.md) |

## JSON

Écrit à la main, dans `internal/jslang/json.go`, trente lignes, parce que le langage fait trente lignes : des chaînes, des nombres, trois mots, six signes de ponctuation. C'est le langage dans lequel est écrit le manifeste de chaque projet Node, et turbo-core ne le colore pas.

| Reconnu | Comme |
| --- | --- |
| `"name"` suivi d'un deux-points — une clé | attribut |
| `"demo"` partout ailleurs — une valeur | chaîne |
| `-12.5e+3`, `42`, `0.5` | nombre |
| `true`, `false`, `null` | constante |
| `{`, `}`, `[`, `]`, `,`, `:` | ponctuation |
| `//` jusqu'à la fin de la ligne ; `/* … */` sur plusieurs lignes | commentaire |
| tout mot nu — `undefined`, `NaN`, une clé sans guillemets | identifiant |

**Une chaîne est une clé quand un deux-points la suit**, au-delà des espaces éventuels, et une valeur sinon. `{"a" 1}` colore `"a"` comme une valeur : ce n'est pas encore une clé.

**Les commentaires sont tolérés, pas approuvés.** Le JSON strict n'en a pas ; `tsconfig.json`, les fichiers `.jsonc` et le fichier de réglages de chaque éditeur en ont, et un scanner qui les peindrait comme cassés aurait tort exactement dans les fichiers les plus susceptibles d'en contenir un.

| Non reconnu | Parce que |
| --- | --- |
| Si le document est du JSON valide | Le scanner colore des tokens ; un mot nu sort comme un identifiant plutôt que d'arrêter la ligne, et une clé dupliquée ressemble à n'importe quelle autre |
| Les chaînes entre apostrophes, les virgules finales et le reste de JSON5 | Pas du JSON ; un `'` est enjambé sans couleur |
| Une chaîne non terminée qui s'arrête ailleurs qu'à sa ligne | Elle est colorée jusqu'à la fin de la ligne, comme une valeur, et la ligne suivante est de nouveau du JSON |

## TOML

| Reconnu | Comme |
| --- | --- |
| `# commentaire` | commentaire |
| `[table]`, `[[tableau]]` | le nom comme type, les crochets comme ponctuation |
| `clé =` | identifiant, puis opérateur |
| `"basique"`, `'littérale'`, `"""multiligne"""`, `'''multiligne'''` | chaîne |
| `true`, `false` | constante |
| nombres, dates, heures, `inf`, `nan` | nombre |

## YAML

Un fichier compose, un manifeste Kubernetes et un workflow de CI sont tous cela : il n'y a pas de dialecte séparé, parce qu'un dialecte serait le schéma de quelqu'un d'autre à maintenir en phase.

| Reconnu | Comme |
| --- | --- |
| `# commentaire` | commentaire |
| `clé:` avant un espace ou la fin de ligne | la clé comme identifiant, le deux-points comme ponctuation |
| `"citée": 1`, `'citée': 1` | la clé citée comme identifiant |
| `- ` ouvrant un élément de séquence | ponctuation |
| `"…"`, `'…'` | chaîne |
| `true`, `false`, `yes`, `no`, `on`, `off`, `null` | constante, quelle que soit la casse |
| nombres, dates et heures écrits sans guillemets | nombre |
| `&ancre`, `*alias` | builtin |
| `!!str`, `!Custom` | type |
| `---`, `...` | toute la ligne comme ponctuation |
| `{`, `}`, `[`, `]`, `,` | ponctuation |
| `\|`, `>`, avec leurs indicateurs de troncature et d'indentation | l'en-tête comme opérateur, le corps comme chaîne |

**Un deux-points n'est un séparateur que si un espace ou la fin de ligne le suit.** `image: node:24-alpine` est une clé et une valeur, et `url: http://example.com/x` est une clé et une URL — colorer les deux-points intérieurs comme séparateurs mettrait chaque tag d'image et chaque URL en trois couleurs.

**L'étendue d'un scalaire bloc est décidée par l'indentation**, pas par un délimiteur. La première ligne de contenu après `|` ou `>` fixe l'indentation du bloc ; chaque ligne indentée au moins autant lui appartient, et la première qui ne l'est pas le termine. **Une ligne vide dans un bloc reste dans le bloc** : un scalaire littéral garde ses lignes vides, et terminer le bloc au premier saut de paragraphe couperait en deux un script shell dans un fichier de CI.

**Un `#` a besoin d'un espace devant pour ouvrir un commentaire**, `colour: ff#00aa` est donc un seul scalaire.

| Non reconnu | Parce que |
| --- | --- |
| Le schéma d'un fichier compose, d'un manifeste ou d'un workflow | Colorer `services:` autrement que n'importe quelle clé signifie porter le schéma de quelqu'un d'autre, et il vieillit le jour où ils ajoutent une clé |
| Les flux multi-documents comme documents séparés | `---` est coloré, mais rien n'est réinitialisé ; rien dans la coloration ne dépend des frontières de documents |
| Si un mot nu est une chaîne ou un nombre pour un parseur | `1.2.3` est une version pour un lecteur et une chaîne pour YAML ; le scanner colore ce à quoi cela ressemble |

## Markdown

| Reconnu | Comme |
| --- | --- |
| `# Titre``###### Titre` | toute la ligne comme titre |
| `**gras**`, `__gras__`, `*italique*`, `_italique_` | emphase |
| `` `code` `` | chaîne |
| `[texte](cible)`, `![alt](src)` | le tout comme lien |
| `- `, `* `, `+ `, `1. `, `1) ` | le marqueur comme ponctuation |
| `>` | ponctuation |
| `---`, `***`, `___` | ponctuation |
| les clôtures ` ``` ` et `~~~` | tout le bloc, lignes d'ouverture et de fermeture comprises, comme chaîne |

Un bloc clôturé est **d'une seule couleur quel que soit le langage annoncé** : ```` ```javascript ```` ne colore pas son contenu comme du JavaScript dans un fichier Markdown. La suite de marqueurs qui ouvre un bloc doit être fermée par le même caractère, une clôture en accents graves n'est donc pas fermée par une en tildes. Une clôture non fermée colore jusqu'à la fin du fichier.

La suite de marqueurs ouvrant une emphase doit être fermée par une suite de même longueur, `**gras**` est donc une portée plutôt que deux italiques.

## HTML

| Reconnu | Comme |
| --- | --- |
| `<tag`, `</tag`, `>`, `/>` | balise |
| les noms d'attributs, dont `data-*`, `xlink:href`, `@click`, `v-bind.prop` | attribut |
| `=` | opérateur |
| `"…"`, `'…'` | chaîne |
| `<!-- … -->`, sur plusieurs lignes | commentaire |
| `&amp;`, `&#169;` | constante |
| `<!DOCTYPE …>` et les autres déclarations | mot-clé |

Le texte entre les balises n'est pas coloré. Un `&` nu sans `;` dans les 32 caractères est laissé tranquille, parce que c'est du texte légal.

**Le contenu de `<script>` et `<style>` n'est pas coloré** comme du JavaScript et du CSS, même dans cet éditeur : le scanner HTML est celui de turbo-core, et il ne confie pas une région d'une ligne à un autre scanner.

## XML

Son propre scanner plutôt que celui de HTML, pour une raison qui compte : CDATA. Tout l'intérêt de `<![CDATA[ … ]]>` est que son contenu n'est *pas* du balisage, et colorer les balises qu'il contient comme des balises est exactement à l'envers.

| Reconnu | Comme |
| --- | --- |
| `<?xml version="1.0"?>` et les autres instructions de traitement | la cible et `?>` comme mot-clé, les paires entre elles comme attributs et chaînes |
| `<!DOCTYPE …>` et les autres formes `<!` | mot-clé |
| `<!-- … -->`, sur plusieurs lignes | commentaire |
| `<![CDATA[ … ]]>`, sur plusieurs lignes | chaîne |
| `<tag`, `</tag`, `>`, `/>` | balise |
| `<ns:tag>`, `xsi:type` | le préfixe et le nom local en **une** portée |
| les noms d'attributs | attribut |
| `=` | opérateur |
| `"…"`, `'…'` | chaîne |
| `&amp;`, `&#169;` | constante |

**Un commentaire et une section CDATA se ferment sur des délimiteurs différents**, et sont portés séparément : un `-->` dans une section CDATA ne la termine pas.

**Un `&` nu sans point-virgule dans les 32 caractères est laissé tranquille**, parce que c'est du texte légal dans bien des documents et qu'avaler le reste de la ligne serait la plus grosse erreur.

Le texte entre les balises n'est pas coloré.

## Shell

Vaut pour `sh`, `bash` et `zsh` : les mots-clés reconnus sont ceux qu'ils partagent.

| Reconnu | Comme |
| --- | --- |
| `if`, `then`, `fi`, `for`, `while`, `case`, `esac`, `function`, `return`, … | mot-clé |
| `true`, `false` | constante |
| `echo`, `printf`, `export`, `local`, `read`, `cd`, `set`, `source`, … | builtin |
| `$NAME`, `${…}`, `$(…)`, `$1`, `$?`, `$@` | builtin |
| le **premier mot nu d'une ligne** | fonction |
| chaque mot nu suivant, et `NAME` dans `NAME=valeur` | identifiant |
| `'…'`, sans rien d'échappé ni de développé dedans | chaîne |
| `"…"`, avec les expansions dedans colorées comme des expansions | chaîne |
| `#` jusqu'à la fin de ligne | commentaire |

`$(a $(b) c)` est une seule portée : l'imbrication est comptée. Une option comme `-euo` est un seul mot, pas un moins et un mot.

**Les heredocs ne sont pas reconnus.** `<<EOF` et le texte qui suit sont colorés comme du shell ordinaire.

## Dockerfile

| Reconnu | Comme |
| --- | --- |
| `FROM`, `RUN`, `COPY`, `ADD`, `ARG`, `ENV`, `CMD`, `ENTRYPOINT`, `EXPOSE`, `LABEL`, `USER`, `VOLUME`, `WORKDIR`, `HEALTHCHECK`, `ONBUILD`, `SHELL`, `STOPSIGNAL`, `MAINTAINER` | mot-clé, quelle que soit la casse |
| `AS`, `NONE` | mot-clé |
| `# commentaire`, y compris les directives `# syntax=` et `# escape=` | commentaire |
| `--from=builder`, `--chown=me:me` | le nom de l'option comme attribut |
| `$NAME`, `${NAME}`, `${NAME:-default}` | builtin, en une portée jusqu'à l'accolade fermante |
| `"…"`, `'…'` | chaîne |
| un `\` final | opérateur |
| les nombres | nombre |
| les chemins et références d'images — `/usr/local/bin`, `node:24-alpine` | identifiant, en **une** portée |

**Seul le premier mot d'une ligne peut être une instruction**, et un mot qui n'en est pas une est un argument — ce qui garde le premier mot d'une ligne de continuation hors de la couleur des mots-clés.

**Rien ne franchit une ligne.** Un `\` joint deux lignes pour Docker, mais chaque moitié se lit toujours comme une commande et est colorée seule.

| Non reconnu | Parce que |
| --- | --- |
| Le shell dans un `RUN` | Il faudrait lancer le scanner shell sur une partie de ligne et reporter ses colonnes, et `RUN` peut contenir n'importe quel langage |
| Les heredocs dans un `RUN` | La même raison que pour le scanner shell |
| Quelle étape un `--from` nomme | Rien ici ne lit le reste du fichier |

## Voir aussi

- [Format des fichiers de thème](themes.md) — chaque clé vers laquelle ces classes résolvent
- [Coloration et complétion](../explanation/colouring-and-completion.md) — pourquoi les scanners sont écrits ainsi
- [Écrire son propre thème](../how-to/write-a-theme.md)