<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Jonathan Konrath RSS Feed]]></title><description><![CDATA[Technical writing, management, documentation systems, API docs, and assorted blog posts from Jonathan Konrath.]]></description><link>http://github.com/dylang/node-rss</link><generator>GatsbyJS</generator><lastBuildDate>Sat, 09 May 2026 17:07:03 GMT</lastBuildDate><item><title><![CDATA[Site migration with Codex]]></title><description><![CDATA[It's probably time I start talking about AI, because it's fundamentally changing everything I do on a day-to-day basis as a manager and tech…]]></description><link>https://www.jonkonrath.com/2026-05-09-codex/</link><guid isPermaLink="false">https://www.jonkonrath.com/2026-05-09-codex/</guid><pubDate>Sat, 09 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;It&apos;s probably time I start talking about AI, because it&apos;s fundamentally changing everything I do on a day-to-day basis as a manager and tech writer. I&apos;ll bloviate on this from a managerial perspective at a later date, but I thought I would start with a basic example.&lt;/p&gt;
&lt;h2&gt;The problem&lt;/h2&gt;
&lt;p&gt;This blog was a Jekyll web site, doing the docs-as-code thing, taking Markdown and using a static site generator to spit this out and publish it on GitHub Pages. Good stuff, but because of life, I haven&apos;t touched it in... well, years. It happens. But almost four years have passed, which is in web-time is like if I was carving this stuff on clay tablets.&lt;/p&gt;
&lt;p&gt;I was sure there was a better approach. I mean, I&apos;ve gone through three of them at the day job, and I know there&apos;s bigger/faster/stronger out there. Also, I have no idea how many blatant security holes this thing might have, how many outdated packages knocked around, how many different ways GitHub changed their publishing process.&lt;/p&gt;
&lt;p&gt;But, I&apos;m completely out of touch with the Jekyll world. I haven&apos;t used it daily since I left TIBCO in 2021. Not only is there no muscle memory in how the site worked, but I don&apos;t know what the cool kids are doing anymore. I have a great Marketing Engineering team at work that&apos;s on the leading edge of this stuff and have the daily at-bats behind them to do this. But they don&apos;t handle my personal blog, and I&apos;ve definitely worked in places where I didn&apos;t have a dev team dedicated to my docs site.&lt;/p&gt;
&lt;h2&gt;The old way&lt;/h2&gt;
&lt;p&gt;Nobody reads this blog and there&apos;s no money involved if I mess it up. But let&apos;s say this was a docs site at a Real Company doing Real Business. How does the typical update or repair scenario usually go down?&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;I don&apos;t know how to fix it.&lt;/li&gt;
&lt;li&gt;I go to a dev group in the company. It&apos;s not their job. They have a job and it&apos;s at 400% right now.&lt;/li&gt;
&lt;li&gt;I go up the chain. A manager higher than me says, &quot;I thought you did that.&quot;&lt;/li&gt;
&lt;li&gt;I bounce around a few other dev groups. I get either &quot;how does this affect ROI?&quot; or &quot;I&apos;ve got 19 things on my roadmap that are shipping this month&quot; or &quot;That sounds like a great idea! Let&apos;s talk next month&quot; or &quot;I thought you did that.&quot;&lt;/li&gt;
&lt;li&gt;I consider hiring a contractor. Back to step 3, but &quot;how does this affect ROI? How much does this cost? Don&apos;t you have a developer? Did you ask (person from 2).&quot;&lt;/li&gt;
&lt;li&gt;Maybe if I look at ancient posts on StackOverflow I can figure this out?&lt;/li&gt;
&lt;li&gt;Goto 1.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This is not a good process. And it happens to me like once a month.&lt;/p&gt;
&lt;h2&gt;The new way&lt;/h2&gt;
&lt;p&gt;I am a &lt;a href=&quot;https://chatgpt.com/codex/&quot;&gt;Codex&lt;/a&gt; apologist. Claude Code seems to be the cool thing these days, and I use that too. But I&apos;m paying for ChatGPT here at home, so Codex it is.&lt;/p&gt;
&lt;p&gt;I fired up Codex, pointed it to my GitHub repo, and asked this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;This Jekyll site hasn&apos;t been touched in almost four years. What has changed with Jekyll that may need to be updated, and are there any package or library changes that need to be made?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Codex chewed on this for a minute, ripped through the site structure and dependencies  then proceeded to tell me exactly what had changed in the Jekyll world in the last four years. Jekyll 4.2.1 was the new hotness and I was still on 3.10.0. The theme got a bump too, and I had some customization to the theme that needed adjustment. Change those and that changes a bunch of stuff downstream, but that&apos;s all handled through the magic of the Gemfile.&lt;/p&gt;
&lt;p&gt;GitHub Pages completely changed their publishing method, and I&apos;d either have to stick to the old legacy way or move to GitHub Actions. I totally would have missed this. And I&apos;m sure many fine people work on GitHub&apos;s docs, but RTFMing this and trial-and-erroring it until it worked is a week of my life I can&apos;t spare. It was amazing that Codex told me all of this, and gave me a plan of action and the steps to take. Now I just had to make a choice on the two methods, and have Codex do the rest:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Align the migration to native github pages dependencies. Do this in a GitHub branch and open a PR&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;There was a brief stumble with getting the latest GitHub CLI running and then logging in. But otherwise, two lines, done. &lt;a href=&quot;https://github.com/jkonrath/jkonrath.github.io/pull/1&quot;&gt;It created a PR&lt;/a&gt;, I gave it a test spin, and then I merged. Flawless.&lt;/p&gt;
&lt;p&gt;I cannot emphasize enough how much of a pain it would have been for me to do this myself. Instead of asking permission and trying to explain this in meetings and getting back the wrong thing, I literally typed two lines and had &quot;someone&quot; else do the entire thing to me. If you&apos;ve been in this predicament before, you can see this is absolutely life-changing.&lt;/p&gt;
&lt;h2&gt;Bonus points: switching tools entirely&lt;/h2&gt;
&lt;p&gt;This was awesome and it worked. But let&apos;s face it, Jekyll is a bit “is the dress blue and black or white and gold?” date-wise, and I thought, &quot;Why not just move to a newer tool?&quot;&lt;/p&gt;
&lt;p&gt;I used Gatsby for years, and I liked it. I absolutely know there are newer static site generators, but Gatsby would be a good test case. So:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;This site is jekyll and I want to move it to Gatsby. I would like to change it from jekyll to Gatsby. Let&apos;s break it up into the following big tasks:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Create a branch jkgatsby and do the work there, as a PR.&lt;/li&gt;
&lt;li&gt;Any structure moves that need to be made to switch to Gatsby, including moves of configs and such.&lt;/li&gt;
&lt;li&gt;Use the gatsby starter &lt;a href=&quot;https://www.gatsbyjs.com/starters/gatsbyjs/gatsby-starter-blog/&quot;&gt;https://www.gatsbyjs.com/starters/gatsbyjs/gatsby-starter-blog/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;We still want to use .md. Do whatever you need to convert in the frontmatter. If _posts isn&apos;t the preferred directory for gatsby, feel free to move it.&lt;/li&gt;
&lt;li&gt;Build the site with a github action when anything is pushed onto main.&lt;/li&gt;
&lt;li&gt;Put a header or menu somewhere that has the about, contact, skills, and resume pages.&lt;/li&gt;
&lt;li&gt;Take the twitter reference out of the footer.&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;Codex took a few moments to sing the song of its people, and &lt;a href=&quot;https://github.com/jkonrath/jkonrath.github.io/pull/2&quot;&gt;spat out a PR&lt;/a&gt;. I had a follow-up on getting pagination going, but that was quick. I merged the PR, and had a brief GitHub Actions fail, but when I explained it and Codex looked at my config, and realized that was botched up a bit. It explained a settings change, and I did that, and it 100% worked.&lt;/p&gt;
&lt;p&gt;A few years ago, I ran into a similar-but-different &lt;a href=&quot;https://jonkonrath.com/2021/10/28/github-pages-custom-domains/&quot;&gt;GitHub problem with HTTPS configuration&lt;/a&gt;. This took &lt;em&gt;days&lt;/em&gt; of reading three different conflicting sets of docs, Googling endlessly to find other blog posts that didn&apos;t have the right answer, and way too much trial and error. This time, I asked a question, got an answer, had a complete implementation ready to review and merge. Done. Back to work.&lt;/p&gt;
&lt;p&gt;There are obvious philosophical, political, and cultural arguments about this. More on that later. But this is an absolute game-changer, and it&apos;s completely changing what it means to be a manager, now that I can manage my own AI &quot;team&quot; of developers.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[MSML]]></title><description><![CDATA[Usual apologies on me never updating this. 1239 days is a bit of a gap. So, some catch up: I went back to school for a second master's…]]></description><link>https://www.jonkonrath.com/2026/03/21/msml/</link><guid isPermaLink="false">https://www.jonkonrath.com/2026/03/21/msml/</guid><pubDate>Sat, 21 Mar 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Usual apologies on me never updating this. 1239 days is a bit of a gap.&lt;/p&gt;
&lt;p&gt;So, some catch up: I went back to school for a second master&apos;s degree in 2023. A bit about that.&lt;/p&gt;
&lt;p&gt;The MBA program I finished at WGU in 2022 overlaps the school&apos;s MS in Management and Leadership program with three classes in common. That meant I would have six classes and the capstone project to get a second degree. The basic difference between the MSML and the MBA is the MSML is more soft-skill stuff around leading teams, innovation, and strategy. The MBA is more core business school stuff like finance and accounting, plus classes on project management and a taste of the leadership stuff. I liked the MBA, but figured as a manager of people, I could probably use more leadership work in a structured way.&lt;/p&gt;
&lt;p&gt;I&apos;ll be honest: I learned a lot of good information in the MSML program, but it was nowhere near as good or as challenging as the MBA. Part of the reason I did this back-to-school thing in 2022 was I didn&apos;t want my brain to go to mush, and crossword puzzles only do so much. I also needed to challenge myself and do something hard that I didn&apos;t think I could do. Taking finance and accounting with absolutely zero background in either was a really big boulder to roll uphill. Getting past that gave me a real sense of accomplishment.&lt;/p&gt;
&lt;p&gt;The MSML? Not so much. The most challenging courses were actually deep-dives on a couple of the most tedious classes in the MBA. One of the &quot;tough&quot; classes, Business Acumen, was basically a junior version of accounting, finance, econ, and marketing rolled up into one course. Two of the harder classes, Strategic Management and Change Management, had so much overlap, the papers gave me a constant &quot;didn&apos;t I just write about this?&quot; situation. And this degree had zero math or Excel, but it had two classes that required a recorded presentation, three that involved Powerpoint, and it had a team project.&lt;/p&gt;
&lt;p&gt;So, there were two proctored tests, twelve papers total. That included the capstone, which was pretty eh. In the MBA, the capstone project was really cool. You played this simulation where you ran a business, competed against other players, and then did everything from pitch for venture cap to write a shareholder report, That was a lot of fun, to be honest. The capstone for this was an annotated bibliography of three sources per class and what we learned from them, which was mostly tedious; then a giant paper on a training plan; then a speech on that paper. A lot of the papers in this class were pure tedium. A lot of people in this program are in HR, so maybe that&apos;s the point.&lt;/p&gt;
&lt;p&gt;The one unusual thing about this degree is I ended up working on it in six different countries. I was either cramming for tests or working on papers in Iceland, England, Qatar, India, and the UAE. I particularly remember being up all night in Dubai, sitting in an airport lounge and downing as many free Diet Cokes as possible while pulling articles for that bibliography.&lt;/p&gt;
&lt;p&gt;I hate to sound bitter about the experience; I was mostly exhausted by it. I did learn a lot, although I think quantifying that is a bit out of this silo and bleeding into the Work Jon silo. But I did pick up some skills that will be useful in my career. I guess it just didn&apos;t challenge me enough. I think I really phoned it in here, and part of it was the return to office, along with the travel. I finished the degree in four months, and probably put half the effort into it that I did the year before.&lt;/p&gt;
&lt;p&gt;Another thing about this degree that was a big spoiler alert on the future: the AI situation. For the MBA in 2022, ChatGPT was not a thing yet; I think it launched the month after I graduated. But it was in full swing for the MSML in 2023, and Reddit was rampant with posts about people who were throwing the syllabus and notes into ChatGPT and asking it to write the papers for them. There were also counter-posts about how ChatGPT was making stuff up like fake citations and hallucinatory text. The school used an anti-plagiarism system for papers, but it wasn&apos;t new enough to catch ChatGPT yet. The rumor was that these systems would start using AI to detect AI though. That&apos;s a fun little arms race that has obviously ratcheted up a bit in the last three years. More on that in another post, I think.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[MBA]]></title><description><![CDATA[I would say it's time for my annual update, but it's like a year and a half now. I actually started typing this from 40,000 feet above the…]]></description><link>https://www.jonkonrath.com/2023/05/07/mba/</link><guid isPermaLink="false">https://www.jonkonrath.com/2023/05/07/mba/</guid><pubDate>Sun, 07 May 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I would say it&apos;s time for my annual update, but it&apos;s like a year and a half now.&lt;/p&gt;
&lt;p&gt;I actually started typing this from 40,000 feet above the Pacific Ocean, on my way to Maui last November, where the plan was to not think about technical writing, management, or work for seven days. I did okay with that, and feel free to bug me about my Maui restaurant list if you&apos;re headed there. Thanks to Git, I started work on this while I was on the plane. That always seems to be the example they give in Git training, right? &quot;So it&apos;s all in your local repo. If you get on a plane and aren&apos;t on the internet, you can still work.&quot; Right? Well, I never pushed my commit, and I never finished writing, so maybe it&apos;s not perfect.&lt;/p&gt;
&lt;p&gt;The big update: I completed an MBA last year. This was at Western Governors University, which has a fully-remote, proficiency-based program. It&apos;s a neat model for learning; basically, you enroll by the term, but then you finish classes as slow or as fast as you want. So instead of like enrolling in twelve credit hours for a semester, you do as many classes as you want to finish in six months.&lt;/p&gt;
&lt;p&gt;I still worked full-time (or more than full-time, really), but I type fast. I was able to finish the two-year program in about five months. I started on June 1, and my graduation date was officially October 24, although I finished my last class about a week before that.&lt;/p&gt;
&lt;p&gt;This program was an IT Management version of the MBA, so it contained a few courses specific to IT project management. But otherwise, it had all the same classes as a regular business MBA. (I think I skipped an operations management class, and a public speaking class, which was good. When I was an undergrad and had to take a speech class, I did it at 8 am in a summer session, so it was only six people.)&lt;/p&gt;
&lt;p&gt;I think the first question people ask me is, &quot;Why?&quot; I know I don&apos;t know any other tech writers with an MBA, and I have never applied for a job that required one. But I had a few thoughts about why I wanted to do this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I am a manager, and I never had any formal training as a manager. I have spent some time on Udemy watching leadership videos, and I have a whole shelf of half-read management books. But I felt like I needed something that said I was a manager, or at least something more than the few Agile crash course certification badges on my LinkedIn.&lt;/li&gt;
&lt;li&gt;I&apos;ve always vaguely wanted a graduate degree, although never knew how that would happen.&lt;/li&gt;
&lt;li&gt;I don&apos;t intend to move on to being a CTO or a PM or anything else. But I could see a future someday at some other company where another department got shoved next to the tech writing department (UX? research? QA?) and I would need to manage both. And I&apos;d like to be prepared for that.&lt;/li&gt;
&lt;li&gt;I&apos;m not starting a company. But in working at a start-up, I&apos;m constantly inundated with discussion about financing and organization and whatever, so maybe I need to know more about it.&lt;/li&gt;
&lt;li&gt;This was way outside my wheelhouse. It would be hard. And I need to do things outside my wheelhouse that are hard.&lt;/li&gt;
&lt;li&gt;It&apos;s arguably more interesting than doing crossword puzzles in my spare time to keep my brain from turning to goo.&lt;/li&gt;
&lt;/ul&gt;
&lt;br/&gt;
The basic summary of the classwork is that things fell into three buckets:
&lt;ul&gt;
&lt;li&gt;Classes that were things I do every day without thinking, or have been trained on to the point of absurdity, and I just needed to get them done quickly. There were leadership, ethics, and people management classes in which more than 50% of the content was the mandatory training I have to take every year that says you shouldn&apos;t bribe a foreign government.&lt;/li&gt;
&lt;li&gt;Classes that were interesting and fun. I took a marketing class where I had to write a marketing plan for releasing Taco Bell menu items in Japan. I also liked the IT classes, which involved things like doing a SWOT analysis for a company to pivot its IT infrastructure to the cloud.&lt;/li&gt;
&lt;li&gt;Classes that were climbing K2 without oxygen. I never took any business as an undergrad, and had to face three classes that almost ended me: accounting, finance, and econ. These were classes with math, equations, ratios, and lots and lots of raw memorization of hundreds of terms.&lt;/li&gt;
&lt;/ul&gt;
&lt;br/&gt;
&lt;p&gt;The capstone project, the big thing at the end, was a lot of fun. It basically put everything together and you had to run a business in a simulation for three quarters, competing against other people. A lot of people complained that the situation was insane, but it was honestly like playing &lt;em&gt;Roller Coaster Tycoon&lt;/em&gt; for a grade. You had to run a bicycle company and decide on everything: factories, distribution, stores, bike features, R&amp;#x26;D, marketing, everything. You had to pitch for venture cap after the first two quarters (which meant I did not avoid public speaking), and you had to write a shareholder report. It was fun making changes to see if I could increase output or sales.&lt;/p&gt;
&lt;p&gt;Overall, the degree had five proctored tests and seven papers which totaled about 190 pages. There was some PowerPoint, and far too much Excel. Almost everything else was Word.&lt;/p&gt;
&lt;p&gt;(Side note: I &lt;strong&gt;do not&lt;/strong&gt; like Excel. Even worse than using it for legitimate purposes like accounting, I am &lt;em&gt;really&lt;/em&gt; not into the standard use in tech writing, which is, &quot;Let&apos;s do a doc plan or analysis by pouring every filename into a sheet that is immediately obsolete and then putting a bunch of random checkmarks and notes and names in 17 columns, and then in a month, we will have no idea why we did this.&quot; If you&apos;re in that situation, use Jira. If you can&apos;t use Jira, use Airtable. If you can&apos;t use Airtable, you&apos;re probably wasting your time on something that doesn&apos;t matter and should stop.)&lt;/p&gt;
&lt;p&gt;The last time I wrote an academic paper, I think I had to find things in a physical card catalog and then ask a librarian to pull the microfiche for me and pay ten cents a page to photocopy the article. Everything has changed 100%. OK, I use Word (begrudgingly) and get that part. But I&apos;d never used a reference manager to track my citations, and that all magically works, without me remembering where the parenthesis go on an APA7 cite. The course was all e-books, and the papers I had to look up and cite were all online in their library. So, search &quot;Jack Welch GE leadership traits&quot; and find a result in Harvard Business Review, and there&apos;s your PDF to skim. Find what you want, and there&apos;s a link next to it with the cite. Copy and paste it exactly and you&apos;re up against a plagiarism checker that will nail you for doing that. It was all completely different than when I would pay my girlfriend&apos;s roommate to type my papers on a Brother word processor for me.&lt;/p&gt;
&lt;p&gt;So, what did I learn? I don&apos;t know how much of this applies directly to being a tech writing manager. But I think for a person living within the wheelhouse of big tech and seeing finance and business in the news, it&apos;s invaluable. Just in general, I think it&apos;s twisted my brain on how companies work. The second that Albertson&apos;s/Kroger merger was announced, I pulled 10-K reports from the SEC for both parties, drilled down to the balance sheet, and started asking my better half (the consumer packaged goods expert of the family) dozens of questions, like &quot;why does Kroger have almost two billion dollars of cash on hand during a pandemic?&quot; From a practical perspective, I think I knew a lot of the IT management stuff like budgeting and SWOT analysis, but it was nice to do it on paper, and the next time I have to do a major tooling acquisition, I know how to make it look.&lt;/p&gt;
&lt;p&gt;WGU was great, too. I love the model, and everyone I worked with was awesome. I talked my sister into going back for her Master&apos;s degree in the education school. And spoiler alert, I&apos;m actually halfway done with another degree. More on that later.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Interview question - calculating a factorial]]></title><description><![CDATA[When I was a tech writer, almost every time a developer interviewed me, they would inevitably ask me to whiteboard how to calculate the…]]></description><link>https://www.jonkonrath.com/2021/10/26/factorial/</link><guid isPermaLink="false">https://www.jonkonrath.com/2021/10/26/factorial/</guid><pubDate>Tue, 26 Oct 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;When I was a tech writer, almost every time a developer interviewed me, they would inevitably ask me to whiteboard how to calculate the factorial of a number. When I moved to Northern California in 2008 and started interviewing at various Bay Area tech firms, I was seriously asked to do this exact problem at least twelve times in interviews with three companies.&lt;/p&gt;
&lt;p&gt;I thought of this recently after reading &lt;a href=&quot;https://codingkaiser.blog/2021/10/20/most-bizzare-sorting-algorithms-you-will-ever-see/&quot;&gt;this&lt;/a&gt;, and thinking of the smart-aleck answers I never did give during interviews, like writing it in PostScript or COBOL.&lt;/p&gt;
&lt;p&gt;(BTW, a factorial is the product of all positive integers between 1 and &lt;em&gt;n&lt;/em&gt;. It&apos;s denoted as &lt;em&gt;n!&lt;/em&gt; So 4! = 1 * 2 * 3 * 4 = 24.)&lt;/p&gt;
&lt;h2&gt;Iteratively&lt;/h2&gt;
&lt;p&gt;The simple/obvious answer is doing it iteratively. In C:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;int factorial(int n)
{
  int i;
  int result=1;
  for (i=1; i&amp;lt;=n; i++){
    result = result * i;
  }
  return result;
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Extra credit:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;That should fail if you called it with a zero or a negative number.&lt;/li&gt;
&lt;li&gt;There isn&apos;t a &lt;code class=&quot;language-text&quot;&gt;main()&lt;/code&gt; that asks for a number and prints the result in a pretty way.&lt;/li&gt;
&lt;li&gt;If you want to be cute, use the assignment operator &lt;code class=&quot;language-text&quot;&gt;result *= i&lt;/code&gt; instead of &lt;code class=&quot;language-text&quot;&gt;result = result * i&lt;/code&gt; and save nine keystrokes.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;br/&gt;&lt;br/&gt;&lt;/p&gt;
&lt;h2&gt;Recursively&lt;/h2&gt;
&lt;p&gt;They won&apos;t always expect this from a writer who doesn&apos;t regularly code, but here&apos;s the other way to do it:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;int factorial(int n)
{
  if (n == 0)
    return 1;
  return n * factorial(n - 1);
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;You can make this way more incomprehensible with the ternary operator:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;int factorial(int n)
{
  return(n==1||n==0) ? 1 : n*(factorial(n-1));
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;...Other&lt;/h2&gt;
&lt;h3&gt;Scheme&lt;/h3&gt;
&lt;p&gt;I went to Indiana University at a time when the first three or four computer science classes were all taught in Scheme. I always wanted to whiteboard this as an answer:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;(define (factorial n)
  (cond ((equal? n 0) 1)
  (else (* n (factorial (- n 1))))))&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Extra credit: do it with tail recursion.&lt;/p&gt;
&lt;h3&gt;Liquid&lt;/h3&gt;
&lt;p&gt;This blog was in Jekyll, so maybe you&apos;ve worked with Liquid templates before.&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;liquid&quot;&gt;&lt;pre class=&quot;language-liquid&quot;&gt;&lt;code class=&quot;language-liquid&quot;&gt;assign n = 20
assign result = 1
for i in (1..n)
assign result = result | times i
endfor
result&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;(Note: wrap all of those in &lt;code class=&quot;language-text&quot;&gt;{%&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;%}&lt;/code&gt; except the last line, which is wrapped in double curly braces. I can&apos;t get it to delimit correctly when I put the whole thing in there and it tries to evaluate the expression.)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;REST API&lt;/h3&gt;
&lt;p&gt;APIs are the future (not speaking for my employer, of course) so maybe you want to use a REST API to do it:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;curl http://api.mathjs.org/v4/?expr=5!&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;(Why use cURL though? &lt;a href=&quot;https://www.postman.com/downloads/&quot;&gt;There&apos;s a much better way&lt;/a&gt;.)&lt;/p&gt;
&lt;h3&gt;Standard libraries&lt;/h3&gt;
&lt;p&gt;If they forget to qualify their question with &quot;don&apos;t use standard libraries&quot; you can do this (Python):&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;import math

def factorial(x):
  print (math.factorial(x))&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h3&gt;Commodore BASIC 2.0&lt;/h3&gt;
&lt;p&gt;Let&apos;s take it back to the beginning:&lt;/p&gt;
&lt;img alt=&quot;C64 BASIC factorial program&quot; src=&quot;/assets/img/c64-factorial.png&quot; /&gt;
&lt;h3&gt;SQL&lt;/h3&gt;
&lt;p&gt;I was trying to figure this out, but my SQL days are long behind me. You could use a recursive common table expression to create a table of &lt;em&gt;n&lt;/em&gt; rows with each row containing the result of the previous row multiplied by the row number... or something.&lt;/p&gt;
&lt;h3&gt;PDF&lt;/h3&gt;
&lt;p&gt;This is the point in my research where I had to give up and walk away for a bit. But if you had the right PDF CLI library, you could write a shell script that creates a one-page blank PDF, then iteratively merges copies of that template PDF onto a result PDF and count the number of pages at completion. There&apos;s some magic number limit of objects in the PDF specification so they still work on 32-bit machines -- eight million or so -- which means this would break just past the factorial of 10.&lt;/p&gt;
&lt;p&gt;Actually, a lot of these would break after about 12, when you&apos;d hit &lt;code class=&quot;language-text&quot;&gt;INT_MAX&lt;/code&gt;. There&apos;s a way to do bigger numbers by creating an array of the number of digits you want to calculate, then writing a multiply function that does all of the carrying when each spot in the array goes past 9, etc. If you really want to push it, use a linked list instead of an array so you won&apos;t waste any space. This probably won&apos;t fit on one whiteboard.&lt;/p&gt;
&lt;h3&gt;PostScript&lt;/h3&gt;
&lt;p&gt;Oh, here it is in PostScript (I don&apos;t know PostScript anymore; I borrowed it from &lt;a href=&quot;https://personal.math.ubc.ca/~cass/graphics/manual/pdf/ch9.pdf&quot;&gt;here&lt;/a&gt;...)&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;/factorial { 1 dict begin
  /n exch def
  n 0 eq {
    1
  }{
    n n 1 sub factorial mul
  } ifelse
end } def&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;(The serious answer to all of this, if you&apos;re a developer tasked with interviewing a tech writer, is to ask them about their problem-solving methodology, and how they figure things out when they don&apos;t know the answer. People who have to write a code sample every other month won&apos;t know off the top of their head how to reverse a linked list. They should be able to talk you through a difficult problem they had to solve once, though. It&apos;s probably a cross-functional review, right? Test their soft skills, not their ability to memorize. Just my opinion.)&lt;/p&gt;</content:encoded></item><item><title><![CDATA[GitHub Pages Custom Domains]]></title><description><![CDATA[I moved this site from Wordpress to GitHub pages a few months ago, and when I got to redirecting the domain, I punted and put an  file on…]]></description><link>https://www.jonkonrath.com/2021/10/28/github-pages-custom-domains/</link><guid isPermaLink="false">https://www.jonkonrath.com/2021/10/28/github-pages-custom-domains/</guid><pubDate>Tue, 26 Oct 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I moved this site from Wordpress to GitHub pages a few months ago, and when I got to redirecting the domain, I punted and put an &lt;code class=&quot;language-text&quot;&gt;.htaccess&lt;/code&gt; file on the old site and 301&apos;ed it over. That almost worked, but after each redirect happened, any old URLs were sent to &lt;code class=&quot;language-text&quot;&gt;jkonrath.github.io/&lt;/code&gt;, which broke all of my old links. I needed to properly point my hostname to the right place, and this was a bit maddening.&lt;/p&gt;
&lt;p&gt;Here&apos;s what I did to get it to work. My domain is registered at Pair Domains, and my old site was running at Pair. This assumes you have created a GitHub account and a repo for your GitHub pages stuff, and have an address like I have &lt;code class=&quot;language-text&quot;&gt;jkonrath.github.io&lt;/code&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Disclaimer: I&apos;m not an IT professional, and you could mess up everything by listening to me. You probably shouldn&apos;t listen to me about anything, let alone something involving data loss. You&apos;ve been warned.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The Pair part:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Log in to the &lt;a href=&quot;https://acc.pair.com&quot;&gt;Pair ACC&lt;/a&gt; site. Back up the old WordPress site. Don&apos;t forget to back up the database, too.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Go to &lt;strong&gt;Domains&lt;/strong&gt; and select the domain from the list.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Select &lt;strong&gt;Delete Domain From Account&lt;/strong&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I only needed to do these three things because the domain was pointed at an IP and subdirectory of another host I run there. If you only registered a domain at Pair Domains and don&apos;t host the site there, you don&apos;t have to do this.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Log in to the &lt;a href=&quot;https://www.pairdomains.com&quot;&gt;Pair Domains&lt;/a&gt; site, and select your domain name.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Go to &lt;strong&gt;Domain Address Settings&lt;/strong&gt;. This may be disabled by default; I had to accept terms and turn it on first.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If you have &lt;strong&gt;Website Forwarding&lt;/strong&gt; set, turn that off by deleting the forwarding URLs.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;From the &lt;strong&gt;Add New Record&lt;/strong&gt; dropdown list, select &lt;strong&gt;CNAME (Parking)&lt;/strong&gt;.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;In the left side under &lt;strong&gt;Alias&lt;/strong&gt;, put &lt;code class=&quot;language-text&quot;&gt;www&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;In the right, under &lt;strong&gt;Points To&lt;/strong&gt;, put &lt;code class=&quot;language-text&quot;&gt;yourusername.github.io&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Select &lt;strong&gt;Add Record&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Go back to &lt;strong&gt;Add New Record&lt;/strong&gt;, and select &lt;strong&gt;A (Round Robin)&lt;/strong&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Under &lt;strong&gt;Host Name&lt;/strong&gt;, put &lt;code class=&quot;language-text&quot;&gt;@&lt;/code&gt; and under &lt;strong&gt;IP Addresses&lt;/strong&gt;, put these four IP numbers:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;185.199.108.153
185.199.109.153
185.199.110.153
185.199.111.153&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Select &lt;strong&gt;Add Record&lt;/strong&gt;. You will now have a CNAME for www pointing to your GitHub Pages domain, and four A records pointing to the IP addresses above.&lt;br/&gt;&lt;br/&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Double-check this nine times. The CNAME is &lt;code class=&quot;language-text&quot;&gt;www &gt;&gt; yourusername.github.io&lt;/code&gt; and there are four A records that are &lt;code class=&quot;language-text&quot;&gt;@ &gt;&gt; 185.199.x.y&lt;/code&gt; If you get the &lt;code class=&quot;language-text&quot;&gt;www&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;@&lt;/code&gt; backwards, this won&apos;t work.&lt;/p&gt;
&lt;p&gt;After you do this, you have to wait. It could be a minute; it could be a day. A good way to test it is &lt;a href=&quot;https://www.whatsmydns.net&quot;&gt;whatsmydns.net&lt;/a&gt;, which shows how your changes have propagated around the world.&lt;/p&gt;
&lt;p&gt;Once that sorts itself out:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Go to GitHub, and open the repo for your blog.&lt;/li&gt;
&lt;li&gt;Select &lt;strong&gt;Settings&lt;/strong&gt;, then &lt;strong&gt;Pages&lt;/strong&gt;. It will say your page is being hosted at &lt;code class=&quot;language-text&quot;&gt;yourusername.github.io&lt;/code&gt;. If it isn&apos;t, you&apos;ve got bigger problems. Sort those out first.&lt;/li&gt;
&lt;li&gt;Under &lt;strong&gt;Custom Domain&lt;/strong&gt;, enter the custom domain and select &lt;strong&gt;Save&lt;/strong&gt;. You&apos;re putting in &lt;code class=&quot;language-text&quot;&gt;www.my-host-name.com&lt;/code&gt;. There&apos;s no protocol in front of it (&lt;code class=&quot;language-text&quot;&gt;http://&lt;/code&gt;) but don&apos;t forget the &lt;a href=&quot;http://www&quot;&gt;www&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;This will churn away and check the DNS for you. It will also kick off a request to Let&apos;s Encrypt to make a certificate for free. You &lt;em&gt;do not&lt;/em&gt; have to pay for anything at Pair or do any other legwork to get this done. The catch is that if you messed up the first part, or if GitHub&apos;s feeling grumpy, that creation step will get botched, and you won&apos;t get any helpful information, except it won&apos;t work.&lt;/li&gt;
&lt;li&gt;Leave it alone for an hour or a day, and then you can select &lt;strong&gt;Enforce HTTPS&lt;/strong&gt; and it will (eventually) enable HTTPS.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;On the last step: it may give you a byzantine error message, like &quot;Unavailable for your site because a certificate has not yet been issued for your domain.&quot; If that happens:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Make sure your CNAME and A records on Pair Domains are correct.&lt;/li&gt;
&lt;li&gt;Wait a bit.&lt;/li&gt;
&lt;li&gt;Under &lt;strong&gt;Custom Domain&lt;/strong&gt; in the GitHub Pages config, select &lt;strong&gt;Remove&lt;/strong&gt;, then add it again. This will redo the request for a new certificate. Or not. I think I did it five times before it took.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;You may need to clear your browser cache or wait a bit more until this works, but test it with and without HTTPS and &lt;a href=&quot;http://www&quot;&gt;www&lt;/a&gt;.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Atom as a Markdown Editor]]></title><description><![CDATA[(Update: nope. I've since switched to VSC, so looks like you should too. I'll leave this here for nostalgia purposes.) Part of this switch…]]></description><link>https://www.jonkonrath.com/2021/10/19/atom-for-markdown/</link><guid isPermaLink="false">https://www.jonkonrath.com/2021/10/19/atom-for-markdown/</guid><pubDate>Tue, 19 Oct 2021 00:00:00 GMT</pubDate><content:encoded>&lt;blockquote&gt;
&lt;p&gt;(Update: &lt;a href=&quot;https://github.blog/2022-06-08-sunsetting-atom/&quot;&gt;nope&lt;/a&gt;. I&apos;ve since switched to VSC, so looks like you should too. I&apos;ll leave this here for nostalgia purposes.)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Part of this switch to Jekyll I mentioned &lt;a href=&quot;/2021/06/13/dogfooding/&quot;&gt;previously&lt;/a&gt; is that I now edit this site in Markdown instead of WordPress. The great thing about Markdown is you can theoretically edit it in anything; you could even use Notepad or TextEdit or even the DOS Edlin editor to make a Markdown file. But you probably want something that adds some conveniences, like a few key bindings to save some time typing, a preview pane, and the ability to search and replace multiple files.&lt;/p&gt;
&lt;p&gt;When I first started using Markdown at work in 2015, I looked for a good editor that would do all of this, but never entirely found it. I stumbled through trying to set up Notepad++ like an IDE (I was stuck on a Windows machine), and I almost considered setting up Eclipse as a Markdown editor, but then I remembered it wasn&apos;t 2003.&lt;/p&gt;
&lt;p&gt;I eventually settled on using &lt;a href=&quot;https://atom.io&quot;&gt;Atom&lt;/a&gt;, which is a text editor-slash-IDE released by GitHub. It&apos;s free, open-source, and customizable, with a lot of optional packages that are easy to add.&lt;/p&gt;
&lt;p&gt;Here&apos;s what I did to set up Atom for my Markdown editing needs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Not part of Atom per se, but life is much easier when I&apos;m also using &lt;a href=&quot;https://desktop.github.com&quot;&gt;GitHub Desktop&lt;/a&gt; along with it. It makes it much easier to handle git commits/pushes/merges/branches. Atom does have its own git integration down in the lower right corner, where you see your current branch, do a quick fetch, and see PR review comments.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;First thing I do is change the theme, because I can&apos;t deal with dark mode (sorry). Go to &lt;strong&gt;Preferences &gt; Settings &gt; Themes&lt;/strong&gt; and pick something; I usually go with One Light, but there are many options.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Then go to &lt;strong&gt;Preferences &gt; Settings &gt; Install&lt;/strong&gt; and grab the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;language-markdown&lt;/code&gt; - adds grammar support for MD files.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;markdown-writer&lt;/code&gt; - adds more MD writing features.&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;markdown-preview-enhanced&lt;/code&gt; - there are a few previewers out there, but this one seems to work best for me. I had problems with &lt;code class=&quot;language-text&quot;&gt;markdown-preview&lt;/code&gt; handling Jekyll files; maybe that&apos;s fixed now?&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Go to &lt;strong&gt;Preferences &gt; Settings &gt; Packages&lt;/strong&gt; and go to the settings for the &lt;code class=&quot;language-text&quot;&gt;spell-check&lt;/code&gt; package. In the &lt;strong&gt;Grammars&lt;/strong&gt; section, add &lt;code class=&quot;language-text&quot;&gt;text.md&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;If you &lt;strong&gt;File &gt; Open&lt;/strong&gt; to the directory of your project, it opens it with the hierarchy shown in the left sidebar, and you can then click around in that to open various files.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I&apos;ve been using this setup daily for a while now at work. But now everyone&apos;s using Visual Studio Code, so maybe I need to switch.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Dogfooding]]></title><description><![CDATA[I can't remember when, but I recently heard someone use the term dogfooding, as in a shorthand verb form of eating your own dog food. Every…]]></description><link>https://www.jonkonrath.com/2021/06/13/dogfooding/</link><guid isPermaLink="false">https://www.jonkonrath.com/2021/06/13/dogfooding/</guid><pubDate>Sun, 13 Jun 2021 18:58:42 GMT</pubDate><content:encoded>&lt;p&gt;I can&apos;t remember when, but I recently heard someone use the term &lt;em&gt;dogfooding&lt;/em&gt;, as in a shorthand verb form of &lt;em&gt;eating your own dog food&lt;/em&gt;. Every noun in tech becomes a verb, usually when it gets to marketing or sales, but this one made me roll my eyes a bit more than usual.&lt;/p&gt;
&lt;p&gt;My wife had never heard the term, which is a bit ironic, since she actually works in the dog food industry. I have mixed feelings about it, although it&apos;s marginally better than &quot;drinking your own champagne,&quot; because I don&apos;t drink, and when I did, champagne was second only to tequila as the alcoholic beverage I disliked the most. But in the late nineties in the tech industry, they would roll out champagne almost as much as they would print team t-shirts. Anyway.&lt;/p&gt;
&lt;p&gt;The term &quot;eating your own dog food&quot; is supposed to mean using the tools your company makes to actually operate your company. If your company makes bug tracking software, you shouldn&apos;t be paying Atlassian to use Jira; you should be using your own software, to show customers that it actually works.&lt;/p&gt;
&lt;p&gt;(Side note: I&apos;ve always called it JIRA. I started at the new place, and everyone was saying Jira. Turns out the name changed in September of 2017. &lt;a href=&quot;https://community.atlassian.com/t5/Jira-questions/Is-it-quot-JIRA-quot-or-quot-Jira-quot/qaq-p/681163&quot;&gt;See here&lt;/a&gt;. This is partly the trend of making everything lowercase, and partly testimony to how infrequently the last place updated their software.)&lt;/p&gt;
&lt;p&gt;So, the actual news here is that I&apos;m &quot;dogfooding&quot; by moving this site away from Wordpress and doing it all with a static site generator. This is the same docs-as-code approach I do at my job. That means:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Writing everything in Markdown.&lt;/li&gt;
&lt;li&gt;Using Atom as my editor.&lt;/li&gt;
&lt;li&gt;Using Jekyll as the SSG.&lt;/li&gt;
&lt;li&gt;Using the Minima theme with some customization, most notably pagination.&lt;/li&gt;
&lt;li&gt;Pushing it all to GitHub.&lt;/li&gt;
&lt;li&gt;Hosting it with GitHub pages.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There&apos;s lots to cover here, and also not everything is done. My redirect from jonkonrath.com to the new hosted site is a bit of a hack, and I&apos;ve barely started any page design. I&apos;ll get to that, and I plan to explain all of it as I go. But first, I need to go eat something other than dog food for lunch and not think about Alpo.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Onward(s) and Upward(s)]]></title><description><![CDATA[Just a small programming note: after ten and a half years, I left my last position, and moved on to a new one. I’m still managing, still…]]></description><link>https://www.jonkonrath.com/2021/03/23/onwards-and-upwards/</link><guid isPermaLink="false">https://www.jonkonrath.com/2021/03/23/onwards-and-upwards/</guid><pubDate>Wed, 24 Mar 2021 01:31:42 GMT</pubDate><content:encoded>&lt;p&gt;Just a small programming note: after ten and a half years, I left my last position, and moved on to a new one. I’m still managing, still writing, but at a much younger company, which is always interesting.&lt;/p&gt;
&lt;p&gt;As per my usual policy, I won’t mention names here, but if you follow me on LinkedIn, you can figure it out.&lt;/p&gt;
&lt;p&gt;Also worth mentioning that as always, all words here are mine, and I don’t speak for my employer.&lt;/p&gt;
&lt;p&gt;Unrelated grammar nit: I was trying to determine if the saying was &lt;em&gt;onward and upward&lt;/em&gt; or &lt;em&gt;onwards and upwards&lt;/em&gt;. The  first one sounded right to me. Both of the &lt;em&gt;-ward&lt;/em&gt; words in question are adverbs with the -s, or adjectives without. (You look downwards; Nine Inch Nails has a great record called &lt;em&gt;The Downward Spiral&lt;/em&gt;.)&lt;/p&gt;
&lt;p&gt;The saying could be using adverbs or adjectives though, so none of this helps. I think both AP and Chicago Manual of Style would say that Americans would drop the -s and British love to keep it. So, onward and upward.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[A quick cmd trick]]></title><description><![CDATA[I wish I could tell the 1990 me that the 2020 me would be posting DOS commands in a blog instead of using a brain-implant computer on the…]]></description><link>https://www.jonkonrath.com/2020/11/14/a-quick-cmd-trick/</link><guid isPermaLink="false">https://www.jonkonrath.com/2020/11/14/a-quick-cmd-trick/</guid><pubDate>Sat, 14 Nov 2020 20:34:29 GMT</pubDate><content:encoded>&lt;p&gt;I wish I could tell the 1990 me that the 2020 me would be posting DOS commands in a blog instead of using a brain-implant computer on the surface of Mars. (I also wish 2020 me could tell 1990 me to patent the idea for an online book store, or that the Reds would sweep the A’s in the World Series.) Anyway, here’s a quick one I should have known already.&lt;/p&gt;
&lt;p&gt;You can set the prompt in a command window by setting the environment variable &lt;code class=&quot;language-text&quot;&gt;PROMPT&lt;/code&gt;. There is a &lt;code class=&quot;language-text&quot;&gt;PROMPT&lt;/code&gt; command too, which I vaguely remember from the DOS days and setting up an &lt;code class=&quot;language-text&quot;&gt;AUTOEXEC.BAT&lt;/code&gt; file. But the &lt;code class=&quot;language-text&quot;&gt;PROMPT&lt;/code&gt; command only works for that session. The variable works for every session.&lt;/p&gt;
&lt;p&gt;The default would be &lt;code class=&quot;language-text&quot;&gt;PROMPT $P$G&lt;/code&gt;: show your current directory, then a greater-than sign, so you get &lt;code class=&quot;language-text&quot;&gt;C:\this\that&gt;&lt;/code&gt; as your prompt. But you can do some other fun stuff:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;$D&lt;/code&gt; – the date&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;$T&lt;/code&gt; – the time&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;$V&lt;/code&gt; – the OS version number&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;$B&lt;/code&gt; – a pipe symbol&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;$G&lt;/code&gt; and &lt;code class=&quot;language-text&quot;&gt;$T&lt;/code&gt; – greater-than and less-than&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;$S&lt;/code&gt; – space&lt;/li&gt;
&lt;li&gt;&lt;code class=&quot;language-text&quot;&gt;$+&lt;/code&gt; – a plus-sign for each level of depth in the &lt;code class=&quot;language-text&quot;&gt;PUSHD&lt;/code&gt; directory (If you’re not a habitual user of &lt;code class=&quot;language-text&quot;&gt;PUSHD&lt;/code&gt;/&lt;code class=&quot;language-text&quot;&gt;POPD&lt;/code&gt;, look into it.)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There are more; do a &lt;code class=&quot;language-text&quot;&gt;PROMPT /?&lt;/code&gt; to see them.&lt;/p&gt;
&lt;p&gt;I normally set an environment windows by right-clicking &lt;strong&gt;My Computer&lt;/strong&gt; and going to &lt;strong&gt;Properties &gt; Advanced &gt; Environment variables&lt;/strong&gt;, but another fun trick is you can use the &lt;code class=&quot;language-text&quot;&gt;SETX&lt;/code&gt; command to do this, too. So I did this:&lt;/p&gt;
&lt;pre&gt;SETX PROMPT=$T $P$G&lt;/pre&gt;
&lt;p&gt;That adds the time to the front of the default prompt. The reason I did this is because Jekyll builds take forever, and I wanted an easy way to tell if I started the build two minutes or seventeen minutes ago, because time loses all meaning on the last day of a release.&lt;/p&gt;
&lt;p&gt;(Thanks: &lt;a href=&quot;http://www.hanselman.com/blog/a-better-prompt-for-cmdexe-or-cool-prompt-environment-variables-and-a-nice-transparent-multiprompt&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;a href=&quot;http://www.hanselman.com/blog/a-better-prompt-for-cmdexe-or-cool-prompt-environment-variables-and-a-nice-transparent-multiprompt&quot;&gt;http://www.hanselman.com/blog/a-better-prompt-for-cmdexe-or-cool-prompt-environment-variables-and-a-nice-transparent-multiprompt&lt;/a&gt;&lt;/a&gt;)&lt;/p&gt;</content:encoded></item><item><title><![CDATA[The one-line web server]]></title><description><![CDATA[Every now and again, I run into a situation where a bunch of HTML files can’t be opened by simply double-clicking the index.html, and need…]]></description><link>https://www.jonkonrath.com/2020/09/17/the-one-line-web-server/</link><guid isPermaLink="false">https://www.jonkonrath.com/2020/09/17/the-one-line-web-server/</guid><pubDate>Fri, 18 Sep 2020 00:38:33 GMT</pubDate><content:encoded>&lt;p&gt;Every now and again, I run into a situation where a bunch of HTML files can’t be opened by simply double-clicking the index.html, and need to be hosted on a web server to behave properly. I think this used to happen with WebWorks output, and built Jekyll output does this. It’s also sometimes handy to have a web server spinning in the background so you can modify and preview things on the fly.&lt;/p&gt;
&lt;p&gt;In the past when this came up, I’d fall down a wormhole about installing the Apache or IIS web server, or trying to figure out where Apple moved the built-in out-of-date Apache web server in the latest version of macOS. (I think it’s gone completely in Catalina.) But instead of sifting through the many different Apache installers and Medium articles about how to get an entire full stack going, I realized this is dead simple if you have Python installed.&lt;/p&gt;
&lt;p&gt;First, do you have Python installed? A quick &lt;code class=&quot;language-text&quot;&gt;python -V&lt;/code&gt; will tell you. If you don’t, &lt;a href=&quot;https://wiki.python.org/moin/BeginnersGuide/Download&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;grab a copy&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Open a command line in the directory you want to serve up, and if you have Python 3, do this:&lt;/p&gt;
&lt;pre&gt;python3 -m http.server&lt;/pre&gt;
&lt;p&gt;If you’re a Windows user, that is probably &lt;code class=&quot;language-text&quot;&gt;python&lt;/code&gt; and not &lt;code class=&quot;language-text&quot;&gt;python3&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If you’re still using Python 2, do this instead:&lt;/p&gt;
&lt;pre&gt;python -m SimpleHTTPServer&lt;/pre&gt;
&lt;p&gt;Now point a web browser at &lt;code class=&quot;language-text&quot;&gt;localhost:8000&lt;/code&gt; and there’s your stuff.&lt;/p&gt;
&lt;p&gt;If you’ve already got something on port 8000, put another port number after the command, like &lt;code class=&quot;language-text&quot;&gt;python3 -m http.server 90125&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Don’t expect to run your Fortune 500’s production environment on this. It’s great for testing, though.&lt;/p&gt;
&lt;p&gt;(Thanks: &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Learn/Common_questions/set_up_a_local_testing_server&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Learn/Common_questions/set_up_a_local_testing_server&quot;&gt;https://developer.mozilla.org/en-US/docs/Learn/Common_questions/set_up_a_local_testing_server&lt;/a&gt;&lt;/a&gt; and &lt;a href=&quot;https://docs.python.org/3/library/http.server.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;a href=&quot;https://docs.python.org/3/library/http.server.html&quot;&gt;https://docs.python.org/3/library/http.server.html&lt;/a&gt;&lt;/a&gt;)&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Various Cabin Fever Projects]]></title><description><![CDATA[Due to cabin fever (or whatever you call it), I’ve been working on a lot of oddball programming projects. I mean, I’m working way too much…]]></description><link>https://www.jonkonrath.com/2020/08/23/various-cabin-fever-projects/</link><guid isPermaLink="false">https://www.jonkonrath.com/2020/08/23/various-cabin-fever-projects/</guid><pubDate>Sun, 23 Aug 2020 19:35:26 GMT</pubDate><content:encoded>&lt;p&gt;Due to cabin fever (or whatever you call it), I’ve been working on a lot of oddball programming projects. I mean, I’m working way too much at the day job, because I can’t really leave the house, so I’m always on. But I’ve also been doing various things (and then not finishing them) mostly because I don’t have a basement where I can start building a boat out of matchsticks or something.&lt;/p&gt;
&lt;p&gt;Anyway, here’s a partial list of what’s on the various back burners of my stove. If you’re really insanely curious about any of these, let me know and maybe I’ll actually finish them.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I’ve been messing around more on GitHub. I’ve been doing this at my job too, but I’m trying to make an effort to be more active on my personal profile. If you have the time and you use any open source software, I’d encourage you to do the same. Even if you’re not a programmer, it’s good to know how to complain about their documentation and maybe fix a few things if you find them. My personal profile is here: &lt;a href=&quot;https://github.com/jkonrath&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;a href=&quot;https://github.com/jkonrath&quot;&gt;https://github.com/jkonrath&lt;/a&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;GitHub has caused me to dig up all of the various college coding projects and see if they’re worthwhile to post on there, just for kicks. They are all fairly horrible, so no. I’m almost tempted to post the first coding project I actually got paid to do, which I still have. It was for the USGS and it did something with well depth analysis, which I totally don’t understand. The code itself is an exercise on how to not to do what we’d call Big Data analysis now, and would probably be about ten lines of Python. Fun nostalgia though.&lt;/li&gt;
&lt;li&gt;Just for kicks, I started writing a Markdown to HTML program, but decided to do it all in straight-up C, using C89 ANSI C and the standard library, nothing more. Outside of Arduino C, I haven’t done much C program in… a long time. I realized why when I started working with strings. I have a newfound appreciation for Python’s built-in string support.&lt;/li&gt;
&lt;li&gt;I also realized, digging through the archives, that I know more XSLT than I realized. I posted a gist about this on GitHub, but I probably should make a whole project that’s a collection of all the dumb little building blocks I used constantly when I did this on a daily basis. (Like I always have to look up how to split one file into many files. I need to write that down somewhere.)&lt;/li&gt;
&lt;li&gt;I found this giant XSLT I used at a previous job to chop up Doxygen’s XML output and convert it into something I could pull into a structured FrameMaker doc. Looking at it, I’m not sure how useful it is, because I was doing a bunch of arbitrary reordering of the doc because… well, let’s say just because.&lt;/li&gt;
&lt;li&gt;I also started working on an XSLT to convert WordPress output to a Flare document. I really do love that Flare documents are just XML, and you can do anything with them.&lt;/li&gt;
&lt;li&gt;I converted this blog to &lt;a href=&quot;https://gohugo.io&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Hugo&lt;/a&gt;, but in the process I realized it’s faster for me on a site this small to keep it in WordPress, so I didn’t use the conversion. It was a fun learning process, though.&lt;/li&gt;
&lt;li&gt;I’ve been messing with &lt;a href=&quot;https://github.com/pirate/ArchiveBox&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;ArchiveBox&lt;/a&gt;, which is a neat idea. It’s a system where you feed in URLs and it archives them in various formats. It’s sort of a DIY Internet Archive. I’ve been learning more Docker by running it with Docker-compose, and complaining on their GitHub page about various minor problems. I should spend some time helping them rewrite their docs.&lt;/li&gt;
&lt;li&gt;Another site where I should pay more attention is Stack Overflow. I’m on there at &lt;a href=&quot;https://stackoverflow.com/users/99038/jon-konrath&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;a href=&quot;https://stackoverflow.com/users/99038/jon-konrath&quot;&gt;https://stackoverflow.com/users/99038/jon-konrath&lt;/a&gt;&lt;/a&gt;. Funny to look back at all the FrameMaker and Doxygen posts I was answering way back when.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Speaking of obsessively building stuff in your basement, this is one of my favorite videos ever: &lt;a href=&quot;https://vimeo.com/166403522&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;a href=&quot;https://vimeo.com/166403522&quot;&gt;https://vimeo.com/166403522&lt;/a&gt;&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[PDF Printing with Headless Chrome]]></title><description><![CDATA[I’ve got docs for a bunch of products in Jekyll, written mostly in Markdown, but also some HTML output from DITA and Flare. It works great…]]></description><link>https://www.jonkonrath.com/2020/06/21/pdf-printing-with-headless-chrome/</link><guid isPermaLink="false">https://www.jonkonrath.com/2020/06/21/pdf-printing-with-headless-chrome/</guid><pubDate>Mon, 22 Jun 2020 00:07:21 GMT</pubDate><content:encoded>&lt;p&gt;I’ve got docs for a bunch of products in Jekyll, written mostly in Markdown, but also some HTML output from DITA and Flare. It works great, but doc reviews are a nightmare. We typically use Acrobat shared reviews for doc review, which mostly works, but the question became how to make PDFs of this stuff, especially the Markdown.&lt;/p&gt;
&lt;p&gt;There are a lot of obvious and not-so-obvious half-answers here. Like, why not save as PDF from your Markdown editor? (You don’t get any of the templating from Jekyll, and none of the variables show up. You also have to do it from each file, by hand.) I spent &lt;em&gt;years&lt;/em&gt; chasing a good solution for this, and tried Pandoc, Prince, PrawnPDF, wkhtmltopdf, dita-ot, and gotenberg, hitting some roadblock with each one.&lt;/p&gt;
&lt;p&gt;My short-term solution was starting Jekyll locally, going to each page in a browser, doing a Ctrl-P, and printing to a PDF. For every page. Every single page. For every review. That was obviously not a great way to handle it.&lt;/p&gt;
&lt;p&gt;This is when I found something genius: &lt;em&gt;Headless Chrome&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Basically, headless Chrome runs the Chrome browser in the background, and then you can throw commands at it and get the output. If you ever used the venerable DZBatcher back in the day for non-interactive FrameMaker, it’s a similar concept. If you’re a Node programmer, there’s a bunch of crazy stuff you can do with it. But there’s also a command-line interface where you can do some basic stuff from a shell script.&lt;/p&gt;
&lt;p&gt;If you have a version of Chrome newer than mid-2017, you’re set. You can do something like this:&lt;/p&gt;
&lt;p&gt;&lt;code class=&quot;language-text&quot;&gt;chrome --headless --disable-gpu --print-to-pdf https://www.jonkonrath.com/&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Another fun command is &lt;code class=&quot;language-text&quot;&gt;--screenshot&lt;/code&gt;, which will dump the page to a PNG.&lt;/p&gt;
&lt;p&gt;There are a bunch of caveats, and there is almost no logging or error messages thrown by Chrome, so it’s maddening trying to debug this. So keep the following in mind:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Headless Chrome uses the location of your Chrome binary as the working directory, and tries to save files there. If you’re using Windows, chances are you can’t write files in &lt;code class=&quot;language-text&quot;&gt;C:\Program Files (x86)&lt;/code&gt;, but it won’t tell you that if it fails. And if it does work, it will pollute that directory with output as you wonder where it’s putting the PDFs. You can specify an output file with &lt;code class=&quot;language-text&quot;&gt;--print-to-pdf=&quot;/full/path/file.pdf&quot;&lt;/code&gt; and give a full absolute directory there.&lt;/li&gt;
&lt;li&gt;There is an &lt;code class=&quot;language-text&quot;&gt;--enable-logging&lt;/code&gt; switch, which is vaguely helpful.&lt;/li&gt;
&lt;li&gt;The URL you specify has to have a protocol in front of it (http:// or https://) or it will silently fail.&lt;/li&gt;
&lt;li&gt;If you do something wrong, Chrome will go sideways, but keep running in the background without complaint. You’ll need to stop every Chrome process to get it to work again.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I can’t publish the Windows CMD script I wrote for two reasons: one, it belongs to my employer because they pay me, and two, it’s the worst piece of garbage you’ve ever seen. The five lines of code I had to write to generate a timestamped directory look like if one of my cats slept on my keyboard for 45 minutes. Anyway, what I basically did:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Pass in a .txt file with a list of URLs in the order I eventually want the output.&lt;/li&gt;
&lt;li&gt;Create a new timestamped directory.&lt;/li&gt;
&lt;li&gt;Loop through the text file, and run the print-to-pdf command once per line, dumping them into the timestamped directory.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;When I named the output files, I stripped off the protocol and hostname from the URL, and numbered the files, and replaced the slashes with dashes in the file. So if I printed &lt;a href=&quot;http://example.com/this/is/the/index.html&quot;&gt;http://example.com/this/is/the/index.html&lt;/a&gt;, it would create 1-this-is-the-index.html. The path thing is so duplicate files don’t overwrite each other.&lt;/p&gt;
&lt;p&gt;Then when I have that directory of PDFs, I Ctrl-A, right-click, and combine the files into a PDF, then run a shared review on that. The beauty is that when I do round two of the review, I simply run the script again, and the files are in the same order. (Otherwise, the files are going to be in alphabetical order, which probably isn’t what your reviewers want.)&lt;/p&gt;
&lt;p&gt;A handy way to get that file started is with a &lt;code class=&quot;language-text&quot;&gt;dir /b &gt; file-list.txt&lt;/code&gt; from the command line in your top-level source directory. Don’t forget to edit out the images and directory names from your list.&lt;/p&gt;
&lt;p&gt;This isn’t a great way to do production-ready PDFs, and you’ll have no good control over headers, footers, page layout, or anything else. Also, all of the links in the PDF won’t work right; they’ll go to localhost if you’re running Jekyll locally. But it’s close enough for review purposes.&lt;/p&gt;
&lt;p&gt;More info on Headless Chrome: &lt;a href=&quot;https://developers.google.com/web/updates/2017/04/headless-chrome&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;a href=&quot;https://developers.google.com/web/updates/2017/04/headless-chrome&quot;&gt;https://developers.google.com/web/updates/2017/04/headless-chrome&lt;/a&gt;&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[xml.etree.ElementTree and OS randomness]]></title><description><![CDATA[OK, I’ll start by doing something you aren’t supposed to do: parse HTML using a bunch of regular expressions in Python. Don’t do this. Life…]]></description><link>https://www.jonkonrath.com/2020/05/05/xml-etree-elementtree-and-os-randomness/</link><guid isPermaLink="false">https://www.jonkonrath.com/2020/05/05/xml-etree-elementtree-and-os-randomness/</guid><pubDate>Tue, 05 May 2020 22:28:21 GMT</pubDate><content:encoded>&lt;p&gt;OK, I’ll start by doing something you aren’t supposed to do: parse HTML using a bunch of regular expressions in Python. Don’t do this. Life is too short. Use something like &lt;a href=&quot;https://www.crummy.com/software/BeautifulSoup/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;BeautifulSoup&lt;/a&gt;. I couldn’t, because I had to use standard libraries only, so here I am.&lt;/p&gt;
&lt;p&gt;Anyway, my program manipulated a tree of XHTML using &lt;code class=&quot;language-text&quot;&gt;xml.etree.ElementTree&lt;/code&gt;. Typical stuff like any tutorial on it:&lt;/p&gt;
&lt;pre&gt;import xml.etree.ElementTree as ET
...
root = ET.parse(htmlfname).getroot()
bod = root.find(&apos;body&apos;)
...&lt;/pre&gt;
&lt;p&gt;Then after a bunch of scraping, I used a regex like this to get the address in the href of the link:&lt;/p&gt;
&lt;pre&gt;anchor_addr = re.search(&quot;&amp;lt;a href=\&quot;([^\&quot;]*)\&quot;&quot;,anchor_base).group(1)
&lt;/pre&gt;
&lt;p&gt;(I’m converting HTML to Markdown. Don’t ask why.)&lt;/p&gt;
&lt;p&gt;Anyway, this worked fine on Windows. I pushed the code, and a Unix machine in the CICD pipeline built it, and failed on this line. The match would fail, and &lt;code class=&quot;language-text&quot;&gt;anchor_addr&lt;/code&gt; wouldn’t have a &lt;code class=&quot;language-text&quot;&gt;.group(1)&lt;/code&gt;, because it was a &lt;code class=&quot;language-text&quot;&gt;NoneType&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;At first, I thought it was the typical problem with linefeeds, like my code was splitting strings into arrays with &lt;code class=&quot;language-text&quot;&gt;\n&lt;/code&gt; and on Windows it had &lt;code class=&quot;language-text&quot;&gt;\r\n&lt;/code&gt;. After messing around with that, I found it it wasn’t the case.&lt;/p&gt;
&lt;p&gt;Here’s the problem: &lt;code class=&quot;language-text&quot;&gt;xml.etree.ElementTree&lt;/code&gt; uses a dictionary to store the attributes of an element it parses. Python dictionaries are inherently unordered. Or they &lt;em&gt;can&lt;/em&gt; be unordered; it’s an implementation detail. And it looks like the version of Python I was using on Windows was ordering them, but the ones I was using on my home Mac and on this unix build machine were returning the attributes alphabetically. So &lt;code class=&quot;language-text&quot;&gt;&amp;lt;a href=&quot;foo&quot; alt=&quot;hi&quot;&gt;&lt;/code&gt; was becoming &lt;code class=&quot;language-text&quot;&gt;&amp;lt;a alt=&quot;hi&quot; href=&quot;foo&quot;&gt;&lt;/code&gt; and breaking my regexp.&lt;/p&gt;
&lt;p&gt;My code didn’t really need to find the entire element and pull the value of the attribute, because it was already inside the element. So I was able to change that regexp to &lt;code class=&quot;language-text&quot;&gt;&quot;href=\&quot;([^\&quot;]*)\&quot;&quot;&lt;/code&gt; and that worked, provided it was never &lt;code class=&quot;language-text&quot;&gt;HREF&lt;/code&gt; or &lt;code class=&quot;language-text&quot;&gt;HREF=&apos;foo&apos;&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Long story short, don’t use regular expressions to parse HTML.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[A few quick updates]]></title><description><![CDATA[Five years, five updates. Sounds about right. A few quick updates, in the interest in posting more than once a year: I’ve been managing…]]></description><link>https://www.jonkonrath.com/2020/05/05/a-few-quick-updates/</link><guid isPermaLink="false">https://www.jonkonrath.com/2020/05/05/a-few-quick-updates/</guid><pubDate>Tue, 05 May 2020 19:43:51 GMT</pubDate><content:encoded>&lt;p&gt;Five years, five updates. Sounds about right.&lt;/p&gt;
&lt;p&gt;A few quick updates, in the interest in posting more than once a year:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I’ve been managing other writers for almost four years now, so I should probably change my byline to reflect that. I’m still writing and working on tool/architecture stuff. But at some point, I should write down some snappy articles with management tips and tricks. Maybe some stuff on synergy and paradigm shifts.&lt;/li&gt;
&lt;li&gt;My byline also mentioned being a FrameMaker nerd. I’ve barely used FrameMaker in the last five years, except to get stuff out of it. Aside from a few things still lingering in &lt;code class=&quot;language-text&quot;&gt;*.fm&lt;/code&gt; files, most of my company uses DITA, and some of use Markdown and Jekyll. But the eventual plan is to move everything to MadCap Flare. So maybe I’ll write about that more later. For now, strike FrameMaker from the byline.&lt;/li&gt;
&lt;li&gt;I’ve been doing some programming lately, mostly in the quest to get a bunch of DITA converted over to Flare. Whenever I’ve run into a conversion or production program that required custom code, I’ve always said “I’m not a programmer” and then spent months trying to get developer time to fix it. I think it’s time I change that to “I’m not a very good programmer” and work on improving that. As of late, that’s involved a lot of Python, so you may see some posts on that.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Of course, I’m saying all of this, and I may not post again until 2024 because I’m so busy. But, stay tuned.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Git choose-your-own-adventure]]></title><description><![CDATA[I use git on a daily basis. Not to age myself, but I went from rcs to cvs to svn to git, with some Perforce and SourceSafe sprinkled in…]]></description><link>https://www.jonkonrath.com/2019/03/10/git-choose-your-own-adventure/</link><guid isPermaLink="false">https://www.jonkonrath.com/2019/03/10/git-choose-your-own-adventure/</guid><pubDate>Sun, 10 Mar 2019 18:03:13 GMT</pubDate><content:encoded>&lt;p&gt;I use git on a daily basis. Not to age myself, but I went from rcs to cvs to svn to git, with some Perforce and SourceSafe sprinkled in there, so I have a long background in source control. But git is just different enough to throw me sometimes. And for whatever reason, a lot of git documentary gets a bit, well, &lt;em&gt;academic&lt;/em&gt;. It’s hard to find a quick answer sometimes, and they’re often buried in very theoretical arguments about whether or not git submodules are essential or the worst thing since Agent Orange.&lt;/p&gt;
&lt;p&gt;Anyway, here’s my go-to for answers when I break something: &lt;a href=&quot;http://sethrobertson.github.io/GitFixUm/fixup.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;a href=&quot;http://sethrobertson.github.io/GitFixUm/fixup.html&quot;&gt;http://sethrobertson.github.io/GitFixUm/fixup.html&lt;/a&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;There are two things I like about this page. First, it gives you answers without a lot of guff. Less is more, etc.&lt;/p&gt;
&lt;p&gt;The second thing is that it’s presented as a choose-your-own-adventure. Are you trying to do this? Did you do this? Do you want to do this? It’s a simple troubleshooting flowchart, something I’ve written in docs before, and something you’ll run into every time you call tech support. (There it gets a bad rap because the first steps are always “did you try restarting?” and that seems insulting. It’s also the problem 90% of the time. That’s another topic, though.)&lt;/p&gt;
&lt;p&gt;But as a kid who grew up devouring Bantam books from the book fair at my grade school, and memorizing _The Cave of Time _way back then, there’s something very intuitive and appealing about this form of docs. I’m not going to say this makes a git branching disaster where you think you lost everything fun, but it makes it easier to drill through the problem and find a solution. I don’t really have any docs at work where I could pull something like this, but as docs in general become more informal and user-oriented, this would be a great format to use.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Contributing to Open Source]]></title><description><![CDATA[One of the questions I’m always asked is how to get experience in tech writing. It’s a chicken/egg problem: you need a job to get experience…]]></description><link>https://www.jonkonrath.com/2018/09/07/contributing-to-open-source/</link><guid isPermaLink="false">https://www.jonkonrath.com/2018/09/07/contributing-to-open-source/</guid><pubDate>Fri, 07 Sep 2018 22:34:55 GMT</pubDate><content:encoded>&lt;p&gt;One of the questions I’m always asked is how to get experience in tech writing. It’s a chicken/egg problem: you need a job to get experience, but you need experience to get a job. You can attend a code camp or complete a certificate program to get some real-world experience to add to your resume, but what I always tell people is to get started with open-source software.&lt;/p&gt;
&lt;p&gt;There is a &lt;em&gt;lot&lt;/em&gt; of open-source software out there these days. I got started in computing before this was the case, but was an early adopter of the Linux OS in the early 90s, which changed everything. Now, entire communities have sprung up around the development of operating systems, servers, programming languages, and desktop software. Tools like GitHub have centralized participation, putting source code in a centralized location, and providing tools for quick communication about projects, instead of crufty old mailing lists. It’s made it very easy to explore projects and contribute to them.&lt;/p&gt;
&lt;p&gt;Here’s a great article about how to get started on this:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://medium.freecodecamp.org/contributing-to-open-source-is-not-hard-here-is-my-journey-to-contributing-to-nodejs-d10760e31194&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;a href=&quot;https://medium.freecodecamp.org/contributing-to-open-source-is-not-hard-here-is-my-journey-to-contributing-to-nodejs-d10760e31194&quot;&gt;https://medium.freecodecamp.org/contributing-to-open-source-is-not-hard-here-is-my-journey-to-contributing-to-nodejs-d10760e31194&lt;/a&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This example is specifically about a developer contributing to the Node.js programming language. But there are a lot of opportunities for tech writers, because documentation for projects is not always that great. The only issue is that there aren’t always that many documentation bugs listed in projects. It requires hunting down a project you like (check out the “explore” section of GitHub to browse through things) and deciding what needs improvement.&lt;/p&gt;
&lt;p&gt;Overall, it’s a great way to gain experience, and also improve tools that everyone will use. And, maybe you’ll someday get a job out of it.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Gray/Grey]]></title><description><![CDATA[I wish I had learned this forever ago: If you are in America, it is gray If you are in England, it is grey It’s that simple. (I partially…]]></description><link>https://www.jonkonrath.com/2018/01/15/graygrey/</link><guid isPermaLink="false">https://www.jonkonrath.com/2018/01/15/graygrey/</guid><pubDate>Mon, 15 Jan 2018 15:30:09 GMT</pubDate><content:encoded>&lt;p&gt;I wish I had learned this forever ago:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If you are in &lt;strong&gt;A&lt;/strong&gt;merica, it is gr&lt;strong&gt;a&lt;/strong&gt;y&lt;/li&gt;
&lt;li&gt;If you are in &lt;strong&gt;E&lt;/strong&gt;ngland, it is gr&lt;strong&gt;e&lt;/strong&gt;y&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It’s that simple.&lt;/p&gt;
&lt;p&gt;(I partially blame this confusion on &lt;em&gt;Fifty Shades of Grey&lt;/em&gt;.)&lt;/p&gt;</content:encoded></item><item><title><![CDATA[FrameMaker and the Kinesis Advantage Keyboard]]></title><description><![CDATA[Because of RSI, I use a Kinesis Advantage keyboard. I used the Microsoft ergonomic keyboards for a while, but I’d burn one out every year…]]></description><link>https://www.jonkonrath.com/2016/06/08/framemaker-and-the-kinesis-advantage-keyboard/</link><guid isPermaLink="false">https://www.jonkonrath.com/2016/06/08/framemaker-and-the-kinesis-advantage-keyboard/</guid><pubDate>Wed, 08 Jun 2016 22:51:49 GMT</pubDate><content:encoded>&lt;p&gt;Because of RSI, I use a Kinesis Advantage keyboard. I used the Microsoft ergonomic keyboards for a while, but I’d burn one out every year, and the membrane keys are a bit mushy. I went whole-hog and spent the money on the Kinesis, which I don’t regret at all, except for one thing: the function keys. The F-keys and Esc are little rubber chicklet keys reminiscent – I’m dating myself here – of the Atari 400. And when you’re in FrameMaker and doing some heavy formatting, those keys are essential.&lt;/p&gt;
&lt;p&gt;You can remap keys in the Kinesis at the keyboard level, but I switch between Windows and Mac machines through a KVM switch, so I wanted to avoid that. Instead, I use AutoHotkey, a nifty little free Windows utility that enables you to easily remap keys at the OS level.&lt;/p&gt;
&lt;p&gt;Head over to &lt;a href=&quot;https://autohotkey.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;a href=&quot;https://autohotkey.com/&quot;&gt;https://autohotkey.com/&lt;/a&gt;&lt;/a&gt; and grab a copy. My &lt;code class=&quot;language-text&quot;&gt;AutoHotkey.ahk&lt;/code&gt; has the following entries for FrameMaker:&lt;/p&gt;
&lt;pre&gt;Home &amp; 5::Send, {F8}
Home &amp; 6::Send, {F9}
End::Send, {Esc}&lt;/pre&gt;
&lt;p&gt;I don’t use the Home and End keys much, so I stole them for my own use. On the Kinesis, they are in my left thumb cluster, and great for frequently-used combo keystrokes. So I map:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Home-5 to F8. That opens the character designer.&lt;/li&gt;
&lt;li&gt;Home-6 to F9. That opens the paragraph designer.&lt;/li&gt;
&lt;li&gt;End to Esc. I use Esc constantly for Frame shortcuts, most notable Esc-j-j to repeat a paragraph assign, and Esc-c-c to repeat a character assign.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;AHK can do a &lt;em&gt;lot&lt;/em&gt; more stuff, like assigning keys to modify and paste the clipboard, run macros from DLLs, and more. If you have a highly repetitive text massage job you can’t tackle in a script, check out the advanced options. But it’s easy to use for a few quick remaps.&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;</content:encoded></item><item><title><![CDATA[Adjusting Mic volume from the command line in Windows]]></title><description><![CDATA[I spend a lot of time in meetings on a USB headset. I have a Windows computer. So every day, multiple times a day, here’s the drill: Plug in…]]></description><link>https://www.jonkonrath.com/2016/03/09/adjusting-mic-volume-from-the-command-line-in-windows/</link><guid isPermaLink="false">https://www.jonkonrath.com/2016/03/09/adjusting-mic-volume-from-the-command-line-in-windows/</guid><pubDate>Thu, 10 Mar 2016 02:58:58 GMT</pubDate><content:encoded>&lt;p&gt;I spend a lot of time in meetings on a USB headset. I have a Windows computer. So every day, multiple times a day, here’s the drill:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Plug in headset.&lt;/li&gt;
&lt;li&gt;Mic volume is a random number.&lt;/li&gt;
&lt;li&gt;Right-click Sound.&lt;/li&gt;
&lt;li&gt;Wait for the right click to register, because half the time it doesn’t, and the lag is horrible.&lt;/li&gt;
&lt;li&gt;Select Recording Devices. See last step about lag.&lt;/li&gt;
&lt;li&gt;Click Microphone.&lt;/li&gt;
&lt;li&gt;Click Properties.&lt;/li&gt;
&lt;li&gt;One in ten times, this will cause the control panel to gray out and freeze, so wait five minutes and/or force quit it and start over.&lt;/li&gt;
&lt;li&gt;Click the Level Tab. (It’s not the first tab, so this takes ten seconds to scan.)&lt;/li&gt;
&lt;li&gt;Change the level back to 100.&lt;/li&gt;
&lt;li&gt;Click OK.&lt;/li&gt;
&lt;li&gt;Click OK.&lt;/li&gt;
&lt;li&gt;Feel the great joy in knowing you’ll have to do this three or four more times that day, which adds up to like 18 months of your life.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The same process on a Mac:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Plug in the headset. It remembers what you had the level set to the last time it was plugged in.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;There is a great way around this. It’s called &lt;a href=&quot;http://www.nirsoft.net/utils/nircmd.html&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;NirCmd&lt;/a&gt;, and it’s a great little free Windows command-line executable that enables you to do all sorts of weird things from a command prompt or batch script.&lt;/p&gt;
&lt;p&gt;Go grab a copy of it at the above link. The first time you click on the exe, it will ask to copy itself to your Windows directory, and then it’s in your path, ready to go. Create a .bat file like this:&lt;/p&gt;
&lt;pre&gt;nircmd setsysvolume 65535 Microphone&lt;/pre&gt;
&lt;p&gt;Each time you put in your headset, run that, and you’re good to go.&lt;/p&gt;
&lt;p&gt;Nircmd also has some commands for shutdown/reboot/standby/logoff if you are sick of digging in the Windows menu for those commands.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[REST API Doc article]]></title><description><![CDATA[I think the big problem with API docs is what to document. And it usually ends up with a comment per method, where you have “createFoo…]]></description><link>https://www.jonkonrath.com/2016/01/11/rest-api-doc-article/</link><guid isPermaLink="false">https://www.jonkonrath.com/2016/01/11/rest-api-doc-article/</guid><pubDate>Tue, 12 Jan 2016 02:16:24 GMT</pubDate><content:encoded>&lt;p&gt;I think the big problem with API docs is what to document. And it usually ends up with a comment per method, where you have “createFoo = creates a foo; deleteFoo = deletes a foo” and no real content. The question always becomes “well, what else?” And the real value of API docs is everything in between, the things you can’t infer by just looking at method signatures.&lt;/p&gt;
&lt;p&gt;The following article is a good list of the other things you need to cover. It talks specifically about REST, but holds true for other API types, also. The TL;DR: what does a consumer need to know to actually use this API? How do you do auth? What are the business uses? What standards does it really follow? What are the other gotchas? What are the SLAs or other requirements for the service?&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://dzone.com/articles/rest-api-documentation-part-1&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;a href=&quot;https://dzone.com/articles/rest-api-documentation-part-1&quot;&gt;https://dzone.com/articles/rest-api-documentation-part-1&lt;/a&gt;&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[The hoarding of 25,000 manuals]]></title><description><![CDATA[I started tech writing right around the time print was dying. My first job involved writing software documentation as a manual and as…]]></description><link>https://www.jonkonrath.com/2015/08/18/the-hoarding-of-25000-manuals/</link><guid isPermaLink="false">https://www.jonkonrath.com/2015/08/18/the-hoarding-of-25000-manuals/</guid><pubDate>Tue, 18 Aug 2015 16:36:03 GMT</pubDate><content:encoded>&lt;p&gt;I started tech writing right around the time print was dying. My first job involved writing software documentation as a manual and as WinHelp, and it all went electronic after that. I also briefly wrote for print books about Linux and Emacs. So I have a box with versions of those manuals, and that box has bounced across the country with me, and is currently sitting in a storage space I never visit. But I always think about that chunk of print in storage, and what the end game is there. As I get new pieces of electronic junk in my life, I try to save the PDF versions of the manuals and get rid of the paper, but there’s a certain something about the print versions, too.&lt;/p&gt;
&lt;p&gt;Anyway – Jason Scott of the Textfiles web site recently ran into a seller of manuals who was going out of business and was going to junk an insanely large archive of print books. It’s an impressive collection of old print books going back to the 30s, apparently old radio equipment or parts manuals and whatnot. The owner gave him carte blanche to grab whatever he wanted, and he’s currently stuffing everything he can into a storage space for later dissemination.&lt;/p&gt;
&lt;p&gt;Check out the photos of the effort – this is some real print manual pornography, if that’s your sort of thing: &lt;a href=&quot;http://ascii.textfiles.com/archives/4683&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;a href=&quot;http://ascii.textfiles.com/archives/4683&quot;&gt;http://ascii.textfiles.com/archives/4683&lt;/a&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;There’s also a paypal to help him cover the costs of storage and shipping and whatnot, if you want to chip in a few bucks for this massive effort to save some classic dead trees.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Removing the Adobe Update Installer from the Mac menu bar]]></title><description><![CDATA[So at some point, Adobe Creative Cloud added a second notification to the menu bar on my Mac. There’s already one that opens the CC app, and…]]></description><link>https://www.jonkonrath.com/2015/08/11/removing-the-adobe-update-installer-from-the-mac-menu-bar/</link><guid isPermaLink="false">https://www.jonkonrath.com/2015/08/11/removing-the-adobe-update-installer-from-the-mac-menu-bar/</guid><pubDate>Tue, 11 Aug 2015 16:41:13 GMT</pubDate><content:encoded>&lt;p&gt;So at some point, Adobe Creative Cloud added a second notification to the menu bar on my Mac. There’s already one that opens the CC app, and always sits in the menu bar. And everyone else wants something in the menu bar. But Adobe started showing this second icon, with a perpetual 1 next to it, even if there were no updates, and all it does is open the first one. No combination of preference-toggling would make it go away, and neither would quitting CC.&lt;/p&gt;
&lt;p&gt;Here’s what I had to do:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Quit Creative Cloud.&lt;/li&gt;
&lt;li&gt;Rename &lt;code class=&quot;language-text&quot;&gt;Applications/Utilities/Adobe Creative Cloud/ACC/Creative Cloud&lt;/code&gt; to &lt;code class=&quot;language-text&quot;&gt;Creative CloudX.&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Go to the new weird menu bar thing and select Open Updater.&lt;/li&gt;
&lt;li&gt;You’ll see the old Adobe Updater. If you see the new CC app, you did 1-3 wrong.&lt;/li&gt;
&lt;li&gt;Go to Preferences and and turn off Notifications.&lt;/li&gt;
&lt;li&gt;Un-rename the file you changed in step 2.&lt;/li&gt;
&lt;li&gt;Start the CC app.&lt;/li&gt;
&lt;li&gt;You probably have to repeat this every time Adobe issues an update, which will be in like five minutes.&lt;/li&gt;
&lt;/ol&gt;</content:encoded></item><item><title><![CDATA[Apple Notes.app and google account with two-factor security not working]]></title><description><![CDATA[So you’ve done something, and the Notes app on the Mac won’t log in to Google anymore. It will sit and spin on a “logging in” forever. Oh…]]></description><link>https://www.jonkonrath.com/2015/07/13/apple-notes-app-and-google-account-with-two-factor-security-not-working/</link><guid isPermaLink="false">https://www.jonkonrath.com/2015/07/13/apple-notes-app-and-google-account-with-two-factor-security-not-working/</guid><pubDate>Mon, 13 Jul 2015 18:18:22 GMT</pubDate><content:encoded>&lt;p&gt;So you’ve done something, and the Notes app on the Mac won’t log in to Google anymore. It will sit and spin on a “logging in” forever.&lt;/p&gt;
&lt;p&gt;Oh, and you’ve also just turned on two-factor auth in Google.  Well, that’s the problem.&lt;/p&gt;
&lt;p&gt;Google considers Notes to be a “less secure” app, and it won’t work with two-factor. What you need to do is create an app password, and then it will.&lt;/p&gt;
&lt;p&gt;See also &lt;a href=&quot;https://support.google.com/accounts/answer/185833&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;a href=&quot;https://support.google.com/accounts/answer/185833&quot;&gt;https://support.google.com/accounts/answer/185833&lt;/a&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;(Not saying two-factor auth is the problem. In fact, you should probably use it for everything.)&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Making Yosemite Readable]]></title><description><![CDATA[I resisted the upgrade to Yosemite, even though I have a pretty new mid-2014 MacBook Pro, because I’d rather let someone else beta-test…]]></description><link>https://www.jonkonrath.com/2015/06/19/making-yosemite-readable/</link><guid isPermaLink="false">https://www.jonkonrath.com/2015/06/19/making-yosemite-readable/</guid><pubDate>Fri, 19 Jun 2015 22:37:32 GMT</pubDate><content:encoded>&lt;p&gt;I resisted the upgrade to Yosemite, even though I have a pretty new mid-2014 MacBook Pro, because I’d rather let someone else beta-test things before I upgrade. When I finally did upgrade, I noticed a problem: my eyes were &lt;em&gt;killing&lt;/em&gt; me.  Granted, I’ve put a few hundred thousand miles on my eyeballs over the last few decades, but this was a sudden and marked problem.&lt;/p&gt;
&lt;p&gt;I think there are a few things going on here, but the big two are the layout and the font. There’s a lot more brightness and transparency in the general look and feel of the layout. And Yosemite switched system fonts, from Lucida Grande to Helvetica Neue. They’re both sans serif fonts, but for whatever reason, the Helvetica taxes my eyes way too much.&lt;/p&gt;
&lt;p&gt;I was reluctant to do anything. I hate customizing my system, because then when I change computers, I have to re-remember everything I configured, and I don’t want to be one of those people that has a freaky version of Windows 8 that’s customized to look like Windows for Workgroups 3.11 with a yellow on pink interface and the fonts in Papyrus, and if I can’t get that, I can’t work.&lt;/p&gt;
&lt;p&gt;But, anyway, here are a few fixes I messed with:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Select** System Preferences &gt; Accessibility &gt; Reduce Transparency** (This is true by default if #3 below is also true. This can also allegedly speed up UI lag.)&lt;/li&gt;
&lt;li&gt;Set &lt;strong&gt;System Preferences &gt; General &gt; Appearance&lt;/strong&gt; to &lt;strong&gt;Graphite&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Select &lt;strong&gt;System Preferences &gt; Accessibility &gt; Increase contrast.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;I don’t do this, selecting &lt;strong&gt;System Preferences &gt; General &gt; Use dark menu bar and dock&lt;/strong&gt; might be to your preference&lt;/li&gt;
&lt;li&gt;Change the system font back using this: &lt;a href=&quot;https://github.com/schreiberstein/lucidagrandeyosemite&quot;&gt;https://github.com/schreiberstein/lucidagrandeyosemite&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt; &lt;/p&gt;</content:encoded></item><item><title><![CDATA[Photoshop CC Keyboard Shortcut Cheat Sheet]]></title><description><![CDATA[It seems like the days of cardboard key templates are over – they were a huge thing back in the old days when I started as a consultant in…]]></description><link>https://www.jonkonrath.com/2015/05/29/photoshop-cc-keyboard-shortcut-cheat-sheet/</link><guid isPermaLink="false">https://www.jonkonrath.com/2015/05/29/photoshop-cc-keyboard-shortcut-cheat-sheet/</guid><pubDate>Fri, 29 May 2015 14:47:05 GMT</pubDate><content:encoded>&lt;p&gt;It seems like the days of cardboard key templates are over – they were a huge thing back in the old days when I started as a consultant in the computer labs back in college. Most of the cool kids would memorize everything, but more of the “returning” students would overlay the laminated cut-outs over the function keys for WordPerfect or Lotus 1-2-3.&lt;/p&gt;
&lt;p&gt;Anyway, I’m only an occasional Photoshop user – touching up screenshots, and making dumb collages of friends’ heads I post on Facebook. So I never remember anything. Here’s a great download for Mac users of Photoshop CC. (There’s also a Windows version mentioned.)&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://petapixel.com/2015/05/28/photoshop-cc-2014-keyboard-shortcut-cheat-sheet-for-mac-users/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;a href=&quot;http://petapixel.com/2015/05/28/photoshop-cc-2014-keyboard-shortcut-cheat-sheet-for-mac-users/&quot;&gt;http://petapixel.com/2015/05/28/photoshop-cc-2014-keyboard-shortcut-cheat-sheet-for-mac-users/&lt;/a&gt;&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Blank Markers in FrameMaker]]></title><link>https://www.jonkonrath.com/2015/04/20/blank-markers-in-framemaker/</link><guid isPermaLink="false">https://www.jonkonrath.com/2015/04/20/blank-markers-in-framemaker/</guid><pubDate>Mon, 20 Apr 2015 08:00:05 GMT</pubDate><content:encoded>&lt;div&gt;
  Here&amp;#8217;s a FrameMaker problem I had once on a 64-bit Windows machine. I don&amp;#8217;t remember having it on my next Win7 machine, but I&amp;#8217;ve seen it more than once.
&lt;/div&gt;
&lt;div&gt;
&lt;/div&gt;
&lt;div&gt;
  The problem: the marker symbols were missing. These are the little &amp;#8220;T&amp;#8221; symbols you normally see when you insert a cross-reference or an index marker.
&lt;/div&gt;
&lt;div&gt;
&lt;/div&gt;
&lt;div&gt;
  The solution: I did not have the &lt;code&gt;fm5font.ttf&lt;/code&gt; font installed. I don&amp;#8217;t know if the installer skipped it, or I did an install when I was supposed to upgrade, or I was just holding it wrong.
&lt;/div&gt;
&lt;div&gt;
  You can find this font in &lt;code&gt;C:\Program Files (x86)\Adobe\AdobeFrameMaker10\fminit&lt;/code&gt;. Double-click it to install, then reboot.
&lt;/div&gt;</content:encoded></item><item><title><![CDATA[Read the Docs]]></title><description><![CDATA[Here’s something neat I found recently, while looking for some api docs. It’s been around for a while, but you might not have seen it if you…]]></description><link>https://www.jonkonrath.com/2015/04/18/read-the-docs/</link><guid isPermaLink="false">https://www.jonkonrath.com/2015/04/18/read-the-docs/</guid><pubDate>Sat, 18 Apr 2015 16:00:11 GMT</pubDate><content:encoded>&lt;p&gt;Here’s something neat I found recently, while looking for some api docs. It’s been around for a while, but you might not have seen it if you don’t work with Python much.&lt;/p&gt;
&lt;p&gt;Check this out: &lt;a href=&quot;https://readthedocs.org&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;a href=&quot;https://readthedocs.org&quot;&gt;https://readthedocs.org&lt;/a&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;It’s a documentation repository, and you can find docs for a lot of Python projects there, in one searchable place. And you can host docs for your own project there, too.&lt;/p&gt;
&lt;p&gt;But what’s neat about it is you can author your docs in reStructuredText or Markdown, and have them built for online reading, or as an ePub or PDF for download. You can import docs from source control systems like git or subversion, and use hooks to automatically rebuild every time you push code.&lt;/p&gt;
&lt;p&gt;This is a pretty cool project with a lot of other features, and totally free, although you may want to &lt;a href=&quot;https://readthedocs.org/sustainability/#about&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;help them out&lt;/a&gt; with a few bucks, too.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[The FrameMaker Text Inset Header Problem]]></title><description><![CDATA[Here’s a FrameMaker thing that burns me once a year, usually a few hours before a release. So, you’ve done this: Created a text inset file…]]></description><link>https://www.jonkonrath.com/2015/04/15/the-framemaker-text-inset-header-problem/</link><guid isPermaLink="false">https://www.jonkonrath.com/2015/04/15/the-framemaker-text-inset-header-problem/</guid><pubDate>Wed, 15 Apr 2015 08:00:34 GMT</pubDate><content:encoded>&lt;p&gt;Here’s a FrameMaker thing that burns me once a year, usually a few hours before a release.&lt;/p&gt;
&lt;p&gt;So, you’ve done this:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Created a text inset file that begins with a Head1 paragraph style.&lt;/li&gt;
&lt;li&gt;Inserted that file as a reference in another file, at a point where the paragraph style was Body.&lt;/li&gt;
&lt;li&gt;Did a book update, and a blank Head1 was magically added right after the inset, causing a blank entry in the TOC. Didn’t notice this until after the book went to QA and they asked why this keeps happening.&lt;/li&gt;
&lt;li&gt;Went to the file with the reference, changed it back to Body, regenerated.&lt;/li&gt;
&lt;li&gt;Repeated step 4 for an hour or two and ended up throwing your computer out of a window.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Here’s how to get around it:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Delete the reference in the file and start over.&lt;/li&gt;
&lt;li&gt;On the line where you add the inset, make that line consist of nothing but a single nonbreaking space (Ctrl-space).&lt;/li&gt;
&lt;li&gt;Move the cursor/insertion point to right BEFORE the nonbreaking space and do a &lt;strong&gt;File &gt; Import&lt;/strong&gt; to add the inset.&lt;/li&gt;
&lt;/ol&gt;</content:encoded></item><item><title><![CDATA[The Hello, World Post]]></title><description><![CDATA[Hi and welcome to my page. This is mostly a “blog about this insane little problem so I’ll remember it in a year,” but maybe some of these…]]></description><link>https://www.jonkonrath.com/2015/04/14/the-hello-world-post/</link><guid isPermaLink="false">https://www.jonkonrath.com/2015/04/14/the-hello-world-post/</guid><pubDate>Wed, 15 Apr 2015 05:10:45 GMT</pubDate><content:encoded>&lt;p&gt;Hi and welcome to my page. This is mostly a “blog about this insane little problem so I’ll remember it in a year,” but maybe some of these factoids will be useful to you, too.&lt;/p&gt;
&lt;p&gt;Click on any of the above to learn more about me. Or keep scrolling to see my current blog posts.&lt;/p&gt;
&lt;p&gt;Thanks,&lt;br&gt;
Jon&lt;/p&gt;</content:encoded></item></channel></rss>