Exemplo n.º 1
0
describe('registerContentType', () => {
  it('throws with bad options object', () => {
    expect(() => {
      registerContentType('')
    }).toThrowError('Invalid content type object, see documentation.')
  })

  values(ContentTypes).forEach((builtInType) => {
    it('throws an when name is ' + builtInType, () => {
      const opts = {
        name: builtInType,
        plural: builtInType,
        slug: builtInType
      }

      expect(() => {
        registerContentType(opts)
      }).toThrowError(`Content type with name "${builtInType}" already exists.`)
    })
  })

  it('adds custom content type to cache', () => {
    const contentType = {
      name: 'article',
      plural: 'articles',
      slug: 'articles'
    }

    registerContentType(contentType)

    expect(getContentTypes().article).toEqual(contentType)
  })
})
Exemplo n.º 2
0
function displayMetrics (metrics) {
  const flatten = require('lodash.flatten')
  const mean = require('lodash.mean')
  const pad = require('lodash.pad')
  const round = require('lodash.round')
  const sum = require('lodash.sum')
  const values = require('lodash.values')

  function rpmSparkline () {
    if (process.platform === 'win32') return
    let sparkline = require('sparkline')
    let points = []
    values(metrics.routerStatus.data).forEach((cur) => {
      for (let i = 0; i < cur.length; i++) {
        let j = Math.floor(i / 3)
        points[j] = (points[j] || 0) + cur[i]
      }
    })
    points.pop()
    return dim(sparkline(points)) + ' last 24 hours rpm'
  }
  let ms = ''
  let rpm = ''
  if (metrics.routerLatency && !empty(metrics.routerLatency.data)) {
    ms = pad(`${round(mean(metrics.routerLatency.data.latency_p50))} ms`, 6)
  }
  if (metrics.routerStatus && !empty(metrics.routerStatus.data)) {
    rpm = `${round(sum(flatten(values(metrics.routerStatus.data))) / 24 / 60)} rpm ${rpmSparkline()}`
  }
  if (rpm || ms) cli.log(`  ${label('Metrics:')} ${ms}${rpm}`)
}
Exemplo n.º 3
0
limitView.on('value', function (snap) {
  var scores = sortby(values(snap.val()), 'tabs').reverse()
  var top = scores.slice(0,3)
  var others = scores.slice(3)

  React.render(<InlineOrderedList offset={ 1 } scores={ top } />, $top)
  React.render(<OrderedList offset={ 4 } scores={ others } />, $othertop)
})
Exemplo n.º 4
0
GroupManager.prototype.removeZone = function (zoneName) {
  values(this.groups).forEach(function (group) {
    var index = group.zones.indexOf(zoneName)
    if (index > -1) {
      group.zones.splice(index, 1)
      this.airProxy.groupManager.removeZone(group.name, zoneName)
    }
  }.bind(this))
}
function connectDevtools(providers) {
  if (window.devToolsExtension) {
    values(providers).forEach(provider => {
      pushEnhancer(
        { provider },
        window.devToolsExtension(config.devtools)
      );
    });
  }
}
Exemplo n.º 6
0
GroupManager.prototype.getNameOfGroupContainingZone = function (zoneName) {
  var foundGroupName = null
  values(this.groups).some(function (group) {
    if (group.zones.indexOf(zoneName) > -1) {
      foundGroupName = group.name
      return true
    }
    return false
  })
  return foundGroupName
}
Exemplo n.º 7
0
    forEach(queryConnectors, (connectorQuery, connectorId) => {
      // Check if queryName is a scoped one
      const actualQueryName = connectorQuery.scopes && connectorQuery.scopes[queryName] || queryName;
      const isInConnectorFragments = connectorQuery.fragments[actualQueryName] && true;
      const isScopedQuery = actualQueryName !== queryName;
      const scopedOther =
        !isScopedQuery && // is not a scoped query
        connectorQuery.scopes && // has scopes
        values(connectorQuery.scopes).indexOf(actualQueryName) !== -1; // query has not been scoped

      // check if query was triggered by this connector
      // 1st case for scoped queries
      // 2nd case for non scope queries (they cannot be a value in scope)
      if ((isInConnectorFragments && isScopedQuery) ||
          (isInConnectorFragments && !isScopedQuery && !scopedOther)) {
        this.connectors[connectorId] = this.connectors[connectorId] || {
          data: {},
          listens: {},
          fragments: {},
          mutations: {}
        };
        const conn = this.connectors[connectorId];
        const isLoadMore =
          connectorQuery.loadMore === actualQueryName &&
          conn.data[actualQueryName] &&
          conn.data[actualQueryName].constructor === Array;


        // Add query data
        Object.assign(conn.data, {
          [actualQueryName]:
            isLoadMore ?
            [...conn.data[actualQueryName], ...relativeNodes] :
            relativeNodes
        });

        // Add listeners data
        Object.assign(conn.listens, {
          [actualQueryName]:
            isLoadMore ?
            [...conn.data[actualQueryName], ...nodes] :
            nodes
        });

        // fragments
        Object.assign(conn.fragments, {
          [actualQueryName]: connectorQuery.fragments[actualQueryName]
        });

        // mutations listeners
        conn.mutations = connectorQuery.mutations || {};
      }
    });
Exemplo n.º 8
0
 function rpmSparkline () {
   if (process.platform === 'win32') return
   let sparkline = require('sparkline')
   let points = []
   values(metrics.routerStatus.data).forEach((cur) => {
     for (let i = 0; i < cur.length; i++) {
       let j = Math.floor(i / 3)
       points[j] = (points[j] || 0) + cur[i]
     }
   })
   points.pop()
   return dim(sparkline(points)) + ' last 24 hours rpm'
 }
Exemplo n.º 9
0
 _spawnParticles (x, y) {
   // const { colors } = this.props;
   const colors = this.props.wowMode
     ? values(this.props.colors).map(toHex)
     : [toHex(this.props.cursorColor)];
   const numParticles = PARTICLE_NUM_RANGE();
   for (let i = 0; i < numParticles; i++) {
     const colorCode = colors[i % colors.length];
     const r = parseInt(colorCode.slice(1, 3), 16);
     const g = parseInt(colorCode.slice(3, 5), 16);
     const b = parseInt(colorCode.slice(5, 7), 16);
     const color = [r, g, b];
     this._particles.push(this._createParticle(x, y, color));
   }
 }
Exemplo n.º 10
0
 render: function(){
   return(
     <div className="oo-language-tab">
       <DataSelector
         {...this.props}
         viewSize={this.props.responsiveView}
         dataItemsPerPage={this.props.dataItemsPerPage}
         selectedData={this.state.selectedLanguage}
         enabled={this.props.closedCaptionOptions.enabled}
         availableDataItems={values(this.props.closedCaptionOptions.availableLanguages.locale)}
         onDataChange={this.changeLanguage}
       />
     </div>
   );
 }
Exemplo n.º 11
0
GroupManager.prototype.getGroupsWithZoneData = function () {
  var mappedGroups = values(this.groups).map(function (group) {
    group = clone(group)
    group.zones = this.zoneManager.getZones().map(function (zone) {
      zone = clone(zone)
      if (group.zones.indexOf(zone.name) > -1) {
        zone.enabled = true
      } else {
        zone.enabled = false
      }
      return zone
    })
    return group
  }.bind(this))
  return mappedGroups
}
Exemplo n.º 12
0
 function calculateHeight(){
   if (!has(heights, 'nav')) {
     var navHeight = $navItems.outerHeight(true) + $navMore.outerHeight();
     var navPadding = $nav.outerHeight() - $nav.height();
     heights.nav = navHeight + navPadding;
   }
   if (!has(heights, 'subNav')) {
     var subNavHeight = 0;
     var subNavPadding = $subnav.outerHeight() - $subnav.height();
     $subnavSections.add($subnavDefault).each(function () {
       subNavHeight = Math.max(subNavHeight, $(this).outerHeight());
     });
     heights.subNav = subNavHeight + subNavPadding;
   }
   var contentHeight = $contentWrapper.outerHeight();
   var contentPadding = $content.outerHeight() - $content.height();
   heights.content = contentHeight + contentPadding;
   return Math.max.apply(null, values(heights));
 }
Exemplo n.º 13
0
  search: (pattern, process) => {
    const fixtures = values(hazy.fixture.pool)

    return reject(
      map(fixtures, (fixture) => {
        const jpMatches = jsonPath.query(fixture, pattern)

        if (!isEmpty(jpMatches)) {
          // process functional matches if desired
          if (Object.is(process, undefined) ? hazy.config.matcher.use : process) {
            return hazy.matcher.process(pattern, fixture)
          }

          return fixture
        }
      }),

      (_) => Object.is(_, undefined)
    )
  },
Exemplo n.º 14
0
function parseObject(body) {
  // Search body for common names of error strings
  var messages = values(pick(body, 'message', 'error', 'errorString', 'response', 'errorResponse', 'msg'));

  // If no error candidate was found, stringify the entire body
  if (messages.length === 0) {
    return JSON.stringify(body);
  }

  // Assume the first key found was the error explanation
  var message = messages[0];

  // If the explanation is an object, recurse and try again
  if (typeof message === 'object') {
    return parseObject(message);
  }

  // Return the first key
  return message;
}
Exemplo n.º 15
0
module.exports = function getValue (obj, valuePath) {
  if (!valuePath || valuePath === '') {
    return obj
  }

  var pathParts = valuePath
    // replace '.' by '' to mimick jq syntax
    .replace(/^\./, '')
    .split('.')
    .map(spacedKeysSavers.restoreSpaces)

  while (obj != null && pathParts != null && pathParts.length > 0) {
    let nextPart = pathParts.shift()

    if (nextPart === '_keys') {
      obj = Object.keys(obj)
    } else if (nextPart === '_map') {
      if (!obj.map) {
        throw new Error(`this object has no map function: ${JSON.stringify(obj)}`)
      }
      const restPath = pathParts.join('.')
      // The loop should stop there as the rest of the parsing will happen in the map
      pathParts = null
      obj = obj.map(e => getValue(e, restPath))
    } else if (nextPart === '_values') {
      obj = values(obj)
    } else if (nextPart === '_first') {
      obj = obj[0]
    } else if (nextPart === '_last') {
      obj = obj.slice(-1)[0]
    } else {
      obj = obj[nextPart]
    }
  }

  return obj
}
Exemplo n.º 16
0
    forEach(queryConnectors, (connectorQuery, connectorId) => {
      // Check if queryName is a scoped one
      const actualQueryName = connectorQuery.scopes && connectorQuery.scopes[queryName] || queryName;
      const isInConnectorFragments = connectorQuery.fragments[actualQueryName] && true;
      const isScopedQuery = actualQueryName !== queryName;
      const scopedOther =
        !isScopedQuery && // is not a scoped query
        connectorQuery.scopes && // has scopes
        values(connectorQuery.scopes).indexOf(actualQueryName) !== -1; // query has not been scoped

      // check if query was triggered by this connector
      // 1st case for scoped queries
      // 2nd case for non scope queries (they cannot be a value in scope)
      if ((isInConnectorFragments && isScopedQuery) ||
          (isInConnectorFragments && !isScopedQuery && !scopedOther)) {
        if (this.connectors[connectorId]) {
          const conn = this.connectors[connectorId];
          Object.assign(conn.data, {
            [actualQueryName]: relativeNodes
          });
          Object.assign(conn.listens, {
            [actualQueryName]: nodes
          });
          conn.mutations = connectorQuery.mutations;
        } else {
          this.connectors[connectorId] = {
            data: {
              [actualQueryName]: relativeNodes
            },
            listens: {
              [actualQueryName]: nodes
            },
            mutations: connectorQuery.mutations || {}
          };
        }
      }
    });
 get targetFuncs() {
   let inputOpt = this.serverless.processedInput.options;
   return inputOpt.function
     ? [inputOpt.functionObj]
     : values(this.serverless.service.functions);
 }
Exemplo n.º 18
0
const mapAssets = assets => values(assets)
  .map(file => urlJoin(process.env.CDN_URL, file))
  .filter(filename => /\.(css|js)$/.test(filename));
Exemplo n.º 19
0
export const Notifications = new NotificationsCollection(null);

export const types = {
  info: 1,
  undo: 2,
};

Notifications.schema = new SimpleSchema({
  message: {
    type: String,
  },
  type: {
    type: Number,
    optional: true,
    defaultValue: types.info,
    allowedValues: values(types),
  },
  duration: {
    type: Number,
    optional: true,
    defaultValue: 3000,
  },
  showOnlyOne: {
    type: Boolean,
    optional: true,
    defaultValue: true,
  },
});

Notifications.attachSchema(Notifications.schema);
Exemplo n.º 20
0
function showReport(store, params, oldParams) {
  /* get params from url. */
  const channelId = params.channel_id;
  const contentScope = params.content_scope;
  const contentScopeId = params.content_scope_id;
  const userScope = params.user_scope;
  const userScopeId = params.user_scope_id;
  const allOrRecent = params.all_or_recent;
  const viewByContentOrLearners = params.view_by_content_or_learners;
  const sortColumn = params.sort_column;
  const sortOrder = params.sort_order;


  /* check if params are semi-valid. */
  if (!(values(Constants.ContentScopes).includes(contentScope)
    && values(Constants.UserScopes).includes(userScope)
    && values(Constants.AllOrRecent).includes(allOrRecent)
    && values(Constants.ViewBy).includes(viewByContentOrLearners)
    && values(Constants.TableColumns).includes(sortColumn)
    && values(Constants.SortOrders).includes(sortOrder))) {
    /* if invalid params, just throw an error. */
    coreActions.handleError(store, 'Invalid report parameters.');
    return;
  }

  const diffKeys = _diffKeys(params, oldParams);

  store.dispatch('SET_PAGE_NAME', Constants.PageNames.REPORTS);

  // these don't require updates from the server
  const localUpdateParams = ['sort_column', 'sort_order'];
  if (diffKeys.every(key => localUpdateParams.includes(key))) {
    store.dispatch('SET_SORT_COLUMN', sortColumn);
    store.dispatch('SET_SORT_ORDER', sortOrder);
    return;
  }

  const resourcePromise = require('./resourcePromise');
  const URL_ROOT = '/coach/api';
  const promises = [];

  // REPORT
  if (userScope === Constants.UserScopes.USER && contentScope === Constants.ContentScopes.CONTENT) {
    promises.push([]); // don't retrieve a report for a single-user, single-item page
  } else {
    let reportUrl = `${URL_ROOT}/${channelId}/${contentScopeId}/${userScope}/${userScopeId}`;
    if (allOrRecent === Constants.AllOrRecent.RECENT) {
      reportUrl += '/recentreport/';
    } else if (viewByContentOrLearners === Constants.ViewBy.CONTENT) {
      reportUrl += '/contentreport/';
    } else if (viewByContentOrLearners === Constants.ViewBy.LEARNERS) {
      reportUrl += '/userreport/';
    } else {
      logging.error('unhandled input parameters');
    }
    promises.push(resourcePromise(reportUrl));
  }


  // CONTENT SUMMARY
  const contentSummaryUrl =
    `${URL_ROOT}/${channelId}/${userScope}/${userScopeId}/contentsummary/${contentScopeId}/`;
  promises.push(resourcePromise(contentSummaryUrl));

  // USER SUMMARY
  if (userScope === Constants.UserScopes.USER) {
    const userSummaryUrl
      = `${URL_ROOT}/${channelId}/${contentScopeId}/usersummary/${userScopeId}/`;
    promises.push(resourcePromise(userSummaryUrl));
  } else {
    promises.push({}); // don't retrieve a summary for a group of users
  }

  // CHANNELS
  const channelPromise = coreActions.setChannelInfo(store);
  promises.push(channelPromise);

  // API response handlers
  Promise.all(promises).then(([report, contentSummary, userSummary]) => {
    // save URL params to store
    store.dispatch('SET_CHANNEL_ID', channelId);
    store.dispatch('SET_CONTENT_SCOPE', contentScope);
    store.dispatch('SET_CONTENT_SCOPE_ID', contentScopeId);
    store.dispatch('SET_USER_SCOPE', userScope);
    store.dispatch('SET_USER_SCOPE_ID', userScopeId);
    store.dispatch('SET_ALL_OR_RECENT', allOrRecent);
    store.dispatch('SET_VIEW_BY_CONTENT_OR_LEARNERS', viewByContentOrLearners);
    store.dispatch('SET_SORT_COLUMN', sortColumn);
    store.dispatch('SET_SORT_ORDER', sortOrder);

    // save results of API request
    store.dispatch('SET_TABLE_DATA', report);
    store.dispatch('SET_CONTENT_SCOPE_SUMMARY', contentSummary);
    store.dispatch('SET_USER_SCOPE_SUMMARY', userSummary);
    store.dispatch('CORE_SET_PAGE_LOADING', false);

    const titleElems = ['Coach Reports'];
    if (userScope === Constants.UserScopes.USER) {
      titleElems.push(`${userSummary.full_name}`);
    } else if (userScope === Constants.UserScopes.FACILITY) {
      titleElems.push('All learners');
    }
    titleElems.push(`${contentSummary.title}`);
    if (allOrRecent === Constants.AllOrRecent.RECENT) {
      titleElems.push('Recent');
    } else if (viewByContentOrLearners === Constants.ViewBy.CONTENT) {
      titleElems.push('Contents');
    } else if (viewByContentOrLearners === Constants.ViewBy.LEARNERS) {
      titleElems.push('Learners');
    }
    store.dispatch('CORE_SET_TITLE', titleElems.join(' - '));
  },
    error => { coreActions.handleError(store, error); }
  );
}
Exemplo n.º 21
0
 function applyNewConstructor () {
   var args = [null].concat(values(arguments))
   var FactoryFn = ctx.bind.apply(ctx, args)
   return new FactoryFn()
 }
Exemplo n.º 22
0
var values = require('lodash.values');
var max = require('lodash.max');
var selectn = require('selectn');
var stats = require('./stats.json');

var popular = max(values(stats), selectn('count'));
console.log('The "%s" page is the most popular with a visitor count of %d!', popular.page, popular.count);
Exemplo n.º 23
0
  // Gets *all* attachments and add-ons and filters locally because the API
  // returns *owned* items not associated items.
  function * addonGetter (api, app) {
    let attachments, addons

    if (app) { // don't disploy attachments globally
      addons = api.get(`/apps/${app}/addons`, {headers: {'Accept-Expansion': 'addon_service,plan'}})

      let sudoHeaders = JSON.parse(process.env.HEROKU_HEADERS || '{}')
      if (sudoHeaders['X-Heroku-Sudo'] && !sudoHeaders['X-Heroku-Sudo-User']) {
        // because the root /addon-attachments endpoint won't include relevant
        // attachments when sudo-ing for another app, we will use the more
        // specific API call and sacrifice listing foreign attachments.
        attachments = api.request({
          method: 'GET',
          path: `/apps/${app}/addon-attachments`
        })
      } else {
        // In order to display all foreign attachments, we'll get out entire
        // attachment list
        attachments = api.get('/addon-attachments')
      }
    } else {
      addons = api.request({
        method: 'GET',
        path: '/addons',
        headers: {'Accept-Expansion': 'addon_service,plan'}
      })
    }

    // Get addons and attachments in parallel
    let items = yield [addons, attachments]

    function isRelevantToApp (addon) {
      return !app ||
      addon.app.name === app ||
      some(addon.attachments, (att) => att.app.name === app)
    }

    attachments = groupBy(items[1], 'addon.id')

    addons = []
    items[0].forEach(function (addon) {
      addon.attachments = attachments[addon.id] || []

      delete attachments[addon.id]

      if (isRelevantToApp(addon)) {
        addons.push(addon)
      }
    })

    // Any attachments left didn't have a corresponding add-on record in API.
    // This is probably normal (because we are asking API for all attachments)
    // but it could also be due to certain types of permissions issues, so check
    // if the attachment looks relevant to the app, and then render whatever
    // information we can.
    values(attachments).forEach(function (atts) {
      let inaccessibleAddon = {
        app: atts[0].addon.app,
        name: atts[0].addon.name,
        addon_service: {},
        plan: {},
        attachments: atts
      }

      if (isRelevantToApp(inaccessibleAddon)) {
        addons.push(inaccessibleAddon)
      }
    })

    return addons
  }
Exemplo n.º 24
0
/**
 * A micro-templating method that handles arbitrary delimiters, preserves
 * whitespace, and correctly escapes quotes within interpolated code.
 *
 * Note: In the development build, `_.template` utilizes sourceURLs for easier
 * debugging. See http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl
 *
 * For more information on precompiling templates see:
 * http://lodash.com/custom-builds
 *
 * For more information on Chrome extension sandboxes see:
 * http://developer.chrome.com/stable/extensions/sandboxingEval.html
 *
 * @static
 * @memberOf _
 * @category Utilities
 * @param {string} text The template text.
 * @param {Object} data The data object used to populate the text.
 * @param {Object} [options] The options object.
 * @param {RegExp} [options.escape] The "escape" delimiter.
 * @param {RegExp} [options.evaluate] The "evaluate" delimiter.
 * @param {Object} [options.imports] An object to import into the template as local variables.
 * @param {RegExp} [options.interpolate] The "interpolate" delimiter.
 * @param {string} [sourceURL] The sourceURL of the template's compiled source.
 * @param {string} [variable] The data object variable name.
 * @returns {Function|string} Returns a compiled function when no `data` object
 *  is given, else it returns the interpolated text.
 * @example
 *
 * // using the "interpolate" delimiter to create a compiled template
 * var compiled = _.template('hello <%= name %>');
 * compiled({ 'name': 'fred' });
 * // => 'hello fred'
 *
 * // using the "escape" delimiter to escape HTML in data property values
 * _.template('<b><%- value %></b>', { 'value': '<script>' });
 * // => '<b>&lt;script&gt;</b>'
 *
 * // using the "evaluate" delimiter to generate HTML
 * var list = '<% _.forEach(people, function(name) { %><li><%- name %></li><% }); %>';
 * _.template(list, { 'people': ['fred', 'barney'] });
 * // => '<li>fred</li><li>barney</li>'
 *
 * // using the ES6 delimiter as an alternative to the default "interpolate" delimiter
 * _.template('hello ${ name }', { 'name': 'pebbles' });
 * // => 'hello pebbles'
 *
 * // using the internal `print` function in "evaluate" delimiters
 * _.template('<% print("hello " + name); %>!', { 'name': 'barney' });
 * // => 'hello barney!'
 *
 * // using a custom template delimiters
 * _.templateSettings = {
 *   'interpolate': /{{([\s\S]+?)}}/g
 * };
 *
 * _.template('hello {{ name }}!', { 'name': 'mustache' });
 * // => 'hello mustache!'
 *
 * // using the `imports` option to import jQuery
 * var list = '<% jq.each(people, function(name) { %><li><%- name %></li><% }); %>';
 * _.template(list, { 'people': ['fred', 'barney'] }, { 'imports': { 'jq': jQuery } });
 * // => '<li>fred</li><li>barney</li>'
 *
 * // using the `sourceURL` option to specify a custom sourceURL for the template
 * var compiled = _.template('hello <%= name %>', null, { 'sourceURL': '/basic/greeting.jst' });
 * compiled(data);
 * // => find the source of "greeting.jst" under the Sources tab or Resources panel of the web inspector
 *
 * // using the `variable` option to ensure a with-statement isn't used in the compiled template
 * var compiled = _.template('hi <%= data.name %>!', null, { 'variable': 'data' });
 * compiled.source;
 * // => function(data) {
 *   var __t, __p = '', __e = _.escape;
 *   __p += 'hi ' + ((__t = ( data.name )) == null ? '' : __t) + '!';
 *   return __p;
 * }
 *
 * // using the `source` property to inline compiled templates for meaningful
 * // line numbers in error messages and a stack trace
 * fs.writeFileSync(path.join(cwd, 'jst.js'), '\
 *   var JST = {\
 *     "main": ' + _.template(mainText).source + '\
 *   };\
 * ');
 */
function template(text, data, options) {
    // based on John Resig's `tmpl` implementation
    // http://ejohn.org/blog/javascript-micro-templating/
    // and Laura Doktorova's doT.js
    // https://github.com/olado/doT
    var settings = templateSettings.imports._.templateSettings || templateSettings;
    text = String(text || '');

    // avoid missing dependencies when `iteratorTemplate` is not defined
    options = defaults({}, options, settings);

    var imports = defaults({}, options.imports, settings.imports),
        importsKeys = keys(imports),
        importsValues = values(imports);

    var isEvaluating,
        index = 0,
        interpolate = options.interpolate || reNoMatch,
        source = "__p += '";

    // compile the regexp to match each delimiter
    var reDelimiters = RegExp(
            (options.escape || reNoMatch).source + '|' +
            interpolate.source + '|' +
            (interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + '|' +
            (options.evaluate || reNoMatch).source + '|$'
        , 'g');

    text.replace(reDelimiters, function (match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) {
        interpolateValue || (interpolateValue = esTemplateValue);

        // escape characters that cannot be included in string literals
        source += text.slice(index, offset).replace(reUnescapedString, escapeStringChar);

        // replace delimiters with snippets
        if (escapeValue) {
            source += "' +\n__e(" + escapeValue + ") +\n'";
        }
        if (evaluateValue) {
            isEvaluating = true;
            source += "';\n" + evaluateValue + ";\n__p += '";
        }
        if (interpolateValue) {
            source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'";
        }
        index = offset + match.length;

        // the JS engine embedded in Adobe products requires returning the `match`
        // string in order to produce the correct `offset` value
        return match;
    });

    source += "';\n";

    // if `variable` is not specified, wrap a with-statement around the generated
    // code to add the data object to the top of the scope chain
    var variable = options.variable,
        hasVariable = variable;

    if (!hasVariable) {
        variable = 'obj';
        source = 'with (' + variable + ') {\n' + source + '\n}\n';
    }
    // cleanup code by stripping empty strings
    source = (isEvaluating ? source.replace(reEmptyStringLeading, '') : source)
        .replace(reEmptyStringMiddle, '$1')
        .replace(reEmptyStringTrailing, '$1;');

    // frame code as the function body
    source = 'function(' + variable + ') {\n' +
        (hasVariable ? '' : variable + ' || (' + variable + ' = {});\n') +
        "var __t, __p = '', __e = _.escape" +
        (isEvaluating
            ? ', __j = Array.prototype.join;\n' +
            "function print() { __p += __j.call(arguments, '') }\n"
            : ';\n'
            ) +
        source +
        'return __p\n}';

    try {
        var result = Function(importsKeys, 'return ' + source).apply(undefined, importsValues);
    } catch (e) {
        e.source = source;
        throw e;
    }
    if (data) {
        return result(data);
    }
    // provide the compiled function's source by its `toString` method, in
    // supported environments, or the `source` property as a convenience for
    // inlining compiled templates during the build process
    result.source = source;
    return result;
}