diff --git a/Dockerfile b/Dockerfile index ff1b0b7..0889aca 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,19 +1,22 @@ -# Use Python 3.9 as the base image -FROM python:3.9-slim +FROM ubuntu:24.04 + +ENV DEBIAN_FRONTEND=noninteractive +ENV DRAWIO_VERSION=26.0.9 # Set the working directory WORKDIR /app -# Install system dependencies for WeasyPrint +# Install system dependencies for WeasyPrint and Draw.io RUN apt-get update && \ - apt-get install -y \ + apt-get install -y --no-install-recommends \ build-essential \ - libpango1.0-0 \ + libpango-1.0-0 \ + libpangocairo-1.0-0 \ libcairo2 \ libgdk-pixbuf2.0-0 \ libffi-dev \ shared-mime-info \ - libjpeg62-turbo \ + libjpeg-turbo8 \ libpng-dev \ libxml2-dev \ libxslt1-dev \ @@ -27,20 +30,32 @@ RUN apt-get update && \ plantuml \ wget \ unzip \ + xvfb \ + dbus \ + dbus-x11 \ + libgtk-3-0 \ + libxtst6 \ + libnss3 \ + libasound2t64 \ + libxss1 \ + libgbm1 \ + ca-certificates \ + libnotify4 \ + xdg-utils \ + libsecret-1-0 \ + graphviz \ && apt-get clean -# Detect architecture and install the correct version of Pandoc -RUN apt-get update && apt-get install -y wget && apt-get clean && \ - wget https://github.com/jgm/pandoc/releases/download/2.5/pandoc-2.5-linux.tar.gz && \ - tar xvfz pandoc-2.5-linux.tar.gz && \ - mv pandoc-2.5/bin/pandoc /usr/local/bin/ && \ - mv pandoc-2.5/bin/pandoc-citeproc /usr/local/bin/ && \ - rm -rf pandoc-2.5 pandoc-2.5-linux.tar.gz; +# Install Python and pip +RUN apt-get update && apt-get install -y python3 python3-pip python3-venv && apt-get clean + +# Create a virtual environment +RUN python3 -m venv /venv -# Install MkDocs and the specified plugins and extensions -RUN pip install --no-cache-dir mkdocs==1.2.4 \ +# Activate the virtual environment and install dependencies +RUN /venv/bin/pip install --no-cache-dir mkdocs==1.2.4 \ mkdocs-izsam-search==0.1.8 \ - mkdocs-bionformatic-izsam-theme==1.0.4 \ + mkdocs-bionformatic-izsam-theme==1.0.5 \ mkdocs-izsam-video==1.0.3 \ mkdocs-redirects==1.2.0 \ mkdocs-izsam-mermaid-to-images==1.0.8 \ @@ -52,14 +67,38 @@ RUN pip install --no-cache-dir mkdocs==1.2.4 \ qrcode==7.3.1 \ weasyprint==62.3 +# Ensure the virtual environment is activated when running commands +ENV PATH="/venv/bin:$PATH" + # Copy the bin folder (including sh directory) into the Docker image COPY . /app -RUN pip install -e /app/plugins/custom +# Install custom plugins +RUN /venv/bin/pip install -e /app/plugins/custom # Set the working directory back to /app WORKDIR /app +# Detect architecture and install the correct version of Pandoc +RUN apt-get update && \ + apt-get install -y wget && \ + apt-get clean && \ + wget https://github.com/jgm/pandoc/releases/download/2.5/pandoc-2.5-linux.tar.gz && \ + tar xvfz pandoc-2.5-linux.tar.gz && \ + mv pandoc-2.5/bin/pandoc /usr/local/bin/ && \ + mv pandoc-2.5/bin/pandoc-citeproc /usr/local/bin/ && \ + rm -rf pandoc-2.5 pandoc-2.5-linux.tar.gz + +# Install draw.io +RUN wget -q https://github.com/jgraph/drawio-desktop/releases/download/v${DRAWIO_VERSION}/drawio-amd64-${DRAWIO_VERSION}.deb && \ + dpkg -i drawio-amd64-${DRAWIO_VERSION}.deb || apt-get -f install -y && \ + rm -f drawio-amd64-${DRAWIO_VERSION}.deb + +# Copy draw.io conversion script +COPY bin/sh/drawio-converter.sh /usr/local/bin/drawio-converter +# Ensure it is executable +RUN chmod +x /usr/local/bin/drawio-converter + # Ensure the entrypoint.sh file has the correct permissions to be executed RUN chmod +x /app/entrypoint.sh diff --git a/bin/sh/drawio-converter.sh b/bin/sh/drawio-converter.sh new file mode 100644 index 0000000..9b9913a --- /dev/null +++ b/bin/sh/drawio-converter.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +# Start dbus if not already running +if [ ! -e /var/run/dbus/pid ]; then + mkdir -p /var/run/dbus + dbus-daemon --system --fork +fi + +if [ "$1" = "-x" ] && [ "$2" = "-f" ] && [ -n "$3" ] && [ "$4" = "-o" ] && [ -n "$5" ] && [ -n "$6" ]; then + dbus-run-session -- xvfb-run drawio --no-sandbox -x -f "$3" -o "$5" "$6" --disable-gpu + exit $? +else + dbus-run-session -- xvfb-run drawio --no-sandbox "$@" +fi diff --git a/entrypoint.sh b/entrypoint.sh index 71f31b0..ddaf388 100755 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -45,4 +45,9 @@ if [ "$1" = "build" ]; then echo "#####################################################################" else exec "$@" +fi + +# Ensure draw.io script is executable +if [ ! -x /usr/local/bin/drawio-converter ]; then + chmod +x /usr/local/bin/drawio-converter fi \ No newline at end of file diff --git a/plugins/init/README.md b/plugins/init/README.md index eff21dc..5bc0834 100644 --- a/plugins/init/README.md +++ b/plugins/init/README.md @@ -4,6 +4,32 @@ The `main.py` file collect all macros available to be used inside Mkdocs file (docs, themes, configuration). Available macros: +### def drawio_export(drawio_file, alt="drawio diagram", fmt=None) + +Convert a .drawio file to an image (SVG/PNG/etc.) via drawio-converter CLI. + +#### Args + +* `drawio_file (str)`: The path to the .drawio file. +* `alt (str)`: The alt text for the image. Defaults to "drawio diagram". +* `fmt (str, optional)`: The format of the output image (e.g., "svg", "png"). Defaults to the value specified in the MkDocs configuration (`extra.drawio_output_format`). If not specified in the configuration, defaults to "svg". + +#### Returns + +```html +{alt} +``` + +#### How to use + +To be used inside `.md` files with the following syntax: + +```markdown +{{ drawio_export("diagram.drawio") }} +{{ drawio_export("diagram.drawio", "some alt text") }} +{{ drawio_export("diagram.drawio", "some alt text", "png") }} +``` + ### def button(text, link) Generates HTML code for a button that opens a link in a new window. diff --git a/plugins/init/main.py b/plugins/init/main.py index 5a32834..2473ac1 100644 --- a/plugins/init/main.py +++ b/plugins/init/main.py @@ -1,8 +1,75 @@ -import markdown import os +import markdown +import shutil +import subprocess +from pathlib import Path def define_env(env): + @env.macro + def drawio_export(drawio_file, alt="drawio diagram", fmt=None): + """ + Convert a .drawio file to an image (SVG/PNG/etc.) via drawio-converter CLI. + + This macro uses an extra configuration parameter in mkdocs.yml: + extra: + drawio_output_format: svg + or in your PDF config: + extra: + drawio_output_format: png + + Usage: + {{ drawio_export("diagram.drawio") }} + {{ drawio_export("diagram.drawio", "some alt text") }} + {{ drawio_export("diagram.drawio", "some alt text", "png") }} + """ + if not env.page: + return f"Error: No page context for {drawio_file}" + + # Read default format from mkdocs config, fallback to 'svg' if not found + config_default_format = env.conf.get("extra", {}).get("drawio_output_format", "svg") + + # If caller didn't supply a format, use the config default + if fmt is None: + fmt = config_default_format + + # If neither the config nor the caller supplied a format, use 'svg' as the default + if fmt is None: + fmt = "svg" + + # Directory of the .md file being processed + page_dir = Path(env.page.file.abs_src_path).parent + + # Full path to the .drawio file + src_path = page_dir / drawio_file + if not src_path.is_file(): + return f"Error: {drawio_file} not found at {src_path}" + + # Output directory under site_dir relative to the current page + output_dir = Path(env.conf['site_dir']) / Path(env.page.url).parent / 'drawio' + output_dir.mkdir(parents=True, exist_ok=True) + final_out_path = output_dir / (src_path.stem + f".{fmt}") + + # Run drawio-converter + try: + result = subprocess.run([ + "drawio-converter", + "-x", # export + "-f", fmt, # format + "-o", str(final_out_path), + str(src_path) + ], check=True, capture_output=True, text=True) + except subprocess.CalledProcessError as e: + return f"Error: Conversion failed for {drawio_file}. {e}" + + # Verify output actually got created + if not final_out_path.exists(): + return f"Error: {final_out_path.name} was not created." + + # Return relative path from the page's directory + relative_out_path = final_out_path.relative_to(Path(env.conf['site_dir']) / Path(env.page.url).parent) + return f'{alt}' + @env.macro def button(text, link): """