Skip to content

Commit 75d2984

Browse files
committed
unrounded stars
1 parent cf893ac commit 75d2984

File tree

6 files changed

+161
-2
lines changed

6 files changed

+161
-2
lines changed

lib/content.js

+15-1
Original file line numberDiff line numberDiff line change
@@ -1 +1,15 @@
1-
console.log('Hello, world!');
1+
import scanElement from './scanElement.js';
2+
3+
async function observe(mutations) {
4+
for (const mutation of mutations) {
5+
for (const node of mutation.addedNodes) {
6+
await scanElement(node);
7+
}
8+
}
9+
}
10+
11+
const observer = new MutationObserver(observe);
12+
observer.observe(document.body, {
13+
subtree: true,
14+
childList: true
15+
});

lib/patches/unroundedStars.js

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import runOnPage from '../runOnPage.js';
2+
import { fiber, state, nth } from '../react.js';
3+
4+
export default async function patch(stats) {
5+
const bg = stats.closest('.Modal-Background');
6+
const { player } = await runOnPage(async (bg, fiber, state, nth) => {
7+
return state(nth(fiber(bg), 2));
8+
})(bg, fiber, state, nth);
9+
for (const line of stats.querySelectorAll('.Player-Info-Line')) {
10+
const header = line.querySelector('.Player-Info-Line-Header').textContent;
11+
12+
const addRating = rating => {
13+
const stars = rating * 5;
14+
const rawStars = document.createElement('div');
15+
rawStars.textContent = stars.toFixed(2);
16+
rawStars.title = stars.toString();
17+
line.style.gridTemplateColumns = '180px auto min-content';
18+
line.append(rawStars);
19+
};
20+
21+
switch (header) {
22+
case 'Batting':
23+
addRating(player.hittingRating);
24+
break;
25+
case 'Pitching':
26+
addRating(player.pitchingRating);
27+
break;
28+
case 'Baserunning':
29+
addRating(player.baserunningRating);
30+
break;
31+
case 'Defense':
32+
addRating(player.defenseRating);
33+
break;
34+
}
35+
}
36+
}

lib/react.js

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
export function fiber(node) {
2+
for (const key in node) {
3+
if (key.startsWith('__reactInternalInstance$')) {
4+
return node[key];
5+
}
6+
}
7+
}
8+
9+
export function state(fiber) {
10+
if (fiber.memoizedState.memoizedState) {
11+
return fiber.memoizedState.memoizedState;
12+
} else {
13+
return fiber.memoizedState.baseQueue.eagerState;
14+
}
15+
}
16+
17+
export function nth(fiber, n) {
18+
for (let i = 0; i < n; i++) {
19+
fiber = fiber.return;
20+
}
21+
22+
return fiber;
23+
}

lib/runOnPage.js

+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import _ from 'lodash';
2+
3+
const makeIdent = () => _.times(20, () => _.random(35).toString(36)).join('');
4+
5+
export default function runOnPage(func) {
6+
return (...args) => new Promise((resolve, reject) => {
7+
const ident = makeIdent();
8+
9+
function onMessage(event) {
10+
if (event.source !== window) return;
11+
12+
if (event.data.ident && event.data.ident === ident) {
13+
window.removeEventListener('message', onMessage);
14+
if ('ret' in event.data) {
15+
resolve(event.data.ret);
16+
} else {
17+
reject(event.data.err);
18+
}
19+
}
20+
}
21+
22+
const serializedArgs = args.map(x => {
23+
if (x instanceof Element) {
24+
if (x.id) {
25+
return { id: x.id };
26+
} else {
27+
x.id = makeIdent();
28+
return { tempId: x.id };
29+
}
30+
} else if (typeof x === 'function') {
31+
return { func: x.toString() };
32+
} else {
33+
return { val: x };
34+
}
35+
});
36+
37+
window.addEventListener('message', onMessage);
38+
39+
const serialized = func.toString();
40+
41+
const scriptContent = `
42+
(async () => {
43+
try {
44+
const serializedArgs = ${JSON.stringify(serializedArgs)};
45+
const args = serializedArgs.map(x => {
46+
if ('id' in x) {
47+
return document.getElementById(x.id);
48+
} else if ('tempId' in x) {
49+
const elem = document.getElementById(x.tempId);
50+
elem.id = '';
51+
return elem;
52+
} else if ('func' in x) {
53+
const generate = new Function('return ' + x.func);
54+
return generate();
55+
} else {
56+
return x.val;
57+
}
58+
});
59+
const ret = await (${serialized})(...args);
60+
window.postMessage({ ident: ${JSON.stringify(ident)}, ret });
61+
} catch (err) {
62+
console.error(err);
63+
window.postMessage({ ident: ${JSON.stringify(ident)}, err });
64+
}
65+
})();
66+
document.currentScript.parentElement.removeChild(document.currentScript);
67+
`;
68+
69+
const script = document.createElement('script');
70+
script.innerHTML = scriptContent;
71+
document.documentElement.prepend(script);
72+
});
73+
}

lib/scanElement.js

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import unroundedStars from './patches/unroundedStars.js';
2+
3+
export default async function scanElement(elem) {
4+
if (!elem.classList || !elem.classList.contains) return;
5+
6+
if (elem.classList.contains('ModalItem-Content')) {
7+
await Promise.all(Array.from(elem.children, x => scanElement(x)));
8+
} else if (elem.classList.contains('Player-Info-Stats')) {
9+
await unroundedStars(elem);
10+
}
11+
}

package.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
"webpack": "^5.23.0",
2323
"webpack-cli": "^4.5.0"
2424
},
25-
"dependencies": {},
25+
"dependencies": {
26+
"lodash": "^4.17.20"
27+
},
2628
"type": "module"
2729
}

0 commit comments

Comments
 (0)