Skip to content

Commit

Permalink
Replace bootstrap alert-info/warning <div>s with custom admonitions (#47
Browse files Browse the repository at this point in the history
)

This is an experimental work-around feature!

See also #46.
  • Loading branch information
mgeier committed Apr 27, 2016
1 parent 6bf9100 commit 00b963f
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 3 deletions.
45 changes: 44 additions & 1 deletion doc/markdown-cells.jupyter
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,51 @@ markdown

The alternative text is shown in browsers that don't support those elements. The same text is also shown in Sphinx's LaTeX output.

> **Note:** You can also use local files for the `<audio>` and `<video>` elements, but you have to create a link to the source file somewhere, because only then are the local files copied to the HTML output directory!
<div class="alert alert-info">

**Note:** You can also use local files for the `<audio>` and `<video>` elements, but you have to create a link to the source file somewhere, because only then are the local files copied to the HTML output directory!
You should do that anyway to make the audio/video file accessible to browsers that don't support the `<audio>` and `<video>` elements.

</div>
markdown
## Info/Warning Boxes

<div class="alert alert-warning">

**Warning:** This is an *experimental feature*!

Its usage will probably change in the future or it might be removed completely!

</div>

Until there is an info/warning extension for Markdown/CommonMark (see [this issue](https://github.com/jupyter/notebook/issues/1292)), such boxes can be created by using HTML `<div>` elements like this:

```html
<div class="alert alert-info">

**Note:** This is a note!

</div>
```

For this to work reliably, you should obey the following guidelines:

* The `class` attribute has to be either `"alert alert-info"` or `"alert alert-warning"`, other values will not be converted correctly.
* No further attributes are allowed.
* For compatibility with CommonMark, you should add an empty line between the `<div>` start tag and the beginning of the content.

<div class="alert alert-info">

**Note:** The text can contain further Markdown formatting.

It is even possible to have nested boxes:

<div class="alert alert-warning">

... but please don't *overuse* this!

</div>
</div>
markdown
## Links to Other Notebooks

Expand Down
58 changes: 56 additions & 2 deletions nbsphinx.py
Original file line number Diff line number Diff line change
Expand Up @@ -422,8 +422,8 @@ class NotebookParser(rst.Parser):

def get_transforms(self):
"""List of transforms for documents parsed by this parser."""
return rst.Parser.get_transforms(self) + [ProcessLocalLinks,
CreateSectionLabels]
return rst.Parser.get_transforms(self) + [
ProcessLocalLinks, CreateSectionLabels, ReplaceAlertDivs]

def parse(self, inputstring, document):
"""Parse `inputstring`, write results to `document`."""
Expand Down Expand Up @@ -836,6 +836,60 @@ def apply(self):
i_still_have_to_create_the_notebook_label = False


class ReplaceAlertDivs(docutils.transforms.Transform):
"""Replace certain <div> elements with AdmonitionNode containers.
This is a quick-and-dirty work-around until a proper
Mardown/CommonMark extension for note/warning boxes is available.
"""

default_priority = 500 # Doesn't really matter

_start_re = re.compile(
r'\s*<div\s*class\s*=\s*(?P<q>"|\')([a-z\s-]*)(?P=q)\s*>\s*\Z',
flags=re.IGNORECASE)
_class_re = re.compile(r'\s*alert\s*alert-(info|warning)\s*\Z')
_end_re = re.compile(r'\s*</div\s*>\s*\Z', flags=re.IGNORECASE)

def apply(self):
start_tags = []
for node in self.document.traverse(docutils.nodes.raw):
if node['format'] != 'html':
continue
start_match = self._start_re.match(node.astext())
if not start_match:
continue
class_match = self._class_re.match(start_match.group(2))
if not class_match:
continue
admonition_class = class_match.group(1)
if admonition_class == 'info':
admonition_class = 'note'
start_tags.append((node, admonition_class))

# Reversed order to allow nested <div> elements:
for node, admonition_class in reversed(start_tags):
content = []
for sibling in node.traverse(include_self=False, descend=False,
siblings=True, ascend=False):
end_tag = (isinstance(sibling, docutils.nodes.raw) and
sibling['format'] == 'html' and
self._end_re.match(sibling.astext()))
if end_tag:
admonition_node = AdmonitionNode(
classes=['admonition', admonition_class])
admonition_node.extend(content)
parent = node.parent
parent.replace(node, admonition_node)
for n in content:
parent.remove(n)
parent.remove(sibling)
break
else:
content.append(sibling)


def builder_inited(app):
"""Add color definitions to LaTeX preamble."""
latex_elements = app.builder.config.latex_elements
Expand Down

0 comments on commit 00b963f

Please sign in to comment.