greghendershott / frog

Frog is a static blog generator implemented in Racket, targeting Bootstrap and able to use Pygments.
916 stars 96 forks source link

Linking to images from Scribble files #227

Open cwebber opened 6 years ago

cwebber commented 6 years ago

It would be good to be able to link to images in the img/ directory in Scribble files. Using @image isn't great because Racket copies the image in question into memory and then writes it out again rather than just using what's already there.

I tried doing this using something like:

#lang scribble/manual

@(require frog/scribble
          scribble/core
          scribble/html-properties)

@(elem
  #:style
  (style #f
         (list (alt-tag "img")
               (attributes '((src . "/img/IMG_20170918_155136272_HDR.jpg")
                             (beep . "boop"))))))

I was surprised to find that the outputted html looked like so:

<img src="/Test//img/IMG_20170918_155136272_HDR.jpg" beep="boop" />

Why did src get modified? I tried running this with the plain scribble command line tool, no Frog involved, and it was fine.

I think I found the source of the problem in frog/private/read-scribble.rkt:

(define (adjust-scribble-html xs img-uri)
  (for/list ([x (in-list xs)])
    (xexpr-map
     (lambda (x _)
       (list
        (match x
          [`(blockquote ([class "SCodeFlow"]) . ,xs)
           `(div ([class "SCodeFlow"]) ,@xs)]
          [`(img ,(list-no-order `[src ,src] x ...))
           `(img ([src ,(str img-uri "/" src)] ,@x))]
          ...))))))

which is being called from write-non-post-page in non-posts.rkt. So it looks like all image src's are being rewritten by Frog, even in the case where this isn't desired.

Happy to submit a patch to fix this... but I guess this was intentionally transforming the html for some reason, and I'm not sure on this layer how to only rewrite certain images but not others.

cwebber commented 6 years ago

A thought: I suspect the purpose of rewriting the paths for these elements is for the ones that are generated by image-element, in other words the images generated inside Racket, like with pict. A way to get around this might be to add a mixin to the scribble HTML renderer used by Scribble. We could override the render-content method so that if it sees that this is an image-element, it modifies the html at that point rather than doing it at the post-rendering-phase of read-scribble.rkt.

What do you think @greghendershott ? I'd be happy to give a crack at it if you're good with the idea.

greghendershott commented 6 years ago

Yes, it's handling the sort of images people generate in Scribble.

(As the comment in read-scribble.rkt mentions, I cribbed this from scriblogify. I did that many years ago, and haven't given it any thought since.)

A way to get around this might be to add a mixin to the scribble HTML renderer used by Scribble. We could override the render-content method so that if it sees that this is an image-element, it modifies the html at that point rather than doing it at the post-rendering-phase of read-scribble.rkt.

That sounds plausible -- although maybe a lot of work.

OR:

Another option might be to follow the example of the pygment-code function provided by frog/scribble. Let's say frog/scribble provides a new function, raw-image (open to a better name). That returns an elem like you tried to do, but also adding some special HTML attribute as a leave-me-alone flag -- say [frog-raw-image "true"]. Then read-scribble can look for that, avoid messing with the image src (and perhaps remove that frog-raw-image attribute so it's not some weird turd in the final HTML output).

Of the two, I'd lean toward the latter. It's a bit of a kludge -- but so is the entire read-scribble.rkt approach of running scribble and munging the output, already. IOW someday/maybe the whole approach should be redone, but in the meantime, there's something to be said for keeping it consistently kludgy? :smile:

greghendershott commented 6 years ago

p.s. I suppose frog-raw-image could instead be the alt-tag. That might be simper to match on, and instead of deleting just that attribute, all you have to do is replace the frog-raw-image tag with the img tag. (Just spitballing here, could be wrong.)

cwebber commented 6 years ago

I'm a-okay with adding a property kludge.

I don't understand what you mean by the alt tag suggestion though... are you suggesting filling in a value in the alt tag that's Frog-related? I'd rather not do that because the alt tag has an important accessibility purpose that we wouldn't want to strip out (providing an alternate name for the visually impaired).

greghendershott commented 6 years ago

I meant alt-tag in your example:

#lang scribble/manual

@(require frog/scribble
          scribble/core
          scribble/html-properties)

@(elem
  #:style
  (style #f
         (list (alt-tag "img")  ;; <========= HERE
               (attributes '((src . "/img/IMG_20170918_155136272_HDR.jpg")
                             (beep . "boop"))))))

Although I'm not familiar with scribble/html-properties, I assume you using (alt-tag "img") was how you output an <img _____> HTML element?

So I was suggesting something like (alt-tag "frog-raw-image") to output <frog-raw-image _____>.

Then in read-scribble.rkt, compared to using some magic attribute mixed in with other normal attributes, I thought it would be simpler match and to change to the desired output (an <img _____> whose src is left alone).

cwebber commented 6 years ago

Oh I see! Yes that makes sense. Sorry, I thought you meant the "alt" property on :)