Skip to content

Commit

Permalink
feat(documentator): Added ability to specify headings level for `in…
Browse files Browse the repository at this point in the history
…clude:document-list` instruction.
  • Loading branch information
LastDragon-ru committed Nov 28, 2024
1 parent 8d4d60a commit 1ef782d
Show file tree
Hide file tree
Showing 9 changed files with 235 additions and 104 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
?>
@foreach ($data->documents as $document)
## {!! $document->title !!}
{{ str_repeat('#', $data->level) }} {!! $document->title !!}
@if($document->summary)

{!! $document->summary !!}
Expand Down
5 changes: 5 additions & 0 deletions packages/documentator/docs/Commands/preprocess.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,11 @@ which will be replaced to FQCN (if possible). Other tags are ignored.
* `template`: `string` = `'default'` - Blade template. The documents passed in the `$data` ([`Data`][code-links/84d51020d324cc16])
variable. Also, be careful with leading whitespaces.
* `order`: [`SortOrder`][code-links/7e5c66e8748c6ff8] = [`SortOrder::Asc`][code-links/08e0648f66e2d1a5] - Sort order.
* `level`: `?int` = `null` - Headings level. Possible values are

* `null`: `<current level> + 1`
* `int`: explicit level (`1-6`)
* `0`: `<current level>`

Returns the list of `*.md` files in the `<target>` directory. Each file
must have `# Header` as the first construction. The first paragraph
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use Generator;
use Iterator;
use LastDragon_ru\LaraASP\Core\Utils\Cast;
use LastDragon_ru\LaraASP\Documentator\Markdown\Nodes\Reference\Block;
use LastDragon_ru\LaraASP\Documentator\PackageViewer;
use LastDragon_ru\LaraASP\Documentator\Processor\Contracts\Dependency;
use LastDragon_ru\LaraASP\Documentator\Processor\Dependencies\FileIterator;
Expand All @@ -16,8 +17,11 @@
use LastDragon_ru\LaraASP\Documentator\Processor\Tasks\Preprocess\Instructions\IncludeDocumentList\Template\Document as TemplateDocument;
use LastDragon_ru\LaraASP\Documentator\Utils\Sorter;
use LastDragon_ru\LaraASP\Documentator\Utils\Text;
use League\CommonMark\Extension\CommonMark\Node\Block\Heading;
use Override;

use function max;
use function min;
use function usort;

/**
Expand Down Expand Up @@ -99,11 +103,42 @@ public function __invoke(Context $context, string $target, mixed $parameters): G

// Render
$template = "document-list.{$parameters->template}";
$level = $this->getLevel($context->node, $parameters);
$list = $this->viewer->render($template, [
'data' => new TemplateData($documents),
'data' => new TemplateData($documents, $level),
]);

// Return
return $list;
}

/**
* @return int<1,6>
*/
private function getLevel(Block $node, Parameters $parameters): int {
$level = match ($parameters->level) {
0 => $this->getNodeLevel($node),
null => $this->getNodeLevel($node) + 1,
default => $parameters->level,
};
$level = min($level, 6);
$level = max($level, 1);

return $level;
}

private function getNodeLevel(Block $block): int {
$level = 0;

do {
$block = $block->previous();

if ($block instanceof Heading) {
$level = $block->getLevel();
$block = null;
}
} while ($block);

return $level;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,74 +11,204 @@
use LastDragon_ru\LaraASP\Documentator\Processor\Tasks\Preprocess\Context;
use LastDragon_ru\LaraASP\Documentator\Testing\Package\ProcessorHelper;
use LastDragon_ru\LaraASP\Documentator\Testing\Package\TestCase;
use LastDragon_ru\LaraASP\Documentator\Utils\SortOrder;
use LastDragon_ru\LaraASP\Serializer\Contracts\Serializer;
use League\CommonMark\Node\Query;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\DataProvider;

use function basename;
use function json_decode;
use function json_encode;

use const JSON_THROW_ON_ERROR;

/**
* @internal
*/
#[CoversClass(Instruction::class)]
final class InstructionTest extends TestCase {
public function testInvokeSameDirectory(): void {
$path = (new FilePath(self::getTestData()->path('Document.md')))->getNormalizedPath();
$root = new Directory($path->getDirectoryPath(), false);
$file = new File($path, false);
$params = new Parameters('...');
$target = './';
$context = new Context($root, $file, new Document(''), new Block(), new Nop());
$instance = $this->app()->make(Instruction::class);
$actual = ProcessorHelper::runInstruction($instance, $context, $target, $params);
// <editor-fold desc="Tests">
// =========================================================================
#[DataProvider('dataProviderInvoke')]
public function testInvoke(string $expected, string $path, string $content): void {
// Prepare
$path = (new FilePath(self::getTestData()->path($path)))->getNormalizedPath();
$root = new Directory($path->getDirectoryPath(), false);
$file = new File($path, false);
$document = new Document($content, $path);
$instruction = (new Query())->where(Query::type(Block::class))->findOne($document->getNode());

self::assertEquals(
self::getTestData()->content('~SameDirectory.md'),
<<<MARKDOWN
<!-- markdownlint-disable -->
self::assertInstanceOf(Block::class, $instruction);

{$actual}
MARKDOWN,
);
// Parameters
$target = $instruction->getDestination();
$parameters = $instruction->getTitle();
$parameters = $parameters !== ''
? (array) json_decode($parameters, true, flags: JSON_THROW_ON_ERROR)
: [];
$parameters['target'] = $target;
$parameters = json_encode($parameters, JSON_THROW_ON_ERROR);
$parameters = $this->app()->make(Serializer::class)->deserialize(Parameters::class, $parameters);

// Test
$context = new Context($root, $file, $document, $instruction, new Nop());
$instance = $this->app()->make(Instruction::class);
$actual = ProcessorHelper::runInstruction($instance, $context, $target, $parameters);

self::assertEquals($expected, $actual);
}
// </editor-fold>
// <editor-fold desc="DataProviders">
// =========================================================================
/**
* @return array<string, array{string, string, string}>
*/
public static function dataProviderInvoke(): array {
return [
'Same Directory / Default parameters' => [
<<<'MARKDOWN'
# `<` Document B `>`
public function testInvokeAnotherDirectory(): void {
$path = (new FilePath(self::getTestData()->path('~AnotherDirectory.md')))->getNormalizedPath();
$root = new Directory($path->getDirectoryPath(), false);
$file = new File($path, false);
$params = new Parameters('...');
$target = basename(self::getTestData()->path('/'));
$context = new Context($root, $file, new Document(''), new Block(), new Nop());
Summary text.
$instance = $this->app()->make(Instruction::class);
$actual = ProcessorHelper::runInstruction($instance, $context, $target, $params);
[Read more](<Document B.md>).
self::assertEquals(
self::getTestData()->content('~AnotherDirectory.md'),
<<<MARKDOWN
<!-- markdownlint-disable -->
# Document A
{$actual}
MARKDOWN,
);
}
Summary text with special characters `<`, `>`, `&`.
public function testInvokeNestedDirectories(): void {
$path = (new FilePath(self::getTestData()->path('nested/Document.md')))->getNormalizedPath();
$root = new Directory($path->getDirectoryPath(), false);
$file = new File($path, false);
$params = new Parameters('...', null, order: SortOrder::Desc);
$target = './';
$context = new Context($root, $file, new Document(''), new Block(), new Nop());
$instance = $this->app()->make(Instruction::class);
$actual = ProcessorHelper::runInstruction($instance, $context, $target, $params);
[Read more](<Document A.md>).

MARKDOWN,
'Document.md',
<<<'MARKDOWN'
[include:document-list]: ./
MARKDOWN,
],
'Another Directory / Default parameters' => [
<<<'MARKDOWN'
# `<` Document B `>`
Summary text.
[Read more](<InstructionTest/Document B.md>).
# Document
Document summary.
[Read more](<InstructionTest/Document.md>).
# Document A
Summary text with special characters `<`, `>`, `&`.
[Read more](<InstructionTest/Document A.md>).

MARKDOWN,
'.php',
<<<'MARKDOWN'
[include:document-list]: ./InstructionTest
MARKDOWN,
],
'Nested Directories' => [
<<<'MARKDOWN'
# Nested B
Summary [text](../Document.md).
[Read more](<B/Document B.md>).
# Nested A
Summary [text](../Document.md).
[Read more](<A/Document A.md>).
# Document C
Summary [text](../Document.md) summary [link](../Document.md "title") and summary and self and self.
[Read more](<Document C.md>).

MARKDOWN,
'nested/Document.md',
<<<'MARKDOWN'
[include:document-list]: . ({"depth": null, "order": "Desc"})
MARKDOWN,
],
'Level `null`' => [
<<<'MARKDOWN'
## `<` Document B `>`
Summary text.
[Read more](<Document B.md>).
## Document A
Summary text with special characters `<`, `>`, `&`.
[Read more](<Document A.md>).

MARKDOWN,
'Document.md',
<<<'MARKDOWN'
# Header
Text text.
[include:document-list]: ./ ({"level": null})
MARKDOWN,
],
'Level `0`' => [
<<<'MARKDOWN'
### `<` Document B `>`
Summary text.
[Read more](<Document B.md>).
### Document A
Summary text with special characters `<`, `>`, `&`.
[Read more](<Document A.md>).

MARKDOWN,
'Document.md',
<<<'MARKDOWN'
### Header
Text text.
[include:document-list]: ./ ({"level": 0})
MARKDOWN,
],
'Level `<number>`' => [
<<<'MARKDOWN'
#### `<` Document B `>`
Summary text.
[Read more](<Document B.md>).
#### Document A
Summary text with special characters `<`, `>`, `&`.
[Read more](<Document A.md>).

MARKDOWN,
'Document.md',
<<<'MARKDOWN'
# Header
self::assertEquals(
self::getTestData()->content('~NestedDirectories.md'),
<<<MARKDOWN
<!-- markdownlint-disable -->
Text text.
{$actual}
MARKDOWN,
);
[include:document-list]: ./ ({"level": 4})
MARKDOWN,
],
];
}
//</editor-fold>
}

This file was deleted.

This file was deleted.

This file was deleted.

Loading

0 comments on commit 1ef782d

Please sign in to comment.