Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
49 changes: 49 additions & 0 deletions docs/multi.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,55 @@ To take a screenshot of just the area of a page defined by a CSS selector, add `
selector: "#bighead"
```

Use `--macro` to run JavaScript before every shot is taken:

shot-scraper multi shots.yml --macro macros.yaml

Macros can be a `script` or a `function`:

* `script` is executed immediately
* `function` exposes a function that can be called in your `javascript` block:

Sample `macros.yaml`:

```yaml
- type: script
javascript: |
function (){
console.log("This runs before the shot is taken")
}

- type: function
name: sayHello
javascript: |
function (){
console.log("Hello World")
}

```

Sample `shots.yaml`:

```yaml
- output: demo.png
url: https://example.com
width: 1920
height: 1080
javascript: |
function(){
console.log("Taking a shot");
sayHello();
}
```

Expected output (if using `--log-console`):

```
This runs before the shot is taken
Taking a shot
Hello World
```

You can pass more than one selector using a `selectors:` list. You can also use `padding:` to specify additional padding:

```yaml
Expand Down
26 changes: 26 additions & 0 deletions shot_scraper/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,11 @@ def _browser_context(
help="Just take shots matching these output files",
multiple=True,
)
@click.option(
"--macro",
type=click.File("r"),
help="Apply the macros contained in this file to all shots",
)
@browser_option
@user_agent_option
@reduced_motion_option
Expand All @@ -403,6 +408,7 @@ def multi(
fail_on_error,
noclobber,
outputs,
macro,
browser,
user_agent,
reduced_motion,
Expand All @@ -426,6 +432,14 @@ def multi(

https://shot-scraper.datasette.io/en/stable/multi.html
"""
# Load macros config
macroConfig = []
if macro:
macroConfig = yaml.safe_load(macro)
if not isinstance(macroConfig, list):
raise click.ClickException("Macro file must contain a list")

# Load shots config
shots = yaml.safe_load(config)
if shots is None:
shots = []
Expand All @@ -451,6 +465,7 @@ def multi(
if outputs and shot.get("output") not in outputs:
continue
try:
shot['macros'] = macroConfig
take_shot(
context,
shot,
Expand Down Expand Up @@ -1004,6 +1019,17 @@ def on_response(response):
if wait:
time.sleep(wait / 1000)

macros = shot.get("macros")
if macros:
for macro in macros:
if macro['type'] == 'script':
_evaluate_js(page, macro['javascript'])
elif macro['type'] == 'function':
_evaluate_js(page, "function(){{ window.{} = {} }}".format(macro['name'], macro['javascript']))
else:
raise click.ClickException("Invalid macro type: '{}'".format(macro['type']))


javascript = shot.get("javascript")
if javascript:
_evaluate_js(page, javascript)
Expand Down