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,127 @@
1
+ // Text layout for sm-dev's help, in a markdown-like form: `## headings`,
2
+ // `- ` bullets, `code` spans for whatever is typed or shown as is
3
+ // (commands, flags, IDs), and **bold** spans.
4
+ //
5
+ // Lines are laid out with their markup, then painted. In color (a
6
+ // terminal that has it), code and headings take the looks of sm-dev's
7
+ // other output (STYLES in output-style.ts): code as a command, headings
8
+ // and **bold** spans as headings. Plain, bold is dropped,
9
+ // and a code span keeps its backticks only where they help it read
10
+ // apart from the prose (`keepsBackticks`). A quiet span (`quiet`), for
11
+ // a list's terms and usage lines, has none.
12
+ //
13
+ // Widths are measured as the text will show in the mode it is laid out
14
+ // for, so columns line up and lines wrap to fit either way.
15
+ import { keepsBackticks, styleCodes } from './output-style.js';
16
+ // Starts a line of a code block, after its indent: shown as is, all of
17
+ // it code.
18
+ const CODE_LINE = '\u0001';
19
+ // A quiet code span's ends.
20
+ const QUIET = '\u0003';
21
+ const QUIET_END = '\u0004';
22
+ // A space inside a span, kept while wrapping so the span stays on one
23
+ // line. (Not a no-break space: \s matches that.)
24
+ const KEPT_SPACE = '\u0002';
25
+ /** Text as a code span with no backticks in plain help: a list's term, a usage line. */
26
+ export const quiet = (text) => QUIET + text + QUIET_END;
27
+ // Each span: code first, so `**` in one (a glob) is code, not bold.
28
+ const SPAN = new RegExp(`\`([^\`]*)\`|${QUIET}([^${QUIET_END}]*)${QUIET_END}|\\*\\*([^*]+)\\*\\*`, 'g');
29
+ // Text as it shows, plain or in color, before any color is added.
30
+ function shown(text) {
31
+ return text.replace(SPAN, (span, code, quieted, bold) => {
32
+ if (code !== undefined)
33
+ return color || !keepsBackticks(code) ? code : span;
34
+ return quieted ?? bold ?? '';
35
+ });
36
+ }
37
+ // Code and headings, on and off, as the rest of sm-dev's output shows them.
38
+ const [CODE, NO_CODE] = styleCodes('cmd');
39
+ const [BOLD, NO_BOLD] = styleCodes('h');
40
+ // Whether the help being laid out is for color. Set for one rendering
41
+ // by `render`.
42
+ let color = false;
43
+ /** Lays out lines for color or not, then paints them: one string, ending in a newline. */
44
+ export function render(inColor, layout) {
45
+ const was = color;
46
+ color = inColor;
47
+ try {
48
+ // A blank line once, where pieces laid out apart each bring one, and
49
+ // none at the end.
50
+ const lines = layout().filter((line, i, all) => line !== '' || (i > 0 && all[i - 1] !== ''));
51
+ while (lines.at(-1) === '')
52
+ lines.pop();
53
+ return lines.map(paint).join('\n') + '\n';
54
+ }
55
+ finally {
56
+ color = was;
57
+ }
58
+ }
59
+ /** How wide text shows. */
60
+ export function visibleLength(text) {
61
+ return shown(text).length;
62
+ }
63
+ /** Text padded with spaces to show `width` wide. */
64
+ export function padTo(text, width) {
65
+ return text + ' '.repeat(Math.max(0, width - visibleLength(text)));
66
+ }
67
+ function paint(line) {
68
+ const code = line.indexOf(CODE_LINE);
69
+ if (code >= 0) {
70
+ const rest = line.slice(code + 1);
71
+ return line.slice(0, code) + (color && rest ? CODE + rest + NO_CODE : rest);
72
+ }
73
+ if (!color)
74
+ return shown(line);
75
+ const spans = line.replace(SPAN, (_span, code, quieted, bold) => (bold !== undefined ? BOLD + bold + NO_BOLD : CODE + (code ?? quieted) + NO_CODE));
76
+ return line.startsWith('#') ? BOLD + spans + NO_BOLD : spans;
77
+ }
78
+ /** Text wrapped to `width`, by the width it shows. A span is never split. */
79
+ export function wrap(text, width) {
80
+ const kept = text.replace(SPAN, (span) => span.replace(/ /g, KEPT_SPACE));
81
+ const lines = [];
82
+ let line = '';
83
+ for (const word of kept.split(/\s+/).filter(Boolean)) {
84
+ if (line && visibleLength(line) + 1 + visibleLength(word) > width) {
85
+ lines.push(line);
86
+ line = word;
87
+ }
88
+ else {
89
+ line = line ? `${line} ${word}` : word;
90
+ }
91
+ }
92
+ if (line)
93
+ lines.push(line);
94
+ // No last line of one word: the line above gives it one of its own,
95
+ // where that still fits.
96
+ const last = lines.length - 1;
97
+ if (last > 0 && !lines[last].includes(' ') && lines[last - 1].split(' ').length > 2) {
98
+ const cut = lines[last - 1].lastIndexOf(' ');
99
+ const moved = `${lines[last - 1].slice(cut + 1)} ${lines[last]}`;
100
+ if (visibleLength(moved) <= width) {
101
+ lines[last] = moved;
102
+ lines[last - 1] = lines[last - 1].slice(0, cut);
103
+ }
104
+ }
105
+ return lines.map((l) => l.replaceAll(KEPT_SPACE, ' '));
106
+ }
107
+ /**
108
+ * A line of text, wrapped to `width`. A bullet (`- `) or numbered item
109
+ * (`1. `), after any spaces of its own, wraps under its text. Any other
110
+ * line starting with spaces is a line of a code block, shown as is, two
111
+ * spaces further in.
112
+ */
113
+ export function textLines(text, width) {
114
+ if (text === '')
115
+ return [''];
116
+ const item = /^(\s*)(- |\d+\. )/.exec(text);
117
+ if (item) {
118
+ const lead = item[0];
119
+ return wrap(text.slice(lead.length), width - lead.length)
120
+ .map((line, i) => (i === 0 ? lead : ' '.repeat(lead.length)) + line);
121
+ }
122
+ if (text.startsWith(' ')) {
123
+ const code = text.trimStart();
124
+ return [` ${text.slice(0, text.length - code.length)}${CODE_LINE}${code}`];
125
+ }
126
+ return wrap(text, width);
127
+ }
@@ -0,0 +1,352 @@
1
+ import { EventEmitter } from 'node:events';
2
+ import type { Frame } from '@playwright/test';
3
+ import type { GmXhrEvent, GmXhrRequestPayload } from '../gm-xhr-types.js';
4
+ import type { PreparedScript } from './prepare.js';
5
+ import { FrameIds } from './frames.js';
6
+ /** One watched page (a tab), as the host sees it. */
7
+ export interface PageLink {
8
+ /** The page's current top-level URL. */
9
+ url(): string;
10
+ }
11
+ export interface TabRecord {
12
+ scriptId: string;
13
+ requestId: string;
14
+ url: string;
15
+ active: boolean;
16
+ at: number;
17
+ closed: boolean;
18
+ }
19
+ export interface MenuCommandRecord {
20
+ scriptId: string;
21
+ commandId: string;
22
+ name: string;
23
+ at: number;
24
+ /**
25
+ * The document that registered it, where it fires: the page's, or one
26
+ * of its iframes'. Absent where the manager doesn't say.
27
+ */
28
+ documentId?: string;
29
+ /** Registered in one of the page's iframes, not the page itself. */
30
+ frame?: true;
31
+ /** Registered in an iframe: its frame id's number (`F3` is 3), when known. */
32
+ frameNumber?: number;
33
+ }
34
+ export interface NotificationRecord {
35
+ scriptId: string;
36
+ /** From an iframe: its frame id's number (`F3` is 3), when known. */
37
+ frameNumber?: number;
38
+ requestId: string;
39
+ text: string;
40
+ title: string;
41
+ at: number;
42
+ /** The last event delivered to the script, if any. */
43
+ event?: 'clicked' | 'closed';
44
+ }
45
+ export interface DownloadRecord {
46
+ scriptId: string;
47
+ /** From an iframe: its frame id's number (`F3` is 3), when known. */
48
+ frameNumber?: number;
49
+ requestId: string;
50
+ url: string;
51
+ name: string;
52
+ at: number;
53
+ outcome?: 'load' | 'error' | 'timeout' | 'abort';
54
+ /** Where the browser saved it, on `load`. */
55
+ filename?: string;
56
+ error?: string;
57
+ }
58
+ export interface XhrRecord {
59
+ scriptId: string;
60
+ /** From an iframe: its frame id's number (`F3` is 3), when known. */
61
+ frameNumber?: number;
62
+ id: string;
63
+ url: string;
64
+ method: string;
65
+ at: number;
66
+ /** How it ended, once it has. */
67
+ outcome?: 'load' | 'error' | 'timeout' | 'abort';
68
+ /** The HTTP status, on `load`. */
69
+ status?: number;
70
+ /** The message the script's `onerror` got, on `error`. */
71
+ error?: string;
72
+ }
73
+ /**
74
+ * SourceMonkey asking whether a script may connect to a host its
75
+ * `@connect` lines don't cover, and the answer once given.
76
+ */
77
+ export interface ConnectPromptRecord {
78
+ scriptId: string;
79
+ /** The script's name. */
80
+ name: string;
81
+ promptId: string;
82
+ host: string;
83
+ url: string;
84
+ method: string;
85
+ at: number;
86
+ answer?: ConnectChoice;
87
+ /** Closed without an answer: its requests timed out or were aborted. */
88
+ closed?: boolean;
89
+ }
90
+ export type ConnectChoice = 'once' | 'cancel' | 'allow' | 'allow-all' | 'deny';
91
+ export interface ScriptReport {
92
+ scriptId: string;
93
+ name: string;
94
+ /** The URL of the document it came from: an iframe's, for `frame`. */
95
+ url: string;
96
+ at: number;
97
+ /** From one of the page's iframes, not the page itself. */
98
+ frame?: true;
99
+ /** The extension's id for the document it came from, where it says. */
100
+ documentId?: string;
101
+ /** From an iframe: its frame id's number (`F3` is 3), when known. */
102
+ frameNumber?: number;
103
+ }
104
+ export interface StartReport extends ScriptReport {
105
+ }
106
+ /** What a manager's report gives for a `ScriptReport`; the host adds `at`. */
107
+ export type ReportFields = Omit<ScriptReport, 'at'>;
108
+ export interface ErrorReport extends ScriptReport {
109
+ message: string;
110
+ stack: string;
111
+ }
112
+ export interface SkipReport extends ScriptReport {
113
+ /** Why the script did not run: the header rule, or the extension's reason. */
114
+ reason: string;
115
+ /**
116
+ * The host's own finding that the header's rules miss the URL, rather
117
+ * than the extension's report, so SourceMonkey's Log has no entry.
118
+ */
119
+ ruleMiss?: true;
120
+ }
121
+ /**
122
+ * A manual script (`@run-at context-menu`) matched a new document,
123
+ * where it waits to be run rather than starting.
124
+ */
125
+ export type ManualReport = ScriptReport;
126
+ export interface HostReports {
127
+ started: StartReport[];
128
+ errors: ErrorReport[];
129
+ skipped: SkipReport[];
130
+ /** Manual scripts waiting in a new document (`ManualReport`). */
131
+ manual: ManualReport[];
132
+ /** Every `GM_xmlhttpRequest`, with its outcome once settled. */
133
+ requests: XhrRecord[];
134
+ /** Every `GM_openInTab`. */
135
+ tabs: TabRecord[];
136
+ /** Menu commands currently registered, in registration order. */
137
+ menuCommands: MenuCommandRecord[];
138
+ /** Every `GM_notification`. */
139
+ notifications: NotificationRecord[];
140
+ /** Every `GM_download` the extension handled. */
141
+ downloads: DownloadRecord[];
142
+ /** Every connection prompt, with its answer once given. */
143
+ connectPrompts: ConnectPromptRecord[];
144
+ }
145
+ export interface WireWrite {
146
+ key: string;
147
+ value?: unknown;
148
+ deleted?: boolean;
149
+ }
150
+ export interface HostEventMap {
151
+ start: [StartReport];
152
+ 'script-error': [ErrorReport];
153
+ skip: [SkipReport];
154
+ manual: [ManualReport];
155
+ 'value-write': [{
156
+ scriptId: string;
157
+ writes: WireWrite[];
158
+ }];
159
+ /** A `GM_xmlhttpRequest` settled; the record carries its outcome. */
160
+ request: [XhrRecord];
161
+ tab: [TabRecord];
162
+ 'menu-command': [MenuCommandRecord];
163
+ notification: [NotificationRecord];
164
+ download: [DownloadRecord];
165
+ /** A connection prompt opened, or was answered (`answer` set). */
166
+ 'connect-prompt': [ConnectPromptRecord];
167
+ }
168
+ declare let codec: {
169
+ encodeValue(v: unknown): unknown;
170
+ decodeValue(v: unknown): unknown;
171
+ } | null;
172
+ export declare function valueCodec(): NonNullable<typeof codec>;
173
+ export type RequestInterceptor = (request: GmXhrRequestPayload, scriptId: string) => GmXhrEvent | null | Promise<GmXhrEvent | null>;
174
+ export declare abstract class HarnessHost extends EventEmitter<HostEventMap> {
175
+ private readonly scripts;
176
+ private readonly owners;
177
+ private readonly values;
178
+ protected readonly recordPages: WeakMap<object, PageLink>;
179
+ private readonly reportWaiters;
180
+ readonly reports: HostReports;
181
+ private readonly manualByPage;
182
+ private readonly menuOwners;
183
+ /** The run's frame ids (`F3`), across all its tabs. */
184
+ readonly frameIds: FrameIds;
185
+ /** Register a prepared script as running in `owner`'s tab. */
186
+ addScript(prepared: PreparedScript, owner: PageLink): void;
187
+ /** `owner` no longer has the script; forget it once nobody does. */
188
+ removeScript(scriptId: string, owner: PageLink): void;
189
+ hasScript(scriptId: string): boolean;
190
+ /**
191
+ * Whether a script is running in a page's current top-frame document:
192
+ * its last word from there is a start rather than a skip. For its
193
+ * iframes, see `frameRuns`.
194
+ */
195
+ isRunning(page: PageLink, scriptId: string): boolean;
196
+ /**
197
+ * Whether the scripts' manager reports their starts, skips and
198
+ * errors. Another manager than SourceMonkey doesn't.
199
+ */
200
+ get getsReports(): boolean;
201
+ /**
202
+ * Of `scriptIds`, the ones with no word from `page` since `since`:
203
+ * not yet started, skipped or thrown there, nor waiting to be run.
204
+ */
205
+ unreported(page: PageLink, scriptIds: readonly string[], since: number): string[];
206
+ /**
207
+ * Resolves once each of `scriptIds` has had its word from `page`
208
+ * since `since` (see `unreported`). Every script the extension runs
209
+ * in a new document gives one, so this is when a load's scripts are
210
+ * done starting. Never rejects. Stops waiting, unresolved, on
211
+ * `signal`, for a page that goes away first.
212
+ */
213
+ untilReported(page: PageLink, scriptIds: readonly string[], since: number, signal?: AbortSignal): Promise<void>;
214
+ /** A script's latest start and latest skip from one page's top frame. */
215
+ lastStartAndSkip(page: PageLink, scriptId: string): {
216
+ started?: StartReport;
217
+ skipped?: SkipReport;
218
+ };
219
+ /**
220
+ * The scripts running in each iframe document of a page that reported
221
+ * any, by the extension's document id: those whose last word from
222
+ * there is a start. Documents since gone are included; the caller
223
+ * knows which are live (`liveFrameDocuments`).
224
+ */
225
+ frameRuns(page: PageLink): Map<string, Set<string>>;
226
+ /**
227
+ * Whether a script started in any iframe document of a page since
228
+ * `since` (when its top document began), and wasn't skipped there
229
+ * after. Documents since gone count too: for picking the tabs to
230
+ * reload, one too many is better than one missed.
231
+ */
232
+ ranInFrames(page: PageLink, scriptId: string, since: number): boolean;
233
+ /**
234
+ * A page's live iframe documents, by the extension's id, each with
235
+ * its Playwright frame. Null where the manager can't say; throws when
236
+ * the extension is too old to report on frames.
237
+ */
238
+ liveFrameDocuments(_page: PageLink): Promise<Map<string, Frame> | null>;
239
+ /** The page a record in `reports` came from, if it is still known. */
240
+ pageOf(record: object): PageLink | undefined;
241
+ scriptIds(): string[];
242
+ /**
243
+ * The ids of the scripts whose rules match `url`; in an iframe
244
+ * (`inFrame`), leaving out those `@noframes` keeps to the top frame.
245
+ */
246
+ scriptsFor(url: string, inFrame: boolean): string[];
247
+ /**
248
+ * `text` with each stack frame from a script's injected entry pointed
249
+ * at the file and line it was written in: a `@require`, or the script
250
+ * itself. Without this, a script with `@require`s reports lines
251
+ * counted from the top of the requires.
252
+ */
253
+ abstract remapStack(text: string): string;
254
+ /** A watched page went away. */
255
+ detachPage(page: PageLink): void;
256
+ /**
257
+ * The manual scripts that can be run in `page`'s current document, at
258
+ * its URL now: one the page moved away from in place (pushState) can't.
259
+ */
260
+ manualScripts(page: PageLink): string[];
261
+ private forgetDocumentState;
262
+ /**
263
+ * Values written by the run or the test, as another tab of the script
264
+ * would. Here only the host's copy; `ExtensionHost` writes them into
265
+ * the extension too.
266
+ */
267
+ setValues(scriptId: string, values: Record<string, unknown>): Promise<void>;
268
+ /** Every value a script has stored, decoded, from the host's copy. */
269
+ getValues(scriptId: string): Record<string, unknown>;
270
+ /**
271
+ * Every value a script has stored, for the run's commands: here the
272
+ * host's copy; `ExtensionHost` asks the extension.
273
+ */
274
+ valuesOf(scriptId: string): Promise<Record<string, unknown>>;
275
+ /**
276
+ * Where `eval` finds a script's eval hook in a page (see
277
+ * src/eval-hook.ts): the key the hooks are kept under, and the id the
278
+ * script has there. Null for a script that has none.
279
+ */
280
+ abstract evalHook(scriptId: string): {
281
+ key: string;
282
+ id: string;
283
+ } | null;
284
+ getValue(scriptId: string, key: string): unknown;
285
+ private applyWrites;
286
+ private storeFor;
287
+ /**
288
+ * A watched page loaded a new document. The extension skips a script
289
+ * whose rules miss the URL silently, so the host records the miss for
290
+ * the developer: which rule kept the script off this URL. `scripts`
291
+ * are the ones the page's tab runs.
292
+ */
293
+ noteNavigation(page: PageLink, scripts: readonly PreparedScript[]): void;
294
+ /** A script started in `from`'s current document. */
295
+ protected recordStart(from: PageLink, fields: ReportFields): void;
296
+ /** A script threw in `from`. */
297
+ protected recordError(from: PageLink, fields: ReportFields & {
298
+ message: string;
299
+ stack: string;
300
+ }): void;
301
+ /** A script didn't run in `from`, for `reason`. */
302
+ protected recordSkip(from: PageLink, fields: ReportFields & {
303
+ reason: string;
304
+ }): void;
305
+ /**
306
+ * A manual script can be run in `from`'s document, where it waits to
307
+ * be run. Once per document: the extension says it again on each
308
+ * navigation, a pushState included, and a back/forward restore
309
+ * (which `forgetDocumentState` has cleared it for).
310
+ */
311
+ protected recordManual(from: PageLink, fields: {
312
+ scriptId: string;
313
+ name: string;
314
+ url: string;
315
+ }): void;
316
+ /** A script in `from` wrote values. */
317
+ protected recordValueWrites(from: PageLink, scriptId: string, writes: WireWrite[], frame?: {
318
+ frameNumber?: number;
319
+ }): void;
320
+ /** A script in `from` registered a menu command. */
321
+ protected registerMenu(from: PageLink, scriptId: string, commandId: string, name: string, documentId?: string, frame?: {
322
+ frameNumber?: number;
323
+ }): void;
324
+ /** A script in `from` removed a menu command. */
325
+ protected unregisterMenu(from: PageLink, scriptId: string, commandId: string, documentId?: string): void;
326
+ /**
327
+ * Invoke a registered menu command by its name, or by id, on the page
328
+ * that registered it. The extension runs all the script's
329
+ * registrations of that caption in the tab, as its menu does.
330
+ */
331
+ fireMenuCommand(nameOrId: string, scriptId?: string): Promise<boolean>;
332
+ /**
333
+ * Fire one entry of `reports.menuCommands` in the page that
334
+ * registered it. False once that page has moved on.
335
+ */
336
+ abstract fireMenuEntry(entry: MenuCommandRecord): Promise<boolean>;
337
+ /**
338
+ * Run a manual script in `page`, as its popup "Run this script" does.
339
+ * Throws with the reason when it can't.
340
+ */
341
+ abstract runManualScript(page: PageLink, scriptId: string): Promise<void>;
342
+ /** Click a shown notification, which runs the script's `onclick`. */
343
+ abstract clickNotification(requestId: string): Promise<boolean>;
344
+ /** Close a shown notification, which fires the script's `ondone`. */
345
+ abstract closeNotification(requestId: string): Promise<boolean>;
346
+ /** Answer a waiting connection prompt. False when it isn't waiting. */
347
+ abstract answerConnectPrompt(promptId: string, choice: ConnectChoice): Promise<boolean>;
348
+ private baseReport;
349
+ protected nameOf(scriptId: string): string;
350
+ protected notify<K extends keyof HostEventMap>(event: K, ...args: HostEventMap[K]): void;
351
+ }
352
+ export {};