diff --git a/resources/css/app.css b/resources/css/app.css index 2046d534..10bb7bda 100644 --- a/resources/css/app.css +++ b/resources/css/app.css @@ -26,6 +26,10 @@ --color-snow-flurry-200: #a2fd00; --color-snow-flurry-300: #97ed00; + /* Torchlight code surface (matches the material-theme-palenight theme) */ + --color-torchlight-surface: #292d3e; + --color-torchlight-text: #a6accd; + --font-poppins: 'Poppins', Verdana, sans-serif; } @@ -296,6 +300,19 @@ nav.docs-navigation li:has(.third-tier .exact-active) > .subsection-header { @apply block min-w-max py-4; } +/* + Fallback for blocks Torchlight returns un-highlighted (e.g. a language + its API can't tokenise, like the Svelte snippets on some plugin pages). + These come back with an empty `style` attribute and no per-token color + spans, so without this they have no background and inherit prose's light + text color, rendering the block invisible. Successfully highlighted + blocks set `background-color` inline, so they're excluded here and keep + their own theme colors. +*/ +.prose pre code.torchlight:not([style*='background-color']) { + @apply bg-torchlight-surface text-torchlight-text; +} + /* Horizontal line padding. */ diff --git a/tests/Feature/TorchlightCodeBlockTest.php b/tests/Feature/TorchlightCodeBlockTest.php new file mode 100644 index 00000000..5f60cb9d --- /dev/null +++ b/tests/Feature/TorchlightCodeBlockTest.php @@ -0,0 +1,58 @@ + 'test-token']); + Http::fake([ + '*' => Http::response(['blocks' => []], 200), + ]); + } + + public function test_fenced_code_renders_as_a_torchlight_block(): void + { + $html = CommonMark::convertToHtml("```php\necho 'hello';\n```"); + + $this->assertStringContainsString("class='torchlight'", $html); + } + + public function test_unhighlighted_block_carries_torchlight_class_for_css_fallback(): void + { + // When Torchlight cannot highlight a block (e.g. a language its API + // can't tokenise, such as the Svelte snippet below) it returns the + // block un-highlighted with an empty `style` attribute and no per-token + // color spans. The fallback CSS targets + // `code.torchlight:not([style*='background-color'])` to give these + // otherwise-invisible blocks a background and readable text, so the + // markup must still carry the `torchlight` class without an inline + // background color. + $svelte = <<<'MD' + ```svelte +
+ {#if status}

{status}

{/if} + +
+ ``` + MD; + + $html = CommonMark::convertToHtml($svelte); + + $this->assertStringContainsString("class='torchlight'", $html); + $this->assertStringContainsString("style=''", $html); + $this->assertStringNotContainsString('background-color', $html); + } +}