Skip to content

Commit 1d8ed58

Browse files
committed
replace css class name with the ones that are exported
1 parent c34aae9 commit 1d8ed58

File tree

2 files changed

+178
-0
lines changed

2 files changed

+178
-0
lines changed

generate_readable_css.mjs

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
import { readFile, writeFile, readdir as readDir, rm, mkdir } from "node:fs/promises";
2+
import { parse, latestEcmaVersion } from "espree";
3+
import { traverse, Syntax } from "estraverse";
4+
import { resolve as pathResolve, basename, dirname, join } from "node:path";
5+
import { fileURLToPath } from "node:url";
6+
7+
const classRegex = /(\.[a-zA-Z0-9_-]+)/g;
8+
9+
const __dirname = dirname(fileURLToPath(import.meta.url));
10+
11+
12+
async function ParseJsFile(file, classNames) {
13+
if (file.endsWith("licenses.js")) {
14+
return;
15+
}
16+
//TODO remove later
17+
if (file.includes("/c.")) {
18+
return;
19+
}
20+
21+
try {
22+
const code = await readFile(file);
23+
const ast = parse(code, {
24+
ecmaVersion: latestEcmaVersion,
25+
sourceType: "module",
26+
loc: true,
27+
});
28+
29+
traverse(ast, {
30+
enter: (node) => {
31+
if (
32+
node.type === Syntax.AssignmentExpression &&
33+
node.left.type === Syntax.MemberExpression &&
34+
node.left.property.type === Syntax.Identifier &&
35+
node.left.property.name === "exports" &&
36+
node.right.type === Syntax.ObjectExpression &&
37+
node.right.properties.constructor === Array
38+
) {
39+
for (const array_node of node.right.properties) {
40+
if (array_node.value.type !== Syntax.Literal || isNumber(String(array_node.value.value), 2)) {
41+
continue;
42+
}
43+
const value = array_node.key.name ?? array_node.key.value;
44+
if (!Object.hasOwn(classNames, array_node.value.value)) {
45+
classNames[array_node.value.value] = value;
46+
} else {
47+
if (!classNames[array_node.value.value]?.includes(value)) {
48+
classNames[array_node.value.value] = `${classNames[array_node.value.value]}|${value}`;
49+
}
50+
}
51+
}
52+
}
53+
},
54+
});
55+
} catch (e) {
56+
console.error(`Unable to parse "${file}":`, e);
57+
}
58+
}
59+
60+
async function FixCssFile(path, classNames) {
61+
try {
62+
const css = (await readFile(path)).toString();
63+
let output = css;
64+
const matches = [...new Set(css.match(classRegex))];
65+
if (matches) {
66+
for (const match of matches) {
67+
if (Object.hasOwn(classNames, match.slice(1))) {
68+
// replacing by multiple classes creates non valid css but it makes it easy to detect issues
69+
output = output.replaceAll(match, `.${classNames[match.slice(1)]}`);
70+
}
71+
}
72+
}
73+
let outputPath
74+
if (path.includes("/ClientExtracted/")) {
75+
outputPath = join(dirname(path), "/c.", basename(path));
76+
77+
}
78+
outputPath = join(__dirname, "/c/", path.replace(__dirname, ""));
79+
80+
if (output !== css) {
81+
await mkdir(dirname(outputPath), { recursive: true });
82+
await writeFile(outputPath, output);
83+
} else {
84+
// best effort to clean our mess if we did some,
85+
// although it might have some problematic effect if the Js parse part stops working at some point in time
86+
await rm(outputPath, { force: true });
87+
}
88+
} catch (e) {
89+
console.error(`Unable to fix "${path}":`, e);
90+
}
91+
}
92+
93+
async function* GetRecursiveFiles(dir, ext) {
94+
const dirents = await readDir(dir, { withFileTypes: true });
95+
for (const dirent of dirents) {
96+
const res = pathResolve(dir, dirent.name);
97+
if (dirent.isDirectory()) {
98+
yield* GetRecursiveFiles(res, ext);
99+
} else if (dirent.isFile() && dirent.name.endsWith(ext)) {
100+
yield res;
101+
}
102+
}
103+
}
104+
105+
// Why is this not working?
106+
// function isNumber(string, nbrRecursiceSlice = 0) {
107+
// return !Number.isNaN(Number(string)) || (string.length > 0 && nbrRecursiceSlice > 0 ) ? isNumber(string.slice(0,-1), nbrRecursiceSlice - 1) : false;
108+
// }
109+
110+
// best effort to guess if a string is a number (tries to remove the unit at the end)
111+
function isNumber(string, nbrRecursiceSlice) {
112+
while (string.length > 0 && nbrRecursiceSlice > 0) {
113+
if (Number.isNaN(Number(string))) {
114+
string = string.slice(0, -1);
115+
} else {
116+
return true;
117+
}
118+
}
119+
return false;
120+
}
121+
122+
async function cleanPreviousRun(cssPath) {
123+
try {
124+
125+
const rmPath = join(__dirname, "/c/", cssPath, "/**.css");
126+
127+
await rm(rmPath, { force: true });
128+
} catch (e) {
129+
console.error(`Unable to clean "${cssPath}":`, e);
130+
}
131+
}
132+
133+
let paths;
134+
if (process.argv.length > 3) {
135+
paths = [process.argv[2]];
136+
}
137+
else {
138+
paths = [
139+
"./Scripts/WebUI/",
140+
"./ClientExtracted/",
141+
"./help.steampowered.com/",
142+
"./partner.steamgames.com/",
143+
"./steamcommunity.com/",
144+
"./store.steampowered.com/",
145+
"./www.dota2.com/",
146+
"./www.underlords.com/",
147+
"./www.counter-strike.net/",
148+
];
149+
}
150+
151+
152+
for (const path of paths) {
153+
const classNames = {};
154+
155+
cleanPreviousRun(path);
156+
157+
for await (const file of GetRecursiveFiles(path, ".js")) {
158+
await ParseJsFile(file, classNames);
159+
}
160+
161+
for await (const file of GetRecursiveFiles(path, ".css")) {
162+
await FixCssFile(file, classNames);
163+
}
164+
}

update.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ class SteamTracker
3030
private bool $ExtractClientArchives = false;
3131
private bool $SyncProtobufs = false;
3232
private bool $DumpJavascriptFiles = false;
33+
private bool $FixCssFiles = false;
3334
private bool $UpdateManifestUrls = false;
3435
private bool $UpdateSSRUrls = false;
3536

@@ -181,6 +182,7 @@ public function __construct( string $Option )
181182
{
182183
$this->Log( '{lightblue}Extracting client archives' );
183184
$this->DumpJavascriptFiles = true;
185+
$this->FixCssFiles = true;
184186
$this->SyncProtobufs = true;
185187

186188
system( 'bash extract_client.sh' );
@@ -196,6 +198,13 @@ public function __construct( string $Option )
196198
system( 'node dump_javascript_urls.mjs' );
197199
}
198200

201+
if( $this->FixCssFiles )
202+
{
203+
$this->Log( '{lightblue}Fixing CSS files' );
204+
205+
system( 'node generate_readable_css.mjs' );
206+
}
207+
199208
if( $this->SyncProtobufs )
200209
{
201210
$this->Log( '{lightblue}Syncing protobufs' );
@@ -604,6 +613,11 @@ private function HandleResponse( string $File, string $Data, string $URL ) : boo
604613

605614
system( 'npm run prettier ' . escapeshellarg( $File ) );
606615

616+
if( str_ends_with( $File, '.css' ) || str_ends_with( $File, '.js' ) )
617+
{
618+
$this->FixCssFiles = true;
619+
}
620+
607621
return true;
608622
}
609623

0 commit comments

Comments
 (0)