1
+ #[ TODO:
2
+ - Style inheritance
3
+ - Plop in a stylesheet if none is present
4
+ - Clean up the code a little, I guess
5
+ ]#
1
6
import
2
7
json,
3
8
macros,
30
35
style: string
31
36
config: JsonNode
32
37
hasIndex: DirTreeNode
38
+ hasCSS: DirTreeNode
39
+ hasHTML: DirTreeNode
33
40
of itemFile:
34
41
fileKind: FileKind
35
42
36
43
37
44
proc getConfig (node: DirTreeNode , key: string ): JsonNode {.inline .}
45
+ proc genLinks (node: DirTreeNode ): string
46
+ proc genPath (node: DirTreeNode ): string
38
47
proc removeSuffixInsensitive (s, suffix: string ): string
39
- proc convertMarkdownToNercPage (tree : DirTreeNode )
48
+ proc convertMarkdownToNercPage (node : DirTreeNode )
40
49
proc buildDirTree (node: DirTreeNode , depth: uint )
41
- proc printTree (tree : DirTreeNode )
50
+ proc printTree (node : DirTreeNode )
42
51
proc genSidebar ( tree: DirTreeNode , currentItem: DirTreeNode ): string
43
52
proc populateDirs (treeRoot: DirTreeNode )
44
53
58
67
DefaultStyle = staticRead (" res/styles.css" )
59
68
DefaultJson = staticRead (" res/config.json" )
60
69
61
- let DefaultConfig = parseJson ( DefaultJson )
70
+ var defaultconfig: JsonNode
62
71
72
+ try :
73
+ defaultconfig = parseJson (DefaultJson )
74
+ except JsonParsingError :
75
+ echo " [ERROR] Built-in config.json does not pass validation. Fix error and recompile."
76
+
77
+ let DefaultConfig = defaultconfig
63
78
64
79
var
65
80
pageTitle: string
69
84
htmlFooterLeft: string
70
85
htmlFooterRight: string
71
86
72
- fsTree: DirTreeNode = DirTreeNode (depth: 0 , label: " Main" , path: " ." , kind: itemDir)
87
+ fsTree: DirTreeNode = DirTreeNode (depth: 0 , name: " Main " , label: " Main" , path: " ." , kind: itemDir)
73
88
74
89
75
90
fsTree.html = DefaultTemplate
@@ -82,14 +97,24 @@ proc removeSuffixInsensitive(s, suffix: string): string =
82
97
return s[0 ..< s.len - suffix.len]
83
98
return s
84
99
100
+ proc getTemplate (node: DirTreeNode ): string =
101
+ if node.hasHTML != nil :
102
+ if node.html != " " :
103
+ return node.html
104
+
105
+ if node.parent != nil :
106
+ return node.parent.getTemplate ()
107
+
108
+ return DefaultTemplate
109
+
85
110
86
- proc getConfig (node: DirTreeNode , key: string ): JsonNode {. inline .} =
111
+ proc getConfig (node: DirTreeNode , key: string ): JsonNode =
87
112
if not node.config.isNil:
88
113
if node.config.hasKey (key):
89
114
return node.config[key]
90
115
91
116
if node.parent != nil :
92
- return getConfig ( node.parent, key)
117
+ return node.parent. getConfig ( key)
93
118
94
119
return DefaultConfig [key]
95
120
@@ -103,22 +128,28 @@ proc genLinks(node: DirTreeNode): string =
103
128
if node.config.isNil: return node.parent.genLinks ()
104
129
let config: JsonNode = node.getConfig (" links" )
105
130
106
- if config.kind != JObject :
107
- # echo "[LINKS] Not generating links."
131
+ if config.kind != JArray :
108
132
return node.parent.genLinks ()
109
133
110
- for label, link in config.pairs ():
134
+ for item in config:
135
+ if item.kind != JObject : continue
136
+ if not item.hasKey (" label" ) and not item.hasKey (" link" ): continue
137
+ if item[" label" ].kind != JString : continue
138
+ if item[" link" ].kind != JString : continue
139
+ let
140
+ label = item[" label" ].getStr ()
141
+ link = item[" link" ].getStr ()
142
+
111
143
separator = if addSeparator: " | " else : " "
112
144
113
- if label == " " and link. getStr () == " SPACER" :
145
+ if label == " " and link == " SPACER" :
114
146
links = links & " <div class=\" spacer\" ></div>"
115
147
addSeparator = false
116
148
continue
117
149
118
- links = links & separator & " <a href=\" " & link. getStr () & " \" >" & label & " </a>"
150
+ links = links & separator & " <a href=\" " & link & " \" >" & label & " </a>"
119
151
addSeparator = true
120
152
121
- # echo "[LINKS] " & links
122
153
return links
123
154
124
155
@@ -129,29 +160,32 @@ proc genPath(node: DirTreeNode): string =
129
160
return path
130
161
131
162
132
- proc convertMarkdownToNercPage (tree: DirTreeNode ) =
133
- echo tree.path[2 ..^ 1 ] & " : " & tree.name & " \n "
134
- if tree.kind == itemDir: return
163
+ proc convertMarkdownToNercPage (node: DirTreeNode ) =
164
+ if node.kind == itemDir: return
135
165
136
- var outPath: string = tree .path[2 ..^ 1 ]
166
+ var outPath: string = node .path[2 ..^ 1 ]
137
167
outPath.removeSuffix (" .md" )
138
168
if toLowerAscii (outPath).endsWith (" readme" ):
139
169
outpath = outPath.removeSuffixInsensitive (" readme" ) & " index"
140
170
outPath = outPath & " .htm"
141
171
142
- let mdFile = readFile (tree .path[2 ..^ 1 ])
172
+ let mdFile = readFile (node .path[2 ..^ 1 ])
143
173
144
- var htmlTxt = DefaultTemplate
145
- if htmlTxt.contains (PageTitleTag ): htmlTxt = htmlTxt.replace ( PageTitleTag , tree.parent.getConfig (" page title" ).getStr () & " - " & tree.name )
146
- if htmlTxt.contains (LinksTag ): htmlTxt = htmlTxt.replace ( LinksTag , tree.parent.genLinks () )
147
- if htmlTxt.contains (SiteTitleTag ): htmlTxt = htmlTxt.replace ( SiteTitleTag , tree.parent.getConfig (" site title" ).getStr () )
148
- if htmlTxt.contains (SubtitleTag ): htmlTxt = htmlTxt.replace ( SubtitleTag , tree.parent.getConfig (" subtitle" ).getStr () )
149
- if htmlTxt.contains (SidebarTag ): htmlTxt = htmlTxt.replace ( SidebarTag , fsTree.genSidebar (tree) )
174
+ var
175
+ htmlTxt = node.parent.getTemplate ()
176
+ pageTitle: string = " "
177
+ if " readme" != node.label.toLowerAscii (): pageTitle = " - " & node.label
178
+ if htmlTxt.contains (PageTitleTag ): htmlTxt = htmlTxt.replace ( PageTitleTag , node.parent.getConfig (" page title" ).getStr () & pageTitle )
179
+ if htmlTxt.contains (LinksTag ): htmlTxt = htmlTxt.replace ( LinksTag , node.parent.genLinks () )
180
+ if htmlTxt.contains (SiteTitleTag ): htmlTxt = htmlTxt.replace ( SiteTitleTag , node.parent.getConfig (" site title" ).getStr () )
181
+ if htmlTxt.contains (SubtitleTag ): htmlTxt = htmlTxt.replace ( SubtitleTag , node.parent.getConfig (" subtitle" ).getStr () )
182
+ if htmlTxt.contains (SidebarTag ): htmlTxt = htmlTxt.replace ( SidebarTag , fsTree.genSidebar (node) )
150
183
if htmlTxt.contains (ContentTag ): htmlTxt = htmlTxt.replace ( ContentTag , mdFile.markdown () )
151
- if htmlTxt.contains (FooterLeftTag ): htmlTxt = htmlTxt.replace ( FooterLeftTag , tree .parent.getConfig (" footer left" ).getStr () )
152
- if htmlTxt.contains (FooterRightTag ): htmlTxt = htmlTxt.replace ( FooterRightTag , tree .parent.getConfig (" footer right" ).getStr () )
184
+ if htmlTxt.contains (FooterLeftTag ): htmlTxt = htmlTxt.replace ( FooterLeftTag , node .parent.getConfig (" footer left" ).getStr () )
185
+ if htmlTxt.contains (FooterRightTag ): htmlTxt = htmlTxt.replace ( FooterRightTag , node .parent.getConfig (" footer right" ).getStr () )
153
186
154
187
writefile (outPath, htmlTxt)
188
+ echo " [GENERATED]: " , outPath
155
189
156
190
157
191
proc buildDirTree (node: DirTreeNode , depth: uint ) =
@@ -161,55 +195,56 @@ proc buildDirTree(node: DirTreeNode, depth: uint) =
161
195
if name[0 ] == '.' : continue # Skip hidden files and directories (such as .git)
162
196
if kind == pcFile:
163
197
var new_node: DirTreeNode = DirTreeNode (depth: depth, kind: itemFile, name: name, path: path & '/' & name, parent: node)
164
- echo " [FILE] " & name
198
+
165
199
if name.toLowerAscii ().endsWith (" .md" ):
166
200
new_node.fileKind = fileMarkdown
167
201
new_node.label = name.split ('.' )[0 ].replace ('_' , ' ' )
168
- echo " [LABEL] " & new_node.label
169
202
if " readme" == new_node.label.toLowerAscii (): node.hasIndex = new_node
170
203
# convertMarkdownToNercPage(path)
171
204
elif name.toLowerAscii () == " config.json" :
172
- echo new_node.path[2 ..^ 1 ]
173
205
var file: string = readFile (new_node.path[2 ..^ 1 ])
174
- echo file
175
- node.config = parseJson (file)
206
+ try :
207
+ node.config = parseJson (file)
208
+ except JsonParsingError :
209
+ echo " [ERROR] " , name, " at " , path, " did not pass validation and will be ignored."
176
210
continue
211
+
177
212
elif name.toLowerAscii () == " template.htm" :
178
213
node.html = readFile (new_node.path)
179
214
continue
215
+
180
216
elif name.toLowerAscii () == " styles.css" :
181
217
182
218
continue
219
+
183
220
elif name.toLowerAscii ().endsWith (" .html" ):
184
221
new_node.fileKind = fileHTML
185
222
else : continue
223
+
186
224
new_node.parent = node
187
- # echo "\t", path & "/" & name
188
225
node.contents.add (new_node)
189
226
190
227
elif kind == pcDir:
191
228
var new_node: DirTreeNode = DirTreeNode (depth: depth, kind: itemDir, name: name, label: name.split ('.' )[0 ].replace ('_' , ' ' ), path: path & '/' & name, parent: node)
192
- # echo path & "/" & name
193
- echo " [DIR] " & name
194
- echo " [LABEL] " & new_node.label
195
229
new_node.parent = node
196
230
buildDirTree (new_node, depth+ 1 )
197
231
node.contents.add (new_node)
198
232
199
233
200
- proc printTree (tree: DirTreeNode ) =
201
- if tree.kind == itemFile:
202
-
203
- case tree.fileKind
204
- of fileMarkdown: echo tree.depth, repeat ('\t ' , tree.depth), tree.name, " : Markdown"
205
- of fileJSON: echo tree.depth, repeat ('\t ' , tree.depth), tree.name, " : JSON"
206
- of fileTemplate: echo tree.depth, repeat ('\t ' , tree.depth), tree.name, " : Template"
207
- of fileHTML: echo tree.depth, repeat ('\t ' , tree.depth), tree.name, " : HTML"
234
+ proc printTree (node: DirTreeNode ) =
235
+ if node.kind == itemFile:
236
+ var fileType: string
237
+ case node.fileKind
238
+ of fileMarkdown: fileType = " Markdown"
239
+ of fileJSON: fileType = " JSON"
240
+ of fileTemplate: fileType = " Template"
241
+ of fileHTML: fileType = " HTML"
242
+ echo " [FILE]" , repeat ('\t ' , node.depth), node.name, " : "
208
243
209
- elif tree .kind == itemDir:
210
- echo repeat ('\t ' , tree .depth), tree .path, " : " , tree .name, " : " , tree .contents.len ()
244
+ elif node .kind == itemDir:
245
+ echo " [DIR] " , repeat ('\t ' , node .depth), node .path, " : " , node .name, " : " , node .contents.len ()
211
246
212
- for item in tree .contents:
247
+ for item in node .contents:
213
248
printTree (item)
214
249
continue
215
250
@@ -233,8 +268,7 @@ proc genSidebar(tree: DirTreeNode, currentItem: DirTreeNode): string =
233
268
234
269
if " index" == toLowerAscii (label): return " "
235
270
if tree == currentItem: label = " >> " & label & " <<"
236
-
237
- echo path
271
+
238
272
return repeat ('\t ' , tree.depth) & " <li class=\" page\" ><a href=\" " & path & " \" >" & label & " </a></li>\n "
239
273
240
274
elif tree.kind == itemDir:
@@ -250,7 +284,6 @@ proc genSidebar(tree: DirTreeNode, currentItem: DirTreeNode): string =
250
284
for item in tree.contents:
251
285
itemList = itemList & genSidebar (item, currentItem)
252
286
253
- echo " Generated Path: " & path
254
287
if tree.hasIndex != nil : label = " <a href=\" " & path & " \" >" & label & " </a>\n "
255
288
itemList =
256
289
" <li class=\" dir\" >" & label & " <ul>\n " &
@@ -278,8 +311,11 @@ proc main() =
278
311
if isValidFileName (args[0 ]):
279
312
echo args[0 ]
280
313
314
+ echo " Scanning..."
281
315
buildDirTree (fsTree, 1 )
282
316
printTree (fsTree)
317
+ echo " \n Generating pages..."
283
318
populateDirs (fsTree)
319
+ echo " \n Done!"
284
320
285
321
main ()
0 commit comments