Astro Indonesia's unit price calculator - Userscript to display the unit price of items in Astro Indonesia's webstore
0
astro-unit-price.user.js
edited
1// ==UserScript==
2// @name Astro Indonesia - Unit price calculator
3// @description Displays the unit price of items in Astro Indonesia webstore
4// @namespace Violentmonkey Scripts
5// @author Angelo <me@angelo.fyi>
6// @icon
7// @version 0.0.1
8// @license AGPL-3.0-or-later
9//
10// @updateURL https://tangled.org/strings/angelo.fyi/3mm5rryhyuq22/raw
11// @supportURL mailto:me@angelo.fyi?subject=Astro%20Unit%20Price%20Question
12//
13// @include https://www.astronauts.id/*
14// @match https://www.astronauts.id/*
15// @grant none
16//
17// ==/UserScript==
18
19// TODO: Further filter pages
20// https://www.astronauts.id/c/produk-terbaru-123456789
21// https://www.astronauts.id/c/astro-basics-11065
22// https://www.astronauts.id/search?q=bawang
23const UNIT_REGEX = /(\d+)(?:-\d+)?(\w+)/;
24const ID_CURRENCY_LOCALE = new Intl.NumberFormat("id-ID", { style: "currency", currency: "IDR" });
25
26function renderUnitPrice() {
27 const items = document.querySelectorAll(".css-ks6u10");
28 for (const item of items) {
29 // Items that doesnt have units literally doesnt have the element
30 const unitEl = item.querySelector(".css-1nnfyv8");
31 if (unitEl == null) continue;
32 // Don't need to re-apply unit price to already calculated
33 if (item.querySelector("[data-unit-price]") != null) continue;
34
35 const priceEl = item.querySelector(".css-tg7xtj");
36 const priceString = priceEl.textContent;
37 const unitString = unitEl.textContent;
38
39 const price = Number.parseInt(priceString.replaceAll("Rp", "").replaceAll(".", ""));
40 let [_, unitCount, unitSymbol] = UNIT_REGEX.exec(unitString);
41
42 // Standardize units
43 switch (unitSymbol) {
44 // Weights
45 case "gram":
46 case "gr":
47 unitCount /= 1000;
48 unitSymbol = "kg";
49 break;
50
51 // Fluids
52 case "liter":
53 case "liters":
54 case "litre":
55 case "litres":
56 unitSymbol = "l";
57 break;
58 case "ml":
59 unitCount /= 1000;
60 unitSymbol = "l";
61 break;
62 case "oz":
63 unitCount *= 29.5735295625;
64 unitCount /= 1000;
65 unitSymbol = "l";
66 break;
67 }
68
69 // Remove plurals; probably too basic of a check
70 if (unitSymbol.endsWith("s")) unitSymbol = unitSymbol.slice(0, -1);
71
72 // Create & append unit price
73 const unitPriceEl = document.createElement("span");
74 unitPriceEl.setAttribute("data-unit-price", "true");
75 unitPriceEl.style = `font-size: 0.5rem;`;
76 unitPriceEl.className = "MuiTypography-root MuiTypography-caption-tiny";
77 unitPriceEl.innerText = `(${ID_CURRENCY_LOCALE.format(price / unitCount)}/${unitSymbol})`;
78 priceEl.append(unitPriceEl);
79 }
80}
81
82(function () {
83 // Mounted on <body>; dehydrated html doesn't contain any sensible HTML structure
84 new MutationObserver(renderUnitPrice).observe(document.querySelector("body"), { subtree: true, childList: true });
85})();