Giter Club home page Giter Club logo

Comments (16)

budparr avatar budparr commented on May 17, 2024

Hi @kylepaulsen - if you haven't already, you may want to go through this pretty carefully: http://www.robinthrift.com/posts/getting-to-know-metalsmith/

from metalsmith.

kylepaulsen avatar kylepaulsen commented on May 17, 2024

So I have been going through that tutorial and it has been helpful. However it doesn't have any examples of putting handlebars in a markdown file. Instead, it puts it in a template or partial file. I also tried downloading your source and putting in some handlebars inside one of your markdown files and it was just copied over like plain text instead of being compiled. I don't think I can put handlebars in templates or partials because I want to do something like:

My main template file:

<html>
    <head>
    ...
    </head>
    <body>
    {{{contents}}}
    </body>
</html>

Where contents would compile to something like:

<div>
    other page specific content here.
</div>
{{#each collections.posts}}
    <li>
        <h3>{{this.title}}</h3>
        <article>{{this.contents}}</article>
    </li>
{{/each}}
<div>
    some more page specific content.
</div>

And then it would be compiled again to get the final result.

I can edit the source of metalsmith-collections to have it double compile and that works great! But obviously I would prefer to not have to do that. What's the best way to do this?

Thanks a lot for your help!

from metalsmith.

unstoppablecarl avatar unstoppablecarl commented on May 17, 2024

What you are looking for is partials.Handlebars partials docs here http://handlebarsjs.com/reference.html

metalsmith-templates supports partials for handlebars and (I think) all the other supported languages but it isn 't mentioned in the docs. If you have a property in your template data (metadata, page metadata, etc) called 'partials '. It will load them automatically.

Usually you denote a file is a partial by prefixing it with _ , but it is not required.

/src/whatever.md

---
title: Whatever
date: 2012-08-20
template: page.html
topContent: this is the top content
bottomContent: this is the bottom content
---

Whatever body content

/templates/page.html

<html>
    <head>
    </head>
    <body>
    {{> _contents}}
    </body>
</html>

/templates/_content.html

<div>
    {{topContent}}
</div>

<div>
{{{contents}}}
</div>

<div>
    {{bottomContent}}
</div>

/build.js

var Metalsmith = require('metalsmith');
var markdown = require("metalsmith-markdown");
var templates = require('metalsmith-templates');

Metalsmith(__dirname)
    .clean(true)
    .metadata({
        partials: {
            _contents: '_contents',
        }
    })
    .use(markdown())
    .use(templates({engine: 'handlebars'}))
    .build();

from metalsmith.

mayo avatar mayo commented on May 17, 2024

I think what @kylepaulsen was possibly after is doing something like:

---
title: my test
hello_name: World
template: post.html
block: content
---
Hello {{hello_name}}!

I used this a lot when I used Hyde to render my site. The use case above is trivial, but it can be very useful tool with larger files or when rendering html files. The way Hyde dealt with it is rendering the file from markdown to html, and then treated the html as a template itself, and then passing it to the parent template, etc. This implied that file contents would be rendered in a template block rather than variable, which potentially limits the template languages that are available (and consequently, there was a 'default_block' metadata value for this).

Expanding following the example above, the template would be:

<html>
  <body>
    {% block content %}{% end block %}
  </body>
</html>

i.e. The md file contents no longer comes as a {{{ contents }}} variable because it itself is treated as a template, so the parent template is extended via inheritance. In the case of the source being a html file, this gives you the ability to override or append blocks in parent templates, avoiding article-specific templates. (Eg: parent template defines css block, and contents block. The source file can append it's own css, and generate some content, without extraneous template/partial with css specific to the source file).

from metalsmith.

unstoppablecarl avatar unstoppablecarl commented on May 17, 2024

@mayo That is a much more powerful technique. The only template language I have used with blocks and inheritance is smarty for php. For js i have mostly used handlebars. What other js template languages have blocks and inheritance?

from metalsmith.

mayo avatar mayo commented on May 17, 2024

@unstoppablecarl I know swig and jade do (and both are supported in consolidate.js, therefore metalsmith-templates), but there were at least two others I ran across when I was looking for templating language to use with Metalsmith.

from metalsmith.

mayo avatar mayo commented on May 17, 2024

Just out of interest I skimmed through the list of consolidate.js supported templating languages, and the following support block-style inheritance: atpl, dust, ect, Hogan, just, nunjucks, swig and potentially liquor.

from metalsmith.

mayo avatar mayo commented on May 17, 2024

@kylepaulsen I was looking at the metalsmith-templates code, and you can have access to file's own metadata via the 'inPlace' option passed to the plugin. See metalsmith-templates/test/fixtures/in-place and the should accept an inPlace option test case.

from metalsmith.

mayo avatar mayo commented on May 17, 2024

@unstoppablecarl I wrote a sample implementation in mayo/metalsmith-stencils@43a2d0d. It's a bit rough around the corners, but works. I started a discussion at segment-boneyard/metalsmith-templates#22.

from metalsmith.

majodev avatar majodev commented on May 17, 2024

Hi, I also needed this functionality while developing my website. My plugins are not published or tested yet, however, I feel like this might be useful for the exact scenario @kylepaulsen was posting in the first place so I created a gist here.

szenario:

---
title: HandlebarsCombiMarkdown
customWorld: Universe
--- 
Hallo {{customWorld}}!

compiles to

<p>Hallo Universe!</p>

from metalsmith.

mayo avatar mayo commented on May 17, 2024

Hey, @majodev, you can already do that by using inPlace: true when setting up your template plugin:

var metalsmith = Metalsmith(__dirname);
metalsmith
  .use(templates({
    "engine": "handlebars",
    "inPlace": true
  }))
  .build();

or check out the 'in-place' test case in metalsmith-templates/test/fixtures/in-place

from metalsmith.

kylepaulsen avatar kylepaulsen commented on May 17, 2024

I finally got some more time to work on this. I was able to get what I wanted using partials and templates a lot. I still wish I could just have 1 or 2 "master" templates and have 0 partials and just be able to write handlebars or jade in my content files.

Also @mayo, I tried using inPlace and it worked... except it didn't render through my template anymore. Any idea how to get around that? I started using jade to take advantage of block inheritance however I haven't had much luck.

content file: (projects is a global object in the global metalsmith metadata created from the collections plugin)

---
template: main.html
---
!= projects

main template:

doctype html
html(lang="en")
    head
        title Metalsmith Test
    body
        p something
        // this prints: != projects
        //   != contents
        // this prints nothing:
        block contents

from metalsmith.

mayo avatar mayo commented on May 17, 2024

(Edit: oops, I confused couple of people that posted comments above, so updating the answer...)

@kylepaulsen inPlace makes the metadata from front matter available in your template. I wasn't sure about your original question, but interpreted it to mean the same as majodev asked in #75 (comment).

metalsmith-templates does not expose template language specific features (like blocks), so it does not create a contents block for you. The data from original template will always only be available as a template variable (the lowest common denominator between all the templating libraries).

As for your last question with blocks, if you need the contents to be a block, check my #75 (comment) above. Although this may be handy, it's not always necessary. You can have a single (or couple of) "master" template, and have more sub-templates that live on top of it (both swig and jade support inheritance via extends). Your content page doesn't necessarily need to be rendered as block, because the template it's using can inherit the master template. There are no partials (as per the strict definition) involved here, because when you extend a template (at least in the above mentioned templating libraries) the template doing the extending can affect and change blocks in the template that's being inherited. For eg. see https://github.com/mayo/oyam.ca/tree/master/templates, base.html, grid.html, contents.html, and/or index.html - that's plain metalsmith-templates functionality without my mods.

from metalsmith.

kylepaulsen avatar kylepaulsen commented on May 17, 2024

Thanks for your example links, @mayo. It got me motivated to really dig into the code to get what I want. I ended up just modifying the template module to do what I want: segment-boneyard/metalsmith-templates#26 . I don't expect it to get merged, but if it does, it might merge conflict with your stuff (which also looks good).

from metalsmith.

mayo avatar mayo commented on May 17, 2024

@kylepaulsen No worries, although you don't need to modify metalsmith-templates to do what the test case does - see my comment on the push request. My modifications provide somewhat different functionality than yours do - mine wrap the source file in a block, so you can override template blocks within the source file.

from metalsmith.

ianstormtaylor avatar ianstormtaylor commented on May 17, 2024

Closing since it's related to metalsmith-templates and not core.

from metalsmith.

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.