Skip to content

Commit

Permalink
Adding action for publishing to PyPi
Browse files Browse the repository at this point in the history
-[ADDED] GitHub action to publish python package to PyPi
-[CHANGED] Formatting with black (PEP 8)
  • Loading branch information
aarons20 authored and christo-ph committed Nov 10, 2023
1 parent 641c330 commit 335a200
Show file tree
Hide file tree
Showing 5 changed files with 165 additions and 78 deletions.
52 changes: 52 additions & 0 deletions .github/workflows/pypi_ci.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
name: Publish python package to PyPi
on:
push:
branches:
- master
- main

permissions:
contents: write

jobs:
build-python-package:
name: Build distribution packages
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v4
with:
python-version: 3.x
- name: Install dependencies and build distribution packages
run: |
python -m pip install --upgrade pip
pip install setuptools wheel twine
python setup.py sdist bdist_wheel
twine check dist/*
- name: Store the distribution packages
uses: actions/upload-artifact@v3
with:
name: python-package-distributions
path: dist/

publish-to-pypi:
name: Publish Python distribution package to PyPI
if: ${{ github.repository == 'quantorconsulting/mkdocs_build_plantuml' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master') }}
needs:
- build-python-package
runs-on: ubuntu-latest
environment:
name: pipy
url: https://pypi.org/p/mkdocs-build-plantuml-plugin
permissions:
id-token: write

steps:
- name: Download all the dists
uses: actions/download-artifact@v3
with:
name: python-package-distributions
path: dist/
- name: Publish distribution packages to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,6 @@ ENV/

# Vs Code
.vscode/

# Python virtual environments
.venv
42 changes: 30 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,49 @@

# MkDocs-Build-Plantuml-Plugin

This plugin builds your Plantuml image files with `mkdocs serve` automatically.
## Table of Contents

My intend was, that I do not like inline diagrams and stumbled upon issues like non-working `!includes`.
- [About the Project](#about-the-project)
- [Prerequisites](#prerequisites)
- [Installation](#installation)
- [Usage](#usage)
- [Dark Mode Support](#dark-mode-support)
- [Known restrictions](#known-restrictions)
- [Contributing](#contributing)

**Note**: if you want inline diagrams in your Markdown files like
## About the Project

This plugin automates the generation of PlantUML image files when using `mkdocs serve`.

The motivation behind this plugin is to provide a solution for users who prefer not to use inline diagrams and have encountered challenges with non-functional !includes.

**Note**: If you want inline diagrams in your Markdown files

````markdown
```plantuml
Alice -> Bob
```
````

this is plugin is _not_ the right one. Please check out [plantuml-markdown](https://github.com/mikitex70/plantuml-markdown) which does exactly that.
this plugin does _not_ meet your requirements. Please check out [plantuml-markdown](https://github.com/mikitex70/plantuml-markdown) which does exactly that.

## Prerequisites

You need to have installed
You need to have installed:

- Python3
- [MkDocs](https://www.mkdocs.org)
- Java for Plantuml (if running locally)
- Java for Plantuml (If running locally)
- [Plantuml](https://plantuml.com) (if running locally)
- This plugin (needs httplib2 for server rendering)

On OSX you can install plantuml with homebrew which puts a plantuml executable in `/usr/local/bin/plantuml`.
On macOS you can install plantuml with homebrew which puts a plantuml executable in `/usr/local/bin/plantuml`.

## Installation

`pip3 install mkdocs-build-plantuml-plugin`
```shell
pip3 install mkdocs-build-plantuml-plugin
```

## Usage

Expand Down Expand Up @@ -93,11 +107,11 @@ Inside your `index.md` or any other Markdown file you can then reference any cre
![file1](diagrams/out/subdir1/file1.svg)
```

## Dark Mode Support with >=1.4 (prefers-color-scheme)
## Dark Mode Support

Since Version 1.4 this plugin can support dark mode when rendering with `server`.
Since Version 1.4 this plugin can support dark mode when rendering with `server` (prefers-color-scheme).

**Note: Not in local mode, only server rendering mode**
**Note**: Not in local mode, only server rendering mode

1. Grab a general (ie. for [Material Theme](https://squidfunk.github.io/mkdocs-material/)) dark mode support css file (i.e. from [henrywhitaker3/mkdocs-material-dark-theme](https://github.com/henrywhitaker3/mkdocs-material-dark-theme)) for your theme
1. Enable theme support in this plugin:
Expand All @@ -122,5 +136,9 @@ You can find an example in the [example folder](./example/)

## Known restrictions

- If you use `!include`s and the `render: "server"` option, this plugin merges those files manually. If there are any issues or side effects because of that, please open a ticket.
- If you use `!include` and the `render: "server"` option, this plugin merges those files manually. If there are any issues or side effects because of that, please open a ticket.
- Dark mode / theme support is currently only available in server rendering mode.
## Contributing
Contributions are welcome! If you find any issues or have suggestions for improvements, please open an issue or submit a pull request.
93 changes: 50 additions & 43 deletions mkdocs_build_plantuml_plugin/plantuml.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,20 @@
plantuml_alphabet = (
string.digits + string.ascii_uppercase + string.ascii_lowercase + "-_"
)
base64_alphabet = string.ascii_uppercase + \
string.ascii_lowercase + string.digits + "+/"
base64_alphabet = string.ascii_uppercase + string.ascii_lowercase + string.digits + "+/"
b64_to_plantuml = maketrans(
base64_alphabet.encode("utf-8"), plantuml_alphabet.encode("utf-8")
)


class BuildPlantumlPluginConfig(base.Config):
render = mkdocs.config.config_options.Type(str, default="server")
server = mkdocs.config.config_options.Type(str, default="http://www.plantuml.com/plantuml")
disable_ssl_certificate_validation = mkdocs.config.config_options.Type(bool, default=False)
server = mkdocs.config.config_options.Type(
str, default="http://www.plantuml.com/plantuml"
)
disable_ssl_certificate_validation = mkdocs.config.config_options.Type(
bool, default=False
)
bin_path = mkdocs.config.config_options.Type(str, default="/usr/local/bin/plantuml")
output_format = mkdocs.config.config_options.Type(str, default="png")
allow_multiple_roots = mkdocs.config.config_options.Type(bool, default=False)
Expand All @@ -47,13 +50,13 @@ class BuildPlantumlPluginConfig(base.Config):


class BuildPlantumlPlugin(BasePlugin[BuildPlantumlPluginConfig]):
""" main plugin entry point """
"""main plugin entry point"""

def __init__(self):
self.total_time = 0

def on_pre_build(self, config):
""" Checking given parameters and looking for files """
"""Checking given parameters and looking for files"""

diagram_roots = []

Expand All @@ -77,7 +80,11 @@ def on_pre_build(self, config):
diagram.out_dir = self._get_out_directory(root, subdir)

# Handle to read source file
with open(os.path.join(diagram.directory, diagram.file), "r", encoding="utf-8") as f:
with open(
os.path.join(diagram.directory, diagram.file),
"r",
encoding="utf-8",
) as f:
diagram.src_file = f.readlines()

# Search for start (@startuml <filename>)
Expand Down Expand Up @@ -107,8 +114,14 @@ def on_pre_build(self, config):
def _make_diagram_root(self, subdir):
diagram_root = DiagramRoot()
diagram_root.root_dir = os.path.join(os.getcwd(), subdir)
diagram_root.src_dir = os.path.join(os.getcwd(), subdir, self.config["input_folder"])
print("root dir: {}, src dir: {}".format(diagram_root.root_dir, diagram_root.src_dir))
diagram_root.src_dir = os.path.join(
os.getcwd(), subdir, self.config["input_folder"]
)
print(
"root dir: {}, src dir: {}".format(
diagram_root.root_dir, diagram_root.src_dir
)
)
return diagram_root

def _get_out_directory(self, root, subdir):
Expand All @@ -135,17 +148,15 @@ def _search_start_tag(self, diagram):
ws = line.find(" ")
if ws > 0:
# we look for <filename> which starts after a whitespace
out_filename = line[ws + 1:]
out_filename = line[ws + 1 :]
diagram.out_file = os.path.join(
diagram.out_dir,
out_filename + "." +
self.config["output_format"],
out_filename + "." + self.config["output_format"],
)
if self.config["theme_enabled"]:
diagram.out_file_dark = os.path.join(
diagram.out_dir,
out_filename + "_dark." +
self.config["output_format"],
out_filename + "_dark." + self.config["output_format"],
)
return True
return False
Expand Down Expand Up @@ -203,19 +214,19 @@ def _readFileRecursively(self, lines, temp_file, diagram, directory, dark_mode):
return temp_file

def _readIncludeLine(self, diagram, line, temp_file, directory, dark_mode):
""" Handles the different include types like !includeurl, !include and !includesub """
# If includeurl is found, we do not have to do anything here.
"""Handles the different include types like !includeurl, !include and !includesub"""
# If includeurl is found, we do not have to do anything here.
# Server can handle that
if re.match(r"^!includeurl\s+\S+\s*$", line):
temp_file += line

elif re.match(r"^!includesub\s+\S+\s*$", line):
# on the eleventh position starts the inluded file
parts = line[11:].strip().split('!')
parts = line[11:].strip().split("!")
if len(parts) == 2:
inc_file = parts[0] # Extract the file path
sub_name = parts[1] # Extract the sub name after the '!'

if dark_mode:
inc_file = inc_file.replace(
self.config["theme_light"], self.config["theme_dark"]
Expand All @@ -239,8 +250,10 @@ def _readIncludeLine(self, diagram, line, temp_file, directory, dark_mode):
print("Could not find included file" + str(e1) + str(e2))
raise e2
else:
raise Exception("Invalid !includesub syntax. Expected: !includesub <filepath>!<sub_name>")

raise Exception(
"Invalid !includesub syntax. Expected: !includesub <filepath>!<sub_name>"
)

elif re.match(r"^!include\s+\S+\s*$", line):
# on the ninth position starts the filename
inc_file = line[9:].rstrip()
Expand Down Expand Up @@ -274,11 +287,11 @@ def _readIncludeLine(self, diagram, line, temp_file, directory, dark_mode):
print("Could not find include " + str(e1) + str(e2))
raise e2
else:
raise Exception("Unnown include type: " + line)
raise Exception("Unknown include type: " + line)
return temp_file

def _read_incl_line_file(self, diagram, temp_file, dark_mode, inc_file_abs):
""" Save the mtime of the inc file to compare """
"""Save the mtime of the inc file to compare"""
try:
local_inc_time = os.path.getmtime(inc_file_abs)
except Exception as _:
Expand All @@ -297,9 +310,9 @@ def _read_incl_line_file(self, diagram, temp_file, dark_mode, inc_file_abs):
)

return temp_file

def _read_incl_sub(self, diagram, temp_file, dark_mode, inc_file_abs, inc_sub_name):
""" Handle !includesub statements """
"""Handle !includesub statements"""
# Save the mtime of the inc file to compare
try:
local_inc_time = os.path.getmtime(inc_file_abs)
Expand All @@ -308,7 +321,7 @@ def _read_incl_sub(self, diagram, temp_file, dark_mode, inc_file_abs, inc_sub_na

if local_inc_time > diagram.inc_time:
diagram.inc_time = local_inc_time

temp_sub = []
add_following = False
with open(inc_file_abs, "r") as inc:
Expand All @@ -320,9 +333,9 @@ def _read_incl_sub(self, diagram, temp_file, dark_mode, inc_file_abs, inc_sub_na
add_following = False
elif add_following:
temp_sub.append(line)

temp_file = self._readFileRecursively(
temp_sub, # Do only use the subs for further recursion
temp_sub, # Do only use the subs for further recursion
temp_file,
diagram,
os.path.dirname(os.path.realpath(inc_file_abs)),
Expand All @@ -339,24 +352,20 @@ def _build_out_filename(self, diagram):
)
if self.config["theme_enabled"]:
diagram.out_file_dark = (
diagram.file[:out_index] + "_dark." +
self.config["output_format"]
diagram.file[:out_index] + "_dark." + self.config["output_format"]
)

diagram.out_file = os.path.join(diagram.out_dir, diagram.out_file)
if self.config["theme_enabled"]:
diagram.out_file_dark = os.path.join(
diagram.out_dir, diagram.out_file_dark)
diagram.out_file_dark = os.path.join(diagram.out_dir, diagram.out_file_dark)

return diagram

def _convert(self, diagram, dark_mode=False):

if not dark_mode:
if (diagram.img_time < diagram.src_time) or (
diagram.inc_time > diagram.img_time
):

print("Converting " + os.path.join(diagram.directory, diagram.file))
if self.config["render"] == "local":
command = self.config["bin_path"].rsplit()
Expand Down Expand Up @@ -385,7 +394,6 @@ def _convert(self, diagram, dark_mode=False):
self._call_server(diagram, diagram.out_file_dark)

def _call_server(self, diagram, out_file):

http = httplib2.Http({})

if self.config["disable_ssl_certificate_validation"]:
Expand All @@ -403,14 +411,13 @@ def _call_server(self, diagram, out_file):
response, content = http.request(url)
if response.status != 200:
print(
"Wrong response status for " +
diagram.file + ": " + str(response.status)
"Wrong response status for "
+ diagram.file
+ ": "
+ str(response.status)
)
except Exception as error:
print(
"Server error while processing "
+ diagram.file + ": " + str(error)
)
print("Server error while processing " + diagram.file + ": " + str(error))
raise error
else:
if not os.path.exists(os.path.join(diagram.out_dir)):
Expand All @@ -431,7 +438,7 @@ def _file_matches_extension(self, file):


class PuElement:
""" plantuml helper object """
"""plantuml helper object"""

def __init__(self, file, subdir):
self.file = file
Expand All @@ -450,7 +457,7 @@ def __init__(self, file, subdir):


class DiagramRoot:
""" object containing the src and out directories per diagram root """
"""object containing the src and out directories per diagram root"""

def __init__(self):
self.root_dir = ""
Expand Down
Loading

0 comments on commit 335a200

Please sign in to comment.