ykmnkmi / jinja.dart

Jinja2 template engine port for Dart.
https://pub.dev/packages/jinja
MIT License
52 stars 11 forks source link

Unable to call macro when included instead of imported: Closure call with mismatched arguments #31

Open Craftplacer opened 1 month ago

Craftplacer commented 1 month ago

I don't know if this is a supported way of using macros, but I thought I should report it here. As a side note: In templates where blocks are used, import statements don't work when not put inside block statements (if the template extends another), leading to me trying this cursed method.

Package version: 0.6.1-dev.5

Error

NoSuchMethodError: Closure call with mismatched arguments: function 'StringSinkRenderer.getMacroFunction.macro'
Receiver: Closure: (List<Object?>, Map<Object?, Object?>) => String
Tried calling: StringSinkRenderer.getMacroFunction.macro(_Map len:18)
Found: StringSinkRenderer.getMacroFunction.macro(List<Object?>, Map<Object?, Object?>) => String
dart:core                                          Function.apply
package:jinja/src/environment.dart 297:21          Environment.callCommon
package:jinja/src/runtime.dart 40:24               Context.call
package:jinja/src/renderer.dart 207:20             StringSinkRenderer.visitCall
package:jinja/src/nodes/expressions.dart 375:20    Call.accept
package:jinja/src/renderer.dart 627:28             StringSinkRenderer.visitInterpolation
package:jinja/src/nodes.dart 76:20                 Interpolation.accept
package:jinja/src/renderer.dart 641:12             StringSinkRenderer.visitOutput
package:jinja/src/nodes.dart 109:20                Output.accept
package:jinja/src/renderer.dart 510:19             StringSinkRenderer.visitFor.render
package:jinja/src/renderer.dart 517:5              StringSinkRenderer.visitFor
[...]

component.jinja

{% macro component(data) %}
{{data}}
{% endmacro %}

page.jinja

{% include 'component.jinja' %}

{{ component("hey") }}
ykmnkmi commented 1 month ago

Can you provide an example with blocks? Use import.

Craftplacer commented 1 month ago

base.jinja

<html>
<body>
    {% block content %}{% endblock %}
</body>
</html>

page.jinja

{% extends "base.jinja" %}

{% import 'component.jinja' as components %}

{% block content %}
{{ components.component("hey") }}
{% endblock %}

component.jinja

{% macro component(data) %}
{{data}}
{% endmacro %}
Craftplacer commented 1 month ago

Macro imports in general seem very flaky or not as robust as the examples in the Jinja documentation may lead to believe. For example, importing 2 files under components at the same time would also cause an error:


{% import "components/a.jinja" as components %}
{% import "components/b.jinja" as components %}

{{ components.a() }}
{{ components.b() }}

and


{% from "components/a.jinja" import components as a %}
{% from "components/b.jinja" import components as b %}

{{ a() }}
{{ b() }}
NoSuchMethodError: The getter 'call' was called on null.
Receiver: null
Tried calling: call
dart:core                                          Object.noSuchMethod
package:jinja/src/runtime.dart 37:25               Context.call
package:jinja/src/renderer.dart 207:20             StringSinkRenderer.visitCall
package:jinja/src/nodes/expressions.dart 375:20    Call.accept
package:jinja/src/renderer.dart 627:28             StringSinkRenderer.visitInterpolation
package:jinja/src/nodes.dart 76:20                 Interpolation.accept
package:jinja/src/renderer.dart 641:12             StringSinkRenderer.visitOutput
package:jinja/src/nodes.dart 109:20                Output.accept
package:jinja/src/renderer.dart 510:19             StringSinkRenderer.visitFor.render
package:jinja/src/renderer.dart 517:5              StringSinkRenderer.visitFor
package:jinja/src/nodes/statements.dart 55:20      For.accept
package:jinja/src/renderer.dart 566:17             StringSinkRenderer.visitIf
package:jinja/src/nodes/statements.dart 143:20     If.accept
package:jinja/src/renderer.dart 641:12             StringSinkRenderer.visitOutput
package:jinja/src/nodes.dart 109:20                Output.accept
package:jinja/src/renderer.dart 181:17             StringSinkRenderer.getMacroFunction.macro
dart:core                                          Function.apply
package:jinja/src/environment.dart 297:21          Environment.callCommon
package:jinja/src/runtime.dart 40:24               Context.call
package:jinja/src/renderer.dart 207:20             StringSinkRenderer.visitCall
package:jinja/src/nodes/expressions.dart 375:20    Call.accept
package:jinja/src/renderer.dart 627:28             StringSinkRenderer.visitInterpolation
package:jinja/src/nodes.dart 76:20                 Interpolation.accept
package:jinja/src/renderer.dart 641:12             StringSinkRenderer.visitOutput
package:jinja/src/nodes.dart 109:20                Output.accept
package:jinja/src/renderer.dart 181:17             StringSinkRenderer.getMacroFunction.macro
ykmnkmi commented 1 month ago

The page.jinja template is correct and expected to work. It's a bug, working on it.

{% extends "base.jinja" %}

{% import 'component.jinja' as components %}

{% block content %}
{{ components.component("hey") }}
{% endblock %}