docs: function (content) {
    // start build pattern: will match
    //  * <!-- build:[target] output -->
    //  * <!-- build:[target](alternate search path) output -->
    // The following matching param are set when there's a match
    //   * 0 : the whole matched expression
    //   * 1 : the target (i.e. type)
    //   * 2 : the alternate search path
    //   * 3 : the output
    //
    var regbuild = /<!--\s*build:(\w+)(?:\(([^\)]+)\))?\s*([^\s]+)\s*-->/;
    // end build pattern -- <!-- endbuild -->
    var regend = /<!--\s*endbuild\s*-->/;
  
    var lines = content.replace(/\r\n/g, '\n').split(/\n/);
    var block = false;
    var sections = [];
    var last;
  
    lines.forEach(function (l) {
      var indent = (l.match(/^\s*/) || [])[0];
      var build = l.match(regbuild);
      var endbuild = regend.test(l);
      var startFromRoot = false;
  
      // discard empty lines
      if (build) {
        block = true;
        // Handle absolute path (i.e. with respect to the server root)
        // if (build[3][0] === '/') {
        //   startFromRoot = true;
        //   build[3] = build[3].substr(1);
        // }
        last = {
          type: build[1],
          dest: build[3],
          startFromRoot: startFromRoot,
          indent: indent,
          searchPath: [],
          src: [],
          raw: []
        };
  
        if (build[2]) {
          // Alternate search path
          last.searchPath.push(build[2]);
        }
      }
      // Check IE conditionals
      var isConditionalStart = l.match(/(<!--\[if.*\]>)(<!-->)?( -->)?/g);
      var isConditionalEnd = l.match(/(<!--\s?)?(<!\[endif\]-->)/g);
      if (block && isConditionalStart) {
        last.conditionalStart = isConditionalStart;
      }
      if (block && isConditionalEnd) {
        last.conditionalEnd = isConditionalEnd;
      }
  
      // switch back block flag when endbuild
      if (block && endbuild) {
        last.raw.push(l);
        sections.push(last);
        block = false;
      }
  
      if (block && last) {
        var asset = l.match(/(href|src)=["']([^'"]+)["']/);
        if (asset && asset[2]) {
          last.src.push(asset[2]);
  
          var media = l.match(/media=['"]([^'"]+)['"]/);
          // FIXME: media attribute should be present for all members of the block *and* having the same value
          if (media) {
            last.media = media[1];
          }
  
          // preserve defer attribute
          var defer = / defer/.test(l);
          if (defer && last.defer === false || last.defer && !defer) {
            throw new Error('Error: You are not supposed to mix deferred and non-deferred scripts in one block.');
          } else if (defer) {
            last.defer = true;
          } else {
            last.defer = false;
          }
  
          // preserve async attribute
          var async = / async/.test(l);
          if (async && last.async === false || last.async && !async) {
            throw new Error('Error: You are not supposed to mix asynced and non-asynced scripts in one block.');
          } else if (async) {
            last.async = true;
          } else {
            last.async = false;
          }
  
          // RequireJS uses a data-main attribute on the script tag to tell it
          // to load up the main entry point of the amp app
          //
          // If we find one, we must record the name of the main entry point,
          // as well the name of the destination file, and treat
          // the furnished requirejs as an asset (src)
          var main = l.match(/data-main=['"]([^'"]+)['"]/);
          if (main) {
            throw new Error('require.js blocks are no more supported.');
          }
        }
        last.raw.push(l);
      }
    });
  
    return sections;
  }