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

Feature request: Add a merge filter similar to Twig #1455

Open
querkmachine opened this issue Dec 7, 2023 · 1 comment
Open

Feature request: Add a merge filter similar to Twig #1455

querkmachine opened this issue Dec 7, 2023 · 1 comment

Comments

@querkmachine
Copy link

querkmachine commented Dec 7, 2023

One of Nunjucks' stated goals is to maintain feature parity with Jinja and Twig, where there isn't conflicts or language-specific features.

Twig has a merge filter that can be used to combine either multiple arrays into a single array, or multiple objects into a single object.

Having this sort of functionality in Nunjucks would be incredibly useful, particularly when working with Nunjucks macros. It's incredibly common for us to want to combine multiple objects together.

For example, we use macros as components. Rather than having lots of default values scattered around the macro that are each selectively overridden by the macro's parameters, we could have a default configuration object set at the top of a macro, and merge a user's configuration object with that, producing a single unified configuration.

To contrive an example, instead of something like this, where the default values are interdependent but scattered around different parts of the macro (or otherwise become a long list of set tags):

{% macro myComponent(params) %}
  {% set foodPlural = params.food.plural | default("cookies") %}

  I once ate {{ params.quantity | default(5) }} {%- if params.adjective %} {{ params.adjective }}{% endif %} {{ (params.food.singular | default("cookie")) if params.quantity == 1 else foodPlural }}.
  I love {{ foodPlural }}!
{% endmacro %}

We could have everything defined in a single object at the top, leaving the body to only have the actual rendering logic.

{% macro myComponent(params) %}
  {% set v = { quantity: 5, food: { singular: "cookie", plural: "cookies" } } | merge(params) %}

  I once ate {{ v.quantity }} {%- if v.adjective %} {{ v.adjective }}{% endif %} {{ v.food.singular if v.quantity == 1 else v.food.plural }}.
  I love {{ v.food.plural }}!
{% endmacro %}

This is only one possible use case and one I encounter basically every day, but there are probably many other uses for merging arrays and objects in this manner.

In the past I've implemented a custom merge filter, but that isn't always practical, especially in cases where these macros are shared across projects and we cannot guarantee that they all share the same Nunjucks configuration or that the custom filters all work in the same underlying way.

Basically I think this'd be a great addition to the templating language (which isn't short of filters that manipulate arrays and objects) and helps meet Nunjucks' goal of parity with other, similar templating languages.

@edwardhorsford
Copy link

edwardhorsford commented Jan 22, 2024

This would be very useful indeed - I end up merging objects all the time.

A related or alternative feature would be to support the javascript spread (...) operator within objects.

You could then do:

{% set defaultOptions = {
  quantity: 5,
  price: "£4.5"
} %}

{% set options = {...defaultOptions, params} %}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants