@@ -540,3 +540,108 @@ fn test_filter_with_path() {
540540
541541 assert_eq ! ( ImplicitPath { value: "42" } . render( ) . unwrap( ) , "-42" ) ;
542542}
543+
544+ #[ test]
545+ fn test_custom_filter_constructs ( ) {
546+ pub ( crate ) mod filters {
547+ use std:: fmt:: Display ;
548+
549+ #[ askama:: filter_fn]
550+ pub fn noargs < T : Display > ( value : T , _env : & dyn askama:: Values ) -> askama:: Result < String > {
551+ Ok ( format ! ( r#""{value}" | noargs()"# ) )
552+ }
553+
554+ #[ askama:: filter_fn]
555+ pub fn req1 < T : Display , F : Display > (
556+ value : T ,
557+ _env : & dyn askama:: Values ,
558+ req0 : F ,
559+ ) -> askama:: Result < String > {
560+ Ok ( format ! ( r#""{value}" | req1({req0})"# ) )
561+ }
562+
563+ #[ askama:: filter_fn]
564+ pub fn opt1 < T : Display > (
565+ value : T ,
566+ _env : & dyn askama:: Values ,
567+ #[ optional( "default" ) ] opt0 : & str ,
568+ ) -> askama:: Result < String > {
569+ Ok ( format ! ( r#""{value}" | opt1({opt0})"# ) )
570+ }
571+
572+ #[ askama:: filter_fn]
573+ pub fn req1_opt1 < T : Display , F : Display > (
574+ value : T ,
575+ _env : & dyn askama:: Values ,
576+ req0 : F ,
577+ #[ optional( "default" ) ] opt0 : & str ,
578+ ) -> askama:: Result < String > {
579+ Ok ( format ! ( r#""{value}" | req1_opt1({req0}, {opt0})"# ) )
580+ }
581+
582+ #[ askama:: filter_fn]
583+ pub fn shared_generic < T : Display > (
584+ value : T ,
585+ _env : & dyn askama:: Values ,
586+ req0 : T ,
587+ ) -> askama:: Result < String > {
588+ Ok ( format ! ( r#""{value}" | shared_generic({req0})"# ) )
589+ }
590+
591+ #[ askama:: filter_fn]
592+ pub fn impl_trait_input (
593+ value : impl Display ,
594+ _env : & dyn askama:: Values ,
595+ ) -> askama:: Result < String > {
596+ Ok ( format ! ( r#""{value}" | impl_trait_input"# ) )
597+ }
598+ }
599+
600+ #[ derive( Template ) ]
601+ #[ template(
602+ source = r#"
603+ {{- test() | noargs | safe }}
604+
605+ {{ test() | req1("lol") | safe }}
606+
607+ {{ test() | opt1 | safe }}
608+ {{ test() | opt1("nodefault") | safe }}
609+ {{ test() | opt1(opt0 = "nodefault") | safe }}
610+
611+ {{ test() | req1_opt1("req") | safe }}
612+ {{ test() | req1_opt1("req", "supplied") | safe }}
613+ {{ test() | req1_opt1("req", opt0 = "supplied") | safe }}
614+
615+ {{ test() | shared_generic("blub") | safe }}
616+ {{ test() | impl_trait_input | safe -}}
617+ "# ,
618+ ext = "html"
619+ ) ]
620+ struct CustomFilterConstructs { }
621+ impl CustomFilterConstructs {
622+ pub fn test ( & self ) -> & ' static str {
623+ "this is a test"
624+ }
625+ }
626+
627+ let should = r#"
628+ "this is a test" | noargs()
629+
630+ "this is a test" | req1(lol)
631+
632+ "this is a test" | opt1(default)
633+ "this is a test" | opt1(nodefault)
634+ "this is a test" | opt1(nodefault)
635+
636+ "this is a test" | req1_opt1(req, default)
637+ "this is a test" | req1_opt1(req, supplied)
638+ "this is a test" | req1_opt1(req, supplied)
639+
640+ "this is a test" | shared_generic(blub)
641+ "this is a test" | impl_trait_input
642+ "#
643+ . trim ( ) ;
644+
645+ let actual = CustomFilterConstructs { } . render ( ) . unwrap ( ) ;
646+ assert_eq ! ( actual, should) ;
647+ }
0 commit comments