vite-plugin-millennium-skin 1.0.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/.prettierrc +7 -0
- package/.vscode/settings.json +3 -0
- package/eslint.config.mjs +29 -0
- package/package.json +57 -0
- package/src/ts/aliasModules.ts +15 -0
- package/src/ts/defaultMatch.ts +9 -0
- package/src/ts/defaultPatches.ts +82 -0
- package/src/ts/index.ts +507 -0
- package/src/ts/versionConfig.ts +2 -0
- package/src/types/babel.d.ts +1 -0
- package/src/types/global.d.ts +0 -0
- package/src/types/index.ts +1 -0
- package/src/types/skin.config.d.ts +86 -0
- package/tsconfig.json +25 -0
- package/vite.config.ts +39 -0
package/.prettierrc
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import js from "@eslint/js";
|
|
2
|
+
import tsPlugin from "@typescript-eslint/eslint-plugin";
|
|
3
|
+
import tsParser from "@typescript-eslint/parser";
|
|
4
|
+
import { defineConfig } from "eslint/config";
|
|
5
|
+
|
|
6
|
+
export default defineConfig([
|
|
7
|
+
js.configs.recommended,
|
|
8
|
+
{
|
|
9
|
+
files: ["**/*.{ts,tsx}"],
|
|
10
|
+
languageOptions: {
|
|
11
|
+
parser: tsParser,
|
|
12
|
+
parserOptions: {
|
|
13
|
+
project: "./tsconfig.json",
|
|
14
|
+
tsconfigRootDir: import.meta.dirname,
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
plugins: {
|
|
18
|
+
"@typescript-eslint": tsPlugin,
|
|
19
|
+
},
|
|
20
|
+
rules: {
|
|
21
|
+
...tsPlugin.configs.recommended.rules,
|
|
22
|
+
"no-undef": "off",
|
|
23
|
+
"@typescript-eslint/no-unused-vars": "error",
|
|
24
|
+
"@typescript-eslint/explicit-function-return-type": "off",
|
|
25
|
+
"@typescript-eslint/no-unsafe-function-type": "off",
|
|
26
|
+
"@typescript-eslint/no-explicit-any": "off",
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
]);
|
package/package.json
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "vite-plugin-millennium-skin",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"main": "index.js",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"directories": {
|
|
7
|
+
"test": "test"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"lint": "eslint . --ext .ts",
|
|
11
|
+
"build": "tsc --noEmit && cross-env RELEASE=beta vite build"
|
|
12
|
+
},
|
|
13
|
+
"repository": {
|
|
14
|
+
"type": "git",
|
|
15
|
+
"url": "git+https://github.com/bviibvii/Transparent-theme.git"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [],
|
|
18
|
+
"author": "",
|
|
19
|
+
"license": "ISC",
|
|
20
|
+
"bugs": {
|
|
21
|
+
"url": "https://github.com/bviibvii/Transparent-theme/issues"
|
|
22
|
+
},
|
|
23
|
+
"homepage": "https://github.com/bviibvii/Transparent-theme#readme",
|
|
24
|
+
"description": "",
|
|
25
|
+
"devDependencies": {
|
|
26
|
+
"@babel/preset-typescript": "^7.28.5",
|
|
27
|
+
"@types/babel__core": "^7.20.5",
|
|
28
|
+
"bestzip": "^2.2.1",
|
|
29
|
+
"eslint": "^9.39.2",
|
|
30
|
+
"globals": "^16.5.0",
|
|
31
|
+
"prettier": "^3.7.3",
|
|
32
|
+
"ts-loader": "^9.5.4",
|
|
33
|
+
"typescript": "^5.9.3",
|
|
34
|
+
"vite": "^7.2.7"
|
|
35
|
+
},
|
|
36
|
+
"eslintConfig": {
|
|
37
|
+
"env": {
|
|
38
|
+
"browser": true,
|
|
39
|
+
"node": true,
|
|
40
|
+
"es2021": true
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"@babel/core": "^7.28.5",
|
|
45
|
+
"@babel/generator": "^7.28.5",
|
|
46
|
+
"@babel/parser": "^7.28.5",
|
|
47
|
+
"@babel/traverse": "^7.28.5",
|
|
48
|
+
"@babel/types": "^7.28.5",
|
|
49
|
+
"@types/react": "^19.2.7",
|
|
50
|
+
"@types/react-dom": "^19.2.3",
|
|
51
|
+
"@typescript-eslint/eslint-plugin": "^8.50.1",
|
|
52
|
+
"babel-plugin-transform-typescript": "^7.0.0-alpha.19",
|
|
53
|
+
"chalk": "^5.6.2",
|
|
54
|
+
"cross-env": "^10.1.0",
|
|
55
|
+
"vite-plugin-dts": "^4.5.4"
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export const __DIRECT__ = 0;
|
|
2
|
+
export const __RUNTIME__ = 1;
|
|
3
|
+
|
|
4
|
+
export default [
|
|
5
|
+
{
|
|
6
|
+
method: __DIRECT__,
|
|
7
|
+
module: /^react$/g,
|
|
8
|
+
links: ["window", "opener", "SP_REACT"],
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
method: __DIRECT__,
|
|
12
|
+
module: /^react-dom$/g,
|
|
13
|
+
links: ["window", "opener", "SP_REACTDOM"],
|
|
14
|
+
},
|
|
15
|
+
];
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export const Root = /^SharedJSContext$/;
|
|
2
|
+
export const LibraryRoot = /^Steam$/;
|
|
3
|
+
export const MenuView = /^View Root Menu$/;
|
|
4
|
+
export const MenuSteam = /^Steam Root Menu$/;
|
|
5
|
+
export const MenuFriends = /^Friends Root Menu$/;
|
|
6
|
+
export const MenuGames = /^Games Root Menu$/;
|
|
7
|
+
export const MenuHelp = /^Help Root Menu$/;
|
|
8
|
+
export const MenuNotifications = /^Notifications Menu$/;
|
|
9
|
+
export const MenuAccount = /^Account Menu$/;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
export default [
|
|
2
|
+
{
|
|
3
|
+
Match: "https://.*.steampowered.com",
|
|
4
|
+
TargetCss: "webkit.css",
|
|
5
|
+
TargetJs: "webkit.js",
|
|
6
|
+
},
|
|
7
|
+
{
|
|
8
|
+
Match: "https://steamcommunity.com",
|
|
9
|
+
TargetCss: "webkit.css",
|
|
10
|
+
TargetJs: "webkit.js",
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
Match: "^Steam$",
|
|
14
|
+
TargetCss: "libraryroot.custom.css",
|
|
15
|
+
TargetJs: "libraryroot.custom.js",
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
Match: "^OverlayBrowser_Browser$",
|
|
19
|
+
TargetCss: "libraryroot.custom.css",
|
|
20
|
+
TargetJs: "libraryroot.custom.js",
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
Match: "^SP Overlay:",
|
|
24
|
+
TargetCss: "libraryroot.custom.css",
|
|
25
|
+
TargetJs: "libraryroot.custom.js",
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
Match: "Supernav$",
|
|
29
|
+
TargetCss: "libraryroot.custom.css",
|
|
30
|
+
TargetJs: "libraryroot.custom.js",
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
Match: "^notificationtoasts_",
|
|
34
|
+
TargetCss: "notifications.custom.css",
|
|
35
|
+
TargetJs: "notifications.custom.js",
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
Match: "^SteamBrowser_Find$",
|
|
39
|
+
TargetCss: "libraryroot.custom.css",
|
|
40
|
+
TargetJs: "libraryroot.custom.js",
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
Match: "^OverlayTab\\d+_Find$",
|
|
44
|
+
TargetCss: "libraryroot.custom.css",
|
|
45
|
+
TargetJs: "libraryroot.custom.js",
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
Match: "^Steam Big Picture Mode$",
|
|
49
|
+
TargetCss: "bigpicture.custom.css",
|
|
50
|
+
TargetJs: "bigpicture.custom.js",
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
Match: "^QuickAccess_",
|
|
54
|
+
TargetCss: "bigpicture.custom.css",
|
|
55
|
+
TargetJs: "bigpicture.custom.js",
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
Match: "^MainMenu_",
|
|
59
|
+
TargetCss: "bigpicture.custom.css",
|
|
60
|
+
TargetJs: "bigpicture.custom.js",
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
Match: ".friendsui-container",
|
|
64
|
+
TargetCss: "friends.custom.css",
|
|
65
|
+
TargetJs: "friends.custom.js",
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
Match: "Menu$",
|
|
69
|
+
TargetCss: "libraryroot.custom.css",
|
|
70
|
+
TargetJs: "libraryroot.custom.js",
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
Match: ".ModalDialogPopup",
|
|
74
|
+
TargetCss: "libraryroot.custom.css",
|
|
75
|
+
TargetJs: "libraryroot.custom.js",
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
Match: ".FullModalOverlay",
|
|
79
|
+
TargetCss: "libraryroot.custom.css",
|
|
80
|
+
TargetJs: "libraryroot.custom.js",
|
|
81
|
+
},
|
|
82
|
+
];
|
package/src/ts/index.ts
ADDED
|
@@ -0,0 +1,507 @@
|
|
|
1
|
+
import type { Plugin, ResolvedConfig, Logger, LogOptions } from "vite";
|
|
2
|
+
import type {
|
|
3
|
+
SkinConfig,
|
|
4
|
+
SkinConfigResult,
|
|
5
|
+
PatchResult,
|
|
6
|
+
bump_tag,
|
|
7
|
+
versionObject,
|
|
8
|
+
} from "../types/index";
|
|
9
|
+
import type { Statement, MemberExpression, Identifier } from "@babel/types";
|
|
10
|
+
import type { NodePath } from "@babel/traverse";
|
|
11
|
+
import t from "@babel/types";
|
|
12
|
+
import { parse } from "@babel/parser";
|
|
13
|
+
import traverse from "@babel/traverse";
|
|
14
|
+
import { generate } from "@babel/generator";
|
|
15
|
+
import path, { join } from "path/posix";
|
|
16
|
+
import { existsSync } from "fs";
|
|
17
|
+
import fsp from "fs/promises";
|
|
18
|
+
import { loadConfigFromFile } from "vite";
|
|
19
|
+
import chalk from "chalk";
|
|
20
|
+
import defaultPatches from "./defaultPatches";
|
|
21
|
+
import aliasModules, { __DIRECT__, __RUNTIME__ } from "./aliasModules";
|
|
22
|
+
import { __AUTO__, __PACKAGE__ } from "./versionConfig";
|
|
23
|
+
|
|
24
|
+
export * from "./aliasModules";
|
|
25
|
+
export * from "./defaultMatch";
|
|
26
|
+
export * from "./versionConfig";
|
|
27
|
+
|
|
28
|
+
const traver = (traverse as any).default as typeof traverse;
|
|
29
|
+
const SEMANTIC_VERSIONING_REGEXP =
|
|
30
|
+
/(?<major>0|[1-9]\d*)\.(?<minor>0|[1-9]\d*)\.(?<patch>0|[1-9]\d*)(?:-(?<preRelease>(?:[a-zA-Z1-9][a-zA-Z\d]*|0\d*[a-zA-Z][a-zA-Z\d]*|0)(?:\.(?:[a-zA-Z1-9][a-zA-Z\d]*|0\d*[a-zA-Z][a-zA-Z\d]*|0))*))?(?:\+(?<metadata>(?:[a-zA-Z\d-]*)(?:\.(?:[a-zA-Z\d-]*))*))?/;
|
|
31
|
+
const SEMANTIC_TAGS_REGEXP =
|
|
32
|
+
/(?:\.)?(?<tag>[a-zA-Z]+)\.(?<number>(?:[1-9]\d*|0\d*|0))/g;
|
|
33
|
+
|
|
34
|
+
export * from "../types/index";
|
|
35
|
+
|
|
36
|
+
let logger: Logger;
|
|
37
|
+
export default function millenniumSkin(): Plugin {
|
|
38
|
+
const jsMap: string[] = [];
|
|
39
|
+
const cssMap: string[] = [];
|
|
40
|
+
let skinConfig: SkinConfig;
|
|
41
|
+
let skinConfigResult: SkinConfigResult;
|
|
42
|
+
let viteConfig: ResolvedConfig;
|
|
43
|
+
return {
|
|
44
|
+
name: "vite-plugin-millennium-skin",
|
|
45
|
+
enforce: "pre",
|
|
46
|
+
|
|
47
|
+
async config(config) {
|
|
48
|
+
const res = await loadConfigFromFile(
|
|
49
|
+
{ command: "build", mode: "profuction" },
|
|
50
|
+
"skin.config.ts",
|
|
51
|
+
config.root,
|
|
52
|
+
);
|
|
53
|
+
if (res === null) new Error("can't find skin.config.ts from root");
|
|
54
|
+
skinConfig = res?.config as SkinConfig;
|
|
55
|
+
|
|
56
|
+
if (skinConfig.Patches === undefined) {
|
|
57
|
+
if (!skinConfig.UseDefaultPatches)
|
|
58
|
+
throw new Error("haven't any patch in skin.config.ts");
|
|
59
|
+
skinConfig.Patches = defaultPatches;
|
|
60
|
+
}
|
|
61
|
+
// 创建构建文件表
|
|
62
|
+
skinConfig.Patches.forEach((patch) => {
|
|
63
|
+
if (patch.TargetJs)
|
|
64
|
+
jsMap.push(join(skinConfig.srcJs, patch.TargetJs));
|
|
65
|
+
if (patch.TargetCss)
|
|
66
|
+
cssMap.push(
|
|
67
|
+
findCssModule(join(skinConfig.srcCss, patch.TargetCss)),
|
|
68
|
+
);
|
|
69
|
+
});
|
|
70
|
+
if (skinConfig.RootColors !== undefined)
|
|
71
|
+
cssMap.push(
|
|
72
|
+
findCssModule(
|
|
73
|
+
join(skinConfig.srcCss, skinConfig.RootColors),
|
|
74
|
+
),
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
return {
|
|
78
|
+
build: {
|
|
79
|
+
rollupOptions: {
|
|
80
|
+
input: [...jsMap, ...cssMap],
|
|
81
|
+
output: {
|
|
82
|
+
entryFileNames: "assets/js/[name].js",
|
|
83
|
+
assetFileNames: (info) => {
|
|
84
|
+
const name = info.names[0];
|
|
85
|
+
const file = path.parse(name);
|
|
86
|
+
if (file.ext === ".css")
|
|
87
|
+
return `assets/css/${name}`;
|
|
88
|
+
|
|
89
|
+
if (
|
|
90
|
+
/\.(png|jpg|jpeg|gif|svg|webp|bmp|heic)/i.test(
|
|
91
|
+
file.ext,
|
|
92
|
+
)
|
|
93
|
+
)
|
|
94
|
+
return `assets/images/${name}`;
|
|
95
|
+
return `assets/css/${name}`;
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
assetsInlineLimit: 0,
|
|
100
|
+
cssCodeSplit: true,
|
|
101
|
+
},
|
|
102
|
+
};
|
|
103
|
+
},
|
|
104
|
+
|
|
105
|
+
configResolved(config) {
|
|
106
|
+
viteConfig = config;
|
|
107
|
+
logger = config.logger;
|
|
108
|
+
},
|
|
109
|
+
|
|
110
|
+
generateBundle(_, bundles) {
|
|
111
|
+
if (skinConfig.Patches === undefined)
|
|
112
|
+
throw new Error("haven't any patch in building");
|
|
113
|
+
const root = viteConfig.root;
|
|
114
|
+
|
|
115
|
+
const patches: PatchResult[] = structuredClone(
|
|
116
|
+
skinConfig.Patches,
|
|
117
|
+
).map((e) => {
|
|
118
|
+
if (e.Match instanceof RegExp) e.Match = e.Match.source;
|
|
119
|
+
if (e.TargetJs) {
|
|
120
|
+
const parsed = path.parse(e.TargetJs);
|
|
121
|
+
e.TargetJs = join(
|
|
122
|
+
root,
|
|
123
|
+
skinConfig.srcJs,
|
|
124
|
+
parsed.dir,
|
|
125
|
+
parsed.name,
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
if (e.TargetCss) {
|
|
129
|
+
const parsed = path.parse(e.TargetCss);
|
|
130
|
+
e.TargetCss = join(
|
|
131
|
+
root,
|
|
132
|
+
skinConfig.srcCss,
|
|
133
|
+
parsed.dir,
|
|
134
|
+
parsed.name,
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
return {
|
|
138
|
+
MatchRegexString: e.Match,
|
|
139
|
+
TargetJs: e.TargetJs,
|
|
140
|
+
TargetCss: e.TargetCss,
|
|
141
|
+
};
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
Object.entries(bundles).forEach(([, bundle]) => {
|
|
145
|
+
const { type } = bundle;
|
|
146
|
+
|
|
147
|
+
const compileLib = bundle.fileName;
|
|
148
|
+
if (type === "chunk") {
|
|
149
|
+
const compileParsed = path.parse(
|
|
150
|
+
bundle.facadeModuleId as string,
|
|
151
|
+
);
|
|
152
|
+
const compilePath = join(
|
|
153
|
+
compileParsed.dir,
|
|
154
|
+
compileParsed.name,
|
|
155
|
+
);
|
|
156
|
+
patches.forEach((patch) => {
|
|
157
|
+
if (compilePath !== patch.TargetJs) return;
|
|
158
|
+
patch.TargetJs = compileLib;
|
|
159
|
+
});
|
|
160
|
+
} else {
|
|
161
|
+
const compileParsed = path.parse(
|
|
162
|
+
join(root, bundle.originalFileNames[0] as string),
|
|
163
|
+
);
|
|
164
|
+
const compilePath = join(
|
|
165
|
+
compileParsed.dir,
|
|
166
|
+
compileParsed.name,
|
|
167
|
+
);
|
|
168
|
+
patches.forEach((patch) => {
|
|
169
|
+
if (compilePath !== patch.TargetCss) return;
|
|
170
|
+
patch.TargetCss = compileLib;
|
|
171
|
+
});
|
|
172
|
+
if (
|
|
173
|
+
skinConfig.RootColors &&
|
|
174
|
+
compilePath ===
|
|
175
|
+
join(
|
|
176
|
+
viteConfig.root,
|
|
177
|
+
skinConfig.srcCss,
|
|
178
|
+
skinConfig.RootColors,
|
|
179
|
+
)
|
|
180
|
+
)
|
|
181
|
+
skinConfig.RootColors = compileLib;
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
skinConfigResult = {
|
|
187
|
+
...skinConfig,
|
|
188
|
+
Patches: patches,
|
|
189
|
+
version: "",
|
|
190
|
+
};
|
|
191
|
+
},
|
|
192
|
+
|
|
193
|
+
async writeBundle() {
|
|
194
|
+
const root = viteConfig.root;
|
|
195
|
+
const pkgPath = join(root, "package.json");
|
|
196
|
+
// 版本自动管理
|
|
197
|
+
try {
|
|
198
|
+
const pkg = JSON.parse(
|
|
199
|
+
await fsp.readFile(pkgPath, {
|
|
200
|
+
flag: "r",
|
|
201
|
+
encoding: "utf-8",
|
|
202
|
+
}),
|
|
203
|
+
);
|
|
204
|
+
if (
|
|
205
|
+
skinConfig.version === __AUTO__ ||
|
|
206
|
+
skinConfig.version === undefined
|
|
207
|
+
) {
|
|
208
|
+
const versions = await bump_version(
|
|
209
|
+
pkg.version,
|
|
210
|
+
process.env.RELEASE as any,
|
|
211
|
+
);
|
|
212
|
+
if (versions) {
|
|
213
|
+
const newVersion = versionObjToString(versions.new);
|
|
214
|
+
skinConfigResult.version = newVersion;
|
|
215
|
+
pkg.version = newVersion;
|
|
216
|
+
await fsp.writeFile(
|
|
217
|
+
pkgPath,
|
|
218
|
+
JSON.stringify(pkg, null, 4),
|
|
219
|
+
);
|
|
220
|
+
info(
|
|
221
|
+
`${versionObjToString(versions.native)} -> ${newVersion}`,
|
|
222
|
+
);
|
|
223
|
+
}
|
|
224
|
+
} else if (skinConfig.version === __PACKAGE__) {
|
|
225
|
+
skinConfigResult.version = pkg.version;
|
|
226
|
+
}
|
|
227
|
+
} catch (e) {
|
|
228
|
+
warn(`can't use package.json: ${e}`);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// 写入skin.json
|
|
232
|
+
try {
|
|
233
|
+
await fsp.writeFile(
|
|
234
|
+
join(root, viteConfig.build.outDir, "skin.json"),
|
|
235
|
+
JSON.stringify(skinConfigResult, null, 4),
|
|
236
|
+
);
|
|
237
|
+
} catch (e) {
|
|
238
|
+
throw new Error(`can't write skin.json: ${e}`);
|
|
239
|
+
}
|
|
240
|
+
},
|
|
241
|
+
|
|
242
|
+
transform(code, id) {
|
|
243
|
+
/**
|
|
244
|
+
* 别名处理, @see aliasModules
|
|
245
|
+
*/
|
|
246
|
+
if (!/.+\.(js|ts|tsx)$/g.test(id)) return;
|
|
247
|
+
|
|
248
|
+
const ast = parse(code, {
|
|
249
|
+
sourceType: "module",
|
|
250
|
+
plugins: ["typescript"],
|
|
251
|
+
});
|
|
252
|
+
traver(ast, {
|
|
253
|
+
Program(path) {
|
|
254
|
+
const body = path.node.body;
|
|
255
|
+
|
|
256
|
+
const runtimeLinks: Record<string, string[]> = {};
|
|
257
|
+
// 处理静态引入别名,收集动态引入别名
|
|
258
|
+
for (let i = body.length - 1; i >= 0; i--) {
|
|
259
|
+
let node = body[i];
|
|
260
|
+
if (!t.isImportDeclaration(node)) continue;
|
|
261
|
+
|
|
262
|
+
const moduleName: string = node.source.value;
|
|
263
|
+
|
|
264
|
+
const match: Statement[] = [];
|
|
265
|
+
for (const aliasMod of aliasModules) {
|
|
266
|
+
if (!aliasMod.module.test(moduleName)) continue;
|
|
267
|
+
const { method } = aliasMod;
|
|
268
|
+
|
|
269
|
+
for (const local of node.specifiers) {
|
|
270
|
+
const exportLocal = local.local.name;
|
|
271
|
+
let links: string[];
|
|
272
|
+
if (local.type === "ImportDefaultSpecifier")
|
|
273
|
+
// 默认导出
|
|
274
|
+
links = aliasMod.links;
|
|
275
|
+
else
|
|
276
|
+
// 指定导出
|
|
277
|
+
links = [
|
|
278
|
+
...aliasMod.links,
|
|
279
|
+
(local as any).imported.name,
|
|
280
|
+
];
|
|
281
|
+
|
|
282
|
+
switch (method) {
|
|
283
|
+
case __RUNTIME__:
|
|
284
|
+
runtimeLinks[exportLocal] =
|
|
285
|
+
aliasMod.links;
|
|
286
|
+
break;
|
|
287
|
+
case __DIRECT__:
|
|
288
|
+
match.push(
|
|
289
|
+
generateConstDeclaration(
|
|
290
|
+
exportLocal,
|
|
291
|
+
links,
|
|
292
|
+
),
|
|
293
|
+
);
|
|
294
|
+
break;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
body.splice(i, 1, ...match);
|
|
299
|
+
}
|
|
300
|
+
// 处理动态引入
|
|
301
|
+
Object.entries(runtimeLinks).forEach(
|
|
302
|
+
([localName, runtimeLink]) => {
|
|
303
|
+
const binding = path.scope.getBinding(localName);
|
|
304
|
+
if (binding === undefined) return;
|
|
305
|
+
|
|
306
|
+
binding.referencePaths.forEach((refPath) => {
|
|
307
|
+
replaceRef(refPath, localName, runtimeLink);
|
|
308
|
+
});
|
|
309
|
+
binding.scope.removeOwnBinding(localName);
|
|
310
|
+
},
|
|
311
|
+
);
|
|
312
|
+
},
|
|
313
|
+
});
|
|
314
|
+
const result = generate(ast);
|
|
315
|
+
return { code: result.code };
|
|
316
|
+
},
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
export function defineConfig(SkinConfig: SkinConfig): SkinConfig {
|
|
321
|
+
return SkinConfig;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
function generateConstDeclaration(moduleName: string, links: string[]) {
|
|
325
|
+
let expression: t.Identifier | t.MemberExpression = t.identifier(links[0]);
|
|
326
|
+
for (let i = 1; i < links.length; i++) {
|
|
327
|
+
expression = t.memberExpression(expression, t.identifier(links[i]));
|
|
328
|
+
}
|
|
329
|
+
const declarator = t.variableDeclarator(
|
|
330
|
+
t.identifier(moduleName),
|
|
331
|
+
expression,
|
|
332
|
+
);
|
|
333
|
+
return t.variableDeclaration("const", [declarator]);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
function findCssModule(cssPath: string): string {
|
|
337
|
+
const parsed = path.parse(cssPath);
|
|
338
|
+
if (parsed.ext !== "") return cssPath;
|
|
339
|
+
|
|
340
|
+
for (const ext of ["scss", "sass", "css"]) {
|
|
341
|
+
const newPath = `${cssPath}.${ext}`;
|
|
342
|
+
if (!existsSync(join(process.cwd(), newPath))) continue;
|
|
343
|
+
return newPath;
|
|
344
|
+
}
|
|
345
|
+
throw new Error(`can't find css module: ${cssPath}`);
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
function replaceRef(refPath: NodePath, localName: string, globalObj: string[]) {
|
|
349
|
+
const parent = refPath.parent;
|
|
350
|
+
|
|
351
|
+
if (t.isMemberExpression(parent) && parent.object === refPath.node) {
|
|
352
|
+
const prop = parent.property;
|
|
353
|
+
if (t.isIdentifier(prop)) {
|
|
354
|
+
const globalMember = createNestedMemberExpression(globalObj);
|
|
355
|
+
if (!refPath.parentPath) return;
|
|
356
|
+
refPath.parentPath.replaceWith(
|
|
357
|
+
t.memberExpression(globalMember, t.identifier(prop.name)),
|
|
358
|
+
);
|
|
359
|
+
}
|
|
360
|
+
return;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
if (refPath.isIdentifier()) {
|
|
364
|
+
const globalMember = createNestedMemberExpression(globalObj);
|
|
365
|
+
refPath.replaceWith(
|
|
366
|
+
t.memberExpression(globalMember, t.identifier(localName)),
|
|
367
|
+
);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
function createNestedMemberExpression(globalObj: string[]): t.MemberExpression {
|
|
372
|
+
if (globalObj.length === 0) {
|
|
373
|
+
throw new Error("globalObj must not be empty");
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
let node: Identifier | MemberExpression = t.identifier(globalObj[0]);
|
|
377
|
+
for (let i = 1; i < globalObj.length; i++) {
|
|
378
|
+
node = t.memberExpression(node, t.identifier(globalObj[i]));
|
|
379
|
+
}
|
|
380
|
+
return node as t.MemberExpression;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
async function bump_version(nativeVersion: string, tag: bump_tag = "snapshot") {
|
|
384
|
+
try {
|
|
385
|
+
const match = SEMANTIC_VERSIONING_REGEXP.exec(nativeVersion);
|
|
386
|
+
|
|
387
|
+
if (!match?.groups) {
|
|
388
|
+
warn(`can't understand version: ${nativeVersion}`);
|
|
389
|
+
return;
|
|
390
|
+
}
|
|
391
|
+
let version: versionObject = {
|
|
392
|
+
major: parseInt(match.groups.major),
|
|
393
|
+
minor: parseInt(match.groups.minor),
|
|
394
|
+
patch: parseInt(match.groups.patch),
|
|
395
|
+
};
|
|
396
|
+
|
|
397
|
+
if (match.groups.preRelease) {
|
|
398
|
+
const tagsMatch = [
|
|
399
|
+
...match.groups.preRelease.matchAll(SEMANTIC_TAGS_REGEXP),
|
|
400
|
+
];
|
|
401
|
+
tagsMatch.forEach((e) => {
|
|
402
|
+
if (!e.groups) return;
|
|
403
|
+
(version as any)[e.groups.tag] = parseInt(e.groups.number);
|
|
404
|
+
});
|
|
405
|
+
}
|
|
406
|
+
const nativeVersionObj = { ...version };
|
|
407
|
+
switch (tag) {
|
|
408
|
+
case null:
|
|
409
|
+
break;
|
|
410
|
+
case undefined:
|
|
411
|
+
break;
|
|
412
|
+
case "major":
|
|
413
|
+
version = {
|
|
414
|
+
major: version.major + 1,
|
|
415
|
+
minor: 0,
|
|
416
|
+
patch: 0,
|
|
417
|
+
};
|
|
418
|
+
break;
|
|
419
|
+
case "minor":
|
|
420
|
+
version = {
|
|
421
|
+
major: version.major,
|
|
422
|
+
minor: version.minor + 1,
|
|
423
|
+
patch: 0,
|
|
424
|
+
};
|
|
425
|
+
break;
|
|
426
|
+
case "patch":
|
|
427
|
+
version = {
|
|
428
|
+
major: version.major,
|
|
429
|
+
minor: version.minor,
|
|
430
|
+
patch: version.patch + 1,
|
|
431
|
+
};
|
|
432
|
+
break;
|
|
433
|
+
case "rc":
|
|
434
|
+
version.rc = (version.rc ?? 0) + 1;
|
|
435
|
+
delete version.gamma;
|
|
436
|
+
delete version.beta;
|
|
437
|
+
delete version.preview;
|
|
438
|
+
delete version.alpha;
|
|
439
|
+
delete version.snapshot;
|
|
440
|
+
break;
|
|
441
|
+
case "gamma":
|
|
442
|
+
version.gamma = (version.gamma ?? 0) + 1;
|
|
443
|
+
delete version.beta;
|
|
444
|
+
delete version.preview;
|
|
445
|
+
delete version.alpha;
|
|
446
|
+
delete version.snapshot;
|
|
447
|
+
break;
|
|
448
|
+
case "beta":
|
|
449
|
+
version.beta = (version.beta ?? 0) + 1;
|
|
450
|
+
delete version.preview;
|
|
451
|
+
delete version.alpha;
|
|
452
|
+
delete version.snapshot;
|
|
453
|
+
break;
|
|
454
|
+
case "preview":
|
|
455
|
+
version.preview = (version.preview ?? 0) + 1;
|
|
456
|
+
delete version.alpha;
|
|
457
|
+
delete version.snapshot;
|
|
458
|
+
break;
|
|
459
|
+
case "alpha":
|
|
460
|
+
version.alpha = (version.alpha ?? 0) + 1;
|
|
461
|
+
delete version.snapshot;
|
|
462
|
+
break;
|
|
463
|
+
case "snapshot":
|
|
464
|
+
version.snapshot = (version.snapshot ?? 0) + 1;
|
|
465
|
+
break;
|
|
466
|
+
}
|
|
467
|
+
return {
|
|
468
|
+
native: nativeVersionObj,
|
|
469
|
+
new: version,
|
|
470
|
+
};
|
|
471
|
+
} catch (e) {
|
|
472
|
+
warn(`can't bump version: ${e}`);
|
|
473
|
+
}
|
|
474
|
+
return undefined;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
function versionObjToString(version: versionObject) {
|
|
478
|
+
let versionString = `${version.major}.${version.minor}.${version.patch}`;
|
|
479
|
+
|
|
480
|
+
const optionalFields: (keyof Omit<
|
|
481
|
+
versionObject,
|
|
482
|
+
"major" | "minor" | "patch"
|
|
483
|
+
>)[] = ["rc", "gamma", "beta", "preview", "alpha", "snapshot"];
|
|
484
|
+
|
|
485
|
+
let first = false;
|
|
486
|
+
for (const field of optionalFields) {
|
|
487
|
+
const value = version[field];
|
|
488
|
+
if (value !== undefined && value !== null) {
|
|
489
|
+
if (!first) {
|
|
490
|
+
versionString += `-${field}.${value}`;
|
|
491
|
+
first = true;
|
|
492
|
+
} else versionString += `.${field}.${value}`;
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
return versionString;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
function warn(msg: string, options?: LogOptions) {
|
|
499
|
+
if (logger) logger.warn(chalk.yellow(`[MillenniumSkin] ${msg}`), options);
|
|
500
|
+
else console.warn(chalk.yellow(`[MillenniumSkin] ${msg}`));
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
function info(msg: string, options?: LogOptions) {
|
|
504
|
+
if (logger)
|
|
505
|
+
logger.info(chalk.greenBright(`[MillenniumSkin] ${msg}`), options);
|
|
506
|
+
else console.log(chalk.greenBright(`[MillenniumSkin] ${msg}`));
|
|
507
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
declare module "@babel/core";
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type * from "./skin.config";
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
export interface SkinConfig {
|
|
2
|
+
name: string;
|
|
3
|
+
description: string;
|
|
4
|
+
author: string;
|
|
5
|
+
version?: versionConfig;
|
|
6
|
+
tags?: string[];
|
|
7
|
+
header_image: string;
|
|
8
|
+
splash_image: string;
|
|
9
|
+
github: {
|
|
10
|
+
owner: string;
|
|
11
|
+
repo_name: string;
|
|
12
|
+
};
|
|
13
|
+
discord_support?: {
|
|
14
|
+
inviteCodeExcludingLink?: string;
|
|
15
|
+
};
|
|
16
|
+
"Steam-WebKit"?: string;
|
|
17
|
+
UseDefaultPatches?: boolean;
|
|
18
|
+
RootColors?: string;
|
|
19
|
+
Patches?: Patch[];
|
|
20
|
+
srcJs: string;
|
|
21
|
+
srcCss: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface SkinConfigResult {
|
|
25
|
+
name: string;
|
|
26
|
+
description: string;
|
|
27
|
+
author: string;
|
|
28
|
+
version: string;
|
|
29
|
+
header_image: string;
|
|
30
|
+
splash_image: string;
|
|
31
|
+
github: {
|
|
32
|
+
owner: string;
|
|
33
|
+
repo_name: string;
|
|
34
|
+
};
|
|
35
|
+
RootColors?: string;
|
|
36
|
+
Patches: PatchResult[];
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface Patch {
|
|
40
|
+
Match: string | RegExp;
|
|
41
|
+
TargetCss?: string;
|
|
42
|
+
TargetJs?: string;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export interface PatchResult {
|
|
46
|
+
MatchRegexString: string;
|
|
47
|
+
TargetCss?: string;
|
|
48
|
+
TargetJs?: string;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export type namedExports = namedExport[];
|
|
52
|
+
|
|
53
|
+
export type namedExport = {
|
|
54
|
+
exportLocal: string;
|
|
55
|
+
links: string[];
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
export type bump_tag =
|
|
59
|
+
| null
|
|
60
|
+
| undefined
|
|
61
|
+
| "major"
|
|
62
|
+
| "minor"
|
|
63
|
+
| "patch"
|
|
64
|
+
| "rc"
|
|
65
|
+
| "gamma"
|
|
66
|
+
| "beta"
|
|
67
|
+
| "preview"
|
|
68
|
+
| "alpha"
|
|
69
|
+
| "snapshot";
|
|
70
|
+
|
|
71
|
+
export type versionObject = {
|
|
72
|
+
major: number;
|
|
73
|
+
minor: number;
|
|
74
|
+
patch: number;
|
|
75
|
+
rc?: number;
|
|
76
|
+
gamma?: number;
|
|
77
|
+
beta?: number;
|
|
78
|
+
preview?: number;
|
|
79
|
+
alpha?: number;
|
|
80
|
+
snapshot?: number;
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
export enum versionConfig {
|
|
84
|
+
auto,
|
|
85
|
+
package,
|
|
86
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"jsx": "react-jsx",
|
|
4
|
+
"module": "esnext",
|
|
5
|
+
"target": "es2020",
|
|
6
|
+
"lib": [
|
|
7
|
+
"ES2015",
|
|
8
|
+
"DOM"
|
|
9
|
+
],
|
|
10
|
+
"moduleResolution": "bundler",
|
|
11
|
+
"esModuleInterop": true,
|
|
12
|
+
"allowSyntheticDefaultImports": true,
|
|
13
|
+
"strict": true,
|
|
14
|
+
"skipLibCheck": true,
|
|
15
|
+
"resolveJsonModule": true,
|
|
16
|
+
"typeRoots": [
|
|
17
|
+
"./node_modules/@types/**/*.d.ts"
|
|
18
|
+
],
|
|
19
|
+
"paths": {
|
|
20
|
+
"react": [
|
|
21
|
+
"./src/types/globalModules.d.ts"
|
|
22
|
+
]
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
package/vite.config.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { defineConfig } from "vite";
|
|
2
|
+
import { resolve } from "path";
|
|
3
|
+
import aaa from "./src/ts/index";
|
|
4
|
+
import dts from "vite-plugin-dts";
|
|
5
|
+
|
|
6
|
+
const rg: any = {
|
|
7
|
+
build: {
|
|
8
|
+
ssr: true,
|
|
9
|
+
lib: {
|
|
10
|
+
entry: resolve(__dirname, "src/ts/index.ts"),
|
|
11
|
+
name: "VitePluginMillenniumSkin",
|
|
12
|
+
fileName: "index",
|
|
13
|
+
formats: ["es"],
|
|
14
|
+
},
|
|
15
|
+
outDir: "dist",
|
|
16
|
+
emptyOutDir: true,
|
|
17
|
+
rollupOptions: {
|
|
18
|
+
external: ["vite"],
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
plugins: [
|
|
22
|
+
dts({
|
|
23
|
+
insertTypesEntry: true,
|
|
24
|
+
}),
|
|
25
|
+
],
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const rt: any = {
|
|
29
|
+
build: {
|
|
30
|
+
outDir: "dist",
|
|
31
|
+
emptyOutDir: true,
|
|
32
|
+
rollupOptions: {
|
|
33
|
+
external: ["vite"],
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
plugins: [aaa()],
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export default defineConfig(rg);
|