question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Hi

I’ve faced one little issue with macros imports.

I hope someone will suggest some good workaround, otherwise that post can be considered as proposal.

In my projects I’m using a lot of macros. I’ve kept all macros in single _macros.nj file and imported it into main layout (which extended by all other layouts) like

{# Calling macros globally #}
{% import "_macros.nj" as macro %}
{# --------- #}

It was quite handy, since it allowed me to access any macros on any layout simply with

{{ macro.myMacro }}

So, it worked quite well until project grew really big and I’ve ended up with tons of macros in single plain file.

In my situation it would be wise to split macros into some kind of partials.

For example, like this:

├── nunjucks
│   ├── macros
│   │   ├── _entry.nj
│   │   ├── _product.nj
│   │   ├── _slider.nj
│   │   └── ...
|   ├── _layout.nj
|   └── index.nj
└── ...

Looks good so far, I though, but then I realized that in fact there is no fashionable way to import all those macros at once as macro object.

This means that I have very few options:

1) Import each macros with separate import

{% import "_entry.nj" as macroEntry %}
{% import "_product.nj" as macroProduct %}
{% import "_slider.nj" as macroSlider %}

But, well, it simply doesn’t look right and spawns tons of new objects

2) Import macros at pages where I need them

In fact, it’s working solution, but it forces you to spend time on calling of macros at each page. Besides, in case you delete macro, you need to find it on each page and delete — not fun too, especially considering that we have global macros here

3) Go “CSS\Sass way”

In other word, collect all macros in some indexing file:

├── macros
│   ├── _entry.nj
│   ├── _product.nj
│   ├── _slider.nj
│   └──  ...
├── _macros.nj ← here is our guy
├── ...

_macros.nj will looks like

{% include "macros/_entry.nj" %}
{% include "macros/_product.nj" %}
{% include "macros/_slider.nj" %}
...

Then we can import our main macros file in main layout like

{# Calling macros globally #}
{% import "_macros.nj" as macro %}
{# --------- #}

And then magic should happen. But, unfortunately, it won’t, since importing of file which include macros will output nothing.

4) Use wildcards globbing

Just import all macros like

{# Calling macros globally #}
{% import "macros/*.nj" as macro %}
{# --------- #}

And it should pick up all .nj files with macros from specified path and import them as macro object`.

It won’t work too, of course, since it’s impossible to use globbing in imports right now.

Now, the question, is it in general bad idea\practice\way to handle macros in such way, or no? Or maybe I’m missing some obvious better solution?

Thanks in advance

Issue Analytics

  • State:closed
  • Created 9 years ago
  • Comments:7 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
ArmorDarkscommented, Aug 30, 2016

Once again necromancing, but this solution might help someone.

After all those years, all efforts, we could never embrace Jinja’s idea of import with mandatory as. It became even worse, when we switched to component-only way of UI building. So, since everything was a component, it was so inconvenient to import everything into new abstract “macros” holders. We wanted single namespace.

Fortunately, with help of custom filter or global, you can merge all macros into single variable.

In our case we used lodash. And, well, yes, it also loads all macros in one go into single variable. This is only because Kotsu is a static website generator, so we can afford it. I wouldn’t recommend such greedy loading in browser environment. Probably.

Anyway, here is a snippet. Adopt it to your needs:

{# Global macros #}
{% set components = {} %}
{% for component in expand('/', '_components/{,**/}_*.nj', 'isFile', path.source.templates) %}
  {% import component as temp with context %}{% set macro = _.assign(components, temp) %}
{% endfor %}

Here are example components, here is how loader declared, and here is how you could use those components/macros.

0reactions
ArmorDarkscommented, Oct 1, 2018

Necromancing once again. Just was passing by, but this might save time for some folks.

A much easier solution would be to use an import, which allows to import specific macro without storing it into an object:

{% from 'components/OutdatedBrowser.nj' import OutdatedBrowser with context %}
{% from 'components/Test.nj' import Test with context %}

{# Now just use macro like so #}
{{ OutdatedBrowser() }}
{{ Test() }}

I’m not sure that those named imports are even mentioned in Nunjucks docs. Compare it with the older way, which forces to create not always useful objects:

{% import 'components/OutdatedBrowser.nj' as macros1 with context %}
{% import 'components/Test.nj' as macros2 with context %}

{{ macros1.OutdatedBrowser() }}
{{ macros2.Test() }}
Read more comments on GitHub >

github_iconTop Results From Across the Web

Macro Food List for Meal Prep | The Body Bulletin
This macro food list will help you understand which foods fall into which category of macronutrient. Download the free grocery list.
Read more >
Food Lists: Quick Reference Guides - Avatar Nutrition
Check out our quick reference lists for protein, carbs and fat!
Read more >
A Macro Food List To Craft Your Perfect Diet - BetterMe
Confused with balancing the macronutrients? A macro food list will help you tell carbs, fat, and protein apart and craft a more healthful...
Read more >
Macro Food List | Noahs Nutrition
Macro food list: Protein that has fats · Nuts and seeds · Fish · Dairy · Beef · Pork & Poultry.
Read more >
Macro Meal Planner: How to Portion Foods to Fit Your Macros
Learn exactly how to portion control your food choices according to your macro diet with these macro food lists and meal planning tools....
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found