Thursday, September 14, 2017

Quick Tips: New User Introduction to Documentation

Goals of introducing new users to your documentation should generally include generating excitement around the product and instruct users how to use the product. An optional step my include taking care of a one-time user account setup but let's not get carried away for our users first introduction to your documentation.

Overviews

While technical documentation may be rather bland at times, the introduction and/or overview pages are your chance to generate some excitement around the product and entice the new user to explore other facets of the documentation. Use of graphics should highlight the product's features and illustrate ease of use. Cross linking should be used but not abused.

Tutorials

Short tutorials and quick start guides are a great way to introduce new users to the product by showing them by how to use the product. Two good examples are Bootstrap's Getting Started and YoYo's introduction to Gamemaker Studio Basics. Each take a different approach to product introduction and both examples leave the user wanting more. Code samples should be well labelled and, if possible, executable. If videos are used, keep the short (under 5 minutes) and concise.

Registration

If your documentation site requires users to register, make sure it's quick and simple. A good percentage of users will be turned off by the notion that they must register before seeing the content they are seeking. One approach is to have a few pages that are open to everyone (like the introduction, overview, quick start, and maybe a handful of tutorials). If the user is still interested in your product after viewing the open pages, then they don't mind as much to register an account.

The three A's

Introducing new users to your documentation is a lot like an on-boarding process in a HR department. When a new employee starts, they are accommodated, assimilated, and accelerated into the company tools, culture, and value of those first two items. With product documentation, its very similar too:
  • Accommodate: give the new user the tools they need to use your documentation to their benefit (excellent navigation, search, current guides and tutorials, and well tagged documents)
  • Assimilate: help the new user to absorb the culture of the documentation site (e.g. use consistent terminology and navigation)
  • Accelerate: encourage the user by delivering the value of the product through easy to learn tutorials and apply documentation of the product (cross-linking tutorials with content found in guides)

Monday, August 14, 2017

Update: Using Node.js for Text Processing

Last month, I gave a lightning talk on "Using Node.js for Text Processing" at the Monthly Front End PDX Meetup and I'd like to share my slides and updated code sample in this month's post.

For the most part, my presentation didn't change that much but what did change is some of the methods I recently started using which made my code more efficient.

Requirements

The required modules section of the script stays the same:

var fs = require('fs');
var cheerio = require('cheerio');
var shell = require('shelljs');
...


Looping through the documents

For a little more efficiency, I didn't declare a variable to hold the list of HTML documents and instead, piped the shell method of ls directly into a map function which allows the script to loop through each item it finds in the /documents directory that matches the HTML file format.:

...
shell.ls('documents/*.html').map(function(file) {

   ...
}

Convert documents to a string

Then, load the document to a string with jQuery-like features (thanks to the cheerio module):

...
$ = cheerio.load(fs.readFileSync(file).toString());
...


Process content

Finally, we do an if/then statement to find what we are looking for, remove it, and save out the file:

...
if ($('div.footer').length > 0) {
  $('div.footer').remove();
  fs.writeFileSync(file,$.html());
}
...


The complete script

Here is the complete revised script:

var fs = require('fs');
var cheerio = require('cheerio');
var shell = require('shelljs');

shell.ls('documents/*.html').map(function(file) {
  $ = cheerio.load(fs.readFileSync(file).toString());
  if ($('div.footer').length > 0) {
    $('div.footer').remove();
    fs.writeFileSync(file,$.html());
  }
}


Friday, July 14, 2017

Inserting A Date Stamp into HTML Documents

Introduction

In Using Node.js for Text Processing, I showed you how a simple method to use Node.js processing content of HTML files. In this tutorial, I'll show you another technique for adding content to HTML files using Node.js as a command line interface (CLI) by supplying a script with arguments (flags), set up a basic help message, and append a date stamp to an user supplied HTML file. If this is your tune, let's jam!

Requirements

You should be fairly comfortable with JavaScript in general and have some working knowledge of how Node.js works prior to digging into this tutorial.

Required npm packages

In this tutorial, we'll need to ensure the following packages have been install in your project directory: 
Note: This tutorial was written with Node.js (version  ~0.12.7).

Building the script

First off, let's create a new file called append_date.js. As with any typical Node.js script, we start off with a few variables requiring our packages:

var fs = require('fs');
var cheerio = require('cheerio');
var program = require('commander');
...


In this snippet, we use fs to read in the target file, cheerio to manipulate the content with jQuery-like features, and commander for the CLI features of our script. Commander is a wonderful library that I recently discovered and works very well with my documentation and web developing needs.

Setting up the CLI

Like any well written CLI, we should start off with defining how it works. In the following snippet, we define the version of the CLI, how to use it (.usage), and any options (.option) available to the user. Commander is kind enough to provide a basic help output if the user types in <command> -h/--help as well as any usage and options you provide. Commander will display the default help message plus any info defined in the snippet below:

...
program
  .version('0.0.3')
  .usage('[required options] -t <path/file.html> -d <date>')
  .option('-t, --target [target]', '*required* target of HTML file (including the path and file name)')
  .option('-d, --date [date]', '*required* date to append to the HTML file')
  .parse(process.argv);
...

Main processing

Next, we check if both the target file and date flags have been supplied. From there, the script will load the target file and convert it to a string. The script will next check to see if a container element (div#content) exist and decide to create or update it. If the div#content element exists, the script will then look to either create or update the span.date element. With the elements in place, the script will now write out the updated HTML file.

...
if (program.target && program.date) {
  console.log('Updating ' + program.target);
  $ = cheerio.load(fs.readFileSync(program.target).toString()); // load file and convert it to a string

  if ($('div#content').length <= 0) { // if div#content doesn't exist, create it
    console.log(program.target + ' does not have div#content element. Adding it and datestamp now.');
    $('body').append('\t<div id="content">\n\t\t\t<span class="date">Last updated: ' + program.date + '</span>\n\t\t</div>\n\t');
  } else { // if div#content exists, look for span.date
    console.log(program.target + ' has div#content element; looking for date stamp')
    if ($('span.date')) { // if the span.date exists, update it
      console.log(program.target + ' has span.date element; updating it now');
      $('span.date').text('Last updated: ' + program.date);
    } else { // span.date doesn't exist; create it
      console.log(program.target + ' dos not have span.date element; adding it now');
      $('div#content').append('\t<span class="date">Last updated: ' + program.date + '</span>\n\t\t'); // add date under the content div
    }
  }

  var updated = $.html(); // collect updated html content
  fs.writeFileSync(program.target,updated); // save out updated HTML file
...



Fail checks

Like any good CLI, it should fail gracefully by informing the user that something was missing or failed in some way. To accomplish that, our script should check if the target and date flags were not filled out as they will be required for the script to carry out it's purpose. In the following code snippet, the first else if statement confirms if the target file wasn't supplied by the user. The second else if statement confirms if the user supplied a date flag. The final else statement is a catch all if something goes skips a beat.

...
} else if (!program.target) {
  console.log('Target for the HTML file was not provided; quitting.');
  process.exit(1);
} else if (!program.date) {
  console.log('No date stamp was provided; quitting');
  process.exit(1);
} else {
  console.log('undefined error; quitting');
  process.exit(1);
}

This completes the script. At this point, we should save the file and call it appendDate.js.

Note: this script doesn't verify the date string you enter into the span.date element. You could add a check for the program.date content to conform to a specific format using Regex (like /(\d[0-9]){2}-(\d[0-9]{1})-(\d[0-9]{1})/g) but that is entirely up to you.

CLI in action

With script completed, lets test it out on a simple HTML file. Copy the following code and save the file name as test.html in the same directory as your node script:

<!DOCTYPE html>
<html>
<head>
  <title>Date Stamp Test</title>
</head>
<body>
</body>
</html>


Let's test our script by executing the following command: node appendDate.js -t test.html -d 2017-03-30 (or whatever date string you wish to use). Examine the test.html. You should see our date stamp appended to the document with our custom date stamp.


Review

In ~40 lines of code, we created a script that takes arguments from the command line for a target file and a date string, loaded the target file, modified the target file with the date string, and wrote out the target file with the update HTML.

I hope this tutorial was useful and thank you for reading it.

Wednesday, June 14, 2017

Write the Docs 2017

This month's post includes my notes and thoughts from Write the Docs 2017 conference in Portland Oregon.
Overall, I had a very enjoyable and educational experience (just like last year). However, this year, I had the pleasure of volunteering to help set up the conference. I worked with a great team and look forward to volunteering again next year.

Error Messages: Being Humble, Human, and Helpful will make users Happy

Presented by Kate Voss
Make the error messages more human
  • Example of a very unhuman message: "Exception has been thrown by the target of an invocation."
Color warning message may be an issue to some users. Use icons in conjunction color.
Emoticons and/or graphics (humorous, cute, brand-related, etc.) puts a different face on the error message but keep in mind in needs to be appropriate for your brand and audience
Items to consider when writing error messages:
  • Put the important info first
  • Use fewer words
  • "Object first, action second"
  • Avoid passive verbs
Remember to:
  • Acknowledge
  • Apologize
  • Explain
  • Help

My take away: If you are tasked with making error messages "human", know your audience and write short but information messages accordingly.

Building Navigation for Your Doc Site: 5 Best Practices

Presented by Tom Johnson
  • Apply design principles ("Universal Principles of Design") to tackle your navigation problem:
    • Hierarchies break down complexity
      • Hierarchies give an idea of the "whole" and show potential related topics
      • Avoid deep nesting
    • Navigate from doc set to doc set
      • progressive disclosure
      • Layer information at different levels. For example:
      • doc portal home
        • product home
          • section hom
            • page
    • Allow navigation within content
      • Even in help, users want to stay inline (sidebar navigation vs. inline link); users are more inclined to click links inline to the document rather than the sidebar navigation
      • Use bottom-up navigation
      • If the viewer reads something that he can do, use, or consider (concept), link it to the respective document
      • Too many links may cause issues with the viewer's decision points (for example Wikipedia entries)
    • Make popular topics easy to access
      • Desire line: "traces of use or wear that indicate preferred methods of interaction with an object or environment" - UPoD
    • Reduce information fragmentation
      • Modularity - "A method of managing system complexity that involves dividing large systems into multiple, smaller self-contained systems" - UPoD
      • Building blocks != presentation
    • Hang signposts along the way
      • wayfinding
      • Example: breadcrumb navigation
      • In a linear guide set, add a link (system) to where to go next

My take away: when building navigation for your doc site, keep these ideas in mind:
  • Use hierarchies to break down complexity
  • Build navigation by category
  • Include navigation elements within the content (sidebars and inline links)
  • Use metadata content linking to make popular topics easier to access
  • Reduce information fragmentation
  • Make navigation easy and clear to use

Christy Lutz - You Have Already Succeeded: Design Critique Guidelines Make Feedback Easier

Presented by Christy Lutz
"Feedback makes you stronger."
Ask questions (to yourself or your teams) on how to ask, give, and deal with feedback.
Feedback leads to better working relationships.
Feedback works (it makes things better. Every time.)
What do you need to start using Design Critique Feedback:
  • Identify stakeholders (including you)
  • Create a scope statement
Write down feedback guidelines (ask for what you need)
How do you start?
  • Just start
  • Listen and repeat
  • Anyone who tells you differently is selling something (you don't need to sell your work)
How do you get people involved?
  • Throw a feedback party
  • Utilizing stickers can be fun and creative resource
Schedule a design review
Gather feedback anywhere and everywhere
How do you give feedback?
  • Criticism
    • passes judgement - Critique poses questions
    • finds fault - critique uncovers opportunity
    • is personal - critique is objective
    • is vague - critique is concrete
    • tears down - critique builds up
    • is egocentric - critique is altruistic
    • is adversarial - is cooperative
    • belittles the documenter/documentation - improves documentation
  • You are a person
Tell me, how do you feel? Ask questions.
The goal of the project is the goal of your feedback. Your role is the Defender of the Goals
Defend yourself (defend the feedback to yourself)
How do you deal with feedback? A.K.A., how can I be feedback royalty?
  • Build up an immunity
  • You are not a documentation vending machine. You own it.
How do you measure your results
  • Follow up on the things you don't understand
  • Does this support the goals of the project?
  • For some feedback, the answer is going to be "no"
Feedback is opportunity for discussion
How do you report your results
It's not about winning
Your goal is not about making everyone happy
Teach design critique guidelines to your team

My take away: Feedback is necessary to build better documentation and relationships with your [product] teams and is an opportunity for discussion.
Develop a feedback system that includes:
  • Identifying stakeholders
  • Defining the scope/goal(s)
  • Setting guidelines
  • Scheduling reviews
  • Measuring results
Feedback is often you (the tech writer) just repeating back what you heard in your terms.
Getting people involved can vary from company to company but the common advice is to make it fun for everyone.
Know the difference between criticism and feedback (negative vs positive). Often time, feedback is little bit of a positive and negative experience (so build up an immunity).
Follow up on things you don't understand.

Testing: It's Not Just for Code Anymore

Presented by Lyzi Diamond
Testing your documentation is good (even if it is informal or formal).
Good documentation pays attention to the small things:
  • Consistency
  • Completeness
  • Correctness
  • Contributability
Without automated testing, their documentation would fail.

My take away: Reviewing and/or testing documentation for consistency, completeness, and correctness should be important to every doc writer. With formal (automated testing) or informal reviews, this can be achieved with ease (once a process has been set up).

Even Naming This Talk Is Hard

Presented by Ruthie BenDor
  • All the good names are already taken
  • Because the good names terms are already taken overloaded
  • Because naming is reduction and we are bad at choosing what to exclude
  • Because names evoke, and we are bad at anticipating that
  • Blacklist and whitelist vs blocklist and allowlist - internal/social context awareness
  • Because naming matters when even (especially when) we think it doesn't matter
  • Why do bad names persists?
    • Because we don't realize they are bad
    • Because we recognize the name is bad but can't or won't justify fixing it
      • sentimental
      • humans hate change
      • overestimated cost of change
      • underestimating value of improved name (projection)
  • What makes a name good or bad?
    • bad names
      • confuse, frustrate, misguide, obscure, and offend
    • good names
      • contextualize, explain, illuminate, and empower
  • How can we name software better?
    • documentarians: let developers know when their names miss the mark
    • developers: writing software is an exercise in naming things

My take away: Naming software is often difficult for many reasons including:
  • good name are already overloaded
  • people are bad at [product] reduction
  • names evoke thoughts and images (both good and bad)
  • some people think it doesn't matter (but it does!)
Bad name persist because [product owners]:
  • don't realize it's bad
  • won't justify fixing it for many reason
bad names confuse, frustrate, misguide, obscure, and offend while good names contextualize, explain, illuminate, and empower
How can we name software better? Get everyone (tech writers and developers) together to have a discussion and go through a few writing/naming exercises.

Everyone's a Player (in a Mid-90s MUD)

Presented by Kenzie Woodbridge
There typically four player types: socializer, explorer, achiever, and killer
Document in game design should emphasis interactive over acting by helping facilities produce vague information and produce cryptic hints when players appear to be stuck
Ways to emphasize acting over interacting:
  • Provide a manual
  • Include auto-map and auto-log facilities
Socializers are natural documenter; they need your support
  • Provide templates, assist with publishing, impose a structure and organization
  • Advocate for them to others, Work to include them where they are excluded, give them public kudos
Explorers are anti-documentation; extract the info from them
  • Documentation: shows off expertise, keeps icky users away (no pestering), is another thing to have knowledge of
  • Reduce barriers (provide templates), rewrite the docs for the audience, help enforce expectation to look at docs first
Achievers are inconsistent documenter; turn it into a game for them
  • To motivate achievers: post doc writing/review stats, make doc authors visible, advocate for docs as critical success criteria in projects
  • Be available on short notice, provide and enforce templates, publicly thank them
Killers are inconsistent documenter and have an element of destructive chaos (power hoarder); get them to document something
  • Self-protection strategies: keep discussions public, document everything (ironically), engage Explorers in the struggle
  • Treat agreements like agreements, follow up, follow up again

My take: As a tech writer, you'll encounter and need to motivate four different personalities for the purpose of getting them motivated to contribute to the documentation base: socializer, explorer, achiever, and killer.
  • Socializers are a natural documenter but they'll need your support. To keep them motivated, provide public kudos from time to time.
  • Explorers are anti-documentation so you'll have to extract the information from them. To get them involved, show them the value of documentation and provide templates as a starting point.
  • Achievers are inconsistent in their documentation efforts but you can turn that behavior around by turning it into a game. To keep the game lively for them, provide stats and reviews periodically, enforce templates (as necessary), and publicly thank them.
  • Killers are inconsistent too but also are power hoarders and getting them to contribute will be very difficult. Employ a self-protection strategy by keeping discussions public, document everything, and treat agreements like agreements. Finally, follow up on your follow-ups.

Treating Documentation Like Code: A Practical Account

Presented by Jodie Putrino
How do we get there?
  • Choose the right tools
  • Automate
  • Collaborate
  • Define, then, design
  • Adapt
"We're all doc writers now." Don't worry about grammar and spelling, I (the tech writer) will correct that.
Questions they had to answer prior to building, publishing, and implemented their documentation:
  • Who are our users?
  • What are they trying to do?
  • How do they use/find our docs?
  • What kinds of docs do we want/need to publish?
  • Content reuse?
  • What should the docs look like?
  • How do we handle versions?
  • How do we track usage?
  • Can we get user feedback?
  • When do we publish?
  • How do we handle beta releases?
"The process is not the thing. It's always worthing asking, do we own the process or does the process own us?" - Jeff Bezos

My take: Treating document like code is good if your organization supports this process. To get there, choose the right tools, automation processes, and design.
Make everyone a doc writer and ensure them that you don't have to worry about the minute details (we the tech writers will fix it).
Ask your team the following questions when it comes time to implement, build, and publish documentation:
  • Who are our users and what are they trying to do?
  • How do they use/find our docs?
  • What kinds of docs do we want/need to publish?
  • Content reuse?
  • What should the docs appear?
  • How do we handle versions and track usage?
  • Getting and using user feedback?
"The process is not the thing. It's always worthing asking, do we own the process or does the process own us?" - Jeff Bezos

Interviewing and Hiring Technical Writers: The Siberian Way

Presented by Sam Faktorovich
Necessary skills for a tech writer typically include:
  • Some technical skills (CS fundamentals, OS knowledge, ability to read code)
  • Capability and willingness to write documentation
Knowing how to write well != knowing how to teach others to write
One approach to grow your tech writer base is to high a non-technical writer and give them a two month crash course in CS (results may vary).
Pre-interview assignment task:
Write a medium size (1-2 pages) document describing a complex technical topic
  • Topic defined by them
  • ...? (missed the slide)
  • Shouldn't mimic their typical day-to-day documents
  • Should show candidate's capability to explain complex things
"Teach, don't tell" - Steve Losh
Tests:
  • Easy: Explain the difference between HTTP and HTTPS
  • Difficult: Explain the difference between UTF-8 and UTF-16
Other approaches to hiring tech writers
  • Recruit your own developers?
  • Grow the job market itself? This approached worked for them:
    • Teach tech writing class at one of the local universities
    • Public lectures promoting the profession
    • Technical writing bootcamps
    • Corporate consulting on setting up documentation dept/process

My take: Hiring a tech writer can be difficult if that field is lacking candidates. Do you teach a developer to write or a (non-tech) writer to learn how to read code? Both have their pros and cons. Teaching either candidate can be a painful training process if your company goes at it themselves but if you build a community around this need, it will could be a well rewarding experience for everyone.
Consider giving your candidates a writing test:

  • Easy: Explain the difference between HTTP and HTTPS
  • Difficult: Explain the difference between UTF-8 and UTF-16

Sunday, May 14, 2017

Jira Dashboards

I recently gave a presentation on how to creating and managing Jira dashboards to a group of tech writers. This post recounts the topics and points I presented which include creating a dashboard from scratch, copying existing dashboards, modifying the layout, adding widgets and gadgets, and saving filters.

Creating a dashboard from scratch

When creating a new dashboard in Jira, you'll want to follow a few guidelines to make your dashboard useful:
  • Give it a good descriptive name. I tend to give my boards a name based on it's function. For example, if I need to keep an eye on all projects assigned to me that are open and are of critical importance, I'll called it something like "Critically assigned to me" (little humor there).
  • While not necessary, I enter a good description as to the purpose of this dashboard. Adding a description can definitely help future-proof your dashboard as most tech writers I know who religiously use Jira tend to have multiple dashboards.
  • You can start from a blank dashboard or use one other existing dashboards available to you. While it may be tempting to template off an existing dashboard, you may end up doing a lot of customization and removal of unnecessary widgets to get exactly what you want. 
  • Sharing is important. By default, the dashboard you create is restricted to you (by default). You can keep the dashboard all to yourself or can share it with everyone or whomever you like. If you are working with a team or other needs access to your dashboard, you will need to enable sharing with others.
Note: sharing a dashboard with everyone does not mean including non-employee users. That is a completely different setting that is tied to Jira projects. Sharing grants access to everyone who has access to your Jira instance.

Copying existing dashboards

If you decide to go the route of copying an existing dashboard, you will need to keep the following information in mind when going this route:
  • You can copy available (shared) dashboards as one of your own. You are creating an original instance of the existing dashboard with all of it's widgets and settings as is. None of these widgets or settings are tied back to the original dashboard.
  • Any changes you make to your copy of the dashboard doesn't affect the original. There's no tie-backs or dynamic linking or anything like that to these dashboards.
  • Give the dashboard a good descriptive name. I urge you not to call it "Copy of <such and such> dashboard" (as noted above).
  • Add a good description (as noted above).
  • Decide if this dashboard will be shared or not. This decision will totally be up to you (and your team) depending on your needs with this cloned dashboard.

Layouts

Modifying the layout of a dashboard is simple as drag and drop if you wish to re-arrange the widget's positioning.
  • This is totally up to your needs for your dashboard. If you have just one big widget, then I'd go with the single panel layout. Otherwise, I would recommend the equal two panel layout to help minimize page scrolling. Some of the widgets available in Jira can get pretty unwieldily if a single panel layout while others seem crowded in a two or three panel layout.
  • Personal note: I don't recommend the three panel layout. Depending on which widgets one uses, this layout tends to squish the content to an unfriendly reading experience. But that also depending on how big your monitor is and what resolution is available. On my little Macbook, if find that two panel layouts work very well.

Adding gadgets

Adding new gadgets and widgets can be done via edit mode of the dashboard. Go to Tools and click the Edit Dashboard Add Gadget button. From here, you add and/or remove gadgets and widgets and adjust the layout as you see fit.
Jira comes packed with tons of great and useful widgets. Plus, you have the ability (though not necessary the capability) to add or purchase more gadgets.

Here are some of my recommendations for building a useful and informative dashboard. These gadget recommendations are for active projects. There is a whole different mindset on dashboard for reporting on project progress and project reviews. The following list is geared toward tech writers who need to keep a tab on project activity, ticket resolution, custom filters, and date-based events:
  • Activity Stream: Depending on how your Atlasssian platform is set up, this gadget can report on both Confluence and Jira activities (and any other connected Atlassian product), apply filters to the stream, and so on. I find this widget useful when I've been out of the loop for a day or three and need to catch up on what my team has been up to while I was offline.
  • Assigned to me: the name kinda says it all. This widget will list all tickets assigned to logged in user. Note that is lists tickets to the logged in user. Even though this may appear on your dashboard, it will not show tickets assigned to if someone else is looking at your dashboard.
  • Created vs. Resolved chart: this gadget is useful only if your team likes to see that kind of reporting over a period of time for a particular project or filter.
  • Favorite Filters: if you have a collection of filters, this is a handy "bookmarking" tool to keep track of them.
  • Filter Results: this gadget is the bread and butter of my dashboards. Its highly customizable and best of all, it takes whatever filter you create for it. For a more informative guide on how to create and save a filter, see Atlassian's guide called Saving your search as a filter.
  • Heat Map: Heat maps are fun and informative to look at but lose their functionality when you have too many matching issues.
  • Jira Issues Calendar: Good calendar view of what tickets were created and/or updated in a simple icon (tick) display.

Creating filters

Creating a filter is as simple as searching in Jira. After you've entered in all the variables you wish to search against and the issues are displayed, you can save the search results by clicking the Save As button.
  • Give this filter a good descriptive name as you'll want to use it again and again.
  • I recommend a functional name (as in what you searched against).
  • Avoid using dates in the name unless the search is time constrained.
For example, if I need to save a search against a members of my team (doc-team), limited to a particular project (Docs), and the priority is "high", I would name the saved filter as "High priority in Docs for doc-team".


Summary

While this is a far cry from a complete guide on how to set up a Jira Dashboard, I believe it is a good start and I will likely expand on this post in the near future. In this post, we looked at how to create a dashboard (from scratch or by copying and modifying an existing one), customizing the layout to suit your needs, adding widgets and gadgets, and how to save a Jira search as a filter.

Friday, April 14, 2017

Automating Content Extraction From Confluence Using Exporter Plugins and Bash

Intro

As a technical writer, one of the many tasks I must work with on a regular basis is pulling content from multiple sources and compiling them into a source file for publication. Early on, the process I used was a very hands on process of manually generating a compressed file from Confluence and other sources, manipulate the contents of the extracted content, bundle everything up, and publish the refined package.

This tutorial's goal is to get novice users familiar with one method of automating content extraction by using a simple Bash script file that pulls content from Confluence using an exporter scheme URL.

The process contains two components: an export scheme URL and a Bash script. I have written two tutorials on how to extract content using two of Scroll's exporter plugins. Refer to Part 2 and/or Part 3 in the Export Content from Confluence series for details on how to generate the export URL using either Scroll's EclipseHelp or HTML Exporter plugins. You will need to complete at least one of these tutorials in order to complete this tutorial as you will need the export scheme URL. The Bash script we will create handles the manual part of extracting content from Confluence.

This tutorial is written for Mac users. The Bash features used in this document has not been tested on Linux but you know your way around wget, this tutorial should work just fine.

Prerequisites

Confluence Command Line Interface

Did you know that Confluence has a CLI? Check out and install Confluence Command Line Interface (CLI) as we may need it to gain access to Confluence via the command line to check against extracted content but I'll leave that up to you to decide if you want to use it or not.

For installation, please review Confluence CLI Installation and Use.

For getting started, reference, examples, and much more info, please review Confluence CLI User's Guide.

wget

Another component to automating the export process is using a command line network transfer tool such as wget. There are a few options out there for handling CLI transfers (such as curl) but I've found wget to be rather flexible, handles redirects well, and stable for my documentation needs. If you have arguments for or against, I'd love to hear them in the comments.

Setting up a "docbot" account for export

Prior to automating the export process from Confluence, you will want to create a non-human account that only has view and export permissions. If you don't plan on sharing or automating content extraction from Confluence, you can use your personal account but I've seen many tech writers get bitten by using their personal accounts.

In this case, I named this new account "docbot". If you don't have the proper credentials to create Atlassian accounts, please contact your Confluence administrator and request the account be created. Otherwise, create a new user account:
  1. Navigate to the Confluence Admin page.
  2. Click on Users under Users & Security section.
  3. Click Add Users.
  4. Enter docbot in Username field.
  5. Enter docbot in Full Name field.
  6. If you have a group email address that is shared with the tech writers, I recommend using that for the Email field. Otherwise, enter your email address.
With the docbot account created, we need to provide it with the proper permissions.
  1. Navigate to your target space's Space Admin page and click on Permissions.
  2. Under the Individual Users section, click the Edit Permission button.
  3. Locate the docbot account and enable only the following permissions:
    • All > View
    • Space > Export
  4. Once those two permissions have been set, click Save all.
Your docbot account should now have the proper permissions to export content from Confluence.

Bash script

Once you have ran through the process of creating and saving an export scheme from either one of the aforementioned plugins, you will need to apply the REST URL in our Bash script.

The Bash script will contain up to four lines: up to three variables and one command. You may wish to add a few additional lines before and after the export process to set up directories like adding a few commands for setting up an export archive and post processing the downloaded file (like renaming the .jar file to a .zip file, unzipping, it and so on).

...
USER='docbot'
PASS='<docbot's password>'
URL='<exporter scheme URL>'

wget --content-disposition "$URL&os_username=$USER&os_password=$PASS"
...


Breakdown of this script

The first three lines are just variables we will pass into the wget command. The fourth line is the backbone of the whole operation. Lets example each component of this command:
  • wget - network transfer command
  • --content-disposition - flag that will force the download to preserve the file name. Note: This flag is will experimental though I've never hand any problems with it.
  • "$URL&os_username=$USER&os_password=$PASS" - string that gets passed into the wget command. When pulling content from Confluence using the exporter scheme URL, you need to specify the exporter URL, provide the user requesting it (which it get checked for proper credentials, and the password). If everything checks out properly on Confluence's side, your command will pull down a compressed file based on the settings in your exporter scheme.
As mentioned earlier, one could use curl to pull content from Confluence but I found that command to be unreliable at times on my Mac. Maybe it was may flag options or some other setting but wget has worked very well for me for years using this configuration.

Note: if your Bash script will be shared with other users or in a hosted environment, you may want to localize the USER and PASS variables in your Bash profile.

From here, you can add any steps to the Bash script to include post processing, executing node scripts to modify extracted content, or whatever else you need to include in this automated process. Or, if you need to use this process on a regular basis, you can simply set a cron or Jenkins job.

Happy automating!

Tuesday, March 14, 2017

Export Content from Confluence - Part 3

Intro

Welcome to the final tutorial of this three part series on how to extract HTML content from Confluence.

In the previous two tutorials, we explored how to export content using Confluence's native solution Export Content from Confluence - Part 1 and Export Content from Confluence - Part 2. In this tutorial, we will run through the steps to generate HTML content into a zip file from an user selected space in Confluence using Scroll's HTML Exporter plugin. The biggest difference in using this plugin versus EclipseHelp Exporter, is that plugin offers the option to generate a search index of your extract content and the wiki's space logo will be a part of the final presentation.

Setup


This document assumes that you have the Scroll HTML Exporter plugin installed and properly enabled and that your user account has the proper credentials (at least view and export permissions) for exporting and plugin usage. If it's not, contact your Confluence administrator and request it to be set up.

This process was tested on Confluence 5.6.4 and Scroll HTML Exporter version 3.5.0. Results may very with other versions.

Exporting using HTML Exporter


  1. Navigate to the top most page in the space you wish to export from Confluence.
  2. Go to Tools > Export HTML.
  3. Click Customize Settings in lower left corner. For this tutorial, we are going to customize the content will wish to pull from Confluence.
  4. In the General step, you will need to make some choices depending on the needs of how and what you want to export from Confluence:
    1. In the Create drop down, you can choose between one HTML file for each Confluence page or a single large HTML file. For this tutorial, we'll be using the former option to export our content to the HTML format.
    2. Since this may be our first time using this plugin, the Template drop down will just list one option, Scroll WebHelp Template. This tutorial will not cover how to create HTML templates.
    3. With the Export option, we'll select This page and its children so we can collect every page starting with the current page and all of it's children.
  5. In the Central Processing step, you will have several options to output a few macros with your content, exporting images with original resolution, converting labels to index terms, and merging single, first heading and page titles. For this step, only enable the Export images with original resolution. If your pages in Confluence used the other macros previously listed and you need your exported content to use them, go ahead and enable those as well. Otherwise, leave those options disabled. I have found that exporting the content in as raw form as possible works best when attempting some post processing in my documentation publication scripts.
  6. In the File Naming step, we can leave the settings to their default values. These settings works very well with the vast majority of export settings and the content coming from Confluence.
  7. In the Search Index step, depending on your export needs, you may want to leave this option disabled. For this tutorial, leave it disable. When enabled, the plugin will generate a full text search index and add it to the exported content. Note: if you decide to export your content into one large HTML file, this feature won't be supported.
  8. Click Start Export and wait a moment or two while Confluence churns on the request. An Export in Progress window will appear informing you of the content export status (pages processed versus total number of pages in the request).
  9. Once the request has finished, your browser will download a zip file with the name of the page you selected to start the process from followed by the version number of the page, a date stamp of when it was exported, and a time stamp (set by the server clock). For example, your zip file name may look like this: Home-v12-20170104_1435.zip. The Export Result window will present with the size and number of pages in the export and how long it took. This window will also allow you to save the export scheme you just created, collect the ReST URL, and manage export schemes. If you are going to use this export process repeatedly, you should follow these steps:
    1. Click the Save Export Scheme ... button and select as new from the drop down. 
    2. In the Save new Export Scheme window, decide if this scheme will be used only in the current space or in all spaces (globally). For this tutorial, select in this space.
    3. Provide a good descriptive name and description in their respective fields.
    4. Click the Save button.
  10. Optional: back in the Export Result window, you can collect the ReST URL if you wish to automate the process in the future. Click the REST URL button and copy the URL listed in the middle of the REST URL window. Save this URL for your automation script.
  11. Optional: back in the Export Result window, you can manage the export schemes in either the current space or in all spaces (globally). A new browser window will open up and present you with options to modify any export schemes you may already have. That is, if you have the proper user permissions to see or edit features in the Space Admin page of the current space.
With the completion of this tutorial, you should have an HTML copy of your selected content and an export scheme that can be used repeatedly to pull content from your desired space in Confluence into an HTML zip file without having to go through this entire process again.

For future exports, all you need to do now is go to Tools > Export to HTML and select the export scheme you created in this tutorial.