docs: function sourceReplacer(source, replacements) {
  
    // shared
    var getBefore = getField('before');
    var getAfter  = getField('after');
  
    // split source code into lines, include the delimiter
    var lines = source.split(/(\r?\n)/g);
  
    // split each line further by the replacements
    for (var i = 0; i < lines.length; i += 2) {
      var split = lines[i] = [].concat(lines[i]); // initialise each line text into an array
      for (var before in replacements) {
        var after = replacements[before];
        split.forEach(splitByReplacement(before, after));
      }
    }
  
    // utility methods
    return {
      toStringBefore: toStringBefore,
      toStringAfter : toStringAfter,
      getColumnAfter: getColumnAfter
    };
  
    /**
     * String representation of text before replacement
     * @returns {string}
     */
    function toStringBefore() {
      return lines.map(getBefore).join('');
    }
  
    /**
     * String representation of text after replacement
     * @returns {string}
     */
    function toStringAfter() {
      return lines.map(getAfter).join('');
    }
  
    /**
     * Get a column position delta as at the given line and column that has occured as a result of replacement.
     * @param {number} lineIndex The line in the original source at which to evaluate the offset
     * @param {number} columnIndex The column in the original source at which to evaluate the offset
     * @returns {number} A column offset in characters
     */
    function getColumnAfter(lineIndex, columnIndex) {
      if (lineIndex in lines) {
        var line   = lines[lineIndex];
        var count  = 0;
        var offset = 0;
        for (var i = 0; i < line.length; i++) {
          var widthBefore = getBefore(line[i]).length;
          var widthAfter  = getAfter(line[i]).length;
          var nextCount   = count + widthBefore;
          if (nextCount > columnIndex) {
            break;
          } else {
            count   = nextCount;
            offset += widthAfter - widthBefore;
          }
        }
        return columnIndex + offset;
      } else {
        throw new Error('Line index is out of range');
      }
    }
  }