Half-Elf on Tech

Thoughts From a Professional Lesbian

Category: How To

  • Bad Habits, Bad Dates

    Bad Habits, Bad Dates

    First of all, the migration of MediaWiki to Jekyll went fine. I binge watched “Person of Interest” and converted things with the clever use of grep and regex. Once I got to the point where I was converting templated files from Wiki to Jekyll, it got a lot easier. The hardest part was date conversion, and it started with some bad filenames.

    MediaWiki let me use whatever I wanted in (almost) whatever way I wanted, which is a problem. Also a problem is MediaWiki’s flat-level structure. Everything was the same level for the URLs, so you had http://example.com/wiki/NAME and, for the most part, that worked out okay. The problem I ran into was how I chose to name files.

    You see, I used the logical names “Interview Source (dd M yyyy)” for the interviews. That converted to the URL of http://example.com/wiki/Interview_Source_(dd_M_yyyy) which is nice and descriptive, if long. And it worked great right up until my subject had seven interviews on one day, two with the same source.

    Take this example. If you have an interview with the CBS morning news and the CBS evening news, on the same CBS local station, do you name the files “CBS Morning News (28 October 2015)” or “CBS News (28 October 2015)”? Obviously you have to go by the unique name (or the more unique one) to avoid name collisions. And for a time that worked out just fine. Except. I also had news articles. So if the CBS Morning News put out a news article on the same date as the interview, I was screwed. I ended up with multiple stupid filenames like “CBS Morning News (28 October 2015 b)” and so on. It was annoying.

    This could have been ‘avoided’ or at least mitigated more if I’d had used the subpage hierarchy for articles, making things http://example.com/wiki/Interview/Interview_Source_(dd_M_yyyy) and http://example.com/wiki/News/Interview_Source_(dd_M_yyyy) instead. And certainly I could have moved everything.

    But for whatever reason, subpages aren’t really super popular with MediaWiki. At least not the self-managed ones I’ve seen. They take a level of awareness that not everyone has. You can’t ‘see’ the subpages easily, not like categories with WordPress, or collections with Jekyll. And that means people just don’t use them. How do you train everyone to know how to do everything?

    Conversely, this naming issue isn’t a problem with WordPress because there has always been a clear delineation between URL and page name. This is made more-so when you use plugins like Yoast SEO, which allows you to remove ‘stopwords’ like ‘a’ and ‘the’ from your URL strings. This looks ‘wrong’ on MediaWiki, sadly, which is used to making pretty URLs that are descriptive.

    In the move to Jekyll, I renamed everything. First I made folders for each year and then I moved all files with that year in the name into the right folder. Since that muddled a few ‘extra’ files in there, I checked each file for the content {{InterviewTemplate or {{NewsTemplate and sorted them into /interviews/year/ or /news/year/ as appropriate. That was easy.

    To rename the files, I used my favorite tool Name Mangler to convert the filenames from Interview_Source_(dd_M_yyyy) to interview-source – nice and short. The ‘gotcha’ with that was, of course, multiple posts from the same source in a given year. And that was a problem because of that stupid naming convention. I would have to sort out some kind of script to rename things in bulk to convert the names into something I could then re-rename in order.

    And then I remembered something…

    'Automating' comes from the roots 'auto-' meaning 'self-', and 'mating', meaning 'screwing'.

    Not that. I remembered that the post-slug didn’t matter. It could represent the date of the post, but also possibly the order in which the posts were created. Which meant they didn’t matter in the slightest and I could batch rename.

    Furthermore, my date convention lead to a massive annoyance inside the content. Jekyll wanted my name convention to be yyyy-mm-dd and there was no really easy way to take yyyy-M-dd and convert it. There is no regex that does that. In the end, I converted dd M yyyy into yyyy-M-dd (which regex can do nicely) and then a search on all files for date: /d{2}-January-/d{4} to replace with date: /1-01-/2 and repeated for every year.

    Annoying, but it worked.

  • Bye Wiki, Hello Jekyll

    Bye Wiki, Hello Jekyll

    I’m trying to make life less messy by learning an entirely new system.

    I have a Wiki with 1000 or so pages and it’s running MediaWiki. And it’s overkill. I don’t update it often enough to need all the bells and whistles. I need it to be fast, I need it to be simple. I need it to work for one editor (hi). Oh and I need it to be secure.

    Create a Git Repository

    There’s a reason for this. My plan is to commit my changes for Jekyll to a git repo and then have it auto-copy the proper files up to the folder on my webserver. My git repository is private and on the same server owned by the same account, so I can do this. Once I had my bare git repo, I ran this in my local repository folder on my laptop:

    git clone ipstenu@example.com:/home/ipstenu/repositories/jekyll.git site-jekyll
    

    And I got a warning: warning: You appear to have cloned an empty repository.

    Which I knew. But that’s fine. I wanted it empty.

    Install Jekyll On Your Computer

    Full stop. This is where I got confused before.

    $ brew install ruby
    $ gem install jekyll
    

    That’s it. That’s how to get it started.

    Create Your Site

    I was still in that other folder, so I ran an install:

    jekyll new . --force
    

    The reason for the force was that I did have some git files in there and a readme. Then I spent a few hours trying to figure out how to write posts and pages in Jekyll. Posts are ‘easy’ in that you create a file named yyyy-mm-dd-PostName.md and it will generate a post with that name. You can read up on Writing Posts for more.

    But. I’m converting a Wiki and pretty much the whole thing is going to be ‘pages’. To be honest, Jekyll’s idea of pages are ugly. The Writing Pages directions want me to put it all in the same folder and I didn’t like that. I thought I’d rather write a mess of posts in the _posts folder and then let Jekyll generate on the fly.

    To do that was relatively easy. I set up permalinks:

    # Outputting
    permalink: "/:title"
    

    After I did that, I realized I would still have to name things that ugly way, so I added this to my _config.yaml file:

    # Pages
    include: ['_pages']
    

    Then I made a folder called _pages and put my files in there, named CSI_Crime_Scene_Investigation_(season_1).html and so on, with headers like this:

    ---
    layout: default
    title:  "CSI: Crime Scene Investigation (season 1)"
    permalink: "/CSI_Crime_Scene_Investigation_(season_1)/"
    categories: television
    tags: csi
    ---
    

    Yeah. It’s starting to make sense. I could change the permalink to ":/title/" and get the same result, where it would match the filename. But for now, the basic idea is enough.

    Themeing

    It was harder than expected. I had to convert a lot of random PHP includes into Jekyll includes (pity I can’t just say ‘include this file, yes, I know it’s PHP…). Then I wanted to add some features like a table of contents, like I had from MediaWiki, which was a little tricky. But. Once I sorted out the way you do includes and how I could do them, it was all a bit easier.

    Importing MediaWiki

    This proved to be incredibly hard. Like table flipping, teeth gnashing, up at night, wondering why the universe was created this way hard. It was so hard, I exported the wiki to XML (easy), converted that to WordPress xml via Perl (hard because of dependancies), edit all instances of <wp:post_type>wiki</wp:post_type> to be a post, import into a WordPress site (easy), and then …

    Then I spent a long time going through the import, fixing the pages, formatting things, uploading images properly, etc. The wiki I was importing was old. It happens to be the oldest part of the website it’s on, and I was using a lot of templates. In a way that was great. But in another way it was really a terrible idea because it locked me in.

    So a lot of things had to happen. First, I had to rebuild all my templates. The wonderful thing with this is that I was using a lot of templates to list things like episodes and I could convert those to yml (or csv) and then have Jekyll run a loop to display them. Once I realized that, it meant I had a lot more freedom with content.

    I ended up not importing everything. A lot of what was on that Wiki was never looked at by anyone but me, and fifteen plus years of cruft leads to a lot of messy things. Between Jekyll collections and data, I was able to break things out into sanity again. But that’s a whole post on it’s own.

    Pushing To My Server

    I’m using Git, and it’s set to auto-push when I push. But this time I did it a little different. Normally I’d run jekyll on the server, but in this case I don’t have the option so I went with adding my _site folder to the git repo (which meant editing .gitignore) and then writing this:

    #!/bin/bash -l
    GIT_REPO=$HOME/repositories/jekyll.git
    TMP_GIT_CLONE=$HOME/tmp/git/repositories
    PUBLIC_WWW=$HOME/www/jekyll
    
    git clone $GIT_REPO $TMP_GIT_CLONE
    cp -r $TMP_GIT_CLONE/_site/* $PUBLIC_WWW
    rm -Rf $TMP_GIT_CLONE
    exit
    

    This is not what I would consider a great idea. I’d rather run git on the box, but Ruby has been misbehaving there, and this actually lets me use the code on a shared box too.

  • Turning It Off And On Again

    Turning It Off And On Again

    Apple’s watchOS 2.0 came out on Monday Sept 21, and I was one of the unlucky ones who had a problem. All of the new ‘native’ apps crashed.

    If you’re unfamiliar with the concept, the original Apple Watch didn’t allow apps to really run on the watch. They ran on the phone and you had to use Bluetooth to connect for data. Now, with watchOS 2, the apps can load locally and use wifi on the Watch itself, making them faster. Exciting times for all. As I explained to my wife, all the Apple default native apps worked fine. The 3rd party ones did not. They all crashed.

    Also my battery life went to shit. So I did what one logically does. I rebooted my Watch. That didn’t help. So I went to Google and Reddit (yes, Reddit) and I dug around and found what everyone else had done to fix it:

    • Unpair and re-pair
    • restore from backup of 2.0
    • Setup as new
    • Let it sit overnight
    • Uninstall apps from phone, reboot phone and watch, reinstall apps on phone, reinstall apps on watch
    • Reinstall from my 1.0.1 backup

    None of that worked for me, so I filed a ticket with Apple support at about 7:15am. They called me back at 7:30 (which was nifty) and we discussed what I’d tried. They walked me through things, I confirmed I’d tried all of that, and detailed what I’d seen happen. Finally the woman apologized, said she didn’t know why it couldn’t work, and asked if I wanted to mail it in to Apple for a replacement.

    I didn’t. I was sure this wasn’t a hardware bug. I asked if I could take it to an Apple Store, and she said yes, making me an appointment at the store for the weekend (the earliest time) but I work .5 miles from a store so I planned to head down after lunch to have a go.

    I ended up not doing that.

    I work in tech. I’m used to troubleshooting. I went over everything I’d done. I checked and double checked that I was sure I did it right. I went back to the Reddit thread and looked to see if anything new had been posted. Sure enough, there was something. A Zen man in the MacRumors forum had an answer:

    • Doing a iphone backup with encryption of data on itunes.
    • Delete content of iphone.
    • Restore from a backup.
    • All native apps are working fine!

    While I couldn’t say that was a ‘great’ idea, I figured I had nothing left to lose. Since I always keep a spare cable for my phone and my watch in my bag, I connected them both and tried.

    And yes. It worked. Immediately I canceled the appointment with the Apple Help Gurus and started a live chat with them to explain how I fixed it. I also contacted the two app companies I’d been chatting with about it and made sure to confirm on Reddit that it worked for me. Because I will never be DenverCoder9.

    The debugging process with the Apple Watch is convoluted. I had a similar headache when I couldn’t get the WiFi working properly. I ended up having to disconnect WiFi from my phone and then re-add it for the Watch to pick it up. It’s not really the best experience, and there’s not a lot of ways to debug things.

    While I do like the Apple Watch, the black-box technology aspect of the iPhone is increased since it’s, literally, impossible to use the watch without a phone. You have to both attempt to fix things on the watch and the phone, without having a way to determine which is the broken one. And a ‘reinstall’ is not really the friendliest thing. Had I not had a handy laptop, I would have had to do an iCloud restore, which would kill my activity history (something I’d already accidentally wiped out).

    The problem comes back to meaningful error messages. All I could say was “The app crashes and kicks me back to the home screen.” Apple faces the same issues we all do with errors. How do we explain things in an informative way that allows people to react to the errors and know what to do next, when there is no way to gauge their skill set? Sadly, Apple’s route is “Take it to a professional.”

    We can’t all do that with our products, and more often than not it leads to frustration and things like ‘Bendgate,’ where people just rant and make a product seem worse when it’s really only a very small percentage of those who are impacted.

    Is there an answer? No. But it’s just one more thing to consider when we discuss elegant failures.

  • Fetch As Google Failed

    Fetch As Google Failed

    Once upon a time, I got an email from Google recently saying that Fetch as Google was failing for ipstenu.org.

    I eyed them like they had a fifth eye. I was on ipstenu.org. I was on halfelf.org. They were clearly wrong. So I went to Google Webmasters Tools and checked out what was going on. I had a whole page that said “Temporarily unreachable.” I gave it a day. Sometimes that’s just Google being weird. But no.

    Google's error - temporarily unreachable

    After cursing a little while, I turned off all the plugins on the site and switched to the default theme. And the fetch worked. So I turned them on one at a time until it stopped.

    And the moral, ladies and gentlemen, is that even though it’s been ten years of WordPress, when someone asks you to make sure you go through the normal debugging steps, you do it.

    • flushing any caching plugins you might be running, as well as server and/or browser caches.
    • deactivating all plugins (yes, all) to see if this resolves the problem. If this works, re-activate the plugins one by one until you find the problematic plugin(s). If you can’t get into your admin dashboard, try resetting the plugins folder by FTP or PhpMyAdmin (read “How to deactivate all plugins when you can’t log in to wp-admin” if you need help). Sometimes, an apparently inactive plugin can still cause problems. Also remember to deactivate any plugins in the mu-plugins folder. The easiest way is to rename that folder to mu-plugins-old
    • switching to the Twenty Fourteen theme to rule out any theme-specific problems. If you can’t log in to change themes, you can remove the theme folders via FTP so the only one is `twentyfifteen`. That will force your site to use it.
    • manually upgrading. When all else fails, download a fresh copy of the latest.zip file of WP (top right on this page) to your computer, and use that to copy up. You may need to delete the wp-admin and wp-includes folders on your server. Read the Manual Update directions first.

    So yes. Do try it.

  • Changing Git History

    Changing Git History

    Working on a group project in Git, I did the smart thing with my code. I made a branch and proceeded to edit my files. I also did a dumb thing. I made four commits.

    The first was for the first, ugly, functional version of the code. The second was a less ugly, kind of broken version. The third was the rewrite and the fourth was the working version. When I wanted to submit my changes for a review, it was going to be ugly. I did not need or want people looking at four commits They only wanted the one.

    Now I’m a weird person for how I do commits. I add a new feature like a new function to parse things, and I commit that. Then I change my CSS and commit that. And so on and so on. This means I can look through my commit history and see exactly when I made a change. When I’m ready to do my release, I document all the changes based on that commit log and have it as my message.

    But when you’re working with a team, and all they want is one clean commit? Well I’m their worst nightmare. There is a cure for this, though! You can squash your commits, merging them all into one.

    Squash

    Actually it’s rebase. It can be squash too, though. I ran the following command which says to rebase my last 4 commits:

    git rebase -i HEAD~4
    

    That opens up another editor

    pick b17617p Crap I need to do this thing!
    pick 122hdla Added feature HUMAN to autogenerate a humans.txt file
    pick nw9v88a Changed comment avatar size to 96px
    pick 8jsdy1m Updated CSS for comment avatars to make them a circle
    
    # Rebase b17617p..8jsdy1m onto b17617p
    #
    # Commands:
    #  p, pick = use commit
    #  r, reword = use commit, but edit the commit message
    #  e, edit = use commit, but stop for amending
    #  s, squash = use commit, but meld into previous commit
    #  f, fixup = like "squash", but discard this commit's log message
    #  x, exec = run command (the rest of the line) using shell
    #
    # If you remove a line here THAT COMMIT WILL BE LOST.
    # However, if you remove everything, the rebase will be aborted.
    #
    

    Now here’s where it’s weird. The first one, b17617p is the one I have to merge everything into. And it has the worst commit message, doesn’t it? Oh and I was totally not using the right formatting for how the company wants me to format my commits. They want the comment to be “Feature: Change” so I would have “Humans: Added new feature to autogenerate humans.txt”

    Since I knew I wanted to merge it all and totally rewrite the commit, I just did this:

    pick b17617p Crap I need to do this thing!
    squash 122hdla Added feature HUMAN to autogenerate a humans.txt file
    squash nw9v88a Changed comment avatar size to 96px
    squash 8jsdy1m Updated CSS for comment avatars to make them a circle
    

    Which, once saved and exited, gave me this:

    # This is a combination of 4 commits.
    # The first commit's message is:
    
    Crap I need to do this thing!
    
    # This is the 2nd commit message:
    
    Added feature HUMAN to autogenerate a humans.txt file
    
    # This is the 3rd commit message:
    
    Changed comment avatar size to 96px
    
    # This is the 4th commit message:
    
    Updated CSS for comment avatars to make them a circle
    
    # Please enter the commit message for your changes. Lines starting
    # with '#' will be ignored, and an empty message aborts the commit.
    # Explicit paths specified without -i nor -o; assuming --only paths...
    # Not currently on any branch.
    # Changes to be committed:
    #   (use "git reset HEAD <file>..." to unstage)
    #
    #	new file:   LICENSE
    #	modified:   README.textile
    #	modified:   Rakefile
    #	modified:   bin/jekyll
    #
    

    Since everything with a # is ignored, I deleted it and made it this:

    Humans: New Feature -- Humans.txt is now autogenerated
    Comments: Changed avatar size to 96px and edited CSS to make it a circle
    

    Yeah, that’s it. Admittedly, these should be two separate changes, but they’re all a part of the same project in this case so it’s okay.

    Of course, at the end of this, I looked at my code on our web tool and swore, because I’d left a debug line in. My hero Mike said “Don’t worry! ammend!”

    I made my change, instead of a normal git commit -a -m "These are my changes" I ran a git add FILENAME and git commit --ammend to fix up your most recent commit.

    It lets you combine staged changes with the previous commit instead of committing it as an entirely new snapshot. It can also be used to simply edit the previous commit message without changing its snapshot.

    And yes, it’s pretty awesome. Use it wisely.

  • Custom Excerpts Read More for Genesis

    Custom Excerpts Read More for Genesis

    I nearly always make a custom excerpt for every post I write. This has the benefit of letting my lede be extended into a great sub-headline. It has the downside of killing my ‘Read More’ links.

    The objective is simple. Have a custom excerpt and a read more link. The problem is that there are multiple excerpts and WordPress handles them all in different ways.

    1. The teaser – This is what you write in a post and end with a <!--more--> tag.
    2. The automatic excerpt – This is the first 55 words of a post.
    3. The custom excerpt – This is what you put in the ‘excerpt’ box on a post.

    Those are parsed in reverse order, so the custom excerpt is given the highest priority. That means in order to show my read-more links, I need to put this in my theme’s function.php file:

    function new_excerpt_more( $more ) {
    	return ' <a class="read-more" href="'. get_permalink( get_the_ID() ) . '">' . __('Read More', 'your-text-domain') . '</a>';
    }
    add_filter( 'excerpt_more', 'new_excerpt_more' );
    

    But. I’m using StudioPress’ Genesis theme. This means I’d like to take advantage of some of the awesome accessibility friendly features so that my read more link looks like this:

    <a href="http://example.com/cookies-and-cake" class="more-link">Read more<span class="more-link-title screen-reader-text"> about Cookies and Cake</span></a>
    

    Okay, cool. How do I do that? Back in the old days, this was how you’d edit the link for Genesis:

    //* Modify the WordPress read more link
    add_filter( 'the_content_more_link', 'sp_read_more_link' );
    function sp_read_more_link() {
    	return '<a class="more-link" href="' . get_permalink() . '">[Continue Reading]</a>';
    }
    

    As of Genesis 2.2, we’re into a world of properly accessibility friendly code, and the function get_the_content_limit() has a major change where it calls genesis_a11y_more_link and that is the function that added in the span for the screen-reader, which requires me to add in the genesis-accessibility theme support for my theme.

    // Customize the read-more links in all situations
    add_filter( 'the_content_more_link', 'sp_more_link_text' );
    add_filter( 'excerpt_more', 'sp_more_link_text' );
    
    function sp_more_link_text() {
    	return '&#x02026; <a class="more-link" href="'. get_permalink( get_the_ID() ) . '">[' . genesis_a11y_more_link( 'Continue Reading' ) . ']</a>';
    }
    

    And as far as it goes, that’s perfect. It makes sure everything matches nicely and is accessibility friendly. But it doesn’t take care of my custom excerpts. For that I need a force command:

    add_action( 'genesis_after_entry_content', 'sp_force_more', 15 );
    function sp_force_more() {
    	global $post;
    	if ( has_excerpt( $post->ID ) && !is_singular() ) {
    		echo '<p><a class="more-link" href="'. get_permalink( $post->ID ) . '">[' . genesis_a11y_more_link( 'Continue Reading' ) . ']</a></p>';
    	}
    }
    

    If there was an genesis_after_entry_excerpt sort of function to hook into, I’d be happier, but this works. It puts a [Continue Reading] paragraph at the end of each of my excerpts for my front page, my archives, and not my individual pages. This helps my readers who are, perhaps, not always as aware as they might be about where to click.