Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pass arguments from .njk to _data file with async functions #471

Closed
alex-page opened this issue Apr 1, 2019 · 11 comments
Closed

Pass arguments from .njk to _data file with async functions #471

alex-page opened this issue Apr 1, 2019 · 11 comments
Labels
education: template language Learning about a template language. waiting-to-close Issue that is probably resolved, waiting on OP confirmation.

Comments

@alex-page
Copy link

alex-page commented Apr 1, 2019

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.

@zachleat
Copy link
Member

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

@zachleat zachleat added education: template language Learning about a template language. waiting-to-close Issue that is probably resolved, waiting on OP confirmation. labels Apr 14, 2019
@alex-page
Copy link
Author

I will give it a go! Thanks @zachleat 💯

@alex-page
Copy link
Author

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>

@Ryuno-Ki
Copy link
Contributor

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

@alex-page
Copy link
Author

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.

@Ryuno-Ki
Copy link
Contributor

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)?

@alex-page
Copy link
Author

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

@Ryuno-Ki
Copy link
Contributor

@alex-page https://github.com/Ryuno-Ki/eleventy-filter-npm-package-downloads - also on npm.

@alex-page
Copy link
Author

@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?

@Ryuno-Ki
Copy link
Contributor

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

@anyuzx
Copy link

anyuzx commented Aug 23, 2019

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 mozilla/nunjucks#838 (comment). However this is not in Nunjucks official documentation

This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
education: template language Learning about a template language. waiting-to-close Issue that is probably resolved, waiting on OP confirmation.
Projects
None yet
Development

No branches or pull requests

4 participants