8000 :sparkles: basic usage · momocow/webpack-userscript@fa09600 · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Commit fa09600

Browse files
committed
✨ basic usage
1 parent c04e96d commit fa09600

File tree

7 files changed

+513
-61
lines changed

7 files changed

+513
-61
lines changed

lib/fs.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/**
2+
* FS-implementation aware functions.
3+
* @module
4+
*/
5+
import _fs from 'fs';
6+
import path from 'path';
7+
import { promisify } from 'util';
8+
9+
export type FS = typeof _fs;
10+
11+
export async function findPackage(
12+
cwd: string,
13+
fs: Pick<FS, 'stat'> = _fs,
14+
): Promise<string> {
15+
const statAsync = promisify(fs.stat);
16+
17+
let dir = cwd;
18+
while (true) {
19+
const parent = path.dirname(dir);
20+
try {
21+
const pkg = await statAsync(path.join(dir, 'package.json'));
22+
if (pkg.isFile()) {
23+
return dir;
24+
}
25+
} catch (e) {
26+
// root directory
27+
if (dir === parent) {
28+
throw new Error(`package.json is not found`);
29+
}
30+
}
31+
dir = parent;
32+
}
33+
}
34+
35+
export async function readJSON<T>(
36+
file: string,
37+
fs: Pick<FS, 'readFile'> = _fs,
38+
): Promise<T> {
39+
const readfileAsync = promisify(fs.readFile);
40+
const buf = await readfileAsync(file, 'utf-8');
41+
return JSON.parse(buf);
42+
}

lib/headers.ts

Lines changed: 226 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,235 @@
11
import { isDeepStrictEqual } from 'node:util';
22

3+
import {
4+
instanceToPlain,
5+
plainToInstance,
6+
Transform,
7+
Type,
8+
} from 'class-transformer';
9+
import {
10+
IsBoolean,
11+
IsEnum,
12+
IsObject,
13+
IsOptional,
14+
IsSemVer,
15+
IsString,
16+
IsUrl,
17+
validateSync,
18+
} from 'class-validator';
19+
20+
export interface HeadersFactoryOptions {
21+
strict: boolean;
22+
}
23+
24+
const TransformArray = (): PropertyDecorator =>
25+
Transform(({ value }) => (Array.isArray(value) ? value : [value]));
26+
27+
const TranformObject = (): PropertyDecorator =>
28+
Transform(({ value }) =>
29+
Array.isArray(value) ? Object.fromEntries(value) : value,
30+
);
31+
32+
export enum RunAt {
33+
DocumentStart = 'document-start',
34+
DocumentBody = 'document-body',
35+
DocumentEnd = 'document-end',
36+
DocumentIdle = 'document-idle',
37+
ContextMenu = 'context-menu',
38+
}
39+
40+
export interface HeadersRenderOptions {
41+
prefix?: string;
42+
suffix?: string;
43+
pretty?: boolean;
44+
}
45+
346
export class Headers {
4-
public toString(): string {
5-
return '';
47+
@IsString()
48+
public readonly name!: string;
49+
50+
@IsOptional()
51+
@IsSemVer()
52+
public readonly version?: string;
53+
54+
@IsOptional()
55+
@IsString()
56+
public readonly namespace?: string;
57+
58+
@IsOptional()
59+
@IsString()
60+
public readonly author?: string;
61+
62+
@IsOptional()
63+
@IsString()
64+
public readonly description?: string;
65+
66+
@IsOptional()
67+
@IsUrl()
68+
public readonly homepage?: string;
69+
70+
@IsOptional()
71+
@IsUrl()
72+
public readonly homepageURL?: string;
73+
74+
@IsOptional()
75+
@IsUrl()
76+
public readonly website?: string;
77+
78+
@IsOptional()
79+
@IsUrl()
80+
public readonly source?: string;
81+
82+
@IsOptional()
83+
@IsUrl()
84+
public readonly icon?: string;
85+
86+
@IsOptional()
87+
@IsUrl()
88+
public readonly iconURL?: string;
89+
90+
@IsOptional()
91+
@IsUrl()
92+
public readonly defaulticon?: string;
93+
94+
@IsOptional()
95+
@IsUrl()
96+
public readonly icon64?: string;
97+
98+
@IsOptional()
99+
@IsUrl()
100+
public readonly icon64URL?: string;
101+
102+
@IsOptional()
103+
@IsUrl()
104+
public readonly updateURL?: string;
105+
106+
@IsOptional()
107+
@IsUrl()
108+
public readonly downloadURL?: string;
109+
110+
@IsOptional()
111+
@IsUrl()
112+
public readonly installURL?: string;
113+
114+
@IsOptional()
115+
@IsUrl()
116+
public readonly supportURL?: string;
117+
118+
@TransformArray()
119+
@IsOptional()
120+
@IsString({ each: true })
121+
public readonly include?: Readonly<string[]>;
122+
123+
@TransformArray()
124+
@IsOptional()
125+
@IsString({ each: true })
126+
public readonly match?: Readonly<string[]>;
127+
128+
@TransformArray()
129+
@IsOptional()
130+
@IsString({ each: true })
131+
public readonly exclude?: Readonly<string[]>;
132+
133+
@TransformArray()
134+
@IsOptional()
135+
@IsString({ each: true })
136+
public readonly require?: Readonly<string[]>;
137+
138+
@TranformObject()
139+
@IsOptional()
140+
@IsObject()
141+
2851 public readonly resource?: Readonly<Record<string, string>>;
142+
143+
@TransformArray()
144+
@IsOptional()
145+
@IsString({ each: true })
146+
public readonly connect?: Readonly<string[]>;
147+
148+
@TransformArray()
149+
@IsOptional()
150+
@IsString({ each: true })
151+
public readonly grant?: Readonly<string[]>;
152+
153+
@TransformArray()
154+
@IsOptional()
155+
@IsString({ each: true })
156+
public readonly webRequest?: Readonly<string[]>;
157+
158+
@Type(() => Boolean)
159+
@IsOptional()
160+
@IsBoolean()
161+
public readonly noframes?: boolean;
162+
163+
@Type(() => Boolean)
164+
@IsOptional()
165+
@IsBoolean()
166+
public readonly unwrap?: boolean;
167+
168+
@TranformObject()
169+
@IsOptional()
170+
@IsObject()
171+
public readonly antifeature?: Readonly<Record<string, string>>;
172+
173+
@IsOptional()
174+
@IsEnum(RunAt)
175+
public readonly ['run-at']?:
176+
| 'document-start'
177+
| 'document-body'
178+
| 'document-end'
179+
| 'document-idle'
180+
| 'context-menu';
181+
182+
public render({
183+
prefix = '// ==UserScript==',
184+
suffix = '// ==/UserScript==',
185+
}: HeadersRenderOptions = {}): string {
186+
const body = Object.entries(
187+
instanceToPlain(this) as Record<
188+
string,
189+
Record<string, string> | string[] | string | boolean
190+
>,
191+
)
192+
.filter(([, value]) => value !== null && value !== undefined)
193+
.map(([tag, value]) => this.renderTag(tag, value))
194+
.join('\n');
195+
return [prefix, body, suffix].join('\n');
196+
}
197+
198+
private renderTag(
199+
tag: string,
200+
value: Record<string, string> | string[] | string | boolean,
201+
): string {
202+
if (Array.isArray(value)) {
203+
return value.map((v) => `// @${tag} ${v}`).join('\n');
204+
}
205+
206+
if (typeof value === 'object') {
207+
return Object.entries(value)
208+
.map(([k, v]) => `// @${tag} ${k} ${v}`)
209+
.join('\n');
210+
}
211+
212+
return `// @${tag} ${String(value)}`;
6213
}
7214

8215
public equals(other: Headers): boolean {
9216
return isDeepStrictEqual(this, other);
10217
}
218+
219+
public static fromJSON(
220+
obj: unknown,
221+
{ strict }: Partial<HeadersFactoryOptions> = {},
222+
): Headers {
223+
const headers = plainToInstance(Headers, obj);
224+
if (strict) {
225+
const errors = validateSync(headers, {
226+
forbidNonWhitelisted: true,
227+
stopAtFirstError: false,
228+
});
229+
if (errors.length > 0) {
230+
throw new Error(errors.map((err) => err.toString()).join('\n'));
231+
}
232+
}
233+
return headers;
234+
}
11235
}

lib/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import 'reflect-metadata';
2+
13
import { UserscriptPlugin } from './plugin';
24

35
export default UserscriptPlugin;

0 commit comments

Comments
 (0)
0