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.
Files changed (367) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +87 -2
  3. package/dist/bytes.js +37 -0
  4. package/dist/channel-placeholder.js +5 -0
  5. package/dist/collection-scan.js +17 -0
  6. package/dist/collections.html +353 -0
  7. package/dist/compare.html +358 -0
  8. package/dist/composed-source.js +205 -0
  9. package/dist/connect-prompt.html +47 -0
  10. package/dist/debug/icons.html +211 -0
  11. package/dist/debug/storage.html +163 -0
  12. package/dist/debug-log.js +75 -0
  13. package/dist/diagnostic-location.js +64 -0
  14. package/dist/eval-hook.js +308 -0
  15. package/dist/extension/background.js +5263 -0
  16. package/dist/extension/channel.js +133 -0
  17. package/dist/extension/code-links.js +187 -0
  18. package/dist/extension/code-tabs.js +460 -0
  19. package/dist/extension/collection-dialog.js +619 -0
  20. package/dist/extension/collection-display.js +322 -0
  21. package/dist/extension/collections.js +2905 -0
  22. package/dist/extension/compare.js +867 -0
  23. package/dist/extension/concurrency.js +186 -0
  24. package/dist/extension/connect-grants.js +109 -0
  25. package/dist/extension/connect-prompt-page.js +70 -0
  26. package/dist/extension/connect-prompt.js +266 -0
  27. package/dist/extension/copy-button.js +63 -0
  28. package/dist/extension/copy-dialog.js +502 -0
  29. package/dist/extension/copy-preference.js +66 -0
  30. package/dist/extension/debug/icons.js +203 -0
  31. package/dist/extension/debug/storage.js +365 -0
  32. package/dist/extension/deep-link.js +77 -0
  33. package/dist/extension/delete-dialog.js +432 -0
  34. package/dist/extension/delete-icon.js +40 -0
  35. package/dist/extension/details-tooltips.js +66 -0
  36. package/dist/extension/directories.js +679 -0
  37. package/dist/extension/export-backup.js +407 -0
  38. package/dist/extension/export-dialog.js +142 -0
  39. package/dist/extension/file-access.js +74 -0
  40. package/dist/extension/file-changes.js +346 -0
  41. package/dist/extension/frame-info.js +85 -0
  42. package/dist/extension/github-provider.js +336 -0
  43. package/dist/extension/glyph.js +84 -0
  44. package/dist/extension/gm-bindings.js +601 -0
  45. package/dist/extension/gm-download.js +419 -0
  46. package/dist/extension/gm-menu.js +228 -0
  47. package/dist/extension/gm-notification.js +141 -0
  48. package/dist/extension/gm-originator-map.js +23 -0
  49. package/dist/extension/gm-tab-data.js +121 -0
  50. package/dist/extension/gm-tab.js +160 -0
  51. package/dist/extension/gm-url-change.js +111 -0
  52. package/dist/extension/gm-url-scheme.js +27 -0
  53. package/dist/extension/gm-values.js +176 -0
  54. package/dist/extension/gm-window-control.js +104 -0
  55. package/dist/extension/gm-xhr-headers.js +333 -0
  56. package/dist/extension/gm-xhr.js +584 -0
  57. package/dist/extension/injector.js +3145 -0
  58. package/dist/extension/install-capture.js +277 -0
  59. package/dist/extension/line-diff.js +233 -0
  60. package/dist/extension/local-copy.js +560 -0
  61. package/dist/extension/local-delete.js +276 -0
  62. package/dist/extension/location-kinds.js +108 -0
  63. package/dist/extension/log-format.js +158 -0
  64. package/dist/extension/managed-changes.js +361 -0
  65. package/dist/extension/managed-items.js +57 -0
  66. package/dist/extension/match-index.js +375 -0
  67. package/dist/extension/missing-scripts.js +66 -0
  68. package/dist/extension/more-menu.js +109 -0
  69. package/dist/extension/move-dialog.js +197 -0
  70. package/dist/extension/offscreen.js +37 -0
  71. package/dist/extension/options.js +504 -0
  72. package/dist/extension/page-heading.js +170 -0
  73. package/dist/extension/page-links.js +199 -0
  74. package/dist/extension/parse-check-client.js +70 -0
  75. package/dist/extension/parse-check.js +161 -0
  76. package/dist/extension/parse-sandbox-host.js +172 -0
  77. package/dist/extension/parse-sandbox.js +175 -0
  78. package/dist/extension/popup-commands-open.js +41 -0
  79. package/dist/extension/popup-view.js +387 -0
  80. package/dist/extension/popup.js +703 -0
  81. package/dist/extension/prism-userscript.js +53 -0
  82. package/dist/extension/refresh-error.js +136 -0
  83. package/dist/extension/refresh-targets.js +160 -0
  84. package/dist/extension/related-versions.js +1144 -0
  85. package/dist/extension/resize-observer-loop.js +19 -0
  86. package/dist/extension/row-cache.js +387 -0
  87. package/dist/extension/script-blobs.js +413 -0
  88. package/dist/extension/script-details.js +658 -0
  89. package/dist/extension/script-enablement.js +285 -0
  90. package/dist/extension/script-identity.js +310 -0
  91. package/dist/extension/script-keys.js +54 -0
  92. package/dist/extension/script-log-id.js +155 -0
  93. package/dist/extension/script-log.js +290 -0
  94. package/dist/extension/script-rejection.js +104 -0
  95. package/dist/extension/script-sites.js +158 -0
  96. package/dist/extension/script-store.js +3507 -0
  97. package/dist/extension/script-updater.js +991 -0
  98. package/dist/extension/script-url-hash.js +61 -0
  99. package/dist/extension/select-all.js +37 -0
  100. package/dist/extension/select-open-guard.js +90 -0
  101. package/dist/extension/site-icon.js +1261 -0
  102. package/dist/extension/sm-dev-link.js +302 -0
  103. package/dist/extension/solo-click.js +58 -0
  104. package/dist/extension/sticky-numbers.js +188 -0
  105. package/dist/extension/storage-breakdown.js +253 -0
  106. package/dist/extension/storage-scan.js +86 -0
  107. package/dist/extension/storage-usage.js +194 -0
  108. package/dist/extension/structural-keys.js +29 -0
  109. package/dist/extension/sw-teardown.js +36 -0
  110. package/dist/extension/tab-status.js +403 -0
  111. package/dist/extension/toolbar-summary.js +105 -0
  112. package/dist/extension/user-scripts-access.js +43 -0
  113. package/dist/extension/userscript.js +3672 -0
  114. package/dist/extension/value-store.js +204 -0
  115. package/dist/extension/version-probe-fetch.js +68 -0
  116. package/dist/extension/worker-client.js +109 -0
  117. package/dist/extension/worker-ops.js +171 -0
  118. package/dist/extension/zip-writer.js +24 -0
  119. package/dist/external-files.js +878 -0
  120. package/dist/file-loader.js +436 -0
  121. package/dist/file-locations.js +439 -0
  122. package/dist/generated-wrappers.js +5 -0
  123. package/dist/github-auth.js +148 -0
  124. package/dist/github-urls.js +46 -0
  125. package/dist/gm-api-catalog.js +217 -0
  126. package/dist/gm-connect.js +273 -0
  127. package/dist/gm-xhr-types.js +5 -0
  128. package/dist/http-read.js +142 -0
  129. package/dist/icons/icon-128.png +0 -0
  130. package/dist/icons/icon-16.png +0 -0
  131. package/dist/icons/icon-48.png +0 -0
  132. package/dist/local-file-overrides.js +558 -0
  133. package/dist/manifest.json +38 -0
  134. package/dist/markup-response.js +126 -0
  135. package/dist/match-targets.js +305 -0
  136. package/dist/menu-captions.js +22 -0
  137. package/dist/offscreen.html +39 -0
  138. package/dist/options.html +197 -0
  139. package/dist/parse-check-protocol.js +51 -0
  140. package/dist/parse-location.js +171 -0
  141. package/dist/parse-sandbox.html +56 -0
  142. package/dist/phase-timing.js +155 -0
  143. package/dist/popup.html +197 -0
  144. package/dist/public-suffixes.js +6957 -0
  145. package/dist/run-context.js +31 -0
  146. package/dist/runtime-messages.js +34 -0
  147. package/dist/sandboxed-page.js +35 -0
  148. package/dist/script-build.js +787 -0
  149. package/dist/script-display.js +383 -0
  150. package/dist/script-icon.js +43 -0
  151. package/dist/script-links.js +204 -0
  152. package/dist/script-source-url.js +214 -0
  153. package/dist/script-world.js +65 -0
  154. package/dist/sm-dev-protocol.js +84 -0
  155. package/dist/source-map.js +177 -0
  156. package/dist/stack-link.js +138 -0
  157. package/dist/styles.css +825 -0
  158. package/dist/unsafe-window-use.js +229 -0
  159. package/dist/url-match.js +734 -0
  160. package/dist/userscript-header.js +248 -0
  161. package/dist/userscript.html +1165 -0
  162. package/dist/vendor/fflate.LICENSE +21 -0
  163. package/dist/vendor/fflate.js +2692 -0
  164. package/dist/vendor/prism/prism-line-numbers.css +1 -0
  165. package/dist/vendor/prism/prism-line-numbers.js +1 -0
  166. package/dist/vendor/prism/prism.css +1 -0
  167. package/dist/vendor/prism/prism.js +1946 -0
  168. package/dist/version-compare.js +141 -0
  169. package/dist/version-probe.js +120 -0
  170. package/lib/build-info.json +1 -0
  171. package/lib/bytes.d.ts +3 -0
  172. package/lib/bytes.js +37 -0
  173. package/lib/channel-placeholder.d.ts +1 -0
  174. package/lib/channel-placeholder.js +5 -0
  175. package/lib/collection-scan.d.ts +8 -0
  176. package/lib/collection-scan.js +17 -0
  177. package/lib/composed-source.d.ts +28 -0
  178. package/lib/composed-source.js +205 -0
  179. package/lib/debug-log.d.ts +9 -0
  180. package/lib/debug-log.js +75 -0
  181. package/lib/diagnostic-location.d.ts +8 -0
  182. package/lib/diagnostic-location.js +64 -0
  183. package/lib/eval-hook.d.ts +34 -0
  184. package/lib/eval-hook.js +308 -0
  185. package/lib/external-files.d.ts +111 -0
  186. package/lib/external-files.js +878 -0
  187. package/lib/file-loader.d.ts +48 -0
  188. package/lib/file-loader.js +436 -0
  189. package/lib/file-locations.d.ts +44 -0
  190. package/lib/file-locations.js +439 -0
  191. package/lib/generated-wrappers.d.ts +11 -0
  192. package/lib/generated-wrappers.js +5 -0
  193. package/lib/github-auth.d.ts +12 -0
  194. package/lib/github-auth.js +148 -0
  195. package/lib/github-urls.d.ts +1 -0
  196. package/lib/github-urls.js +46 -0
  197. package/lib/gm-api-catalog.d.ts +24 -0
  198. package/lib/gm-api-catalog.js +217 -0
  199. package/lib/gm-connect.d.ts +34 -0
  200. package/lib/gm-connect.js +273 -0
  201. package/lib/gm-xhr-types.d.ts +68 -0
  202. package/lib/gm-xhr-types.js +5 -0
  203. package/lib/harness/browser-extensions.d.ts +73 -0
  204. package/lib/harness/browser-extensions.js +285 -0
  205. package/lib/harness/browser-lang.d.ts +20 -0
  206. package/lib/harness/browser-lang.js +86 -0
  207. package/lib/harness/browser-launch.d.ts +14 -0
  208. package/lib/harness/browser-launch.js +184 -0
  209. package/lib/harness/checks.d.ts +110 -0
  210. package/lib/harness/checks.js +321 -0
  211. package/lib/harness/cli.d.ts +2 -0
  212. package/lib/harness/cli.js +2259 -0
  213. package/lib/harness/command-args.d.ts +91 -0
  214. package/lib/harness/command-args.js +369 -0
  215. package/lib/harness/command-lines.d.ts +80 -0
  216. package/lib/harness/command-lines.js +180 -0
  217. package/lib/harness/command-list.d.ts +206 -0
  218. package/lib/harness/command-list.js +1475 -0
  219. package/lib/harness/console-commands.d.ts +463 -0
  220. package/lib/harness/console-commands.js +3216 -0
  221. package/lib/harness/download-watch.d.ts +21 -0
  222. package/lib/harness/download-watch.js +156 -0
  223. package/lib/harness/extension-backend.d.ts +41 -0
  224. package/lib/harness/extension-backend.js +100 -0
  225. package/lib/harness/extension-host.d.ts +112 -0
  226. package/lib/harness/extension-host.js +552 -0
  227. package/lib/harness/extension-launch.d.ts +67 -0
  228. package/lib/harness/extension-launch.js +285 -0
  229. package/lib/harness/extension-link.d.ts +315 -0
  230. package/lib/harness/extension-link.js +607 -0
  231. package/lib/harness/external-manager.d.ts +146 -0
  232. package/lib/harness/external-manager.js +414 -0
  233. package/lib/harness/fixture.d.ts +165 -0
  234. package/lib/harness/fixture.js +461 -0
  235. package/lib/harness/frame-sessions.d.ts +71 -0
  236. package/lib/harness/frame-sessions.js +248 -0
  237. package/lib/harness/frames.d.ts +68 -0
  238. package/lib/harness/frames.js +216 -0
  239. package/lib/harness/help-format.d.ts +17 -0
  240. package/lib/harness/help-format.js +127 -0
  241. package/lib/harness/host.d.ts +352 -0
  242. package/lib/harness/host.js +423 -0
  243. package/lib/harness/index.d.ts +8 -0
  244. package/lib/harness/index.js +10 -0
  245. package/lib/harness/input-file.d.ts +18 -0
  246. package/lib/harness/input-file.js +61 -0
  247. package/lib/harness/json-output.d.ts +565 -0
  248. package/lib/harness/json-output.js +71 -0
  249. package/lib/harness/manager-actions.d.ts +21 -0
  250. package/lib/harness/manager-actions.js +129 -0
  251. package/lib/harness/manager-commands.d.ts +142 -0
  252. package/lib/harness/manager-commands.js +1196 -0
  253. package/lib/harness/manager-fetch.d.ts +33 -0
  254. package/lib/harness/manager-fetch.js +239 -0
  255. package/lib/harness/managers.d.ts +24 -0
  256. package/lib/harness/managers.js +27 -0
  257. package/lib/harness/output-style.d.ts +125 -0
  258. package/lib/harness/output-style.js +322 -0
  259. package/lib/harness/page-commands.d.ts +134 -0
  260. package/lib/harness/page-commands.js +1141 -0
  261. package/lib/harness/page-output.d.ts +67 -0
  262. package/lib/harness/page-output.js +139 -0
  263. package/lib/harness/page-watch.d.ts +171 -0
  264. package/lib/harness/page-watch.js +607 -0
  265. package/lib/harness/parse-check-node.d.ts +3 -0
  266. package/lib/harness/parse-check-node.js +132 -0
  267. package/lib/harness/path-args.d.ts +22 -0
  268. package/lib/harness/path-args.js +148 -0
  269. package/lib/harness/playwright-chromium.d.ts +16 -0
  270. package/lib/harness/playwright-chromium.js +86 -0
  271. package/lib/harness/prepare.d.ts +168 -0
  272. package/lib/harness/prepare.js +364 -0
  273. package/lib/harness/prompt-editor.d.ts +17 -0
  274. package/lib/harness/prompt-editor.js +354 -0
  275. package/lib/harness/prompt-history.d.ts +13 -0
  276. package/lib/harness/prompt-history.js +89 -0
  277. package/lib/harness/rebuild-advice.d.ts +6 -0
  278. package/lib/harness/rebuild-advice.js +39 -0
  279. package/lib/harness/run-log.d.ts +47 -0
  280. package/lib/harness/run-log.js +140 -0
  281. package/lib/harness/run-logs.d.ts +132 -0
  282. package/lib/harness/run-logs.js +241 -0
  283. package/lib/harness/run.d.ts +194 -0
  284. package/lib/harness/run.js +1973 -0
  285. package/lib/harness/runs.d.ts +229 -0
  286. package/lib/harness/runs.js +726 -0
  287. package/lib/harness/save-html.d.ts +39 -0
  288. package/lib/harness/save-html.js +89 -0
  289. package/lib/harness/saved-pages.d.ts +120 -0
  290. package/lib/harness/saved-pages.js +275 -0
  291. package/lib/harness/script-mark.d.ts +17 -0
  292. package/lib/harness/script-mark.js +56 -0
  293. package/lib/harness/snapshot.d.ts +143 -0
  294. package/lib/harness/snapshot.js +474 -0
  295. package/lib/harness/stuck-tabs.d.ts +19 -0
  296. package/lib/harness/stuck-tabs.js +131 -0
  297. package/lib/harness/tab-refs.d.ts +20 -0
  298. package/lib/harness/tab-refs.js +80 -0
  299. package/lib/harness/tampermonkey.d.ts +71 -0
  300. package/lib/harness/tampermonkey.js +356 -0
  301. package/lib/harness/tm-ids.d.ts +18 -0
  302. package/lib/harness/tm-ids.js +88 -0
  303. package/lib/harness/violentmonkey.d.ts +34 -0
  304. package/lib/harness/violentmonkey.js +162 -0
  305. package/lib/harness/wait.d.ts +77 -0
  306. package/lib/harness/wait.js +458 -0
  307. package/lib/http-read.d.ts +30 -0
  308. package/lib/http-read.js +142 -0
  309. package/lib/local-file-overrides.d.ts +35 -0
  310. package/lib/local-file-overrides.js +558 -0
  311. package/lib/manifest.json +38 -0
  312. package/lib/markup-response.d.ts +11 -0
  313. package/lib/markup-response.js +126 -0
  314. package/lib/match-targets.d.ts +18 -0
  315. package/lib/match-targets.js +305 -0
  316. package/lib/menu-captions.d.ts +1 -0
  317. package/lib/menu-captions.js +22 -0
  318. package/lib/parse-check-protocol.d.ts +27 -0
  319. package/lib/parse-check-protocol.js +51 -0
  320. package/lib/parse-location.d.ts +12 -0
  321. package/lib/parse-location.js +171 -0
  322. package/lib/phase-timing.d.ts +12 -0
  323. package/lib/phase-timing.js +155 -0
  324. package/lib/public-suffixes.d.ts +1 -0
  325. package/lib/public-suffixes.js +6957 -0
  326. package/lib/run-context.d.ts +2 -0
  327. package/lib/run-context.js +31 -0
  328. package/lib/runtime-messages.d.ts +10 -0
  329. package/lib/runtime-messages.js +34 -0
  330. package/lib/sandboxed-page.d.ts +5 -0
  331. package/lib/sandboxed-page.js +35 -0
  332. package/lib/script-build.d.ts +111 -0
  333. package/lib/script-build.js +787 -0
  334. package/lib/script-display.d.ts +51 -0
  335. package/lib/script-display.js +383 -0
  336. package/lib/script-icon.d.ts +16 -0
  337. package/lib/script-icon.js +43 -0
  338. package/lib/script-links.d.ts +24 -0
  339. package/lib/script-links.js +204 -0
  340. package/lib/script-source-url.d.ts +8 -0
  341. package/lib/script-source-url.js +214 -0
  342. package/lib/script-world.d.ts +6 -0
  343. package/lib/script-world.js +65 -0
  344. package/lib/sm-dev-protocol.d.ts +251 -0
  345. package/lib/sm-dev-protocol.js +84 -0
  346. package/lib/source-map.d.ts +32 -0
  347. package/lib/source-map.js +177 -0
  348. package/lib/stack-link.d.ts +15 -0
  349. package/lib/stack-link.js +138 -0
  350. package/lib/unsafe-window-use.d.ts +1 -0
  351. package/lib/unsafe-window-use.js +229 -0
  352. package/lib/url-match.d.ts +40 -0
  353. package/lib/url-match.js +734 -0
  354. package/lib/userscript-header.d.ts +33 -0
  355. package/lib/userscript-header.js +248 -0
  356. package/lib/version-compare.d.ts +6 -0
  357. package/lib/version-compare.js +141 -0
  358. package/lib/version-probe.d.ts +17 -0
  359. package/lib/version-probe.js +120 -0
  360. package/package.json +55 -3
  361. package/skills/SourceMonkey-dev/SKILL.md +868 -0
  362. package/skills/SourceMonkey-dev/references/cdp.md +293 -0
  363. package/skills/SourceMonkey-dev/references/commands.md +297 -0
  364. package/skills/SourceMonkey-dev/references/other-managers.md +63 -0
  365. package/skills/SourceMonkey-dev/references/specs.md +46 -0
  366. package/skills/SourceMonkey-friction/SKILL.md +103 -0
  367. 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).