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,61 @@
|
|
|
1
|
+
// Pure helpers for the userscript viewer's URL-fragment navigation.
|
|
2
|
+
//
|
|
3
|
+
// The viewer keeps the current tab + highlight reflected in
|
|
4
|
+
// `location.hash` so a URL can be copied / shared / reopened and
|
|
5
|
+
// land in the same place. Empty hash → main script, no highlight.
|
|
6
|
+
//
|
|
7
|
+
// Fragment grammar:
|
|
8
|
+
// <empty> main script tab, no highlight
|
|
9
|
+
// Log the Log tab
|
|
10
|
+
// <filename> tab whose `label` matches `filename`
|
|
11
|
+
// <filename>:<line> tab + highlighted line
|
|
12
|
+
// <filename>:<line>:<col> tab + highlighted line + column accent
|
|
13
|
+
export function parseHash(rawHash) {
|
|
14
|
+
let hash = rawHash;
|
|
15
|
+
if (hash.startsWith('#'))
|
|
16
|
+
hash = hash.slice(1);
|
|
17
|
+
if (!hash)
|
|
18
|
+
return { kind: 'empty' };
|
|
19
|
+
if (hash === 'Log')
|
|
20
|
+
return { kind: 'log' };
|
|
21
|
+
const parts = hash.split(':');
|
|
22
|
+
let filename;
|
|
23
|
+
try {
|
|
24
|
+
filename = decodeURIComponent(parts[0]);
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
// Malformed %-escape — keep the raw form rather than throwing.
|
|
28
|
+
filename = parts[0];
|
|
29
|
+
}
|
|
30
|
+
const out = { kind: 'code', filename };
|
|
31
|
+
if (parts.length > 1) {
|
|
32
|
+
const n = parseInt(parts[1], 10);
|
|
33
|
+
if (Number.isFinite(n) && n > 0)
|
|
34
|
+
out.line = n;
|
|
35
|
+
}
|
|
36
|
+
if (parts.length > 2 && out.line !== undefined) {
|
|
37
|
+
const n = parseInt(parts[2], 10);
|
|
38
|
+
if (Number.isFinite(n) && n > 0)
|
|
39
|
+
out.col = n;
|
|
40
|
+
}
|
|
41
|
+
return out;
|
|
42
|
+
}
|
|
43
|
+
// Build a hash fragment from the current viewer state. Returns the
|
|
44
|
+
// string WITHOUT a leading "#" — empty string means "no fragment"
|
|
45
|
+
// (main-script-no-highlight is the default landing).
|
|
46
|
+
export function buildHash(args) {
|
|
47
|
+
if (args.tab === 'log')
|
|
48
|
+
return 'Log';
|
|
49
|
+
// Default landing: main tab, no highlight, no fragment.
|
|
50
|
+
if (args.tab === 'main' && args.line === undefined)
|
|
51
|
+
return '';
|
|
52
|
+
if (!args.filename)
|
|
53
|
+
return '';
|
|
54
|
+
let h = encodeURIComponent(args.filename);
|
|
55
|
+
if (args.line !== undefined) {
|
|
56
|
+
h += ':' + args.line;
|
|
57
|
+
if (args.col !== undefined)
|
|
58
|
+
h += ':' + args.col;
|
|
59
|
+
}
|
|
60
|
+
return h;
|
|
61
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// Ctrl/Cmd-A that selects a page's content rather than the page.
|
|
2
|
+
//
|
|
3
|
+
// On the viewer and the compare page the one thing worth copying is
|
|
4
|
+
// the code (or the log, or a diff), and a page-wide selection drags the
|
|
5
|
+
// header, details rows and button labels along with it, which nobody
|
|
6
|
+
// wants to paste. Each page says what the key should select, given
|
|
7
|
+
// where focus is; this installs the key.
|
|
8
|
+
//
|
|
9
|
+
// Left alone inside a text control or an open dialog, where select-all
|
|
10
|
+
// means what it always did — and whenever the page answers null, which
|
|
11
|
+
// is its way of saying the browser's own select-all is the right one.
|
|
12
|
+
export function installSelectAll(target) {
|
|
13
|
+
document.addEventListener('keydown', (ev) => {
|
|
14
|
+
if (ev.defaultPrevented)
|
|
15
|
+
return;
|
|
16
|
+
// `code` as well as `key`: on a non-Latin layout the A key reports
|
|
17
|
+
// its own letter, and Chrome's select-all still fires on it.
|
|
18
|
+
if (ev.key.toLowerCase() !== 'a' && ev.code !== 'KeyA')
|
|
19
|
+
return;
|
|
20
|
+
if (!(ev.ctrlKey || ev.metaKey) || ev.altKey || ev.shiftKey)
|
|
21
|
+
return;
|
|
22
|
+
const from = ev.target;
|
|
23
|
+
if (from instanceof Element && from.closest('input, textarea, select, [contenteditable], dialog[open]'))
|
|
24
|
+
return;
|
|
25
|
+
const el = target();
|
|
26
|
+
if (!el)
|
|
27
|
+
return;
|
|
28
|
+
ev.preventDefault();
|
|
29
|
+
const selection = window.getSelection();
|
|
30
|
+
if (!selection)
|
|
31
|
+
return;
|
|
32
|
+
const range = document.createRange();
|
|
33
|
+
range.selectNodeContents(el);
|
|
34
|
+
selection.removeAllRanges();
|
|
35
|
+
selection.addRange(range);
|
|
36
|
+
});
|
|
37
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
// Makes a native `<select>` open its list on the mouse *release*
|
|
2
|
+
// rather than the press, so the click that opens it cannot also pick
|
|
3
|
+
// out of it.
|
|
4
|
+
//
|
|
5
|
+
// The hazard is the browser's own popup placement. Chrome usually
|
|
6
|
+
// draws the list below the closed control, but when it doesn't fit
|
|
7
|
+
// there — near the bottom of the screen, a short window, a long list —
|
|
8
|
+
// it shifts the list up over the control, which puts an entry directly
|
|
9
|
+
// under the pointer that just pressed. Chrome's press-drag-release
|
|
10
|
+
// support (hold the button, slide down the list, release on an entry)
|
|
11
|
+
// then treats the release of that same click as a pick: the dropdown
|
|
12
|
+
// appears to open, choose at random, and close, with the list never
|
|
13
|
+
// seen.
|
|
14
|
+
//
|
|
15
|
+
// Why the page has to handle it: the popup is a browser widget, not
|
|
16
|
+
// DOM. We can't place it, we can't see it, no event says it opened,
|
|
17
|
+
// and the gesture has no opt-out.
|
|
18
|
+
//
|
|
19
|
+
// So the press is cancelled and the list is opened from the `click`
|
|
20
|
+
// that follows, by which time no button is held:
|
|
21
|
+
//
|
|
22
|
+
// - `mousedown` is `preventDefault`ed, which is what stops Chrome
|
|
23
|
+
// opening the popup (and, as a side effect, the focus the press
|
|
24
|
+
// would have given — so focus is set by hand);
|
|
25
|
+
// - the `click` that press produced calls `showPicker()`, the same
|
|
26
|
+
// list, opened with the mouse already up. Wherever Chrome draws
|
|
27
|
+
// it, nothing is committed until the user presses on an entry
|
|
28
|
+
// deliberately.
|
|
29
|
+
//
|
|
30
|
+
// What it costs: press-drag-release no longer picks — the gesture that
|
|
31
|
+
// causes the bug. Press, release, click the entry still does, as does
|
|
32
|
+
// every keyboard path, which never goes near this code.
|
|
33
|
+
//
|
|
34
|
+
// The alternative — letting the stray pick happen and undoing it — was
|
|
35
|
+
// worse in practice: the list is torn down and re-opened under the
|
|
36
|
+
// cursor, which reads as a flash over the whole popup on every click.
|
|
37
|
+
import { dlog } from '../debug-log.js';
|
|
38
|
+
import { describeError } from '../script-build.js';
|
|
39
|
+
// Open `select`'s list on release instead of on press.
|
|
40
|
+
export function guardSelectOpeningClick(select) {
|
|
41
|
+
// Nothing to take over with, so the native press-to-open has to
|
|
42
|
+
// stand, bug and all — a cancelled press with no replacement is a
|
|
43
|
+
// dead control. `showPicker` has been in Chrome since 121, well
|
|
44
|
+
// below the extension's floor, so this covers only a future context
|
|
45
|
+
// that withholds it.
|
|
46
|
+
if (typeof select.showPicker !== 'function')
|
|
47
|
+
return;
|
|
48
|
+
// Cleared if `showPicker` ever refuses, which hands the control back
|
|
49
|
+
// to the browser's own press-to-open rather than leaving a dropdown
|
|
50
|
+
// that cannot be opened at all. The click that discovered the
|
|
51
|
+
// refusal is spent — its press was already cancelled — so that one
|
|
52
|
+
// opens nothing and the next one opens natively.
|
|
53
|
+
let takeover = true;
|
|
54
|
+
// A press of ours is waiting for its release. This, rather than any
|
|
55
|
+
// property of the click, is what says the list should open: a click
|
|
56
|
+
// the guard didn't cancel a press for must not open a picker, and
|
|
57
|
+
// there are several — the keyboard's Enter / Space, a click
|
|
58
|
+
// forwarded by the `for=` label beside the install dropdown, a
|
|
59
|
+
// `select.click()` from any future code, a press that began on
|
|
60
|
+
// something else and released here.
|
|
61
|
+
let openFromPress = false;
|
|
62
|
+
select.addEventListener('mousedown', (event) => {
|
|
63
|
+
// Only the button that opens the popup. Anything else is left to
|
|
64
|
+
// the browser, context menu included.
|
|
65
|
+
if (!takeover || event.button !== 0)
|
|
66
|
+
return;
|
|
67
|
+
event.preventDefault();
|
|
68
|
+
openFromPress = true;
|
|
69
|
+
// The cancelled press took the focus it would have given with it.
|
|
70
|
+
// Without scrolling: the control is under the pointer, so it is on
|
|
71
|
+
// screen already, and a press never scrolls.
|
|
72
|
+
select.focus({ preventScroll: true });
|
|
73
|
+
});
|
|
74
|
+
select.addEventListener('click', () => {
|
|
75
|
+
// Cleared on every click, ours or not: the flag is about one
|
|
76
|
+
// press, and a click that isn't its release must not leave it
|
|
77
|
+
// armed for a later one.
|
|
78
|
+
const ours = openFromPress;
|
|
79
|
+
openFromPress = false;
|
|
80
|
+
if (!takeover || !ours)
|
|
81
|
+
return;
|
|
82
|
+
try {
|
|
83
|
+
select.showPicker();
|
|
84
|
+
}
|
|
85
|
+
catch (err) {
|
|
86
|
+
takeover = false;
|
|
87
|
+
dlog(`[SourceMonkey] could not open the collection list: ${describeError(err)}`);
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
}
|