@remixmate/cli 0.9.72 → 0.9.73
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.
- package/LICENSE +45 -21
- package/README.md +1 -1
- package/README.zh-CN.md +1 -1
- package/dist/argv.js +1 -51
- package/dist/auth/auth-lock.js +1 -100
- package/dist/auth/auto-login.js +7 -75
- package/dist/auth/commands.js +40 -290
- package/dist/auth/credential-store.js +1 -143
- package/dist/auth/device-flow-runner.js +13 -110
- package/dist/auth/device-flow.js +1 -132
- package/dist/auth/ensure.js +1 -62
- package/dist/auth/environment.js +1 -69
- package/dist/auth/pending-store.js +1 -45
- package/dist/auth/resolve.js +1 -44
- package/dist/billing.js +3 -76
- package/dist/capabilities.js +1 -75
- package/dist/cli.js +39 -211
- package/dist/diagnostics.js +2 -70
- package/dist/doctor.js +9 -188
- package/dist/errors.js +1 -33
- package/dist/exec.js +4 -47
- package/dist/handlers/gen-digital-human.js +33 -264
- package/dist/handlers/gen-image.js +9 -113
- package/dist/handlers/gen-post.js +15 -192
- package/dist/handlers/gen-video.js +7 -185
- package/dist/handlers/gen-voice.js +19 -133
- package/dist/handlers/index.js +1 -20
- package/dist/handlers/shared.js +1 -66
- package/dist/handlers/template-init.js +1 -21
- package/dist/http.js +3 -155
- package/dist/index.js +1 -8
- package/dist/install.js +40 -448
- package/dist/manifest.json +44 -3
- package/dist/progress.js +2 -15
- package/dist/project/commands.js +34 -156
- package/dist/project/host.js +1 -151
- package/dist/project/resolve.js +1 -65
- package/dist/project/store.js +2 -97
- package/dist/project/take.js +1 -106
- package/dist/project/trace.js +5 -278
- package/dist/registry.js +3 -70
- package/dist/runner.js +7 -225
- package/dist/skill-schema.js +1 -194
- package/dist/template/args.js +1 -69
- package/dist/template/check.js +2 -30
- package/dist/template/commands.js +34 -163
- package/dist/template/constants.js +1 -46
- package/dist/template/init.js +5 -133
- package/dist/template/list.js +1 -46
- package/dist/template/preview.js +7 -318
- package/dist/template/proc.js +1 -43
- package/dist/template/project.js +6 -161
- package/dist/template/publish.js +5 -185
- package/dist/template/render-client.js +2 -79
- package/dist/template/upgrade.js +4 -123
- package/dist/text.js +1 -15
- package/package.json +2 -35
- package/skills/doc-parse/scripts/extract_via_render.py +32 -32
- package/skills/export-jianying/scripts/gen_jianying_draft.py +188 -188
- package/skills/gen-script/SKILL.md +23 -1
- package/skills/gen-script/scripts/gen_script.py +644 -551
- package/skills/gen-script/skill.json +12 -0
- package/skills/gen-script/version.json +1 -1
- package/skills/prepare-video-assets/scripts/prepare_video_assets.py +21 -21
- package/skills/render-video/scripts/_chrome_vendor.py +17 -17
- package/skills/render-video/scripts/_digital_human_segments.py +34 -34
- package/skills/render-video/scripts/_video_probe.py +33 -33
- package/skills/render-video/scripts/_vod_polling.py +13 -13
- package/skills/render-video/scripts/remote_renderer_client.py +42 -42
- package/skills/render-video/scripts/render_video.py +639 -639
- package/skills/render-video/scripts/required_props.py +37 -37
- package/skills/render-video/scripts/upload_video.py +35 -35
- package/skills/render-video/version.json +1 -1
- package/skills/template-registry/SKILL.md +16 -0
- package/skills/template-registry/scripts/countdown_spec.py +92 -92
- package/skills/template-registry/scripts/doc_extract.py +40 -40
- package/skills/template-registry/scripts/list_templates.py +303 -191
- package/skills/template-registry/scripts/log_diagnostics.py +1 -1
- package/skills/template-registry/scripts/match_template.py +87 -87
- package/skills/template-registry/scripts/payload_hydrator.py +89 -89
- package/skills/template-registry/scripts/registry_loader.py +159 -159
- package/skills/template-registry/scripts/render_job_client.py +75 -75
- package/skills/template-registry/scripts/showcase_loader.py +44 -44
- package/skills/template-registry/skill.json +4 -1
- package/skills/template-registry/version.json +1 -1
- package/skills/template-registry/video_dsl/runtime/__init__.py +8 -8
- package/skills/template-registry/video_dsl/runtime/dsl_validator.py +329 -329
- package/skills/template-registry/video_dsl/runtime/narration_budget.py +36 -36
- package/skills/template-registry/video_dsl/runtime/payload_contract.py +7 -7
- package/skills/template-registry/video_dsl/runtime/prompt_enhancer.py +98 -98
- package/skills/template-registry/video_dsl/runtime/timeline_compiler.py +127 -127
- package/skills/template-registry/video_dsl/schema/video-dsl-v1alpha1.json +14 -1
- package/skills/video-parser/scripts/analyze_video.py +173 -173
- package/skills/video-parser/scripts/deconstruct_video.py +91 -91
- package/skills/video-parser/scripts/parse_via_render.py +21 -21
- package/skills/web-screenshot/scripts/_media_screenshot/__init__.py +4 -4
- package/skills/web-screenshot/scripts/_media_screenshot/bootstrap.py +7 -7
- package/skills/web-screenshot/scripts/_media_screenshot/browser.py +4 -4
- package/skills/web-screenshot/scripts/_media_screenshot/cli_args.py +4 -4
- package/skills/web-screenshot/scripts/_media_screenshot/js_loader.py +2 -2
- package/skills/web-screenshot/scripts/_media_screenshot/overlay.py +1 -1
- package/skills/web-screenshot/scripts/_media_screenshot/reader.py +40 -40
- package/skills/web-screenshot/scripts/_media_screenshot/recording.py +11 -11
- package/skills/web-screenshot/scripts/_media_screenshot/scenes/__init__.py +8 -8
- package/skills/web-screenshot/scripts/_media_screenshot/scenes/arrow.py +2 -2
- package/skills/web-screenshot/scripts/_media_screenshot/scenes/caption.py +1 -1
- package/skills/web-screenshot/scripts/_media_screenshot/scenes/click.py +1 -1
- package/skills/web-screenshot/scripts/_media_screenshot/scenes/code_lines.py +5 -5
- package/skills/web-screenshot/scripts/_media_screenshot/scenes/focus.py +1 -1
- package/skills/web-screenshot/scripts/_media_screenshot/scenes/highlight.py +3 -3
- package/skills/web-screenshot/scripts/_media_screenshot/scenes/hover.py +1 -1
- package/skills/web-screenshot/scripts/_media_screenshot/scenes/redact.py +1 -1
- package/skills/web-screenshot/scripts/_media_screenshot/scenes/scroll.py +1 -1
- package/skills/web-screenshot/scripts/_media_screenshot/scenes/sequence.py +1 -1
- package/skills/web-screenshot/scripts/_media_screenshot/scenes/title_card.py +1 -1
- package/skills/web-screenshot/scripts/_media_screenshot/scenes/type.py +1 -1
- package/skills/web-screenshot/scripts/_media_screenshot/scenes/wait.py +1 -1
- package/skills/web-screenshot/scripts/_media_screenshot/scenes/zoom.py +2 -2
- package/skills/web-screenshot/scripts/_media_screenshot/screenshot.py +15 -15
- package/skills/web-screenshot/scripts/_media_screenshot/storyboard.py +2 -2
- package/skills/web-screenshot/scripts/_media_screenshot/template.py +11 -11
- package/skills/web-screenshot/scripts/_media_screenshot/trim.py +10 -10
- package/skills/web-screenshot/scripts/_media_screenshot/urlguard.py +22 -22
- package/skills/web-screenshot/scripts/_media_upload.py +33 -33
- package/skills/web-screenshot/scripts/read_page.py +15 -15
- package/skills/web-screenshot/scripts/record.py +26 -26
- package/skills/web-screenshot/scripts/screenshot.py +5 -5
- package/dist/argv.d.ts +0 -15
- package/dist/auth/auth-lock.d.ts +0 -26
- package/dist/auth/auto-login.d.ts +0 -20
- package/dist/auth/commands.d.ts +0 -8
- package/dist/auth/credential-store.d.ts +0 -60
- package/dist/auth/device-flow-runner.d.ts +0 -58
- package/dist/auth/device-flow.d.ts +0 -52
- package/dist/auth/ensure.d.ts +0 -55
- package/dist/auth/environment.d.ts +0 -38
- package/dist/auth/pending-store.d.ts +0 -33
- package/dist/auth/resolve.d.ts +0 -30
- package/dist/billing.d.ts +0 -44
- package/dist/capabilities.d.ts +0 -63
- package/dist/cli.d.ts +0 -13
- package/dist/diagnostics.d.ts +0 -24
- package/dist/doctor.d.ts +0 -22
- package/dist/errors.d.ts +0 -29
- package/dist/exec.d.ts +0 -18
- package/dist/handlers/gen-digital-human.d.ts +0 -17
- package/dist/handlers/gen-image.d.ts +0 -20
- package/dist/handlers/gen-post.d.ts +0 -22
- package/dist/handlers/gen-video.d.ts +0 -19
- package/dist/handlers/gen-voice.d.ts +0 -26
- package/dist/handlers/index.d.ts +0 -20
- package/dist/handlers/shared.d.ts +0 -26
- package/dist/handlers/template-init.d.ts +0 -10
- package/dist/http.d.ts +0 -72
- package/dist/index.d.ts +0 -9
- package/dist/install.d.ts +0 -71
- package/dist/progress.d.ts +0 -23
- package/dist/project/commands.d.ts +0 -19
- package/dist/project/host.d.ts +0 -91
- package/dist/project/resolve.d.ts +0 -43
- package/dist/project/store.d.ts +0 -31
- package/dist/project/take.d.ts +0 -50
- package/dist/project/trace.d.ts +0 -98
- package/dist/registry.d.ts +0 -30
- package/dist/runner.d.ts +0 -39
- package/dist/skill-schema.d.ts +0 -138
- package/dist/template/args.d.ts +0 -25
- package/dist/template/check.d.ts +0 -23
- package/dist/template/commands.d.ts +0 -25
- package/dist/template/constants.d.ts +0 -39
- package/dist/template/init.d.ts +0 -28
- package/dist/template/list.d.ts +0 -23
- package/dist/template/preview.d.ts +0 -60
- package/dist/template/proc.d.ts +0 -26
- package/dist/template/project.d.ts +0 -47
- package/dist/template/publish.d.ts +0 -43
- package/dist/template/render-client.d.ts +0 -39
- package/dist/template/upgrade.d.ts +0 -44
- package/dist/text.d.ts +0 -8
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
"""Read operation: load a page and extract its main content as text.
|
|
2
1
|
|
|
3
|
-
The DOM work lives in ``js/extract_article.js`` (one injected pass returning
|
|
4
|
-
typed blocks); this module drives the browser, renders those blocks into the
|
|
5
|
-
requested format, and enforces the character budget.
|
|
6
2
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
12
|
from __future__ import annotations
|
|
13
13
|
|
|
14
14
|
import json
|
|
@@ -20,20 +20,20 @@ from . import js_loader
|
|
|
20
20
|
from .bootstrap import ensure_runtime
|
|
21
21
|
from .browser import apply_pre_action_waits, build_context_options, launch_with_browser_install
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
|
|
24
|
+
|
|
25
25
|
_SKIPPED_RESOURCE_TYPES = {"image", "media", "font", "stylesheet"}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
|
|
30
30
|
_SUBRESOURCE_TIMEOUT_MS = 8000
|
|
31
|
-
|
|
31
|
+
|
|
32
32
|
_DOM_READY_TIMEOUT_MS = 15000
|
|
33
33
|
|
|
34
34
|
|
|
35
35
|
class _SubresourceGate:
|
|
36
|
-
|
|
36
|
+
|
|
37
37
|
|
|
38
38
|
def __init__(self) -> None:
|
|
39
39
|
self.stalled: list[str] = []
|
|
@@ -53,7 +53,7 @@ class _SubresourceGate:
|
|
|
53
53
|
try:
|
|
54
54
|
route.abort()
|
|
55
55
|
except Exception:
|
|
56
|
-
pass
|
|
56
|
+
pass
|
|
57
57
|
return
|
|
58
58
|
try:
|
|
59
59
|
route.fulfill(response=resp)
|
|
@@ -67,9 +67,9 @@ class _SubresourceGate:
|
|
|
67
67
|
|
|
68
68
|
|
|
69
69
|
def _navigation_error(url: str, e: Exception) -> SystemExit:
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
|
|
73
73
|
first = str(e).splitlines()[0] if str(e) else ""
|
|
74
74
|
kind = "超时未响应" if type(e).__name__ == "TimeoutError" else "连接失败"
|
|
75
75
|
return SystemExit(
|
|
@@ -82,7 +82,7 @@ def _navigation_error(url: str, e: Exception) -> SystemExit:
|
|
|
82
82
|
|
|
83
83
|
|
|
84
84
|
def extract(cfg: dict) -> dict:
|
|
85
|
-
|
|
85
|
+
|
|
86
86
|
ensure_runtime()
|
|
87
87
|
from playwright.sync_api import sync_playwright
|
|
88
88
|
|
|
@@ -104,7 +104,7 @@ def extract(cfg: dict) -> dict:
|
|
|
104
104
|
page.route("**/*", gate)
|
|
105
105
|
try:
|
|
106
106
|
try:
|
|
107
|
-
|
|
107
|
+
|
|
108
108
|
response = page.goto(cfg["url"], wait_until="commit")
|
|
109
109
|
except Exception as e:
|
|
110
110
|
raise _navigation_error(cfg["url"], e)
|
|
@@ -120,13 +120,13 @@ def extract(cfg: dict) -> dict:
|
|
|
120
120
|
print(f"[web_read] {note}", file=sys.stderr)
|
|
121
121
|
status = response.status if response else None
|
|
122
122
|
if status is not None and status >= 400:
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
|
|
126
126
|
pass
|
|
127
127
|
apply_pre_action_waits(page, cfg)
|
|
128
|
-
|
|
129
|
-
|
|
128
|
+
|
|
129
|
+
|
|
130
130
|
try:
|
|
131
131
|
page.wait_for_load_state("networkidle", timeout=cfg.get("networkIdleMs", 8000))
|
|
132
132
|
except Exception:
|
|
@@ -145,10 +145,10 @@ def extract(cfg: dict) -> dict:
|
|
|
145
145
|
browser.close()
|
|
146
146
|
|
|
147
147
|
|
|
148
|
-
|
|
148
|
+
|
|
149
149
|
|
|
150
150
|
def _render_blocks(blocks: list, fmt: str) -> list[str]:
|
|
151
|
-
|
|
151
|
+
|
|
152
152
|
md = fmt == "markdown"
|
|
153
153
|
out: list[str] = []
|
|
154
154
|
for block in blocks:
|
|
@@ -227,14 +227,14 @@ def _header(data: dict, fmt: str) -> str:
|
|
|
227
227
|
|
|
228
228
|
|
|
229
229
|
def render(data: dict, cfg: dict) -> tuple[str, str, bool]:
|
|
230
|
-
"""Return (stdout_text, full_text, truncated).
|
|
231
230
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
|
|
235
235
|
fmt = cfg.get("format", "markdown")
|
|
236
236
|
blocks = list(data.get("blocks") or [])
|
|
237
|
-
|
|
237
|
+
|
|
238
238
|
title = ((data.get("metadata") or {}).get("title") or "").strip()
|
|
239
239
|
if blocks and title and blocks[0].get("type") == "heading":
|
|
240
240
|
first = (blocks[0].get("text") or "").strip().rstrip("¶").strip()
|
|
@@ -254,8 +254,8 @@ def render(data: dict, cfg: dict) -> tuple[str, str, bool]:
|
|
|
254
254
|
"blocks": data.get("blocks"),
|
|
255
255
|
}
|
|
256
256
|
full = json.dumps(payload, ensure_ascii=False, indent=2)
|
|
257
|
-
|
|
258
|
-
|
|
257
|
+
|
|
258
|
+
|
|
259
259
|
return full, full, False
|
|
260
260
|
|
|
261
261
|
full = f"{_header(data, fmt)}\n\n{body}".strip()
|
|
@@ -264,7 +264,7 @@ def render(data: dict, cfg: dict) -> tuple[str, str, bool]:
|
|
|
264
264
|
if max_chars <= 0 or len(full) <= max_chars:
|
|
265
265
|
return full, full, False
|
|
266
266
|
|
|
267
|
-
|
|
267
|
+
|
|
268
268
|
head = f"{_header(data, fmt)}\n\n"
|
|
269
269
|
kept: list[str] = []
|
|
270
270
|
used = len(head)
|
|
@@ -274,7 +274,7 @@ def render(data: dict, cfg: dict) -> tuple[str, str, bool]:
|
|
|
274
274
|
kept.append(part)
|
|
275
275
|
used += len(part) + 2
|
|
276
276
|
if not kept:
|
|
277
|
-
|
|
277
|
+
|
|
278
278
|
kept = [body[: max(0, max_chars - len(head))]]
|
|
279
279
|
shown = (head + "\n\n".join(kept)).strip()
|
|
280
280
|
notice = (
|
|
@@ -285,7 +285,7 @@ def render(data: dict, cfg: dict) -> tuple[str, str, bool]:
|
|
|
285
285
|
|
|
286
286
|
|
|
287
287
|
def do_read(cfg: dict) -> dict:
|
|
288
|
-
|
|
288
|
+
|
|
289
289
|
data = extract(cfg)
|
|
290
290
|
|
|
291
291
|
if data.get("error") == "selector-not-found":
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
|
|
2
2
|
from __future__ import annotations
|
|
3
3
|
|
|
4
4
|
import sys
|
|
@@ -59,11 +59,11 @@ def _wait_for_stop_condition(page, cfg: dict) -> str:
|
|
|
59
59
|
|
|
60
60
|
|
|
61
61
|
def do_record(cfg: dict) -> tuple[Path, int, int]:
|
|
62
|
-
"""Plain recording — returns (output_path, start_ms, end_ms).
|
|
63
62
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
|
|
67
67
|
ensure_runtime()
|
|
68
68
|
from playwright.sync_api import sync_playwright
|
|
69
69
|
|
|
@@ -74,8 +74,8 @@ def do_record(cfg: dict) -> tuple[Path, int, int]:
|
|
|
74
74
|
with sync_playwright() as p:
|
|
75
75
|
browser = launch_with_browser_install(p, cfg.get("browser"))
|
|
76
76
|
try:
|
|
77
|
-
|
|
78
|
-
|
|
77
|
+
|
|
78
|
+
|
|
79
79
|
t0 = time.time()
|
|
80
80
|
context = browser.new_context(**build_context_options(p, cfg, out_dir))
|
|
81
81
|
if cfg.get("timeout"):
|
|
@@ -87,8 +87,8 @@ def do_record(cfg: dict) -> tuple[Path, int, int]:
|
|
|
87
87
|
try:
|
|
88
88
|
page.goto(cfg["url"], wait_until="domcontentloaded")
|
|
89
89
|
apply_pre_action_waits(page, cfg)
|
|
90
|
-
|
|
91
|
-
|
|
90
|
+
|
|
91
|
+
|
|
92
92
|
wait_until_settled(page, cfg)
|
|
93
93
|
start_ms = int((time.time() - t0) * 1000)
|
|
94
94
|
if cfg.get("scrollThrough"):
|
|
@@ -112,6 +112,6 @@ def do_record(cfg: dict) -> tuple[Path, int, int]:
|
|
|
112
112
|
src = Path(video_path)
|
|
113
113
|
if src.resolve() != output:
|
|
114
114
|
src.replace(output)
|
|
115
|
-
|
|
116
|
-
|
|
115
|
+
|
|
116
|
+
|
|
117
117
|
return output, start_ms, end_ms
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
"""Scene registry.
|
|
2
1
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
7
|
from __future__ import annotations
|
|
8
8
|
|
|
9
9
|
from typing import Callable
|
|
@@ -28,9 +28,9 @@ def known_types() -> list[str]:
|
|
|
28
28
|
return sorted(_REGISTRY.keys())
|
|
29
29
|
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
|
|
34
34
|
import importlib as _importlib
|
|
35
35
|
import pkgutil as _pkgutil
|
|
36
36
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
|
|
2
2
|
from __future__ import annotations
|
|
3
3
|
|
|
4
4
|
from .. import js_loader
|
|
@@ -7,7 +7,7 @@ from . import register
|
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
def _resolve_anchor(page, anchor: dict) -> tuple[float, float]:
|
|
10
|
-
|
|
10
|
+
|
|
11
11
|
if anchor is None:
|
|
12
12
|
raise RuntimeError("arrow: missing anchor (need from/to)")
|
|
13
13
|
if "x" in anchor and "y" in anchor:
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
"""Code-lines scene: highlight a contiguous line range in a code view.
|
|
2
1
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
7
|
from __future__ import annotations
|
|
8
8
|
|
|
9
9
|
from .. import js_loader
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
|
|
2
2
|
from __future__ import annotations
|
|
3
3
|
|
|
4
4
|
from .. import js_loader
|
|
@@ -7,8 +7,8 @@ from . import register
|
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
def _union_box(page, selectors: list[str]) -> dict | None:
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
|
|
11
|
+
|
|
12
12
|
resolve_locator(page, selectors[0])
|
|
13
13
|
boxes: list[dict] = []
|
|
14
14
|
for sel in selectors:
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
|
|
2
2
|
from __future__ import annotations
|
|
3
3
|
|
|
4
4
|
from .. import js_loader
|
|
@@ -60,7 +60,7 @@ def scene_zoom(page, scene: dict) -> None:
|
|
|
60
60
|
target = scene.get("target", "element")
|
|
61
61
|
locator = resolve_locator(page, scene["selector"])
|
|
62
62
|
locator.scroll_into_view_if_needed()
|
|
63
|
-
|
|
63
|
+
|
|
64
64
|
locator.evaluate(
|
|
65
65
|
"el => el.scrollIntoView({ block: 'center', inline: 'center', behavior: 'instant' })"
|
|
66
66
|
)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
|
|
4
4
|
from __future__ import annotations
|
|
5
5
|
|
|
6
6
|
import json
|
|
@@ -18,7 +18,7 @@ from .overlay import ensure_overlay
|
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
def _apply_hide(page, selectors: list[str]) -> None:
|
|
21
|
-
|
|
21
|
+
|
|
22
22
|
if not selectors:
|
|
23
23
|
return
|
|
24
24
|
page.evaluate(
|
|
@@ -36,7 +36,7 @@ def _apply_hide(page, selectors: list[str]) -> None:
|
|
|
36
36
|
|
|
37
37
|
|
|
38
38
|
def _apply_annotations(page, annotations: list[dict], settle_ms: int) -> None:
|
|
39
|
-
|
|
39
|
+
|
|
40
40
|
if not annotations:
|
|
41
41
|
return
|
|
42
42
|
ensure_overlay(page)
|
|
@@ -49,8 +49,8 @@ def _apply_annotations(page, annotations: list[dict], settle_ms: int) -> None:
|
|
|
49
49
|
file=sys.stderr,
|
|
50
50
|
)
|
|
51
51
|
continue
|
|
52
|
-
|
|
53
|
-
|
|
52
|
+
|
|
53
|
+
|
|
54
54
|
ann_copy = dict(ann)
|
|
55
55
|
ann_copy.setdefault("duration", 0)
|
|
56
56
|
ann_copy.setdefault("holdMs", 0)
|
|
@@ -63,7 +63,7 @@ def _apply_annotations(page, annotations: list[dict], settle_ms: int) -> None:
|
|
|
63
63
|
|
|
64
64
|
|
|
65
65
|
def _load_annotations(spec) -> tuple[list[dict], int]:
|
|
66
|
-
|
|
66
|
+
|
|
67
67
|
if spec is None:
|
|
68
68
|
return [], 0
|
|
69
69
|
settle_ms = 900
|
|
@@ -93,7 +93,7 @@ def _build_mask_locators(page, selectors: list[str]):
|
|
|
93
93
|
|
|
94
94
|
|
|
95
95
|
def do_screenshot(cfg: dict) -> Path:
|
|
96
|
-
|
|
96
|
+
|
|
97
97
|
ensure_runtime()
|
|
98
98
|
from playwright.sync_api import sync_playwright
|
|
99
99
|
from playwright.sync_api import TimeoutError as PlaywrightTimeoutError
|
|
@@ -126,14 +126,14 @@ def do_screenshot(cfg: dict) -> Path:
|
|
|
126
126
|
|
|
127
127
|
if cfg.get("selector"):
|
|
128
128
|
locator = page.locator(cfg["selector"]).first
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
|
|
133
133
|
probe_timeout = cfg.get("selectorTimeout")
|
|
134
134
|
if probe_timeout is None:
|
|
135
|
-
|
|
136
|
-
|
|
135
|
+
|
|
136
|
+
|
|
137
137
|
probe_timeout = min(cfg.get("timeout") or 8000, 8000)
|
|
138
138
|
try:
|
|
139
139
|
locator.wait_for(state="attached", timeout=probe_timeout)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
|
|
2
2
|
from __future__ import annotations
|
|
3
3
|
|
|
4
4
|
import sys
|
|
@@ -45,7 +45,7 @@ def _run_storyboard(page, cfg: dict) -> None:
|
|
|
45
45
|
|
|
46
46
|
|
|
47
47
|
def do_storyboard(cfg: dict) -> tuple[Path, int, int]:
|
|
48
|
-
|
|
48
|
+
|
|
49
49
|
ensure_runtime()
|
|
50
50
|
from playwright.sync_api import sync_playwright
|
|
51
51
|
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
10
|
from __future__ import annotations
|
|
11
11
|
|
|
12
12
|
import json
|
|
@@ -71,7 +71,7 @@ def list_templates() -> list[Path]:
|
|
|
71
71
|
|
|
72
72
|
|
|
73
73
|
def load_template(name: str) -> dict:
|
|
74
|
-
|
|
74
|
+
|
|
75
75
|
p = Path(name)
|
|
76
76
|
if not p.exists():
|
|
77
77
|
p = _TEMPLATES_DIR / f"{name}.json"
|
|
@@ -85,7 +85,7 @@ def load_template(name: str) -> dict:
|
|
|
85
85
|
|
|
86
86
|
|
|
87
87
|
def render_template(name: str, params: dict[str, str]) -> dict:
|
|
88
|
-
|
|
88
|
+
|
|
89
89
|
tpl = load_template(name)
|
|
90
90
|
meta = tpl.pop("_meta", {})
|
|
91
91
|
declared = meta.get("params", {}) or {}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
9
|
from __future__ import annotations
|
|
10
10
|
|
|
11
11
|
import os
|
|
@@ -48,11 +48,11 @@ def trim_video(out: Path, start_ms: int, end_ms: int) -> None:
|
|
|
48
48
|
|
|
49
49
|
video_dur = _probe_duration(out)
|
|
50
50
|
if video_dur is None:
|
|
51
|
-
|
|
51
|
+
|
|
52
52
|
start_s = max(0.0, (start_ms - lead_ms) / 1000.0)
|
|
53
53
|
duration_s = keep_ms / 1000.0
|
|
54
54
|
else:
|
|
55
|
-
|
|
55
|
+
|
|
56
56
|
start_s = max(0.0, video_dur - keep_ms / 1000.0)
|
|
57
57
|
duration_s = video_dur - start_s
|
|
58
58
|
|
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
18
18
|
from __future__ import annotations
|
|
19
19
|
|
|
20
20
|
import ipaddress
|
|
@@ -41,7 +41,7 @@ def _is_blocked(ip: ipaddress._BaseAddress) -> bool:
|
|
|
41
41
|
|
|
42
42
|
|
|
43
43
|
def assert_public_url(raw_url: str) -> None:
|
|
44
|
-
|
|
44
|
+
|
|
45
45
|
parsed = urlparse(raw_url)
|
|
46
46
|
if parsed.scheme not in ("http", "https"):
|
|
47
47
|
raise SystemExit(
|
|
@@ -54,7 +54,7 @@ def assert_public_url(raw_url: str) -> None:
|
|
|
54
54
|
if allow_private_hosts():
|
|
55
55
|
return
|
|
56
56
|
|
|
57
|
-
|
|
57
|
+
|
|
58
58
|
try:
|
|
59
59
|
literal = ipaddress.ip_address(host)
|
|
60
60
|
except ValueError:
|
|
@@ -75,9 +75,9 @@ def assert_public_url(raw_url: str) -> None:
|
|
|
75
75
|
ip = ipaddress.ip_address(addr)
|
|
76
76
|
except ValueError:
|
|
77
77
|
continue
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
|
|
81
81
|
if _is_blocked(ip):
|
|
82
82
|
raise SystemExit(_refusal(host, addr))
|
|
83
83
|
|