s9e/repdoc
REPdoc is a CLI tool that brings Read-Eval-Print to documentation. It supports Markdown with paired fenced code blocks: a php block to run, immediately followed by an output block (any language) showing the expected printed result.
Installation:
composer require s9e/repdoc --dev
composer.json under require-dev to avoid production bloat.First Use Case:
Create a Markdown file (e.g., docs/api_example.md) with a PHP snippet and expected output:
```php
$user = new App\Models\User(['name' => 'John Doe']);
$user->save();
echo $user->id;
1
Run REPdoc via:
vendor/bin/repdoc docs/api_example.md
Expected "1", got "2").Where to Look First:
vendor/bin/repdoc --help for flags (e.g., --output to save results).vendor/s9e/repdoc/src/Repdoc.php for extensibility points (e.g., custom evaluators).Local Development:
php artisan repdoc docs/*.md # Process all doc files
post-update-cmd in composer.json:
"scripts": {
"post-update-cmd": [
"@php artisan repdoc docs/api.md"
]
}
CI/CD Validation:
# .github/workflows/docs.yml
- name: Validate Documentation Examples
run: vendor/bin/repdoc docs/api.md || exit 1
Web Integration:
Route::get('/docs/api', function () {
return file_get_contents(public_path('docs/evaluated.html'));
});
php artisan repdoc:generate --cache=3600 # Cache for 1 hour
Artisan Command Wrapper: Create a custom command to extend REPdoc (e.g., add Laravel-specific evaluators):
php artisan make:command RepdocDocs
// app/Console/Commands/RepdocDocs.php
use S9e\Repdoc\Repdoc;
protected $signature = 'repdoc:docs {path : Path to Markdown file}';
public function handle() {
$repdoc = new Repdoc();
$result = $repdoc->processFile($this->argument('path'));
$this->info($result);
}
Sandboxed Evaluation:
Restrict REPdoc to a subset of PHP functions/classes (e.g., Laravel’s App\Models):
$repdoc = new Repdoc();
$repdoc->setAllowedFunctions(['App\Models\User', 'App\Models\Post']);
$repdoc->processFile('docs/model_example.md');
Markdown Processing Pipeline:
Chain REPdoc with Laravel’s Markdown parsers (e.g., spatie/laravel-markdown):
use Spatie\Markdown\MarkdownRenderer;
$renderer = new MarkdownRenderer();
$html = $renderer->toHtml(file_get_contents('docs/example.md'));
// Inject REPdoc output dynamically
Security Risks:
ini_set('disable_functions', 'exec,system,...') to block dangerous functions.box/spout for isolation.Output Mismatches:
time(), rand(), or DB queries will fail. Use fixed seeds or avoid such code in docs.trim() or preg_replace.Dependency Conflicts:
use App\Models\.... Prepend paths:
$repdoc->setIncludePaths([app_path()]);
Performance:
parallel-lint.Verbose Mode:
vendor/bin/repdoc --verbose docs/example.md
Dry Runs:
Use --dry-run to validate syntax without execution:
vendor/bin/repdoc --dry-run docs/example.md
Custom Evaluators: Override REPdoc’s default evaluator for Laravel-specific logic:
$repdoc->setEvaluator(function ($code) {
// Prepend Laravel autoloader
require app_path('bootstrap/autoload.php');
return eval($code);
});
Custom Markup: Extend REPdoc to support Laravel Blade snippets or SQL queries:
// Example: Add a `sql` block type
$repdoc->addBlockType('sql', function ($code) {
return DB::selectOne($code)->toJson();
});
Output Formatting: Modify output to include Laravel-specific metadata (e.g., timestamps, user context):
$repdoc->setOutputFormatter(function ($output) {
return "<div class='laravel-repdoc'>$output</div>";
});
CI Integration: Fail builds on specific doc files or output patterns:
- name: Check API Docs
run: |
vendor/bin/repdoc docs/api.md || \
(echo "API doc validation failed" && exit 1)
Environment Variables:
REPdoc runs in a clean PHP environment by default. Load Laravel’s .env:
$repdoc->setEnvironmentVariables([
'APP_ENV' => 'testing',
'DB_CONNECTION' => 'sqlite',
]);
Service Providers:
Docs using Laravel services (e.g., Auth::user()) require bootstrapping:
$repdoc->setBootstrap(function () {
$app = require __DIR__.'/../bootstrap/app.php';
$app->make(Kernel::class)->bootstrap();
});
Testing: Mock REPdoc in PHPUnit tests:
$repdoc = Mockery::mock(S9e\Repdoc\Repdoc::class);
$repdoc->shouldReceive('processFile')->andReturn('valid output');
How can I help you explore Laravel packages today?