The Apple Class-Action Lawsuit

To the surprise of no one
May 15, 2018

It was only a matter of time before someone wielded a class-action lawsuit and charged after Apple:

The suit alleges repeatedly that Apple “promoted and sold laptops it knew were defective in that they contain a keyboard that is substantially certain to fail prematurely,” and that selling these computers not only directly to its customers but also to third party retailers constitutes a violation of good faith. The plaintiffs are seeking damages and legal fees, and demand that Apple admit to the design flaw and cover all costs for remedying or replacing the defective computers. The full class action complaint is embedded below.

I’m shocked, shocked I tell you!

Seriously, though, on the surface, it’s hard to argue that Apple didn’t know the keyboards were a problem. They first made an appearance on the 12” MacBook, the ultra-thin one-port metal slab, a few years ago. After making their way to the MacBook Pro 13” and 15”, some tweaks were made to key travel but largely stayed the same.

The best outcome I see here is a settlement for a small handful of dollars per person. A recall won’t fix the problem unless Apple has an entirely new keyboard they can slot into place. If that’s the case, one could reasonably wonder why Apple didn’t come out and say they have a fix (that new keyboard)?

Beyond all this, though, I won’t be surprised if the whole debacle ends up being a side-note at WWDC. Apple wouldn’t admit they screwed up on a public stage like that. Jony Ive wouldn’t let that happen.

You can read the entire lawsuit here.

more about:apple / legal

Lazy-loading Retina Images in a Jekyll Site

Poppin' in them extra pixels (but only when necessary)
May 14, 2018

Something I’ve wanted to touch on ever since a couple posts ago was lazy loading images. Now that I’m trying to consciously serve 2x images for those with such a pixel density, I’m setting myself up for increased page loads and folks may never even make it that far down the page. Since there’s no need to load what one won’t see, I set out to add lazy image loading support to the blog.

This really doesn’t apply specifically to Jekyll, in fact there’s nothing about this that’s unique to Jekyll but during my searches, I initially felt I needed to find a Jekyll plugin to solve this problem. Since I had that idea, I’m certain others will, too, so I want to catch as many of those folks as I can and let them know it’s easier than that!

As far as the JavaScript goes, I’m using the vanilla-JavaScript-based lazyload.js. I just need to toss it into the footer (no point in loading it before everything else, which technically means we’re lazy-loading the lazy-loader):

<script>
  (function(w, d){
	var b = d.getElementsByTagName('body')[0];
	var s = d.createElement("script"); s.async = true;
	var v = !("IntersectionObserver" in w) ? "8.7.1" : "10.5.2";
	s.src = "https://cdnjs.cloudflare.com/ajax/libs/vanilla-lazyload/" + v + "/lazyload.min.js";
	w.lazyLoadOptions = {}; // Your options here. See "recipes" for more information about async.
	b.appendChild(s);
}(window, document));
</script>

What we’re doing here (courtesy of the lazyload.js documentation) is selecting the best version of it based on the browser. Version 8.x plays better with everything and since not all browsers support IntersectionObserver, it’s important to be backwards compatible. Version 10.x will load for Firefox, Chrome and Edge, while 8.x will load for pretty much everything else.

Now that our JavaScript is in play, the only other step is to update the image tags. I have a TextExpander snippet to help me out here, since I’m also inserting retina (@2x) images. It looks like this:

[![](){: data-src="%filltext:name=1x image%" data-srcset="%filltext:name=2x field% 2x" data-proofer-ignore}](%filltext:name=full image%){: data-lightbox="%filltext:name=lightbox tag%"}

This creates four fields, the paths to the 1x small image 2x small image, the full-size image loaded and the tag needed by lightbox.js. The finished markdown product looks like this (taken from a previous post):

[![](){: data-src="/assets/images/2018/05/07/gtmetrix-0512-sm.jpg" data-srcset="/assets/images/2018/05/07/[email protected] 2x"}](/assets/images/2018/05/07/gtmetrix-0512.jpg){: data-lightbox="image-3"}

Pretty slick, eh? With this in place, some bytes will be saved every day.

You might have noticed the data-proofer-ignore attribute. That’s to keep htmlproofer from tripping over these images because they have no src or srcset attributes defined. It’ll essentially skip them during its check. The downside is if I need to do an audit on images, I’ll have to bulk eliminate data-proofer-ignore at least temporarily.

Once this is all said and done, let the better test results come pouring in!

more about:javascript / jekyll / static sites

Easy Redirect Links Within Jekyll

These hacks are safe for all ages.
May 06, 2018

I am buttoning up the final touches on my new Jekyll-powered blog. One thing I wanted to attempt without having to spin up yet another app or service was short link redirects.

My goal was to be able to take http://johnathan.org/goto/something and have it redirect to a full URL of my choice. Jekyll is trigger happy with creating a page for everything. I knew I had to find some way to manage the data long term.

Forestry offers the ability to manage arbitrary data sets within Jekyll. Since I’m using it, I knew it was going to be a breeze so that’s the path I took.

I first started by creating a new file in the _data folder called shortlinks.yml. Anything I plug into this YAML file becomes an extension of the site object. My data file has three fields per entry: title, key, and destination. The title and destination are self-explanatory. The key is the short URL keyword. This is what we’ll use after /goto/ in the path.

Having these fields in mind, my shortlinks.yml would look something like this:

- title: A cool page
  key: coolpage
  destination: https://google.com
- title: A mediocre page
  key: mehpage
  destination: https://bing.com

This means I can now access my links under the site.shortlinks array by iterating over it. Unfortunately, we still have a bit of a roadblock. Since everything about Jekyll is static, I can’t create a dynamic page that would access the data. Wwll, I could, like something in PHP, but I don’t want to. Instead, we’ll have to use the data as a base for a set of pages we’ll create that act as redirects.

This is like how Jekyll Collections work, except we don’t want to create the pages ahead of time, only on jekyll build. This is where data_page_generator.rb comes into play. By placing it in_ _plugins and feeding it a few settings in config.yml, we can instruct it to build pages based on shortlinks.yml.

That code would look something like this:

page_gen:
  - data: shortlinks
    template: redirect
    name: key
    dir: goto

Seems easy enough. Let’s break it down. data is the data file we want to use. It makes assumptions about the file type. template directs the plugin what base template to use. What that template looks like is in the next section. name is the key from earlier. This is the file name that we create within the dir directory. In this example, the redirect files land as _site/goto/key.html_, provided the base directory is _site.

Now that we have the configuration squared away, we need to create an _includes/redirect.html template. Since we’re doing immediate redirects, it doesn’t need to be fancy, nor does it need to have style. This will do:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta http-equiv="refresh" content="0; url={{ page.destination }}" />
  <script type="text/javascript">
    window.location.href = "{{ page.destination }}"
  </script>
  <title>Redirecting...</title>
</head>
<body>
Redirecting to {{ page.destination }}. If it doesn't load, click <a href="{{ page.destination }}" />here</a>.
</body>
</html>

data_page_generator.rb will take each object in the data file and pump the values into this template. In our example, we’re only interested in destination.

With our template set, there’s one last thing we need to do.

You might need to make a tweak to convince it that /goto/something and /goto/something.html are alike and not return a `404 (dependent on your Webserver configuration). In my case with Nginx, all I had to do was swap:

location / {
    try_files $uri $uri/ =404;
}

with

location / {
    try_files $uri $uri.html $uri/ =404;
}

For those following along at home, all I added was $uri.html. What we’re doing is instructing Nginx to take the presented URI–in the case of /goto/something, the URI is something and try it against something by itself, then something.html (this is what we’ve added), and finally something/ before giving up and looking for a 404 page. If it matches something, try to render it no matter what.

Now, we can push everything and give it a go. In my real-world example, I have a couple links already set up as I write this. My new favorite air purifier/filtration system is Molekule so clicking that link will take you straight there.

Long-term, I’m uncertain about this solution’s long-term scalability. This will be fine on the scale of a few hundred links as Jekyll can turn through a few hundred pages in a matter of seconds (especially when paired with Ruby >= 2.5.x). How well this works long term will come down to a couple things:

  • The effort required to manage the data file
  • The tools in place to automate the building of the Jekyll site

For the latter, I use Circle CI so I’m fine with it taking a handful of seconds or even a half-minute longer to update. For the former, I use Forestry. I haven’t pushed it to the point where it has several hundred items in the shortlinks.yml data file. The limits of its capability are unknown in this regard.

My alternative plans were to move to Bit.ly (using a short domain of some sort) or setting up Polr on the server. I’ll have to spend some time thinking about how I can track clickthroughs. As I wrapped this up, I pondered plopping Google Analytics on the redirect page. This allows me to measure the movements into /goto pages as clicks.

I’m happy with how this turned out. Like all things I do, there’ll be persistent tweaking involved.

more about:forestry / jekyll / nginx / ruby

Hi friend. What's your email address?

...or follow the RSS feed.