1
1
//! Handlebars template processing.
2
2
3
- use crate :: format:: Formatter ;
3
+ use std:: collections:: HashMap ;
4
+ use std:: path:: Path ;
5
+
4
6
use anyhow:: Error ;
5
7
use handlebars:: {
6
- handlebars_helper, Context , Decorator , Handlebars , Helper , HelperDef , HelperResult , Output ,
7
- RenderContext , RenderError , Renderable ,
8
+ handlebars_helper, Context , Decorator , DirectorySourceOptions , Handlebars , Helper , HelperDef ,
9
+ HelperResult , Output , RenderContext , RenderError , RenderErrorReason , Renderable ,
8
10
} ;
9
- use std :: collections :: HashMap ;
10
- use std :: path :: Path ;
11
+
12
+ use crate :: format :: Formatter ;
11
13
12
14
type FormatterRef < ' a > = & ' a ( dyn Formatter + Send + Sync ) ;
13
15
@@ -22,7 +24,12 @@ pub fn expand(file: &Path, formatter: FormatterRef<'_>) -> Result<String, Error>
22
24
handlebars. register_decorator ( "set" , Box :: new ( set_decorator) ) ;
23
25
handlebars. register_template_file ( "template" , file) ?;
24
26
let includes = file. parent ( ) . unwrap ( ) . join ( "includes" ) ;
25
- handlebars. register_templates_directory ( ".md" , includes) ?;
27
+ let options = DirectorySourceOptions {
28
+ tpl_extension : ".md" . to_string ( ) ,
29
+ hidden : false ,
30
+ temporary : false ,
31
+ } ;
32
+ handlebars. register_templates_directory ( includes, options) ?;
26
33
let man_name = file
27
34
. file_stem ( )
28
35
. expect ( "expected filename" )
@@ -42,22 +49,29 @@ struct OptionsHelper<'a> {
42
49
impl HelperDef for OptionsHelper < ' _ > {
43
50
fn call < ' reg : ' rc , ' rc > (
44
51
& self ,
45
- h : & Helper < ' reg , ' rc > ,
52
+ h : & Helper < ' rc > ,
46
53
r : & ' reg Handlebars < ' reg > ,
47
54
ctx : & ' rc Context ,
48
55
rc : & mut RenderContext < ' reg , ' rc > ,
49
56
out : & mut dyn Output ,
50
57
) -> HelperResult {
51
58
if in_options ( rc) {
52
- return Err ( RenderError :: new ( "options blocks cannot be nested" ) ) ;
59
+ return Err (
60
+ RenderErrorReason :: Other ( "options blocks cannot be nested" . to_string ( ) ) . into ( ) ,
61
+ ) ;
53
62
}
54
63
// Prevent nested {{#options}}.
55
64
set_in_context ( rc, "__MDMAN_IN_OPTIONS" , serde_json:: Value :: Bool ( true ) ) ;
56
65
let s = self . formatter . render_options_start ( ) ;
57
66
out. write ( & s) ?;
58
67
let t = match h. template ( ) {
59
68
Some ( t) => t,
60
- None => return Err ( RenderError :: new ( "options block must not be empty" ) ) ,
69
+ None => {
70
+ return Err ( RenderErrorReason :: Other (
71
+ "options block must not be empty" . to_string ( ) ,
72
+ )
73
+ . into ( ) ) ;
74
+ }
61
75
} ;
62
76
let block = t. renders ( r, ctx, rc) ?;
63
77
out. write ( & block) ?;
@@ -83,20 +97,23 @@ struct OptionHelper<'a> {
83
97
impl HelperDef for OptionHelper < ' _ > {
84
98
fn call < ' reg : ' rc , ' rc > (
85
99
& self ,
86
- h : & Helper < ' reg , ' rc > ,
100
+ h : & Helper < ' rc > ,
87
101
r : & ' reg Handlebars < ' reg > ,
88
102
ctx : & ' rc Context ,
89
103
rc : & mut RenderContext < ' reg , ' rc > ,
90
104
out : & mut dyn Output ,
91
105
) -> HelperResult {
92
106
if !in_options ( rc) {
93
- return Err ( RenderError :: new ( "option must be in options block" ) ) ;
107
+ return Err (
108
+ RenderErrorReason :: Other ( "option must be in options block" . to_string ( ) ) . into ( ) ,
109
+ ) ;
94
110
}
95
111
let params = h. params ( ) ;
96
112
if params. is_empty ( ) {
97
- return Err ( RenderError :: new (
98
- "option block must have at least one param" ,
99
- ) ) ;
113
+ return Err ( RenderErrorReason :: Other (
114
+ "option block must have at least one param" . to_string ( ) ,
115
+ )
116
+ . into ( ) ) ;
100
117
}
101
118
// Convert params to strings.
102
119
let params = params
@@ -105,12 +122,19 @@ impl HelperDef for OptionHelper<'_> {
105
122
param
106
123
. value ( )
107
124
. as_str ( )
108
- . ok_or_else ( || RenderError :: new ( "option params must be strings" ) )
125
+ . ok_or_else ( || {
126
+ RenderErrorReason :: Other ( "option params must be strings" . to_string ( ) )
127
+ } )
128
+ . into ( )
109
129
} )
110
- . collect :: < Result < Vec < & str > , RenderError > > ( ) ?;
130
+ . collect :: < Result < Vec < & str > , RenderErrorReason > > ( ) ?;
111
131
let t = match h. template ( ) {
112
132
Some ( t) => t,
113
- None => return Err ( RenderError :: new ( "option block must not be empty" ) ) ,
133
+ None => {
134
+ return Err (
135
+ RenderErrorReason :: Other ( "option block must not be empty" . to_string ( ) ) . into ( ) ,
136
+ ) ;
137
+ }
114
138
} ;
115
139
// Render the block.
116
140
let block = t. renders ( r, ctx, rc) ?;
@@ -127,7 +151,7 @@ impl HelperDef for OptionHelper<'_> {
127
151
let option = self
128
152
. formatter
129
153
. render_option ( & params, & block, man_name)
130
- . map_err ( |e| RenderError :: new ( format ! ( "option render failed: {}" , e) ) ) ?;
154
+ . map_err ( |e| RenderErrorReason :: Other ( format ! ( "option render failed: {}" , e) ) ) ?;
131
155
out. write ( & option) ?;
132
156
Ok ( ( ) )
133
157
}
@@ -141,30 +165,30 @@ struct ManLinkHelper<'a> {
141
165
impl HelperDef for ManLinkHelper < ' _ > {
142
166
fn call < ' reg : ' rc , ' rc > (
143
167
& self ,
144
- h : & Helper < ' reg , ' rc > ,
168
+ h : & Helper < ' rc > ,
145
169
_r : & ' reg Handlebars < ' reg > ,
146
170
_ctx : & ' rc Context ,
147
171
_rc : & mut RenderContext < ' reg , ' rc > ,
148
172
out : & mut dyn Output ,
149
173
) -> HelperResult {
150
174
let params = h. params ( ) ;
151
175
if params. len ( ) != 2 {
152
- return Err ( RenderError :: new ( "{{man}} must have two arguments" ) ) ;
176
+ return Err (
177
+ RenderErrorReason :: Other ( "{{man}} must have two arguments" . to_string ( ) ) . into ( ) ,
178
+ ) ;
153
179
}
154
- let name = params[ 0 ]
155
- . value ( )
156
- . as_str ( )
157
- . ok_or_else ( || RenderError :: new ( "man link name must be a string" ) ) ?;
158
- let section = params[ 1 ]
159
- . value ( )
160
- . as_u64 ( )
161
- . ok_or_else ( || RenderError :: new ( "man link section must be an integer" ) ) ?;
162
- let section =
163
- u8:: try_from ( section) . map_err ( |_e| RenderError :: new ( "section number too large" ) ) ?;
180
+ let name = params[ 0 ] . value ( ) . as_str ( ) . ok_or_else ( || {
181
+ RenderErrorReason :: Other ( "man link name must be a string" . to_string ( ) )
182
+ } ) ?;
183
+ let section = params[ 1 ] . value ( ) . as_u64 ( ) . ok_or_else ( || {
184
+ RenderErrorReason :: Other ( "man link section must be an integer" . to_string ( ) )
185
+ } ) ?;
186
+ let section = u8:: try_from ( section)
187
+ . map_err ( |_e| RenderErrorReason :: Other ( "section number too large" . to_string ( ) ) ) ?;
164
188
let link = self
165
189
. formatter
166
190
. linkify_man_to_md ( name, section)
167
- . map_err ( |e| RenderError :: new ( format ! ( "failed to linkify man: {}" , e) ) ) ?;
191
+ . map_err ( |e| RenderErrorReason :: Other ( format ! ( "failed to linkify man: {}" , e) ) ) ?;
168
192
out. write ( & link) ?;
169
193
Ok ( ( ) )
170
194
}
@@ -174,7 +198,7 @@ impl HelperDef for ManLinkHelper<'_> {
174
198
///
175
199
/// This sets a variable to a value within the template context.
176
200
fn set_decorator (
177
- d : & Decorator < ' _ , ' _ > ,
201
+ d : & Decorator < ' _ > ,
178
202
_: & Handlebars < ' _ > ,
179
203
_ctx : & Context ,
180
204
rc : & mut RenderContext < ' _ , ' _ > ,
0 commit comments