# 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 | `