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

Allow shortcodes to return promises #429

Closed
LandonSchropp opened this issue Feb 24, 2019 · 14 comments
Closed

Allow shortcodes to return promises #429

LandonSchropp opened this issue Feb 24, 2019 · 14 comments
Assignees
Labels
enhancement: favorite Vanity label! The maintainer likes this enhancement request a lot. enhancement high-priority
Milestone

Comments

@LandonSchropp
Copy link

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 LandonSchropp changed the title Allow shortcodes to return promises. Allow shortcodes to return promises Feb 24, 2019
@LandonSchropp
Copy link
Author

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
Copy link
Member

zachleat commented Mar 8, 2019

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 zachleat added needs-votes A feature request on the backlog that needs upvotes or downvotes. Remove this label when resolved. enhancement: favorite Vanity label! The maintainer likes this enhancement request a lot. labels Mar 8, 2019
@zachleat
Copy link
Member

zachleat commented Mar 8, 2019

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 👍!

@zachleat zachleat closed this as completed Mar 8, 2019
@LandonSchropp
Copy link
Author

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
Copy link
Contributor

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
Copy link
Contributor

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
Copy link
Contributor

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
Copy link
Author

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

@zachleat zachleat added this to the Next Minor Version milestone Aug 30, 2019
@zachleat zachleat self-assigned this Aug 30, 2019
zachleat added a commit that referenced this issue Aug 30, 2019
@zachleat zachleat removed the needs-votes A feature request on the backlog that needs upvotes or downvotes. Remove this label when resolved. label Aug 30, 2019
@zachleat
Copy link
Member

zachleat commented Aug 30, 2019

@zachleat
Copy link
Member

@LandonSchropp
Copy link
Author

This is awesome! Thank you!

zachleat added a commit that referenced this issue Sep 5, 2019
…utputs readable errors (especially when they are async). Related to #429. Fixes #681
@KyleMit
Copy link

KyleMit commented Dec 28, 2019

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
Copy link
Member

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

zachleat added a commit to 11ty/11ty-website that referenced this issue Dec 28, 2019
@zachleat
Copy link
Member

zachleat commented Jan 3, 2023

This was extended further in this upcoming 2.0 feature #2726

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement: favorite Vanity label! The maintainer likes this enhancement request a lot. enhancement high-priority
Projects
None yet
Development

No branches or pull requests

4 participants