pax_global_header00006660000000000000000000000064145353274250014524gustar00rootroot0000000000000052 comment=f7fc9503a8a6d6ff8ae9ee8bcf430e5e05da390c pandoc-plantuml-filter-0.1.5/000077500000000000000000000000001453532742500161105ustar00rootroot00000000000000pandoc-plantuml-filter-0.1.5/.github/000077500000000000000000000000001453532742500174505ustar00rootroot00000000000000pandoc-plantuml-filter-0.1.5/.github/workflows/000077500000000000000000000000001453532742500215055ustar00rootroot00000000000000pandoc-plantuml-filter-0.1.5/.github/workflows/deploy.yml000066400000000000000000000012451453532742500235260ustar00rootroot00000000000000name: Upload Python Package on: release: types: [published] jobs: deploy: runs-on: ubuntu-latest permissions: # IMPORTANT: this permission is mandatory for trusted publishing id-token: write steps: - uses: actions/checkout@v3 - name: Set up Python uses: actions/setup-python@v3 with: python-version: '3.x' - name: Install dependencies run: | python -m pip install --upgrade pip python -m pip install build - name: Build package run: python -m build - name: Publish package distributions to PyPI uses: pypa/gh-action-pypi-publish@release/v1 pandoc-plantuml-filter-0.1.5/.github/workflows/main.yml000066400000000000000000000026721453532742500231630ustar00rootroot00000000000000name: CI on: [push, pull_request] jobs: lint: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Set up Python 3.12 uses: actions/setup-python@v4 with: python-version: 3.12 - name: Setup and install tools run: | python -m pip install --upgrade black flake8 - name: black format check run: python -m black --check --line-length 120 pandoc_plantuml_filter.py tests - name: flake8 format check run: python -m flake8 --max-line-length 120 pandoc_plantuml_filter.py tests test: strategy: fail-fast: false matrix: python-version: [3.8, 3.12] runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} - name: Setup build and test environment run: python -m pip install --upgrade pip build pytest pytest-mock - name: Build package run: python -m build - name: Install package run: python -m pip install --pre dist/pandoc_plantuml_filter-*.whl - name: run unit tests run: python -m pytest tests/test_unit.py - name: install dependencies for integration tests run: sudo apt update && sudo apt install -y pandoc plantuml - name: run integration tests run: python -m pytest tests/test_integration.py pandoc-plantuml-filter-0.1.5/.gitignore000066400000000000000000000002051453532742500200750ustar00rootroot00000000000000.env/ build/ dist/ __pycache__/ example.png images/ missfont.log pandoc_plantuml_filter.egg-info/ plantuml-images/ sample.pdf dist/ pandoc-plantuml-filter-0.1.5/LICENSE000066400000000000000000000020541453532742500171160ustar00rootroot00000000000000MIT License Copyright (c) 2018 Timo Furrer 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. pandoc-plantuml-filter-0.1.5/README.md000066400000000000000000000026111453532742500173670ustar00rootroot00000000000000# pandoc-plantuml-filter Pandoc filter which converts PlantUML code blocks to PlantUML images. ```` ```plantuml Alice -> Bob: Authentication Request Bob --> Alice: Authentication Response Alice -> Bob: Another authentication Request Alice <-- Bob: another authentication Response ``` ```` ## Usage Install it with pip: ``` pip install pandoc-plantuml-filter ``` And use it like any other pandoc filter: ``` pandoc tests/sample.md -o sample.pdf --filter pandoc-plantuml ``` The PlantUML binary must be in your `$PATH` or can be set with the `PLANTUML_BIN` environment variable. ### Additional parameters You could pass additional parameters into `plantuml` filter which will be processed as picture's options: ```` ```{ .plantuml height=50% plantuml-filename=test.png } Alice -> Bob: Authentication Request Bob --> Alice: Authentication Response ``` ```` The `plantuml-filename` parameter create a symlink for the destination picture, which could be used in the same file as an image directly. ### Control the output file-type The generated file-type can be controlled via the file metadata: ``` --- plantuml-format: svg --- ``` Or directly via the cli `--metadata` argument. ``` pandoc tests/sample.md -o sample.pdf --filter pandoc-plantuml --metadata=plantuml-format=svg ``` ## But there is ... There are a few other filters trying to convert PlantUML code blocks however they all failed for me. pandoc-plantuml-filter-0.1.5/pandoc_plantuml_filter.py000077500000000000000000000052641453532742500232210ustar00rootroot00000000000000#!/usr/bin/env python """ Pandoc filter to process code blocks with class "plantuml" into plant-generated images. Needs `plantuml.jar` from http://plantuml.com/. """ import os import sys import subprocess from pandocfilters import toJSONFilter, Para, Image from pandocfilters import get_filename4code, get_caption, get_extension PLANTUML_BIN = os.environ.get("PLANTUML_BIN", "plantuml") def rel_mkdir_symlink(src, dest): dest_dir = os.path.dirname(dest) if dest_dir and not os.path.exists(dest_dir): os.makedirs(dest_dir) if os.path.exists(dest): os.remove(dest) src = os.path.relpath(src, dest_dir) os.symlink(src, dest) def calculate_filetype(format_, plantuml_format): if plantuml_format: # File-type is overwritten via cli # --metadata=plantuml-format:svg if plantuml_format["t"] == "MetaString": return get_extension(format_, plantuml_format["c"]) # File-type is overwritten in the meta data block of the document # --- # plantuml-format: svg # --- elif plantuml_format["t"] == "MetaInlines": return get_extension(format_, plantuml_format["c"][0]["c"]) # Default per output-type eg. output-type: html -> file-type: svg return get_extension(format_, "png", html="svg", latex="png") def plantuml(key, value, format_, meta): if key == "CodeBlock": [[ident, classes, keyvals], code] = value if "plantuml" in classes: caption, typef, keyvals = get_caption(keyvals) filename = get_filename4code("plantuml", code) filetype = calculate_filetype(format_, meta.get("plantuml-format")) src = filename + ".uml" dest = filename + "." + filetype # Generate image only once if not os.path.isfile(dest): txt = code.encode(sys.getfilesystemencoding()) if not txt.startswith(b"@start"): txt = b"@startuml\n" + txt + b"\n@enduml\n" with open(src, "wb") as f: f.write(txt) subprocess.check_call(PLANTUML_BIN.split() + ["-t" + filetype, src]) sys.stderr.write("Created image " + dest + "\n") # Update symlink each run for ind, keyval in enumerate(keyvals): if keyval[0] == "plantuml-filename": link = keyval[1] keyvals.pop(ind) rel_mkdir_symlink(dest, link) dest = link break return Para([Image([ident, [], keyvals], caption, [dest, typef])]) def main(): toJSONFilter(plantuml) if __name__ == "__main__": main() pandoc-plantuml-filter-0.1.5/pyproject.toml000066400000000000000000000023241453532742500210250ustar00rootroot00000000000000[build-system] requires = ["setuptools", "setuptools-scm"] build-backend = "setuptools.build_meta" [project] name = "pandoc-plantuml-filter" authors = [ {name = "Timo Furrer", email = "tuxtimo@gmail.com"}, ] description = "Pandoc filter for PlantUML code blocks" readme = "README.md" requires-python = ">=3.8" keywords = ["plantuml", "pandoc-filter", "pandoc"] license = {text = "MIT"} classifiers = [ "Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Natural Language :: English", "Operating System :: OS Independent", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", "Programming Language :: Python :: Implementation", "Programming Language :: Python :: Implementation :: CPython", "Topic :: Software Development :: Libraries :: Python Modules", ] dependencies = [ "pandocfilters", ] dynamic = ["version"] [project.scripts] pandoc-plantuml = "pandoc_plantuml_filter:main" [tool.setuptools_scm] pandoc-plantuml-filter-0.1.5/tests/000077500000000000000000000000001453532742500172525ustar00rootroot00000000000000pandoc-plantuml-filter-0.1.5/tests/sample.md000066400000000000000000000011741453532742500210600ustar00rootroot00000000000000# Some PantUML sample ```plantuml Alice -> Bob: Authentication Request Bob --> Alice: Authentication Response Alice -> Bob: Another authentication Request Alice <-- Bob: another authentication Response ``` Nice, huh? # Another example which referenced later This tests relative path w/ subdirectory ```{ .plantuml width=60% plantuml-filename=images/example.png } [producer] -> [consumer]: data streaming ``` This tests relative path w/o subdirectories ```{ .plantuml width=60% plantuml-filename=example.png } [producer] -> [consumer]: data streaming ``` Here's a UML # Reference ![And here's the reference](images/example.png) pandoc-plantuml-filter-0.1.5/tests/test_integration.py000066400000000000000000000047471453532742500232220ustar00rootroot00000000000000import os import re import subprocess from pathlib import Path import pytest __TEST_BASE_DIR__ = Path(os.path.dirname(__file__)) / "testdata" @pytest.mark.parametrize( "filename, expected_content, expected_files", [ ("single-diagram", ["\\includegraphics{plantuml-images/"], []), ("single-diagram-with-config", ["\\includegraphics", "width=0.6"], []), ( "single-diagram-with-filename-and-subdirectory", ["\\includegraphics", "images/example.png"], ["images/example.png"], ), ( "single-diagram-with-filename-without-subdirectory", ["\\includegraphics", "example.png"], ["example.png"], ), ( "single-diagram-reference", [ "\\includegraphics", "images/example.png", "\\includegraphics{images/example.png}", ], ["images/example.png"], ), ], ) def test_digrams(tmp_path, filename, expected_content, expected_files): input_file = str(__TEST_BASE_DIR__ / f"{filename}.md") output_file = str(tmp_path / f"{filename}.tex") cmd = subprocess.run(["pandoc", input_file, "-o", output_file, "--filter", "pandoc-plantuml"]) assert cmd.returncode == 0 with open(output_file) as f: content = f.read() for line in expected_content: assert line in content for file in expected_files: assert os.path.exists(file) def test_filetype_param_from_meta(tmp_path): input_file = str(__TEST_BASE_DIR__ / "single-diagram-with-meta.md") output_file = str(tmp_path / "single-diagram-with-meta.tex") cmd = subprocess.run(["pandoc", input_file, "-o", output_file, "--filter", "pandoc-plantuml"]) assert cmd.returncode == 0 with open(output_file) as f: content = f.read() pattern = re.compile(r"plantuml-images\/.*\.svg") match = pattern.search(content) assert match def test_filetype_metadata_is_overridden_from_cli(tmp_path): input_file = str(__TEST_BASE_DIR__ / "single-diagram-with-meta.md") output_file = str(tmp_path / "single-diagram-with-meta.tex") args = ["--metadata=plantuml-format:jpg"] cmd = subprocess.run(["pandoc", input_file, "-o", output_file, "--filter", "pandoc-plantuml"] + args) assert cmd.returncode == 0 with open(output_file) as f: content = f.read() pattern = re.compile(r"plantuml-images\/.*\.jpg") match = pattern.search(content) assert match pandoc-plantuml-filter-0.1.5/tests/test_unit.py000066400000000000000000000006451453532742500216470ustar00rootroot00000000000000from pandoc_plantuml_filter import plantuml def test_call_plantuml_create_para_object(mocker): mocker.patch("os.path.isfile", return_value=False) mock = mocker.patch("subprocess.check_call") ret = plantuml(key="CodeBlock", value=[["", ["plantuml"], []], ""], format_=None, meta={}) assert isinstance(ret, dict) assert "t" in ret.keys() assert ret["t"] == "Para" mock.assert_called_once() pandoc-plantuml-filter-0.1.5/tests/testdata/000077500000000000000000000000001453532742500210635ustar00rootroot00000000000000pandoc-plantuml-filter-0.1.5/tests/testdata/single-diagram-reference.md000066400000000000000000000003341453532742500262240ustar00rootroot00000000000000# Single PlantUML diagram which referenced later ```{ .plantuml width=60% plantuml-filename=images/example.png } [producer] -> [consumer]: data streaming ``` # Reference ![And here's the reference](images/example.png) pandoc-plantuml-filter-0.1.5/tests/testdata/single-diagram-with-config.md000066400000000000000000000001571453532742500265070ustar00rootroot00000000000000# Single PlantUML diagram with config ```{ .plantuml width=60% } [producer] -> [consumer]: data streaming ``` pandoc-plantuml-filter-0.1.5/tests/testdata/single-diagram-with-filename-and-subdirectory.md000066400000000000000000000002501453532742500322700ustar00rootroot00000000000000# Single PlantUML diagram with filename and sub-directory ```{ .plantuml width=60% plantuml-filename=images/example.png } [producer] -> [consumer]: data streaming ``` pandoc-plantuml-filter-0.1.5/tests/testdata/single-diagram-with-filename-without-subdirectory.md000066400000000000000000000002451453532742500332350ustar00rootroot00000000000000# Single PlantUML diagram with filename without sub-directory ```{ .plantuml width=60% plantuml-filename=example.png } [producer] -> [consumer]: data streaming ``` pandoc-plantuml-filter-0.1.5/tests/testdata/single-diagram-with-meta.md000066400000000000000000000003621453532742500261660ustar00rootroot00000000000000--- plantuml-format: svg --- # Single PlantUML digaram ```plantuml Alice -> Bob: Authentication Request Bob --> Alice: Authentication Response Alice -> Bob: Another authentication Request Alice <-- Bob: another authentication Response ``` pandoc-plantuml-filter-0.1.5/tests/testdata/single-diagram.md000066400000000000000000000003241453532742500242670ustar00rootroot00000000000000# Single PlantUML digaram ```plantuml Alice -> Bob: Authentication Request Bob --> Alice: Authentication Response Alice -> Bob: Another authentication Request Alice <-- Bob: another authentication Response ```