Why recipes cannot run code
A shotlist recipe is data. There is no step that evaluates JavaScript, no expression language, and no escape hatch into the page's runtime. This page explains the reasoning, and what it costs.
The problem an escape hatch solves, and creates
Every screenshot tool that drives a browser eventually meets a page it cannot describe: a canvas that has to be primed, a component that only settles after an internal event, a value that has to be computed. The usual answer is an eval step, and it works immediately.
It also changes what the file is. A recipe with one line of JavaScript in it is no longer a description of a screenshot; it is a program that happens to produce one. That difference shows up in four places.
Who can fix a broken screenshot
Documentation screenshots break for boring reasons, usually a button that was renamed. If the recipe is data, the person who renamed the button can read the file and fix it, whatever their role. If the recipe contains code, fixing it becomes a task for whoever is comfortable reading that code, and in practice it waits.
What review can catch
A change to a recipe can be reviewed by reading it. A step list has a fixed vocabulary, so a reviewer knows what the whole file is capable of. Arbitrary code has no such bound, and reviewing it means reasoning about what it could do rather than what it says.
What can be validated ahead of time
Because recipes are data, they can be checked against a schema before anything runs. shotlist ships those schemas, editors use them for completion, and a malformed recipe is rejected at parse time rather than halfway through a run that has already written files. Code can only be validated by running it.
What a configuration is allowed to do
A recipe you did not write is often something you have to run anyway: a pull request from a fork, a submission to a hosted service. With no evaluation step, the worst a recipe can do is bounded by the step vocabulary and by the limits described in What a configuration can do. An eval step would make that analysis worthless, because the answer would always be "anything the browser can do".
What it costs
The cost is real. Some screenshots cannot be described with the current vocabulary, and when that happens there is no workaround available to the person who hit it. They have to wait for a verb to be added.
That is the intended trade. A missing verb is a gap in a language that can be closed once, for everybody, with the screenshot that needed it as the evidence for its design. An escape hatch closes the same gap privately, in one repository, in a way nobody else benefits from and no reviewer can check.
Where the line actually falls
Two things are worth distinguishing, because only one of them is forbidden.
- Driving the page is fully supported, and is what
setupsteps are for. Clicking, typing, selecting, waiting and looping are all available. - Executing your own code inside the page is not available, and will not be.
Queries travel into the page as data rather than as source, so a malformed selector produces a parse error rather than an execution. site.serve runs a program directly, without a shell, so the command in your configuration cannot become a shell script by adding a pipe to it.
If you need a step that does not exist
Open an issue and describe the screenshot you cannot take. A missing verb is a bug report with a clear test case, and the step vocabulary grows that way rather than by anticipation.
Worth putting in it: the page, the state you need it in, and the step you reached for and could not find. Worth leaving out: a proposed name or signature. A verb is easier to design from the screenshot that needed it than from a guess at its shape.
Related
- Steps reference, for the vocabulary as it stands
- What a configuration can do
- Why Playwright is a peer dependency