Markdown Code Block Language List and Aliases
Choose the language tag documented by your destination, and keep the code fence even if that destination does not highlight code. A Markdown code block language list helps with four cases: choosing a tag, a valid tag with no colors, an unlabelled block, and deliberately plain output.
Match the block to its rendering problem
Match the symptom to the rendering layer before changing a language tag.
| What you have | How to recognize it | Which path to take |
|---|---|---|
| Code that needs a language label | The opening fence has no language word | Choose an identifier from the common list and the target's registry |
| A labelled block with no colors | The HTML contains a code block and a language class, but no syntax markup | Inspect the highlighter configuration and loaded grammar |
| An unlabelled block that receives unwanted colors | The source fence has no label, while the destination assigns colors | Use that destination's explicit plain-text convention |
| Logs or literal text that need no highlighting | The content is output, not source code to classify | Choose a documented plain-text label or disable highlighting |
The word after the opening fence is part of the info string. CommonMark describes using its first word for the language as a convention, while leaving its treatment to implementations. A successful code fence therefore establishes a code block without guaranteeing that a highlighter recognizes the label. 1
Put the identifier after the opening backticks, and leave the closing fence without a language name. This input was used in the local comparison:
```javascript
const name = "Ada";
console.log(name);
console.log(name.length);
```
The code is JavaScript regardless of whether the destination colors it. Changing the language word selects a different requested grammar; it does not translate the code or execute it. If the block itself fails to form, adding an alias cannot repair the fence delimiters. 19
A Markdown code block language list to copy
Use a familiar language name, with aliases tied to the highlighter that documents them.
The table is a starting reference drawn from the official highlight.js and Prism directories. It lists common identifiers rather than every supported language. Neither directory guarantees that a website has loaded every grammar, and the alias columns describe those libraries, not GitHub or every Markdown editor. 23
| Content | Start with | highlight.js aliases | Prism aliases |
|---|---|---|---|
| JavaScript | javascript |
js, jsx |
js |
| TypeScript | typescript |
ts, tsx |
ts |
| Python | python |
py |
py |
| Bash script | bash |
sh, zsh |
sh, shell |
| C | c |
h |
Use the full identifier |
| C++ | cpp |
c++, cxx |
Use the full identifier |
| C# | csharp |
cs |
cs, dotnet |
| Java | java |
jsp |
Use the full identifier |
| Go | go |
golang |
Use the full identifier |
| Rust | rust |
rs |
Use the full identifier |
| Ruby | ruby |
rb |
rb |
| JSON | json |
Use the full identifier | Use the full identifier |
| YAML | yaml |
yml |
yml |
| HTML | html |
xml, xhtml |
markup, xml |
| CSS | css |
Use the full identifier | Use the full identifier |
| SQL | sql |
Use the full identifier | Use the full identifier |
| Markdown | markdown |
md |
md |
| A patch | diff |
patch |
Use the full identifier |
An alias is a name a particular library recognizes. It can select a broad grammar rather than a dedicated dialect. For example, an accepted JSX alias does not establish that another library's JavaScript grammar handles JSX identically. Keep the language distinction when your source needs it, and consult the destination's own entry for that dialect. 23
The word shell needs particular care. Prism lists it as an alias for Bash, while highlight.js lists shell with console under its Shell entry. Prism gives shell sessions separate identifiers, including shell-session and shellsession. For a Bash script, bash avoids that ambiguity. For a transcript containing prompts and command output, use the destination's session identifier. 23
Use python or javascript as readable defaults when the target accepts them. Preserve a target-specific alias when the publishing system requires it.
Find the list that belongs to your target
The authoritative list belongs to your destination's highlighter or application.
| Destination | Where to look | What the list establishes |
|---|---|---|
| GitHub.com | GitHub's code-block documentation, then Linguist's language registry | The language names and aliases GitHub directs authors to use |
| A site using highlight.js | Its supported-language directory and the site's imports | The available definitions, subject to what the site loads |
| A site using Prism | Its language directory and the configured components | The grammars and aliases available to that build |
| Python-Markdown | The enabled extensions and CodeHilite configuration | Whether labels are passed through or Pygments is involved |
| Pandoc | The installed executable's --list-highlight-languages output |
The language names recognized by that Pandoc installation |
GitHub documents using Linguist to select third-party grammars. Its guide links to the language registry rather than promising that any spelling from another highlighter will work. GitHub Pages has its own publishing stack; GitHub's guide recommends lowercase identifiers when the same block should highlight there. Our local Pandoc GFM run does not test either hosted destination. 4
For a site you maintain, distinguish a library's catalog from the application's loaded subset. A language can appear in an official directory while the build omits its definition. Renaming a valid identifier cannot load an absent grammar. The concrete configuration question is which language modules the application imports, alongside the script and styles it uses to display highlighted code. 23
Prism and highlight.js were not executed for this guide. Their entries above are documentation checks.
A valid language tag can still produce plain code
A recognized fence can preserve its language label without generating syntax markup.
In markdown-it-py with CommonMark mode and no highlighting callback, the JavaScript sample retained its label but received no token markup. Its fence renderer handles the label separately from highlighting: it calls the configured callback when one exists, otherwise escapes the code, then adds the language class. A misspelled tag follows the same class-writing path. 59
Output from our JavaScript sample, unedited:
<pre><code class="language-javascript">const name = "Ada";
console.log(name);
console.log(name.length);
</code></pre>
Python-Markdown with only the fenced-code extension produced the same visible HTML text. Its preprocessor enters the highlighting branch only when the relevant CodeHilite configuration enables Pygments. The alternative branch escapes the code and adds a language class. Installing or enabling fence parsing alone therefore leaves a separate highlighting choice to the application. 679
Output from our JavaScript sample, unedited:
<pre><code class="language-javascript">const name = "Ada";
console.log(name);
console.log(name.length);
</code></pre>
Pandoc's GFM reader with its internal highlighter produced token markup for both the full JavaScript name and its short alias. Removing a letter from the name left the code intact but produced no such markup. The misspelling remained attached to the outer block, so its presence in an HTML class would still be insufficient evidence of grammar recognition. 912
Output from our misspelled JavaScript sample, unedited:
<pre class="javascrpt"><code>const name = "Ada";
console.log(name);
console.log(name.length);</code></pre>
The outputs do not show browser colors. Pandoc supplies its own highlighting stage, while the tested parser configurations leave that stage absent. Changing aliases in those parser configurations cannot activate a callback or extension that was never configured. 568
Choose plain output or fix the failing layer
Fix the missing stage, and use the destination's explicit plain-text convention for output that needs no colors.
| Observed failure | What it points to | Concrete next action |
|---|---|---|
| The intended code block is absent | Fence parsing or surrounding structure | Correct the opening and closing delimiters before changing the label |
| A misspelled label survives in HTML without token markup | Label transfer without grammar recognition | Replace it with the destination's documented identifier |
| A known label survives, but every labelled block lacks token markup | An absent or disabled highlighting stage is a candidate | Inspect the configured callback, extension, or loaded browser highlighter |
| Token markup exists but the code appears monochrome | Styling is a candidate | Inspect the token element's applied color rules in browser developer tools |
| Only a particular language fails | The grammar or identifier is a candidate | Compare that language with the actual modules included in the build |
The styling row is an inference from Prism's documented token classes and CSS model. Our experiment did not render a browser page. 39
For deliberate plain output, highlight.js documents plaintext, txt, and text for Plaintext. Prism documents language-none to opt out of highlighting and language-plain when plugins should remain available. A Markdown renderer that passes the language word through as a class can carry those conventions to the relevant library. A blank fence alone does not specify a universal policy for automatic detection. 23
Use the plain-text convention documented by the publishing target, especially when output contains words that resemble a programming language. Keep genuine source code labelled with the language it contains.
For material that starts as a PDF, a PDF to Markdown converter addresses the conversion stage. Apply these fence choices when editing the resulting Markdown. A recovered snippet needs a language identifiable from its source. Keep uncertain material plain according to the destination's convention.
Use the common list for spelling, the destination's registry for support, and the rendered block for locating a failure. When a known label reaches the HTML without syntax markup, inspect the highlighting stage. When the label is unknown, correct the identifier. When the content should remain plain, choose that behavior explicitly in the destination.
How we tested
The local runs measured code-block structure and preserved text, not appearance in a hosted editor.
Tests ran on 2026-11-01 using Python 3.11.14, markdown-it-py 4.0.0, Python-Markdown 3.10.2, and Pandoc 3.11. The upstream syntax matrix in lab/renderers/results.json supplied the initial code-block.md case. Unrelated newline, table, and list cases are outside this article. The focused probe used these inputs: 9
Input filenames in lab/renderers/ |
What they represent |
|---|---|
language-javascript.md, language-js.md, language-javascript-upper.md |
Identical JavaScript with a full name, alias, and mixed-case label |
language-javascrpt.md, language-unlabelled.md |
The same JavaScript with a typo or no label |
language-text.md, language-plaintext.md, language-none.md |
The same body with plain-output label candidates |
language-python.md, language-py.md |
Identical Python with its full name and alias |
language-bash.md, language-sh.md, language-shell.md, language-console.md, language-shellsession.md |
Identical terminal-session text under script/session label candidates |
Run from the repository root in the prepared environment:
PYTHONDONTWRITEBYTECODE=1 .venv/bin/python runs/2026-11-01-markovo-markdown-code-block-language-list/lab/renderers/language_probe.py
The script calls MarkdownIt('commonmark', {'highlight': None}).render(source) and markdown.markdown(source, extensions=['fenced_code']). It feeds each input to the first Pandoc command and records the installed language registry with the second:
pandoc -f gfm -t html --syntax-highlighting=pygments
pandoc --list-highlight-languages
The first command reads Markdown on standard input. The second records the installed registry as pandoc-highlight-languages.txt. Pandoc's pygments name selects a theme; its internal highlighting engine is skylighting, not Python Pygments. The probe never executes the fenced JavaScript, Python, or terminal commands. Prism, highlight.js, and CodeHilite/Pygments were not executed for this guide. 810
Each raw output is named language-<sample>--<renderer>.txt in lab/renderers/. The renderer suffixes are markdown-it-commonmark, python-markdown-fenced, and pandoc-gfm. The excerpts above come from language-javascript--markdown-it-commonmark.txt, language-javascript--python-markdown-fenced.txt, and language-javascrpt--pandoc-gfm.txt. Full-name/alias Pandoc outputs are linked with the results. 91112
The following counts are copied from language-results.json. “Token spans” counts class-bearing span elements inside code, excluding line-ID spans and anchors. Every listed row had one pre and one code element. “Text kept” compares decoded code text with the input body, allowing only a single final newline difference. These measures do not score visual fidelity, grammar correctness, or complete token coverage. 9
| Input label | markdown-it token spans | Python-Markdown token spans | Pandoc token spans | Text kept |
|---|---|---|---|---|
| javascript | 0 | 0 | 14 | All three |
| js | 0 | 0 | 14 | All three |
| JavaScript | 0 | 0 | 14 | All three |
| javascrpt | 0 | 0 | 0 | All three |
| No label | 0 | 0 | 0 | All three |
| text | 0 | 0 | 0 | All three |
| plaintext | 0 | 0 | 0 | All three |
| none | 0 | 0 | 0 | All three |
| python | 0 | 0 | 5 | All three |
| py | 0 | 0 | 5 | All three |
| bash | 0 | 0 | 4 | All three |
| sh | 0 | 0 | 4 | All three |
| shell | 0 | 0 | 0 | All three |
| console | 0 | 0 | 0 | All three |
| shellsession | 0 | 0 | 0 | All three |
The local source excerpts markdown-it-fence-source.txt and python-markdown-fence-source.txt preserve the installed functions discussed above. The script records source/output hashes and checks them against files on disk. All 45 tool-by-input rows are reported, including outputs without token markup. These are local implementations: markdown-it-py CommonMark mode and Pandoc GFM do not constitute tests of GitHub.com or VS Code. No CSS rendering, hosted editor, PDF conversion, or OCR test was performed. 91013
Sources
- CommonMark 0.31.2, fenced code blocks
- highlight.js supported languages
- Prism language directory and usage
- GitHub: creating and highlighting code blocks
- markdown-it-py v4.0.0 renderer source
- Python-Markdown 3.10.2 fenced-code source
- Python-Markdown CodeHilite configuration
- Pandoc syntax highlighting
- Focused rendering results and hashes
- Reproduction script
- JavaScript output: markdown-it-py
- Pandoc misspelling output
- Installed fence renderer source


