Eleventy: Pass arguments from `.njk` to `_data` file with async functions

Created on 1 Apr 2019  路  11Comments  路  Source: 11ty/eleventy

I am not sure if this is similar to #335 . I would like in the data file to take the npm package name from the markdown and use it to get data from npm:

_data/livestats.js

module.exports = {
  packageDownloads: async( packageName ) => await getDownloads( packageName ),
}
---
layout: page--project
pagetitle: A11yColor
npm: a11ycolor
github: alex-page/a11ycolor
---

page-project.njk

{%if npm %}
  <li>{{ livestats.packageDownloads( npm ) }}</li>
  <li>
    <a href="https://npmjs.org/package/{{npm}}"><code>npm i {{npm}}</code></a>
  </li>
{% endif %}

This currently returns [object Promise] but it would be awesome to await and return the result.

The problem I am trying to get around is iterating through markdown to find frontmatter that contains npm. It would be great if I could pass the npm string to a function to fetch information.

template language waiting-to-close

Most helpful comment

All 11 comments

I believe to get async behavior in Nunjucks (in this way) you want an async filter: https://www.11ty.io/docs/languages/nunjucks/#asynchronous-nunjucks-filters

I will give it a go! Thanks @zachleat 馃挴

For anyone who comes across this issue in the future, this is how I solved it:
.eleventy.js

/**
 * Get the npm package downloads
 */
eleventyConfig.addNunjucksAsyncFilter( "packageDownloads", async( packageName, callback ) => {
    try {
        const url = `https://api.npmjs.org/downloads/point/last-week/${ packageName }`;
        const { body } = await Got( url );
        const downloads = JSON.parse( body ).downloads;
        callback( null, downloads );
    }
    catch( error ){
        callback( error );
    }
});

page.njk

<p>{{ npm | packageDownloads }} downloads this week</p>

Why did you use Got? (I mean, axios is quite popular). Others brought fetch to node.js.

I just like the API for got if I am being honest. There are a bunch of solutions for fetch so feel free to swap it out for whatever suits.

Would be awesome if that would become a filter for eleventy published on npm.

Would you like to create one?
Or can I copy your approach (and refer to the comment in this thread to credit you)?

@Ryuno-Ki go for it, happy to review the code when you are done!

@Ryuno-Ki nice work and you made it so quickly.

I think it would be useful to decouple it though. So you can fetch a URL and return the data. The user can then change it up if they wanted to fetch GitHub stars or from another API. What do you think?

The input would be something like URL and options the output would be the body of the request?

Please fill a ticket in that GitHub repo of mine :-)

For anyone wanders here... If you use a nunjucks asyncfilter inside a template and include that template inside a if condition like the following,

{% if condition %}
  {% include "partial.njk" %} // your asyncfilter is inside partial.njk
{% endif %}

it won't render at all. You can use ifAsync instead of if to solve the issue. I found the info in this issue https://github.com/mozilla/nunjucks/issues/838#issue-175972669. However this is not in Nunjucks official documentation

Was this page helpful?
0 / 5 - 0 ratings

Related issues

jamrelian picture jamrelian  路  3Comments

michrome picture michrome  路  3Comments

zac-heisey picture zac-heisey  路  3Comments

veleek picture veleek  路  3Comments

kaloja picture kaloja  路  3Comments