Eleventy: Allow shortcodes to return promises

Created on 24 Feb 2019  路  13Comments  路  Source: 11ty/eleventy

I'm writing a simple shortcode that hooks into the Embedly API. This function should return some HTML that can be rendered directly into my static template.

I was surprised that Eleventy doesn't support promises in shortcodes. It would be great if support for those could be added.

Here's what my shortcode function looks like for reference.

const Embedly = require('embedly');

module.exports = function embedlyHTML(embedURL) {
  let embedly = new Embedly({ key: process.env.EMBEDLY_KEY });

  return new Promise((resolve, reject) => {
    embedly.oembed({ url: embedURL }, (error, [ result ]) => {
      if (error) { reject(error); }
      return resolve(result);
    });
  });
}
enhancement favorite high-priority

All 13 comments

I was able to work around this by using a custom Nunjucks tag. However, it would be more convenient if shortcodes worked with promises.

function embedlyHTML(embedURL) {
  let api = new Embedly({ key: process.env.EMBEDLY_KEY });

  return new Promise((resolve, reject) => {
    api.oembed({ url: embedURL }, (error, [ result ]) => {
      if (error) { reject(error); }
      return resolve(result);
    });
  });
}

module.exports = (nunjucksEngine) => {

  return {
    tags: [ "embedly" ],

    parse(parser, nodes) {
      let token = parser.nextToken();
      let args = parser.parseSignature(null, true);

      parser.advanceAfterBlockEnd(token.value);
      return new nodes.CallExtensionAsync(this, "run", args);
    },

    run(context, embedURL, callback) {
      embedlyHTML(embedURL).then(({ html }) => {
        callback(null, new nunjucksEngine.runtime.SafeString(html));
      });
    }
  };
};

I agree that this absolutely should happen. I鈥檓 not sure if all of the Shortcode compatible template engines support asynchronous code like this, however. Nunjucks probably does, as you seem to have tested. Not sure about Liquid or Handlebars though.

This repository is now using lodash style issue management for enhancements. This means enhancement issues will now be closed instead of leaving them open.

View the enhancement backlog here. Don鈥檛 forget to upvote the top comment with 馃憤!

I just wanted to comment and add that I ran across another use case for this. I'm writing a shortcode that uses SVGO, and that library returns a promise. Here's an example from their documentation.

I was thinking about this request (supporting promises) as well.
I'd like to build a shortcode for displaying a GitHub profile card, but just finished my port over from harp.js yesterday.

Just published my first eleventy plugin today.

Oh my! Can we think about how the ideal API would look like?
Can we reduce the boilerplate code for plugin a bit?

Personally, I'd also see some kind of declarative API about what name the tag implements.

This way, eleventy could suggest which package to install once one was removed.
E.g. embedly from the package above.

It's a pain point I had with WordPress (before moving off that platform).

I'd envision this as an collection on 11ty.io at the very least.

@Ryuno-Ki I ended up implementing something somewhat similar in my project. I agree that the API is a little complex here, as well as in a few other areas. In particular, I found these difficult to work with:

  • Adding custom async tags.
  • Creating arbitrary data sources. My project pulls its content from Contentful, and I had to jump through a few hoops to get this to work. In my mind, I should be able to call the addCollection function, asynchronously feed in arbitrary data in an expected format, and have that data magically show up as "pages".
  • Generating pages via the pagination API. I understand the desire to want to combine the generation of individual pages with the pagination API, but I found the API a little confusing as currently written.
  • Templatizing front matter data. I ended up doing this in custom JavaScript instead because I couldn't find a good way to do it inside of Eleventy.
  • Calling eleventy from JavaScript. I'm using Gulp to compile my assets. As far as I could tell, there wasn't a way to call eleventy outside of the CLI, or to feed the engine specific files. I ended up having to drop an ugly hack into my Gulp task in order to get it to work.

That being said, I don't want to sound like a complainer. Eleventy is awesome, and for the most part, it was a joy to use. 馃槂

  • This already works out of the box in Liquid.
  • This works as expected in JavaScript templates (you can just use await in a async function in one of those)
  • Additional configuration is necessary for Nunjucks but will work fine when the next release ships.
  • Handlebars has no support for this feature upstream https://github.com/wycats/handlebars.js/issues/717

This is awesome! Thank you!

The doc updates point to async shortcodes being added in 0.9.1

But I can't find the v0.9.1 release on github releases or npm releases, and #429 is listed in the release notes for v0.10.0 beta

Might be helpful to update the following line in docs/languages/nunjucks.md

### Asynchronous Shortcodes {% addedin "0.9.1" %}

But maybe this is all pre-emptive and will get updated when v0.10.0 comes out of beta

Ah yep sorry @KyleMit, I鈥檒l update that to say 0.10.0.

Was this page helpful?
0 / 5 - 0 ratings