sourcemonkey 0.0.0-stage → 0.5.0
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 +21 -0
- package/README.md +87 -2
- package/dist/bytes.js +37 -0
- package/dist/channel-placeholder.js +5 -0
- package/dist/collection-scan.js +17 -0
- package/dist/collections.html +353 -0
- package/dist/compare.html +358 -0
- package/dist/composed-source.js +205 -0
- package/dist/connect-prompt.html +47 -0
- package/dist/debug/icons.html +211 -0
- package/dist/debug/storage.html +163 -0
- package/dist/debug-log.js +75 -0
- package/dist/diagnostic-location.js +64 -0
- package/dist/eval-hook.js +308 -0
- package/dist/extension/background.js +5263 -0
- package/dist/extension/channel.js +133 -0
- package/dist/extension/code-links.js +187 -0
- package/dist/extension/code-tabs.js +460 -0
- package/dist/extension/collection-dialog.js +619 -0
- package/dist/extension/collection-display.js +322 -0
- package/dist/extension/collections.js +2905 -0
- package/dist/extension/compare.js +867 -0
- package/dist/extension/concurrency.js +186 -0
- package/dist/extension/connect-grants.js +109 -0
- package/dist/extension/connect-prompt-page.js +70 -0
- package/dist/extension/connect-prompt.js +266 -0
- package/dist/extension/copy-button.js +63 -0
- package/dist/extension/copy-dialog.js +502 -0
- package/dist/extension/copy-preference.js +66 -0
- package/dist/extension/debug/icons.js +203 -0
- package/dist/extension/debug/storage.js +365 -0
- package/dist/extension/deep-link.js +77 -0
- package/dist/extension/delete-dialog.js +432 -0
- package/dist/extension/delete-icon.js +40 -0
- package/dist/extension/details-tooltips.js +66 -0
- package/dist/extension/directories.js +679 -0
- package/dist/extension/export-backup.js +407 -0
- package/dist/extension/export-dialog.js +142 -0
- package/dist/extension/file-access.js +74 -0
- package/dist/extension/file-changes.js +346 -0
- package/dist/extension/frame-info.js +85 -0
- package/dist/extension/github-provider.js +336 -0
- package/dist/extension/glyph.js +84 -0
- package/dist/extension/gm-bindings.js +601 -0
- package/dist/extension/gm-download.js +419 -0
- package/dist/extension/gm-menu.js +228 -0
- package/dist/extension/gm-notification.js +141 -0
- package/dist/extension/gm-originator-map.js +23 -0
- package/dist/extension/gm-tab-data.js +121 -0
- package/dist/extension/gm-tab.js +160 -0
- package/dist/extension/gm-url-change.js +111 -0
- package/dist/extension/gm-url-scheme.js +27 -0
- package/dist/extension/gm-values.js +176 -0
- package/dist/extension/gm-window-control.js +104 -0
- package/dist/extension/gm-xhr-headers.js +333 -0
- package/dist/extension/gm-xhr.js +584 -0
- package/dist/extension/injector.js +3145 -0
- package/dist/extension/install-capture.js +277 -0
- package/dist/extension/line-diff.js +233 -0
- package/dist/extension/local-copy.js +560 -0
- package/dist/extension/local-delete.js +276 -0
- package/dist/extension/location-kinds.js +108 -0
- package/dist/extension/log-format.js +158 -0
- package/dist/extension/managed-changes.js +361 -0
- package/dist/extension/managed-items.js +57 -0
- package/dist/extension/match-index.js +375 -0
- package/dist/extension/missing-scripts.js +66 -0
- package/dist/extension/more-menu.js +109 -0
- package/dist/extension/move-dialog.js +197 -0
- package/dist/extension/offscreen.js +37 -0
- package/dist/extension/options.js +504 -0
- package/dist/extension/page-heading.js +170 -0
- package/dist/extension/page-links.js +199 -0
- package/dist/extension/parse-check-client.js +70 -0
- package/dist/extension/parse-check.js +161 -0
- package/dist/extension/parse-sandbox-host.js +172 -0
- package/dist/extension/parse-sandbox.js +175 -0
- package/dist/extension/popup-commands-open.js +41 -0
- package/dist/extension/popup-view.js +387 -0
- package/dist/extension/popup.js +703 -0
- package/dist/extension/prism-userscript.js +53 -0
- package/dist/extension/refresh-error.js +136 -0
- package/dist/extension/refresh-targets.js +160 -0
- package/dist/extension/related-versions.js +1144 -0
- package/dist/extension/resize-observer-loop.js +19 -0
- package/dist/extension/row-cache.js +387 -0
- package/dist/extension/script-blobs.js +413 -0
- package/dist/extension/script-details.js +658 -0
- package/dist/extension/script-enablement.js +285 -0
- package/dist/extension/script-identity.js +310 -0
- package/dist/extension/script-keys.js +54 -0
- package/dist/extension/script-log-id.js +155 -0
- package/dist/extension/script-log.js +290 -0
- package/dist/extension/script-rejection.js +104 -0
- package/dist/extension/script-sites.js +158 -0
- package/dist/extension/script-store.js +3507 -0
- package/dist/extension/script-updater.js +991 -0
- package/dist/extension/script-url-hash.js +61 -0
- package/dist/extension/select-all.js +37 -0
- package/dist/extension/select-open-guard.js +90 -0
- package/dist/extension/site-icon.js +1261 -0
- package/dist/extension/sm-dev-link.js +302 -0
- package/dist/extension/solo-click.js +58 -0
- package/dist/extension/sticky-numbers.js +188 -0
- package/dist/extension/storage-breakdown.js +253 -0
- package/dist/extension/storage-scan.js +86 -0
- package/dist/extension/storage-usage.js +194 -0
- package/dist/extension/structural-keys.js +29 -0
- package/dist/extension/sw-teardown.js +36 -0
- package/dist/extension/tab-status.js +403 -0
- package/dist/extension/toolbar-summary.js +105 -0
- package/dist/extension/user-scripts-access.js +43 -0
- package/dist/extension/userscript.js +3672 -0
- package/dist/extension/value-store.js +204 -0
- package/dist/extension/version-probe-fetch.js +68 -0
- package/dist/extension/worker-client.js +109 -0
- package/dist/extension/worker-ops.js +171 -0
- package/dist/extension/zip-writer.js +24 -0
- package/dist/external-files.js +878 -0
- package/dist/file-loader.js +436 -0
- package/dist/file-locations.js +439 -0
- package/dist/generated-wrappers.js +5 -0
- package/dist/github-auth.js +148 -0
- package/dist/github-urls.js +46 -0
- package/dist/gm-api-catalog.js +217 -0
- package/dist/gm-connect.js +273 -0
- package/dist/gm-xhr-types.js +5 -0
- package/dist/http-read.js +142 -0
- package/dist/icons/icon-128.png +0 -0
- package/dist/icons/icon-16.png +0 -0
- package/dist/icons/icon-48.png +0 -0
- package/dist/local-file-overrides.js +558 -0
- package/dist/manifest.json +38 -0
- package/dist/markup-response.js +126 -0
- package/dist/match-targets.js +305 -0
- package/dist/menu-captions.js +22 -0
- package/dist/offscreen.html +39 -0
- package/dist/options.html +197 -0
- package/dist/parse-check-protocol.js +51 -0
- package/dist/parse-location.js +171 -0
- package/dist/parse-sandbox.html +56 -0
- package/dist/phase-timing.js +155 -0
- package/dist/popup.html +197 -0
- package/dist/public-suffixes.js +6957 -0
- package/dist/run-context.js +31 -0
- package/dist/runtime-messages.js +34 -0
- package/dist/sandboxed-page.js +35 -0
- package/dist/script-build.js +787 -0
- package/dist/script-display.js +383 -0
- package/dist/script-icon.js +43 -0
- package/dist/script-links.js +204 -0
- package/dist/script-source-url.js +214 -0
- package/dist/script-world.js +65 -0
- package/dist/sm-dev-protocol.js +84 -0
- package/dist/source-map.js +177 -0
- package/dist/stack-link.js +138 -0
- package/dist/styles.css +825 -0
- package/dist/unsafe-window-use.js +229 -0
- package/dist/url-match.js +734 -0
- package/dist/userscript-header.js +248 -0
- package/dist/userscript.html +1165 -0
- package/dist/vendor/fflate.LICENSE +21 -0
- package/dist/vendor/fflate.js +2692 -0
- package/dist/vendor/prism/prism-line-numbers.css +1 -0
- package/dist/vendor/prism/prism-line-numbers.js +1 -0
- package/dist/vendor/prism/prism.css +1 -0
- package/dist/vendor/prism/prism.js +1946 -0
- package/dist/version-compare.js +141 -0
- package/dist/version-probe.js +120 -0
- package/lib/build-info.json +1 -0
- package/lib/bytes.d.ts +3 -0
- package/lib/bytes.js +37 -0
- package/lib/channel-placeholder.d.ts +1 -0
- package/lib/channel-placeholder.js +5 -0
- package/lib/collection-scan.d.ts +8 -0
- package/lib/collection-scan.js +17 -0
- package/lib/composed-source.d.ts +28 -0
- package/lib/composed-source.js +205 -0
- package/lib/debug-log.d.ts +9 -0
- package/lib/debug-log.js +75 -0
- package/lib/diagnostic-location.d.ts +8 -0
- package/lib/diagnostic-location.js +64 -0
- package/lib/eval-hook.d.ts +34 -0
- package/lib/eval-hook.js +308 -0
- package/lib/external-files.d.ts +111 -0
- package/lib/external-files.js +878 -0
- package/lib/file-loader.d.ts +48 -0
- package/lib/file-loader.js +436 -0
- package/lib/file-locations.d.ts +44 -0
- package/lib/file-locations.js +439 -0
- package/lib/generated-wrappers.d.ts +11 -0
- package/lib/generated-wrappers.js +5 -0
- package/lib/github-auth.d.ts +12 -0
- package/lib/github-auth.js +148 -0
- package/lib/github-urls.d.ts +1 -0
- package/lib/github-urls.js +46 -0
- package/lib/gm-api-catalog.d.ts +24 -0
- package/lib/gm-api-catalog.js +217 -0
- package/lib/gm-connect.d.ts +34 -0
- package/lib/gm-connect.js +273 -0
- package/lib/gm-xhr-types.d.ts +68 -0
- package/lib/gm-xhr-types.js +5 -0
- package/lib/harness/browser-extensions.d.ts +73 -0
- package/lib/harness/browser-extensions.js +285 -0
- package/lib/harness/browser-lang.d.ts +20 -0
- package/lib/harness/browser-lang.js +86 -0
- package/lib/harness/browser-launch.d.ts +14 -0
- package/lib/harness/browser-launch.js +184 -0
- package/lib/harness/checks.d.ts +110 -0
- package/lib/harness/checks.js +321 -0
- package/lib/harness/cli.d.ts +2 -0
- package/lib/harness/cli.js +2259 -0
- package/lib/harness/command-args.d.ts +91 -0
- package/lib/harness/command-args.js +369 -0
- package/lib/harness/command-lines.d.ts +80 -0
- package/lib/harness/command-lines.js +180 -0
- package/lib/harness/command-list.d.ts +206 -0
- package/lib/harness/command-list.js +1475 -0
- package/lib/harness/console-commands.d.ts +463 -0
- package/lib/harness/console-commands.js +3216 -0
- package/lib/harness/download-watch.d.ts +21 -0
- package/lib/harness/download-watch.js +156 -0
- package/lib/harness/extension-backend.d.ts +41 -0
- package/lib/harness/extension-backend.js +100 -0
- package/lib/harness/extension-host.d.ts +112 -0
- package/lib/harness/extension-host.js +552 -0
- package/lib/harness/extension-launch.d.ts +67 -0
- package/lib/harness/extension-launch.js +285 -0
- package/lib/harness/extension-link.d.ts +315 -0
- package/lib/harness/extension-link.js +607 -0
- package/lib/harness/external-manager.d.ts +146 -0
- package/lib/harness/external-manager.js +414 -0
- package/lib/harness/fixture.d.ts +165 -0
- package/lib/harness/fixture.js +461 -0
- package/lib/harness/frame-sessions.d.ts +71 -0
- package/lib/harness/frame-sessions.js +248 -0
- package/lib/harness/frames.d.ts +68 -0
- package/lib/harness/frames.js +216 -0
- package/lib/harness/help-format.d.ts +17 -0
- package/lib/harness/help-format.js +127 -0
- package/lib/harness/host.d.ts +352 -0
- package/lib/harness/host.js +423 -0
- package/lib/harness/index.d.ts +8 -0
- package/lib/harness/index.js +10 -0
- package/lib/harness/input-file.d.ts +18 -0
- package/lib/harness/input-file.js +61 -0
- package/lib/harness/json-output.d.ts +565 -0
- package/lib/harness/json-output.js +71 -0
- package/lib/harness/manager-actions.d.ts +21 -0
- package/lib/harness/manager-actions.js +129 -0
- package/lib/harness/manager-commands.d.ts +142 -0
- package/lib/harness/manager-commands.js +1196 -0
- package/lib/harness/manager-fetch.d.ts +33 -0
- package/lib/harness/manager-fetch.js +239 -0
- package/lib/harness/managers.d.ts +24 -0
- package/lib/harness/managers.js +27 -0
- package/lib/harness/output-style.d.ts +125 -0
- package/lib/harness/output-style.js +322 -0
- package/lib/harness/page-commands.d.ts +134 -0
- package/lib/harness/page-commands.js +1141 -0
- package/lib/harness/page-output.d.ts +67 -0
- package/lib/harness/page-output.js +139 -0
- package/lib/harness/page-watch.d.ts +171 -0
- package/lib/harness/page-watch.js +607 -0
- package/lib/harness/parse-check-node.d.ts +3 -0
- package/lib/harness/parse-check-node.js +132 -0
- package/lib/harness/path-args.d.ts +22 -0
- package/lib/harness/path-args.js +148 -0
- package/lib/harness/playwright-chromium.d.ts +16 -0
- package/lib/harness/playwright-chromium.js +86 -0
- package/lib/harness/prepare.d.ts +168 -0
- package/lib/harness/prepare.js +364 -0
- package/lib/harness/prompt-editor.d.ts +17 -0
- package/lib/harness/prompt-editor.js +354 -0
- package/lib/harness/prompt-history.d.ts +13 -0
- package/lib/harness/prompt-history.js +89 -0
- package/lib/harness/rebuild-advice.d.ts +6 -0
- package/lib/harness/rebuild-advice.js +39 -0
- package/lib/harness/run-log.d.ts +47 -0
- package/lib/harness/run-log.js +140 -0
- package/lib/harness/run-logs.d.ts +132 -0
- package/lib/harness/run-logs.js +241 -0
- package/lib/harness/run.d.ts +194 -0
- package/lib/harness/run.js +1973 -0
- package/lib/harness/runs.d.ts +229 -0
- package/lib/harness/runs.js +726 -0
- package/lib/harness/save-html.d.ts +39 -0
- package/lib/harness/save-html.js +89 -0
- package/lib/harness/saved-pages.d.ts +120 -0
- package/lib/harness/saved-pages.js +275 -0
- package/lib/harness/script-mark.d.ts +17 -0
- package/lib/harness/script-mark.js +56 -0
- package/lib/harness/snapshot.d.ts +143 -0
- package/lib/harness/snapshot.js +474 -0
- package/lib/harness/stuck-tabs.d.ts +19 -0
- package/lib/harness/stuck-tabs.js +131 -0
- package/lib/harness/tab-refs.d.ts +20 -0
- package/lib/harness/tab-refs.js +80 -0
- package/lib/harness/tampermonkey.d.ts +71 -0
- package/lib/harness/tampermonkey.js +356 -0
- package/lib/harness/tm-ids.d.ts +18 -0
- package/lib/harness/tm-ids.js +88 -0
- package/lib/harness/violentmonkey.d.ts +34 -0
- package/lib/harness/violentmonkey.js +162 -0
- package/lib/harness/wait.d.ts +77 -0
- package/lib/harness/wait.js +458 -0
- package/lib/http-read.d.ts +30 -0
- package/lib/http-read.js +142 -0
- package/lib/local-file-overrides.d.ts +35 -0
- package/lib/local-file-overrides.js +558 -0
- package/lib/manifest.json +38 -0
- package/lib/markup-response.d.ts +11 -0
- package/lib/markup-response.js +126 -0
- package/lib/match-targets.d.ts +18 -0
- package/lib/match-targets.js +305 -0
- package/lib/menu-captions.d.ts +1 -0
- package/lib/menu-captions.js +22 -0
- package/lib/parse-check-protocol.d.ts +27 -0
- package/lib/parse-check-protocol.js +51 -0
- package/lib/parse-location.d.ts +12 -0
- package/lib/parse-location.js +171 -0
- package/lib/phase-timing.d.ts +12 -0
- package/lib/phase-timing.js +155 -0
- package/lib/public-suffixes.d.ts +1 -0
- package/lib/public-suffixes.js +6957 -0
- package/lib/run-context.d.ts +2 -0
- package/lib/run-context.js +31 -0
- package/lib/runtime-messages.d.ts +10 -0
- package/lib/runtime-messages.js +34 -0
- package/lib/sandboxed-page.d.ts +5 -0
- package/lib/sandboxed-page.js +35 -0
- package/lib/script-build.d.ts +111 -0
- package/lib/script-build.js +787 -0
- package/lib/script-display.d.ts +51 -0
- package/lib/script-display.js +383 -0
- package/lib/script-icon.d.ts +16 -0
- package/lib/script-icon.js +43 -0
- package/lib/script-links.d.ts +24 -0
- package/lib/script-links.js +204 -0
- package/lib/script-source-url.d.ts +8 -0
- package/lib/script-source-url.js +214 -0
- package/lib/script-world.d.ts +6 -0
- package/lib/script-world.js +65 -0
- package/lib/sm-dev-protocol.d.ts +251 -0
- package/lib/sm-dev-protocol.js +84 -0
- package/lib/source-map.d.ts +32 -0
- package/lib/source-map.js +177 -0
- package/lib/stack-link.d.ts +15 -0
- package/lib/stack-link.js +138 -0
- package/lib/unsafe-window-use.d.ts +1 -0
- package/lib/unsafe-window-use.js +229 -0
- package/lib/url-match.d.ts +40 -0
- package/lib/url-match.js +734 -0
- package/lib/userscript-header.d.ts +33 -0
- package/lib/userscript-header.js +248 -0
- package/lib/version-compare.d.ts +6 -0
- package/lib/version-compare.js +141 -0
- package/lib/version-probe.d.ts +17 -0
- package/lib/version-probe.js +120 -0
- package/package.json +55 -3
- package/skills/SourceMonkey-dev/SKILL.md +868 -0
- package/skills/SourceMonkey-dev/references/cdp.md +293 -0
- package/skills/SourceMonkey-dev/references/commands.md +297 -0
- package/skills/SourceMonkey-dev/references/other-managers.md +63 -0
- package/skills/SourceMonkey-dev/references/specs.md +46 -0
- package/skills/SourceMonkey-friction/SKILL.md +103 -0
- package/skills/SourceMonkey-friction/references/template.md +59 -0
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
# Raw CDP alongside a run
|
|
2
|
+
|
|
3
|
+
sm-dev drives tabs over CDP (Chrome DevTools Protocol). For what it has
|
|
4
|
+
no command for, send raw calls to the same tab while the run goes on.
|
|
5
|
+
|
|
6
|
+
- Protocol reference: https://chromedevtools.github.io/devtools-protocol/
|
|
7
|
+
- Afterwards, `$R wait` lets the page settle, and `$R eval` or
|
|
8
|
+
`$R logs` shows the effect in sm-dev's terms.
|
|
9
|
+
|
|
10
|
+
## The `cdp` command
|
|
11
|
+
|
|
12
|
+
One call, its result printed as JSON:
|
|
13
|
+
|
|
14
|
+
```sh
|
|
15
|
+
$R cdp Runtime.evaluate '{"expression": "document.title", "returnByValue": true}'
|
|
16
|
+
$R cdp T2 Page.reload # another tab
|
|
17
|
+
$R cdp Browser.getVersion # browser-level domains work too
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
- It acts on the current tab, or the one named first (`T2`,
|
|
21
|
+
`targetId=...`).
|
|
22
|
+
- Several calls go in a `{{` block, one per line, run in order on one
|
|
23
|
+
session. It stops at the first that fails, and says why:
|
|
24
|
+
|
|
25
|
+
```sh
|
|
26
|
+
$R --stdin <<'EOF'
|
|
27
|
+
cdp T2 {{
|
|
28
|
+
Page.enable
|
|
29
|
+
Page.getNavigationHistory
|
|
30
|
+
}}
|
|
31
|
+
EOF
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
- `cdp --file calls.txt` reads the calls from a file, one per line.
|
|
35
|
+
- In a block or file, blank lines and lines starting with `#` are skipped.
|
|
36
|
+
- Params go on the method's line: bare, or in single quotes (which may
|
|
37
|
+
hold `'` in the JSON's strings).
|
|
38
|
+
- `Browser.*` and `Target.*` work from the tab's session, and default
|
|
39
|
+
to its tab: `Browser.getWindowForTarget` with no params gives the
|
|
40
|
+
tab's window.
|
|
41
|
+
- Each call gets 10 seconds. One that never answers (a paused page)
|
|
42
|
+
fails with a message. One cut off by the page navigating (a
|
|
43
|
+
navigating `Runtime.evaluate`) says so, and counts as done.
|
|
44
|
+
- `cdp` doesn't wait for the page to settle. Run `wait` after it.
|
|
45
|
+
- **Session state ends with the command.** `Emulation.*` overrides,
|
|
46
|
+
enabled domains and event subscriptions last only as long as its
|
|
47
|
+
session: one command, or one block.
|
|
48
|
+
- To use one across sm-dev commands, hold a connection open in your
|
|
49
|
+
own script (below), and clear what you set before it exits.
|
|
50
|
+
- So a call that sets something up for a later navigation
|
|
51
|
+
(`Page.addScriptToEvaluateOnNewDocument`) goes in the same block as
|
|
52
|
+
the `Page.navigate`.
|
|
53
|
+
- **A call can't use an earlier call's result.** An `objectId` from
|
|
54
|
+
`Runtime.evaluate` can't be passed to the next call in a block. For
|
|
55
|
+
chains like that, write a script.
|
|
56
|
+
- `cdp` can't listen for events. For that, write a script.
|
|
57
|
+
|
|
58
|
+
## Your own script
|
|
59
|
+
|
|
60
|
+
sm-dev's connection doesn't own the browser: its CDP port accepts other
|
|
61
|
+
clients at the same time.
|
|
62
|
+
|
|
63
|
+
- The port: a temp browser (the default) picks a random one, or uses
|
|
64
|
+
`--browser`'s. With `--open-browser` or `--existing-browser`, 9233
|
|
65
|
+
by default, or the `--browser` / `$SM_DEV_BROWSER` sm-dev uses. `status`
|
|
66
|
+
shows it on its first line (`browser 127.0.0.1:9233`).
|
|
67
|
+
- The tab: its `targetId`. The run prints it when it opens the tab
|
|
68
|
+
(`Opening <url> in T1 [targetId=...]`), and `tabs` lists them all.
|
|
69
|
+
Never pick a tab by URL.
|
|
70
|
+
- Or read it from the tab itself, with no text to scrape:
|
|
71
|
+
`$R cdp T2 Target.getTargetInfo` gives `targetInfo.targetId`.
|
|
72
|
+
|
|
73
|
+
Node 22+ has a built-in `WebSocket`, so a script needs no dependencies:
|
|
74
|
+
|
|
75
|
+
```js
|
|
76
|
+
const port = 9233, targetId = process.argv[2];
|
|
77
|
+
const tabs = await (await fetch(`http://127.0.0.1:${port}/json/list`)).json();
|
|
78
|
+
const ws = new WebSocket(tabs.find((t) => t.id === targetId).webSocketDebuggerUrl);
|
|
79
|
+
await new Promise((r) => { ws.onopen = r; });
|
|
80
|
+
let id = 0; const waiting = new Map();
|
|
81
|
+
ws.onmessage = ({ data }) => {
|
|
82
|
+
const m = JSON.parse(data);
|
|
83
|
+
if (m.id) waiting.get(m.id)?.(m); else console.log('event', m.method, JSON.stringify(m.params));
|
|
84
|
+
};
|
|
85
|
+
const send = (method, params = {}) => new Promise((r) => {
|
|
86
|
+
waiting.set(++id, r); ws.send(JSON.stringify({ id, method, params }));
|
|
87
|
+
});
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
- `GET /json/version` gives the browser-level socket
|
|
91
|
+
(`webSocketDebuggerUrl`).
|
|
92
|
+
- Or use Playwright: `chromium.connectOverCDP('http://127.0.0.1:9233')`,
|
|
93
|
+
then find the page whose `Target.getTargetInfo` (from
|
|
94
|
+
`context.newCDPSession(page)`) has the `targetId`. Connect with
|
|
95
|
+
`noDefaults: true`, or Playwright changes the person's browser
|
|
96
|
+
(focus emulation, color scheme, downloads).
|
|
97
|
+
- Put a script that imports the repo's own dependencies (Playwright)
|
|
98
|
+
inside the repo, in a git-ignored folder: Node looks for imports
|
|
99
|
+
from the script's own directory, so one in `/tmp` can't find them.
|
|
100
|
+
- A `Runtime.evaluate` that navigates the page never gets its reply
|
|
101
|
+
(the document is gone). Use `Page.navigate`, or `$R open`.
|
|
102
|
+
|
|
103
|
+
## Recipes
|
|
104
|
+
|
|
105
|
+
### Back and forward
|
|
106
|
+
|
|
107
|
+
No CDP needed:
|
|
108
|
+
|
|
109
|
+
```sh
|
|
110
|
+
$R eval 'history.back()' -- wait
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Or by history entry: `Page.getNavigationHistory` lists `entries` with
|
|
114
|
+
ids and the `currentIndex`, then
|
|
115
|
+
`Page.navigateToHistoryEntry '{"entryId": N}'`.
|
|
116
|
+
|
|
117
|
+
### Where an element is
|
|
118
|
+
|
|
119
|
+
Input events take viewport coordinates in CSS pixels. Get them from the
|
|
120
|
+
page:
|
|
121
|
+
|
|
122
|
+
```sh
|
|
123
|
+
$R eval '(r => [Math.round(r.x + r.width / 2), Math.round(r.y + r.height / 2)])(document.querySelector(".target").getBoundingClientRect())'
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
The element must be on screen: `$R eval 'document.querySelector(".target").scrollIntoView({block: "center"})'`
|
|
127
|
+
first.
|
|
128
|
+
|
|
129
|
+
### Mouse wheel
|
|
130
|
+
|
|
131
|
+
Real wheel input, which the page sees differently from a synthetic
|
|
132
|
+
`WheelEvent` (targeting, default scrolling, passive listeners):
|
|
133
|
+
|
|
134
|
+
```sh
|
|
135
|
+
$R cdp Input.dispatchMouseEvent '{"type": "mouseWheel", "x": 400, "y": 300, "deltaX": 0, "deltaY": 600}' -- wait -- eval scrollY
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
- Pinch zoom on a trackpad arrives as a wheel event with `ctrlKey`: add
|
|
139
|
+
`"modifiers": 2`.
|
|
140
|
+
|
|
141
|
+
### Clicks at a point
|
|
142
|
+
|
|
143
|
+
**On an element, don't use CDP.** Use sm-dev's `click`, which finds
|
|
144
|
+
the element's center (or the point `--at` gives), scrolls to it, and
|
|
145
|
+
checks nothing covers it:
|
|
146
|
+
|
|
147
|
+
```sh
|
|
148
|
+
$R click e14 --button right # or middle
|
|
149
|
+
$R click '.item' --modifiers Shift # Control+Alt, etc.
|
|
150
|
+
$R click '.word' --count 2 # double-click
|
|
151
|
+
$R click '.row' --at 300,12 # a point in it, from its top left
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
Raw CDP is only needed for a point `click` can't aim at: one on no
|
|
155
|
+
element it can find, or where its checks (covered, moving) get in the
|
|
156
|
+
way. Move there first (pages that react to hover need it), then press
|
|
157
|
+
and release at the same point:
|
|
158
|
+
|
|
159
|
+
```sh
|
|
160
|
+
$R --stdin <<'EOF'
|
|
161
|
+
cdp {{
|
|
162
|
+
Input.dispatchMouseEvent {"type": "mouseMoved", "x": 50, "y": 50}
|
|
163
|
+
Input.dispatchMouseEvent {"type": "mousePressed", "x": 50, "y": 50, "button": "right", "clickCount": 1}
|
|
164
|
+
Input.dispatchMouseEvent {"type": "mouseReleased", "x": 50, "y": 50, "button": "right", "clickCount": 1}
|
|
165
|
+
}}
|
|
166
|
+
EOF
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
- `button`: `left`, `middle`, `right`, `back`, `forward`.
|
|
170
|
+
- `modifiers` is a bitmask: Alt 1, Ctrl 2, Meta (Cmd) 4, Shift 8. So
|
|
171
|
+
Shift-click is `"modifiers": 8` on both events; Ctrl-Shift is 10.
|
|
172
|
+
- Double-click: a press/release with `clickCount: 1`, then another with
|
|
173
|
+
`clickCount: 2`.
|
|
174
|
+
- Get the point from the page (see [Where an element is](#where-an-element-is)).
|
|
175
|
+
|
|
176
|
+
Either way:
|
|
177
|
+
|
|
178
|
+
- A right-click gives the page `contextmenu` and `auxclick` events.
|
|
179
|
+
Chrome's own context menu can't be driven over CDP, so its entries
|
|
180
|
+
(an extension's included) can't be picked; fire userscript menu
|
|
181
|
+
commands with `$R menu`.
|
|
182
|
+
- A Ctrl- or middle-click on a link opens a tab that the run follows
|
|
183
|
+
(it has an opener), as `T2`.
|
|
184
|
+
|
|
185
|
+
### Drag
|
|
186
|
+
|
|
187
|
+
Press, move in steps, release:
|
|
188
|
+
|
|
189
|
+
```sh
|
|
190
|
+
$R --stdin <<'EOF'
|
|
191
|
+
cdp {{
|
|
192
|
+
Input.dispatchMouseEvent {"type": "mousePressed", "x": 100, "y": 100, "button": "left", "clickCount": 1}
|
|
193
|
+
Input.dispatchMouseEvent {"type": "mouseMoved", "x": 150, "y": 100, "button": "left", "buttons": 1}
|
|
194
|
+
Input.dispatchMouseEvent {"type": "mouseMoved", "x": 200, "y": 100, "button": "left", "buttons": 1}
|
|
195
|
+
Input.dispatchMouseEvent {"type": "mouseReleased", "x": 200, "y": 100, "button": "left", "clickCount": 1}
|
|
196
|
+
}}
|
|
197
|
+
wait
|
|
198
|
+
EOF
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
- This drives pointer and mouse listeners (sliders, canvas, most
|
|
202
|
+
custom drag code).
|
|
203
|
+
- Native HTML5 drag-and-drop (`draggable`, `dragstart`/`drop`) needs
|
|
204
|
+
`Input.setInterceptDrags` and `Input.dispatchDragEvent` in a script
|
|
205
|
+
that listens for `Input.dragIntercepted`.
|
|
206
|
+
|
|
207
|
+
### Window size
|
|
208
|
+
|
|
209
|
+
In a browser with a window (`--open-browser`, or the person's own):
|
|
210
|
+
|
|
211
|
+
```sh
|
|
212
|
+
W=$($R cdp Browser.getWindowForTarget | grep -o '"windowId": [0-9]*' | grep -o '[0-9]*$')
|
|
213
|
+
$R cdp Browser.setWindowBounds "{\"windowId\": $W, \"bounds\": {\"windowState\": \"normal\", \"width\": 900, \"height\": 700}}"
|
|
214
|
+
$R wait -- eval '[innerWidth, innerHeight]'
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
- It's a real resize: it lasts, affects the window's other tabs, and
|
|
218
|
+
fires `resize` in the page. Put it back when done.
|
|
219
|
+
- A headless browser (a temp browser, unless headed) ignores it. There, use
|
|
220
|
+
`Emulation.setDeviceMetricsOverride` from a script that keeps its
|
|
221
|
+
connection open, and `Emulation.clearDeviceMetricsOverride` before it
|
|
222
|
+
exits. An override left set confuses later measurements.
|
|
223
|
+
|
|
224
|
+
### Fullscreen
|
|
225
|
+
|
|
226
|
+
- Enter it as a person would: `$R key f`, or `$R click` the site's
|
|
227
|
+
button. Both count as a user action, so `requestFullscreen()` is
|
|
228
|
+
allowed.
|
|
229
|
+
- Check it:
|
|
230
|
+
`$R eval '[document.fullscreenElement?.outerHTML.slice(0, 200), innerWidth, innerHeight]'`.
|
|
231
|
+
In real fullscreen the size is the screen's.
|
|
232
|
+
- Exit with `$R eval document.exitFullscreen()`. `key Escape` reaches
|
|
233
|
+
the page but doesn't exit: Escape leaving fullscreen is a browser
|
|
234
|
+
shortcut, and CDP keys go straight to the page.
|
|
235
|
+
- Switching tabs exits fullscreen, as does a `GM_openInTab` with
|
|
236
|
+
`active`.
|
|
237
|
+
- **Force it off** when the page won't exit: set the window back to
|
|
238
|
+
normal with `Browser.setWindowBounds` and
|
|
239
|
+
`{"windowState": "normal"}`, as above. This works even when the page
|
|
240
|
+
is stuck.
|
|
241
|
+
- **Don't call `Emulation.setFocusEmulationEnabled`.** With it on,
|
|
242
|
+
`requestFullscreen` only fills the tab, and the page lays out at the
|
|
243
|
+
window's size. sm-dev leaves it off.
|
|
244
|
+
|
|
245
|
+
### Tracing a transition per frame
|
|
246
|
+
|
|
247
|
+
Screenshots are too slow to catch a flash, a gap or a jump. Record
|
|
248
|
+
what's on top at chosen points on every frame, then trigger the
|
|
249
|
+
change, then read the record. This runs in the page (`eval --page`);
|
|
250
|
+
change `points` to spots in the image or video:
|
|
251
|
+
|
|
252
|
+
```sh
|
|
253
|
+
$R --stdin <<'EOF'
|
|
254
|
+
eval --page {{
|
|
255
|
+
window.smTrace = [];
|
|
256
|
+
const points = [[400, 300], [20, 20]];
|
|
257
|
+
const t0 = performance.now();
|
|
258
|
+
let last = '';
|
|
259
|
+
const name = (el) => !el ? 'nothing'
|
|
260
|
+
: el.tagName.toLowerCase() + (el.id ? `#${el.id}` : '') + [...el.classList].slice(0, 2).map((c) => `.${c}`).join('');
|
|
261
|
+
(function frame() {
|
|
262
|
+
const now = (document.fullscreenElement ? 'fullscreen: ' : '') + points.map(([x, y]) => name(document.elementFromPoint(x, y))).join(' | ');
|
|
263
|
+
if (now !== last) window.smTrace.push(`${Math.round(performance.now() - t0)}ms ${now}`);
|
|
264
|
+
last = now;
|
|
265
|
+
if (performance.now() - t0 < 3000) requestAnimationFrame(frame);
|
|
266
|
+
else console.log('[trace] done');
|
|
267
|
+
})();
|
|
268
|
+
}}
|
|
269
|
+
key ArrowRight
|
|
270
|
+
wait log '[trace] done' --timeout-seconds 10
|
|
271
|
+
eval --page window.smTrace
|
|
272
|
+
EOF
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
- It keeps only the frames where something changed, for 3 seconds.
|
|
276
|
+
- Frames don't run in a background tab: trace the visible one
|
|
277
|
+
(`$R focus`).
|
|
278
|
+
- To follow an image or video's source, add `el.currentSrc` to `name`.
|
|
279
|
+
|
|
280
|
+
### Other things worth knowing
|
|
281
|
+
|
|
282
|
+
- **Dark mode, reduced motion, print**: `Emulation.setEmulatedMedia`
|
|
283
|
+
with `features` (`prefers-color-scheme: dark`). Session-scoped: set
|
|
284
|
+
it and check the page (`Runtime.evaluate`, `Page.captureScreenshot`)
|
|
285
|
+
in one `cdp {{` block, or from a script that stays connected.
|
|
286
|
+
- **Network**: `Network.enable` in a script, then
|
|
287
|
+
`Network.requestWillBeSent` / `Network.responseReceived` events;
|
|
288
|
+
`Network.getResponseBody` for a body. The script's own
|
|
289
|
+
`GM_xmlhttpRequest`s don't need this: the run's stream prints each
|
|
290
|
+
one's method, URL and outcome.
|
|
291
|
+
- **A background tab's screenshot** renders WebGL canvases (maps)
|
|
292
|
+
blank. Bring it forward first: `$R focus T2`.
|
|
293
|
+
- **Closing the last tab quits Chromium on Linux.** Leave one open.
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
# sm-dev commands by task
|
|
2
|
+
|
|
3
|
+
A summary. `pnpm sm-dev help` lists the help topics, and
|
|
4
|
+
`help <topic>` shows one. `help <command>` (or `<command> --help`)
|
|
5
|
+
shows a command's exact options, and `help script save` (or
|
|
6
|
+
`script save --help`) one subcommand's; `help commands` lists the
|
|
7
|
+
commands, and `help all` everything.
|
|
8
|
+
|
|
9
|
+
## Shape of a command line
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
sm-dev [global options] <command> [args] [-- <command> ...]
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
- Global options go first: `--run ID`,
|
|
16
|
+
`--open-browser`, `--existing-browser`, `--browser URL|PORT`,
|
|
17
|
+
`--manager sm|tm|vm`, `--headed`, `--headless`, `--mute`, `--nomute`,
|
|
18
|
+
`--stdin`, `--interactive`,
|
|
19
|
+
`--root DIR`, `--local DIR`, `--json`.
|
|
20
|
+
- Read the text output by default: it's shorter, and says what an
|
|
21
|
+
empty answer means and where to look next.
|
|
22
|
+
- Add `--json` when you'll parse the output, with `jq` or a script:
|
|
23
|
+
`$R --json scripts | jq -r '.scripts[] | select(.status == "invalid") | .name'`.
|
|
24
|
+
- `--json` works for `list`, `status`, `scripts`, `tabs`, `frames`,
|
|
25
|
+
`values`, `get`, `match`, `validate`, `menu`, `logs`, `probe`, and every
|
|
26
|
+
`collection` and `script` verb (`script list`, `script show`, ...).
|
|
27
|
+
Each prints one JSON object; other commands print text as usual.
|
|
28
|
+
- Other messages and failures stay text, on stderr, with the usual
|
|
29
|
+
exit code.
|
|
30
|
+
- An empty list means nothing was found.
|
|
31
|
+
- A script's `state` on a tab: `running`, `not-running`, or
|
|
32
|
+
`manual` (a `@run-at context-menu` script not run yet); for a
|
|
33
|
+
SourceMonkey-managed script (E1, ...) also `kept-out` (the run
|
|
34
|
+
keeps it out of its tabs), `not-started`, `error` (it threw),
|
|
35
|
+
`refused` (Chrome refused it), `unexpected` (running though it
|
|
36
|
+
doesn't match), `changed` (changed since it started) and `unknown`
|
|
37
|
+
(the page loaded before SourceMonkey started).
|
|
38
|
+
- Every field:
|
|
39
|
+
https://github.com/jshute96/SourceMonkey/blob/main/docs/sm-dev-json.md
|
|
40
|
+
- `--` separates commands. They run in order and stop at the first
|
|
41
|
+
failure (a `match` or `validate` miss excepted).
|
|
42
|
+
- Exit codes: 0 success, 1 a command failed (a check missed, no
|
|
43
|
+
element, an `eval` threw, a `wait` gave up), 2 invalid command
|
|
44
|
+
(`ERROR:`). A few commands still exit 0 when they fail, and `probe`
|
|
45
|
+
reports a missing selector without failing: read the output.
|
|
46
|
+
- Flags take a value after a space or `=` (`--out f.txt`,
|
|
47
|
+
`--out=f.txt`). An unknown flag's error lists the flags the command
|
|
48
|
+
takes; stray arguments are refused, with the command's usage.
|
|
49
|
+
- Quotes: in `--stdin` lines, most commands take off one level of
|
|
50
|
+
quotes around an argument. `eval` and `cdp` don't: their quotes are
|
|
51
|
+
JavaScript's and JSON's. A quoted word is never a flag.
|
|
52
|
+
- Flags can go anywhere, also after or inside `eval`'s JavaScript or
|
|
53
|
+
`wait log`'s text (`eval 'await x()' --timeout-seconds 45`). A word
|
|
54
|
+
there shaped like a flag (`--name`) is taken as one, and an unknown
|
|
55
|
+
one is an error. To keep one as text, quote the text as a whole
|
|
56
|
+
(`type #q 'a --b'`), or in JavaScript write it so the `--` isn't a
|
|
57
|
+
word of its own (`a = '--b'`, `(--n)`).
|
|
58
|
+
|
|
59
|
+
## Names
|
|
60
|
+
|
|
61
|
+
| Thing | Written | Notes |
|
|
62
|
+
| --- | --- | --- |
|
|
63
|
+
| Run | `D1`, or `Dname` from `--run` | `list` shows them |
|
|
64
|
+
| Script | `1`, its path, file name, `@name`, or a unique piece | `T2.3`: script 3 on tab T2 |
|
|
65
|
+
| Tab | `T1`, `targetId=<id>` (or 6+ chars of it) | Page commands take one first: `click T2 .x` |
|
|
66
|
+
| Installed script | `E1` | SourceMonkey's own number, the same in every run |
|
|
67
|
+
| Collection | `C1`, its name or a unique piece, `id=<id>` | A run's test collection: its run, `D1` |
|
|
68
|
+
| Menu command | `M1`, `T2.M1`, or its label | |
|
|
69
|
+
| Element | CSS or Playwright selector, or a ref (`e4`, `f2e6`) | Refs from the latest `snapshot`. A selector in an iframe: `--frame F2` |
|
|
70
|
+
| Frame | `F2`, `T1.F2`, `frameId=<id>`; the top frame is its tab, `T1` | From `frames`; kept across the frame's reloads |
|
|
71
|
+
| Page | URL, file, glob, or script number (its default page) | Scheme optional for hosts |
|
|
72
|
+
|
|
73
|
+
## Browsers
|
|
74
|
+
|
|
75
|
+
| Command | Use |
|
|
76
|
+
| --- | --- |
|
|
77
|
+
| `sm-dev start ...` | The default: a temp, throwaway browser for this run, with SourceMonkey loaded. Good for pages with no login. Headed when the line goes to a prompt |
|
|
78
|
+
| `sm-dev --open-browser` | Start a lasting, visible browser on port 9233 (kept profile, so logins persist). A no-op if one is up |
|
|
79
|
+
| `sm-dev --existing-browser ...` | Connect to the browser already on port 9233 |
|
|
80
|
+
| `--browser 9300` | With `--open-browser` or `--existing-browser`: the browser on another port. With a temp browser: the port to launch it on |
|
|
81
|
+
| `--headed`, `--headless`, `--nomute` | When sm-dev launches the browser: show or hide its window; sound on (a temp browser is muted otherwise) |
|
|
82
|
+
|
|
83
|
+
- A run pushes its scripts into SourceMonkey in that browser. With
|
|
84
|
+
`--open-browser` or `--existing-browser`, it must be loaded there with
|
|
85
|
+
Allow User Scripts on: `manager install` does both.
|
|
86
|
+
- Commands for a browser with no run (`manager install`, `collection`,
|
|
87
|
+
`script`) need `--existing-browser` or `--open-browser`.
|
|
88
|
+
|
|
89
|
+
### Managers
|
|
90
|
+
|
|
91
|
+
`--manager` picks SourceMonkey (`sm`, the default), Tampermonkey (`tm`)
|
|
92
|
+
or Violentmonkey (`vm`). A run keeps the one it started with. How to
|
|
93
|
+
test a script under VM or TM:
|
|
94
|
+
[other-managers.md](other-managers.md).
|
|
95
|
+
|
|
96
|
+
| Command | Does |
|
|
97
|
+
| --- | --- |
|
|
98
|
+
| `--manager tm manager fetch` | Download or update TM (or VM) from the Chrome Web Store into `~/.cache/sm-dev/managers` |
|
|
99
|
+
| `[--manager tm] manager install` | Load the manager into the browser unpacked, with Allow User Scripts on. No run needed |
|
|
100
|
+
| `[--manager tm] manager enable` / `disable` | Turn it on or off in the browser. Not SourceMonkey while a run uses it |
|
|
101
|
+
| `--manager vm start <script> <url>` | A run under VM (or `tm`): its scripts are installed in the manager, and removed when it ends. `values`, `get`, `set`, `menu`, `connect` and `--values` are refused |
|
|
102
|
+
| `--manager vm script list`, `script E3 show`, ... | The manager's scripts, by E-ids, in one collection, `C0`. `collection C0 disable` is its switch for all scripts |
|
|
103
|
+
|
|
104
|
+
- A manager enabled beside the chosen one runs its scripts in the run's
|
|
105
|
+
tabs too: the run's first lines and `status` warn of it.
|
|
106
|
+
- Under VM or TM, `scripts` and `status` show which scripts each tab
|
|
107
|
+
is expected to run, by their match rules (`Expected on tab T1 using
|
|
108
|
+
match rules:`), not what ran. A run's script shows its E-id there
|
|
109
|
+
too: `1: Hello (hello.user.js), E6 in Violentmonkey`.
|
|
110
|
+
- Under VM or TM, a run never replaces a script the manager already
|
|
111
|
+
has by the same name and namespace: `start` refuses, naming it.
|
|
112
|
+
|
|
113
|
+
## Runs
|
|
114
|
+
|
|
115
|
+
| Command | Does |
|
|
116
|
+
| --- | --- |
|
|
117
|
+
| `start [script]... [url]... --detach` | Start a run in the background; returns once pages settle |
|
|
118
|
+
| `start ... --watch` | Re-push and reload on each save of a script or local `@require` |
|
|
119
|
+
| `start ... --values '<json>'` | Seed GM storage first |
|
|
120
|
+
| `start ... --values-file <path>` | Seed GM storage first, from a JSON file |
|
|
121
|
+
| `start ... --log-source all` | Also stream the site's own lines and errors (sources: `sm`, `event`, `script`, `page`) |
|
|
122
|
+
| `start ... --lang zh-CN,en` | Tabs prefer these languages |
|
|
123
|
+
| `start ... --all` | Open each script's default page, a tab each |
|
|
124
|
+
| `start [url]...` | No scripts: just a browser to drive (`load` adds them later) |
|
|
125
|
+
| `start ... --notab` | No tab at first; `newtab` later |
|
|
126
|
+
| `start ... --detach --new` | Start another detached run, keeping earlier ones |
|
|
127
|
+
| `list` | The active runs |
|
|
128
|
+
| `status` | The run, its log file, tabs, and each script's state. With no run picked: every active run; with `--existing-browser`, also that browser and its managers |
|
|
129
|
+
| `attach [ID]` | Follow a run's stream (Ctrl-C leaves it going) |
|
|
130
|
+
| `stop [ID]`, `stop --all` | End a run |
|
|
131
|
+
| `exit` | End this sm-dev (at a prompt or on stdin); runs it started without `--detach` stop |
|
|
132
|
+
| `start --stop-after-idle-seconds N` | Idle timeout (default 30 minutes; `0` never) |
|
|
133
|
+
|
|
134
|
+
## Scripts
|
|
135
|
+
|
|
136
|
+
| Command | Does |
|
|
137
|
+
| --- | --- |
|
|
138
|
+
| `validate <path>...` | Header, `@require` and syntax checks, plus warnings, e.g. an `@icon` that can't be shown (files, dirs, globs) |
|
|
139
|
+
| `match <script>... <url>...` | Would it run there; which rules matched or excluded it |
|
|
140
|
+
| `match`, `match all` | In a run: the selected script on the current tab; all scripts on all tabs. `--frames`: each of the tab's iframes too |
|
|
141
|
+
| `scripts`, `script <script>` | List; pick the one `get`/`set`/`match` use. It also lists SourceMonkey-managed scripts on the tab as E1, ...; `scripts E1` picks one for `get`/`set`, any installed script (`script list` lists them), on the tab or not (`set key --force <json>` outside a temp browser) |
|
|
142
|
+
| `load <script>...` | Add scripts to the run |
|
|
143
|
+
| `update [script]` | Re-read changed scripts and reload affected tabs |
|
|
144
|
+
| `collection list` (or `collections`) | SourceMonkey's collections (C1, ...), with kind, script count, enabled. No run needed |
|
|
145
|
+
| `script list [collection]` | Every installed script (E1, ...) under its collection, or one collection's. No run needed |
|
|
146
|
+
| `script [script] show`, `script [script] print` | One script in full (rules, status, files, values count, and in a run its state on each tab); its installed text. No run needed |
|
|
147
|
+
| `script [script] print --file <name> [--out <file>]` | One of its `@require` / `@resource` / `@icon` files as installed, by a `@resource`'s name, part of its URL, or `icon`. `--out` writes it to a file |
|
|
148
|
+
| `script [script] save <dir> [--include <parts>] [--flat] [--force]` | Save the script and its files as installed into a directory, in folders by URL (`--flat`: all in one). `--force` replaces existing files |
|
|
149
|
+
| `collection <collection> show` | One collection and its scripts. No run needed |
|
|
150
|
+
|
|
151
|
+
### Changing what's installed
|
|
152
|
+
|
|
153
|
+
The script or collection comes before the verb: `script E4 disable`,
|
|
154
|
+
`collection C3 refresh`; quote a name of several words. In a run, a
|
|
155
|
+
script left out is the selected one, except for `uninstall`.
|
|
156
|
+
|
|
157
|
+
These change SourceMonkey's real collections and scripts, as its pages
|
|
158
|
+
do, and need no run (with no run, they need `--existing-browser`).
|
|
159
|
+
Outside a temp browser they're the person's own: change them only when
|
|
160
|
+
asked to.
|
|
161
|
+
|
|
162
|
+
| Command | What it does |
|
|
163
|
+
| --- | --- |
|
|
164
|
+
| `script [script] enable` / `disable` | Turn one on or off. In a run, one of its own too |
|
|
165
|
+
| `script [script] refresh` | Re-read it from its location; a run's own from disk, as `update` does |
|
|
166
|
+
| `script install <file\|url>` | Install for every tab, to stay (`load` is for the run only). `--collection <C>`. Under VM, replacing the person's script of the same name needs `--force`: ask first |
|
|
167
|
+
| `script <script> uninstall`, `script [script] move <C>` | Remove one from, or move it between, container collections |
|
|
168
|
+
| `collection <C> enable` / `disable` / `refresh`, `collection <C> rename <name>` | The same for a whole collection |
|
|
169
|
+
|
|
170
|
+
- `script uninstall` needs `--force` outside a temp browser.
|
|
171
|
+
- A run's test collection and other runs' scripts are refused, as is
|
|
172
|
+
uninstalling or moving a script that a directory or manifest
|
|
173
|
+
collection lists.
|
|
174
|
+
- The listings mark a local file changed since it loaded: `(modified
|
|
175
|
+
on disk)`, and a collection's `Refresh pending: ...`. `script
|
|
176
|
+
refresh` / `collection refresh` load it.
|
|
177
|
+
- Installing, moving or enabling a script turns off its other running
|
|
178
|
+
copies, as SourceMonkey does, and lists each one. Enabling a
|
|
179
|
+
collection does the same without listing them, and disabling it
|
|
180
|
+
turns back on what it turned off. A new file a `collection refresh`
|
|
181
|
+
finds lands disabled when its script already has an enabled copy. An
|
|
182
|
+
enabled script in a disabled collection is said not to run.
|
|
183
|
+
|
|
184
|
+
## Tabs
|
|
185
|
+
|
|
186
|
+
| Command | Does |
|
|
187
|
+
| --- | --- |
|
|
188
|
+
| `tabs`, `tab T2` | List (with targetIds); pick the current tab. `--frames`: each tab's iframes too |
|
|
189
|
+
| `frames [T2\|F3\|all]` | A tab's iframes (`F1`, ...) as a tree, with the scripts running in each, `(hidden)` ones marked, each one's CDP `frameId`, and the `targetId` of one from another site |
|
|
190
|
+
| `newtab [page...]` | Open a controlled tab (becomes current) |
|
|
191
|
+
| `newtab --noscript <url>` | A tab the scripts stay out of (sticky) |
|
|
192
|
+
| `closetab [T2 T3...\|all]` | Close the current tab, the ones named, or all. A page's "Leave site?" dialog waits for `accept`/`dismiss`; `--force` skips it |
|
|
193
|
+
| `open [tab] [page]` | Navigate the current tab, or the one named |
|
|
194
|
+
| `reload [T2\|all]` | Reload |
|
|
195
|
+
| `focus [tab]` | Bring to the front |
|
|
196
|
+
| `--from-saved [--offline] [--url U]` | On `newtab`/`open`/`start`: serve `.html` files at their recorded URL |
|
|
197
|
+
| `--timeout-seconds S` | On `newtab`/`open`/`reload`: give a slow page S seconds to load (default 30) and settle (default 5) |
|
|
198
|
+
|
|
199
|
+
## Reading the page
|
|
200
|
+
|
|
201
|
+
| Command | Does |
|
|
202
|
+
| --- | --- |
|
|
203
|
+
| `snapshot [sel] [--visible] [--out F]` | Accessibility tree with refs |
|
|
204
|
+
| `snapshot [sel] --find <text>` | Only elements containing the text (case insensitive), within `sel`'s matches |
|
|
205
|
+
| `snapshot ... [--up N] [--context] [--limit N]` | For each match of `sel` or `--find`: N levels up, or with wrapper divs and small containers; first 5 matches (0: all) |
|
|
206
|
+
| `probe <sel>... [--css] [--html]` | Which match and how many; selector / HTML of the first 10 |
|
|
207
|
+
| `eval <js>` | Evaluate inside the selected script, where its `GM_*` APIs, `@require` libraries, top-level declarations and IIFE locals are visible; prints JSON (promises awaited). In the page when no script is selected or it hasn't run there |
|
|
208
|
+
| `eval --page <js>` | Evaluate in the page, where the page's own globals are |
|
|
209
|
+
| `eval --script=<script> <js>` | Evaluate inside the named script |
|
|
210
|
+
| `eval --frame F2 <js>` | Evaluate in an iframe: in the script instance there, or in its page with `--page`. Cross-origin frames too |
|
|
211
|
+
| `eval --file <path>` | Evaluate a JavaScript file |
|
|
212
|
+
| `eval --out FILE <js>` | Write the result to a file; printed results are cut past 10,000 characters |
|
|
213
|
+
| `cdp <Method> [json]` | A raw CDP call on the tab; the result as JSON. A `{{` block or `--file` holds several, one per line (see [cdp.md](cdp.md)) |
|
|
214
|
+
| `cdp --frame F2 <Method> [json]` | The same on the target an iframe is in: its own (one from another site), else its page's |
|
|
215
|
+
| `screenshot [sel] [--full] <file>` | PNG of the view, the page, or an element |
|
|
216
|
+
| `savehtml <file>` | Save the DOM for `--from-saved` / `serveHtml` |
|
|
217
|
+
| `logs [T2\|all] [script]` | The run's log for the tab (its scripts' lines and events), timestamped and whole (the stream cuts a line past 1000 characters) |
|
|
218
|
+
| `logs ... --log-source all` | The site's own lines too; or a list, e.g. `sm` for SourceMonkey's Log entries alone |
|
|
219
|
+
| `logs ... --find <text\|/re/>`, `--tail 50`, `--tail 30s` | Only matching lines; the last N, or the last stretch of time |
|
|
220
|
+
| `logs ... --since <position>` | Only lines after a log ID (`Logs up to` gives the last), an ISO 8601 time, or a time of day (`14:05:12`) |
|
|
221
|
+
|
|
222
|
+
## Driving the page
|
|
223
|
+
|
|
224
|
+
| Command | Does |
|
|
225
|
+
| --- | --- |
|
|
226
|
+
| `click <sel>`, `hover <sel>` | Real mouse input, scrolled into view. A failure names the check that failed (hidden, disabled, moving, covered by what) |
|
|
227
|
+
| `click <sel> --button right --modifiers Shift --count 2` | Right or middle button, keys held (`Control+Alt`), double or triple click |
|
|
228
|
+
| `click <sel> --at 300,12`, `hover <sel> --at 4,4` | At that point in the element (pixels from its top left), not its center |
|
|
229
|
+
| `hover <sel> --modifiers Alt` | Keys held during the hover |
|
|
230
|
+
| `type <sel> <text>` | Type key by key |
|
|
231
|
+
| `type <sel> {{` | Type several lines exactly (line breaks are Enter; the final one before `}}` isn't typed) |
|
|
232
|
+
| `type <sel> --file <path>` | Type a file's text exactly, including a final line break |
|
|
233
|
+
| `type <sel> --clear [text]` | Empty the field first, then type the text if given |
|
|
234
|
+
| `key <keys>...` | `key j Shift+ArrowRight ctrl+end esc` |
|
|
235
|
+
| `accept [tab] [text]`, `dismiss [tab]` | Answer an open dialog |
|
|
236
|
+
| `connect once\|cancel\|allow\|deny\|allow-all [host]` | Answer SourceMonkey's prompt for a host the selected script's `@connect` doesn't cover |
|
|
237
|
+
| `--nowait` | On any of these: don't wait for the page to settle |
|
|
238
|
+
| `--timeout-seconds S` | On any command that waits (these, `start`, `eval`, `snapshot`, `probe`, `screenshot`, `closetab`, `load`, `update`, `menu`): S seconds for each wait, in place of its default. On `cdp`, for each call (default 10) |
|
|
239
|
+
|
|
240
|
+
## Waiting
|
|
241
|
+
|
|
242
|
+
| Command | Waits for |
|
|
243
|
+
| --- | --- |
|
|
244
|
+
| `wait [T2\|all]` | The tab to settle |
|
|
245
|
+
| `wait selector <css>`, `wait selector-gone <css>` | An element to appear / disappear |
|
|
246
|
+
| `wait log <text>`, `wait log /regex/` | A log line since the previous command began (or `--since`). `--find <text>` works too |
|
|
247
|
+
| `wait 500ms`, `wait 2s` | Time (last resort) |
|
|
248
|
+
| `--timeout-seconds S` | Give up after S seconds (default 5). On a delay, it may be given if not shorter |
|
|
249
|
+
|
|
250
|
+
- A tab goes before the form: `wait T2 selector '.x'`.
|
|
251
|
+
- `wait log` sees every log source, the site's own lines too, unless
|
|
252
|
+
`--log-source` narrows it. Each is matched in the form the run
|
|
253
|
+
would print it: `[page log] KEYUP 143`.
|
|
254
|
+
- It ends with `Found at <log ID>`, or `Searched up to <log ID>` when
|
|
255
|
+
it gives up.
|
|
256
|
+
|
|
257
|
+
Settled means: loaded, scripts started, no requests (under 3 seconds
|
|
258
|
+
old) or DOM changes for 200ms. Timers aren't waited for.
|
|
259
|
+
|
|
260
|
+
## Scripts' GM state
|
|
261
|
+
|
|
262
|
+
| Command | Does |
|
|
263
|
+
| --- | --- |
|
|
264
|
+
| `menu`, `menu all` | List menu commands (`M1`...) |
|
|
265
|
+
| `menu <label or M1>` | Fire one. Piped in, waits up to 5 s for it to be registered; `--timeout-seconds S` for longer |
|
|
266
|
+
| `values [script\|T2\|E1]` | Stored values (`E1`: a SourceMonkey-managed script) |
|
|
267
|
+
| `get <key>`, `set <key> <json>` | One value; `set` fires change listeners |
|
|
268
|
+
| `set <key> --file <path>` | The value from a JSON file (or a `{{` block, as `eval` takes) |
|
|
269
|
+
|
|
270
|
+
## eval
|
|
271
|
+
|
|
272
|
+
- The rest of the line is JavaScript: `eval document.title`. Quote it
|
|
273
|
+
for the shell when it has spaces or special characters.
|
|
274
|
+
- The value is the last expression, as in the DevTools console. A
|
|
275
|
+
top-level `return` works too (the code runs as a function body).
|
|
276
|
+
Its `const`/`let` then stay in that function, not kept for later
|
|
277
|
+
evals.
|
|
278
|
+
- In the page (`--page`), a top-level `const` or `let` can clash with
|
|
279
|
+
a name the page's own scripts declare ("Identifier 'a' has already
|
|
280
|
+
been declared"). Wrap the code in `{ ... }`.
|
|
281
|
+
- `eval --file probe.js` runs a file's JavaScript, with no shell
|
|
282
|
+
quoting: handy for a probe you run more than once.
|
|
283
|
+
- Several lines, on stdin or at a prompt:
|
|
284
|
+
|
|
285
|
+
```
|
|
286
|
+
eval {{
|
|
287
|
+
const rows = [...document.querySelectorAll('.row')];
|
|
288
|
+
rows.map((r) => r.id)
|
|
289
|
+
}}
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
`{{` ends the first line; a line of just `}}` closes it. A tab and
|
|
293
|
+
flags go before the `{{`.
|
|
294
|
+
- Elements print as DevTools describes them; return
|
|
295
|
+
`el.outerHTML` or specific fields for more.
|
|
296
|
+
- An expression that navigates prints a note instead of a value;
|
|
297
|
+
follow it with `wait`.
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# Testing under other managers
|
|
2
|
+
|
|
3
|
+
A run can load its scripts into **Tampermonkey** (TM) or
|
|
4
|
+
**Violentmonkey** (VM) instead of SourceMonkey: to check a script is
|
|
5
|
+
portable across managers, or to debug something that works in one but
|
|
6
|
+
not another. Both work the same way; the examples use VM, and
|
|
7
|
+
`--manager tm` does the same under TM. Runs under each can go side by
|
|
8
|
+
side, with different `--run` ids, to compare.
|
|
9
|
+
|
|
10
|
+
```sh
|
|
11
|
+
pnpm sm-dev --manager vm manager fetch # once: download VM into sm-dev's cache
|
|
12
|
+
R="pnpm sm-dev --manager vm --run Dvm"
|
|
13
|
+
|
|
14
|
+
$R start sites/x/y.user.js https://x.com/ --detach
|
|
15
|
+
$R scripts # each tab's expected scripts, with their VM ids
|
|
16
|
+
$R logs # the script's console lines and errors
|
|
17
|
+
$R stop # removes the run's scripts from VM
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
- `--manager vm` goes before the command, and the run keeps it: later
|
|
21
|
+
commands to the run work without it.
|
|
22
|
+
- A temp browser (the default) loads the fetched manager, fetching it
|
|
23
|
+
the first time, and lets scripts run on local `file://` pages:
|
|
24
|
+
- VM blocks them by default, and sm-dev clears that in a temp
|
|
25
|
+
browser;
|
|
26
|
+
- TM needs Chrome's file access, which is on for the unpacked copy a
|
|
27
|
+
temp browser loads, but off by default for one from the Chrome
|
|
28
|
+
Web Store.
|
|
29
|
+
- For a site that needs a login, the person's `--open-browser` browser
|
|
30
|
+
needs VM: `pnpm sm-dev --existing-browser --manager vm manager
|
|
31
|
+
install`. Ask first, and about turning SourceMonkey off there
|
|
32
|
+
(`--existing-browser --manager sm manager disable`), since every
|
|
33
|
+
enabled manager runs its scripts.
|
|
34
|
+
- The run's scripts go into the manager as ordinary scripts, marked by
|
|
35
|
+
a last line `// sm-dev: run=...`, and are removed when the run ends.
|
|
36
|
+
- Under TM, local `@require` lines show rewritten to
|
|
37
|
+
`https://sm-dev.invalid/...` in TM's editor: TM can't resolve them
|
|
38
|
+
otherwise. `script print` shows them as written.
|
|
39
|
+
- Each keeps its run number, with its VM id beside it: `1: Hello
|
|
40
|
+
(hello.user.js), E6 in Violentmonkey`. Either names it.
|
|
41
|
+
- `start` refuses a script VM already has by the same name and
|
|
42
|
+
namespace, naming it. Ask the person before
|
|
43
|
+
`script E<n> uninstall --force` to make room.
|
|
44
|
+
|
|
45
|
+
What differs from SourceMonkey:
|
|
46
|
+
|
|
47
|
+
- **Nothing reports what ran.** `scripts` and `status` list the run's
|
|
48
|
+
scripts under `Expected on tab T1 using match rules:` and `Not
|
|
49
|
+
expected on tab T1:`, from their headers. Check the page itself
|
|
50
|
+
(`snapshot`, `eval --page`) to see a script worked.
|
|
51
|
+
- **Every script in the manager runs in every tab**, the person's own and other
|
|
52
|
+
runs' too: nothing keeps them out of the run's tabs.
|
|
53
|
+
- **No reach into a script:** `values`, `get`, `set`, `menu`,
|
|
54
|
+
`connect` and `--values` are refused, and `eval` runs in the page,
|
|
55
|
+
not inside the script.
|
|
56
|
+
- **A script's uncaught error** is a `[script error]` log line, not a
|
|
57
|
+
`threw` event.
|
|
58
|
+
- `collection` and `script` work on the manager's scripts, in one
|
|
59
|
+
collection, `C0`, whose `disable` turns all its scripts off.
|
|
60
|
+
- Under TM, saving needs its "Easy save" setting on, as it is by
|
|
61
|
+
default; sm-dev says so when it's off.
|
|
62
|
+
- More: [sm-dev-violentmonkey.md](https://github.com/jshute96/SourceMonkey/blob/main/docs/sm-dev-violentmonkey.md)
|
|
63
|
+
and [sm-dev-tampermonkey.md](https://github.com/jshute96/SourceMonkey/blob/main/docs/sm-dev-tampermonkey.md).
|