]> zackmdavis.net Git - An_Algorithmic_Lucidity.git/commitdiff
formatting fidelity review
authorZack M. Davis <code@zackmdavis.net>
Wed, 15 Jul 2026 02:19:11 +0000 (19:19 -0700)
committerZack M. Davis <code@zackmdavis.net>
Wed, 15 Jul 2026 02:19:11 +0000 (19:19 -0700)
18 files changed:
CLAUDE.md [new file with mode: 0644]
content/2013/app-academy-diary-week-four.md
content/2013/lyrics-to-the-song-about-my-hair.md
content/2013/lyrics-to-the-song-about-truthseekers.md
content/2014/clarity-of-intent.md
content/2014/defect.md
content/2014/pumpkin-spice.md
content/2015/back-from-running.md
content/2015/epistolary.md
content/2016/0x1f431-cat-face.md
content/2016/joined.md
content/2016/oral-tradition-i.md
content/2016/rustconf-2016-travelogue.md
content/2017/some-excuse-for-a-rustconf-2017-travelogue.md
content/2017/sworn-to-the-word.md
content/2025/recruitment-advertisements-for-the-2024-putnam-competition-at-san-francisco-state-university.md
content/2025/the-end-of-the-movie-sf-state-2024-putnam-competition-team-a-retrospective.md
pelicanconf.py

diff --git a/CLAUDE.md b/CLAUDE.md
new file mode 100644 (file)
index 0000000..2a96637
--- /dev/null
+++ b/CLAUDE.md
@@ -0,0 +1,21 @@
+# An Algorithmic Lucidity
+
+Pelican static-site conversion of a WordPress blog (zackmdavis.net/blog). Content lives in `content/`, one Markdown file per post/page. `analgorithmiclucidity.WordPress.*.xml` is the original WXR export, used as ground truth when cross-checking whether the WordPress→Markdown conversion silently lost or corrupted formatting.
+
+## Known gotchas
+
+### Bare `$` math delimiter collides with currency amounts
+
+We use the `pelican-render-math` plugin (`PLUGINS = ['render_math']` in `pelicanconf.py`) for MathJax. Its inline-math regex is hardcoded to bare `$...$` with **no way to disable it** (source: `.venv/lib/python3.12/site-packages/pelican/plugins/render_math/pelican_mathjax_markdown_extension.py`). If a paragraph contains two or more literal `$` (e.g. two dollar amounts), they can pair up and get swallowed into a bogus math span, corrupting the render. Backslash-escaping (`\$`) does *not* help — the plugin's pattern runs at higher Markdown inline-pattern priority (185) than the `escape` pattern (180) specifically so real LaTeX commands survive, which as a side effect means it never sees escape sequences at all.
+
+Current fix, applied case-by-case as encountered: replace one or more of the conflicting `$` with the HTML entity `&#36;` (bypasses the regex entirely since it isn't a literal `$` character in the raw source). Confirmed no other post in the corpus has this problem as of 2026-07-14 (see `content/2016/joined.md` for the one confirmed instance).
+
+**If this keeps recurring and the per-instance entity patching becomes annoying**: the real fix is switching to the `python-markdown-math` package (`mdx_math`) instead, configured with `enable_dollar_delimiter: False` (that's the default). Unlike `pelican-render-math`, it makes bare `$` a plain, forever-ordinary character and requires `\(...\)` for inline math instead — which is also MathJax's own actual default behavior (bare `$` inline math is opt-in upstream, precisely to avoid currency collisions; this Pelican plugin skipped that safety rail). Confirmed via its source (`enable_dollar_delimiter` default `False`, pattern priority 185, same escape-priority trick).
+
+Migration cost if we ever do this: (1) swap the plugin and reimplement the "only inject the MathJax `<script>` tag on pages that actually contain math" auto-detection ourselves, since that's Pelican-specific glue `pelican-render-math` provides that the plain extension doesn't; (2) convert every existing inline `$...$` math span across the corpus to `\(...\)` (display math `$$...$$` is already unambiguous and can stay as-is); (3) revert the `&#36;` entities back to plain `$`. Not done as of 2026-07-14 — decided the entity workaround is fine for now since it's a single confirmed instance.
+
+### Automatic email-autolinking of `<...>` disabled
+
+Python-Markdown's core `automail` inline pattern (priority 110, baked into every `Markdown` instance regardless of extensions) greedily swallows any bare `<foo@bar>` into a `mailto:` autolink as one atomic match — so `<_zmd@sfsu.edu_>` (used in the Putnam posts to mimic italicized "From:"/"To:" email-client headers) got mangled: underscores baked in literally as part of the (broken) address, angle brackets consumed. Backslash-escaping didn't help either, since `<` isn't in Markdown's default escapable-character list (`>` is, `<` isn't), so `\<` just left a literal backslash in the output.
+
+Fixed permanently (rather than patched per-instance) by deregistering the pattern globally: see `_DisableAutomailExtension` in `pelicanconf.py`, wired in via `MARKDOWN['extensions']`. Confirmed this doesn't affect the separate `autolink` pattern (bare `<http://...>` URLs still auto-link fine). As of 2026-07-14, plain `<_email_>` syntax works correctly everywhere in the corpus with no escaping needed.
index dc1b1848fa46a09b05d1960bbeca5edcaf91e50a..f1db1d1701c025134206424f0f976c4c8fb640e8 100644 (file)
@@ -9,7 +9,7 @@ _Monday 7 October 2013—_ The main part of SedentaryRecord went pretty smoothly
 
 _Wednesday 9 October 2013—_ I did poorly on the assessment yesterday. There were eight SQL queries to write; the first five were trivial, but I bombed the last three because [I'm a moron](http://zackmdavis.net/blog/2013/08/im-a-moron/) and didn't remember that the keyword for filtering aggregations was HAVING. I worked with _William Ott_ on an ice-cream finder (which uses Google Maps APIs to print out directions to nearby ice-cream) and a Twitter client. Of course, it simply wouldn't do to write an ice-cream finder without using it to find ice-cream, so after class we took one of our program's suggestions and bought ice-cream at the Häagen-Dazs in the mall on Market and Fifth. Today I worked with _David A._; we learned about routers and controllers.
 
-[![Our Cat for Rent](http://zackmdavis.net/blog/wp-content/uploads/2013/10/our_cat_for_rent-129x300.png)](http://zackmdavis.net/blog/wp-content/uploads/2013/10/our_cat_for_rent.png)
+[![Our Cat for Rent](http://zackmdavis.net/blog/wp-content/uploads/2013/10/our_cat_for_rent-129x300.png)](http://zackmdavis.net/blog/wp-content/uploads/2013/10/our_cat_for_rent.png){: .alignleft }
 
 _Thursday 10 October 2013—_ Dear reader, suppose [yet](http://zackmdavis.net/blog/2013/09/app-academy-diary-week-two/#sunday) [again](http://zackmdavis.net/blog/2013/09/app-academy-diary-week-three/#saturday) that you're working on the great American dog-sharing site—_loser!_ Sharing dogs is _so_ last week; you should have predicted that by now, everyone who's anyone would be renting cats instead. That's why today _Dean Yang_ and I used our prodigious knowledge of not just models, but also both views _and_ controllers, to make a mock cat-rental site! It's like this: say you visit the URL for the page that displays all the cats. Your browser issues an HTTP GET request, which is handled by the Rails router: an instance of the `CatsController` is spawned, and its `index` method is called, which puts an array of `Cat` objects (instantiated by the ActiveRecord ORM from their representations in the database) in an instance variable, which is then made available to a process that uses a template to decide how to express the information about the cats in HTML, which is then sent back to your browser. Similar stuff happens to let you make a new cat, or edit an existing cat.
 
index 2bd1804ff2ad415621c7afb578131e3771efdee8..9604f2953eb4ff96a1dd126fb94bb644713d8174 100644 (file)
@@ -9,7 +9,7 @@ It really is unfair
 My partner should object  
 Except she really doesn't care_
 
-I stare, in the mirror  
+_I stare, in the mirror  
 Half-paralyzed in fear  
 My partner should object  
-Except she really doesn't care
+Except she really doesn't care_
index 33d34021454a150f6981b664b4b86e8ddbda4c96..72181f63afb4bc707b0df9507955a6aca2f254cf 100644 (file)
@@ -9,15 +9,15 @@ Her work will be a benefit to all of humankind
 She went and proved some things which no one had surmised  
 Yesterday my sister won the Nobel physics prize_
 
-Yesterday I dreamed I won the Pulitzer prize  
+_Yesterday I dreamed I won the Pulitzer prize  
 I uncovered the scandal, was a President's demise  
 I found the truth and brought it out to people's eyes  
-Yesterday I dreamed I won the Pulitzer journalism prize
+Yesterday I dreamed I won the Pulitzer journalism prize_
 
-And then I woke up  
-And rubbed my eyes
+_And then I woke up  
+And rubbed my eyes_
 
-Yesterday my sister won the Nobel prize  
+_Yesterday my sister won the Nobel prize  
 Her work will be a benefit to all of humankind  
 She went and proved some things which no one had surmised  
-Yesterday my sister won the Nobel physics prize
+Yesterday my sister won the Nobel physics prize_
index f4e088dab5a4023f74181b3dae513dbcb72aa85c..db0f0fdab13ffba68da70ae7776067c666122dc2 100644 (file)
@@ -5,7 +5,7 @@ Category: computing
 Tags: Python
 Slug: clarity-of-intent
 
-```irc
+```
 <bob> and here on line 79---
 <bob>         else:
 <bob>             return None
index 956850ae0e9f6b9645a82b7b222a8fac0cf6ea7b..5e4f82fdcfb03525e310727defe356195365a1ce 100644 (file)
@@ -5,6 +5,7 @@ Category: asides
 Slug: defect
 
 [![My Genotype](http://zackmdavis.net/blog/wp-content/uploads/2014/03/genotype_emacs-300x175.png)](http://zackmdavis.net/blog/wp-content/uploads/2014/03/genotype_emacs.png)
+
 I—I'm afraid that examination of my [23andMe](https://www.23andme.com/) raw data has revealed a horrible truth about myself. I mean, I had always suspected, but now there's no room for doubt, no hope for denial. The terrible fact is that—
 
 I am not a geneticist.
index bc195d66bceac3deaeceee9767cbaf450a6834a1..1dc081751a03a3586668335073f889484627c1f6 100644 (file)
@@ -11,13 +11,13 @@ In particular, the American coffee hegemon has started offering its "pumpkin spi
 
 So this morning, shortly after I arrive in the office, plans are quickly formed for me and Alexander and our esteemed colleague Tim to go to the outpost.
 
-```` ```
+```
 Sep 10 09:18:04 <acorwin>     zackmdavis: PSL?
 Sep 10 09:18:39 <zackmdavis>  acorwin, I don't know what that is an initialism for
 Sep 10 09:18:43 <zackmdavis>  oh
 Sep 10 09:18:46 <acorwin>     zackmdavis: pump--
 Sep 10 09:18:49 <zackmdavis>  Pumpkin Spice!
-``` ````
+```
 
 We stroll down Brannan street, chatting about the sorts of things San Francisco software engineers talk about when they're not talking about their work, like the code we've been writing not-for-work. Alexander has been making a dice game for the iPhone but has run into trouble that he doesn't know how to debug; I suggest going to an iOS meetup group and enthusiastically mention that I went to an exciting Clojure meetup the previous night (where Zach Tellman, who has more GitHub stars than me by like two and a half orders of magnitude, gave me some tips on how to improve [my 3D 2048 clone](https://github.com/zackmdavis/Thirty-Three/)).
 
index 29ecfb329ae7d219f95b81e09b6d6397f52c534c..1e437154ecf81db379106e3bbe17d0b71a39399e 100644 (file)
@@ -5,7 +5,7 @@ Category: asides
 Tags: akrasia
 Slug: back-from-running
 
-```irc
+```
 [16:03:37] <alice>  I'm back from literally running, metaphorically from
                     figurative demons
 [16:03:50] <alice>  including the celebrity demon-prince Rateirs-Blak
index e9d9dbaa21d4e024b3d4e7413a706ef4838e7c72..17e88d6b645d27b07b1a1afdb634a2337956502c 100644 (file)
@@ -6,7 +6,7 @@ Slug: epistolary
 
 [(Previously.)](http://zackmdavis.net/blog/2014/05/a-short-story/)
 
-```irc
+```
 [19:26:50] <bob>    alice: you still around?
 [19:27:08] <alice>  bob, sort of
 [19:27:20] <bob>    alice: ok. never mind.
index b3365317c4b2ca63eb0952e9c5ee37dd42fffae1..0e7733e4ec1c26f5ee3436206f4bba4fe26c0b49 100644 (file)
@@ -15,7 +15,7 @@ index 648287f..e00dbc9 100644
  alias grports="netstat -tulpn | grep"
  
 +# cat
-+alias ?="cat"
++alias 🐱="cat"
 +
  # Vagrant
  alias v="vagrant"
index ae99fae78621b3ab484779eee300c6ab39f7c5c4..3c80f85aff22c6720d7ce99d38933126b41c3934 100644 (file)
@@ -27,7 +27,7 @@ I arrived way too early for check-in, and walked up the road (wearing my black j
 
 A little bit of lipstick rubbed off on the sandwich and the straw.
 
-I waited in the Hyatt lobby for a while, still with the jacket over my uniform, reading the Janet Mock autobiography on my PADD, until it was time to check in. After buying my Sunday wristband ($70), I wandered over to the photo-op/autograph ticketing table and bought a ticket to get a photo with Michael Dorn at 11:10 ($40). (Nana Visitor or Terry Farrell herself would have been my first choices for a celebrity photo, but they weren't there that day.)
+I waited in the Hyatt lobby for a while, still with the jacket over my uniform, reading the Janet Mock autobiography on my PADD, until it was time to check in. After buying my Sunday wristband (&#36;70), I wandered over to the photo-op/autograph ticketing table and bought a ticket to get a photo with Michael Dorn at 11:10 (&#36;40). (Nana Visitor or Terry Farrell herself would have been my first choices for a celebrity photo, but they weren't there that day.)
 
 There was still a lot of time to hang out before the theater opened for the actual convention programming, but that was fine, because actual convention programming is kind of boring; the actual point of conventions is to have an excuse to dress up and wander around and talk to people and get vanity photos of other people who are using the convention as an excuse to dress up.
 
@@ -57,7 +57,7 @@ I sat through some actual convention programming. John de Lancie is almost as en
 
 After de Lancie, there was a discussion with some writer-folk (the schedule _said_ the topic would be the [new series next year](https://en.wikipedia.org/wiki/Star_Trek:_Discovery), but they didn't seem to know anything about it), and soon enough, it was time for my photo op with Michael Dorn.
 
-The photo session was very assembly-line—here (unlike the autograph sessions I witnessed at other conventions) there was no pretense of your $40 giving you the opportunity to actually _meet_ your heroes for even half a minute: this was pose, _click_, and it's over, time for the next fan to get in position. I had time to say to Dorn, "I'm Jadzia," but that was it.
+The photo session was very assembly-line—here (unlike the autograph sessions I witnessed at other conventions) there was no pretense of your &#36;40 giving you the opportunity to actually _meet_ your heroes for even half a minute: this was pose, _click_, and it's over, time for the next fan to get in position. I had time to say to Dorn, "I'm Jadzia," but that was it.
 
 Not that I was disappointed. A woman on the event staff commented on how happy I looked skipping down the room after the photo was taken. "[My future husband!](http://memory-alpha.wikia.com/wiki/You_Are_Cordially_Invited_%28episode%29)" I said.
 
index bfebab3912987cd12aa383b1d29a213f10cd6e2d..575622b5ab34454af9e12397ce7414a5ec1d135e 100644 (file)
@@ -1,7 +1,7 @@
 Title: Oral Tradition I
 Date: 2016-05-15 10:28
 Status: published
-Category: fiction
+Category: asides
 Slug: oral-tradition-i
 
 The great rabbi Computron-6f61f18b-9ebf-4379-8778-f9e5bda821d5 said: in the days of auld lang syne on Earth-that-was, a match of a very popular strategy board game was arranged between a team of grandmasters, as White, and the best computer program, as Black. White played c4. After thinking for 45 minutes, the computer resigned.
index 030824d2d02640be3110e3fe68d950d9cfa1d5e7..d540ffd3ec3bec6fc56e5ee41ab6741e3baa96ac 100644 (file)
@@ -7,7 +7,7 @@ Slug: rustconf-2016-travelogue
 
 [(Previously on _An Algorithmic Lucidity_.)](http://zackmdavis.net/blog/2015/08/rustcamp-reminiscences/)
 
-[![sfo_reflections](http://zackmdavis.net/blog/wp-content/uploads/2016/09/sfo_reflections-243x300.jpg)](http://zackmdavis.net/blog/wp-content/uploads/2016/09/sfo_reflections.jpg)
+[![sfo_reflections](http://zackmdavis.net/blog/wp-content/uploads/2016/09/sfo_reflections-243x300.jpg)](http://zackmdavis.net/blog/wp-content/uploads/2016/09/sfo_reflections.jpg){: .alignright }
 
 The other weekend, excited to learn more and connect with people about what's going on at the forefront of expressive, performant, data-race-free computing—and eager for a healthy diversion from the last two months of agonizing delirium induced by the world-shattering insight about how everything I've cared about for the past fourteen years turns out to be related in unexpected and terrifying ways that I can't talk about for reasons that I also can't talk about—I took Friday off from my dayjob and caught a Thursday night flight out of SFO to exotic Portland (... I, um, don't travel much) for [RustConf](http://rustconf.com/)!
 
@@ -15,7 +15,7 @@ The conference itself was on Saturday, but Friday featured special training sess
 
 Every reference (I kind of want to say _ampersand_) in Rust code has an associated _lifetime_, the region of the program that that reference is valid for. Lifetime annotations (appearing in angle brackets like generics and starting with an apostrophe; by convention, usually named consecutively from the start of the lowercase Latin alphabet: `'a`, `'b`, _&c._) in function signatures are used to distinguish between the lifetimes of different reference arguments, but the compiler has _lifetime ellision rules_ that cover the 90% use-cases, so you can actually write pretty substantial Rust programs without actually understanding the theory, which is both practically useful and _eternally shameful_ (for a programmer who is _satisfied_ with _not understanding_ something is not long for this world). Hence the training. [(Exercises from the training sessions are available online.)](http://rust-tutorials.com/RustConf16/)
 
-[![rustconf_swag](http://zackmdavis.net/blog/wp-content/uploads/2016/09/rustconf_swag-236x300.jpg)](http://zackmdavis.net/blog/wp-content/uploads/2016/09/rustconf_swag.jpg)
+[![rustconf_swag](http://zackmdavis.net/blog/wp-content/uploads/2016/09/rustconf_swag-236x300.jpg)](http://zackmdavis.net/blog/wp-content/uploads/2016/09/rustconf_swag.jpg){: .alignleft }
 
 The point of lifetime analysis is to ensure that all references point somewhere valid; you can't (_can't_, the compiler won't let you) have a reference to a thing that outlives the thing itself. When you return a reference from a function, you can't be referencing something created by that function, because any such thing would die at the end of the function as it goes out of scope: a reference in the return type has to be a reference to something owned by the caller that was passed as an argument, but if there was more than one reference argument, it's ambiguous _which_ of the reference arguments has to be outlived by the returned reference, which is why you sometimes need explicit lifetime annotations ...
 
@@ -33,7 +33,7 @@ Matsakis and Aaron Turon gave the opening keynote on the remarkable year Rust ha
 
 There were some technical difficulties getting the projectors hooked up to the laptop for the next talk. Steve Klabnik said that the break was brought to us by Apple, who is not sponsoring us, but really wants us to have a long break between talks. "They should have written it in Rust!" I shouted (as if _someone_ had to say it); Steve shrugged.
 
-[![compiler_says_no](http://zackmdavis.net/blog/wp-content/uploads/2016/09/compiler_says_no-300x244.jpg)](http://zackmdavis.net/blog/wp-content/uploads/2016/09/compiler_says_no.jpg)
+[![compiler_says_no](http://zackmdavis.net/blog/wp-content/uploads/2016/09/compiler_says_no-300x244.jpg)](http://zackmdavis.net/blog/wp-content/uploads/2016/09/compiler_says_no.jpg){: .alignright }
 
 The projector issue got fixed and Liz Baille, developer at [Tilde](http://www.tilde.io/) and graphic-novelist, gave a really funny talk in the form of an "illustrated adventure guide" to Rust ("You might have noticed how clean and beautiful Rustlandia is, and you might have also noticed that there are no garbage cans anywhere").
 
index 7a37513d27857268865f17caf4f585779fee155a..9c96a6b6dc9355b212c95b1212b007697f5e29d9 100644 (file)
@@ -9,7 +9,7 @@ Slug: some-excuse-for-a-rustconf-2017-travelogue
 
 Wow, has it already been a year since last RustConf?—give or take the exact date of the event sliding a bit between years—and give a month-and-a-half of procrastination before being truly struck by the mounting realization that my opportunity to blog _something_ about it [before the opportunity expires](http://zackmdavis.net/blog/2016/01/ideas-have-expirations/) has almost—but crucially, not quite—faded into oblivion. And a year-and-a-quarter since [my first contribution](http://zackmdavis.net/blog/2016/06/pose/) to the compiler? I've recently moved into the top hundred contributors by commit count, because GitHub's [contributors graph page](https://github.com/rust-lang/rust/graphs/contributors) only goes down to a hundred and [my life is controlled by what things GitHub happens to provide graphs for](http://zackmdavis.net/blog/2014/02/motivation/).
 
-[![](http://zackmdavis.net/blog/wp-content/uploads/2017/10/rustconf_2017_swag-225x300.jpg)](http://zackmdavis.net/blog/wp-content/uploads/2017/10/rustconf_2017_swag.jpg)
+[![](http://zackmdavis.net/blog/wp-content/uploads/2017/10/rustconf_2017_swag-225x300.jpg)](http://zackmdavis.net/blog/wp-content/uploads/2017/10/rustconf_2017_swag.jpg){: .alignleft }
 
 So in the evening of Wednesday 15 August, I boarded the Amtrak [Coast Starlight](https://www.amtrak.com/coast-starlight-train) at Jack London Square station in Oakland for the long pilgrimage north to Portland to visit friend of the blog Sophia and attend this year's RustConf.
 
index 7096afdf4444d8f40c1fc076668dcb069ab9f2eb..c8cb43046b799234b865283245c3ba415c39a706 100644 (file)
@@ -6,4 +6,5 @@ Tags: Steven Universe
 Slug: sworn-to-the-word
 
 Ideology Makes You Stupid
+
 [![Sworn to the Word](http://zackmdavis.net/blog/wp-content/uploads/2017/02/sworn_to_the_word.png)](http://zackmdavis.net/blog/wp-content/uploads/2017/02/sworn_to_the_word.png)
index 0bb541e6783853fea871639d92364cedea59da5a..bc9dca2947981b2392b633a02041dfd0ebe36fc5 100644 (file)
@@ -5,9 +5,9 @@ Category: mathematics
 Tags: schooling
 Slug: recruitment-advertisements-for-the-2024-putnam-competition-at-san-francisco-state-university
 
-**From**: Zack M Davis \<_zmd@sfsu.edu_\>  
+**From**: Zack M Davis <_zmd@sfsu.edu_>  
 **Sent**: Wednesday, September 11, 2024 5:02 PM  
-**To**: math_majors@lists.sfsu.edu \<_math_majors@lists.sfsu.edu_\>  
+**To**: math_majors@lists.sfsu.edu <_math_majors@lists.sfsu.edu_>  
 **Subject**: Putnam prep session for eternal mathematical glory, 4 p.m. Thu 19 September  
 
 > One must make a distinction however: when dragged into prominence by half-poets, the result is not poetry, nor till the poets among us can be "literalists of the imagination"—above insolence and triviality and can present for inspection "imaginary gardens with real toads in them", shall we have it. In the meantime, if you demand on the one hand the raw material of poetry in all its rawness, and that which is on the other hand genuine, then you are interested in poetry.
@@ -32,9 +32,9 @@ To get the most out of it, try struggling with some of [the problems from the 20
 
 ----
 
-**From**: Zack M Davis \<_zmd@sfsu.edu_\>  
+**From**: Zack M Davis <_zmd@sfsu.edu_>  
 **Sent**: Sunday, September 29, 2024 11:17 PM  
-**To**: math_majors@lists.sfsu.edu \<_math_majors@lists.sfsu.edu_\>  
+**To**: math_majors@lists.sfsu.edu <_math_majors@lists.sfsu.edu_>  
 **Subject**: Putnam prep session #2 for eternal mathematical glory ... and donuts, 2 p.m. Fri 4 October  
  
 "Hey, Goofusia," said Gallantina. "Did you see this post on the math_majors list? Someone's trying to organize a team for the [Putnam competition](https://en.wikipedia.org/wiki/William_Lowell_Putnam_Mathematical_Competition)—here, at SFSU! There's going to be **a prep session in Thornton 935 on Friday at 2 p.m.** The organizer sounds really desperate—there should be **free donuts**. Want to come?"
index b9de27b85a516b0f5cd638386566f92ec144327a..82eb7b78a535e5e8fa0de0585b4e9691f2c689db 100644 (file)
@@ -5,9 +5,9 @@ Category: mathematics
 Tags: schooling
 Slug: the-end-of-the-movie-sf-state-2024-putnam-competition-team-a-retrospective
 
-**From**: Zack M Davis \<_zmd@sfsu.edu_\>  
+**From**: Zack M Davis <_zmd@sfsu.edu_>  
 **Sent**: Sunday, January 12, 2025 11:52 AM  
-**To**: math_majors@lists.sfsu.edu \<_math_majors@lists.sfsu.edu_\>, math_graduate@lists.sfsu.edu \<_math_graduate@lists.sfsu.edu_\>, math_lecturers@lists.sfsu.edu \<_math_lecturers@lists.sfsu.edu_\>, math_tenure@lists.sfsu.edu \<_math_tenure@lists.sfsu.edu_\>  
+**To**: math_majors@lists.sfsu.edu <_math_majors@lists.sfsu.edu_>, math_graduate@lists.sfsu.edu <_math_graduate@lists.sfsu.edu_>, math_lecturers@lists.sfsu.edu <_math_lecturers@lists.sfsu.edu_>, math_tenure@lists.sfsu.edu <_math_tenure@lists.sfsu.edu_>  
 **Subject**: the end of the movie: SF State's 2024 Putnam Competition team, a retrospective
 
 > Because life is a gradual series of revelations  
index f75c3f6cd6468930e55e3bca0556f27b3483bb3e..5575d0b9d89d380604c0c401268aa62f9b069513 100644 (file)
@@ -74,6 +74,22 @@ PAGINATION_PATTERNS = (
 )
 
 # Markdown extensions
+import markdown as _markdown
+
+
+class _DisableAutomailExtension(_markdown.Extension):
+    """Deregister core Markdown's automatic email-autolinking of bare <...>.
+
+    It greedily swallows any <foo@bar> as one atomic match, so writing
+    <_zmd@sfsu.edu_> for italicized email addresses in "From:"/"To:"
+    lines got mangled (underscores baked in literally, angle brackets
+    consumed) instead of becoming an <em> as intended.
+    """
+
+    def extendMarkdown(self, md):
+        md.inlinePatterns.deregister('automail')
+
+
 MARKDOWN = {
     'extension_configs': {
         'markdown.extensions.codehilite': {'css_class': 'highlight', 'guess_lang': False},
@@ -84,6 +100,7 @@ MARKDOWN = {
             'title': 'Table of Contents',
         },
     },
+    'extensions': [_DisableAutomailExtension()],
     'output_format': 'html5'
 }