@@ -48,7 +48,7 @@ module EvaluatorHelpers =
4848 path.Replace( " \\ " , " \\\\ " )
4949
5050 let internal invokeFunction ( f : obj ) ( args : obj seq ) =
51- // Recusive partial evaluation of f, terminate when no args are left.
51+ // Recusive partial evaluation of f, terminate when no args are left.
5252 let rec helper ( next : obj ) ( args : obj list ) =
5353 match args with
5454 | head:: tail ->
@@ -62,7 +62,7 @@ module EvaluatorHelpers =
6262 helper res tail
6363 else None // Error case, arg exists but can't be applied
6464 | [] ->
65- Some next
65+ Some next
6666 helper f ( args |> List.ofSeq )
6767
6868 let internal compileExpression ( input : FsiValue ) =
@@ -115,9 +115,9 @@ module LoaderEvaluator =
115115 runLoader fsi loaderPath
116116 |> Result.bind ( fun ft ->
117117 let generator = compileExpression ft
118- invokeFunction generator [ box projectRoot; box siteContent]
118+ invokeFunction generator [ box projectRoot; box siteContent]
119119 |> function
120- | Some r ->
120+ | Some r ->
121121 try r :?> SiteContents |> Ok
122122 with _ -> sprintf " File loader %s incorrect return type" loaderPath |> Error
123123 | None -> sprintf " File loader %s couldn't be compiled" loaderPath |> Error)
@@ -171,12 +171,26 @@ module GeneratorEvaluator =
171171 |> Result.bind ( fun ft ->
172172 let generator = compileExpression ft
173173
174- invokeFunction generator [ box siteContent; box projectRoot; box page ]
174+ invokeFunction generator [ box siteContent; box projectRoot; box page ]
175175 |> Option.bind ( tryUnbox< string>)
176176 |> function
177177 | Some s -> Ok s
178178 | None -> sprintf " HTML generator %s couldn't be compiled" generatorPath |> Error)
179179
180+ ///`generatorPath` - absolute path to `.fsx` file containing the generator
181+ ///`projectRoot` - path to root of the site project
182+ ///`page` - path to the file that should be transformed
183+ let evaluateMultiple ( fsi : FsiEvaluationSession ) ( siteContent : SiteContents ) ( generatorPath : string ) ( projectRoot : string ) ( page : string ) =
184+ getGeneratorContent fsi generatorPath
185+ |> Result.bind ( fun ft ->
186+ let generator = compileExpression ft
187+
188+ invokeFunction generator [ box siteContent; box projectRoot; box page ]
189+ |> Option.bind ( tryUnbox<( string * string) list>)
190+ |> function
191+ | Some s -> Ok s
192+ | None -> sprintf " HTML generator %s couldn't be compiled" generatorPath |> Error)
193+
180194module ConfigEvaluator =
181195 open FSharp.Compiler .Interactive .Shell
182196 open EvaluatorHelpers
@@ -241,11 +255,15 @@ type GeneratorResult =
241255 | GeneratorSuccess of GeneratorMessage option
242256 | GeneratorFailure of GeneratorMessage
243257
258+ type GeneratorPick =
259+ | Simple of genartorPath : string * outputPath : string
260+ | Multiple of generatorPath : string * outputMapper : ( string -> string )
261+
244262let pickGenerator ( cfg : Config.Config ) ( siteContent : SiteContents ) ( projectRoot : string ) ( page : string ) =
245- let generator =
263+ let generator =
246264 match siteContent.TryGetError page with
247265 | Some _ -> None
248- | None ->
266+ | None ->
249267 cfg.Generators |> List.tryFind ( fun n ->
250268 match n.Trigger with
251269 | Once -> false //Once-trigger run globally, not for particular file
@@ -256,16 +274,21 @@ let pickGenerator (cfg: Config.Config) (siteContent : SiteContents) (projectRoo
256274 match generator with
257275 | None -> None
258276 | Some generator ->
259- let outputPath =
260- let newPage =
261- match generator.OutputFile with
262- | SameFileName -> page
263- | ChangeExtension( newExtension) -> Path.ChangeExtension( page, newExtension)
264- | NewFileName( newFileName) -> newFileName
265- | Custom( handler) -> handler page
266- Path.Combine( projectRoot, " _public" , newPage)
267277 let generatorPath = Path.Combine( projectRoot, " generators" , generator.Script)
268- Some( generatorPath, outputPath)
278+ match generator.OutputFile with
279+ | MultipleFiles mapper ->
280+ Some( Multiple ( generatorPath, mapper))
281+ | _ ->
282+ let outputPath =
283+ let newPage =
284+ match generator.OutputFile with
285+ | SameFileName -> page
286+ | ChangeExtension( newExtension) -> Path.ChangeExtension( page, newExtension)
287+ | NewFileName( newFileName) -> newFileName
288+ | Custom( handler) -> handler page
289+ | MultipleFiles(_) -> failwith " Shouldn't happen"
290+ Path.Combine( projectRoot, " _public" , newPage)
291+ Some( Simple ( generatorPath, outputPath))
269292
270293
271294///`projectRoot` - path to the root of website
@@ -275,39 +298,9 @@ let generate fsi (cfg: Config.Config) (siteContent : SiteContents) (projectRoot
275298 match pickGenerator cfg siteContent projectRoot page with
276299 | None ->
277300 GeneratorIgnored
278- | Some ( layoutPath, outputPath) ->
279-
280- let result = GeneratorEvaluator.evaluate fsi siteContent layoutPath projectRoot page
281- match result with
282- | Ok r ->
283- let dir = Path.GetDirectoryName outputPath
284- if not ( Directory.Exists dir) then Directory.CreateDirectory dir |> ignore
285- File.WriteAllText( outputPath, r)
286- let endTime = DateTime.Now
287- let ms = ( endTime - startTime) .Milliseconds
288- sprintf " [%s ] '%s ' generated in %d ms" ( endTime.ToString( " HH:mm:ss" )) outputPath ms
289- |> Some
290- |> GeneratorSuccess
291- | Error message ->
292- let endTime = DateTime.Now
293- sprintf " [%s ] '%s ' generation failed" ( endTime.ToString( " HH:mm:ss" )) outputPath
294- |> ( fun s -> message + Environment.NewLine + s)
295- |> GeneratorFailure
301+ | Some ( Simple( layoutPath, outputPath)) ->
296302
297- let runOnceGenerators fsi ( cfg : Config.Config ) ( siteContent : SiteContents ) ( projectRoot : string ) =
298- cfg.Generators
299- |> List.filter ( fun n -> match n.Trigger with | Once -> true | _ -> false )
300- |> List.filter ( fun n -> match n.OutputFile with | NewFileName _ -> true | _ -> false )
301- |> List.map ( fun generator ->
302- let startTime = DateTime.Now
303- let outputPath =
304- let newPage =
305- match generator.OutputFile with
306- | NewFileName( newFileName) -> newFileName
307- | _ -> failwith " Shouldn't happen"
308- Path.Combine( projectRoot, " _public" , newPage)
309- let generatorPath = Path.Combine( projectRoot, " generators" , generator.Script)
310- let result = GeneratorEvaluator.evaluate fsi siteContent generatorPath projectRoot " "
303+ let result = GeneratorEvaluator.evaluate fsi siteContent layoutPath projectRoot page
311304 match result with
312305 | Ok r ->
313306 let dir = Path.GetDirectoryName outputPath
@@ -323,6 +316,79 @@ let runOnceGenerators fsi (cfg: Config.Config) (siteContent : SiteContents) (pro
323316 sprintf " [%s ] '%s ' generation failed" ( endTime.ToString( " HH:mm:ss" )) outputPath
324317 |> ( fun s -> message + Environment.NewLine + s)
325318 |> GeneratorFailure
319+ | Some ( Multiple( layoutPath, mapper)) ->
320+ let result = GeneratorEvaluator.evaluateMultiple fsi siteContent layoutPath projectRoot page
321+ match result with
322+ | Ok results ->
323+ results |>
324+ List.iter ( fun ( o , r ) ->
325+ let outputPath = mapper o
326+ let outputPath = Path.Combine( projectRoot, " _public" , outputPath)
327+ let dir = Path.GetDirectoryName outputPath
328+ if not ( Directory.Exists dir) then Directory.CreateDirectory dir |> ignore
329+ File.WriteAllText( outputPath, r)
330+ )
331+ let endTime = DateTime.Now
332+ let ms = ( endTime - startTime) .Milliseconds
333+ sprintf " [%s ] multiple files generated in %d ms" ( endTime.ToString( " HH:mm:ss" )) ms
334+ |> Some
335+ |> GeneratorSuccess
336+ | Error message ->
337+ let endTime = DateTime.Now
338+ sprintf " [%s ] multiple files generation failed" ( endTime.ToString( " HH:mm:ss" ))
339+ |> ( fun s -> message + Environment.NewLine + s)
340+ |> GeneratorFailure
341+
342+ let runOnceGenerators fsi ( cfg : Config.Config ) ( siteContent : SiteContents ) ( projectRoot : string ) =
343+ cfg.Generators
344+ |> List.filter ( fun n -> match n.Trigger with | Once -> true | _ -> false )
345+ |> List.filter ( fun n -> match n.OutputFile with | NewFileName _ | MultipleFiles _ -> true | _ -> false )
346+ |> List.map ( fun generator ->
347+ let startTime = DateTime.Now
348+ let generatorPath = Path.Combine( projectRoot, " generators" , generator.Script)
349+ match generator.OutputFile with
350+ | NewFileName newFileName ->
351+
352+ let outputPath = Path.Combine( projectRoot, " _public" , newFileName)
353+ let result = GeneratorEvaluator.evaluate fsi siteContent generatorPath projectRoot " "
354+ match result with
355+ | Ok r ->
356+ let dir = Path.GetDirectoryName outputPath
357+ if not ( Directory.Exists dir) then Directory.CreateDirectory dir |> ignore
358+ File.WriteAllText( outputPath, r)
359+ let endTime = DateTime.Now
360+ let ms = ( endTime - startTime) .Milliseconds
361+ sprintf " [%s ] '%s ' generated in %d ms" ( endTime.ToString( " HH:mm:ss" )) outputPath ms
362+ |> Some
363+ |> GeneratorSuccess
364+ | Error message ->
365+ let endTime = DateTime.Now
366+ sprintf " [%s ] '%s ' generation failed" ( endTime.ToString( " HH:mm:ss" )) outputPath
367+ |> ( fun s -> message + Environment.NewLine + s)
368+ |> GeneratorFailure
369+ | MultipleFiles mapper ->
370+ let result = GeneratorEvaluator.evaluateMultiple fsi siteContent generatorPath projectRoot " "
371+ match result with
372+ | Ok results ->
373+ results |>
374+ List.iter ( fun ( o , r ) ->
375+ let outputPath = mapper o
376+ let outputPath = Path.Combine( projectRoot, " _public" , outputPath)
377+ let dir = Path.GetDirectoryName outputPath
378+ if not ( Directory.Exists dir) then Directory.CreateDirectory dir |> ignore
379+ File.WriteAllText( outputPath, r)
380+ )
381+ let endTime = DateTime.Now
382+ let ms = ( endTime - startTime) .Milliseconds
383+ sprintf " [%s ] multiple files generated in %d ms" ( endTime.ToString( " HH:mm:ss" )) ms
384+ |> Some
385+ |> GeneratorSuccess
386+ | Error message ->
387+ let endTime = DateTime.Now
388+ sprintf " [%s ] multiple files generation failed" ( endTime.ToString( " HH:mm:ss" ))
389+ |> ( fun s -> message + Environment.NewLine + s)
390+ |> GeneratorFailure
391+ | _ -> failwith " Shouldn't happen"
326392 )
327393
328394// Module to print colored message in the console
0 commit comments