Skip to content

Commit e30dbb5

Browse files
committed
Add lang_prefix config option.
1 parent 3ab4259 commit e30dbb5

File tree

9 files changed

+155
-20
lines changed

9 files changed

+155
-20
lines changed

.spell-dict

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ PHP
7777
Posix
7878
postprocessor
7979
postprocessors
80+
prepend
81+
prepended
8082
preprocessor
8183
preprocessors
8284
Pygments

docs/change_log/release-3.3.md

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,29 @@ PyPy3.
77

88
## Backwards-incompatible changes
99

10-
...
10+
### The prefix `language-` is now prepended to all language classes by default on code blocks.
11+
12+
The [HTML5 spec][spec] recomends that the class defining the language of a code block be prefixed with `language-`.
13+
Therefore, by default, both the [fenced_code] and [codehilite] extensions now prepend the prefix when code
14+
highlighting is disabled.
15+
16+
If you have previously been including the prefix manuually in your fenced code blocks, then you will not want a second
17+
instance of the prefix. Similarily, if you are using a third party syntax highlighting tool which does not recognize
18+
the prefix, or requires a different prefix, then you will want to redefine the prefix globaly using the `lang_prefix`
19+
configuration option of either the `fenced_code` or `codehilite` extensions.
20+
21+
For example, to confiurgure `fenced_code` to not apply any prefix (the previous behavior), set the option to an empty string:
22+
23+
```python
24+
from markdown.extensions.fenced_code import FencedCodeExtension
25+
26+
markdown.markdown(src, extensions=[FencedCodeExtension(lang_prefix='')])
27+
```
28+
29+
!!! note
30+
When code highlighting is [enabled], the output from Pygments is used unaltered. Currently, Pygments does not
31+
provide an option to include the language class in the output, let alone prefix it. Therefore, any language prefix
32+
is only applied when syntax highlighting is disabled.
1133

1234
## New features
1335

@@ -33,3 +55,8 @@ The following bug fixes are included in the 3.3 release:
3355

3456
* Fix issues with complex emphasis (#979).
3557
* Limitations of `attr_list` extension are Documented (#965).
58+
59+
[spec]: https://www.w3.org/TR/html5/text-level-semantics.html#the-code-element
60+
[fenced_code]: ../extensions/fenced_code_blocks.md
61+
[codehilite]: ../extensions/code_hilite.md
62+
[enabled]: ../extensions/fenced_code_blocks.md#enabling-syntax-highlighting

docs/extensions/code_hilite.md

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ configuring extensions.
185185

186186
The following options are provided to configure the output:
187187

188-
* **`linenums`**:
188+
* **`linenums`**{ #linenums }:
189189
An alias to Pygments' `linenos` formatter option. Possible values are `True` for yes, `False` for no and `None`
190190
for auto. Defaults to `None`.
191191

@@ -195,39 +195,44 @@ The following options are provided to configure the output:
195195
Using `False` will turn off all line numbers, even when using shebangs
196196
(`#!`) for language identification.
197197

198-
* **`guess_lang`**:
198+
* **`guess_lang`**{ #guess_lang }:
199199
Automatic language detection. Defaults to `True`.
200200

201201
Using `False` will prevent Pygments from guessing the language, and thus
202202
highlighting blocks only when you explicitly set the language.
203203

204-
* **`css_class`**:
204+
* **`css_class`**{ #css_class }:
205205
An alias to Pygments `cssclass` formatter option. Set CSS class name for the wrapper `<div>` tag. Defaults to
206206
`codehilite`.
207207

208-
* **`pygments_style`**:
208+
* **`pygments_style`**{ #pygments_style }:
209209
Pygments HTML Formatter Style (`ColorScheme`). Defaults to `default`.
210210

211211
!!! Note
212212
This is useful only when `noclasses` is set to `True`, otherwise the
213213
CSS styles must be provided by the end user.
214214

215-
* **`noclasses`**:
215+
* **`noclasses`**{ #noclasses }:
216216
Use inline styles instead of CSS classes. Defaults to `False`.
217217

218-
* **`use_pygments`**:
218+
* **`use_pygments`**{ #use_pygments }:
219219
Specifies the use of Pygments in generating the output.
220220

221221
If `True` (the default) and Pygments is available, CodeHilite will use
222222
Pygments to analyze and format the output. Additionally, if using Pygments
223223
&gt;= 2.4, the output will be wrapped in `<code>` tags, whereas earlier
224224
versions will not.
225225

226-
Otherwise, Pygments will not be used. If a language is defined for a code
227-
block, it will be assigned to the `<code>` tag as a class in the manner
228-
suggested by the [HTML5 spec][spec] (alternate output will not be
229-
entertained) and may be used by a JavaScript library in the browser to
230-
highlight the code block.
226+
Otherwise, Pygments will not be used. If a language is defined for a code block, it will be assigned to the
227+
`<code>` tag as a class in the manner suggested by the [HTML5 spec][spec] and may be used by a JavaScript library
228+
in the browser to highlight the code block. See the [`lang_prefix`](#lang_prefix) option to customize the prefix.
229+
230+
* **`lang_prefix`**{ #lang_prefix }:
231+
The prefix prepended to the language class assigned to the HTML `<code>` tag. Default: `language-`.
232+
233+
This option only applies when `use_pygments` is `False` as Pygments does not provide an option to include a
234+
language prefix.
235+
231236

232237
* Any other Pygments' options:
233238

docs/extensions/fenced_code_blocks.md

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,8 @@ Either of the above examples will output the following HTML:
116116

117117
Note that the language name has been prefixed with `language-` and it has been assigned to the `class` attribute on
118118
the `<code>` tag, which is the format suggested by the [HTML 5 Specification][html5] (see the second "example" in the
119-
Specification).
119+
Specification). While `language` is the default prefix, the prefix may be overridden using the
120+
[`lang_prefix`](#lang_prefix) configuration option.
120121

121122
#### Classes
122123

@@ -240,7 +241,12 @@ they would if syntax highlighting was disabled for that code block regardless of
240241

241242
See [Extensions] for general extension usage. Use `fenced_code` as the name of the extension.
242243

243-
This extension does not accept any special configuration options.
244+
See the [Library Reference] for information about configuring extensions.
245+
246+
The following option is provided to configure the output:
247+
248+
* **`lang_prefix`**{#lang_prefix}:
249+
The prefix prepended to the language class assigned to the HTML `<code>` tag. Default: `language-`.
244250

245251
A trivial example:
246252

@@ -260,3 +266,4 @@ markdown.markdown(some_text, extensions=['fenced_code'])
260266
[PHP lexer's]: https://pygments.org/docs/lexers/#lexers-for-php-and-related-languages
261267
[setup]: ./code_hilite.md#setup
262268
[Extensions]: ./index.md
269+
[Library Reference]: ../reference.md#extensions

markdown/extensions/codehilite.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ def __init__(self, src, **options):
9595
self.lang = options.pop('lang', None)
9696
self.guess_lang = options.pop('guess_lang', True)
9797
self.use_pygments = options.pop('use_pygments', True)
98+
self.lang_prefix = options.pop('lang_prefix', 'language-')
9899

99100
if 'linenos' not in options:
100101
options['linenos'] = options.pop('linenums', None)
@@ -145,7 +146,7 @@ def hilite(self):
145146
txt = txt.replace('"', '&quot;')
146147
classes = []
147148
if self.lang:
148-
classes.append('language-{}'.format(self.lang))
149+
classes.append('{}{}'.format(self.lang_prefix, self.lang))
149150
if self.options['linenos']:
150151
classes.append('linenums')
151152
class_str = ''
@@ -268,7 +269,11 @@ def __init__(self, **kwargs):
268269
'use_pygments': [True,
269270
'Use Pygments to Highlight code blocks. '
270271
'Disable if using a JavaScript library. '
271-
'Default: True']
272+
'Default: True'],
273+
'lang_prefix': [
274+
'language-',
275+
'Prefix prepended to the language when use_pygments is false. Default: "language-"'
276+
]
272277
}
273278

274279
for key, value in kwargs.items():

markdown/extensions/fenced_code.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,17 @@
2626

2727

2828
class FencedCodeExtension(Extension):
29+
def __init__(self, **kwargs):
30+
self.config = {
31+
'lang_prefix': ['language-', 'Prefix prepended to the language. Default: "language-"']
32+
}
33+
super().__init__(**kwargs)
2934

3035
def extendMarkdown(self, md):
3136
""" Add FencedBlockPreprocessor to the Markdown instance. """
3237
md.registerExtension(self)
3338

34-
md.preprocessors.register(FencedBlockPreprocessor(md), 'fenced_code_block', 25)
39+
md.preprocessors.register(FencedBlockPreprocessor(md, self.getConfigs()), 'fenced_code_block', 25)
3540

3641

3742
class FencedBlockPreprocessor(Preprocessor):
@@ -48,9 +53,9 @@ class FencedBlockPreprocessor(Preprocessor):
4853
re.MULTILINE | re.DOTALL | re.VERBOSE
4954
)
5055

51-
def __init__(self, md):
56+
def __init__(self, md, config):
5257
super().__init__(md)
53-
58+
self.config = config
5459
self.checked_for_deps = False
5560
self.codehilite_conf = {}
5661
self.use_attr_list = False
@@ -116,7 +121,10 @@ def run(self, lines):
116121
else:
117122
id_attr = class_attr = kv_pairs = ''
118123
if classes:
119-
class_attr = ' class="{}"'.format('language-' + ' '.join(classes))
124+
class_attr = ' class="{}{}"'.format(
125+
self.config.get('lang_prefix', 'language-'),
126+
' '.join(classes)
127+
)
120128
if id:
121129
id_attr = ' id="{}"'.format(id)
122130
if self.use_attr_list and config and not config.get('use_pygments', False):

mkdocs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ nav:
4141
- Test Tools: test_tools.md
4242
- Contributing to Python-Markdown: contributing.md
4343
- Change Log: change_log/index.md
44+
- Release Notes for v.3.3: change_log/release-3.3.md
4445
- Release Notes for v.3.2: change_log/release-3.2.md
4546
- Release Notes for v.3.1: change_log/release-3.1.md
4647
- Release Notes for v.3.0: change_log/release-3.0.md

tests/test_syntax/extensions/test_code_hilite.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,24 @@ def test_codehilite_use_pygments_false(self):
128128
)
129129
self.assertOutputEquals('<?php print("Hello World"); ?>', expected, lang='php', use_pygments=False)
130130

131+
def test_codehilite_lang_prefix_empty(self):
132+
expected = (
133+
'<pre class="codehilite"><code class="php">&lt;?php print(&quot;Hello World&quot;); ?&gt;\n'
134+
'</code></pre>'
135+
)
136+
self.assertOutputEquals(
137+
'<?php print("Hello World"); ?>', expected, lang='php', use_pygments=False, lang_prefix=''
138+
)
139+
140+
def test_codehilite_lang_prefix(self):
141+
expected = (
142+
'<pre class="codehilite"><code class="lang-php">&lt;?php print(&quot;Hello World&quot;); ?&gt;\n'
143+
'</code></pre>'
144+
)
145+
self.assertOutputEquals(
146+
'<?php print("Hello World"); ?>', expected, lang='php', use_pygments=False, lang_prefix='lang-'
147+
)
148+
131149
def test_codehilite_linenos_true(self):
132150
if has_pygments:
133151
expected = (
@@ -495,6 +513,32 @@ def testUsePygmentsFalse(self):
495513
extensions=[CodeHiliteExtension(use_pygments=False)]
496514
)
497515

516+
def testLangPrefixEmpty(self):
517+
self.assertMarkdownRenders(
518+
(
519+
'\t:::Python\n'
520+
'\t# A Code Comment'
521+
),
522+
(
523+
'<pre class="codehilite"><code class="python"># A Code Comment\n'
524+
'</code></pre>'
525+
),
526+
extensions=[CodeHiliteExtension(use_pygments=False, lang_prefix='')]
527+
)
528+
529+
def testLangPrefix(self):
530+
self.assertMarkdownRenders(
531+
(
532+
'\t:::Python\n'
533+
'\t# A Code Comment'
534+
),
535+
(
536+
'<pre class="codehilite"><code class="lang-python"># A Code Comment\n'
537+
'</code></pre>'
538+
),
539+
extensions=[CodeHiliteExtension(use_pygments=False, lang_prefix='lang-')]
540+
)
541+
498542
def testDoubleEscape(self):
499543
if has_pygments:
500544
expected = (

tests/test_syntax/extensions/test_fenced_code.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -703,3 +703,39 @@ def testFencedLanguagePygmentsEnabledInAttrNoCodehiliteWithAttrList(self):
703703
),
704704
extensions=['fenced_code', 'attr_list']
705705
)
706+
707+
def testFencedLanguageNoPrefix(self):
708+
self.assertMarkdownRenders(
709+
self.dedent(
710+
'''
711+
``` python
712+
# Some python code
713+
```
714+
'''
715+
),
716+
self.dedent(
717+
'''
718+
<pre><code class="python"># Some python code
719+
</code></pre>
720+
'''
721+
),
722+
extensions=[markdown.extensions.fenced_code.FencedCodeExtension(lang_prefix='')]
723+
)
724+
725+
def testFencedLanguageAltPrefix(self):
726+
self.assertMarkdownRenders(
727+
self.dedent(
728+
'''
729+
``` python
730+
# Some python code
731+
```
732+
'''
733+
),
734+
self.dedent(
735+
'''
736+
<pre><code class="lang-python"># Some python code
737+
</code></pre>
738+
'''
739+
),
740+
extensions=[markdown.extensions.fenced_code.FencedCodeExtension(lang_prefix='lang-')]
741+
)

0 commit comments

Comments
 (0)