sphinxcontrib-screenshot 0.1.3__tar.gz → 0.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of sphinxcontrib-screenshot might be problematic. Click here for more details.

Files changed (24) hide show
  1. {sphinxcontrib_screenshot-0.1.3/sphinxcontrib_screenshot.egg-info → sphinxcontrib_screenshot-0.2.0}/PKG-INFO +23 -62
  2. sphinxcontrib_screenshot-0.2.0/README.md +33 -0
  3. sphinxcontrib_screenshot-0.2.0/pyproject.toml +109 -0
  4. sphinxcontrib_screenshot-0.2.0/setup.cfg +4 -0
  5. sphinxcontrib_screenshot-0.2.0/sphinxcontrib/screenshot.py +325 -0
  6. {sphinxcontrib_screenshot-0.1.3 → sphinxcontrib_screenshot-0.2.0/sphinxcontrib_screenshot.egg-info}/PKG-INFO +23 -62
  7. {sphinxcontrib_screenshot-0.1.3 → sphinxcontrib_screenshot-0.2.0}/sphinxcontrib_screenshot.egg-info/SOURCES.txt +9 -3
  8. {sphinxcontrib_screenshot-0.1.3 → sphinxcontrib_screenshot-0.2.0}/sphinxcontrib_screenshot.egg-info/requires.txt +12 -0
  9. sphinxcontrib_screenshot-0.2.0/tests/test_browsers.py +49 -0
  10. sphinxcontrib_screenshot-0.2.0/tests/test_color_scheme.py +48 -0
  11. sphinxcontrib_screenshot-0.2.0/tests/test_contexts.py +32 -0
  12. sphinxcontrib_screenshot-0.2.0/tests/test_full_page.py +46 -0
  13. sphinxcontrib_screenshot-0.2.0/tests/test_headers.py +33 -0
  14. sphinxcontrib_screenshot-0.2.0/tests/test_pdf.py +34 -0
  15. sphinxcontrib_screenshot-0.2.0/tests/test_root.py +61 -0
  16. sphinxcontrib_screenshot-0.2.0/tests/test_wsgi_apps.py +32 -0
  17. sphinxcontrib_screenshot-0.1.3/README.md +0 -84
  18. sphinxcontrib_screenshot-0.1.3/setup.cfg +0 -60
  19. sphinxcontrib_screenshot-0.1.3/setup.py +0 -17
  20. sphinxcontrib_screenshot-0.1.3/sphinxcontrib/screenshot.py +0 -205
  21. sphinxcontrib_screenshot-0.1.3/tests/test_it.py +0 -70
  22. {sphinxcontrib_screenshot-0.1.3 → sphinxcontrib_screenshot-0.2.0}/LICENSE +0 -0
  23. {sphinxcontrib_screenshot-0.1.3 → sphinxcontrib_screenshot-0.2.0}/sphinxcontrib_screenshot.egg-info/dependency_links.txt +0 -0
  24. {sphinxcontrib_screenshot-0.1.3 → sphinxcontrib_screenshot-0.2.0}/sphinxcontrib_screenshot.egg-info/top_level.txt +0 -0
@@ -1,103 +1,64 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: sphinxcontrib-screenshot
3
- Version: 0.1.3
4
- Summary: A Shpinx extension to embed webpage screenshots.
5
- Home-page: https://github.com/tushuhei/sphinxcontrib-screenshot/
6
- Author: Shuhei Iitsuka
7
- Author-email: tushuhei@gmail.com
3
+ Version: 0.2.0
4
+ Summary: A Sphinx extension to embed webpage screenshots.
5
+ Author-email: Shuhei Iitsuka <tushuhei@gmail.com>
8
6
  License: Apache-2.0
7
+ Project-URL: repository, https://github.com/tushuhei/sphinxcontrib-screenshot/
9
8
  Classifier: Development Status :: 3 - Alpha
10
9
  Classifier: Operating System :: OS Independent
11
10
  Classifier: License :: OSI Approved :: Apache Software License
12
11
  Classifier: Programming Language :: Python :: 3.9
13
12
  Classifier: Programming Language :: Python :: 3.10
14
13
  Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Programming Language :: Python :: 3.13
15
16
  Requires-Python: >=3.9
16
17
  Description-Content-Type: text/markdown
17
18
  License-File: LICENSE
18
19
  Requires-Dist: playwright
19
20
  Requires-Dist: sphinx
21
+ Requires-Dist: portpicker
20
22
  Provides-Extra: dev
21
23
  Requires-Dist: beautifulsoup4; extra == "dev"
22
24
  Requires-Dist: build; extra == "dev"
23
25
  Requires-Dist: flake8; extra == "dev"
26
+ Requires-Dist: flake8-pyproject; extra == "dev"
24
27
  Requires-Dist: isort; extra == "dev"
25
28
  Requires-Dist: mypy; extra == "dev"
26
29
  Requires-Dist: Pillow; extra == "dev"
30
+ Requires-Dist: pre-commit; extra == "dev"
27
31
  Requires-Dist: pytest; extra == "dev"
32
+ Requires-Dist: pytest-regressions[image]; extra == "dev"
28
33
  Requires-Dist: sphinx[test]; extra == "dev"
29
34
  Requires-Dist: toml; extra == "dev"
35
+ Requires-Dist: tox; extra == "dev"
30
36
  Requires-Dist: twine; extra == "dev"
31
37
  Requires-Dist: types-beautifulsoup4; extra == "dev"
32
38
  Requires-Dist: types-docutils; extra == "dev"
39
+ Requires-Dist: types-portpicker; extra == "dev"
33
40
  Requires-Dist: types-Pillow; extra == "dev"
34
41
  Requires-Dist: types-setuptools; extra == "dev"
42
+ Requires-Dist: user-agents; extra == "dev"
35
43
  Requires-Dist: yapf; extra == "dev"
44
+ Provides-Extra: doc
45
+ Requires-Dist: myst-parser; extra == "doc"
46
+ Requires-Dist: shibuya; extra == "doc"
47
+ Requires-Dist: sphinx; extra == "doc"
36
48
 
37
49
  # sphinxcontrib-screenshot
38
50
 
39
51
  A Sphinx extension to embed website screenshots.
40
52
 
41
- ![Example screenshot](https://raw.githubusercontent.com/tushuhei/sphinxcontrib-screenshot/main/example.png)
42
-
43
- ## Install
44
-
45
- ```bash
46
- pip install sphinxcontrib-screenshot
47
- playwright install
48
- ```
49
-
50
- ## Usage
51
-
52
- Add `sphinxcontrib.screenshot` to your `conf.py`.
53
-
54
- ```py
55
- extensions = ["sphinxcontrib.screenshot"]
56
- ```
57
-
58
- Then use the `screenshot` directive in your Sphinx source file.
59
-
60
- ```rst
61
- .. screenshot:: http://www.example.com
62
- ```
63
-
64
- You can also specify the screen size for the screenshot with `width` and `height` parameters.
65
-
66
- ```rst
67
- .. screenshot:: http://www.example.com
68
- :width: 1280
69
- :height: 960
70
- ```
71
-
72
- You can include a caption for the screenshot's `figure` directive.
73
-
74
53
  ```rst
75
54
  .. screenshot:: http://www.example.com
76
- :caption: This is a screenshot for www.example.com
77
- ```
78
-
79
- You can describe the interaction that you want to have with the webpage before taking a screenshot in JavaScript.
80
-
81
- ```rst
82
- .. screenshot:: http://www.example.com
83
-
84
- document.querySelector('button').click();
85
- ```
86
-
87
- ## Pro tips
88
- `sphinxcontrib-screenshot` supports URLs with the HTTP and HTTPS protocols.
89
- To take screenshots of local files and build the document while running a local server for them, you can use the NPM library [concurrently](https://www.npmjs.com/package/concurrently) in the following way:
90
-
91
- ### Build the document
92
- ```bash
93
- npx --yes concurrently -k --success=first "make html" "python3 -m http.server 3000 --directory=examples"
94
- ```
95
-
96
- ### Watch and build the document
97
- ```bash
98
- npx --yes concurrently -k "make livehtml" "python3 -m http.server 3000 --directory=examples"
55
+ :browser: chromium
56
+ :viewport-width: 1280
57
+ :viewport-height: 960
58
+ :color-scheme: dark
99
59
  ```
100
60
 
61
+ Read more in the [documentation](https://sphinxcontrib-screenshot.readthedocs.io).
101
62
 
102
63
  ## Notes
103
64
 
@@ -0,0 +1,33 @@
1
+ # sphinxcontrib-screenshot
2
+
3
+ A Sphinx extension to embed website screenshots.
4
+
5
+ ```rst
6
+ .. screenshot:: http://www.example.com
7
+ :browser: chromium
8
+ :viewport-width: 1280
9
+ :viewport-height: 960
10
+ :color-scheme: dark
11
+ ```
12
+
13
+ Read more in the [documentation](https://sphinxcontrib-screenshot.readthedocs.io).
14
+
15
+ ## Notes
16
+
17
+ This extension uses [Playwright](https://playwright.dev) to capture a screenshot of the specified website only.
18
+ No data is sent to any other external server; the request is limited to the specified website.
19
+ Be cautious: avoid including sensitive information (such as authentication data) in the directive content.
20
+
21
+ ## Contributing
22
+
23
+ See [`CONTRIBUTING.md`](CONTRIBUTING.md) for details.
24
+
25
+ ## License
26
+
27
+ Apache 2.0; see [`LICENSE`](LICENSE) for details.
28
+
29
+ ## Disclaimer
30
+
31
+ This project is not an official Google project. It is not supported by
32
+ Google and Google specifically disclaims all warranties as to its quality,
33
+ merchantability, or fitness for a particular purpose.
@@ -0,0 +1,109 @@
1
+ [build-system]
2
+ requires = ["setuptools>=42", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "sphinxcontrib-screenshot"
7
+ version = "0.2.0"
8
+ description = "A Sphinx extension to embed webpage screenshots."
9
+ readme = "README.md"
10
+ license = { text = "Apache-2.0" }
11
+ authors = [
12
+ { name = "Shuhei Iitsuka", email = "tushuhei@gmail.com" }
13
+ ]
14
+ urls = { repository = "https://github.com/tushuhei/sphinxcontrib-screenshot/" }
15
+ classifiers = [
16
+ "Development Status :: 3 - Alpha",
17
+ "Operating System :: OS Independent",
18
+ "License :: OSI Approved :: Apache Software License",
19
+ "Programming Language :: Python :: 3.9",
20
+ "Programming Language :: Python :: 3.10",
21
+ "Programming Language :: Python :: 3.11",
22
+ "Programming Language :: Python :: 3.12",
23
+ "Programming Language :: Python :: 3.13",
24
+ ]
25
+ requires-python = ">=3.9"
26
+ dependencies = [
27
+ "playwright",
28
+ "sphinx",
29
+ "portpicker",
30
+ ]
31
+
32
+ [project.optional-dependencies]
33
+ dev = [
34
+ "beautifulsoup4",
35
+ "build",
36
+ "flake8",
37
+ "flake8-pyproject",
38
+ "isort",
39
+ "mypy",
40
+ "Pillow",
41
+ "pre-commit",
42
+ "pytest",
43
+ "pytest-regressions[image]",
44
+ "sphinx[test]",
45
+ "toml",
46
+ "tox",
47
+ "twine",
48
+ "types-beautifulsoup4",
49
+ "types-docutils",
50
+ "types-portpicker",
51
+ "types-Pillow",
52
+ "types-setuptools",
53
+ "user-agents",
54
+ "yapf",
55
+ ]
56
+
57
+ doc = [
58
+ "myst-parser",
59
+ "shibuya",
60
+ "sphinx",
61
+ ]
62
+
63
+ [tool.setuptools]
64
+ packages = ["sphinxcontrib"]
65
+ include-package-data = true
66
+
67
+ [tool.setuptools.package-data]
68
+ "sphinxcontrib" = ["*"]
69
+
70
+ [tool.yapf]
71
+ based_on_style = "yapf"
72
+
73
+ [tool.flake8]
74
+ indent-size = 2
75
+
76
+ [tool.mypy]
77
+ python_version = 3.9
78
+ pretty = true
79
+ packages = ["sphinxcontrib"]
80
+
81
+ [tool.tox]
82
+ requires = ["tox>=4.19"]
83
+ env_list = [
84
+ "py39",
85
+ "py310",
86
+ "py311",
87
+ "py312",
88
+ "py313",
89
+ "style",
90
+ ]
91
+
92
+ [tool.tox.env_run_base]
93
+ deps = ["-e .[dev]"]
94
+ commands = [
95
+ ["pytest", "--showlocals", "--full-trace", "{posargs}"],
96
+ ]
97
+
98
+ [tool.tox.env.style]
99
+ skip_install = true
100
+ commands = [
101
+ ["pre-commit", "run", "--all-files", "--show-diff-on-failure"],
102
+ ]
103
+
104
+ [tool.tox.env.doc]
105
+ skip_install = true
106
+ deps = ["-e .[doc]"]
107
+ commands = [
108
+ ["sphinx-build", "--builder", "html", "doc", "build/sphinx/html"],
109
+ ]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,325 @@
1
+ # Copyright 2023 Google LLC
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ import hashlib
16
+ import importlib
17
+ import importlib.metadata
18
+ import os
19
+ import threading
20
+ import typing
21
+ import wsgiref.simple_server
22
+ from concurrent.futures import ThreadPoolExecutor
23
+ from urllib.parse import urlparse
24
+
25
+ from docutils import nodes
26
+ from docutils.parsers.rst import directives
27
+ from docutils.parsers.rst.directives.images import Figure
28
+ from playwright._impl._helper import ColorScheme
29
+ from playwright.sync_api import Browser, BrowserContext
30
+ from playwright.sync_api import TimeoutError as PlaywrightTimeoutError
31
+ from playwright.sync_api import sync_playwright
32
+ from portpicker import pick_unused_port
33
+ from sphinx.application import Sphinx
34
+ from sphinx.config import Config
35
+ from sphinx.util.docutils import SphinxDirective
36
+
37
+ Meta = typing.TypedDict('Meta', {
38
+ 'version': str,
39
+ 'parallel_read_safe': bool,
40
+ 'parallel_write_safe': bool
41
+ })
42
+
43
+
44
+ class ScreenshotDirective(SphinxDirective, Figure):
45
+ """Sphinx Screenshot Dirctive.
46
+
47
+ This directive embeds a screenshot of a webpage.
48
+
49
+ # Example
50
+
51
+ You can simply pass a URL for a webpage that you want to take a screenshot.
52
+
53
+ ```rst
54
+ .. screenshot:: http://www.example.com
55
+ ```
56
+
57
+ You can also specify the screen size for the screenshot with
58
+ `viewport-width` and `viewport-height` parameters in pixel.
59
+
60
+ ```rst
61
+ .. screenshot:: http://www.example.com
62
+ :viewport-width: 1280
63
+ :viewport-height: 960
64
+ ```
65
+
66
+ You can describe the interaction that you want to have with the webpage
67
+ before taking a screenshot in JavaScript.
68
+
69
+ ```rst
70
+ .. screenshot:: http://www.example.com
71
+
72
+ document.querySelector('button').click();
73
+ ```
74
+
75
+ It also generates a PDF file when `pdf` option is given, which might be
76
+ useful when you need scalable image assets.
77
+
78
+ ```rst
79
+ .. screenshot:: http://www.example.com
80
+ :pdf:
81
+ ```
82
+ """
83
+
84
+ required_arguments = 1 # URL
85
+ option_spec = {
86
+ **Figure.option_spec,
87
+ 'browser': str,
88
+ 'viewport-height': directives.positive_int,
89
+ 'viewport-width': directives.positive_int,
90
+ 'interactions': str,
91
+ 'pdf': directives.flag,
92
+ 'color-scheme': str,
93
+ 'full-page': directives.flag,
94
+ 'context': str,
95
+ 'headers': directives.unchanged,
96
+ }
97
+ pool = ThreadPoolExecutor()
98
+
99
+ @staticmethod
100
+ def take_screenshot(
101
+ url: str, browser_name: str, viewport_width: int, viewport_height: int,
102
+ filepath: str, init_script: str, interactions: str, generate_pdf: bool,
103
+ color_scheme: ColorScheme, full_page: bool,
104
+ context_builder: typing.Optional[typing.Callable[[Browser, str, str],
105
+ BrowserContext]],
106
+ headers: dict):
107
+ """Takes a screenshot with Playwright's Chromium browser.
108
+
109
+ Args:
110
+ url (str): The HTTP/HTTPS URL of the webpage to screenshot.
111
+ viewport_width (int): The width of the screenshot in pixels.
112
+ viewport_height (int): The height of the screenshot in pixels.
113
+ filepath (str): The path to save the screenshot to.
114
+ init_script (str): JavaScript code to be evaluated after the document
115
+ was created but before any of its scripts were run. See more details at
116
+ https://playwright.dev/python/docs/api/class-page#page-add-init-script
117
+ interactions (str): JavaScript code to run before taking the screenshot
118
+ after the page was loaded.
119
+ generate_pdf (bool): Generate a PDF file along with the screenshot.
120
+ color_scheme (str): The preferred color scheme. Can be 'light' or 'dark'.
121
+ context: A method to build the Playwright context.
122
+ """
123
+ with sync_playwright() as playwright:
124
+ browser = getattr(playwright, browser_name).launch()
125
+
126
+ if context_builder:
127
+ try:
128
+ context = context_builder(browser, url, color_scheme)
129
+ except PlaywrightTimeoutError:
130
+ raise RuntimeError(
131
+ 'Timeout error occured at %s in executing py init script %s' %
132
+ (url, context_builder.__name__))
133
+ else:
134
+ context = browser.new_context(color_scheme=color_scheme)
135
+
136
+ page = context.new_page()
137
+ page.set_default_timeout(10000)
138
+ page.set_viewport_size({
139
+ 'width': viewport_width,
140
+ 'height': viewport_height
141
+ })
142
+
143
+ try:
144
+ if init_script:
145
+ page.add_init_script(init_script)
146
+ page.set_extra_http_headers(headers)
147
+ page.goto(url)
148
+ page.wait_for_load_state('networkidle')
149
+
150
+ # Execute interactions
151
+ if interactions:
152
+ page.evaluate(interactions)
153
+ page.wait_for_load_state('networkidle')
154
+ except PlaywrightTimeoutError:
155
+ raise RuntimeError('Timeout error occured at %s in executing\n%s' %
156
+ (url, interactions))
157
+ page.screenshot(path=filepath, full_page=full_page)
158
+ if generate_pdf:
159
+ page.emulate_media(media='screen')
160
+ root, ext = os.path.splitext(filepath)
161
+ page.pdf(
162
+ width=f'{viewport_width}px',
163
+ height=f'{viewport_height}px',
164
+ path=root + '.pdf')
165
+ page.close()
166
+ browser.close()
167
+
168
+ def evaluate_substitutions(self, text: str) -> str:
169
+ substitutions = self.state.document.substitution_defs
170
+ for key, value in substitutions.items():
171
+ text = text.replace(f"|{key}|", value.astext())
172
+ return text
173
+
174
+ def run(self) -> typing.Sequence[nodes.Node]:
175
+ screenshot_init_script: str = self.env.config.screenshot_init_script or ''
176
+
177
+ # Ensure the screenshots directory exists
178
+ ss_dirpath = os.path.join(self.env.app.outdir, '_static', 'screenshots')
179
+ os.makedirs(ss_dirpath, exist_ok=True)
180
+
181
+ # Parse parameters
182
+ raw_url = self.arguments[0]
183
+ url = self.evaluate_substitutions(raw_url)
184
+ interactions = self.options.get('interactions', '')
185
+ browser = self.options.get('browser',
186
+ self.env.config.screenshot_default_browser)
187
+ viewport_height = self.options.get(
188
+ 'viewport-height', self.env.config.screenshot_default_viewport_height)
189
+ viewport_width = self.options.get(
190
+ 'viewport-width', self.env.config.screenshot_default_viewport_width)
191
+ color_scheme = self.options.get(
192
+ 'color-scheme', self.env.config.screenshot_default_color_scheme)
193
+ pdf = 'pdf' in self.options
194
+ full_page = ('full-page' in self.options or
195
+ self.env.config.screenshot_default_full_page)
196
+ context = self.options.get('context', '')
197
+ headers = self.options.get('headers', '')
198
+
199
+ request_headers = {**self.env.config.screenshot_default_headers}
200
+ if headers:
201
+ for header in headers.strip().split("\n"):
202
+ name, value = header.split(" ", 1)
203
+ request_headers[name] = value
204
+
205
+ if urlparse(url).scheme not in {'http', 'https'}:
206
+ raise RuntimeError(
207
+ f'Invalid URL: {url}. Only HTTP/HTTPS URLs are supported.')
208
+
209
+ # Generate filename based on hash of parameters
210
+ hash_input = "_".join([
211
+ raw_url, browser,
212
+ str(viewport_height),
213
+ str(viewport_width), color_scheme, context, interactions,
214
+ str(full_page)
215
+ ])
216
+ filename = hashlib.md5(hash_input.encode()).hexdigest() + '.png'
217
+ filepath = os.path.join(ss_dirpath, filename)
218
+
219
+ if context:
220
+ context_builder_path = self.config.screenshot_contexts[context]
221
+ context_builder = resolve_python_method(context_builder_path)
222
+ else:
223
+ context_builder = None
224
+
225
+ # Check if the file already exists. If not, take a screenshot
226
+ if not os.path.exists(filepath):
227
+ fut = self.pool.submit(ScreenshotDirective.take_screenshot, url, browser,
228
+ viewport_width, viewport_height, filepath,
229
+ screenshot_init_script, interactions, pdf,
230
+ color_scheme, full_page, context_builder,
231
+ request_headers)
232
+ fut.result()
233
+
234
+ # Create image and figure nodes
235
+ docdir = os.path.dirname(self.env.doc2path(self.env.docname))
236
+ rel_ss_dirpath = os.path.relpath(ss_dirpath, start=docdir)
237
+ rel_filepath = os.path.join(rel_ss_dirpath, filename).replace(os.sep, '/')
238
+
239
+ self.arguments[0] = rel_filepath
240
+ return super().run()
241
+
242
+
243
+ app_threads = {}
244
+
245
+
246
+ def resolve_python_method(import_path: str):
247
+ module_path, method_name = import_path.split(":")
248
+ module = importlib.import_module(module_path)
249
+ method = getattr(module, method_name)
250
+ return method
251
+
252
+
253
+ def setup_apps(app: Sphinx, config: Config):
254
+ """Start the WSGI application threads.
255
+
256
+ A new replacement is created for each WSGI app."""
257
+ for wsgi_app_name, wsgi_app_path in config.screenshot_apps.items():
258
+ port = pick_unused_port()
259
+ config.rst_prolog = (
260
+ config.rst_prolog or
261
+ "") + f"\n.. |{wsgi_app_name}| replace:: http://localhost:{port}\n"
262
+ app_builder = resolve_python_method(wsgi_app_path)
263
+ wsgi_app = app_builder(app)
264
+ httpd = wsgiref.simple_server.make_server("localhost", port, wsgi_app)
265
+ thread = threading.Thread(target=httpd.serve_forever)
266
+ thread.start()
267
+ app_threads[wsgi_app_name] = (httpd, thread)
268
+
269
+
270
+ def teardown_apps(app: Sphinx, exception: typing.Optional[Exception]):
271
+ """Shut down the WSGI application threads."""
272
+ for httpd, thread in app_threads.values():
273
+ httpd.shutdown()
274
+ thread.join()
275
+
276
+
277
+ def setup(app: Sphinx) -> Meta:
278
+ app.add_directive('screenshot', ScreenshotDirective)
279
+ app.add_config_value('screenshot_init_script', '', 'env')
280
+ app.add_config_value(
281
+ 'screenshot_default_viewport_width',
282
+ 1280,
283
+ 'env',
284
+ description="The default width for screenshots")
285
+ app.add_config_value(
286
+ 'screenshot_default_viewport_height',
287
+ 960,
288
+ 'env',
289
+ description="The default height for screenshots")
290
+ app.add_config_value(
291
+ 'screenshot_default_browser',
292
+ 'chromium',
293
+ 'env',
294
+ description="The default browser for screenshots")
295
+ app.add_config_value(
296
+ 'screenshot_default_full_page',
297
+ False,
298
+ 'env',
299
+ description="Whether to take full page screenshots")
300
+ app.add_config_value(
301
+ 'screenshot_default_color_scheme',
302
+ 'null',
303
+ 'env',
304
+ description="The default color scheme for screenshots")
305
+ app.add_config_value(
306
+ 'screenshot_contexts', {},
307
+ 'env',
308
+ types=[dict[str, str]],
309
+ description="A dict of paths to Playwright context build methods")
310
+ app.add_config_value(
311
+ 'screenshot_default_headers', {},
312
+ 'env',
313
+ description="The default headers to pass in requests")
314
+ app.add_config_value(
315
+ 'screenshot_apps', {},
316
+ 'env',
317
+ types=[dict[str, str]],
318
+ description="A dict of WSGI apps")
319
+ app.connect('config-inited', setup_apps)
320
+ app.connect('build-finished', teardown_apps)
321
+ return {
322
+ 'version': importlib.metadata.version('sphinxcontrib-screenshot'),
323
+ 'parallel_read_safe': True,
324
+ 'parallel_write_safe': True,
325
+ }