-
Notifications
You must be signed in to change notification settings - Fork 14
/
postloader.fsx
executable file
·117 lines (96 loc) · 3.68 KB
/
postloader.fsx
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
#r "../_lib/Fornax.Core.dll"
#r "../_lib/Markdig.dll"
open Markdig
type PostConfig = {
disableLiveRefresh: bool
}
type Post = {
file: string
link : string
title: string
author: string option
published: System.DateTime option
tags: string list
content: string
summary: string
}
let contentDir = "posts"
let markdownPipeline =
MarkdownPipelineBuilder()
.UsePipeTables()
.UseGridTables()
.Build()
let isSeparator (input : string) =
input.StartsWith "---"
let isSummarySeparator (input: string) =
input.Contains "<!--more-->"
///`fileContent` - content of page to parse. Usually whole content of `.md` file
///returns content of config that should be used for the page
let getConfig (fileContent : string) =
let fileContent = fileContent.Split '\n'
let fileContent = fileContent |> Array.skip 1 //First line must be ---
let indexOfSeperator = fileContent |> Array.findIndex isSeparator
let splitKey (line: string) =
let seperatorIndex = line.IndexOf(':')
if seperatorIndex > 0 then
let key = line.[.. seperatorIndex - 1].Trim().ToLower()
let value = line.[seperatorIndex + 1 ..].Trim()
Some(key, value)
else
None
fileContent
|> Array.splitAt indexOfSeperator
|> fst
|> Seq.choose splitKey
|> Map.ofSeq
///`fileContent` - content of page to parse. Usually whole content of `.md` file
///returns HTML version of content of the page
let getContent (fileContent : string) =
let fileContent = fileContent.Split '\n'
let fileContent = fileContent |> Array.skip 1 //First line must be ---
let indexOfSeperator = fileContent |> Array.findIndex isSeparator
let _, content = fileContent |> Array.splitAt indexOfSeperator
let summary, content =
match content |> Array.tryFindIndex isSummarySeparator with
| Some indexOfSummary ->
let summary, _ = content |> Array.splitAt indexOfSummary
summary, content
| None ->
content, content
let summary = summary |> Array.skip 1 |> String.concat "\n"
let content = content |> Array.skip 1 |> String.concat "\n"
Markdown.ToHtml(summary, markdownPipeline),
Markdown.ToHtml(content, markdownPipeline)
let trimString (str : string) =
str.Trim().TrimEnd('"').TrimStart('"')
let loadFile n =
let text = System.IO.File.ReadAllText n
let config = getConfig text
let summary, content = getContent text
let file = System.IO.Path.Combine(contentDir, (n |> System.IO.Path.GetFileNameWithoutExtension) + ".md").Replace("\\", "/")
let link = "/" + System.IO.Path.Combine(contentDir, (n |> System.IO.Path.GetFileNameWithoutExtension) + ".html").Replace("\\", "/")
let title = config |> Map.find "title" |> trimString
let author = config |> Map.tryFind "author" |> Option.map trimString
let published = config |> Map.tryFind "published" |> Option.map (trimString >> System.DateTime.Parse)
let tags =
let tagsOpt =
config
|> Map.tryFind "tags"
|> Option.map (trimString >> fun n -> n.Split ',' |> Array.toList)
defaultArg tagsOpt []
{ file = file
link = link
title = title
author = author
published = published
tags = tags
content = content
summary = summary }
let loader (projectRoot: string) (siteContent: SiteContents) =
let postsPath = System.IO.Path.Combine(projectRoot, contentDir)
System.IO.Directory.GetFiles postsPath
|> Array.filter (fun n -> n.EndsWith ".md")
|> Array.map loadFile
|> Array.iter (fun p -> siteContent.Add p)
siteContent.Add({disableLiveRefresh = false})
siteContent