Thursday, December 14, 2017

Quick tip: Unwrap for Cheerio

Overview

I recently completed a request to parse, cleanup, and remove select elements from hundreds of HTML documents. Not a major task considering I have a node.js script in my toolbox that can handle this. At least, that's what I thought I had. When it came to removing select elements and leaving it's children elements and content intact, I found that there was a series of span elements wrapping around other elements. Apparently, the source documentation for these HTML files uses spans for all sorts of formatting features. Outside it's original source, these span elements serve absolutely no purpose. So, I was tasked with with removing them.

Like before, I figured I could use the cheerio module to use jQuery-like features (in particular unwrap to remove this unwanted element) and be done with it. Unfortunately, cheerio version 1.0.0 doesn't have an unwrap method.

After some time researching this problem, I found the contents method in cheerio and figured I can use this method to accomplish my task.

The code

Here is the entire code followed by the breakdown.

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

shell.ls('documents/*.html').map(function(file) {
  console.log('Unwrapping elements from ' + file);
  $ = cheerio.load(fs.readFileSync(file).toString());
  $('span[class^="unnecessary"]').each(function(i,elem) {
    var contents = $(this).contents();
    $(this).replaceWith(contents);
  });
  fs.writeFileSync(file,$.html());
});


Like most node.js scripts, we start off with requiring a few modules. Next we use shell's ls method to find all HTML documents in the documents directory and use the map method on this returned array to parse each found document.

Like before, we use cheerio to load each HTML document into the script with jQuery-like features.
Now, here is the tricky part: Find the element you want to remove, grab the content of said element and replace the selected element with it's contents. Essentially what this part of the script does is loads the selected element into an variable called contents and replaces the current element with the items of the content variable.

From there, we write out the modified document and carry on with the next one in the returned array.

Tuesday, November 14, 2017

Build an user macro with parameters in Confluence

Overview

Continuing off of last month's post entitled "Build an user macro in Confluence", this document will show you how to write an user macro that accepts input from the user. We will be creating an feature that allows for page redirects in Confluence. The macro will accept two inputs from the user: 1- page title to redirect the current page to and 2- delay before current page is redirect (which should include a default of 10 seconds). From there, the macro will display a basic redirect message, derived in part from the user's input, and load the target page after the delay has passed.

For this tutorial, you should have completed either last month's tutorial and/or Guide to User Macro TemplatesVelocity, and be comfortable with HTML and JavaScript.

Parameters

This user macro will take two user inputs: page title to redirect the current page to and a delay time. Let's take a look at these parameters and then break them down:

## @param URL:title=URL|type=string|required=true|desc=URL to redirect to.
## @param Time:title=Time|type=int|default=10|desc=Time to redirect (in seconds). Defaults to 10 seconds.


To declare a parameter, we use the ## @param <parameter name> definition. The parameter name can be anything as long as there are no spaces or starts with a number. It's a good habit to get into naming the parameter names by their purpose.

Next, we have the title of the parameter. The parameter is displayed in the macro's properties when entering the value for the parameter. Here, you can use any combination of characters and spaces as you see fit. The title value should be human readable.

To help the Confluence user macro determine what kind of value it is using and to make the user macro more user friendly, we define the type of input we are providing to the user macro. For the URL parameter, we declare the type to be a basic string (which means the value can be anything). For the Time parameter, we set the type to be int (integer (numbers only)).

For the URL parameter, we set a property called required to be true which tells Confluence that this parameter is mandatory. Not setting this parameter will result in an undefined value and thus disable the macro under it is defined.

For the Time parameter, we use the default property to provide the macro with a default value of 10 (seconds). This is a convenience for the user as they won't need to enter a value unless they want to use something other than the default value.

The last property in both of these parameters is the description (desc). This is the text that will be displayed in the user macro window when filling out the various parameters. You should strive to keep it short, simple, and direct to the point.

Macro Browser Information

As mentioned in the previous tutorial, you don't necessarily need to fill out every field in this section of the user macro but you are required to at least fill out the Macro Name and Macro Title. The others are up to you fill out as needed. But for this user macro I included the following values:
  • Macro Name: redirect
  • Visibility: Visible to all users in the Macro Browser
  • Macro Title: redirect
  • Description: Redirect current page to a new URL within a user specified time (seconds).
  • Categories: Navigation

Definition of User Macro

Since we won't be including any body information in this user macro, we'll set the Macro Body Processing to No macro body.

Template

For the template (code) of the user macro, we'll break it down into two sections: Setting Velocity variables and the rest of the code.

Setting Velocity variables

We set Velocity variable like this:
#set($variable=value)

For our macro's delay, we need to use the following to set up the input variable as milliseconds:

#set($timeOut= $paramTime + "000")

Here, we are setting the variable $timeOut to be the value of the Time parameter which the user supplies in the macro or the macro provides via it's default value.

Basic redirect message

Next, we need to set up the basic message that this page will redirect the current page to the target page.

<div id="redirectBox">This page will be redirected to <a href="$paramURL">$paramURL</a> in $paramTime seconds.</div>


Note the usage of the parameter variables and not the Velocity $timeOut variable so far. The code provides the wiki page with a few elements that displays a basic redirect notice and provides the user with a link in case the redirect function doesn't work automatically or the user wants to forego the delay and visit the target page sooner than later.

Redirect function

The last bit is the JavaScript function to redirect the page after the specified delay:

<script type="text/javascript">
  function Redirect() {
    window.location="$paramURL";
  }


  setTimeout('Redirect()', $timeOut);
</script>


Ideally, this JavaScript function would be included in a library that your Confluence server makes available globally but since it's a small and, hopefully, rarely used macro, it wouldn't hurt the page load time too much if we just include this function on every instance of the macro.

Complete macro code

## @param URL:title=URL|type=string|required=true|desc=URL to redirect to.
## @param Time:title=Time|type=int|default=10|desc=Time to redirect (in seconds). Defaults to 10 seconds.
#set($timeOut= $paramTime + "000")
<div id="redirectBox">This page will be redirected to <a href="$paramURL">$paramURL</a> in $paramTime seconds.</div>

<script type="text/javascript">
function Redirect() {
  window.location="$paramURL";
  }
setTimeout('Redirect()', $timeOut);
</script>



Resources

Saturday, October 14, 2017

Build an user macro in Confluence

As a tech writer, I often find myself using a good collection of Confluence macros in my documentation. So of the most commonly used macros are the table of contents, style, Jira issues, align, attachment, children display, html, and live search. There's actually dozens of macros that I utilize on a regular basis but I commonly use these in some in some combination with each other. For example, I use the table of contents macro nested within the align macro so I can avoid the dreaded long list of anchor links at the top of a document and have the table of contents listed in a floating (left) element so the content of the page can flow around it.

Wouldn't it be nice to combine some of these macros into one "uber macro"? In this tutorial, I'll walk you through the process to do just that: create a table of contents nested within a float left element.

User macro anatomy

Writing an user macro isn't for everyone. It requires some basic knowledge of how HTML and Confluence XML macros works. Plus any skills with CSS, JavaScript, jQuery, and Velocity would be to your benefit to create more advanced user macros. If you don't feel comfortable getting started with this tutorial, you can check out Guide to User Macro Templates by Atlassian for a good overview of what user macros templates are and how to write a basic user macro.

The typical anatomy of an user macro in Confluence looks something like this:
  • Macro settings
  • Macro definition
    • In-macro comments
    • Declaration of parameter usage (or not)
    • Template (macro code)
  • Detailed documentation (external to the macro)

Macro settings

Every macro must declare the following items:
  • Macro Name
  • Macro Title
These parameters of the user macro are required and the Macro Name should be all lowercase and unique. The Macro Title should reflect the Macro Name but you should be write it so it's human readable as this is the name of the macro that will appear in the macro browser.

The following macro settings are optional but highly encouraged to be filled out:
  • Visibility
    • You must decide if this macro will be available to everyone or to just the system admins
  • Description
    • This is the description of the macro that your users will see when selecting this macro from the macro browser
  • Categories
    • The macro browser can be sorted by different categories of macro. Choose yours accordingly. 
  • Icon URL
    • If an icon is not defined, Confluence will assign it a generic icon. For faster load times, the macro should be internal to your system. Historically, an icon can be hosted somewhere within the server as long as it is reachable by the standard user. Or, it could be hosted on a wiki page as an attachment.
  • Documentation URL
    • To say the least, this macro should be documented somewhere on the wiki

Macro definition

The Definition of User Macro is the section of the user macro that allows you to define the Macro Body Processing and it's Template.

Macro Body Processing options

The Macro Body Processing allows you to instruct Confluence how the macro should process the body before passing it your macro. The macro body is what gets display on the Confluence page, if the macro has a body that is.

Option for processing includes:
  • No macro body
    • Use this option if your macro does not utilize a body
  • Escaped
    • Use this option to render the contents of the body as HTML markup
  • Unrendered
    • HTML content will be processed before being rendered
  • Rendered
    • HTML content is rendered but doesn't guarantee that it will be rendered before the page finishes rendering. 
For our macro, we'll set this parameter to No macro body as we won't be utilizing any body elements.

Template

The Template is where you provide you macro with the code that it will utilize to render the desired results. You can use a combination of HTML and Confluence-specific XML elements, and Velocity.

In-macro comments

As an good code is well commented, user macros should utilize comments as well. To add a comment, you must use the #* comment *# format.

While it's not 100% necessary, it is helpful to include the two comments at the top of your macro: one sentence description (if the description is not filled out) and a link to it's documentation (if no link is provided for the Documentation URL). For the macro we will build in this tutorial, our comment should look something like this:

#* floatLeftToC is a left floating table of content *#
#* for more info, see <tiny url> *#

Parameters

Parameters allows the users to pass in options that the macro may use. Discussing the different options and features of macro parameters can be a whole tutorial in itself.

For the macro we are going to build, it won't take any options or parameters. Therefore, the parameter line in our code should look something like this:

## @noparams desc=Creates a left aligned floating table of contents

Code

For this macro, we want to wrap whatever content into a div element so we can float the element and it's content to the left of the page. To accomplish these, we can do the following:

<div style="float: left; margin: 0 10px 10px 0; padding: 5px 10px 5px 0; min-width: 50px; max-width: 250px; border: solid thin black; border-radius: 5px;">
  <ac:structured-macro ac:name="toc"/>
</div>

Ideally, the CSS would not be inline to the element we are using to wrap around the ToC. In my experience, the CSS should be a globally declared rule that Confluence makes available throughout your wiki.
Note: the border attributes in the style attribute is complete superficial. I like to use this when developing and/or debugging user macros that act as a container.

The nested structured-macro handles the table of contents thanks to a native Confluence macro.

Documentation

The documentation should include the following information:
  • Purpose
  • Usage
    • Intent
    • Parameters
  • Change history
  • Creator info
    • Name, email, etc.
  • Known issues and/or limitations
  • Links to related content
  • Attachment of the code
The purpose of the macro should be clearly defined with it's intent. One doesn't need to justify it's existence (as one assumes this macro was created out of a request or to fulfill an existing need).

The usage section should plainly define it's intended usage, and the parameters (if any) are used, and provide a few examples of the macro in use.

Depending on your work environment, you can include the change history of this macro (if you're not using Github or similar services). The same is true with the creator info and attachments of the code sections.

Depending on it's usage, you may want to include a section about known issues or limitations. While the macro should be designed to work with everything in the Confluence environment, it may not due to a multitude of reasons. Sometimes, the most innocent macro make work perfectly by itself but when combined with another, it may break the other itself or other macros. One recent example that comes to mind is a macro that wrapped a div element around an existing Confluence macro that changes the appearance of it via CSS. While this macro was written to only affect that one macro wrapped within it, it caused several issues with the non-wrapped macro on the same page.

Gotchas

It should be noted that if you have a typo anywhere in your macro's template, it will either fail to render the macro, display an error message, or at the worse, cause the page where the user macro is utilized to fail to render completely.
As a happy accident, while I was exploring which macro I should create, I failed to include the closing parentheses for some CSS rules. This caused the macro to not render and Confluence didn't inform me of anything wrong with the macro.

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.

Tuesday, February 14, 2017

Export Content from Confluence - Part 2

This tutorial is part two in the three series of how to export content from Confluence. In the previous tutorial, we covered how to export content from Confluence using it's native solution Export Content from Confluence - Part 1.

In this post, we'll explore the process of how to export content from our favorite wiki using Scroll's EclipseHelp plugin into an HTML zip file.

Setup

This document assumes that you have the Scroll EclipseHelp 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 EclipseHelp plugin version 3.5.0. Results may very with other versions.

Exporting using EclipseHelp
  1. Navigate to the top most page in the space you wish to export from Confluence.
  2. To start the process, go to menu for Tools > Export to EclipseHelp.
  3. If this is your first time using this plugin, you may see a few global templates to choose from. This tutorial opts to create an export using custom settings so you can see what is available via this plugin. In the bottom left corner, click on the Customize Settings option.
  4. From the General step, select the Default EclipseHelp Template from the Template option (selected by default).
  5. From the Export option, you can select what you need to export (the current page and it's children, only the current page, or the current page and any children with an user specified label). For this tutorial, we'll use the option to export the current page and all it's children.
  6. Click the Content Processing step next. From here, you have several options on what you want to export with your content like exporting the table of contents (toc), children, section, and numbered-headings macros, images with original resolution, and merging single, first heading and page title. To keep it simple, let's not include any of these options except for the images with the original resolution. By selecting this option, the process will download the original size of any and all images that are included on the selected wiki pages.
  7. Skip down to EclipseHelp Features. In this step, you can add any additional features you would like to include in your export. The features you choose to include in your export will be up to you but if the content you are pulling from Confluence is meant to be a stand-alone doc set, I would at least include the following:
    1. From the Index option, select the Create Index and Convert Labels to Index Terms. Including an index will generate additional documents called index.xml, toc.xml, and a few others associated with all your pages that you included in this export.
    2. From the Compatibility option, Export to doc.zip. Once the export has finished, everything will be nicely wrapped up in a zip file called doc.zip.
  8. In the File Naming step, you can define how the exported content should be handled. I normally leave this section alone as the default values work well for most common needs.
  9. With you export options selected, click the Start Export button to start the export process. Depending on the size of the space or page selection you made, Confluence will churn for a moment or two. You should see an indicator window pop up telling you where you are in the export process. Once Confluence has finished with the export process, you will see your browser download a doc.zip file.
  10. Upon the completion of the export, EclipseHelp will tell you the size of the content, how many pages you exported, how long the process took, and present you with a few options can you can use in the future to make this process go a little faster: Saving the export scheme, capture the ReST URL (for automation reasons), and managing the export schemes. If you know you will be exporting this space with these settings repeatedly, I recommend saving the export scheme you just created. Click the Save Export Scheme ... drop down and select as new.
  11. Decide if this export scheme will be used globally throughout your Confluence instance or localized to just this particular space.
  12. Provide a good name and description and click the Save button.
  13. If you wish to automate the process by using the ReST URL, you will need to save the export scheme first (see steps 9 through 12 to save the scheme).
  14. With the export scheme saved, you can now click the REST URL button to receive the URL you can use for automating this export process. 
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 EclipseHelp and select the export scheme you created in this tutorial.

Tuesday, January 10, 2017

Export Content from Confluence - Part 1

Intro

This post is the first of a three part series (part 2) of tutorials in which we'll explore the basics of exporting content from Atlassian's Confluence. This series will cover three different methods for exporting content from Confluence to a HTML format. In the first tutorial, we will cover how to use Confluence's native solution for exporting content to HTML and the pros and cons of this method. In later tutorials, we will cover how to use Scroll's EclipseHelp and HTML Export plugins to accomplish the same result but without the pitfalls that the native solution brings to the table.

Confluence has the capability of exporting the contents of a space to many formats such as PDF, Word, XML, and HTML. In this series, we will only focus on exporting to the HTML format. The reason why we will be focusing on the HTML format is that is a flexiable format that allows technical writers to apply post operations to the content prior to posting the content to it's final presentation form.

By the end of this tutorial, you should have a zip file with all the content you wish to export from Confluence in the HTML format.
  1. Navigate to the top most page in the space you wish to export from Confluence.
  2. Go to Space Tools  > Content Tools. The location of this link will vary depending on the theme you are using.
  3. Click on the Export tab.
  4. If you wish to export in HTML, select HTML from the Export Formats option and click Next. You can also choose from XML and PDF but those options will not be covered in this post.
  5. If you wish to export everything in your target space, select Normal Export. However, if you wish to export a particular set of pages, select Custom Export.
  6. By selecting Custom Export, you will be presented with every page in the space that can be exported (by default). 
  7. Click the Deselect All option and check off with pages you wish to export. If you select a page that has children pages, those pages will automatically be selected as well.
  8. If you wish to include comments with your select pages, leave the Include comments option enabled.
  9. With the pages selected, scroll to the bottom of the page and click Export. Confluence will churn for a moment and present you with a download link. Click the download link to receive your zipped file of HTML content.
This method is kind enough to generate an index.html file that lists, and links, the content you just generated along with space details at the top of the page, and document generation date in the footer of the page. This zip file will also include any and all images, and style sheets used in the pages you selected. If you were hoping that it would include any JavaScript code from features found on your Confluence pages, I'm afraid you're out of luck. While some JavaScript files may be exported, I didn't see any evidence of scripts that recreate the behaviors found in the macros typically used within Confluence.

Drawbacks

There are two drawbacks to this export method: 1: It isn't automatable. 2: No options to save export settings. I'm all about automating any documentation task. But, as far as I know, this method cannot be automated (please correct me if I'm wrong). Unlike the other export methods available to Confluence (see Scroll's plugin solution), this method doesn't offer any options to save the export settings or which pages to export.

Notes

If you applied any properties to the images found on your pages that you selected, they may not appear the same as before. At the time of writing this post, properties like floats and borders did not translate. The CSS rules and classes are in the code that is included in the export but the effects of the CSS didn't work out of the box.

This tutorial was tested on Confluence 5.6.4. Mileage may very on other versions.


Source

Exporting Confluence Pages and Spaces to HTML