Each chapter in the right-hand menu gets a caret that unfolds its numbered sections (e.g. the prologue's 28 scenes); clicking one jumps straight to it. The chapter you're reading starts unfolded, other chapters' sections link across (/storyline/overview#section-…), and the section at the top of the pane is highlighted as you scroll. - ChapterOutline service parses each rendered chapter for its <h2 class="storyline-section"> headings, adds anchor ids and returns the outline; the controller renders all chapters once to feed the sidebar. - storyline-toc Stimulus controller: fold/unfold, in-pane jump, scroll-spy (works in the split view and in the small-screen window-scroll fallback). - Tests for the outline parser. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
35 lines
1.3 KiB
PHP
35 lines
1.3 KiB
PHP
<?php
|
|
|
|
namespace App\Tests\Storyline;
|
|
|
|
use App\Storyline\ChapterOutline;
|
|
use PHPUnit\Framework\TestCase;
|
|
|
|
class ChapterOutlineTest extends TestCase
|
|
{
|
|
public function testFindsSectionsAndAddsAnchors(): void
|
|
{
|
|
$html = '<p>intro</p>'
|
|
.'<h2 class="storyline-section"><span>21</span> Finding the Hearthburrow</h2><p>x</p>'
|
|
.'<h2 class="storyline-section"><span>+</span> Appendix — Timing</h2>';
|
|
|
|
$out = (new ChapterOutline())->process($html);
|
|
|
|
self::assertSame('21', $out['sections'][0]['num']);
|
|
self::assertSame('Finding the Hearthburrow', $out['sections'][0]['title']);
|
|
self::assertSame('section-1-finding-the-hearthburrow', $out['sections'][0]['id']);
|
|
self::assertSame('+', $out['sections'][1]['num']);
|
|
self::assertSame('Appendix — Timing', $out['sections'][1]['title']);
|
|
self::assertStringContainsString('<h2 class="storyline-section" id="section-1-finding-the-hearthburrow">', $out['html']);
|
|
self::assertStringContainsString('<p>intro</p>', $out['html']);
|
|
}
|
|
|
|
public function testChapterWithoutSectionsIsUntouched(): void
|
|
{
|
|
$out = (new ChapterOutline())->process('<p>plain</p>');
|
|
|
|
self::assertSame([], $out['sections']);
|
|
self::assertSame('<p>plain</p>', $out['html']);
|
|
}
|
|
}
|