| import Papa from "papaparse"; |
|
|
| export async function loadExtensionsCSV(path, fetchOptions = {}) { |
| const url = path + (path.includes("?") ? "&" : "?") + "t=" + Date.now(); |
| const res = await fetch(url, fetchOptions); |
| if (!res.ok) |
| throw new Error(`Failed to load CSV: ${res.status} ${res.statusText}`); |
| const text = await res.text(); |
| const { data } = Papa.parse(text, { |
| header: true, |
| skipEmptyLines: true, |
| transformHeader: (header) => header.trim(), |
| }); |
| return { rows: data.map(normalizeRow) }; |
| } |
|
|
| function normalizeRow(r) { |
| const clone = { ...r }; |
|
|
| clone.downloads_count = safeNumber(r.no_of_stars); |
| clone.rating = safeNumber(r.no_of_stars) / 10; |
| clone.reviews_count = safeNumber(r.no_of_contributors); |
|
|
| clone.categories = typeof r.tags === "string" ? r.tags.trim() : ""; |
|
|
| clone.publisher = |
| typeof r.action_title === "string" && r.action_title.trim() !== "" |
| ? r.action_title.trim() |
| : "(unknown)"; |
|
|
| clone.tags = typeof r.tags === "string" ? r.tags : ""; |
|
|
| clone.ai_enabled = parseBool(r.is_action_verified); |
|
|
| clone.name = r.action_title; |
| clone.verified = parseBool(r.is_action_verified); |
| clone.stars = safeNumber(r.no_of_stars); |
| clone.contributors = safeNumber(r.no_of_contributors); |
|
|
| return clone; |
| } |
|
|
| function safeNumber(v) { |
| if (v === null || v === undefined || v === "") return 0; |
|
|
| const cleaned = String(v).replace(/,/g, "").replace(/\s+/g, "").trim(); |
|
|
| const n = Number(cleaned); |
| return Number.isFinite(n) ? n : 0; |
| } |
|
|
| function parseBool(v) { |
| if (v === true || v === 1) return true; |
| if (!v) return false; |
| const s = String(v).trim().toLowerCase(); |
| return s === "true" || s === "1" || s === "yes" || s === "y"; |
| } |
|
|