Highlighting Liquid Template Blocks in Marked.app

For many years, I’ve used an old version of Jekyll to write this blog. For previewing, I use Marked.app, and one of the things I like about it is how you can get it to preprocess your Markdown files before processing by the markdown processor, or use a custom markdown processor altogether.

In my case, I use Liquid Templates, although the only part of them I use often are the syntax highlighting features. I have some neat TextMate language extensions so that I see the code blocks for Python, SQL and other languages syntax highlighted in the “proper” way for that code block.

Until recently, I think I had a custom markdown processor which used to apply the syntax highlighting so I saw them in Marked.app as I would in the browser after rendering using Jekyll, but that stopped working. So tonight, I wrote a small tool in python to use Pygments to apply the syntax highlighting.

There’s not much to it: it’s more glue code: it uses re.sub to switch out the highlight block with the syntax highlighted version. Something like:

import pathlib
import sys

from pygments import highlight
from pygments.lexers import get_lexer_by_name
from pygments.formatters.html import HtmlFormatter


def highlight_block(match):
    data = match.groupdict()
    formatter = HtmlFormatter(noclasses=True, linenos=False)
    lexer = get_lexer_by_name(data['language'], stripall=True)
    return highlight(data['code'], lexer, formatter)


re.sub(
  r'{% highlight (?P<language>.*?) %}\n(?P<code>.*?)\n{% endhighlight %}',
  highlight_block,
  pathlib.Path(sys.argv[1])
)

However, it is a bit slow to syntax highlight the files. It might be nice to cache them somewhere:

import pathlib

CACHE_DIR = pathlib.Path('/tmp/pygments-cache/')
CACHE_DIR.mkdir(exist_ok=True)


def highlight_block(match):
    data = match.groupdict()
    cache = CACHE_DIR / '{language}.{hash}.html'.format(
        hash=hash(data['code']),
        language=data['language'],
    )

    if cache.exists():
        return cache.open().read()

    formatter = HtmlFormatter(
        noclasses=True,
        linenos='linenos' in data
    )
    lexer = get_lexer_by_name(data['language'], stripall=True)
    output = pygments.highlight(data['code'], lexer, formatter)
    cache.open('w').write(output)
    return output

Now it doesn’t need to rebuild syntax highlighting for blocks that have already been highlighted, and the cache automatically invalidates when there are changes to the block.

This is almost the same solution I implemented as a Jekyll plugin to make that run a bunch faster: although this version does inline styles, which means I don’t have to use the same CSS from my blog.

This is packaged up into a command line tool, and installed using:

$ pipx install --spec \
        hg+https://hg.sr.ht/~schinckel/liquid-highlight \
        liquid_highlight

(or would be if sourcehut’s public urls worked).

Adding Extra MIME-types to WordPress.

(Site Admin) → Options → Mime types

File Extension/Associated mime-type.

Add mime-type »

Untitled 1

I received this in email today:

ZTMC is interested in advertising text links on schinckel.net, or other websites that you might own.

ZTMC manages a network of advertisers that range from large corporate sites to kid friendly sites.Many types of advertisers are represented in the network, with the exception of adult sites and warez (hacker/pirated software) content.Again, no warez or adult sites ads are displayed.We would like to display four links randomly on your site, ideally on every page of your site.Home page only or run of sub-section ads are also an option.Typically, the ads are placed in the footer of your site but they could also be in the header or a side bar.Payment for these ads would be upfront each month, the first month being paid once the ads are live and reviewed for proper setup.

Our monthly agreement would continue indefinitely, and we will pay you in advance based on the day of the month you began running our ads, providing your site performs as expected.

These ads are not banner ads, they are simple one line text links.You will be able to theme the links, adjusting the size and color to fit your site as you see fit, as long as they are properly visible to the users.

I hope you agree that this is an interesting way to help you grow your website and monetize your hard work.

Please contact me if this interests you.I will provide examples of these ads on existing sites and hopefully we can agree on a monthly fee that will be mutually beneficial.

Thank you for your time,

Nicole,
Marketing Manager
ZTMC, Inc.

Now, this is actually the first Spam email I’ve ever seen that might be selling a product I might be interested in. Apart from the fact that I don’t use that website anymore (although they have addressed this), and I already have an Ad system. Not that I’m really that happy with Google AdSense, but I’m close enough to actually receiving a payment after several years I can’t stand to leave.

And finally, I cannot bear to respond to a Spam email. So bad luck, Nicole, you should have chosen a more appropriate method of trying to get new business.

Spam Galore

I’ve had lots (and I mean lots) of Spam comments lately. Akismet has nabbed most of them, but a few have gotten through. And I keep having to moderate those snagged by Akismet. Tempted to try another, additional level of Spam protection.

Fuck off Yahoo! Slurp

9000 hits upon my site. Even if you factor in images, scripts, etc, there is no way there are that many pages. 207Mb downloaded by Yahoo! Slurp. I have less than 1/6 of that in data. Especially since I get less than 1% of my traffic from Yahoo! I’m fairly tempted to block their stupid crawler altogether. Fuck You, Yahoo!

Move to NearlyFreeSpeech nearly complete.

Well, I’ve moved over from Blogsome to NearlyFreeSpeech.net It’s very cool, and looks to be pretty cheap. I might have a high bandwidth bill for the last two days as I had to keep uploading SQL dump files (much faster than editing using nano over ssh!). When I imported all of my comments, the posts weren’t updated with the number of comments they each had, so I needed to run the following PHP script:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
    <?php  
    require_once('admin.php');  
    
    echo "Approving comments...";  
    
    // Approve all comments  
    
    $wpdb->query("UPDATE $wpdb->comments SET comment_approved = '1'");  
    
    echo "Updating post counts...";  
    
    // Populate comment_count field of posts table  
    
    $comments = $wpdb->get_results( "SELECT comment_post_ID, COUNT(*) as c FROM $wpdb->comments WHERE comment_approved = '1' GROUP BY comment_post_ID" );  
    
    if( is_array( $comments ) ) {  
    
    foreach ($comments as $comment) {  
    
    $wpdb->query( "UPDATE $wpdb->posts SET comment_count = $comment->c WHERE ID = '$comment->comment_post_ID'" );  
    
    }  
    
    }  
    
    echo "Done.";  
    
    ?>

Proper Web Hosting

Well, I’ve actually felt like I outgrown Blogsome for some time. Don’t get me wrong, she’s been excellent to me, but there is lots of stuff I can’t really do properly that I want. For instance, I have some serious javascript hackery going on to get the data I want displayed. Stuff that does find and replace on dates, for instance. It would be much nicer to have this all done in PHP on the server. But some of it is very cumbersome to do in Smarty Tags, which are all Blogsome allows. I also have stuff scattered across various servers. The scripts for this site, for instance live at http://scripts.schinckel.net, which is just a redirect to somewhere else. http://files.schinckel.net is also another redirect. So, I’ve considered a hosting plan. When I originally registered schinckel.net, it came with 12 months of free hosting with DreamHost (originally, it appeared to be free for life, but as soon as I realised it wasn’t, I didn’t bother using it), and I’ve looked at them for hosting this, and several other domains. From what I can understand, you can point limitless domains there, and host them all under the one account. I’ve read the terms and conditions, and from them I also think I can resell my hosting space. That is, I can be webmaster for other domains, and have them all under the one hosting plan. Their data limits are far more generous than other hosts I have come across, and they are also rather inexpensive. $9.95/month for monthly payments, which drops to $7.95/month if you pay 2 years in advance. I might set up one of these accounts, unless anyone knows of a better place to host. And by better, I mean cheaper, with similar data limits (ie, very large), whilst still fairly stable.

Technorati and...

… blogs with multiple domain names. This blog has a couple of different domain names by which it can be accessed. I would prefer it all to be schinckel.net, but it’s not possible to have Blogsome work properly if it thinks that is the domain name. I’ve got it pretty close (most of the links, for instance, point to a schinckel.net location), but since it is a multiple user system, and the way it works out which database the data should be gathered from, the domain name must end with blogsome.com. So, in one sense future-proofing myself (if Blogsome shut down, I would simply repost all of the data onto a new system, and just point schinckel.net there), and another because it’s a shorter domain, I want links to go to there instead. But, there is one bad side-effect. I use technorati for seeing incoming links, but with the setting change I talked about above, it only now picks up links coming to schinckel.net, not schinckel.net, which isn’t really good enough. Since I get more links coming to the latter than the former. So my dashboard doesn’t get to see most of the links I’m really interested in…

Show more of first post

I’ve had a good idea for a way to simplify the front page of a blog: have the newest post displayed in it’s full glory, but have other posts only have an excerpt. Actually, what I might do is make it so that is uses JavaScript, and only the post headers of other posts are shown, but clicking on the title displays the whole text…

Let Your Soul Be Your Pilot • Sting & The Police • The Very Best Of Sting & The Police ★

Gmail for schinckel.net

I have my own domain name, schinckel.net, which is registered with MyDomain.com, and has several sub-domains, which are mainly shortcuts to other sites I manage. Including this one. I also use their email forwarding service, and have it forwarded to my Gmail account. Which is pretty good, but occasionally they have a glitch, and email doesn’t get through, or is delivered late - in some cases up to a week late. This is usually not a big issue for me, as most of my email contact is not urgent (I tend not to use it for business or work purposes), however for my partner it is a real issue. Having a reliable MX server is important for her. I’ve also recently been accepted into the Gmail for Domains programme beta, and am going through the process of setting this up. I won’t create a tutorial - if you don’t know enough about how to do this, I’m not going to try to help you out for free, but I will detail some of the issues I have come across. The first account you create will be the admin account. I set this up as an admin@ address, and then decided I wanted a matt@ address also. I then deleted this, and created a pointer from matt@ to admin@. Later, I decided I would recreate the matt@ address, and use a seperate account for admin related email, even though I will have my email client check both accounts. But, I get the error:

We were unable to create matt@schinckel.net as a new account because you recently deleted an account with the same username. If you or one of your users needs to receive mail at this address, you can create matt@schinckel.net as an email list or nickname.

The Read More page then indicates:

I deleted a user, and would like to recycle the username. What are my options? There are a couple of things you can do if you’d like to recycle a deleted username.

  • Create an email list with that username immediately.
  • Wait five days, and create a new user with the deleted username.

Guess I won’t be going live for another 5 days… The other main issue I am having at the moment is with account creation. Sometimes (rarely) it works, but mostly I get the following error:

Failed to create account! Service is unavailable, please try again later

I’ve also set up a URL forwarding, so that mail.schinckel.net points at the right location on the gmail servers. This is seeming to take a while to propagate, but it will make it much easier for other users.