Skip to content

Commit 526611f

Browse files
committed
Initial commit
1 parent 2aa14f2 commit 526611f

35 files changed

+3441
-1
lines changed

.eslint/deno-json.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// deno run deno-json.ts > deno.json
2+
3+
const caseInsensitiveSort = (strA: string, strB: string): number => {
4+
const a = strA.toLowerCase();
5+
const b = strB.toLowerCase();
6+
if (a < b) return -1;
7+
if (a > b) return 1;
8+
return 0;
9+
};
10+
11+
const sortedGlobals = [...Object.getOwnPropertyNames(globalThis)]
12+
.sort(caseInsensitiveSort);
13+
14+
const globals: Record<string, string> = {};
15+
for (const key of sortedGlobals) globals[key] = 'readonly';
16+
17+
const spaces = 2;
18+
const json = JSON.stringify({globals}, null, spaces);
19+
20+
console.log(json);

.eslint/deno.json

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
{
2+
"globals": {
3+
"AbortController": "readonly",
4+
"AbortSignal": "readonly",
5+
"addEventListener": "readonly",
6+
"AggregateError": "readonly",
7+
"alert": "readonly",
8+
"Array": "readonly",
9+
"ArrayBuffer": "readonly",
10+
"atob": "readonly",
11+
"Atomics": "readonly",
12+
"BigInt": "readonly",
13+
"BigInt64Array": "readonly",
14+
"BigUint64Array": "readonly",
15+
"Blob": "readonly",
16+
"Boolean": "readonly",
17+
"btoa": "readonly",
18+
"ByteLengthQueuingStrategy": "readonly",
19+
"clearInterval": "readonly",
20+
"clearTimeout": "readonly",
21+
"close": "readonly",
22+
"closed": "readonly",
23+
"CloseEvent": "readonly",
24+
"confirm": "readonly",
25+
"console": "readonly",
26+
"CountQueuingStrategy": "readonly",
27+
"crypto": "readonly",
28+
"CustomEvent": "readonly",
29+
"DataView": "readonly",
30+
"Date": "readonly",
31+
"decodeURI": "readonly",
32+
"decodeURIComponent": "readonly",
33+
"Deno": "readonly",
34+
"dispatchEvent": "readonly",
35+
"DOMException": "readonly",
36+
"encodeURI": "readonly",
37+
"encodeURIComponent": "readonly",
38+
"Error": "readonly",
39+
"ErrorEvent": "readonly",
40+
"escape": "readonly",
41+
"eval": "readonly",
42+
"EvalError": "readonly",
43+
"Event": "readonly",
44+
"EventTarget": "readonly",
45+
"fetch": "readonly",
46+
"File": "readonly",
47+
"FileReader": "readonly",
48+
"FinalizationRegistry": "readonly",
49+
"Float32Array": "readonly",
50+
"Float64Array": "readonly",
51+
"FormData": "readonly",
52+
"Function": "readonly",
53+
"globalThis": "readonly",
54+
"GPU": "readonly",
55+
"GPUAdapter": "readonly",
56+
"GPUAdapterFeatures": "readonly",
57+
"GPUAdapterLimits": "readonly",
58+
"GPUBindGroup": "readonly",
59+
"GPUBindGroupLayout": "readonly",
60+
"GPUBuffer": "readonly",
61+
"GPUBufferUsage": "readonly",
62+
"GPUColorWrite": "readonly",
63+
"GPUCommandBuffer": "readonly",
64+
"GPUCommandEncoder": "readonly",
65+
"GPUComputePassEncoder": "readonly",
66+
"GPUComputePipeline": "readonly",
67+
"GPUDevice": "readonly",
68+
"GPUMapMode": "readonly",
69+
"GPUOutOfMemoryError": "readonly",
70+
"GPUPipelineLayout": "readonly",
71+
"GPUQuerySet": "readonly",
72+
"GPUQueue": "readonly",
73+
"GPURenderBundle": "readonly",
74+
"GPURenderBundleEncoder": "readonly",
75+
"GPURenderPassEncoder": "readonly",
76+
"GPURenderPipeline": "readonly",
77+
"GPUSampler": "readonly",
78+
"GPUShaderModule": "readonly",
79+
"GPUShaderStage": "readonly",
80+
"GPUTexture": "readonly",
81+
"GPUTextureUsage": "readonly",
82+
"GPUTextureView": "readonly",
83+
"GPUValidationError": "readonly",
84+
"Headers": "readonly",
85+
"Infinity": "readonly",
86+
"Int16Array": "readonly",
87+
"Int32Array": "readonly",
88+
"Int8Array": "readonly",
89+
"Intl": "readonly",
90+
"isFinite": "readonly",
91+
"isNaN": "readonly",
92+
"JSON": "readonly",
93+
"Location": "readonly",
94+
"location": "readonly",
95+
"Map": "readonly",
96+
"Math": "readonly",
97+
"MessageEvent": "readonly",
98+
"NaN": "readonly",
99+
"Navigator": "readonly",
100+
"navigator": "readonly",
101+
"Number": "readonly",
102+
"Object": "readonly",
103+
"onload": "readonly",
104+
"onunload": "readonly",
105+
"parseFloat": "readonly",
106+
"parseInt": "readonly",
107+
"Performance": "readonly",
108+
"performance": "readonly",
109+
"PerformanceEntry": "readonly",
110+
"PerformanceMark": "readonly",
111+
"PerformanceMeasure": "readonly",
112+
"ProgressEvent": "readonly",
113+
"Promise": "readonly",
114+
"prompt": "readonly",
115+
"Proxy": "readonly",
116+
"queueMicrotask": "readonly",
117+
"RangeError": "readonly",
118+
"ReadableStream": "readonly",
119+
"ReadableStreamDefaultReader": "readonly",
120+
"ReferenceError": "readonly",
121+
"Reflect": "readonly",
122+
"RegExp": "readonly",
123+
"removeEventListener": "readonly",
124+
"Request": "readonly",
125+
"Response": "readonly",
126+
"self": "readonly",
127+
"Set": "readonly",
128+
"setInterval": "readonly",
129+
"setTimeout": "readonly",
130+
"SharedArrayBuffer": "readonly",
131+
"String": "readonly",
132+
"Symbol": "readonly",
133+
"SyntaxError": "readonly",
134+
"TextDecoder": "readonly",
135+
"TextEncoder": "readonly",
136+
"TransformStream": "readonly",
137+
"TypeError": "readonly",
138+
"Uint16Array": "readonly",
139+
"Uint32Array": "readonly",
140+
"Uint8Array": "readonly",
141+
"Uint8ClampedArray": "readonly",
142+
"undefined": "readonly",
143+
"unescape": "readonly",
144+
"URIError": "readonly",
145+
"URL": "readonly",
146+
"URLSearchParams": "readonly",
147+
"WeakMap": "readonly",
148+
"WeakRef": "readonly",
149+
"WeakSet": "readonly",
150+
"WebAssembly": "readonly",
151+
"WebSocket": "readonly",
152+
"Window": "readonly",
153+
"window": "readonly",
154+
"Worker": "readonly",
155+
"WritableStream": "readonly",
156+
"WritableStreamDefaultWriter": "readonly"
157+
}
158+
}

.eslint/eslintrc.cjs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
const deno = require('./deno.json');
2+
const tsEslint = require('./typescript-eslint-base.json');
3+
4+
module.exports = {
5+
extends: [...tsEslint.extends, '@jsejcksn'],
6+
globals: deno.globals,
7+
parser: tsEslint.parser,
8+
plugins: tsEslint.plugins,
9+
root: true,
10+
};
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"extends": [
3+
"eslint:recommended",
4+
"plugin:@typescript-eslint/recommended"
5+
],
6+
"parser": "@typescript-eslint/parser",
7+
"plugins": [
8+
"@typescript-eslint"
9+
],
10+
"root": true
11+
}

.eslintrc.cjs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
module.exports = {
2+
...require('./.eslint/eslintrc.cjs'),
3+
rules: {'func-style': 'off'},
4+
};

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
/untracked/
2+
13
# Logs
24
logs
35
*.log

.vscode/settings.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"deno.enable": true,
3+
"deno.lint": false,
4+
"deno.unstable": true,
5+
"deno.suggest.imports.hosts": {
6+
"https://deno.land": true
7+
}
8+
}

README.md

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,69 @@
1-
# deno-userscript-bundler
1+
# deno-userscript-bundler
2+
3+
4+
## To-do
5+
6+
- Write documentation
7+
- Write tests
8+
9+
10+
## Install
11+
12+
```
13+
deno install --unstable --name uscript-deno main.ts
14+
```
15+
16+
> To avoid being prompted for permissions every time, install with the following permissions:
17+
18+
```
19+
deno install --unstable --allow-net --allow-read --allow-run --allow-write --name uscript-deno main.ts
20+
```
21+
22+
(Some permissions aren't strictly necessary, but allow for an enhanced experience — e.g. `--allow-run` is only used to open files in VS Code and to get the correct Windows path in WSL)
23+
24+
25+
## Use
26+
27+
Generate a new directory with a script template (main.ts) and metablock template (metablock.yaml)
28+
```sh
29+
uscript-deno new $DIR
30+
# uscript-deno new path/to/new/dir
31+
```
32+
```
33+
Created:
34+
path/to/new/dir
35+
├ main.ts
36+
└ metablock.yaml
37+
```
38+
39+
Bundle userscript
40+
```sh
41+
uscript-deno bundle $ENTRYPOINT
42+
# uscript-deno bundle path/to/project/main.ts
43+
```
44+
```
45+
Written:
46+
path/to/project/main.bundle.user.js
47+
```
48+
49+
Run in development mode: Watches entrypoint file for changes and bundles again on each change. Also provides metablock userscript on localhost server for quick installation by a script manager extension (e.g. Tampermonkey) (requires fs access by the script manager)
50+
```sh
51+
uscript-deno dev $ENTRYPOINT
52+
# uscript-deno dev path/to/project/main.ts
53+
```
54+
```
55+
Development userscript metablock at:
56+
http://localhost:10741/meta.user.js
57+
58+
Watching for file changes…
59+
Use ctrl+c to stop.
60+
61+
18:33:11.796 Bundling…
62+
18:33:13.211 Done (1416ms)
63+
64+
```
65+
66+
67+
## Notes
68+
69+
Template file data can be modified before installing and are located at [`data/templates.ts`](data/templates.ts)

bundler/mod.ts

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import {emitOptions} from './options.ts';
2+
export {baseCompilerOptions} from './options.ts';
3+
4+
export type BundleOptions = {
5+
6+
/**
7+
* TypeScript compiler options used by Deno. If not provided, a set of default
8+
* options will be used, targeted for a browser and ESNext features
9+
*/
10+
compilerOptions?: Deno.CompilerOptions;
11+
12+
/**
13+
* String to prepend to the module text. If provided, a newline will be
14+
* automatically inserted after the string.
15+
*/
16+
header?: string;
17+
18+
/**
19+
* Print any compilation diagnostic messages to the console. Default: `false`
20+
*/
21+
logDiagnostics?: boolean;
22+
23+
/** Default: `"esm"` */
24+
moduleType?: Deno.EmitOptions['bundle'];
25+
};
26+
27+
export type BundleResult = {
28+
bundle: string;
29+
result: Deno.EmitResult;
30+
};
31+
32+
export async function bundleModule (
33+
entrypointPath: string,
34+
options?: BundleOptions,
35+
): Promise<BundleResult> {
36+
const result = await Deno.emit(entrypointPath, {
37+
bundle: options?.moduleType ?? emitOptions.bundle,
38+
compilerOptions: options?.compilerOptions ?? emitOptions.compilerOptions,
39+
});
40+
41+
if (options?.logDiagnostics) {
42+
if (result.ignoredOptions?.length) {
43+
let message = 'Ignored options:\n';
44+
message += result.ignoredOptions.map(str => ` ${str}`).join('\n');
45+
console.warn(message);
46+
}
47+
if (result.diagnostics.length) {
48+
console.warn(Deno.formatDiagnostics(result.diagnostics));
49+
}
50+
}
51+
52+
// https://deno.land/manual@v1.9.2/typescript/runtime#bundling
53+
let bundle = result.files['deno:///bundle.js'];
54+
55+
if (options?.header) bundle = `${options.header}\n${bundle}`;
56+
57+
return {bundle, result};
58+
}

bundler/options.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/* eslint-disable line-comment-position, max-len */
2+
// This is as close as possible to "WSYIWYG/just erase types"
3+
export const baseCompilerOptions: Deno.CompilerOptions = {
4+
// allowJs: true // default
5+
// declaration: true, // not supported for bundles [yet]
6+
// declarationDir: 'types', // doesn't seem to work [yet?]
7+
// inlineSourceMap: true,
8+
// inlineSources: true,
9+
lib: ['ESNext'],
10+
// jsx: 'react-jsx', // not supported [yet?]
11+
// module: 'esnext', // default
12+
// noImplicitAny: true, // default
13+
noImplicitReturns: true,
14+
// removeComments: true, // default
15+
sourceMap: false, // is documented as false by default, but appears to be true by default
16+
// strict: true, // default
17+
// target: 'esnext', // default
18+
// types: [] // needed?
19+
};
20+
/* eslint-enable line-comment-position, max-len */
21+
22+
export const browserCompilerOptions: Deno.CompilerOptions = {
23+
...baseCompilerOptions,
24+
lib: [
25+
'DOM',
26+
'DOM.Iterable',
27+
'ESNext',
28+
],
29+
};
30+
31+
export const emitOptions: Deno.EmitOptions = {
32+
bundle: 'esm',
33+
compilerOptions: browserCompilerOptions,
34+
// sources: {},
35+
};

0 commit comments

Comments
 (0)