2016

Previously: 2015, 2014, 2013, 2012, 2011, 2010, 2009.

Good bye and good riddance to 2016!

Some highs:

  • My kids and my wife are amazing. My five-year-old started kindergarten and is learning to read. My almost-two-year-old went from a baby on January 1 to a sweet, talkative, out-of-control kid on December 31. My wife is most of the way through her PhD coursework. I’m very lucky.
  • I had a pretty successful year business-wise. I made more money and did some work that I found interesting and gratifying. In the next couple weeks, I’ll kick myself into gear and write about some of the client work I did in 2016, probably over on my Hard G blog.
  • I remained pretty active in the WordPress and BuddyPress projects. I managed to scale back a bit, especially as regards WordPress, when compared to 2015, but this was mostly by design, so counts as a good thing. I wrote a separate post laying out this work in 2016.

The lows? It was a rough year in so many ways. Over the last few months, I’ve reacted to the more awful parts of 2016 with a couple of changes to my routine. I guess these are kind of like “resolutions” that are already in progress.

The main theme is the idea of reclaim. I went through a period a few years ago where I attempted to take control of my digital life by moving from proprietary, third-party services to free-as-in-speech software that’s more under my control, a process I called Project Reclaim. Today, I’m focused less on technology, and more on energy and time. There are just so many hours in a day, and I’ve only got so much emotional and intellectual energy to spare. I’ve been taking steps to make sure that these resources don’t go to waste.

  • The news – I have a reflex to read the news when I have a few minutes to spare. Under normal circumstances, this habit would be a time-waster. In 2016, it’s become actively harmful to my well-being. Reading the news is something I need to brace myself for, so I’m now doing it just two or three times per day, at times I’ve set aside for information consumption. And never after 6pm! It keeps me up at night.
  • TwitterI stopped using Twitter actively a few years ago. But in 2016, I slipped into periods where I’d waste time scrolling through once or twice a day. This, despite the fact that nearly every time, I find it emotionally devestating. So, around the beginning of October, I stopped looking at the site altogether – aside from a weekly check to see if I have any mentions to respond to.
  • Magazines etc – 2016 was a Year of Thinkpieces, and I read too many of them for my own health. I’m going to mostly cut them out in 2017. Aside from other problems with the genre, I find myself disgusted with the smug slactivism that oozes from thinkpiece culture, the idea that engaging pithily with election analysis or with apocalypse porn or with red state travelogues amounts to doing something productive with your intellectual angst. I’m going to spend this energy engaging in my community instead.
  • The phone – I ditched my smartphone in 2014. After having a second kid and moving to Chicago, I caved and decided to get another smartphone late in 2015. Mainly, I wanted a convenient camera, so that I could have more pictures of my youngest. But I slowly found myself using the smartphone for other reasons, and feeling all the old awfulness creep back. Reading the news and reading Twitter and reading email are all potentially traumatic experiences, and having all those things in my pocket – even just potentially – is emotionally crippling for me. On November 10, I switched back to my dumbphone, and it felt soooo good.
  • Books – In 2015, I read 45 or 50 books. In 2016, I read maybe 10 or 15 – mostly for the reasons described above. I need to do better in 2017.
  • Separation – All year, I teetered on the edge of work-related burnout. This is partly because I treated free software contribution as “hobby”, at least in part: I spent a fair number of evenings catching up on ticket backlogs. In 2017, I’ll be more disciplined in this area, treating free software work as part of my workweek, not as something I’ll get around to if I have “free time”.

I can’t remember a January 1 where I felt so uneasy about the upcoming year. I’m reclaiming my energies and focusing them on things like my family and my community rather than letting them be exploited by the internet, a strategy that I hope will help me to make the best of 2017.

Posted in etc, year in review | Comments Off on 2016

Handling LaTeX in WordPress and React.js

I’m in the midst of building a WordPress plugin that interfaces with WeBWorK, a web application for math and science homework. The plugin features a JavaScript app powered by React and Redux, which lives inside of a WordPress page template and communicates with WP via custom API endpoints. The project is for City Tech OpenLab and it’s pretty cool. I’ll write up some more general details when it’s closer to release.

The tool is designed for use in undergraduate math courses, so LaTeX-formatted content features heavily. LaTeX is beautiful when used on its own, but it’s hard to handle in the context of web applications. A few lessons and strategies are described below.

Delimiters

I’m dealing with “mixed” content: plain text that is interspersed with LaTeX. Some of this content is coming directly from WeBWorK, which formats LaTeX to be rendered with MathJax. WeBWorK is sending markup that, when simplified, looks like this:

This is plain text.
Here is an inline equation: <script type="math/tex">E = mc^2</script>
And here is the same equation as a standalone block:
<script type="math/tex; mode=display">E = mc^2</script>

It’s also possible for users to enter LaTeX from the front-end of the WP application. In this case, we’ve settled on the verbose delimiters \begin{math} and \end{math}, but we also support a shorthand delimiter borrowed from Jetpack’s LaTeX renderer:

This is plain text.
Here is an inline equation: \begin{math}E = mc^2\end{math}
And here is the same equation as a standalone block:
$latex E = mc^2$

Some of these delimiter formats are more fragile than others, for various reasons – script tags that cannot be escaped, false positives due to use of literal dollar signs, etc – so I standardized on some invented delimiters for data storage. Before saving any LaTeX content to the database, I’m converting all delimiters to the following formats (of my own invention, which explains their Great Beauty):

This is plain text.
Here is an inline equation: {{{LATEX_DELIM_INLINE_OPEN}}}E = mc^2{{{LATEX_DELIM_INLINE_CLOSE}}}
And here is the same equation as a standalone block:
{{{LATEX_DELIM_DISPLAY_OPEN}}}E = mc^2{{{LATEX_DELIM_DISPLAY_CLOSE}}}

This way, the delimiters are unique and easy to process on display.

Slashes

I’m using WordPress custom post types to store data. The lowest-level function available for saving post data is wp_insert_post(). Thanks to a glorious accident of history, this function expects data to be “slashed”, as in addslashes() and magic quotes. If you’re looking for a fun way to spend a few hours, read through this WordPress ticket and figure out a solution, please.

LaTeX uses \ as its escape character, which makes LaTeX-formatted content look “slashed” to WordPress. As such, attempting to save chunks of LaTeX using wp_insert_post() will result in slashes being removed and formatting being lost. So I had two choices: don’t use wp_insert_post(), or don’t use slashes.

I chose the latter. Before saving any content to the database, I identify text that appears between LaTeX delimiters, and I replace all slashes with a custom character. In all its glory:

public function swap_latex_escape_characters( $text ) {
    $regex = ';(\{\{\{LATEX_DELIM_((?:DISPLAY)|(?:INLINE))_OPEN\}\}\})(.*?)(\{\{\{LATEX_DELIM_\2_CLOSE\}\}\});s';
    $text = preg_replace_callback( $regex, function( $matches ) {
        $tex = str_replace( '\\', '{{{LATEX_ESCAPE_CHARACTER}}}', $matches[3] );
        return $matches[1] . $tex . $matches[4];
    }, $text );

return $text;
}

So a chunk of LaTeX like E = \frac{mc^2}{\sqrt{1-\frac{v^2}{c^2}}} goes into the database as

E = {{{LATEX_ESCAPE_CHARACTER}}}frac{mc^2}{{{{LATEX_ESCAPE_CHARACTER}}}sqrt{1-{{{LATEX_ESCAPE_CHARACTER}}}frac{v^2}{c^2}}}

They get converted back to slashes before being served via the API endpoints.

Rendering in a React component

I decided to stick with MathJax for rendering the LaTeX. MathJax has some preprocessors that allow you to configure custom delimiters, but I had a hard time making them work inside of my larger JavaScript framework. So I decided to skip the preprocessors and generate the <script type="math/tex"> tags myself.

React escapes output pretty aggressively. This is generally a good thing. But it makes it hard to print script tags and unescaped LaTeX characters. To make it work, I needed to live dangerously. But I didn’t want to print any more raw content than necessary. So I have two components for rendering text that may contain LaTeX. Click the links for the full source code; here’s a summary of what’s going on:

  1. FormattedProblem performs a regular expression to find pieces of text that are set off by my custom delimiters. Text within delimiters gets passed to a LaTeX component. Text between LaTeX chunks becomes a span.
  2. LaTeX puts content to be formatted as LaTeX into a script tag, as expected by MathJax. Once the component is rendered by React, I then tell MathJax to queue it for (re)processing. See how updateTex() is called both in componentDidMount() and componentDidUpdate(). Getting the MathJax queue logic correct here was hard: I spent a lot of time dealing with unrendered or double-rendered TeX, as well as slow performance when a page contains dozens of LaTeX chunks.

A reminder that React’s dangerouslySetInnerHTML is dangerous. I’m running LaTeX content through WP’s esc_html() before delivering it to the endpoint. And because I control both the endpoint and the client, I can trust that the proper escaping is happening somewhere in the chain.

I use a very slightly modified technique to provide a live preview of formatted LaTeX. Here it is in action:

output

Pretty cool TeXnology, huh? ROFLMAO

Posted in JavaScript, open education, React.js, wordpress | Comments Off on Handling LaTeX in WordPress and React.js

Improved ‘equalto’ validation for Parsley.js

I’ve been playing with Parsely.js for form validation on a client project. It’s pretty nice, but I was unhappy with the ‘equalto’ implementation. ‘equalto’ allows you to link two fields whose entries should always match, such as when you have password or email confirmation fields during account registration. parsley-equalto is not symmetrical. If you enter some text into A, and enter non-matching text into B, B will not validate. If you correct B so that it matches A, then B will validate. So far, so good. But if you correct A so that it matches B, it won’t change the validation.

So I wrote a custom implementation that triggers validation on the paired field, making the link between the fields symmetrical. It’s pretty ugly (to avoid recursion) and doesn’t have any error handling, but it should point you in the right direction. (I’ve called it iff, which you can look up.)

The markup:

<input
  name="password"
  id="password"
  data-parsley-trigger="blur"
  data-parsley-iff="#password-confirm"
  data-parsley-iff-message=""
/>

<input
  name="password-confirm"
  id="password-confirm"
  data-parsley-trigger="blur"
  data-parsley-iff="#password"
  data-parsley-iff-message="Passwords must match."
/>

The validator:

var iffRecursion = false;
window.Parsley.addValidator( 'iff', {
    validateString: function( value, requirement, instance ) {
        var $partner = $( requirement );
        var isValid = $partner.val() == value;
        if ( iffRecursion ) {
            iffRecursion = false;
        } else {
            iffRecursion = true;
            $partner.parsley().validate();
        }
	return isValid;
    }
} );
Posted in JavaScript, Parsley.js | Comments Off on Improved ‘equalto’ validation for Parsley.js