Skip to content

Commit eebdc53

Browse files
authored
Merge pull request #25 from elkirby/fenced-code-blocks-835
Fenced code blocks 835
2 parents 425332c + 637ac3f commit eebdc53

File tree

12 files changed

+369
-9
lines changed

12 files changed

+369
-9
lines changed

Authors.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@ Contributors
1212

1313
* Dave MacNamara <dave@mobelux.com>
1414
* Justin Michalicek <justin@mobelux.com>
15+
* Erin Kirby <erin@mobelux.com>

CONTRIBUTING.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ Before you submit a pull request, check that it meets these guidelines:
101101
2. If the pull request adds functionality, the docs should be updated. Put
102102
your new functionality into a function with a docstring, and add the
103103
feature to the list in README.rst.
104-
3. The pull request should work for Python 2.7, 3.2, 3.3, 3.4 and 3.5, and for PyPy. Check
104+
3. The pull request should work for Python 2.7, 3.4, 3.5, 3.6 and 3.7, and for PyPy. Check
105105
https://travis-ci.org/livio/DocDown-Python/pull_requests
106106
and make sure that the tests pass for all supported Python versions.
107107

HISTORY.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,16 @@
22
History
33
=======
44

5+
0.3.1 (2021-04-20)
6+
------------------
7+
8+
* Place a hard cap below 3.0 on Markdown to address compatibility issues
9+
10+
0.3.0 (2021-04-19)
11+
------------------
12+
13+
* Add Scoped Code Tabs Markdown Extension
14+
515
0.2.7 (2019-11-20)
616
------------------
717

docdown/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22

33
__author__ = """Jason Emerick"""
44
__email__ = 'jason@mobelux.com'
5-
__version__ = '0.2.7'
5+
__version__ = '0.3.1'

docdown/scoped_code_tabs.py

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
# -*- coding: utf-8 -*-
2+
3+
"""
4+
scoped_code_tabs
5+
----------------------------------
6+
7+
docdown.scoped_code_tabs Markdown extension module
8+
"""
9+
import re
10+
11+
from markdown.preprocessors import Preprocessor
12+
from markdown_fenced_code_tabs import CodeTabsExtension
13+
14+
15+
class ScopedCodeTabsPreprocessor(Preprocessor):
16+
RE_FENCE_START = r'^ *\|\~\s*$' # start line, e.g., ` |~ `
17+
RE_FENCE_END = r'^\s*\~\|\s*$' # last non-blank line, e.g, '~|\n \n\n'
18+
19+
def __init__(self, md, code_tabs_preprocessor):
20+
self.code_tabs_preprocessor = code_tabs_preprocessor
21+
super(ScopedCodeTabsPreprocessor, self).__init__(md)
22+
23+
def run(self, lines):
24+
new_lines = []
25+
fenced_code_tab = []
26+
starting_line = None
27+
in_tab = False
28+
29+
for line in lines:
30+
if re.search(self.RE_FENCE_START, line):
31+
# Start block pattern, save line in case of no end fence
32+
in_tab = True
33+
starting_line = line
34+
elif re.search(self.RE_FENCE_END, line):
35+
# End of code block, run through fenced code tabs pre-processor and reset code tab list
36+
new_lines += self.code_tabs_preprocessor.run(fenced_code_tab)
37+
fenced_code_tab = []
38+
in_tab = False
39+
elif in_tab:
40+
# Still in tab -- append to tab list
41+
fenced_code_tab.append(line)
42+
else:
43+
# Not in a fenced code tab, and not starting/ending one -- pass as usual
44+
new_lines.append(line)
45+
46+
# Non-terminated code tab block, append matching starting fence and remaining lines without processing
47+
if fenced_code_tab:
48+
new_lines += [starting_line] + fenced_code_tab
49+
return new_lines
50+
51+
52+
class ScopedCodeTabExtension(CodeTabsExtension):
53+
54+
def __init__(self, **kwargs):
55+
"""
56+
A Markdown extension that serves to scope where Fenced Code Tabs are rendered by way of |~ ... ~| fences.
57+
58+
Example:
59+
60+
## A set of code tabs in Python and Java
61+
|~
62+
```python
63+
def main():
64+
print("This would be passed through markdown_fenced_code_tabs")
65+
```
66+
67+
```java
68+
public static void main(String[] args) {
69+
System.out.println("This would be passed through markdown_fenced_code_tabs");
70+
}
71+
```
72+
~|
73+
74+
## A regular, non-tabbed code block in Bash
75+
```bash
76+
codeblockinfo() {
77+
echo("This would NOT be passed through markdown_fenced_code tabs");
78+
}
79+
```
80+
"""
81+
super(ScopedCodeTabExtension, self).__init__(**kwargs)
82+
83+
def extendMarkdown(self, md, md_globals):
84+
super(ScopedCodeTabExtension, self).extendMarkdown(md, md_globals)
85+
md.registerExtension(self)
86+
87+
md.preprocessors.add('scoped_code_tabs',
88+
ScopedCodeTabsPreprocessor(md,
89+
code_tabs_preprocessor=md.preprocessors['fenced_code_block']),
90+
">normalize_whitespace")
91+
del md.preprocessors['fenced_code_block']
92+
93+
94+
def makeExtension(*args, **kwargs):
95+
return ScopedCodeTabExtension(*args, **kwargs)

docs/docdown.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,14 @@ docdown.platform_section module
5959
:undoc-members:
6060
:show-inheritance:
6161

62+
docdown.scoped_code_tabs module
63+
-------------------------------
64+
65+
.. automodule:: docdown.scoped_code_tabs
66+
:members:
67+
:undoc-members:
68+
:show-inheritance:
69+
6270
docdown.sequence module
6371
-----------------------
6472

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
######################
2+
Scoped Code Tabs
3+
######################
4+
5+
Scoped Code Tabs allows for the explicit annotation of when and where to tabulate a set of code blocks versus rendering them
6+
separately.
7+
8+
A scoped code tab is delimited by an opening ``|~`` fence and closing ``~|`` fence. The code blocks within the fences
9+
are defined as typical code blocks, using backticks, with the opening backtick fence specifying the code language contained
10+
within the block.
11+
12+
The configuration for rendering the tabs is as directly defined by the `markdown_fenced_code_tabs`_ extension.
13+
14+
15+
=============
16+
Dependencies
17+
=============
18+
The ``docdown.scoped_code_tabs`` extension requires the third-party extension `markdown_fenced_code_tabs`_ in order to process
19+
the tabulated fenced code blocks.
20+
21+
==============
22+
Configuration
23+
==============
24+
25+
single_block_as_tab
26+
Whether a single code block should still be rendered as a code tab. Default: ``False``
27+
active_class
28+
The CSS class to apply to the active tab. Default: ``active``
29+
template
30+
Which template to use to render code tabs. One of: [``default``, ``bootstrap3``, ``bootstrap4``]. Default: ``default``
31+
Please see the *-template.html files in the `markdown_fenced_code_tabs`_ extension.
32+
33+
34+
=======
35+
Usage
36+
=======
37+
In documents
38+
-------------
39+
40+
.. code-block:: md
41+
42+
### Hello World Examples
43+
|~
44+
```bash
45+
helloWorld() {
46+
greeting=${1:-World}
47+
echo(`Hello ${greeting}`)
48+
}
49+
```
50+
~|
51+
52+
```python
53+
def hello_world(greeting: str = "World") -> None:
54+
print(f"Hello {greeting}")
55+
```
56+
57+
Python
58+
--------------
59+
60+
.. code-block:: python
61+
62+
config = {
63+
'docdown.scoped_code_tabs': {
64+
'single_block_as_tab': True,
65+
'template': 'bootstrap4',
66+
'active_class': 'tab-active'
67+
}
68+
}
69+
70+
text = """\
71+
### Hello World Examples
72+
|~
73+
```bash
74+
helloWorld() {
75+
greeting=${1:-World}
76+
echo(`Hello ${greeting}`)
77+
}
78+
```
79+
~|
80+
```python
81+
def hello_world(greeting: str = "World") -> None:
82+
print(f"Hello {greeting}")
83+
```
84+
"""
85+
86+
html = markdown.markdown(
87+
text,
88+
extensions=['docdown.scoped_code_tabs'],
89+
extension_configs=config,
90+
output_format='html5')
91+
92+
=======
93+
Output
94+
=======
95+
Note the extra classes and divs for tabulation around the ``|~`` ``~|`` code block.
96+
97+
.. code-block:: html
98+
99+
<h3>Hello World Examples</h3>
100+
<p> <div class=md-fenced-code-tabs id=tab-tab-group-0><ul class="nav nav-tabs"><li class=nav-item><a class="nav-link tab-active" href=#tab-group-0-0_bash-panel role=tab id=tab-group-0-0_bash-tab data-toggle=tab data-lang=bash aria-controls=tab-group-0-0_bash-panel aria-selected=true>Bash</a></li></ul><div class=tab-content><div id=tab-group-0-0_bash-panel class="tab-pane show tab-active" role=tabpanel aria-labelledby=tab-group-0-0_bash-tab><pre><code class=bash>helloWorld() {
101+
greeting=${1:-World}
102+
echo(`Hello ${greeting}`)
103+
}
104+
</code></pre></div></div></div></p>
105+
<p><code>python
106+
def hello_world(greeting: str = "World") -&gt; None:
107+
print(f"Hello {greeting}")</code></p>
108+
109+
.. _`markdown_fenced_code_tabs`: https://github.com/yacir/markdown-fenced-code-tabs

requirements_dev.txt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
pip==9.0.1
22
bumpversion==0.5.3
33
wheel==0.29.0
4-
watchdog==0.8.3
4+
#watchdog==0.8.3
55
flake8==2.6.0
66
tox==2.5.0
77
coverage==4.1
88
Sphinx==1.4.8
99
twine==1.13.0
1010

11-
Markdown==2.6.6
11+
Markdown<3.0.0
12+
markdown-fenced-code-tabs==1.0.5
1213
unicodecsv==0.14.1
1314

1415
# note_block templating

setup.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[bumpversion]
2-
current_version = 0.2.7
2+
current_version = 0.3.1
33
commit = True
44
tag = True
55

setup.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@
1111

1212
requirements = [
1313
# TODO: put package requirements here
14+
'Markdown < 3.0.0',
1415
'unicodecsv >= 0.14.1',
16+
'markdown-fenced-code-tabs >= 1.0.5',
1517
]
1618

1719
test_requirements = [
@@ -20,7 +22,7 @@
2022

2123
setup(
2224
name='docdown',
23-
version='0.2.7',
25+
version='0.3.1',
2426
description="DocDown is a Markdown extension for source code documentation.",
2527
long_description=readme + '\n\n' + history,
2628
author="Jason Emerick, Justin Michalicek",
@@ -42,9 +44,10 @@
4244
"Programming Language :: Python :: 2",
4345
'Programming Language :: Python :: 2.7',
4446
'Programming Language :: Python :: 3',
45-
'Programming Language :: Python :: 3.3',
4647
'Programming Language :: Python :: 3.4',
4748
'Programming Language :: Python :: 3.5',
49+
'Programming Language :: Python :: 3.6',
50+
'Programming Language :: Python :: 3.7',
4851
],
4952
test_suite='tests',
5053
tests_require=test_requirements

0 commit comments

Comments
 (0)