master 59498d0c537c cached
66 files
140.1 KB
37.2k tokens
46 symbols
1 requests
Download .txt
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


[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) 
[![PyPI](https://img.shields.io/pypi/v/mkdocs-mermaid2-plugin)](https://pypi.org/project/mkdocs-mermaid2-plugin/)
![Github](https://img.shields.io/github/v/tag/fralau/mkdocs-mermaid2-plugin?label=github%20tag)
![Downloads(PyPI)](https://img.shields.io/pypi/dm/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).


[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) 
[![PyPI](https://img.shields.io/pypi/v/mkdocs-mermaid2-plugin)](https://pypi.org/project/mkdocs-mermaid2-plugin/)
![Github](https://img.shields.io/github/v/tag/fralau/mkdocs-mermaid2-plugin?label=github%20tag)
![Downloads(PyPI)](https://img.shields.io/pypi/dm/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:

![error message](error.png)

> **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 }

---

[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![PyPI](https://img.shields.io/pypi/v/mkdocs-mermaid2-plugin)](https://pypi.org/project/mkdocs-mermaid2-plugin/)
![Github](https://img.shields.io/github/v/tag/fralau/mkdocs-mermaid2-plugin?label=github%20tag)
![Downloads(PyPI)](https://img.shields.io/pypi/dm/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:

![](img/custom_colors1.png)

![](img/custom_colors2.png)

!!! 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:

![error message](img/error.png)

!!! 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'

Download .txt
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
Download .txt
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[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](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[![License: MIT](https://img.shields.io/badge/L"
  },
  {
    "path": "webdoc/docs/library.md",
    "chars": 5930,
    "preview": "# Using the JavaScript Mermaid Library\n\n> _From version 1.1.0 of Mkdocs-Mermaid2_\n\n## Introduction\nBy default, MkDocs-Me"
  },
  {
    "path": "webdoc/docs/superfences.md",
    "chars": 4166,
    "preview": "# Using the mermaid2 with Superfences\n\n## Introduction\n\n[Superfences](https://facelessuser.github.io/pymdown-extensions/"
  },
  {
    "path": "webdoc/docs/tips.md",
    "chars": 9026,
    "preview": "# Tips and Tricks\n\n## Advanced Mermaid Functions\n\n### Setting the security level to \"loose\"\n\nTo access the following fun"
  },
  {
    "path": "webdoc/docs/troubleshooting.md",
    "chars": 10687,
    "preview": "\n## Important notice\n\nIf mermaid diagrams are not displayed correctly, or not displayed at all\n**read this section first"
  },
  {
    "path": "webdoc/extra_requirements.txt",
    "chars": 43,
    "preview": "mkdocs-mermaid2-plugin\nmkdocs-material>=6.2"
  },
  {
    "path": "webdoc/mkdocs.yml",
    "chars": 1338,
    "preview": "site_name: MkDocs-Mermaid2\nsite_description: Mkdocs plugin for mermaid diagrams\ndocs_dir: docs # indispensable or readth"
  }
]

About this extraction

This page contains the full source code of the fralau/mkdocs-mermaid2-plugin GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). 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.

Copied to clipboard!