diff --git a/CHANGELOG.md b/CHANGELOG.md index 66c5fac7ef8..d99b01fb51c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,7 +19,7 @@ This serves two purposes: ### Added - Added a configuration option to disable the footer scroll-to-top button independently of the footer in https://github.com/hydephp/develop/pull/2459 - Added Blade Blocks for rendering Blade and Blade components from fenced code blocks in Markdown pages. They are controlled by the existing `markdown.enable_blade` option. ([#2504](https://github.com/hydephp/develop/pull/2504)) -- Added built-in `terminal` fenced code blocks with command prompt styling, an optional window title using the `title="…"` modifier, and optional Symfony Console formatting using the `terminal xml` info string. ([#2188](https://github.com/hydephp/develop/issues/2188), [#2485](https://github.com/hydephp/develop/issues/2485)) +- Added built-in `terminal` fenced code blocks with command prompt styling, an optional window title using the `title="…"` modifier, and optional XML style formatting using the `terminal xml` info string. ([#2188](https://github.com/hydephp/develop/issues/2188), [#2485](https://github.com/hydephp/develop/issues/2485)) - Added support for lazy `InMemoryPage` contents closures. The current page is passed as the first argument whenever the contents are requested. ### Changed diff --git a/HYDEPHP_V3_PLANNING.md b/HYDEPHP_V3_PLANNING.md index 80af955630e..28e6e4a4a79 100644 --- a/HYDEPHP_V3_PLANNING.md +++ b/HYDEPHP_V3_PLANNING.md @@ -25,7 +25,7 @@ Having this document in code lets us know the devlopment state at any given poin - Redirects can now be declared as source and destination path pairs in the `hyde.redirects` configuration array. Hyde registers them with the kernel, includes them in `route:list`, and generates them through the normal site build. - Blog posts can now be kept out of the published site through two zero-configuration publication states. Setting `draft: true` in front matter excludes a post indefinitely, until the property is removed or set to `false`, which suits content that is unfinished or awaiting approval. Setting a date in the future schedules a post, excluding it until that date has passed. Drafts and scheduled posts are skipped during auto-discovery when building the site: they get no route, are not present in the kernel's page and route collections, and are left out of post listings, the sitemap, and the RSS feed. The date rule supports both front matter dates and filename date prefixes, and an explicit draft outranks the date, so a draft stays excluded even after its date passes. Posts are published by default, making `draft: false` a no-op. Both states remain served by the realtime compiler, which is treated as an authoring preview, so posts can be written and proofread at their normal URL without editing their front matter: `serve` shows everything you are working on, while `build` publishes only what is eligible. Since Hyde is a static site generator, a scheduled post does not publish itself once its date passes: it is included in the first site build run after that point, so recurring builds (for example a cron-scheduled GitHub Actions workflow) are needed for a post to go live on its own. The new `MarkdownPost::isDraft()` and `MarkdownPost::isScheduled()` methods expose the checks. ([#2441](https://github.com/hydephp/develop/issues/2441), [#2572](https://github.com/hydephp/develop/pull/2572)) - Added Blade Blocks for rendering Blade and Blade components from fenced code blocks in Markdown pages. The supported directives are `blade render` and `blade component="name"`, and the feature is controlled by `markdown.enable_blade`. ([#2504](https://github.com/hydephp/develop/pull/2504)) -- Added built-in terminal code blocks using the `terminal` fence language. Command prompts are styled for selection-free copying, and `terminal xml` supports four Symfony-style Console formatter tags. The window's title bar can be titled per block with `terminal title="Installing Hyde"`, which the terminal view receives as a `$title` variable, falling back to the `Terminal` label when a block sets no title. The modifiers are order-independent, so they can be combined as either `terminal xml title="Build output"` or `terminal title="Build output" xml`. ([#2188](https://github.com/hydephp/develop/issues/2188), [#2485](https://github.com/hydephp/develop/issues/2485)) +- Added built-in terminal code blocks using the `terminal` fence language. Command prompts are styled for selection-free copying, and `terminal xml` supports four XML style formatter tags. The window's title bar can be titled per block with `terminal title="Installing Hyde"`, which the terminal view receives as a `$title` variable, falling back to the `Terminal` label when a block sets no title. The modifiers are order-independent, so they can be combined as either `terminal xml title="Build output"` or `terminal title="Build output" xml`. ([#2188](https://github.com/hydephp/develop/issues/2188), [#2485](https://github.com/hydephp/develop/issues/2485)) ### Feature Changes diff --git a/docs/digging-deeper/advanced-markdown.md b/docs/digging-deeper/advanced-markdown.md index e50408fe597..c603f85f8ea 100644 --- a/docs/digging-deeper/advanced-markdown.md +++ b/docs/digging-deeper/advanced-markdown.md @@ -165,10 +165,9 @@ quote. The title is HTML-escaped when rendered. The `title` modifier must use a quoted value with no whitespace around the `=`, such as `title="Build output"`. Unquoted values, unclosed quotes, and whitespace around the `=` are reported as errors instead of being guessed at. -### Symfony Console formatting +### XML style formatting -Add the `xml` modifier to style four commonly used Symfony Console formatter tags using colors from Hyde's terminal -theme: +Add the `xml` modifier to style four formatter tags using colors from Hyde's terminal theme: ````markdown ```terminal xml diff --git a/docs/digging-deeper/composable-markdown-blocks.md b/docs/digging-deeper/composable-markdown-blocks.md index a788ea44be7..8bf91a68a16 100644 --- a/docs/digging-deeper/composable-markdown-blocks.md +++ b/docs/digging-deeper/composable-markdown-blocks.md @@ -245,10 +245,10 @@ An empty title (`title=""`) is respected as written, leaving the title bar with modifier must otherwise use a quoted value with no whitespace around the `=`. Malformed title syntax causes the build to fail rather than being silently ignored. -#### Symfony formatting +#### XML style formatting -The `xml` modifier renders the four [Symfony Console formatter tags](https://symfony.com/doc/current/console/coloring.html) -(``, ``, ``, and ``) as coloured output, letting you paste console output verbatim. +The `xml` modifier renders four formatter tags (``, ``, ``, and ``) as coloured +output, letting you paste console-style output verbatim. ````markdown ```terminal xml title="Build output" @@ -273,8 +273,8 @@ usual, including unknown tags and tags that are not closed in the order they wer | `$title` | `string`/`null` | The title set by the block, or `null` when it did not set one. | The renderer does the per-line work before the view is involved: it escapes the raw text, wraps `$ ` prompts in -`hyde-terminal-command`/`hyde-terminal-prompt` spans, and — when the `xml` modifier is present — converts Symfony -Console formatter tags into coloured spans. The view receives a single finished string. +`hyde-terminal-command`/`hyde-terminal-prompt` spans, and — when the `xml` modifier is present — converts the +formatter tags into coloured spans. The view receives a single finished string. The title is passed through as it was written, so the view is what decides both how it is displayed and what an untitled block falls back to. The shipped view escapes it with `{{ }}` and falls back to `Terminal`. @@ -291,10 +291,10 @@ untitled block falls back to. The shipped view escapes it with `{{ }}` and falls | `hyde-terminal-body` | The `
` output area                    |
 | `hyde-terminal-command`   | A line beginning with a `$ ` prompt        |
 | `hyde-terminal-prompt`    | The `$ ` prompt itself                     |
-| `hyde-terminal-info`      | Symfony `` output                    |
-| `hyde-terminal-comment`   | Symfony `` output                 |
-| `hyde-terminal-question`  | Symfony `` output                |
-| `hyde-terminal-error`     | Symfony `` output                   |
+| `hyde-terminal-info`      | `` output                            |
+| `hyde-terminal-comment`   | `` output                         |
+| `hyde-terminal-question`  | `` output                        |
+| `hyde-terminal-error`     | `` output                           |
 
 ### Customization example
 
diff --git a/packages/framework/src/Markdown/Extensions/Processing/TransformTerminalBlocks.php b/packages/framework/src/Markdown/Extensions/Processing/TransformTerminalBlocks.php
index 7941479051f..5d6eb3832f2 100644
--- a/packages/framework/src/Markdown/Extensions/Processing/TransformTerminalBlocks.php
+++ b/packages/framework/src/Markdown/Extensions/Processing/TransformTerminalBlocks.php
@@ -41,25 +41,25 @@ public function __invoke(DocumentParsedEvent $event): void
 
     protected function makeViewModel(FencedCode $node): TerminalBlockViewModel
     {
-        [$usesSymfonyFormatting, $title] = $this->parseModifiers($node->getInfo() ?? '');
+        [$usesFormatting, $title] = $this->parseModifiers($node->getInfo() ?? '');
 
-        return new TerminalBlockViewModel($node->getLiteral(), $title, $usesSymfonyFormatting);
+        return new TerminalBlockViewModel($node->getLiteral(), $title, $usesFormatting);
     }
 
     /**
      * Parse the modifiers following the language, which are order-independent.
      *
-     * @return array{0: bool, 1: string|null} Whether Symfony formatting is used, and the window title.
+     * @return array{0: bool, 1: string|null} Whether formatting is used, and the window title.
      */
     protected function parseModifiers(string $info): array
     {
         $tokens = $this->tokenizeModifiers($info);
 
-        return [$this->usesSymfonyFormatting($tokens), $this->parseTitleModifier($tokens, 'terminal block')];
+        return [$this->usesFormatting($tokens), $this->parseTitleModifier($tokens, 'terminal block')];
     }
 
     /** @param array $tokens */
-    protected function usesSymfonyFormatting(array $tokens): bool
+    protected function usesFormatting(array $tokens): bool
     {
         foreach ($tokens as $token) {
             if ($token['word'] !== null && strtolower($token['word']) === 'xml') {
diff --git a/packages/framework/src/Markdown/Extensions/TerminalBlockViewModel.php b/packages/framework/src/Markdown/Extensions/TerminalBlockViewModel.php
index 702fc43144e..24fe4a69ed2 100644
--- a/packages/framework/src/Markdown/Extensions/TerminalBlockViewModel.php
+++ b/packages/framework/src/Markdown/Extensions/TerminalBlockViewModel.php
@@ -25,7 +25,7 @@ class TerminalBlockViewModel
     public function __construct(
         public readonly string $literal,
         public readonly ?string $title = null,
-        public readonly bool $usesSymfonyFormatting = false,
+        public readonly bool $usesFormatting = false,
     ) {
         $this->contents = $this->formatContents();
     }
@@ -67,7 +67,7 @@ protected function formatLine(string $line): string
 
     protected function formatText(string $text): string
     {
-        if (! $this->usesSymfonyFormatting) {
+        if (! $this->usesFormatting) {
             return e($text);
         }
 
diff --git a/packages/framework/tests/Feature/Documentation/ComposableMarkdownBlocksDocumentationTest.php b/packages/framework/tests/Feature/Documentation/ComposableMarkdownBlocksDocumentationTest.php
index ceded5aa436..543aa3e2907 100644
--- a/packages/framework/tests/Feature/Documentation/ComposableMarkdownBlocksDocumentationTest.php
+++ b/packages/framework/tests/Feature/Documentation/ComposableMarkdownBlocksDocumentationTest.php
@@ -522,7 +522,7 @@ public function testTheRendererWrapsPromptLinesInCommandAndPromptSpans()
         );
     }
 
-    public function testTheXmlModifierConvertsSymfonyConsoleFormatterTagsIntoColouredSpans()
+    public function testTheXmlModifierConvertsFormatterTagsIntoColouredSpans()
     {
         $html = Markdown::render("```terminal xml\nInfo Comment Question Error\n```");
 
@@ -558,7 +558,7 @@ public function testModifiersAreOrderIndependent()
             $html = Markdown::render("```terminal $modifiers\nHyde was installed successfully.\n```");
 
             $this->assertStringContainsString('Build output', $html, "The modifiers [$modifiers] did not set the title.");
-            $this->assertStringContainsString('assertStringContainsString('assertStringContainsString("\n\$VARIABLE\n", $html);
     }
 
-    public function testXmlModifierRendersSymfonyFormatterTags(): void
+    public function testXmlModifierRendersFormatterTags(): void
     {
         $html = Markdown::render(
             "```terminal xml\nReady Wait Continue? Failed\n```"
@@ -286,7 +286,7 @@ public function testParsedBlocksCarryTheViewModelTheyWereParsedInto(): void
 
         $this->assertSame('$ php hyde build', $node->viewModel->literal);
         $this->assertSame('Build output', $node->viewModel->title);
-        $this->assertTrue($node->viewModel->usesSymfonyFormatting);
+        $this->assertTrue($node->viewModel->usesFormatting);
     }
 
     public function testViewModelRendersTheTerminalView(): void
@@ -307,7 +307,7 @@ public function testViewModelGivesTheViewTheSameDataAsBefore(): void
 
     public function testViewModelContentsAreFinishedMarkup(): void
     {
-        $viewModel = new TerminalBlockViewModel('Ready Bold', usesSymfonyFormatting: true);
+        $viewModel = new TerminalBlockViewModel('Ready Bold', usesFormatting: true);
 
         $this->assertSame(
             'Ready <b>Bold</b>',
diff --git a/packages/framework/tests/Unit/TerminalBlockViewModelUnitTest.php b/packages/framework/tests/Unit/TerminalBlockViewModelUnitTest.php
index 90409c1ba1e..87da15dd9d1 100644
--- a/packages/framework/tests/Unit/TerminalBlockViewModelUnitTest.php
+++ b/packages/framework/tests/Unit/TerminalBlockViewModelUnitTest.php
@@ -29,7 +29,7 @@ public function testCanConstructWithOnlyLiteral()
 
         $this->assertSame('Output', $model->literal);
         $this->assertNull($model->title);
-        $this->assertFalse($model->usesSymfonyFormatting);
+        $this->assertFalse($model->usesFormatting);
     }
 
     public function testCanConstructWithAllArguments()
@@ -38,7 +38,7 @@ public function testCanConstructWithAllArguments()
 
         $this->assertSame('Output', $model->literal);
         $this->assertSame('Console', $model->title);
-        $this->assertTrue($model->usesSymfonyFormatting);
+        $this->assertTrue($model->usesFormatting);
     }
 
     public function testContentsAreFormattedOnConstruction()
@@ -97,13 +97,13 @@ public function testOnlyCommandLinesAreWrapped()
         );
     }
 
-    public function testFormatterTagsAreEscapedWithoutSymfonyFormatting()
+    public function testFormatterTagsAreEscapedWithoutFormatting()
     {
         $this->assertSame('<info>Ready</info>', (new TerminalBlockViewModel('Ready'))->contents);
     }
 
     #[\PHPUnit\Framework\Attributes\DataProvider('formatterTagProvider')]
-    public function testSymfonyFormatterTagsAreConvertedToSpans(string $literal, string $expected)
+    public function testFormatterTagsAreConvertedToSpans(string $literal, string $expected)
     {
         $this->assertSame($expected, (new TerminalBlockViewModel($literal, null, true))->contents);
     }
@@ -118,7 +118,7 @@ public static function formatterTagProvider(): array
         ];
     }
 
-    public function testSymfonyFormatterTagsCanBeNested()
+    public function testFormatterTagsCanBeNested()
     {
         $this->assertSame(
             'Ready soon',
@@ -126,7 +126,7 @@ public function testSymfonyFormatterTagsCanBeNested()
         );
     }
 
-    public function testUnclosedSymfonyFormatterTagsAreClosedAtTheEndOfTheLine()
+    public function testUnclosedFormatterTagsAreClosedAtTheEndOfTheLine()
     {
         $this->assertSame(
             'Ready soon',
@@ -134,7 +134,7 @@ public function testUnclosedSymfonyFormatterTagsAreClosedAtTheEndOfTheLine()
         );
     }
 
-    public function testMismatchedSymfonyFormatterTagsAreEscaped()
+    public function testMismatchedFormatterTagsAreEscaped()
     {
         $this->assertSame(
             'Ready</comment>',
@@ -142,17 +142,17 @@ public function testMismatchedSymfonyFormatterTagsAreEscaped()
         );
     }
 
-    public function testUnopenedSymfonyFormatterTagsAreEscaped()
+    public function testUnopenedFormatterTagsAreEscaped()
     {
         $this->assertSame('Ready</info>', (new TerminalBlockViewModel('Ready', null, true))->contents);
     }
 
-    public function testUnknownTagsAreEscapedWithSymfonyFormatting()
+    public function testUnknownTagsAreEscapedWithFormatting()
     {
         $this->assertSame('<unknown>text</unknown>', (new TerminalBlockViewModel('text', null, true))->contents);
     }
 
-    public function testSymfonyFormattingIsAppliedWithinCommandLines()
+    public function testFormattingIsAppliedWithinCommandLines()
     {
         $this->assertSame(
             'php hyde build --force',
@@ -160,7 +160,7 @@ public function testSymfonyFormattingIsAppliedWithinCommandLines()
         );
     }
 
-    public function testSymfonyFormatterTagsDoNotSpanMultipleLines()
+    public function testFormatterTagsDoNotSpanMultipleLines()
     {
         $this->assertSame(
             'Ready'."\n".'Done</info>',