我有一个脚本,可以渲染如下所示的nunjucks contact.html
模板:
let fs = require('fs');
let nj = require('nunjucks');
var contact = fs.readFileSync('./src/contact.html','utf8');
nj.configure('src');
let result = nj.render('contact.html');
console.log(result);
它可以正常工作并记录正确的result
。
我现在尝试添加一个宏,并将定义放入templates/forms.njk
文件中。然后,我尝试像这样从contacts.html
加载它:
{% import "templates/forms.njk" as forms %}
{% set title = 'Contact' %}
{% extends '_layout.html' %}
{% block content %}
<h1>Test Template</h1>
{% endblock %}
现在results
的记录为null
,但是如果我删除了宏,导入将记录呈现的联系人模板。有想法吗?
src
目录布局如下:
├── contact.html
├── index.html
├── _layout.html
└── templates
└── forms.njk
答案 0 :(得分:1)
第二个宏缺少结束语句function foo(a: string, b: string, c: number): string {
return 'Yay!'
}
// Attempt 1:
// Taken from
// https://github.com/facebook/flow/issues/4672#issuecomment-377649789
declare function arguments<A>((A) => any): [A]
declare function arguments<A, B>((A, B) => any): [A, B]
declare function arguments<A, B, C>((A, B, C) => any): [A, B, C]
declare function arguments<A, B, C, D>((A, B, C, D) => any): [A, B, C, D]
type Arguments<T> = $Call<typeof arguments, T>
function hof1 <T: Function> (t: T): (...Arguments<T>) => void {
return (...args) => undefined;
}
const augmentedFn = hof1(foo)("This", "works", 2);
// const augmentedFn2 = hof1(foo)("this", "should't", "work");
// const augmentedFn2 = hof1(foo)("Also", "check", 2, "number of args");
// Attempt 2: using array of mixed.
// This one doesn't seem to have limit to the arguments you can provide,
// but it doesn't seem to fail when extra args are passed.
// Notice that the return type is specified in the function signature
function hof2 <T: Array<mixed>>(func: (...T) => any): (...args: T) => any {
return (...args) => null;
}
hof2(foo)("2", "2", 1);
// hof2(foo)(1, "this fails correctly", 1);
hof2(foo)("2", "2", 1, "This one has extra arg, but this method can't limit them");
// If we define the generic return type in the returned function, flow breaks
function hof2broken <T: Array<mixed>>(func: (...T) => any) {
return (...args: T) => null;
}
// hof2broken(foo)("This should work", "but fails with a cryptic message", 1);
// Attempt 3, using generics to capture the tuple values.
// It requires us to declare one generic for each arg in any function
// that uses them. Notice that I have to redeclare all the A, B, C and D generic
// types just to pass them to the tuple type.
type genericTuple<A, B, C, D> = [A] | [A, B] | [A, B, C] | [A, B, C, D]
function hof3<A, B, C, D, T: genericTuple<A, B, C, D>>(func: (...T) => any): (...args: T) => any {
return (...args) => null;
}
hof3(foo)("This", "works", 2);
// hof3(foo)("this", "should't", "work");
hof3(foo)("Also", "fails", 2, "to check the argument's length");
// hof3(foo)("Also", "fails", 2, "to check the argument's length", "until it exceeds the number of possible args");
// Attempt 4
// It seems to be possible to ommit the generics by using tuples of 'any'
// This seems to have the same issues of not checking for extra unwanted args
type anyTuple = [any] | [any, any] | [any, any, any] | [any, any, any, any]
function hof4<T: anyTuple>(func: (...T) => any): (...args: T) => any {
return (...args) => null;
}
hof4(foo)("This", "works", 2);
// hof4(foo)("this", "should't", "work");
hof4(foo)("Also", "fails", 2, "to check the argument's length");
// Attempt 5:
// Trying to extract the type calculated in
// https://github.com/facebook/flow/issues/4672#issuecomment-377649789
// without getting redeclaration warnings
// This works in the 'try' console, but doesn't in the 0.80.0 version
// in Mac OS, so I can't stick with it
// I think that this working on the 'try' console is probably a bug
type ArgsFrom<T> = $Call<
(<A>((A) => any) => [A]) &
(<A, B>((A, B) => any) => [A, B]) &
(<A, B, C>((A, B, C) => any) => [A, B, C]) &
(<A, B, C, D>((A, B, C, D) => any) => [A, B, C, D]), T>
// type Arguments2<T> = $Call<argtest, T>
function hof5 <T: Function> (t: T): (...ArgsFrom<T>) => void {
return (...args) => undefined;
}
let testVar = hof5(foo);
hof5(foo)("This", "works", 2);
// hof5(foo)("this", "should't", "work");
// hof5(foo)("Correctly", "fails", 2, "when there are extra args");
// Attempt 6: I read somewhere that overloading is supported
// on interfaces, so I gave it a try. It seems to work and I will stick with it.
type Arguments3 = {
<A>((A) => any): [A],
<A, B>((A, B) => any): [A, B],
<A, B, C>((A, B, C) => any): [A, B, C],
<A, B, C, D>((A, B, C) => any): [A, B, C, D],
}
function hof6 <T: Function> (t: T): (...$Call<Arguments3, T>) => void {
return (...args) => undefined;
}
hof6(foo);
hof6((a: string, b: boolean) => null)("Also works", true);
hof6(foo)("This", "works", 2);
hof6(foo)("this", "should't", "work");
hof6(foo)("Correctly", "fails", 2, "when there are extra args");
// Yay! Works and kind of makes sense
。 Sample project here if anyone wants to play with the setup。
Note还更新了{% endmacro %}
调用以记录错误。