sourcemonkey 0.0.0-stage → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +87 -2
- package/dist/bytes.js +37 -0
- package/dist/channel-placeholder.js +5 -0
- package/dist/collection-scan.js +17 -0
- package/dist/collections.html +353 -0
- package/dist/compare.html +358 -0
- package/dist/composed-source.js +205 -0
- package/dist/connect-prompt.html +47 -0
- package/dist/debug/icons.html +211 -0
- package/dist/debug/storage.html +163 -0
- package/dist/debug-log.js +75 -0
- package/dist/diagnostic-location.js +64 -0
- package/dist/eval-hook.js +308 -0
- package/dist/extension/background.js +5263 -0
- package/dist/extension/channel.js +133 -0
- package/dist/extension/code-links.js +187 -0
- package/dist/extension/code-tabs.js +460 -0
- package/dist/extension/collection-dialog.js +619 -0
- package/dist/extension/collection-display.js +322 -0
- package/dist/extension/collections.js +2905 -0
- package/dist/extension/compare.js +867 -0
- package/dist/extension/concurrency.js +186 -0
- package/dist/extension/connect-grants.js +109 -0
- package/dist/extension/connect-prompt-page.js +70 -0
- package/dist/extension/connect-prompt.js +266 -0
- package/dist/extension/copy-button.js +63 -0
- package/dist/extension/copy-dialog.js +502 -0
- package/dist/extension/copy-preference.js +66 -0
- package/dist/extension/debug/icons.js +203 -0
- package/dist/extension/debug/storage.js +365 -0
- package/dist/extension/deep-link.js +77 -0
- package/dist/extension/delete-dialog.js +432 -0
- package/dist/extension/delete-icon.js +40 -0
- package/dist/extension/details-tooltips.js +66 -0
- package/dist/extension/directories.js +679 -0
- package/dist/extension/export-backup.js +407 -0
- package/dist/extension/export-dialog.js +142 -0
- package/dist/extension/file-access.js +74 -0
- package/dist/extension/file-changes.js +346 -0
- package/dist/extension/frame-info.js +85 -0
- package/dist/extension/github-provider.js +336 -0
- package/dist/extension/glyph.js +84 -0
- package/dist/extension/gm-bindings.js +601 -0
- package/dist/extension/gm-download.js +419 -0
- package/dist/extension/gm-menu.js +228 -0
- package/dist/extension/gm-notification.js +141 -0
- package/dist/extension/gm-originator-map.js +23 -0
- package/dist/extension/gm-tab-data.js +121 -0
- package/dist/extension/gm-tab.js +160 -0
- package/dist/extension/gm-url-change.js +111 -0
- package/dist/extension/gm-url-scheme.js +27 -0
- package/dist/extension/gm-values.js +176 -0
- package/dist/extension/gm-window-control.js +104 -0
- package/dist/extension/gm-xhr-headers.js +333 -0
- package/dist/extension/gm-xhr.js +584 -0
- package/dist/extension/injector.js +3145 -0
- package/dist/extension/install-capture.js +277 -0
- package/dist/extension/line-diff.js +233 -0
- package/dist/extension/local-copy.js +560 -0
- package/dist/extension/local-delete.js +276 -0
- package/dist/extension/location-kinds.js +108 -0
- package/dist/extension/log-format.js +158 -0
- package/dist/extension/managed-changes.js +361 -0
- package/dist/extension/managed-items.js +57 -0
- package/dist/extension/match-index.js +375 -0
- package/dist/extension/missing-scripts.js +66 -0
- package/dist/extension/more-menu.js +109 -0
- package/dist/extension/move-dialog.js +197 -0
- package/dist/extension/offscreen.js +37 -0
- package/dist/extension/options.js +504 -0
- package/dist/extension/page-heading.js +170 -0
- package/dist/extension/page-links.js +199 -0
- package/dist/extension/parse-check-client.js +70 -0
- package/dist/extension/parse-check.js +161 -0
- package/dist/extension/parse-sandbox-host.js +172 -0
- package/dist/extension/parse-sandbox.js +175 -0
- package/dist/extension/popup-commands-open.js +41 -0
- package/dist/extension/popup-view.js +387 -0
- package/dist/extension/popup.js +703 -0
- package/dist/extension/prism-userscript.js +53 -0
- package/dist/extension/refresh-error.js +136 -0
- package/dist/extension/refresh-targets.js +160 -0
- package/dist/extension/related-versions.js +1144 -0
- package/dist/extension/resize-observer-loop.js +19 -0
- package/dist/extension/row-cache.js +387 -0
- package/dist/extension/script-blobs.js +413 -0
- package/dist/extension/script-details.js +658 -0
- package/dist/extension/script-enablement.js +285 -0
- package/dist/extension/script-identity.js +310 -0
- package/dist/extension/script-keys.js +54 -0
- package/dist/extension/script-log-id.js +155 -0
- package/dist/extension/script-log.js +290 -0
- package/dist/extension/script-rejection.js +104 -0
- package/dist/extension/script-sites.js +158 -0
- package/dist/extension/script-store.js +3507 -0
- package/dist/extension/script-updater.js +991 -0
- package/dist/extension/script-url-hash.js +61 -0
- package/dist/extension/select-all.js +37 -0
- package/dist/extension/select-open-guard.js +90 -0
- package/dist/extension/site-icon.js +1261 -0
- package/dist/extension/sm-dev-link.js +302 -0
- package/dist/extension/solo-click.js +58 -0
- package/dist/extension/sticky-numbers.js +188 -0
- package/dist/extension/storage-breakdown.js +253 -0
- package/dist/extension/storage-scan.js +86 -0
- package/dist/extension/storage-usage.js +194 -0
- package/dist/extension/structural-keys.js +29 -0
- package/dist/extension/sw-teardown.js +36 -0
- package/dist/extension/tab-status.js +403 -0
- package/dist/extension/toolbar-summary.js +105 -0
- package/dist/extension/user-scripts-access.js +43 -0
- package/dist/extension/userscript.js +3672 -0
- package/dist/extension/value-store.js +204 -0
- package/dist/extension/version-probe-fetch.js +68 -0
- package/dist/extension/worker-client.js +109 -0
- package/dist/extension/worker-ops.js +171 -0
- package/dist/extension/zip-writer.js +24 -0
- package/dist/external-files.js +878 -0
- package/dist/file-loader.js +436 -0
- package/dist/file-locations.js +439 -0
- package/dist/generated-wrappers.js +5 -0
- package/dist/github-auth.js +148 -0
- package/dist/github-urls.js +46 -0
- package/dist/gm-api-catalog.js +217 -0
- package/dist/gm-connect.js +273 -0
- package/dist/gm-xhr-types.js +5 -0
- package/dist/http-read.js +142 -0
- package/dist/icons/icon-128.png +0 -0
- package/dist/icons/icon-16.png +0 -0
- package/dist/icons/icon-48.png +0 -0
- package/dist/local-file-overrides.js +558 -0
- package/dist/manifest.json +38 -0
- package/dist/markup-response.js +126 -0
- package/dist/match-targets.js +305 -0
- package/dist/menu-captions.js +22 -0
- package/dist/offscreen.html +39 -0
- package/dist/options.html +197 -0
- package/dist/parse-check-protocol.js +51 -0
- package/dist/parse-location.js +171 -0
- package/dist/parse-sandbox.html +56 -0
- package/dist/phase-timing.js +155 -0
- package/dist/popup.html +197 -0
- package/dist/public-suffixes.js +6957 -0
- package/dist/run-context.js +31 -0
- package/dist/runtime-messages.js +34 -0
- package/dist/sandboxed-page.js +35 -0
- package/dist/script-build.js +787 -0
- package/dist/script-display.js +383 -0
- package/dist/script-icon.js +43 -0
- package/dist/script-links.js +204 -0
- package/dist/script-source-url.js +214 -0
- package/dist/script-world.js +65 -0
- package/dist/sm-dev-protocol.js +84 -0
- package/dist/source-map.js +177 -0
- package/dist/stack-link.js +138 -0
- package/dist/styles.css +825 -0
- package/dist/unsafe-window-use.js +229 -0
- package/dist/url-match.js +734 -0
- package/dist/userscript-header.js +248 -0
- package/dist/userscript.html +1165 -0
- package/dist/vendor/fflate.LICENSE +21 -0
- package/dist/vendor/fflate.js +2692 -0
- package/dist/vendor/prism/prism-line-numbers.css +1 -0
- package/dist/vendor/prism/prism-line-numbers.js +1 -0
- package/dist/vendor/prism/prism.css +1 -0
- package/dist/vendor/prism/prism.js +1946 -0
- package/dist/version-compare.js +141 -0
- package/dist/version-probe.js +120 -0
- package/lib/build-info.json +1 -0
- package/lib/bytes.d.ts +3 -0
- package/lib/bytes.js +37 -0
- package/lib/channel-placeholder.d.ts +1 -0
- package/lib/channel-placeholder.js +5 -0
- package/lib/collection-scan.d.ts +8 -0
- package/lib/collection-scan.js +17 -0
- package/lib/composed-source.d.ts +28 -0
- package/lib/composed-source.js +205 -0
- package/lib/debug-log.d.ts +9 -0
- package/lib/debug-log.js +75 -0
- package/lib/diagnostic-location.d.ts +8 -0
- package/lib/diagnostic-location.js +64 -0
- package/lib/eval-hook.d.ts +34 -0
- package/lib/eval-hook.js +308 -0
- package/lib/external-files.d.ts +111 -0
- package/lib/external-files.js +878 -0
- package/lib/file-loader.d.ts +48 -0
- package/lib/file-loader.js +436 -0
- package/lib/file-locations.d.ts +44 -0
- package/lib/file-locations.js +439 -0
- package/lib/generated-wrappers.d.ts +11 -0
- package/lib/generated-wrappers.js +5 -0
- package/lib/github-auth.d.ts +12 -0
- package/lib/github-auth.js +148 -0
- package/lib/github-urls.d.ts +1 -0
- package/lib/github-urls.js +46 -0
- package/lib/gm-api-catalog.d.ts +24 -0
- package/lib/gm-api-catalog.js +217 -0
- package/lib/gm-connect.d.ts +34 -0
- package/lib/gm-connect.js +273 -0
- package/lib/gm-xhr-types.d.ts +68 -0
- package/lib/gm-xhr-types.js +5 -0
- package/lib/harness/browser-extensions.d.ts +73 -0
- package/lib/harness/browser-extensions.js +285 -0
- package/lib/harness/browser-lang.d.ts +20 -0
- package/lib/harness/browser-lang.js +86 -0
- package/lib/harness/browser-launch.d.ts +14 -0
- package/lib/harness/browser-launch.js +184 -0
- package/lib/harness/checks.d.ts +110 -0
- package/lib/harness/checks.js +321 -0
- package/lib/harness/cli.d.ts +2 -0
- package/lib/harness/cli.js +2259 -0
- package/lib/harness/command-args.d.ts +91 -0
- package/lib/harness/command-args.js +369 -0
- package/lib/harness/command-lines.d.ts +80 -0
- package/lib/harness/command-lines.js +180 -0
- package/lib/harness/command-list.d.ts +206 -0
- package/lib/harness/command-list.js +1475 -0
- package/lib/harness/console-commands.d.ts +463 -0
- package/lib/harness/console-commands.js +3216 -0
- package/lib/harness/download-watch.d.ts +21 -0
- package/lib/harness/download-watch.js +156 -0
- package/lib/harness/extension-backend.d.ts +41 -0
- package/lib/harness/extension-backend.js +100 -0
- package/lib/harness/extension-host.d.ts +112 -0
- package/lib/harness/extension-host.js +552 -0
- package/lib/harness/extension-launch.d.ts +67 -0
- package/lib/harness/extension-launch.js +285 -0
- package/lib/harness/extension-link.d.ts +315 -0
- package/lib/harness/extension-link.js +607 -0
- package/lib/harness/external-manager.d.ts +146 -0
- package/lib/harness/external-manager.js +414 -0
- package/lib/harness/fixture.d.ts +165 -0
- package/lib/harness/fixture.js +461 -0
- package/lib/harness/frame-sessions.d.ts +71 -0
- package/lib/harness/frame-sessions.js +248 -0
- package/lib/harness/frames.d.ts +68 -0
- package/lib/harness/frames.js +216 -0
- package/lib/harness/help-format.d.ts +17 -0
- package/lib/harness/help-format.js +127 -0
- package/lib/harness/host.d.ts +352 -0
- package/lib/harness/host.js +423 -0
- package/lib/harness/index.d.ts +8 -0
- package/lib/harness/index.js +10 -0
- package/lib/harness/input-file.d.ts +18 -0
- package/lib/harness/input-file.js +61 -0
- package/lib/harness/json-output.d.ts +565 -0
- package/lib/harness/json-output.js +71 -0
- package/lib/harness/manager-actions.d.ts +21 -0
- package/lib/harness/manager-actions.js +129 -0
- package/lib/harness/manager-commands.d.ts +142 -0
- package/lib/harness/manager-commands.js +1196 -0
- package/lib/harness/manager-fetch.d.ts +33 -0
- package/lib/harness/manager-fetch.js +239 -0
- package/lib/harness/managers.d.ts +24 -0
- package/lib/harness/managers.js +27 -0
- package/lib/harness/output-style.d.ts +125 -0
- package/lib/harness/output-style.js +322 -0
- package/lib/harness/page-commands.d.ts +134 -0
- package/lib/harness/page-commands.js +1141 -0
- package/lib/harness/page-output.d.ts +67 -0
- package/lib/harness/page-output.js +139 -0
- package/lib/harness/page-watch.d.ts +171 -0
- package/lib/harness/page-watch.js +607 -0
- package/lib/harness/parse-check-node.d.ts +3 -0
- package/lib/harness/parse-check-node.js +132 -0
- package/lib/harness/path-args.d.ts +22 -0
- package/lib/harness/path-args.js +148 -0
- package/lib/harness/playwright-chromium.d.ts +16 -0
- package/lib/harness/playwright-chromium.js +86 -0
- package/lib/harness/prepare.d.ts +168 -0
- package/lib/harness/prepare.js +364 -0
- package/lib/harness/prompt-editor.d.ts +17 -0
- package/lib/harness/prompt-editor.js +354 -0
- package/lib/harness/prompt-history.d.ts +13 -0
- package/lib/harness/prompt-history.js +89 -0
- package/lib/harness/rebuild-advice.d.ts +6 -0
- package/lib/harness/rebuild-advice.js +39 -0
- package/lib/harness/run-log.d.ts +47 -0
- package/lib/harness/run-log.js +140 -0
- package/lib/harness/run-logs.d.ts +132 -0
- package/lib/harness/run-logs.js +241 -0
- package/lib/harness/run.d.ts +194 -0
- package/lib/harness/run.js +1973 -0
- package/lib/harness/runs.d.ts +229 -0
- package/lib/harness/runs.js +726 -0
- package/lib/harness/save-html.d.ts +39 -0
- package/lib/harness/save-html.js +89 -0
- package/lib/harness/saved-pages.d.ts +120 -0
- package/lib/harness/saved-pages.js +275 -0
- package/lib/harness/script-mark.d.ts +17 -0
- package/lib/harness/script-mark.js +56 -0
- package/lib/harness/snapshot.d.ts +143 -0
- package/lib/harness/snapshot.js +474 -0
- package/lib/harness/stuck-tabs.d.ts +19 -0
- package/lib/harness/stuck-tabs.js +131 -0
- package/lib/harness/tab-refs.d.ts +20 -0
- package/lib/harness/tab-refs.js +80 -0
- package/lib/harness/tampermonkey.d.ts +71 -0
- package/lib/harness/tampermonkey.js +356 -0
- package/lib/harness/tm-ids.d.ts +18 -0
- package/lib/harness/tm-ids.js +88 -0
- package/lib/harness/violentmonkey.d.ts +34 -0
- package/lib/harness/violentmonkey.js +162 -0
- package/lib/harness/wait.d.ts +77 -0
- package/lib/harness/wait.js +458 -0
- package/lib/http-read.d.ts +30 -0
- package/lib/http-read.js +142 -0
- package/lib/local-file-overrides.d.ts +35 -0
- package/lib/local-file-overrides.js +558 -0
- package/lib/manifest.json +38 -0
- package/lib/markup-response.d.ts +11 -0
- package/lib/markup-response.js +126 -0
- package/lib/match-targets.d.ts +18 -0
- package/lib/match-targets.js +305 -0
- package/lib/menu-captions.d.ts +1 -0
- package/lib/menu-captions.js +22 -0
- package/lib/parse-check-protocol.d.ts +27 -0
- package/lib/parse-check-protocol.js +51 -0
- package/lib/parse-location.d.ts +12 -0
- package/lib/parse-location.js +171 -0
- package/lib/phase-timing.d.ts +12 -0
- package/lib/phase-timing.js +155 -0
- package/lib/public-suffixes.d.ts +1 -0
- package/lib/public-suffixes.js +6957 -0
- package/lib/run-context.d.ts +2 -0
- package/lib/run-context.js +31 -0
- package/lib/runtime-messages.d.ts +10 -0
- package/lib/runtime-messages.js +34 -0
- package/lib/sandboxed-page.d.ts +5 -0
- package/lib/sandboxed-page.js +35 -0
- package/lib/script-build.d.ts +111 -0
- package/lib/script-build.js +787 -0
- package/lib/script-display.d.ts +51 -0
- package/lib/script-display.js +383 -0
- package/lib/script-icon.d.ts +16 -0
- package/lib/script-icon.js +43 -0
- package/lib/script-links.d.ts +24 -0
- package/lib/script-links.js +204 -0
- package/lib/script-source-url.d.ts +8 -0
- package/lib/script-source-url.js +214 -0
- package/lib/script-world.d.ts +6 -0
- package/lib/script-world.js +65 -0
- package/lib/sm-dev-protocol.d.ts +251 -0
- package/lib/sm-dev-protocol.js +84 -0
- package/lib/source-map.d.ts +32 -0
- package/lib/source-map.js +177 -0
- package/lib/stack-link.d.ts +15 -0
- package/lib/stack-link.js +138 -0
- package/lib/unsafe-window-use.d.ts +1 -0
- package/lib/unsafe-window-use.js +229 -0
- package/lib/url-match.d.ts +40 -0
- package/lib/url-match.js +734 -0
- package/lib/userscript-header.d.ts +33 -0
- package/lib/userscript-header.js +248 -0
- package/lib/version-compare.d.ts +6 -0
- package/lib/version-compare.js +141 -0
- package/lib/version-probe.d.ts +17 -0
- package/lib/version-probe.js +120 -0
- package/package.json +55 -3
- package/skills/SourceMonkey-dev/SKILL.md +868 -0
- package/skills/SourceMonkey-dev/references/cdp.md +293 -0
- package/skills/SourceMonkey-dev/references/commands.md +297 -0
- package/skills/SourceMonkey-dev/references/other-managers.md +63 -0
- package/skills/SourceMonkey-dev/references/specs.md +46 -0
- package/skills/SourceMonkey-friction/SKILL.md +103 -0
- package/skills/SourceMonkey-friction/references/template.md +59 -0
|
@@ -0,0 +1,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 {};
|