6
6
7
7
from datetime import datetime
8
8
from os .path import join
9
+ from typing import NotRequired , TypedDict
9
10
10
11
import mako .template
11
12
import mako .lookup
32
33
)
33
34
34
35
35
- def copyinto (src , dst , symlinks = False , ignore = None ):
36
+ class Page (TypedDict ):
37
+ """A page on the site."""
38
+
39
+ # Brief introductory comment above at the start of a page
40
+ author_comment : NotRequired [str ]
41
+ # YYYY-MM-DD date of the page
42
+ date : str
43
+ # A brief summary of the page
44
+ excerpt : str
45
+ # The rendered HTML of the page
46
+ html : NotRequired [str ]
47
+ # The next page in chronological series of pages
48
+ next : "Page"
49
+ # Flag to skip rendering the page
50
+ skip : NotRequired [bool ]
51
+ # The URL slug of the page
52
+ slug : str
53
+ # The path to the source document of the page
54
+ src : str
55
+ # The template to use to render the page
56
+ template : NotRequired [str ]
57
+ # The title of the page
58
+ title : str
59
+
60
+
61
+ def copyinto (src : str , dst : str , symlinks = False , ignore = None ):
36
62
"""
37
- Copy files and subdirectoryes from src into dst.
63
+ Copy files and subdirectories from src into dst.
38
64
39
65
http://stackoverflow.com/questions/1868714/how-do-i-copy-an-entire-directory-of-files-into-an-existing-directory-using-pyth
40
66
"""
@@ -47,7 +73,7 @@ def copyinto(src, dst, symlinks=False, ignore=None):
47
73
shutil .copy2 (s , d )
48
74
49
75
50
- def save_rss (pages ):
76
+ def save_rss (pages : list [ Page ] ):
51
77
"""Save a RSS document listing all of the pages."""
52
78
rss_tmpl = TMPL_LOOKUP .get_template ("rss.mako" )
53
79
xml = rss_tmpl .render (
@@ -61,7 +87,7 @@ def save_rss(pages):
61
87
f .write (xml )
62
88
63
89
64
- def save_atom (pages ):
90
+ def save_atom (pages : list [ Page ] ):
65
91
"""Save an Atom document listing of all of the pages."""
66
92
atom_tmpl = TMPL_LOOKUP .get_template ("atom.mako" )
67
93
xml = atom_tmpl .render (
@@ -76,7 +102,7 @@ def save_atom(pages):
76
102
f .write (xml )
77
103
78
104
79
- def save_archive (pages ):
105
+ def save_archive (pages : list [ Page ] ):
80
106
"""Save an HTML document listing all of the pages."""
81
107
archive_tmpl = TMPL_LOOKUP .get_template ("archive.mako" )
82
108
html = archive_tmpl .render (site_name = SITE_NAME , site_root = ".." , all_pages = pages )
@@ -85,7 +111,7 @@ def save_archive(pages):
85
111
f .write (html )
86
112
87
113
88
- def save_latest (pages ):
114
+ def save_latest (pages : list [ Page ] ):
89
115
"""Save the latest page as index.html."""
90
116
page = pages [0 ]
91
117
tmpl_name = page .get ("template" , "page.mako" )
@@ -100,7 +126,7 @@ def save_latest(pages):
100
126
f .write (html )
101
127
102
128
103
- def save_html (pages ):
129
+ def save_html (pages : list [ Page ] ):
104
130
"""Save every page as an HTML document."""
105
131
for page in pages :
106
132
in_tree = page ["src" ]
@@ -117,11 +143,10 @@ def save_html(pages):
117
143
f .write (html )
118
144
119
145
120
- def org_pages (pages ):
146
+ def org_pages (pages : list [ Page ] ):
121
147
"""Sort pages from newest to oldest.
122
148
123
- Use the `date` key for sorting. Add a `next` key to link one page to the
124
- next.
149
+ Use the `date` key for sorting. Add a `next` key to link one page to the next.
125
150
"""
126
151
for page in pages :
127
152
if "date" in page :
@@ -135,23 +160,17 @@ def org_pages(pages):
135
160
136
161
137
162
class MarkdownParser :
138
- md = markdown .Markdown (
139
- extensions = ["meta" , "fenced_code" , "codehilite" ], output_format = "html"
140
- )
141
-
142
- def execute (self , path , page ):
143
- """Parse an md file in the path and update the page with its
144
- contents.
163
+ def __init__ (self ):
164
+ self .md = markdown .Markdown (
165
+ extensions = ["meta" , "fenced_code" , "codehilite" ], output_format = "html"
166
+ )
145
167
146
- Use the page filename or fall back on index.md as the default.
147
- Add metadata from the extended metadata section of the document to the
148
- page along with the rendered HTML.
149
- """
150
- fn = join (path , page .get ("filename" , "index.md" ))
151
- if not os .path .isfile (fn ) or not fn .endswith (".md" ):
168
+ def execute (self , path : str , page : Page ):
169
+ """Parse an md file in the path and update the page with its HTML rendered content and
170
+ metadata."""
171
+ fn = join (path , "index.md" )
172
+ if not os .path .isfile (fn ):
152
173
return
153
- else :
154
- page .setdefault ("filename" , "index.md" )
155
174
with open (fn ) as f :
156
175
print ("Processing" , path , "as Markdown" )
157
176
text = f .read ()
@@ -169,10 +188,9 @@ def execute(self, path, page):
169
188
page ["slug" ] = os .path .basename (path )
170
189
page ["html" ] = html
171
190
172
- def _build_excerpt (self , text ):
173
- """Build an excerpt from the first non-blank line after the first blank
174
- line separating the metadata from the content of the doc.
175
- """
191
+ def _build_excerpt (self , text : str ):
192
+ """Build an excerpt from the first non-blank line after the first blank line separating the
193
+ metadata from the content of the doc."""
176
194
lines = []
177
195
prior = None
178
196
@@ -192,21 +210,18 @@ def _build_excerpt(self, text):
192
210
def load_pages ():
193
211
"""Parse data and metadata for all pages.
194
212
195
- Iterate over the page directories. Pass the page source document and
196
- in-memory page representation to all parsers. Raise a RuntimeError if
197
- no parser emits HTML for the page.
213
+ Iterate over the page directories. Pass the page source document and in-memory page
214
+ representation to all parsers. Raise a RuntimeError if no parser emits HTML for the page.
198
215
"""
199
216
pages = []
200
217
handlers = [MarkdownParser ()]
201
218
for path in glob .glob (join (PAGES_DIR , "*" )):
202
- page = {}
219
+ page : Page = {}
203
220
for handler in handlers :
204
221
handler .execute (path , page )
205
222
if "skip" in page :
206
223
continue
207
224
elif "html" not in page :
208
- print ("WARN: Nothing rendered HTML for" , path )
209
- continue
210
225
raise RuntimeError ("Nothing rendered HTML for " + path )
211
226
pages .append (page )
212
227
return pages
0 commit comments