Storyline: unfoldable section list per chapter in the sidebar
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>
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
<?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']);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user