Skip to content

Commit

Permalink
Merge pull request #418 from hydephp/404-clean-up-generatesdocumentat…
Browse files Browse the repository at this point in the history
…ionsearchindexfile

Clean up GeneratesDocumentationSearchIndexFile
  • Loading branch information
caendesilva authored Aug 12, 2022
2 parents 7773d7c + aade541 commit 9d87258
Show file tree
Hide file tree
Showing 3 changed files with 35 additions and 38 deletions.
1 change: 1 addition & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ This release continues refactoring the internal codebase. As part of this, a lar
### Changed
- Blog posts now have the same open graph title format as other pages
- Merged deprecated method `getRoutesForModel` into `getRoutes` in `RouteCollection`
- Cleans up and refactors `GeneratesDocumentationSearchIndexFile`, and marks it as internal
- internal: Inline deprecated internal method usage `getOutputPath` replacing it `Hyde::pages()` helper with in `HydeRebuildStaticSiteCommand`

### Deprecated
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,82 +8,74 @@
use Hyde\Framework\Models\Pages\DocumentationPage;
use Illuminate\Support\Collection;
use Illuminate\Support\Str;
use JetBrains\PhpStorm\ArrayShape;

/**
* Generate a JSON file that can be used as a search index for documentation pages.
* @internal Generate a JSON file that can be used as a search index for documentation pages.
*
* @todo Convert into Service, and add more strategies, such as slug-only (no file parsing)
* search which while dumber, would be much faster to compile and take way less space.
* @todo Refactor to use custom site output paths
*
* @see \Hyde\Framework\Testing\Feature\Actions\GeneratesDocumentationSearchIndexFileTest
*
* @phpstan-consistent-constructor
*/
class GeneratesDocumentationSearchIndexFile implements ActionContract
final class GeneratesDocumentationSearchIndexFile implements ActionContract
{
use InteractsWithDirectories;

public Collection $searchIndex;
public static string $filePath = '_site/docs/search.json';

public static function run(): void
public static function run(): self
{
(new static())->execute();
return (new self())->execute();
}

public function __construct()
{
$this->searchIndex = new Collection();

static::$filePath = '_site/'.config('docs.output_directory', 'docs').'/search.json';
static::$filePath = Hyde::pathToRelative(Hyde::getSiteOutputPath(
DocumentationPage::getOutputDirectory().'/search.json')
);
}

public function execute(): void
public function execute(): self
{
$this->generate();
$this->save();

return $this;
}

public function generate(): static
public function generate(): self
{
/** @var DocumentationPage $page */
foreach (DocumentationPage::all() as $page) {
if (! in_array($page->identifier, config('docs.exclude_from_search', []))) {
$this->searchIndex->push(
$this->generatePageObject($page)
$this->generatePageEntry($page)
);
}
}

return $this;
}

public function generatePageObject(DocumentationPage $page): object
#[ArrayShape(['slug' => 'string', 'title' => 'string', 'content' => 'string', 'destination' => 'string'])]
public function generatePageEntry(DocumentationPage $page): array
{
return (object) [
return [
'slug' => basename($page->identifier),
'title' => $page->title,
'content' => trim($this->getSearchContentForDocument($page)),
'destination' => $this->getDestinationForSlug(basename($page->identifier)),
];
}

public function getObject(): object
{
return (object) $this->searchIndex;
}

public function getJson(): string
{
return json_encode($this->getObject());
}

public function save(): static
protected function save(): self
{
$this->needsDirectory(Hyde::path(str_replace('/search.json', '', static::$filePath)));

file_put_contents(Hyde::path(static::$filePath), $this->getJson());
file_put_contents(Hyde::path(static::$filePath), $this->searchIndex->toJson());

return $this;
}
Expand All @@ -110,7 +102,7 @@ public function save(): static
* Returning $document->body as is: 500ms
* Returning $document->body as Str::markdown(): 920ms + 10ms for regex
*/
public function getSearchContentForDocument(DocumentationPage $page): string
protected function getSearchContentForDocument(DocumentationPage $page): string
{
// This is compiles the Markdown body into HTML, and then strips out all
// HTML tags to get a plain text version of the body. This takes a long
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,23 +74,24 @@ public function test_it_handles_generation_even_when_there_are_no_pages()

public function test_save_method_saves_the_file_to_the_correct_location()
{
(new Action())->save();
Action::run();

$this->assertFileExists('_site/docs/search.json');
}

public function test_generate_page_object_method_generates_a_page_object()
public function test_generate_page_entry_method_generates_a_page_entry()
{
$expected = new \stdClass;
$expected->slug = 'foo';
$expected->title = 'Bar';
$expected->content = "Bar \n Hello World";
$expected->destination = 'foo.html';
$expected = [
'slug' => 'foo',
'title' => 'Bar',
'content' => "Bar \n Hello World",
'destination' => 'foo.html',
];

file_put_contents(Hyde::path('_docs/foo.md'), "# Bar\n\n Hello World");

$this->assertEquals(
$expected, (new Action())->generatePageObject(DocumentationPage::parse('foo'))
$expected, (new Action())->generatePageEntry(DocumentationPage::parse('foo'))
);

unlink(Hyde::path('_docs/foo.md'));
Expand All @@ -101,10 +102,11 @@ public function test_it_generates_a_valid_JSON()
file_put_contents(Hyde::path('_docs/foo.md'), "# Bar\n\n Hello World");
file_put_contents(Hyde::path('_docs/bar.md'), "# Foo\n\n Hello World");

$generatesDocumentationSearchIndexFile = (new Action())->generate();
$this->assertEquals(
'[{"slug":"bar","title":"Foo","content":"Foo \n Hello World","destination":"bar.html"},'.
'{"slug":"foo","title":"Bar","content":"Bar \n Hello World","destination":"foo.html"}]',
(new Action())->generate()->getJson()
json_encode($generatesDocumentationSearchIndexFile->searchIndex->toArray())
);

unlink(Hyde::path('_docs/foo.md'));
Expand Down Expand Up @@ -134,7 +136,8 @@ public function test_excluded_pages_are_not_present_in_the_search_index()
Hyde::touch(('_docs/excluded.md'));
config(['docs.exclude_from_search' => ['excluded']]);

$this->assertStringNotContainsString('excluded', (new Action())->generate()->getJson());
$generatesDocumentationSearchIndexFile = (new Action())->generate();
$this->assertStringNotContainsString('excluded', json_encode($generatesDocumentationSearchIndexFile->searchIndex->toArray()));

unlink(Hyde::path('_docs/excluded.md'));
}
Expand All @@ -144,7 +147,8 @@ public function test_nested_source_files_do_not_retain_directory_name_in_search_
mkdir(Hyde::path('_docs/foo'));
touch(Hyde::path('_docs/foo/bar.md'));

$this->assertStringNotContainsString('foo', (new Action())->generate()->getJson());
$generatesDocumentationSearchIndexFile = (new Action())->generate();
$this->assertStringNotContainsString('foo', json_encode($generatesDocumentationSearchIndexFile->searchIndex->toArray()));

unlink(Hyde::path('_docs/foo/bar.md'));
rmdir(Hyde::path('_docs/foo'));
Expand Down

0 comments on commit 9d87258

Please sign in to comment.