Germ parses and generates Gemtext, converts it to HTML or Markdown, handles
response metadata, and makes Gemini requests. Its default features include
the request client and its network and TLS dependencies. Disable default
features to use ast, convert, meta, or quick without normal dependencies.
[dependencies]
germ = "0.5.0"To select features without the default request client:
[dependencies]
germ = { version = "0.5.0", default-features = false, features = ["ast"] }| Feature | Description |
|---|---|
default |
ast, convert, meta, request |
ast |
Construct AST trees from raw Gemtext |
blocking |
Make blocking Gemini requests |
convert |
Convert Gemtext to HTML or Markdown |
request |
Make asynchronous Gemini requests |
meta |
Parse and format Gemini response metadata |
macros |
Generate AST and converted output with macros |
quick |
Build individual Gemtext lines |
Gemini requests verify server certificates against Mozilla CA roots by default.
For a self-signed capsule, add its certificate in DER form to a
rustls::RootCertStore, then pass that store to
request::blocking::request_with_roots or
request::non_blocking::request_with_roots. The store is a trust anchor, not an
exact certificate fingerprint pin. Save and review the certificate separately
before trusting it; the default request functions do not remember certificates
between calls.
Requests time out after 30 seconds and have a 16 MiB response limit, including
the header. To change these limits or the trusted roots, set the fields of
request::RequestOptions and pass it to
request::blocking::request_with_options or
request::non_blocking::request_with_options. The blocking system DNS lookup
may outlast the timeout before it returns.
For trust on first use, implement request::CertificateStore with durable
storage keyed by hostname and port, then pass it to
blocking::request_with_tofu or non_blocking::request_with_tofu alongside
RequestOptions. These methods verify the presented certificate and complete
the TLS handshake before saving a first-use certificate or checking an existing
one, and before sending the URL. They reject an unexpected certificate change
until the stored certificate expires. An expired certificate is replaced after
the new one passes validation. The store must persist each update before
returning; callers can remove a pin deliberately when changing trust early.
Store methods run synchronously, including in the async request path.
TOFU uses the timeout and response size limits from RequestOptions but
ignores its root_certificates field.
Ast::to_gemtext() serialises parsed nodes and retains a consistent LF or CRLF
style and a final line ending. Mixed line endings and optional spaces after
Gemtext markers can be normalised, so exact source round trips are not
guaranteed.
HTML conversion escapes Gemtext content. HTML and Markdown conversion emit links for relative targets and Gemini, Gopher, HTTP, HTTPS, mailto, and FTP URLs; other schemes are shown as text. Markdown conversion escapes literal text, link labels, and destinations, and chooses a code fence that does not close inside preformatted content.
Meta parses quoted MIME parameters and quotes values as needed when formatting
them.
quick::link(url, label) takes the URL first and an optional label second.
Unknown Gemini status codes retain their numeric value. Use
Status::category() to inspect the response category indicated by the first
digit.
Runnable examples can be found within the
examples/ directory.
Run one with just example ast_to_gemtext.
just diff fetches gemini://geminiprotocol.net/ with a process-local TOFU
certificate store. The certificate pin is not retained between runs. The
example reports source formatting changes and checks that serialising and
reparsing preserves the parsed nodes.
Licensed under either of Apache License, Version 2.0 or MIT license at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this crate by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.