Today I completed the implementation of handling code-fenced blocks (surrounded by three backticks) and "regular" text blocks. The differences between the two is that the code block can have embedded blank lines, but regular text uses blank lines to separate the paragraph blocks. For example, given this Quizdown text:
Here, line 2 is blank, meaning that the first line is a regular text paragraph. However, while line 8 is blank, it's inside of a code block, so it remains all one block up through line 11, where the code-fence ends. Then line 12 is a blank outside of a code block, so the final two lines (not separated by a blank line) are considered the third block (a paragraph).
Getting the above correct, while also handling inline markup (e.g., asterisks and underscores to bold and italicize words) was a bit tricky, but good tests helped me get it all straight.
Since one of the main goals of the Quizdown project is to easily include Java code into the questions and answer choices, I have to be able to show things inside angle brackets for generics, e.g.,
List<String>. Normally things inside angle brackets are treated as HTML tags, but I had thought that if they were inside of a
<pre> tag, they'd be shown as-is. In fact, the Mozilla docs for
pre say (emphasis mine):
<pre>element represents preformatted text which is to be presented exactly as written in the HTML file.
This isn't exactly true, as angle brackets still need to be escaped, i.e., the
< is replaced with
So, this meant I had to do HTML entity escaping on all text -- but before I turned any Quizdown into HTML (the dreaded double-encoding).
I use the Prism library and CSS to do the syntax highlighting for the Java code fragments in the quiz. When I finished processing the code-fenced blocks, which I surrounded with a
<pre>, I wasn't seeing any syntax highlighting. It turns out, that Prism has the additional requirement that any code needs to be inside of a
<code> element as well for it to highlight it. The docs need to be improved on this (and some other) areas, with better examples. I'll be looking into filing a pull-request for that.
Even though I've been doing TDD for many years, I still fall into the habit of jumping in to fix the code first instead of a test. As a reminder (to myself, if nobody else) the rule is:
Do not change code unless it is to make a failing test pass (or fail better).
By fail better, sometimes a failing test is a success if it failed as predicted and desired.
I forgot to mention in yesterday's "lessons learned" that wietlol (one of my Twitch VIP viewers) taught me how to use backreferences so that I always match underscores with underscores (e.g.,
_italic_) and stars with stars (e.g.,
**bold**) and not a mixture (e.g.,
_oops*). An example regex that uses backreferences is:
which means: first, match on either a star or underscore, then some text (with a named capture group), and then match in the same way as was matched up-front. The
?! at the end is a negative lookahead so the when I'm doing the replacement, I match against the right-most character. To see how this works, looking at the Quizdown test might be useful.
Tune in to my next live coding stream: https://Twitch.tv/jitterted.