-
Notifications
You must be signed in to change notification settings - Fork 3
/
Server.fs
140 lines (117 loc) · 5.34 KB
/
Server.fs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
module Felizia.Server
open System
open System.IO
open System.Threading.Tasks
open FSharp.Control.Tasks.V2
open Feliz.ViewEngine
open Giraffe
open Microsoft.AspNetCore.Http
open Felizia
open Felizia.Common
/// Render output as JSON. Only Url with Content.
let json (model: obj) : HttpHandler = fun next ctx ->
match model with
| :? Model as model ->
let currentPage = model.CurrentPage
let content = currentPage.Content |> Option.defaultValue ""
let segments = currentPage.Url
ctx.WriteJsonAsync { Url=segments; Content=content }
| _ -> failwith "Missing model"
/// Render output as HTML
let html (templates: IRouter) (theme: Theme) (model: obj) : HttpHandler = fun next ctx ->
match model with
| :? Model as model ->
let currentPage = model.CurrentPage
printfn "currentPage.Url: %A" currentPage.Url
printfn "template: %A" templates
let template =
let segments = currentPage.Url
let url =
// Remove default language from URL.
if (not << List.isEmpty) segments && List.head segments = model.Language then
segments
|> List.skip 1
else
segments
match templates.TryGetValue url with
| true, tmpl -> tmpl
| false, _ ->
//Log.Debug "Did not find template for {url}, using defaults"
if currentPage.IsPage
then theme.Single
else theme.List
ctx.WriteHtmlStringAsync (template model ignore |> Render.htmlDocument)
| _ -> ctx.WriteStringAsync "Not found"
let getLanguage (model: Model) (site: Site) (ctx: HttpContext) =
let hdr = ctx.GetRequestHeader "Accept-Language"
model.Language
(*
match model.Language, hdr with
| Some lang, _ -> lang
| None, Ok lang ->
let browserLangs = lang.Split(",") |> Seq.map (fun lang -> lang.Split(";") |> (fun xs -> xs.[0])) |> List.ofSeq
let languages = model.Sites |> List.map (fun lang -> lang.Language.Lang)
match List.tryFind (fun lang -> List.contains lang languages) browserLangs with
| Some lang -> lang
| None -> site.DefaultContentLanguage
| _ -> site.DefaultContentLanguage
*)
let renderPaged (model: Model) (paginationPath: string) (pageNumber: int) (segments: string list): HttpHandler = fun next ctx ->
let site = model.CurrentSite
let language = getLanguage model site ctx
let config = ctx.GetService<FeliziaConfig>()
let url, lang =
if language = site.DefaultContentLanguage
then segments, ""
else List.append [ language ] segments, language
task {
let fileName = "index.html"
let pathName = Path.Combine(config.HtmlPath, Path.Combine(segments |> Array.ofList), fileName)
let! html =
if File.Exists pathName
then File.ReadAllTextAsync pathName
else Task.FromResult String.Empty
let model' = model.SetLanguage language
let page = Model.GetPage url model'.CurrentSite.Home
match page with
| Some page ->
let paginator =
if page.IsPage then None
else Paginator(page.Pages, site.Paginate, site.PaginatePath, pageNumber, url) |> Some
let model'' = {
model' with
CurrentPage = { page with Content = Some html; Paginator = paginator }
CurrentUrl = url
PageNumber = pageNumber
}
return! Successful.OK model'' next ctx
| None ->
printfn "Did not find page: %A" url
return! next ctx
}
let renderPage (model: Model) (segments: string list): HttpHandler =
renderPaged model "" 1 segments
let route (model: Model) =
let sites = model.Sites
let content site lang = choose [
let model = { model with CurrentSite = site; Language = lang }
routex "(/?)" >=> renderPage model []
routef "/%s" (fun page -> renderPage model [ page ])
routef "/%s/" (fun page -> renderPage model [ page ])
routef "/%s/%i" (fun (paginationPath, pageNumber) -> renderPaged model paginationPath pageNumber [])
routef "/%s/%s" (fun (section, page) -> renderPage model [ section; page ])
routef "/%s/%s/" (fun (section, page) -> renderPage model [ section; page ])
routef "/%s/%s/%i" (fun (section, paginationPath, pageNumber) -> renderPaged model paginationPath pageNumber [ section ])
routef "/%s/%s/%s" (fun (section, subsection, page) -> renderPage model [ section; subsection; page ])
routef "/%s/%s/%s/" (fun (section, subsection, page) -> renderPage model [ section; subsection; page ])
routef "/%s/%s/%s/%i" (fun (section, subsection, paginationPath, pageNumber) -> renderPaged model paginationPath pageNumber [ section; subsection ])
]
choose [
// Add site for each specific language, i.e '/nb', '/en'
for site in sites do
let basePath = Uri site.BaseUrl
subRoute (basePath.AbsolutePath +/ site.Language.BaseUrl) (content site (site.Language.Lang))
// Add site for default language , i.e ''
let defaultSite = sites |> List.find (fun site -> site.Language.Lang = site.DefaultContentLanguage)
content defaultSite defaultSite.DefaultContentLanguage
]