Created
March 16, 2016 21:45
-
-
Save mbutterick/e16400c14e1c7d7c164c to your computer and use it in GitHub Desktop.
Scribble to X-expression conversion
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#lang at-exp br | |
(require scribble/manual scribble/core txexpr) | |
(provide scribble->xexpr) | |
(define (style->attrs s style-accessor) | |
(let* ([style-datum (style-accessor s)]) | |
(if (style? style-datum) ; either style struct, or simple symbol name | |
`((style ,(~a (style-name style-datum))) | |
(properties ,(string-join (map ~a (style-properties style-datum)) " "))) | |
`((style ,(~a style-datum)))))) | |
;; Unfortunately there seems to be no generic way of fetching the style & elements from a Scribble structure | |
;; the specific struct accessors must be used. | |
(define #'structure->txexpr | |
(λ(stx) | |
(syntax-match stx | |
[#'(_ structure-name elem-name id) | |
(syntax-let ([#'structure-name-elem-name (format-id stx "~a-~a" #'structure-name #'elem-name)] | |
[#'structure-name-style (format-id stx "~a-style" #'structure-name)]) | |
#'(let* ([elem-raw (structure-name-elem-name id)] | |
[elems (map scribble->xexpr (if (list? elem-raw) | |
(flatten elem-raw) | |
(list elem-raw)))]) | |
(list* 'structure-name (style->attrs id structure-name-style) elems)))]))) | |
(define (scribble->xexpr s) | |
(cond | |
[(nested-flow? s) (structure->txexpr nested-flow blocks s)] | |
[(paragraph? s) (structure->txexpr paragraph content s)] | |
[(element? s) (structure->txexpr element content s)] | |
[else s])) | |
(module+ test | |
(require rackunit) | |
(define-simple-check (check-sx? s) | |
(check-true (txexpr? (scribble->xexpr s)))) | |
(check-sx? @racketblock[(list +)]) | |
(check-sx? @racket[(list +)]) | |
(check-sx? @code{(list +)})) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment