Skip to content

Commit 967a208

Browse files
feat: configurable toolbar
Co-authored-by: Yves Chevallier <yves.chevallier@heig-vd.ch> Signed-off-by: Jan Larwig <jan@larwig.com>
1 parent fe5c6b8 commit 967a208

File tree

5 files changed

+189
-61
lines changed

5 files changed

+189
-61
lines changed

README.md

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -71,12 +71,20 @@ Further options are:
7171
```yaml
7272
plugins:
7373
- drawio:
74-
toolbar: true # control if hovering on a diagram shows a toolbar for zooming or not (default: true)
75-
tooltips: true # control if tooltips will be shown (default: true)
76-
edit: true # control if edit button will be shown in the lightbox view (default: true)
77-
border: 10 # increase or decrease the border / margin around your diagrams (default: 0)
78-
darkmode: true # support darkmode. allows for automatic switching between dark and lightmode based on the theme toggle. (default: false)
79-
highlight: "#0000FF" # color hyperlinks on mouse hover over (default: no color)
74+
tooltips: true # Enable tooltips on diagram elements
75+
border: 5 # Border size / padding around diagrams
76+
edit: true # Enable opening the editor for diagrams
77+
darkmode: true # Enable dark mode support (classic MkDocs and Material)
78+
highlight: "#0000FF" # Highlight color for hyperlinks
79+
lightbox: true # Enable opening the lightbox on click
80+
toolbar: # Control the looks and behaviour of the toolbar
81+
pages: true # Display the page selector (data-toolbar-pages)
82+
tags: true # Display the tags selector (data-toolbar-tags)
83+
zoom: true # Display the zoom controls (data-toolbar-zoom)
84+
layers: true # Display the layer controls (data-toolbar-layers)
85+
lightbox: true # Display the lightbox / fullscreen button (data-toolbar-lightbox)
86+
position: "top" # Control the position of the toolbar (top or bottom) (data-toolbar-position)
87+
no_hide: false # Do not hide the toolbar when not hovering over diagrams (data-toolbar-no-hide)
8088
```
8189
8290
## Material Integration

examples/docs/configuration.md

Lines changed: 36 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -15,44 +15,61 @@ Further options are the following with their default value:
1515
```yaml
1616
plugins:
1717
- drawio:
18-
# Control if hovering on a diagram shows a toolbar for zooming or not
19-
toolbar: true
2018

21-
# Control if tooltips will be shown (data-tooltips)
19+
# URL to the Drawio viewer JavaScript file
20+
viewer_js: "https://viewer.diagrams.net/js/viewer-static.min.js"
21+
22+
# Enable tooltips on diagram elements
2223
tooltips: true
2324

24-
# Increase or decrease the padding around your diagrams
25-
# (data-border)
25+
# Border size / padding around diagrams
2626
border: 5
2727

28-
# Control if edit button will be shown in the lightbox view
29-
# (data-edit)
28+
# Enable opening the editor for diagrams
3029
edit: true
3130

32-
# Control if darkmode is supported
31+
# Enable dark mode support
3332
# When activated the color scheme for your diagrams is automatically toggled
3433
# based on the selected theme. Supports classic mkdocs and mkdocs-material.
3534
darkmode: true
3635

37-
# Set the color of hyperlink highlighting
36+
# Highlight color for hyperlinks
3837
# When a diagram element has a hyperlink on it, the element is highlighted
3938
# on mouse hover over to better indicate a hylerlink is present. This
4039
# parameter controls the color of the highlight boarder. If omitted, no
4140
# highlighting happens.
4241
highlight: "#0000FF"
43-
```
44-
## HTML Attributes
45-
For each global configuration option you can also use the attribute in the diagram itself. This will override the global configuration. Here is an example:
46-
```markdown
47-
![](my-diagram.drawio){ data-toolbar-zoom="false" }
48-
```
4942

50-
To use these attributes you need to enable the markdown extension `attr_list` in your `mkdocs.yml`:
43+
# Enable to open the lightbox on click
44+
lightbox: true
5145

52-
```yaml
53-
markdown_extensions:
54-
- attr_list
46+
# Toolbar specific options
47+
toolbar:
48+
# Display the page selector
49+
pages: true
50+
51+
# Display the tags selector
52+
tags: true
53+
54+
# Display the zoom controls
55+
zoom: true
56+
57+
# Display the layer controls
58+
layers: true
59+
60+
# Display the tags control
61+
tags: true
62+
63+
# Display the lightbox / fullscreen button
64+
lightbox: true
65+
66+
# Position of the toolbar (top/bottom)
67+
position: "top"
68+
69+
# Do not hide the toolbar when not hovering over diagrams
70+
no_hide: false
5571
```
72+
5673
## Material Integration
5774
5875
If you are using the Material Theme and want to use the [instant-loading](https://squidfunk.github.io/mkdocs-material/setup/setting-up-navigation/?h=instant#instant-loading) feature. You will have to configure the following:

examples/mkdocs-classic.yml

Lines changed: 28 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,41 @@
1-
site_name: test_mkdocs_drawio
1+
site_name: MkDocs Drawio Plugin
22
docs_dir: docs
3+
34
nav:
45
- Documentation:
56
- Getting Started: index.md
67
- Configuration: configuration.md
78
- Plumbing: plumbing.md
8-
- Tests:
9-
- Simple Diagram: 'tests/simple-diagram/index.md'
10-
- Error Handling: 'tests/error-handling/index.md'
11-
- Configuration: 'tests/configuration/index.md'
12-
- Code Blocks: 'tests/code-blocks/index.md'
13-
- Relative Paths (a): 'tests/relative-paths/index.md'
14-
- Relative Paths (b): 'tests/relative-paths/example.md'
15-
- Pagging: 'tests/pagging/index.md'
16-
- External URL: 'tests/external-url/index.md'
17-
- SVG Diagram: 'tests/svg/index.md'
9+
- Examples:
10+
- Simple Diagram: "tests/simple-diagram/index.md"
11+
- Error Handling: "tests/error-handling/index.md"
12+
- Configuration: "tests/configuration/index.md"
13+
- Code Blocks: "tests/code-blocks/index.md"
14+
- Relative Paths (Index): "tests/relative-paths/index.md"
15+
- Relative Paths (Subpage): "tests/relative-paths/example.md"
16+
- Pagging: "tests/pagging/index.md"
17+
- External URL: "tests/external-url/index.md"
18+
- SVG Diagram: "tests/svg/index.md"
19+
- Hyperlinks: "tests/hyperlinks/index.md"
1820

1921
theme:
20-
name: mkdocs
21-
user_color_mode_toggle: true
22+
name: mkdocs
23+
user_color_mode_toggle: true
2224

2325
plugins:
24-
- search
25-
- drawio:
26-
toolbar: true
27-
tooltips: true
28-
edit: true
29-
border: 20
30-
darkmode: true
31-
- print-site
32-
26+
- search
27+
- drawio:
28+
toolbar:
29+
position: "bottom"
30+
zoom: true
31+
lightbox: false
32+
lightbox: true
33+
tooltips: true
34+
edit: true
35+
border: 20
36+
darkmode: true
37+
highlight: "#0000FF"
38+
- print-site
3339

3440
markdown_extensions:
3541
- attr_list

examples/mkdocs.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,11 @@ markdown_extensions:
4545
plugins:
4646
- search
4747
- drawio:
48-
toolbar: true
48+
toolbar:
49+
position: "bottom"
50+
zoom: true
51+
lightbox: false
52+
lightbox: true
4953
tooltips: true
5054
edit: true
5155
border: 20

mkdocs_drawio/plugin.py

Lines changed: 106 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
import string
44
import logging
55
from lxml import etree
6-
from typing import Dict
76
from html import escape
87
from pathlib import Path
8+
from typing import Dict
99
from bs4 import BeautifulSoup
1010
from mkdocs.utils import copy_file
1111
from mkdocs.plugins import BasePlugin
@@ -18,43 +18,130 @@
1818
LOGGER = logging.getLogger("mkdocs.plugins.diagrams")
1919

2020

21+
class Toolbar(base.Config):
22+
"""Configuration options for the toolbar, mostly taken from
23+
https://www.drawio.com/doc/faq/embed-html-options
24+
"""
25+
26+
pages = c.Type(bool, default=True)
27+
""" Display the page selector """
28+
29+
tags = c.Type(bool, default=True)
30+
""" Display the tags selector """
31+
32+
zoom = c.Type(bool, default=True)
33+
""" Display the zoom controls """
34+
35+
layers = c.Type(bool, default=True)
36+
""" Display the layer controls """
37+
38+
lightbox = c.Type(bool, default=True)
39+
""" Display the lightbox / fullscreen button """
40+
41+
position = c.Choice(["top", "bottom"], default="bottom")
42+
""" Position of the toolbar """
43+
44+
no_hide = c.Type(bool, default=False)
45+
""" Do not hide the toolbar when not hovering over diagrams """
46+
47+
2148
class DrawioConfig(base.Config):
2249
"""Configuration options for the Drawio Plugin"""
2350

2451
viewer_js = c.Type(
2552
str, default="https://viewer.diagrams.net/js/viewer-static.min.js"
2653
)
27-
toolbar = c.Type(bool, default=True)
54+
""" URL to the Drawio viewer JavaScript file """
55+
56+
toolbar = c.Type((bool, dict), default=True)
57+
""" Configuration for the toolbar, can be a bool or a dict """
58+
""" If bool, enables or disables the toolbar completely. If dict,"""
59+
""" allows to configure individual toolbar items. """
60+
2861
tooltips = c.Type(bool, default=True)
62+
""" Enable tooltips on diagram elements """
63+
2964
border = c.Type(int, default=0)
65+
""" Border size / padding around diagrams """
66+
3067
edit = c.Type(bool, default=True)
68+
""" Enable opening the editor for diagrams """
69+
3170
darkmode = c.Type(bool, default=False)
71+
""" Enable dark mode support """
72+
3273
highlight = c.Type(str, default="")
74+
""" Highlight color for hyperlinks """
75+
76+
lightbox = c.Type(bool, default=True)
77+
""" Enable to open the lightbox on click """
3378

3479

3580
class DrawioPlugin(BasePlugin[DrawioConfig]):
3681
"""
3782
Plugin for embedding Drawio Diagrams into your MkDocs
3883
"""
3984

40-
def on_post_page(self, output_content, config, page, **kwargs):
41-
return self.render_drawio_diagrams(output_content, page)
85+
def get_diagram_config(self) -> Dict:
86+
"""Build diagram config using only global plugin settings."""
4287

43-
def render_drawio_diagrams(self, output_content, page):
44-
if ".drawio" not in output_content.lower():
45-
return output_content
88+
toolbar_items = []
4689

47-
soup = BeautifulSoup(output_content, "html.parser")
90+
if self.toolbar_config.get("pages"):
91+
toolbar_items.append("pages")
92+
if self.toolbar_config.get("tags"):
93+
toolbar_items.append("tags")
94+
if self.toolbar_config.get("zoom"):
95+
toolbar_items.append("zoom")
96+
if self.toolbar_config.get("layers"):
97+
toolbar_items.append("layers")
98+
if self.toolbar_config.get("lightbox"):
99+
toolbar_items.append("lightbox")
48100

49-
diagram_config = {
50-
"toolbar": "zoom" if self.config.toolbar else None,
101+
toolbar_value = " ".join(toolbar_items) if toolbar_items else None
102+
103+
config = {
104+
"toolbar-position": self.toolbar_config.position,
105+
"toolbar-nohide": "1" if self.toolbar_config.no_hide else "0",
51106
"tooltips": "1" if self.config.tooltips else "0",
52107
"border": self.config.border + 5,
53108
"resize": "1",
54109
"edit": "_blank" if self.config.edit else None,
55-
"highlight": self.config.highlight if self.config.highlight else None,
110+
"highlight": self.config.highlight or None,
111+
"lightbox": "1" if self.config.lightbox else "0",
56112
}
57113

114+
if toolbar_value is not None:
115+
config["toolbar"] = toolbar_value
116+
117+
return {key: value for key, value in config.items() if value is not None}
118+
119+
def get_toolbar_config(self, toolbar_config) -> Toolbar:
120+
config = Toolbar()
121+
122+
# Bool means enable defaults or disable completely.
123+
if isinstance(toolbar_config, bool):
124+
if toolbar_config is False:
125+
# Flip all toolbar items off but keep other defaults intact.
126+
for key in ("pages", "tags", "zoom", "layers", "lightbox"):
127+
setattr(config, key, False)
128+
129+
if isinstance(toolbar_config, dict):
130+
# Load values through mkdocs config validation to respect defaults.
131+
config.load_dict(toolbar_config)
132+
133+
config.validate()
134+
return config
135+
136+
def on_post_page(self, output_content, config, page, **kwargs):
137+
return self.render_drawio_diagrams(output_content, page)
138+
139+
def render_drawio_diagrams(self, output_content, page):
140+
if ".drawio" not in output_content.lower():
141+
return output_content
142+
143+
soup = BeautifulSoup(output_content, "html.parser")
144+
58145
# search for images using drawio extension
59146
diagrams = soup.find_all(
60147
"img", src=re.compile(r".*\.drawio(.svg)?$", re.IGNORECASE)
@@ -69,6 +156,8 @@ def render_drawio_diagrams(self, output_content, page):
69156
# substitute images with embedded drawio diagram
70157
path = Path(page.file.abs_dest_path).parent
71158

159+
diagram_config = self.get_diagram_config()
160+
72161
for diagram in diagrams:
73162
if re.search("^https?://", diagram["src"]):
74163
mxgraph = BeautifulSoup(
@@ -107,7 +196,8 @@ def substitute_with_file(config: Dict, path: Path, src: str, page: str) -> str:
107196
diagram_xml = etree.parse(path.joinpath(src).resolve())
108197
except Exception as e:
109198
LOGGER.error(
110-
f"Error: Could not parse diagram file '{src}' on path '{path}': {e}"
199+
f"Error: Could not parse diagram file '{
200+
src}' on path '{path}': {e}"
111201
)
112202
config["xml"] = ""
113203
return SUB_TEMPLATE.substitute(config=escape(json.dumps(config)))
@@ -144,7 +234,10 @@ def parse_diagram(data, page_name, src="", path=None) -> str:
144234
return etree.tostring(mxfile, encoding=str)
145235

146236
def on_config(self, config: base.Config):
147-
"""Load embedded files"""
237+
# Prepare toolbar configuration
238+
self.toolbar_config = self.get_toolbar_config(self.config.toolbar)
239+
240+
# Prepare list of embedded files
148241
self.base = Path(__file__).parent
149242
self.css = []
150243
self.js = []

0 commit comments

Comments
 (0)