let apiData = options => {
  options = options || {};

  if (typeof options === "string") {
    options = {name: options};
  }

  let root = DocsData[options.name];

  if (! root) {
    console.log("API Data not found: " + options.name);
  }

  if (_.has(options, "options")) {
    root = _.clone(root);

    let includedOptions = options.options.split(';');

    root.options = _.filter(
      root.options,
      option => _.contains(includedOptions, option.name)
    );
  }

  return root;
};

let changeNamesIfNeeded = nameList => {
  return _.map(nameList, name => {
    // decode the "Array.<Type>" syntax
    if (name.slice(0, 7) === "Array.<") {
      // get the part inside angle brackets like in Array<String>
      name = name.match(/<([^>]+)>/)[1];

      if (name) {
        return "Array of " + name + "s";
      }

      console.log("no array type defined");
      return "Array";
    }

    return name;
  });
};

let toOrSentence = array => {
  if (array.length === 1) {
    return array[0];
  } else if (array.length === 2) {
    return array.join(" or ");
  }

  return _.initial(array).join(", ") + ", or " + _.last(array);
};

let typeNames = nameList => {
  // change names if necessary
  nameList = changeNamesIfNeeded(nameList);
  nameList = _.flatten(nameList);

  return toOrSentence(nameList);
};

Template.autoApiBox.helpers({
  apiData: apiData,
  signature() {
    let signature;
    let escapedLongname = _.escape(this.longname);
    let params, paramNames;

    if (this.istemplate || this.ishelper) {
      if (this.istemplate) {
        signature = "{{> ";
      } else {
        signature = "{{ ";
      }

      signature += escapedLongname;

      params = this.params;

      paramNames = _.map(params, param => {
        let name = param.name;

        name = name + "=" + name;

        if (param.optional) {
          return "[" + name + "]";
        }

        return name;
      });

      signature += " " + paramNames.join(" ");

      signature += " }}";
    } else {
      let beforeParens = escapedLongname;

      if (this.scope === "instance") {
        if (apiData(this.memberof)) {
          beforeParens = "<em>" + apiData(this.memberof).instancename + "</em>." + this.name;
        }
      } else if (this.kind === "class") {
        beforeParens = "new " + escapedLongname;
      }

      signature = beforeParens;

      // if it is a function, and therefore has arguments
      if (_.contains(["function", "class"], this.kind)) {
        params = this.params;

        paramNames = _.map(params, param => {
          if (param.optional) {
            return "[" + param.name + "]";
          }

          return param.name;
        });

        signature += "(" + paramNames.join(", ") + ")";
      }
    }

    return signature;
  },
  typeNames() {
    if (Session.get("showAllTypes") && this.type) {
      return typeNames(this.type.names);
    }
  },
  id() {
    return this.longname && this.longname.replace(/[.#]/g, "-");
  },
  arguments() {
    return _.reject(this.params, param => !! this[param.name]);
  },
  specialArguments() {
    return _.map(this.params, param => {
      if (this[param.name]) {
        return {
          name     : param.name,
          arguments: this[param.name]
        }
      }
    });
  }
});

Template.api_box_args.helpers({
  typeNames() {
    return this.type && typeNames(this.type.names);
  }
});

Template.api_box_eg.onRendered(function() {
  hljs.configure({
    tabReplace: "  ",
    useBR: true,
    languages: ["javascript", "css", "json", "coffeescript"]
  });

  this.$("code").each((i, block) => hljs.highlightBlock(block));
});

@@ -498,121 +498,41 @@
 let 
-changeNamesIfNeeded = nameList =%3E %7B%0A  return _.map(nameList, name =%3E %7B%0A    // decode the %22Array.%3CType%3E%22 syntax%0A  
+matchArrayTypeInName = name =%3E %7B%0A
   if
@@ -563,26 +563,24 @@
 Array.%3C%22) %7B%0A
-  
     // get t
@@ -639,50 +639,145 @@
     
-  name = name.match(/%3C(%5B%5E%3E%5D+)%3E/)%5B1
+let regEx    = /%5E(%5B%5E%3E%5D+)%5C.%3C(%5B%5E%3E%5D+)/;%0A    let newName  = %22Array%22;%0A    let match    = name.match(regEx);%0A    let baseType = match%5B2
 %5D;%0A%0A    
   if
@@ -772,25 +772,29 @@
 %5D;%0A%0A    
- 
- 
 if (
-nam
+! baseTyp
 e) %7B%0A   
@@ -800,31 +800,178 @@
     
-  return %22Array
+console.log(%22no array type defined%22);%0A      return newName;%0A    %7D%0A%0A    if (match%5B1%5D.match(regEx) !== null) %7B%0A      newName += %22 of Array%22;%0A    %7D%0A%0A    newName += %22
  of %22 + 
 name
@@ -962,27 +962,31 @@
 += %22 of %22 + 
-nam
+baseTyp
 e + %22s%22;%0A   
@@ -986,81 +986,233 @@
 s%22;%0A
+%0A
     
-  %7D%0A%0A      console.log(%22no array type defined%22);%0A      return %22Array%22
+return newName;%0A  %7D%0A%7D;%0A%0Alet changeNamesIfNeeded = nameList =%3E %7B%0A  return _.map(nameList, name =%3E %7B%0A    // decode the %22Array.%3CType%3E%22 syntax%0A    if (name.slice(0, 7) === %22Array.%3C%22) %7B%0A      return matchArrayTypeInName(name)
 ;%0A  

Handle proper display of "Array of Array of Types".