Files: 42fd8897ab16ba7f6d7f843ba1695042431b025d / generator / templates / entry.py
11352 bytesRaw
1 | import marko |
2 | |
3 | import common |
4 | |
5 | |
6 | def links_to_nearby_entries(id): |
7 | earlier_entries = [ |
8 | e for e in reversed(list(common.entries)[: list(common.entries).index(id)]) |
9 | ] |
10 | later_entries = [ |
11 | e for e in list(common.entries)[1 + list(common.entries).index(id) :] |
12 | ] |
13 | relevant_earlier_entries = {} |
14 | relevant_later_entries = {} |
15 | for other_entry in earlier_entries: |
16 | if earlier_entries.index(other_entry) == 0: |
17 | relevant_earlier_entries[other_entry] = relevant_earlier_entries.get( |
18 | other_entry, {} |
19 | ) |
20 | relevant_earlier_entries[other_entry].update({"rel": "prev"}) |
21 | if "series" in common.entries[id] and "series" in common.entries[other_entry]: |
22 | if common.slugify(common.entries[id]["series"]) == common.slugify( |
23 | common.entries[other_entry]["series"] |
24 | ): |
25 | entries_in_this_series = common.entries_in_series( |
26 | common.entries[id]["series"] |
27 | ) |
28 | if other_entry == common.offset_id(entries_in_this_series, id, -1): |
29 | relevant_earlier_entries[ |
30 | other_entry |
31 | ] = relevant_earlier_entries.get(other_entry, {}) |
32 | relevant_earlier_entries[other_entry][ |
33 | "labels" |
34 | ] = relevant_earlier_entries[other_entry].get("labels", []) |
35 | relevant_earlier_entries[other_entry]["labels"] += [ |
36 | common.entries[id]["series"] |
37 | ] |
38 | relevant_earlier_entries[other_entry].update({"rel": "prev"}) |
39 | if "tags" in common.entries[id] and "tags" in common.entries[other_entry]: |
40 | for tag_string in [ |
41 | tag_string |
42 | for tag_string in common.entries[id]["tags"] |
43 | if common.slugify(tag_string) |
44 | in map(common.slugify, common.entries[other_entry]["tags"]) |
45 | ]: |
46 | entries_with_this_tag = common.entries_with_tag(tag_string) |
47 | if other_entry == common.offset_id(entries_with_this_tag, id, -1): |
48 | relevant_earlier_entries[ |
49 | other_entry |
50 | ] = relevant_earlier_entries.get(other_entry, {}) |
51 | relevant_earlier_entries[other_entry][ |
52 | "labels" |
53 | ] = relevant_earlier_entries[other_entry].get("labels", []) |
54 | if ( |
55 | "series" in common.entries[id] |
56 | and "series" in common.entries[other_entry] |
57 | and common.slugify(common.entries[id]["series"]) |
58 | == common.slugify(common.entries[other_entry]["series"]) |
59 | ): |
60 | relevant_earlier_entries[other_entry]["labels"] += [ |
61 | common.entries[id]["series"] |
62 | ] |
63 | relevant_earlier_entries[other_entry]["labels"] += [tag_string] |
64 | relevant_earlier_entries[other_entry].update({"rel": "prev"}) |
65 | for other_entry in later_entries: |
66 | if later_entries.index(other_entry) == 0: |
67 | relevant_later_entries[other_entry] = relevant_later_entries.get( |
68 | other_entry, {} |
69 | ) |
70 | relevant_later_entries[other_entry].update({"rel": "next"}) |
71 | if "series" in common.entries[id] and "series" in common.entries[other_entry]: |
72 | if common.slugify(common.entries[id]["series"]) == common.slugify( |
73 | common.entries[other_entry]["series"] |
74 | ): |
75 | entries_in_this_series = common.entries_in_series( |
76 | common.entries[id]["series"] |
77 | ) |
78 | if other_entry == common.offset_id(entries_in_this_series, id, +1): |
79 | relevant_later_entries[other_entry] = relevant_later_entries.get( |
80 | other_entry, {} |
81 | ) |
82 | relevant_later_entries[other_entry][ |
83 | "labels" |
84 | ] = relevant_later_entries[other_entry].get("labels", []) |
85 | relevant_later_entries[other_entry]["labels"] += [ |
86 | common.entries[id]["series"] |
87 | ] |
88 | relevant_later_entries[other_entry].update({"rel": "next"}) |
89 | if "tags" in common.entries[id] and "tags" in common.entries[other_entry]: |
90 | for tag_string in [ |
91 | tag_string |
92 | for tag_string in common.entries[id]["tags"] |
93 | if common.slugify(tag_string) |
94 | in map(common.slugify, common.entries[other_entry]["tags"]) |
95 | ]: |
96 | entries_with_this_tag = common.entries_with_tag(tag_string) |
97 | if other_entry == common.offset_id(entries_with_this_tag, id, +1): |
98 | relevant_later_entries[other_entry] = relevant_later_entries.get( |
99 | other_entry, {} |
100 | ) |
101 | relevant_later_entries[other_entry][ |
102 | "labels" |
103 | ] = relevant_later_entries[other_entry].get("labels", []) |
104 | if ( |
105 | "series" in common.entries[id] |
106 | and "series" in common.entries[other_entry] |
107 | and common.slugify(common.entries[id]["series"]) |
108 | == common.slugify(common.entries[other_entry]["series"]) |
109 | ): |
110 | relevant_later_entries[other_entry]["labels"] += [ |
111 | common.entries[id]["series"] |
112 | ] |
113 | relevant_later_entries[other_entry]["labels"] += [tag_string] |
114 | relevant_later_entries[other_entry].update({"rel": "next"}) |
115 | links = "" |
116 | if len(relevant_earlier_entries) > 0: |
117 | links += ( |
118 | "<h2>Earlier:</h2>" |
119 | + "<ul>" |
120 | + "".join( |
121 | "<li>" |
122 | + common.link_to_entry(other_id, **relevant_earlier_entries[other_id]) |
123 | + "</li>" |
124 | for other_id in relevant_earlier_entries |
125 | ) |
126 | + "</ul>" |
127 | ) |
128 | if len(relevant_later_entries) > 0: |
129 | links += ( |
130 | "<h2>Later:</h2>" |
131 | + "<ul>" |
132 | + "".join( |
133 | "<li>" |
134 | + common.link_to_entry(other_id, **relevant_later_entries[other_id]) |
135 | + "</li>" |
136 | for other_id in relevant_later_entries |
137 | ) |
138 | + "</ul>" |
139 | ) |
140 | return links |
141 | |
142 | |
143 | def html(entries, id): |
144 | entry = entries[id] |
145 | byline = ( |
146 | ( |
147 | '<div class="series">' |
148 | + "from " |
149 | + f'<a href="{common.url_of_series(entry["series"])}">' |
150 | + entry["series"] |
151 | + "</a>" |
152 | + "</div>" |
153 | if "series" in entry |
154 | else "" |
155 | ) |
156 | + '<div class="byline">' |
157 | + 'by <a href="/">Grey Nicholson</a>' |
158 | + "</div>" |
159 | + '<div class="datestamp">' |
160 | + ("published " if "modified" in entry else "") |
161 | + f'<time datetime="{entry["date"]:%Y-%m-%dT%H:%MZ}">' |
162 | f'{entry["date"]:%Y-%m-%d}' |
163 | " · " |
164 | f'stardate {common.stardate(entry["date"])}' |
165 | "</time>" |
166 | + ( |
167 | "<div>" |
168 | + "edited " |
169 | + f'<time datetime="{entry["modified"]:%Y-%m-%dT%H:%MZ}">' |
170 | + f'{entry["modified"]:%Y-%m-%d}' |
171 | + " · " |
172 | + f'stardate {common.stardate(entry["modified"])}' |
173 | + "</time>" |
174 | + "</div>" |
175 | if "modified" in entry |
176 | else "" |
177 | ) |
178 | + "</div>" |
179 | ) |
180 | colour_class = ( |
181 | common.slugify(entry["series"]) |
182 | if "series" in entry |
183 | else f'month-{entry["date"].month:02d}' |
184 | ) |
185 | decoration = ( |
186 | f"""<div class="decoration" style="background-image: url('{entry["image"]["filename"]}');""" |
187 | + ( |
188 | f""" background-position: {entry["image"]["position"]};""" |
189 | if "position" in entry["image"] |
190 | else "" |
191 | ) |
192 | + ( |
193 | f""" height: {entry["image"]["height"]};""" |
194 | if "height" in entry["image"] |
195 | else "" |
196 | ) |
197 | + '"></div>' |
198 | if "image" in entry |
199 | else '<div class="decoration"></div>' |
200 | if "series" in entry |
201 | else "" |
202 | ) |
203 | description = ( |
204 | ('<div class="description">' + marko.convert(entry["description"]) + "</div>") |
205 | if "description" in entry |
206 | else "" |
207 | ) |
208 | entry_links = ( |
209 | ( |
210 | "<hr/>" |
211 | + "<nav>" |
212 | + "<h2>See also:</h2>" |
213 | + "<ul>" |
214 | + "".join( |
215 | ("<li>" + common.link_with_details(**link) + "</li>") |
216 | for link in entry["links"] |
217 | ) |
218 | + "</ul>" |
219 | + "</nav>" |
220 | ) |
221 | if "links" in entry |
222 | else "" |
223 | ) |
224 | |
225 | repeated_tags = ( |
226 | list( |
227 | common.slugify(tag) |
228 | for tag in entry["tags"] |
229 | if common.slugify(tag) in common.repeated_tags |
230 | ) |
231 | if "tags" in entry |
232 | else [] |
233 | ) |
234 | head = "".join( |
235 | f"""<link href="{common.url_of_tag_feed(tag)}" rel="alternate" type="application/atom+xml" title="{common.title(tag)}">""" |
236 | + "\n" |
237 | for tag in repeated_tags |
238 | ) |
239 | small = "<p><small>" + entry["small"] + "</small></p>" if "small" in entry else "" |
240 | tags = ( |
241 | ( |
242 | '<div class="tags">tags: ' |
243 | + ", ".join( |
244 | f'<a href="{common.url_of_tag(tag)}" rel="tag">' + tag + "</a>" |
245 | for tag in repeated_tags |
246 | ) |
247 | + "</ul>" |
248 | + "</div>" |
249 | ) |
250 | if repeated_tags |
251 | else "" |
252 | ) |
253 | tags = "" # No tags for now |
254 | |
255 | return common.print_html( |
256 | f"""<!doctype html> |
257 | <html> |
258 | <head> |
259 | {common.head} |
260 | {head} |
261 | <title>{entry['title']}</title> |
262 | </head> |
263 | <body class="entry {colour_class}"> |
264 | <article> |
265 | <header> |
266 | {decoration} |
267 | <h1>{entry['title']}</h1> |
268 | </header> |
269 | <main> |
270 | <hr/> |
271 | <section> |
272 | {marko.convert(entry.content)} |
273 | </section> |
274 | <footer> |
275 | <hr/> |
276 | <section> |
277 | {byline} |
278 | {description} |
279 | {tags} |
280 | {small} |
281 | </section> |
282 | {entry_links} |
283 | </footer> |
284 | </main> |
285 | </article> |
286 | <footer> |
287 | <hr/> |
288 | <nav> |
289 | {links_to_nearby_entries(id)} |
290 | </nav> |
291 | </footer> |
292 | {common.footer} |
293 | </body> |
294 | </html> |
295 | """ |
296 | ) |
297 |
Built with git-ssb-web