Cobblers

This is the first useful thing I've written in Racket, converting simple gemtext to html.

My aim in using gemtext is to pare down what I write so that I don't get bogged down with how things look, or think about any audience other than myself.

cobblers.rkt:

#! /usr/bin/env racket
#lang racket

(require racket/cmdline)
(require racket/file)
(require string-util)
(require gemtext)

(define (transform-url url-string)
  (regexp-replace #rx".gmi" url-string ".html"))

(define (sanitize-text text)
  (let* ((text (regexp-replace* #rx"&" text "\\&"))
         (text (regexp-replace* #rx"<" text "\\<"))
         (text (regexp-replace* #rx">" text "\\>")))
    text))

(define (gmi-heading->html element)
  (let ((level (gmi-heading-level element))
        (text  (gmi-heading-text  element)))
    (format "~a\n"
            level
            (sanitize-text text)
            level)))

(define (gmi-link->html element)
  (let ((url  (gmi-link-url element))
        (text (gmi-link-text element)))
    (format "~a
\n" (transform-url url) (sanitize-text text)))) (define (gmi-list->html elements) (format "\n" (apply string-append (for/list ((element (gmi-list-items elements))) (format "
  • ~a
  • \n" (sanitize-text element)))))) (define (gmi-blockquote->html element) (format "
    ~a
    \n" (sanitize-text (gmi-blockquote-body element)))) (define (gmi-pre->html elements) (format "
    \n~a
    \n" (apply string-append (for/list ((element (gmi-pre-body elements))) (format "~a\n" (sanitize-text element)))))) (define (gmi->html gmi-elements) (format (string-append (file->string "./template/prelude.html") "~a" (file->string "./template/postlude.html")) (apply string-append (for/list ((element gmi-elements)) (cond ((gmi-heading? element) (gmi-heading->html element)) ((gmi-link? element) (gmi-link->html element)) ((gmi-list? element) (gmi-list->html element)) ((gmi-blockquote? element) (gmi-blockquote->html element)) ((gmi-pre? element) (gmi-pre->html element)) ((string? element) (if (string=? element "") "" (format "

    ~a

    \n" (sanitize-text element)))) (else "")))))) (define (main) (command-line #:args (input-file-name output-file-name) (display-to-file (gmi->html (string->gmi (file->string input-file-name))) output-file-name #:exists 'replace))) (main)

    That does the conversion for a single file, so then I use make to automate the process of building, and publishing, the site.

    Makefile:

    GMI_FILES = $(shell find gemini/ -type f -name '*.gmi')
    HTML_FILES = $(patsubst gemini/%.gmi, website/%.html, $(GMI_FILES))
    
    build: $(HTML_FILES) website/style.css
    
    all: clean build publish
    
    website/%.html: gemini/%.gmi
    	@mkdir -p "$(@D)"
    	$(CURDIR)/cobblers.rkt "$<" "$@"
    
    website/style.css: template/style.css
    	@cp template/style.css website/style.css
    
    clean:
    	rm -rf website/*
    
    publish:
    	rsync -a --delete-after website/ monospod@tty.sdf.org:html/
    

    ... and it's "Cobblers", because it's both cobbled together, and a comment on what I'm sure I'll be writing.