• Skip to primary navigation
  • Skip to main content
  • Skip to primary sidebar

Will Angley

Just another WordPress site

  • About
  • Photos
  • Words
  • Resume
  • Contact

Will Angley

Marking myself into a corner: server-side Markdown, AMP, and inline math

December 27, 2020 by Will Angley

I spoke too soon. Shortly after thinking I’d be happy in the Gutenberg editor for everything, I found that it pushed me towards not writing complicated documents effectively – it’s hard to move sentences that cross paragraph boundaries around, and hard to set information aside when it doesn’t work well – and started writing in Markdown again.

Preparing to publish one of these stories, I turned on server-side Markdown:

  1. install the Classic Editor plugin
  2. enable Markdown in Jetpack
  3. create a post in the Classic Editor.

since it’s closer to the Markdown dialects I’m familiar with than Jetpack’s Markdown block. I did some quick tests, and found that footnotes work1, but syntax highlighting and math don’t:

And then I remembered that I’d only gotten them working with syntax highlighting and MathML Gutenberg blocks. Oops.

What was I supposed to do?

Markdown code blocks output classes compatible with SyntaxHighlighter Evolved, which seems instructive: it looks like I’m meant to handle this in JavaScript.

I can’t, though, because I’m using AMP. This is by design: it’s how AMP is cacheable on third-party servers, and how it defends against XSS. I don’t get enough traffic for caching to matter but I do like having baked-in XSS defense, especially if I want to turn on comments later, and I’m hoping not to turn off AMP.

Instead, if I want to use these with server-side Markdown and AMP, I’ll need to either:

  • use alternatives to native Markdown syntax to embed these in posts, like:
    • GitHub Gists
    • Carbon images of code
    • LaTeX in Jetpack
  • render these in JavaScript on the server side. this is seldom done in WordPress, but Wikipedia has been doing this at scale with Mathoid for some time now
  • or glue together Markdown and the server-side logic I’m already using

I don’t like the way LaTeX in Jetpack renders to images – they’re blurry on the monitor I use most often for this – and I don’t want to upgrade my server in order to run Node, so I started exploring what it would take to render math here. With any luck this will be a superset of the work needed to get syntax highlighting working, too, and I’ll be able to do both quickly once I’ve done one.

Inline math is hard

The normal way of denoting math is $...$ for inline math, and $$
...
$$
for display math.

Double dollar signs are uncommon, so it’s pretty safe to use regexes to match them.

It’s just my $0.02, but I want to type single dollar signs often enough I wouldn’t want them to introduce a math context every time I use them. There are a couple ways of dealing with this:

  • Wrap them in inline code, following Yihui Xie
  • Tighten up the parser, since Marked, Pandoc and Rmarkdown don’t have this problem.

I think I’d rather tighten up the parser, since I’m already using Marked to preview Markdown on the Mac. Marked is closed source, so I can’t be sure what it does. But Pandoc is open-source, and instructive: it uses careful rules to restrict where single dollar signs introduce math contexts, and parser combinators to implement them (source).

A sketch of getting inline math working

  1. Dust off my local development environment, since it tends to bitrot.
  2. Set up a core functionality plugin for my site. Right now I’ve got this logic scattered throughout a Genesis child theme and a bunch of two or three line plugins.
  3. Port the CommonMark Math extension from Haskell to PHP. A straight port is possible, since PHP has parser combinator libraries nowadays like Parsica.
  4. Write a filter that replaces $...$ with <span class="math inline">...</span> and $$...$$ with <span class="math display">...</span>
  5. Write a filter that conditionally replaces <span class="math ..."> with the corresponding <amp-mathml> tags when AMP is enabled
  6. Wire them together in an AMP Custom Sanitizer

It seems simple enough. But I haven’t actually done any step after the first before, and recognize there are ways things could go wrong at each, or all, of the levels2. And I’ll likely need to ask for help along the way if I pick this up; it’ll be the most PHP I’ve written in a decade.

So I might as well write this down and go looking for help before things go wrong rather than after 😛


  1. and are amazing ↩
  2. “it’s in PHP” is not one of them. I’d much rather deal with this than figure out how to build photo essays from scratch in Django or Flask. ↩

Filed Under: Words

Building willangley.org, 2019–Present

November 22, 2020 by Will Angley

I didn’t take notes on how I was building willangley.org in 2019, because I was only planning to build it once; I planned to deal with things going wrong with backups, and things going right with in-place capacity upgrades.

Now it’s prompting me to upgrade, from Ubuntu 18.04 LTS to Ubuntu 20.04 LTS. It’s sometimes necessary to rebuild servers when an in place upgrade doesn’t work, so I might need to build this twice after all; restoring to before a failed upgrade is likely to bring you to a state where the upgrade will fail again ?.

This is a good reminder to figure out what I did and write it down, even if I don’t upgrade immediately.

ℹ Info

Although I’ve published my notes here, I’ve also kept a copy off the system in Bear so I can get to them if willangley.org is broken.

Development environment

I’ve been using Local to run WordPress on my machine since before I knew if I’d go live with a WordPress site, or how I’d serve it if I did.

I don’t develop PHP at work any more and lean heavily on an editor (usually either Sublime Text or Visual Studio Code) to remind me what I’m looking at, and this makes them work well.

I’ve tried to make my site portable between both my server and Local.

Server

I mostly followed the 2019 version of Hosting WordPress Yourself, with some exceptions that follow below.

Machine

willangley.org runs on a single DigitalOcean Basic droplet, with DigitalOcean backups taking weekly snapshots on the server.

PHP

I’m using PHP 7.2, since it’s packaged with Ubuntu, rather than adding a PPA to get a more modern version.

I’ve also added several extensions to PHP to get one plugin or another working. Running dpkg -l | grep php says I’ve got: php-common php-igbinary php-imagick php-intl php-pear php-redis php7.2-bcmath php7.2-cli php7.2-common php7.2-curl php7.2-dev php7.2-fpm php7.2-gd php7.2-imap php7.2-intl php7.2-json php7.2-mbstring php7.2-mysql php7.2-opcache php7.2-readline php7.2-soap php7.2-xml php7.2-xmlrpc php7.2-zip pkg-php-tools installed now, and will likely need them again on a new server too. (Some, but not all, of them are installed by the base PHP install.)

SSH

I followed the guide , set up an SSH key pair, and turned off passwords.

Since then I’ve installed Tailscale on the server, and firewalled off SSH from most of the Internet. Then Jetpack complained, so I opened up SSH back up for their IP address ranges only.

This firewall is applied at the DigitalOcean Networking level, rather than running on the droplet. It’ll apply to my new server automatically when I add it to the web-serving firewall group.

DNS

DNS for my domain lives on Google Domains, but my server lives in DigitalOcean.

In Google Domains, I have an NS record for do.willangley.org that delegates them to DigitalOcean, and I have A records for @ and www that point directly to the IP address of my server in DigitalOcean.

In DigitalOcean, I have an NS record for DigitalOcean, and an A record for the server running willangley.org.

I’d been trying to avoid troubleshooting mail forwarding for @willangley.org by moving as little as possible, because I use a @willangley.org address as a login for some services. But this split setup is seeming like a mistake in hindsight and I’ll likely back it out.

Monitoring

Is set up through the DigitalOcean agent. CPU looks good,

memory meh but probably fine.

Object Cache

I skipped using Redis initially, then came back when I installed the AMP plugin and it asked for an object cache.

I used WP Redis instead of Redis Object Cache like the tutorial recommended, because I wanted to use Redis on a Unix domain socket and Redis Object Cache doesn’t support that. Unix domain sockets mean one less thing to manage passwords and firewall rules for.

Page Cache

I set up WP Super Cache for page caching, instead of handling caching in nginx and using Nginx Cache like the tutorial recommended.

I can’t remember why I did this but it might’ve had something to do with using Local for development instead of a copy of the server.

Email

I ignored the part about sending email from a WordPress plugin. This makes a lot of sense if you’re hosting WordPress for clients, and want them to get WordPress emails and you to get system emails.

But I’m not; I want both WordPress and system emails to go to me. So I followed the Sending email with SendGrid instructions to send mail from Postfix instead.

Backups

I ignored the part about tarball backups, and signed up for Jetpack backups instead.

Since I was already planning to use other Jetpack features this made sense to me. It still largely does, although it’s never fit in super well with Local (protip: Local will create a database for you when it’s creating a site, but the .sql script that Jetpack Backups gives you expects not to have this. Drop the tables in phpMyAdmin, then run the script, and things will work cleanly) and iterating on my theme a few weeks ago didn’t seem to prompt real-time backups.

Automatic security updates

I’ve configured unattended-upgrades to perform security updates and to restart automatically. I did not request a specific reboot time, since I’d rather have brief downtime than run an old kernel for a day until the time arrives again.

Additionally, I’ve set it to use minimal steps to avoid blocking shutdown, and to mail me on upgrades.

Unattended-Upgrade::MinimalSteps "true";

Unattended-Upgrade::Mail "root";Code language: PHP (php)

This reminds me that my server is taking care of itself, and if something goes wrong I’ll hopefully have an email with the bad upgrade in my inbox before an email from Jetpack downtime monitoring telling me that things are broken.

WordPress build

I did this locally first, rather than starting with wp-cli on the server, and copied it over later. I’ve got some plugins with config settings in them, and a customized theme, that both seemed easier to develop this way than across the Internet.

The smallest Basic droplet is powerful enough to serve a pretty good amount of traffic, but Visual Studio Code Remote Development will bring it to its knees in a hurry.

I disabled comments before serving my site. This isn’t a permanent decision – I think they can add value – but I’m only going to think about enabling them if I get to blogging regularly enough I think I’ll be able to sustain a community.

Jetpack is enabled. I’m actively using Anti-Spam (on the contact form only), Backups, Brute Force Login Protection, Contact Form, Downtime Monitoring, Image Optimization, Scan, and Stats.

Automatic updates are turned for WordPress, plugins, and themes too.

Planning to build on 20.04

Now that I’ve poked at this a bit I’m pretty sure it’ll translate to the new version of Hosting WordPress Yourself, Set Up a DigitalOcean Virtual Server for WordPress on Ubuntu 20.04.

Even though 18.04 will be supported for another two and a half years, I’m hoping to go to 20.04 sooner. WordPress is already recommending PHP 7.4, and I’d rather upgrade than spend time getting backports working.

But this time I’ll write down what I’m doing so I don’t have to reverse engineer it all over again when 22.04 comes out.

Filed Under: Words

Not-running a server cost me more than running a server ever has

November 7, 2020 by Will Angley

willangley.org, and some short-lived predecessor blogs, ran without a server for about a decade total: intermittently between 2004 and 2009, and then steadily from 2014 through the middle of 2019. Most of this time was spent running as a static site with Jekyll on GitHub Pages.

I really enjoyed writing in Markdown. Sublime Text is a great Markdown editor; Marked 2 is a great Markdown previewer. You can get a lot of writing done quickly. And the environment really does make it easier to concentrate by hiding formatting controls away.

But I hit a wall almost as soon as I wanted to share something that wasn’t writing.

Hitting a wall

I’d picked up an old Pentax K1000 and started taking photos on film in 2015, and by 2018 I had several albums that my friends had enjoyed seeing in person and I wanted to share with the world.

In September 2018 I spent three days putting an image gallery on my site to share the photos for one roll of film, and was incredibly frustrated at the end.

I had no idea how to extend Jekyll, since I had never learned Ruby. I thought “well, let’s switch to something I can extend,” and knew Go, so I spent two days migrating my site to Hugo on essentially a reflex.

This was a bad decision, and although I didn’t realize it, it was documented as such at the time. I spent the third day in a tarpit of slow thumbnail rebuilds as I kludged together a {{< gallery >}} shortcode to scale my scanned photos down to thumbnails and show them as a film strip.

I checked in the images, realized I was going to run out of room in the GitHub repo that held my site if I shot a roll of film every weekend for nine months, and then put off dealing with it until spring 2019.

Searching for something better

I spent a long time looking in Spring 2019, and ran down a lot of dead ends: letting myself have ideas about things I wanted, not writing them down, trying an approach that might fulfill one idea, and then realizing I’d hedged myself out of another thing I wanted.

I talked to some very smart engineers at Google as I was looking, and it didn’t help; we’d all read the same things that had steered us wrong.

Solving my problem

I got out of this by talking to different people, who I knew from outside of work, and who made websites for a living. They used WordPress.

It was hard to get myself to try this, because it’s got tons of what Silicon Valley culture doesn’t like in a program. It’s 20 years old, complicated, made of PHP, and you need to run a server to use it. And I’d personally spent some years saying “friends don’t let friends run WordPress,” after helping recover a hacked WordPress site and move it to Squarespace.

I was wrong to repeat that. Even if I couldn’t teach someone how to run their small business from WordPress in 2014, I might be able to learn enough to run my personal website in 2019. And not trying it was feeling increasingly like a mistake of values – like not making a painting because someone might rip the canvas.

I found a guide on Hosting WordPress Yourself that looked reasonable, and it worked.

When I got stuck theming the website, I asked my friend what they did for that. I was a little surprised by their answer, so I asked at the local WordPress meetup‘s help desk, and they said the same thing: use the Genesis Framework. So I did.

That worked too. Even though I hadn’t written PHP for 10 years, I was able to finish theming my site within a day.

Retrospective

I caught up on all of the photo albums I was sitting on and then some, and my site’s been running smoothly ever since: downtime monitoring says my site’s gone down for an hour and a half of downtime in a year and a half of running, so I’m north of 99.9% uptime.

There’ve been a few kinks, mostly in the spaces I know I didn’t quite follow the guides that I was working from; now that my server is prompting me to upgrade it I need to figure out what I did, write it down, and get ready to build it again.

But even with that, not-running a server cost me more than running a server ever has.

Filed Under: Words

A bibliography for resume writing

September 6, 2020 by Will Angley

It’s easy to search for resume tips, but too many of them come back; it’s unlikely they’re all right.

So I started looking for scientific papers in the area to see if anyone had studied it systematically. Eventually the Google keywords [evidence based job search] turned up a review paper that looked useful and that I had access to:

Liu, Songqi, Jason L. Huang, and Mo Wang. 2014. “Effectiveness of Job Search Interventions: A Meta-Analytic Review.” Psychological Bulletin 140 (4): 1009–41. https://doi.org/10.1037/a0035923.

Working outwards from there, I’ve found that we’re pretty sure about:

Writing

Competency statements (Bright and Hutton, 2000) work. They work well enough that copy-pasting them into resumes meaningfully boosted how managers rated them in a systematic survey.

Length

I’ve not been able to find a decision rule for “how long should I make my resume,” but it’s increasingly seeming like the answer is “as short as possible.”

Recruiters sometimes only turned out to have shortlisted one page resumes (Lipovsky, 2014), and studies that varied design (Wilgenburg, 2017; Uskaurs, 2018) used one page resumes exclusively.

Bright and Hutton, which varied content and left design fixed, used two page resumes and a cover letter.

No one asked recruiters to look at three page resumes, presumably because the response rate would have been too poor to publish.

Design

Design risks rarely paid off when studied, although the relationship between design and outcomes is difficult to describe. Reportedly, it may depend on:

  • fashion, with (Arnulf et al., 2010) finding creative resume designs uniformly underperforming traditional ones, and later studies turning up more qualified answers
  • intelligibility, with (Lipovsky, 2014) finding recruiters selected organized resumes
  • the length of time a recruiter looks at your resume, with shorter review times favoring splashy resumes (Wilgenburg, 2017)
  • the position applied for, with creative positions favoring creative resumes, and others favoring restrained, one column layouts (ibid; Uskars, 2018)

The best we can say is there’s more evidence for investing time in writing and proofreading than in visual design. Unless you’re applying for a design position, focus on making an easy to follow resume, with one column or one column and a sidebar, and move on.

References

Arnulf, Jan Ketil, Lisa Tegner, and Øyunn Larssen. 2010. “Impression Making by Résumé Layout: Its Impact on the Probability of Being Shortlisted.” European Journal of Work and Organizational Psychology 19 (2): 221–30. https://doi.org/10.1080/13594320902903613

Azrin, N. H., T. Flores, and S. J. Kaplan. 1975. “Job-Finding Club: A Group-Assisted Program for Obtaining Employment.” Behaviour Research and Therapy 13 (1): 17–27. https://doi.org/10.1016/0005-7967(75)90048-0.

Bright, Jim E. H., and Sonia Hutton. 2000. “The Impact of Competency Statements on Résumés for Short‐listing Decisions.” International Journal of Selection and Assessment 8 (2): 41–53. https://doi.org/10.1111/1468-2389.00132.

Higgins, Chad A., and Timothy A. Judge. 2004. “The Effect of Applicant Influence Tactics on Recruiter Perceptions of Fit and Hiring Recommendations: A Field Study.” The Journal of Applied Psychology 89 (4): 622–32. https://doi.org/10.1037/0021-9010.89.4.622.

Lipovsky, Caroline. 2014. “The CV as a Multimodal Text.” Visual Communication 13 (4): 429–58. https://doi.org/10.1177/1470357213497869.

Liu, Songqi, Jason L. Huang, and Mo Wang. 2014. “Effectiveness of Job Search Interventions: A Meta-Analytic Review.” Psychological Bulletin 140 (4): 1009–41. https://doi.org/10.1037/a0035923.

Uskaurs, Matiss. 2018. “The Impact of a Resume on a Job Interview and First Impression.” Edited by Thomas Sabel. Vaasa University of Applied Sciences. https://www.semanticscholar.org/paper/834c681f76b20b6928f17f3218834c7aa5941e05.

Wilgenburg, Florence van. 2017. “The Impact of Creativity in Resume Shortlisting.” Edited by dr Ruud Koolen. Masters in Communication and Information Sciences, Tilburg University. http://arno.uvt.nl/show.cgi?fid=145069

Filed Under: Words

Incident of the day: Blackbaud

August 19, 2020 by Will Angley

Blackbaud Data Security Incident

From: blackbaudincident@wm.edu

Dear Friend of William & Mary,

We take your privacy seriously at William & Mary and value the trust you place in us when you share your personal information. We wanted to make you aware of a data security incident involving Blackbaud, Inc., a vendor of William & Mary and the William & Mary Business School Foundation that provides data processing and hosting services for advancement-related activities. Blackbaud also provides similar services to thousands of universities and nonprofits worldwide.   

Blackbaud recently notified us that it was the victim of a ransomware attack in which a bad actor removed a copy of certain backup files maintained by Blackbaud. The files contained some limited personal information of a subset of our alumni and donor population, including your personal information. 

…

It’s between the lines in this email, but Blackbaud paid the ransom. ?

Filed Under: Words Tagged With: (In)security

Word of the day: wishmagining

June 18, 2020 by Will Angley

It’s where you imagine something is true for a time, then realize you were probably just wishing for it to be true.

“I’d thought work would have started by now, but was just wishmagining it.”

The thing imagined needs to have been plausible and the stakes should be low. Wishmagining is supposed to be funny, and wishful thinking isn’t 😛

Filed Under: Words Tagged With: Word of the day

  • « Go to Previous Page
  • Page 1
  • Page 2
  • Page 3
  • Page 4
  • Page 5
  • Page 6
  • Go to Next Page »

Primary Sidebar

About the Author

Will Angley likes to take photos, and pays the bills by writing code for a big company.

By clicking submit, you agree to share your email address with the site owner and Mailchimp to receive marketing, updates, and other emails from the site owner. Use the unsubscribe link in those emails to opt out at any time.

Follow me

  • GitHub
  • Instagram
  • LinkedIn
  • RSS
  • Twitter

Top Posts

  • How I set up Tailscale on my WiFi router
  • Returning the Logitech G PRO X TKL to wired mode

Recent Posts

  • ✅ Visual glitches should be fixed now!
  • 🐞 Visual glitches on older posts
  • Make Logitech G PRO X TKL macros ready sooner
  • Returning the Logitech G PRO X TKL to wired mode
  • 🗽Statue of Liberty

Categories

  • Photos
  • Words

Copyright © 2014–2025 Will Angley · Privacy Policy · Made with ❤️ and WordPress in NYC