[Background - I'm porting my golang blog app to racket, and figuring it out as I go]
I've been working through the web-server-lib docs and learning to use include-template
. In my existing app, the installation of the blog software is separate from the templates, content, and other assets for a specific site. I did some work to configure the site-base and relative template and posts paths, but found that include-template
will not read the template, but fails with "bad relative pathname string". After some frustrating RTFMing I found that all the variants of include*
in racket expect a path-spec
that is only a relative path:
That is, string
refers to a file using a platform-independent relative path
A jump to Github led me to the actual code:
(unless (module-path? s)
(raise-syntax-error
#f
"bad relative pathname string"
stx
fn))
I didn't read up on module-path?
yet but I assume it keeps to things under the module file system structure.
I can imagine this is a security feature since include-template
derives (not in the technical sense) from the same code that is used for require
, ie trying to avoid a malicious program from include
-ing /etc/passwd
for example.
This leaves me with the question: is there a way to integrate with web-server/templates
where I read the files myself and add them to some namespace so that they can be included (including in sub-templates) or am I trying to do something 1) bad 2) stupid 3) both?
I really don't want to embed the entire look and feel of a site into the racket application?
--Steve
2 Likes
After a lot more research realized this was way more complicated than I needed, and I'm looking now at just copying the templates to a "nearby" tmp directory that can be required from (hoping it works)
1 Like
Keep in mind that, in using include-template
from web-server/templates
, you're effectively running a program written in #lang scribble/text
, IIRC.
As for the relative paths, probably you need to set current-load-relative-directory
to the directory containing the template. Then use the relative file names in the requires.
Also, to access certain variables within the template -- e.g. @contents
or @title
and so on, which is kind of the whole point of a template approach -- then you need to:
- create a namespace
- attach/require some other modules into that
- make a form that introduces your own variable bindings and calls
include-template
-
eval
that form in that namespace (and with the load-relative directory set).
I found this confusing when I did it many years agoo, for my now-dormant blog app, Frog. I got some help on the old mailing list, and cargo-culted some things. I barely understood how/why it worked, years ago, much less today.
Having said that, you're welcome to scrounge my old code. See template.rkt, which provides a wrapper for include-template
-- a render-template
function. It takes a directory, a template file path, and a dictionary of variables/values to be used within the template. It returns the HTML text. Search other files for some example uses of render-template
.
Hi Greg! I actually found Frog and have been trolling through the code for a few days! Thanks! I do need to revisit your template code, I didn't understand it at all when I started, but I've been deep in racket's include code recently so hopefully it will make more sense.
Question @greghendershott -- I understand that templates are their own "lang" (scribble/text) but is there a performance hit or something? Your "keep in mind" felt a bit like a "beware"
Not re performance. Just in terms of how to use include-template
. Using the template is effectively like running an end user program, and you need to be aware of things like namespaces and load-directories, which you wouldn't with a "normal" function call. Also the use of eval
, which is usually a smell, is IIUC fine here.
1 Like