Repository navigation
Let packages supply a mark look (ainotate.looks entry point) - #5
Closed
testy-cool wants to merge 1 commit into
Closed
testy-cool wants to merge 1 commit into
testy-cool wants to merge 1 commit into
Conversation
People want marks that look different from AInotate's bold default, for
example a calm hand-drawn style. Building each style into AInotate would
add fonts and drawing code to every install. A plug-in point keeps AInotate
small: a look lives in its own package and is used only where installed.
render() now draws every mark through a Look object. The built-in look,
the only one shipped, is `ainotate.looks.Look` (also importable from
ainotate.render). It holds exactly the drawing calls render() made before:
colors, label font and size, labels and text notes, outlines, step badges,
arrows, highlights, the spotlight dim and corner, the redaction fill, the
keycap font, the magnifier line width and the drop shadow. A package
registers a subclass under the entry point group "ainotate.looks" and
overrides what it changes. A look can change a redaction's color, never
its area.
The look is chosen by spec "look" (also --look on annotate and shoot, and
the `look` argument of the MCP annotate, preview and shoot tools), then the
env AINOTATE_LOOK, then `look` in config.toml, then "default", the same
order as the output folder. A look never breaks a render: when it is not
installed, cannot be imported, raises while being constructed or raises
while drawing, the default look is used and the render gets a warning
that names the look and the error, or lists the installed looks. The
warning reaches users like every render warning: result.warnings, the
CLI's WARN lines and the MCP result's warnings. A failure while drawing
redraws the whole image with the default look, so a half-drawn mix never
ships.
A look can never change a redaction or the caller's spec. An installed
look gets its own copies of the page, marks, rects and points, and its
own copy of the page image in every hook that is handed it, so nothing
it changes reaches the render, the redo or the spec. Every value render()
reads from it (attributes such as shadow and stroke, and the results of
color, redact_fill, label_size and keys_font) is read and checked inside
the same guard, so an attribute that raises or a value Pillow cannot
draw ("not-a-color"), or a number that is not finite, is a failure of the
look, with the same fallback; a color name such as "info" is passed on as
the color it names. As a last line, when an installed look is in use and
anything else raises, even AInotate's own code on a value the look gave
it, the image is redrawn from the spec with the default look and a
warning. An error the default look hits as well is AInotate's or the
spec's, and is raised as before.
The spec reference, the renderer notes served as ainotate://spec, the MCP
fallback summary and a description on the MCP `look` parameter say how to
pick a look.
Testing: the default look is pixel-identical. A test pins the sha256 of
a render of every mark type, light and dark, from before this change
(Pillow 12.3.0 / FreeType 2.14.3; other versions skip the pin). The
golden label-position test is unchanged but needs macOS Helvetica and
skips on Linux; run with DejaVu Sans Bold instead, its three specs give
the same label boxes and identical images on origin/main and this branch.
New tests register a fake look and check that it draws, that the flag,
env and config pick it, each fallback with its exact warning, the CLI
and MCP output, the MCP schema text, that looks which change their
geometry, spec data or page image leave redactions and the spec intact,
that a raising attribute, bad hook results, an infinite shadow and a
label size no frame can hold fall back, that a color name works, and that
an error the default look also hits is still raised.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
visul
added a commit
that referenced
this pull request
Oct 10, 2026
#6) Rebases testy-cool's #5 onto main: the look hook from #4 is replaced by this version, which also recovers when a look fails mid-draw. Default renders stay pixel-identical (per-platform pins kept from #4; golden tests pass on macOS). Co-authored-by: testy-cool <202153476+testy-cool@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Contributor
|
Thanks! #4 had already shipped the first version of the look hook in 0.1.8, so this branch conflicted with main. I rebased it in #6 (merged, with you as co-author): your |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Option 1 from #3: an
ainotate.looksentry point, so a package can supply a mark look. The default look stays the only one built in; no font and no neat code here.Your four checks:
tests/test_golden.pyis unmodified. It skips on Linux (needs Helvetica Neue), so we also compared renders of all 12 mark types, light and dark, againstmain: 52 comparisons, zero differing pixels. Please run the golden tests on your Mac.warningsandresult.warnings:spec.mdhas a "Looks" paragraph; the MCPannotate,previewandshoottools document theirlookargument.cli.pyandmcp_server.pyat 485,render.pyat 426. The look plumbing lives in a newlooks.py(191).Picking a look:
"look"in a spec,--look, or the MCPlookargument; otherwiseAINOTATE_LOOK, thenlookin the config file, thendefault.Tests: 617 passed (
tests/test_privacy.py::test_dom_fixturefails on Linux onmaintoo). The neat package's 36 tests pass against this branch.🤖 Generated with Claude Code