setBreaksEnabled(true); $htmlBody = $parsedown->text($md); $address = $ctx['address'] ?? ''; $preparedFor = $ctx['prepared_for'] ?? '—'; $preparedBy = $ctx['prepared_by'] ?? 'Modulos Design'; $when = date('j F Y'); $intent = trim((string)($ctx['project_intent'] ?? '')); $pw = new PhpWord(); // Base styles $pw->addTitleStyle(1, ['size'=>20,'bold'=>true,'color'=>'1f2937']); $pw->addTitleStyle(2, ['size'=>16,'bold'=>true,'color'=>'334155']); $pw->addTitleStyle(3, ['size'=>13,'bold'=>true,'color'=>'475569']); $pw->setDefaultFontName('Calibri'); $pw->setDefaultFontSize(11); // COVER SECTION $cover = $pw->addSection(); $cover->addText('Supporting Planning Report', ['bold'=>true,'size'=>28,'color'=>'0f172a'], ['spaceAfter'=>240]); if ($address) $cover->addText('Address: '.$address, [], ['spaceAfter'=>120]); $cover->addText('Prepared for: '.$preparedFor); $cover->addText('Prepared by: '.$preparedBy); $cover->addText('Date: '.$when); if ($intent) { $cover->addTextBreak(1); $cover->addText('Project intent: '.$intent, ['italic'=>true]); } $cover->addPageBreak(); // TOC SECTION $toc = $pw->addSection(); $toc->addText('Contents', ['bold'=>true,'size'=>18], ['spaceAfter'=>200]); $pw->addTableStyle('TOCStyle', [], ['indent'=>0, 'tabLeader'=>TOCStyle::TABLEADER_DOT]); $toc->addTOC(['size'=>11], ['tabLeader'=>TOCStyle::TABLEADER_DOT, 'indent'=>0, 'name'=>'TOCStyle']); $toc->addPageBreak(); // BODY SECTION (inject HTML; Parsedown produced h1/h2/h3 → Word titles) $body = $pw->addSection(); Html::addHtml($body, $htmlBody, false, false); // Save to tmp and stream URL back (or data URI) $tmpDir = sys_get_temp_dir(); $file = $tmpDir . '/PlanningReport-' . preg_replace('~[^\w\-]+~','_', $address ?: 'Site') . '.docx'; IOFactory::createWriter($pw, 'Word2007')->save($file); echo json_encode(['ok'=>true, 'url'=>"download.php?file=".basename($file)]); } catch (Throwable $e) { http_response_code(500); echo json_encode(['ok'=>false,'error'=>$e->getMessage()]); }