Mac Mini + SSD = Happy. You Should Have Done This Years Ago.

It took me longer to reboot my well-out-of-Applecare 2014/2015 Mac Mini after a Monterey (OSX 12.1. Not even the upgrade to 12.2!) install than it did to:

  1. Say "f-it, this stinks."
  2. Pull a Crucial SSD drive from an unused Linux box
  3. Find my Mac-friendly tool set – it, like the alphabet, contains all the answers for the questions you might ask during this process. This Kobalt 20-Piece Kit does the trick (and more) if you can find it.
  4. Watch this video –
  5. Do the full upgrade with three brief pauses. I did not need the coat hanger trick. A few good pushes with the fingers on one hand was enough to dislodge the logic board.
  6. Cut, crimp, and run new cat6 from switch to entertainment center
  7. Run an Internet Recovery install (of Monterey)
  8. Set up two user accounts
  9. Transfer a full Photos library

As a parent with a toddler obsessed with trucks (20, to be exact), NASA and SpaceX launches, and (this month) Rush (The Professor!) concerts, the minutes saved on the reboots and youtube loading is worth its weight in gold-pressed latinum. The performance change is dramatic and the upgrade is completely worth your time.

Mark or Marc. I did not dig harder. Bless this man.

PRSAnnotationExtractor For The Sony PRS-350 In Ubuntu 18.04 (And Related) – Ruby Installs, Error Messages, And Simple Tweak

The Sony PRS-350 remains a wonderful eReader after many years (and it's cheap on eBay!) and I am pleased to report that, despite its age, some Ruby exists to extract annotations.

The trusty Sony PRS-350.

After attempts to save annotations using Kovid Goyal's tremendous Calibre with the Calibre-Annotations plug-in, it was eventually discovered that the PRS-350 annotation saving is a bit different from what later Sony readers and other current readers employ. I then stumbled upon Elie Morisse's PRSAnnotationExtractor – now eight years past any updates and written around (it seems) a later Sony Reader (at least the PRS-650, as reported for testing).

Fortunately, with the right installs in place, PRSAnnotationExtractor works just fine to process book annotations provided both the epub and the annot files are in the right place, both of which are accessible from the mounted PRS-350 device on your desktop.


  1. The process below works just fine under Ubuntu 18.04.5 LTS and should work just fine for others.
  2. The install process and associated errors from a semi-fresh Ubuntu install are included under the assumption that someone searching for how to install PRSAnnotationExtractor is getting the same errors.

Ruby Installs

Working from the requirements listed on the PRSAnnotationExtractor page, you need nokogiri, csspool, and zipruby

Install and failure of nokogiri …

user@machine:~$ sudo gem install nokogiri

Fetching: racc-1.5.2.gem (100%)
Building native extensions. This could take a while...
ERROR:  Error installing nokogiri:
	ERROR: Failed to build gem native extension.

    current directory: /var/lib/gems/2.5.0/gems/racc-1.5.2/ext/racc/cparse
/usr/bin/ruby2.5 -r ./siteconf20210719-2367-hgn9lr.rb extconf.rb
mkmf.rb can't find header files for ruby at /usr/lib/ruby/include/ruby.h

extconf failed, exit code 1

Gem files will remain installed in /var/lib/gems/2.5.0/gems/racc-1.5.2 for inspection.
Results logged to /var/lib/gems/2.5.0/extensions/x86_64-linux/2.5.0/racc-1.5.2/gem_make.out

… because you've not the necessary Ruby files installed by default (ruby2.5-dev or whatever the available version is in that range).

user@machine:~$ sudo apt-get install ruby2.5-dev 
Reading package lists... Done
Building dependency tree       
Reading state information... Done
Setting up ruby2.5-dev:amd64 (2.5.1-1ubuntu1.9) ...
Processing triggers for libc-bin (2.27-3ubuntu1.4) ...

With ruby2.5-dev installed …

user@machine:~$ sudo gem install nokogiri
Building native extensions. This could take a while...
Successfully installed racc-1.5.2
Fetching: nokogiri-1.11.7-x86_64-linux.gem (100%)
Successfully installed nokogiri-1.11.7-x86_64-linux
Parsing documentation for racc-1.5.2
Installing ri documentation for racc-1.5.2
Parsing documentation for nokogiri-1.11.7-x86_64-linux
Installing ri documentation for nokogiri-1.11.7-x86_64-linux
Done installing documentation for racc, nokogiri after 2 seconds
2 gems installed

… goes without issue, as does csspool.

user@machine:~$ sudo gem install csspool
Fetching: csspool-4.0.5.gem (100%)
Successfully installed csspool-4.0.5
Parsing documentation for csspool-4.0.5
Installing ri documentation for csspool-4.0.5
Done installing documentation for csspool after 0 seconds
1 gem installed

An initial zipruby install produced the error below …

user@machine:~$ sudo gem install zipruby
Fetching: zipruby-0.3.6.gem (100%)
Building native extensions. This could take a while...
ERROR:  Error installing zipruby:
	ERROR: Failed to build gem native extension.

    current directory: /var/lib/gems/2.5.0/gems/zipruby-0.3.6/ext
/usr/bin/ruby2.5 -r ./siteconf20210719-3294-m0tqur.rb extconf.rb
checking for zlib.h... no
*** extconf.rb failed ***
Could not create Makefile due to some reason, probably lack of necessary
libraries and/or headers.  Check the mkmf.log file for more details.  You may
need configuration options.

Provided configuration options:

To see why this extension failed to compile, please check the mkmf.log which can be found here:


extconf failed, exit code 1

Gem files will remain installed in /var/lib/gems/2.5.0/gems/zipruby-0.3.6 for inspection.
Results logged to /var/lib/gems/2.5.0/extensions/x86_64-linux/2.5.0/zipruby-0.3.6/gem_make.out

… which, upon inspection, is due to missing zlib.h.

user@machine:~$ more  /var/lib/gems/2.5.0/extensions/x86_64-linux/2.5.0/zipruby-0.3.6/mkmf.log
have_header: checking for zlib.h... -------------------- no

"gcc -o conftest -I/usr/include/x86_64-linux-gnu/ruby-2.5.0 -I/usr/include/ruby-2.5.0/ruby/backward -I/usr/include/ruby-2.5.0 -I. -Wdate-time -D_FORTIFY_SOURCE=2   -g -O2 -fdebug-prefix-map=/build/r
uby2.5-FWwz7w/ruby2.5-2.5.1=. -fstack-protector-strong -Wformat -Werror=format-security -fPIC conftest.c  -L. -L/usr/lib/x86_64-linux-gnu -L. -Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-z,now -fstack
-protector -rdynamic -Wl,-export-dynamic     -lruby-2.5  -lpthread -lgmp -ldl -lcrypt -lm   -lc"
checked program was:
/* begin */
1: #include "ruby.h"
3: int main(int argc, char **argv)
4: {
5:   return 0;
6: }
/* end */

"gcc -E -I/usr/include/x86_64-linux-gnu/ruby-2.5.0 -I/usr/include/ruby-2.5.0/ruby/backward -I/usr/include/ruby-2.5.0 -I. -Wdate-time -D_FORTIFY_SOURCE=2   -g -O2 -fdebug-prefix-map=/build/ruby2.5-FW
wz7w/ruby2.5-2.5.1=. -fstack-protector-strong -Wformat -Werror=format-security -fPIC  conftest.c -o conftest.i"
conftest.c:3:10: fatal error: zlib.h: No such file or directory
 #include <zlib.h>
compilation terminated.
checked program was:
/* begin */
1: #include "ruby.h"
3: #include <zlib.h>
/* end */


Install of zlib1g-dev solves this issue …

user@machine:~$ sudo apt install zlib1g-dev
Reading package lists... Done
Building dependency tree       
Reading state information... Done
Setting up zlib1g-dev:amd64 (1:1.2.11.dfsg-0ubuntu2) ...
Processing triggers for man-db (2.8.3-2ubuntu0.1) ...

… and zipruby now cleanly installs.

user@machine:~$ sudo gem install zipruby
Building native extensions. This could take a while...
Successfully installed zipruby-0.3.6
Parsing documentation for zipruby-0.3.6
Installing ri documentation for zipruby-0.3.6
Done installing documentation for zipruby after 0 seconds
1 gem installed


Now, with the downloaded (click the green "Code" and "Download Zip"), we expand …

user@machine:~$ unzip 
   creating: PRSAnnotationExtractor-master/
  inflating: PRSAnnotationExtractor-master/.gitignore  
  inflating: PRSAnnotationExtractor-master/prsannotextract.rb  
  inflating: PRSAnnotationExtractor-master/screenshot.png

… and confirm contents:

user@machine:~$ cd PRSAnnotationExtractor-master/
user@machine:~/PRSAnnotationExtractor-master$ ls -l
total 116
drwxrwxr-x 7 user user  4096 Oct 22  2013 csspool
-rw-rw-r-- 1 user user   488 Oct 22  2013 csspool.rb
-rw-rw-r-- 1 user user 15292 Oct 22  2013 inlineparser.rb
-rw-rw-r-- 1 user user  4028 Oct 22  2013 inlineparser.y
-rw-rw-r-- 1 user user  7066 Oct 22  2013 inlinetokenizer.rb
-rw-rw-r-- 1 user user  3661 Oct 22  2013 inlinetokenizer.rex
-rw-rw-r-- 1 user user  1079 Oct 22  2013 LICENSE
-rw-rw-r-- 1 user user  1110 Oct 22  2013 LICENSE.csspool
-rwxr-xr-x 1 user user 15905 Oct 22  2013 prsannotextract.rb
-rw-rw-r-- 1 user user  1848 Oct 22  2013
-rw-rw-r-- 1 user user 47437 Oct 22  2013 screenshot.png

Usage And Tweak

To run, you copy the .epub and .annot files for the epub into the folder containing prsannotextract.rb and:

ruby prsannotextract.rb book.epub.annot book.epub

Upon mounting the PRS-350, your book location and annotation location are:

Reader > database > media > books

Reader > Digital Editions > Annotations > database > media > books

For ease, simply copy the book and annotation files into the PRSAnnotationExtractor-master folder. That said, first execution on my sample book (out of the PRS-350-formatted .annot file) produced the following:

user@machine:~/PRSAnnotationExtractor-master$ ruby prsannotextract.rb book.epub.annot book.epub
Traceback (most recent call last):
	23: from prsannotextract.rb:535:in `<main>'
	22: from prsannotextract.rb:410:in `extract'
	21: from prsannotextract.rb:410:in `new'
	20: from /var/lib/gems/2.5.0/gems/nokogiri-1.11.7-x86_64-linux/lib/nokogiri/xml/builder.rb:296:in `initialize'
	19: from prsannotextract.rb:421:in `block in extract'
	18: from prsannotextract.rb:421:in `open'
	17: from prsannotextract.rb:428:in `block (2 levels) in extract'
	16: from /var/lib/gems/2.5.0/gems/nokogiri-1.11.7-x86_64-linux/lib/nokogiri/xml/builder.rb:378:in `method_missing'
	15: from /var/lib/gems/2.5.0/gems/nokogiri-1.11.7-x86_64-linux/lib/nokogiri/xml/builder.rb:395:in `insert'
	14: from prsannotextract.rb:443:in `block (3 levels) in extract'
	13: from /var/lib/gems/2.5.0/gems/nokogiri-1.11.7-x86_64-linux/lib/nokogiri/xml/builder.rb:378:in `method_missing'
	12: from /var/lib/gems/2.5.0/gems/nokogiri-1.11.7-x86_64-linux/lib/nokogiri/xml/builder.rb:395:in `insert'
	11: from prsannotextract.rb:446:in `block (4 levels) in extract'
	10: from /var/lib/gems/2.5.0/gems/nokogiri-1.11.7-x86_64-linux/lib/nokogiri/xml/node_set.rb:238:in `each'
	 9: from /var/lib/gems/2.5.0/gems/nokogiri-1.11.7-x86_64-linux/lib/nokogiri/xml/node_set.rb:238:in `upto'
	 8: from /var/lib/gems/2.5.0/gems/nokogiri-1.11.7-x86_64-linux/lib/nokogiri/xml/node_set.rb:239:in `block in each'
	 7: from prsannotextract.rb:449:in `block (5 levels) in extract'
	 6: from /var/lib/gems/2.5.0/gems/nokogiri-1.11.7-x86_64-linux/lib/nokogiri/xml/builder.rb:378:in `method_missing'
	 5: from /var/lib/gems/2.5.0/gems/nokogiri-1.11.7-x86_64-linux/lib/nokogiri/xml/builder.rb:395:in `insert'
	 4: from prsannotextract.rb:456:in `block (6 levels) in extract'
	 3: from /var/lib/gems/2.5.0/gems/nokogiri-1.11.7-x86_64-linux/lib/nokogiri/xml/builder.rb:378:in `method_missing'
	 2: from /var/lib/gems/2.5.0/gems/nokogiri-1.11.7-x86_64-linux/lib/nokogiri/xml/builder.rb:395:in `insert'
	 1: from prsannotextract.rb:489:in `block (7 levels) in extract'
prsannotextract.rb:349:in `wraptext': invalid byte sequence in UTF-8 (ArgumentError

This issue here, which I address without proper workup, is due to lines 349 – 351 in prsannotextract.rb – the UTF-8 error is not an error for the purposes of extracting the annotations from the PRS-350 (again, something must have changed in the PRS-650 and similar devices). Simply commenting out the block of lines (add the #'s) in a text editor …

#    if not /[^\s]/ =~ text
#      return
#    end

… yields a working annotation extraction program – which, initially, writes to the terminal.

user@machine:~/PRSAnnotationExtractor-master$ ruby prsannotextract.rb book.epub.annot book.epub
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "">
<html xmlns="">
    <meta http-equiv="content-type" content="application/xhtml+xml; charset=UTF-8"/>
        div#wrapper { margin:0 auto; background-color:#d8d880; }
        div.Annotation { margin:10px 0; border:thin dotted #080808; background-color:#f2f2ff; max-width:750px; }
        div.AnnotationTitle { margin-left:2px; }
        span.AnnotTitle { font-weight:bold; }
        span.AnnotDate { font-size:90%; color:sienna; }
        div.AnnotationBody { margin-left:8px; margin-top:3px; }
    <div class="Annotation">
      <div class="AnnotationTitle">
        <span class="AnnotTitle">Elevate</span>
        <span class="AnnotDate">2010-01-02 10:45:34</span>
      <div class="AnnotationBody">
          <span style="font-size:0.875em;">zeitgeist </span>
    <div class="Annotation">
      <div class="AnnotationTitle">
        <span class="AnnotTitle">Elevate</span>
        <span class="AnnotDate">2010-01-02 11:11:14</span>
      <div class="AnnotationBody">
          <span style="font-size:0.875em;">Annotation... </span>

Simply redirect to book.html and your annotations are visible and cleanly formatted.

ruby prsannotextract.rb book.epub.annot book.epub > book.html