Skip to content

Instantly share code, notes, and snippets.

@otherjoel
Created August 14, 2018 23:58
Show Gist options
  • Save otherjoel/eec9ac921ab9123ec3dcfe17118d4bfa to your computer and use it in GitHub Desktop.
Save otherjoel/eec9ac921ab9123ec3dcfe17118d4bfa to your computer and use it in GitHub Desktop.
Example module that replaces the last space in a tagged X-expression with the HTML nbsp entity
#lang racket
(require txexpr)
(define (string-reverse str)
(list->string (reverse (string->list str))))
(define (replace-first-space str)
(string-replace str " " " " #:all? #f))
(define (replace-last-space str)
(string-reverse (string-replace (string-reverse str) " " ";psbn&" #:all? #f)))
(define (nbsp xpr [found? #f])
(cond
[found? (values xpr found?)]
[(and (string? xpr) (string-contains? xpr " "))
(values (replace-last-space xpr) #t)]
[(txexpr? xpr)
(define-values (result-elements found-within?)
(for/fold ([result-xprs null]
[found-yet? #f])
([this-expr (in-list (reverse (get-elements xpr)))])
(define-values (this-result found-this-time?) (nbsp this-expr found-yet?))
(values (cons this-result result-xprs) found-this-time?)))
(values (txexpr (get-tag xpr) (get-attrs xpr) result-elements) found-within?)]
[else (values xpr found?)]))
(define (last-nbsp xpr)
(let-values ([(result _) (nbsp xpr)]) result))
(module+ test
(require rackunit)
(check-equal? (last-nbsp '(p "This is my only number"))
'(p "This is my only number"))
;; What if we break up the x-expression?
(check-equal? (last-nbsp '(p "This is my " (em "only") " number"))
'(p "This is my " (em "only") " number"))
;; Hide the space in the middle tag
(check-equal? (last-nbsp '(p "This is my " (em "only ") "number"))
'(p "This is my " (em "only ") "number"))
;; Hide the space in between two tags
(check-equal? (last-nbsp '(p "This is my " (em "only") " " (strong "number")))
'(p "This is my " (em "only") " " (strong "number")))
;; Doesn't mess with attributes
(check-equal? (last-nbsp '(p "This is my " (em "only") " " (strong [[class "c1 c2"]] "number")))
'(p "This is my " (em "only") " " (strong ((class "c1 c2")) "number"))))
;; Doesn't properly handle multiple spaces
;; such as:
;; '(p "This is my only number")
;; OR:
;; '(p "This is my " (em "only ") " number")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment