<commit_before>(function() {

//  ---------------------------------------------------------------------------------------------------------------  //
//  no.Model
//  ---------------------------------------------------------------------------------------------------------------  //

//  Базовый класс для моделей. Конструктор пустой, чтобы легче было наследоваться.
//  Вся инициализация делается в _init(), который вызывает фабрикой no.Model.create().
//
no.Model = function() {};

//  ---------------------------------------------------------------------------------------------------------------  //

//  Добавляем методы из no.Events: on(), off(), trigger().
no.extend(no.Model.prototype, no.Events);

//  ---------------------------------------------------------------------------------------------------------------  //

var _ctors = {};
var _infos = {};

var _cache = {};

var _keySuffix = 0;

//  ---------------------------------------------------------------------------------------------------------------  //

no.Model.prototype._init = function(id, params, data) {
    this.id = id;
    this.params = params;

    this._reset();
    this.setData(data);

    var info = this.info = _infos[id];

    this.key = no.Model.key(id, params, info);

    this.timstamp = 0;
};

no.Model.prototype._reset = function(status) {
    this.data = null;
    this.error = null;
    /*
        Возможные варианты status:

            'none'          данные еще не загружались
            'loading'       данные загружаются в данный момент
            'failed'        данные загрузились с ошибкой, нужен retry
            'error'         данные загрузились с ошибкой, retry невозможен
            'ok'            данные загрузились успешно
            'invalid'       модель вручную инвалидирована.
    */
    this.status = status || 'none';
    this.retries = 0;
    this.requests = 0;
};

//  ---------------------------------------------------------------------------------------------------------------  //

//  Определяем новую модель.
//
//      //  Простая модель, без параметров.
//      no.Model.define('profile');
//
//      no.Model.define('album', {
//          params: {
//              //  Любое значение, кроме null расценивается как дефолтное значение этого параметра.
//              //  На самом деле, конечно, не любое -- смысл имеют только Number и String.
//              'author-login': null,
//              'album-id': null,
//
//              //  Этим двум параметрам заданы дефолтные значения.
//              'page': 0,
//              'pageSize': 20
//          }
//      });
//
no.Model.define = function(id, info, ctor) {
    info = info || {};
    if (info.methods) {
        //  Нужно унаследоваться от no.Model и добавить в прототип info.models.
        ctor = no.inherits(function() {}, no.Model, info.methods);
    } else {
        ctor = ctor || no.Model;
    }

    var params = info.params || (( info.params = {} ));

    info.pNames = no.object.keys(params);

    //  Для do-моделей отдельные правила кэширования и построения ключей.
    info.isDo = /^do-/.test(id);

    _infos[id] = info;
    _ctors[id] = ctor;

    //  Создаем пустой кэш для всех моделей с данным id.
    _cache[id] = {};
};

//  Фабрика для моделей. Создает инстанс нужного класса и инициализирует его.
no.Model.create = function(id, params, data)  {
    var model = no.Model.get(id, params);

    if (!model) {
        var ctor = _ctors[id];
        model = new ctor();
        model._init(id, params, data);

        no.Model.store(model);
    } else if (data) {
        //  Модель уже существует, а мы пытаемся создать такую же, но с непустой data.
        throw Error('Model already exists');
    }

    return model;
};

//  ---------------------------------------------------------------------------------------------------------------  //

no.Model.info = function(id) {
    return _infos[id];
};

//  ---------------------------------------------------------------------------------------------------------------  //

no.Model.key = function(id, params, info) {
    info || ( info = _infos[id] );

    //  Для do-моделей ключ строим особым образом.
    if (info.isDo) {
        return 'do-' + _keySuffix++;
    }

    var defaults = info.params;
    var pNames = info.pNames;

    var key = 'model=' + id;

    for (var i = 0, l = pNames.length; i < l; i++) {
        var pName = pNames[i];

        var pValue = params[pName];
        //  Нельзя просто написать params[pName] || defaults[pName] --
        //  т.к. params[pName] может быть 0 или ''.
        pValue = (pValue === undefined) ? defaults[pName] : pValue;

        if (pValue != null) {
            key += '&' + pName + '=' + pValue;
        }
    }

    return key;
};

//  ---------------------------------------------------------------------------------------------------------------  //

//  Инвалидируем все модели с заданным id,
//  удовлетворяющие фильтру filter (функция, принимающая
//  параметром модель и возвращающая boolean).
no.Model.invalidate = function(id, filter) {
    var models = _cache[id];

    for (var key in models) {
        var model = models[key];
        if ( filter(model) ) {
            model.invalidate();
        }
    }
};

no.Model.prototype.invalidate = function() {
    this._reset('invalid');
};

no.Model.prototype.isValid = function() {
    return (this.status === 'ok');
};

//  ---------------------------------------------------------------------------------------------------------------  //

//  Возвращает данные, находящиеся по пути path.
//
//      var foo = model.get('foo'); // model.data.foo.
//      var bar = model.get('foo.bar'); // model.data.foo.bar (если foo существует).
//
no.Model.prototype.get = function(path) {
    var data = this.data;
    if (data) {
        return no.path(path, data);
    }
};

//  Сохраняет value по пути path.
//
//  Возможные флаги, которые могут быть в options:
//
//      {
//          silent: true        //  Не генерить событие о том, что модель изменилась,
//      }
//
no.Model.prototype.set = function(path, value, options) {
    var data = this.data;
    if (!data) { return; }

    //  Сохраняем новое значение и одновременно получаем старое значение.
    var oldValue = no.path(path, data, value);

    if ( !( (options && options.silent) || no.object.isEqual(value, oldValue) ) ) {
        //  FIXME: Может быть отправлять старое/новое значение?
        this.trigger('changed.' + path);
    }
};

//  ---------------------------------------------------------------------------------------------------------------  //

no.Model.prototype.getData = function() {
    return this.data;
};

//  Заменяет данные модели на data.
//
//  При этом по-дефолту на модели генерится событие 'changed'.
//  Это поведение можно поменять, передав объект options:
//
//      {
//          silent: true        //  Не генерить событие о том, что модель изменилась,
//      }
//
no.Model.prototype.setData = function(data, options) {
    if (data) {
        var old = this.data;
        this.data = this.preprocessData(data);
        this.error = null;
        this.status = 'ok';

        //  Не проверяем здесь, действительно ли data отличается от oldData --
        //  setData должен вызываться только когда обновленная модель целиком перезапрошена.
        //  Можно считать, что она в этом случае всегда меняется.
        if (old != null && !(options && options.silent) ) {
            this.trigger('changed');
        }
    }

};

no.Model.prototype.getError = function() {
    return this.error;
};

no.Model.prototype.setError = function(error) {
    this.data = null;
    this.error = error;
    this.status = 'failed';
};

no.Model.prototype.preprocessData = function(data) {
    return data;
};

//  ---------------------------------------------------------------------------------------------------------------  //

//  FIXME: Этот код сильно пересекается с вычислением ключа.
//  Нельзя ли избавиться от копипаста?
no.Model.prototype.getRequestParams = function() {
    var params = this.params;

    var defaults = this.info.params;
    var reqParams = {};

    for (var pName in defaults) {
        var pValue = params[pName];

        pValue = (pValue === undefined) ? defaults[pName] : pValue;
        if (pValue != null) {
            reqParams[pName] = pValue;
        }
    }

    return reqParams;
};

//  ---------------------------------------------------------------------------------------------------------------  //

//  Работа с кэшем.

//  Достаем модель из кэша.
no.Model.get = function(id, key) {
    key = (typeof key === 'string') ? key : no.Model.key(id, key);

    var model = _cache[id][key];
    return model;
};

//  Сохраняем модель в кэше.
no.Model.store = function(model) {
    if ( model.isDo() ) {
        return;
    }

    var id = model.id;
    var key = model.key;

    var cached = _cache[id][key];
    if (!cached) {
        _cache[id][key] = model;
    } else {
        //  NOTE: Почему тут нельзя просто заменить старую модель на новую.
        //  Потому, что в этом случае все, кто был подписан на события от старой модели
        //  не смогут переподписаться на новую модель.
        cached.data = model.data;
    }
};

//  Проверяем, есть ли модель в кэше и валидна ли она.
no.Model.isValid = function(id, key) {
    var model = no.Model.get(id, key);
    if (!model) { return; } // undefined означает, что кэша нет вообще, а false -- что он инвалидный.

    return model.isValid();
};

//  ---------------------------------------------------------------------------------------------------------------  //

//  Возвращает, можно ли перезапрашивать эту модель, если предыдущий запрос не удался.
no.Model.prototype.canRetry = function(error) {
    //  do-модели нельзя перезапрашивать.
    return ( !this.isDo() && this.retries < 3 );
};

//  ---------------------------------------------------------------------------------------------------------------  //

no.Model.prototype.extractData = function(result) {
    if (result) {
        return result.result;
    }
};

no.Model.prototype.extractError = function(result) {
    if (result) {
        return result.error;
    }
};

//  ---------------------------------------------------------------------------------------------------------------  //

no.Model.prototype.isDo = function() {
    return this.info.isDo;
};

//  ---------------------------------------------------------------------------------------------------------------  //

})();

<commit_msg>Не бросаем эксепшн при попытки повторно создать модель<commit_after>(function() {

//  ---------------------------------------------------------------------------------------------------------------  //
//  no.Model
//  ---------------------------------------------------------------------------------------------------------------  //

//  Базовый класс для моделей. Конструктор пустой, чтобы легче было наследоваться.
//  Вся инициализация делается в _init(), который вызывает фабрикой no.Model.create().
//
no.Model = function() {};

//  ---------------------------------------------------------------------------------------------------------------  //

//  Добавляем методы из no.Events: on(), off(), trigger().
no.extend(no.Model.prototype, no.Events);

//  ---------------------------------------------------------------------------------------------------------------  //

var _ctors = {};
var _infos = {};

var _cache = {};

var _keySuffix = 0;

//  ---------------------------------------------------------------------------------------------------------------  //

no.Model.prototype._init = function(id, params, data) {
    this.id = id;
    this.params = params;

    this._reset();
    this.setData(data);

    var info = this.info = _infos[id];

    this.key = no.Model.key(id, params, info);

    this.timstamp = 0;
};

no.Model.prototype._reset = function(status) {
    this.data = null;
    this.error = null;
    /*
        Возможные варианты status:

            'none'          данные еще не загружались
            'loading'       данные загружаются в данный момент
            'failed'        данные загрузились с ошибкой, нужен retry
            'error'         данные загрузились с ошибкой, retry невозможен
            'ok'            данные загрузились успешно
            'invalid'       модель вручную инвалидирована.
    */
    this.status = status || 'none';
    this.retries = 0;
    this.requests = 0;
};

//  ---------------------------------------------------------------------------------------------------------------  //

//  Определяем новую модель.
//
//      //  Простая модель, без параметров.
//      no.Model.define('profile');
//
//      no.Model.define('album', {
//          params: {
//              //  Любое значение, кроме null расценивается как дефолтное значение этого параметра.
//              //  На самом деле, конечно, не любое -- смысл имеют только Number и String.
//              'author-login': null,
//              'album-id': null,
//
//              //  Этим двум параметрам заданы дефолтные значения.
//              'page': 0,
//              'pageSize': 20
//          }
//      });
//
no.Model.define = function(id, info, ctor) {
    info = info || {};
    if (info.methods) {
        //  Нужно унаследоваться от no.Model и добавить в прототип info.models.
        ctor = no.inherits(function() {}, no.Model, info.methods);
    } else {
        ctor = ctor || no.Model;
    }

    var params = info.params || (( info.params = {} ));

    info.pNames = no.object.keys(params);

    //  Для do-моделей отдельные правила кэширования и построения ключей.
    info.isDo = /^do-/.test(id);

    _infos[id] = info;
    _ctors[id] = ctor;

    //  Создаем пустой кэш для всех моделей с данным id.
    _cache[id] = {};
};

//  Фабрика для моделей. Создает инстанс нужного класса и инициализирует его.
no.Model.create = function(id, params, data)  {
    var model = no.Model.get(id, params);

    if (!model) {
        var ctor = _ctors[id];
        model = new ctor();
        model._init(id, params, data);

        no.Model.store(model);
    } else if (data) {
        //  Модель уже существует, а мы пытаемся создать такую же, но с непустой data.
        //  FIXME: Все же непонятно, что нужно делать.
        //  Может быть, нужно передавать { silent: true }?
        model.setData(data);
        /// throw Error('Model already exists');
    }

    return model;
};

//  ---------------------------------------------------------------------------------------------------------------  //

no.Model.info = function(id) {
    return _infos[id];
};

//  ---------------------------------------------------------------------------------------------------------------  //

no.Model.key = function(id, params, info) {
    info || ( info = _infos[id] );

    //  Для do-моделей ключ строим особым образом.
    if (info.isDo) {
        return 'do-' + _keySuffix++;
    }

    var defaults = info.params;
    var pNames = info.pNames;

    var key = 'model=' + id;

    for (var i = 0, l = pNames.length; i < l; i++) {
        var pName = pNames[i];

        var pValue = params[pName];
        //  Нельзя просто написать params[pName] || defaults[pName] --
        //  т.к. params[pName] может быть 0 или ''.
        pValue = (pValue === undefined) ? defaults[pName] : pValue;

        if (pValue != null) {
            key += '&' + pName + '=' + pValue;
        }
    }

    return key;
};

//  ---------------------------------------------------------------------------------------------------------------  //

//  Инвалидируем все модели с заданным id,
//  удовлетворяющие фильтру filter (функция, принимающая
//  параметром модель и возвращающая boolean).
no.Model.invalidate = function(id, filter) {
    var models = _cache[id];

    for (var key in models) {
        var model = models[key];
        if ( filter(model) ) {
            model.invalidate();
        }
    }
};

no.Model.prototype.invalidate = function() {
    this._reset('invalid');
};

no.Model.prototype.isValid = function() {
    return (this.status === 'ok');
};

//  ---------------------------------------------------------------------------------------------------------------  //

//  Возвращает данные, находящиеся по пути path.
//
//      var foo = model.get('foo'); // model.data.foo.
//      var bar = model.get('foo.bar'); // model.data.foo.bar (если foo существует).
//
no.Model.prototype.get = function(path) {
    var data = this.data;
    if (data) {
        return no.path(path, data);
    }
};

//  Сохраняет value по пути path.
//
//  Возможные флаги, которые могут быть в options:
//
//      {
//          silent: true        //  Не генерить событие о том, что модель изменилась,
//      }
//
no.Model.prototype.set = function(path, value, options) {
    var data = this.data;
    if (!data) { return; }

    //  Сохраняем новое значение и одновременно получаем старое значение.
    var oldValue = no.path(path, data, value);

    if ( !( (options && options.silent) || no.object.isEqual(value, oldValue) ) ) {
        //  FIXME: Может быть отправлять старое/новое значение?
        this.trigger('changed.' + path);
    }
};

//  ---------------------------------------------------------------------------------------------------------------  //

no.Model.prototype.getData = function() {
    return this.data;
};

//  Заменяет данные модели на data.
//
//  При этом по-дефолту на модели генерится событие 'changed'.
//  Это поведение можно поменять, передав объект options:
//
//      {
//          silent: true        //  Не генерить событие о том, что модель изменилась,
//      }
//
no.Model.prototype.setData = function(data, options) {
    if (data) {
        var old = this.data;
        this.data = this.preprocessData(data);
        this.error = null;
        this.status = 'ok';

        //  Не проверяем здесь, действительно ли data отличается от oldData --
        //  setData должен вызываться только когда обновленная модель целиком перезапрошена.
        //  Можно считать, что она в этом случае всегда меняется.
        if (old != null && !(options && options.silent) ) {
            this.trigger('changed');
        }
    }

};

no.Model.prototype.getError = function() {
    return this.error;
};

no.Model.prototype.setError = function(error) {
    this.data = null;
    this.error = error;
    this.status = 'failed';
};

no.Model.prototype.preprocessData = function(data) {
    return data;
};

//  ---------------------------------------------------------------------------------------------------------------  //

//  FIXME: Этот код сильно пересекается с вычислением ключа.
//  Нельзя ли избавиться от копипаста?
no.Model.prototype.getRequestParams = function() {
    var params = this.params;

    var defaults = this.info.params;
    var reqParams = {};

    for (var pName in defaults) {
        var pValue = params[pName];

        pValue = (pValue === undefined) ? defaults[pName] : pValue;
        if (pValue != null) {
            reqParams[pName] = pValue;
        }
    }

    return reqParams;
};

//  ---------------------------------------------------------------------------------------------------------------  //

//  Работа с кэшем.

//  Достаем модель из кэша.
no.Model.get = function(id, key) {
    key = (typeof key === 'string') ? key : no.Model.key(id, key);

    var model = _cache[id][key];
    return model;
};

//  Сохраняем модель в кэше.
no.Model.store = function(model) {
    if ( model.isDo() ) {
        return;
    }

    var id = model.id;
    var key = model.key;

    var cached = _cache[id][key];
    if (!cached) {
        _cache[id][key] = model;
    } else {
        //  NOTE: Почему тут нельзя просто заменить старую модель на новую.
        //  Потому, что в этом случае все, кто был подписан на события от старой модели
        //  не смогут переподписаться на новую модель.
        cached.data = model.data;
    }
};

//  Проверяем, есть ли модель в кэше и валидна ли она.
no.Model.isValid = function(id, key) {
    var model = no.Model.get(id, key);
    if (!model) { return; } // undefined означает, что кэша нет вообще, а false -- что он инвалидный.

    return model.isValid();
};

//  ---------------------------------------------------------------------------------------------------------------  //

//  Возвращает, можно ли перезапрашивать эту модель, если предыдущий запрос не удался.
no.Model.prototype.canRetry = function(error) {
    //  do-модели нельзя перезапрашивать.
    return ( !this.isDo() && this.retries < 3 );
};

//  ---------------------------------------------------------------------------------------------------------------  //

no.Model.prototype.extractData = function(result) {
    if (result) {
        return result.result;
    }
};

no.Model.prototype.extractError = function(result) {
    if (result) {
        return result.error;
    }
};

//  ---------------------------------------------------------------------------------------------------------------  //

no.Model.prototype.isDo = function() {
    return this.info.isDo;
};

//  ---------------------------------------------------------------------------------------------------------------  //

})();

<|endoftext|>


<commit_before>///////////////////   Parameters   /////////////////

var paperMinRadius = 5,
    paperMaxRadius = 15,
    paperInnerWhiteCircleRatio =.4,
    paperOutlineWidth = 4,	// UNUSED - this divided by 2 must be > min radius
    paperMarginBottom = 5,
    titleBaselineOffset = 6,  // depends on font size
    titleXOffset = 5,
    paperXOffsetWhenSelected = - (2*paperMaxRadius - titleXOffset);

// Defines the dimension of each region, index by the current view (core, toread, fringe)
// The apparent width is the horizontal space that we want the region to occupy on the screen
// An appropriate offset for the x-position of the center will be computed as -radius+apparentWidth
var coreRadius = [120,120,120],
    toreadRadius = [2000,2000,2000],
    fringeRadius = [2000,2000,2000],
    coreApparentWidth = [120,120,120],
    fringeApparentWidth = [420,420,420],
    toreadApparentWidth = [420,420,fringeApparentWidth[2]-paperMaxRadius+titleXOffset];

var colors={
	"blue":"#00A1CB",
	"green":"#61AE24",
	"pink":"#D70060",
	"orange":"#F18D05",
	"darkblue":"#113F8C",
	"turquoise":"#01A4A4",	    // This color and all the following are not to be used for the nodes
	"red":"#E54028",
	"darkgray":"#616161",
    "toread":"rgb(242, 210, 166)",
    "core":"rgb(223, 111, 95)"
}

var currentYear=2010;

////////////////	Global variables    //////////////

var view=2;	// 0=core, 1=to read, 2=fringe

////////////////	Main rendering      //////////////

// I'm not sure what was the point of .select("body").append("svg") instead of select("svg")...
var svg = d3.select("body").append("svg")
            .attr("width",window.innerWidth)
            .attr("height",window.innerHeight);

// Build the components of the vis, in the appropriate z-index order
d3.tsv("data/SmallDataset.tsv", function(data){
    // toread
    svg.append("circle")
        .attr("id","toread")
        //.attr("class","shadowOnHover")    // for some reason the circle changes size when adding the shadow...

    // core
    svg.append("circle")
        .attr("id","core")
        .attr("class","shadowOnHover")

    // fringe
    var papers = svg.selectAll(".paper")
        .data(data)
    .enter()
    .append("g")
        .attr("class","paper")
        .attr("selected",0)

    papers.append("circle")
        .attr("class", "node")
        .style("fill",randomColor)  // eventually this style attr should be defined in drawVis

    papers.append("circle")
        .attr("class", "innerNode")

    papers.append("text")
        .attr("class", "title")
        .text(function(d,i) {return d.title;} )

    // Initialize interaction & visual appearance
    bindListeners();
    drawVis();
});

// Specify interaction
function bindListeners(){

    d3.selectAll(".shadowOnHover")
    .on("mouseover",function() {
        d3.select(this).attr("filter","url(#drop-shadow)")
    })
    .on("mouseleave",function() {
        d3.select(this).attr("filter","none")
    })

    // highlight papers
    d3.selectAll(".paper")
    .on("mouseover",function() {
        d3.select(this).select(".node").attr("filter","url(#drop-shadow)")
        d3.select(this).select(".title").attr("font-weight","bold").style("fill","#444").style("letter-spacing","normal")
    })
    .on("mouseleave",function() {
        d3.select(this).select(".node").attr("filter","none")
        d3.select(this)
            // to keep the selected elements bold
            .filter(function(){ return d3.select(this).attr("selected")==0;})
            .select(".title").attr("font-weight","normal").style("fill","#222").style("letter-spacing",".54px")
    })

    // clicking papers on the fringe translates them to the left
    .on("click",function() {
        var paper=d3.select(this)
        console.log(paper.attr("selected"))
        if(paper.attr("selected")==0){
            paper.attr("transform", "translate(" + paperXOffsetWhenSelected + ", 0)")
            paper.attr("selected",1)
        }
        else{
            paper.attr("transform","matrix(1 0 0 1 0 0)")
            paper.attr("selected",0)
        }
    })
}

function drawVis(){
    // fringe
    d3.selectAll(".node")
        .attr("cx", function(d,i) { return fringePaperX(i);} )
        .attr("cy", function(d,i) { return fringePaperY(i);} )
        .attr("r", function(d,i) {return radius(d.year);} )

    d3.selectAll(".innerNode")
        .attr("cx", function(d,i) { return fringePaperX(i);} )
        .attr("cy", function(d,i) { return fringePaperY(i);} )
        .attr("r", function(d,i) {return radius(d.year)*paperInnerWhiteCircleRatio;} )
        .style("fill","white")

    d3.selectAll(".title")
        .attr("x", function(d,i) { return fringePaperX(i)+paperMaxRadius+titleXOffset;} )
        .attr("y", function(d,i) {return fringePaperY(i)+titleBaselineOffset;} )

    // toread
    d3.selectAll("#toread")
        .attr("cx",-toreadRadius[view]+toreadApparentWidth[view])
        .attr("cy","50%")
        .attr("r",toreadRadius[view])
        .style("fill",colors.toread)

    // core
    d3.selectAll("#core")
        .attr("cx",-coreRadius[view]+coreApparentWidth[view])
        .attr("cy","50%")
        .attr("r",coreRadius[view])
        .style("fill",colors.core)

    // sidebar
/*    svg.append("rect")
        .attr("x","")
        .attr("y","0")
        .attr("width","100")
        .attr("height","100%")
        .attr("fill",colors.darkgray);*/
}

// Dynamic resize
window.onresize = function(){
    svg.attr("width", window.innerWidth)
       .attr("height", window.innerHeight);
    drawVis();
}

////////////////	Helper functions    //////////////

// Compute X coordinate for the i-th paper on the fringe, based on a circle
function fringePaperX(i){
	var h=window.innerHeight;
    var xoffset=-fringeRadius[view]+fringeApparentWidth[view];
	return xoffset+Math.sqrt(Math.pow(fringeRadius[view],2)-Math.pow(h/2-fringePaperY(i),2))+paperMaxRadius;
}

// Compute Y coordinate for the i-th paper on the fringe
function fringePaperY(i){
	return paperMaxRadius+i*(2*paperMaxRadius+paperMarginBottom);
}

// Compute a node radius from the value supplied, between min and max
// If we want to display an outline instead of a fill circle, the radius must be smaller
function radius(value){
	return Math.max(paperMinRadius, Math.min(paperMaxRadius,
		currentYear-value));
}

// Return a random color except red or turquoise
function randomColor(){
	var keys=Object.keys(colors);
	return colors[keys[ (keys.length-5) * Math.random() << 0]];
}<commit_msg>eyecandy for the toread list<commit_after>///////////////////   Parameters   /////////////////

var paperMinRadius = 5,
    paperMaxRadius = 15,
    paperInnerWhiteCircleRatio =.4,
    paperOutlineWidth = 4,	// UNUSED - this divided by 2 must be > min radius
    paperMarginBottom = 5,
    titleBaselineOffset = 6,  // depends on font size
    titleXOffset = 5,
    paperXOffsetWhenSelected = - (2*paperMaxRadius - titleXOffset);

// Defines the dimension of each region, index by the current view (core, toread, fringe)
// The apparent width is the horizontal space that we want the region to occupy on the screen
// An appropriate offset for the x-position of the center will be computed as -radius+apparentWidth
var coreRadius = [120,120,120],
    toreadRadius = [2000,2000,2000],
    fringeRadius = [2000,2000,2000],
    coreApparentWidth = [120,120,120],
    fringeApparentWidth = [420,420,420],
    toreadApparentWidth = [420,420,fringeApparentWidth[2]-paperMaxRadius+titleXOffset];

var colors={
	"blue":"#00A1CB",
	"green":"#61AE24",
	"pink":"#D70060",
	"orange":"#F18D05",
	"darkblue":"#113F8C",
	"turquoise":"#01A4A4",	    // This color and all the following are not to be used for the nodes
	"red":"#E54028",
	"darkgray":"#616161",
    "toread":"rgb(242, 222, 195)",
    "toreadBorder":"rgb(242, 210, 166)",
    "core":"rgb(223, 111, 95)"
}

var currentYear=2010;

////////////////	Global variables    //////////////

var view=2;	// 0=core, 1=to read, 2=fringe

////////////////	Main rendering      //////////////

// I'm not sure what was the point of .select("body").append("svg") instead of select("svg")...
var svg = d3.select("body").append("svg")
            .attr("width",window.innerWidth)
            .attr("height",window.innerHeight);

// Build the components of the vis, in the appropriate z-index order
d3.tsv("data/SmallDataset.tsv", function(data){
    // toread
    svg.append("circle")
        .attr("id","toread")
        //.attr("class","shadowOnHover")    // for some reason the circle changes size when adding the shadow...

    // core
    svg.append("circle")
        .attr("id","core")
        .attr("class","shadowOnHover")

    // fringe
    var papers = svg.selectAll(".paper")
        .data(data)
    .enter()
    .append("g")
        .attr("class","paper")
        .attr("selected",0)

    papers.append("circle")
        .attr("class", "node")
        .style("fill",randomColor)  // eventually this style attr should be defined in drawVis

    papers.append("circle")
        .attr("class", "innerNode")

    papers.append("text")
        .attr("class", "title")
        .text(function(d,i) {return d.title;} )

    // Initialize interaction & visual appearance
    bindListeners();
    drawVis();
});

// Specify interaction
function bindListeners(){

    d3.selectAll(".shadowOnHover")
    .on("mouseover",function() {
        d3.select(this).attr("filter","url(#drop-shadow)")
    })
    .on("mouseleave",function() {
        d3.select(this).attr("filter","none")
    })

    // highlight papers
    d3.selectAll(".paper")
    .on("mouseover",function() {
        d3.select(this).select(".node").attr("filter","url(#drop-shadow)")
        d3.select(this).select(".title").attr("font-weight","bold").style("fill","#444").style("letter-spacing","normal")
    })
    .on("mouseleave",function() {
        d3.select(this).select(".node").attr("filter","none")
        d3.select(this)
            // to keep the selected elements bold
            .filter(function(){ return d3.select(this).attr("selected")==0;})
            .select(".title").attr("font-weight","normal").style("fill","#222").style("letter-spacing",".54px")
    })

    // clicking papers on the fringe translates them to the left
    .on("click",function() {
        var paper=d3.select(this)
        console.log(paper.attr("selected"))
        if(paper.attr("selected")==0){
            paper.attr("transform", "translate(" + paperXOffsetWhenSelected + ", 0)")
            paper.attr("selected",1)
        }
        else{
            paper.attr("transform","matrix(1 0 0 1 0 0)")
            paper.attr("selected",0)
        }
    })
}

function drawVis(){
    // fringe
    d3.selectAll(".node")
        .attr("cx", function(d,i) { return fringePaperX(i);} )
        .attr("cy", function(d,i) { return fringePaperY(i);} )
        .attr("r", function(d,i) {return radius(d.year);} )

    d3.selectAll(".innerNode")
        .attr("cx", function(d,i) { return fringePaperX(i);} )
        .attr("cy", function(d,i) { return fringePaperY(i);} )
        .attr("r", function(d,i) {return radius(d.year)*paperInnerWhiteCircleRatio;} )
        .style("fill","white")

    d3.selectAll(".title")
        .attr("x", function(d,i) { return fringePaperX(i)+paperMaxRadius+titleXOffset;} )
        .attr("y", function(d,i) {return fringePaperY(i)+titleBaselineOffset;} )

    // toread
    d3.selectAll("#toread")
        .attr("cx",-toreadRadius[view]+toreadApparentWidth[view])
        .attr("cy","50%")
        .attr("r",toreadRadius[view])
        .style("fill",colors.toread)
        .style("stroke",colors.toreadBorder)
        .style("stroke-width",2)

    // core
    d3.selectAll("#core")
        .attr("cx",-coreRadius[view]+coreApparentWidth[view])
        .attr("cy","50%")
        .attr("r",coreRadius[view])
        .style("fill",colors.core)

    // sidebar
/*    svg.append("rect")
        .attr("x","")
        .attr("y","0")
        .attr("width","100")
        .attr("height","100%")
        .attr("fill",colors.darkgray);*/
}

// Dynamic resize
window.onresize = function(){
    svg.attr("width", window.innerWidth)
       .attr("height", window.innerHeight);
    drawVis();
}

////////////////	Helper functions    //////////////

// Compute X coordinate for the i-th paper on the fringe, based on a circle
function fringePaperX(i){
	var h=window.innerHeight;
    var xoffset=-fringeRadius[view]+fringeApparentWidth[view];
	return xoffset+Math.sqrt(Math.pow(fringeRadius[view],2)-Math.pow(h/2-fringePaperY(i),2))+paperMaxRadius;
}

// Compute Y coordinate for the i-th paper on the fringe
function fringePaperY(i){
	return paperMaxRadius+i*(2*paperMaxRadius+paperMarginBottom);
}

// Compute a node radius from the value supplied, between min and max
// If we want to display an outline instead of a fill circle, the radius must be smaller
function radius(value){
	return Math.max(paperMinRadius, Math.min(paperMaxRadius,
		currentYear-value));
}

// Return a random color except red or turquoise
function randomColor(){
	var keys=Object.keys(colors);
	return colors[keys[ (keys.length-5) * Math.random() << 0]];
}<|endoftext|>


<commit_before>define(function () {

    /**
     * Get sign of the value.
     */
    function sign(val) {
    	if (val === 0) return 0;

        return val < 0? -1 : 1;
    }

    return sign;

});
<commit_msg>fix indent<commit_after>define(function () {

    /**
     * Get sign of the value.
     */
    function sign(val) {
        if (val === 0) return 0;

        return val < 0? -1 : 1;
    }

    return sign;

});
<|endoftext|>


<commit_before>function keys (obj) {
  var result = []
  var key

  for (key in obj) {
    if (obj.hasOwnProperty(key)) {
      result.push(key)
    }
  }
  return result
}

module.exports = keys
<commit_msg>update object/keys use Object.prototype.hasOwnProperty. this is more safe despite the minor  speed hit with fn.call<commit_after>function keys (obj) {
  var hasOwn = Object.prototype.hasOwnProperty
  var result = []
  var key

  for (key in obj) {
    if (hasOwn.call(obj, key)) {
      result.push(key)
    }
  }
  return result
}

module.exports = keys
<|endoftext|>


<commit_before>export const githubFileUrlRoot =
  'https://github.com/blockstack/blockstack/blob/master'

export const socialLinks = {
  twitter: 'https://www.twitter.com/blockstack',
  telegram: 'https://t.me/BlockstackChat',
  youtube: 'https://www.youtube.com/channel/UC3J2iHnyt2JtOvtGVf_jpHQ',
  slack: 'http://chat.blockstack.org',
  meetup: 'http://www.meetup.com/topics/blockstack/',
  reddit: 'https://www.reddit.com/r/blockstack',
  forum: 'https://forum.blockstack.org',
  blog: 'http://blog.blockstack.org',
  github: 'https://github.com/blockstack',
  branding: 'https://projects.invisionapp.com/boards/HE2VVROFSGB27/',
}

export const installationLinks = {
  portalMacOS:
    'https://github.com/blockstack/blockstack-browser/releases/download/v0.9.0/Blockstack-v0.9.app.zip',
  portalDevelopers: 'https://github.com/blockstack/blockstack-browser/releases',
  portalDevelopersMacOS:
    'https://github.com/blockstack/blockstack-browser/releases/download/v0.26.2/Blockstack-for-macOS-v0.26.2.dmg',
  portalDevelopersWindows:
    'https://github.com/blockstack/blockstack-browser/releases/download/v0.26.2/Blockstack-for-win10-v0.26.2.msi',
  portalDevelopersLinux:
    'https://github.com/blockstack/blockstack-browser/releases/download/v0.26.2/Blockstack-for-Linux-v0.26.2.sh',
  portalDevelopersWeb: 'https://browser.blockstack.org',
  cliDevelopers: 'https://github.com/blockstack/blockstack-core',
}

export const jobs = [
  {
    title: 'Frontend Engineer',
    url:
      'https://jobs.lever.co/blockstack/431188cd-63a3-4314-8d30-55a4d91722af?lever-origin=applied&lever-source%5B%5D=Blockstack.org',
  },
  {
    title: 'Backend Engineer',
    url:
      'https://jobs.lever.co/blockstack/cf85b3ac-0e7c-4070-a8a4-af687a3fbac9?lever-origin=applied&lever-source%5B%5D=blockstack.org',
  },
  {
    title: 'Technical Product Manager',
    url:
      'https://jobs.lever.co/blockstack/f6a98e76-b1f6-4284-9c39-1bda11e7160a?lever-origin=applied&lever-source%5B%5D=Blockstack.com',
  },
]

export const featuredApps = [
  {
    name: 'Coins',
    icon: '/images/logos/app-icon-coins-512x512.png',
    description: `Coins is a decentralized and encrypted cryptocurrency portfolio app. Analyze your performance with flexible, customizable reporting. Track your holdings, watch your favorite tokens and optionally send pricing alerts.`,
  },
  {
    name: 'Graphite',
    icon: '/images/logos/app-icon-graphite-512x512.png',
    description: `Graphite gives you ownership over your data and files. Write, create, connect—all without giving up your privacy.`,
  },
  {
    name: 'Casa',
    icon: '/images/logos/app-icon-casa-512x512.png',
    description: `Casa is the world's first open source homesharing protocol and decentralized network. Book rooms without platform fees or trusted intermediaries and securely transact with encrypted chat and multi-party escrow.`,
  },
  {
    name: 'Afia',
    icon: '/images/logos/app-icon-afia-512x512.png',
    description:
      'Afia gives individuals the power to own and manage their personal health records. Keep your health data safe on your personal encrypted cloud storage and securely share your data with healthcare providers as you see fit.',
  },
  {
    name: 'DotPodcast',
    icon: '/images/logos/app-icon-dotpodcast-512x512.png',
    description:
      'DotPodcast helps creators get paid, protects against censorship, and allows listeners to enjoy podcasts without privacy-invading tracking.',
  },
]

export const teamMembers = [
  {
    blockstackId: 'muneeb',
    name: 'Muneeb Ali',
    avatar: 'https://s3.amazonaws.com/kd4/muneeb',
    bio:
      'Muneeb Ali is a distributed systems PhD from Princeton and gives guest lectures on cloud computing there. He went through Y Combinator and was awarded a J. William Fulbright Fellowship.',
  },
  {
    blockstackId: 'ryan',
    name: 'Ryan Shea',
    avatar: 'https://s3.amazonaws.com/kd4/ryan',
    bio:
      'Ryan Shea studied engineering at Princeton, went through Y Combinator, and was inducted into the Forbes 30 Under 30. He has authored several popular open source libraries in cryptography and blockchains.',
  },
  {
    blockstackId: 'judecn',
    name: 'Jude Nelson',
    avatar: 'https://s3.amazonaws.com/kd4/judecn',
    bio:
      'Jude Nelson did PhD-level research in distributed systems at Princeton and worked as a core member of PlanetLab, which received the ACM Test of Time Award for enabling planetary scale experimentation and deployment.',
  },
  {
    blockstackId: 'blankstein',
    name: 'Aaron Blankstein',
    avatar: '/images/avatars/aaron-blankstein.jpg',
    bio:
      'Aaron joined the Blockstack engineering team from an academic background, finishing his PhD in 2017. His doctoral research spanned a range of topics, mostly focusing on web application performance and security. He’s worked in information flow tracking systems, caching algorithms, compilers, and applied cryptography. 10+ years of Emacs usage.',
  },
  {
    blockstackId: 'larry',
    name: 'Larry Salibra',
    avatar: 'https://s3.amazonaws.com/kd4/larry',
    bio:
      'Larry Salibra co-founded Pay4Bugs, a crowdsourced security analysis and software testing platform, and is a founding member of the Bitcoin Association of Hong Kong. His work exposed private data leakage in Chinese Tinder clone Tantan, and how Apple censors apps in China.',
  },
  {
    blockstackId: 'ginaabrams',
    name: 'Gina Abrams',
    avatar: '/images/avatars/gina-abrams.jpg',
    bio:
      'Gina Abrams studied Psychology and Social Sciences at Binghamton University. Previously she spent two years in agency technical recruiting, during which time she assisted numerous NYC start-ups in mission critical DevOps, SRE and Security hires.',
  },
  {
    blockstackId: 'pstanley',
    name: 'Patrick Stanley',
    avatar: '/images/avatars/patrick-stanley.jpg',
    bio:
      'Patrick Stanley studied Economics and Psychology at Johns Hopkins, and was the first employee at data-driven lending startup Earnest which sold to Navient for $155m in 2017. In a growth role there, he helped it scale from from 1 to 200 employees and go from $0 to $2B in originations within 3 years.',
  },
  {
    blockstackId: 'jack_zampolin',
    name: 'Jack Zampolin',
    avatar: '/images/avatars/jack-zampolin.jpg',
    bio:
      'Jack came to Blockstack from InfluxData where he engaged with and grew the developer community as a Developer Evangelist. A self taught programmer, he is an active contributor to Open Source projects including Blockstack, InfluxDB, and Helm.',
  },
  {
    blockstackId: 'yukan',
    name: 'Ken Liao',
    avatar: '/images/avatars/ken-liao.jpg',
    bio:
      'Ken Liao studied Computer Engineering at the University of Waterloo and co-founded the fashion brand marketplace, PR-A-PO. He designed and built mobile apps which were featured as Best New App on the Apple App Store.',
  },
  {
    blockstackId: 'sebastiandunkel',
    name: 'Sebastian Dunkel',
    avatar: '/images/avatars/sebastian-dunkel.jpg',
    bio:
      'Sebastian received his MA in Linguistics and Communications from the University of Heidelberg, Germany, and the University of Brighton, UK. Before joining the Blockstack team, he worked in localization and product support for Apple, Vimeo, and Master & Dynamic.',
  },
  {
    blockstackId: '',
    name: 'Shannon Voight',
    avatar: '/images/avatars/shannon-voight.jpg',
    bio:
      "Shannon drives event and marketing programs focusing on Blockstack's growth and expansion. Prior to joining Blockstack in 2017, Shannon spent over 11 years honing her skills as event and program producer, talent manager and brand strategist at Condé Nast and Time Inc. ",
  },
  {
    blockstackId: 'xan',
    name: 'Xan Ditkoff',
    avatar: '/images/avatars/xan-ditkoff.jpg',
    bio:
      'Xan came to Blockstack with backgrounds in private equity, investment banking, and the military. He is passionate about driving the creation, growth, and expansion of application ecosystems through his growth role and with the Signature Fund.',
  },
  {
    blockstackId: 'clintnelson',
    name: 'Clint Nelsen',
    avatar: '/images/avatars/clint-nelsen.jpg',
    bio:
      'Clint is part of the growth team at Blockstack and previously was the founder of Startup Weekend.  Clint grew Startup Weekend to a team of 80 employees and community of 8,000 local organizers producing 3,000+ hackathons spanning 600 cities and 147 countries.  Clint is a published author and regularly serves as a lecturer on entrepreneurship & startups.',
  },
  {
    blockstackId: 'hologram',
    name: 'Chase Wackerfuss',
    avatar: '/images/avatars/chase-wackerfuss.jpg',
    bio:
      "Chase joined Blockstack's engineering team after being an active contributor to the community. A self taught programmer and UI designer, his focus is on cultivating a user-friendly front end developer experience and helping scale client-side applications.",
  },
  {
    blockstackId: 'ariella',
    name: 'Ariella Steinhorn',
    avatar: '/images/avatars/ariella-steinhorn.jpg',
    bio:
     "Ariella is Blockstack’s Communications Partner. She previously led communications and public policy efforts at Managed by Q. Before that, she held several communications positions at Uber, and was a speechwriter in Washington, DC."
  },
  {
    blockstackId: 'jesse',
    name: 'Jesse Soslow',
    avatar: '/images/avatars/jesse-soslow.jpg',
    bio:
     "Jesse is Blockstack’s Operations Partner.  Prior to Blockstack, he led operations at Everwise, a Sequoia-backed SaaS startup, and worked as a technology transactions attorney for a large, international law firm.  Jesse received his J.D. and B.A., in math, both from the University of Pennsylvania."
  },
  {
    blockstackId: 'mfreed',
    name: 'Michael Freedman, Technical Advisor',
    avatar: '/images/avatars/mike-freedman.jpg',
    bio:
      'Michael Freedman is a distributed systems Professor at Princeton. He was awarded the Presidential Early Career Award (PECASE), the Sloan Fellowship, and his research has led to commercial products and deployed systems reaching millions of users daily.',
  },
  {
    blockstackId: 'jpsingh',
    name: 'JP Singh, Technical Advisor',
    avatar: '/images/avatars/jp-singh.jpg',
    bio:
      'JP Singh received his PhD from from Stanford University and is a leading authority on scalable infrastructure and applications. He is the director of the Princeton CTO Program, serves on the board of 8x8, Inc., and has been a consultant to Intel, Microsoft, and the U.S. Government.',
  },
]

export const blogAuthors = {
  'larry.id': {
    blockstackId: 'larry',
    name: 'Larry Salibra',
    avatar: 'https://s3.amazonaws.com/kd4/larry',
    twitter: 'larrysalibra',
    github: 'larrysalibra',
  },
  'judecn.id': {
    blockstackId: 'judecn',
    name: 'Jude Nelson',
    avatar: 'https://s3.amazonaws.com/kd4/judecn',
    twitter: 'judecnelson',
    github: 'jcnelson',
  },
  'guylepage3.id': {
    blockstackId: 'guylepage3',
    name: 'Guy Lepage',
    avatar: 'https://s3.amazonaws.com/kd4/guylepage3',
    twitter: 'guylepage3',
    github: 'guylepage3',
  },
  'muneeb.id': {
    blockstackId: 'muneeb',
    name: 'Muneeb Ali',
    avatar: 'https://s3.amazonaws.com/kd4/muneeb',
    twitter: 'muneeb',
    github: 'muneeb-ali',
  },
  'ryan.id': {
    blockstackId: 'ryan',
    name: 'Ryan Shea',
    avatar: 'https://s3.amazonaws.com/kd4/ryan',
    twitter: 'ryaneshea',
    github: 'shea256',
  },
  'blockstack.id': {
    blockstackId: 'blockstack',
    name: 'Muneeb & Ryan',
    avatar: 'https://s3.amazonaws.com/kd4/muneeb-and-ryan.jpg',
    twitter: 'blockstack',
    github: 'blockstack',
  },
  'founders.id': {
    blockstackId: 'blockstack',
    name: 'Ryan & Muneeb',
    avatar: 'https://s3.amazonaws.com/kd4/muneeb-and-ryan.jpg',
    twitter: 'blockstack',
    github: 'blockstack',
  },
  'mfreed.id': {
    blockstackId: 'mfreed',
    name: 'Mike Freedman',
    avatar: '/images/avatars/mike-freedman.jpg',
    twitter: 'michaelfreedman',
    github: 'mfreed',
  },
  'stanley1.id': {
    blockstackId: 'stanley1',
    name: 'Patrick Stanley',
    avatar: 'https://s3.amazonaws.com/kd4/stanley1',
    twitter: 'patrickwstanley',
    github: 'pstan26',
  },
  'yukan.id': {
    blockstackId: 'yukan',
    name: 'Ken Liao',
    avatar: 'https://blockstack.org/images/avatars/ken-liao.jpg',
    twitter: 'yukanl',
    github: 'yknl',
  },
  'arsteinhorn': {
    blockstackId: 'ariella',
    name: 'Ariella Steinhorn',
    avatar: 'https://blockstack.org/images/avatars/ariella-steinhorn.jpg',
    twitter: 'arsteinhorn',
    github: 'arsteinhorn',
  },
  'chase': {
    blockstackId: 'hologram',
    name: 'Chase Wackerfuss',
    avatar: 'https://blockstack.org/images/avatars/chase-wackerfuss.jpg',
    twitter: 'vockerfoos',
    github: 'cwackerfuss'
  }
}
<commit_msg>Update Ariella ghost blog ID.<commit_after>export const githubFileUrlRoot =
  'https://github.com/blockstack/blockstack/blob/master'

export const socialLinks = {
  twitter: 'https://www.twitter.com/blockstack',
  telegram: 'https://t.me/BlockstackChat',
  youtube: 'https://www.youtube.com/channel/UC3J2iHnyt2JtOvtGVf_jpHQ',
  slack: 'http://chat.blockstack.org',
  meetup: 'http://www.meetup.com/topics/blockstack/',
  reddit: 'https://www.reddit.com/r/blockstack',
  forum: 'https://forum.blockstack.org',
  blog: 'http://blog.blockstack.org',
  github: 'https://github.com/blockstack',
  branding: 'https://projects.invisionapp.com/boards/HE2VVROFSGB27/',
}

export const installationLinks = {
  portalMacOS:
    'https://github.com/blockstack/blockstack-browser/releases/download/v0.9.0/Blockstack-v0.9.app.zip',
  portalDevelopers: 'https://github.com/blockstack/blockstack-browser/releases',
  portalDevelopersMacOS:
    'https://github.com/blockstack/blockstack-browser/releases/download/v0.26.2/Blockstack-for-macOS-v0.26.2.dmg',
  portalDevelopersWindows:
    'https://github.com/blockstack/blockstack-browser/releases/download/v0.26.2/Blockstack-for-win10-v0.26.2.msi',
  portalDevelopersLinux:
    'https://github.com/blockstack/blockstack-browser/releases/download/v0.26.2/Blockstack-for-Linux-v0.26.2.sh',
  portalDevelopersWeb: 'https://browser.blockstack.org',
  cliDevelopers: 'https://github.com/blockstack/blockstack-core',
}

export const jobs = [
  {
    title: 'Frontend Engineer',
    url:
      'https://jobs.lever.co/blockstack/431188cd-63a3-4314-8d30-55a4d91722af?lever-origin=applied&lever-source%5B%5D=Blockstack.org',
  },
  {
    title: 'Backend Engineer',
    url:
      'https://jobs.lever.co/blockstack/cf85b3ac-0e7c-4070-a8a4-af687a3fbac9?lever-origin=applied&lever-source%5B%5D=blockstack.org',
  },
  {
    title: 'Technical Product Manager',
    url:
      'https://jobs.lever.co/blockstack/f6a98e76-b1f6-4284-9c39-1bda11e7160a?lever-origin=applied&lever-source%5B%5D=Blockstack.com',
  },
]

export const featuredApps = [
  {
    name: 'Coins',
    icon: '/images/logos/app-icon-coins-512x512.png',
    description: `Coins is a decentralized and encrypted cryptocurrency portfolio app. Analyze your performance with flexible, customizable reporting. Track your holdings, watch your favorite tokens and optionally send pricing alerts.`,
  },
  {
    name: 'Graphite',
    icon: '/images/logos/app-icon-graphite-512x512.png',
    description: `Graphite gives you ownership over your data and files. Write, create, connect—all without giving up your privacy.`,
  },
  {
    name: 'Casa',
    icon: '/images/logos/app-icon-casa-512x512.png',
    description: `Casa is the world's first open source homesharing protocol and decentralized network. Book rooms without platform fees or trusted intermediaries and securely transact with encrypted chat and multi-party escrow.`,
  },
  {
    name: 'Afia',
    icon: '/images/logos/app-icon-afia-512x512.png',
    description:
      'Afia gives individuals the power to own and manage their personal health records. Keep your health data safe on your personal encrypted cloud storage and securely share your data with healthcare providers as you see fit.',
  },
  {
    name: 'DotPodcast',
    icon: '/images/logos/app-icon-dotpodcast-512x512.png',
    description:
      'DotPodcast helps creators get paid, protects against censorship, and allows listeners to enjoy podcasts without privacy-invading tracking.',
  },
]

export const teamMembers = [
  {
    blockstackId: 'muneeb',
    name: 'Muneeb Ali',
    avatar: 'https://s3.amazonaws.com/kd4/muneeb',
    bio:
      'Muneeb Ali is a distributed systems PhD from Princeton and gives guest lectures on cloud computing there. He went through Y Combinator and was awarded a J. William Fulbright Fellowship.',
  },
  {
    blockstackId: 'ryan',
    name: 'Ryan Shea',
    avatar: 'https://s3.amazonaws.com/kd4/ryan',
    bio:
      'Ryan Shea studied engineering at Princeton, went through Y Combinator, and was inducted into the Forbes 30 Under 30. He has authored several popular open source libraries in cryptography and blockchains.',
  },
  {
    blockstackId: 'judecn',
    name: 'Jude Nelson',
    avatar: 'https://s3.amazonaws.com/kd4/judecn',
    bio:
      'Jude Nelson did PhD-level research in distributed systems at Princeton and worked as a core member of PlanetLab, which received the ACM Test of Time Award for enabling planetary scale experimentation and deployment.',
  },
  {
    blockstackId: 'blankstein',
    name: 'Aaron Blankstein',
    avatar: '/images/avatars/aaron-blankstein.jpg',
    bio:
      'Aaron joined the Blockstack engineering team from an academic background, finishing his PhD in 2017. His doctoral research spanned a range of topics, mostly focusing on web application performance and security. He’s worked in information flow tracking systems, caching algorithms, compilers, and applied cryptography. 10+ years of Emacs usage.',
  },
  {
    blockstackId: 'larry',
    name: 'Larry Salibra',
    avatar: 'https://s3.amazonaws.com/kd4/larry',
    bio:
      'Larry Salibra co-founded Pay4Bugs, a crowdsourced security analysis and software testing platform, and is a founding member of the Bitcoin Association of Hong Kong. His work exposed private data leakage in Chinese Tinder clone Tantan, and how Apple censors apps in China.',
  },
  {
    blockstackId: 'ginaabrams',
    name: 'Gina Abrams',
    avatar: '/images/avatars/gina-abrams.jpg',
    bio:
      'Gina Abrams studied Psychology and Social Sciences at Binghamton University. Previously she spent two years in agency technical recruiting, during which time she assisted numerous NYC start-ups in mission critical DevOps, SRE and Security hires.',
  },
  {
    blockstackId: 'pstanley',
    name: 'Patrick Stanley',
    avatar: '/images/avatars/patrick-stanley.jpg',
    bio:
      'Patrick Stanley studied Economics and Psychology at Johns Hopkins, and was the first employee at data-driven lending startup Earnest which sold to Navient for $155m in 2017. In a growth role there, he helped it scale from from 1 to 200 employees and go from $0 to $2B in originations within 3 years.',
  },
  {
    blockstackId: 'jack_zampolin',
    name: 'Jack Zampolin',
    avatar: '/images/avatars/jack-zampolin.jpg',
    bio:
      'Jack came to Blockstack from InfluxData where he engaged with and grew the developer community as a Developer Evangelist. A self taught programmer, he is an active contributor to Open Source projects including Blockstack, InfluxDB, and Helm.',
  },
  {
    blockstackId: 'yukan',
    name: 'Ken Liao',
    avatar: '/images/avatars/ken-liao.jpg',
    bio:
      'Ken Liao studied Computer Engineering at the University of Waterloo and co-founded the fashion brand marketplace, PR-A-PO. He designed and built mobile apps which were featured as Best New App on the Apple App Store.',
  },
  {
    blockstackId: 'sebastiandunkel',
    name: 'Sebastian Dunkel',
    avatar: '/images/avatars/sebastian-dunkel.jpg',
    bio:
      'Sebastian received his MA in Linguistics and Communications from the University of Heidelberg, Germany, and the University of Brighton, UK. Before joining the Blockstack team, he worked in localization and product support for Apple, Vimeo, and Master & Dynamic.',
  },
  {
    blockstackId: '',
    name: 'Shannon Voight',
    avatar: '/images/avatars/shannon-voight.jpg',
    bio:
      "Shannon drives event and marketing programs focusing on Blockstack's growth and expansion. Prior to joining Blockstack in 2017, Shannon spent over 11 years honing her skills as event and program producer, talent manager and brand strategist at Condé Nast and Time Inc. ",
  },
  {
    blockstackId: 'xan',
    name: 'Xan Ditkoff',
    avatar: '/images/avatars/xan-ditkoff.jpg',
    bio:
      'Xan came to Blockstack with backgrounds in private equity, investment banking, and the military. He is passionate about driving the creation, growth, and expansion of application ecosystems through his growth role and with the Signature Fund.',
  },
  {
    blockstackId: 'clintnelson',
    name: 'Clint Nelsen',
    avatar: '/images/avatars/clint-nelsen.jpg',
    bio:
      'Clint is part of the growth team at Blockstack and previously was the founder of Startup Weekend.  Clint grew Startup Weekend to a team of 80 employees and community of 8,000 local organizers producing 3,000+ hackathons spanning 600 cities and 147 countries.  Clint is a published author and regularly serves as a lecturer on entrepreneurship & startups.',
  },
  {
    blockstackId: 'hologram',
    name: 'Chase Wackerfuss',
    avatar: '/images/avatars/chase-wackerfuss.jpg',
    bio:
      "Chase joined Blockstack's engineering team after being an active contributor to the community. A self taught programmer and UI designer, his focus is on cultivating a user-friendly front end developer experience and helping scale client-side applications.",
  },
  {
    blockstackId: 'ariella',
    name: 'Ariella Steinhorn',
    avatar: '/images/avatars/ariella-steinhorn.jpg',
    bio:
     "Ariella is Blockstack’s Communications Partner. She previously led communications and public policy efforts at Managed by Q. Before that, she held several communications positions at Uber, and was a speechwriter in Washington, DC."
  },
  {
    blockstackId: 'jesse',
    name: 'Jesse Soslow',
    avatar: '/images/avatars/jesse-soslow.jpg',
    bio:
     "Jesse is Blockstack’s Operations Partner.  Prior to Blockstack, he led operations at Everwise, a Sequoia-backed SaaS startup, and worked as a technology transactions attorney for a large, international law firm.  Jesse received his J.D. and B.A., in math, both from the University of Pennsylvania."
  },
  {
    blockstackId: 'mfreed',
    name: 'Michael Freedman, Technical Advisor',
    avatar: '/images/avatars/mike-freedman.jpg',
    bio:
      'Michael Freedman is a distributed systems Professor at Princeton. He was awarded the Presidential Early Career Award (PECASE), the Sloan Fellowship, and his research has led to commercial products and deployed systems reaching millions of users daily.',
  },
  {
    blockstackId: 'jpsingh',
    name: 'JP Singh, Technical Advisor',
    avatar: '/images/avatars/jp-singh.jpg',
    bio:
      'JP Singh received his PhD from from Stanford University and is a leading authority on scalable infrastructure and applications. He is the director of the Princeton CTO Program, serves on the board of 8x8, Inc., and has been a consultant to Intel, Microsoft, and the U.S. Government.',
  },
]

export const blogAuthors = {
  'larry.id': {
    blockstackId: 'larry',
    name: 'Larry Salibra',
    avatar: 'https://s3.amazonaws.com/kd4/larry',
    twitter: 'larrysalibra',
    github: 'larrysalibra',
  },
  'judecn.id': {
    blockstackId: 'judecn',
    name: 'Jude Nelson',
    avatar: 'https://s3.amazonaws.com/kd4/judecn',
    twitter: 'judecnelson',
    github: 'jcnelson',
  },
  'guylepage3.id': {
    blockstackId: 'guylepage3',
    name: 'Guy Lepage',
    avatar: 'https://s3.amazonaws.com/kd4/guylepage3',
    twitter: 'guylepage3',
    github: 'guylepage3',
  },
  'muneeb.id': {
    blockstackId: 'muneeb',
    name: 'Muneeb Ali',
    avatar: 'https://s3.amazonaws.com/kd4/muneeb',
    twitter: 'muneeb',
    github: 'muneeb-ali',
  },
  'ryan.id': {
    blockstackId: 'ryan',
    name: 'Ryan Shea',
    avatar: 'https://s3.amazonaws.com/kd4/ryan',
    twitter: 'ryaneshea',
    github: 'shea256',
  },
  'blockstack.id': {
    blockstackId: 'blockstack',
    name: 'Muneeb & Ryan',
    avatar: 'https://s3.amazonaws.com/kd4/muneeb-and-ryan.jpg',
    twitter: 'blockstack',
    github: 'blockstack',
  },
  'founders.id': {
    blockstackId: 'blockstack',
    name: 'Ryan & Muneeb',
    avatar: 'https://s3.amazonaws.com/kd4/muneeb-and-ryan.jpg',
    twitter: 'blockstack',
    github: 'blockstack',
  },
  'mfreed.id': {
    blockstackId: 'mfreed',
    name: 'Mike Freedman',
    avatar: '/images/avatars/mike-freedman.jpg',
    twitter: 'michaelfreedman',
    github: 'mfreed',
  },
  'stanley1.id': {
    blockstackId: 'stanley1',
    name: 'Patrick Stanley',
    avatar: 'https://s3.amazonaws.com/kd4/stanley1',
    twitter: 'patrickwstanley',
    github: 'pstan26',
  },
  'yukan.id': {
    blockstackId: 'yukan',
    name: 'Ken Liao',
    avatar: 'https://blockstack.org/images/avatars/ken-liao.jpg',
    twitter: 'yukanl',
    github: 'yknl',
  },
  'arsteinhorn.id': {
    blockstackId: 'ariella',
    name: 'Ariella Steinhorn',
    avatar: 'https://blockstack.org/images/avatars/ariella-steinhorn.jpg',
    twitter: 'arsteinhorn',
    github: 'arsteinhorn',
  },
  'chase': {
    blockstackId: 'hologram',
    name: 'Chase Wackerfuss',
    avatar: 'https://blockstack.org/images/avatars/chase-wackerfuss.jpg',
    twitter: 'vockerfoos',
    github: 'cwackerfuss'
  }
}
<|endoftext|>


<commit_before>'use strict'
import React from 'react'
import Helmet from 'react-helmet'
import {defaultHelmetMeta, Layout} from '../components/layout'

const Index = () => (
  <Layout>

      SPB Frontend — петербургское сообщество фронтенд-разработчиков. Мы
      регулярно проводим встречи с 2014 года. Обычно это встречи с докладами по
      30 минут, но бывают разные форматы. Встречаемся обычно в пространствах в
      центре города.

      Если хотите выступить с докладом, напишите письмо на{' '}
      hi@spb-frontend.ru.

      Иногда мы проводим дринкапы : встречи в барах без докладов, просто чтобы
      пообщаться друг с другом, познакомиться, поговорить о наболевшем.

Еще по четвергам теперь бывают фронтенд-завтраки в центре города.

      Чтобы следить за новыми событиями сообщества, подписывайтесь на{' '}
      группу ВКонтакте
      ,
      Твиттер или{' '}
      Телеграм канал.

      Еще у нас есть Слак-чат для
      свободного общения на фронт-темы. Вопросы приветствуются. Получить инвайт
      в чат можно{' '}
      на специальной странице.

      Если хотите предложить вакансию, то это можно сделать только в канале{' '}

        #jobs-list
      {' '}
      нашего Слак-чата.

      Если хотите предложить спонсорство или площадку (от 100 человек), пишите
      нам на почту hi@spb-frontend.ru.

    <Helmet>
      {[
        ...defaultHelmetMeta,
        <title key="title">SPB Frontend. Frontend artisans</title>,
      ]}
    </Helmet>
  </Layout>
)

export default Index
<commit_msg>poke ci<commit_after>'use strict'
import React from 'react'
import Helmet from 'react-helmet'
import {defaultHelmetMeta, Layout} from '../components/layout'

const Index = () => (
  <Layout>

      SPB Frontend — петербургское сообщество фронтенд-разработчиков. Мы
      регулярно проводим встречи с 2014 года. Обычно это встречи с докладами по
      30 минут, но бывают разные форматы. Встречаемся обычно в пространствах в
      центре города.

      Если хотите выступить с докладом, напишите письмо на{' '}
      hi@spb-frontend.ru.

      Иногда мы проводим дринкапы: встречи в барах без докладов, просто чтобы
      пообщаться друг с другом, познакомиться, поговорить о наболевшем.

Еще по четвергам теперь бывают фронтенд-завтраки в центре города.

      Чтобы следить за новыми событиями сообщества, подписывайтесь на{' '}
      группу ВКонтакте
      ,
      Твиттер или{' '}
      Телеграм канал.

      Еще у нас есть Слак-чат для
      свободного общения на фронт-темы. Вопросы приветствуются. Получить инвайт
      в чат можно{' '}
      на специальной странице.

      Если хотите предложить вакансию, то это можно сделать только в канале{' '}

        #jobs-list
      {' '}
      нашего Слак-чата.

      Если хотите предложить спонсорство или площадку (от 100 человек), пишите
      нам на почту hi@spb-frontend.ru.

    <Helmet>
      {[
        ...defaultHelmetMeta,
        <title key="title">SPB Frontend. Frontend artisans</title>,
      ]}
    </Helmet>
  </Layout>
)

export default Index
<|endoftext|>


<commit_before>import { do_plot_json } from "../components/chart";
import { setupTimeline } from "../components/timeline";
import { setupGlobeByClass } from "../components/globe";
import { setupTippy } from "../components/tippy";

const IndexPage = context => {
  $(document).ready(function() {
    $(".dashboard-graph", context).each(function() {
      var graph = $(this);
      var graph_data = base64.decode(graph.data("plot-data"));
      var options_in = base64.decode(graph.data("plot-options"));
      do_plot_json(graph_data, options_in);
    });
    $(".visualization", context).each(function() {
      setupTimeline($(this), {});
    });
    $(".globe", context).each(function() {
      setupGlobeByClass($(this));
    });
    setupTippy(context);
  });
};

export { IndexPage };
<commit_msg>Fix graphs on dashboard not working<commit_after>import { do_plot_json } from "../components/chart";
import { setupTimeline } from "../components/timeline";
import { setupGlobeByClass } from "../components/globe";
import { setupTippy } from "../components/tippy";

const IndexPage = context => {
  $(document).ready(function() {
    $(".dashboard-graph", context).each(function() {
      var graph = $(this);
      var graph_data = graph.data("plot-data");
      var options_in = graph.data("plot-options");
      do_plot_json(graph_data, options_in);
    });
    $(".visualization", context).each(function() {
      setupTimeline($(this), {});
    });
    $(".globe", context).each(function() {
      setupGlobeByClass($(this));
    });
    setupTippy(context);
  });
};

export { IndexPage };
<|endoftext|>


<commit_before>import React from 'react';
import GatsbyLink from 'gatsby-link';
import Helmet from 'react-helmet';

import Link from '../components/Link';

import '../css/blog-post.css';
import '../css/index.css';
import '../css/basics.css';

export default function Index({ data }) {
  const { edges: posts } = data.allMarkdownRemark;
  return (

      {posts
        .filter(post => post.node.frontmatter.title.length > 0)
        .map(({ node: post }) => {
          return (

              <GatsbyLink to={post.frontmatter.path}  className="blog-post-preview link" key={post.id}>

                  {post.frontmatter.date}

                    {post.frontmatter.title}

                  {post.excerpt}

Read more

              </GatsbyLink>

          );
        })}

  );
}

import '../components/HelloFunc.js';

export const pageQuery = graphql`
  query IndexQuery {
    allMarkdownRemark(sort: { order: DESC, fields: [frontmatter___date] }) {
      edges {
        node {
          excerpt(pruneLength: 250)
          id
          frontmatter {
            title
            date(formatString: "MMMM DD, YYYY")
            path
          }
        }
      }
    }
  }
`;
<commit_msg>erase `hello` script import in index<commit_after>import React from 'react';
import GatsbyLink from 'gatsby-link';
import Helmet from 'react-helmet';

import Link from '../components/Link';

import '../css/blog-post.css';
import '../css/index.css';
import '../css/basics.css';

export default function Index({ data }) {
  const { edges: posts } = data.allMarkdownRemark;
  return (

      {posts
        .filter(post => post.node.frontmatter.title.length > 0)
        .map(({ node: post }) => {
          return (

              <GatsbyLink to={post.frontmatter.path}  className="blog-post-preview link" key={post.id}>

                  {post.frontmatter.date}

                    {post.frontmatter.title}

                  {post.excerpt}

Read more

              </GatsbyLink>

          );
        })}

  );
}

export const pageQuery = graphql`
  query IndexQuery {
    allMarkdownRemark(sort: { order: DESC, fields: [frontmatter___date] }) {
      edges {
        node {
          excerpt(pruneLength: 250)
          id
          frontmatter {
            title
            date(formatString: "MMMM DD, YYYY")
            path
          }
        }
      }
    }
  }
`;
<|endoftext|>


<commit_before>/**
 * Copyright (C) 2018 Glayzzle (BSD3 License)
 * @authors https://github.com/glayzzle/php-parser/graphs/contributors
 * @url http://glayzzle.com
 */
"use strict";

module.exports = {
  /*
   * reading an enum
   * ```ebnf
   * enum ::= enum_scope? T_ENUM T_STRING (':' NAMESPACE_NAME)? (T_IMPLEMENTS (NAMESPACE_NAME ',')* NAMESPACE_NAME)? '{' ENUM_BODY '}'
   * ```
   */
  read_enum_declaration_statement: function (attrs) {
    const result = this.node("enum");
    // graceful mode : ignore token & go next
    if (this.token !== this.tok.T_ENUM) {
      this.error(this.tok.T_ENUM);
      this.next();
      return null;
    }
    this.next().expect(this.tok.T_STRING);
    let propName = this.node("identifier");
    const name = this.text();
    this.next();
    propName = propName(name);
    const valueType = this.read_enum_value_type();
    const propImplements = this.read_implements_list();
    this.expect("{");
    const body = this.next().read_class_body(false, true);
    const node = result(propName, valueType, propImplements, body);
    if (attrs) node.attrGroups = attrs;
    return node;
  },

  read_enum_value_type: function () {
    if (this.token === ":") {
      return this.next().read_namespace_name();
    }

    return null;
  },

  read_enum_case: function () {
    this.expect(this.tok.T_CASE);
    const result = this.node("enumcase");
    let caseName = this.node("identifier");
    const name = this.next().text();
    this.next();
    caseName = caseName(name);

    const value = this.token === "=" ? this.next().read_expr() : null;
    this.expect(";");

    return result(caseName, value);
  },
};
<commit_msg>Simplify.<commit_after>/**
 * Copyright (C) 2018 Glayzzle (BSD3 License)
 * @authors https://github.com/glayzzle/php-parser/graphs/contributors
 * @url http://glayzzle.com
 */
"use strict";

module.exports = {
  /*
   * reading an enum
   * ```ebnf
   * enum ::= enum_scope? T_ENUM T_STRING (':' NAMESPACE_NAME)? (T_IMPLEMENTS (NAMESPACE_NAME ',')* NAMESPACE_NAME)? '{' ENUM_BODY '}'
   * ```
   */
  read_enum_declaration_statement: function (attrs) {
    const result = this.node("enum");
    // graceful mode : ignore token & go next
    if (!this.expect(this.tok.T_ENUM)) {
      return null;
    }
    this.next().expect(this.tok.T_STRING);
    let propName = this.node("identifier");
    const name = this.text();
    this.next();
    propName = propName(name);
    const valueType = this.read_enum_value_type();
    const propImplements = this.read_implements_list();
    this.expect("{");
    const body = this.next().read_class_body(false, true);
    const node = result(propName, valueType, propImplements, body);
    if (attrs) node.attrGroups = attrs;
    return node;
  },

  read_enum_value_type: function () {
    if (this.token === ":") {
      return this.next().read_namespace_name();
    }

    return null;
  },

  read_enum_case: function () {
    this.expect(this.tok.T_CASE);
    const result = this.node("enumcase");
    let caseName = this.node("identifier");
    const name = this.next().text();
    this.next();
    caseName = caseName(name);

    const value = this.token === "=" ? this.next().read_expr() : null;
    this.expect(";");

    return result(caseName, value);
  },
};
<|endoftext|>


<commit_before>'use strict';

/*!
 * Snakeskin
 * https://github.com/SnakeskinTpl/Snakeskin
 *
 * Released under the MIT license
 * https://github.com/SnakeskinTpl/Snakeskin/blob/master/LICENSE
 */

import esprima from '../deps/esprima';
import Parser from './constructor';
import { ws, r } from '../helpers/string';
import { applyDefEscape } from '../helpers/escape';
import { $dirNameAliases } from '../consts/cache';
import { IS_NODE } from '../consts/hacks';
import { G_MOD } from '../consts/literals';

/**
 * Returns a real directive name
 *
 * @param {string} name - source name
 * @return {string}
 */
Parser.prototype.getDirName = function (name) {
	return $dirNameAliases[name] || name;
};

/**
 * Returns a function name from a string
 *
 * @param {string} str - source string
 * @param {?boolean=} [opt_empty=false] - if is true, then function name can be empty
 * @return {string}
 */
Parser.prototype.getFnName = function (str, opt_empty) {
	const
		tmp = /^[^(]+/.exec(str),
		val = tmp ? tmp[0].trim() : '';

	if (!opt_empty && !val) {
		this.error(`invalid "${this.name}" declaration`);
	}

	return val;
};

/**
 * Replaces all find blocks %fileName% to the active file name
 * and returns a new string
 *
 * @param {string} str - source string
 * @return {string}
 */
Parser.prototype.replaceFileNamePatterns = function (str) {
	const
		{file} = this.info;

	let basename;
	str = this.replaceDangerBlocks(str.replace(/(.?)%fileName%/g, (str, $1) => {
		if (!file) {
			this.error(`the placeholder %fileName% can't be used without the "file" option`);
			return '';
		}

		if (!IS_NODE) {
			this.error(`the placeholder %fileName% can't be used with live compilation in a browser`);
			return '';
		}

		if (!basename) {
			const path = require('path');
			basename = path.basename(file, path.extname(file));
		}

		let
			res = basename;

		if ($1) {
			if ($1 !== '.') {
				res = `${$1}'${res}'`;

			} else {
				res = $1 + res;
			}
		}

		return res;
	}));

	return str;
};

export const
	nmRgxp = /\.|\[/,
	nmssRgxp = new RegExp(`^(${r(G_MOD)}?)\\[`),
	nmsRgxp = /\[/g,
	nmeRgxp = /]/g;

/**
 * Returns a block name from a string
 *
 * @param {string} name - source string
 * @param {?boolean=} [opt_parseLiteralScope=false] - if true, then wil be parse literal scope declaration
 * @return {string}
 */
Parser.prototype.getBlockName = function (name, opt_parseLiteralScope) {
	try {
		const parts = this.replaceFileNamePatterns(name)
			.replace(nmssRgxp, (str, $0) => `${$0 ? `${this.scope[this.scope.length - 1]}.` : ''}%`)
			.replace(nmsRgxp, '.%')
			.replace(nmeRgxp, '')
			.split('.');

		let res = '';
		for (let i = 0; i < parts.length; i++) {
			let el = parts[i];

			const
				custom = el[0] === '%';

			el = opt_parseLiteralScope && i === 0 || custom ?
				this.out(custom ? el.slice(1) : el, {unsafe: true}) : el;

			if (custom) {
				res += ws`['${applyDefEscape(this.returnEvalVal(el))}']`;
				continue;
			}

			res += (res ? `.${el}` : el);
		}

		name = res.trim();
		esprima.parse(name);

	} catch (err) {
		this.error(err.message);
		return '';
	}

	return name;
};

/**
 * Normalizes the specified block name
 *
 * @param {string} name
 * @return {string}
 */
Parser.prototype.normalizeBlockName = function (name) {
	name = this.replaceDangerBlocks(name)
		.replace(nmsRgxp, '.')
		.replace(nmeRgxp, '');

	return this.pasteDangerBlocks(name)
		.replace(/\.['"]|['"]\./g, '.')
		.replace(/^\.|['"]$/, '');
};
<commit_msg>Added %dirName% placeholder<commit_after>'use strict';

/*!
 * Snakeskin
 * https://github.com/SnakeskinTpl/Snakeskin
 *
 * Released under the MIT license
 * https://github.com/SnakeskinTpl/Snakeskin/blob/master/LICENSE
 */

import esprima from '../deps/esprima';
import Parser from './constructor';
import { ws, r } from '../helpers/string';
import { applyDefEscape } from '../helpers/escape';
import { $dirNameAliases } from '../consts/cache';
import { IS_NODE } from '../consts/hacks';
import { G_MOD } from '../consts/literals';

/**
 * Returns a real directive name
 *
 * @param {string} name - source name
 * @return {string}
 */
Parser.prototype.getDirName = function (name) {
	return $dirNameAliases[name] || name;
};

/**
 * Returns a function name from a string
 *
 * @param {string} str - source string
 * @param {?boolean=} [opt_empty=false] - if is true, then function name can be empty
 * @return {string}
 */
Parser.prototype.getFnName = function (str, opt_empty) {
	const
		tmp = /^[^(]+/.exec(str),
		val = tmp ? tmp[0].trim() : '';

	if (!opt_empty && !val) {
		this.error(`invalid "${this.name}" declaration`);
	}

	return val;
};

/**
 * Replaces all find blocks %fileName% to the active file name
 * and returns a new string
 *
 * @param {string} str - source string
 * @return {string}
 */
Parser.prototype.replaceFileNamePatterns = function (str) {
	const
		{file} = this.info;

	let
		basename,
		dirname;

	str = this.replaceDangerBlocks(str.replace(/(.?)%(fileName|dirName)%/g, (str, $1, placeholder) => {
		if (!file) {
			this.error(`the placeholder %${placeholder}% can't be used without the "file" option`);
			return '';
		}

		if (!IS_NODE) {
			this.error(`the placeholder %${placeholder}% can't be used with live compilation in a browser`);
			return '';
		}

		const
			path = require('path');

		let res;
		switch (placeholder) {
			case 'fileName':
				if (!basename) {
					basename = path.basename(file, path.extname(file));
				}

				res = basename;
				break;

			case 'dirName':
				if (!dirname) {
					dirname = path.basename(path.dirname(file));
				}

				res = dirname;
				break;
		}

		if ($1) {
			if ($1 !== '.') {
				res = `${$1}'${res}'`;

			} else {
				res = $1 + res;
			}
		}

		return res;
	}));

	return str;
};

export const
	nmRgxp = /\.|\[/,
	nmssRgxp = new RegExp(`^(${r(G_MOD)}?)\\[`),
	nmsRgxp = /\[/g,
	nmeRgxp = /]/g;

/**
 * Returns a block name from a string
 *
 * @param {string} name - source string
 * @param {?boolean=} [opt_parseLiteralScope=false] - if true, then wil be parse literal scope declaration
 * @return {string}
 */
Parser.prototype.getBlockName = function (name, opt_parseLiteralScope) {
	try {
		const parts = this.replaceFileNamePatterns(name)
			.replace(nmssRgxp, (str, $0) => `${$0 ? `${this.scope[this.scope.length - 1]}.` : ''}%`)
			.replace(nmsRgxp, '.%')
			.replace(nmeRgxp, '')
			.split('.');

		let res = '';
		for (let i = 0; i < parts.length; i++) {
			let el = parts[i];

			const
				custom = el[0] === '%';

			el = opt_parseLiteralScope && i === 0 || custom ?
				this.out(custom ? el.slice(1) : el, {unsafe: true}) : el;

			if (custom) {
				res += ws`['${applyDefEscape(this.returnEvalVal(el))}']`;
				continue;
			}

			res += (res ? `.${el}` : el);
		}

		name = res.trim();
		esprima.parse(name);

	} catch (err) {
		this.error(err.message);
		return '';
	}

	return name;
};

/**
 * Normalizes the specified block name
 *
 * @param {string} name
 * @return {string}
 */
Parser.prototype.normalizeBlockName = function (name) {
	name = this.replaceDangerBlocks(name)
		.replace(nmsRgxp, '.')
		.replace(nmeRgxp, '');

	return this.pasteDangerBlocks(name)
		.replace(/\.['"]|['"]\./g, '.')
		.replace(/^\.|['"]$/, '');
};
<|endoftext|>


<commit_before>const path = require('path');
const webpack = require('webpack');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextWebpackPlugin = require('extract-text-webpack-plugin');
const StyleExtHtmlWebpackPlugin = require('style-ext-html-webpack-plugin');
const OfflinePlugin = require('offline-plugin');
const WebpackDashboardPlugin = require('webpack-dashboard/plugin');

const { isDevelopment, port } = require('./configuration');

const baseEntry = [
  'babel-polyfill',
  'normalize.css',
  'raleway-webfont/raleway.css',
  'roboto-mono-webfont/roboto-mono.css',
  './src/shared/assets/avatar.jpg',
  './src/shared/assets/images',
  './src/client/index.jsx',
];
const devEntry = [
  'react-hot-loader/patch',
  `webpack-dev-server/client?http://localhost:${port}`,
  'webpack/hot/only-dev-server',
];
const entry = isDevelopment ? devEntry.concat(baseEntry) : baseEntry;

const basePlugins = [
  new webpack.EnvironmentPlugin(['NODE_ENV']),
  new CopyWebpackPlugin([{ from: 'src/shared/assets/favicon' }]),
  new HtmlWebpackPlugin({
    filename: isDevelopment ? 'index.html' : '../build/index.html',
    template: 'src/shared/index.html',
    inject: 'body',
    minify: { collapseWhitespace: true },
  }),
  new ExtractTextWebpackPlugin('[name].[hash].css'),
  new StyleExtHtmlWebpackPlugin({ minify: true }),
];
const devPlugins = [
  new webpack.HotModuleReplacementPlugin(),
  new webpack.NamedModulesPlugin(),
  new WebpackDashboardPlugin(),
];
const prodPlugins = [
  new webpack.LoaderOptionsPlugin({ minimize: true, debug: false }),
  new webpack.optimize.UglifyJsPlugin({ compress: { warnings: false } }),
  new OfflinePlugin({
    publicPath: '/',
    relativePaths: true,
    caches: {
      main: [':rest:'],
      additional: ['*.chunk.js'],
    },
    safeToUseOptionalCaches: true,
    AppCache: false,
  }),
];
const plugins = basePlugins.concat(isDevelopment ? devPlugins : prodPlugins);

module.exports = {
  entry,
  output: {
    path: path.join(__dirname, 'public'),
    publicPath: '/',
    filename: '[name].[chunkhash].js',
    chunkFilename: '[name].[chunkhash].chunk.js',
  },
  devtool: isDevelopment ? 'eval-source-map' : false,
  resolve: { extensions: ['.js', '.jsx'] },
  plugins,
  module: {
    rules: [
      { test: /\.jsx?$/, loader: 'eslint-loader', enforce: 'pre' },
      { test: /\.jsx?$/, loader: 'babel-loader', exclude: /node_modules/, options: { babelrc: false, presets: [['env', { modules: false }], 'stage-0', 'react'], plugins: ['react-hot-loader/babel'] } },
      { test: /\.css$/, use: ExtractTextWebpackPlugin.extract({ fallback: 'style-loader', use: 'css-loader' }) },
      { test: /\.md$/, use: [{ loader: 'raw-loader' }, { loader: 'remarkable-loader', options: { html: true } }] },
      { test: /\.(jpe?g|png)$/, use: [{ loader: 'file-loader', options: { name: 'assets/[name].[ext]' } }, { loader: 'image-webpack-loader', options: { mozjpeg: { quality: 80 } } }], include: /assets/ },
      { test: /\.(woff2?|ttf|eot|svg)(\?.*)?$/, loader: 'url-loader', options: { limit: 10000 } },
    ],
  },
  devServer: {
    port,
    compress: true,
    hot: true,
    historyApiFallback: true,
  },
};
<commit_msg>Change the caches<commit_after>const path = require('path');
const webpack = require('webpack');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const ExtractTextWebpackPlugin = require('extract-text-webpack-plugin');
const StyleExtHtmlWebpackPlugin = require('style-ext-html-webpack-plugin');
const OfflinePlugin = require('offline-plugin');
const WebpackDashboardPlugin = require('webpack-dashboard/plugin');

const { isDevelopment, port } = require('./configuration');

const baseEntry = [
  'babel-polyfill',
  'normalize.css',
  'raleway-webfont/raleway.css',
  'roboto-mono-webfont/roboto-mono.css',
  './src/shared/assets/avatar.jpg',
  './src/shared/assets/images',
  './src/client/index.jsx',
];
const devEntry = [
  'react-hot-loader/patch',
  `webpack-dev-server/client?http://localhost:${port}`,
  'webpack/hot/only-dev-server',
];
const entry = isDevelopment ? devEntry.concat(baseEntry) : baseEntry;

const basePlugins = [
  new webpack.EnvironmentPlugin(['NODE_ENV']),
  new CopyWebpackPlugin([{ from: 'src/shared/assets/favicon' }]),
  new HtmlWebpackPlugin({
    filename: isDevelopment ? 'index.html' : '../build/index.html',
    template: 'src/shared/index.html',
    inject: 'body',
    minify: { collapseWhitespace: true },
  }),
  new ExtractTextWebpackPlugin('[name].[hash].css'),
  new StyleExtHtmlWebpackPlugin({ minify: true }),
];
const devPlugins = [
  new webpack.HotModuleReplacementPlugin(),
  new webpack.NamedModulesPlugin(),
  new WebpackDashboardPlugin(),
];
const prodPlugins = [
  new webpack.LoaderOptionsPlugin({ minimize: true, debug: false }),
  new webpack.optimize.UglifyJsPlugin({ compress: { warnings: false } }),
  new OfflinePlugin({
    publicPath: '/',
    relativePaths: false,
    caches: {
      main: [':rest:'],
      additional: [':externals'],
      optional: ['*.chunk.js'],
    },
    AppCache: false,
  }),
];
const plugins = basePlugins.concat(isDevelopment ? devPlugins : prodPlugins);

module.exports = {
  entry,
  output: {
    path: path.join(__dirname, 'public'),
    publicPath: '/',
    filename: '[name].[chunkhash].js',
    chunkFilename: '[name].[chunkhash].chunk.js',
  },
  devtool: isDevelopment ? 'eval-source-map' : false,
  resolve: { extensions: ['.js', '.jsx'] },
  plugins,
  module: {
    rules: [
      { test: /\.jsx?$/, loader: 'eslint-loader', enforce: 'pre' },
      { test: /\.jsx?$/, loader: 'babel-loader', exclude: /node_modules/, options: { babelrc: false, presets: [['env', { modules: false }], 'stage-0', 'react'], plugins: ['react-hot-loader/babel'] } },
      { test: /\.css$/, use: ExtractTextWebpackPlugin.extract({ fallback: 'style-loader', use: 'css-loader' }) },
      { test: /\.md$/, use: [{ loader: 'raw-loader' }, { loader: 'remarkable-loader', options: { html: true } }] },
      { test: /\.(jpe?g|png)$/, use: [{ loader: 'file-loader', options: { name: 'assets/[name].[ext]' } }, { loader: 'image-webpack-loader', options: { mozjpeg: { quality: 80 } } }], include: /assets/ },
      { test: /\.(woff2?|ttf|eot|svg)(\?.*)?$/, loader: 'url-loader', options: { limit: 10000 } },
    ],
  },
  devServer: {
    port,
    compress: true,
    hot: true,
    historyApiFallback: true,
  },
};
<|endoftext|>


<commit_before>/**
 * Created by leituo56 on 11/23/14.
 */
var sqlite3 = require('sqlite3').verbose();
var db_cfg = new sqlite3.Database('db/cfg.db');
var db_lease = new sqlite3.Database('db/lease.db');

exports.db_cfg = db_cfg;
exports.db_lease = db_lease;<commit_msg>db path<commit_after>/**
 * Created by leituo56 on 11/23/14.
 */
var sqlite3 = require('sqlite3').verbose();
var db_cfg = new sqlite3.Database('/mnt/glusterfs/cfg.db');
var db_lease = new sqlite3.Database('/mnt/glusterfs/lease.db');

exports.db_cfg = db_cfg;
exports.db_lease = db_lease;
<|endoftext|>


<commit_before>// NOTE: Import this file before any other files
// Overwrite path to load resources or use default one.
__webpack_public_path__ = window.__patternslib_public_path__ || window.PORTAL_URL + "/++plone++static/" || "/dist/"; // eslint-disable-line no-undef
<commit_msg>Plone integration: Fix public path to not break local mockup dev.<commit_after>// NOTE: Import this file before any other files
// Overwrite path to load resources or use default one.
__webpack_public_path__ = window.__patternslib_public_path__ || window.PORTAL_URL ? window.PORTAL_URL + "/++plone++static/" : null || "/dist/"; // eslint-disable-line no-undef
<|endoftext|>


<commit_before>/* @flow strict-local */
import type { ComponentType, ElementConfig } from 'react';
import { connect as connectInner } from 'react-redux';

import type { GlobalState, Dispatch } from './types';

/* eslint-disable flowtype/generic-spacing */

/**
 * The type `S`, plus a check that `S` is a supertype of `T`.
 *
 * Gives an error unless `S` is a supertype of `T` -- i.e., a `T` can always
 * be used where an `S` is required.
 */
type IsSupertype<+S, +T: S> = S; // eslint-disable-line no-unused-vars

/**
 * An inverse of the operation `(A, B) => {| ...A, ...B |}`, with checking.
 *
 * Similar to `$Diff`, but checks that the subtraction makes sense.
 * Also always subtracts a given property completely, even if its type on
 * `L` happens to be more specific than on `U`.
 *
 * Assumes both U and L are exact object types.  (If not, behavior unknown.)
 * Returns a solution, where possible, to the type equation
 *   `U == {| ...D, ...L |}`
 * with an (inexact) object type `D`.
 *
 * More generally, returns the most general solution `D` to the relation
 *   `{| ...D, ...L |}: U`  (read "subtype of")
 * I.e., the most general type `D` such that `{| ...D, ...L |}` can be used
 * where a `U` is expected.  If there is no such `D`, causes a type error.
 *
 * In particular, this means:
 *  * Error if `L` has any extra properties that aren't in `U`.
 *  * Error unless each property of `L` has the same type as in `U`, or a subtype
 *    (i.e., the property's values in `L` are valid for `U`).
 *  * `D` has exactly the properties in `U` that aren't in `L`.
 *  * Each property of `D` has the same type as in `U`.
 */
// Oddly, Flow accepts this declaration with <-U, -L> but also with <+U, +L>.
export type BoundedDiff<-U, -L> = $Diff<
  // This `IsSupertype` is the part that checks that all of L's properties
  // (a) are present on U and (b) have appropriate types to use on U.
  IsSupertype<U, $ReadOnly<{| ...U, ...L |}>>,
  // This `$ObjMap` makes a variant of `L` that `$Diff` treats as more
  // powerful, ensuring that all properties in `L` are removed completely.
  $ObjMap<L, () => mixed>,
>;

export type OwnProps<-C, -SP> = $Diff<
  BoundedDiff<$Exact<ElementConfig<C>>, SP>,
  {| dispatch: Dispatch |},
>;

/**
 * Exactly like the `connect` in `react-redux` upstream, but more typed.
 *
 * The upstream function, and its libdef in `flow-typed`, has an extremely
 * complex type involving many overloads, and it's difficult to get useful
 * results with it from the type-checker.  This trivial wrapper leaves out a
 * bunch of features we don't use, and then gives a more specific type.
 *
 * (Most of those features probably *could* be supported with a more-helpful
 * type like this if desired, just with a moderate amount of further work.
 * Finding this type was a lot of work, and the extra features were left out
 * for the sake of focus while iterating on that.)
 */
// prettier-ignore
export function connect<SP, P, C: ComponentType<P>>(
  mapStateToProps?: (GlobalState, OwnProps<C,
    // Error "property `foo` is missing"?  Add to inner component's props.
    SP>) => SP,
): C => ComponentType<$ReadOnly<OwnProps<C, SP>>> {
  return connectInner(mapStateToProps);
}

/**
 * DEPRECATED.  Don't add new uses; and PRs to remove existing uses are welcome.
 *
 * This is exactly like `connect` except with type-checking disabled.
 * Any place we use it, it's because there's a type error there.
 * To fix: change the call site to use `connect`; see what error Flow
 * reports; and fix the error.
 *
 * (Backstory: for a long time `connect` had a type that partly defeated
 * type-checking, so we accumulated a number of type errors that that hid.
 * This untyped version lets us fix those errors one by one, while using the
 * new, well-typed `connect` everywhere else.)
 */
export const connectFlowFixMe = (mapStateToProps: $FlowFixMe) => (c: $FlowFixMe) =>
  connect(mapStateToProps)(c);
<commit_msg>connect [nfc]: Delete connectFlowFixMe! \o/<commit_after>/* @flow strict-local */
import type { ComponentType, ElementConfig } from 'react';
import { connect as connectInner } from 'react-redux';

import type { GlobalState, Dispatch } from './types';

/* eslint-disable flowtype/generic-spacing */

/**
 * The type `S`, plus a check that `S` is a supertype of `T`.
 *
 * Gives an error unless `S` is a supertype of `T` -- i.e., a `T` can always
 * be used where an `S` is required.
 */
type IsSupertype<+S, +T: S> = S; // eslint-disable-line no-unused-vars

/**
 * An inverse of the operation `(A, B) => {| ...A, ...B |}`, with checking.
 *
 * Similar to `$Diff`, but checks that the subtraction makes sense.
 * Also always subtracts a given property completely, even if its type on
 * `L` happens to be more specific than on `U`.
 *
 * Assumes both U and L are exact object types.  (If not, behavior unknown.)
 * Returns a solution, where possible, to the type equation
 *   `U == {| ...D, ...L |}`
 * with an (inexact) object type `D`.
 *
 * More generally, returns the most general solution `D` to the relation
 *   `{| ...D, ...L |}: U`  (read "subtype of")
 * I.e., the most general type `D` such that `{| ...D, ...L |}` can be used
 * where a `U` is expected.  If there is no such `D`, causes a type error.
 *
 * In particular, this means:
 *  * Error if `L` has any extra properties that aren't in `U`.
 *  * Error unless each property of `L` has the same type as in `U`, or a subtype
 *    (i.e., the property's values in `L` are valid for `U`).
 *  * `D` has exactly the properties in `U` that aren't in `L`.
 *  * Each property of `D` has the same type as in `U`.
 */
// Oddly, Flow accepts this declaration with <-U, -L> but also with <+U, +L>.
export type BoundedDiff<-U, -L> = $Diff<
  // This `IsSupertype` is the part that checks that all of L's properties
  // (a) are present on U and (b) have appropriate types to use on U.
  IsSupertype<U, $ReadOnly<{| ...U, ...L |}>>,
  // This `$ObjMap` makes a variant of `L` that `$Diff` treats as more
  // powerful, ensuring that all properties in `L` are removed completely.
  $ObjMap<L, () => mixed>,
>;

export type OwnProps<-C, -SP> = $Diff<
  BoundedDiff<$Exact<ElementConfig<C>>, SP>,
  {| dispatch: Dispatch |},
>;

/**
 * Exactly like the `connect` in `react-redux` upstream, but more typed.
 *
 * The upstream function, and its libdef in `flow-typed`, has an extremely
 * complex type involving many overloads, and it's difficult to get useful
 * results with it from the type-checker.  This trivial wrapper leaves out a
 * bunch of features we don't use, and then gives a more specific type.
 *
 * (Most of those features probably *could* be supported with a more-helpful
 * type like this if desired, just with a moderate amount of further work.
 * Finding this type was a lot of work, and the extra features were left out
 * for the sake of focus while iterating on that.)
 */
// prettier-ignore
export function connect<SP, P, C: ComponentType<P>>(
  mapStateToProps?: (GlobalState, OwnProps<C,
    // Error "property `foo` is missing"?  Add to inner component's props.
    SP>) => SP,
): C => ComponentType<$ReadOnly<OwnProps<C, SP>>> {
  return connectInner(mapStateToProps);
}
<|endoftext|>