5 people like it.

DotLiquid integration with Suave

Example of integrating DotLiquid with a simple Suave server. The snippet automatically registers all public members of a record as members that can be accessed by DotLiquid templates.

DotLiquid template integration for Suave

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
let parseTemplate<'T> template =
  let rec registerTypeTree ty =
    if FSharpType.IsRecord ty then
      let fields = FSharpType.GetRecordFields(ty)
      Template.RegisterSafeType(ty, [| for f in fields -> f.Name |])
      for f in fields do registerTypeTree f.PropertyType
    elif ty.IsGenericType &&
        ( let t = ty.GetGenericTypeDefinition()
          in t = typedefof<seq<_>> || t = typedefof<list<_>> ) then
      () //registerTypeTree (ty.GetGenericArguments().[0])
      registerTypeTree (ty.GetGenericArguments().[0])
    else () (* printfn "%s" ty.FullName *)

  registerTypeTree typeof<'T>
  let t = Template.Parse(template)
  fun k (v:'T) -> t.Render(Hash.FromDictionary(dict [k, box v]))

Simple demo

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
type Task =
  { What : string }
type Person =
  { Name : string
    Tasks : seq<Task> }

let t = parseTemplate<Person> """<p>{{ user.Name }} has to do:</p>
  <ul>
    {% for item in user.Tasks -%}
      <li>{{ item.What }}</li>
    {% endfor -%}
  </ul>
"""

let app = OK (t "user" {Name="Tomas"; Tasks = [ {What="sleep"}; {What="eat"} ]})
val parseTemplate : template:string -> (string -> 'T -> string)

Full name: Script.parseTemplate
val template : string
val registerTypeTree : (Type -> unit)
val ty : Type
type FSharpType =
  static member GetExceptionFields : exceptionType:Type * ?bindingFlags:BindingFlags -> PropertyInfo []
  static member GetFunctionElements : functionType:Type -> Type * Type
  static member GetRecordFields : recordType:Type * ?bindingFlags:BindingFlags -> PropertyInfo []
  static member GetTupleElements : tupleType:Type -> Type []
  static member GetUnionCases : unionType:Type * ?bindingFlags:BindingFlags -> UnionCaseInfo []
  static member IsExceptionRepresentation : exceptionType:Type * ?bindingFlags:BindingFlags -> bool
  static member IsFunction : typ:Type -> bool
  static member IsModule : typ:Type -> bool
  static member IsRecord : typ:Type * ?bindingFlags:BindingFlags -> bool
  static member IsTuple : typ:Type -> bool
  ...

Full name: Microsoft.FSharp.Reflection.FSharpType
static member FSharpType.IsRecord : typ:Type * ?allowAccessToPrivateRepresentation:bool -> bool
static member FSharpType.IsRecord : typ:Type * ?bindingFlags:Reflection.BindingFlags -> bool
val fields : Reflection.PropertyInfo []
static member FSharpType.GetRecordFields : recordType:Type * ?allowAccessToPrivateRepresentation:bool -> Reflection.PropertyInfo []
static member FSharpType.GetRecordFields : recordType:Type * ?bindingFlags:Reflection.BindingFlags -> Reflection.PropertyInfo []
type Template =
  member Assigns : Hash
  member Errors : List<Exception>
  member InstanceAssigns : Hash
  member Registers : Hash
  member Render : unit -> string + 4 overloads
  member Root : Document with get, set
  static val NamingConvention : INamingConvention
  static member FileSystem : IFileSystem with get, set
  static member GetSafeTypeTransformer : type:Type -> Func<obj, obj>
  static member GetTagType : name:string -> Type
  ...

Full name: DotLiquid.Template
Template.RegisterSafeType(type: Type, func: Func<obj,obj>) : unit
Template.RegisterSafeType(type: Type, allowedMembers: string []) : unit
Template.RegisterSafeType(type: Type, allowedMembers: string [], func: Func<obj,obj>) : unit
val f : Reflection.PropertyInfo
property Reflection.MemberInfo.Name: string
property Reflection.PropertyInfo.PropertyType: Type
property Type.IsGenericType: bool
val t : Type
Type.GetGenericTypeDefinition() : Type
val typedefof<'T> : Type

Full name: Microsoft.FSharp.Core.Operators.typedefof
Multiple items
val seq : sequence:seq<'T> -> seq<'T>

Full name: Microsoft.FSharp.Core.Operators.seq

--------------------
type seq<'T> = Collections.Generic.IEnumerable<'T>

Full name: Microsoft.FSharp.Collections.seq<_>
type 'T list = List<'T>

Full name: Microsoft.FSharp.Collections.list<_>
Type.GetGenericArguments() : Type []
val typeof<'T> : Type

Full name: Microsoft.FSharp.Core.Operators.typeof
val t : Template
Template.Parse(source: string) : Template
val k : string
val v : 'T
Template.Render() : string
Template.Render(parameters: RenderParameters) : string
Template.Render(localVariables: Hash) : string
Template.Render(stream: Stream, parameters: RenderParameters) : unit
Template.Render(result: TextWriter, parameters: RenderParameters) : unit
Multiple items
type Hash =
  new : unit -> Hash + 2 overloads
  member Add : item:KeyValuePair<string, obj> -> unit + 2 overloads
  member Clear : unit -> unit
  member Contains : key:obj -> bool + 1 overload
  member ContainsKey : key:string -> bool
  member CopyTo : array:KeyValuePair<string, obj>[] * arrayIndex:int -> unit + 1 overload
  member Count : int
  member Get<'T> : key:string -> 'T
  member GetEnumerator : unit -> IEnumerator<KeyValuePair<string, obj>>
  member IsFixedSize : bool
  ...

Full name: DotLiquid.Hash

--------------------
Hash() : unit
Hash(defaultValue: obj) : unit
Hash(lambda: Func<Hash,string,obj>) : unit
Hash.FromDictionary(dictionary: Collections.Generic.IDictionary<string,obj>) : Hash
val dict : keyValuePairs:seq<'Key * 'Value> -> Collections.Generic.IDictionary<'Key,'Value> (requires equality)

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.dict
val box : value:'T -> obj

Full name: Microsoft.FSharp.Core.Operators.box
type Task =
  {What: string;}

Full name: Script.Task
Task.What: string
Multiple items
val string : value:'T -> string

Full name: Microsoft.FSharp.Core.Operators.string

--------------------
type string = String

Full name: Microsoft.FSharp.Core.string
type Person =
  {Name: string;
   Tasks: seq<Task>;}

Full name: Script.Person
Person.Name: string
Person.Tasks: seq<Task>
val t : (string -> Person -> string)

Full name: Script.t
val app : obj

Full name: Script.app
Raw view Test code New version

More information

Link:http://fssnip.net/rd
Posted:8 years ago
Author:Tomas Petricek
Tags: dotliquid , suave , web