vite-userscript-plugin 1.6.6 → 1.7.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/README.md CHANGED
@@ -44,9 +44,9 @@ export default defineConfig((config) => {
44
44
  name,
45
45
  version,
46
46
  match: [
47
- 'https://example.com',
48
- 'https://example.org',
49
- 'https://example.edu'
47
+ 'https://example.com/',
48
+ 'https://example.org/',
49
+ 'https://example.edu/'
50
50
  ]
51
51
  },
52
52
  server: {
@@ -87,29 +87,34 @@ export default defineConfig((config) => {
87
87
 
88
88
  ```ts
89
89
  interface ServerConfig {
90
- /**
91
- * {@link https://github.com/sindresorhus/get-port}
92
- */
93
- port?: number;
94
- /**
95
- * @default false
96
- */
97
- open?: boolean;
90
+ /**
91
+ * {@link https://github.com/sindresorhus/get-port}
92
+ */
93
+ port?: number;
94
+
95
+ /**
96
+ * @default false
97
+ */
98
+ open?: boolean;
98
99
  }
99
100
 
100
101
  interface UserscriptPluginConfig {
101
- /**
102
- * Path of userscript entry.
103
- */
104
- entry: string;
105
- /**
106
- * Userscript header config.
107
- */
108
- header: HeaderConfig;
109
- /**
110
- * Server config.
111
- */
112
- server?: ServerConfig;
102
+ /**
103
+ * Path of userscript entry.
104
+ */
105
+ entry: string;
106
+
107
+ /**
108
+ * Userscript header config.
109
+ *
110
+ * @see https://www.tampermonkey.net/documentation.php
111
+ */
112
+ header: HeaderConfig;
113
+
114
+ /**
115
+ * Server config.
116
+ */
117
+ server?: ServerConfig;
113
118
  }
114
119
  ```
115
120
 
package/dist/index.cjs CHANGED
@@ -1,5 +1,5 @@
1
- "use strict";var re=Object.create;var u=Object.defineProperty;var ne=Object.getOwnPropertyDescriptor;var se=Object.getOwnPropertyNames;var oe=Object.getPrototypeOf,ie=Object.prototype.hasOwnProperty;var ae=(e,t,r)=>t in e?u(e,t,{enumerable:!0,configurable:!0,writable:!0,value:r}):e[t]=r;var le=(e,t)=>{for(var r in t)u(e,r,{get:t[r],enumerable:!0})},O=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of se(t))!ie.call(e,o)&&o!==r&&u(e,o,{get:()=>t[o],enumerable:!(n=ne(t,o))||n.enumerable});return e};var g=(e,t,r)=>(r=e!=null?re(oe(e)):{},O(t||!e||!e.__esModule?u(r,"default",{value:e,enumerable:!0}):r,e)),ce=e=>O(u({},"__esModule",{value:!0}),e);var d=(e,t,r)=>(ae(e,typeof t!="symbol"?t+"":t,r),r);var fe={};le(fe,{default:()=>I});module.exports=ce(fe);var p=require("fs"),K=require("http"),l=require("path"),A=require("url"),H=g(require("get-port"),1),N=g(require("open"),1),T=g(require("picocolors"),1),W=g(require("sanitize-filename"),1),q=g(require("serve-handler"),1),B=require("vite"),z=require("websocket");var h=class{constructor(t){this.config=t;d(this,"header",[]);d(this,"configKeys");d(this,"maxKeyLength");this.downloadMeta(),this.configKeys=Object.keys(this.config),this.maxKeyLength=Math.max(...this.configKeys.map(r=>r.length))+1}downloadMeta(){let{name:t,homepage:r,updateURL:n,downloadURL:o}=this.config;r&&!n&&!o&&(this.config.updateURL=new URL(`${t}.meta.js`,r).href,this.config.downloadURL=new URL(`${t}.user.js`,r).href)}addSpaces(t){return" ".repeat(this.maxKeyLength-t.length)}addMetadata(t,r){let n=typeof r=="boolean";n&&!r||(r=n?"":`${this.addSpaces(t)}${r}`,this.header.push(`// @${t}${r}`))}generate(){for(let[t,r]of Object.entries(this.config))if(Array.isArray(r))r.forEach(n=>this.addMetadata(t,n));else{if(r===void 0)continue;this.addMetadata(t,r)}return["// ==UserScript==",...this.header,"// ==/UserScript=="].join(`
2
- `)}};function E({entry:e,header:t}){return{build:{lib:{entry:e,name:t.name,formats:["iife"],fileName:()=>`${t.name}.js`},rollupOptions:{output:{extend:!0}}}}}var j="vite-userscript-plugin",U='console.warn("__STYLE__")',k=new RegExp(/\.(t|j)sx?$/),L=new RegExp(/\.(s[ac]|c|le)ss$/),pe=["setValue","getValue","deleteValue","listValues","setClipboard","addStyle","addElement","addValueChangeListener","removeValueChangeListener","registerMenuCommand","unregisterMenuCommand","download","getTab","getTabs","saveTab","openInTab","notification","getResourceURL","getResourceText","xmlhttpRequest","log","info"],me=["unsafeWindow","window.onurlchange","window.focus","window.close"],y=pe.map(e=>[`GM_${e}`,`GM.${e}`]).flat();y.push(...me);var V=require("vite");function M(e){return[...new Set(Array.isArray(e)?e:e?[e]:[])]}async function w({file:e,name:t,loader:r}){let{code:n}=await(0,V.transformWithEsbuild)(e,t,{loader:r,minify:!0,sourcemap:!1,legalComments:"none"});return n}function D(e){let t=[];for(let r of y)e.indexOf(r)!==-1&&t.push(r);return t}var G=class{constructor(){d(this,"styles",new Map)}async add(t,r){let n=await w({file:t,name:r,loader:"css"});return this.styles.set(r,n.replace(`
3
- `,"")),""}inject(){return this.styles.size?`GM_addStyle(\`${[...this.styles.values()].join("")}\`)`:void 0}merge(t){let r=[];for(let n of t){let o=this.styles.get(n);!o||r.push([n,o])}this.styles.clear(),r.forEach(n=>this.styles.set(...n))}},$=new G;var de={};function I(e){try{let t,r,n=null,o=(0,l.dirname)((0,A.fileURLToPath)(de.url)),C=(0,B.createLogger)("info",{prefix:`[${j}]`,allowClearScreen:!0}),x=(0,K.createServer)((s,i)=>(0,q.default)(s,i,{public:t.build.outDir})),J=z.server;return new J({httpServer:x}).on("request",s=>{n=s.accept(null,s.origin)}),{name:j,apply:"build",config(){return E(e)},async configResolved(s){t=s,r=s.build.watch??!1,e.entry=(0,l.resolve)(s.root,e.entry),e.header.name=(0,W.default)(e.header.name),Array.from(["match","require","include","exclude","resource","connect"]).forEach(i=>{let a=e.header[i];e.header[i]=M(a)}),e.server={port:await(0,H.default)(),open:!1,...e.server}},async transform(s,i){let a=s;return L.test(i)&&(a=await $.add(s,i)),i.includes(e.entry)&&(a=s+U),{code:a,map:null}},generateBundle(s,i){for(let a of Object.values(i)){if(a.type==="asset")continue;let m=Object.keys(a.modules).filter(S=>L.test(S));m.length&&$.merge(m)}},async writeBundle(s,i){let{open:a,port:m}=e.server,S=`${e.header.name}.user.js`,_=`${e.header.name}.proxy.user.js`,Y=`${e.header.name}.meta.js`;for(let[f]of Object.entries(i))if(k.test(f)){let v=t.root,b=t.build.outDir,P=(0,l.resolve)(v,b,f),Q=(0,l.resolve)(v,b,S),X=(0,l.resolve)(v,b,_),Z=(0,l.resolve)(v,b,Y),R=(0,l.resolve)(o,`ws-${e.header.name}.js`);try{let c=(0,p.readFileSync)(P,"utf8");if(c=c.replace(U,`${$.inject()}`),c=await w({file:c,name:f,loader:"js"}),e.header.grant=M(r?y:[...D(c),...e.header.grant??[]]),r){let ee=(0,p.readFileSync)((0,l.resolve)(o,"ws.js"),"utf8"),te=await w({file:ee.replace("__WS__",`ws://localhost:${m}`),name:R,loader:"js"});(0,p.writeFileSync)(R,te),(0,p.writeFileSync)(X,new h({...e.header,require:[...e.header.require,"file://"+R,"file://"+P]}).generate())}let F=new h(e.header).generate();(0,p.writeFileSync)(P,c),(0,p.writeFileSync)(Z,F),(0,p.writeFileSync)(Q,`${F}
1
+ "use strict";var J=Object.create;var v=Object.defineProperty;var Y=Object.getOwnPropertyDescriptor;var Q=Object.getOwnPropertyNames;var X=Object.getPrototypeOf,Z=Object.prototype.hasOwnProperty;var ee=(e,t)=>{for(var r in t)v(e,r,{get:t[r],enumerable:!0})},O=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of Q(t))!Z.call(e,o)&&o!==r&&v(e,o,{get:()=>t[o],enumerable:!(n=Y(t,o))||n.enumerable});return e};var x=(e,t,r)=>(r=e!=null?J(X(e)):{},O(t||!e||!e.__esModule?v(r,"default",{value:e,enumerable:!0}):r,e)),te=e=>O(v({},"__esModule",{value:!0}),e);var ie={};ee(ie,{default:()=>H});module.exports=te(ie);function L(e){return{name:"vite-userscript-plugin:config",config(){return{build:{lib:{entry:e.entry,name:e.header.name,formats:["iife"],fileName:()=>`${e.header.name}.js`},rollupOptions:{input:e.entry}}}}}}var G=require("http"),T=x(require("get-port"),1),_=x(require("open"),1),S=x(require("picocolors"),1),C=x(require("serve-handler"),1),F=require("vite"),E=require("websocket");function k(e){let t,r,n,o=null,a=(0,F.createLogger)("info",{prefix:"[vite-userscript-plugin]",allowClearScreen:!0}),i=(0,G.createServer)((s,u)=>(0,C.default)(s,u,{public:n.build.outDir})),l=E.server;return new l({httpServer:i}).on("request",s=>{o=s.accept(null,s.origin)}),{name:"vite-userscript-plugin:server",async configResolved(s){t=!!s.build.watch,n=s,r={port:await(0,T.default)(),open:!1,...e.server}},async writeBundle(){if(t&&!i.listening){let s=`http://localhost:${r.port}/${e.header.name}.proxy.user.js`;i.listen(r.port,()=>{a.clearScreen("info"),a.info(S.default.blue(`Running at: ${S.default.gray(s)}`))}),r.open&&await(0,_.default)(s)}else t||(i.close(),process.exit(0))},buildEnd(){t&&(a.clearScreen("info"),o&&o.sendUTF(JSON.stringify({message:"reload"})))}}}var m=require("fs"),c=require("path"),V=require("url");var d=class{constructor(t){this.config=t;this.addHomepageMeta(),this.maxKeyLength=Math.max(...Object.keys(this.config).map(r=>r.length))+1}header=[];maxKeyLength;addHomepageMeta(){let t=this.config.homepage??this.config.homepageURL;t&&(this.config.updateURL=new URL(`${this.config.name}.meta.js`,t).href,this.config.downloadURL=new URL(`${this.config.name}.user.js`,t).href)}addSpaces(t){return" ".repeat(this.maxKeyLength-t.length)}addMetadata(t,r){r=Array.isArray(r)?r.join(" "):r===!0?"":r,this.header.push(`// @${t}${this.addSpaces(t)}${r}`)}generate(){for(let[t,r]of Object.entries(this.config))if(Array.isArray(r))r.forEach(n=>this.addMetadata(t,n));else{if(r===void 0)continue;this.addMetadata(t,r)}return["// ==UserScript==",...this.header,"// ==/UserScript=="].join(`
2
+ `)}};var $='console.warn("__STYLE__")',A=new RegExp(/\.(t|j)sx?$/),U=new RegExp(/\.(s[ac]|c|le)ss$/),re=["setValue","getValue","deleteValue","listValues","setClipboard","addStyle","addElement","addValueChangeListener","removeValueChangeListener","registerMenuCommand","unregisterMenuCommand","download","getTab","getTabs","saveTab","openInTab","notification","getResourceURL","getResourceText","xmlhttpRequest","log","info"],ne=["unsafeWindow","window.onurlchange","window.focus","window.close"],g=re.map(e=>[`GM_${e}`,`GM.${e}`]).flat();g.push(...ne);var B=require("vite");function R(e){return[...new Set(Array.isArray(e)?e:e?[e]:[])]}async function y({file:e,name:t,loader:r}){let{code:n}=await(0,B.transformWithEsbuild)(e,t,{loader:r,minify:!0,sourcemap:!1,legalComments:"none"});return n}function D(e){let t=[];for(let r of g)e.indexOf(r)!==-1&&t.push(r);return t}var P=class{styles=new Map;async add(t,r){let n=await y({file:t,name:r,loader:"css"});return this.styles.set(r,n.replace(`
3
+ `,"")),""}inject(){return this.styles.size?`GM_addStyle(\`${[...this.styles.values()].join("")}\`)`:void 0}merge(t){let r=[];for(let n of t){let o=this.styles.get(n);o&&r.push([n,o])}this.styles.clear(),r.forEach(n=>this.styles.set(...n))}};var oe={};function W(e){let t,r,n=new P,o=(0,c.dirname)((0,V.fileURLToPath)(oe.url));return{name:"vite-userscript-plugin",apply:"build",async configResolved(a){r=a,t=!!a.build.watch,e.entry=(0,c.resolve)(a.root,e.entry),Array.from(["match","require","include","exclude","resource","connect"]).forEach(i=>{let l=e.header[i];e.header[i]=R(l)})},async transform(a,i){let l=a;return U.test(i)&&(l=await n.add(a,i)),i.includes(e.entry)&&(l=a+$),{code:l,map:null}},generateBundle(a,i){for(let l of Object.values(i)){if(l.type==="asset")continue;let f=Object.keys(l.modules).filter(s=>U.test(s));f.length&&n.merge(f)}},async writeBundle(a,i){let l=`${e.header.name}.user.js`,f=`${e.header.name}.proxy.user.js`,s=`${e.header.name}.meta.js`;for(let[u]of Object.entries(i))if(A.test(u)){let h=r.root,w=r.build.outDir,b=(0,c.resolve)(h,w,u),q=(0,c.resolve)(h,w,l),K=(0,c.resolve)(h,w,f),N=(0,c.resolve)(h,w,s),j=(0,c.resolve)(o,`ws-${e.header.name}.js`);try{let p=(0,m.readFileSync)(b,"utf8");if(p=p.replace($,`${n.inject()}`),p=await y({file:p,name:u,loader:"js"}),e.header.grant=R(t?g:[...D(p),...e.header.grant??[]]),t){let z=(0,m.readFileSync)((0,c.resolve)(o,"ws.js"),"utf8"),I=await y({file:z.replace("__WS__",`ws://localhost:${e.server.port}`),name:j,loader:"js"});(0,m.writeFileSync)(j,I),(0,m.writeFileSync)(K,new d({...e.header,require:[...e.header.require,"file://"+j,"file://"+b]}).generate())}let M=new d(e.header).generate();(0,m.writeFileSync)(b,p),(0,m.writeFileSync)(N,M),(0,m.writeFileSync)(q,`${M}
4
4
 
5
- ${c}`)}catch(c){console.log(c)}}if(r&&!x.listening){let f=`http://localhost:${m}`;x.listen(m,()=>{C.clearScreen("info"),C.info(T.default.blue(`Running at: ${T.default.gray(f)}`))}),a&&await(0,N.default)(`${f}/${_}`)}else r||(x.close(),process.exit(0))},buildEnd(){r&&(C.clearScreen("info"),n&&n.sendUTF(JSON.stringify({message:"reload"})))}}}catch(t){return console.error(t),{name:j}}}0&&(module.exports={});
5
+ ${p}`)}catch(p){console.log(p)}}}}}function H(e){return[L(e),W(e),k(e)]}0&&(module.exports={});
package/dist/index.d.ts CHANGED
@@ -8,187 +8,136 @@ type GMLiterals<T extends string> = [`GM_${T}` | `GM.${T}`];
8
8
  type GMWindow = typeof GMwindow[number];
9
9
  type Grants = GMWindow | GMLiterals<typeof GM[number]>[number];
10
10
  type HeaderConfig = {
11
- [property: string]: string | boolean | number | string[] | undefined;
11
+ [property: string]: any;
12
12
  /**
13
- * The name of the script.
14
- * Internationalization is done by adding an appendix naming the locale.
13
+ * @see https://www.tampermonkey.net/documentation.php#meta:name
15
14
  */
16
15
  name: string;
17
16
  /**
18
- * Version of the script,
19
- * it can be used to check if a script has new versions. It is composed
20
- * of several parts, joined by `.` Each part must start with numbers,
21
- * and can be followed by alphabetic characters.
17
+ * @see https://www.tampermonkey.net/documentation.php#meta:namespace
18
+ */
19
+ namespace?: string;
20
+ /**
21
+ * @see https://www.tampermonkey.net/documentation.php#meta:copyright
22
+ */
23
+ copyright?: string;
24
+ /**
25
+ * @see https://www.tampermonkey.net/documentation.php#meta:version
22
26
  */
23
27
  version: string;
24
28
  /**
25
- * A brief summary to describe the script.
29
+ * @see https://www.tampermonkey.net/documentation.php#meta:description
26
30
  */
27
31
  description?: string;
28
32
  /**
29
- * The scripts author.
33
+ * @see https://www.tampermonkey.net/documentation.php#meta:icon
30
34
  */
31
- author?: string;
35
+ icon?: string;
32
36
  /**
33
- * The script license.
37
+ * @see https://www.tampermonkey.net/documentation.php#meta:icon
34
38
  */
35
- license?: string;
39
+ iconURL?: string;
36
40
  /**
37
- * The combination of `@namespace` and `@name` is the unique identifier for
38
- * a userscript. `@namespace` can be any string, for example the homepage
39
- * of a group of userscripts by the same author. If not provided
40
- * the `@namespace` falls back to an empty string ('').
41
+ * @see https://www.tampermonkey.net/documentation.php#meta:icon
41
42
  */
42
- namespace?: string;
43
+ defaulticon?: string;
44
+ /**
45
+ * @see https://www.tampermonkey.net/documentation.php#meta:icon64
46
+ */
47
+ icon64?: string;
48
+ /**
49
+ * @see https://www.tampermonkey.net/documentation.php#meta:icon64
50
+ */
51
+ icon64URL?: string;
52
+ /**
53
+ * @see https://www.tampermonkey.net/documentation.php#meta:grant
54
+ */
55
+ grant?: Grants[];
43
56
  /**
44
- * The authors homepage that is used at the options page to link from
45
- * the scripts name to the given page. Please note that if the `@namespace`
46
- * tag starts with `https://` its content will be used for this too.
57
+ * @see https://www.tampermonkey.net/documentation.php#meta:author
58
+ */
59
+ author?: string;
60
+ /**
61
+ * @see https://www.tampermonkey.net/documentation.php#meta:homepage
47
62
  */
48
63
  homepage?: string;
49
64
  /**
50
- * An update URL for the userscript.
51
- * Note:
52
- * - a `@version` tag is required to make update checks work.
65
+ * @see https://www.tampermonkey.net/documentation.php#meta:homepage
53
66
  */
54
- updateURL?: string;
67
+ homepageURL?: string;
55
68
  /**
56
- * Defines the URL where the script will be downloaded from when an update was
57
- * detected. If the value none is used, then no update check will be done.
69
+ * @see https://www.tampermonkey.net/documentation.php#meta:homepage
58
70
  */
59
- downloadURL?: string;
71
+ website?: string;
60
72
  /**
61
- * Defines the URL where the user can report issues and get personal support.
73
+ * @see https://www.tampermonkey.net/documentation.php#meta:homepage
62
74
  */
63
- supportURL?: string;
75
+ source?: string;
64
76
  /**
65
- * Specify an icon for the script. Almost any image will work,
66
- * but a 32x32 pixel size is best. This value may be specified relative
67
- * to the URL the script itself is downloaded from.
77
+ * @see https://www.tampermonkey.net/documentation.phpmeta:antifeature
68
78
  */
69
- icon?: string;
70
- icon64?: string;
79
+ antifeature?: [type: string, description: string][];
71
80
  /**
72
- * Each `@include` and `@exclude` rule can be one of the following:
73
- * - a normal string
74
- * > If the string does not start or end with a slash (/),
75
- * > it will be used as a normal string.
76
- * > If there are wildcards (*), each of them matches any characters.
77
- * > e.g. https://www.google.com/* matches the following:
78
- * - https://www.google.com/
79
- * - https://www.google.com/any/subview
80
- * > but not the following:
81
- * - http://www.google.com/
82
- * - https://www.google.com.hk/
83
- * > If there is no wildcard in the string, the rule matches the entire URL.
84
- * > e.g. https://www.google.com/ matches only https://www.google.com/
85
- * > but not https://www.google.com/any/subview.
86
- * > The host part accepts .tld to match top level domain suffix.
87
- * > e.g. https://www.google.tld/ matches both https://www.google.com/
88
- * > and https://www.google.co.jp/.
89
- *
90
- * - a regular expression
91
- * > If the string starts and ends with a slash (/),
92
- * > it will be compiled as a regular expression.
93
- * > e.g. /\.google\.com[\.\/]/ matches the following:
94
- * - https://www.google.com/,
95
- * - https://www.google.com/any/subview
96
- * - http://www.google.com/
97
- * - https://www.google.com.hk/
81
+ * @see https://www.tampermonkey.net/documentation.php#meta:require
82
+ */
83
+ require?: string[] | string;
84
+ /**
85
+ * @see https://www.tampermonkey.net/documentation.php#meta:resource
86
+ */
87
+ resource?: [key: string, value: string][];
88
+ /**
89
+ * @see https://www.tampermonkey.net/documentation.php#meta:include
98
90
  */
99
91
  include?: string[] | string;
100
- exclude?: string[] | string;
101
92
  /**
102
- * More or less equal to the `@include` tag.
103
- * You can get more information
104
- * [here](https://developer.chrome.com/docs/extensions/mv2/match_patterns/).
105
- *
106
- * Note:
107
- * - The `<all_urls>` statement is not yet supported and the scheme part also
108
- * accepts `http*://`.
93
+ * @see https://www.tampermonkey.net/documentation.php#meta:match
94
+ * @see https://violentmonkey.github.io/api/metadata-block/#match--exclude-match
109
95
  */
110
96
  match: string[] | string;
111
97
  /**
112
- * Points to a JavaScript file that is loaded and executed before the script
113
- * itself starts running.
114
- *
115
- * Note:
116
- * - The scripts loaded via `@require` and their "use strict" statements
117
- * might influence the userscript's strict mode!
98
+ * @see https://violentmonkey.github.io/api/metadata-block/#match--exclude-match
118
99
  */
119
- require?: string[] | string;
100
+ 'exclude-match'?: string[] | string;
120
101
  /**
121
- * Preloads resources that can by accessed
122
- * via `GM_getResourceURL` and `GM_getResourceText` by the script.
102
+ * @see https://www.tampermonkey.net/documentation.php#meta:exclude
123
103
  */
124
- resource?: string[] | string;
104
+ exclude?: string[] | string;
125
105
  /**
126
- * This tag defines the domains (no top-level domains) including subdomains
127
- * which are allowed to be retrieved by `GM_xmlhttpRequest`
128
- *
129
- * - domains like tampermonkey.net (this will also allow all sub-domains)
130
- * - sub-domains i.e. safari.tampermonkey.net
131
- * - self to whitelist the domain the script is currently running at
132
- * - localhost to access the localhost
133
- * - 1.2.3.4 to connect to an IP address
134
- *
135
- * If it's not possible to declare all domains a userscript might connect
136
- * to then it's a good practice to do the following: ***Declare all known or
137
- * at least all common domains*** that might be connected by the script.
138
- * This way the confirmation dialog can be avoided for most of the users.
139
- *
140
- * Additionally add `@connect *` to the script. By doing so Tampermonkey will
141
- * still ask the user whether the next connection to a not mentioned domain
142
- * is allowed, but also ***offer a "Always allow all domains" button***.
143
- * If the user clicks at this button then all future requestswill
144
- * be permitted automatically.
106
+ * @see https://www.tampermonkey.net/documentation.php#meta:run_at
107
+ */
108
+ 'run-at'?: RunAt;
109
+ /**
110
+ * @see https://www.tampermonkey.net/documentation.phpmeta:sandbox
111
+ */
112
+ sandbox?: string;
113
+ /**
114
+ * @see https://www.tampermonkey.net/documentation.php#meta:connect
145
115
  */
146
116
  connect?: string[] | string;
147
117
  /**
148
- * This tag makes the script running on the main pages, but not at iframes.
149
- * @default false
118
+ * @see https://www.tampermonkey.net/documentation.php#meta:noframes
150
119
  */
151
120
  noframes?: boolean;
152
121
  /**
153
- * `@grant` is used to whitelist GM_* functions, the `unsafeWindow` object and
154
- * some powerful window functions. If no `@grant` tag is given TM guesses
155
- * the scripts needs.
122
+ * @see https://www.tampermonkey.net/documentation.php#meta:updateURL
156
123
  */
157
- grant?: Grants[];
124
+ updateURL?: string;
158
125
  /**
159
- * Defines the moment the script is injected. In opposition to other script
160
- * handlers, `@run-at` defines the first possible moment a script wants to
161
- * run. This means it may happen, that a script that uses the `@require` tag
162
- * may be executed after the document is already loaded, cause fetching the
163
- * required script took that long. Anyhow, all `DOMNodeInserted` and
164
- * `DOMContentLoaded` events that happended after the given injection
165
- * moment are cached and delivered to the script when it is injected.
166
- *
167
- * - `document-start`
168
- * The script will be injected as fast as possible.
169
- *
170
- * - `document-body`
171
- * The script will be injected if the body element exists.
172
- *
173
- * - `document-end`
174
- * The script will be injected when or after the `DOMContentLoaded` event
175
- * was dispatched.
176
- *
177
- * - `document-idle`
178
- * The script will be injected after the DOMContentLoaded event was
179
- * dispatched. This is the default value if no `@run-at` tag is given.
180
- *
181
- * - `context-menu`
182
- * The script will be injected if it is clicked at the browser context menu
183
- * (desktop Chrome-based browsers only).
184
- *
185
- * Note:
186
- * - all `@include` and `@exclude` statements will be ignored if this value
187
- * is used, but this may change in the future.
188
- *
189
- * @default 'document-idle'
126
+ * @see https://www.tampermonkey.net/documentation.php#meta:downloadURL
190
127
  */
191
- 'run-at'?: RunAt;
128
+ downloadURL?: string;
129
+ /**
130
+ * @see https://www.tampermonkey.net/documentation.php#meta:supportURL
131
+ */
132
+ supportURL?: string;
133
+ /**
134
+ * @see https://www.tampermonkey.net/documentation.php#meta:webRequest
135
+ */
136
+ webRequest?: string[];
137
+ /**
138
+ * @see https://www.tampermonkey.net/documentation.php#meta:unwrap
139
+ */
140
+ unwrap?: boolean;
192
141
  };
193
142
  interface ServerConfig {
194
143
  /**
@@ -207,6 +156,8 @@ interface UserscriptPluginConfig {
207
156
  entry: string;
208
157
  /**
209
158
  * Userscript header config.
159
+ *
160
+ * @see https://www.tampermonkey.net/documentation.php
210
161
  */
211
162
  header: HeaderConfig;
212
163
  /**
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
- var W=Object.defineProperty;var q=(e,r,t)=>r in e?W(e,r,{enumerable:!0,configurable:!0,writable:!0,value:t}):e[r]=t;var f=(e,r,t)=>(q(e,typeof r!="symbol"?r+"":r,t),t);import{readFileSync as O,writeFileSync as h}from"fs";import{createServer as J}from"http";import{dirname as Y,resolve as c}from"path";import{fileURLToPath as Q}from"url";import X from"get-port";import Z from"open";import E from"picocolors";import ee from"sanitize-filename";import te from"serve-handler";import{createLogger as re}from"vite";import{server as ne}from"websocket";var d=class{constructor(r){this.config=r;f(this,"header",[]);f(this,"configKeys");f(this,"maxKeyLength");this.downloadMeta(),this.configKeys=Object.keys(this.config),this.maxKeyLength=Math.max(...this.configKeys.map(t=>t.length))+1}downloadMeta(){let{name:r,homepage:t,updateURL:n,downloadURL:l}=this.config;t&&!n&&!l&&(this.config.updateURL=new URL(`${r}.meta.js`,t).href,this.config.downloadURL=new URL(`${r}.user.js`,t).href)}addSpaces(r){return" ".repeat(this.maxKeyLength-r.length)}addMetadata(r,t){let n=typeof t=="boolean";n&&!t||(t=n?"":`${this.addSpaces(r)}${t}`,this.header.push(`// @${r}${t}`))}generate(){for(let[r,t]of Object.entries(this.config))if(Array.isArray(t))t.forEach(n=>this.addMetadata(r,n));else{if(t===void 0)continue;this.addMetadata(r,t)}return["// ==UserScript==",...this.header,"// ==/UserScript=="].join(`
2
- `)}};function T({entry:e,header:r}){return{build:{lib:{entry:e,name:r.name,formats:["iife"],fileName:()=>`${r.name}.js`},rollupOptions:{output:{extend:!0}}}}}var v="vite-userscript-plugin",P='console.warn("__STYLE__")',_=new RegExp(/\.(t|j)sx?$/),R=new RegExp(/\.(s[ac]|c|le)ss$/),B=["setValue","getValue","deleteValue","listValues","setClipboard","addStyle","addElement","addValueChangeListener","removeValueChangeListener","registerMenuCommand","unregisterMenuCommand","download","getTab","getTabs","saveTab","openInTab","notification","getResourceURL","getResourceText","xmlhttpRequest","log","info"],z=["unsafeWindow","window.onurlchange","window.focus","window.close"],u=B.map(e=>[`GM_${e}`,`GM.${e}`]).flat();u.push(...z);import{transformWithEsbuild as I}from"vite";function U(e){return[...new Set(Array.isArray(e)?e:e?[e]:[])]}async function g({file:e,name:r,loader:t}){let{code:n}=await I(e,r,{loader:t,minify:!0,sourcemap:!1,legalComments:"none"});return n}function F(e){let r=[];for(let t of u)e.indexOf(t)!==-1&&r.push(t);return r}var L=class{constructor(){f(this,"styles",new Map)}async add(r,t){let n=await g({file:r,name:t,loader:"css"});return this.styles.set(t,n.replace(`
3
- `,"")),""}inject(){return this.styles.size?`GM_addStyle(\`${[...this.styles.values()].join("")}\`)`:void 0}merge(r){let t=[];for(let n of r){let l=this.styles.get(n);!l||t.push([n,l])}this.styles.clear(),t.forEach(n=>this.styles.set(...n))}},b=new L;function se(e){try{let r,t,n=null,l=Y(Q(import.meta.url)),j=re("info",{prefix:`[${v}]`,allowClearScreen:!0}),y=J((s,o)=>te(s,o,{public:r.build.outDir})),k=ne;return new k({httpServer:y}).on("request",s=>{n=s.accept(null,s.origin)}),{name:v,apply:"build",config(){return T(e)},async configResolved(s){r=s,t=s.build.watch??!1,e.entry=c(s.root,e.entry),e.header.name=ee(e.header.name),Array.from(["match","require","include","exclude","resource","connect"]).forEach(o=>{let i=e.header[o];e.header[o]=U(i)}),e.server={port:await X(),open:!1,...e.server}},async transform(s,o){let i=s;return R.test(o)&&(i=await b.add(s,o)),o.includes(e.entry)&&(i=s+P),{code:i,map:null}},generateBundle(s,o){for(let i of Object.values(o)){if(i.type==="asset")continue;let p=Object.keys(i.modules).filter($=>R.test($));p.length&&b.merge(p)}},async writeBundle(s,o){let{open:i,port:p}=e.server,$=`${e.header.name}.user.js`,M=`${e.header.name}.proxy.user.js`,V=`${e.header.name}.meta.js`;for(let[m]of Object.entries(o))if(_.test(m)){let w=r.root,x=r.build.outDir,C=c(w,x,m),D=c(w,x,$),K=c(w,x,M),A=c(w,x,V),S=c(l,`ws-${e.header.name}.js`);try{let a=O(C,"utf8");if(a=a.replace(P,`${b.inject()}`),a=await g({file:a,name:m,loader:"js"}),e.header.grant=U(t?u:[...F(a),...e.header.grant??[]]),t){let H=O(c(l,"ws.js"),"utf8"),N=await g({file:H.replace("__WS__",`ws://localhost:${p}`),name:S,loader:"js"});h(S,N),h(K,new d({...e.header,require:[...e.header.require,"file://"+S,"file://"+C]}).generate())}let G=new d(e.header).generate();h(C,a),h(A,G),h(D,`${G}
1
+ function U(e){return{name:"vite-userscript-plugin:config",config(){return{build:{lib:{entry:e.entry,name:e.header.name,formats:["iife"],fileName:()=>`${e.header.name}.js`},rollupOptions:{input:e.entry}}}}}}import{createServer as A}from"http";import B from"get-port";import D from"open";import R from"picocolors";import V from"serve-handler";import{createLogger as W}from"vite";import{server as H}from"websocket";function M(e){let r,t,n,l=null,s=W("info",{prefix:"[vite-userscript-plugin]",allowClearScreen:!0}),o=A((i,f)=>V(i,f,{public:n.build.outDir})),a=H;return new a({httpServer:o}).on("request",i=>{l=i.accept(null,i.origin)}),{name:"vite-userscript-plugin:server",async configResolved(i){r=!!i.build.watch,n=i,t={port:await B(),open:!1,...e.server}},async writeBundle(){if(r&&!o.listening){let i=`http://localhost:${t.port}/${e.header.name}.proxy.user.js`;o.listen(t.port,()=>{s.clearScreen("info"),s.info(R.blue(`Running at: ${R.gray(i)}`))}),t.open&&await D(i)}else r||(o.close(),process.exit(0))},buildEnd(){r&&(s.clearScreen("info"),l&&l.sendUTF(JSON.stringify({message:"reload"})))}}}import{readFileSync as G,writeFileSync as y}from"fs";import{dirname as z,resolve as p}from"path";import{fileURLToPath as I}from"url";var u=class{constructor(r){this.config=r;this.addHomepageMeta(),this.maxKeyLength=Math.max(...Object.keys(this.config).map(t=>t.length))+1}header=[];maxKeyLength;addHomepageMeta(){let r=this.config.homepage??this.config.homepageURL;r&&(this.config.updateURL=new URL(`${this.config.name}.meta.js`,r).href,this.config.downloadURL=new URL(`${this.config.name}.user.js`,r).href)}addSpaces(r){return" ".repeat(this.maxKeyLength-r.length)}addMetadata(r,t){t=Array.isArray(t)?t.join(" "):t===!0?"":t,this.header.push(`// @${r}${this.addSpaces(r)}${t}`)}generate(){for(let[r,t]of Object.entries(this.config))if(Array.isArray(t))t.forEach(n=>this.addMetadata(r,n));else{if(t===void 0)continue;this.addMetadata(r,t)}return["// ==UserScript==",...this.header,"// ==/UserScript=="].join(`
2
+ `)}};var b='console.warn("__STYLE__")',O=new RegExp(/\.(t|j)sx?$/),j=new RegExp(/\.(s[ac]|c|le)ss$/),q=["setValue","getValue","deleteValue","listValues","setClipboard","addStyle","addElement","addValueChangeListener","removeValueChangeListener","registerMenuCommand","unregisterMenuCommand","download","getTab","getTabs","saveTab","openInTab","notification","getResourceURL","getResourceText","xmlhttpRequest","log","info"],K=["unsafeWindow","window.onurlchange","window.focus","window.close"],d=q.map(e=>[`GM_${e}`,`GM.${e}`]).flat();d.push(...K);import{transformWithEsbuild as N}from"vite";function S(e){return[...new Set(Array.isArray(e)?e:e?[e]:[])]}async function g({file:e,name:r,loader:t}){let{code:n}=await N(e,r,{loader:t,minify:!0,sourcemap:!1,legalComments:"none"});return n}function L(e){let r=[];for(let t of d)e.indexOf(t)!==-1&&r.push(t);return r}var v=class{styles=new Map;async add(r,t){let n=await g({file:r,name:t,loader:"css"});return this.styles.set(t,n.replace(`
3
+ `,"")),""}inject(){return this.styles.size?`GM_addStyle(\`${[...this.styles.values()].join("")}\`)`:void 0}merge(r){let t=[];for(let n of r){let l=this.styles.get(n);l&&t.push([n,l])}this.styles.clear(),t.forEach(n=>this.styles.set(...n))}};function T(e){let r,t,n=new v,l=z(I(import.meta.url));return{name:"vite-userscript-plugin",apply:"build",async configResolved(s){t=s,r=!!s.build.watch,e.entry=p(s.root,e.entry),Array.from(["match","require","include","exclude","resource","connect"]).forEach(o=>{let a=e.header[o];e.header[o]=S(a)})},async transform(s,o){let a=s;return j.test(o)&&(a=await n.add(s,o)),o.includes(e.entry)&&(a=s+b),{code:a,map:null}},generateBundle(s,o){for(let a of Object.values(o)){if(a.type==="asset")continue;let m=Object.keys(a.modules).filter(i=>j.test(i));m.length&&n.merge(m)}},async writeBundle(s,o){let a=`${e.header.name}.user.js`,m=`${e.header.name}.proxy.user.js`,i=`${e.header.name}.meta.js`;for(let[f]of Object.entries(o))if(O.test(f)){let h=t.root,w=t.build.outDir,x=p(h,w,f),_=p(h,w,a),C=p(h,w,m),F=p(h,w,i),P=p(l,`ws-${e.header.name}.js`);try{let c=G(x,"utf8");if(c=c.replace(b,`${n.inject()}`),c=await g({file:c,name:f,loader:"js"}),e.header.grant=S(r?d:[...L(c),...e.header.grant??[]]),r){let E=G(p(l,"ws.js"),"utf8"),k=await g({file:E.replace("__WS__",`ws://localhost:${e.server.port}`),name:P,loader:"js"});y(P,k),y(C,new u({...e.header,require:[...e.header.require,"file://"+P,"file://"+x]}).generate())}let $=new u(e.header).generate();y(x,c),y(F,$),y(_,`${$}
4
4
 
5
- ${a}`)}catch(a){console.log(a)}}if(t&&!y.listening){let m=`http://localhost:${p}`;y.listen(p,()=>{j.clearScreen("info"),j.info(E.blue(`Running at: ${E.gray(m)}`))}),i&&await Z(`${m}/${M}`)}else t||(y.close(),process.exit(0))},buildEnd(){t&&(j.clearScreen("info"),n&&n.sendUTF(JSON.stringify({message:"reload"})))}}}catch(r){return console.error(r),{name:v}}}export{se as default};
5
+ ${c}`)}catch(c){console.log(c)}}}}}function J(e){return[U(e),T(e),M(e)]}export{J as default};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vite-userscript-plugin",
3
- "version": "1.6.6",
3
+ "version": "1.7.0",
4
4
  "type": "module",
5
5
  "types": "./dist/index.d.ts",
6
6
  "main": "./dist/index.cjs",
@@ -13,6 +13,16 @@
13
13
  "dist",
14
14
  "types"
15
15
  ],
16
+ "scripts": {
17
+ "dev": "tsup --watch",
18
+ "build": "tsup",
19
+ "test": "vitest",
20
+ "test:ui": "vitest --ui --watch",
21
+ "dev:examples": "turbo run dev --filter='./examples/*'",
22
+ "build:examples": "turbo run build --filter='./examples/*'",
23
+ "format": "prettier --write --ignore-unknown **",
24
+ "prepublishOnly": "pnpm build"
25
+ },
16
26
  "repository": {
17
27
  "type": "git",
18
28
  "url": "git+https://github.com/crashmax-dev/vite-userscript-plugin.git"
@@ -35,37 +45,27 @@
35
45
  "url": "https://github.com/crashmax-dev/vite-userscript-plugin/issues"
36
46
  },
37
47
  "dependencies": {
38
- "get-port": "^6.1.2",
39
- "open": "^8.4.0",
40
- "picocolors": "^1.0.0",
41
- "sanitize-filename": "^1.6.3",
42
- "serve-handler": "^6.1.5",
43
- "websocket": "^1.0.34"
48
+ "get-port": "6.1.2",
49
+ "open": "8.4.2",
50
+ "picocolors": "1.0.0",
51
+ "serve-handler": "6.1.5",
52
+ "websocket": "1.0.34"
44
53
  },
45
54
  "devDependencies": {
46
- "@crashmax/prettier-config": "^2.1.0",
47
- "@crashmax/tsconfig": "^1.0.2",
48
- "@types/node": "^18.11.9",
49
- "@types/serve-handler": "^6.1.1",
50
- "@types/websocket": "^1.0.5",
51
- "@vitest/ui": "^0.25.3",
52
- "tsup": "^6.5.0",
53
- "turbo": "^1.6.3",
54
- "typescript": "^4.9.3",
55
- "vite": "^3.2.4",
56
- "vite-plugin-dts": "^1.7.1",
57
- "vitest": "^0.25.3"
55
+ "@crashmax/prettier-config": "3.2.1",
56
+ "@crashmax/tsconfig": "2.0.1",
57
+ "@types/node": "18.15.3",
58
+ "@types/serve-handler": "6.1.1",
59
+ "@types/websocket": "1.0.5",
60
+ "@vitest/ui": "0.29.2",
61
+ "tsup": "6.6.3",
62
+ "turbo": "1.8.3",
63
+ "typescript": "4.9.5",
64
+ "vite": "4.1.4",
65
+ "vite-plugin-dts": "2.1.0",
66
+ "vitest": "0.29.2"
58
67
  },
59
68
  "peerDependencies": {
60
- "vite": ">=2.9.0"
61
- },
62
- "scripts": {
63
- "dev": "tsup --watch",
64
- "build": "tsup",
65
- "test": "vitest",
66
- "test:ui": "vitest --ui --watch",
67
- "dev:examples": "turbo run dev --filter='./examples/*'",
68
- "build:examples": "turbo run build --filter='./examples/*'",
69
- "format": "prettier --write --ignore-unknown **"
69
+ "vite": ">=3.0.0"
70
70
  }
71
- }
71
+ }
@@ -1,314 +1,246 @@
1
- // Type definitions for Greasemonkey 4.x
1
+ // Type definitions for Greasemonkey 3.x
2
2
  // Project: http://www.greasespot.net/
3
3
  // Definitions by: Kota Saito <https://github.com/kotas>
4
- // Nikolay Borzov <https://github.com/nikolay-borzov>
5
4
  // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
6
5
 
7
- // This definition is based on the API reference of Greasemonkey
8
- // https://wiki.greasespot.net/Greasemonkey_Manual:API
9
- // TypeScript Version: 3.2
6
+ // This definition is based on the API reference of Greasemonkey.
7
+ // http://wiki.greasespot.net/Greasemonkey_Manual:API
10
8
 
11
- declare namespace GM {
12
- interface ScriptInfo {
13
- /** Possibly empty string. */
9
+ ////////////////
10
+ // Global variable
11
+ ////////////////
12
+
13
+ /**
14
+ * Window object of the content page where the user script is running on.
15
+ * @see {@link http://wiki.greasespot.net/UnsafeWindow}
16
+ */
17
+ declare var unsafeWindow: Window
18
+
19
+ /**
20
+ * Meta data about the running user script.
21
+ * @see {@link http://wiki.greasespot.net/GM_info}
22
+ */
23
+ declare var GM_info: {
24
+ script: {
14
25
  description: string
15
26
  excludes: string[]
16
27
  includes: string[]
17
28
  matches: string[]
18
29
  name: string
19
- /** Possibly empty string. */
20
30
  namespace: string
21
- /**
22
- * An object keyed by resource name.
23
- * Each value is an object with keys `name` and `mimetype` and `url`
24
- * with string values.
25
- */
26
- resources: {
27
- [resourceName: string]: {
28
- name: string
29
- mimetype: string
30
- url: string
31
- }
32
- }
33
- /** @default 'end' */
34
- runAt: 'start' | 'end' | 'idle'
35
- uuid: string
36
- /** Possibly empty string. */
31
+ resources: Object
32
+ 'run-at': string
33
+ unwrap: boolean
37
34
  version: string
38
35
  }
36
+ scriptMetaStr: string
37
+ scriptWillUpdate: boolean
38
+ version: string
39
+ }
39
40
 
40
- type Value = string | boolean | number
41
-
42
- interface Response<TContext> {
43
- readonly responseHeaders: string
44
- readonly finalUrl: string
45
- /** The same object passed into the original request */
46
- readonly context?: TContext | undefined
47
-
48
- readonly readyState: 1 | 2 | 3 | 4
49
- readonly response: any
50
- readonly responseText: string
51
- readonly responseXML: Document | false
52
- readonly status: number
53
- readonly statusText: string
54
- }
41
+ ////////////////
42
+ // Values
43
+ ////////////////
55
44
 
56
- interface ProgressResponse<TContext> extends Response<TContext> {
57
- lengthComputable: boolean
58
- loaded: number
59
- total: number
60
- }
45
+ /**
46
+ * Deletes an existing name / value pair from the script storage.
47
+ * @param name a name of the pair to delete.
48
+ * @see {@link http://wiki.greasespot.net/GM_deleteValue}
49
+ */
50
+ declare function GM_deleteValue(name: string): void
61
51
 
62
- interface Request<TContext = any> {
63
- // Fields
52
+ /**
53
+ * Retrieves a value from the script storage.
54
+ * @param name a name to retrieve.
55
+ * @param defaultValue a value to be returned when the name does not exist.
56
+ * @returns a retrieved value, or passed default value, or undefined.
57
+ * @see {@link http://wiki.greasespot.net/GM_getValue}
58
+ */
59
+ declare function GM_getValue(name: string, defaultValue?: any): any
60
+ declare function GM_getValue(name: string, defaultValue?: string): string
61
+ declare function GM_getValue(name: string, defaultValue?: number): number
62
+ declare function GM_getValue(name: string, defaultValue?: boolean): boolean
64
63
 
65
- /**
66
- * The URL to make the request to. Must be an absolute URL, beginning
67
- * with the scheme. May be relative to the current page.
68
- */
69
- url: string
70
- /** String type of HTTP request to make (E.G. "GET", "POST") */
71
- method:
72
- | 'GET'
73
- | 'POST'
74
- | 'PUT'
75
- | 'DELETE'
76
- | 'PATCH'
77
- | 'HEAD'
78
- | 'TRACE'
79
- | 'OPTIONS'
80
- | 'CONNECT'
81
- /**
82
- * When true, the data is sent as a Blob
83
- * @default false
84
- */
85
- binary?: boolean | undefined
86
- /**
87
- * Any object (Compatibility: 1.10+). This object will also be the
88
- * context property of the Response Object.
89
- */
90
- context?: TContext | undefined
91
- /**
92
- * Data to send in the request body. Usually for POST method requests.
93
- * If the data field contains form-encoded data, you usually must also
94
- * set the header `'Content-Type': 'application/x-www-form-urlencoded'`
95
- * in the `headers` field.
96
- */
97
- data?: string | undefined
98
- /** A set of headers to include in the request */
99
- headers?:
100
- | {
101
- [header: string]: string
102
- }
103
- | undefined
104
- /**
105
- * A MIME type to specify with the request (e.g.
106
- * "text/html; charset=ISO-8859-1")
107
- */
108
- overrideMimeType?: string | undefined
109
- /** User name to use for authentication purposes. */
110
- user?: string | undefined
111
- /** Password to use for authentication purposes */
112
- password?: string | undefined
113
- /** Decode the response as specified type. Default value is "text" */
114
- responseType?: XMLHttpRequestResponseType | undefined
115
- /**
116
- * When `true`, this is a synchronous request.
117
- * Be careful: The entire Firefox UI will be locked and frozen until the
118
- * request completes.In this mode, more data will be available in the
119
- * return value.
120
- */
121
- synchronous?: boolean | undefined
122
- /**
123
- * The number of milliseconds to wait before terminating the call. Zero
124
- * (the default) means wait forever.
125
- */
126
- timeout?: number | undefined
127
- /**
128
- * Object containing optional function callbacks to monitor the upload
129
- * of data.
130
- */
131
- upload?:
132
- | {
133
- onabort?(response: Response<TContext>): void
134
- onerror?(response: Response<TContext>): void
135
- onload?(response: Response<TContext>): void
136
- onprogress?(response: ProgressResponse<TContext>): void
137
- }
138
- | undefined
64
+ /**
65
+ * Retrieves an array of names stored in the script storage.
66
+ * @returns an array of names in the storage.
67
+ * @see {@link http://wiki.greasespot.net/GM_listValues}
68
+ */
69
+ declare function GM_listValues(): string[]
139
70
 
140
- // Event handlers
71
+ /**
72
+ * Stores a name / value pair to the script storage.
73
+ * @param name a name of the pair.
74
+ * @param value a value to be stored.
75
+ * @see {@link http://wiki.greasespot.net/GM_setValue}
76
+ */
77
+ declare function GM_setValue(name: string, value: string): void
78
+ declare function GM_setValue(name: string, value: boolean): void
79
+ declare function GM_setValue(name: string, value: number): void
141
80
 
142
- /** Will be called when the request is aborted */
143
- onabort?(response: Response<TContext>): void
144
- /** Will be called if an error occurs while processing the request */
145
- onerror?(response: Response<TContext>): void
146
- /** Will be called when the request has completed successfully */
147
- onload?(response: Response<TContext>): void
148
- /** Will be called when the request progress changes */
149
- onprogress?(response: ProgressResponse<TContext>): void
150
- /** Will be called repeatedly while the request is in progress */
151
- onreadystatechange?(response: Response<TContext>): void
152
- /** Will be called if/when the request times out */
153
- ontimeout?(response: Response<TContext>): void
154
- }
155
- }
81
+ ////////////////
82
+ // Resources
83
+ ////////////////
156
84
 
157
85
  /**
158
- * Window object of the content page where the user script is running on.
159
- * @see {@link http://wiki.greasespot.net/UnsafeWindow}
86
+ * Gets a content of a resouce defined by {@link http://wiki.greasespot.net/Metadata_Block#.40resource|@resource}.
87
+ * @param resourceName a name of the resource to get.
88
+ * @returns the content of the resource.
89
+ * @see {@link http://wiki.greasespot.net/GM_getResourceText}
160
90
  */
161
- declare var unsafeWindow: Window
91
+ declare function GM_getResourceText(resourceName: string): string
162
92
 
163
- declare var GM: {
164
- // Headers
93
+ /**
94
+ * Gets a URL of a resource defined by {@link http://wiki.greasespot.net/Metadata_Block#.40resource|@resource}.
95
+ * @param resourceName a name of the resource.
96
+ * @returns a URL that returns the content of the resource.
97
+ * @see {@link http://wiki.greasespot.net/GM_getResourceURL}
98
+ */
99
+ declare function GM_getResourceURL(resourceName: string): string
165
100
 
166
- /**
167
- * Meta data about the running user script.
168
- * @see {@link https://wiki.greasespot.net/GM.info}
169
- */
170
- info: {
171
- /** An object containing data about the currently running script */
172
- script: GM.ScriptInfo
173
- /**
174
- * A string, the entire literal Metadata Block (without the delimiters)
175
- * for the currently running script
176
- */
177
- scriptMetaStr: string
178
- /**
179
- * The name of the user script engine handling this script's execution.
180
- * The string `Greasemonkey`
181
- */
182
- scriptHandler: string
183
- /** The version of Greasemonkey, a string e.g. `4.0` */
184
- version: string
185
- }
101
+ ////////////////
102
+ // Utilities
103
+ ////////////////
186
104
 
187
- // Values
105
+ /**
106
+ * Adds CSS to the content page.
107
+ * @param css a CSS string. It can have multiple style definitions.
108
+ * @see {@link http://wiki.greasespot.net/GM_addStyle}
109
+ */
110
+ declare function GM_addStyle(css: string): void
188
111
 
189
- /**
190
- * Allows user script authors to persist simple values across page loads and
191
- * across origins.
192
- * Strings, booleans, and integers are currently the only allowed data types.
193
- * @see {@link https://wiki.greasespot.net/GM.setValue}
194
- * @param name The unique (within this script) name for this value.
195
- * Should be restricted to valid Javascript identifier characters.
196
- * @param value Any valid value of these types. Any other type may cause
197
- * undefined behavior, including crashes
198
- * @returns A Promise, resolved successfully with no value on success,
199
- * rejected with no value on failure
200
- */
201
- setValue(name: string, value: GM.Value): Promise<void>
112
+ /**
113
+ * Writes a message as a log to the console with the script identifier.
114
+ * @param message a message to be written.
115
+ * @see {@link http://wiki.greasespot.net/GM_log}
116
+ */
117
+ declare function GM_log(message: any): void
202
118
 
203
- /**
204
- * Retrieves a value that was set with `GM.setValue`
205
- * @see {@link https://wiki.greasespot.net/GM.getValue}
206
- * @param name The property name to get
207
- * @param defaultValue The default value to be returned when none has
208
- * previously been set
209
- * @returns A Promise, rejected in case of error and otherwise resolved with:
210
- * - When this name has been set - `string`, `integer` or `boolean` as
211
- * previously set
212
- * - When this name has not been set, and default is provided - The value
213
- * passed as default
214
- * - When this name has not been set, and default is not provided -
215
- * `undefined`
216
- * @example
217
- * // Retrieving the value associated with the name 'timezoneOffset' with a default value defined:
218
- * const timezoneOffset = await GM.getValue("timezoneOffset", -5)
219
- * @example
220
- * // For structured data used `JSON.stringify()` to place an object into storage and then `JSON.parse()` to convert it back
221
- * const storedObject = JSON.parse(await GM.getValue('foo', '{}'));
222
- */
223
- getValue(name: string): Promise<GM.Value | undefined>
224
- getValue<TValue = GM.Value>(
225
- name: string,
226
- defaultValue: TValue
227
- ): Promise<TValue>
119
+ /**
120
+ * Opens a URL in a new tab.
121
+ * @param url a URL to open.
122
+ * @returns window object of the opened tab.
123
+ * @see {@link http://wiki.greasespot.net/GM_openInTab}
124
+ */
125
+ declare function GM_openInTab(url: string): Window
228
126
 
229
- /**
230
- * Deletes an existing name / value pair from storage.
231
- * @see {@link https://wiki.greasespot.net/GM.deleteValue}
232
- * @param name Property name to delete
233
- * @returns A Promise, resolved successfully with no value on success,
234
- * rejected with no value on failure.
235
- */
236
- deleteValue(name: string): Promise<void>
127
+ /**
128
+ * Registers an item as a submenu of User Script Commands.
129
+ * @param caption a caption of the menu item.
130
+ * @param commandFunc a function to be invoked when the item has been selected.
131
+ * @param accessKey a single character that can be used to select the item by keyboard.
132
+ * It should be a letter in the caption.
133
+ * @see {@link http://wiki.greasespot.net/GM_registerMenuCommand}
134
+ */
135
+ declare function GM_registerMenuCommand(
136
+ caption: string,
137
+ commandFunc: Function,
138
+ accessKey?: string
139
+ ): void
237
140
 
238
- /**
239
- * Retrieves an array of preference names that this script has stored
240
- * @see {@link https://wiki.greasespot.net/GM.listValues}
241
- * @returns A Promise, rejected in case of error and otherwise resolved with
242
- * an string[] for previously set values
243
- */
244
- listValues(): Promise<string[]>
141
+ /**
142
+ * Sets a text to the clipboard of the opeating system.
143
+ * @param text a text to be set to the clipboard.
144
+ * @see {@link http://wiki.greasespot.net/GM_setClipboard}
145
+ */
146
+ declare function GM_setClipboard(text: string): void
245
147
 
246
- // Resources
148
+ ////////////////
149
+ // XMLHttpRequest
150
+ ////////////////
247
151
 
248
- /**
249
- * Given a defined `@resource`, this method returns it as a URL
250
- * @see {@link https://wiki.greasespot.net/GM.getResourceUrl}
251
- * @param resourceName The name provided when the `@resource` was defined
252
- * @returns A Promise, rejected on failure and resolved with a string URL on
253
- * success.
254
- * Treat the result as opaque string. It will work where you need a URL
255
- * (for a `<link>` or `<style>` for CSS, for an `<img>` tag, or similar).
256
- */
257
- getResourceUrl(resourceName: string): Promise<string>
152
+ /**
153
+ * Request options for {@link GM_xmlhttpRequest}.
154
+ * @see {@link http://wiki.greasespot.net/GM_xmlhttpRequest#Arguments}
155
+ */
156
+ interface GMXMLHttpRequestOptions {
157
+ binary?: boolean | undefined
158
+ context?: any
159
+ data?: string | undefined
160
+ headers?: Object | undefined
161
+ method: string
162
+ onabort?: ((response: GMXMLHttpRequestResponse) => any) | undefined
163
+ onerror?: ((response: GMXMLHttpRequestResponse) => any) | undefined
164
+ onload?: ((response: GMXMLHttpRequestResponse) => any) | undefined
165
+ onprogress?: ((response: GMXMLHttpRequestProgressResponse) => any) | undefined
166
+ onreadystatechange?: ((response: GMXMLHttpRequestResponse) => any) | undefined
167
+ ontimeout?: ((response: GMXMLHttpRequestResponse) => any) | undefined
168
+ overrideMimeType?: string | undefined
169
+ password?: string | undefined
170
+ synchronous?: boolean | undefined
171
+ timeout?: number | undefined
172
+ upload?:
173
+ | {
174
+ onabort?: ((response: GMXMLHttpRequestResponse) => any) | undefined
175
+ onerror?: ((response: GMXMLHttpRequestResponse) => any) | undefined
176
+ onload?: ((response: GMXMLHttpRequestResponse) => any) | undefined
177
+ onprogress?:
178
+ | ((response: GMXMLHttpRequestProgressResponse) => any)
179
+ | undefined
180
+ }
181
+ | undefined
182
+ url: string
183
+ user?: string | undefined
184
+ }
258
185
 
259
- // Other
186
+ /**
187
+ * Response object for general events of {@link GM_xmlhttpRequest}.
188
+ * @see {@link http://wiki.greasespot.net/GM_xmlhttpRequest#Response_Object}
189
+ */
190
+ interface GMXMLHttpRequestResponse {
191
+ readyState: number
192
+ responseHeaders: string
193
+ responseText: string
194
+ status: number
195
+ statusText: string
196
+ context: any
197
+ finalUrl: string
198
+ }
260
199
 
261
- /**
262
- * Displays a notification to the user, using the underlying operating
263
- * system's notification mechanism
264
- * @see {@link https://wiki.greasespot.net/GM.notification}
265
- * @param text The main notification text
266
- * @param title The title of the notification
267
- * @param image The URL for an image to display in the dialog. If not
268
- * provided, the Greasemonkey logo by default.
269
- * @param onClick Callback, triggered when the notification's button is
270
- * clicked.
271
- */
272
- notification(
273
- text: string,
274
- title: string,
275
- image?: string,
276
- onClick?: () => void
277
- ): void
200
+ /**
201
+ * Response object for onprogress event of {@link GM_xmlhttpRequest}.
202
+ */
203
+ interface GMXMLHttpRequestProgressResponse extends GMXMLHttpRequestResponse {
204
+ lengthComputable: boolean
205
+ loaded: number
206
+ total: number
207
+ }
278
208
 
279
- /**
280
- * Opens the specified URL in a new tab.
281
- * @see {@link https://wiki.greasespot.net/GM.openInTab}
282
- * @param url The URL to navigate the new tab to
283
- * @param openInBackground Force tab to/to not open in a background tab.
284
- * Default (unspecified) behavior honors Firefox configuration.
285
- */
286
- openInTab(url: string, openInBackground?: boolean): void
209
+ /**
210
+ * Returned object by {@link GM_xmlhttpRequest} in asynchronous mode.
211
+ */
212
+ interface GMXMLHttpRequestAsyncResult {
213
+ abort(): void
214
+ }
287
215
 
288
- /**
289
- * Adds an item to the User Script Commands menu.
290
- * @param caption The caption to display on the menu item.
291
- * @param commandFunc The function to call when the menu item is selected.
292
- * @param accessKey A single character that can be used to select the
293
- * item when the menu is open. It should be a letter in the caption.
294
- * @see {@link https://wiki.greasespot.net/GM.registerMenuCommand}
295
- */
296
- registerMenuCommand(
297
- caption: string,
298
- commandFunc: () => void,
299
- accessKey?: string
300
- ): void
216
+ /**
217
+ * Returned object by {@link GM_xmlhttpRequest} in synchronouse mode.
218
+ */
219
+ interface GMXMLHttpRequestSyncResult {
220
+ abort(): void
221
+ finalUrl: string
222
+ readyState: number
223
+ responseHeaders: string
224
+ responseText: string
225
+ status: number
226
+ statusText: string
227
+ }
301
228
 
302
- /**
303
- * Sets the current contents of the operating system's clipboard
304
- * @see {@link https://wiki.greasespot.net/GM.setClipboard}
305
- */
306
- setClipboard(text: string): void
229
+ /**
230
+ * Returned object by {@link GM_xmlhttpRequest}.
231
+ * @see {@link http://wiki.greasespot.net/GM_xmlhttpRequest#Returns}
232
+ */
233
+ interface GMXMLHttpRequestResult
234
+ extends GMXMLHttpRequestAsyncResult,
235
+ GMXMLHttpRequestSyncResult {}
307
236
 
308
- /**
309
- * Performs a similar function to the standard XMLHttpRequest object, but
310
- * allows these requests to cross the [same origin policy]{@link https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy} boundaries.
311
- * @see {@link https://wiki.greasespot.net/GM.xmlHttpRequest}
312
- */
313
- xmlHttpRequest(details: GM.Request): void
314
- }
237
+ /**
238
+ * Sends a HTTP request to a URL.
239
+ * @param options options and callbacks for HTTP request.
240
+ * @returns an object which can abort the request.
241
+ * If the request is sent in the synchronous mode, it also contains the response information.
242
+ * @see {@link http://wiki.greasespot.net/GM_setClipboard}
243
+ */
244
+ declare function GM_xmlhttpRequest(
245
+ options: GMXMLHttpRequestOptions
246
+ ): GMXMLHttpRequestResult
@@ -2,6 +2,8 @@
2
2
  // Project: https://tampermonkey.net
3
3
  // Definitions by: Steven Wang <https://github.com/silverwzw>
4
4
  // Nikolay Borzov <https://github.com/nikolay-borzov>
5
+ // taozhiyu <https://github.com/taozhiyu>
6
+ // double-beep <https://github.com/double-beep>
5
7
  // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
6
8
 
7
9
  // This definition is based on the API reference of Tampermonkey
@@ -69,19 +71,8 @@ declare namespace Tampermonkey {
69
71
  response: TResponse
70
72
  ) => void
71
73
 
72
- type RequestMethods =
73
- | 'POST'
74
- | 'GET'
75
- | 'PUT'
76
- | 'PATCH'
77
- | 'DELETE'
78
- | 'HEAD'
79
- | 'TRACE'
80
- | 'OPTIONS'
81
- | 'CONNECT'
82
-
83
74
  interface Request<TContext = object> {
84
- method?: RequestMethods
75
+ method?: 'GET' | 'HEAD' | 'POST' | undefined
85
76
  /** Destination URL */
86
77
  url: string
87
78
  /**
@@ -284,11 +275,16 @@ declare namespace Tampermonkey {
284
275
  comment: string | null
285
276
  compat_foreach: boolean
286
277
  compat_metadata: boolean
278
+ compat_powerful_this: boolean | null
287
279
  compat_prototypes: boolean
288
280
  compat_wrappedjsobject: boolean
289
281
  compatopts_for_requires: boolean
290
282
  noframes: boolean | null
291
283
  run_at: string
284
+ sandbox: string | null
285
+ tab_types: string | null
286
+ unwrap: boolean | null
287
+
292
288
  override: ScriptMetadataOverrides
293
289
  }
294
290
 
@@ -298,9 +294,32 @@ declare namespace Tampermonkey {
298
294
  */
299
295
  interface ScriptResource {
300
296
  name: string
301
- url: string
302
- content: string
303
- meta: string
297
+ url?: string
298
+ content?: string
299
+ meta?: string
300
+ error?: string
301
+ }
302
+
303
+ interface WebRequestRule {
304
+ selector:
305
+ | {
306
+ include?: string | string[]
307
+ match?: string | string[]
308
+ exclude?: string | string[]
309
+ }
310
+ | string
311
+ action:
312
+ | string
313
+ | {
314
+ cancel?: boolean
315
+ redirect?:
316
+ | {
317
+ url: string
318
+ from?: string
319
+ to?: string
320
+ }
321
+ | string
322
+ }
304
323
  }
305
324
 
306
325
  /**
@@ -311,18 +330,17 @@ declare namespace Tampermonkey {
311
330
  antifeatures: Record<string, Record<string, string>>
312
331
  author: string | null
313
332
 
314
- /**
315
- * Idk what this is, nothing I did changed this from any empty array
316
- * and it's not documented anywhere
317
- */
318
- blockers: any[]
333
+ blockers: string[]
319
334
 
320
335
  copyright: string | null
336
+ deleted?: number | undefined
321
337
  description: string | null
322
- description_i18n: Record<string, string>
338
+ description_i18n: Record<string, string> | null
323
339
  downloadURL: string | null
340
+ enabled?: boolean
324
341
  evilness: number
325
342
  excludes: string[]
343
+ fileURL?: string | null
326
344
  grant: string[]
327
345
  header: string
328
346
  homepage: string | null
@@ -332,7 +350,7 @@ declare namespace Tampermonkey {
332
350
  lastModified: number
333
351
  matches: string[]
334
352
  name: string
335
- name_i18n: Record<string, string>
353
+ name_i18n: Record<string, string> | null
336
354
  namespace: string | null
337
355
  options: ScriptSettings
338
356
 
@@ -345,21 +363,23 @@ declare namespace Tampermonkey {
345
363
  'run-at': string
346
364
 
347
365
  supportURL: string | null
348
- sync: {
349
- imported: boolean
366
+ sync?: {
367
+ imported?: number | undefined
350
368
  }
369
+ system?: boolean | undefined
351
370
  unwrap: boolean
352
371
  updateURL: string | null
353
372
  uuid: string
354
373
  version: string
355
- webRequest: string[]
374
+ webRequest: WebRequestRule[] | null
356
375
  }
357
376
 
358
377
  interface ScriptInfo {
359
378
  downloadMode: 'native' | 'browser' | 'disabled'
360
- isFirstPartyIsolation: boolean | undefined
379
+ isFirstPartyIsolation?: boolean
361
380
  isIncognito: boolean
362
381
  script: ScriptMetadata
382
+ sandboxMode: 'js' | 'raw' | 'dom'
363
383
 
364
384
  /**
365
385
  * In tampermonkey it's "Tampermonkey"
@@ -368,13 +388,13 @@ declare namespace Tampermonkey {
368
388
  */
369
389
  scriptHandler: string
370
390
 
371
- scriptMetaStr: string
391
+ scriptMetaStr: string | null
372
392
  scriptSource: string
373
- scriptUpdateURL: string | undefined
393
+ scriptUpdateURL: string | null
374
394
  scriptWillUpdate: boolean
375
395
 
376
396
  /** This refers to tampermonkey's version */
377
- version: string
397
+ version?: string
378
398
  }
379
399
 
380
400
  type ContentType =
@@ -386,7 +406,57 @@ declare namespace Tampermonkey {
386
406
  * The unsafeWindow object provides full access to the pages javascript
387
407
  * functions and variables
388
408
  */
389
- declare var unsafeWindow: Window
409
+ declare var unsafeWindow: Window &
410
+ Omit<
411
+ typeof globalThis,
412
+ | 'GM_addStyle'
413
+ | 'GM_addValueChangeListener'
414
+ | 'GM_deleteValue'
415
+ | 'GM_download'
416
+ | 'GM_download'
417
+ | 'GM_getResourceText'
418
+ | 'GM_getResourceURL'
419
+ | 'GM_getTab'
420
+ | 'GM_getTabs'
421
+ | 'GM_getValue'
422
+ | 'GM_info'
423
+ | 'GM_listValues'
424
+ | 'GM_log'
425
+ | 'GM_notification'
426
+ | 'GM_notification'
427
+ | 'GM_openInTab'
428
+ | 'GM_registerMenuCommand'
429
+ | 'GM_removeValueChangeListener'
430
+ | 'GM_saveTab'
431
+ | 'GM_setClipboard'
432
+ | 'GM_setValue'
433
+ | 'GM_unregisterMenuCommand'
434
+ | 'GM_xmlhttpRequest'
435
+ | 'GM'
436
+ >
437
+
438
+ /**
439
+ *
440
+ * Patched onurlchange attribute based on document {@link https://www.tampermonkey.net/documentation.php#meta:grant}
441
+ * @url https://www.tampermonkey.net/documentation.php#meta:grant
442
+ */
443
+ interface Window {
444
+ /**
445
+ * check before use addEventListener
446
+ *
447
+ * According to the documentation and code, the value can currently only be of type null
448
+ * @url https://www.tampermonkey.net/documentation.php#meta:grant
449
+ * @example
450
+ * if (window.onurlchange === null) {
451
+ * window.addEventListener('urlchange', (info) => console.log(info));
452
+ * }
453
+ */
454
+ onurlchange: null
455
+ addEventListener(
456
+ type: 'urlchange',
457
+ listener: (urlObject: { url: string }) => void
458
+ ): void
459
+ }
390
460
 
391
461
  // Styles
392
462
 
@@ -461,7 +531,7 @@ declare function GM_unregisterMenuCommand(menuCommandId: number): void
461
531
 
462
532
  /** Makes an xmlHttpRequest */
463
533
  declare function GM_xmlhttpRequest<TContext = any>(
464
- details: Tampermonkey.Request<TContext> // tslint:disable-line:no-unnecessary-generics
534
+ details: Tampermonkey.Request<TContext> // eslint-disable-line no-unnecessary-generics
465
535
  ): Tampermonkey.AbortHandle<void>
466
536
 
467
537
  /** Downloads a given URL to the local disk */
@@ -488,7 +558,7 @@ declare function GM_getTabs(
488
558
 
489
559
  // Utils
490
560
 
491
- declare const GM_info: Tampermonkey.ScriptInfo
561
+ declare var GM_info: Tampermonkey.ScriptInfo
492
562
 
493
563
  /** Log a message to the console */
494
564
  declare function GM_log(...message: any[]): void
@@ -552,7 +622,7 @@ declare function GM_setClipboard(
552
622
  /**
553
623
  * `GM` has all the `GM_*` apis in promisified form
554
624
  */
555
- declare const GM: Readonly<{
625
+ declare var GM: Readonly<{
556
626
  // Styles
557
627
 
558
628
  /**
@@ -628,7 +698,7 @@ declare const GM: Readonly<{
628
698
  */
629
699
  xmlHttpRequest<TContext = any>(
630
700
  // onload and the like still work
631
- details: Tampermonkey.Request<TContext> // tslint:disable-line:no-unnecessary-generics
701
+ details: Tampermonkey.Request<TContext> // eslint-disable-line no-unnecessary-generics
632
702
  ): Promise<Tampermonkey.Response<TContext>>
633
703
 
634
704
  // GM_download has two signatures, GM.download has one