summaryrefslogtreecommitdiff
path: root/res/about/help.gmi
diff options
context:
space:
mode:
Diffstat (limited to 'res/about/help.gmi')
-rw-r--r--res/about/help.gmi87
1 files changed, 87 insertions, 0 deletions
diff --git a/res/about/help.gmi b/res/about/help.gmi
index 3f21adb8..af534c2e 100644
--- a/res/about/help.gmi
+++ b/res/about/help.gmi
@@ -315,12 +315,99 @@ Other Unix : ~/.config/lagrange/
315 315
316* bindings.txt 316* bindings.txt
317* bookmarks.txt 317* bookmarks.txt
318* feeds.txt
318* idents.binary and idents/ 319* idents.binary and idents/
320* mimehooks.txt
319* prefs.cfg 321* prefs.cfg
320* state.binary 322* state.binary
321* trusted.txt 323* trusted.txt
322* visited.txt 324* visited.txt
323 325
326# MIME hooks
327
328MIME hooks enable piping Gemini responses through external programs for arbitrary processing. This allows leveraging scripting languages and binary executables to perform format conversions, content transformation, and data analysis.
329
330Hooks are configured using the file "mimehooks.txt" in Lagrange's config directory. Each hook has a regexp that is matched against the response MIME type and parameters, and each matching hook is offered the response body via stdin. The called external programs are free to rewrite the entire response, including the MIME type. If one of the hooks returns a valid response, it is used as the final response of the Gemini request.
331
332Example use cases:
333* Parsing an Atom XML feed and generating a Gemini feed index page
334* Rendering a MIDI file using Timidity as PCM WAV
335* Generate a graph PNG based on values in a CSV
336* Converting HTML or Markdown to 'text/gemini'
337* Language translations
338
339## Interface
340
341When a hook is called, it is given the MIME type and parameters via command line arguments. The response body is provided via stdin.
342
343The MIME type and parameters are split at semicolons, so "text/gemini; lang=ja" would be called as:
344```
345hookprogram text/gemini lang=ja
346```
347
348Output from the program (via stdout) must be a valid "20" Gemini response that includes the new MIME type:
349```
35020 text/gemini; lang=en\r\n
351{...body...}
352```
353
354Any output that does not follow this format is considered to mean that the hook refused to process the contents. The next hook will be offered the response instead.
355
356## mimehooks.txt syntax
357
358Like other Lagrange configuration lines, mimehooks.txt has a simple line-oriented syntax. Lagrange must be restarted for changes to the configuration file to take effect.
359
360Each hook is specified as three lines:
361* A human-readable label (for reporting to the user)
362* MIME type/parameter regular expression
363* Command to execute, plus additional arguments each separated with semicolons
364
365For example:
366```
367Convert Atom to Gemini feed
368application/xml
369/usr/bin/python3;/home/jaakko/atomconv.py
370```
371
372The hook program is executed directly without involving the shell. This means scripts must be invoked via the interpreter executable.
373
374## Example: Converting from Atom to Gemini
375
376The following simple Python script demonstrates how a MIME hook could be used to parse an Atom XML document using Python 3 and output a Gemini feed index page based on the parsed entries. This is just a simple example; a more robust script could include more content from the Atom feed and handle errors, too.
377```
378import sys
379import xml.etree.ElementTree as ET
380
381def atomtag(n):
382 return '{http://www.w3.org/2005/Atom}' + n
383
384root = ET.fromstring(sys.stdin.read())
385if root.tag != atomtag('feed'):
386 sys.exit(0)
387feed_title = ''
388feed_author = ''
389feed_entries = []
390for child in root:
391 if child.tag == atomtag('title'):
392 feed_title = child.text
393 elif child.tag == atomtag('entry'):
394 feed_entries.append(child)
395print("20 text/gemini\r")
396print(f'# {feed_title}')
397for entry in feed_entries:
398 entry_date = ''
399 entry_title = ''
400 entry_link = ''
401 for child in entry:
402 if child.tag == atomtag('updated'):
403 entry_date = child.text[:10]
404 elif child.tag == atomtag('title'):
405 entry_title = child.text
406 elif child.tag == atomtag('link'):
407 entry_link = child.attrib['href']
408 print(f'=> {entry_link} {entry_date} {entry_title}')
409```
410
324# Open source licenses 411# Open source licenses
325 412
326=> about:license 413=> about:license