Custom extension
This extension adds one document metric without changing syntax or rendering. It demonstrates registration and namespacing with a complete small implementation.
<?php
use Alto\Markdown\Extension\Stats\StatsContext;
use Alto\Markdown\Extension\Stats\StatsMetric;
use Alto\Markdown\Extension\Stats\StatsMetricDefinition;
use Alto\Markdown\Extension\StatsExtensionInterface;
use Alto\Markdown\Markdown;
final readonly class AcmeMetrics implements StatsExtensionInterface
{
public function name(): string
{
return 'acme';
}
public function statsMetrics(): iterable
{
yield new StatsMetricDefinition(
name: 'block-count',
summary: 'Number of parsed blocks.',
factory: static fn (): StatsMetric => new BlockCount(),
);
}
}
final readonly class BlockCount implements StatsMetric
{
public function measure(StatsContext $context): int
{
return count($context->blocks());
}
}
$document = Markdown::github()
->with(new AcmeMetrics())
->fromString("# Guide\n\nBody.\n");
$metrics = $document->stats()->extensionStats;The value is stored under the extension and metric names, preventing unrelated
packages from claiming the same metric identity. A metric receives an immutable
context and returns only a finite scalar value or null.
Use another capability interface only when the extension owns that behavior. Do not implement parser syntax merely to run analysis, and do not perform resource I/O without an injected resolver. See Extension points for the available contracts.