Supported languages

Six languages are identified by name. Anything else that is clearly code still gets highlighted — just without language-specific rules.

How a language is chosen

Once a block has been confirmed as code, it is compared against a fingerprint for each supported language and the best match wins — but only if it wins clearly. Evidence for one language is often evidence against another, so a block that is unmistakably one thing tends to be unmistakably not the others, and the answer arrives with a comfortable margin.

When no language wins clearly, the block is labelled Unknown rather than guessed at, and coloured with a shared grammar instead. That is a deliberate outcome, not a failure: Java coloured as JavaScript looks worse than code coloured neutrally.

The fingerprints themselves are not published. They are the part of the tool that took the longest to get right, and knowing them does not help you use it — the label on every block is shown to you, and you can see for yourself whether it is correct. More on that decision.

Python

The easiest of the six to recognise, because its block syntax is unlike the rest: colon-terminated headers and significant indentation instead of braces and semicolons. Decorators, docstrings, f-strings and the dunder names are all strong tells, and the absence of C-family punctuation is as informative as any keyword.

Highlighting covers keywords, built-ins, decorators, all three string forms including triple-quoted blocks and f-string interpolation, numeric literals, and # comments.

Java

Recognised by its ceremony: access modifiers, the class-per-file structure, System.out, the standard-library package names, annotations and the public static void main signature. Java is rarely confused with anything else once more than a couple of lines are present.

Highlighting covers keywords, annotations, types, string and character literals, numeric literals with suffixes, and both // and /* */ comments, including Javadoc blocks — which are treated as part of the block they document rather than being stranded above it as prose.

C++

Recognised by the preprocessor, the standard-library namespace, stream operators, templates and the reference and pointer syntax that no other supported language shares. A listing with std:: in it is emphatically not Java or JavaScript, and the identification reflects that.

Highlighting covers keywords, preprocessor directives, standard types, string, character and raw-string literals, numeric literals, and both comment forms.

C

C and C++ share almost everything, so the two are not separated by which scores higher — that would be a coin toss on ordinary C. They are separated by asking whether anything in the listing actually requires C++. If nothing does, the block is C. A listing that would compile as either gets the smaller label, which is the honest answer.

Highlighting covers the C keyword set, the preprocessor, the standard integer and fixed-width types, string and character literals, and both comment forms.

JavaScript

Recognised by const and let, arrow functions, template literals, async/await, the module syntax, and the browser and Node globals. The absence of type annotations is what keeps it apart from TypeScript.

Highlighting covers keywords, built-in objects, template literals with their embedded expressions, regular-expression literals, numeric literals, and both comment forms.

TypeScript

Everything JavaScript has, plus the type system: annotations, interfaces, type aliases, generics, enums and the access modifiers on class members. Because TypeScript is a superset, the same rule used for C and C++ applies here — a listing is only called TypeScript if something in it genuinely requires TypeScript. Otherwise it is JavaScript.

Highlighting covers the JavaScript set plus type annotations, interfaces, generics and enum members.

When one language contains another

C++ contains C, and TypeScript contains JavaScript. For these two pairs, "whichever matches more" is the wrong question — the larger language matches everything the smaller one does, so the two would sit on top of each other and perfectly ordinary C would come back as Unknown.

Both pairs are settled the same way instead: does the larger language's own exclusive syntax appear at all? If not, the smaller label is used. It is the one that will compile either way.

How certain the identification is in practice

On a block of any real length — roughly five lines or more — identification is close to a solved problem, and it stays solved even in a document with no formatting hints at all, because a language leaves too many fingerprints across five lines to be mistaken for another.

Ambiguity shows up in short snippets, where there is simply not enough evidence for anything to stand out. Three lines of a C-family language that use nothing language-specific genuinely could be four different languages, and that is exactly when the tool declines to name one. You will see Unknown on the block rather than a confident wrong answer, and the code is still coloured.

What "Unknown" gets you

Blocks that cannot be identified still receive comment, string, number, keyword, function and type colouring from a shared grammar. In practice that covers Go, Rust, C#, PHP, Kotlin, Swift, SQL, shell and JSON well enough to read comfortably, even though none of them is formally supported.

Terminal output is handled separately and is never given a language at all — it is not source, so it is rendered on its own darker surface without keyword colouring, which is usually the fastest way to see that the tool understood your document correctly.

Adding a language

Adding a language is additive: the existing ones are unaffected. Go, Rust, C# and shell are the most likely next additions. If you need one, say so — requests are the main input to that decision.

Read next

How it works

What happens to your document between dropping it in and getting it back.

Worked examples

Real documents before and after, in every supported language.