Gemtext (text/gemini) parser and HTML encoder for PHP
Add contributing guidelines
Publish on SourceHut and Packagist
Align name on Packagist with Git repo



You can also use your local clone with git send-email.


Gemtext (text/gemini) parser and HTML encoder

License Latest Stable Version Total Downloads builds.sr.ht status

This package implements a PHP parser for Gemtext (text/gemini) as specified here: https://gemini.circumlunar.space/docs/gemtext.gmi


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:


$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:


$transformer = new \Ancarda\Gemini\Gemtext\Util\SimpleTransformer;

echo $transformer->transform($gemText);


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:


$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;