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