Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
a71d849
Add search field for API documentation
JesusValeraDev Jan 16, 2022
f118695
Improve dropdown CSS
JesusValeraDev Jan 16, 2022
918999d
Normalize function names for searcher
Chemaclass Jan 17, 2022
ac0eeec
Refactor and fix the api-page.php script
Chemaclass Jan 17, 2022
3514bbe
Create DocFileGenerator
Chemaclass Jan 17, 2022
47bf3e2
Improve search results
JesusValeraDev Jan 17, 2022
64f3802
Rename some vars
JesusValeraDev Jan 17, 2022
706277b
Install Gacela and create FileGenerator module
Chemaclass Jan 17, 2022
1e709e7
Add new empty line at the end of all php files
Chemaclass Jan 17, 2022
1e3fb2f
Merge branch 'feature/search-field' into refactoring/add-tests--doc-f…
JesusValeraDev Jan 17, 2022
d8ce471
Merge pull request #26 from phel-lang/refactoring/add-tests--doc-file…
JesusValeraDev Jan 17, 2022
b9a3f56
Fix array PHPDoc
JesusValeraDev Jan 17, 2022
3acda15
Fix ApiSearchGenerator
Chemaclass Jan 17, 2022
2fa2836
Add another SPECIAL_ENDING_CHARS to ApiSearchGenerator
Chemaclass Jan 17, 2022
b221d19
PhelFnNormalizer use strtolower for the groupKey
Chemaclass Jan 17, 2022
32338b6
Add more ApiSearchGenerator unit tests
Chemaclass Jan 17, 2022
6ac72dc
Restructure FileGenerator under php dir
Chemaclass Jan 17, 2022
fc3d36e
Minor CSS tweaks
JesusValeraDev Jan 17, 2022
e882d43
Add elasticlunr.min.js file + center search bar
JesusValeraDev Jan 18, 2022
141dfca
Hide search results when user click in one element
JesusValeraDev Jan 18, 2022
ac895aa
Format md item description from [a](b) to <i>a</i>
JesusValeraDev Jan 18, 2022
7b33c47
Minor cleanup
Chemaclass Jan 18, 2022
8a52de3
Add composer build command
JesusValeraDev Jan 19, 2022
a2e6163
Improved top navigation on mobile
jenshaase Jan 20, 2022
551d281
Improve JS structure
JesusValeraDev Jan 21, 2022
7eadb9c
Fix special chars in search field
JesusValeraDev Jan 21, 2022
000665b
Improve UX from search field
JesusValeraDev Jan 21, 2022
ba3a74a
Revert CSS border by padding
JesusValeraDev Jan 21, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# https://help.github.com/en/categories/automating-your-workflow-with-github-actions

on:
- pull_request
- push

name: CI

jobs:

tests:
name: Tests on PHP ${{ matrix.php }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
php: ['7.4']
steps:
- uses: actions/checkout@v2

- uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
coverage: none
tools: composer

- name: Get composer cache directory
id: composer-cache
run: echo "::set-output name=dir::$(composer config cache-files-dir)"

- name: Cache dependencies
uses: actions/cache@v2
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
restore-keys: ${{ runner.os }}-composer-

- name: Install dependencies
run: composer install --no-interaction --no-ansi --no-progress

- name: Run tests
run: vendor/bin/phpunit
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
.vscode
.phel-repl-history
.phpunit.result.cache

/content/documentation/api.md
/public
/static/api_search.js
/vendor
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,5 @@ zola build # build & publish

```bash
composer install # install phel as composer dependency
php build/api-page.php > content/documentation/api.md
composer build # build the API documentation page & the API search index
```
43 changes: 6 additions & 37 deletions build/api-page.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,50 +2,19 @@

declare(strict_types=1);

use Gacela\Framework\Gacela;
use Phel\Lang\Keyword;
use Phel\Lang\TypeFactory;
use Phel\Run\RunFacade;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Output\ConsoleOutput;

require __DIR__ . '/../vendor/autoload.php';

use Gacela\Framework\Gacela;
use PhelDocBuild\FileGenerator\Facade;

Gacela::bootstrap(__DIR__, [
'config' => [
'type' => 'php',
'path' => 'phel-config.php',
'path_local' => 'phel-config-local.php',
],
]);
$rf = new RunFacade();
$rf->getRunCommand()->run(new ArrayInput(['path' => __DIR__ . '/src/doc.phel']), new ConsoleOutput());

echo "+++\n";
echo "title = \"API\"\n";
echo "weight = 110\n";
echo "template = \"page-api.html\"\n";
echo "+++\n\n";

$normalizedData = [];
foreach ($GLOBALS['__phel'] as $ns => $functions) {
$normalizedNs = str_replace('phel\\', '', $ns);
$moduleName = $normalizedNs === 'core' ? '' : $normalizedNs . '/';
foreach ($functions as $fnName => $fn) {
$fullFnName = $moduleName . $fnName;

$normalizedData[$fullFnName] = $GLOBALS['__phel_meta'][$ns][$fnName] ?? TypeFactory::getInstance()->emptyPersistentMap();
}
}

ksort($normalizedData);
foreach ($normalizedData as $fnName => $meta) {
$doc = $meta[Keyword::create('doc')] ?? '';
$isPrivate = $meta[Keyword::create('private')] ?? false;

if (!$isPrivate) {
echo "## `$fnName`\n\n";
echo $doc;
echo "\n\n";
}
}
$fileGeneratorFacade = new Facade();
$fileGeneratorFacade->generateMdPage();
$fileGeneratorFacade->generateApiSearch();
2 changes: 1 addition & 1 deletion build/phel-config.php
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?php

return [
'src-dirs' => ['/src'],
'src-dirs' => ['/src/phel'],
'test-dirs' => [],
'vendor-dir' => '/../vendor'
];
File renamed without changes.
15 changes: 15 additions & 0 deletions build/src/php/FileGenerator/Config.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

declare(strict_types=1);

namespace PhelDocBuild\FileGenerator;

use Gacela\Framework\AbstractConfig;

final class Config extends AbstractConfig
{
public function getSrcDir(): string
{
return __DIR__ . '/../..';
}
}
22 changes: 22 additions & 0 deletions build/src/php/FileGenerator/DependencyProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

declare(strict_types=1);

namespace PhelDocBuild\FileGenerator;

use Gacela\Framework\AbstractDependencyProvider;
use Gacela\Framework\Container\Container;
use Phel\Run\RunFacade;

/**
* @method Factory getFactory()
*/
final class DependencyProvider extends AbstractDependencyProvider
{
public const FACADE_PHEL_RUN = 'FACADE_PHEL_RUN';

public function provideModuleDependencies(Container $container): void
{
$container->set(self::FACADE_PHEL_RUN, fn() => new RunFacade());
}
}
51 changes: 51 additions & 0 deletions build/src/php/FileGenerator/Domain/ApiSearchGenerator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php

declare(strict_types=1);

namespace PhelDocBuild\FileGenerator\Domain;

final class ApiSearchGenerator
{
private const SPECIAL_ENDING_CHARS = ['=', '*', '?', '+', '>', '<', '!'];

/**
* @return array<string,array{fnName:string,fnSignature:string,desc:string,anchor:string}>
*/
public function generateSearchIndex(array $groupNormalizedData): array
{
/**
* Zola ignores the especial chars, and uses instead a number. This variable keep track
* of the appearances and uses an autoincrement number to follow the proper link.
*
* For example, consider the two functions: `table` and `table?`
* They belong to the same group `table`, and their anchor will be such as:
* table -> table
* table? -> table-1
*/
$groupFnNameAppearances = [];

$result = [];
foreach ($groupNormalizedData as $groupKey => $values) {
$groupFnNameAppearances[$groupKey] = 0;

foreach ($values as ['fnName' => $fnName, 'fnSignature' => $fnSignature, 'desc' => $desc]) {
if ($groupFnNameAppearances[$groupKey] === 0) {
$anchor = $groupKey;
$groupFnNameAppearances[$groupKey]++;
} else {
$sanitizedFnName = str_replace(['/', ...self::SPECIAL_ENDING_CHARS], ['-', ''], $fnName);
$anchor = rtrim($sanitizedFnName, '-') . '-' . $groupFnNameAppearances[$groupKey]++;
}

$result[] = [
'fnName' => $fnName,
'fnSignature' => $fnSignature,
'desc' => $desc,
'anchor' => $anchor,
];
}
}

return $result;
}
}
32 changes: 32 additions & 0 deletions build/src/php/FileGenerator/Domain/MdPageRenderer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

declare(strict_types=1);

namespace PhelDocBuild\FileGenerator\Domain;

final class MdPageRenderer
{
private OutputInterface $output;

public function __construct(OutputInterface $output)
{
$this->output = $output;
}

public function renderMdPage(array $groupNormalizedData): void
{
$this->output->writeln("+++");
$this->output->writeln("title = \"API\"");
$this->output->writeln("weight = 110");
$this->output->writeln("template = \"page-api.html\"");
$this->output->writeln("+++\n");

foreach ($groupNormalizedData as $values) {
foreach ($values as ['fnName' => $fnName, 'doc' => $doc]) {
$this->output->writeln("## `$fnName`\n");
$this->output->write($doc);
$this->output->writeln("\n");
}
}
}
}
12 changes: 12 additions & 0 deletions build/src/php/FileGenerator/Domain/OutputInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

declare(strict_types=1);

namespace PhelDocBuild\FileGenerator\Domain;

interface OutputInterface
{
public function write(string $line): void;

public function writeln(string $line): void;
}
15 changes: 15 additions & 0 deletions build/src/php/FileGenerator/Domain/PhelFnLoaderInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php

declare(strict_types=1);

namespace PhelDocBuild\FileGenerator\Domain;

use Phel\Lang\Collections\Map\PersistentMapInterface;

interface PhelFnLoaderInterface
{
/**
* @return array<string,PersistentMapInterface>
*/
public function getNormalizedPhelFunctions(): array;
}
68 changes: 68 additions & 0 deletions build/src/php/FileGenerator/Domain/PhelFnNormalizer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
<?php

declare(strict_types=1);

namespace PhelDocBuild\FileGenerator\Domain;

use Phel\Lang\Keyword;

final class PhelFnNormalizer
{
private PhelFnLoaderInterface $phelFnLoader;

public function __construct(PhelFnLoaderInterface $phelFnLoader)
{
$this->phelFnLoader = $phelFnLoader;
}

/**
* @return array<string,array{fnName:string,doc:string,fnSignature:string,desc:string}>
*/
public function getNormalizedGroupedPhelFns(): array
{
$normalizedData = $this->phelFnLoader->getNormalizedPhelFunctions();

$result = [];
foreach ($normalizedData as $fnName => $meta) {
$isPrivate = $meta[Keyword::create('private')] ?? false;
if ($isPrivate) {
continue;
}

$groupKey = preg_replace(
'/[^a-zA-Z0-9\-]+/',
'',
str_replace('/', '-', $fnName)
);

$doc = $meta[Keyword::create('doc')] ?? '';
$pattern = '#(```phel\n(?<fnSignature>.*)\n```\n)?(?<desc>.*)#s';
preg_match($pattern, $doc, $matches);

$result[strtolower(rtrim($groupKey, '-'))][] = [
'fnName' => $fnName,
'doc' => $meta[Keyword::create('doc')] ?? '',
'fnSignature' => $matches['fnSignature'] ?? '',
'desc' => $this->formatDescription($matches['desc'] ?? ''),
];
}

foreach ($result as $values) {
usort($values, static fn(array $a, array $b) => $a['fnName'] <=> $b['fnName']);
}

return $result;
}

/**
* The $desc is in Markdown format, the regex transforms links `[printf](https://...)` into `<i>printf</i>`.
*/
private function formatDescription(string $desc): string
{
return preg_replace(
'#\[([^\]]+)\]\(([^\)]+)\)#',
'<i>\1</i>',
$desc
);
}
}
27 changes: 27 additions & 0 deletions build/src/php/FileGenerator/Facade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

declare(strict_types=1);

namespace PhelDocBuild\FileGenerator;

use Gacela\Framework\AbstractFacade;

/**
* @method Factory getFactory()
*/
final class Facade extends AbstractFacade
{
public function generateMdPage(): void
{
$this->getFactory()
->createDocFileGenerator()
->renderMdPage();
}

public function generateApiSearch(): void
{
$this->getFactory()
->createDocFileGenerator()
->generateApiSearch();
}
}
Loading