You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
typesetting/quad/quadwriter/tags.rkt

179 lines
6.5 KiB
Racket

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

#lang debug racket/base
(require quad/qexpr
pollen/tag
quadwriter/core
racket/string
racket/list
racket/dict
racket/match
txexpr/base
"font.rkt"
"attrs.rkt")
(provide (all-defined-out))
(define (root attrs exprs)
;; don't put any attributes in root, so they can be overriden by top-level attributes in source
(qexpr attrs exprs))
(define-tag-function (p attrs exprs)
(match exprs
[(cons (? txexpr? tx) _)
#:when (equal? (attr-ref tx :font-family #false) "code")
;; wrap code blocks in `pre` to distinguish them from inline
(apply pre attrs exprs)]
;; no font-family so that it adopts whatever the surrounding family is
[_ (qexpr (append (list->attrs
:keep-first-lines "2"
:keep-last-lines "3"
:font-size "1em"
:display (symbol->string (gensym)))
attrs) exprs)]))
(define-tag-function (img attrs exprs)
(qexpr (list->attrs
:line-height "false"
:image-height "150"
:line-align "center" ; need `last` because img is a block-level element.
:image-file (second (assq 'src attrs))
:image-alt (second (assq 'alt attrs))
:display "block") exprs))
(define-tag-function (br attrs exprs) line-break)
(define-tag-function (hr attrs exprs) hr-break)
(define-tag-function (blockquote attrs exprs)
(qexpr (append (list->attrs
:display "block"
:first-line-indent "0"
:background-color "#eee"
:block-clip "true"
:font-family "blockquote"
:font-size "10"
:line-height "14"
:border-width-top "0.5"
:border-color-top "gray"
:border-inset-top "8"
:border-width-left "3"
:border-color-left "gray"
:border-inset-left "20"
:border-width-bottom "0.5"
:border-color-bottom "gray"
:border-inset-bottom "-2"
:border-width-right "0.5"
:border-color-right "gray"
:border-inset-right "20"
:inset-top "10"
:inset-bottom "8"
:inset-left "30"
:inset-right "30"
:keep-first-lines "all")
attrs) exprs))
(define id (default-tag-function 'id))
(define class (default-tag-function 'class))
(define-tag-function (strong attrs exprs)
(qexpr (append (list->attrs
:font-bold "true"
:font-size "1em")
attrs) exprs))
(define b strong)
(define-tag-function (a attrs exprs)
(qexpr (list->attrs
:link (second (assoc :href attrs))
:font-color "MediumVioletRed") exprs))
(define-tag-function (em attrs exprs)
(qexpr (append
(list->attrs
:font-italic "true"
:font-size "1em") attrs) exprs))
(define i em)
(define-syntax-rule (attr-list . attrs) 'attrs)
(define (heading-base font-size inset-top attrs exprs)
(qexpr (append (list->attrs
:font-family "heading"
:font-features "tnum 1"
:first-line-indent "0"
:display "block"
:font-size (number->string font-size)
:line-height (number->string (* 1.2 font-size))
:border-width-top "0.5"
:border-inset-top "9"
:inset-bottom "-3"
:inset-top (number->string inset-top)
:keep-with-next "true") attrs) exprs))
(define-tag-function (h1 attrs exprs)
(qexpr null (list page-break (heading-base 20 6 attrs exprs))))
(define-tag-function (h2 attrs exprs) (heading-base 16 7 attrs exprs))
(define-tag-function (h3 attrs exprs) (heading-base 14 8 attrs exprs))
(define h4 h3)
(define h5 h3)
(define h6 h3)
(define-tag-function (code attrs exprs)
(qexpr (append (list->attrs
:font-family "code"
:font-size "10"
:bg "aliceblue") attrs) exprs))
(define-tag-function (pre attrs exprs)
;; pre needs to convert white space to equivalent layout elements
(define new-exprs (add-between
(for*/list ([expr (in-list exprs)]
[str (in-list (string-split (string-join (get-elements expr) "") "\n"))])
(list (get-tag expr) (get-attrs expr) (string-replace str " " " ")))
line-break))
(qexpr (append (list->attrs
:display "block"
:background-color "aliceblue"
:first-line-indent "0"
:block-clip "true"
:font-family "code"
:font-size "11"
:line-height "14"
:border-inset-top "10"
:border-width-left "2"
:border-color-left "#669"
:border-inset-left "0"
:border-inset-bottom "-4"
:inset-left "12"
:inset-top "12"
:inset-bottom "8")
attrs) new-exprs))
(define (list-base attrs exprs [bullet-val #f])
(define bullet-space-factor 2.5)
(define em (dict-ref attrs :font-size default-font-size))
(define bullet-indent (* bullet-space-factor em))
(qexpr (cons (list :inset-left (number->string bullet-indent)) attrs)
(add-between
(for/list ([(expr idx) (in-indexed exprs)]
#:when (txexpr? expr))
(list* (get-tag expr) (cons (list :list-index (or bullet-val (format "~a" (add1 idx)))) (get-attrs expr)) (get-elements expr)))
para-break)))
(define bullet-quad '(q ((special "bullet"))))
(define-tag-function (ol attrs exprs) (list-base attrs exprs))
(define-tag-function (ul attrs exprs) (list-base attrs exprs ""))
(define-tag-function (li attrs exprs)
(define new-bullet-quad (match exprs
[(cons (txexpr _ attrs _) _)
(match bullet-quad
[(txexpr tag battrs elems)
(define new-attrs
(hash->attrs
(copy-block-attrs (attrs->hash attrs) (attrs->hash battrs))))
(txexpr tag new-attrs elems)])]
[_ bullet-quad]))
(qexpr attrs (cons new-bullet-quad exprs)))