@fayz-ai/plugin-menu 0.10.8 → 0.10.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{MenuPage-SO7EDR6R.js → MenuPage-GC6ATJTT.js} +100 -104
- package/dist/MenuPage-GC6ATJTT.js.map +1 -0
- package/dist/chunk-FVDAVCK4.js +14 -0
- package/dist/chunk-FVDAVCK4.js.map +1 -0
- package/dist/components/DraftSectionCard.d.ts.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +52 -3
- package/dist/index.js.map +1 -1
- package/dist/lib/agent-surface.d.ts +12 -0
- package/dist/lib/agent-surface.d.ts.map +1 -1
- package/dist/locales/en.d.ts.map +1 -1
- package/dist/locales/pt-BR.d.ts.map +1 -1
- package/dist/store.d.ts +18 -0
- package/dist/store.d.ts.map +1 -1
- package/dist/views/MenuManagerView.d.ts.map +1 -1
- package/package.json +4 -4
- package/dist/MenuPage-SO7EDR6R.js.map +0 -1
- package/dist/chunk-C6W53TML.js +0 -65
- package/dist/chunk-C6W53TML.js.map +0 -1
package/dist/chunk-C6W53TML.js
DELETED
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
// src/lib/extract-parse.ts
|
|
2
|
-
function parsePrice(raw) {
|
|
3
|
-
if (typeof raw === "number") return Number.isFinite(raw) ? Math.max(0, raw) : 0;
|
|
4
|
-
if (typeof raw !== "string") return 0;
|
|
5
|
-
const cleaned = raw.replace(/[^\d.,-]/g, "").trim();
|
|
6
|
-
if (!cleaned) return 0;
|
|
7
|
-
const lastComma = cleaned.lastIndexOf(",");
|
|
8
|
-
const lastDot = cleaned.lastIndexOf(".");
|
|
9
|
-
let normalized = cleaned;
|
|
10
|
-
if (lastComma > lastDot) normalized = cleaned.replace(/\./g, "").replace(",", ".");
|
|
11
|
-
else if (lastDot > lastComma) normalized = cleaned.replace(/,/g, "");
|
|
12
|
-
else normalized = cleaned.replace(",", ".");
|
|
13
|
-
const value = Number.parseFloat(normalized);
|
|
14
|
-
return Number.isFinite(value) ? Math.max(0, value) : 0;
|
|
15
|
-
}
|
|
16
|
-
function normalizeName(value) {
|
|
17
|
-
return value.normalize("NFD").replace(/[̀-ͯ]/g, "").toLowerCase().replace(/\s+/g, " ").trim();
|
|
18
|
-
}
|
|
19
|
-
function normalizeExtraction(payload, fallbackSection = "Geral") {
|
|
20
|
-
const raw = payload ?? {};
|
|
21
|
-
const rawSections = raw.sections ?? raw.categories ?? [];
|
|
22
|
-
const merged = /* @__PURE__ */ new Map();
|
|
23
|
-
for (const entry of Array.isArray(rawSections) ? rawSections : []) {
|
|
24
|
-
const section = entry ?? {};
|
|
25
|
-
const name = String(section.name ?? "").trim() || fallbackSection;
|
|
26
|
-
const key = normalizeName(name);
|
|
27
|
-
if (!merged.has(key)) merged.set(key, { name, items: /* @__PURE__ */ new Map() });
|
|
28
|
-
const target = merged.get(key);
|
|
29
|
-
const rawItems = section.items ?? [];
|
|
30
|
-
for (const itemEntry of Array.isArray(rawItems) ? rawItems : []) {
|
|
31
|
-
const item = itemEntry ?? {};
|
|
32
|
-
const itemName = String(item.name ?? "").trim();
|
|
33
|
-
if (!itemName) continue;
|
|
34
|
-
const price = parsePrice(item.price);
|
|
35
|
-
const description = String(item.description ?? "").trim();
|
|
36
|
-
const itemKey = `${normalizeName(itemName)}|${price.toFixed(2)}`;
|
|
37
|
-
if (target.items.has(itemKey)) continue;
|
|
38
|
-
target.items.set(itemKey, {
|
|
39
|
-
name: itemName,
|
|
40
|
-
price,
|
|
41
|
-
description: description || void 0
|
|
42
|
-
});
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
const sections = Array.from(merged.values()).map((section) => ({ name: section.name, items: Array.from(section.items.values()) })).filter((section) => section.items.length > 0);
|
|
46
|
-
const warnings = [];
|
|
47
|
-
const priceless = sections.reduce((count, s) => count + s.items.filter((i) => i.price === 0).length, 0);
|
|
48
|
-
if (priceless > 0) warnings.push(`price_missing:${priceless}`);
|
|
49
|
-
if (sections.length === 0) warnings.push("nothing_found");
|
|
50
|
-
return {
|
|
51
|
-
sections,
|
|
52
|
-
model: typeof raw.model === "string" ? raw.model : void 0,
|
|
53
|
-
warnings
|
|
54
|
-
};
|
|
55
|
-
}
|
|
56
|
-
function countExtracted(menu) {
|
|
57
|
-
return {
|
|
58
|
-
sections: menu.sections.length,
|
|
59
|
-
items: menu.sections.reduce((count, section) => count + section.items.length, 0)
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
export { countExtracted, normalizeExtraction, normalizeName };
|
|
64
|
-
//# sourceMappingURL=chunk-C6W53TML.js.map
|
|
65
|
-
//# sourceMappingURL=chunk-C6W53TML.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/lib/extract-parse.ts"],"names":[],"mappings":"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","file":"chunk-C6W53TML.js","sourcesContent":["import type { ExtractedMenu, ExtractedSection, ExtractedItem } from '../types'\n\n// ---------------------------------------------------------------------------\n// Turning what a model read off a photo into something safe to write.\n//\n// The model is asked for JSON, and it mostly obliges — but a menu photographed\n// in four overlapping slices comes back with the same dish three times, prices\n// as \"R$ 29,90\", and the odd section with no items. None of that should reach\n// the review screen, let alone the database.\n// ---------------------------------------------------------------------------\n\n/** \"R$ 29,90\" → 29.9 · \"12\" → 12 · \"\" → 0. Never NaN. */\nexport function parsePrice(raw: unknown): number {\n if (typeof raw === 'number') return Number.isFinite(raw) ? Math.max(0, raw) : 0\n if (typeof raw !== 'string') return 0\n const cleaned = raw\n .replace(/[^\\d.,-]/g, '')\n .trim()\n if (!cleaned) return 0\n // pt-BR writes 1.234,56 and en-US writes 1,234.56 — the LAST separator is the\n // decimal one in both, which is enough to tell them apart.\n const lastComma = cleaned.lastIndexOf(',')\n const lastDot = cleaned.lastIndexOf('.')\n let normalized = cleaned\n if (lastComma > lastDot) normalized = cleaned.replace(/\\./g, '').replace(',', '.')\n else if (lastDot > lastComma) normalized = cleaned.replace(/,/g, '')\n else normalized = cleaned.replace(',', '.')\n const value = Number.parseFloat(normalized)\n return Number.isFinite(value) ? Math.max(0, value) : 0\n}\n\n/** Accent- and case-insensitive key for deduplication. */\nexport function normalizeName(value: string): string {\n return value\n .normalize('NFD')\n .replace(/[̀-ͯ]/g, '')\n .toLowerCase()\n .replace(/\\s+/g, ' ')\n .trim()\n}\n\n/**\n * Normalize + merge a raw model payload.\n * Sections with the same name merge; items merge on name+price, so the same\n * dish appearing in two overlapping photo slices lands once.\n */\nexport function normalizeExtraction(payload: unknown, fallbackSection = 'Geral'): ExtractedMenu {\n const raw = (payload ?? {}) as Record<string, unknown>\n const rawSections = (raw.sections ?? raw.categories ?? []) as unknown[]\n const merged = new Map<string, { name: string; items: Map<string, ExtractedItem> }>()\n\n for (const entry of Array.isArray(rawSections) ? rawSections : []) {\n const section = (entry ?? {}) as Record<string, unknown>\n const name = String(section.name ?? '').trim() || fallbackSection\n const key = normalizeName(name)\n if (!merged.has(key)) merged.set(key, { name, items: new Map() })\n const target = merged.get(key)!\n\n const rawItems = (section.items ?? []) as unknown[]\n for (const itemEntry of Array.isArray(rawItems) ? rawItems : []) {\n const item = (itemEntry ?? {}) as Record<string, unknown>\n const itemName = String(item.name ?? '').trim()\n if (!itemName) continue\n const price = parsePrice(item.price)\n const description = String(item.description ?? '').trim()\n const itemKey = `${normalizeName(itemName)}|${price.toFixed(2)}`\n if (target.items.has(itemKey)) continue\n target.items.set(itemKey, {\n name: itemName,\n price,\n description: description || undefined,\n })\n }\n }\n\n const sections: ExtractedSection[] = Array.from(merged.values())\n .map((section) => ({ name: section.name, items: Array.from(section.items.values()) }))\n .filter((section) => section.items.length > 0)\n\n const warnings: string[] = []\n const priceless = sections.reduce((count, s) => count + s.items.filter((i) => i.price === 0).length, 0)\n if (priceless > 0) warnings.push(`price_missing:${priceless}`)\n if (sections.length === 0) warnings.push('nothing_found')\n\n return {\n sections,\n model: typeof raw.model === 'string' ? raw.model : undefined,\n warnings,\n }\n}\n\nexport function countExtracted(menu: ExtractedMenu): { sections: number; items: number } {\n return {\n sections: menu.sections.length,\n items: menu.sections.reduce((count, section) => count + section.items.length, 0),\n }\n}\n"]}
|