gradio

Форк
0
/
build_plugins.ts 
313 строк · 7.0 Кб
1
import type { Plugin } from "vite";
2
import { parse, HTMLElement } from "node-html-parser";
3

4
import { join } from "path";
5
import { writeFileSync } from "fs";
6

7
export function inject_ejs(): Plugin {
8
	return {
9
		name: "inject-ejs",
10
		enforce: "post",
11
		transformIndexHtml: (html) => {
12
			return html.replace(
13
				/%gradio_config%/,
14
				`<script>window.gradio_config = {{ config | toorjson }};</script>`
15
			);
16
		}
17
	};
18
}
19

20
export function generate_cdn_entry({
21
	version,
22
	cdn_base
23
}: {
24
	version: string;
25
	cdn_base: string;
26
}): Plugin {
27
	return {
28
		name: "generate-cdn-entry",
29
		enforce: "post",
30
		writeBundle(config, bundle) {
31
			if (
32
				!config.dir ||
33
				!bundle["index.html"] ||
34
				bundle["index.html"].type !== "asset"
35
			)
36
				return;
37

38
			const source = bundle["index.html"].source as string;
39
			const tree = parse(source);
40

41
			const script = Array.from(
42
				tree.querySelectorAll("script[type=module]")
43
			).find((node) => node.attributes.src?.includes("assets"));
44

45
			const output_location = join(config.dir, "gradio.js");
46

47
			writeFileSync(output_location, make_entry(script?.attributes.src || ""));
48

49
			if (!script) return;
50

51
			const transformed_html =
52
				(bundle["index.html"].source as string).substring(0, script?.range[0]) +
53
				`<script type="module" crossorigin src="${cdn_base}/${version}/gradio.js"></script>` +
54
				(bundle["index.html"].source as string).substring(
55
					script?.range[1],
56
					source.length
57
				);
58

59
			const share_html_location = join(config.dir, "share.html");
60
			writeFileSync(share_html_location, transformed_html);
61
		}
62
	};
63
}
64

65
const RE_SVELTE_IMPORT =
66
	/import\s+([\w*{},\s]+)\s+from\s+['"](svelte|svelte\/internal)['"]/g;
67

68
export function generate_dev_entry({ enable }: { enable: boolean }): Plugin {
69
	return {
70
		name: "generate-dev-entry",
71
		transform(code, id) {
72
			if (!enable) return;
73

74
			const new_code = code.replace(RE_SVELTE_IMPORT, (str, $1, $2) => {
75
				return `const ${$1.replace(
76
					" as ",
77
					": "
78
				)} = window.__gradio__svelte__internal;`;
79
			});
80

81
			return {
82
				code: new_code,
83
				map: null
84
			};
85
		}
86
	};
87
}
88

89
function make_entry(script: string): string {
90
	return `import("${script}");
91
`;
92
}
93

94
export function handle_ce_css(): Plugin {
95
	return {
96
		enforce: "post",
97
		name: "custom-element-css",
98

99
		writeBundle(config, bundle) {
100
			let file_to_insert = {
101
				filename: "",
102
				source: ""
103
			};
104

105
			if (
106
				!config.dir ||
107
				!bundle["index.html"] ||
108
				bundle["index.html"].type !== "asset"
109
			)
110
				return;
111

112
			for (const key in bundle) {
113
				const chunk = bundle[key];
114
				if (chunk.type === "chunk") {
115
					const _chunk = chunk;
116

117
					const found = _chunk.code?.indexOf("ENTRY_CSS");
118

119
					if (found > -1)
120
						file_to_insert = {
121
							filename: join(config.dir, key),
122
							source: _chunk.code
123
						};
124
				}
125
			}
126

127
			const tree = parse(bundle["index.html"].source as string);
128

129
			const { style, fonts } = Array.from(
130
				tree.querySelectorAll("link[rel=stylesheet]")
131
			).reduce(
132
				(acc, next) => {
133
					if (/.*\/index(.*?)\.css/.test(next.attributes.href)) {
134
						return { ...acc, style: next };
135
					}
136
					return { ...acc, fonts: [...acc.fonts, next.attributes.href] };
137
				},
138
				{ fonts: [], style: undefined } as {
139
					fonts: string[];
140
					style: HTMLElement | undefined;
141
				}
142
			);
143

144
			writeFileSync(
145
				file_to_insert.filename,
146
				file_to_insert.source
147
					.replace("__ENTRY_CSS__", style!.attributes.href)
148
					.replace(
149
						'"__FONTS_CSS__"',
150
						`[${fonts.map((f) => `"${f}"`).join(",")}]`
151
					)
152
			);
153

154
			const share_html_location = join(config.dir, "share.html");
155
			const share_html = readFileSync(share_html_location, "utf8");
156
			const share_tree = parse(share_html);
157
			const node = Array.from(
158
				share_tree.querySelectorAll("link[rel=stylesheet]")
159
			).find((node) => /.*\/index(.*?)\.css/.test(node.attributes.href));
160

161
			if (!node) return;
162
			const transformed_html =
163
				share_html.substring(0, node.range[0]) +
164
				share_html.substring(node.range[1], share_html.length);
165

166
			writeFileSync(share_html_location, transformed_html);
167
		}
168
	};
169
}
170

171
// generate component importsy
172

173
import * as url from "url";
174
const __filename = url.fileURLToPath(import.meta.url);
175
const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
176

177
import { readdirSync, existsSync, readFileSync, statSync } from "fs";
178

179
function get_export_path(
180
	path: string,
181
	root: string,
182
	pkg_json: Record<string, any>
183
): string | undefined {
184
	if (!pkg_json.exports) return undefined;
185
	const _path = join(root, "..", `${pkg_json.exports[`${path}`]}`);
186

187
	return existsSync(_path) ? _path : undefined;
188
}
189

190
const ignore_list = [
191
	"tootils",
192
	"_cdn-test",
193
	"_spaces-test",
194
	"_website",
195
	"app",
196
	"atoms",
197
	"fallback",
198
	"icons",
199
	"lite",
200
	"preview",
201
	"simpledropdown",
202
	"simpleimage",
203
	"simpletextbox",
204
	"storybook",
205
	"theme",
206
	"timeseries",
207
	"tooltip",
208
	"upload",
209
	"utils",
210
	"wasm"
211
];
212
function generate_component_imports(): string {
213
	const exports = readdirSync(join(__dirname, ".."))
214
		.map((dir) => {
215
			if (ignore_list.includes(dir)) return undefined;
216
			if (!statSync(join(__dirname, "..", dir)).isDirectory()) return undefined;
217

218
			const package_json_path = join(__dirname, "..", dir, "package.json");
219
			if (existsSync(package_json_path)) {
220
				const package_json = JSON.parse(
221
					readFileSync(package_json_path, "utf8")
222
				);
223

224
				const component = get_export_path(".", package_json_path, package_json);
225
				const example = get_export_path(
226
					"./example",
227
					package_json_path,
228
					package_json
229
				);
230

231
				if (!component && !example) return undefined;
232

233
				return {
234
					name: package_json.name,
235
					component,
236
					example
237
				};
238
			}
239
			return undefined;
240
		})
241
		.filter((x) => x !== undefined);
242

243
	const imports = exports.reduce((acc, _export) => {
244
		if (!_export) return acc;
245

246
		const example = _export.example
247
			? `example: () => import("${_export.name}/example"),\n`
248
			: "";
249
		return `${acc}"${_export.name.replace("@gradio/", "")}": {
250
			${example}
251
			component: () => import("${_export.name}")
252
			},\n`;
253
	}, "");
254

255
	return imports;
256
}
257

258
function load_virtual_component_loader(): string {
259
	const loader_path = join(__dirname, "component_loader.js");
260
	const component_map = `
261
const component_map = {
262
	${generate_component_imports()}
263
};
264
`;
265
	return `${component_map}\n\n${readFileSync(loader_path, "utf8")}`;
266
}
267

268
export function inject_component_loader(): Plugin {
269
	const v_id = "virtual:component-loader";
270
	const resolved_v_id = "\0" + v_id;
271

272
	return {
273
		name: "inject-component-loader",
274
		enforce: "pre",
275
		resolveId(id: string) {
276
			if (id === v_id) return resolved_v_id;
277
		},
278
		load(id: string) {
279
			if (id === resolved_v_id) {
280
				return load_virtual_component_loader();
281
			}
282
		}
283
	};
284
}
285

286
export function resolve_svelte(enable: boolean): Plugin {
287
	return {
288
		enforce: "pre",
289
		name: "resolve-svelte",
290
		async resolveId(id: string) {
291
			if (!enable) return;
292

293
			if (
294
				id === "./svelte/svelte.js" ||
295
				id === "svelte" ||
296
				id === "svelte/internal"
297
			) {
298
				const mod = join(
299
					__dirname,
300
					"..",
301
					"..",
302
					"gradio",
303
					"templates",
304
					"frontend",
305
					"assets",
306
					"svelte",
307
					"svelte.js"
308
				);
309
				return { id: mod, external: "absolute" };
310
			}
311
		}
312
	};
313
}
314

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.