From fc0ddb03a14fa822213bb5474fb221b6fd12b747 Mon Sep 17 00:00:00 2001 From: nk-batman21 Date: Mon, 2 Nov 2026 05:47:04 +0700 Subject: [PATCH] Fix fenced code blocks for languages like c# and f# The language name after an opening fence only allowed word characters, `+` and `-`, so a fence such as ```c#, ```f# or ```vb.net was not treated as a fence. Its code was parsed as Markdown (C# `#region` lines became headers) and the closing fence opened a new code block. Also allow `#` and `.`, which Pygments uses in lexer names. --- CHANGES.md | 1 + lib/markdown2.py | 2 +- .../fenced_code_blocks_lang_with_symbols.html | 18 ++++++++++++++++++ .../fenced_code_blocks_lang_with_symbols.opts | 1 + .../fenced_code_blocks_lang_with_symbols.tags | 1 + .../fenced_code_blocks_lang_with_symbols.text | 15 +++++++++++++++ 6 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 test/tm-cases/fenced_code_blocks_lang_with_symbols.html create mode 100644 test/tm-cases/fenced_code_blocks_lang_with_symbols.opts create mode 100644 test/tm-cases/fenced_code_blocks_lang_with_symbols.tags create mode 100644 test/tm-cases/fenced_code_blocks_lang_with_symbols.text diff --git a/CHANGES.md b/CHANGES.md index cee783ed..afb0be54 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -26,6 +26,7 @@ - [pull #737] Fix XSS from code spans that the span gamut doesn't treat as code spans in safe mode (#726) - [pull #743] Add a `strip-syntax` option to the `header-ids` extra that leaves link URLs, image paths, inline HTML tags and emphasis markers out of header ids (#192) - [pull #747] Fix `link-patterns` extra linking text inside Markdown links and images whose label wraps onto another line +- [pull #759] Fix `fenced-code-blocks` extra not recognizing code blocks whose language name contains `#` or `.`, such as `c#`, `f#` and `vb.net` ## python-markdown2 2.5.5 diff --git a/lib/markdown2.py b/lib/markdown2.py index 3632a54e..e35bf5d2 100755 --- a/lib/markdown2.py +++ b/lib/markdown2.py @@ -3685,7 +3685,7 @@ class FencedCodeBlocks(Extra): fenced_code_block_re = re.compile(r''' (?:\n+|\A\n?|(?<=\n)) - (^[ \t]*`{3,})\s{0,99}?([\w+-]+)?\s{0,99}?\n # $1 = opening fence (captured for back-referencing), $2 = optional lang + (^[ \t]*`{3,})\s{0,99}?([\w+\#.-]+)?\s{0,99}?\n # $1 = opening fence (captured for back-referencing), $2 = optional lang (.*?) # $3 = code block content \1[ \t]*\n # closing fence ''', re.M | re.X | re.S) diff --git a/test/tm-cases/fenced_code_blocks_lang_with_symbols.html b/test/tm-cases/fenced_code_blocks_lang_with_symbols.html new file mode 100644 index 00000000..0f9e14f1 --- /dev/null +++ b/test/tm-cases/fenced_code_blocks_lang_with_symbols.html @@ -0,0 +1,18 @@ +
+
#region Setup
+var x = 1;
+#endregion
+
+
+ +

Some text between the blocks.

+ +
+
let x = 1
+
+
+ +
+
Dim x As Integer
+
+
diff --git a/test/tm-cases/fenced_code_blocks_lang_with_symbols.opts b/test/tm-cases/fenced_code_blocks_lang_with_symbols.opts new file mode 100644 index 00000000..ba411ac7 --- /dev/null +++ b/test/tm-cases/fenced_code_blocks_lang_with_symbols.opts @@ -0,0 +1 @@ +{"extras": ["fenced-code-blocks"]} diff --git a/test/tm-cases/fenced_code_blocks_lang_with_symbols.tags b/test/tm-cases/fenced_code_blocks_lang_with_symbols.tags new file mode 100644 index 00000000..7fa5d6a0 --- /dev/null +++ b/test/tm-cases/fenced_code_blocks_lang_with_symbols.tags @@ -0,0 +1 @@ +extra fenced-code-blocks pygments pygments>=2.21 diff --git a/test/tm-cases/fenced_code_blocks_lang_with_symbols.text b/test/tm-cases/fenced_code_blocks_lang_with_symbols.text new file mode 100644 index 00000000..98e2cea7 --- /dev/null +++ b/test/tm-cases/fenced_code_blocks_lang_with_symbols.text @@ -0,0 +1,15 @@ +```c# +#region Setup +var x = 1; +#endregion +``` + +Some *text* between the blocks. + +```f# +let x = 1 +``` + +```vb.net +Dim x As Integer +```