Git Product home page Git Product logo

kroki's Introduction

sphinxcontrib-kroki

Embed PlantUML, DOT, etc. diagrams in your Sphinx-based documentation using kroki.

Instalation

Install this package via pip:

pip install sphinxcontrib-kroki

and enable in project configuration (conf.py):

extensions = [
    'sphinxcontrib.kroki',
]

Usage

Inline diagram, show as svg:

.. kroki::
   :caption: Diagram

    @startuml
    Alice -> Bob: Authentication Request
    Bob --> Alice: Authentication Response

    Alice -> Bob: Another authentication Request
    Alice <-- Bob: Another authentication Response
    @enduml

Load a diagram from a file and show as png:

.. kroki:: ./path/to/graph.puml png

Options

  • :align: The horizontal alignment of the diagram (left, center or right);
  • :caption: The caption of the diagram;
  • :class: The class names (a list of class names separeted by spaces);
  • :filename: The path to the file with the diagram;
  • :format: The output format of the diagram (default svg);
  • :name: The hyperlink reference to the element;
  • :options:: The diagram options in yaml format;
  • :type: The type of the diagram (actdiag, blockdiag, bpmn, bytefield, c4plantuml, dot, ditaa, er, erd, excalidraw, graphviz, mermaid, nomnoml, nwdiag, packetdiag, pikchr, plantuml, rackdiag, structurizr, seqdiag, svgbob, umlet, vega, vegalite, wavedrom).

The diagram type can be automatically derived from the file extension (as same as type). Additional supported extensions:

Extension Type
*.bob svgbob
*.c4 c4plantuml
*.c4puml c4plantuml
*.dot graphviz
*.dsl structurizr
*.er erd
*.gv graphviz
*.iuml plantuml
*.pu plantuml
*.puml plantuml
*.uxf umlet
*.vg vega
*.vgl vegalite
*.vl vegalite
*.wsd plantuml

Configuration

  • kroki_url (default https://kroki.io).
  • kroki_output_format (default svg).
  • kroki_inline_svg (dafault False).

Alternatives

kroki's People

Contributors

hason avatar jdillard avatar pypamart avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

kroki's Issues

Rendering structurizr workspace

Structurizr not only uses the DSL to create graphics, but also stores position data of the objects within the workspace.json. These are so far not further usable by kroki, since here only the dsl part can be interprtiert.

Is it planned to be able to interpret the position data vllt also in the future / to be able to parse the workspace.json?

question- when is the 'type' argument required?

looking through the README, the 'type' of the diagram is configured on the directive.
The diagrams also state that when using a diagram file, the 'type' can be inferred from the file extension
The readme contains a plantuml example- in that example the 'type' is not specified. Does this mean the diagram 'type' can also be inferred when using the inline syntax?

Add :name: option for referencing figure with :numref:

Hello,

As a user,
I want to use an reference option,
In order to reference/cite my figure from the text or other document location.

Solution : add '"name": directives.unchanged' in the option_spec of Kroki class located at kroki.py file line 87.

Thank you.

Add support for wireviz

The build fails for wireviz

/workspaces/project/docs/test.rst:4: ERROR: Error in "kroki" directive:
invalid option value: (option: "type"; value: 'wireviz')
'dict_keys' object is not subscriptable.

.. kroki::
    :type: wireviz

        connectors:
        X1:
            type: D-Sub
            subtype: female
            pinlabels: [DCD, RX, TX, DTR, GND, DSR, RTS, CTS, RI]
        X2:
            type: Molex KK 254
            subtype: female
            pinlabels: [GND, RX, TX]

        cables:
        W1:
            gauge: 0.25 mm2
            length: 0.2
            color_code: DIN
            wirecount: 3
            shield: true

        connections:
        -
            - X1: [5,2,3]
            - W1: [1,2,3]
            - X2: [1,3,2]
        -
            - X1: 5
            - W1: s

Hyperlink in mermaid SVG diagram is not working

Hi,

I am using kroki to render the following example mermaid diagram:

graph LR;
    A-->B;
    B-->C;
    C-->D;
    D-->E;
    click A "http://www.github.com" _blank
    click B "http://www.github.com" "Open this in a new tab" _blank
    click C href "http://www.github.com" _blank
    click D href "http://www.github.com" "Open this in a new tab" _blank
Loading

Output in sphinx page:

image

Looks like the hyperlink in SVG is not clickable.

I tried enabling inline SVG in conf.py, but still the same output. Although when I open SVG image alone in the new TAB, hyperlinks work fine.

Am I missing something?

1.3.0: pytest is failing

I'm packaging your module as an rpm package so I'm using the typical PEP517 based build, install and test cycle used on building packages from non-root account.

  • python3 -sBm build -w --no-isolation
  • because I'm calling build with --no-isolation I'm using during all processes only locally installed modules
  • install .whl file in </install/prefix>
  • run pytest with PYTHONPATH pointing to sitearch and sitelib inside </install/prefix>

Here is pytest output:

+ PYTHONPATH=/home/tkloczko/rpmbuild/BUILDROOT/python-sphinxcontrib-kroki-1.3.0-2.fc35.x86_64/usr/lib64/python3.8/site-packages:/home/tkloczko/rpmbuild/BUILDROOT/python-sphinxcontrib-kroki-1.3.0-2.fc35.x86_64/usr/lib/python3.8/site-packages
+ /usr/bin/pytest -ra
=========================================================================== test session starts ============================================================================
platform linux -- Python 3.8.13, pytest-7.1.2, pluggy-1.0.0
libraries: Sphinx-5.1.1, docutils-0.18.1
base tempdir: /tmp/pytest-of-tkloczko/pytest-913
rootdir: /home/tkloczko/rpmbuild/BUILD/kroki-1.3.0, configfile: pyproject.toml
collected 1 item

tests/test_kroki.py F                                                                                                                                                [100%]

================================================================================= FAILURES =================================================================================
_____________________________________________________________________________ test_kroki_html ______________________________________________________________________________

builder = <sphinx.builders.html.StandaloneHTMLBuilder object at 0x7f4400c59d90>, diagram_type = 'mermaid', diagram_source = 'graph TD\n  A[ Anyone ]', output_format = 'svg'
diagram_options = {}, prefix = 'kroki'

    def render_kroki(
        builder: Builder,
        diagram_type: str,
        diagram_source: str,
        output_format: str,
        diagram_options: Dict[str, Any] = {},
        prefix: str = "kroki",
    ) -> Path:
        kroki_url: str = builder.config.kroki_url
        payload: Dict[str, Union[str, Dict]] = {
            "diagram_source": diagram_source,
            "diagram_type": diagram_type,
            "diagram_options": diagram_options,
            "output_format": output_format,
        }

        hashkey = (str(kroki_url) + str(payload)).encode()
        fname = "%s-%s.%s" % (prefix, sha1(hashkey).hexdigest(), output_format)
        outfn = Path(builder.outdir).joinpath(builder.imagedir, fname)

        if outfn.is_file():
            return outfn

        try:
            outfn.parent.mkdir(parents=True, exist_ok=True)

            response = requests.post(kroki_url, json=payload, stream=True)
>           response.raise_for_status()

../../BUILDROOT/python-sphinxcontrib-kroki-1.3.0-2.fc35.x86_64/usr/lib/python3.8/site-packages/sphinxcontrib/kroki/kroki.py:269:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <Response [500]>

    def raise_for_status(self):
        """Raises :class:`HTTPError`, if one occurred."""

        http_error_msg = ""
        if isinstance(self.reason, bytes):
            # We attempt to decode utf-8 first because some servers
            # choose to localize their reason strings. If the string
            # isn't utf-8, we fall back to iso-8859-1 for all other
            # encodings. (See PR #3538)
            try:
                reason = self.reason.decode("utf-8")
            except UnicodeDecodeError:
                reason = self.reason.decode("iso-8859-1")
        else:
            reason = self.reason

        if 400 <= self.status_code < 500:
            http_error_msg = (
                f"{self.status_code} Client Error: {reason} for url: {self.url}"
            )

        elif 500 <= self.status_code < 600:
            http_error_msg = (
                f"{self.status_code} Server Error: {reason} for url: {self.url}"
            )

        if http_error_msg:
>           raise HTTPError(http_error_msg, response=self)
E           requests.exceptions.HTTPError: 500 Server Error: Internal Server Error for url: https://kroki.io/

/usr/lib/python3.8/site-packages/requests/models.py:1021: HTTPError

The above exception was the direct cause of the following exception:

self = <sphinxcontrib.kroki.transform.KrokiToImageTransform object at 0x7f4400c5ff10>, node = <kroki: >, prefix = 'kroki'

    def render(self, node: kroki, prefix: str = "kroki") -> Path:
        builder = self.app.builder
        output_format = self.output_format(node)
        diagram_type = node["type"]
        diagram_source = node["source"]
        diagram_options = node["options"] if "options" in node else {}

        try:
>           out = render_kroki(
                builder,
                diagram_type,
                diagram_source,
                output_format,
                diagram_options,
                prefix,
            )

../../BUILDROOT/python-sphinxcontrib-kroki-1.3.0-2.fc35.x86_64/usr/lib/python3.8/site-packages/sphinxcontrib/kroki/transform.py:44:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

builder = <sphinx.builders.html.StandaloneHTMLBuilder object at 0x7f4400c59d90>, diagram_type = 'mermaid', diagram_source = 'graph TD\n  A[ Anyone ]', output_format = 'svg'
diagram_options = {}, prefix = 'kroki'

    def render_kroki(
        builder: Builder,
        diagram_type: str,
        diagram_source: str,
        output_format: str,
        diagram_options: Dict[str, Any] = {},
        prefix: str = "kroki",
    ) -> Path:
        kroki_url: str = builder.config.kroki_url
        payload: Dict[str, Union[str, Dict]] = {
            "diagram_source": diagram_source,
            "diagram_type": diagram_type,
            "diagram_options": diagram_options,
            "output_format": output_format,
        }

        hashkey = (str(kroki_url) + str(payload)).encode()
        fname = "%s-%s.%s" % (prefix, sha1(hashkey).hexdigest(), output_format)
        outfn = Path(builder.outdir).joinpath(builder.imagedir, fname)

        if outfn.is_file():
            return outfn

        try:
            outfn.parent.mkdir(parents=True, exist_ok=True)

            response = requests.post(kroki_url, json=payload, stream=True)
            response.raise_for_status()
            with outfn.open(mode="wb") as f:
                for chunk in response.iter_content(chunk_size=128):
                    f.write(chunk)

            return outfn
        except requests.exceptions.RequestException as e:
>           raise KrokiError(__("kroki did not produce a diagram")) from e
E           sphinxcontrib.kroki.kroki.KrokiError: kroki did not produce a diagram

../../BUILDROOT/python-sphinxcontrib-kroki-1.3.0-2.fc35.x86_64/usr/lib/python3.8/site-packages/sphinxcontrib/kroki/kroki.py:276: KrokiError

The above exception was the direct cause of the following exception:

app = <SphinxTestApp buildername='html'>, status = <_io.StringIO object at 0x7f4401baf3a0>, warning = <_io.StringIO object at 0x7f4401baf430>

    @pytest.mark.sphinx(
        "html", testroot="kroki", confoverrides={"master_doc": "index"}
    )
    def test_kroki_html(app, status, warning):
>       content = get_content(app)

tests/test_kroki.py:24:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
tests/test_kroki.py:14: in get_content
    app.builder.build_all()
/usr/lib/python3.8/site-packages/sphinx/builders/__init__.py:265: in build_all
    self.build(None, summary=__('all source files'), method='all')
/usr/lib/python3.8/site-packages/sphinx/builders/__init__.py:317: in build
    updated_docnames = set(self.read())
/usr/lib/python3.8/site-packages/sphinx/builders/__init__.py:424: in read
    self._read_serial(docnames)
/usr/lib/python3.8/site-packages/sphinx/builders/__init__.py:445: in _read_serial
    self.read_doc(docname)
/usr/lib/python3.8/site-packages/sphinx/builders/__init__.py:498: in read_doc
    publisher.publish()
/usr/lib/python3.8/site-packages/docutils/core.py:219: in publish
    self.apply_transforms()
/usr/lib/python3.8/site-packages/docutils/core.py:200: in apply_transforms
    self.document.transformer.apply_transforms()
/usr/lib/python3.8/site-packages/sphinx/transforms/__init__.py:80: in apply_transforms
    super().apply_transforms()
/usr/lib/python3.8/site-packages/docutils/transforms/__init__.py:171: in apply_transforms
    transform.apply(**kwargs)
../../BUILDROOT/python-sphinxcontrib-kroki-1.3.0-2.fc35.x86_64/usr/lib/python3.8/site-packages/sphinxcontrib/kroki/transform.py:26: in apply
    out = self.render(node)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <sphinxcontrib.kroki.transform.KrokiToImageTransform object at 0x7f4400c5ff10>, node = <kroki: >, prefix = 'kroki'

    def render(self, node: kroki, prefix: str = "kroki") -> Path:
        builder = self.app.builder
        output_format = self.output_format(node)
        diagram_type = node["type"]
        diagram_source = node["source"]
        diagram_options = node["options"] if "options" in node else {}

        try:
            out = render_kroki(
                builder,
                diagram_type,
                diagram_source,
                output_format,
                diagram_options,
                prefix,
            )
        except KrokiError as exc:
            logger.warning(
                __("kroki %s diagram (%s) with source %r: %s"),
                diagram_type,
                output_format,
                diagram_source,
                exc,
            )
>           raise SkipNode from exc
E           docutils.nodes.SkipNode

../../BUILDROOT/python-sphinxcontrib-kroki-1.3.0-2.fc35.x86_64/usr/lib/python3.8/site-packages/sphinxcontrib/kroki/transform.py:60: SkipNode
------------------------------------------------------------------------- Captured stdout teardown -------------------------------------------------------------------------
# testroot: root
# builder: html
# srcdir: /tmp/pytest-of-tkloczko/pytest-913/kroki
# outdir: /tmp/pytest-of-tkloczko/pytest-913/kroki/_build/html
# status:
Running Sphinx v5.1.1
building [html]: all source files
updating environment: [new config] 1 added, 0 changed, 0 removed
reading sources... [100%] index
# warning:
WARNING: kroki mermaid diagram (svg) with source 'graph TD\n  A[ Anyone ]': kroki did not produce a diagram

============================================================================= warnings summary =============================================================================
tests/test_kroki.py::test_kroki_html
  /home/tkloczko/rpmbuild/BUILDROOT/python-sphinxcontrib-kroki-1.3.0-2.fc35.x86_64/usr/lib/python3.8/site-packages/sphinxcontrib/kroki/transform.py:17: PendingDeprecationWarning: nodes.Node.traverse() is obsoleted by Node.findall().
    for node in self.document.traverse(kroki):

-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
========================================================================= short test summary info ==========================================================================
FAILED tests/test_kroki.py::test_kroki_html - docutils.nodes.SkipNode
======================================================================= 1 failed, 1 warning in 0.91s =======================================================================

Here is list of modules installed in build env:

Package                       Version
----------------------------- -----------------
alabaster                     0.7.12
attrs                         22.1.0
Babel                         2.10.2
Brlapi                        0.8.3
build                         0.8.0
charset-normalizer            2.1.0
codespell                     2.1.0
cycler                        0.11.0
distro                        1.7.0
docutils                      0.18.1
extras                        1.0.0
fixtures                      4.0.0
flit_core                     3.7.1
fonttools                     4.37.1
gpg                           1.17.1-unknown
idna                          3.3
imagesize                     1.4.1
importlib-metadata            4.12.0
iniconfig                     1.1.1
Jinja2                        3.1.1
kiwisolver                    1.4.4
libcomps                      0.1.18
louis                         3.22.0
MarkupSafe                    2.1.1
matplotlib                    3.5.3
numpy                         1.23.1
olefile                       0.46
packaging                     21.3
pbr                           5.9.0
pep517                        0.12.0
Pillow                        9.2.0
pip                           22.2.1
pluggy                        1.0.0
py                            1.11.0
Pygments                      2.13.0
PyGObject                     3.42.2
pyparsing                     3.0.9
pytest                        7.1.2
python-dateutil               2.8.2
pytz                          2022.1
PyYAML                        6.0
requests                      2.28.1
rpm                           4.17.0
setuptools                    65.3.0
six                           1.16.0
snowballstemmer               2.2.0
Sphinx                        5.1.1
sphinxcontrib-applehelp       1.0.2.dev20220730
sphinxcontrib-devhelp         1.0.2.dev20220730
sphinxcontrib-htmlhelp        2.0.0
sphinxcontrib-jsmath          1.0.1.dev20220730
sphinxcontrib-qthelp          1.0.3.dev20220730
sphinxcontrib-serializinghtml 1.1.5
testtools                     2.5.0
tomli                         2.0.1
urllib3                       1.26.12
wheel                         0.37.1
zipp                          3.8.1

Kroki not supported in Latex builder

Unable to build latex documents when kroki directives are present, even with the sphinxcontrib-svg2pdfconverter extension installed.

writing... failed

Exception occurred:
File "c:<snip>\venv\lib\site-packages\sphinx\writers\latex.py", line 2044, in unknown_visit
raise NotImplementedError('Unknown node: ' + node.class.name)
NotImplementedError: Unknown node: kroki

Rendering structurizr graphic with includes fails

Watching the payload of sphinx->kroki and a quick view into the (nice) code (btw) leads me to create this issue

In structurizr dsl it is possible to spread a complex graphic/model into separate file using an include.

.. kroki::
   :type: structurizr
   :filename: workspace.dsl
   :options:
      view-key: some-view

with a workspace.dsl like this

!include some_file.dsl

workspace {
    //...
}

Rendering this graphic causes kroki server to fail with

java.lang.RuntimeException: some_file.dsl could not be found

This error message is correct, since the payload of the graphic contains only the workspace.dsl (not the included file).


By now in my eyes two paths are not worse to investigate further:

  • send several files to kroki
  • do the code embedding on sphinx-contrib/kroki side and send as one payload object (nothing more magic seams to be done by the include statement in structurizr dsl)

Does someone (maybe @hason as author, @pypamart as contributer) has a feeling about one over the other?

SVG format with latexpdf and figure size

Hello,

can you please provide an example of how to use this lib with latex and SVG output format? I get this error,

! LaTeX Error: Cannot determine size of graphic in kroki-8b950f35ccb0109a8c0a9e
d6fb9394ab4e1e7eec.svg (no BoundingBox).

Moreover, how I can set the size of the produced figure? The figure is stretched (when using the png format) resulting in poor image quality. It would be really useful if options like with/height/scale were provided (like https://github.com/sphinx-contrib/plantuml)

Latex-Output broken

I made a sample page. HTML-Output works fine. Building latexpdf always returns the error:
Latexmk: Missing input file: '{kroki-3a635e48c50e44520508cf7da4fece5094219393}.svg' from line

Looking at the tex-file it seems, that the filename is enclosed with "{}" which seems to be a bug.

grep kroki build/latex/sampledoc.tex
\noindent\sphinxincludegraphics{{kroki-3a635e48c50e44520508cf7da4fece5094219393}.svg}

I am not able to open a PR since i am not good enough in python to deliver one.

Scale generated diagram in sphinx docs / make it zoomable

Hi, is there a way to scale the generated diagram in a sphinx document, e.g. something like:

 .. kroki:: ./puml/file.puml 
    :scale: 50%

A related issue is that setting a scale in a sphinx image directive would make the image clickable, allowing an implicit zooming functionality. Is there a way to achieve something similar with this extension? Thank you in advance!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.