<commit_before>"use strict";


/*global nodeca, _*/


// stdlib
var path = require('path');


// nodeca
var NLib = require('nlib');


////////////////////////////////////////////////////////////////////////////////


// dummy helper that fills env.response.data.head.assets with only those assets
// from the list of `names` which are actually exist
function inject_asset(pathname) {
  var link;

  /*jshint validthis:true,boss:true*/

  link = this.helpers.asset_path(pathname);

  if ('#' !== link) {
    this.response.data.head.assets.push({
      type: path.extname(link).substring(1),
      link: link
    });
  }
}


////////////////////////////////////////////////////////////////////////////////


// Middleware that populates `env.response.head.assets` with generic assets
// needed for the given method (based on locale, theme and namespace), such as:
// translations, views, etc.
//
nodeca.filters.before('', { weight: 50 }, function inject_assets_info(params, callback) {
  var locale    = this.session.locale,
      theme     = this.session.theme,
      assets    = [];

  if (this.origin.rpc) {
    // do not inject assets to the RPC
    callback(null);
    return;
  }

  this.extras.puncher.start('Assets check');

  if (this.origin.http) {
    assets.push(
      'lib.js', 'app.js', 'app.css',
      'views/' + locale + '/' + theme + '/layouts.js',
      'views/' + locale + '/' + theme + '/common.js',
      'views/' + locale + '/' + theme + '/widgets.js',
      'common/i18n/' + locale + '.js',
      'common/app.css',
      'common/api.js',
      'common/app.js'
    );
  }

  ['forum', 'blogs', 'users', 'admin'].forEach(function (namespace) {
    assets.push(
      'views/' + locale + '/' + theme + '/' + namespace + '.js',
      namespace + '/i18n/' + locale + '.js',
      namespace + '/app.css',
      namespace + '/api.js',
      namespace + '/app.js'
    );
  });

  // inject assets
  assets.forEach(inject_asset, this);
<commit_msg>Refactor assets list generation<commit_after>"use strict";


/*global nodeca, _*/


// stdlib
var path = require('path');


// nodeca
var NLib = require('nlib');


////////////////////////////////////////////////////////////////////////////////


var assets_info_cache = {};


////////////////////////////////////////////////////////////////////////////////


// returns list of asset (URLs) that are actually exists only
//
function get_filtered_assets(arr) {
  var result = [];

  _.each(arr, function (logicalPath) {
     var asset = nodeca.runtime.assets.manifest.assets[logicalPath];
     if (asset) {
       result.push("/assets/" + asset);
     }
  });

  return result;
}


function get_cache_key(env) {
  return env.session.locale + ':' + env.session.theme;
}


function get_from_cache(env) {
  var assets = assets_info_cache[get_cache_key(env)];
  return assets ? _.map(assets, function (o) { return _.clone(o); }) : false;
}


function put_into_cache(env, assets) {
  assets_info_cache[get_cache_key(env)] = _.map(assets, function (o) {
    return _.clone(o);
  });
}


////////////////////////////////////////////////////////////////////////////////


// Middleware that populates `env.response.head.assets` with generic assets
// needed for the given method (based on locale, theme and namespace), such as:
// translations, views, etc.
//
nodeca.filters.before('', { weight: 50 }, function inject_assets_info(params, callback) {
  var locale    = this.session.locale,
      theme     = this.session.theme,
      assets    = get_from_cache(this);

  if (!this.origin.http) {
    // we inject assets infor for HTTP only
    callback(null);
    return;
  }

  this.extras.puncher.start('Assets check');

  if (!!assets) {
    this.response.data.head.assets = assets;
  } else {
    assets = [];

    assets.push({
      test: function () { /*global window*/ return !!window.JSON; },
      nope: get_filtered_assets(['json2.js'])
    });

    assets.push({
      load: get_filtered_assets(
        'lib.js', 'app.js', 'app.css',
        'views/' + locale + '/' + theme + '/layouts.js',
        'views/' + locale + '/' + theme + '/widgets.js'
      )
    });

    // FIXME: should be determined on the base of loaded apps
    ['common', 'forum', 'blogs', 'users', 'admin'].forEach(function (namespace) {
      assets.push({
        namespace: 'common',
        load: get_filtered_assets(
          'views/' + locale + '/' + theme + '/' + namespace + '.js',
          namespace + '/i18n/' + locale + '.js',
          namespace + '/app.css',
          namespace + '/api.js',
          namespace + '/app.js'
        )
      });
    });

    put_into_cache(this, assets);
    this.response.data.head.assets = assets;
  }

{'fraction_non_alphanumeric': 0.23895882227437593, 'fraction_numerical': 0.002560273095796885, 'mean_word_length': 1.9558638083228248, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '799063', 'n_tokens_mistral': 1443, 'n_tokens_neox': 1382, 'n_words': 330}