# Generating svgs using the html renderer for Scribble

**URL:** <https://racket.discourse.group/t/generating-svgs-using-the-html-renderer-for-scribble/1634>\
**Category:** General\
**Created:** [January 11, 2023, 4:09pm UTC](https://racket.discourse.group/t/generating-svgs-using-the-html-renderer-for-scribble/1634 "2023-01-11T16:09:43Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![soegaard](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/soegaard/32/19_2.png) [@soegaard](https://racket.discourse.group/u/soegaard)\
**Post date:** [January 11, 2023, 4:09pm UTC](https://racket.discourse.group/t/generating-svgs-using-the-html-renderer-for-scribble/1634/1 "2023-01-11T16:09:43Z")

</div>

Hi All,

The the html renderer for Scribble has a keyword argument `#:image-preferences`.  
The argument can be used to pass a list of preferred image formats to Scribble,  
such as svg, png etc.

In the example program below, I am passing a pict to the html renderer.  
Despite passing `(svg)` as the list of preferred image formats, the  
program generates a png file.

What have I overlooked? Is there an additional parameter I need to set?

```scheme
#lang racket
(require scribble/render scribble/manual scribble/core scribble/decode
         scribble/base-render scribble/xref
         (prefix-in html: scribble/html-render)
         setup/xref)

(define no-style (style "from_scribble" '()))

; The result of prepare is a list of parts.

(define (block->part x) (part #f '() #f no-style '() (list x) '()))
(define (blocks->part xs) (part #f '() #f no-style '() xs '()))

(define (content->block x) (paragraph no-style x))
(define (contents->block xs) (paragraph no-style xs))
(define (content->part x) (block->part (content->block x)))
(define (contents->part xs) (block->part (contents->block xs)))

(define (element->paragrah x) (paragraph no-style x))
(define (paragraph->part x) (block->part x))
(define (element->part x) (paragraph->part (element->paragrah x)))

(define (prepare x)
  (define who 'prepare)
  (cond
    [(part? x) (list x)]
    [(block? x) (list (block->part x))]
    [(box-splice? x) (map prepare (splice-run x))]
    [(list? x) (prepare* x)]
    [(element? x) (when (eq? (element-style x) 'tt)
                       (newline)(newline) (write x) (newline)(newline))
                     (element->part x)]
    [(content? x) (list (content->part x))]     
    [else (error who (~a "unexpected input, got: " x))]))

(define (prepare* xs)
  (define who 'prepare*)
  (cond
    [(andmap part? xs) xs]
    [(andmap block? xs) (list (blocks->part (prepare* xs)))]
    [(andmap content? xs) (list (contents->part (prepare* xs)))]
    
    [(list? xs) (append-map prepare xs)]
    [else (prepare xs)]))

(define (render docs
                names
                ; #:render-mixin [render-mixin html:render-mixin]
                #:dest-dir [dest-dir #f]
                #:helper-file-prefix [helper-file-prefix #f]
                #:prefix-file [prefix-file #f]
                #:style-file [style-file #f]
                #:style-extra-files [style-extra-files null]
                #:extra-files [extra-files null]
                #:image-preferences [image-preferences null]
                ; redirects sets set-external-tag-path
                #:redirect [redirect #f]  
                ; redirect-main sets set-external-root-url
                #:redirect-main [redirect-main #f]  
                #:directory-depth [directory-depth 0]
                #:xrefs [xrefs null]
                #:info-in-files [info-input-files null]
                #:info-out-file [info-output-file #f]
                #:quiet? [quiet? #t]
                #:warn-undefined? [warn-undefined? (not quiet?)])
  ; (set! docs (map prepare docs))
  (define out #f)
  (define render-mixin html:render-mixin)
  ; (when dest-dir (make-directory* dest-dir))
  (let ([renderer (new (render-mixin render%)
                       [dest-dir dest-dir]
                       [prefix-file prefix-file]
                       [style-file style-file]
                       [style-extra-files style-extra-files]
                       [extra-files extra-files]
                       [image-preferences image-preferences]
                       [helper-file-prefix helper-file-prefix])])
    ; tags are used for cross referencing
    (when redirect
      (send renderer set-external-tag-path redirect))
    (when redirect-main
      (send renderer set-external-root-url redirect-main))
    ; generate multiple files? (0 and 1 is treated the same)
    (unless (zero? directory-depth)
      (send renderer set-directory-depth directory-depth))
    ; if false, writes output-file information to current output port
    (unless quiet?
      (send renderer report-output!))
    ; build filenames from names
    (let* ([fns (map (lambda (fn)
                       (let-values ([(base name dir?) (split-path fn)])
                         (let ([fn (path-replace-suffix
                                    name
                                    (send renderer get-suffix))])
                           (if dest-dir (build-path dest-dir fn) fn))))
                     names)]
           ; 1. Traverse
           [fp (send renderer traverse docs fns)]
           ; 2. Collect 
           [info (send renderer collect docs fns fp)])
      ; additional cross-reference information
      (for ([file (in-list info-input-files)])
        (let ([s (with-input-from-file file read)])
          (send renderer deserialize-info s info)))
      ; transfer information to info
      (for ([xr (in-list xrefs)])
        (xref-transfer-info renderer info xr))
      ; 3. Resolve
      ; (match hyperlink references with targets)
      (let ([r-info (send renderer resolve docs fns info)])
        ; 4. Render
        (set! out
              (for/list ([doc docs])
                (send renderer render-part doc #;fns r-info)))
        ; Write cross-reference info to info-output-file
        (when info-output-file
          (let ([s (send renderer serialize-info r-info)])
            (with-output-to-file info-output-file
              #:exists 'truncate/replace
              (lambda () (write s)))))
        ; Maybe warn
        (when warn-undefined?
          (let ([undef (send renderer get-undefined r-info)])
            (unless (null? undef)
              (eprintf "Warning: some cross references may be broken due to undefined tags:\n")
              (for ([t (in-list undef)])
                (eprintf " ~s\n" t))))))
      (append* out))))

(define (embed-scribble x)
  (define docs (flatten (prepare x)))
  (render docs
          (build-list (length docs)
                      (λ(_) (~a "/tmp/fake-filename" (random 10000) ".rkt")))
          #:image-preferences '(svg)
          #:redirect "https://docs.racket-lang.org/local-redirect/index.html"
          #:redirect-main "http://docs.racket-lang.org/"
          #:xrefs (list (make-collections-xref))))

(require (prefix-in pict: pict))
(embed-scribble (pict:circle 10))

```

My output:

```scheme
'((p
   ((class "from_scribble"))
   (img ((style "vertical-align: 0px; margin: -3px -3px -3px -3px;") (src "pict.png") (alt "image") (width "16") (height "16")))))

```

And the file "pict.png" is created in the same folder as the source file.

---

<div class="post-metadata">

**Author:** ![soegaard](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/soegaard/32/19_2.png) [@soegaard](https://racket.discourse.group/u/soegaard)\
**Post date:** [January 11, 2023, 8:57pm UTC](https://racket.discourse.group/t/generating-svgs-using-the-html-renderer-for-scribble/1634/2 "2023-01-11T20:57:24Z")

</div>

The problem is that I am calling the method `render-part` directly  
and that the setup happens in the method `render`.

```scheme
(define/override (render ds fns ri)
      (parameterize ([current-render-convertible-requests
                      (sort-image-requests (current-render-convertible-requests)
                                           image-preferences)])
        (render-top ds fns ri)))

```

So either I need a way to parameterize `current-render-convertible-requests`  
my self (but it isn't exported) or put the part into something that `render` can receive.

---

<div class="post-metadata">

**Author:** ![soegaard](https://yyz2.discourse-cdn.com/free1/user_avatar/racket.discourse.group/soegaard/32/19_2.png) [@soegaard](https://racket.discourse.group/u/soegaard)\
**Post date:** [January 11, 2023, 9:14pm UTC](https://racket.discourse.group/t/generating-svgs-using-the-html-renderer-for-scribble/1634/3 "2023-01-11T21:14:02Z")

</div>

Parameterizing `current-render-convertible-requests` worked.

```scheme
(require rackunit)
(require/expose scribble/html-render (current-render-convertible-requests))

(define (embed-scribble x)
  (define docs (flatten (prepare x)))
  (parameterize ([current-render-convertible-requests '(svg-bytes)])
    (render docs
            (build-list (length docs)
                        (λ(_) (~a "/tmp/fake-filename" (random 10000) ".rkt")))
            #:image-preferences '(svg)
            #:redirect "https://docs.racket-lang.org/local-redirect/index.html"
            #:redirect-main "http://docs.racket-lang.org/"
            #:xrefs (list (make-collections-xref)))))

```
