diff --git a/src/stores/gull.js b/src/stores/gull.js
index e1a2fa2..c5a9c14 100644
--- a/src/stores/gull.js
+++ b/src/stores/gull.js
@@ -2,25 +2,57 @@
const { decodeHtml, cleanText, extractFirstImgUrl } = require("../utils/html");
const { normalizeCspc } = require("../utils/sku");
-const { extractPriceFromTmbBlock } = require("../utils/woocommerce");
const { makePageUrl } = require("../utils/url");
function looksInStock(block) {
const s = String(block || "");
if (/\boutofstock\b/i.test(s)) return false;
- // your sample has:
1 in stock
if (/\bin-stock\b/i.test(s)) return true;
if (/\binstock\b/i.test(s)) return true;
if (/>\s*\d+\s+in\s+stock\s*= 1.00 (sale price if present).
+function extractGullPriceFromBlock(block) {
+ const s = String(block || "");
+ const nums = [];
+
+ // Match WooCommerce "Price amount" blocks, pull out the BDI contents,
+ // then strip tags/entities and parse as float.
+ const re =
+ /]*class=["'][^"']*\bwoocommerce-Price-amount\b[^"']*["'][^>]*>\s*]*>([\s\S]*?)<\/bdi>/gi;
+
+ for (const m of s.matchAll(re)) {
+ const raw = cleanText(decodeHtml(m[1] || "")); // e.g. "$24.05"
+ const n = parseFloat(String(raw).replace(/[^0-9.]/g, ""));
+ if (Number.isFinite(n)) nums.push(n);
+ }
+
+ // Filter out bottle deposits / tiny fees (usually 0.10, 0.20, etc.)
+ const big = nums.filter((n) => n >= 1.0);
+
+ if (!big.length) return "";
+
+ // If sale price exists, Woo often renders old then new; taking the last >=1
+ // typically yields the current price.
+ const chosen = big[big.length - 1];
+
+ // Normalize formatting
+ return `$${chosen.toFixed(2)}`;
+}
+
function parseProductsGull(html, ctx) {
const s = String(html || "");
const items = [];
// split on
- const parts = s.split(/]*class=["'][^"']*\bproduct\b[^"']*["'][^>]*>/i);
+ const parts = s.split(
+ /]*class=["'][^"']*\bproduct\b[^"']*["'][^>]*>/i
+ );
if (parts.length <= 1) return items;
const base = `https://${(ctx && ctx.store && ctx.store.host) || "gullliquorstore.com"}/`;
@@ -30,7 +62,9 @@ function parseProductsGull(html, ctx) {
if (!looksInStock(block)) continue;
- const hrefM = block.match(/]*href=["']([^"']+)["'][^>]*class=["'][^"']*\bwoocommerce-LoopProduct-link\b/i);
+ const hrefM = block.match(
+ /]*href=["']([^"']+)["'][^>]*class=["'][^"']*\bwoocommerce-LoopProduct-link\b/i
+ );
if (!hrefM || !hrefM[1]) continue;
let url;
@@ -40,17 +74,18 @@ function parseProductsGull(html, ctx) {
continue;
}
- const titleM = block.match(/]*class=["'][^"']*\bwoocommerce-loop-product__title\b[^"']*["'][^>]*>([\s\S]*?)<\/h2>/i);
+ const titleM = block.match(
+ /]*class=["'][^"']*\bwoocommerce-loop-product__title\b[^"']*["'][^>]*>([\s\S]*?)<\/h2>/i
+ );
const name = cleanText(decodeHtml(titleM ? titleM[1] : ""));
if (!name) continue;
- // Price is in standard Woo ...
- const price = extractPriceFromTmbBlock(block) || "";
+ const price = extractGullPriceFromBlock(block);
const sku = normalizeCspc(
block.match(/\bdata-product_sku=["']([^"']+)["']/i)?.[1] ||
- block.match(/\bSKU\b[^0-9]{0,20}(\d{6})\b/i)?.[1] ||
- url
+ block.match(/\bSKU\b[^0-9]{0,20}(\d{6})\b/i)?.[1] ||
+ url
);
const img = extractFirstImgUrl(block, base);
@@ -63,6 +98,7 @@ function parseProductsGull(html, ctx) {
return [...uniq.values()];
}
+
function createStore(defaultUa) {
return {
key: "gull",
@@ -72,26 +108,26 @@ function createStore(defaultUa) {
parseProducts: parseProductsGull,
makePageUrl, // enables /page/N/ paging
categories: [
- {
- key: "whisky",
- label: "Whisky",
- startUrl: "https://gullliquorstore.com/product-category/spirits/?spirit_type=whisky",
- discoveryStartPage: 3,
- discoveryStep: 2,
- pageConcurrency: 1,
- pageStaggerMs: 10000,
- discoveryDelayMs: 10000
- },
- {
- key: "rum",
- label: "Rum",
- startUrl: "https://gullliquorstore.com/product-category/spirits/?spirit_type=rum",
- discoveryStartPage: 3,
- discoveryStep: 2,
- pageConcurrency: 1,
- pageStaggerMs: 10000,
- discoveryDelayMs: 10000
- },
+ {
+ key: "whisky",
+ label: "Whisky",
+ startUrl: "https://gullliquorstore.com/product-category/spirits/?spirit_type=whisky",
+ discoveryStartPage: 3,
+ discoveryStep: 2,
+ pageConcurrency: 1,
+ pageStaggerMs: 10000,
+ discoveryDelayMs: 10000,
+ },
+ {
+ key: "rum",
+ label: "Rum",
+ startUrl: "https://gullliquorstore.com/product-category/spirits/?spirit_type=rum",
+ discoveryStartPage: 3,
+ discoveryStep: 2,
+ pageConcurrency: 1,
+ pageStaggerMs: 10000,
+ discoveryDelayMs: 10000,
+ },
],
};
}