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,248 @@
|
|
|
1
|
+
// Parser for the Tampermonkey-style metadata block at the top of a
|
|
2
|
+
// userscript:
|
|
3
|
+
//
|
|
4
|
+
// // ==UserScript==
|
|
5
|
+
// // @name Hello
|
|
6
|
+
// // @match https://example.com/*
|
|
7
|
+
// // @grant none
|
|
8
|
+
// // ==/UserScript==
|
|
9
|
+
//
|
|
10
|
+
// We return a flat list of `{tag, locale?, value}` entries in source
|
|
11
|
+
// order so callers can decide which tags are single-valued (@name,
|
|
12
|
+
// @version) and which can repeat (@match, @grant, @require, …) without
|
|
13
|
+
// the parser baking that policy in. Tag names are lowercased so lookups
|
|
14
|
+
// are case-insensitive; locales like `@name:de` are kept on the side.
|
|
15
|
+
// Every line-terminator shape the metadata-block scanner recognizes.
|
|
16
|
+
// One definition so "which line is this tag on?" is counted by exactly
|
|
17
|
+
// the rule the block is split by — count and split disagreeing is how
|
|
18
|
+
// every header diagnostic in a DOS or classic-Mac file ends up one line
|
|
19
|
+
// off.
|
|
20
|
+
//
|
|
21
|
+
// Deliberately NOT the same set as `countLines` in composed-source.ts,
|
|
22
|
+
// which adds U+2028/U+2029 because V8 treats them as terminators. Those
|
|
23
|
+
// can't appear in a metadata line anyway (`TAG_LINE`'s `.` doesn't
|
|
24
|
+
// match them), and widening the split here would change what this
|
|
25
|
+
// long-standing parser considers a line.
|
|
26
|
+
const LINE_BREAK = /\r\n|\r|\n/;
|
|
27
|
+
const LINE_BREAK_G = /\r\n|\r|\n/g;
|
|
28
|
+
function countLineBreaks(text) {
|
|
29
|
+
return text.match(LINE_BREAK_G)?.length ?? 0;
|
|
30
|
+
}
|
|
31
|
+
// A marker line is `//`, optional spaces or tabs, then the marker, with
|
|
32
|
+
// anything before or after it on the line, as VM matches it. GreasyFork
|
|
33
|
+
// serves scripts opening with `/// ==UserScript==` or closing with
|
|
34
|
+
// `// ==/UserScript==////`, and TM and VM both install them. Each match
|
|
35
|
+
// takes the whole line, so text after a closing marker (part of that
|
|
36
|
+
// comment) stays in the header rather than starting the body.
|
|
37
|
+
//
|
|
38
|
+
// `[^\r\n]` and a lookbehind rather than `/m` with `.`, `^` and `$`:
|
|
39
|
+
// those also break at U+2028/U+2029, which `LINE_BREAK` deliberately
|
|
40
|
+
// doesn't treat as line breaks.
|
|
41
|
+
const BLOCK_START = /(?<![^\r\n])[^\r\n]*?\/\/[ \t]*==UserScript==[^\r\n]*/;
|
|
42
|
+
const BLOCK_END = /(?<![^\r\n])[^\r\n]*?\/\/[ \t]*==\/UserScript==[^\r\n]*/;
|
|
43
|
+
// Strip a single leading UTF-8 BOM. Most fetch paths (`response.text()`,
|
|
44
|
+
// `TextDecoder`) drop it for us, but the page-context `file://` XHR path
|
|
45
|
+
// (`directories.ts`) hands back `xhr.responseText` with the BOM intact.
|
|
46
|
+
// The marker regexes would take it as text before the `//` on line 1,
|
|
47
|
+
// leaving it in `headerText` (and GM_info's metadata string) rather than
|
|
48
|
+
// dropped. The BOM only ever appears at file position 0.
|
|
49
|
+
function stripLeadingBom(source) {
|
|
50
|
+
return source.charCodeAt(0) === 0xfeff ? source.slice(1) : source;
|
|
51
|
+
}
|
|
52
|
+
// The ways the split can fail, as the text a user reads.
|
|
53
|
+
//
|
|
54
|
+
// Named constants rather than inline literals because these strings are
|
|
55
|
+
// both the message and the value something compares against — today the
|
|
56
|
+
// corpus validator, which groups failures by message. A reworded
|
|
57
|
+
// literal would silently stop matching.
|
|
58
|
+
//
|
|
59
|
+
// Phrased to read correctly in all three places they appear: alone in
|
|
60
|
+
// the viewer's message bar, alone in the Log tab, and after the
|
|
61
|
+
// preview's `This file cannot be installed: ` prefix. Capitalized and
|
|
62
|
+
// unpunctuated per docs/diagnostics.md#wording; that still rules out a
|
|
63
|
+
// bare fragment like `No metadata block`, which needs a subject.
|
|
64
|
+
export const NO_METADATA_BLOCK = 'No // ==UserScript== metadata block, so this is not a userscript';
|
|
65
|
+
// The fix is phrased as a need rather than an instruction ("it needs",
|
|
66
|
+
// not "add"): this message carries a location, so it renders as
|
|
67
|
+
// `… — add a … line (in f.user.js, line 1)`, where the parenthetical
|
|
68
|
+
// reads as *where to add it*. Line 1 is where the block opened.
|
|
69
|
+
export const UNTERMINATED_METADATA_BLOCK = 'The // ==UserScript== metadata block is never closed and needs a // ==/UserScript== line';
|
|
70
|
+
// A file with no userscript block but a `/* ==UserStyle==` one is a
|
|
71
|
+
// user style (CSS for a style manager extension, not a userscript).
|
|
72
|
+
// GreasyFork lists them alongside userscripts, so naming what the file
|
|
73
|
+
// is beats calling it "not a userscript".
|
|
74
|
+
export const USERSTYLE_NOT_SUPPORTED = 'This is a user style (a /* ==UserStyle== block), not a userscript. User styles need a user style manager extension.';
|
|
75
|
+
const USERSTYLE_START = /\/\*[ \t]*==UserStyle==/;
|
|
76
|
+
// Split a userscript source into the (rare) text above the metadata
|
|
77
|
+
// block, the raw metadata block itself, and the body text.
|
|
78
|
+
//
|
|
79
|
+
// Failure modes:
|
|
80
|
+
// - no `==UserScript==` line → NO_METADATA_BLOCK, or
|
|
81
|
+
// USERSTYLE_NOT_SUPPORTED when there's a `/* ==UserStyle==` instead
|
|
82
|
+
// - open marker but no matching close → UNTERMINATED_METADATA_BLOCK
|
|
83
|
+
// In every case we return leadingText = '', headerText = '', and
|
|
84
|
+
// bodyText = the whole source so callers always have something to
|
|
85
|
+
// display.
|
|
86
|
+
export function splitHeaderBody(source) {
|
|
87
|
+
source = stripLeadingBom(source);
|
|
88
|
+
const startMatch = BLOCK_START.exec(source);
|
|
89
|
+
if (!startMatch) {
|
|
90
|
+
const error = USERSTYLE_START.test(source) ? USERSTYLE_NOT_SUPPORTED : NO_METADATA_BLOCK;
|
|
91
|
+
return { leadingText: '', headerText: '', bodyText: source, error };
|
|
92
|
+
}
|
|
93
|
+
const headerStartLine = countLineBreaks(source.slice(0, startMatch.index)) + 1;
|
|
94
|
+
const afterStart = source.slice(startMatch.index + startMatch[0].length);
|
|
95
|
+
const endMatch = BLOCK_END.exec(afterStart);
|
|
96
|
+
if (!endMatch) {
|
|
97
|
+
return {
|
|
98
|
+
leadingText: '',
|
|
99
|
+
headerText: '',
|
|
100
|
+
bodyText: source,
|
|
101
|
+
error: UNTERMINATED_METADATA_BLOCK,
|
|
102
|
+
headerStartLine,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
const blockEnd = startMatch.index + startMatch[0].length + endMatch.index + endMatch[0].length;
|
|
106
|
+
// Skip a single trailing newline after the closing marker so bodyText
|
|
107
|
+
// doesn't start with a stray blank line.
|
|
108
|
+
let bodyStart = blockEnd;
|
|
109
|
+
if (source[bodyStart] === '\r')
|
|
110
|
+
bodyStart++;
|
|
111
|
+
if (source[bodyStart] === '\n')
|
|
112
|
+
bodyStart++;
|
|
113
|
+
return {
|
|
114
|
+
leadingText: source.slice(0, startMatch.index),
|
|
115
|
+
headerText: source.slice(startMatch.index, blockEnd),
|
|
116
|
+
bodyText: source.slice(bodyStart),
|
|
117
|
+
headerStartLine,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
// One metadata line: `// @tag[:locale][ value]`. The value group is
|
|
121
|
+
// `.*\S` so trailing whitespace is excluded; the whole value group is
|
|
122
|
+
// optional so flag tags like `@noframes` parse with value = "".
|
|
123
|
+
const TAG_LINE = /^[ \t]*\/\/[ \t]*@([A-Za-z][\w-]*)(?::([\w-]+))?(?:[ \t]+(.*\S))?[ \t]*$/;
|
|
124
|
+
// Reassemble the original on-disk source from the three parts
|
|
125
|
+
// produced by `splitHeaderBody`. The reassembly is line-for-line
|
|
126
|
+
// faithful so that an error reported on injected line N also points
|
|
127
|
+
// at line N of this reconstructed string (which is what the viewer
|
|
128
|
+
// shows in the main tab).
|
|
129
|
+
//
|
|
130
|
+
// The `'\n'` between `headerText` and `bodyText` restores the line
|
|
131
|
+
// break `splitHeaderBody` skipped past the closing marker; with no
|
|
132
|
+
// metadata block, both `leadingText` and `headerText` are empty so
|
|
133
|
+
// the body is returned verbatim.
|
|
134
|
+
export function joinFullSource(leadingText, headerText, bodyText) {
|
|
135
|
+
if (!headerText)
|
|
136
|
+
return leadingText + bodyText;
|
|
137
|
+
return leadingText + headerText + '\n' + bodyText;
|
|
138
|
+
}
|
|
139
|
+
// Parse the metadata block. Returns null if there is no
|
|
140
|
+
// `==UserScript==` / `==/UserScript==` pair.
|
|
141
|
+
export function parseHeader(source) {
|
|
142
|
+
source = stripLeadingBom(source);
|
|
143
|
+
const startMatch = BLOCK_START.exec(source);
|
|
144
|
+
if (!startMatch)
|
|
145
|
+
return null;
|
|
146
|
+
const afterStart = source.slice(startMatch.index + startMatch[0].length);
|
|
147
|
+
const endMatch = BLOCK_END.exec(afterStart);
|
|
148
|
+
if (!endMatch)
|
|
149
|
+
return null;
|
|
150
|
+
const block = afterStart.slice(0, endMatch.index);
|
|
151
|
+
const startLine = countLineBreaks(source.slice(0, startMatch.index)) + 1;
|
|
152
|
+
const tags = [];
|
|
153
|
+
// Split on every line-terminator shape — `\r\n` (DOS), `\n` (Unix),
|
|
154
|
+
// and bare `\r` (classic Mac). `splitHeaderBody`'s marker regexes
|
|
155
|
+
// stop at all three too, so we keep parity here.
|
|
156
|
+
//
|
|
157
|
+
// `block` begins with the terminator that ended the `==UserScript==`
|
|
158
|
+
// line, so element 0 is always the empty remainder of that line and
|
|
159
|
+
// element i is `startLine + i` — no off-by-one correction needed.
|
|
160
|
+
for (const [i, rawLine] of block.split(LINE_BREAK).entries()) {
|
|
161
|
+
const m = TAG_LINE.exec(rawLine);
|
|
162
|
+
if (!m)
|
|
163
|
+
continue;
|
|
164
|
+
const [, tag, locale, value] = m;
|
|
165
|
+
const entry = {
|
|
166
|
+
tag: tag.toLowerCase(),
|
|
167
|
+
value: value ?? '',
|
|
168
|
+
line: startLine + i,
|
|
169
|
+
};
|
|
170
|
+
if (locale)
|
|
171
|
+
entry.locale = locale;
|
|
172
|
+
tags.push(entry);
|
|
173
|
+
}
|
|
174
|
+
return { tags, startLine };
|
|
175
|
+
}
|
|
176
|
+
// First non-localized value for `tag`, or undefined.
|
|
177
|
+
export function getValue(header, tag) {
|
|
178
|
+
const t = tag.toLowerCase();
|
|
179
|
+
for (const e of header.tags) {
|
|
180
|
+
if (e.tag === t && e.locale === undefined)
|
|
181
|
+
return e.value;
|
|
182
|
+
}
|
|
183
|
+
return undefined;
|
|
184
|
+
}
|
|
185
|
+
// All non-localized values for `tag`, in source order.
|
|
186
|
+
export function getValues(header, tag) {
|
|
187
|
+
const t = tag.toLowerCase();
|
|
188
|
+
const out = [];
|
|
189
|
+
for (const e of header.tags) {
|
|
190
|
+
if (e.tag === t && e.locale === undefined)
|
|
191
|
+
out.push(e.value);
|
|
192
|
+
}
|
|
193
|
+
return out;
|
|
194
|
+
}
|
|
195
|
+
// Map of locale → value for tags like `@name:de`. Excludes the
|
|
196
|
+
// unlocalized form.
|
|
197
|
+
export function getLocalized(header, tag) {
|
|
198
|
+
const t = tag.toLowerCase();
|
|
199
|
+
const out = {};
|
|
200
|
+
for (const e of header.tags) {
|
|
201
|
+
if (e.tag === t && e.locale !== undefined)
|
|
202
|
+
out[e.locale] = e.value;
|
|
203
|
+
}
|
|
204
|
+
return out;
|
|
205
|
+
}
|
|
206
|
+
// True if the tag appears at all (useful for flag-style tags like
|
|
207
|
+
// `@noframes` or `@unwrap`).
|
|
208
|
+
export function hasTag(header, tag) {
|
|
209
|
+
const t = tag.toLowerCase();
|
|
210
|
+
return header.tags.some((e) => e.tag === t);
|
|
211
|
+
}
|
|
212
|
+
// The `@run-at` values that pick a point in the page load. Anything
|
|
213
|
+
// else (a typo) runs at `document-idle`: see `normalizeDeclaredRunAt`
|
|
214
|
+
// in injector.ts. The exception is `context-menu`, which makes the
|
|
215
|
+
// script manual instead (see `CONTEXT_MENU_RUN_AT`).
|
|
216
|
+
export const SUPPORTED_RUN_AT = [
|
|
217
|
+
'document-start',
|
|
218
|
+
'document-body',
|
|
219
|
+
'document-end',
|
|
220
|
+
'document-idle',
|
|
221
|
+
];
|
|
222
|
+
// The script's declared `@run-at` when it is one we don't honor, so
|
|
223
|
+
// the caller can say it runs at `document-idle` instead. Undefined when
|
|
224
|
+
// the tag is absent, blank, supported, or `context-menu`.
|
|
225
|
+
export function unsupportedRunAt(header) {
|
|
226
|
+
if (!header)
|
|
227
|
+
return undefined;
|
|
228
|
+
const value = (getValue(header, 'run-at') ?? '').trim();
|
|
229
|
+
if (value === '' || SUPPORTED_RUN_AT.includes(value.toLowerCase()))
|
|
230
|
+
return undefined;
|
|
231
|
+
if (value.toLowerCase() === CONTEXT_MENU_RUN_AT)
|
|
232
|
+
return undefined;
|
|
233
|
+
return value;
|
|
234
|
+
}
|
|
235
|
+
// Tampermonkey's `@run-at context-menu`: don't run on page load, run
|
|
236
|
+
// from a right-click menu item instead. We call these manual scripts:
|
|
237
|
+
// they match pages as usual, but run only when the person picks "Run
|
|
238
|
+
// this script" in the popup (or sm-dev fires it). See
|
|
239
|
+
// docs/manual-scripts.md.
|
|
240
|
+
export const CONTEXT_MENU_RUN_AT = 'context-menu';
|
|
241
|
+
// The command that runs a manual script now: first in its popup row,
|
|
242
|
+
// and in sm-dev's `menu`.
|
|
243
|
+
export const RUN_SCRIPT_LABEL = 'Run this script';
|
|
244
|
+
export function isContextMenuRunAt(header) {
|
|
245
|
+
if (!header)
|
|
246
|
+
return false;
|
|
247
|
+
return (getValue(header, 'run-at') ?? '').trim().toLowerCase() === CONTEXT_MENU_RUN_AT;
|
|
248
|
+
}
|