refactor: small Divi tree helpers out of DiviWriter (M3)

Block::isPlaceholder replaces the divi/placeholder literals (ledger T4);
NodeIndex::parentBlock/sectionLabel replace the two parentBlock copies and
DiviWriter::sectionLabel; DiviChange::idOf and Outline::summary replace the
duplicated id resolution and outline text; DiviSchema holds the shared
input properties. Behaviour unchanged.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
This commit is contained in:
2026-09-26 18:24:29 +02:00
co-authored by Claude Opus 5.5
parent ecfece719d
commit d2cc82f31b
18 changed files with 188 additions and 86 deletions
@@ -32,6 +32,29 @@ final class Outline
return $this->truncated;
}
/**
* The outline text of a write result: the whole page ($sectionIds null) or the given
* sections one after another (none: text null), and whether any breadth cap fired (S18).
*
* @param list<string>|null $sectionIds
* @return array{text: ?string, truncated: bool}
*/
public function summary(NodeIndex $index, ?array $sectionIds = null): array
{
if ($sectionIds === []) {
return ['text' => null, 'truncated' => false];
}
$texts = [];
$truncated = false;
foreach ($sectionIds ?? [null] as $sectionId) {
$texts[] = $this->text($this->rows($index, $sectionId));
$truncated = $truncated || $this->wasTruncated();
}
return ['text' => implode("\n", $texts), 'truncated' => $truncated];
}
/**
* @return list<array{id: string, type: string, label: string, excerpt: string, info: string,
* presets: list<string>, children: int, editable: bool, depth: int, truncated: bool}>