ancarda / gemtext-parser
Gemtext (text/gemini) parser with conversion to HTML
Requires
- php: ^8.0
Requires (Dev)
- ancarda/coverage-enforcer: ^1.0
- infection/infection: ^0.26.6
- phpstan/phpstan: ^1.5
- phpstan/phpstan-phpunit: ^1.1
- phpstan/phpstan-strict-rules: ^1.1
- phpunit/phpunit: ^9.5
- squizlabs/php_codesniffer: ^3.6
README
Gemtext (text/gemini) parser and HTML encoder
This package implements a PHP parser for Gemtext (text/gemini
) as specified
here: https://gemini.circumlunar.space/docs/gemtext.gmi
Useful Links
- Source Code: https://git.sr.ht/~ancarda/gemtext-parser/
- Issue Tracker: https://todo.sr.ht/~ancarda/gemtext-parser/
- Mailing List: https://lists.sr.ht/~ancarda/gemtext-parser/
Usage
All the low level classes are built around Generator
, which makes plugging in
middleware easy while keeping memory usage low.
Unfortunately, Generators can be a bit of work to actually use. As such, a
utility class, SimpleTransformer
is available which abstracts this away if
you just want a Gemtext to HTML conversion quickly and easily.
Here's how to convert Gemtext to HTML with the low level (Generator
) API:
<?php $parser = new Ancarda\Gemini\Gemtext\Parser; $encoder = new Ancarda\Gemini\Gemtext\Encoder\HTML; $nodes = $parser->parse(explode("\n", $gemtext)); $html = implode("\n", iterator_to_array($encoder->encode($nodes)));
And here's the higher level utility class, which abstracts this away:
<?php $transformer = new \Ancarda\Gemini\Gemtext\Util\SimpleTransformer; echo $transformer->transform($gemText);
Pipelining
You can create lightweight middleware by creating a function that accepts and
returns Generator<Node>
. This function would be inserted between encode
and
parse
, like so:
$encoder->encode($middleware($parser->parse(explode("\n", $gemtext))));
Here, middleware's __invoke
method accepts and returns Generator<Node>
.
Middleware could make modifications, inject new nodes, drop some nodes, and so
on. For instance:
<?php $reverse_paragraphs = new class { public function __invoke(Generator $nodes): Generator { foreach ($nodes as $node) { if ($node instanceof Paragraph) { yield new Paragraph(strrev($node->getText())); } else { yield $node; } } } };