Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 12 additions & 9 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,22 +32,25 @@ jobs:
- name: Install test dependencies
run: |
pip install pybtex
- name: Setup Java
uses: actions/setup-java@v1
with:
java-version: 8
- name: Install PlantUML
env:
PLANTUML_VERSION: 1.2020.24
run: |
# Not using "apt-get install plantuml" because it's an old version
sudo apt-get install default-jre-headless

# Avoid Java logging "Created user preferences directory"
mkdir -p ~/.java/.userPrefs

wget -q -O "${{github.workspace}}/plantuml.jar" "https://repo1.maven.org/maven2/net/sourceforge/plantuml/plantuml/${PLANTUML_VERSION}/plantuml-${PLANTUML_VERSION}.jar"
PLANTUML_VERSION: 1.2021.4
run: wget -q -O "${{github.workspace}}/plantuml.jar" "https://repo1.maven.org/maven2/net/sourceforge/plantuml/plantuml/${PLANTUML_VERSION}/plantuml-${PLANTUML_VERSION}.jar"
- name: Run tests
env:
PLANTUML_EXEC: java -Djava.awt.headless=true -jar ${{github.workspace}}/plantuml.jar
run: |
py.test --color=yes tests/
- name: Run PlantUML PicoWeb tests
env:
PLANTUML_SYSTEM: picoweb
PLANTUML_PICOWEB_START_COMMAND: java -Djava.awt.headless=true -jar ${{github.workspace}}/plantuml.jar -picoweb:0:localhost
run: |
py.test --color=yes tests/test_plantuml*
flake8:
name: Linting (flake8)
strategy:
Expand Down
7 changes: 6 additions & 1 deletion tests/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import re
import os
from functools import lru_cache
from pathlib import Path
from textwrap import dedent
Expand All @@ -11,6 +11,7 @@
__all__ = [
'cached_property',
'execute_plugin_tasks',
'getenv_split',
'simple_html_page',
'TEST_DATA_PATH',
'V7_PLUGIN_PATH',
Expand All @@ -36,6 +37,10 @@ def execute_plugin_tasks(plugin: Task, verbosity: int = 0):
raise Exception("Task error for '{}'\n{}".format(t.name, catched.get_msg()))


def getenv_split(key: str, default=None):
return os.environ[key].split() if key in os.environ else default


def simple_html_page(body: str) -> str:
return dedent('''
<!doctype html>
Expand Down
21 changes: 20 additions & 1 deletion tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
from nikola import Nikola
from nikola.post import Post
from nikola.utils import LocaleBorg
from tests import cached_property, simple_html_page
from tests import cached_property, getenv_split, simple_html_page
from v8.plantuml.plantuml import PICOWEB_URL_ENV_VAR


@fixture
Expand Down Expand Up @@ -115,6 +116,24 @@ def localeborg_setup(default_locale):
LocaleBorg.reset()


@fixture
def maybe_plantuml_picoweb_server(monkeypatch, tmp_site_path):
if os.getenv('PLANTUML_SYSTEM') == 'picoweb':
from v8.plantuml.plantuml import DEFAULT_PLANTUML_PICOWEB_START_COMMAND, DEFAULT_PLANTUML_PICOWEB_START_TIMEOUT_SECONDS, \
DEFAULT_PLANTUML_PICOWEB_URL, PicoWebSupervisor
supervisor = PicoWebSupervisor()
supervisor.start(
command=getenv_split('PLANTUML_PICOWEB_START_COMMAND', DEFAULT_PLANTUML_PICOWEB_START_COMMAND),
timeout=os.getenv('PLANTUML_PICOWEB_START_TIMEOUT_SECONDS', DEFAULT_PLANTUML_PICOWEB_START_TIMEOUT_SECONDS),
url_template=os.getenv('PLANTUML_PICOWEB_URL', DEFAULT_PLANTUML_PICOWEB_URL),
)
monkeypatch.setenv(PICOWEB_URL_ENV_VAR, supervisor.url)
yield
supervisor.stop()
else:
yield


@fixture
def tmp_site_path(monkeypatch, tmp_path):
monkeypatch.chdir(tmp_path)
Expand Down
16 changes: 8 additions & 8 deletions tests/test_plantuml.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
from textwrap import dedent
from typing import Dict

from tests import execute_plugin_tasks
from v8.plantuml.plantuml import PlantUmlTask
from tests import execute_plugin_tasks, getenv_split
from v8.plantuml.plantuml import DEFAULT_PLANTUML_EXEC, DEFAULT_PLANTUML_SYSTEM, PlantUmlTask


# Note this test is also sufficient to prove that rendering binary image files will work
def test_render_file_success(tmp_site_path):
def test_render_file_success(maybe_plantuml_picoweb_server, tmp_site_path):
(tmp_site_path / 'pages' / 'test.puml').write_text(dedent('''\
@startuml
title filename="%filename()"
Expand All @@ -21,7 +21,7 @@ def test_render_file_success(tmp_site_path):
(tmp_site_path / 'pages' / 'includes' / 'include2.iuml').write_text('participant "included-2"')

plugin = create_plugin({
'PLANTUML_ARGS': [
'PLANTUML_FILE_OPTIONS': [
'-chide footbox',
'-Ipages/includes/include1.iuml',
],
Expand All @@ -47,7 +47,7 @@ def test_render_file_success(tmp_site_path):
]


def test_render_file_error(tmp_site_path):
def test_render_file_error(maybe_plantuml_picoweb_server, tmp_site_path):
(tmp_site_path / 'pages' / 'test.puml').write_text(dedent('''\
@startuml
A -> B
Expand Down Expand Up @@ -104,7 +104,7 @@ def test_gen_tasks(tmp_site_path):

def test_task_depends_on_included_files(tmp_site_path):
plugin = create_plugin({
'PLANTUML_ARGS': [
'PLANTUML_FILE_OPTIONS': [
'-Iincludes/include1.iuml',
'-Iincludes/include2.iuml',
'-Iincludes/bar*.iuml',
Expand Down Expand Up @@ -142,10 +142,10 @@ def __init__(self, config: Dict):
'FILTERS': {},
'OUTPUT_FOLDER': 'output',
'PLANTUML_DEBUG': True,
'PLANTUML_EXEC': getenv_split('PLANTUML_EXEC', DEFAULT_PLANTUML_EXEC),
'PLANTUML_SYSTEM': os.getenv('PLANTUML_SYSTEM', DEFAULT_PLANTUML_SYSTEM),
}
self.config.update(config)
if 'PLANTUML_EXEC' in os.environ:
self.config['PLANTUML_EXEC'] = os.environ['PLANTUML_EXEC'].split()


def plugin_tasks(plugin):
Expand Down
10 changes: 6 additions & 4 deletions tests/test_plantuml_markdown.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@
if sys.version_info < (3, 6):
raise pytest.skip("plantuml_markdown plugin requires Python >= 3.6", allow_module_level=True)

from tests import V8_PLUGIN_PATH
from tests import V8_PLUGIN_PATH, getenv_split
from tests.conftest import CompileResult
from v8.plantuml.plantuml import DEFAULT_PLANTUML_EXEC, DEFAULT_PLANTUML_SYSTEM
from v8.plantuml_markdown.plantuml_markdown import PlantUmlMarkdownProcessor, first_line_for_listing_block


Expand Down Expand Up @@ -146,20 +147,21 @@ def test_first_line_for_listing_block(line, expected):


@fixture
def do_compile_test(basic_compile_test):
def do_compile_test(basic_compile_test, maybe_plantuml_picoweb_server):
def f(data: str, plantuml_continue_after_failure=False) -> CompileResult:
return basic_compile_test(
'.md',
data,
extra_config={
'PLANTUML_DEBUG': True,
'PLANTUML_CONTINUE_AFTER_FAILURE': plantuml_continue_after_failure,
'PLANTUML_EXEC': os.environ.get('PLANTUML_EXEC', 'plantuml').split(),
'PLANTUML_MARKDOWN_ARGS': [
'PLANTUML_EXEC': getenv_split('PLANTUML_EXEC', DEFAULT_PLANTUML_EXEC),
'PLANTUML_MARKDOWN_OPTIONS': [
'-chide footbox',
'-nometadata',
'-Sshadowing=false',
],
'PLANTUML_SYSTEM': os.getenv('PLANTUML_SYSTEM', DEFAULT_PLANTUML_SYSTEM),
},
extra_plugins_dirs=[
V8_PLUGIN_PATH / 'plantuml',
Expand Down
12 changes: 12 additions & 0 deletions v8/plantuml/CHANGES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# 1.0.0
* Add support for PlantUML PicoWeb server.
* Rename `PLANTUML_ARGS` config option to `PLANTUML_FILE_OPTIONS`.

# 0.2.0
* Add `PlantUmlTask.plantuml_manager` so the `plantuml_markdown` plugin can use it.

# 0.1.1
* Update `PLANTUML_FILES` in `conf.py.sample` to match the default behaviour.

# 0.1
* First release.
11 changes: 3 additions & 8 deletions v8/plantuml/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,17 @@ This plugin converts [PlantUML](https://plantuml.com/) files.

The default configuration will output all `*.puml` files found under the `plantuml` dir as SVG files.

Developed against PlantUML version 1.2020.24. Probably works with some earlier versions.

# Unicode

The plugin expects PlantUML files to be encoded with UTF-8.

# Known Issues

- It's slow! Every PlantUML rendering launches a new Java process, on my laptop it takes 4-8 seconds per file.
I have some ideas to speed this up, and they may be available in future plugin versions.

- Changes to files included via `!include ...` or via a pattern (e.g. `-Ipath/to/*.iuml`) will NOT trigger a rebuild.
Instead, if you include them explicitly in `PLANTUML_ARGS` (e.g. `-Ipath/to/foo.iuml`) then they will trigger a
rebuild.
Instead, if you include them explicitly in `PLANTUML_FILE_OPTIONS` (e.g. `-Ipath/to/foo.iuml`) then they will trigger
a rebuild.

- `nikola auto` does not watch dirs in `PLANTUML_FILES` or files included via `PLANTUML_ARGS` / `!include`.
- `nikola auto` does not watch dirs in `PLANTUML_FILES` or files included via `PLANTUML_FILE_OPTIONS` / `!include`.
As a workaround you could put PlantUML files under any dir listed in `POSTS` or `PAGES` because those dirs
are watched.
(Use `.iuml` suffix for include files to prevent them matching the `*.puml` wildcard in `PLANTUML_FILES`)
Expand Down
55 changes: 49 additions & 6 deletions v8/plantuml/conf.py.sample
Original file line number Diff line number Diff line change
@@ -1,7 +1,24 @@
#
# PLANTUML_SYSTEM ('exec' or 'picoweb')
#
# exec The PLANTUML_EXEC command is run separately for each rendering,
# this starts a new Java process each time so will be slow.
#
# picoweb An HTTP request is sent to PLANTUML_PICOWEB_URL for each rendering, this is much faster than 'exec'.
#
# If PLANTUML_PICOWEB_START_COMMAND is an empty list then Nikola assumes PicoWeb is already running,
# otherwise Nikola will run PLANTUML_PICOWEB_START_COMMAND the first time PicoWeb is needed.
#
# However if the 'PLANTUML_PICOWEB_URL' environment variable is set then that URL is used and
# PLANTUML_PICOWEB_START_COMMAND / PLANTUML_PICOWEB_URL config options are ignored.
# This is kind of a kludge so 'nikola auto' can start the server and share it with child builds processes.
#
PLANTUML_SYSTEM = 'exec'

#
# PLANTUML_EXEC (list of strings) - The command to run PlantUML
#
# '%site_path%' anywhere in PLANTUML_EXEC will be replaced with the full path to the site dir.
# %site_path% anywhere in PLANTUML_EXEC will be replaced with the full path to the site dir.
# PlantUML is run in the site dir so often this is not needed.
#
# Examples
Expand All @@ -16,7 +33,7 @@
PLANTUML_EXEC = ['plantuml']

#
# PLANTUML_ARGS (list of strings) - CLI arguments that are sent to PlantUML when rendering PlantUML files,
# PLANTUML_FILE_OPTIONS (list of strings) - options used when rendering PlantUML files,
# see https://plantuml.com/command-line
#
# Examples
Expand All @@ -27,10 +44,10 @@ PLANTUML_EXEC = ['plantuml']
# Specify the style in conf.py
# [ '-chide footbox', '-SShadowing=false' ]
#
PLANTUML_ARGS = []
PLANTUML_FILE_OPTIONS = []

#
# PLANTUML_FILES contains (wildcard, destination, extension, args) tuples.
# PLANTUML_FILES contains (wildcard, destination, extension, options) tuples.
#
# <wildcard> is used to generate a list of source files in the same way as POSTS and PAGES.
#
Expand All @@ -39,7 +56,7 @@ PLANTUML_ARGS = []
#
# As with POSTS and PAGES you can create any directory structure you want and it will be reflected in the output.
#
# <args> is a list of cli arguments that are appended to PLANTUML_ARGS
# <options> is a list of strings that is appended to PLANTUML_FILE_OPTIONS
#
PLANTUML_FILES = (
('plantuml/*.puml', 'plantuml', '.svg', ['-tsvg']),
Expand All @@ -48,11 +65,37 @@ PLANTUML_FILES = (
#
# PLANTUML_CONTINUE_AFTER_FAILURE (boolean) - If True then Nikola will continue executing after any PlantUML failures.
#
# PlantUML puts its error messages in the rendered output so you might find this option helpful when running `nikola auto`.
# PlantUML puts its error messages in the rendered output so you might find this option helpful when running 'nikola auto'.
#
PLANTUML_CONTINUE_AFTER_FAILURE = False

#
# PLANTUML_DEBUG (boolean) - Control plugin verbosity
#
PLANTUML_DEBUG = False

#
# PLANTUML_PICOWEB_START_COMMAND (list of strings) - The command to start a PlantUML PicoWeb Server
#
# %site_path% anywhere in PLANTUML_PICOWEB_START_COMMAND will be replaced with the full path to the site dir.
# PlantUML is run in the site dir so often this is not needed.
#
PLANTUML_PICOWEB_START_COMMAND = ['plantuml', '-picoweb:0:localhost']

#
# PLANTUML_PICOWEB_URL (string) - URL of the PicoWeb Server
#
# If Nikola starts a PicoWeb Server then %port% anywhere in PLANTUML_PICOWEB_URL will be replaced by the actual
# port number of the server.
#
PLANTUML_PICOWEB_URL = 'http://localhost:%port%'

#
# PLANTUML_PICOWEB_START_TIMEOUT_SECONDS (int) - Maximum time to wait for the PicoWeb server to start.
#
PLANTUML_PICOWEB_START_TIMEOUT_SECONDS = 30

#
# PLANTUML_PICOWEB_RENDER_TIMEOUT_SECONDS (int) - Maximum time to wait for a single rendering.
#
PLANTUML_PICOWEB_RENDER_TIMEOUT_SECONDS = 30
2 changes: 1 addition & 1 deletion v8/plantuml/plantuml.plugin
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@ PluginCategory = Task

[Documentation]
Author = Matthew Leather
Version = 0.2.0
Version = 1.0.0
Website = https://plugins.getnikola.com/#plantuml
Description = Renders PlantUML files
Loading