11ty / eleventy

A simpler site generator. Transforms a directory of templates (of varying types) into HTML.
https://www.11ty.dev/
MIT License
17.19k stars 494 forks source link

Allow shortcodes to return promises #429

Closed LandonSchropp closed 5 years ago

LandonSchropp commented 5 years ago

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);
    });
  });
}
LandonSchropp commented 5 years ago

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));
      });
    }
  };
};
zachleat commented 5 years ago

I agree that this absolutely should happen. I’m 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.

zachleat commented 5 years ago

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’t forget to upvote the top comment with 👍!

LandonSchropp commented 5 years ago

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.

Ryuno-Ki commented 5 years ago

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.

Ryuno-Ki commented 5 years ago

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?

Ryuno-Ki commented 5 years ago

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.

LandonSchropp commented 5 years ago

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

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. 😃

zachleat commented 5 years ago
zachleat commented 5 years ago

Docs added/modified at: https://www.11ty.io/docs/shortcodes/ https://www.11ty.io/docs/languages/javascript/ https://www.11ty.io/docs/languages/liquid/ https://www.11ty.io/docs/languages/nunjucks/ https://www.11ty.io/docs/languages/handlebars/

LandonSchropp commented 5 years ago

This is awesome! Thank you!

KyleMit commented 4 years ago

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

zachleat commented 4 years ago

Ah yep sorry @KyleMit, I’ll update that to say 0.10.0.

zachleat commented 1 year ago

This was extended further in this upcoming 2.0 feature https://github.com/11ty/eleventy/issues/2726