Repository: fralau/mkdocs-mermaid2-plugin
Branch: master
Commit: 59498d0c537c
Files: 66
Total size: 140.1 KB
Directory structure:
gitextract_rndg2_6l/
├── .github/
│ └── workflows/
│ └── greetings.yml
├── .gitignore
├── .readthedocs.yml
├── CHANGELOG.md
├── LICENSE
├── MANIFEST.in
├── README.md
├── README_old.md
├── mermaid2/
│ ├── __init__.py
│ ├── fence.py
│ ├── plugin.py
│ ├── pyjs.py
│ └── util.py
├── pyproject.toml
├── setup.py
├── test/
│ ├── __init__.py
│ ├── extra_javascript/
│ │ ├── docs/
│ │ │ ├── index.md
│ │ │ └── second.md
│ │ └── mkdocs.yml
│ ├── fixture.py
│ ├── http_lib/
│ │ ├── docs/
│ │ │ ├── index.md
│ │ │ └── second.md
│ │ └── mkdocs.yml
│ ├── local_lib/
│ │ ├── docs/
│ │ │ ├── index.md
│ │ │ └── second.md
│ │ └── mkdocs.yml
│ ├── material/
│ │ ├── __init__.py
│ │ ├── docs/
│ │ │ ├── index.md
│ │ │ ├── js/
│ │ │ │ └── extra.js
│ │ │ └── second.md
│ │ ├── mkdocs.yml
│ │ └── test_site.py
│ ├── medium/
│ │ ├── docs/
│ │ │ ├── index.md
│ │ │ ├── js/
│ │ │ │ └── extra.js
│ │ │ └── second.md
│ │ └── mkdocs.yml
│ ├── simple/
│ │ ├── __init__.py
│ │ ├── docs/
│ │ │ ├── index.md
│ │ │ ├── js/
│ │ │ │ └── extra.js
│ │ │ └── second.md
│ │ ├── mkdocs.yml
│ │ └── test_site.py
│ ├── simple_format/
│ │ ├── docs/
│ │ │ ├── index.md
│ │ │ ├── js/
│ │ │ │ └── extra.js
│ │ │ └── second.md
│ │ └── mkdocs.yml
│ ├── simple_pre_10/
│ │ ├── docs/
│ │ │ ├── index.md
│ │ │ ├── js/
│ │ │ │ └── extra.js
│ │ │ └── second.md
│ │ └── mkdocs.yml
│ └── superfences/
│ ├── __init__.py
│ ├── docs/
│ │ ├── index.md
│ │ ├── js/
│ │ │ └── loader.js
│ │ └── second.md
│ ├── mkdocs.yml
│ └── test_site.py
├── update_pypi.sh
└── webdoc/
├── docs/
│ ├── contribute.md
│ ├── description.md
│ ├── index.md
│ ├── library.md
│ ├── superfences.md
│ ├── tips.md
│ └── troubleshooting.md
├── extra_requirements.txt
└── mkdocs.yml
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/workflows/greetings.yml
================================================
name: Greetings
on: [pull_request, issues]
jobs:
greeting:
runs-on: ubuntu-latest
steps:
- uses: actions/first-interaction@v1
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
issue-message: 'Thank you for your contribution! This is very appreciated.'
pr-message: 'Message that will be displayed on users'' first pr'
================================================
FILE: .gitignore
================================================
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
.pytest_cache/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# Jupyter Notebook
.ipynb_checkpoints
# pyenv
.python-version
# celery beat schedule file
celerybeat-schedule
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
site/
__test__/
# mypy
.mypy_cache/
================================================
FILE: .readthedocs.yml
================================================
# .readthedocs.yml
# Read the Docs configuration file
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
# Required
version: 2
# Build documentation in the docs/ directory with Sphinx
# sphinx:
# configuration: docs/conf.py
build:
os: ubuntu-22.04
tools:
python: "3.11"
# You can also specify other tool versions:
# nodejs: "20"
# rust: "1.70"
# golang: "1.20"
# Python environment
python:
install:
# these are needed, because they are not part of standard setup
- requirements: webdoc/extra_requirements.txt
# Build documentation with MkDocs
mkdocs:
configuration: webdoc/mkdocs.yml
fail_on_warning: false
# Optionally build your docs in additional formats such as PDF and ePub
formats: all
================================================
FILE: CHANGELOG.md
================================================
# Changelog: Mkdocs-Mermaid2
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## 1.2.3, 2025-10-15
* Added: documented the use of variables and macros with MkDocs-Macros
in Tips and Tricks (#123); dividing the the page into 3 sections.
## 1.2.2, 2025-08-27
* Fixed: deprecation warning by BeautifulSoup (#119, #120)
## 1.2.1, 2024-11-02
* Added: a test framework with MkDocs-Test and pytest
* Changed: migrated from `setup.py` to `pyproject.toml`
## 1.1.2, 2024-09-05
* Changed: If the `javascript` parameter starts with http(s) and no Internet
access is available, a WARNING is now issued
(mkdocs no longer fails with an exception).
## 1.1.1, 2023-09-26
* Fixed: Bug with local javascript library
## 1.1.0, 2023-09-01
* Added: Parameter `javascript` in config file for optionally specifying the
URL or path of the Mermaid javascript library.
* Changed: Parameter `extra_javascript` in config file is DEPRECATED,
for optionally specifying the URL or path of the Mermaid javascript library
* Changed: Updated documentation.
## 1.0.8, 2023-08-09
* Fixed: Arguments of config file not taken into consideration,
for mermaid.js version > 10 (#82)
## 1.0.5, 2023-07-29
* Added: A new [doc website is available on Read The Docs](https://mkdocs-mermaid2.readthedocs.io/en/latest/).
## 1.0.1, 2023-07
* Added: Now the plugin works with versions of the library > 10 and lower (#75)
* Added: Added: A new [doc website is available on Read The Docs](https://mkdocs-mermaid2.readthedocs.io/en/latest/).
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2018 PuGong -- 2020, others
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: MANIFEST.in
================================================
include README.md
include LICENSE.md
================================================
FILE: README.md
================================================
<div align="center">
# Mkdocs-Mermaid2
[](https://opensource.org/licenses/MIT)
[](https://pypi.org/project/mkdocs-mermaid2-plugin/)


An [MkDocs](https://www.mkdocs.org/) plugin that renders [Mermaid](https://mermaid-js.github.io/mermaid) text descriptions into diagrams (flow charts, sequence diagrams, pie charts, etc.).
</div>
---
* **See the [mkdocs-mermaid2 documentation on Read The Docs](https://mkdocs-mermaid2.readthedocs.io).**
* See the [package on Pypi](https://pypi.org/project/mkdocs-mermaid2-plugin/).
* View the [general Mkdocs documentation](https://www.mkdocs.org/)
> As of version 1.0.0, this plugin works with versions of the Mermaid library > 10,
> **and** with lower versions.
<!-- To update the toc, run the following command:
markdown-toc -i README.md
-->
<!-- toc -->
- [Mkdocs-Mermaid2](#mkdocs-mermaid2)
- [Introduction](#introduction)
- [Installation](#installation)
- [Automatic](#automatic)
- [Manual](#manual)
- [Test](#test)
- [Configuration](#configuration)
- [Basic configuration](#basic-configuration)
- [Specifying the version of the Mermaid library](#specifying-the-version-of-the-mermaid-library)
- [Additional settings for the Material theme](#additional-settings-for-the-material-theme)
- [For more information](#for-more-information)
<!-- tocstop -->
## Introduction
Mermaid2 allows you to insert mermaid markup in the markdown
of your mkdocs pages.
For example, a markdown page containing the following diagram:
```mermaid
graph LR
hello --> world
world --> again
again --> hello
```
will then be displayed in the final HTML page as:
```mermaid
graph LR
hello --> world
world --> again
again --> hello
```
The diagram will be rendered on the fly by the web browser,
with the use of the mermaid javascript library.
mkdocs-mermaid2 takes care of inserting the javascript library into
the html page.
> You can use all the diagrams types supported by the version of the Mermaid
> javascript library that you are using (flowchart, class, state, timeline,
> etc.).
## Installation
### Automatic
```bash
pip install mkdocs-mermaid2-plugin
```
### Manual
Clone this repository in a local directory and install the package:
```bash
python setup.py install
```
### Test
For running the examples the `test` directory,
you will also need the mkdocs-material theme. You may
[install it directly](https://squidfunk.github.io/mkdocs-material/getting-started/),
or use the following command to install the whole package:
```bash
pip install mkdocs-mermaid2-plugin[test]
```
## Configuration
### Basic configuration
To enable this plugin, you need to declare it in your [mkdocs config file](https://www.mkdocs.org/user-guide/configuration/)
(`mkdocs.yml`).
In order to work, the plugin also requires the
[mermaid](https://www.npmjs.com/package/mermaid) javascript
library (in the example below, it fetched from the last version
from the [unpkg](https://unpkg.com/) repository; change the version
no as needed).
```yaml
plugins:
- search
- mermaid2
```
> **Note:** If you declare plugins, you need to declare _all_ of them,
> including `search` (which would otherwise have been installed by default.)
### Specifying the version of the Mermaid library
By default, the plugin selects a version of the Mermaid javascript library
that is known to work (some versions work better than others).
You may specify a different version of the Mermaid library, like so:
```yaml
plugins:
- search
- mermaid2:
version: 10.0.2
```
The plugin will insert the correct call to the javascript library
inside the final HTML page.
### Additional settings for the Material theme
> The [Material theme](https://squidfunk.github.io/mkdocs-material/),
> developed by [squidfunk](https://github.com/squidfunk)
> is not mandatory, but recommended.
**Mermaid diagrams will automatically adapt their colors to the theme
and palette.**
Here are the _additional_ recommended settings in the configuration file:
```yaml
markdown_extensions:
- pymdownx.superfences:
# make exceptions to highlighting of code:
custom_fences:
- name: mermaid
class: mermaid
format: !!python/name:mermaid2.fence_mermaid_custom
```
> Do not use these additional settings for other themes,
> as diagrams will probably **not** be displayed correctly.
## For more information
See the [documentation on ReadTheDocs](https://mkdocs-mermaid2.readthedocs.io).
================================================
FILE: README_old.md
================================================
# mkdocs-mermaid2-plugin
**THIS IS AN OLD VERSION, KEPT HERE FOR REFERENCE**
[Use the documentation on ReadTheDocs](https://mkdocs-mermaid2.readthedocs.io).
[](https://opensource.org/licenses/MIT)
[](https://pypi.org/project/mkdocs-mermaid2-plugin/)


An [MkDocs](https://www.mkdocs.org/) plugin that renders textual graph
descriptions into [Mermaid](https://mermaid-js.github.io/mermaid) graphs
(flow charts, sequence diagrams, pie charts, etc.).
> As of version 1.0.0, this plugin works with versions of the Mermaid library > 10,
> **and** with lower versions.
<!-- To update the toc, run the following command:
markdown-toc -i README.md
-->
<!-- toc -->
- [Introduction](#introduction)
- [Installation](#installation)
* [Automatic](#automatic)
* [Manual](#manual)
* [Test](#test)
- [How it works](#how-it-works)
- [Configuration](#configuration)
* [Basic configuration](#basic-configuration)
* [Specifying the version of the Mermaid library](#specifying-the-version-of-the-mermaid-library)
* [Explicit declaration of the Mermaid library](#explicit-declaration-of-the-mermaid-library)
- [Usage](#usage)
* [General Principle](#general-principle)
* [How to write Mermaid diagrams](#how-to-write-mermaid-diagrams)
* [Adding arguments to the Mermaid engine](#adding-arguments-to-the-mermaid-engine)
* [Testing](#testing)
* [Adding a Javascript callback function](#adding-a-javascript-callback-function)
+ [Use Case](#use-case)
+ [Method](#method)
- [Tips and Tricks](#tips-and-tricks)
* [Setting the security level to "loose"](#setting-the-security-level-to-loose)
* [Formatting text in diagrams](#formatting-text-in-diagrams)
* [Adding Hyperlinks to a Diagram (versions of Mermaid javascript >~ 8.5.0)](#adding-hyperlinks-to-a-diagram-versions-of-mermaid-javascript--850)
* [Adding Hyperlinks to a Diagram (versions of Mermaid javascript <~ 8.5.0)](#adding-hyperlinks-to-a-diagram-versions-of-mermaid-javascript--850)
* [Auto-configure dark mode based on Host OS](#auto-configure-dark-mode-based-on-host-os)
* [Material Theme: Switching the Mermaid diagram on the fly between light and dark mode](#material-theme-switching-the-mermaid-diagram-on-the-fly-between-light-and-dark-mode)
- [Compatibility](#compatibility)
* [List](#list)
* [Using Mermaid and code highlighting at the same time](#using-mermaid-and-code-highlighting-at-the-same-time)
+ [Usage](#usage-1)
+ [Use of markdown extensions](#use-of-markdown-extensions)
+ [Declaring the superfences extension](#declaring-the-superfences-extension)
- [Troubleshooting](#troubleshooting)
* [The mermaid diagram is not displayed (or displayed incorrectly)](#the-mermaid-diagram-is-not-displayed-or-displayed-incorrectly)
+ [Seeing an error message at the place of the diagram?](#seeing-an-error-message-at-the-place-of-the-diagram)
+ [The mermaid source code appears as-is (not read)?](#the-mermaid-source-code-appears-as-is-not-read)
+ [Using another theme than material ?](#using-another-theme-than-material-)
+ [Using superfences, but no diagram is displayed?](#using-superfences-but-no-diagram-is-displayed)
+ [Is mkdocs' version up to date (>= 1.1) ?](#is-mkdocs-version-up-to-date--11-)
+ [Is the javascript library properly called?](#is-the-javascript-library-properly-called)
+ [A certain type of diagram (e.g. mindmap, etc.) is not displayed, or the syntax is incorrectly interpreted?](#a-certain-type-of-diagram-eg-mindmap-etc-is-not-displayed-or-the-syntax-is-incorrectly-interpreted)
* [Other issues](#other-issues)
+ [Rich text diagrams, or links are not displayed properly?](#rich-text-diagrams-or-links-are-not-displayed-properly)
+ [With pymdownx.details, diagrams in collapsed elements are not displayed?](#with-pymdownxdetails-diagrams-in-collapsed-elements-are-not-displayed)
- [Using the mermaid2.dumps() function](#using-the-mermaid2dumps-function)
- [How to contribute](#how-to-contribute)
- [Credits](#credits)
<!-- tocstop -->
## Introduction
Mermaid2 allows you to insert mermaid markup in the markdown
of your mkdocs pages.
For example, a markdown page containing the following diagram:
```mermaid
graph LR
hello --> world
world --> again
again --> hello
```
will then be displayed in the final HTML page as:
```mermaid
graph LR
hello --> world
world --> again
again --> hello
```
The diagram will be rendered on the fly by the web browser,
with the use of the mermaid javascript library.
mkdocs-mermaid2 takes care of inserting the javascript library into
the html page.
> You can use all the diagrams types supported by the version of the Mermaid
> javascript library that you are using (flowchart, class, state, timeline,
> etc.).
## Installation
### Automatic
```bash
pip install mkdocs-mermaid2-plugin
```
### Manual
Clone this repository in a local directory and install the package:
```bash
python setup.py install
```
### Test
For running the examples the `test` directory,
you will also need the mkdocs-material theme. You may
[install it directly](https://squidfunk.github.io/mkdocs-material/getting-started/),
or use the following command to install the whole package:
```bash
pip install mkdocs-mermaid2-plugin[test]
```
## How it works
When converting the markdown into HTML, mkdocs normally inserts the
Mermaid code (text) describing the diagram
into segments `<pre><code class='mermaid>`:
<pre><div class="mermaid">
...
</div></pre>
To make the HTML/css page more robust, the mermaid plugin converts
those segments into `<div>` elements in the final HTML page:
<div class="mermaid">
...
</div>
It also inserts a call to the
[javascript library](https://github.com/mermaid-js/mermaid) :
> **From version 1.0 of mkdocs-mermaid2:**
[For versions from 10.0.0 of the Mermaid javascript library, the plugin uses the ESM format](https://github.com/mermaid-js/mermaid/releases/tag/v10.0.0), since
it is the only one available. This requires a specific call from the HTML
page e.g.:
```html
<script type="module">
import mermaid from "https://unpkg.com/mermaid@10.0.2/dist/mermaid.esm.min.mjs"
</script>
```
For an earlier version of the library, the plugin uses the traditional call
from HTML:
```html
<script src="https://unpkg.com/mermaid@8.8.2/dist/mermaid.min.js">
</script>
```
To start displaying of the diagrams, the plugin then automatically inserts
a separate call to initialize the Mermaid library:
<script>
mermaid.initialize()
</script>
The user's browser will then read this code and render it on the fly.
> No svg/png images are produced during the rendering of that graph.
## Configuration
### Basic configuration
To enable this plugin, you need to declare it in your [mkdocs config file](https://www.mkdocs.org/user-guide/configuration/)
(`mkdocs.yml`).
In order to work, the plugin also requires the
[mermaid](https://www.npmjs.com/package/mermaid) javascript
library (in the example below, it fetched from the last version
from the [unpkg](https://unpkg.com/) repository; change the version
no as needed).
```yaml
plugins:
- search
- mermaid2
```
> **Note:** If you declare plugins, you need to declare _all_ of them,
> including `search` (which would otherwise have been installed by default.)
> **Important:** If you use another theme than material you **must** use a version of the plugin >= 0.5.0.
### Specifying the version of the Mermaid library
> **For plugin version >= 0.4**
By default, the plugin selects a version of the Mermaid javascript library
that is known to work (some versions work better than others).
You may specify a different version of the Mermaid library, like so:
```yaml
plugins:
- search
- mermaid2:
version: 10.0.2
```
The plugin will insert the correct call to the javascript library
inside the final HTML page.
### Explicit declaration of the Mermaid library
You _may_ specify the mermaid library explicitly, as long as it is
call mermaid (independently of extension):
```yaml
extra_javascript:
- https://unpkg.com/mermaid@8.7.0/dist/mermaid.min.js
```
This will be translated in the final HTML page as:
```html
<script src="https://unpkg.com/mermaid@8.7.0/dist/mermaid.min.js">
```
> This will work **only** for versions of the Mermaid javascript
> library that can be called in that way, i.e. that do not use the ES Module
> standard (ESM). [Above version 10.0.0 only ESM format libraries are
> available](https://github.com/mermaid-js/mermaid/releases/tag/v10.0.0).
As a workaround you could declare a local script file:
```yaml
extra_javascript:
- js/mermaidloader.js
```
Where `js` is a subdirectory of the document directory (`docs`).
If you are using a local javascript file, it is up to you to write the import,
with a version of the Mermaid library > 10 e.g.:
```javascript
import mermaid from "https://unpkg.com/mermaid@10.0.2/dist/mermaid.esm.min.mjs"
```
No explicit call to `mermaid.initialize()` is required, since it is
automatically inserted by the plugin.
## Usage
### General Principle
In order to insert a Mermaid diagram in a markdown page, simply
type it using the mermaid syntax,
and surround it with the code fence for Mermaid:
```mermaid
graph TD
A[Client] --> B[Load Balancer]
B --> C[Server01]
B --> D[Server02]
```
### How to write Mermaid diagrams
* For instructions on how to make a diagram, see [the official website](https://mermaid.js.org).
* If you are not familiar, see the [Mermaid Overview for Beginners](https://mermaid.js.org/community/n00b-overview.html).
* In case of doubt, you will want to test your diagrams in the [Mermaid Live Editor](https://mermaid.live).
### Adding arguments to the Mermaid engine
By default, the plugin automatically inserts
a Javascript command `mermaid.initialize();`
in the HTML pages, which starts the interpretation.
Sometimes, however, you may want to add some
initialization commands (see [full list](https://github.com/mermaid-js/mermaid/blob/master/docs/config/setup/modules/mermaidAPI.md#mermaidapi-configuration-defaults)).
For example, you could change the theme of the diagram,
using 'dark' instead of the default one.
Simply add those arguments in the config file, e.g.
```yaml
plugins:
- search
- mermaid2:
arguments:
theme: 'dark'
```
### Testing
To test your website with a diagram, restart the mkdocs server:
mkdocs serve
In your browser, open the webpage on the localhost
(by default: `https://localhost:8000`)
### Adding a Javascript callback function
_New in 0.3.0_
**CAUTION**: As of the [version 10.0.0 of the javascript Library(https://github.com/mermaid-js/mermaid/blob/develop/CHANGELOG.md#changelog)], callbacks are no longer accepted.
If you wish to use callbacks, specify a lower version of the
library in the config file.
#### Use Case
To make modifications that are not possible with css, it can be useful
to insert a callback function (Javascript) into the target HTML page.
This can be done using the standard pattern, e.g.:
```javascript
<script src="js/extra.js">
<script>mermaid.initialize({
theme: "dark",
mermaid: {
callback: myMermaidCallbackFunction
}
});</script>
```
In this case, `myMermaidCallbackFunction`is located in
the `js/extra.js` on the site's root directory.
Here is a simplistic example:
```
// js/extra.js
function myMermaidCallbackFunction(id) {
console.log('myMermaidCallbackFunction', id);
```
> You will see the results if you display the browser's console.
#### Method
This can be translated into the config (`mkdocs.yaml`) file as:
```yaml
plugins:
- mermaid2:
arguments:
theme: dark
mermaid:
callback: ^myMermaidCallbackFunction
extra_javascript:
- https://unpkg.com/mermaid/dist/mermaid.min.js
- js/extra.js
```
1. Note that **the name of the function must be preceded by a ^ (caret)**
to signify it's a literal and not a string.
2. Consider the **directory path** for the script
as **relative to the document directory** (`docs`).
Mkdocs will then put it in the proper place in the hierarchy of the
html pages.
## Tips and Tricks
### Setting the security level to "loose"
To access these functions, you need to relax mermaid's security level,
([since version 8.2](https://mermaid-js.github.io/mermaid/#/?id=special-note-regarding-version-82)).
> This requires, of course, your application taking responsibility
> for the security of the diagram source.
If that is OK with you, you can set the argument in the configuration of the
plugin:
```yaml
- mermaid2:
arguments:
securityLevel: 'loose'
```
### Formatting text in diagrams
> To enable this function, you need to [relax mermaid's security level to 'loose'](#setting-the-security-level-to-loose).
You may use HTML in the diagram.
> **Note:** This is guaranteed to work with Mermaid 8.6.4, but
> does not work e.g. on 8.7.0.
```mermaid
graph LR
hello["<b>Hello</b>"] --> world["<big><i>World</i></big>"]
world --> mermaid[mermaid web site]
```
Use this in the config file:
```yaml
extra_javascript:
- https://unpkg.com/mermaid@8.6.4/dist/mermaid.min.js
```
### Adding Hyperlinks to a Diagram (versions of Mermaid javascript >~ 8.5.0)
> To enable this function, you need to [relax mermaid's security level to 'loose'](#setting-the-security-level-to-loose).
Use the click directive in the language (for more information,
see [Interaction](https://mermaid-js.github.io/mermaid/#/flowchart?id=interaction) on the official mermaid website).
```mermaid
graph LR
hello --> world
world --> mermaid[mermaid web site]
click mermaid "https://mermaid-js.github.io/mermaid" "Website"
```
### Adding Hyperlinks to a Diagram (versions of Mermaid javascript <~ 8.5.0)
> To enable this function, you need to [relax mermaid's security level to 'loose'](#setting-the-security-level-to-loose).
It is possible to add hyperlinks to a diagram, e.g.:
```
box1[An <b>important</b> <a href="https://google.com">link</a>]
```
### Auto-configure dark mode based on Host OS
Using a combination of the unquote (`^`) functionality of this plugin and the
[prefers-color-scheme](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme)
CSS media feature, one can have the plugin automatically enable dark mode.
```yaml
plugins:
- search
- mermaid2:
arguments:
theme: |
^(window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) ? 'dark' : 'light'
```
This works well with the `scheme: preference` option in
[mkdocs-material](https://squidfunk.github.io/mkdocs-material/) and referenced in [their documentation](https://squidfunk.github.io/mkdocs-material/setup/changing-the-colors/#color-scheme).
### Material Theme: Switching the Mermaid diagram on the fly between light and dark mode
The Material theme for MkDocs allows [toggling between colors](https://squidfunk.github.io/mkdocs-material/setup/changing-the-colors/#color-palette-toggle).
Unfortunately the Mermaid diagram will not switch out of the box from light to
dark or vice versa.
This solution is similar to [switch the theme according to the OS color](#auto-configure-dark-mode-based-on-host-os),
though that earlier, simpler solution cannot toggle dynamically.
A workable solution has been proposed by [elgalu](https://github.com/elgalu)
(for more information see [Issue 39](https://github.com/fralau/mkdocs-mermaid2-plugin/issues/39)).
**`mkdocs.yml`**
(The palette is an example, where primary color, accent, icons, toggle message, etc. can be adapted to your needs.)
```yaml
theme:
name: material
# https://squidfunk.github.io/mkdocs-material/setup/changing-the-colors/#color-palette
palette:
- media: "(prefers-color-scheme: light)"
scheme: default
primary: indigo
accent: light-blue
toggle:
icon: material/toggle-switch-off-outline
name: Switch to dark mode
- media: "(prefers-color-scheme: dark)"
scheme: slate
primary: black
accent: deep orange
toggle:
icon: material/toggle-switch
name: Switch to light mode
# https://facelessuser.github.io/pymdown-extensions/extensions/superfences/
pymdownx.superfences:
custom_fences:
- name: mermaid
class: mermaid
format: !!python/name:mermaid2.fence_mermaid
plugins:
- mermaid2:
arguments:
# test if its __palette_1 (dark) or __palette_2 (light)
# for mkdocs-material >=8.0.0
theme: |
^(JSON.parse(__md_get("__palette").index == 1)) ? 'dark' : 'light'
# for mkdocs-material <8.0.0
# ^(JSON.parse(window.localStorage.getItem(__prefix('__palette'))).index == 1) ? 'dark' : 'light'
extra_javascript:
- extra/refresh_on_toggle_dark_light.js
```
> The caret operator (`^`) means "unquote". It is used here to insert Javascript code into the initialization code of `mermaid.initialize()`.
**`docs/extra/refresh_on_toggle_dark_light.js`**
To avoid refreshing the page after switching between dark/light modes so that Mermaid diagram can be updated, two listeners
must be installed, which are instructed to reload the page, whenever
they detect a change.
That is the function of the additional script
(`refresh_on_toggle_dark_light.js`):
```javascript
var paletteSwitcher1 = document.getElementById("__palette_1");
var paletteSwitcher2 = document.getElementById("__palette_2");
paletteSwitcher1.addEventListener("change", function () {
location.reload();
});
paletteSwitcher2.addEventListener("change", function () {
location.reload();
});
```
## Compatibility
### List
Here is a short list of compatibilities and incompatibilities for
the mermaid plugin:
| Item | Type | Status | Note |
|--------------------------|-----------|--------|------------------------------------------------------------------|
| **mkdocs** | theme | YES | (default) plugin version >= 0.5 |
| **material** | theme | YES | |
| **windmill** | theme | YES | plugin version >= 0.5 |
| **admonition** | extension | YES | |
| **footnotes** | extension | YES | |
| **minify** | plugin | NO | Breaks the mermaid diagrams. |
| **pymdownx.highlight** | extension | NO | Use [pymdownx.superfences](#declaring-the-superfences-extension) |
| **pymdownx.superfences** | extension | OK | [see paragraph](#declaring-the-superfences-extension) |
| **search** | plugin | OK | Do not forget to declare it in `config.yml`. |
### Using Mermaid and code highlighting at the same time
>**IMPORTANT** Do NOT use Superfences unless you want code highlighting.
#### Usage
It is quite natural that we want to display **mermaid diagrams**,
while having usual **code highlighting** (for bash, python, etc.).
#### Use of markdown extensions
**Symptom**: The mermaid code is not transformed into a diagram,
but processed as code to be displayed (colors, etc.).
The likely reason is that you have a markdown extension that interprets
all fenced code as code to display, and it prevents the mkdocs-mermaid2
plugin from doing its job.
**Do not use the [codehilite](https://squidfunk.github.io/mkdocs-material/extensions/codehilite/) markdown extension.**
Instead, use [facelessusers](https://github.com/facelessuser)'s splendid
[PyMdown's superfences](https://facelessuser.github.io/pymdown-extensions/extensions/superfences/); and use the
**[custom fences](https://facelessuser.github.io/pymdown-extensions/extensions/superfences/#custom-fences)**
facility.
#### Declaring the superfences extension
In the config file (`mkdocs.yaml`):
```yaml
markdown_extensions:
- pymdownx.superfences:
# make exceptions to highlighting of code:
custom_fences:
- name: mermaid
class: mermaid
format: !!python/name:mermaid2.fence_mermaid
```
It means:
1. Take the fenced parts marked with mermaid
2. Turn them into `class='mermaid'`.
3. To format those pieces, use the function `fence_mermaid`,
from the mermaid2 package.
There are **two** functions:
* `fence_mermaid` for the general case.
* `fence_mermaid_custom` for the Material theme (note the use of
the **custom** suffix)
Hence, for the Material theme (only):
```yaml
markdown_extensions:
- pymdownx.superfences:
# make exceptions to highlighting of code:
custom_fences:
- name: mermaid
class: mermaid
format: !!python/name:mermaid2.fence_mermaid_custom
```
> **IMPORTANT:** Note that the superfences will be slightly more demanding with
> HTML tags inside a mermaid diagram:
> **take care to always close the HTML tags that require it**
> (e.g. `<small>` must have its corresponding `</small>` tag).
> Otherwise, the extension system will attempt to close those tags
> and it will break the diagram.
## Troubleshooting
### The mermaid diagram is not displayed (or displayed incorrectly)
> To start with, use a simple diagram that you know is syntactically correct.
e.g.
```mermaid
graph TD
A[Client] --> B[Load Balancer]
B --> C[Server01]
B --> D[Server02]
```
#### Seeing an error message at the place of the diagram?
In recent versions of the javascript library (> 8.6.0), a pretty
error message is displayed in case of incorrect syntax:

> **In earlier versions, the library displays nothing, which
> can be confusing.**
If you see the error message, it is at least an indication that
the mermaid javascript library was called.
#### The mermaid source code appears as-is (not read)?
In that case, the javascript library was probably not called.
See the next questions.
#### Using superfences, but no diagram is displayed?
If you are using the superfences extension, but you see the source
code, you probably forgot to declare the custom_fences.
Se more explanations under [Declaring the superfences extension](#declaring-the-superfences-extension)
#### Is mkdocs' version up to date (>= 1.1) ?
Use `mkdocs -v`.
If not, update it:
pip install mkdocs --upgrade
Or, if you cloned this repo:
python setup.py install
#### Is the javascript library properly called?
In order to work, the proper javascript library must called from
the html page (this is done automatically).
If necessary check the link used in the HTML page generated, e.g.:
```HTML
<script type="module">import mermaid from "https://unpkg.com/mermaid@10.0.2/dist/mermaid.esm.min.mjs"</script>
```
Every diagram should start with a valid preamble, e.g. `graph TD`.
In case of doubt, you may want to test your diagram in the
[Mermaid Live Editor](https://mermaid-js.github.io/mermaid-live-editor).
> Note, however, that the Mermaid Live Editor **does not
> support loose mode** (with HTML code in the mermaid code).
#### A certain type of diagram (e.g. mindmap, etc.) is not displayed, or the syntax is incorrectly interpreted?
Check the version of the javascript mermaid library you are using (it's indicated
in the error message; as a last resort, check in the html page).
You can [change the library version if needed](#specifying-the-version-of-the-mermaid-library).
### Other issues
#### Rich text diagrams, or links are not displayed properly?
1. As a first step, [set the security level to 'loose'](#setting-the-security-level-to-loose).
2. Make sure you use a compatible version of the javascript library
(8.6.4, 8.8.0, ~~8.7.0~~). In principle, the version used
by the plugin is compatible (see instructions to
[change the version](#specifying-the-version-of-the-mermaid-library)).
#### With pymdownx.details, diagrams in collapsed elements are not displayed?
**This fix is experimental (it has been tested once and it worked).**
If you declared `pymdownx.details` in `config.yml`
(under `markdown_extensions`), you may notice that a diagram will not
display correctly in that case:
```markdown
???- note "Collapsed"
```mermaid
graph TD
A[Client] --> B[Load Balancer]
```
This is additional text.
```
Depending on the browser, you may have a dot, or nothing, etc.
In that case, use the following declaration in your `markdown_extensions`:
```yaml
- pymdownx.superfences:
# make exceptions to highlighting of code:
custom_fences:
- name: mermaid
class: mermaid
format: !!python/name:mermaid2.fence_mermaid_custom
```
The use of this function will trigger a custom behavior, with two effects:
1. It will create custom HTML tags, `<pre class='mermaid'><code>`.
2. It will deactivate the auto-load.
You **must** then use a special custom javascript loader for the diagram,
developed by [facelessuser](https://github.com/facelessuser):
1. Copy the code from
the [website of PyMdown Extension](https://facelessuser.github.io/pymdown-extensions/extras/mermaid/#putting-it-all-together).
2. Paste it in a file in your project: `docs/js/loader.js`
3. Declare this script in the `config.yml` file:
```yaml
extra_javascript:
- js/loader.js
```
## Using the mermaid2.dumps() function
As a bonus, mermaid2 exports the function `dumps()` which produces a string
describing a [JavaScript object](https://javascript.info/object).
It can be used to help generate JavaScript code from Python
(this is typically needed, when generating an HTML page that contains
JavaScript).
A JavaScript object is not exactly the same as a JSON object.
The reason why this why introduced is that sometimes one needs to produce
a key/value pair as:
```JavaScript
foo = MyFunctioName
```
where the value is _not_ a string but an identifier (in this case:
a function name).
Here is an example:
```python
import mermaid2
obj = { "hello": "world",
"barbaz": "^bazbar",
"foo": {"bar": 2},
"bar": True}
s = mermaid2.dumps(obj)
```
The purpose of the caret is to specify that the value should be
an identifier and not a string. The result will be:
```JavasScript
{
hello: "world",
barbaz: bazbar,
foo: {
bar: 2
},
bar: true
}
```
## How to contribute
Contributions are welcome.
Use the Issues to signal a bug or propose a feature you believe is necessary.
If this is a usage question, prefer the discussions.
Always open an Issue and consider the answers, before submitting a PR.
## Credits
mkdocs-mermaid2 is a fork from
[Pugong Liu's excellent project](https://github.com/pugong/mkdocs-mermaid-plugin),
which is no longer maintained. This new plugin offers expanded documentation as
well as new functions.
It is also compatible with versions of the mermaid library > 10.0.
Thanks to all the members of the community who participated to the
improvement of this project with ideas and PRs.
================================================
FILE: mermaid2/__init__.py
================================================
"Exports of mermaid2"
# export the dumps function (for producing a JS object)
from .pyjs import dumps
# export the fence_mermaid for pymdownx.superfences
from .fence import fence_mermaid, fence_mermaid_custom
================================================
FILE: mermaid2/fence.py
================================================
"""
Special fence for PyMdown Extensions Superfences
See: https://facelessuser.github.io/pymdown-extensions/extensions/superfences/#formatters
NOTE: SUPERFENCES AND CUSTOM_FENCES ARE NOT NEEDED UNLESS
CODE HIGHLIGHTING IS REQUIRED.
- fence_mermaid() for most Mkdocs themes
- fence_mermaid_custom() for Material theme
"""
from functools import partial
def fence_mermaid(source, language, css_class, options, md,
classes=None, id_value='', custom=False, **kwargs):
"""
For mermaid loose mode:
This function is needed for correctly displaying the mermaid
HTML in diagrams when pymdownx.superfences is activated,
so that code highlighting is activated.
Contrary to the standard fence_div_format used in
https://github.com/facelessuser/pymdown-extensions/blob/9489bd8d94eebf4a109b7dada613bc2db378e31f/pymdownx/superfences.py#L149,
this function it format sources as <div>...</div> but
WITHOUT escaping the < and > characters in the HTML.
It should be called in the mkdocs.yaml file as:
markdown_extensions:
- ...
- ...
- pymdownx.superfences:
# make exceptions to highlighting of code:
custom_fences:
- name: mermaid
class: mermaid
format: !!python/name:mermaid2.fence_mermaid
"""
if id_value:
id_value = ' id="{}"'.format(id_value)
classes = css_class if classes is None else ' '.join(classes + [css_class])
if custom:
html = '<pre %s class="%s"><code>%s\n</code></pre>' % \
(id_value, classes, source)
else:
html = '<div %s class="%s">%s\n</div>' % \
(id_value, classes, source)
# print("--- Mermaid ---\n", html, "\n------")
return html
# special custom function for Material theme
# (do not forget to specify name!)
fence_mermaid_custom = partial(fence_mermaid, custom=True)
fence_mermaid_custom.__name__ = 'fence_mermaid_custom'
================================================
FILE: mermaid2/plugin.py
================================================
"""
Main plugin module for mermaid2
"""
import os
from mkdocs.plugins import BasePlugin
from mkdocs.config.config_options import Type as PluginType
from bs4 import BeautifulSoup
from . import pyjs
from .util import info, libname, url_exists
# ------------------------
# Constants and utilities
# ------------------------
# the default (recommended) mermaid lib:
JAVASCRIPT_VERSION = '10.4.0'
JAVASCRIPT_PRE_10 = "https://unpkg.com/mermaid@%s/dist/mermaid.min.js"
# New format (ESM):
JAVASCRIPT = "https://unpkg.com/mermaid@%s/dist/mermaid.esm.min.mjs"
# Two conditions for activating custom fences:
SUPERFENCES_EXTENSION = 'pymdownx.superfences'
CUSTOM_FENCE_FN = 'fence_mermaid_custom'
# ------------------------
# Plugin
# ------------------------
class MarkdownMermaidPlugin(BasePlugin):
"""
Plugin for interpreting Mermaid code
"""
config_scheme = (
('version', PluginType(str, default=JAVASCRIPT_VERSION)),
('javascript', PluginType(str, default=None)),
('arguments', PluginType(dict, default={})),
# ('custom_loader', PluginType(bool, default=False))
)
# ------------------------
# Properties
# Do not call them before on_config was run!
# ------------------------
@property
def full_config(self):
"""
The full plugin's configuration object,
which also includes the contents of the yaml config file.
"""
return self._full_config
@property
def mermaid_args(self):
"""
The arguments for mermaid, found in the config file.
"""
return self._mermaid_args
@property
def mermaid_version(self) -> str:
"""
The version of mermaid
This information comes from the YAML file parameter,
or, if empty, from JAVASCRIPT_VERSION.
"""
version = self.config['version'] or JAVASCRIPT_VERSION
assert version, "No correct version of mermaid is provided!"
return version
@property
def mermaid_major_version(self) -> int:
"""
Major version of mermaid (e.g. 8. 9, 10) as int
"""
major = self.mermaid_version.split('.')[0]
try:
return int(major)
except:
ValueError("Mermaid version provided has incorrect format")
@property
def extra_javascript(self) -> str:
"""
Provides the mermaid.js library defined in mkdocs.yml
under extra_javascript.
To be recognized, the library must have 'mermaid' in the filename.
WARNING:
Using extra_javascript for that purpose was the original way,
but is now DEPRECATED; it bypasses the new and better mechanisms
for selecting the javascript library.
It will insert the mermaid library in all pages, regardless
of whether a mermaid diagram is present or not.
"""
if not hasattr(self, '_extra_javascript'):
# As of mkdocs 1.5, extra_javascript is a list of objects;
# no longer a string. Call to str was used.
# Patched in 1.5.1, with __fspath___ method,
# see https://github.com/mkdocs/mkdocs/issues/3310
# But we keep it, to guarantee it's a string.
extra_javascript = map(str, self.full_config.get('extra_javascript', []))
for lib in extra_javascript:
# check that 'mermaid' is in the filename, minus the extension.
basename = os.path.basename(lib)
basename, ext = os.path.splitext(basename)
if 'mermaid' in basename.lower():
self._extra_javascript = lib
return lib
self._extra_javascript = None
return self._extra_javascript
@property
def javascript(self) -> str:
"""
Provides the url/pathanme of mermaid library according to version
(distinction on the default, between version < 10 and after)
"""
if not hasattr(self, '_javascript'):
# check if a mermaid javascript parameter exists:
javascript = self.config['javascript']
if not javascript:
if self.mermaid_major_version < 10:
javascript = JAVASCRIPT_PRE_10 % self.mermaid_version
else:
# newer versions
javascript = JAVASCRIPT % self.mermaid_version
# make checks
if not url_exists(javascript,
local_base_dir=self.full_config['docs_dir']):
raise FileNotFoundError("Cannot find Mermaid library: %s" %
javascript)
self._javascript = javascript
return self._javascript
@property
def activate_custom_loader(self) -> bool:
"""
Predicate: activate the custom loader for superfences?
The rule is to activate:
1. superfences extension is activated
2. it specifies 'fence_mermaid_custom' as
as format function (instead of fence_mermaid)
"""
try:
return self._activate_custom_loader
except AttributeError:
# first call:
# superfences_installed = ('pymdownx.superfences' in
# self.full_config['markdown_extensions'])
# custom_loader = self.config['custom_loader']
# self._activate_custom_loader = (superfences_installed and
# custom_loader)
# return self._activate_custom_loader
self._activate_custom_loader = False
superfences_installed = (SUPERFENCES_EXTENSION in
self.full_config['markdown_extensions'])
if superfences_installed:
# get the config extension configs
mdx_configs = self.full_config['mdx_configs']
# get the superfences config, if exists:
superfence_config = mdx_configs.get(SUPERFENCES_EXTENSION)
if superfence_config:
info("Found superfences config: %s" % superfence_config)
custom_fences = superfence_config.get('custom_fences', [])
for fence in custom_fences:
format_fn = fence.get('format')
if format_fn.__name__ == CUSTOM_FENCE_FN:
self._activate_custom_loader = True
info("Found '%s' function: "
"activate custom loader for superfences"
% CUSTOM_FENCE_FN)
break
return self._activate_custom_loader
# ------------------------
# Event handlers
# ------------------------
def on_config(self, config):
"""
The initial configuration
store the configuration in properties
"""
# the full config info for the plugin is there
# we copy it into our own variable, to keep it accessible
self._full_config = config
# Storing the arguments to be passed to the Javascript library;
# they are found under `mermaid2:arguments` in the config file:
self._mermaid_args = self.config['arguments']
# Here we used the standard self.config property
# (this can get confusing...)
assert isinstance(self.mermaid_args, dict)
info("Initialization arguments:", self.mermaid_args)
# info on the javascript library:
if self.extra_javascript:
info("Explicit mermaid javascript library from extra_javascript:\n ",
self.extra_javascript)
info("WARNING: Using extra_javascript is now DEPRECATED; "
"use mermaid:javascript instead!")
elif self.config['javascript']:
info("Using specified javascript library: %s" %
self.config['javascript'])
else:
info("Using javascript library (%s):\n "%
self.config['version'],
self.javascript)
def on_post_page(self, output_content, config, page, **kwargs):
"""
Actions for each page:
generate the HTML code for all code items marked as 'mermaid'
"""
if "mermaid" not in output_content:
# Skip unecessary HTML parsing
return output_content
soup = BeautifulSoup(output_content, 'html.parser')
page_name = page.title
# first, determine if the page has diagrams:
if self.activate_custom_loader:
# the custom loader has its specific marking
# <pre class = 'mermaid'><code> ... </code></pre>
info("Custom loader activated")
mermaids = len(soup.select("pre.mermaid code"))
else:
# standard mermaid can accept two types of marking:
# <pre><code class = 'mermaid'> ... </code></pre>
# but since we want only <div> for best compatibility,
# it needs to be replaced
# NOTE: Python-Markdown changed its representation of code blocks
# https://python-markdown.github.io/change_log/release-3.3/
pre_code_tags = (soup.select("pre code.mermaid") or
soup.select("pre code.language-mermaid"))
no_found = len(pre_code_tags)
if no_found:
info("Page '%s': found %s diagrams "
"(with <pre><code='[language-]mermaid'>), converting to <div>..." %
(page_name, len(pre_code_tags)))
for tag in pre_code_tags:
content = tag.text
new_tag = soup.new_tag("div", attrs={"class": "mermaid"})
new_tag.append(content)
# replace the parent:
tag.parent.replace_with(new_tag)
# Count the diagrams <div class = 'mermaid'> ... </div>
mermaids = len(soup.select("div.mermaid"))
# if yes, add the javascript snippets:
if mermaids:
info("Page '%s': found %s diagrams, adding scripts" %
(page_name, mermaids))
# insertion of the <script> tag, with the initialization arguments
new_tag = soup.new_tag("script")
js_code = [] # the code lines
if not self.extra_javascript:
javascript = self.javascript.strip()
if not javascript.startswith("http"):
# it is necessary to adapt the link
javascript = os.path.relpath(javascript,
os.path.dirname(page.url))
# if no extra library mentioned,
# add the <SCRIPT> tag needed for mermaid
if javascript.endswith('.mjs'):
# <script type="module">
# import mermaid from ...
new_tag['type'] = "module"
js_code.append('import mermaid from "%s";'
% javascript)
else:
# <script src="...">
# generally for self.mermaid_major_version < 10:
new_tag['src'] = javascript
# it's necessary to close and reopen the tag:
soup.body.append(new_tag)
new_tag = soup.new_tag("script")
# (self.mermaid_args), as found in the config file.
if self.activate_custom_loader:
# if the superfences extension is present, use the specific loader
self.mermaid_args['startOnLoad'] = False
js_args = pyjs.dumps(self.mermaid_args)
js_code.append("window.mermaidConfig = {default: %s};" %
js_args)
else:
# normal case
js_args = pyjs.dumps(self.mermaid_args)
js_code.append("mermaid.initialize(%s);" % js_args)
# merge the code lines into a string:
new_tag.string = "\n".join(js_code)
soup.body.append(new_tag)
return str(soup)
================================================
FILE: mermaid2/pyjs.py
================================================
"""
Writer for JavaScript objects
(not JSON syntax)
https://stackoverflow.com/questions/3975859/what-are-the-differences-between-json-and-javascript-object
In principle, JSON _could_ work.
However, we occasionally need to use identifiers, e.g. for function names;
the problem is that json.dumps() only produces strings, never literals.
"""
from typing import Any, Callable
from jsbeautifier import beautify
def dumps(obj:Any,
pretty:bool=True,
default:Callable[[Any], str]=None) -> str:
"""
Serialize an object into a JavaScript object syntax.
Arguments:
---------
- obj: the input object
- pretty: indent the result
- default: function to be used of no serialization is pssible
Usage Note
----------
When a string starts with a ^ character (caret),
the rest of the string will be considered as an identifier.
Returns
-------
A string containing a Javascript object
"""
if isinstance(obj, bool):
if obj:
return "true"
else:
return "false"
elif isinstance(obj, (int, float)):
return obj
elif isinstance(obj, str):
# return strings
if not obj:
# empty
r = '""'
elif obj[0] == '^':
# it's a literal
r = obj[1:]
else:
# normal string
r = '"%s"' % obj
return r
elif isinstance(obj, dict):
l = []
for key, value in obj.items():
s_value = dumps(value, False, default)
# print("Key, value, s_value:", key, value, s_value)
v = '%s: %s' % (key, s_value)
l.append(v)
#return indent('\n'.join(l), level)
r = "{ %s }" % ', '.join(l)
if pretty:
r = beautify(r)
# r = str(level) + r
return r
elif isinstance(obj, list):
l = []
for value in obj:
s_value = dumps(value, False, default)
l.append('%s' % s_value)
r = "[ %s ]" % ', '.join(l)
if pretty:
r = beautify(r)
return r
elif default:
return default(obj)
else:
raise ValueError("Unrecognized type %s for Javascript" %
type(obj).__name__)
if __name__ == "__main__":
a = { "hello": "world",
"barbaz": "^bazbar",
"foo": {"bar": 2},
"bar": True}
r = dumps(a)
print("FIRST")
print("- Python:", a)
print("- Javascript:")
print(r)
assert '"bazbar"' not in r
assert 'bazbar' in r
print("SECOND")
import yaml
config_yaml = """
plugins:
- mermaid2:
arguments:
theme: neutral
mermaid:
callback: ^myMermaidCallbackFunction
extra_javascript:
- https://unpkg.com/mermaid@8.5.2/dist/mermaid.min.js
- js/extra.js
"""
config = yaml.load(config_yaml, Loader=yaml.BaseLoader)
print("- YAML:")
print(config_yaml)
print("- dumps:")
print(dumps(config))
================================================
FILE: mermaid2/util.py
================================================
"""
Utilities for mermaid2 module
"""
import os
import requests
import logging
from packaging.version import Version
import mkdocs
# -------------------
# Logging
# -------------------
log = logging.getLogger("mkdocs.plugins." + __name__)
MKDOCS_LOG_VERSION = '1.2'
if Version(mkdocs.__version__) < Version(MKDOCS_LOG_VERSION):
# filter doesn't do anything since that version
from mkdocs.utils import warning_filter
log.addFilter(warning_filter)
MERMAID_LABEL = "MERMAID2 -" # plugin's signature label
TRACE_LEVELS = {
'debug' : logging.DEBUG,
'info' : logging.INFO,
'warning' : logging.WARNING,
'error' : logging.ERROR,
'critical': logging.CRITICAL
}
def trace(*args, level:str='info'):
"""
General purpose print function, as trace,
for the mkdocs-macros framework;
it will appear unless --quiet option is activated.
The level is 'debug', 'info', 'warning', 'error' or 'critical'.
"""
args = [MERMAID_LABEL] + [str(arg) for arg in args]
msg = ' '.join(args)
try:
log.log(TRACE_LEVELS[level], msg)
except KeyError:
raise ValueError("Unknown level '%s' %s" % (level,
tuple(TRACE_LEVELS.keys())
)
)
return msg
def info(*args) -> str:
"Write information on the console, preceded by the signature label"
# args = [MERMAID_LABEL] + [str(arg) for arg in args]
# msg = ' '.join(args)
# log.info(msg)
return trace(*args)
# -------------------
# Paths and URLs
# -------------------
def libname(lib:str) -> str:
"Get the library name from a path -- not used"
basename = os.path.basename(lib)
# remove extension three times, e.g. mermaid.min.js => mermaid
t = basename
for _ in range(3):
t = os.path.splitext(t)[0]
return t
def url_exists(url:str, local_base_dir:str='') -> bool:
"Checks that a url exists"
if url.startswith('http'):
try:
request = requests.get(url)
return request.status_code == 200
except requests.exceptions.RequestException as e:
trace("Cannot check URL, no Internet access? (%s):\n\n%s" % (url, e),
level='warning')
return True
else:
pathname = os.path.join(local_base_dir, url)
return os.path.exists(pathname)
================================================
FILE: pyproject.toml
================================================
[project]
name = "mkdocs-mermaid2-plugin"
# This version number is the REFERENCE for the rest of the project,
# particularly for update_pypi.sh
version = "1.2.3"
description = "A MkDocs plugin for including mermaid graphs in markdown sources"
readme = "README.md"
license = { text = "MIT" }
requires-python = ">=3.8"
authors = [{ name = "Laurent Franceschetti" }]
keywords = ["markdown", "mermaid", "mkdocs", "python"]
classifiers = [
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers",
"Intended Audience :: Information Technology",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.5",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
]
dependencies = [
"beautifulsoup4>=4.6.3",
"jsbeautifier",
"mkdocs>=1.0.4",
"pymdown-extensions >= 8.0",
"requests",
"setuptools>=18.5",
]
[tool.setuptools]
packages = { find = { exclude = ["*.tests"] } }
[project.optional-dependencies]
test = ["mkdocs-macros-test", "mkdocs-material", "packaging", "requests-html"]
[project.entry-points."mkdocs.plugins"]
mermaid2 = "mermaid2.plugin:MarkdownMermaidPlugin"
[project.urls]
Homepage = "https://github.com/fralau/mkdocs-mermaid2-plugin"
================================================
FILE: setup.py
================================================
"""
Installation using setup.py is no longer supported.
Use `python -m pip install .` instead.
"""
from setuptools import setup
# Fake reference so GitHub still considers it a real package for statistics purposes.
setup(
name='mkdocs-mermaid2-plugin',
)
================================================
FILE: test/__init__.py
================================================
================================================
FILE: test/extra_javascript/docs/index.md
================================================
# Mermaid test (simple)
## Mermaid usual
This is a test of Mermaid:
```mermaid
graph TD
hello --> world
world --> world2
```
> If you don't see a graph here, it's broken.
## Git Graph
This is a test of Git Graph:
```mermaid
gitGraph
commit
commit
branch develop
checkout develop
commit
commit
checkout main
merge develop
commit
commit
```
## Normal fences
This is usual fenced code (with no highlighting)
```python
for page in pages:
page.read()
```
================================================
FILE: test/extra_javascript/docs/second.md
================================================
# Second page
Testing special cases
## Wrong diagram
```mermaid
graph FG
A[Client]
```
## Correct
```mermaid
graph TD
A[Client] --> B[Load Balancer]
```
## Other
```mermaid
graph TD
A[Client] --> B[Load Balancer]
B --> C[Server01]
B --> D[Server02]
```
================================================
FILE: test/extra_javascript/mkdocs.yml
================================================
site_name: Mermaid test (simple, extra_javascript)
site_description: Test for mermaid
docs_dir: docs # indispensable or readthedocs will fail
theme: readthedocs # you may want to try windmill?
nav:
- Main: index.md
- Second: second.md
plugins:
- search
- mermaid2
extra_javascript:
- js/mermaid.min.js
================================================
FILE: test/fixture.py
================================================
"""
Specific for MkDocs Projects
(C) Laurent Franceschetti 2024
"""
import re
import requests
from super_collections import SuperDict
from mkdocs_test import DocProject, MkDocsPage
from packaging import version
URL_PATTERN = r'https://[^\s"]+'
VERSION_PATTERN = r"@(\d+\.\d+\.\d+)"
def extract_url(s:str) -> str|None:
"Extract the first url from a string"
match = re.search(URL_PATTERN, s)
if match:
url = match.group(0)
return url
else:
return None
def get_last_version(mermaid_url:str) -> version.Version:
"Get the last version from a mermaid url"
response = requests.get(mermaid_url)
version_no = response.url.split('@')[1].split('/')[0]
return version.parse(version_no)
def assert_string_contains(txt:str, items:list) -> bool:
"""
Find items in a string.
All items must be present (AND); however, if one item is an
iterable-non-string, then each subitem will an OR.
['foo', 'bar', ('baz', 'barbaz')] -> 'foo' AND 'bar' AND ('baz' OR 'barbaz')
"""
for item in items:
if isinstance(item, str):
assert item in txt, f"'{item}' not found in:\n{txt}!"
else:
assert any(subitem in txt for subitem in item), f"None of {item} found in:\n{txt}!"
class Mermaid2Page(MkDocsPage):
"Specific for Mermaid2"
LIB_VERSION_CHANGE = version.parse('10')
@property
def mermaid_script(self) -> str:
"""
Get the call to the mermaid javascript library
(in the two versions, pre- and post- 10.0).
Performs checks and initializes the js_version property.
For testing purposes, this function contains INVARIANTS
(principles that should remain the same in time, and
across different configurations).
"""
try:
self._mermaid_script
except AttributeError:
mermaid_script = self.find('script', type="module")
if mermaid_script:
# Version >= 10
script_txt = mermaid_script.string
FIND_TEXT = ["import mermaid", "esm.min.mjs",
('mermaid.initialize', 'mermaidConfig')]
assert_string_contains(script_txt, FIND_TEXT)
# Get the version number from the string; if not, from the Mermaid url:
mermaid_url = extract_url(script_txt)
assert mermaid_url, "No URL found for mermaid"
assert 'mermaid' in mermaid_url, f"Error in url: {mermaid_url}"
self._js_version = get_last_version(mermaid_url)
return script_txt
else:
# Version < 10
# Find the script calling the library
mermaid_script = self.find('script', src=lambda x: x and 'mermaid' in x)
assert mermaid_script, "Couldn't find the < 10 Mermaid library!"
src = mermaid_script.get('src')
match = re.search(VERSION_PATTERN, src)
# If < 10, it demands that the script version be explicit (x.y.z)
if match:
version_str = match.group(1)
version = version.Version(version_str)
self._js_version = version
else:
raise ValueError("No version number with < 10 Mermaid library")
return mermaid_script.string
@property
def js_version(self) -> version.Version:
"""
Get the version of the javascript library, while performing checks.
"""
try:
return self._js_version
except AttributeError:
# Initialize
self.mermaid_script
return self._js_version
class Mermaid2DocProject(DocProject):
"Specific for MkDocs-Macros"
@property
def plugin_version(self) -> version.Version|None:
"Get the Mermaid2 javascript library version from the plugin"
plugin = self.get_plugin('mermaid2')
try:
return version.Version(plugin.version)
except AttributeError:
pass
@property
def pages(self) -> dict[Mermaid2Page]:
"List of pages"
pages = super().pages
return {key: Mermaid2Page(value) for key, value in pages.items()}
================================================
FILE: test/http_lib/docs/index.md
================================================
# Mermaid test (simple)
## Mermaid usual
This is a test of Mermaid:
```mermaid
graph TD
hello --> world
world --> world2
```
> If you don't see a graph here, it's broken.
## Git Graph
This is a test of Git Graph:
```mermaid
gitGraph
commit
commit
branch develop
checkout develop
commit
commit
checkout main
merge develop
commit
commit
```
## Normal fences
This is usual fenced code (with no highlighting)
```python
for page in pages:
page.read()
```
================================================
FILE: test/http_lib/docs/second.md
================================================
# Second page
Testing special cases
## Wrong diagram
```mermaid
graph FG
A[Client]
```
## Correct
```mermaid
graph TD
A[Client] --> B[Load Balancer]
```
## Other
```mermaid
graph TD
A[Client] --> B[Load Balancer]
B --> C[Server01]
B --> D[Server02]
```
================================================
FILE: test/http_lib/mkdocs.yml
================================================
site_name: Mermaid test (simple, with local specified library)
site_description: Test for mermaid
docs_dir: docs # indispensable or readthedocs will fail
theme: readthedocs # you may want to try windmill?
nav:
- Main: index.md
- Second: second.md
plugins:
- search
- mermaid2:
javascript: https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs
================================================
FILE: test/local_lib/docs/index.md
================================================
# Mermaid test (simple)
## Mermaid usual
This is a test of Mermaid:
```mermaid
graph TD
hello --> world
world --> world2
```
> If you don't see a graph here, it's broken.
## Git Graph
This is a test of Git Graph:
```mermaid
gitGraph
commit
commit
branch develop
checkout develop
commit
commit
checkout main
merge develop
commit
commit
```
## Normal fences
This is usual fenced code (with no highlighting)
```python
for page in pages:
page.read()
```
================================================
FILE: test/local_lib/docs/second.md
================================================
# Second page
Testing special cases
## Wrong diagram
```mermaid
graph FG
A[Client]
```
## Correct
```mermaid
graph TD
A[Client] --> B[Load Balancer]
```
## Other
```mermaid
graph TD
A[Client] --> B[Load Balancer]
B --> C[Server01]
B --> D[Server02]
```
================================================
FILE: test/local_lib/mkdocs.yml
================================================
site_name: Mermaid test (simple, with local specified library)
site_description: Test for mermaid
docs_dir: docs # indispensable or readthedocs will fail
theme: readthedocs # you may want to try windmill?
nav:
- Main: index.md
- Second: second.md
plugins:
- search
- mermaid2:
javascript: js/mermaid.min.js
================================================
FILE: test/material/__init__.py
================================================
================================================
FILE: test/material/docs/index.md
================================================
# Mermaid test (Material theme)
## Mermaid usual
This is a test of Mermaid:
```mermaid
graph TD
hello --> world
world --> world2
```
> If you don't see a graph here, it's broken.
## Git Graph
This is a test of Git Graph:
```mermaid
gitGraph
commit
commit
branch develop
checkout develop
commit
commit
checkout main
merge develop
commit
commit
```
## Normal fences
This is usual fenced code (with no highlighting)
```python
for page in pages:
page.read()
```
================================================
FILE: test/material/docs/js/extra.js
================================================
// js/extra.js
function myMermaidCallbackFunction(id) {
var d = new Date();
var now = d.toLocaleTimeString();
console.log('Hello, this is myMermaidCallbackFunction', id, now);
}
// import uml from "./uml"
// (() => {
// const onReady = function(fn) {
// if (document.addEventListener) {
// document.addEventListener("DOMContentLoaded", fn)
// document.addEventListener("DOMContentSwitch", fn)
// } else {
// document.attachEvent("onreadystatechange", () => {
// if (document.readyState === "interactive") {
// fn()
// }
// })
// }
// }
// onReady(() => {
// if (typeof mermaid !== "undefined") {
// uml("mermaid")
// }
// })
// })()
================================================
FILE: test/material/docs/second.md
================================================
# Second page
Testing special cases
## Wrong diagram
```mermaid
graph FG
A[Client]
```
## Correct
```mermaid
graph TD
A[Client] --> B[Load Balancer]
```
## Other
```mermaid
graph TD
A[Client] --> B[Load Balancer]
B --> C[Server01]
B --> D[Server02]
```
================================================
FILE: test/material/mkdocs.yml
================================================
site_name: Mermaid test (Material theme)
site_description: Test for mermaid
docs_dir: docs # indispensable or readthedocs will fail
# theme: material # you may want to try windmill?
theme: material
nav:
- Main: index.md
- Second: second.md
plugins:
- search
- test
- mermaid2:
version: '10.1.0'
================================================
FILE: test/material/test_site.py
================================================
"""
Testing the project
Material theme, otherwise normal
(C) Laurent Franceschetti 2024
"""
import pytest
from mkdocs_test import DocProject
from test.fixture import Mermaid2DocProject
def test_pages():
"Test this project"
# ----------------
# First page
# ----------------
project = Mermaid2DocProject(".")
build_result = project.build(strict=False)
# did not fail
return_code = project.build_result.returncode
assert not return_code, f"Build returned with {return_code} {build_result.args})"
# ----------------
# First page
# ----------------
page = project.get_page('index')
# find the diagrams; they are divs
diagrams = page.find_all('div', class_='mermaid')
assert len(diagrams) == 2
assert diagrams[0].string.startswith('graph TD')
assert diagrams[1].string.startswith('gitGraph')
# use the fixture:
version = page.js_version
assert version == project.plugin_version
print("Version:", version)
assert version
assert version > page.LIB_VERSION_CHANGE
# find the piece of Python code
my_code = page.find('code', class_='language-python')
assert 'page.read()' in my_code.string
# ----------------
# Second page
# ----------------
page = project.get_page('second')
# find the diagrams; they are divs:
diagrams = page.find_all('div', class_='mermaid')
assert len(diagrams) == 3
wrong_diagram = diagrams[0].string # this one is wrong
assert wrong_diagram.startswith('graph FG')
assert "A[Client]" in wrong_diagram
# the other two are correct:
assert diagrams[1].string.startswith('graph TD')
assert diagrams[2].string.startswith('graph TD')
# check that the second page has same version as first
assert page.js_version == version
================================================
FILE: test/medium/docs/index.md
================================================
# Mermaid test (medium, with arguments)
## Mermaid usual
This is a test of Mermaid:
```mermaid
graph TD
hello --> world
world --> world2
```
> If you don't see a graph here, it's broken.
> The diagram must be **green** (forest).
> If it isn't then arguments in config.yaml are not taken
> into consideration!
## Mermaid (with HTML)
This code exploits the 'loose' security level.
> If you don't see a graph here, it's broken.
> **Hello** should be bold, and *World* should be big and italic.
>
> If you see the tags `<b>` or `<i>`, it's broken.
```mermaid
graph LR
hello["<b>Hello</b>"] --> world["<big><i>World</i></big>"]
world --> mermaid[mermaid web site]
click mermaid "https://mermaid-js.github.io/mermaid" "Website"
```
> The box **mermaid web site** is clickable!
## Normal fences
This is usual fenced code (with color highlighting)
```python
for page in pages:
page.read()
```
## Javascript callback
Check **in the web console** that a message of that type is displayed:
```
Hello, this is myMermaidCallbackFunction mermaid-1598273751083 14:55:51
```
This is the result of this directive in the config file:
```
extra_javascript:
- js/extra.js
```
================================================
FILE: test/medium/docs/js/extra.js
================================================
// js/extra.js
function myMermaidCallbackFunction(id) {
var d = new Date();
var now = d.toLocaleTimeString();
console.log('Hello, this is myMermaidCallbackFunction', id, now);
}
================================================
FILE: test/medium/docs/second.md
================================================
# Second page
Testing special cases
## Wrong diagram
```mermaid
graph FG
A[Client]
```
## Correct diagram
```mermaid
graph LR
hello --> world
world --> again
again --> hello
```
================================================
FILE: test/medium/mkdocs.yml
================================================
site_name: Mermaid test (medium, arguments)
site_description: Test for mermaid
docs_dir: docs # indispensable or readthedocs will fail
theme:
name: material
language: en
font: "Open Sans"
nav:
- Main: index.md
- Second: second.md
plugins:
- search
- mermaid2:
version: '10.1.0' # just because we can
arguments:
securityLevel: 'loose'
theme: forest # we want also that to work
mermaid:
callback: ^myMermaidCallbackFunction
markdown_extensions:
- admonition
- pymdownx.details
- pymdownx.superfences:
# make exceptions to highlighting of code:
custom_fences:
- name: mermaid
class: mermaid
format: !!python/name:mermaid2.fence_mermaid_custom
extra_javascript:
# Callback function
- js/extra.js
================================================
FILE: test/simple/__init__.py
================================================
================================================
FILE: test/simple/docs/index.md
================================================
# Mermaid test (simple)
## Mermaid usual
This is a test of Mermaid:
```mermaid
graph TD
hello --> world
world --> world2
```
> If you don't see a graph here, it's broken.
## Git Graph
This is a test of Git Graph:
```mermaid
gitGraph
commit
commit
branch develop
checkout develop
commit
commit
checkout main
merge develop
commit
commit
```
## Normal fences
This is usual fenced code (with no highlighting)
```python
for page in pages:
page.read()
```
================================================
FILE: test/simple/docs/js/extra.js
================================================
// js/extra.js
function myMermaidCallbackFunction(id) {
var d = new Date();
var now = d.toLocaleTimeString();
console.log('Hello, this is myMermaidCallbackFunction', id, now);
}
// import uml from "./uml"
// (() => {
// const onReady = function(fn) {
// if (document.addEventListener) {
// document.addEventListener("DOMContentLoaded", fn)
// document.addEventListener("DOMContentSwitch", fn)
// } else {
// document.attachEvent("onreadystatechange", () => {
// if (document.readyState === "interactive") {
// fn()
// }
// })
// }
// }
// onReady(() => {
// if (typeof mermaid !== "undefined") {
// uml("mermaid")
// }
// })
// })()
================================================
FILE: test/simple/docs/second.md
================================================
# Second page
Testing special cases
## Wrong diagram
```mermaid
graph FG
A[Client]
```
## Correct
```mermaid
graph TD
A[Client] --> B[Load Balancer]
```
## Other
```mermaid
graph TD
A[Client] --> B[Load Balancer]
B --> C[Server01]
B --> D[Server02]
```
================================================
FILE: test/simple/mkdocs.yml
================================================
site_name: Mermaid test (simple, default theme)
site_description: Test for mermaid
docs_dir: docs # indispensable or readthedocs will fail
theme: readthedocs # you may want to try windmill?
nav:
- Main: index.md
- Second: second.md
plugins:
- search
- test
- mermaid2
================================================
FILE: test/simple/test_site.py
================================================
"""
Testing the project
(C) Laurent Franceschetti 2024
"""
import pytest
from mkdocs_test import DocProject
from test.fixture import Mermaid2DocProject
def test_pages():
"Test this project"
FIND_TEXT = ["import mermaid", "mermaid.initialize", "esm.min.mjs"]
# ----------------
# First page
# ----------------
project = Mermaid2DocProject(".")
build_result = project.build(strict=False)
# did not fail
return_code = project.build_result.returncode
assert not return_code, f"Build returned with {return_code} {build_result.args})"
# ----------------
# First page
# ----------------
page = project.get_page('index')
# find the diagrams; they are divs
diagrams = page.find_all('div', class_='mermaid')
assert len(diagrams) == 2
# find the mermaid script
mermaid_script = page.find('script', type="module")
for text in FIND_TEXT:
assert text in mermaid_script.string, f"'{text}' not found!"
# use the fixture:
version = page.js_version
print("Version:", version)
assert version
assert version > page.LIB_VERSION_CHANGE
# ----------------
# Second page
# ----------------
# there is intentionally an error (`foo` does not exist)
page = project.get_page('second')
diagrams = page.find_all('div', class_='mermaid')
assert len(diagrams) == 3
# with open('output_file.html', 'w') as f:
# f.write(page.html)
================================================
FILE: test/simple_format/docs/index.md
================================================
# Mermaid test (simple, with formatting of diagrams)
## Mermaid usual
This is a test of Mermaid:
```mermaid
graph TD
hello --> world
world --> world2
```
> If you don't see a graph here, it's broken.
## Git Graph
This is a test of Git Graph:
```mermaid
gitGraph
commit
commit
branch develop
checkout develop
commit
commit
checkout main
merge develop
commit
commit
```
## Normal fences
This is usual fenced code (with no highlighting)
```python
for page in pages:
page.read()
```
================================================
FILE: test/simple_format/docs/js/extra.js
================================================
// js/extra.js
function myMermaidCallbackFunction(id) {
var d = new Date();
var now = d.toLocaleTimeString();
console.log('Hello, this is myMermaidCallbackFunction', id, now);
}
// import uml from "./uml"
// (() => {
// const onReady = function(fn) {
// if (document.addEventListener) {
// document.addEventListener("DOMContentLoaded", fn)
// document.addEventListener("DOMContentSwitch", fn)
// } else {
// document.attachEvent("onreadystatechange", () => {
// if (document.readyState === "interactive") {
// fn()
// }
// })
// }
// }
// onReady(() => {
// if (typeof mermaid !== "undefined") {
// uml("mermaid")
// }
// })
// })()
================================================
FILE: test/simple_format/docs/second.md
================================================
# Second page
Testing special cases
## Wrong diagram
```mermaid
graph FG
A[Client]
```
## Correct
```mermaid
graph TD
A[Client] --> B[Load Balancer]
```
## Other
```mermaid
graph TD
A[Client] --> B[Load Balancer]
B --> C[Server01]
B --> D[Server02]
```
================================================
FILE: test/simple_format/mkdocs.yml
================================================
site_name: Mermaid test (simple, with formatting)
site_description: Test for mermaid
docs_dir: docs # indispensable or readthedocs will fail
theme: readthedocs # you may want to try windmill?
nav:
- Main: index.md
- Second: second.md
plugins:
- search
- mermaid2:
version: '10.1.0'
arguments:
theme: 'dark'
themeVariables:
primaryColor: '#BB2528'
primaryTextColor: '#fff'
primaryBorderColor: '#7C0000'
lineColor: '#F8B229'
secondaryColor: '#006100'
tertiaryColor: '#fff'
================================================
FILE: test/simple_pre_10/docs/index.md
================================================
# Mermaid test (simple)
## Mermaid usual
This is a test of Mermaid:
```mermaid
graph TD
hello --> world
world --> world2
```
> If you don't see a graph here, it's broken.
## Normal fences
This is usual fenced code (with no highlighting)
```python
for page in pages:
page.read()
```
================================================
FILE: test/simple_pre_10/docs/js/extra.js
================================================
// js/extra.js
function myMermaidCallbackFunction(id) {
var d = new Date();
var now = d.toLocaleTimeString();
console.log('Hello, this is myMermaidCallbackFunction', id, now);
}
// import uml from "./uml"
// (() => {
// const onReady = function(fn) {
// if (document.addEventListener) {
// document.addEventListener("DOMContentLoaded", fn)
// document.addEventListener("DOMContentSwitch", fn)
// } else {
// document.attachEvent("onreadystatechange", () => {
// if (document.readyState === "interactive") {
// fn()
// }
// })
// }
// }
// onReady(() => {
// if (typeof mermaid !== "undefined") {
// uml("mermaid")
// }
// })
// })()
================================================
FILE: test/simple_pre_10/docs/second.md
================================================
# Second page
Testing special cases
## Wrong diagram
```mermaid
graph FG
A[Client]
```
## Correct
```mermaid
graph TD
A[Client] --> B[Load Balancer]
```
## Other
```mermaid
graph TD
A[Client] --> B[Load Balancer]
B --> C[Server01]
B --> D[Server02]
```
================================================
FILE: test/simple_pre_10/mkdocs.yml
================================================
site_name: Mermaid test (simple)
site_description: Test for mermaid
docs_dir: docs # indispensable or readthedocs will fail
theme: readthedocs # you may want to try windmill?
nav:
- Main: index.md
- Second: second.md
plugins:
- search
- mermaid2:
version: 8.8.2
# extra_javascript:
# - https://unpkg.com/mermaid/dist/mermaid.min.js
================================================
FILE: test/superfences/__init__.py
================================================
================================================
FILE: test/superfences/docs/index.md
================================================
# Mermaid test (SuperFences, custom loader)
!!! Note
This is a test of the Mermaid plugin, with:
1. the [pymdownx.superfences extension](https://facelessuser.github.io/pymdown-extensions/extensions/superfences/)
2. Custom fences with the `mermaid2.fence_mermaid_custom()` formatter
3. the custom loader is specified as `extra_javascript -> js/loader.js`
## Mermaid (normal)
```mermaid
graph TD
hello --> world
world --> world2
```
> If you don't see a graph here, it's broken.
## Mermaid (with HTML)
** This doesn't work! Known bug. **
This code exploits the 'loose' security level.
> If you don't see a graph here, it's broken.
> **Hello** should be bold, and *World* should be big and italic.
>
> If you see the tags `<b>` or `<i>`, it's broken.
```mermaid
graph LR
hello["<b>Hello</b>"] --> world["<big><i>World</i></big>"]
world --> mermaid[mermaid web site]
click mermaid "https://mermaid-js.github.io/mermaid" "Website"
```
## Superfence
This is usual superfenced code, with code highlighting.
> The keyword `for` should be colored in blue.
```python
for page in pages:
page.read()
```
================================================
FILE: test/superfences/docs/js/loader.js
================================================
function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
(function () {
'use strict';
function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
function _inherits(subClass, superClass) {
if (typeof superClass !== "function" && superClass !== null) {
throw new TypeError("Super expression must either be null or a function");
}
subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: {
value: subClass,
writable: true,
configurable: true
}
});
if (superClass) _setPrototypeOf(subClass, superClass);
}
function _getPrototypeOf(o) {
_getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {
return o.__proto__ || Object.getPrototypeOf(o);
};
return _getPrototypeOf(o);
}
function _setPrototypeOf(o, p) {
_setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
o.__proto__ = p;
return o;
};
return _setPrototypeOf(o, p);
}
function _isNativeReflectConstruct() {
if (typeof Reflect === "undefined" || !Reflect.construct) return false;
if (Reflect.construct.sham) return false;
if (typeof Proxy === "function") return true;
try {
Date.prototype.toString.call(Reflect.construct(Date, [], function () {}));
return true;
} catch (e) {
return false;
}
}
function _construct(Parent, args, Class) {
if (_isNativeReflectConstruct()) {
_construct = Reflect.construct;
} else {
_construct = function _construct(Parent, args, Class) {
var a = [null];
a.push.apply(a, args);
var Constructor = Function.bind.apply(Parent, a);
var instance = new Constructor();
if (Class) _setPrototypeOf(instance, Class.prototype);
return instance;
};
}
return _construct.apply(null, arguments);
}
function _isNativeFunction(fn) {
return Function.toString.call(fn).indexOf("[native code]") !== -1;
}
function _wrapNativeSuper(Class) {
var _cache = typeof Map === "function" ? new Map() : undefined;
_wrapNativeSuper = function _wrapNativeSuper(Class) {
if (Class === null || !_isNativeFunction(Class)) return Class;
if (typeof Class !== "function") {
throw new TypeError("Super expression must either be null or a function");
}
if (typeof _cache !== "undefined") {
if (_cache.has(Class)) return _cache.get(Class);
_cache.set(Class, Wrapper);
}
function Wrapper() {
return _construct(Class, arguments, _getPrototypeOf(this).constructor);
}
Wrapper.prototype = Object.create(Class.prototype, {
constructor: {
value: Wrapper,
enumerable: false,
writable: true,
configurable: true
}
});
return _setPrototypeOf(Wrapper, Class);
};
return _wrapNativeSuper(Class);
}
function _assertThisInitialized(self) {
if (self === void 0) {
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
}
return self;
}
function _possibleConstructorReturn(self, call) {
if (call && (_typeof(call) === "object" || typeof call === "function")) {
return call;
}
return _assertThisInitialized(self);
}
function _createSuper(Derived) {
var hasNativeReflectConstruct = _isNativeReflectConstruct();
return function _createSuperInternal() {
var Super = _getPrototypeOf(Derived),
result;
if (hasNativeReflectConstruct) {
var NewTarget = _getPrototypeOf(this).constructor;
result = Reflect.construct(Super, arguments, NewTarget);
} else {
result = Super.apply(this, arguments);
}
return _possibleConstructorReturn(this, result);
};
}
/* Notes (as of Mermaid 8.7.0):
* - Gantt: width is always relative to the parent, if you have a small parent, the chart will be squashed.
* Can't help it.
* - Journey: Suffers from the same issues that Gantt does.
* - Pie: These charts have no default height or width. Good luck pinning them down to a reasonable size.
* - Git: The render portion is agnostic to the size of the parent element. But padding of the SVG is relative
* to the parent element. You will never find a happy size.
*/
/**
* Targets special code or div blocks and converts them to UML.
* @param {string} className is the name of the class to target.
* @return {void}
*/
var uml = function uml(className) {
// Custom element to encapsulate Mermaid content.
var MermaidDiv = /*#__PURE__*/function (_HTMLElement) {
_inherits(MermaidDiv, _HTMLElement);
var _super = _createSuper(MermaidDiv);
/**
* Creates a special Mermaid div shadow DOM.
* Works around issues of shared IDs.
* @return {void}
*/
function MermaidDiv() {
var _this;
_classCallCheck(this, MermaidDiv);
_this = _super.call(this); // Create the Shadow DOM and attach style
var shadow = _this.attachShadow({
mode: "open"
});
var style = document.createElement("style");
style.textContent = "\n :host {\n display: block;\n line-height: initial;\n font-size: 16px;\n }\n div.mermaid {\n margin: 0;\n overflow: visible;\n }";
shadow.appendChild(style);
return _this;
}
return MermaidDiv;
}( /*#__PURE__*/_wrapNativeSuper(HTMLElement));
if (typeof customElements.get("mermaid-div") === "undefined") {
customElements.define("mermaid-div", MermaidDiv);
}
var getFromCode = function getFromCode(parent) {
// Handles <pre><code> text extraction.
var text = "";
for (var j = 0; j < parent.childNodes.length; j++) {
var subEl = parent.childNodes[j];
if (subEl.tagName.toLowerCase() === "code") {
for (var k = 0; k < subEl.childNodes.length; k++) {
var child = subEl.childNodes[k];
var whitespace = /^\s*$/;
if (child.nodeName === "#text" && !whitespace.test(child.nodeValue)) {
text = child.nodeValue;
break;
}
}
}
}
return text;
}; // We use this to determine if we want the dark or light theme.
// This is specific for our MkDocs Material environment.
// You should load your configs based on your own environment's needs.
var defaultConfig = {
startOnLoad: false,
theme: "default",
flowchart: {
htmlLabels: false
},
er: {
useMaxWidth: false
},
sequence: {
useMaxWidth: false,
noteFontWeight: "14px",
actorFontSize: "14px",
messageFontSize: "16px"
}
};
mermaid.mermaidAPI.globalReset(); // Non Material themes should just use "default"
var scheme = null;
try {
scheme = document.querySelector("[data-md-color-scheme]").getAttribute("data-md-color-scheme");
} catch (err) {
scheme = "default";
}
var config = typeof mermaidConfig === "undefined" ? defaultConfig : mermaidConfig[scheme] || mermaidConfig["default"] || defaultConfig;
mermaid.initialize(config); // Find all of our Mermaid sources and render them.
var blocks = document.querySelectorAll("pre.".concat(className, ", mermaid-div"));
var surrogate = document.querySelector("html");
var _loop = function _loop(i) {
var block = blocks[i];
var parentEl = block.tagName.toLowerCase() === "mermaid-div" ? block.shadowRoot.querySelector("pre.".concat(className)) : block; // Create a temporary element with the typeset and size we desire.
// Insert it at the end of our parent to render the SVG.
var temp = document.createElement("div");
temp.style.visibility = "hidden";
temp.style.display = "display";
temp.style.padding = "0";
temp.style.margin = "0";
temp.style.lineHeight = "initial";
temp.style.fontSize = "16px";
surrogate.appendChild(temp);
try {
mermaid.mermaidAPI.render("_mermaind_".concat(i), getFromCode(parentEl), function (content) {
var el = document.createElement("div");
el.className = className;
el.innerHTML = content; // Insert the render where we want it and remove the original text source.
// Mermaid will clean up the temporary element.
var shadow = document.createElement("mermaid-div");
shadow.shadowRoot.appendChild(el);
block.parentNode.insertBefore(shadow, block);
parentEl.style.display = "none";
shadow.shadowRoot.appendChild(parentEl);
if (parentEl !== block) {
block.parentNode.removeChild(block);
}
}, temp);
} catch (err) {} // eslint-disable-line no-empty
if (surrogate.contains(temp)) {
surrogate.removeChild(temp);
}
};
for (var i = 0; i < blocks.length; i++) {
_loop(i);
}
};
(function () {
var onReady = function onReady(fn) {
document.addEventListener("DOMContentLoaded", fn);
document.addEventListener("DOMContentSwitch", fn);
};
var observer = new MutationObserver(function (mutations) {
mutations.forEach(function (mutation) {
if (mutation.type === "attributes") {
var scheme = mutation.target.getAttribute("data-md-color-scheme");
if (!scheme) {
scheme = "default";
}
localStorage.setItem("data-md-color-scheme", scheme);
if (typeof mermaid !== "undefined") {
uml("mermaid");
}
}
});
});
onReady(function () {
observer.observe(document.querySelector("body"), {
attributeFilter: ["data-md-color-scheme"]
});
if (typeof mermaid !== "undefined") {
uml("mermaid");
}
});
})();
})();
================================================
FILE: test/superfences/docs/second.md
================================================
# Second page
Testing special cases
## Wrong diagram
```mermaid
graph FG
A[Client]
```
## First Note (collapsible open)
???+ note "Collapsable but open"
```mermaid
graph TD
A[Client] --> B[Load Balancer]
```
## Second note (collapsed)
Click on the arrow, to reveal the diagram,
???- note "Collapsed"
```mermaid
graph TD
A[Client] --> B[Load Balancer]
```
This is additional text.
================================================
FILE: test/superfences/mkdocs.yml
================================================
site_name: Mermaid test (SuperFences) + custom loader
site_description: Test for mermaid
docs_dir: docs # indispensable or readthedocs will fail
theme:
name: material
language: en
nav:
- Main: index.md
- Second: second.md
plugins:
- search
- test
- mermaid2:
custom_loader: true
arguments:
securityLevel: 'loose'
theme: forest # we want also that to work
markdown_extensions:
- admonition
- pymdownx.details
- pymdownx.superfences:
# make exceptions to highlighting of code:
custom_fences:
- name: mermaid
class: mermaid
format: !!python/name:mermaid2.fence_mermaid_custom
# format: !!python/name:pymdownx.superfences.fence_div_format
================================================
FILE: test/superfences/test_site.py
================================================
"""
Testing the project
Superfences, the behavior changes
(C) Laurent Franceschetti 2024
"""
import pytest
from mkdocs_test import DocProject
from test.fixture import Mermaid2DocProject
def test_pages():
"Test this project"
# ----------------
# First page
# ----------------
project = Mermaid2DocProject(".")
build_result = project.build(strict=False)
# did not fail
return_code = project.build_result.returncode
assert not return_code, f"Build returned with {return_code} {build_result.args})"
project.self_check()
# ----------------
# First page
# ----------------
page = project.get_page('index')
# find the diagrams; they are divs
diagrams = page.find_all('pre', class_='mermaid')
assert len(diagrams) == 2
assert diagrams[0].code.string.startswith('graph TD')
print("Second diagram's code:\n", diagrams[1].code)
assert diagrams[1].code.decode_contents().startswith('graph LR')
# use the fixture:
version = page.js_version
print("Version:", version)
assert version
assert version > page.LIB_VERSION_CHANGE
# Find the piece of color-highlighted Python code
# now that the HTML is highlighted, it is almost unrecognizable
# it contains a <code> tag that contains <span> tags.
my_code = page.find('div', class_='highlight')
assert my_code, "Couldn't find the expected highlighted code block."
code_text = my_code.get_text() # that strips the tags
assert 'page.read()' in code_text
assert 'foo' not in code_text # negative control
code = my_code.find('code')
assert code, "Couldn't find code element!"
spans = my_code.find_all('span')
assert len(spans) > 5
# ----------------
# Second page
# ----------------
page = project.get_page('second')
# find the diagrams; they are divs:
diagrams = page.find_all('pre', class_='mermaid')
assert len(diagrams) == 3
wrong_diagram = diagrams[0].code.string # this one is wrong
assert wrong_diagram.startswith('graph FG')
assert "A[Client]" in wrong_diagram
# the other two are correct:
assert diagrams[1].code.string.startswith('graph TD')
assert diagrams[2].code.decode_contents().startswith('graph TD')
# check that the second page has same version as first
assert page.js_version == version
================================================
FILE: update_pypi.sh
================================================
# -------------------------------------------------------------
# update the package on pypi
# 2024-10-12
#
# Tip: if you don't want to retype pypi's username every time
# define it as an environment variable (TWINE_USERNAME)
#
# -------------------------------------------------------------
function warn {
GREEN='\033[0;32m'
NORMAL='\033[0m'
echo -e "${GREEN}$1${NORMAL}"
}
function get_value {
# get the value from the config file (requires the Python toml package)
toml get --toml-path pyproject.toml $1
}
# Clean the subdirs, for safety and to guarantee integrity
# ./cleanup.sh
# Check for changes in the files compared to the repository
if ! git diff --quiet; then
warn "Won't do it: there are changes in the repository. Please commit first!"
exit 1
fi
# get the project inform
package_name=$(get_value project.name)
package_version=v$(get_value project.version) # add a 'v' in front (git convention)
# update Pypi
warn "Rebuilding $package_name..."
rm -rf build dist *.egg-info # necessary to guarantee integrity
python3.11 -m build
if twine upload dist/*; then
git push # just in case
warn "... create tag $package_version, and push to remote git repo..."
git tag $package_version
git push --tags
warn "Done ($package_version)!"
else
warn "Failed ($package_version)!"
exit 1
fi
================================================
FILE: webdoc/docs/contribute.md
================================================
## Guidance
1. Contributions are welcome.
2. Before submitting an issue, consider this documentation, and particularly
the [troubleshooting](troubleshooting.md) section.
3. Use the [Issues](https://github.com/fralau/mkdocs-mermaid2-plugin/issues) to signal a bug or propose a feature you believe is necessary.
4. If this is a usage question, prefer the [discussions](https://github.com/fralau/mkdocs-mermaid2-plugin/discussions).
5. **Before submitting a PR, always open an Issue and consider the answers.**
6. As a rule, changes get a new version number;
they are first [pushed on github](https://github.com/fralau/mkdocs-mermaid2-plugin), and then [deployed on pypi](https://pypi.org/project/mkdocs-mermaid2-plugin/).
## Making a distinction between the software components
When assessing issues or bugs, it is important to understand which
components are involved.
!!! Tip
The items marked with an asterisk (*) are clickable.
```mermaid
graph TD
subgraph plugins
mkdocs-mermaid["Mkdocs-Mermaid2"]
end
subgraph browser["Browser"]
rendering[/"HTML/css/Javascript engine"\]
html(HTML) ==> rendering
css(css) ==> rendering
javascript(Javascript) ==> rendering
end
subgraph main
mkdocs["MkDocs*"] -- generates --> html
mkdocs -- generates --> javascript
end
mkdocs-mermaid -.plugin of.-> mkdocs
mkdocs -.-> Material
mkdocs -.extra_javascript.-> mermaid
Superfences -- custom fence --> mermaid
subgraph libraries["Javascript libraries"]
mermaid[Mermaid.js*] -- provides --> javascript
end
subgraph extensions["Markdown extensions"]
mkdocs -.markdown_extensions.-> Superfences
Superfences["Superfences*"]
end
subgraph themes
Material[Material*] -- provides --> css
Material --> html2("HTML (templates)") --> html
end
click mkdocs "https://www.mkdocs.org/" _blank
click Material "https://squidfunk.github.io/mkdocs-material/" _blank
click Superfences "https://facelessuser.github.io/pymdown-extensions/extensions/superfences/" _blank
click mermaid "https://mermaid.js.org/intro/" _blank
```
## Credits
mkdocs-mermaid2 is a fork from
[Pugong Liu's excellent project](https://github.com/pugong/mkdocs-mermaid-plugin),
which is no longer maintained. This new plugin offers expanded documentation as
well as new functions.
It is also compatible with versions of the mermaid library > 10.0.
Thanks to all the members of the community who participated to the
improvement of this project with ideas and PRs.
================================================
FILE: webdoc/docs/description.md
================================================
# Detailed description of the page production process
## Steps for the preparation of an HTML page
There are three steps in the preparation of the HTML page:
```mermaid
flowchart TD
subgraph Page [Page production]
HTML(1. Setting up the HTML tags around the diagram.) --> JS("2. Inserting the call to Mermaid.js")
JS --> Init(3. Initialization/customization)
end
```
When the webserver serves the statig html page,
the Mermaid.js library is executed in the user's browser, to render the diagram.
## Conversion to HTML
When converting the markdown into HTML, MkDocs normally inserts the
Mermaid code (text) describing the diagram
into segments, which will then be processed by the Mermaid.js library
(in the user's browser):
```html
<pre class="mermaid">
<code>
...
</code>
</pre>
```
To make the HTML/css page more robust for most MkDocs themes,
the Mkdocs-Mermaid2 plugin systematically converts
those segments directly into `<div>` elements:
```html
<div class="mermaid">
...
</div>
```
!!! Note "Superfences extension"
The principle remains the same
when using the [Superfences](superfences.md) extension.
That extension is **not** mandatory, except
when using the Material theme.
## Automatic insertion of the Javascript Library
The plugin then inserts a call to the
[javascript library](https://github.com/mermaid-js/mermaid).
By default, the plugin will use one of the latest versions of Mermaid.js.
As already mentioned, you can specify, in the config file, the version
of Mermaid.js required:
```yaml
- mermaid2:
version: '10.1.0'
```
!!! Note
Mkdocs-Macros inserts the Mermaid.js library into the HTML page
**only** when a Mermaid diagram is detected in the markdown page.
!!! Warning "Change of distribution format"
The behavior of the plugin depends of the version of Mermaid.js.
[As of version 10 of the Mermaid javascript library, the plugin uses the ESM format for distribution](https://github.com/mermaid-js/mermaid/releases/tag/v10.0.0) (see also the [changelog](https://github.com/mermaid-js/mermaid/blob/develop/CHANGELOG.md#1000)).
More information can be found on [ECMAScript Module](https://nodejs.org/api/esm.html#modules-ecmascript-modules)
(or **ESM**), but for our purposes:
1. **The main file is recognizable because it has the `.mjs` extension.**
2. The HTML call must have the form: `<script src="<URL>", type="module">`
3. A module in ESM format is not a single file, but a hierarchy of directories/files.
**MkDocs-Mermaid2, as of version 1.0, takes this difference into account.**
=== "ESM Library"
> For versions of MkDocs-Mermaid2 >= 1 and versions of Mermaid2.js >= 10
This requires a specific call from the HTML
page e.g.:
``` html
<script src="https://unpkg.com/mermaid@10.0.2/dist/mermaid.esm.min.mjs" type="module">
</script>
```
The plugin automatically inserts this call.
=== "All-in-one Library"
For an earlier version of the Mermaid.js (<10),
the plugin continues to use the traditional version, which is an **all-in-one file**.
Those library files are recognizable because they have the `.js` extension.
The call in the HTML page is:
``` html
<script src="https://unpkg.com/mermaid@8.8.2/dist/mermaid.min.js">
mermaid.initialize()
</script>
```
The plugin automatically inserts this call.
** This is still a valid method.** (Even though the very first versions after 10.0.0 no longer provided
this file, later versions have resumed providing it.)
## Initialization sequence
### Default sequence
To start displaying of the diagrams, the plugin then automatically inserts
a separate call to initialize the Mermaid library:
```javascript
mermaid.initialize()
```
The user's browser will then read this code and render it on the fly.
> No svg/png images are produced during the rendering of that graph.
### Additional arguments to the Mermaid engine
Sometimes, however, you may want to add some
additional initialization commands (see [full list](https://github.com/knsv/mermaid/blob/master/docs/mermaidAPI.md#mermaidapi-configuration-defaults)).
For example, you could change the theme of the diagram,
using 'dark' instead of the default one.
Simply add those arguments in the config file, e.g.
```yaml
plugins:
- search
- mermaid2:
version: '10.1.0'
arguments:
theme: 'dark'
themeVariables:
primaryColor: '#BB2528'
primaryTextColor: '#fff'
primaryBorderColor: '#7C0000'
lineColor: '#F8B229'
secondaryColor: '#006100'
tertiaryColor: '#fff'
```
The plugin then automatically adds the initialization sequence:
=== "ESM modules"
Both `import` and `mermaid.initialize()` must be in the same `<script>`
tag. This is the code produced by the plugin:
```html
<script type="module">import mermaid from "https://unpkg.com/mermaid@10.1.0/dist/mermaid.esm.min.mjs";
mermaid.initialize({
theme: "dark",
themeVariables: {
primaryColor: "#BB2528",
primaryTextColor: "#fff",
primaryBorderColor: "#7C0000",
lineColor: "#F8B229",
secondaryColor: "#006100",
tertiaryColor: "#fff"
}
});
</script>
```
=== "Traditional modules"
For traditional (all-in-one file) javascript modules, **two** calls to the `<script>` tag are required. This is the code produced by the plugin:
```html
<script src="https://unpkg.com/mermaid@9.1.0/dist/mermaid.min.js"></script>
<script>mermaid.initialize({
theme: "dark",
themeVariables: {
primaryColor: "#BB2528",
primaryTextColor: "#fff",
primaryBorderColor: "#7C0000",
lineColor: "#F8B229",
secondaryColor: "#006100",
tertiaryColor: "#fff"
}
});
</script>
```
================================================
FILE: webdoc/docs/index.md
================================================
# Mkdocs-Mermaid2<br>A diagrams plugin for Mkdocs { align=center }
---
[](https://opensource.org/licenses/MIT)
[](https://pypi.org/project/mkdocs-mermaid2-plugin/)


## Introduction
**Mkdocs-Mermaid2** is a plugin for the [MkDocs](https://www.mkdocs.org/)
static sites generator, which allows you
to render Mermaid diagrams inserted (as text) into the markdown pages.
- [The official repository of Mermaid2 is on github.](https://github.com/fralau/mkdocs-mermaid2-plugin)
- [Mermaid2 is available from Pypi.](https://pypi.org/project/mkdocs-mermaid2-plugin/)
### What is Mermaid?
[Mermaid](https://mermaid.js.org/intro/) is two things:
1. A simple language for the creation of diagrams.
2. A [javascript library](https://github.com/mermaid-js/mermaid) (Mermaid.js)
for displaying those diagrams in an HTML page.
### General Principle
In order to insert a Mermaid diagram in a markdown page,
1. Start a new line with a [code fence](https://www.markdownguide.org/extended-syntax/#fenced-code-blocks) (triple backticks),
with the codeword `mermaid`.
2. Type the diagram using the Mermaid syntax.
2. End with a code fence.
For example, a markdown page containing the following diagram (left-right graph):
```mermaid
graph LR
hello --> world
world --> again
again --> hello
```
will then be displayed in the final HTML page as:
```mermaid
graph LR
hello --> world
world --> again
again --> hello
```
The diagram will be rendered on the fly by the web browser,
with the use of the mermaid javascript library.
The mkdocs-mermaid2 plugin takes care of inserting the javascript library into
the html page and inserting the script to start it.
!!! Note
You can use all the diagrams types supported by the version of the Mermaid
javascript library that you are using (flowchart, class, state, timeline,
etc.).
Here is another example:
```mermaid
pie title Which animals do you prefer as pets?
"Dogs" : 386
"Cats" : 85
"Rabbits" : 53
"Hamsters" : 101
```
It will be rendered as (a pie chart):
```mermaid
pie title Which animals do you prefer as pets?
"Dogs" : 386
"Cats" : 85
"Rabbits" : 53
"Hamsters" : 101
```
### How to write Mermaid diagrams
* For instructions on how to make a diagram, see [the official website](https://mermaid.js.org).
* If you are not familiar, see the [Mermaid Overview for Beginners](https://mermaid.js.org/intro/getting-started.html).
* In case of doubt, you will want to test your diagrams in the [Mermaid Live Editor](https://mermaid.live).
## Installation
### Pre-requisites
* Python 3 >= 3.6
* [Mkdocs](https://www.mkdocs.org/user-guide/installation/)
### Automatic
The most up-to-date, stable production version of mkdocs-mermaid2 is available from the [pypi repository](https://pypi.org/project/mkdocs-mermaid2-plugin/):
```bash
pip install mkdocs-mermaid2-plugin
```
### Manual
The most up-to-date version of the package is available from [github](https://github.com/fralau/mkdocs-mermaid2-plugin).
Clone this repository in a local directory and install the package:
```bash
python setup.py install
```
### Installing and running the test examples
For running the examples the `test` directory,
you will also need the mkdocs-material theme. You may
[install it directly](https://squidfunk.github.io/mkdocs-material/getting-started/),
or use the following command to install the whole package:
```bash
pip install mkdocs-mermaid2-plugin[test]
```
## Configuration
### Basic configuration
To enable this plugin, you need to declare it in your [mkdocs config file](https://www.mkdocs.org/user-guide/configuration/)
(`mkdocs.yml`).
In order to work, the plugin also requires the
[mermaid](https://www.npmjs.com/package/mermaid) javascript
library (in the example below, it fetched from the last version
from the [unpkg](https://unpkg.com/) repository; change the version
no as needed).
```yaml
plugins:
- search
- mermaid2
```
!!! Warning "Caution"
If you declare plugins in the config file, you need to declare _all_ of them,
including `search` (which would otherwise have been installed by default.)
### Specifying the version of the Mermaid library
By default, the plugin selects a version of the Mermaid javascript library
that is known to work (some versions work better than others).
You may specify a different version of the Mermaid library, like so:
```yaml
plugins:
- search
- mermaid2:
version: 10.0.2
```
The plugin will insert the correct call to the javascript library
inside the final HTML page.
### Specifying your own Mermaid library
By default, mkdocs-mermaid2 automatically inserts the proper calls to
Mermaid.js (according to the correct version),
so that the diagrams are correctly interpreted.
You may, however, specify your own explicit call:
```yaml
plugins:
- search
- mermaid2:
javascript: https://unpkg.com/mermaid@10.4.0/dist/mermaid.esm.min.mjs
```
For more details, [see the relative page](library.md).
### Use of the Material theme
!!! Note
The [Material theme](https://squidfunk.github.io/mkdocs-material/),
developed by [squidfunk](https://github.com/squidfunk)
is not mandatory, but recommended.
**Mermaid diagrams will automatically adapt their colors to the theme
and palette.**
Here are the recommended settings in the configuration file:
```yaml
markdown_extensions:
- pymdownx.superfences:
# make exceptions to highlighting of code:
custom_fences:
- name: mermaid
class: mermaid
format: !!python/name:mermaid2.fence_mermaid_custom
```
See the [technical explanation](superfences.md/#usage-for-the-material-theme).
### Other Themes
If you don't use the Material theme, it will be up to you to define the
theme and colors of the diagrams, by adding arguments to the plugin, e.g. :
```yaml
plugins:
- search
- mermaid2:
version: '9.4.3' # only works with version < 10
arguments:
theme: 'dark'
themeVariables:
primaryColor: '#BB2528'
primaryTextColor: '#fff'
primaryBorderColor: '#7C0000'
lineColor: '#F8B229'
secondaryColor: '#006100'
tertiaryColor: '#fff'
```
The result would be as follows, for the diagrams above:


!!! Tip
As of mkdocs-mermaid2 version 1.0.8, this works also with versions of Mermaid.js >= 10.
### Testing
To test your website with a diagram, restart the mkdocs server:
mkdocs serve
In your browser, open the webpage on the localhost
(by default: `https://localhost:8000`)
================================================
FILE: webdoc/docs/library.md
================================================
# Using the JavaScript Mermaid Library
> _From version 1.1.0 of Mkdocs-Mermaid2_
## Introduction
By default, MkDocs-Mermaid2 automatically inserts the proper calls to
[the Mermaid.js library, according to the correct version](description.md/#insertion-of-the-javascript-library) (all-in one file, or ESM),
so that the diagrams are correctly interpreted.
You may, however, specify your own version, using to the
`javascript` parameter of Mermaid2,
in the [config file of MkDocs](https://mkdocs.readthedocs.io/en/859/user-guide/configuration/).
```yaml
plugins:
- search
- mermaid2:
javascript: https://unpkg.com/mermaid@10.4.0/dist/mermaid.esm.min.mjs
```
The files can be found on [unpkg](https://unpkg.com/browse/mermaid@10.4.0/) or [jsdelivr.com](https://www.jsdelivr.com/package/npm/mermaid).
Mkdocs-Mermaid2 will still insert the appropriate call to the JavaScript library
into the HTML page, according to the type of library (as all-in-one
javascript function, or [ESM module](description.md/#automatic-insertion-of-the-javascript-library)),
as well as the [initialization
sequence](description.md/#initialization-sequence).
To determine which version, it will use the extension:
File extension | Type | HTML Code
--- | -- |
`.js` | All-in-one javascript file (function) | `<script src="URL>"</script>`
`.mjs` | ESM Module | `<script type="module">import mermaid from "URL"</script>`
!!! Warning
In that case, the `version` parameter is ignored.
## Deploying Mermaid.js with the MkDocs website
In case you wish to use local version of the Mermaid.js library,
you can do so.
```yaml
plugins:
- search
- mermaid2:
javascript: js/mermaid.min.js
```
The path is relative to the docs directory of Mkdocs. In the above example:
mkdocs.yaml
├─ docs/
│ ├─ index.md
│ ├─ ...
│ ├─ js/
│ │ ├─ mermaid.min.js
The typical way to download the library from unpkg or cdn.jsdelivr.net,
changing the version number to determine the version you want
(here: **10.2.0**):
```
https://cdn.jsdelivr.net/npm/mermaid@10.2.0/dist/mermaid.min.js
```
!!! Note
No explicit call to `mermaid.initialize()` is required, since it is
automatically inserted by the plugin.
!!! Warning "Use the .js file"
The recommended way to do this, is to work with the file that contains
the traditional, all-in-one package that ends with `.js`.
It **may** be possible to use the full ESM module (with a reference to
the script that ends with `.mjs`). That would require, however,
downloading the whole directory structure. Using the `.mjs` file
on its ownlwill definitely **not** work, since there will be broken
links.
!!! Warning "Behavior in case of incorrect URL/no Internet access"
1. An incorrect URL will cause an error that aborts MkDocs.
2. If the address starts with http(s) and no Internet access
is available at time of compile, MkDocs-Mermaid will continue and issue
a WARNING. That behavior is for containers that do not
have necessarily have Internet access at compile time
(however, if you want to abort
in that case use the strict mode: `mkdocs build --strict`.
## Using `extra_javascript`
Mkdocs, by default, provides a standard mechanism for inserting a library into the
HTML pages, which relies on the
[parameter `extra_javascript` in the config file](https://mkdocs.readthedocs.io/en/859/user-guide/configuration/#extra_javascript).
!!! Warning "DEPRECATED in default cases"
As of version 1.1.0 of Mkdocs-Mermaid2,
using `extra_javascript` in the config file
as the default solution to explictly call
the Mermaid javascript library is **DEPRECATED**.
Use instead the standard config of Mkdocs-Mermaid2 parameters.
!!! Important "Failsafe mechanism"
However, `extra_javascript` was not kept only
as a backward compatibility measure.
Its purpose is now to be a **failsafe mechanism**.
**If Mkdocs-Mermaid2 detects a name of library that contains the
word `mermaid`, it will deactivate its own automatic/manual
insertion mecanism and fall back on the standard mechanism of MkDocs.**
You can (and possibly should) use `extra_javascript` mechanism,
if the standard defaults
of MkDocs-Plugin do not match your needs.
```yaml
extra_javascript:
- https://unpkg.com/mermaid@8.8.2/dist/mermaid.min.js
```
It still works for versions > 10:
```yaml
extra_javascript:
- https://unpkg.com/mermaid@10.4.0/dist/mermaid.min.js
```
or (if using a local version):
```yaml
extra_javascript:
- js/mermaid.min.js
```
(where the path is relative to the docs directory.)
!!! Note "Going 'full manual'?"
If you feel that you need the flexibility of the `extra_javascript`
parameter,
you might start to weigh the pros and cons of using MkDocs-Mermaid2
as a plugin.
You might want to go "full manual",
**and deactivate the Mkdocs-Mermaid2 plugin.**
Or on the contrary, if you are using the **Material theme**, you might consider
[using its default config for Mermaid](https://squidfunk.github.io/mkdocs-material/reference/diagrams/)
(if it works better for you).
!!! Warning "Workaround for versions of MkDocs < 1.5"
> _Versions of MkDocs < 1.5.0 were unable to call the ESM library._
The best solution is to call the `.js` file:
```yaml
extra_javascript:
- https://unpkg.com/mermaid@10.2.0/dist/mermaid.min.js
```
If you **really** want to use the ESM module,
you could declare a local script file:
```yaml
extra_javascript:
- js/mermaidloader.js
```
(where `js` is a subdirectory of the docs directory.)
`mermaidloader.js` must contains the code for the import statement:
```javascript
import mermaid from "https://unpkg.com/mermaid@10.0.2/dist/mermaid.esm.min.mjs"
```
================================================
FILE: webdoc/docs/superfences.md
================================================
# Using the mermaid2 with Superfences
## Introduction
[Superfences](https://facelessuser.github.io/pymdown-extensions/extensions/superfences/) is a markdown extension that allows a better management
of code blocks, particularly syntax highlighting for the different languages.
!!! Warning
Do not use the [codehilite](https://python-markdown.github.io/extensions/code_hilite/) markdown extension, as it is deprecated in this context.
Hence, for a Python code block:
```python
import foo.bar
```
It belongs to the PyMdown extension package (see [installation instructions](https://facelessuser.github.io/pymdown-extensions/installation/)) created
by [facelessuser](https://github.com/facelessuser).
!!! Danger "Caution with Superfences"
The problem is that if you activate Superfences, you will deactivate
automatically the display of Mermaid diagrams (they will simply be
color-highlighted), **unless** you specify an exception for those diagrams,
called a **custom_fence**.
Hence the code:
```mermaid
graph LR
hello --> world
world --> again
again --> hello
```
Will be highlighted instead of being displayed!
See the next paragraph, for how to do that.
!!! Important
The Superfences extension is **not** mandatory, its main purpose
is to allow highlighting in code blocks.
It is, however, [**recommended** for the Material theme](#usage-for-the-material-theme).
## Specifying the Mermaid custom fence
Hence, to speciy the custom fence in the configuration file:
```yaml
markdown_extensions:
...
- pymdownx.superfences:
# make exceptions to highlighting of code:
custom_fences:
- name: mermaid
class: mermaid
format: !!python/name:mermaid2.fence_mermaid
```
Each time a code block of `mermaid` type is found in the markdown,
then the code will **not** be highlighted, but transformed into a diagram.
This is done by the `fence_mermaid` function provided by mermaid2,
which encloses the Mermaid code
in the following way (in alignment with the plugin's policy):
<div class="mermaid">
...
</div>
!!! Note "Important"
1. For better results with the Material theme, use the `fence_mermaid_custom`
function (see below).
2. Do not use `fence_mermaid_custom` with themes other than Material, as
this will prevent the Mermaid diagrams from displaying.
3. Superfences is slightly more demanding with
HTML tags inside a mermaid diagram:
**take care to always close the HTML tags that require it**
(e.g. `<small>` must have its corresponding `</small>` tag).
Otherwise, the extension system will attempt to close those tags
and it will break the diagram.
## Usage for the Material theme
The [Material theme](https://squidfunk.github.io/mkdocs-material/), developed by [squidfunk](https://github.com/squidfunk), is designed out of the box
[so as to exploit the Mermaid.js library](https://squidfunk.github.io/mkdocs-material/reference/diagrams/).
A beautiful feature is that the color theme will be reflected
on the mermaid diagram, with a much better rendering of the diagrams
according to the palette.
It will also use proper colors for Mermaid diagrams if you use a **dark mode**
in the theme (`scheme: slate`) e.g., in the Config file:
```yaml
theme:
# name: readthedocs
name: material
language: en
palette:
scheme: slate
primary: red
accent: pink
```
!!! Important "Recommended usage with Material theme"
This requires, however,
1. The use of the Superfences extension.
2. To use the default `<pre class="mermaid"><code>` representation, and
not the `<div class="mermaid">` representation used by mkdocs-mermaid2.
**This is achieved by using the `fence_mermaid_custom` function.**
Hence in the configuration file:
```yaml
markdown_extensions:
...
- pymdownx.superfences:
# make exceptions to highlighting of code:
custom_fences:
- name: mermaid
class: mermaid
format: !!python/name:mermaid2.fence_mermaid_custom
```
================================================
FILE: webdoc/docs/tips.md
================================================
# Tips and Tricks
## Advanced Mermaid Functions
### Setting the security level to "loose"
To access the following functions, you need to relax mermaid's security level,
([since version 8.2](https://mermaid-js.github.io/mermaid/#/?id=special-note-regarding-version-82)).
!!! Caution
This requires you, of course, to take the responsibility
for the security of the diagram source.
If that is OK with you, you can set the argument in the configuration of the
plugin:
```yaml
- mermaid2:
arguments:
securityLevel: 'loose'
```
### Formatting text in diagrams
> To enable this function, you need to [relax mermaid's security level to 'loose'](#setting-the-security-level-to-loose).
You may use HTML in the diagram.
!!! Caution
This is guaranteed to work with Mermaid 8.6.4, but
does not work e.g. on 8.7.0.
It may not work on more recent versions.
Use HTML formatting:
```mermaid
graph LR
hello["<b>Hello</b>"] --> world["<big><i>World</i></big>"]
world --> mermaid[mermaid web site]
```
```mermaid
graph LR
hello["<b>Hello</b>"] --> world["<big><i>World</i></big>"]
world --> mermaid[mermaid web site]
```
Use this in the config file:
```yaml
extra_javascript:
- https://unpkg.com/mermaid@8.6.4/dist/mermaid.min.js
```
### Adding Hyperlinks to a Diagram
> To enable this function, you need to [relax mermaid's security level to 'loose'](#setting-the-security-level-to-loose).
=== "Mermaid.js >~ 8.5.0"
Use the **click** directive in the language (for more information,
see [Interaction](https://mermaid-js.github.io/mermaid/#/flowchart?id=interaction) on the official mermaid website).
```mermaid
graph LR
hello --> world
world --> mermaid[mermaid web site]
click mermaid "https://mermaid-js.github.io/mermaid" "Website"
```
```mermaid
graph LR
hello --> world
world --> mermaid[mermaid web site]
click mermaid "https://mermaid-js.github.io/mermaid" "Website"
```
=== "Mermaid.js < ~ 8.5.0"
It is possible to add hyperlinks to a diagram, e.g.:
```
box1[An <b>important</b> <a href="https://google.com">link</a>]
```
## Using variables and macros in diagrams (MkDocs-Macros)
### Variables
What if your diagrams contain a repetitive string, such as the URL of a website
[in your hyperlinks](#adding-hyperlinks-to-a-diagram)?
Instead of writing:
```
graph TD;
Platform-->Gaming;
click Gaming "http://127.0.0.1:8000/Gaming/";
```
You might want to use a **variable**:
```
graph TD;
Platform-->Gaming;
click Gaming "{{ my_website }}/Gaming/";
```
You define that variable in your project's config file (`mkdocs.yml`):
```yaml
extra:
my_website: http://127.0.0.1:8000
```
In this way, you will be able to change that value wherever it appears in the pages,
simply by modifying the value in the config file.
To do that, you would have to use the [Mkdocs-Macros plugin](https://mkdocs-macros-plugin.readthedocs.io/).
This requires [installing the plugin](https://mkdocs-macros-plugin.readthedocs.io/en/latest/#standard-installation), and declaring it in the config file.
!!! Caution
Variables are **not** part of the Mermaid specification. The Macros plugin simply expands the variables in the
Markdown page, so that the result is a standard Mermaid diagram.
Declare the plugins in the config file, in that order:
```yaml
plugins:
- search
- macros
- mermaid2
```
!!! Tip "Uses of variables"
You can use an MkDocs-Macros variable to represent _any_ string that you need to repeat
in Mermaid diagrams, or that could change (over time, or because you have two possible configs).
Variables can be used in any part of a page, inside or outside of Mermaid diagrams.
MkDocs-Macros and Mkdocs-Mermaid2 are two plugins that work very well together.
Read the documentation of [MkDocs-Macros](https://mkdocs-macros-plugin.readthedocs.io/),
to discover all its possibilities!
### Using macros to generate Mermaid code
If you can program in Python, you could go further than that with MkDocs-Macros:
you could use a Python module (`main.py`) to define
[**macros** (functions)](https://mkdocs-macros-plugin.readthedocs.io/en/latest/macros/)
that produce hyperlinks or pieces of diagrams from data,
or even complete diagrams from a source file.
For example the macro `make_choice()` would create a full diagram from three components.
```python
def define_env(env):
@env.macro
def make_choice(start, choice1, choice2):
"""
Generate a Mermaid decision diagram with two choices from a starting point,
within a fenced code block.
"""
lines = [
"```mermaid",
"graph TD",
f" {start} -->|first| {choice1}",
f" {start} -->|second| {choice2}",
"```"
]
return "\n".join(lines)
```
Then you could write, in your markdown page:
```markdown
{{ make_choice("Start", "OptionA", "OptionB") }}
```
Which would be translated into:
```mermaid
graph TD
Start -->|first| OptionA
Start -->|second| OptionB
```
And then rendered by your browser as:
```mermaid
graph TD
Start -->|first| OptionA
Start -->|second| OptionB
```
## Switching between light and dark mode
### Auto-configure dark mode based on Host OS
Using a combination of the unquote (`^`) functionality of this plugin and the
[prefers-color-scheme](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme)
CSS media feature, one can have the plugin automatically enable dark mode.
```yaml
plugins:
- search
- mermaid2:
arguments:
theme: |
^(window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) ? 'dark' : 'light'
```
This works well with the `scheme: preference` option in
[mkdocs-material](https://squidfunk.github.io/mkdocs-material/) and referenced in [their documentation](https://squidfunk.github.io/mkdocs-material/setup/changing-the-colors/#color-scheme).
### Material Theme: Switching on the fly between light and dark mode
The Material theme for MkDocs allows [toggling between colors](https://squidfunk.github.io/mkdocs-material/setup/changing-the-colors/#color-palette-toggle).
Unfortunately the Mermaid diagram will not switch out of the box from light to
dark or vice versa.
This solution is similar to [switch the theme according to the OS color](#auto-configure-dark-mode-based-on-host-os),
though that earlier, simpler solution cannot toggle dynamically.
A workable solution has been proposed by [elgalu](https://github.com/elgalu)
(for more information see [Issue 39](https://github.com/fralau/mkdocs-mermaid2-plugin/issues/39)).
**`mkdocs.yml`**
(The palette is an example, where primary color, accent, icons, toggle message, etc. can be adapted to your needs.)
```yaml
theme:
name: material
# https://squidfunk.github.io/mkdocs-material/setup/changing-the-colors/#color-palette
palette:
- media: "(prefers-color-scheme: light)"
scheme: default
primary: indigo
accent: light-blue
toggle:
icon: material/toggle-switch-off-outline
name: Switch to dark mode
- media: "(prefers-color-scheme: dark)"
scheme: slate
primary: black
accent: deep orange
toggle:
icon: material/toggle-switch
name: Switch to light mode
# https://facelessuser.github.io/pymdown-extensions/extensions/superfences/
pymdownx.superfences:
custom_fences:
- name: mermaid
class: mermaid
format: !!python/name:mermaid2.fence_mermaid
plugins:
- mermaid2:
arguments:
# test if its __palette_1 (dark) or __palette_2 (light)
# for mkdocs-material >=8.0.0
theme: |
^(JSON.parse(__md_get("__palette").index == 1)) ? 'dark' : 'light'
# for mkdocs-material <8.0.0
# ^(JSON.parse(window.localStorage.getItem(__prefix('__palette'))).index == 1) ? 'dark' : 'light'
extra_javascript:
- extra/refresh_on_toggle_dark_light.js
```
> The caret operator (`^`) means "unquote". It is used here to insert Javascript code into the initialization code of `mermaid.initialize()`.
**`docs/extra/refresh_on_toggle_dark_light.js`**
To avoid refreshing the page after switching between dark/light modes so that Mermaid diagram can be updated, two listeners
must be installed, which are instructed to reload the page, whenever
they detect a change.
That is the function of the additional script
(`refresh_on_toggle_dark_light.js`):
```javascript
var paletteSwitcher1 = document.getElementById("__palette_1");
var paletteSwitcher2 = document.getElementById("__palette_2");
paletteSwitcher1.addEventListener("change", function () {
location.reload();
});
paletteSwitcher2.addEventListener("change", function () {
location.reload();
});
```
================================================
FILE: webdoc/docs/troubleshooting.md
================================================
## Important notice
If mermaid diagrams are not displayed correctly, or not displayed at all
**read this section first**!
## Mermaid diagram is not displayed (or displayed incorrectly)
!!! Tip
To start with, use a simple diagram that you know is syntactically correct.
e.g.
```mermaid
graph TD
A[Client] --> B[Load Balancer]
B --> C[Server01]
B --> D[Server02]
```
```mermaid
graph TD
A[Client] --> B[Load Balancer]
B --> C[Server01]
B --> D[Server02]
```
!!! Notes
1. Every diagram should start with a valid preamble, e.g. `graph TD`.
2. In case of doubt, you may want to test your diagram in the
[Mermaid Live Editor](https://mermaid-js.github.io/mermaid-live-editor)
3. Note, however, that the Mermaid Live Editor **does not
support loose mode** (with HTML code in the mermaid code).
### Seeing an error message at the place of the diagram?
In recent versions of the javascript library (> 8.6.0), a pretty
error message is displayed in case of incorrect syntax:

!!! Note
In earlier versions, the library displayed nothing, which
could be confusing.
If you see the error message, it is at least an indication that
the mermaid javascript library was called.
### The mermaid source code appears as-is (not read)?
In that case, the javascript library was probably not called.
!!! Tip
**Examine the HTML code produced in the page and see the next questions.**
### Using superfences, but no diagram is displayed?
If you are using the superfences extension, but you see the source
code, you probably forgot to declare the custom_fences, or declared the wrong
one.
See more explanations under [Declaring the superfences extension](superfences.md#specifying-the-mermaid-custom-fence)
!!! Tip
**Examine the HTML code produced in the page and see the next questions.**
### Is mkdocs' version up to date (>= 1.1) ?
!!! Note
As an absolute minimum, you should use a version of mkdocs > 1.1.
A version >= 1.5 is recommended.
To determine the version, use `mkdocs -V`.
To update mkdocs:
pip install mkdocs --upgrade
Or, if you cloned the repo:
python setup.py install
### Is the javascript library properly called?
In order to work, the proper javascript library must called from
the html page (by default, the call is inserted automatically).
Control the link used in the HTML page generated, e.g.:
```HTML
<script type="module">import mermaid from "https://unpkg.com/mermaid@10.0.2/dist/mermaid.esm.min.mjs"</script>
```
### A certain type of diagram (e.g. mindmap, etc.) is not displayed, or the syntax is incorrectly interpreted?
Check the version of the javascript mermaid library you are using (it's indicated
in the error message; as a last resort, check in the html page).
You can [change the library version if needed](index.md/#specifying-the-version-of-the-mermaid-library).
### The arguments in the config file (color, etc.) do not work
For example, the following specification ([see description](index.md/#other-themes)) does not work:
```yaml
plugins:
- search
- mermaid2:
version: '10.1.0'
arguments:
theme: 'dark'
themeVariables:
primaryColor: '#BB2528'
primaryTextColor: '#fff'
primaryBorderColor: '#7C0000'
lineColor: '#F8B229'
secondaryColor: '#006100'
tertiaryColor: '#fff'
```
Due to the change of javascript library format as of mermaid.js **as of
version 10.0**, this did not work any more (but it worked for lower versions).
This was fixed in version 1.0.8 of the mkdocs-mermaid2 library
([see github issue for a full description](https://github.com/mermaid-js/mermaid/issues/4672)).
**Upgrade mkdocs-mermaid2 to the most recent version.**
### What if nothing worked?
1. Check the [test cases](https://github.com/fralau/mkdocs-mermaid2-plugin/tree/1ab72b5c6a5acf35cc702b7d85019b08678a52e2/test) on the github repository
and try to run them on your machine;
start with the `simple` website.
2. Open a question on the [discussion page for the project](https://github.com/fralau/mkdocs-mermaid2-plugin/discussions).
## Explicit calls of the Mermaid library with `extra_javascript`
> For reference information see the [`extra_javascript` section](library.md/#using-extra_javascript)
> in the JavaScript page.
!!! Tip "Easy Fix"
**Upgrade Mkdocs and Mkdocs-Macros to the latest
version and stop using `extra_javascript`. Use the [`javascript` parameter instead](library.md)**.
Otherwise, read on.
!!! Warning "Important"
If you [specify the version number in the config file](index.md/#specifying-the-version-of-the-mermaid-library),
then the mkdocs-mermaid2 will insert the correct calls for you.
Remember that explicit calls to the Mermaid.js
(through `extra_javascript` in the config file) are **optional**
and are considered a **hack** (failsafe) mecanism
for cases when the default procedure doesn't work.
**As of version 1.1 of Mkdocs-Mermaid2 the use of `extra_javascript` is DEPRECATED, as a default solution.**
Use the [`javascript` parameter instead](library.md).
### Issues with versions
**Mermaid.js**: Above version 10.0.0, [the official format for the Mermaid library is ESM](https://github.com/mermaid-js/mermaid/releases/tag/v10.0.0).
**MkDocs**: Under version 1.5.0, the `extra_javascript` directive in the config
file (`mkdocs.yml`) does not process ESM libraries correctly.
### Version of Mermaid.js < 10
All versions of mkdocs manage correctly the traditional call to javascript
code.
``` html
<script src="https://unpkg.com/mermaid@8.8.2/dist/mermaid.min.js">
</script>
```
You _may_ specify the mermaid library explicitly in the config file,
as long as it is call mermaid (independently of extension):
```yaml
extra_javascript:
- https://unpkg.com/mermaid@8.8.2/dist/mermaid.min.js
```
This will be translated in the final HTML page as:
```html
<script src="https://unpkg.com/mermaid@8.8.2/dist/mermaid.min.js">
```
### Version of Mermaid.js >= 10
As an ESM javascript library, Mermaid.js requires an `import` statement.
``` html
<script type="module">
import mermaid from "https://unpkg.com/mermaid@10.0.2/dist/mermaid.esm.min.mjs"
</script>
```
=== "MkDocs < 1.5.0"
Versions of MkDocs < 1.5.0 translate the call into `<script src=...>`
in all cases, and this is incorrect.
**Upgrade to MkDocs >= 1.5.0 and this should fix the problem!**
Otherwise, as a workaround you could declare a local script file:
```yaml
extra_javascript:
- js/mermaidloader.js
```
Where `js` is a subdirectory of the document directory (`docs`).
The file contains the code for the import statement:
```javascript
import mermaid from "https://unpkg.com/mermaid@10.0.2/dist/mermaid.esm.min.mjs"
```
=== "MkDocs >= 1.5.0"
MkDocs correctly recognizes this case and will create the import statement.
**Treat this case normally.**
```yaml
extra_javascript:
- https://unpkg.com/mermaid@10.0.2/dist/mermaid.esm.min.mjs
```
!!! Warning
The "traditional", min.js packages are still unoficially available.
Even though mkdocs-mermaid2 will not insert them by default,
you can use them, at your own peril.
```yaml
extra_javascript:
- https://cdn.jsdelivr.net/npm/mermaid@10.1.0/dist/mermaid.min.js
```
For some reason, they require the `mermaid2.fence_mermaid` function
in order to work. It means that with the Material theme,
your diagrams will not inherit the theme's color
([see more information on this subject](superfences.md/#usage-for-the-material-theme)).
## Other issues
### Rich text diagrams, or links are not displayed properly?
1. As a first step, [set the security level to 'loose'](tips.md/#setting-the-security-level-to-loose).
2. Make sure you use a compatible version of the javascript library
(8.6.4, 8.8.0, ~~8.7.0~~). In principle, the version used
by the plugin is compatible (see instructions to
[change the version](index.md/#specifying-the-version-of-the-mermaid-library)).
### With pymdownx.details, diagrams in collapsed elements are not displayed?
**This fix is experimental (it has been tested once and it worked).**
If you declared `pymdownx.details` in `config.yml`
(under `markdown_extensions`), you may notice that a diagram will not
display correctly in that case:
```markdown
???- note "Collapsed"
```mermaid
graph TD
A[Client] --> B[Load Balancer]
```
This is additional text.
```
Depending on the browser, you may have a dot, or nothing, etc.
In that case, use the following declaration in your `markdown_extensions`:
```yaml
- pymdownx.superfences:
# make exceptions to highlighting of code:
custom_fences:
- name: mermaid
class: mermaid
format: !!python/name:mermaid2.fence_mermaid_custom
```
The use of this function will trigger a custom behavior, with two effects:
1. It will create custom HTML tags, `<pre class='mermaid'><code>`.
2. It will deactivate the auto-load.
You **must** then use a special custom javascript loader for the diagram,
developed by [facelessuser](https://github.com/facelessuser):
1. Copy the code from
the [website of PyMdown Extension](https://facelessuser.github.io/pymdown-extensions/extras/mermaid/#putting-it-all-together).
2. Paste it in a file in your project: `docs/js/loader.js`
3. Declare this script in the `config.yml` file:
```yaml
extra_javascript:
- js/loader.js
```
## Using the mermaid2.dumps() function
As a bonus, mkdocs-mermaid2 exports the Python function `dumps()`
which produces a string
describing a [JavaScript object](https://javascript.info/object).
It can be used to help generate JavaScript code from Python
(this is typically needed, when generating an HTML page that contains
JavaScript).
A JavaScript object is not exactly the same as a JSON object.
The reason why this why introduced is that sometimes one needs to produce
a key/value pair as:
```JavaScript
foo = MyFunctioName
```
where the value is _not_ a string but an identifier (in this case:
a function name).
Here is an example:
```python
import mermaid2
obj = { "hello": "world",
"barbaz": "^bazbar",
"foo": {"bar": 2},
"bar": True}
s = mermaid2.dumps(obj)
```
The purpose of the caret is to specify that the value should be
an identifier and not a string. The result will be:
```JavasScript
{
hello: "world",
barbaz: bazbar,
foo: {
bar: 2
},
bar: true
}
```
================================================
FILE: webdoc/extra_requirements.txt
================================================
mkdocs-mermaid2-plugin
mkdocs-material>=6.2
================================================
FILE: webdoc/mkdocs.yml
================================================
site_name: MkDocs-Mermaid2
site_description: Mkdocs plugin for mermaid diagrams
docs_dir: docs # indispensable or readthedocs will fail
theme:
# name: readthedocs
name: material
icon:
logo: fontawesome/solid/diagram-project
language: en
palette:
# scheme: slate
primary: red
accent: pink
repo_url: https://github.com/fralau/mkdocs-mermaid2-plugin
edit_uri: edit/master/webdoc/docs/
copyright: © Laurent Franceschetti, 2024. This work is licensed under CC BY-SA 4.0.
nav:
- How to get started: index.md
- Detailed description: description.md
- Superfences: superfences.md
- Using the Mermaid library: library.md
- Tips and tricks: tips.md
- troubleshooting.md
- How to contribute: contribute.md
markdown_extensions:
- attr_list
- admonition
- footnotes
- pymdownx.superfences:
# make exceptions to highlighting of code:
custom_fences:
- name: mermaid
class: mermaid
format: !!python/name:mermaid2.fence_mermaid_custom
- pymdownx.tabbed:
alternate_style: true
# - attr_list
# - pymdownx.emoji:
# emoji_index: !!python/name:materialx.emoji.twemoji
# emoji_generator: !!python/name:materialx.emoji.to_svg
plugins:
- search
- mermaid2:
arguments:
securitylevel: loose
version: '10.9.0'
gitextract_rndg2_6l/
├── .github/
│ └── workflows/
│ └── greetings.yml
├── .gitignore
├── .readthedocs.yml
├── CHANGELOG.md
├── LICENSE
├── MANIFEST.in
├── README.md
├── README_old.md
├── mermaid2/
│ ├── __init__.py
│ ├── fence.py
│ ├── plugin.py
│ ├── pyjs.py
│ └── util.py
├── pyproject.toml
├── setup.py
├── test/
│ ├── __init__.py
│ ├── extra_javascript/
│ │ ├── docs/
│ │ │ ├── index.md
│ │ │ └── second.md
│ │ └── mkdocs.yml
│ ├── fixture.py
│ ├── http_lib/
│ │ ├── docs/
│ │ │ ├── index.md
│ │ │ └── second.md
│ │ └── mkdocs.yml
│ ├── local_lib/
│ │ ├── docs/
│ │ │ ├── index.md
│ │ │ └── second.md
│ │ └── mkdocs.yml
│ ├── material/
│ │ ├── __init__.py
│ │ ├── docs/
│ │ │ ├── index.md
│ │ │ ├── js/
│ │ │ │ └── extra.js
│ │ │ └── second.md
│ │ ├── mkdocs.yml
│ │ └── test_site.py
│ ├── medium/
│ │ ├── docs/
│ │ │ ├── index.md
│ │ │ ├── js/
│ │ │ │ └── extra.js
│ │ │ └── second.md
│ │ └── mkdocs.yml
│ ├── simple/
│ │ ├── __init__.py
│ │ ├── docs/
│ │ │ ├── index.md
│ │ │ ├── js/
│ │ │ │ └── extra.js
│ │ │ └── second.md
│ │ ├── mkdocs.yml
│ │ └── test_site.py
│ ├── simple_format/
│ │ ├── docs/
│ │ │ ├── index.md
│ │ │ ├── js/
│ │ │ │ └── extra.js
│ │ │ └── second.md
│ │ └── mkdocs.yml
│ ├── simple_pre_10/
│ │ ├── docs/
│ │ │ ├── index.md
│ │ │ ├── js/
│ │ │ │ └── extra.js
│ │ │ └── second.md
│ │ └── mkdocs.yml
│ └── superfences/
│ ├── __init__.py
│ ├── docs/
│ │ ├── index.md
│ │ ├── js/
│ │ │ └── loader.js
│ │ └── second.md
│ ├── mkdocs.yml
│ └── test_site.py
├── update_pypi.sh
└── webdoc/
├── docs/
│ ├── contribute.md
│ ├── description.md
│ ├── index.md
│ ├── library.md
│ ├── superfences.md
│ ├── tips.md
│ └── troubleshooting.md
├── extra_requirements.txt
└── mkdocs.yml
SYMBOL INDEX (46 symbols across 14 files)
FILE: mermaid2/fence.py
function fence_mermaid (line 14) | def fence_mermaid(source, language, css_class, options, md,
FILE: mermaid2/plugin.py
class MarkdownMermaidPlugin (line 37) | class MarkdownMermaidPlugin(BasePlugin):
method full_config (line 55) | def full_config(self):
method mermaid_args (line 63) | def mermaid_args(self):
method mermaid_version (line 70) | def mermaid_version(self) -> str:
method mermaid_major_version (line 81) | def mermaid_major_version(self) -> int:
method extra_javascript (line 93) | def extra_javascript(self) -> str:
method javascript (line 126) | def javascript(self) -> str:
method activate_custom_loader (line 150) | def activate_custom_loader(self) -> bool:
method on_config (line 193) | def on_config(self, config):
method on_post_page (line 222) | def on_post_page(self, output_content, config, page, **kwargs):
FILE: mermaid2/pyjs.py
function dumps (line 17) | def dumps(obj:Any,
FILE: mermaid2/util.py
function trace (line 35) | def trace(*args, level:str='info'):
function info (line 56) | def info(*args) -> str:
function libname (line 66) | def libname(lib:str) -> str:
function url_exists (line 77) | def url_exists(url:str, local_base_dir:str='') -> bool:
FILE: test/fixture.py
function extract_url (line 18) | def extract_url(s:str) -> str|None:
function get_last_version (line 28) | def get_last_version(mermaid_url:str) -> version.Version:
function assert_string_contains (line 36) | def assert_string_contains(txt:str, items:list) -> bool:
class Mermaid2Page (line 52) | class Mermaid2Page(MkDocsPage):
method mermaid_script (line 59) | def mermaid_script(self) -> str:
method js_version (line 105) | def js_version(self) -> version.Version:
class Mermaid2DocProject (line 117) | class Mermaid2DocProject(DocProject):
method plugin_version (line 121) | def plugin_version(self) -> version.Version|None:
method pages (line 131) | def pages(self) -> dict[Mermaid2Page]:
FILE: test/material/docs/js/extra.js
function myMermaidCallbackFunction (line 2) | function myMermaidCallbackFunction(id) {
FILE: test/material/test_site.py
function test_pages (line 19) | def test_pages():
FILE: test/medium/docs/js/extra.js
function myMermaidCallbackFunction (line 2) | function myMermaidCallbackFunction(id) {
FILE: test/simple/docs/js/extra.js
function myMermaidCallbackFunction (line 2) | function myMermaidCallbackFunction(id) {
FILE: test/simple/test_site.py
function test_pages (line 18) | def test_pages():
FILE: test/simple_format/docs/js/extra.js
function myMermaidCallbackFunction (line 2) | function myMermaidCallbackFunction(id) {
FILE: test/simple_pre_10/docs/js/extra.js
function myMermaidCallbackFunction (line 2) | function myMermaidCallbackFunction(id) {
FILE: test/superfences/docs/js/loader.js
function _typeof (line 1) | function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol ===...
function _classCallCheck (line 6) | function _classCallCheck(instance, Constructor) {
function _inherits (line 12) | function _inherits(subClass, superClass) {
function _getPrototypeOf (line 27) | function _getPrototypeOf(o) {
function _setPrototypeOf (line 34) | function _setPrototypeOf(o, p) {
function _isNativeReflectConstruct (line 43) | function _isNativeReflectConstruct() {
function _construct (line 56) | function _construct(Parent, args, Class) {
function _isNativeFunction (line 73) | function _isNativeFunction(fn) {
function _wrapNativeSuper (line 77) | function _wrapNativeSuper(Class) {
function _assertThisInitialized (line 111) | function _assertThisInitialized(self) {
function _possibleConstructorReturn (line 119) | function _possibleConstructorReturn(self, call) {
function _createSuper (line 127) | function _createSuper(Derived) {
function MermaidDiv (line 174) | function MermaidDiv() {
FILE: test/superfences/test_site.py
function test_pages (line 19) | def test_pages():
Condensed preview — 66 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (153K chars).
[
{
"path": ".github/workflows/greetings.yml",
"chars": 359,
"preview": "name: Greetings\n\non: [pull_request, issues]\n\njobs:\n greeting:\n runs-on: ubuntu-latest\n steps:\n - uses: actions"
},
{
"path": ".gitignore",
"chars": 1213,
"preview": "# Byte-compiled / optimized / DLL files\n__pycache__/\n*.py[cod]\n*$py.class\n\n# C extensions\n*.so\n\n# Distribution / packagi"
},
{
"path": ".readthedocs.yml",
"chars": 762,
"preview": "# .readthedocs.yml\n# Read the Docs configuration file\n# See https://docs.readthedocs.io/en/stable/config-file/v2.html fo"
},
{
"path": "CHANGELOG.md",
"chars": 1718,
"preview": "# Changelog: Mkdocs-Mermaid2\n\nAll notable changes to this project will be documented in this file.\n\nThe format is based "
},
{
"path": "LICENSE",
"chars": 1079,
"preview": "MIT License\n\nCopyright (c) 2018 PuGong -- 2020, others\n\nPermission is hereby granted, free of charge, to any person obta"
},
{
"path": "MANIFEST.in",
"chars": 36,
"preview": "include README.md\ninclude LICENSE.md"
},
{
"path": "README.md",
"chars": 4831,
"preview": "<div align=\"center\">\n\n# Mkdocs-Mermaid2\n\n\n[](https:/"
},
{
"path": "README_old.md",
"chars": 27663,
"preview": "# mkdocs-mermaid2-plugin\n\n\n**THIS IS AN OLD VERSION, KEPT HERE FOR REFERENCE**\n\n[Use the documentation on ReadTheDocs](h"
},
{
"path": "mermaid2/__init__.py",
"chars": 213,
"preview": "\"Exports of mermaid2\"\n\n# export the dumps function (for producing a JS object)\nfrom .pyjs import dumps\n\n# export the fen"
},
{
"path": "mermaid2/fence.py",
"chars": 1982,
"preview": "\"\"\"\nSpecial fence for PyMdown Extensions Superfences\nSee: https://facelessuser.github.io/pymdown-extensions/extensions/s"
},
{
"path": "mermaid2/plugin.py",
"chars": 12396,
"preview": "\"\"\"\nMain plugin module for mermaid2\n\"\"\"\n\nimport os\n\n\nfrom mkdocs.plugins import BasePlugin\nfrom mkdocs.config.config_opt"
},
{
"path": "mermaid2/pyjs.py",
"chars": 3087,
"preview": "\"\"\"\nWriter for JavaScript objects\n(not JSON syntax)\n\nhttps://stackoverflow.com/questions/3975859/what-are-the-difference"
},
{
"path": "mermaid2/util.py",
"chars": 2432,
"preview": "\"\"\"\nUtilities for mermaid2 module\n\"\"\"\nimport os\nimport requests\nimport logging\nfrom packaging.version import Version\n\nim"
},
{
"path": "pyproject.toml",
"chars": 1360,
"preview": "[project]\nname = \"mkdocs-mermaid2-plugin\"\n\n# This version number is the REFERENCE for the rest of the project,\n# particu"
},
{
"path": "setup.py",
"chars": 259,
"preview": "\"\"\"\nInstallation using setup.py is no longer supported.\nUse `python -m pip install .` instead.\n\"\"\"\n\nfrom setuptools impo"
},
{
"path": "test/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "test/extra_javascript/docs/index.md",
"chars": 512,
"preview": "# Mermaid test (simple)\n\n## Mermaid usual\nThis is a test of Mermaid:\n\n```mermaid\ngraph TD\n hello --> world\n world "
},
{
"path": "test/extra_javascript/docs/second.md",
"chars": 266,
"preview": "# Second page\nTesting special cases\n\n## Wrong diagram\n\n```mermaid\ngraph FG\nA[Client] \n```\n\n## Correct\n\n```mermaid\ngraph "
},
{
"path": "test/extra_javascript/mkdocs.yml",
"chars": 323,
"preview": "site_name: Mermaid test (simple, extra_javascript)\nsite_description: Test for mermaid\ndocs_dir: docs # indispensable or "
},
{
"path": "test/fixture.py",
"chars": 4329,
"preview": "\"\"\"\nSpecific for MkDocs Projects\n\n(C) Laurent Franceschetti 2024\n\"\"\"\n\nimport re\nimport requests\n\nfrom super_collections "
},
{
"path": "test/http_lib/docs/index.md",
"chars": 512,
"preview": "# Mermaid test (simple)\n\n## Mermaid usual\nThis is a test of Mermaid:\n\n```mermaid\ngraph TD\n hello --> world\n world "
},
{
"path": "test/http_lib/docs/second.md",
"chars": 266,
"preview": "# Second page\nTesting special cases\n\n## Wrong diagram\n\n```mermaid\ngraph FG\nA[Client] \n```\n\n## Correct\n\n```mermaid\ngraph "
},
{
"path": "test/http_lib/mkdocs.yml",
"chars": 377,
"preview": "site_name: Mermaid test (simple, with local specified library)\nsite_description: Test for mermaid\ndocs_dir: docs # indis"
},
{
"path": "test/local_lib/docs/index.md",
"chars": 512,
"preview": "# Mermaid test (simple)\n\n## Mermaid usual\nThis is a test of Mermaid:\n\n```mermaid\ngraph TD\n hello --> world\n world "
},
{
"path": "test/local_lib/docs/second.md",
"chars": 266,
"preview": "# Second page\nTesting special cases\n\n## Wrong diagram\n\n```mermaid\ngraph FG\nA[Client] \n```\n\n## Correct\n\n```mermaid\ngraph "
},
{
"path": "test/local_lib/mkdocs.yml",
"chars": 331,
"preview": "site_name: Mermaid test (simple, with local specified library)\nsite_description: Test for mermaid\ndocs_dir: docs # indis"
},
{
"path": "test/material/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "test/material/docs/index.md",
"chars": 520,
"preview": "# Mermaid test (Material theme)\n\n## Mermaid usual\nThis is a test of Mermaid:\n\n```mermaid\ngraph TD\n hello --> world\n "
},
{
"path": "test/material/docs/js/extra.js",
"chars": 735,
"preview": "// js/extra.js\nfunction myMermaidCallbackFunction(id) {\n var d = new Date();\n var now = d.toLocaleTimeString();\n "
},
{
"path": "test/material/docs/second.md",
"chars": 266,
"preview": "# Second page\nTesting special cases\n\n## Wrong diagram\n\n```mermaid\ngraph FG\nA[Client] \n```\n\n## Correct\n\n```mermaid\ngraph "
},
{
"path": "test/material/mkdocs.yml",
"chars": 314,
"preview": "site_name: Mermaid test (Material theme)\nsite_description: Test for mermaid\ndocs_dir: docs # indispensable or readthedoc"
},
{
"path": "test/material/test_site.py",
"chars": 1842,
"preview": "\"\"\"\nTesting the project\n\nMaterial theme, otherwise normal\n\n(C) Laurent Franceschetti 2024\n\"\"\"\n\n\nimport pytest\n\nfrom mkdo"
},
{
"path": "test/medium/docs/index.md",
"chars": 1200,
"preview": "# Mermaid test (medium, with arguments)\n\n## Mermaid usual\nThis is a test of Mermaid:\n\n```mermaid\ngraph TD\n hello --> "
},
{
"path": "test/medium/docs/js/extra.js",
"chars": 194,
"preview": "// js/extra.js\nfunction myMermaidCallbackFunction(id) {\n var d = new Date();\n var now = d.toLocaleTimeString();\n "
},
{
"path": "test/medium/docs/second.md",
"chars": 196,
"preview": "# Second page\nTesting special cases\n\n## Wrong diagram\n\n```mermaid\ngraph FG\nA[Client] \n```\n\n## Correct diagram\n\n```mermai"
},
{
"path": "test/medium/mkdocs.yml",
"chars": 817,
"preview": "site_name: Mermaid test (medium, arguments)\nsite_description: Test for mermaid\ndocs_dir: docs # indispensable or readthe"
},
{
"path": "test/simple/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "test/simple/docs/index.md",
"chars": 512,
"preview": "# Mermaid test (simple)\n\n## Mermaid usual\nThis is a test of Mermaid:\n\n```mermaid\ngraph TD\n hello --> world\n world "
},
{
"path": "test/simple/docs/js/extra.js",
"chars": 735,
"preview": "// js/extra.js\nfunction myMermaidCallbackFunction(id) {\n var d = new Date();\n var now = d.toLocaleTimeString();\n "
},
{
"path": "test/simple/docs/second.md",
"chars": 266,
"preview": "# Second page\nTesting special cases\n\n## Wrong diagram\n\n```mermaid\ngraph FG\nA[Client] \n```\n\n## Correct\n\n```mermaid\ngraph "
},
{
"path": "test/simple/mkdocs.yml",
"chars": 283,
"preview": "site_name: Mermaid test (simple, default theme)\nsite_description: Test for mermaid\ndocs_dir: docs # indispensable or rea"
},
{
"path": "test/simple/test_site.py",
"chars": 1483,
"preview": "\"\"\"\nTesting the project\n\n(C) Laurent Franceschetti 2024\n\"\"\"\n\n\nimport pytest\n\nfrom mkdocs_test import DocProject\n\n\nfrom t"
},
{
"path": "test/simple_format/docs/index.md",
"chars": 541,
"preview": "# Mermaid test (simple, with formatting of diagrams)\n\n## Mermaid usual\nThis is a test of Mermaid:\n\n```mermaid\ngraph TD\n "
},
{
"path": "test/simple_format/docs/js/extra.js",
"chars": 735,
"preview": "// js/extra.js\nfunction myMermaidCallbackFunction(id) {\n var d = new Date();\n var now = d.toLocaleTimeString();\n "
},
{
"path": "test/simple_format/docs/second.md",
"chars": 266,
"preview": "# Second page\nTesting special cases\n\n## Wrong diagram\n\n```mermaid\ngraph FG\nA[Client] \n```\n\n## Correct\n\n```mermaid\ngraph "
},
{
"path": "test/simple_format/mkdocs.yml",
"chars": 572,
"preview": "site_name: Mermaid test (simple, with formatting)\nsite_description: Test for mermaid\ndocs_dir: docs # indispensable or r"
},
{
"path": "test/simple_pre_10/docs/index.md",
"chars": 302,
"preview": "# Mermaid test (simple)\n\n## Mermaid usual\nThis is a test of Mermaid:\n\n```mermaid\ngraph TD\n hello --> world\n world "
},
{
"path": "test/simple_pre_10/docs/js/extra.js",
"chars": 735,
"preview": "// js/extra.js\nfunction myMermaidCallbackFunction(id) {\n var d = new Date();\n var now = d.toLocaleTimeString();\n "
},
{
"path": "test/simple_pre_10/docs/second.md",
"chars": 266,
"preview": "# Second page\nTesting special cases\n\n## Wrong diagram\n\n```mermaid\ngraph FG\nA[Client] \n```\n\n## Correct\n\n```mermaid\ngraph "
},
{
"path": "test/simple_pre_10/mkdocs.yml",
"chars": 353,
"preview": "site_name: Mermaid test (simple)\nsite_description: Test for mermaid\ndocs_dir: docs # indispensable or readthedocs will f"
},
{
"path": "test/superfences/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "test/superfences/docs/index.md",
"chars": 1147,
"preview": "# Mermaid test (SuperFences, custom loader)\n\n!!! Note\n This is a test of the Mermaid plugin, with:\n\n 1. the [pymdo"
},
{
"path": "test/superfences/docs/js/loader.js",
"chars": 10474,
"preview": "function _typeof(obj) { \"@babel/helpers - typeof\"; if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbo"
},
{
"path": "test/superfences/docs/second.md",
"chars": 428,
"preview": "# Second page\nTesting special cases\n\n## Wrong diagram\n\n```mermaid\ngraph FG\nA[Client] \n```\n\n## First Note (collapsible op"
},
{
"path": "test/superfences/mkdocs.yml",
"chars": 737,
"preview": "site_name: Mermaid test (SuperFences) + custom loader\nsite_description: Test for mermaid\ndocs_dir: docs # indispensable "
},
{
"path": "test/superfences/test_site.py",
"chars": 2384,
"preview": "\"\"\"\nTesting the project\n\nSuperfences, the behavior changes\n\n(C) Laurent Franceschetti 2024\n\"\"\"\n\n\nimport pytest\n\nfrom mkd"
},
{
"path": "update_pypi.sh",
"chars": 1326,
"preview": "# -------------------------------------------------------------\n# update the package on pypi\n# 2024-10-12\n#\n# Tip: if yo"
},
{
"path": "webdoc/docs/contribute.md",
"chars": 2577,
"preview": "## Guidance\n\n1. Contributions are welcome.\n2. Before submitting an issue, consider this documentation, and particularly "
},
{
"path": "webdoc/docs/description.md",
"chars": 5961,
"preview": "# Detailed description of the page production process\n\n## Steps for the preparation of an HTML page\n\nThere are three ste"
},
{
"path": "webdoc/docs/index.md",
"chars": 7057,
"preview": "# Mkdocs-Mermaid2<br>A diagrams plugin for Mkdocs { align=center }\n\n---\n\n[. The extraction includes 66 files (140.1 KB), approximately 37.2k tokens, and a symbol index with 46 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.