docs: function plugin(options) {
    options = options || {};
  
    options.elements = options.elements || DEFAULT_ELEMENTS;
    options.langModule = options.langModule || 'hyphenation.en-us';
  
    if ((options.ignore !== undefined) &&
      (Object.prototype.toString.call(options.ignore) === '[object String]')) {
      options.ignore = [options.ignore];
    }
    debug('File ignore glob expressions: %j', options.ignore);
  
    try {
      var hypher = new Hypher(require(options.langModule));
    } catch (err) {
      console.log("Language module %s is not installed. Try 'npm install %s'",
        options.langModule, options.langModule);
    }
  
    /**
     * Check if a `value` is present in the array.
     *
     * @param {array} arr
     * @param value
     * @return {Boolean}
     */
    function isPresent(arr, value) {
      return arr.indexOf(value) < 0 ? false : true;
    }
  
    /**
     * Check if a `file` is HTML.
     *
     * @param {String} file
     * @return {Boolean}
     */
  
    function isHtml(file) {
      return /\.html?/.test(extname(file));
    }
  
    /**
     * Traverses throught parsed DOM, and hyphenate text nodes
     *
     * @param {String} domString
     * @return {String}
     */
    function hyphenateText(dom, forceHyphenateAllChildren) {
      if (dom.childNodes !== undefined) {
        dom.childNodes.forEach(function(node) {
          if (node.nodeName === '#text' && !isSkippable(node) && (forceHyphenateAllChildren || isPresent(options.elements, dom.tagName))) {
            node.value = hypher.hyphenateText(node.value);
          } else {
            hyphenateText(node, isPresent(options.elements, dom.tagName));
          }
        });
      }
  
      return dom;
    }
  
    /**
     * Check if the node is marked for skip
     *
     * @param {String} DOM node
     * @return {Boolean}
     */
     function isSkippable(node) {
      var result = false;
      if (node && node.parentNode && node.parentNode.attrs && Array.isArray(node.parentNode.attrs)) {
        node.parentNode.attrs.forEach(function(attr) {
          if (attr.name && attr.value && attr.name === HYPHENATE_DATA_ATTR && attr.value === 'false') {
            result = true;
          }
        });
      }
  
      return result;
     }
  
    /**
     * Check if the file matches the ignore glob patterns
     *
     * @param {String} file
     * @return {Boolean}
     */
    function isIgnoredFile(file) {
      if (options.ignore !== undefined) {
        var result = false;
  
        options.ignore.forEach(function(pattern) {
          if (minimatch(file, pattern)) {
            result = true;
            return false;
          }
        });
  
        return result;
      }
  
      return false;
    }
  
    return function(files, metalsmith, done) {
      setImmediate(done);
  
      Object.keys(files).forEach(function(file) {
        debug('checking if file matches ignore patterns: %s', file);
        if (isIgnoredFile(file) === true) {
          return;
        }
  
        debug('checking if it is an HTML file: %s', file);
        if (isHtml(file) === false) {
          return;
        }
  
        debug('hyphenating "%s"', file);
        var dom = p5.parse(files[file].contents.toString());
        dom = hyphenateText(dom);
        files[file].contents = new Buffer(p5.serialize(dom));
      });
    };
  }