Skip to content

Commit

Permalink
Add markdown container (#26)
Browse files Browse the repository at this point in the history
  • Loading branch information
anders-kiaer authored May 28, 2019
1 parent 14e3990 commit db79ec5
Show file tree
Hide file tree
Showing 7 changed files with 167 additions and 4 deletions.
6 changes: 4 additions & 2 deletions examples/basic_example.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@ pages:
image: ./example_banner.png
title: My banner image
- Webviz created from configuration file.
- Some other text, potentially with strange letters like Åre, Smørbukk Sør.

- title: Another page
- title: Markdown example
content:
- Some other text, potentially with strange letters like Åre, Smørbukk Sør.
- container: Markdown
markdown_file: ./example-markdown.md

- title: Table example
content:
Expand Down
39 changes: 39 additions & 0 deletions examples/example-markdown.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# This is a big title

## This is a somewhat smaller title

### This is a subsubtitle

Hi from a Markdown container containing Norwegian letters (æ ø å), some
**bold** letters, _italic_ letters. _You can also **combine** them._

#### An unordered list

* Item 1
* Item 2
* Item 2a
* Item 2b

#### An automatically ordered list

1. Item 1
1. Item 2
1. Item 2a
1. Item 2b

#### An image with a caption

![Alt text](./example_banner.png "Some caption")

#### Quote

> Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
> tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
> quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
#### An example table

First Header | Second Header
------------ | -------------
Content Cell | Content Cell
Content Cell | Content Cell
3 changes: 2 additions & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@

tests_requires = [
'chromedriver-binary>=74.0.3729.6.0',
'markdown>=3.0.1',
'pylint>=2.3.1',
'pytest-dash==2.1.2',
'pycodestyle>=2.5.0',
Expand Down Expand Up @@ -34,12 +33,14 @@
],
},
install_requires=[
'bleach>=3.1.0',
'cryptography>=2.4',
'dash==0.41',
'dash-auth==1.3.2',
'flask-caching>=1.4.0',
'flask-talisman>=0.6.0',
'jinja2>=2.10',
'markdown>=3.0.1',
'pandas==0.24.1',
'plotly-express>=0.1.3',
'pyarrow>=0.11.1',
Expand Down
4 changes: 3 additions & 1 deletion webviz_config/containers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from ._syntax_highlighter import SyntaxHighlighter
from ._table_plotter import TablePlotter
from ._embed_pdf import EmbedPdf
from ._markdown import Markdown

__all__ = ['ExampleContainer',
'ExampleAssets',
Expand All @@ -22,7 +23,8 @@
'DataTable',
'SyntaxHighlighter',
'TablePlotter',
'EmbedPdf']
'EmbedPdf',
'Markdown']

for entry_point in pkg_resources.iter_entry_points('webviz_config_containers'):
globals()[entry_point.name] = entry_point.load()
Expand Down
101 changes: 101 additions & 0 deletions webviz_config/containers/_markdown.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
from pathlib import Path
import bleach
import markdown
from markdown.util import etree
from markdown.extensions import Extension
from markdown.inlinepatterns import ImageInlineProcessor, IMAGE_LINK_RE
import dash_core_components as html
from ..webviz_assets import webviz_assets


class _WebvizMarkdownExtension(Extension):
def __init__(self, base_path):
self.base_path = base_path

super(_WebvizMarkdownExtension, self).__init__()

def extendMarkdown(self, md):
md.inlinePatterns['image_link'] = \
_MarkdownImageProcessor(IMAGE_LINK_RE, md, self.base_path)


class _MarkdownImageProcessor(ImageInlineProcessor):
def __init__(self, image_link_re, md, base_path):
self.base_path = base_path

super(_MarkdownImageProcessor, self).__init__(image_link_re, md)

def handleMatch(self, match, data):
image, start, index = super().handleMatch(match, data)

if image is None or not image.get('title'):
return image, start, index

src = image.get('src')
caption = image.get('title')

if src.startswith('http'):
raise ValueError(f'Image path {src} has been given. Only images '
'available on the file system can be added.')

image_path = Path(src)
if not image_path.is_absolute():
image_path = (self.base_path / image_path).resolve()

url = webviz_assets.add(image_path)

image.set('src', url)
image.set('class', '_markdown_image')

container = etree.Element('span', attrib={'style': 'display: block'})
container.append(image)

etree.SubElement(container,
'span',
attrib={'class': '_markdown_image_caption'}
).text = caption

return container, start, index


class Markdown:
'''### Include Markdown
This container renders and includes the content from a Markdown file. Images
are supported, and should in the markdown file be given as either relative
paths to the markdown file itself, or absolute paths.
* `markdown_file`: Path to the markdown file to render and include. Either
absolute path or relative to the configuration file.
'''

ALLOWED_TAGS = [
'h1', 'h2', 'h3', 'h4', 'h5', 'h6',
'b', 'i', 'strong', 'em', 'tt',
'p', 'br', 'span', 'div', 'blockquote', 'code', 'hr',
'ul', 'ol', 'li', 'dd', 'dt', 'img', 'a', 'sub', 'sup',
'table', 'thead', 'tbody', 'tr', 'th', 'td'
]

ALLOWED_ATTRIBUTES = {
'*': ['id', 'class', 'style'],
'img': ['src', 'alt', 'title'],
'a': ['href', 'alt', 'title']
}

def __init__(self, markdown_file: Path):
self.html = bleach.clean(
markdown.markdown(
markdown_file.read_text(),
extensions=['tables',
'sane_lists',
_WebvizMarkdownExtension(
base_path=markdown_file.parent
)]),
Markdown.ALLOWED_TAGS,
Markdown.ALLOWED_ATTRIBUTES
)

@property
def layout(self):
return html.Markdown(self.html, dangerously_allow_html=True)
16 changes: 16 additions & 0 deletions webviz_config/static/assets/webviz_config.css
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,19 @@
background-position: center;

}

._markdown_image {

display: block;
margin: auto;
max-width: 90%;
max-height: 90vw;

}

._markdown_image_caption {

display: block;
text-align: center;

}
2 changes: 2 additions & 0 deletions webviz_config/webviz_assets.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ def add(self, filename):
if filename not in self._assets.values():
assigned_id = self._generate_id(path.name)
self._assets[assigned_id] = filename
else:
assigned_id = {v: k for k, v in self._assets.items()}[filename]

return os.path.normcase(os.path.join(self._base_folder(), assigned_id))

Expand Down

0 comments on commit db79ec5

Please sign in to comment.