<commit_before>var snorkel = true;
var torrdass = true;
var utsiktsplats = true;
var wc = true;
var rastplats = true;
var taltplats = true;
var badplats = true;
var information = true;
var eldplats = true;
var menuVisible = false;

var infospotsNotVisible = true;
var hotspotsNotVisible = true;

//var MapModule = require('ti.map');
var trailsCollection = getTrailsCollection();
var hotspotCollection = getHotspotCollection();

//-----------------------------------------------------------
// Visar markers för vandringslederna
//-----------------------------------------------------------
function displayTrailMarkers() {
	try {
		trailsCollection.fetch({
			query : 'SELECT name, pinLon, pinLat, color FROM trailsModel'
		});

		var jsonObj = trailsCollection.toJSON();
		for (var i = 0; i < jsonObj.length; i++) {
			var markerAnnotation = MapModule.createAnnotation({
				id : jsonObj[i].name,
				latitude : jsonObj[i].pinLat,
				longitude : jsonObj[i].pinLon,
				title : jsonObj[i].name,
				subtitle : 'Läs mer om ' + jsonObj[i].name + ' här!',
				pincolor : MapModule.ANNOTATION_GREEN,
				rightButton : '/images/arrow.png',
				name : 'trail'
			});

			baseMap.addAnnotation(markerAnnotation);
		}
	} catch(e) {
		newError("Något gick fel när sidan skulle laddas, prova igen!", "map - displayTrailMarkers");
	}
}

//-----------------------------------------------------------
// Visar markers för hotspots
//-----------------------------------------------------------
function displayMarkers() {
	try {
		var markerArray = [];
		hotspotCollection.fetch();

		var markersJSON = hotspotCollection.toJSON();
		for (var u = 0; u < markersJSON.length; u++) {

			if (OS_IOS) {
				var marker = MapModule.createAnnotation({
					id : markersJSON[u].name,
					latitude : markersJSON[u].xkoord,
					longitude : markersJSON[u].ykoord,
					title : markersJSON[u].name,
					subtitle : 'Läs mer om ' + markersJSON[u].name + ' här!',
					pincolor : MapModule.ANNOTATION_PURPLE,
					rightButton : '/images/arrow.png',
					name : 'hotspot'
				});
			}

			markerArray.push(marker);
		}

		baseMap.addAnnotations(markerArray);
		hotspotsNotVisible = false;

	} catch(e) {
		newError("Något gick fel när sidan skulle laddas, prova igen!", "map - displayMarkers");
	}
}

//-----------------------------------------------------------
// Visar ikoner för alla informationsobjekt
//-----------------------------------------------------------
function displayInfoSpots(type) {
	try {
		var markerArray = [];
		var infospotCollection = getInfospotCollection();
		infospotCollection.fetch({
			query : 'select infospotModel.name, infospotModel.icon, infospotCoordinatesModel.latitude, infospotCoordinatesModel.longitude from infospotCoordinatesModel join infospotModel on infospotCoordinatesModel.infospotID = infospotModel.id WHERE infospotModel.name ="' + type + '"'
		});

		var infoJSON = infospotCollection.toJSON();
		for (var u = 0; u < infoJSON.length; u++) {
			var marker = MapModule.createAnnotation({
				latitude : infoJSON[u].latitude,
				longitude : infoJSON[u].longitude,
				image : '/images/map_' + infoJSON[u].icon
			});

			markerArray.push(marker);
		}

		return markerArray;
	} catch(e) {
		newError("Något gick fel när sidan skulle laddas, prova igen!", "map - displayInfoSpots");
	}
}

function removeAnnotations() {
	baseMap.removeAllAnnotations();
}

function normalMap() {
	baseMap.mapType = MapModule.NORMAL_TYPE;
}

function hybridMap() {
	baseMap.mapType = MapModule.HYBRID_TYPE;
}

function satelliteMap() {
	baseMap.mapType = MapModule.SATELLITE_TYPE;
}

function showHotspots() {
	if (hotspotsNotVisible) {
		displayMarkers();
		hotspotsNotVisible = false;
	}
}

function showWC() {
	baseMap.addAnnotations(displayInfoSpots("wc"));
}

function showEldplats() {
	baseMap.addAnnotations(displayInfoSpots("eldplats"));
}

function showSnorkelled() {
	baseMap.addAnnotations(displayInfoSpots("snorkelled"));
}

function showInformation() {
	baseMap.addAnnotations(displayInfoSpots("information"));
}

function showBadplats() {
	baseMap.addAnnotations(displayInfoSpots("badplats"));
}

function showRastplats() {
	baseMap.addAnnotations(displayInfoSpots("rastplats"));
}

function showTaltplats() {
	baseMap.addAnnotations(displayInfoSpots("taltplats"));
}

function showUtkiksplats() {
	baseMap.addAnnotations(displayInfoSpots("utsiktsplats"));
}

function showTorrdass() {
	baseMap.addAnnotations(displayInfoSpots("torrdass"));
}

function showMenuWidget(){
	if(!menuVisible){
		$.mapmenu.show();
		menuVisible = true;
	}
	else{
		$.mapmenu.hide();
		menuVisible = false;
	}
};

function closeMapMenu(){
		$.mapmenu.hide();
		menuVisible = false;
}

Alloy.Globals.showMenuWidget = showMenuWidget;
Alloy.Globals.closeMapMenu = closeMapMenu;
<commit_msg>Title på infospots<commit_after>var snorkel = true;
var torrdass = true;
var utsiktsplats = true;
var wc = true;
var rastplats = true;
var taltplats = true;
var badplats = true;
var information = true;
var eldplats = true;
var menuVisible = false;

var infospotsNotVisible = true;
var hotspotsNotVisible = true;

//var MapModule = require('ti.map');
var trailsCollection = getTrailsCollection();
var hotspotCollection = getHotspotCollection();

//-----------------------------------------------------------
// Visar markers för vandringslederna
//-----------------------------------------------------------
function displayTrailMarkers() {
	try {
		trailsCollection.fetch({
			query : 'SELECT name, pinLon, pinLat, color FROM trailsModel'
		});

		var jsonObj = trailsCollection.toJSON();
		for (var i = 0; i < jsonObj.length; i++) {
			var markerAnnotation = MapModule.createAnnotation({
				id : jsonObj[i].name,
				latitude : jsonObj[i].pinLat,
				longitude : jsonObj[i].pinLon,
				title : jsonObj[i].name,
				subtitle : 'Läs mer om ' + jsonObj[i].name + ' här!',
				pincolor : MapModule.ANNOTATION_GREEN,
				rightButton : '/images/arrow.png',
				name : 'trail'
			});

			baseMap.addAnnotation(markerAnnotation);
		}
	} catch(e) {
		newError("Något gick fel när sidan skulle laddas, prova igen!", "map - displayTrailMarkers");
	}
}

//-----------------------------------------------------------
// Visar markers för hotspots
//-----------------------------------------------------------
function displayMarkers() {
	try {
		var markerArray = [];
		hotspotCollection.fetch();

		var markersJSON = hotspotCollection.toJSON();
		for (var u = 0; u < markersJSON.length; u++) {

			if (OS_IOS) {
				var marker = MapModule.createAnnotation({
					id : markersJSON[u].name,
					latitude : markersJSON[u].xkoord,
					longitude : markersJSON[u].ykoord,
					title : markersJSON[u].name,
					subtitle : 'Läs mer om ' + markersJSON[u].name + ' här!',
					pincolor : MapModule.ANNOTATION_PURPLE,
					rightButton : '/images/arrow.png',
					name : 'hotspot'
				});
			}

			markerArray.push(marker);
		}

		baseMap.addAnnotations(markerArray);
		hotspotsNotVisible = false;

	} catch(e) {
		newError("Något gick fel när sidan skulle laddas, prova igen!", "map - displayMarkers");
	}
}

//-----------------------------------------------------------
// Visar ikoner för alla informationsobjekt
//-----------------------------------------------------------
function displayInfoSpots(type) {
	try {
		var markerArray = [];
		var infospotCollection = getInfospotCollection();
		infospotCollection.fetch({
			query : 'select infospotModel.name, infospotModel.icon, infospotCoordinatesModel.latitude, infospotCoordinatesModel.longitude from infospotCoordinatesModel join infospotModel on infospotCoordinatesModel.infospotID = infospotModel.id WHERE infospotModel.name ="' + type + '"'
		});

		var infoJSON = infospotCollection.toJSON();
		for (var u = 0; u < infoJSON.length; u++) {
			var marker = MapModule.createAnnotation({
				latitude : infoJSON[u].latitude,
				longitude : infoJSON[u].longitude,
				image : '/images/map_' + infoJSON[u].icon
			});

			if (infoJSON[u].name == 'taltplats') {
				marker.title = 'Tältplats';
			} else if (infoJSON[u].name == 'wc') {
				marker.title = 'WC';
			} else {
				marker.title = capitalizeFirstLetter(infoJSON[u].name);
			}

			markerArray.push(marker);
		}

		return markerArray;
	} catch(e) {
		newError("Något gick fel när sidan skulle laddas, prova igen!", "map - displayInfoSpots");
	}
}

function capitalizeFirstLetter(string) {
	return string.charAt(0).toUpperCase() + string.slice(1);
}

function removeAnnotations() {
	baseMap.removeAllAnnotations();
}

function normalMap() {
	baseMap.mapType = MapModule.NORMAL_TYPE;
}

function hybridMap() {
	baseMap.mapType = MapModule.HYBRID_TYPE;
}

function satelliteMap() {
	baseMap.mapType = MapModule.SATELLITE_TYPE;
}

function showHotspots() {
	if (hotspotsNotVisible) {
		displayMarkers();
		hotspotsNotVisible = false;
	}
}

function showWC() {
	baseMap.addAnnotations(displayInfoSpots("wc"));
}

function showEldplats() {
	baseMap.addAnnotations(displayInfoSpots("eldplats"));
}

function showSnorkelled() {
	baseMap.addAnnotations(displayInfoSpots("snorkelled"));
}

function showInformation() {
	baseMap.addAnnotations(displayInfoSpots("information"));
}

function showBadplats() {
	baseMap.addAnnotations(displayInfoSpots("badplats"));
}

function showRastplats() {
	baseMap.addAnnotations(displayInfoSpots("rastplats"));
}

function showTaltplats() {
	baseMap.addAnnotations(displayInfoSpots("taltplats"));
}

function showUtkiksplats() {
	baseMap.addAnnotations(displayInfoSpots("utsiktsplats"));
}

function showTorrdass() {
	baseMap.addAnnotations(displayInfoSpots("torrdass"));
}

function showMenuWidget() {
	if (!menuVisible) {
		$.mapmenu.show();
		menuVisible = true;
	} else {
		$.mapmenu.hide();
		menuVisible = false;
	}
};

function closeMapMenu() {
	$.mapmenu.hide();
	menuVisible = false;
}

Alloy.Globals.showMenuWidget = showMenuWidget;
Alloy.Globals.closeMapMenu = closeMapMenu;
<|endoftext|>


<commit_before>import _ from 'lodash'
import * as Config from '@Config/config'

// the base configuration
export const global_default_config={
    APP_CITY: 'Scheme Area',
    APP_CURRENCY: 'Currency Name',
    APP_WEBSITE: 'https://github.com/ScottLogic/CityPoundSourceCode',
    TXT2PAY_NO: undefined,
    CYCLOS: {
        host: undefined,
        cyclosPrefix: undefined,
        network: undefined,
        wsPrefix: undefined,
        channel: undefined,
    },
    DIRECTORY: {
        host: undefined,
        cyclosPrefix: undefined,
        network: undefined,
        wsPrefix: undefined,
    },
    ALLOW_LOGIN: true,
    DEFAULT_COORDINATES: { latitude: 0, longitude:  0 },
}

const default_secret={
    CHANNEL_SECRET: '',
}

const secrets           = {}
var importedSecrets     = {}

if (Config.secrets) {
    importedSecrets     = require('@Config/secrets').default
}

_.forEach(['staging', 'development', 'production'], function(flavour) {

    const branch        = _.has(importedSecrets, flavour)
                        ? importedSecrets[flavour]
                        : {}

    _.defaultsDeep(branch, default_secret)

    secrets[flavour]    = branch
})

export const cyclosUrl = (config) => {
    config.CYCLOS.url = 'https://'+config.CYCLOS.host	+'/'+config.CYCLOS.cyclosPrefix +'/'+config.CYCLOS.network +'/api/'

    return config
}

const normaliseConfigurations = (configurations, flavour, default_config) => {

    const extendConfigurations = (c, f, cc) => {
        const result = {}

        // copy flavour config
        _.defaultsDeep(result, c)

        // copy default config
        _.defaultsDeep(result, default_config)

        // copy global default config
        _.defaultsDeep(result, global_default_config)

        cyclosUrl(result)

        result['secrets']   = _.has(secrets, flavour)
                            ? secrets[flavour]
                            : default_secret

        // save flavour
        result.FLAVOUR = f

        cc[f] = result
    }

    // extend the customisations
    _.each(configurations, extendConfigurations)

    const result    = _.has(configurations, flavour)
                    ? configurations[flavour]
                    : cyclosUrl(_.merge({}, default_config))

    return result
}

_.merge(Config.default, normaliseConfigurations(Config.configurations, Config.flavour, Config.default_config))
<commit_msg>use relative path, rather than module name for @Config/secrets<commit_after>import _ from 'lodash'
import * as Config from '@Config/config'

// the base configuration
export const global_default_config={
    APP_CITY: 'Scheme Area',
    APP_CURRENCY: 'Currency Name',
    APP_WEBSITE: 'https://github.com/ScottLogic/CityPoundSourceCode',
    TXT2PAY_NO: undefined,
    CYCLOS: {
        host: undefined,
        cyclosPrefix: undefined,
        network: undefined,
        wsPrefix: undefined,
        channel: undefined,
    },
    DIRECTORY: {
        host: undefined,
        cyclosPrefix: undefined,
        network: undefined,
        wsPrefix: undefined,
    },
    ALLOW_LOGIN: true,
    DEFAULT_COORDINATES: { latitude: 0, longitude:  0 },
}

const default_secret={
    CHANNEL_SECRET: '',
}

const secrets           = {}
var importedSecrets     = {}

if (Config.secrets) {
    importedSecrets     = require('../../../config/secrets').default
}

_.forEach(['staging', 'development', 'production'], function(flavour) {

    const branch        = _.has(importedSecrets, flavour)
                        ? importedSecrets[flavour]
                        : {}

    _.defaultsDeep(branch, default_secret)

    secrets[flavour]    = branch
})

export const cyclosUrl = (config) => {
    config.CYCLOS.url = 'https://'+config.CYCLOS.host	+'/'+config.CYCLOS.cyclosPrefix +'/'+config.CYCLOS.network +'/api/'

    return config
}

const normaliseConfigurations = (configurations, flavour, default_config) => {

    const extendConfigurations = (c, f, cc) => {
        const result = {}

        // copy flavour config
        _.defaultsDeep(result, c)

        // copy default config
        _.defaultsDeep(result, default_config)

        // copy global default config
        _.defaultsDeep(result, global_default_config)

        cyclosUrl(result)

        result['secrets']   = _.has(secrets, flavour)
                            ? secrets[flavour]
                            : default_secret

        // save flavour
        result.FLAVOUR = f

        cc[f] = result
    }

    // extend the customisations
    _.each(configurations, extendConfigurations)

    const result    = _.has(configurations, flavour)
                    ? configurations[flavour]
                    : cyclosUrl(_.merge({}, default_config))

    return result
}

_.merge(Config.default, normaliseConfigurations(Config.configurations, Config.flavour, Config.default_config))
<|endoftext|>


<commit_before>import { customRender as annoTextCustomRender } from '../util/annotext';

const clozedAnnotextHTML = annoTextCustomRender(
  context.primary.annoText,
  (a, inner) => {
    if (a.kind === 'ruby') {
      return ['<ruby>', ...inner, '<rp>(</rp><rt>', escape(a.data), '</rt><rp>)</rp></ruby>'];
    } else if (a.kind === 'highlight') {
      // Compute cloze number as a hash of contained text.
      //  Hacky, but will give us stable cloze ids.
      const textSlice = cpSlice(context.primary.annoText.text, a.cpBegin, a.cpEnd);
      const clozeNum = parseInt(shajs('sha1').update(textSlice).digest('hex'), 16) % 1000000000;
      return ['{{c' + clozeNum + '::', ...inner, '}}'];
    } else {
      return inner;
    }
  },
  (c, i) => (c === '\n' ? '<br/>' : escape(c))
).join('');
<commit_msg>On second thought, remove not-yet-used code<commit_after><|endoftext|>


<commit_before>/*
 * Struttura della risposta delle twitter API
 *
{ id: 85769942,
  time_zone: null,
  profile_use_background_image: true,
  entities: { description: { urls: [] } },
  profile_text_color: '333333',
  id_str: '85769942',
  geo_enabled: false,
  listed_count: 0,
  is_translator: false,
  profile_sidebar_border_color: 'C0DEED',
  utc_offset: null,
  name: 'Francesco T',
  lang: 'en',
  follow_request_sent: false,
  profile_background_tile: false,
  followers_count: 41,
  created_at: 'Wed Oct 28 08:12:38 +0000 2009',
  protected: false,
  profile_sidebar_fill_color: 'DDEEF6',
  default_profile_image: false,
  profile_image_url_https: 'https://twimg0-a.akamaihd.net/profile_images/1673873900/image_normal.jpg',
  url: null,
  friends_count: 96,
  favourites_count: 9,
  statuses_count: 54,
  profile_background_color: 'C0DEED',
  verified: false,
  following: false,
  notifications: false,
  profile_image_url: 'http://a0.twimg.com/profile_images/1673873900/image_normal.jpg',
  profile_background_image_url_https: 'https://twimg0-a.akamaihd.net/images/themes/theme1/bg.png',
  profile_background_image_url: 'http://a0.twimg.com/images/themes/theme1/bg.png',
  profile_link_color: '0084B4',
  location: null,
  status:
   { entities: { urls: [], hashtags: [Object], user_mentions: [Object] },
     place: null,
     favorited: false,
     created_at: 'Wed Jan 30 11:47:25 +0000 2013',
     in_reply_to_status_id_str: null,
     geo: null,
     in_reply_to_user_id_str: null,
     contributors: null,
     retweet_count: 5,
     retweeted_status:
      { entities: [Object],
        place: null,
        favorited: false,
        created_at: 'Wed Jan 30 10:08:58 +0000 2013',
        in_reply_to_status_id_str: null,
        geo: null,
        in_reply_to_user_id_str: null,
        contributors: null,
        retweet_count: 5,
        retweeted: false,
        text: 'Memoria corta? Pastiglia N.2\n\n#Alfano: "Il lavoro al primo posto!Parleremo anche di accesso al credito. Ok agenda Monti.Ci sarò"\n\n12/03/2012',
        id_str: '296560628825481216',
        source: 'Twitter for Mac',
        coordinates: null,
        in_reply_to_screen_name: null,
        in_reply_to_user_id: null,
        in_reply_to_status_id: null,
        id: 296560628825481200,
        truncated: false },
     retweeted: false,
     text: 'RT @carlo_secchi: Memoria corta? Pastiglia N.2\n\n#Alfano: "Il lavoro al primo posto!Parleremo anche di accesso al credito. Ok agenda Mont ...',
     id_str: '296585406223376384',
     source: 'Twitter for iPad',
     coordinates: null,
     in_reply_to_screen_name: null,
     in_reply_to_user_id: null,
     in_reply_to_status_id: null,
     id: 296585406223376400,
     truncated: false },
  screen_name: 'francescocomo',
  default_profile: true,
  description: null,
  contributors_enabled: false }

 *
 */

var config = require('../config.js');
var mongoose = require('mongoose');
var twitter = require('ntwitter');
var credentials = require('../config_twitter.js');

mongoose.set('debug', config.db_debug)

console.log("opening connection with " + config.db_name + "@" + config.db_host );
var db = mongoose.createConnection(config.db_host, config.db_name);

var t = new twitter({
    consumer_key: credentials.twit_consumer_key,
    consumer_secret: credentials.twit_consumer_secret,
    access_token_key: credentials.twit_access_token,
    access_token_secret: credentials.twit_token_secret
});

// if you have problems here change ulimit "ulimit -n [how-much-you-want]"
process.setMaxListeners(0);
db.once('open', function() {
    function saveExtraInfo(info, usr, callback){
        usr.mep_follower_count = info.mep_follower_count;
        usr.mep_last_tweet_time = info.mep_last_tweet_time;
        usr.mep_last_tweet = info.mep_last_tweet;
        usr.mep_tweet_count = info.mep_tweet_count;
        usr.save(function(err, type){
            if (err) {
                console.error('Saving user ' + usr.mep_firstName + ' problem.');
                process.exit(0);
              }
            callback();
        });
        // nome generico
    }

    var mepSchema = config.schema
    var MepModel = db.model(config.db_collection, mepSchema);

    // avatar importer async version
    var counter = 0;
    var counterInGroup = 0;
    var group = 0;
    var counterResponse = 0;
    var countResponseDiff = 0;
    MepModel.find({/*"mep_follower_count" :  { $ne: "" }*/}, function(err, meps) {
      count = meps.length;
      mep_twitterUrls = new Array();
      meps.forEach(function(i) {
    	mep_twitterUrls[group] = i.mep_twitterUrl;
      	group++;
    	counterInGroup++;
		if(group == 99 || meps.length-counterInGroup == 0){
			console.log("group: " + group);
			console.log("remains: " + (meps.length-counterInGroup));
	    	var params = {screen_name : mep_twitterUrls.join(',')};
		      mep_twitterUrls = new Array();
	        var url = "https://api.twitter.com/1.1/users/lookup.json";

	        t.get(url, params, function(err, data) {
	            if (err) {
	                console.log(err);
		            counter = counter+100;
	              }
	            else{
            		counterResponse += data.length;
            		countResponseDiff = countResponseDiff+(group-data.length);
	            	data.forEach(function(user) {
	    	              MepModel.findOneAndUpdate({"mep_twitterUrl" :  user.screen_name }, {
	 	            		   "mep_follower_count" : user.followers_count,
	 	           		       "mep_last_tweet_time" : (typeof(user.status) != "undefined" && typeof(user.status.created_at) !== "undefined") ? user.status.created_at : null,
	 	        		       "mep_last_tweet" : (typeof(user.status) != "undefined" && typeof(user.status.text) !== "undefined") ? user.status.text : null,
	 	        		       "mep_tweet_count" : user.statuses_count
	 	            		},
	 	            		function(err) {
			    	            counter++;
			    	            if (counter == meps.length || meps.length-counterResponse-countResponseDiff == 0) {
			    	              console.log('Imported: ' + counterResponse + ' extra info.');
			    	              mongoose.disconnect();
			    	              process.exit();
			    	            }
			    	          });
	 	            		}
	 	            	);

/*
*/
	            }
	        });
			group = 0;
		}
      });
    });
});

// force disconnect to avoid infinit loop
 setTimeout( function () {
     mongoose.disconnect();
  }, 5000);
<commit_msg>Correzione di alcuni bug:<commit_after>/*
 * Struttura della risposta delle twitter API
 *
{ id: 85769942,
  time_zone: null,
  profile_use_background_image: true,
  entities: { description: { urls: [] } },
  profile_text_color: '333333',
  id_str: '85769942',
  geo_enabled: false,
  listed_count: 0,
  is_translator: false,
  profile_sidebar_border_color: 'C0DEED',
  utc_offset: null,
  name: 'Francesco T',
  lang: 'en',
  follow_request_sent: false,
  profile_background_tile: false,
  followers_count: 41,
  created_at: 'Wed Oct 28 08:12:38 +0000 2009',
  protected: false,
  profile_sidebar_fill_color: 'DDEEF6',
  default_profile_image: false,
  profile_image_url_https: 'https://twimg0-a.akamaihd.net/profile_images/1673873900/image_normal.jpg',
  url: null,
  friends_count: 96,
  favourites_count: 9,
  statuses_count: 54,
  profile_background_color: 'C0DEED',
  verified: false,
  following: false,
  notifications: false,
  profile_image_url: 'http://a0.twimg.com/profile_images/1673873900/image_normal.jpg',
  profile_background_image_url_https: 'https://twimg0-a.akamaihd.net/images/themes/theme1/bg.png',
  profile_background_image_url: 'http://a0.twimg.com/images/themes/theme1/bg.png',
  profile_link_color: '0084B4',
  location: null,
  status:
   { entities: { urls: [], hashtags: [Object], user_mentions: [Object] },
     place: null,
     favorited: false,
     created_at: 'Wed Jan 30 11:47:25 +0000 2013',
     in_reply_to_status_id_str: null,
     geo: null,
     in_reply_to_user_id_str: null,
     contributors: null,
     retweet_count: 5,
     retweeted_status:
      { entities: [Object],
        place: null,
        favorited: false,
        created_at: 'Wed Jan 30 10:08:58 +0000 2013',
        in_reply_to_status_id_str: null,
        geo: null,
        in_reply_to_user_id_str: null,
        contributors: null,
        retweet_count: 5,
        retweeted: false,
        text: 'Memoria corta? Pastiglia N.2\n\n#Alfano: "Il lavoro al primo posto!Parleremo anche di accesso al credito. Ok agenda Monti.Ci sarò"\n\n12/03/2012',
        id_str: '296560628825481216',
        source: 'Twitter for Mac',
        coordinates: null,
        in_reply_to_screen_name: null,
        in_reply_to_user_id: null,
        in_reply_to_status_id: null,
        id: 296560628825481200,
        truncated: false },
     retweeted: false,
     text: 'RT @carlo_secchi: Memoria corta? Pastiglia N.2\n\n#Alfano: "Il lavoro al primo posto!Parleremo anche di accesso al credito. Ok agenda Mont ...',
     id_str: '296585406223376384',
     source: 'Twitter for iPad',
     coordinates: null,
     in_reply_to_screen_name: null,
     in_reply_to_user_id: null,
     in_reply_to_status_id: null,
     id: 296585406223376400,
     truncated: false },
  screen_name: 'francescocomo',
  default_profile: true,
  description: null,
  contributors_enabled: false }

 *
 */

var config = require('../config.js');
var mongoose = require('mongoose');
var twitter = require('ntwitter');
var credentials = require('../config_twitter.js');

mongoose.set('debug', config.db_debug)

console.log("opening connection with " + config.db_name + "@" + config.db_host );
var db = mongoose.createConnection(config.db_host, config.db_name);

var t = new twitter({
    consumer_key: credentials.twit_consumer_key,
    consumer_secret: credentials.twit_consumer_secret,
    access_token_key: credentials.twit_access_token,
    access_token_secret: credentials.twit_token_secret
});

// if you have problems here change ulimit "ulimit -n [how-much-you-want]"
process.setMaxListeners(0);
db.once('open', function() {
    function saveExtraInfo(info, usr, callback){
        usr.mep_follower_count = info.mep_follower_count;
        usr.mep_last_tweet_time = info.mep_last_tweet_time;
        usr.mep_last_tweet = info.mep_last_tweet;
        usr.mep_tweet_count = info.mep_tweet_count;
        usr.save(function(err, type){
            if (err) {
                console.error('Saving user ' + usr.mep_firstName + ' problem.');
                process.exit(0);
              }
            callback();
        });
        // nome generico
    }

    var mepSchema = config.schema
    var MepModel = db.model(config.db_collection, mepSchema);

    // avatar importer async version
    var counter = 0;
    var counterInGroup = 0;
    var group = 0;
    var counterResponseItems = 0;
    var countResponseDiff = 0;
    var counterResponse = 0;
    var counterRequest = 0;
    var option = {};
    if(process.argv.length == 3){
    	option = {"mep_follower_count" : {$not : {$gt : -1}}};
    }

    MepModel.find(option, function(err, meps) {
      count = meps.length;
      mep_twitterUrls = new Array();
      meps.forEach(function(i) {
      	mep_twitterUrls[group] = i.mep_twitterUserName;
      	group++;
    	counterInGroup++;
		if(group == 100 || meps.length-counterInGroup == 0){
			console.log("group: " + group);
			console.log("remains: " + (meps.length-counterInGroup));
	    	var params = {screen_name : mep_twitterUrls.join(',')};
		      mep_twitterUrls = new Array();
	        var url = "https://api.twitter.com/1.1/users/lookup.json";

	        t.get(url, params, function(err, data) {
	        	counterResponse++;
	            if (err) {
	                console.log(err);
		            counter = counter+100;
    	            if (counter == meps.length || counterRequest == counterResponse) {
	    	              console.log('Imported: ' + counterResponseItems + ' extra info.');
	    	              mongoose.disconnect();
	    	              process.exit();
	    	            }
	              }
	            else{
	            	counterResponseItems += data.length;
	            	countResponseDiff = countResponseDiff+(group-data.length);
	            	data.forEach(function(user) {
	    	              MepModel.findOneAndUpdate({"mep_twitterUserName" :  { $regex : "^" + user.screen_name + "$", $options: 'i' }}, {
	 	            		   "mep_follower_count" : user.followers_count,
	 	           		       "mep_last_tweet_time" : (typeof(user.status) != "undefined" && typeof(user.status.created_at) !== "undefined") ? user.status.created_at : null,
	 	        		       "mep_last_tweet" : (typeof(user.status) != "undefined" && typeof(user.status.text) !== "undefined") ? user.status.text : null,
	 	        		       "mep_tweet_count" : user.statuses_count
	 	            		},
	 	            		function(err) {
			    	            counter++;
			    	            if (counter == meps.length || counterRequest == counterResponse) {
				    	              console.log('Imported: ' + counterResponseItems + ' extra info.');
				    	              mongoose.disconnect();
				    	              process.exit();
			    	            }
			    	          });
	 	            		}
	 	            	);

/*
*/
	            }
	        });
			group = 0;
		}
      });
    });
});

// force disconnect to avoid infinit loop
 setTimeout( function () {
     mongoose.disconnect();
  }, 5000);
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2014
 *
 * This file is licensed under the Affero General Public License version 3
 * or later.
 *
 * See the COPYING-README file.
 *
 */

(function() {
	OC.Update = {
		_started : false,

		/**
		 * Start the update process.
		 *
		 * @param $el progress list element
		 */
		start: function($el, options) {
			if (this._started) {
				return;
			}

			var hasWarnings = false;

			this.$el = $el;

			this._started = true;

			var self = this;

			$(window).on('beforeunload.inprogress', function () {
				return t('core', 'The update is in progress, leaving this page might interrupt the process in some environments.');
			});

			$('#update-progress-title').html(t(
				'core',
				'Update to {version}', {
					version: options.version
				})
			);

			var updateEventSource = new OC.EventSource(OC.webroot+'/core/ajax/update.php');
			updateEventSource.listen('success', function(message) {
				self.setMessage(message);
			});
			updateEventSource.listen('notice', function(message) {
				self.setPermanentMessage(message);
				hasWarnings = true;
			});
			updateEventSource.listen('error', function(message) {
				$('#update-progress-message').hide();
				$('#update-progress-icon')
					.addClass('icon-error-white')
					.removeClass('icon-loading-dark');
				message = message || t('core', 'An error occurred.');
				$(window).off('beforeunload.inprogress');
				self.setErrorMessage(message);
				message = t('core', 'Please reload the page.');
				$('').addClass('error').append(''+message+'
').appendTo($el);
				updateEventSource.close();
			});
			updateEventSource.listen('failure', function(message) {
				$(window).off('beforeunload.inprogress');
				$('#update-progress-message').hide();
				$('#update-progress-icon')
					.addClass('icon-error-white')
					.removeClass('icon-loading-dark');

				self.setErrorMessage(message);
				var span = $('')
					.addClass('bold');
				if(message === 'Exception: Updates between multiple major versions and downgrades are unsupported.') {
					span.append(t('core', 'The update was unsuccessful. For more information check our forum post covering this issue.', {'url': 'https://forum.owncloud.org/viewtopic.php?f=17&t=32087'}));
				} else {
					span.append(t('core', 'The update was unsuccessful. ' +
						'Please report this issue to the ' +
						'Nextcloud community.'));
				}
				span.appendTo($el);
			});
			updateEventSource.listen('done', function() {
				$(window).off('beforeunload.inprogress');

				$('#update-progress-message').hide();

				$('#update-progress-icon')
					.addClass('icon-checkmark-white')
					.removeClass('icon-loading-dark');

				if (hasWarnings) {
					$el.find('.update-show-detailed').before(
						$('<input type="button" class="update-continue" value="'+t('core', 'Continue to Nextcloud')+'">').on('click', function() {
							window.location.reload();
						})
					);
				} else {
					// FIXME: use product name
					$el.find('.update-show-detailed').before(
						$('
'+t('core', 'The update was successful. Redirecting you to Nextcloud now.')+'
')
					);
					setTimeout(function () {
						OC.redirect(OC.webroot + '/');
					}, 3000);
				}
			});
		},

		setMessage: function(message) {
			$('#update-progress-message').html(message);
			$('#update-progress-detailed')
				.append($(''))
				.append(message)
				.append($('
'));
		},

		setPermanentMessage: function(message) {
			$('#update-progress-message').html(message);
			$('#update-progress-message-warnings')
				.show()
				.append($('
').append(message));
			$('#update-progress-detailed')
				.append($(''))
				.append(message)
				.append($('
'));
		},

		setErrorMessage: function (message) {
			$('#update-progress-message-error')
				.show()
				.html(message);
			$('#update-progress-detailed')
				.append($(''))
				.append(message)
				.append($('
'));
		}
	};

})();

$(document).ready(function() {
	$('.updateButton').on('click', function() {
		var $updateEl = $('.update');
		var $progressEl = $('.update-progress');
		$progressEl.removeClass('hidden');
		$('.updateOverview').addClass('hidden');
		$('#update-progress-message-error').hide();
		$('#update-progress-message-warnings').hide();
		OC.Update.start($progressEl, {
			productName: $updateEl.attr('data-productname'),
			version: $updateEl.attr('data-version')
		});
		return false;
	});
	$('.update-show-detailed').on('click', function() {
		$('#update-progress-detailed').toggleClass('hidden');
		return false;
	});
});
<commit_msg>Don't link to the oC forum<commit_after>/*
 * Copyright (c) 2014
 *
 * This file is licensed under the Affero General Public License version 3
 * or later.
 *
 * See the COPYING-README file.
 *
 */

(function() {
	OC.Update = {
		_started : false,

		/**
		 * Start the update process.
		 *
		 * @param $el progress list element
		 */
		start: function($el, options) {
			if (this._started) {
				return;
			}

			var hasWarnings = false;

			this.$el = $el;

			this._started = true;

			var self = this;

			$(window).on('beforeunload.inprogress', function () {
				return t('core', 'The update is in progress, leaving this page might interrupt the process in some environments.');
			});

			$('#update-progress-title').html(t(
				'core',
				'Update to {version}', {
					version: options.version
				})
			);

			var updateEventSource = new OC.EventSource(OC.webroot+'/core/ajax/update.php');
			updateEventSource.listen('success', function(message) {
				self.setMessage(message);
			});
			updateEventSource.listen('notice', function(message) {
				self.setPermanentMessage(message);
				hasWarnings = true;
			});
			updateEventSource.listen('error', function(message) {
				$('#update-progress-message').hide();
				$('#update-progress-icon')
					.addClass('icon-error-white')
					.removeClass('icon-loading-dark');
				message = message || t('core', 'An error occurred.');
				$(window).off('beforeunload.inprogress');
				self.setErrorMessage(message);
				message = t('core', 'Please reload the page.');
				$('').addClass('error').append(''+message+'
').appendTo($el);
				updateEventSource.close();
			});
			updateEventSource.listen('failure', function(message) {
				$(window).off('beforeunload.inprogress');
				$('#update-progress-message').hide();
				$('#update-progress-icon')
					.addClass('icon-error-white')
					.removeClass('icon-loading-dark');

				self.setErrorMessage(message);
				var span = $('')
					.addClass('bold');
				if(message === 'Exception: Updates between multiple major versions and downgrades are unsupported.') {
					span.append(t('core', 'The update was unsuccessful. For more information check our forum post covering this issue.', {'url': 'https://help.nextcloud.com/t/updates-between-multiple-major-versions-are-unsupported/7094'}));
				} else {
					span.append(t('core', 'The update was unsuccessful. ' +
						'Please report this issue to the ' +
						'Nextcloud community.'));
				}
				span.appendTo($el);
			});
			updateEventSource.listen('done', function() {
				$(window).off('beforeunload.inprogress');

				$('#update-progress-message').hide();

				$('#update-progress-icon')
					.addClass('icon-checkmark-white')
					.removeClass('icon-loading-dark');

				if (hasWarnings) {
					$el.find('.update-show-detailed').before(
						$('<input type="button" class="update-continue" value="'+t('core', 'Continue to Nextcloud')+'">').on('click', function() {
							window.location.reload();
						})
					);
				} else {
					// FIXME: use product name
					$el.find('.update-show-detailed').before(
						$('
'+t('core', 'The update was successful. Redirecting you to Nextcloud now.')+'
')
					);
					setTimeout(function () {
						OC.redirect(OC.webroot + '/');
					}, 3000);
				}
			});
		},

		setMessage: function(message) {
			$('#update-progress-message').html(message);
			$('#update-progress-detailed')
				.append($(''))
				.append(message)
				.append($('
'));
		},

		setPermanentMessage: function(message) {
			$('#update-progress-message').html(message);
			$('#update-progress-message-warnings')
				.show()
				.append($('
').append(message));
			$('#update-progress-detailed')
				.append($(''))
				.append(message)
				.append($('
'));
		},

		setErrorMessage: function (message) {
			$('#update-progress-message-error')
				.show()
				.html(message);
			$('#update-progress-detailed')
				.append($(''))
				.append(message)
				.append($('
'));
		}
	};

})();

$(document).ready(function() {
	$('.updateButton').on('click', function() {
		var $updateEl = $('.update');
		var $progressEl = $('.update-progress');
		$progressEl.removeClass('hidden');
		$('.updateOverview').addClass('hidden');
		$('#update-progress-message-error').hide();
		$('#update-progress-message-warnings').hide();
		OC.Update.start($progressEl, {
			productName: $updateEl.attr('data-productname'),
			version: $updateEl.attr('data-version')
		});
		return false;
	});
	$('.update-show-detailed').on('click', function() {
		$('#update-progress-detailed').toggleClass('hidden');
		return false;
	});
});
<|endoftext|>


<commit_before>var fs = require('fs');
var path = require('path');
var favicon = require('serve-favicon');
var async = require('neo-async');
var winston = require('winston');

var common = require('./common');

function getThemeList(themeFolder, callback) {
    fs.readdir(themeFolder, function (error, directories) {
        async.map(directories, getThemeInfo,
            function (error, result) {
                callback(result);
            });
    });
}

function getThemeInfo(directory, done) {
    console.log(' = Processed directory...', directory);

    function getScreenshot(done) {
        var screenshot;
        var file = path.join('theme', directory, 'screenshot.jpg');
        fs.access(file, fs.R_OK, function (err) {
            if (err) {
                winston.warn(err);
            } else {
                screenshot = 'screenshot.jpg';
            }
            done(null, screenshot);
        });
    }

    function getDescription(done) {
        var description = {}, md;
        var file = path.join('theme', directory, 'description.md');
        fs.access(file, fs.R_OK, function (err) {
            if (err) {
                winston.warn(err);
            } else {
                md = fs.readFileSync(file, 'utf8');
                description = common.destructMarkdown(md);
            }
            done(null, description);
        });
    }

    async.parallel([getScreenshot, getDescription], function (error, result) {
        var themeInfo = {
            folderName: directory,
            screenshot: result[0],
            description: result[1],
            included: ['A', 'M', 'S']   // admin, manage, site
        };

        done(null, themeInfo);
    });
}

function getFavicon(themeName) {
    var themeFaviconPath = path.join('.', 'theme', themeName, 'common', 'asset', 'favicon.ico');
    var defaultFaviconPath = path.join('public', 'common', 'favicon.ico');

    if (fs.existsSync(themeFaviconPath)) {
        winston.info('bind theme favicon: /' + themeFaviconPath);

        return favicon(themeFaviconPath);
    } else {
        winston.verbose('bind default favicon: /' + defaultFaviconPath);

        return favicon(defaultFaviconPath);
    }
}

function bindFavicon(router, themeName) {
    var faviconPath = path.join('.', 'theme', themeName, 'common', 'asset', 'favicon.ico');

    fs.stat(faviconPath, function (error, stat) {
        if (error) {
            winston.info('bind theme favicon');

            router.use(favicon(path.join('public', 'common', 'favicon.ico')))
        } else {
            winston.verbose('bind default favicon');

            router.use(favicon(faviconPath));
        }
    });
}

function get404Handler(themeName) {
    return function _404Handler(req, res, next){
        res.status(404);
        winston.warn(`error status 404: ${req.url}`);

        // respond with html page
        if (req.accepts('html')) {
            fs.stat(path.join('.', 'theme', themeName, 'page', '_500.html'), function (error, stat) {
                if (error) {
                    res.render('status404', { url: req.url });
                } else {
                    res.render('../theme/' + themeName + '/page/_404', { url: req.url });
                }
            });
            return;
        }

        // respond with json
        if (req.accepts('json')) {
            res.send({ error: 'Not found' });
            return;
        }

        // default to plain-text. send()
        res.type('txt').send('Not found');
    }
}

function get500Handler(themeName) {
    return function _500Handler(err, req, res, next){
        // we may use properties of the error object
        // here and next(err) appropriately, or if
        // we possibly recovered from the error, simply next().
        res.status(err.status || 500);
        winston.error(`get 500 handler ${err}`);

        // set default 500 page
        fs.stat(path.join('.', 'theme', themeName, 'page', '_500.html'), function (error, stat) {
            if (error) {
                res.render('status500', { error: err });
            } else {
                res.render('../theme/' + themeName + '/page/_500', { error: err });
            }
        });
    }
}

module.exports = {
    getThemeList: getThemeList,
    getFavicon: getFavicon,
    bindFavicon: bindFavicon,
    get404Handler: get404Handler,
    get500Handler: get500Handler
};<commit_msg>Removed deprecated fs method<commit_after>var fs = require('fs');
var path = require('path');
var favicon = require('serve-favicon');
var async = require('neo-async');
var winston = require('winston');

var common = require('./common');

function getThemeList(themeFolder, callback) {
    fs.readdir(themeFolder, function (error, directories) {
        async.map(directories, getThemeInfo,
            function (error, result) {
                callback(result);
            });
    });
}

function getThemeInfo(directory, done) {
    console.log(' = Processed directory...', directory);

    function getScreenshot(done) {
        var screenshot;
        var file = path.join('theme', directory, 'screenshot.jpg');
        fs.access(file, fs.R_OK, function (err) {
            if (err) {
                winston.warn(err);
            } else {
                screenshot = 'screenshot.jpg';
            }
            done(null, screenshot);
        });
    }

    function getDescription(done) {
        var description = {}, md;
        var file = path.join('theme', directory, 'description.md');
        fs.access(file, fs.R_OK, function (err) {
            if (err) {
                winston.warn(err);
            } else {
                md = fs.readFileSync(file, 'utf8');
                description = common.destructMarkdown(md);
            }
            done(null, description);
        });
    }

    async.parallel([getScreenshot, getDescription], function (error, result) {
        var themeInfo = {
            folderName: directory,
            screenshot: result[0],
            description: result[1],
            included: ['A', 'M', 'S']   // admin, manage, site
        };

        done(null, themeInfo);
    });
}

function getFavicon(themeName) {
    var themeFaviconPath = path.join('.', 'theme', themeName, 'common', 'asset', 'favicon.ico');
    var defaultFaviconPath = path.join('public', 'common', 'favicon.ico');

    try {
        fs.accessSync(themeFaviconPath)
        winston.info('bind theme favicon: /' + themeFaviconPath);

        return favicon(themeFaviconPath);
    } catch(err) {
        winston.verbose('bind default favicon: /' + defaultFaviconPath);

        return favicon(defaultFaviconPath);
    }
}

function bindFavicon(router, themeName) {
    var faviconPath = path.join('.', 'theme', themeName, 'common', 'asset', 'favicon.ico');

    fs.stat(faviconPath, function (error, stat) {
        if (error) {
            winston.info('bind theme favicon');

            router.use(favicon(path.join('public', 'common', 'favicon.ico')))
        } else {
            winston.verbose('bind default favicon');

            router.use(favicon(faviconPath));
        }
    });
}

function get404Handler(themeName) {
    return function _404Handler(req, res, next){
        res.status(404);
        winston.warn(`error status 404: ${req.url}`);

        // respond with html page
        if (req.accepts('html')) {
            fs.stat(path.join('.', 'theme', themeName, 'page', '_500.html'), function (error, stat) {
                if (error) {
                    res.render('status404', { url: req.url });
                } else {
                    res.render('../theme/' + themeName + '/page/_404', { url: req.url });
                }
            });
            return;
        }

        // respond with json
        if (req.accepts('json')) {
            res.send({ error: 'Not found' });
            return;
        }

        // default to plain-text. send()
        res.type('txt').send('Not found');
    }
}

function get500Handler(themeName) {
    return function _500Handler(err, req, res, next){
        // we may use properties of the error object
        // here and next(err) appropriately, or if
        // we possibly recovered from the error, simply next().
        res.status(err.status || 500);
        winston.error(`get 500 handler ${err}`);

        // set default 500 page
        fs.stat(path.join('.', 'theme', themeName, 'page', '_500.html'), function (error, stat) {
            if (error) {
                res.render('status500', { error: err });
            } else {
                res.render('../theme/' + themeName + '/page/_500', { error: err });
            }
        });
    }
}

module.exports = {
    getThemeList: getThemeList,
    getFavicon: getFavicon,
    bindFavicon: bindFavicon,
    get404Handler: get404Handler,
    get500Handler: get500Handler
};<|endoftext|>


<commit_before>'use strict'

const { isString, assign } = require('lodash')
const createLogger = require('acho')

const isTest = process.env.NODE_ENV === 'test'

function log (opts) {
  if (isString(opts)) opts = { keyword: opts }

  const loggerOpts = assign({}, opts, {
    level: isTest && 'muted'
  })

  return createLogger(loggerOpts)
}

module.exports = log
<commit_msg>Adjust prod level<commit_after>'use strict'

const { isString, assign } = require('lodash')
const createLogger = require('acho')

const isTest = process.env.NODE_ENV === 'test'

function log (opts) {
  if (isString(opts)) opts = { keyword: opts }

  const loggerOpts = assign({}, opts, {
    level: isTest ? 'muted' : 'all'
  })

  return createLogger(loggerOpts)
}

module.exports = log
<|endoftext|>


<commit_before>/* jslint node: true */
'use strict';

//  ENiGMA½
const MenuModule            = require('./menu_module.js').MenuModule;

const {
    getModDatabasePath,
    getTransactionDatabase
}                           = require('./database.js');

//  deps
const sqlite3               = require('sqlite3');
const async                 = require('async');
const _                     = require('lodash');
const moment                = require('moment');

/*
    Module :TODO:
    * Add ability to at least alternate formatStrings -- every other
*/

exports.moduleInfo = {
    name        : 'Onelinerz',
    desc        : 'Standard local onelinerz',
    author      : 'NuSkooler',
    packageName : 'codes.l33t.enigma.onelinerz',
};

const MciViewIds = {
    view    :  {
        entries     : 1,
        addPrompt   : 2,
    },
    add : {
        newEntry        : 1,
        entryPreview    : 2,
        addPrompt       : 3,
    }
};

const FormIds = {
    view    : 0,
    add     : 1,
};

exports.getModule = class OnelinerzModule extends MenuModule {
    constructor(options) {
        super(options);

        const self = this;

        this.menuMethods = {
            viewAddScreen : function(formData, extraArgs, cb) {
                return self.displayAddScreen(cb);
            },

            addEntry : function(formData, extraArgs, cb) {
                if(_.isString(formData.value.oneliner) && formData.value.oneliner.length > 0) {
                    const oneliner = formData.value.oneliner.trim();    //  remove any trailing ws

                    self.storeNewOneliner(oneliner, err => {
                        if(err) {
                            self.client.log.warn( { error : err.message }, 'Failed saving oneliner');
                        }

                        self.clearAddForm();
                        return self.displayViewScreen(true, cb);    //  true=cls
                    });

                } else {
                    //  empty message - treat as if cancel was hit
                    return self.displayViewScreen(true, cb);    //  true=cls
                }
            },

            cancelAdd : function(formData, extraArgs, cb) {
                self.clearAddForm();
                return self.displayViewScreen(true, cb);    //  true=cls
            }
        };
    }

    initSequence() {
        const self = this;
        async.series(
            [
                function beforeDisplayArt(callback) {
                    return self.beforeArt(callback);
                },
                function display(callback) {
                    return self.displayViewScreen(false, callback);
                }
            ],
            err => {
                if(err) {
                    //  :TODO: Handle me -- initSequence() should really take a completion callback
                }
                self.finishedLoading();
            }
        );
    }

    displayViewScreen(clearScreen, cb) {
        const self = this;

        async.waterfall(
            [
                function prepArtAndViewController(callback) {
                    if(self.viewControllers.add) {
                        self.viewControllers.add.setFocus(false);
                    }

                    return self.prepViewControllerWithArt(
                        'view',
                        FormIds.view,
                        {
                            clearScreen,
                            trailingLF : false
                        },
                        (err, artInfo, wasCreated) => {
                            if(!err && !wasCreated) {
                                self.viewControllers.view.setFocus(true);
                                self.viewControllers.view.getView(MciViewIds.view.addPrompt).redraw();
                            }
                            return callback(err);
                        }
                    );
                },
                function fetchEntries(callback) {
                    const entriesView = self.viewControllers.view.getView(MciViewIds.view.entries);
                    const limit = entriesView.dimens.height;
                    let entries = [];

                    self.db.each(
                        `SELECT *
                        FROM (
                            SELECT *
                            FROM onelinerz
                            ORDER BY timestamp DESC
                            LIMIT ${limit}
                            )
                        ORDER BY timestamp ASC;`,
                        (err, row) => {
                            if(!err) {
                                row.timestamp = moment(row.timestamp);  //  convert -> moment
                                entries.push(row);
                            }
                        },
                        err => {
                            return callback(err, entriesView, entries);
                        }
                    );
                },
                function populateEntries(entriesView, entries, callback) {
                    const tsFormat = self.menuConfig.config.timestampFormat || self.client.currentTheme.helpers.getDateFormat('short');

                    entriesView.setItems(entries.map( e => {
                        return {
                            userId      : e.user_id,
                            userName    : e.user_name,
                            oneliner    : e.oneliner,
                            ts          : e.timestamp.format(tsFormat),
                        };
                    }));

                    entriesView.redraw();
                    return callback(null);
                },
                function finalPrep(callback) {
                    const promptView = self.viewControllers.view.getView(MciViewIds.view.addPrompt);
                    promptView.setFocusItemIndex(1);    //  default to NO
                    return callback(null);
                }
            ],
            err => {
                if(cb) {
                    return cb(err);
                }
            }
        );
    }

    displayAddScreen(cb) {
        const self = this;

        async.waterfall(
            [
                function clearAndDisplayArt(callback) {
                    self.viewControllers.view.setFocus(false);

                    return self.prepViewControllerWithArt(
                        'add',
                        FormIds.add,
                        {
                            clearScreen : true,
                            trailingLF  : false
                        },
                        (err, artInfo, wasCreated) => {
                            if(!wasCreated) {
                                self.viewControllers.add.setFocus(true);
                                self.viewControllers.add.redrawAll();
                                self.viewControllers.add.switchFocus(MciViewIds.add.newEntry);
                            }
                            return callback(err);
                        }
                    );
                },
                function initPreviewUpdates(callback) {
                    const previewView   = self.viewControllers.add.getView(MciViewIds.add.entryPreview);
                    const entryView     = self.viewControllers.add.getView(MciViewIds.add.newEntry);
                    if(previewView) {
                        let timerId;
                        entryView.on('key press', () => {
                            clearTimeout(timerId);
                            timerId = setTimeout( () => {
                                const focused = self.viewControllers.add.getFocusedView();
                                if(focused === entryView) {
                                    previewView.setText(entryView.getData());
                                    focused.setFocus(true);
                                }
                            }, 500);
                        });
                    }
                    return callback(null);
                }
            ],
            err => {
                if(cb) {
                    return cb(err);
                }
            }
        );
    }

    clearAddForm() {
        this.setViewText('add', MciViewIds.add.newEntry, '');
        this.setViewText('add', MciViewIds.add.entryPreview, '');
    }

    initDatabase(cb) {
        const self = this;

        async.series(
            [
                function openDatabase(callback) {
                    self.db = getTransactionDatabase(new sqlite3.Database(
                        getModDatabasePath(exports.moduleInfo),
                        err => {
                            return callback(err);
                        }
                    ));
                },
                function createTables(callback) {
                    self.db.run(
                        `CREATE TABLE IF NOT EXISTS onelinerz (
                            id              INTEGER PRIMARY KEY,
                            user_id         INTEGER_NOT NULL,
                            user_name       VARCHAR NOT NULL,
                            oneliner        VARCHAR NOT NULL,
                            timestamp       DATETIME NOT NULL
                        );`
                        ,
                        err => {
                            return callback(err);
                        });
                }
            ],
            err => {
                return cb(err);
            }
        );
    }

    storeNewOneliner(oneliner, cb) {
        const self  = this;
        const ts    = moment().format('YYYY-MM-DDTHH:mm:ss.SSSZ');

        async.series(
            [
                function addRec(callback) {
                    self.db.run(
                        `INSERT INTO onelinerz (user_id, user_name, oneliner, timestamp)
                        VALUES (?, ?, ?, ?);`,
                        [ self.client.user.userId, self.client.user.username, oneliner, ts ],
                        callback
                    );
                },
                function removeOld(callback) {
                    //  keep 25 max most recent items - remove the older ones
                    self.db.run(
                        `DELETE FROM onelinerz
                        WHERE id IN (
                            SELECT id
                            FROM onelinerz
                            ORDER BY id DESC
                            LIMIT -1 OFFSET 25
                        );`,
                        callback
                    );
                }
            ],
            err => {
                return cb(err);
            }
        );
    }

    beforeArt(cb) {
        super.beforeArt(err => {
            return err ? cb(err) : this.initDatabase(cb);
        });
    }
};
<commit_msg>Allow how many to keep in DB by config 'retainCount'<commit_after>/* jslint node: true */
'use strict';

//  ENiGMA½
const MenuModule            = require('./menu_module.js').MenuModule;

const {
    getModDatabasePath,
    getTransactionDatabase
}                           = require('./database.js');

//  deps
const sqlite3               = require('sqlite3');
const async                 = require('async');
const _                     = require('lodash');
const moment                = require('moment');

/*
    Module :TODO:
    * Add ability to at least alternate formatStrings -- every other
*/

exports.moduleInfo = {
    name        : 'Onelinerz',
    desc        : 'Standard local onelinerz',
    author      : 'NuSkooler',
    packageName : 'codes.l33t.enigma.onelinerz',
};

const MciViewIds = {
    view    :  {
        entries     : 1,
        addPrompt   : 2,
    },
    add : {
        newEntry        : 1,
        entryPreview    : 2,
        addPrompt       : 3,
    }
};

const FormIds = {
    view    : 0,
    add     : 1,
};

exports.getModule = class OnelinerzModule extends MenuModule {
    constructor(options) {
        super(options);

        const self = this;

        this.menuMethods = {
            viewAddScreen : function(formData, extraArgs, cb) {
                return self.displayAddScreen(cb);
            },

            addEntry : function(formData, extraArgs, cb) {
                if(_.isString(formData.value.oneliner) && formData.value.oneliner.length > 0) {
                    const oneliner = formData.value.oneliner.trim();    //  remove any trailing ws

                    self.storeNewOneliner(oneliner, err => {
                        if(err) {
                            self.client.log.warn( { error : err.message }, 'Failed saving oneliner');
                        }

                        self.clearAddForm();
                        return self.displayViewScreen(true, cb);    //  true=cls
                    });

                } else {
                    //  empty message - treat as if cancel was hit
                    return self.displayViewScreen(true, cb);    //  true=cls
                }
            },

            cancelAdd : function(formData, extraArgs, cb) {
                self.clearAddForm();
                return self.displayViewScreen(true, cb);    //  true=cls
            }
        };
    }

    initSequence() {
        const self = this;
        async.series(
            [
                function beforeDisplayArt(callback) {
                    return self.beforeArt(callback);
                },
                function display(callback) {
                    return self.displayViewScreen(false, callback);
                }
            ],
            err => {
                if(err) {
                    //  :TODO: Handle me -- initSequence() should really take a completion callback
                }
                self.finishedLoading();
            }
        );
    }

    displayViewScreen(clearScreen, cb) {
        const self = this;

        async.waterfall(
            [
                function prepArtAndViewController(callback) {
                    if(self.viewControllers.add) {
                        self.viewControllers.add.setFocus(false);
                    }

                    return self.prepViewControllerWithArt(
                        'view',
                        FormIds.view,
                        {
                            clearScreen,
                            trailingLF : false
                        },
                        (err, artInfo, wasCreated) => {
                            if(!err && !wasCreated) {
                                self.viewControllers.view.setFocus(true);
                                self.viewControllers.view.getView(MciViewIds.view.addPrompt).redraw();
                            }
                            return callback(err);
                        }
                    );
                },
                function fetchEntries(callback) {
                    const entriesView = self.viewControllers.view.getView(MciViewIds.view.entries);
                    const limit = entriesView.dimens.height;
                    let entries = [];

                    self.db.each(
                        `SELECT *
                        FROM (
                            SELECT *
                            FROM onelinerz
                            ORDER BY timestamp DESC
                            LIMIT ${limit}
                            )
                        ORDER BY timestamp ASC;`,
                        (err, row) => {
                            if(!err) {
                                row.timestamp = moment(row.timestamp);  //  convert -> moment
                                entries.push(row);
                            }
                        },
                        err => {
                            return callback(err, entriesView, entries);
                        }
                    );
                },
                function populateEntries(entriesView, entries, callback) {
                    const tsFormat = self.menuConfig.config.timestampFormat || self.client.currentTheme.helpers.getDateFormat('short');

                    entriesView.setItems(entries.map( e => {
                        return {
                            userId      : e.user_id,
                            userName    : e.user_name,
                            oneliner    : e.oneliner,
                            ts          : e.timestamp.format(tsFormat),
                        };
                    }));

                    entriesView.redraw();
                    return callback(null);
                },
                function finalPrep(callback) {
                    const promptView = self.viewControllers.view.getView(MciViewIds.view.addPrompt);
                    promptView.setFocusItemIndex(1);    //  default to NO
                    return callback(null);
                }
            ],
            err => {
                if(cb) {
                    return cb(err);
                }
            }
        );
    }

    displayAddScreen(cb) {
        const self = this;

        async.waterfall(
            [
                function clearAndDisplayArt(callback) {
                    self.viewControllers.view.setFocus(false);

                    return self.prepViewControllerWithArt(
                        'add',
                        FormIds.add,
                        {
                            clearScreen : true,
                            trailingLF  : false
                        },
                        (err, artInfo, wasCreated) => {
                            if(!wasCreated) {
                                self.viewControllers.add.setFocus(true);
                                self.viewControllers.add.redrawAll();
                                self.viewControllers.add.switchFocus(MciViewIds.add.newEntry);
                            }
                            return callback(err);
                        }
                    );
                },
                function initPreviewUpdates(callback) {
                    const previewView   = self.viewControllers.add.getView(MciViewIds.add.entryPreview);
                    const entryView     = self.viewControllers.add.getView(MciViewIds.add.newEntry);
                    if(previewView) {
                        let timerId;
                        entryView.on('key press', () => {
                            clearTimeout(timerId);
                            timerId = setTimeout( () => {
                                const focused = self.viewControllers.add.getFocusedView();
                                if(focused === entryView) {
                                    previewView.setText(entryView.getData());
                                    focused.setFocus(true);
                                }
                            }, 500);
                        });
                    }
                    return callback(null);
                }
            ],
            err => {
                if(cb) {
                    return cb(err);
                }
            }
        );
    }

    clearAddForm() {
        this.setViewText('add', MciViewIds.add.newEntry, '');
        this.setViewText('add', MciViewIds.add.entryPreview, '');
    }

    initDatabase(cb) {
        const self = this;

        async.series(
            [
                function openDatabase(callback) {
                    self.db = getTransactionDatabase(new sqlite3.Database(
                        getModDatabasePath(exports.moduleInfo),
                        err => {
                            return callback(err);
                        }
                    ));
                },
                function createTables(callback) {
                    self.db.run(
                        `CREATE TABLE IF NOT EXISTS onelinerz (
                            id              INTEGER PRIMARY KEY,
                            user_id         INTEGER_NOT NULL,
                            user_name       VARCHAR NOT NULL,
                            oneliner        VARCHAR NOT NULL,
                            timestamp       DATETIME NOT NULL
                        );`
                        ,
                        err => {
                            return callback(err);
                        });
                }
            ],
            err => {
                return cb(err);
            }
        );
    }

    storeNewOneliner(oneliner, cb) {
        const self  = this;
        const ts    = moment().format('YYYY-MM-DDTHH:mm:ss.SSSZ');

        async.series(
            [
                function addRec(callback) {
                    self.db.run(
                        `INSERT INTO onelinerz (user_id, user_name, oneliner, timestamp)
                        VALUES (?, ?, ?, ?);`,
                        [ self.client.user.userId, self.client.user.username, oneliner, ts ],
                        callback
                    );
                },
                function removeOld(callback) {
                    //  keep 25 max most recent items by default - remove the older ones
                    const retainCount = self.menuConfig.config.retainCount || 25;
                    self.db.run(
                        `DELETE FROM onelinerz
                        WHERE id IN (
                            SELECT id
                            FROM onelinerz
                            ORDER BY id DESC
                            LIMIT -1 OFFSET ${retainCount}
                        );`,
                        callback
                    );
                }
            ],
            err => {
                return cb(err);
            }
        );
    }

    beforeArt(cb) {
        super.beforeArt(err => {
            return err ? cb(err) : this.initDatabase(cb);
        });
    }
};
<|endoftext|>


<commit_before>var {defineSupportCode} = require('cucumber');
const {asserters} = require('wd');
const fs = require('fs');

const PixelDiff = require('pixel-diff');
const path = require('path');

const NEW_IMAGES_PATH = `${(process.env.CIRCLE_ARTIFACTS || '/tmp/agorask_build')}/screenshots`;

const cropOpts = {
  y: 75,
};
function createPixelDiff(imageAPath, imageBPath, diffFileFullName) {
  return new PixelDiff({
    imageAPath,
    imageBPath,
    cropImageA: cropOpts,
    cropImageB: cropOpts,

    thresholdType: PixelDiff.THRESHOLD_PERCENT,
    threshold: 0.02, // 1% threshold

    imageOutputPath: diffFileFullName
  });
}

function shouldUpdateScreenshot(fileName, updateScreenshots) {
  if (!updateScreenshots) return false;
  if (typeof updateScreenshots === 'string' && updateScreenshots.toLocaleLowerCase === 'all') {
    return true;
  }
  if (updateScreenshots instanceof Array && updateScreenshots.includes(fileName)) {
    return true;
  }
  return false;
}

function takeScreenshot(fileName) {
  const {updateScreenshots, screenshotsDirectories: {initial, newImages}} = this.parameters;
  const imageAPath = path.join(initial, `${fileName}.png`);
  const imageBPath = path.join(newImages, `${fileName}_new.png`);
  const diffFileFullName = path.join(newImages, `${fileName}_diff.png`);
  const diff = createPixelDiff(imageAPath, imageBPath, diffFileFullName);
  if (!fs.existsSync(imageAPath)) {
    console.log(`${imageAPath} doesn't exists, creating it`)
    return this.driver.saveScreenshot(imageAPath)
  }
  if (shouldUpdateScreenshot(fileName, updateScreenshots)) {
    console.log(`Updating ${fileName}`)
    return this.driver.saveScreenshot(imageAPath)
  }
  return this.driver.saveScreenshot(imageBPath)
    .then(() => diff.runWithPromise())
    .then((result) => {
      if (diff.hasPassed(result.code)) {
        return Promise.resolve();
      }
      console.log(result);
      return Promise.reject(`Found ${result.differences} differences`);
    });
}

defineSupportCode(function({Given, When, Then}) {
  When(/^I take a screenshot named "([^"]+)"$/, function (fileName) {
    return takeScreenshot.bind(this)(fileName);
  });
  When(/^I take a screenshot named "([^"]+)" after ([0-9]+) ?ms$/, function (fileName, delay) {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        takeScreenshot.bind(this)(fileName)
          .then(resolve).catch(reject);
      }, delay);
    })
  });

  When("wait ([0-9]+) ?ms", function(delay) {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve();
      }, delay);
    })
  });
  When("I hide the keyboard", function() {
    return this.driver.hideDeviceKeyboard();
  });
});<commit_msg>CI: wait before taking the login filled screenshot [ ci updateScreenshots login_filled,login_empty]<commit_after>var {defineSupportCode} = require('cucumber');
const {asserters} = require('wd');
const fs = require('fs');

const PixelDiff = require('pixel-diff');
const path = require('path');

const NEW_IMAGES_PATH = `${(process.env.CIRCLE_ARTIFACTS || '/tmp/agorask_build')}/screenshots`;

const cropOpts = {
  y: 75,
};
function createPixelDiff(imageAPath, imageBPath, diffFileFullName) {
  return new PixelDiff({
    imageAPath,
    imageBPath,
    cropImageA: cropOpts,
    cropImageB: cropOpts,

    thresholdType: PixelDiff.THRESHOLD_PERCENT,
    threshold: 0.02, // 1% threshold

    imageOutputPath: diffFileFullName
  });
}

function shouldUpdateScreenshot(fileName, updateScreenshots) {
  if (!updateScreenshots) return false;
  if (typeof updateScreenshots === 'string' && updateScreenshots.toLocaleLowerCase === 'all') {
    return true;
  }
  if (updateScreenshots instanceof Array && updateScreenshots.includes(fileName)) {
    return true;
  }
  return false;
}

function takeScreenshot(fileName) {
  const {updateScreenshots, screenshotsDirectories: {initial, newImages}} = this.parameters;
  const imageAPath = path.join(initial, `${fileName}.png`);
  const imageBPath = path.join(newImages, `${fileName}_new.png`);
  const diffFileFullName = path.join(newImages, `${fileName}_diff.png`);
  const diff = createPixelDiff(imageAPath, imageBPath, diffFileFullName);
  if (!fs.existsSync(imageAPath)) {
    console.log(`${imageAPath} doesn't exists, creating it`)
    return this.driver.saveScreenshot(imageAPath)
  }
  if (shouldUpdateScreenshot(fileName, updateScreenshots)) {
    console.log(`Updating ${fileName}`)
    return this.driver.saveScreenshot(imageAPath)
  }
  return this.driver.saveScreenshot(imageBPath)
    .then(() => diff.runWithPromise())
    .then((result) => {
      if (diff.hasPassed(result.code)) {
        return Promise.resolve();
      }
      console.log(result);
      return Promise.reject(`Found ${result.differences} differences`);
    });
}

defineSupportCode(function({Given, When, Then}) {
  When(/^I take a screenshot named "([^"]+)"$/, function (fileName) {
    return takeScreenshot.bind(this)(fileName);
  });
  When(/^I take a screenshot named "([^"]+)" after ([0-9]+) ?ms$/, function (fileName, delay) {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        takeScreenshot.bind(this)(fileName)
          .then(resolve).catch(reject);
      }, delay);
    })
  });

  When(/wait ([0-9]+) ?ms$/, function(delay) {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve();
      }, delay);
    })
  });
  When("I hide the keyboard", function() {
    return this.driver.hideDeviceKeyboard();
  });
});<|endoftext|>


<commit_before>/*
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the 'License');
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an 'AS IS' BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

const cheerio = require('cheerio');
const slug = require('uslug');
const path = require('path');
const storedImages = require('../helpers/stored-images');

/**
 * Adds .type--page-nav and .toc__link to TOC links because we can't control the output otherwise.
 *
 * @param {string} content - Content of each file.
 * @param {string} outputPath - Output path of the file
 *
 * @return {string}
 */
function domTransform(content, outputPath) {
  if (path.extname(outputPath) !== '.html') return content;

  const $ = cheerio.load(content);

  /**
   * Add missing classes
   */
  // Add type--page-nav and toc__link classes to TOC links
  $('.toc li').addClass('type--caption');
  $('.toc a').addClass('type--page-nav toc__link');

  // Add link class to Cookie Disclaimer link
  $('#cookieDisclaimer a').addClass('type--link');

  // Add classes to footnotes
  $('.footnotes-list').addClass('type--small');
  $('.footnote-backref').addClass('type--link');
  $('.foornote-item > p').addClass('footnote-item__p');

  // Add message class to messages
  $('[class*="message--"]').addClass('message');

  /**
   * Add IDs to terms
   */
  $('dt').each((i, elem) => $(elem).attr('id', `term--${slug($(elem).text())}`));

  /**
   * Make tables responsive
   */
  $('table').each((_, table) => {
    // get the table headers.
    const headers = $(table)
      .find('thead th')
      .map((_, th) => $(th).text());
    // loop over the all the table rows and assign a data attr to each column
    // with the corresponding column header.
    $(table)
      .find('tbody > tr')
      .each((_, tr) => {
        $(tr)
          .find('td')
          .each((i, td) => {
            $(td).attr('data-header', headers[i]);
          });
      });
  });

  /**
   * Add Blockquote Citation
   */
  $('blockquote').each((i, el) => {
    const next = $(el).next();

    if (next.hasClass('cite')) {
      const cite = $('').append(
        $(next)
          .clone()
          .removeClass('cite'),
      );
      $(next).remove();
      $(el).append(cite);
    }
  });

  /**
   * Add Header Anchor class
   */
  $('.header-anchor').each((i, el) => {
    const parent = $(el).parent();
    parent.addClass('header-anchor--wrapper');
  });

  /**
   * Add programming language header
   */
  $('pre[class*="language"]').each((i, el) => {
    const lang = $(el)
      .attr('class')
      .split(' ')
      .find(r => r.match(/^language-/))
      .replace('language-', '');

    const title = $(el).attr('title');

    $(el).wrap('

');
    let codeDescription = lang;
    if (!codeDescription || codeDescription.toLowerCase() == 'unknown') {
      codeDescription = '';
    }
    if (title != null) {
      codeDescription = codeDescription.concat(' - ', `<span class="type--revert">${title}</span>`);
    }
    $(`<figcaption class="code-figure--caption type--label">${codeDescription}</figcaption>`).insertBefore(el);
  });

  /**
   * Images from Google Storage
   */
  $('img[src^="gs://"]').each((i, el) => {
    buildGoogleStorageImage($, el);
  });

  return $.html();
}

// Storage things
const storageBase = 'https://firebasestorage.googleapis.com/v0/b/cros-staging.appspot.com/o/';

/**
 *
 * @param {Cheerio} $ - Cheerio instance
 * @param {Element} el - Cheerio element
 */
function buildGoogleStorageImage($, el) {
  const src = $(el).attr('src');
  const image = storedImages[src];
  const base = src.replace('gs://', '').replace(/\//g, '%2F');
  const url = storageBase + base;
  const newSrc = `${url}.${image.cuts.sort((a, b) => a - b)[Math.round((image.cuts.length - 1) / 2)]}${image.types.filter(t => t.extension !== '.webp')[0].extension}?alt=media`;

  const sources = image.types
    .map(type => {
      let source = `<source sizes="${image.sizes}" type="${type.type}"`;
      source += ` srcset="${image.cuts.map(c => `${url}.${c}${type.extension}?alt=media ${c}w`).join(', ')}"`;
      source += '>';
      return source;
    })
    .join('\n');

  $(el).attr('loading', 'lazy');
  $(el).attr('height', image.height);
  $(el).attr('width', image.width);
  $(el).attr('src', newSrc);
  $(el).wrap('<picture></picture>');
  $(sources).insertBefore(el);
}

module.exports = eleventy => {
  eleventy.addTransform('domTransform', domTransform);
};
<commit_msg>♻ (code) Use Google Buck URLs for external images<commit_after>/*
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the 'License');
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an 'AS IS' BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

const cheerio = require('cheerio');
const slug = require('uslug');
const path = require('path');
const storedImages = require('../helpers/stored-images');

/**
 * Adds .type--page-nav and .toc__link to TOC links because we can't control the output otherwise.
 *
 * @param {string} content - Content of each file.
 * @param {string} outputPath - Output path of the file
 *
 * @return {string}
 */
function domTransform(content, outputPath) {
  if (path.extname(outputPath) !== '.html') return content;

  const $ = cheerio.load(content);

  /**
   * Add missing classes
   */
  // Add type--page-nav and toc__link classes to TOC links
  $('.toc li').addClass('type--caption');
  $('.toc a').addClass('type--page-nav toc__link');

  // Add link class to Cookie Disclaimer link
  $('#cookieDisclaimer a').addClass('type--link');

  // Add classes to footnotes
  $('.footnotes-list').addClass('type--small');
  $('.footnote-backref').addClass('type--link');
  $('.foornote-item > p').addClass('footnote-item__p');

  // Add message class to messages
  $('[class*="message--"]').addClass('message');

  /**
   * Add IDs to terms
   */
  $('dt').each((i, elem) => $(elem).attr('id', `term--${slug($(elem).text())}`));

  /**
   * Make tables responsive
   */
  $('table').each((_, table) => {
    // get the table headers.
    const headers = $(table)
      .find('thead th')
      .map((_, th) => $(th).text());
    // loop over the all the table rows and assign a data attr to each column
    // with the corresponding column header.
    $(table)
      .find('tbody > tr')
      .each((_, tr) => {
        $(tr)
          .find('td')
          .each((i, td) => {
            $(td).attr('data-header', headers[i]);
          });
      });
  });

  /**
   * Add Blockquote Citation
   */
  $('blockquote').each((i, el) => {
    const next = $(el).next();

    if (next.hasClass('cite')) {
      const cite = $('').append(
        $(next)
          .clone()
          .removeClass('cite'),
      );
      $(next).remove();
      $(el).append(cite);
    }
  });

  /**
   * Add Header Anchor class
   */
  $('.header-anchor').each((i, el) => {
    const parent = $(el).parent();
    parent.addClass('header-anchor--wrapper');
  });

  /**
   * Add programming language header
   */
  $('pre[class*="language"]').each((i, el) => {
    const lang = $(el)
      .attr('class')
      .split(' ')
      .find(r => r.match(/^language-/))
      .replace('language-', '');

    const title = $(el).attr('title');

    $(el).wrap('

');
    let codeDescription = lang;
    if (!codeDescription || codeDescription.toLowerCase() == 'unknown') {
      codeDescription = '';
    }
    if (title != null) {
      codeDescription = codeDescription.concat(' - ', `<span class="type--revert">${title}</span>`);
    }
    $(`<figcaption class="code-figure--caption type--label">${codeDescription}</figcaption>`).insertBefore(el);
  });

  /**
   * Images from Google Storage
   */
  $('img[src^="gs://"]').each((i, el) => {
    buildGoogleStorageImage($, el);
  });

  return $.html();
}

// Storage things
const storageBase = 'https://storage.googleapis.com/cros-staging.appspot.com/';

/**
 *
 * @param {Cheerio} $ - Cheerio instance
 * @param {Element} el - Cheerio element
 */
function buildGoogleStorageImage($, el) {
  const src = $(el).attr('src');
  const image = storedImages[src];
  const base = src.replace('gs://', '');
  const url = storageBase + base;
  const newSrc = `${url}.${image.cuts.sort((a, b) => a - b)[Math.round((image.cuts.length - 1) / 2)]}${image.types.filter(t => t.extension !== '.webp')[0].extension}`;

  const sources = image.types
    .map(type => {
      let source = `<source sizes="${image.sizes}" type="${type.type}"`;
      source += ` srcset="${image.cuts.map(c => `${url}.${c}${type.extension} ${c}w`).join(', ')}"`;
      source += '>';
      return source;
    })
    .join('\n');

  $(el).attr('loading', 'lazy');
  $(el).attr('height', image.height);
  $(el).attr('width', image.width);
  $(el).attr('src', newSrc);
  $(el).wrap('<picture></picture>');
  $(sources).insertBefore(el);
}

module.exports = eleventy => {
  eleventy.addTransform('domTransform', domTransform);
};
<|endoftext|>