Git Product home page Git Product logo

Comments (13)

tdammers avatar tdammers commented on August 27, 2024 1

from ginger.

tdammers avatar tdammers commented on August 27, 2024

This happens on the Haskell side of things; you need to pass context variables in when calling runGinger. http://hackage.haskell.org/package/ginger-0.5.1.2/docs/Text-Ginger-Run.html explains things in some more detail; however, essentially what you need to do is write a context lookup function which returns a suitable GVal value for each variable name, then you use one of the makeContext functions to turn it into a GingerContext, and then you pass that to the runGinger(M) function. E.g.:

let contextLookup varName =
           case varName of
               "username" -> toGVal username
               "imageURL" -> toGVal imageURL
               _ -> def -- def for GVal is equivalent to a NULL value
    context = makeContext contextLookup
htmlSource $ runGinger context template

Alternatively, you can write your context object as any dictionary-like data type that has a ToGVal instance, and use the easyRender(M) API.

from ginger.

tdammers avatar tdammers commented on August 27, 2024

This should probably be fixed in the documentation.

from ginger.

GildedHonour avatar GildedHonour commented on August 27, 2024

Is there any way to create a parent/child template?

from ginger.

tdammers avatar tdammers commented on August 27, 2024

Sure. You have two options here: {% include %} and {% extend %}/{% block %}.

{% include %} is just a dumb inclusion mechanism; it picks up the file you reference and injects it at the current position, similar to how #include works in C.

{% extends %} and {% block %} implement "template inheritance". It works as follows:

  • First, you write a parent template. This is just a regular template, but you can wrap blocks that you want to be able to override in {% block block_name %} / {% endblock %}.
  • Then you write the child template; this is not a regular template, it starts with an {% extends %} statement, and after that, only {% block %} statements are allowed, which override blocks of the same name from the parent template.

For example, you might write a parent template like so:

<!DOCTYPE html>
<html>
    <head>
        <title>{% block title %}My Super Fun Site{% endblock %}</title>
    </head>
    <body>
        <header>My Super Fun Site</header>
        <main>
            <h1>{% block main_header %}Hello!{% endblock %}</h1>
            {% block content %}
            {% endblock %}
        </main>
        <footer>
            Copyright (c) 2017 myself. All Rights Reserved.
        </footer>
    </body>
</html>

And then you can have a child template that overrides some of these blocks:

{% extends 'master.html' %}

{%- block title %}This is a different title.{% endblock -%}

{%- block content %}
Lorem ipsum dolor sit amet adipiscing elit. And so on.
{% endblock -%}

This will render a page using the same structure as the master template, but overriding the title and content blocks.

In order for this to work correctly, you need to tell the template loader how to load the parent template; the CLI contained in the main repo demonstrates this; you need to pass an IncludeResolver to parseGinger (or parseGingerFile), which is essentially a function that takes a file name and monadically return source code. The actual type is SourceName -> m (Maybe Source), with Monad m; however both Source and SourceName are aliases for String, and m is usually IO or something similar.

Hope that clears things up.

from ginger.

GildedHonour avatar GildedHonour commented on August 27, 2024

thanks, I'll try.

from ginger.

GildedHonour avatar GildedHonour commented on August 27, 2024

how is your library better compared to https://github.com/sourrust/karver ?

from ginger.

GildedHonour avatar GildedHonour commented on August 27, 2024

@tdammers up

from ginger.

tdammers avatar tdammers commented on August 27, 2024

how is your library better compared to https://github.com/sourrust/karver ?

Well, the most important differences should be obvious (ish) from the API and its types; anyway, from what I can gather from Karver's documentation, here's a (probably incomplete) list of what Ginger does differently (though whether that is necessarily better is debatable and depends on priorities and context):

  • Effectful templates. This was a big one for me, because I want template to be able to trigger effects such as loading additional data from the backend, getting the current time, etc. At the same time, I still wanted to keep things sandboxable, so Ginger doesn't just come with a truckload of I/O primitives, instead it allows you to parametrize your template loaders and runners over arbitrary monads, and then you can pass your effectful functions in as context variables.
  • Multi-tagged unitype context variables. For lack of a better word. Karver's context object is a hashmap of Text to Text; Ginger has a more sophisticated unitype that can express functions, lists, hashmaps, numbers, booleans, null, strings, and encoded HTML. The last one is especially important, because being able to tag HTML as "already encoded" means you hardly ever have to worry about XSS anymore. It also allows us to do things like write a |markdown filter that takes a raw string, interprets it as markdown, and spits out pre-encoded HTML - without the tag-level distinction between text and HTML, the template engine would HTML-encode the markdown output, which is not what you want.
  • Separate parsing and running steps. This is important for two reasons; one, you can cache parsed templates, avoiding a re-parse on future usages (and you can precompile all your templates at startup, reducing per-request overhead further, and catching template syntax errors early); and two, you can control effects for the parsing and running stages individually, that is, you can have effectful parses (for loading external templates, e.g. using {% include %}) but keep the running stage pure, or you can hook extra effects into the running stage that you don't need for parsing, or you can use an alternative loader mechanism (such as an in-memory hashmap of template names to template sources) for the parser while keeping the interpreter in plain IO.
  • More complete implementation of the Jinja2 language. Ginger implements most of the core Jinja2 syntax; I deviated only with features that don't make sense in a language like Haskell (the "blatant Pythonisms" mentioned elsewhere), or where I truly believe that making things simpler would be better (this is why filters, functions, and tests are all the same thing in Ginger - {{ foo|bar }} and {{ bar(foo) }} compile to exactly the same thing).
  • More programming features in the template language. Ginger is, in fact, a full-blown dynamic programming language; you can define your own functions, there's variables with scopes and all, there's a complete expression sublanguage (and it's used in every place you'd expect to put a variable, so you can, for example, loop over the output of a function that you call on a sublist of a context variable filtered through a function returned from another function call, if you want), you can even drop into "script mode" and write a Ginger flavor that's similar to a Python/JavaScript hybrid.

The only real problem I see with Karver is that it uses unsafePerformIO to load included templates from disk - IMO this is really really really not what you should use unsafePerformIO for.

Hope that clears things up a little.

from ginger.

GildedHonour avatar GildedHonour commented on August 27, 2024

thanks.

from ginger.

GildedHonour avatar GildedHonour commented on August 27, 2024

Is there a MVP of returning an html file to a client?

in this code, how is "index.html", assuming that's the name of an html file, supposed to be passed to it?

loadFile fn = openFile fn ReadMode >>= hGetContents

loadFileMay fn =
    tryIOError (loadFile fn) >>= \e ->
         case e of
            Right contents ->
                return (Just contents)
            Left err -> do
                print err -- remove this line if you want to fail silently
                return Nothing

from ginger.

GildedHonour avatar GildedHonour commented on August 27, 2024

that's not a library, but a pain. part of code here, part there, setup this, adjust that. how to run it after all? in the documentation -- nothing.

in https://github.com/sourrust/karver everything is comprehensible.

from ginger.

tdammers avatar tdammers commented on August 27, 2024

Also, this has long gone beyond the scope of "how am I supposed to pass these variables -- title, naviagation, body -- to this template?", so I'm closing this.

from ginger.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.