mbutterick / pollen-users

please use https://forums.matthewbutterick.com/c/typesetting/ instead
https://forums.matthewbutterick.com/c/typesetting/
53 stars 0 forks source link

Meta values not evaluated? #104

Closed casouri closed 3 years ago

casouri commented 3 years ago

I have a small helper jpgs that marks a piece of text Japanese:

In pollen.rkt:

(define (jpns text)
  (txexpr 'span '((class "jpns")) (list text)))

And in my document I set the artist meta to "流線形":

In day-22.html.pm:

◊define-meta[artist]{◊jpns{流線形}}

Finally, I insert the artist information in my template:

In template.html.p:

<html>
  <head><meta charset="UTF-8"></head>
  <body>
    <p>◊(->html (select-from-metas 'artist (current-metas)))</p>
    ◊(->html doc)
  </body>
</html>

However in the output file (day-22.html), I get <jpns>流線形</jpns> instead of <span class="jpns">流線形</span>.

Is this just how metas work? Is there any way to work around this? Thanks in advance.

mbutterick commented 3 years ago

metas is a hash table (specifically a hasheq), so it can only hold literal values. In this case, you are inserting ◊jpns{流線形} hoping it will be evaluated as code later. But no — it is treated as the literal X-expression '(jpns "流線形").

  1. You could just use "流線形" as the meta value, and put the jpns tag in the template.

  2. You could just use jpns as a tag. Web browsers treat unspecified tags as span elements.

casouri commented 3 years ago

Thanks! I cannot use either of the two approaches. I can't put the jpns tag in the template because there are artist names that are not in Japanese, and I can't detect the language automatically because CJK characters could be Chinese, Korean, Japanese, etc. For the second approach, I have more complicated contents like links that I want to put into meta, those cannot work literally.

However, knowing that metas won't cut it, I came up with this. I split the document into two sections, head and body:

◊head{
◊cover{◊image{./流線形--tokyo-sniper.jpg}}
◊artist{◊jpns{流線形}}
◊title{Time Machine Love}
◊album{◊link["https://youtu.be/pk2C6hBdlOs"]{Tokyo Sniper}}
◊year{2006}
}

◊body{
The main text that I want to show.
}

And in the template, I extract values from head and only show the content in body:

<html>
  <head>
    <meta charset="UTF-8">
    <title>◊(day-title)</title>
  </head>
  <body>

    <p>◊(->html (select 'cover doc))</p>
    <p>◊(->html (select 'title doc))</p>

    ◊(->html (select* 'body doc))
  </body>
</html>

Hopefully, this could help others that need to generate structural content.

otherjoel commented 3 years ago

Note that you can alter (current-metas) from within a tag function, which would allow you to place the result of an expression in your metas. This is partially because current-metas is a parameter than can be updated, and partially because Pollen is designed to preserve any updates that remain after root is finished.

Example pollen.rkt:

#lang racket

(provide set-meta!)

(define (set-meta! sym val)
  (current-metas (hash-set (current-metas) sym val)))

Example source file:

#lang pollen

Hello

◊set-meta!['title (number->string (+ 100 5))]

Result of “running” the above file in the DrRacket REPL:

'(root "Hello")
> metas
'#hasheq((here-path . "/[…]/test.html.pm") (title . "105"))
casouri commented 3 years ago

Thanks! This is really helpful.