extensions/amp-analytics/0.1/variables.js
/**
   * @param {string} template The template to expand
   * @param {!ExpansionOptions} options configuration to use for expansion
   * @return {!Promise<!string>} The expanded string
   */
@param {string} template The template to expand
@param {!ExpansionOptions} options configuration to use for expansion
@return {!Promise} The expanded string
@param { string } template The template to expand @param { !ExpansionOptions } options configuration to use for expansion @return { !Promise } The expanded string
expandTemplate(template, options) {
    if (options.iterations < 0) {
      user().error(TAG, 'Maximum depth reached while expanding variables. ' +
          'Please ensure that the variables are not recursive.');
      return Promise.resolve(template);
    }
    const replacementPromises = [];
    let replacement = template.replace(/\${([^}]*)}/g, (match, key) => {
      const tokens = key.split('|');
      const initialValue = tokens.shift().trim();
      if (!initialValue) {
        return Promise.resolve('');
      }
      const {name, argList} = this.getNameArgs_(initialValue);
      const raw = options.vars[name] != null ? options.vars[name] : '';
      let p;
      if (typeof raw == 'string') {
        p = this.expandTemplate(raw,
            new ExpansionOptions(options.vars, options.iterations - 1,
                true ));
      } else {
        p = Promise.resolve(raw);
      }
      p = p.then(expandedValue =>
            this.applyFilters_(expandedValue, tokens))
        .then(finalRawValue => {
          const val = options.noEncode
              ? finalRawValue
              : this.encodeVars(finalRawValue, name);
          return val ? val + argList : val;
        })
        .then(encodedValue => {
          replacement = replacement.replace(match, encodedValue);
        });
      replacementPromises.push(p);
      return match;
    });
    return Promise.all(replacementPromises).then(() => replacement);
  }
expandTemplate ( template , options ) { if ( options . iterations < 0 ) { user ( ) . error ( TAG , 'Maximum depth reached while expanding variables. ' + 'Please ensure that the variables are not recursive.' ) ; return Promise . resolve ( template ) ; } const replacementPromises = [ ] ; let replacement = template . replace ( / \${([^}]*)} / g , ( match , key ) => { const tokens = key . split ( '|' ) ; const initialValue = tokens . shift ( ) . trim ( ) ; if ( ! initialValue ) { return Promise . resolve ( '' ) ; } const { name , argList } = this . getNameArgs_ ( initialValue ) ; const raw = options . vars [ name ] != null ? options . vars [ name ] : '' ; let p ; if ( typeof raw == 'string' ) { p = this . expandTemplate ( raw , new ExpansionOptions ( options . vars , options . iterations - 1 , true ) ) ; } else { p = Promise . resolve ( raw ) ; } p = p . then ( expandedValue => this . applyFilters_ ( expandedValue , tokens ) ) . then ( finalRawValue => { const val = options . noEncode ? finalRawValue : this . encodeVars ( finalRawValue , name ) ; return val ? val + argList : val ; } ) . then ( encodedValue => { replacement = replacement . replace ( match , encodedValue ) ; } ) ; replacementPromises . push ( p ) ; return match ; } ) ; return Promise . all ( replacementPromises ) . then ( ( ) => replacement ) ; }
@param {string} template The template to expand
 @param {!ExpansionOptions} options configuration to use for expansion
 @return {!Promise<!string>} The expanded string
@param { string } template The template to expand @param { !ExpansionOptions } options configuration to use for expansion @return { !Promise<!string > } The expanded string
// Note: The parsing for variables breaks when `|` is used as // something other than the filter separator. A full-fledged parser would // be needed to fix this. // Expand string values further. /* noEncode */ // Values can also be arrays and objects. Don't expand them. // First apply filters // Then encode the value // Replace it in the string // Queue current replacement promise after the last replacement. // Since the replacement will happen later, return the original template. // Once all the promises are complete, return the expanded value.