Review forthcoming.
Archives for January 2019
Quickly (& Sometimes Neatly): On Jotting and Pen Preferences
I jot notes, physically, on paper, by hand, often, though I produce work predominantly through the abstraction of a computer screen. I’m notably less productive when I don’t scribble—even just a few words or fragmented incoherencies—over the course of a day. I tend to make sense of whatever faster when I scratch into matter, which isn’t quite replicated by way of the ephemeral processes of electronic journaling or noting. The act is akin to catapulting globs of stagnant, fetid goo out of the skull and onto stiff bedrock. “Here we are, thoughts: face to face. I see you, now, and you are demonstrably mine.”
We are cavemen at heart, after all, and it’s impertinent to constrain a spatial being. The keyboard is a straitjacket of sorts; it limits movement. Try to dismount. Try pirouetting away. It’s not easy. The right brain yearns to express at least slightly more than which it can computationally. (Kersplat!) So jot!
Tools of Trade
I choose to jot with pens, gel- and click-style, in particular, because they are effective and low maintenance. But there are many pens one could choose from. Too many, in fact: It’s perilously easy to lose oneself in the multitudinous aisles of online pen retailers (see: “timesuck”). I demoed about twenty pens the past couple of years because firsthand was the only way I could translate the practical scope of these objects in working contexts—and I advise readers to do the same. JetPens’ popular section (under $10) is a logical place to start. (ProTip: Use their filters.)
My formerly gross collection has been pared down to two pedestrian pens, in two categories, selected scrupulously for specific ends:
For Writing Quickly
The Pilot G2 (0.7mm) is my go-to in most circumstances. I write fastest legibly with this pen. Rapidity is mainly all I care about—fast, fast, fast; go and a minute ago. The pen doesn’t yield the most consistent lines, but I find the ink clear to read and the point satisfying to push/pull/yank across a page.
I write quickly with this pen because of how it’s balanced. I’m able to hold the pen in a way, with fulcrum (i.e., grip) distanced from the gel point, that allows minimal effort to write legible characters. The technique is similar to that of “choking down” on a baseball bat to swing with more force but less control. In this case, the ballpoint moves further with each gesture of the hand at the expense of precision.
I also use the 0.5mm G2, but in less instances, like when I’m scribbling notes while reading. Results from this pen tend to be sloppy; thinner points expose deficiencies in handwriting. I don’t particularly enjoy using the 0.5, but it’s the appropriate pen at times.
For Writing Neatly, in Small Spaces
I use a goofy, hybrid setup in these scenarios: I’m partial to the ink from the Uni-ball Signo 307 (Micro Point)—it’s grand!—but I abhor the Signo body. It’s thick and unwieldy, not unlike the jumbo crayons I scrawled with as a kid. And the clicker is a bore, no fun. But the ink!—it makes me want to attempt art. It flows smoothly and is consistently neat. I’m sure I could reproduce The Sleep of Reason… if I tried.
So: I attempted to transplant the Signo ink refill (while donning a surgical mask and scrubs) (“SCALPEL!”) into other pen bodies that I prefer, and found it’s compatible with the Zebra Sarasa Push Clip (any size). I really like the Zebra Clip. Its clip mechanism is novel and I think flat-out better than that of the average pen, whose mechanism is more susceptible to breaking and doesn’t engage with a pocket nearly as well. (I confess: I delight in clipping the Clip; I swoon when a marginally fussy, unthought task suddenly becomes a conscious cinch.)
Furthermore, the Clip is conducive to neat handwriting because there is little distance between the gel tip and where the pen is comfortable to grip in hand. It encourages the user to “choke up.” This gives way to higher precision than the G2, at the expense of speed. (Which makes sense: The faster one writes, the sloppier the handwriting. The Clip, by way of form, slows the hand down.)
Clip ink is okay—0.5mm I find to be best—but Signo ink is more reliable.
The most common use-case for me, for this Franken-pen, is addressing envelopes, which I don’t do all that often, truthfully. It sees sporadic use, now, though I wrote with it more in the past.
Uni-ball Signo 307 (Medium Point) ink is also compatible with the Clip body, but I almost always prefer to write quickly than neatly at 0.7mm size, so I seldom operate this combo.
Hastily, On Paper
When structure seems apposite, I write on cheap, yellow legal pads. Otherwise, I jot on plain, unlined computer paper (lightweight stock, high brightness, e.g., 20lb / 96 bright) to afford my thoughts abandon.
And Where to Buy
I’ve included product links above that point to Amazon. I get a small kickback if you purchase from them, which allows me to continue producing this type of content. But: The Pilot and Uni-ball can be found for the lowest price at Walmart. That’s where I buy them. The Zebra Clip is only available online (and at specialty stores, I assume); JetPens had the best price on the Clip, last I checked.
Save Jetpack “Site Stats” Pageviews as Post Meta
A website that pulls decent traffic may want to display the number of views each of its pages has gotten. This information can make a website seem more active or credible (or, generally, worthwhile perusing) than it would otherwise to a visitor. This datum can also subtly and meaningfully guide a user’s interactions with a website (i.e., a page with more views is likely worth visiting in preference to a page with less views). YouTube, for example, leverages view counts to (and which) influence whether a video may be worth watching.
WordPress doesn’t track pageviews out of the box, but Jetpack is a popular plugin, which many WordPress websites use, that does track pageviews. It does not save pageviews, however, in a way which makes this data readily available to plugin or theme developers. But it is possible to import Jetpack’s pageviews so that the data is useable. And it makes sense to piggyback off Jetpack’s stats, rather than devise a unique solution to track pageviews; such inventions are typically unstable, imprecise, or prone to bogging down performance. Holding hands with Jetpack is a pretty sure-fire solution which adds minimal overhead (and elegance, too).
How It Works / The Approach
The data that Jetpack collects is available through the WordPress.com Stats API which can be accessed with the stats_get_csv
function provided by Jetpack. This API can be called while a page is loading, i.e., before the page is displayed to the visitor (in the wp_footer
action, for example), but a better method is to call the API after the page has finished loading, via Ajax. An Ajax implementation allows the user to visit the page unimpeded—without waiting for the API request to process first, which may take a split second or two—a relative eternity in the context of the internet (where instantaneous responses are generally expected). Instead, the call happens in the background, after the page has loaded, which affords the user a better experience.
The Code (Action!)
First, load a JavaScript file to trigger an Ajax request:
This is the JavaScript file—place it in the correct path (defined by wp_enqueue_script
above):
Finally, process the Ajax request (triggered by the JavaScript above):
Combined, this code will:
- save the pageviews for each
post
- in post meta key
views
- every ~4 hours.
This data can be displayed with get_post_meta
and posts can be sorted by views
, e.g., to query for popular posts:
Hacking “days”
The WordPress.com Stats API caches requests. This is problematic for us, because it means that a page’s current view count may not be returned for our request; we could instead be provided a view count from days ago. Typically, -1
is supplied for the days
parameter, in this API call, to return “total views” (views accumulated in the past “infinite” [or all] days). However, the results from 'days' => -1
cache for an indeterminate amount of time, and thus will not always be current when requested.
To work around this, we attempt to bust the cache with each call, by requesting a page’s view count from the past X
days (instead of -1
days), where X
is a random number from 36,500 to 2,147,483,647.
The former figure I chose somewhat arbitrarily; it is roughly 100 years in days. (I figure WordPress will be history by that point.) The latter figure comes from PHP’s getrandmax
function.
This range has proven sufficient—for me, anyway—to reliably bust the Stats cache with each API request.
Use Git to Manage WordPress Projects Developed Locally on macOS
Git is a system for keeping track of changes in code. It’s particularly useful for collaboration (“Hello, world of fellow programmers!”) and reversion when a project’s source code has inadvertently ventured treacherously and irrevocably astray (fervently spamming CMD+Z is not always enough to re-establish baseline).
I obdurately refused to learn git for many years, because I am a doofus, and worked mostly solo on projects (verily to detriment). I recommend learning git, sharing code, and collaborating with others. Feedback is invaluable; you’ll get way better way faster than I did working this way.
Because I didn’t exactly hit the ground running, in terms of adapting git, I’ve typed out loose directions for personal reference—and for others whose interest is piqued and could use a guiding hand.
First: Initialize Git
- Install Xcode command line tools:
open new Terminal tab/window
xcode-select --install
(orxcode-select --reset
) (see: link) - Go through seemingly pertinent GitHub setup guides: link
- Generate SSH key (and add passphrase to keychain): link
- Add SSH key to GitHub account: link
Second: Create Origin Repository
- Visit: link
- Choose repository name and public/private (skip other options)
- Create repository
- Leave succeeding page open (it lists helpful commands and SSH URL needed below)
Third: Initialize & Commit Remote Repository to Origin
- Navigate to local, top-level project directory (e.g., WordPress theme or root):
open new Terminal window/tab
cd [Local Path]
(drag folder from Finder to Terminal to get path) - Add remote repository:
git init
git remote add origin git@github.com:[GitHub Username]/[Repository Name].git
- (Pull remote repository:)
git pull origin master
(see: link) - Create
.gitignore
file to ignore files in repository:
touch .gitignore
edit w/ text editor (see: link for guidance w/ file contents) - Add files and commit changes:
git add -A
git commit -am "[Message]"
(e.g.,git commit -am "first commit"
) - Push to remote repository:
git push -u origin master
Misc. Maintenance
- View status:
git status
- Remove .DS_Store:
find . -name .DS_Store -print0 | xargs -0 git rm -f --ignore-unmatch
(see: link)
git add -A
git commit -am "delete .DS_Store"
- Remove remote repository:
rm -rf .git
rm .gitignore
Moby-Dick
Favorite Quotes
- “[…] every stroke of his dead limb sounded like a coffin-tap.”
- “[…] cucumbers is the word.”
- “[…] I have heard hunters who declared them akin to Free-Mason signs and symbols; […]”
- “[…] his brain, if he ever had one, must have early oozed along into the muscles of his fingers.”
- “[…] he suddenly thrust out his face fiercely, snuffing up the sea air as a sagacious ship’s dog will […]”
- “The glittering mouth yawned beneath the boat like an open-doored marble tomb […]”
Good Words
- obstreperously
- farrago
- insular
- celerity
- perfidious
- pertinacious
Fix Line Height for Input Placeholders in Safari
I had a difficult, hair-twirling time (hair-twirling being a prime indicator of internalized consternation) attempting to control the vertical positioning of the placeholder attribute of a search input field, located here, in Safari. Here’s a gif to illustrate the issue:
The placeholder attribute (gray text) differed in line-height
from the value attribute (black text), so as I began to type in the field, it felt like the text was shifting down two pixels, and it was vexing. I tried redeclaring the line-height of the input, but, I assume to due wonkiness with my CSS in conjunction with Safari’s user agent stylesheet, the texts still didn’t align satisfactorily.
I subsequently resorted to fiddling with padding
, vertical-align
, and position
to no avail. Then, huzzah:
line-height: revert;
is a valid property–value combo I’d never before encountered and that appears undocumented. (I only came across it cycling through the populated values for line-height in Safari’s web inspector.) In Chrome, the placeholder assumes line-height without issue. Goofy.
Add Partner/Associates/Tracking ID/Tag to Amazon Links
Many websites link to products on Amazon, this one included, in hopes of capturing commission from Amazon’s affiliate program. In order to be credited with the sales generated through their promotional efforts, the affiliate needs to affix a tracking ID (or tag; the verbiage varies) onto their links, like so:
https://www.amazon.com/
https://www.amazon.com/?tag=adamcapr-20
Here are a couple of options to automatically tag Amazon links, within post content, with a specified tracking ID, using regular expressions.
v1: Raw
This first version will indiscriminately add a tracking tag to (or replace an existing one on) any amazon.com
URLs:
v2: Clean
This second version extracts ASINs from amazon.com/dp/
URLs, then rewrites those URLs, so that extraneous strings and parameters are stripped before adding the tracking tag. Other, non-/dp/
amazon.com
URLs will have the tracking tag assimilated in the manner above.
The advantage to implementing automation like this is that it lessens cognitive demands for precision and thus can expedite publishing processes.
Of course, it’s probably more prudent to curate Amazon short links (e.g., https://amzn.to/2Mkz6k2) which are less susceptible to the type of manipulations performed above. Web browsers and other services can more easily hijack full links, diverting revenue away from those who instituted them.
Add Fancybox Attribute to Image Links
Fancybox is my lightbox script of choice. I feel it improves the end-user’s web-browsing experience, so I use it in most projects.
To enable Fancybox on an image, it’s necessary to:
- Surround the
<img>
element with a link that points to an image file. - Add a
data-fancybox
attribute (and optional group declaration) to the link.
Typically, you’ll be including the hyperlink along with the image when you insert it through the WordPress post editor. This code will automatically add the still-needed Fancybox attribute for you:
Other lightbox scripts are enabled similarly; this code is adaptable.
Automatically Bold (or Style) the First X Words of Content
I first noticed the usage of lede styling on Wired.com, which styling, at least in Wired’s implementation, is where the first three words of a news story are styled differently that the rest of the piece, to attract the wandering eye’s attention. (“Reader: Start here!”) The concept is similar in principle to that of the drop cap, which has been used in print for centuries.
I wanted to apply similar styling to the content on my website, but I didn’t want to go through every post I’ve ever written to add the necessary HTML—a <span>
element with an arbitrary class name around the first three (or however many) words of a post. So, instead, I wrote this content filter to do it automatically:
With the markup in place, the text can be styled as so:
It will likely be possible to achieve this targeted styling with CSS alone sometime in the future—through an `::nth-word()`-esque pseudo element, without HTML markup—but for now, this solution affords an immediate response and flexibility.
The number of lede words can be controlled through a custom field—here I use the meta key _lede_words
—and I’m partial to solutions like Carbon Fields or CMB2 to assist with the selection. Here’s the corresponding metabox for Carbon Fields that I’ve created:
Note: If any of the lede words are hyperlinked, the above regex will fail. Manually add markup in those odd scenarios, or attempt to amend the code.
Move from Local macOS Development Sandbox (MAMP) to Live Production Environment
Follow these steps to move a local, MAMP development environment to a live, production environment (that has shell and WP-CLI enabled; good web hosts do). We will be using command line to achieve this end. The reason to use command line instead of graphical interfaces, like the myriad of available (S)FTP clients or phpMyAdmin, is that command line lends better performance and reliability. Graphical interfaces will time out, or seemingly take forever to load, if your files are large. There is a higher learning curve to command line—it will feel initially like yawping haphazardly into a void—but the reaped time savings make it well worth practicing.
Finalize everything in your local development environment (by adding, removing, editing, and updating plugins, themes, WordPress, content) before proceeding.
First: Back Up
- Local
wp-content
folder:
open new Terminal window/tab
cd [Local WordPress Path]
(drag WordPress folder from Finder to Terminal to get path)
mkdir -p my-wp-backups && tar -czvf wp-content-`date +%F`.tar.gz wp-content -C my-wp-backups
- Local
wp-config.php
file:
cp wp-config.php my-wp-backups/wp-config-`date +%F`.php
- Local
MySQL
database:
[Local mysqldump Path] -u [DB_USER] -p --opt [DB_NAME] > wp-database.sql
(e.g.,/Applications/MAMP/Library/bin/mysqldump
) (see localwp-config.php
file forDB_USER
,DB_NAME
, andDB_PASSWORD
)
enterDB_PASSWORD
tar -czvf wp-database-`date +%F`.sql.tar.gz wp-database.sql -C my-wp-backups
rm wp-database.sql
- Production
wp-content
folder:
open new Terminal window/tab
ssh username@example.com
(e.g.,ssh adamcap.com@adamcap.com
)
enter password
cd [Production WordPress Path]
(e.g.,cd html
)
mkdir -p my-wp-backups && tar -czvf wp-content-`date +%F`.tar.gz wp-content -C my-wp-backups
- Production
wp-config.php
file:
cp wp-config.php my-wp-backups/wp-config-`date +%F`.php
- Production
MySQL
database:
wp db export wp-database.sql
tar -czvf wp-database-`date +%F`.sql.tar.gz wp-database.sql -C my-wp-backups
rm wp-database.sql
Second: Upload wp-content
- Gzip local
wp-content
folder:
open new Terminal window/tab
cd [Local WordPress Path]
(drag WordPress folder from Finder to Terminal to get path)
mv wp-content wp-content-new && tar -czvf wp-content-new.tar.gz wp-content-new && mv wp-content-new wp-content
- Upload local
.tar.gz
file to production:
open new Terminal window/tab
scp [Local .tar.gz Path] [username@example.com]:[Production WordPress Path]
(drag.tar.gz
file from Finder to Terminal to get path) (obtain from web host; e.g.,adamcap.com@adamcap.com:/var/www/html/ad/adamcap.com
)
enter password - Unzip production
.tar.gz
file:
ssh username@example.com
(e.g.,ssh adamcap.com@adamcap.com
)
enter password
cd [Production WordPress Path]
(e.g.,cd html
)
mkdir wp-content-new && tar -xzvf wp-content-new.tar.gz -C wp-content-new --strip-components 1
- (Switch production
wp-content
folder:)
mv wp-content wp-content-old && mv wp-content-new wp-content
- (Revert production
wp-content
folder:)
mv wp-content wp-content-new && mv wp-content-old wp-content
Third: Prepare wp-config.php
- Copy production
wp-config.php
file:
open new Terminal window/tab
ssh username@example.com
(e.g.,ssh adamcap.com@adamcap.com
)
enter password
cd [Production WordPress Path]
(e.g.,cd html
)
cp wp-config.php wp-config-new.php
- Edit production
wp-config-new.php
file:
nano wp-config-new.php
UpdateDB_NAME
,DB_USER
, andDB_PASSWORD
(and verify$table_prefix
)
control + O (to save), control + X (to exit) - (Switch production
wp-config.php
file:)
mv wp-config.php wp-config-old.php && mv wp-config-new.php wp-config.php
- (Revert production
wp-config.php
file:)
mv wp-config.php wp-config-new.php && mv wp-config-old.php wp-config.php
Fourth: Move database
- Export local
MySQL
database:
open new Terminal window/tab
cd [Local WordPress Path]
(drag WordPress folder from Finder to Terminal to get path)
[Local mysqldump Path] -u [DB_USER] -p[DB_PASSWORD] --opt [DB_NAME] > wp-database-new.sql
(e.g.,/Applications/MAMP/Library/bin/mysqldump
) (see localwp-config.php
file forDB_USER
,DB_NAME
, andDB_PASSWORD
) - Gzip local
.sql
file:
tar -czvf wp-database-new.sql.tar.gz wp-database-new.sql
- Upload local
.tar.gz
file:
open new Terminal window/tab
scp [Local .tar.gz Path] [username@example.com]:[Production WordPress Path]
(drag.tar.gz
file from Finder to Terminal to get path) (obtain from web host; e.g.,adamcap.com@adamcap.com:/var/www/html/ad/adamcap.com
)
enter password - (Delete unneeded/old local files and folders:)
rm wp-content-new.tar.gz
rm wp-database-new.sql
rm wp-database-new.sql.tar.gz
- Unzip production
.tar.gz
file:
ssh [username@example.com]
(e.g.,ssh adamcap.com@adamcap.com
)
enter password
cd [Production WordPress Path]
(e.g.,cd html
)
tar -xzvf wp-database-new.sql.tar.gz
- Switch production
wp-content
folder:
mv wp-content wp-content-old && mv wp-content-new wp-content
- Switch production
wp-config.php
file:
mv wp-config.php wp-config-old.php && mv wp-config-new.php wp-config.php
(wp config shuffle-salts
) - Create new production database:
wp db drop ; wp db create
- Import production
.sql
file into production database:
wp db import wp-database-new.sql
- Search/replace production database:
wp search-replace $(wp option get siteurl) [Production Site URL]
(e.g.,wp search-replace $(wp option get siteurl) https://adamcap.com
)
(wp search-replace [Local Hostname] [Production Hostname]
)
(wp search-replace http://[Production Hostname] https://[Production Hostname]
) - (Revert production wp-content folder:)
mv wp-content wp-content-new && mv wp-content-old wp-content
- (Revert production wp-config.php file:)
mv wp-config.php wp-config-new.php && mv wp-config-old.php wp-config.php
- (Delete unneeded/old production files and folders:)
rm wp-content-new.tar.gz
rm wp-database-new.sql
rm wp-database-new.sql.tar.gz
rm -rf wp-content-old
rm wp-config-old.php
See Also
- Move from Live Production Environment to Local macOS Development Sandbox (MAMP) (coming soon)