import fs from "node:fs"; const doc = JSON.parse(fs.readFileSync("file.json", "utf8")); function isProcedureHeader(text, label) { if (label !== "section_header") return false; const s = text.trim(); if (/^chef's notes?:?$/i.test(s)) return false; if (/^table of contents|foreword|introduction|acknowledgements|how to use/i.test(s)) return false; return /procedure|assembly|variations?|baking|shaping|finishing|glaz|infusion/i.test(s) || s.endsWith(":"); } function cleanProcedureHeader(raw) { const t = raw.trim().replace(/^['"]+|['":]+$/g, "").trim(); if (/^procedure$/i.test(t)) return ""; const cleaned = t.replace(/\s+procedure$/i, "").trim(); return cleaned ? `${cleaned}:` : ""; } function testPages(pages, title) { const texts = doc.texts.filter(t => pages.includes(t.prov?.[0]?.page_no)); console.log(`\nTesting on ${title} (pages ${pages.join("-")}):`); let inProcedure = false; const steps = []; for (const t of texts) { const text = t.text.trim(); if (/^chef's notes?:?$/i.test(text)) { inProcedure = false; continue; } if (isProcedureHeader(text, t.label)) { inProcedure = true; const heading = cleanProcedureHeader(text); if (heading) { steps.push({ id: `step_${steps.length + 1}`, order: steps.length + 1, instruction: heading }); } continue; } if (inProcedure && (t.label === "list_item" || t.label === "text") && !/^\d+$/.test(text) && !/^yields?:/i.test(text)) { steps.push({ id: `step_${steps.length + 1}`, order: steps.length + 1, instruction: text }); } } console.log("Extracted steps count:", steps.length); steps.forEach(s => console.log(" " + (s.instruction.endsWith(":") ? "📂 " : " • ") + s.instruction)); } testPages([312, 313], "Fig Bars"); testPages([26, 27], "Chocolate Puff Pastry");