sphinxcontrib-screenshot 0.1.3__tar.gz → 0.1.4__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.
- {sphinxcontrib_screenshot-0.1.3/sphinxcontrib_screenshot.egg-info → sphinxcontrib_screenshot-0.1.4}/PKG-INFO +21 -60
- sphinxcontrib_screenshot-0.1.4/README.md +33 -0
- sphinxcontrib_screenshot-0.1.4/pyproject.toml +109 -0
- sphinxcontrib_screenshot-0.1.4/setup.cfg +4 -0
- {sphinxcontrib_screenshot-0.1.3 → sphinxcontrib_screenshot-0.1.4}/sphinxcontrib/screenshot.py +155 -15
- {sphinxcontrib_screenshot-0.1.3 → sphinxcontrib_screenshot-0.1.4/sphinxcontrib_screenshot.egg-info}/PKG-INFO +21 -60
- {sphinxcontrib_screenshot-0.1.3 → sphinxcontrib_screenshot-0.1.4}/sphinxcontrib_screenshot.egg-info/SOURCES.txt +10 -3
- {sphinxcontrib_screenshot-0.1.3 → sphinxcontrib_screenshot-0.1.4}/sphinxcontrib_screenshot.egg-info/requires.txt +12 -0
- sphinxcontrib_screenshot-0.1.4/tests/test_browsers.py +49 -0
- sphinxcontrib_screenshot-0.1.4/tests/test_color_scheme.py +48 -0
- sphinxcontrib_screenshot-0.1.4/tests/test_contexts.py +32 -0
- sphinxcontrib_screenshot-0.1.3/setup.py → sphinxcontrib_screenshot-0.1.4/tests/test_figclass.py +13 -2
- sphinxcontrib_screenshot-0.1.4/tests/test_full_page.py +46 -0
- sphinxcontrib_screenshot-0.1.4/tests/test_headers.py +33 -0
- sphinxcontrib_screenshot-0.1.4/tests/test_pdf.py +34 -0
- sphinxcontrib_screenshot-0.1.3/tests/test_it.py → sphinxcontrib_screenshot-0.1.4/tests/test_root.py +32 -26
- sphinxcontrib_screenshot-0.1.4/tests/test_wsgi_apps.py +32 -0
- sphinxcontrib_screenshot-0.1.3/README.md +0 -84
- sphinxcontrib_screenshot-0.1.3/setup.cfg +0 -60
- {sphinxcontrib_screenshot-0.1.3 → sphinxcontrib_screenshot-0.1.4}/LICENSE +0 -0
- {sphinxcontrib_screenshot-0.1.3 → sphinxcontrib_screenshot-0.1.4}/sphinxcontrib_screenshot.egg-info/dependency_links.txt +0 -0
- {sphinxcontrib_screenshot-0.1.3 → sphinxcontrib_screenshot-0.1.4}/sphinxcontrib_screenshot.egg-info/top_level.txt +0 -0
|
@@ -1,103 +1,64 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
2
|
Name: sphinxcontrib-screenshot
|
|
3
|
-
Version: 0.1.
|
|
4
|
-
Summary: A
|
|
5
|
-
|
|
6
|
-
Author: Shuhei Iitsuka
|
|
7
|
-
Author-email: tushuhei@gmail.com
|
|
3
|
+
Version: 0.1.4
|
|
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
|
-

|
|
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
53
|
```rst
|
|
67
54
|
.. screenshot:: http://www.example.com
|
|
55
|
+
:browser: chromium
|
|
68
56
|
:width: 1280
|
|
69
57
|
:height: 960
|
|
58
|
+
:color-scheme: dark
|
|
70
59
|
```
|
|
71
60
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
```rst
|
|
75
|
-
.. 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"
|
|
99
|
-
```
|
|
100
|
-
|
|
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
|
+
:width: 1280
|
|
9
|
+
: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.1.4"
|
|
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
|
+
]
|
{sphinxcontrib_screenshot-0.1.3 → sphinxcontrib_screenshot-0.1.4}/sphinxcontrib/screenshot.py
RENAMED
|
@@ -13,17 +13,25 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
15
|
import hashlib
|
|
16
|
+
import importlib
|
|
17
|
+
import importlib.metadata
|
|
16
18
|
import os
|
|
19
|
+
import threading
|
|
17
20
|
import typing
|
|
21
|
+
import wsgiref.simple_server
|
|
18
22
|
from concurrent.futures import ThreadPoolExecutor
|
|
19
23
|
from urllib.parse import urlparse
|
|
20
24
|
|
|
21
25
|
from docutils import nodes
|
|
22
26
|
from docutils.parsers.rst import directives
|
|
23
27
|
from docutils.statemachine import ViewList
|
|
28
|
+
from playwright._impl._helper import ColorScheme
|
|
29
|
+
from playwright.sync_api import Browser, BrowserContext
|
|
24
30
|
from playwright.sync_api import TimeoutError as PlaywrightTimeoutError
|
|
25
31
|
from playwright.sync_api import sync_playwright
|
|
32
|
+
from portpicker import pick_unused_port
|
|
26
33
|
from sphinx.application import Sphinx
|
|
34
|
+
from sphinx.config import Config
|
|
27
35
|
from sphinx.util.docutils import SphinxDirective
|
|
28
36
|
|
|
29
37
|
Meta = typing.TypedDict('Meta', {
|
|
@@ -32,8 +40,6 @@ Meta = typing.TypedDict('Meta', {
|
|
|
32
40
|
'parallel_write_safe': bool
|
|
33
41
|
})
|
|
34
42
|
|
|
35
|
-
__version__ = '0.1.3'
|
|
36
|
-
|
|
37
43
|
|
|
38
44
|
class ScreenshotDirective(SphinxDirective):
|
|
39
45
|
"""Sphinx Screenshot Dirctive.
|
|
@@ -92,17 +98,27 @@ class ScreenshotDirective(SphinxDirective):
|
|
|
92
98
|
required_arguments = 1 # URL
|
|
93
99
|
has_content = True
|
|
94
100
|
option_spec = {
|
|
101
|
+
'browser': str,
|
|
95
102
|
'height': directives.positive_int,
|
|
96
103
|
'width': directives.positive_int,
|
|
97
104
|
'caption': directives.unchanged,
|
|
98
105
|
'figclass': directives.unchanged,
|
|
99
106
|
'pdf': directives.flag,
|
|
107
|
+
'color-scheme': str,
|
|
108
|
+
'full-page': directives.flag,
|
|
109
|
+
'context': str,
|
|
110
|
+
'headers': directives.unchanged,
|
|
100
111
|
}
|
|
101
112
|
pool = ThreadPoolExecutor()
|
|
102
113
|
|
|
103
114
|
@staticmethod
|
|
104
|
-
def take_screenshot(
|
|
105
|
-
|
|
115
|
+
def take_screenshot(
|
|
116
|
+
url: str, browser_name: str, width: int, height: int, filepath: str,
|
|
117
|
+
init_script: str, interactions: str, generate_pdf: bool,
|
|
118
|
+
color_scheme: ColorScheme, full_page: bool,
|
|
119
|
+
context_builder: typing.Optional[typing.Callable[[Browser, str, str],
|
|
120
|
+
BrowserContext]],
|
|
121
|
+
headers: dict):
|
|
106
122
|
"""Takes a screenshot with Playwright's Chromium browser.
|
|
107
123
|
|
|
108
124
|
Args:
|
|
@@ -116,15 +132,30 @@ class ScreenshotDirective(SphinxDirective):
|
|
|
116
132
|
interactions (str): JavaScript code to run before taking the screenshot
|
|
117
133
|
after the page was loaded.
|
|
118
134
|
generate_pdf (bool): Generate a PDF file along with the screenshot.
|
|
135
|
+
color_scheme (str): The preferred color scheme. Can be 'light' or 'dark'.
|
|
136
|
+
context: A method to build the Playwright context.
|
|
119
137
|
"""
|
|
120
138
|
with sync_playwright() as playwright:
|
|
121
|
-
browser = playwright.
|
|
122
|
-
|
|
139
|
+
browser = getattr(playwright, browser_name).launch()
|
|
140
|
+
|
|
141
|
+
if context_builder:
|
|
142
|
+
try:
|
|
143
|
+
context = context_builder(browser, url, color_scheme)
|
|
144
|
+
except PlaywrightTimeoutError:
|
|
145
|
+
raise RuntimeError(
|
|
146
|
+
'Timeout error occured at %s in executing py init script %s' %
|
|
147
|
+
(url, context_builder.__name__))
|
|
148
|
+
else:
|
|
149
|
+
context = browser.new_context(color_scheme=color_scheme)
|
|
150
|
+
|
|
151
|
+
page = context.new_page()
|
|
123
152
|
page.set_default_timeout(10000)
|
|
124
153
|
page.set_viewport_size({'width': width, 'height': height})
|
|
154
|
+
|
|
125
155
|
try:
|
|
126
156
|
if init_script:
|
|
127
157
|
page.add_init_script(init_script)
|
|
158
|
+
page.set_extra_http_headers(headers)
|
|
128
159
|
page.goto(url)
|
|
129
160
|
page.wait_for_load_state('networkidle')
|
|
130
161
|
|
|
@@ -135,7 +166,7 @@ class ScreenshotDirective(SphinxDirective):
|
|
|
135
166
|
except PlaywrightTimeoutError:
|
|
136
167
|
raise RuntimeError('Timeout error occured at %s in executing\n%s' %
|
|
137
168
|
(url, interactions))
|
|
138
|
-
page.screenshot(path=filepath)
|
|
169
|
+
page.screenshot(path=filepath, full_page=full_page)
|
|
139
170
|
if generate_pdf:
|
|
140
171
|
page.emulate_media(media='screen')
|
|
141
172
|
root, ext = os.path.splitext(filepath)
|
|
@@ -143,6 +174,12 @@ class ScreenshotDirective(SphinxDirective):
|
|
|
143
174
|
page.close()
|
|
144
175
|
browser.close()
|
|
145
176
|
|
|
177
|
+
def evaluate_substitutions(self, text: str) -> str:
|
|
178
|
+
substitutions = self.state.document.substitution_defs
|
|
179
|
+
for key, value in substitutions.items():
|
|
180
|
+
text = text.replace(f"|{key}|", value.astext())
|
|
181
|
+
return text
|
|
182
|
+
|
|
146
183
|
def run(self) -> typing.List[nodes.Node]:
|
|
147
184
|
screenshot_init_script: str = self.env.config.screenshot_init_script or ''
|
|
148
185
|
|
|
@@ -151,28 +188,56 @@ class ScreenshotDirective(SphinxDirective):
|
|
|
151
188
|
os.makedirs(ss_dirpath, exist_ok=True)
|
|
152
189
|
|
|
153
190
|
# Parse parameters
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
191
|
+
raw_url = self.arguments[0]
|
|
192
|
+
url = self.evaluate_substitutions(raw_url)
|
|
193
|
+
browser = self.options.get('browser',
|
|
194
|
+
self.env.config.screenshot_default_browser)
|
|
195
|
+
height = self.options.get('height',
|
|
196
|
+
self.env.config.screenshot_default_height)
|
|
197
|
+
width = self.options.get('width', self.env.config.screenshot_default_width)
|
|
198
|
+
color_scheme = self.options.get(
|
|
199
|
+
'color-scheme', self.env.config.screenshot_default_color_scheme)
|
|
157
200
|
caption_text = self.options.get('caption', '')
|
|
158
201
|
figclass = self.options.get('figclass', '')
|
|
159
202
|
pdf = 'pdf' in self.options
|
|
203
|
+
full_page = ('full-page' in self.options or
|
|
204
|
+
self.env.config.screenshot_default_full_page)
|
|
205
|
+
context = self.options.get('context', '')
|
|
160
206
|
interactions = '\n'.join(self.content)
|
|
207
|
+
headers = self.options.get('headers', '')
|
|
208
|
+
|
|
209
|
+
request_headers = {**self.env.config.screenshot_default_headers}
|
|
210
|
+
if headers:
|
|
211
|
+
for header in headers.strip().split("\n"):
|
|
212
|
+
name, value = header.split(" ", 1)
|
|
213
|
+
request_headers[name] = value
|
|
161
214
|
|
|
162
215
|
if urlparse(url).scheme not in {'http', 'https'}:
|
|
163
216
|
raise RuntimeError(
|
|
164
217
|
f'Invalid URL: {url}. Only HTTP/HTTPS URLs are supported.')
|
|
165
218
|
|
|
166
219
|
# Generate filename based on hash of parameters
|
|
167
|
-
hash_input =
|
|
220
|
+
hash_input = "_".join([
|
|
221
|
+
raw_url, browser,
|
|
222
|
+
str(height),
|
|
223
|
+
str(width), color_scheme, context, interactions,
|
|
224
|
+
str(full_page)
|
|
225
|
+
])
|
|
168
226
|
filename = hashlib.md5(hash_input.encode()).hexdigest() + '.png'
|
|
169
227
|
filepath = os.path.join(ss_dirpath, filename)
|
|
170
228
|
|
|
229
|
+
if context:
|
|
230
|
+
context_builder_path = self.config.screenshot_contexts[context]
|
|
231
|
+
context_builder = resolve_python_method(context_builder_path)
|
|
232
|
+
else:
|
|
233
|
+
context_builder = None
|
|
234
|
+
|
|
171
235
|
# Check if the file already exists. If not, take a screenshot
|
|
172
236
|
if not os.path.exists(filepath):
|
|
173
|
-
fut = self.pool.submit(ScreenshotDirective.take_screenshot, url,
|
|
174
|
-
height, filepath, screenshot_init_script,
|
|
175
|
-
interactions, pdf
|
|
237
|
+
fut = self.pool.submit(ScreenshotDirective.take_screenshot, url, browser,
|
|
238
|
+
width, height, filepath, screenshot_init_script,
|
|
239
|
+
interactions, pdf, color_scheme, full_page,
|
|
240
|
+
context_builder, request_headers)
|
|
176
241
|
fut.result()
|
|
177
242
|
|
|
178
243
|
# Create image and figure nodes
|
|
@@ -195,11 +260,86 @@ class ScreenshotDirective(SphinxDirective):
|
|
|
195
260
|
return [figure_node]
|
|
196
261
|
|
|
197
262
|
|
|
263
|
+
app_threads = {}
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
def resolve_python_method(import_path: str):
|
|
267
|
+
module_path, method_name = import_path.split(":")
|
|
268
|
+
module = importlib.import_module(module_path)
|
|
269
|
+
method = getattr(module, method_name)
|
|
270
|
+
return method
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
def setup_apps(app: Sphinx, config: Config):
|
|
274
|
+
"""Start the WSGI application threads.
|
|
275
|
+
|
|
276
|
+
A new replacement is created for each WSGI app."""
|
|
277
|
+
for wsgi_app_name, wsgi_app_path in config.screenshot_apps.items():
|
|
278
|
+
port = pick_unused_port()
|
|
279
|
+
config.rst_prolog = (
|
|
280
|
+
config.rst_prolog or
|
|
281
|
+
"") + f"\n.. |{wsgi_app_name}| replace:: http://localhost:{port}\n"
|
|
282
|
+
app_builder = resolve_python_method(wsgi_app_path)
|
|
283
|
+
wsgi_app = app_builder(app)
|
|
284
|
+
httpd = wsgiref.simple_server.make_server("localhost", port, wsgi_app)
|
|
285
|
+
thread = threading.Thread(target=httpd.serve_forever)
|
|
286
|
+
thread.start()
|
|
287
|
+
app_threads[wsgi_app_name] = (httpd, thread)
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
def teardown_apps(app: Sphinx, exception: typing.Optional[Exception]):
|
|
291
|
+
"""Shut down the WSGI application threads."""
|
|
292
|
+
for httpd, thread in app_threads.values():
|
|
293
|
+
httpd.shutdown()
|
|
294
|
+
thread.join()
|
|
295
|
+
|
|
296
|
+
|
|
198
297
|
def setup(app: Sphinx) -> Meta:
|
|
199
298
|
app.add_directive('screenshot', ScreenshotDirective)
|
|
200
299
|
app.add_config_value('screenshot_init_script', '', 'env')
|
|
300
|
+
app.add_config_value(
|
|
301
|
+
'screenshot_default_width',
|
|
302
|
+
1280,
|
|
303
|
+
'env',
|
|
304
|
+
description="The default width for screenshots")
|
|
305
|
+
app.add_config_value(
|
|
306
|
+
'screenshot_default_height',
|
|
307
|
+
960,
|
|
308
|
+
'env',
|
|
309
|
+
description="The default height for screenshots")
|
|
310
|
+
app.add_config_value(
|
|
311
|
+
'screenshot_default_browser',
|
|
312
|
+
'chromium',
|
|
313
|
+
'env',
|
|
314
|
+
description="The default browser for screenshots")
|
|
315
|
+
app.add_config_value(
|
|
316
|
+
'screenshot_default_full_page',
|
|
317
|
+
False,
|
|
318
|
+
'env',
|
|
319
|
+
description="Whether to take full page screenshots")
|
|
320
|
+
app.add_config_value(
|
|
321
|
+
'screenshot_default_color_scheme',
|
|
322
|
+
'null',
|
|
323
|
+
'env',
|
|
324
|
+
description="The default color scheme for screenshots")
|
|
325
|
+
app.add_config_value(
|
|
326
|
+
'screenshot_contexts', {},
|
|
327
|
+
'env',
|
|
328
|
+
types=[dict[str, str]],
|
|
329
|
+
description="A dict of paths to Playwright context build methods")
|
|
330
|
+
app.add_config_value(
|
|
331
|
+
'screenshot_default_headers', {},
|
|
332
|
+
'env',
|
|
333
|
+
description="The default headers to pass in requests")
|
|
334
|
+
app.add_config_value(
|
|
335
|
+
'screenshot_apps', {},
|
|
336
|
+
'env',
|
|
337
|
+
types=[dict[str, str]],
|
|
338
|
+
description="A dict of WSGI apps")
|
|
339
|
+
app.connect('config-inited', setup_apps)
|
|
340
|
+
app.connect('build-finished', teardown_apps)
|
|
201
341
|
return {
|
|
202
|
-
'version':
|
|
342
|
+
'version': importlib.metadata.version('sphinxcontrib-screenshot'),
|
|
203
343
|
'parallel_read_safe': True,
|
|
204
344
|
'parallel_write_safe': True,
|
|
205
345
|
}
|
|
@@ -1,103 +1,64 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
2
|
Name: sphinxcontrib-screenshot
|
|
3
|
-
Version: 0.1.
|
|
4
|
-
Summary: A
|
|
5
|
-
|
|
6
|
-
Author: Shuhei Iitsuka
|
|
7
|
-
Author-email: tushuhei@gmail.com
|
|
3
|
+
Version: 0.1.4
|
|
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
|
-

|
|
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
53
|
```rst
|
|
67
54
|
.. screenshot:: http://www.example.com
|
|
55
|
+
:browser: chromium
|
|
68
56
|
:width: 1280
|
|
69
57
|
:height: 960
|
|
58
|
+
:color-scheme: dark
|
|
70
59
|
```
|
|
71
60
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
```rst
|
|
75
|
-
.. 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"
|
|
99
|
-
```
|
|
100
|
-
|
|
61
|
+
Read more in the [documentation](https://sphinxcontrib-screenshot.readthedocs.io).
|
|
101
62
|
|
|
102
63
|
## Notes
|
|
103
64
|
|
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
LICENSE
|
|
2
2
|
README.md
|
|
3
|
-
|
|
4
|
-
setup.py
|
|
3
|
+
pyproject.toml
|
|
5
4
|
sphinxcontrib/screenshot.py
|
|
6
5
|
sphinxcontrib_screenshot.egg-info/PKG-INFO
|
|
7
6
|
sphinxcontrib_screenshot.egg-info/SOURCES.txt
|
|
8
7
|
sphinxcontrib_screenshot.egg-info/dependency_links.txt
|
|
9
8
|
sphinxcontrib_screenshot.egg-info/requires.txt
|
|
10
9
|
sphinxcontrib_screenshot.egg-info/top_level.txt
|
|
11
|
-
tests/
|
|
10
|
+
tests/test_browsers.py
|
|
11
|
+
tests/test_color_scheme.py
|
|
12
|
+
tests/test_contexts.py
|
|
13
|
+
tests/test_figclass.py
|
|
14
|
+
tests/test_full_page.py
|
|
15
|
+
tests/test_headers.py
|
|
16
|
+
tests/test_pdf.py
|
|
17
|
+
tests/test_root.py
|
|
18
|
+
tests/test_wsgi_apps.py
|
|
@@ -1,19 +1,31 @@
|
|
|
1
1
|
playwright
|
|
2
2
|
sphinx
|
|
3
|
+
portpicker
|
|
3
4
|
|
|
4
5
|
[dev]
|
|
5
6
|
beautifulsoup4
|
|
6
7
|
build
|
|
7
8
|
flake8
|
|
9
|
+
flake8-pyproject
|
|
8
10
|
isort
|
|
9
11
|
mypy
|
|
10
12
|
Pillow
|
|
13
|
+
pre-commit
|
|
11
14
|
pytest
|
|
15
|
+
pytest-regressions[image]
|
|
12
16
|
sphinx[test]
|
|
13
17
|
toml
|
|
18
|
+
tox
|
|
14
19
|
twine
|
|
15
20
|
types-beautifulsoup4
|
|
16
21
|
types-docutils
|
|
22
|
+
types-portpicker
|
|
17
23
|
types-Pillow
|
|
18
24
|
types-setuptools
|
|
25
|
+
user-agents
|
|
19
26
|
yapf
|
|
27
|
+
|
|
28
|
+
[doc]
|
|
29
|
+
myst-parser
|
|
30
|
+
shibuya
|
|
31
|
+
sphinx
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Copyright 2024 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
|
+
from io import StringIO
|
|
15
|
+
|
|
16
|
+
import pytest
|
|
17
|
+
from bs4 import BeautifulSoup
|
|
18
|
+
from sphinx.testing.util import SphinxTestApp
|
|
19
|
+
|
|
20
|
+
browsers = ["chromium", "firefox"]
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@pytest.mark.parametrize("browser", browsers)
|
|
24
|
+
@pytest.mark.sphinx('html', testroot="browsers")
|
|
25
|
+
def test_browser_option(browser, app: SphinxTestApp, status: StringIO,
|
|
26
|
+
warning: StringIO, image_regression) -> None:
|
|
27
|
+
app.build()
|
|
28
|
+
out_html = app.outdir / f"{browser}.html"
|
|
29
|
+
|
|
30
|
+
soup = BeautifulSoup(out_html.read_text(), "html.parser")
|
|
31
|
+
imgs = soup.find_all('img')
|
|
32
|
+
|
|
33
|
+
img_path = app.outdir / imgs[0]['src']
|
|
34
|
+
with open(img_path, "rb") as fd:
|
|
35
|
+
image_regression.check(fd.read())
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@pytest.mark.sphinx('html', testroot="default-browser")
|
|
39
|
+
def test_default_browser(app: SphinxTestApp, status: StringIO,
|
|
40
|
+
warning: StringIO, image_regression) -> None:
|
|
41
|
+
app.build()
|
|
42
|
+
out_html = app.outdir / "index.html"
|
|
43
|
+
|
|
44
|
+
soup = BeautifulSoup(out_html.read_text(), "html.parser")
|
|
45
|
+
imgs = soup.find_all('img')
|
|
46
|
+
|
|
47
|
+
img_path = app.outdir / imgs[0]['src']
|
|
48
|
+
with open(img_path, "rb") as fd:
|
|
49
|
+
image_regression.check(fd.read())
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Copyright 2024 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
|
+
from io import StringIO
|
|
15
|
+
|
|
16
|
+
import pytest
|
|
17
|
+
from bs4 import BeautifulSoup
|
|
18
|
+
from sphinx.testing.util import SphinxTestApp
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@pytest.mark.sphinx('html', testroot="color-schemes")
|
|
22
|
+
def test_color_scheme_option(app: SphinxTestApp, status: StringIO,
|
|
23
|
+
warning: StringIO, image_regression) -> None:
|
|
24
|
+
app.build()
|
|
25
|
+
out_html = app.outdir / "index.html"
|
|
26
|
+
|
|
27
|
+
soup = BeautifulSoup(out_html.read_text(), "html.parser")
|
|
28
|
+
imgs = soup.find_all('img')
|
|
29
|
+
|
|
30
|
+
img_path = app.outdir / imgs[0]['src']
|
|
31
|
+
with open(img_path, "rb") as fd:
|
|
32
|
+
image_regression.check(fd.read())
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@pytest.mark.sphinx('html', testroot="default-color-scheme")
|
|
36
|
+
def test_default_color_scheme_config_parameter(app: SphinxTestApp,
|
|
37
|
+
status: StringIO,
|
|
38
|
+
warning: StringIO,
|
|
39
|
+
image_regression) -> None:
|
|
40
|
+
app.build()
|
|
41
|
+
out_html = app.outdir / "index.html"
|
|
42
|
+
|
|
43
|
+
soup = BeautifulSoup(out_html.read_text(), "html.parser")
|
|
44
|
+
imgs = soup.find_all('img')
|
|
45
|
+
|
|
46
|
+
img_path = app.outdir / imgs[0]['src']
|
|
47
|
+
with open(img_path, "rb") as fd:
|
|
48
|
+
image_regression.check(fd.read())
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Copyright 2024 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
|
+
from io import StringIO
|
|
15
|
+
|
|
16
|
+
import pytest
|
|
17
|
+
from bs4 import BeautifulSoup
|
|
18
|
+
from sphinx.testing.util import SphinxTestApp
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@pytest.mark.sphinx('html', testroot="contexts")
|
|
22
|
+
def test_default(app: SphinxTestApp, status: StringIO, warning: StringIO,
|
|
23
|
+
image_regression) -> None:
|
|
24
|
+
app.build()
|
|
25
|
+
out_html = app.outdir / "index.html"
|
|
26
|
+
|
|
27
|
+
soup = BeautifulSoup(out_html.read_text(), "html.parser")
|
|
28
|
+
imgs = soup.find_all('img')
|
|
29
|
+
|
|
30
|
+
img_path = app.outdir / imgs[0]['src']
|
|
31
|
+
with open(img_path, "rb") as fd:
|
|
32
|
+
image_regression.check(fd.read())
|
sphinxcontrib_screenshot-0.1.3/setup.py → sphinxcontrib_screenshot-0.1.4/tests/test_figclass.py
RENAMED
|
@@ -12,6 +12,17 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
import pytest
|
|
16
|
+
from bs4 import BeautifulSoup
|
|
17
|
+
from sphinx.testing.util import SphinxTestApp
|
|
16
18
|
|
|
17
|
-
|
|
19
|
+
|
|
20
|
+
@pytest.mark.sphinx('html', testroot='figclass')
|
|
21
|
+
def test_default(app: SphinxTestApp) -> None:
|
|
22
|
+
app.build()
|
|
23
|
+
out_html = app.outdir / "index.html"
|
|
24
|
+
soup = BeautifulSoup(out_html.read_text(), "html.parser")
|
|
25
|
+
|
|
26
|
+
# The figure node should have the class name specified.
|
|
27
|
+
figure = soup.select_one('figure.round')
|
|
28
|
+
assert figure is not None
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Copyright 2024 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
|
+
from io import StringIO
|
|
15
|
+
|
|
16
|
+
import pytest
|
|
17
|
+
from bs4 import BeautifulSoup
|
|
18
|
+
from sphinx.testing.util import SphinxTestApp
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@pytest.mark.sphinx('html', testroot="full-page")
|
|
22
|
+
def test_full_page_option(app: SphinxTestApp, status: StringIO,
|
|
23
|
+
warning: StringIO, image_regression) -> None:
|
|
24
|
+
app.build()
|
|
25
|
+
out_html = app.outdir / "index.html"
|
|
26
|
+
|
|
27
|
+
soup = BeautifulSoup(out_html.read_text(), "html.parser")
|
|
28
|
+
imgs = soup.find_all('img')
|
|
29
|
+
|
|
30
|
+
img_path = app.outdir / imgs[0]['src']
|
|
31
|
+
with open(img_path, "rb") as fd:
|
|
32
|
+
image_regression.check(fd.read())
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@pytest.mark.sphinx('html', testroot="default-full-page")
|
|
36
|
+
def test_default_full_page(app: SphinxTestApp, status: StringIO,
|
|
37
|
+
warning: StringIO, image_regression) -> None:
|
|
38
|
+
app.build()
|
|
39
|
+
out_html = app.outdir / "index.html"
|
|
40
|
+
|
|
41
|
+
soup = BeautifulSoup(out_html.read_text(), "html.parser")
|
|
42
|
+
imgs = soup.find_all('img')
|
|
43
|
+
|
|
44
|
+
img_path = app.outdir / imgs[0]['src']
|
|
45
|
+
with open(img_path, "rb") as fd:
|
|
46
|
+
image_regression.check(fd.read())
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Copyright 2024 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
|
+
from io import StringIO
|
|
15
|
+
|
|
16
|
+
import pytest
|
|
17
|
+
from bs4 import BeautifulSoup
|
|
18
|
+
from sphinx.testing.util import SphinxTestApp
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@pytest.mark.sphinx('html', testroot="headers")
|
|
22
|
+
def test_headers(app: SphinxTestApp, status: StringIO, warning: StringIO,
|
|
23
|
+
image_regression) -> None:
|
|
24
|
+
app.build()
|
|
25
|
+
out_html = app.outdir / "index.html"
|
|
26
|
+
|
|
27
|
+
soup = BeautifulSoup(out_html.read_text(), "html.parser")
|
|
28
|
+
imgs = soup.find_all('img')
|
|
29
|
+
|
|
30
|
+
img_path = app.outdir / imgs[0]['src']
|
|
31
|
+
with open(img_path, "rb") as fd:
|
|
32
|
+
# Tolerance of 0.5%
|
|
33
|
+
image_regression.check(fd.read(), diff_threshold=0.5)
|
|
@@ -0,0 +1,34 @@
|
|
|
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 os
|
|
16
|
+
|
|
17
|
+
import pytest
|
|
18
|
+
from bs4 import BeautifulSoup
|
|
19
|
+
from sphinx.testing.util import SphinxTestApp
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@pytest.mark.sphinx('html', testroot='pdf')
|
|
23
|
+
def test_default(app: SphinxTestApp) -> None:
|
|
24
|
+
app.build()
|
|
25
|
+
out_html = app.outdir / "index.html"
|
|
26
|
+
soup = BeautifulSoup(out_html.read_text(), "html.parser")
|
|
27
|
+
img = soup.select_one('img')
|
|
28
|
+
assert img
|
|
29
|
+
|
|
30
|
+
imgsrc = str(img['src'])
|
|
31
|
+
root, ext = os.path.splitext(os.path.basename(imgsrc))
|
|
32
|
+
pdf_filepath = app.outdir / '_static' / 'screenshots' / f'{root}.pdf'
|
|
33
|
+
# Should generate a screenshot PDF.
|
|
34
|
+
assert os.path.exists(pdf_filepath)
|
sphinxcontrib_screenshot-0.1.3/tests/test_it.py → sphinxcontrib_screenshot-0.1.4/tests/test_root.py
RENAMED
|
@@ -12,7 +12,6 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
-
import os
|
|
16
15
|
from io import StringIO
|
|
17
16
|
|
|
18
17
|
import pytest
|
|
@@ -21,16 +20,15 @@ from PIL import Image
|
|
|
21
20
|
from sphinx.testing.util import SphinxTestApp
|
|
22
21
|
|
|
23
22
|
|
|
24
|
-
@pytest.mark.sphinx('html')
|
|
25
|
-
def test_default(app: SphinxTestApp
|
|
26
|
-
warning: StringIO) -> None:
|
|
23
|
+
@pytest.mark.sphinx('html', testroot='root')
|
|
24
|
+
def test_default(app: SphinxTestApp) -> None:
|
|
27
25
|
app.build()
|
|
28
26
|
out_html = app.outdir / "index.html"
|
|
29
27
|
soup = BeautifulSoup(out_html.read_text(), "html.parser")
|
|
30
28
|
|
|
31
29
|
# Every screenshot directive should become an image.
|
|
32
30
|
imgs = soup.find_all('img')
|
|
33
|
-
assert len(list(imgs)) ==
|
|
31
|
+
assert len(list(imgs)) == 3
|
|
34
32
|
|
|
35
33
|
# The image size should be set as specified.
|
|
36
34
|
img_obj = Image.open(app.outdir / imgs[0]['src'])
|
|
@@ -39,32 +37,40 @@ def test_default(app: SphinxTestApp, status: StringIO,
|
|
|
39
37
|
assert height == 320
|
|
40
38
|
|
|
41
39
|
# The caption should be rendered.
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
img_after_interaction.getdata())
|
|
40
|
+
figcaptions = [
|
|
41
|
+
figcaption.get_text().strip()
|
|
42
|
+
for figcaption in soup.select('figcaption span')
|
|
43
|
+
]
|
|
44
|
+
assert figcaptions == [
|
|
45
|
+
'This is a test screenshot', 'This is another screenshot',
|
|
46
|
+
'Changing the background.'
|
|
47
|
+
]
|
|
51
48
|
|
|
52
49
|
# The images should be the same if the difference is only the caption.
|
|
53
50
|
img_with_caption_a = imgs[0]
|
|
54
51
|
img_with_caption_b = imgs[1]
|
|
55
52
|
assert img_with_caption_a['src'] == img_with_caption_b['src']
|
|
56
53
|
|
|
57
|
-
# The
|
|
58
|
-
|
|
54
|
+
# The images should be different after the specified user interaction.
|
|
55
|
+
imgsrc_before_interaction = app.outdir / imgs[1]['src']
|
|
56
|
+
imgsrc_after_interaction = app.outdir / imgs[2]['src']
|
|
57
|
+
assert imgsrc_before_interaction != imgsrc_after_interaction
|
|
58
|
+
assert list(Image.open(imgsrc_before_interaction).getdata()) != list(
|
|
59
|
+
Image.open(imgsrc_after_interaction).getdata())
|
|
60
|
+
|
|
59
61
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
62
|
+
@pytest.mark.sphinx('html', testroot="default-size")
|
|
63
|
+
def test_default_size(app: SphinxTestApp, status: StringIO, warning: StringIO,
|
|
64
|
+
image_regression) -> None:
|
|
65
|
+
"""Test the 'screenshot_default_width' and
|
|
66
|
+
'screenshot_default_height' configuration parameters."""
|
|
67
|
+
app.build()
|
|
68
|
+
out_html = app.outdir / "index.html"
|
|
65
69
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
70
|
+
soup = BeautifulSoup(out_html.read_text(), "html.parser")
|
|
71
|
+
imgs = soup.find_all('img')
|
|
72
|
+
|
|
73
|
+
img_obj = Image.open(app.outdir / imgs[0]['src'])
|
|
74
|
+
width, height = img_obj.size
|
|
75
|
+
assert width == 1920
|
|
76
|
+
assert height == 1200
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Copyright 2024 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
|
+
from io import StringIO
|
|
15
|
+
|
|
16
|
+
import pytest
|
|
17
|
+
from bs4 import BeautifulSoup
|
|
18
|
+
from sphinx.testing.util import SphinxTestApp
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@pytest.mark.sphinx('html', testroot="wsgi-apps")
|
|
22
|
+
def test_default(app: SphinxTestApp, status: StringIO, warning: StringIO,
|
|
23
|
+
image_regression) -> None:
|
|
24
|
+
app.build()
|
|
25
|
+
out_html = app.outdir / "index.html"
|
|
26
|
+
|
|
27
|
+
soup = BeautifulSoup(out_html.read_text(), "html.parser")
|
|
28
|
+
imgs = soup.find_all('img')
|
|
29
|
+
|
|
30
|
+
img_path = app.outdir / imgs[0]['src']
|
|
31
|
+
with open(img_path, "rb") as fd:
|
|
32
|
+
image_regression.check(fd.read())
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
# sphinxcontrib-screenshot
|
|
2
|
-
|
|
3
|
-
A Sphinx extension to embed website screenshots.
|
|
4
|
-
|
|
5
|
-

|
|
6
|
-
|
|
7
|
-
## Install
|
|
8
|
-
|
|
9
|
-
```bash
|
|
10
|
-
pip install sphinxcontrib-screenshot
|
|
11
|
-
playwright install
|
|
12
|
-
```
|
|
13
|
-
|
|
14
|
-
## Usage
|
|
15
|
-
|
|
16
|
-
Add `sphinxcontrib.screenshot` to your `conf.py`.
|
|
17
|
-
|
|
18
|
-
```py
|
|
19
|
-
extensions = ["sphinxcontrib.screenshot"]
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
Then use the `screenshot` directive in your Sphinx source file.
|
|
23
|
-
|
|
24
|
-
```rst
|
|
25
|
-
.. screenshot:: http://www.example.com
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
You can also specify the screen size for the screenshot with `width` and `height` parameters.
|
|
29
|
-
|
|
30
|
-
```rst
|
|
31
|
-
.. screenshot:: http://www.example.com
|
|
32
|
-
:width: 1280
|
|
33
|
-
:height: 960
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
You can include a caption for the screenshot's `figure` directive.
|
|
37
|
-
|
|
38
|
-
```rst
|
|
39
|
-
.. screenshot:: http://www.example.com
|
|
40
|
-
:caption: This is a screenshot for www.example.com
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
You can describe the interaction that you want to have with the webpage before taking a screenshot in JavaScript.
|
|
44
|
-
|
|
45
|
-
```rst
|
|
46
|
-
.. screenshot:: http://www.example.com
|
|
47
|
-
|
|
48
|
-
document.querySelector('button').click();
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
## Pro tips
|
|
52
|
-
`sphinxcontrib-screenshot` supports URLs with the HTTP and HTTPS protocols.
|
|
53
|
-
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:
|
|
54
|
-
|
|
55
|
-
### Build the document
|
|
56
|
-
```bash
|
|
57
|
-
npx --yes concurrently -k --success=first "make html" "python3 -m http.server 3000 --directory=examples"
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
### Watch and build the document
|
|
61
|
-
```bash
|
|
62
|
-
npx --yes concurrently -k "make livehtml" "python3 -m http.server 3000 --directory=examples"
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
## Notes
|
|
67
|
-
|
|
68
|
-
This extension uses [Playwright](https://playwright.dev) to capture a screenshot of the specified website only.
|
|
69
|
-
No data is sent to any other external server; the request is limited to the specified website.
|
|
70
|
-
Be cautious: avoid including sensitive information (such as authentication data) in the directive content.
|
|
71
|
-
|
|
72
|
-
## Contributing
|
|
73
|
-
|
|
74
|
-
See [`CONTRIBUTING.md`](CONTRIBUTING.md) for details.
|
|
75
|
-
|
|
76
|
-
## License
|
|
77
|
-
|
|
78
|
-
Apache 2.0; see [`LICENSE`](LICENSE) for details.
|
|
79
|
-
|
|
80
|
-
## Disclaimer
|
|
81
|
-
|
|
82
|
-
This project is not an official Google project. It is not supported by
|
|
83
|
-
Google and Google specifically disclaims all warranties as to its quality,
|
|
84
|
-
merchantability, or fitness for a particular purpose.
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
[metadata]
|
|
2
|
-
name = sphinxcontrib-screenshot
|
|
3
|
-
version = attr: sphinxcontrib.screenshot.__version__
|
|
4
|
-
description = A Shpinx extension to embed webpage screenshots.
|
|
5
|
-
long_description = file: README.md
|
|
6
|
-
long_description_content_type = text/markdown
|
|
7
|
-
license = Apache-2.0
|
|
8
|
-
author = Shuhei Iitsuka
|
|
9
|
-
author_email = tushuhei@gmail.com
|
|
10
|
-
url = https://github.com/tushuhei/sphinxcontrib-screenshot/
|
|
11
|
-
classifiers =
|
|
12
|
-
Development Status :: 3 - Alpha
|
|
13
|
-
Operating System :: OS Independent
|
|
14
|
-
License :: OSI Approved :: Apache Software License
|
|
15
|
-
Programming Language :: Python :: 3.9
|
|
16
|
-
Programming Language :: Python :: 3.10
|
|
17
|
-
Programming Language :: Python :: 3.11
|
|
18
|
-
|
|
19
|
-
[options]
|
|
20
|
-
python_requires = >= 3.9
|
|
21
|
-
packages =
|
|
22
|
-
sphinxcontrib
|
|
23
|
-
include_package_data = True
|
|
24
|
-
test_suite = tests
|
|
25
|
-
install_requires =
|
|
26
|
-
playwright
|
|
27
|
-
sphinx
|
|
28
|
-
|
|
29
|
-
[options.extras_require]
|
|
30
|
-
dev =
|
|
31
|
-
beautifulsoup4
|
|
32
|
-
build
|
|
33
|
-
flake8
|
|
34
|
-
isort
|
|
35
|
-
mypy
|
|
36
|
-
Pillow
|
|
37
|
-
pytest
|
|
38
|
-
sphinx[test]
|
|
39
|
-
toml
|
|
40
|
-
twine
|
|
41
|
-
types-beautifulsoup4
|
|
42
|
-
types-docutils
|
|
43
|
-
types-Pillow
|
|
44
|
-
types-setuptools
|
|
45
|
-
yapf
|
|
46
|
-
|
|
47
|
-
[yapf]
|
|
48
|
-
based_on_style = yapf
|
|
49
|
-
|
|
50
|
-
[flake8]
|
|
51
|
-
indent-size = 2
|
|
52
|
-
|
|
53
|
-
[mypy]
|
|
54
|
-
python_version = 3.9
|
|
55
|
-
pretty = True
|
|
56
|
-
|
|
57
|
-
[egg_info]
|
|
58
|
-
tag_build =
|
|
59
|
-
tag_date = 0
|
|
60
|
-
|
|
File without changes
|
|
File without changes
|
|
File without changes
|