Skip to content

Commit

Permalink
feat(documentator): IncludeExample can include raw markdown output …
Browse files Browse the repository at this point in the history
…via `<markdown>raw</markdown>` tag.
  • Loading branch information
LastDragon-ru committed Aug 28, 2023
1 parent 92bdcd1 commit caaa368
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 15 deletions.
4 changes: 4 additions & 0 deletions packages/documentator/docs/commands/preprocess.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ Includes contents of the `<target>` file as an example wrapped into
` ```code block``` `. It also searches for `<target>.run` file, execute
it if found, and include its result right after the code block.

By default, output of `<target>.run` will be included as ` ```plain text``` `
block. You can wrap the output into `<markdown>text</markdown>` tags to
insert it as is.

#### `[include:exec]: <target>`

* `<target>` - Path to the executable.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,17 @@
use function dirname;
use function is_file;
use function pathinfo;
use function preg_match;
use function preg_match_all;
use function preg_replace_callback;
use function trim;

use const PATHINFO_EXTENSION;
use const PREG_UNMATCHED_AS_NULL;

class IncludeExample extends IncludeFile {
public const Limit = 20;
public const Limit = 20;
protected const MarkdownRegexp = '/^\<(?P<tag>markdown)\>(?P<markdown>.*?)\<\/(?P=tag)\>$/msu';

public function __construct(
protected readonly Process $process,
Expand All @@ -33,6 +37,10 @@ public static function getDescription(): string {
Includes contents of the `<target>` file as an example wrapped into
` ```code block``` `. It also searches for `<target>.run` file, execute
it if found, and include its result right after the code block.
By default, output of `<target>.run` will be included as ` ```plain text``` `
block. You can wrap the output into `<markdown>text</markdown>` tags to
insert it as is.
DESC;
}

Expand All @@ -51,30 +59,61 @@ public function process(string $path, string $target): string {
$command = $this->getCommand($path, $target);

if ($command) {
// Call
try {
$output = $this->process->run($command, dirname($path));
$output = trim($output);
} catch (Exception $exception) {
throw new TargetExecFailed($path, $target, $exception);
}

if (preg_match_all('/\R/u', $output) > static::Limit) {
// Markdown?
$isMarkdown = (bool) preg_match(static::MarkdownRegexp, $output);

if ($isMarkdown) {
$output = trim(
(string) preg_replace_callback(
pattern : static::MarkdownRegexp,
callback: static function (array $matches): string {
return $matches['markdown'];
},
subject : $output,
flags : PREG_UNMATCHED_AS_NULL,
),
);
}

// Format
$isTooLong = preg_match_all('/\R/u', $output) > static::Limit;

if ($isMarkdown && $isTooLong) {
$output = <<<CODE
<details><summary>Example output</summary>
{$output}
</details>
CODE;
} elseif ($isMarkdown) {
// as is
} elseif ($isTooLong) {
$output = <<<CODE
<details><summary>Output</summary>
<details><summary>Example output</summary>
```plain
$output
```
```plain
{$output}
```
</details>
CODE;
</details>
CODE;
} else {
$output = <<<CODE
Output:
Example output:
```plain
$output
```
CODE;
```plain
$output
```
CODE;
}

$content .= "\n\n{$output}";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ public function testProcess(): void {
{$expected}
```
Output:
Example output:
```plain
{$output}
Expand Down Expand Up @@ -95,7 +95,7 @@ public function testProcessLongOutput(): void {
{$expected}
```
<details><summary>Output</summary>
<details><summary>Example output</summary>
```plain
{$output}
Expand All @@ -106,4 +106,64 @@ public function testProcessLongOutput(): void {
$instance->process($path, $file),
);
}

public function testProcessMarkdown(): void {
$path = self::getTestData()->path('~runnable.md');
$file = basename(self::getTestData()->path('~runnable.md'));
$expected = trim(self::getTestData()->content('~runnable.md'));
$output = 'command output';
$process = Mockery::mock(Process::class);
$process
->shouldReceive('run')
->with([self::getTestData()->path('~runnable.run')], dirname($path))
->once()
->andReturn("<markdown>{$output}</markdown>");

$instance = $this->app->make(IncludeExample::class, [
'process' => $process,
]);

self::assertEquals(
<<<EXPECTED
```md
{$expected}
```
{$output}
EXPECTED,
$instance->process($path, $file),
);
}

public function testProcessMarkdownLongOutput(): void {
$path = self::getTestData()->path('~runnable.md');
$file = self::getTestData()->path('~runnable.md');
$expected = trim(self::getTestData()->content('~runnable.md'));
$output = implode("\n", range(0, IncludeExample::Limit + 1));
$process = Mockery::mock(Process::class);
$process
->shouldReceive('run')
->with([self::getTestData()->path('~runnable.run')], dirname($path))
->once()
->andReturn("<markdown>{$output}</markdown>");

$instance = $this->app->make(IncludeExample::class, [
'process' => $process,
]);

self::assertEquals(
<<<EXPECTED
```md
{$expected}
```
<details><summary>Example output</summary>
{$output}
</details>
EXPECTED,
$instance->process($path, $file),
);
}
}

0 comments on commit caaa368

Please sign in to comment.