Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
62eac24
Add toolchain definitions and command builder
ea42gh Jan 1, 2026
f481527
Add toolchain definitions and command builder
ea42gh Jan 1, 2026
00e12c7
Execute toolchains in temp dir (minimal)
ea42gh Jan 1, 2026
1b06a57
Add golden SVG test for render_svg
ea42gh Jan 1, 2026
be4da9b
crop and normalize added
ea42gh Jan 1, 2026
17173b1
render and crp
ea42gh Jan 1, 2026
b8af811
keep intermediate files
ea42gh Jan 2, 2026
5243ccc
fixed "
ea42gh Jan 3, 2026
f7da159
fixed "
ea42gh Jan 3, 2026
f9a00fc
fixed quoting
ea42gh Jan 3, 2026
1d413ff
added toolchain
ea42gh Jan 3, 2026
d42ee23
cropping
ea42gh Jan 3, 2026
67786e0
padding and cropping
ea42gh Jan 4, 2026
7f11048
padding pytest passes, need checking
ea42gh Jan 4, 2026
0885628
working padding
ea42gh Jan 4, 2026
5147ba8
cropping, bounds, frame around plot!
ea42gh Jan 4, 2026
99505f8
added svg box
ea42gh Jan 4, 2026
0f1c30b
svg string output fix
ea42gh Jan 4, 2026
ecc12a5
migration step
ea42gh Jan 7, 2026
a779071
added tests to prevent regression
ea42gh Jan 7, 2026
0d59445
migration step
ea42gh Jan 7, 2026
5f3b290
migration step
ea42gh Jan 7, 2026
704ce1c
migration step
ea42gh Jan 7, 2026
de2f7e1
migration step
ea42gh Jan 7, 2026
f8d47cc
migration step
ea42gh Jan 7, 2026
ba753c6
migration step
ea42gh Jan 7, 2026
798e76a
rename
ea42gh Jan 7, 2026
3a71336
migration step
ea42gh Jan 7, 2026
a3479f5
improve documentation
ea42gh Jan 22, 2026
4c09c5c
test functions pass
ea42gh Jan 23, 2026
beaa17e
Harden subprocess execution and align core rendering behavior
ea42gh Feb 14, 2026
b65d684
Expand regression coverage for command execution, SVG normalization, …
ea42gh Feb 14, 2026
0bff5d9
Update docs for toolchain behavior, troubleshooting, and security cha…
ea42gh Feb 14, 2026
c7c8a8a
Refresh documentation notebooks for current API and cleanup workflow
ea42gh Feb 14, 2026
85b5ce1
Improve executor result typing and diagnostic consistency
ea42gh Feb 14, 2026
2cb8fac
Refactor jupyter_tikz module into focused components with facade comp…
ea42gh Feb 14, 2026
fed8c5d
Improve TEXINPUTS defaults for relative TeX inputs and update docs/tests
ea42gh Feb 14, 2026
994ea3e
Add keep-temp output-dir support and align versioning/docs
ea42gh Feb 14, 2026
7e7e586
Refactor validation paths, strengthen CI checks, and update docs/note…
ea42gh Feb 14, 2026
199077c
text ocument fix
ea42gh Feb 17, 2026
3e5c11d
text ocument fix
ea42gh Feb 17, 2026
c76400e
text ocument fix
ea42gh Feb 17, 2026
afde445
text documentation build fix
ea42gh Feb 17, 2026
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
91 changes: 85 additions & 6 deletions .github/workflows/python-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,97 @@ name: Test Python package
on: [push, pull_request]

jobs:
test:
lint-type:
name: Lint and Type Checks
runs-on: ubuntu-latest


steps:
- uses: actions/checkout@v4

- name: Set up Python 3.10
uses: actions/setup-python@v5
with:
python-version: "3.10"

- name: Install poetry
run: pip install poetry

- name: Install dependencies
run: poetry install --without doc

- name: Run ruff
run: poetry run task lint_check

- name: Run mypy subset
run: poetry run task type_check

validation-cross-platform:
name: Validation tests (${{ matrix.os }})
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest]
runs-on: ${{ matrix.os }}

steps:
- uses: actions/checkout@v4

- name: Set up Python 3.10
uses: actions/setup-python@v5
with:
python-version: "3.10"

- name: Install poetry
run: pip install poetry

- name: Install dependencies
run: poetry install --without doc

- name: Run validation/unit contract tests
run: poetry run pytest -q tests/test_args.py tests/test_magic_params.py tests/test_toolchains.py tests/test_executor.py tests/test_help_snapshot.py tests/test_diagnostics_contract.py

test:
strategy:
fail-fast: false
matrix:
include:
- tex_engine: pdflatex
default_toolchain: pdftex_pdftocairo
include_xetex: false
include_luatex: false
experimental: false
- tex_engine: xelatex
default_toolchain: xelatex_pdftocairo
include_xetex: true
include_luatex: false
experimental: false
- tex_engine: lualatex
default_toolchain: pdftex_pdftocairo
include_xetex: false
include_luatex: true
experimental: true
continue-on-error: ${{ matrix.experimental }}
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- name: Install LaTeX and Poppler
run: |
sudo apt update
sudo apt install -y texlive-latex-extra texlive-luatex poppler-utils

sudo apt install -y texlive-latex-extra poppler-utils
if [ "${{ matrix.include_xetex }}" = "true" ]; then
sudo apt install -y texlive-xetex
fi
if [ "${{ matrix.include_luatex }}" = "true" ]; then
sudo apt install -y texlive-luatex
fi

- name: Set up Python 3.10
uses: actions/setup-python@v5
with:
python-version: '3.10'

- name: Install poetry
run: |
pip install poetry
Expand All @@ -28,10 +103,14 @@ jobs:
poetry install --without doc

- name: Run tests
env:
JUPYTER_TIKZ_DEFAULT_TOOLCHAIN: ${{ matrix.default_toolchain }}
JUPYTER_TIKZ_RUN_RENDER_TESTS: "1"
run: |
poetry run task test

- name: Upload coverage to Codecov
if: ${{ !matrix.experimental }}
uses: codecov/codecov-action@v4.0.1
with:
token: ${{ secrets.CODECOV_TOKEN }}
token: ${{ secrets.CODECOV_TOKEN }}
File renamed without changes.
17 changes: 17 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
.PHONY: fmt lint type test ci-local

fmt:
poetry run task fmt

lint:
poetry run task lint_check

type:
poetry run task type_check

test:
poetry run task test

ci-local:
poetry run task ci_local

104 changes: 102 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
Jupyter-TikZ is a Python (3.10+) and IPython Magics library. However, in order for Jupyter-TikZ to work properly, some non-Python dependencies need to be installed first:

- LaTeX
- latexmk
- Poppler

### LaTeX
Expand All @@ -64,6 +65,16 @@ You can test if a LaTeX distribution is installed by using the following command
pdflatex --version
```

### latexmk

The default `%%tikz` / `%tikz` magic rendering path uses `latexmk` to compile TeX.

Check if `latexmk` is available:

```shell
latexmk -v
```

### Poppler

This application requires Poppler's `pdftocairo`. You must install it beforehand.
Expand Down Expand Up @@ -110,6 +121,14 @@ custom_pdftocairo_path = os.path.join(
os.environ["JUPYTER_TIKZ_PDFTOCAIROPATH"] = custom_pdftocairo_path
```

By default, executor-based rendering adds your current working directory to
TeX's search path (`TEXINPUTS`). This allows relative inputs like
`\input{grid.tikz}` and PGFPlots `table {data.tsv}` while still compiling in an
isolated temporary directory. Set `JUPYTER_TIKZ_DISABLE_CWD_TEXINPUTS=1` to opt
out.
`-k`/`--keep-temp` is for retaining build artifacts (debugging), not for
enabling relative file loading.

## Install Jupyter TikZ

You can install `jupyter-tikz` by using the following command in your terminal:
Expand Down Expand Up @@ -218,7 +237,11 @@ All additional options are listed below:
| `-d=<int>`<br>`--dpi=<int>` | DPI to use when rasterizing the image.<br>&nbsp;&nbsp;&nbsp;&nbsp;*Example:* `--dpi=300`.<br>&nbsp;&nbsp;&nbsp;&nbsp;*Defaults* to `-d=96`. |
| `-g`<br>`--gray` | Set grayscale to the rasterized image. |
| `-e`<br>`--full-err` | Print the full error message when an error occurs. |
| `-k`<br>`--keep-temp` | Keep temporary files. |
| `-k[=<dir>]`<br>`--keep-temp[=<dir>]` | Keep temporary files for debugging. Without a value, files are kept in the current directory; with a value, files are kept in the specified directory. |
| `-os=<name>`<br>`--output-stem=<name>` | Override artifact filename stem used by `%tikz`/`%%tikz` execution and kept temp files (`[A-Za-z0-9][A-Za-z0-9._-]*`). |
| `-tc=<name>`<br>`--toolchain=<name>` | Explicitly select executor toolchain.<br>&nbsp;&nbsp;&nbsp;&nbsp;*Example:* `--toolchain=xelatex_pdftocairo`.<br>&nbsp;&nbsp;&nbsp;&nbsp;*Defaults* to auto-resolution from `--tex-program`/environment. |
| `-dg`<br>`--diagnose` | Print toolchain diagnostics and skip rendering. |
| `-j`<br>`--json` | Use JSON diagnostics output. Must be combined with `--diagnose`; using `--json` alone returns an argument error. Legacy `-json` is still accepted. |
| `-tp=<str>`<br>`--tex-program=<str>` | TeX program to use for compilation.<br>&nbsp;&nbsp;&nbsp;&nbsp;*Example:* `-tp=xelatex` or `-tp=lualatex`.<br>&nbsp;&nbsp;&nbsp;&nbsp;*Defaults* to `-tp=pdflatex`. |
| `-ta=<str>`<br>`--tex-args=<str>` | Arguments to pass to the TeX program.<br>&nbsp;&nbsp;&nbsp;&nbsp;*Example:* `-ta "$tex_args_ipython_variable"`.<br>&nbsp;&nbsp;&nbsp;&nbsp;*Defaults* to None. |
| `-nc`<br>`--no-compile` | Do not compile the TeX code. |
Expand All @@ -237,10 +260,87 @@ Contributions are welcome from everyone! Whether you're reporting bugs, submitti
<li>If you're interested in developing the software further, please refer to <a href="https://jupyter-tikz.readthedocs.io/stable/about/development/">development guide</a>.</li>
</ol>

## Local quality commands

To run the same quality gates used by CI:

```bash
make ci-local
```

Or run step-by-step:

```bash
make fmt
make lint
make type
make test
```

# Changelog

All notable changes to this project are presented below.

## Migration notes (vs `main`)

- `artifacts_path` is now directory-only in `render_svg(...)`.
- If you used `artifacts_path` as a filename prefix in `main`, migrate to
`artifacts_prefix`.
- `%tikz --json` now requires `--diagnose`.
`--json` alone is rejected and rendering is skipped.
- Output-path validation is stricter for user-provided paths.
Relative `..` path segments are rejected for `--keep-temp`, save targets,
and `JUPYTER_TIKZ_SAVEDIR`-scoped writes.
- Magic default routing changed for common engines.
`-tp=pdflatex` and `-tp=xelatex` now run through the executor/toolchain
path by default, which may change output details and dependency behavior.
- Public validation now includes typed exceptions:
`InvalidToolchainError`, `InvalidOutputStemError`, `InvalidPathError`
(all are `ValueError` subclasses).
- Toolchain/magic option precedence:
1. `--toolchain` (explicit executor toolchain)
2. `--tex-program` mapping (`pdflatex`/`xelatex`) when `--tex-args` is not set
3. legacy path for other engines or custom `--tex-args`

## Option precedence

| If you provide... | Selected rendering path |
| --- | --- |
| `--toolchain=<name>` | Executor with that exact toolchain |
| no `--toolchain`, `-tp=pdflatex`, no `--tex-args` | Executor `pdftex_pdftocairo` |
| no `--toolchain`, `-tp=xelatex`, no `--tex-args` | Executor `xelatex_pdftocairo` |
| no `--toolchain`, `-tp=lualatex` | Legacy `TexDocument.run_latex` |
| any `--tex-args` (without explicit `--toolchain`) | Legacy `TexDocument.run_latex` |

## Migration cookbook (`main` -> current)

| Common pattern in `main` | Use now |
| --- | --- |
| `render_svg(..., artifacts_path=\"out/demo\")` (prefix-style path) | `render_svg(..., artifacts_prefix=\"out/demo\")` |
| `%tikz --json` | `%tikz --diagnose --json` (or `%tikz -dg -j`) |
| catching generic toolchain/path/stem `ValueError` only | Optionally catch typed errors: `InvalidToolchainError`, `InvalidPathError`, `InvalidOutputStemError` |
| `%tikz -tp=pdflatex` expected legacy path behavior | Expect executor default (`pdftex_pdftocairo`) unless you force legacy via custom `--tex-args` or other engine |
| relative `..` in output targets (e.g. `--keep-temp ../tmp`) | Use a local/safe path (e.g. `--keep-temp outputs/tmp`) or an absolute path |

## v0.5.8

**✨ Improvements**

- Magic rendering now uses the executor/toolchain pipeline by default for `pdflatex` and `xelatex`.
- Hardened legacy command execution by switching from shell command strings to argument-vector subprocess calls.
- Improved executor result typing with a dataclass-based `ExecutionResult` API.
- Standardized uncached-render failures to include the same stderr/log diagnostic tails as artifact-based failures.
- Refactored monolithic `jupyter_tikz.py` into focused internal modules (`args`, `models`, `magic`, `legacy_render`) with backward-compatible facade exports.
- Added default CWD `TEXINPUTS` injection so relative TeX inputs/PGFPlots tables work in temp-build mode (opt out with `JUPYTER_TIKZ_DISABLE_CWD_TEXINPUTS=1`).
- Extended `-k`/`--keep-temp` to accept an optional output directory (e.g., `-k=outputs/tmp`) while preserving existing `-k` behavior.
- Made artifact retention paths consistent: `artifacts_path` now means directory retention, and `artifacts_prefix` provides explicit prefix-based naming.
- Added explicit `--toolchain=<name>` magic option with validation, and diagnostic reporting via `--diagnose`.

**📚 Docs**

- Updated installation and troubleshooting guides to document `latexmk` and toolchain PATH requirements.
- Added notes to the magic usage guide explaining `--tex-program` toolchain mapping and legacy fallback behavior.

## v0.5.6

**✨ Improvements**
Expand Down Expand Up @@ -384,4 +484,4 @@ I had been using [ITikZ](https://github.com/jbn/itikz) for years. However, it do

Copyright 2024 &copy; [Lucas Lima Rodrigues](https://github.com/lucaslrodri).

Distributed under the terms of the [MIT License](https://github.com/lucaslrodri/jupyter-tikz/blob/main/LICENSE), Jupyter-TikZ is free and open-source software.
Distributed under the terms of the [MIT License](https://github.com/lucaslrodri/jupyter-tikz/blob/main/LICENSE), Jupyter-TikZ is free and open-source software.
37 changes: 37 additions & 0 deletions docs/about/changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,42 @@
All notable changes to this project are presented below.

## v0.5.8

**✨ Improvements**

- Magic rendering now uses the executor/toolchain pipeline by default for `pdflatex` and `xelatex`.
- Hardened legacy command execution by switching from shell command strings to argument-vector subprocess calls.
- Improved executor result typing with a dataclass-based `ExecutionResult` API.
- Standardized uncached-render failures to include the same stderr/log diagnostic tails as artifact-based failures.
- Refactored monolithic `jupyter_tikz.py` into focused internal modules (`args`, `models`, `magic`, `legacy_render`) with backward-compatible facade exports.
- Extended `-k`/`--keep-temp` to accept an optional output directory (e.g., `-k=outputs/tmp`) while preserving existing `-k` behavior.
- Made artifact retention paths consistent: `artifacts_path` now means directory retention, and `artifacts_prefix` provides explicit prefix-based naming.
- Added explicit `--toolchain=<name>` magic option with validation, and diagnostic reporting via `--diagnose`.
- `%tikz --json` now requires `--diagnose` (invalid standalone usage is rejected with a clear error).
- Added typed public validation errors for invalid toolchain/path/output-stem inputs and wired them across magic/executor paths.
- Hardened `render_svg_with_artifacts(...)` by validating `output_stem` with the same filename safety rules as `render_svg(...)`.
- Consolidated save-destination validation/resolution into a shared helper used by both magic and legacy save paths.

**🚨 Breaking Changes (vs `main`)**

- `%tikz --json` now requires `--diagnose`; standalone `%tikz --json` is rejected.
- Magic defaults for `-tp=pdflatex` and `-tp=xelatex` now use the executor/toolchain path.
- User-provided output paths reject relative `..` segments for safer write behavior.

**📚 Docs**

- Updated installation and troubleshooting guides to document `latexmk` and toolchain PATH requirements.
- Added notes to the magic usage guide explaining `--tex-program` toolchain mapping and legacy fallback behavior.
- Added concise option-precedence and migration-cookbook sections to README and docs index.
- Added notebook snippets showing expected invalid-path validation errors.

**🧪 Tests / CI**

- Added help-text snapshot tests to detect `%tikz?` argument drift.
- Added diagnostics JSON contract tests for stable machine-readable output shape.
- Added a cross-platform (Linux/Windows) CI validation job for argument/diagnostics/validation tests.
- Added CI enforcement for stricter lint and type checks (`ruff` and a focused `mypy` subset on core modules).

## v0.5.6

**✨ Improvements**
Expand Down
4 changes: 2 additions & 2 deletions docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ This package provides two classes to create and render LaTeX documents:
- `TexDocument`: Create and render a LaTeX document given the full LaTeX code
- `TexFragment`: Create and render a LaTeX standalone document given a LaTeX fragment or a TikZ Picture.

::: jupyter_tikz.TexDocument
::: jupyter_tikz.models.TexDocument

::: jupyter_tikz.TexFragment
::: jupyter_tikz.models.TexFragment
25 changes: 23 additions & 2 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,26 @@ hide:

{% include "templates/basic-usage.md" %}

## Option precedence

| If you provide... | Selected rendering path |
| --- | --- |
| `--toolchain=<name>` | Executor with that exact toolchain |
| no `--toolchain`, `-tp=pdflatex`, no `--tex-args` | Executor `pdftex_pdftocairo` |
| no `--toolchain`, `-tp=xelatex`, no `--tex-args` | Executor `xelatex_pdftocairo` |
| no `--toolchain`, `-tp=lualatex` | Legacy `TexDocument.run_latex` |
| any `--tex-args` (without explicit `--toolchain`) | Legacy `TexDocument.run_latex` |

## Migration cookbook (`main` -> current)

| Common pattern in `main` | Use now |
| --- | --- |
| `render_svg(..., artifacts_path="out/demo")` (prefix-style path) | `render_svg(..., artifacts_prefix="out/demo")` |
| `%tikz --json` | `%tikz --diagnose --json` (or `%tikz -dg -j`) |
| Catching generic toolchain/path/stem `ValueError` only | Optionally catch typed errors: `InvalidToolchainError`, `InvalidPathError`, `InvalidOutputStemError` |
| `%tikz -tp=pdflatex` expected legacy path behavior | Expect executor default (`pdftex_pdftocairo`) unless you force legacy via custom `--tex-args` or other engine |
| relative `..` in output targets (e.g. `--keep-temp ../tmp`) | Use a local/safe path (e.g. `--keep-temp outputs/tmp`) or an absolute path |

## Next steps

Choose the following links to continue your journey:
Expand All @@ -62,7 +82,8 @@ Explore additional resources and related links for this project:
<div class="grid">
{% for href, icon, text in [
("https://pypi.org/project/jupyter-tikz/", "python", "<strong>PyPI</strong> page"),
("https://github.com/lucaslrodri/jupyter-tikz/blob/main/notebooks/GettingStarted.ipynb", "jupyter", "Getting Started <strong>notebook</strong>"),
("notebooks/GettingStarted.ipynb", "jupyter", "Getting Started <strong>notebook</strong>"),
("notebooks/Enhancements.ipynb", "jupyter", "Enhanced capabilities <strong>notebook</strong>"),
("https://github.com/lucaslrodri/jupyter-tikz/", "github", "<strong>Source code</strong> in Github"),
("https://github.com/lucaslrodri/jupyter-tikz/issues/", "issues", "Github <strong>issues</strong> page")
] %}
Expand All @@ -80,4 +101,4 @@ Explore additional resources and related links for this project:

## License

{% include "templates/copyright.md" %}
{% include "templates/copyright.md" %}
Loading