mirror of
https://github.com/samsonjs/spirit-tracker.git
synced 2026-03-25 09:25:51 +00:00
feat: Linker page fixes
This commit is contained in:
parent
d47f2fe9ee
commit
028f0d741a
1 changed files with 54 additions and 12 deletions
|
|
@ -184,14 +184,24 @@ function storesOverlap(aItem, bItem) {
|
|||
|
||||
/* ---------------- Mapping helpers ---------------- */
|
||||
|
||||
function buildMappedSkuSet(links) {
|
||||
function buildMappedSkuSet(links, rules) {
|
||||
const s = new Set();
|
||||
for (const x of Array.isArray(links) ? links : []) {
|
||||
const a = String(x?.fromSku || "").trim();
|
||||
const b = String(x?.toSku || "").trim();
|
||||
if (a) s.add(a);
|
||||
if (b) s.add(b);
|
||||
|
||||
function add(k) {
|
||||
const x = String(k || "").trim();
|
||||
if (!x) return;
|
||||
s.add(x);
|
||||
if (rules && typeof rules.canonicalSku === "function") {
|
||||
const c = String(rules.canonicalSku(x) || "").trim();
|
||||
if (c) s.add(c);
|
||||
}
|
||||
}
|
||||
|
||||
for (const x of Array.isArray(links) ? links : []) {
|
||||
add(x?.fromSku);
|
||||
add(x?.toSku);
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
|
|
@ -651,8 +661,23 @@ export async function renderSkuLinker($app) {
|
|||
const allRows = Array.isArray(idx.items) ? idx.items : [];
|
||||
|
||||
const URL_BY_SKU_STORE = new Map();
|
||||
|
||||
function urlQuality(r) {
|
||||
// Prefer “better” URLs if dupes exist.
|
||||
// Heuristics: longer path > shorter, avoid obvious legacy/short generic slugs when possible.
|
||||
const u = String(r?.url || "").trim();
|
||||
if (!u) return -1;
|
||||
let s = 0;
|
||||
s += u.length; // more specific tends to be longer
|
||||
if (/\bproduct\/\d+\//.test(u)) s += 50;
|
||||
if (/[a-z0-9-]{8,}/i.test(u)) s += 10; // sluggy
|
||||
return s;
|
||||
}
|
||||
|
||||
for (const r of allRows) {
|
||||
// Keep active only
|
||||
if (!r || r.removed) continue;
|
||||
|
||||
const skuKey = String(keySkuForRow(r) || "").trim();
|
||||
if (!skuKey) continue;
|
||||
|
||||
|
|
@ -662,13 +687,30 @@ export async function renderSkuLinker($app) {
|
|||
|
||||
let m = URL_BY_SKU_STORE.get(skuKey);
|
||||
if (!m) URL_BY_SKU_STORE.set(skuKey, (m = new Map()));
|
||||
if (!m.has(storeLabel)) m.set(storeLabel, url);
|
||||
|
||||
const prevUrl = m.get(storeLabel);
|
||||
if (!prevUrl) {
|
||||
m.set(storeLabel, url);
|
||||
continue;
|
||||
}
|
||||
|
||||
// If duplicates exist, prefer the “better” URL deterministically.
|
||||
const prevScore = urlQuality({ url: prevUrl });
|
||||
const nextScore = urlQuality(r);
|
||||
|
||||
if (nextScore > prevScore) {
|
||||
m.set(storeLabel, url);
|
||||
} else if (nextScore === prevScore && url < prevUrl) {
|
||||
// stable tie-break
|
||||
m.set(storeLabel, url);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const allAgg = aggregateBySku(allRows, (x) => x);
|
||||
|
||||
const meta = await loadSkuMetaBestEffort();
|
||||
const mappedSkus = buildMappedSkuSet(meta.links || []);
|
||||
const mappedSkus = buildMappedSkuSet(meta.links || [], rules);
|
||||
let ignoreSet = rules.ignoreSet;
|
||||
|
||||
function isIgnoredPair(a, b) {
|
||||
|
|
@ -895,7 +937,7 @@ export async function renderSkuLinker($app) {
|
|||
rules = await loadSkuRules();
|
||||
ignoreSet = rules.ignoreSet;
|
||||
|
||||
const rebuilt = buildMappedSkuSet(rules.links || []);
|
||||
const rebuilt = buildMappedSkuSet(rules.links || [], rules);
|
||||
mappedSkus.clear();
|
||||
for (const x of rebuilt) mappedSkus.add(x);
|
||||
|
||||
|
|
@ -952,7 +994,7 @@ export async function renderSkuLinker($app) {
|
|||
rules = await loadSkuRules();
|
||||
ignoreSet = rules.ignoreSet;
|
||||
|
||||
const rebuilt = buildMappedSkuSet(rules.links || []);
|
||||
const rebuilt = buildMappedSkuSet(rules.links || [], rules);
|
||||
mappedSkus.clear();
|
||||
for (const x of rebuilt) mappedSkus.add(x);
|
||||
|
||||
|
|
@ -1055,7 +1097,7 @@ export async function renderSkuLinker($app) {
|
|||
rules = await loadSkuRules();
|
||||
ignoreSet = rules.ignoreSet;
|
||||
|
||||
const rebuilt = buildMappedSkuSet(rules.links || []);
|
||||
const rebuilt = buildMappedSkuSet(rules.links || [], rules);
|
||||
mappedSkus.clear();
|
||||
for (const x of rebuilt) mappedSkus.add(x);
|
||||
|
||||
|
|
@ -1136,7 +1178,7 @@ export async function renderSkuLinker($app) {
|
|||
rules = await loadSkuRules();
|
||||
ignoreSet = rules.ignoreSet;
|
||||
|
||||
const rebuilt = buildMappedSkuSet(rules.links || []);
|
||||
const rebuilt = buildMappedSkuSet(rules.links || [], rules);
|
||||
mappedSkus.clear();
|
||||
for (const x of rebuilt) mappedSkus.add(x);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue