├── .gitattributes ├── README.md ├── manifest.json └── background.js /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # How to use 2 | - Go to chrome://extensions/ 3 | - Open developer mode in right top corner 4 | - Click "Load unpacked" 5 | - Select this folder 6 | - Have a nice day 7 | -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "HN Mini Avatars", 3 | "description": "Hey", 4 | "version": "1.0", 5 | "manifest_version": 2, 6 | 7 | "background": { 8 | "scripts": ["background.js"], 9 | "persistent": false 10 | }, 11 | "content_scripts": [ 12 | { 13 | "matches": [ 14 | "https://news.ycombinator.com/item*", 15 | "https://news.ycombinator.com/user*" 16 | ], 17 | "js": ["background.js"] 18 | } 19 | ], 20 | "permissions": ["tabs", "http://*/*", "https://*/*", "activeTab"] 21 | } 22 | -------------------------------------------------------------------------------- /background.js: -------------------------------------------------------------------------------- 1 | let observer = new IntersectionObserver( 2 | (entries) => { 3 | entries.forEach((entry, i) => { 4 | if (entry.isIntersecting) { 5 | const p = 2; 6 | const c = document.createElement("canvas"); 7 | const x = c.getContext("2d"); 8 | c.width = 18; 9 | c.height = 14; 10 | const s = entry.target.innerText; 11 | const r = 1; 12 | 13 | if (s) { 14 | for ( 15 | let s = entry.target.innerText, r = 1, i = 28 + s.length; 16 | i--; 17 | 18 | ) { 19 | // xorshift32 20 | (r ^= r << 13), (r ^= r >>> 17), (r ^= r << 5); 21 | const X = i & 3, 22 | Y = i >> 2; 23 | if (i >= 28) { 24 | // seed state 25 | r += s.charCodeAt(i - 28); 26 | x.fillStyle = 27 | "#" + ((r >> 8) & 0xffffff).toString(16).padStart(0, 6); 28 | } else { 29 | // draw pixel 30 | if (r >>> 29 > (X * X) / 3 + Y / 2) 31 | x.fillRect(p * 3 + p * X, p * Y, p, p), 32 | x.fillRect(p * 3 - p * X, p * Y, p, p); 33 | } 34 | } 35 | } 36 | 37 | entry.target.prepend(c); 38 | } else { 39 | if (entry.target.firstChild.tagName === "CANVAS") 40 | entry.target.firstChild.remove(); 41 | } 42 | }); 43 | }, 44 | { rootMargin: "0px 0px 0px 0px" } 45 | ); 46 | 47 | document.querySelectorAll(".hnuser").forEach((user) => { 48 | observer.observe(user); 49 | }); 50 | --------------------------------------------------------------------------------