Title case in Drafts

Earlier this evening, I complained on Twitter about the Caps Lock function on the iOS keyboard.

Typing R.E.S.P.E.C.T. on my iPhone just now reminds me how much I hate iOS’s Caps Lock that doesn’t stay locked through punctuation.
Dr. Drang (@drdrang) Jun 24 2015 5:41 PM

The obvious solution to this problem is to train myself to always always always switch to Drafts before typing anything on my phone. If Drafts doesn’t have the transformation I want already built in, it’s usually pretty easy to add it through a JavaScript keyboard extension. And indeed, as was first pointed out to me by Tim Nahumck, there’s an UPPER keyboard extension, written by Greg Pierce himself, in the Drafts Action Directory. I now have that and the similar lower extension on my Drafts keyboard bar.

Merlin Mann pointed out another case transformation problem in iOS:

@drdrang I’d also love a secret mode for doing Title Case.
Merlin Mann (@hotdogsladies) Jun 24 2015 5:45 PM

I’m sure Merlin would prefer something universal that would work in all apps, but I don’t have that kind of power. I can, however, make a Drafts keyboard extension like Greg’s UPPER and lower extensions.

There is already in the Drafts Action Directory a keyboard extension that says it converts to title case, but it’s too naive. It capitalizes every word, which is not what title case is. Title case is actually kind of complicated. In some styles, titles are capitalized the same way sentences are—that’s what I use here at ANIAT. More common are styles like the one in an answer at the English Language Stack Exchange:

  1. Always capitalize the first and the last word.
  2. Capitalize all nouns, pronouns, adjectives, verbs, adverbs, and subordinate conjunctions (“as”, “because”, “although”, “if”, etc.).
  3. Lowercase all articles, coordinate conjunctions (“and”, “or”, “nor”), and prepositions regardless of length, when they are other than the first or last word. (Note: NIVA prefers to capitalize prepositions of five characters or more [“after”, “among”, “between”].)
  4. Lowercase the “to” in an infinitive.

John Gruber, back when he still posted scripts at Daring Fireball, wrote an excellent Perl script for converting to title case. A good chunk of it was rewritten by David Gouch and put in a GitHub repository. I mashed David’s script together with a slightly adjusted version of Greg’s UPPER script, and the result was this:

 1:  /* 
 2:    * To Title Case 2.1 – http://individed.com/code/to-title-case/
 3:    * Copyright © 2008–2013 David Gouch. Licensed under the MIT License.
 4:   */
 6:  String.prototype.toTitleCase = function(){
 7:    var smallWords = /^(a|an|and|as|at|but|by|en|for|if|in|nor|of|on|or|per|the|to|vs?\.?|via)$/i;
 9:    return this.replace(/[A-Za-z0-9\u00C0-\u00FF]+[^\s-]*/g, function(match, index, title){
10:      if (index > 0 && index + match.length !== title.length &&
11:        match.search(smallWords) > -1 && title.charAt(index - 2) !== ":" &&
12:        (title.charAt(index + match.length) !== '-' || title.charAt(index - 1) === '-') &&
13:        title.charAt(index - 1).search(/[^\s-]/) < 0) {
14:        return match.toLowerCase();
15:      }
17:      if (match.substr(1).search(/[A-Z]|\../) > -1) {
18:        return match;
19:      }
21:      return match.charAt(0).toUpperCase() + match.substr(1);
22:    });
23:  };
25:  // Addition by Dr. Drang to work as a Drafts keyboard extension.
26:  // Convert selected text to title case.
27:  var s = getSelectedText();
28:  setSelectedText(s.toTitleCase());

To save you the time and annoyance of copying and pasting the script into Drafts, I’ve posted it to the Drafts Action Directory. Go to this page in Safari on your iPhone or iPad and you’ll see a button that’ll install it directly in Drafts for you. You do have Drafts, don’t you?

Here’s what it looks like on my phone. I have the three case transformation buttons in a little cluster.

Drafts Case Buttons

You’ll note in David’s script that three of the “little words” that don’t get capitalized are the common conjuctions and, but, and or, so it’s only appropriate that I end with this:

This post is brought to you by your favorite general, General Foods.