<commit_before>;(function($$){ 'use strict';

  $$.style.applyFromString = function( style, string ){
    var remaining = '' + string;
    var selAndBlockStr;
    var blockRem;
    var propAndValStr;

    // remove comments from the style string
    remaining = remaining.replace(/[/][*](\s|.)+?[*][/]/g, '');

    function removeSelAndBlockFromRemaining(){
      // remove the parsed selector and block from the remaining text to parse
      if( remaining.length > selAndBlockStr.length ){
        remaining = remaining.substr( selAndBlockStr.length );
      } else {
        remaining = '';
      }
    }

    function removePropAndValFromRem(){
      // remove the parsed property and value from the remaining block text to parse
      if( blockRem.length > propAndValStr.length ){
        blockRem = blockRem.substr( propAndValStr.length );
      } else {
        blockRem = '';
      }
    }

    while(true){
      var nothingLeftToParse = remaining.match(/^\s*$/);
      if( nothingLeftToParse ){ break; }

      var selAndBlock = remaining.match(/^\s*((?:.|\s)+?)\s*\{((?:.|\s)+?)\}/);

      if( !selAndBlock ){
        $$.util.error('Halting stylesheet parsing: String stylesheet contains more to parse but no selector and block found in: ' + remaining);
        break;
      }

      selAndBlockStr = selAndBlock[0];

      // parse the selector
      var selectorStr = selAndBlock[1];
      var selector = new $$.Selector( selectorStr );
      if( selector._private.invalid && selectorStr !== 'core' ){
        $$.util.error('Skipping parsing of block: Invalid selector found in string stylesheet: ' + selectorStr);

        // skip this selector and block
        removeSelAndBlockFromRemaining();
        continue;
      }

      // parse the block of properties and values
      var blockStr = selAndBlock[2];
      var invalidBlock = false;
      blockRem = blockStr;
      var props = [];

      while(true){
        var nothingLeftToParse = blockRem.match(/^\s*$/);
        if( nothingLeftToParse ){ break; }

        var propAndVal = blockRem.match(/^\s*(.+?)\s*:\s*(.+?)\s*;/);

        if( !propAndVal ){
          $$.util.error('Skipping parsing of block: Invalid formatting of style property and value definitions found in:' + blockStr);
          invalidBlock = true;
          break;
        }

        propAndValStr = propAndVal[0];
        var propStr = propAndVal[1];
        var valStr = propAndVal[2];

        var prop = $$.style.properties[ propStr ];
        if( !prop ){
          $$.util.error('Skipping property: Invalid property name in: ' + propAndValStr);

          // skip this property in the block
          removePropAndValFromRem();
          continue;
        }

        var parsedProp = style.parse( propStr, valStr );

        if( !parsedProp ){
          $$.util.error('Skipping property: Invalid property definition in: ' + propAndValStr);

          // skip this property in the block
          removePropAndValFromRem();
          continue;
        }

        props.push({
          name: propStr,
          val: valStr
        });
        removePropAndValFromRem();
      }

      if( invalidBlock ){
        removeSelAndBlockFromRemaining();
        break;
      }

      // put the parsed block in the style
      style.selector( selectorStr );
      for( var i = 0; i < props.length; i++ ){
        var prop = props[i];
        style.css( prop.name, prop.val );
      }

      removeSelAndBlockFromRemaining();
    }

    return style;
  };

  $$.style.fromString = function( cy, string ){
    var style = new $$.Style(cy);

    $$.style.applyFromString( style, string );

    return style;
  };

  $$.styfn.fromString = function( string ){
    var style = this;

    style.resetToDefault();

    $$.style.applyFromString( style, string );

    return style;
  };

})( cytoscape );
<commit_msg> String stylesheet : error message : `core` invalid #856<commit_after>;(function($$){ 'use strict';

  $$.style.applyFromString = function( style, string ){
    var remaining = '' + string;
    var selAndBlockStr;
    var blockRem;
    var propAndValStr;

    // remove comments from the style string
    remaining = remaining.replace(/[/][*](\s|.)+?[*][/]/g, '');

    function removeSelAndBlockFromRemaining(){
      // remove the parsed selector and block from the remaining text to parse
      if( remaining.length > selAndBlockStr.length ){
        remaining = remaining.substr( selAndBlockStr.length );
      } else {
        remaining = '';
      }
    }

    function removePropAndValFromRem(){
      // remove the parsed property and value from the remaining block text to parse
      if( blockRem.length > propAndValStr.length ){
        blockRem = blockRem.substr( propAndValStr.length );
      } else {
        blockRem = '';
      }
    }

    while(true){
      var nothingLeftToParse = remaining.match(/^\s*$/);
      if( nothingLeftToParse ){ break; }

      var selAndBlock = remaining.match(/^\s*((?:.|\s)+?)\s*\{((?:.|\s)+?)\}/);

      if( !selAndBlock ){
        $$.util.error('Halting stylesheet parsing: String stylesheet contains more to parse but no selector and block found in: ' + remaining);
        break;
      }

      selAndBlockStr = selAndBlock[0];

      // parse the selector
      var selectorStr = selAndBlock[1];
      if( selectorStr !== 'core' ){
        var selector = new $$.Selector( selectorStr );
        if( selector._private.invalid ){
          $$.util.error('Skipping parsing of block: Invalid selector found in string stylesheet: ' + selectorStr);

          // skip this selector and block
          removeSelAndBlockFromRemaining();
          continue;
        }
      }

      // parse the block of properties and values
      var blockStr = selAndBlock[2];
      var invalidBlock = false;
      blockRem = blockStr;
      var props = [];

      while(true){
        var nothingLeftToParse = blockRem.match(/^\s*$/);
        if( nothingLeftToParse ){ break; }

        var propAndVal = blockRem.match(/^\s*(.+?)\s*:\s*(.+?)\s*;/);

        if( !propAndVal ){
          $$.util.error('Skipping parsing of block: Invalid formatting of style property and value definitions found in:' + blockStr);
          invalidBlock = true;
          break;
        }

        propAndValStr = propAndVal[0];
        var propStr = propAndVal[1];
        var valStr = propAndVal[2];

        var prop = $$.style.properties[ propStr ];
        if( !prop ){
          $$.util.error('Skipping property: Invalid property name in: ' + propAndValStr);

          // skip this property in the block
          removePropAndValFromRem();
          continue;
        }

        var parsedProp = style.parse( propStr, valStr );

        if( !parsedProp ){
          $$.util.error('Skipping property: Invalid property definition in: ' + propAndValStr);

          // skip this property in the block
          removePropAndValFromRem();
          continue;
        }

        props.push({
          name: propStr,
          val: valStr
        });
        removePropAndValFromRem();
      }

      if( invalidBlock ){
        removeSelAndBlockFromRemaining();
        break;
      }

      // put the parsed block in the style
      style.selector( selectorStr );
      for( var i = 0; i < props.length; i++ ){
        var prop = props[i];
        style.css( prop.name, prop.val );
      }

      removeSelAndBlockFromRemaining();
    }

    return style;
  };

  $$.style.fromString = function( cy, string ){
    var style = new $$.Style(cy);

    $$.style.applyFromString( style, string );

    return style;
  };

  $$.styfn.fromString = function( string ){
    var style = this;

    style.resetToDefault();

    $$.style.applyFromString( style, string );

    return style;
  };

})( cytoscape );
<|endoftext|>


<commit_before>/**
 * Functions for working with the automagic URI/Slug generation with multipleslug support.
 *
 * @mixin
 * @namespace Bolt.fields.slug
 *
 * @param {Object} bolt - The Bolt module.
 * @param {Object} $ - jQuery.
 * @param {Object} Clipboard.
 */
(function (bolt, $, Clipboard) {
    'use strict';

    /**
     * Field configuration.
     *
     * @typedef {Object} FieldConf
     * @memberof Bolt.fields.slug
     *
     * @property {string} bind - Always 'slug'.
     * @property {string|null} contentId - Content Id.
     * @property {boolean} isEmpty - Is not set?
     * @property {string} key - The field key
     * @property {string} slug - Content slug.
     * @property {Array} uses - Fields used to automatically generate a slug.
     */

    /**
     * Field data.
     *
     * @typedef {Object} FieldData
     * @memberof Bolt.fields.slug
     *
     * @property {Object} group - Group container.
     * @property {Object} show - Slug display.
     * @property {Object} prefix - URL prefix (like `/contenttype/` ).
     * @property {Object} data - Data field.
     * @property {Object} lock - Lock button.
     * @property {Object} unlock - Unlock button.
     * @property {Object} edit - Edit button.
     * @property {Object} copy - Copy button.
     * @property {string} key - The field key
     * @property {Array} uses - Fields used to automatically generate a slug.
     * @property {string} slug - Content slug.
     * @property {string|null} id - Content Id.
     */

    /**
     * Bolt.fields.slug mixin container.
     *
     * @private
     * @type {Object}
     */
    var slug = {};

    /**
     * Bind slug field.
     *
     * @static
     * @function init
     * @memberof Bolt.fields.slug
     *
     * @param {Object} fieldset
     * @param {FieldConf} fconf
     */
    slug.init = function (fieldset, fconf) {
        var field = {
                group: $(fieldset).find('.input-group'),
                show: $(fieldset).find('em'),
                prefix: $(fieldset).find('span.prefix'),
                data: $(fieldset).find('input'),
                lock: $(fieldset).find('li.lock a'),
                unlock: $(fieldset).find('li.unlock a'),
                edit: $(fieldset).find('li.edit a'),
                copy: $(fieldset).find('li.copy'),
                key: fconf.key,
                uses: fconf.uses,
                slug: fconf.slug,
                id: fconf.contentId
            };

        field.lock.on('click', function () {
            lock(field);
        });

        field.unlock.on('click', function () {
            unlock(field, fconf.isEmpty);
        });

        field.edit.on('click', function () {
            edit(field);
        });

        if (fconf.isEmpty) {
            field.unlock.trigger('click');
        }

        var clipboard = new Clipboard('.copy');

        clipboard.on('success', function(e) {
            console.info('Copied:', e.text);
            e.clearSelection();
        });

    };

    /**
     * Timeout.
     *
     * @private
     * @type {Array}
     * @memberof Bolt.fields.slug
     */
    var timeout = [];

    /**
     * Locks the slug field.
     *
     * @private
     * @function lock
     * @memberof Bolt.fields.slug
     *
     * @param {FieldData} field - Field data.
     */
    function lock(field) {
        field.group.removeClass('unlocked').addClass('locked');
        stopAutoGeneration(field);
    }

    /**
     * Unlocks the slug field.
     *
     * @private
     * @function unlock
     * @memberof Bolt.fields.slug
     *
     * @param {FieldData} field - Field data.
     * @param {boolean} wasEmpty - Slug is currently empty
     */
    function unlock(field, wasEmpty) {
        // "unlock" if it's currently empty, _or_ we've confirmed that we want to do so.
        if (wasEmpty || confirm(bolt.data('field.slug.message.unlock'))) {
            field.group.removeClass('locked').addClass('unlocked');
            startAutoGeneration(field);
        }
    }

    /**
     * Edit the slug.
     *
     * @private
     * @function edit
     * @memberof Bolt.fields.slug
     *
     * @param {FieldData} field - Field data.
     */
    function edit(field) {
        var newslug = prompt(bolt.data('field.slug.message.set'), field.data.val());

        if (newslug) {
            field.group.removeClass('unlocked').addClass('locked');
            stopAutoGeneration(field);
            getUriAjax(field, newslug);
        }
    }

    /**
     * Get URI for slug from remote.
     *
     * @private
     * @function getUriAjax
     * @memberof Bolt.fields.slug
     *
     * @param {FieldData} field - Field data.
     * @param {string} text - New slug text.
     */
    function getUriAjax(field, text) {
        $.ajax({
            url: bolt.conf('paths.async') + 'makeuri',
            type: 'GET',
            data: {
                title: text,
                contenttypeslug: field.slug,
                id: field.id,
                slugfield: field.key,
                fulluri: false
            },
            success: function (uri) {
                field.data.val(uri);
                field.show.html(uri);
                field.copy.attr('data-clipboard-text', field.prefix.text() + uri);
            },
            error: function () {
                console.log('failed to get an URI');
            }
        });
    }

    /**
     * Start generating slugs from uses fields.
     *
     * @private
     * @function startAutoGeneration
     * @memberof Bolt.fields.slug
     *
     * @param {FieldData} field - Field data.
     */
    function startAutoGeneration(field) {
        $.each(field.uses, function (i, bindField) {
            $('#' + bindField).on('propertychange.bolt input.bolt change.bolt', function () {
                var usesValue = [];

                $.each(field.uses, function (i, useField) {
                    var field = $('#' + useField);

                    if (field.is('select')) {
                        field.find('option:selected').each(function(i, option) {
                            if (option.text !== '') {
                                usesValue.push(option.text);
                            }
                        });
                    } else if (field.val()) {
                        usesValue.push(field.val());
                    }
                });

                clearTimeout(timeout[field.key]);
                timeout[field.key] = setTimeout(
                    function () {
                        getUriAjax(field, usesValue.join(' '));
                    },
                    200
                );
            }).trigger('change.bolt');
        });
    }

    /**
     * Stop generating slugs from uses fields.
     *
     * @private
     * @function stopAutoGeneration
     * @memberof Bolt.fields.slug
     *
     * @param {FieldData} field - Field data.
     */
    function stopAutoGeneration(field) {
        $.each(field.uses, function (i, name) {
            $('#' + name).off('propertychange.bolt input.bolt change.bolt');
        });
        clearTimeout(timeout[field.key]);
    }

    // Apply mixin container
    bolt.fields.slug = slug;

})(Bolt || {}, jQuery, Clipboard);
<commit_msg>Doubleclick on slug to unlock. Don't ask confirmation.<commit_after>/**
 * Functions for working with the automagic URI/Slug generation with multipleslug support.
 *
 * @mixin
 * @namespace Bolt.fields.slug
 *
 * @param {Object} bolt - The Bolt module.
 * @param {Object} $ - jQuery.
 * @param {Object} Clipboard.
 */
(function (bolt, $, Clipboard) {
    'use strict';

    /**
     * Field configuration.
     *
     * @typedef {Object} FieldConf
     * @memberof Bolt.fields.slug
     *
     * @property {string} bind - Always 'slug'.
     * @property {string|null} contentId - Content Id.
     * @property {boolean} isEmpty - Is not set?
     * @property {string} key - The field key
     * @property {string} slug - Content slug.
     * @property {Array} uses - Fields used to automatically generate a slug.
     */

    /**
     * Field data.
     *
     * @typedef {Object} FieldData
     * @memberof Bolt.fields.slug
     *
     * @property {Object} group - Group container.
     * @property {Object} show - Slug display.
     * @property {Object} prefix - URL prefix (like `/contenttype/` ).
     * @property {Object} data - Data field.
     * @property {Object} lock - Lock button.
     * @property {Object} unlock - Unlock button.
     * @property {Object} edit - Edit button.
     * @property {Object} copy - Copy button.
     * @property {string} key - The field key
     * @property {Array} uses - Fields used to automatically generate a slug.
     * @property {string} slug - Content slug.
     * @property {string|null} id - Content Id.
     */

    /**
     * Bolt.fields.slug mixin container.
     *
     * @private
     * @type {Object}
     */
    var slug = {};

    /**
     * Bind slug field.
     *
     * @static
     * @function init
     * @memberof Bolt.fields.slug
     *
     * @param {Object} fieldset
     * @param {FieldConf} fconf
     */
    slug.init = function (fieldset, fconf) {
        var field = {
                group: $(fieldset).find('.input-group'),
                show: $(fieldset).find('em'),
                prefix: $(fieldset).find('span.prefix'),
                data: $(fieldset).find('input'),
                lock: $(fieldset).find('li.lock a'),
                unlock: $(fieldset).find('li.unlock a'),
                edit: $(fieldset).find('li.edit a'),
                copy: $(fieldset).find('li.copy'),
                key: fconf.key,
                uses: fconf.uses,
                slug: fconf.slug,
                id: fconf.contentId
            };

        field.lock.on('click', function () {
            lock(field);
        });

        field.unlock.on('click', function () {
            unlock(field);
        });

        field.group.on('dblclick', function () {
            unlock(field);
        });

        field.edit.on('click', function () {
            edit(field);
        });

        if (fconf.isEmpty) {
            field.unlock.trigger('click');
        }

        var clipboard = new Clipboard('.copy');

        clipboard.on('success', function(e) {
            console.info('Copied:', e.text);
            e.clearSelection();
        });

    };

    /**
     * Timeout.
     *
     * @private
     * @type {Array}
     * @memberof Bolt.fields.slug
     */
    var timeout = [];

    /**
     * Locks the slug field.
     *
     * @private
     * @function lock
     * @memberof Bolt.fields.slug
     *
     * @param {FieldData} field - Field data.
     */
    function lock(field) {
        field.group.removeClass('unlocked').addClass('locked');
        stopAutoGeneration(field);
    }

    /**
     * Unlocks the slug field.
     *
     * @private
     * @function unlock
     * @memberof Bolt.fields.slug
     *
     * @param {FieldData} field - Field data.
     * @param {boolean} wasEmpty - Slug is currently empty
     */
    function unlock(field) {
        // "unlock" if it's currently empty.
        // Note: We don't ask for confirmation anymore. Too many clicks.
        field.group.removeClass('locked').addClass('unlocked');
        startAutoGeneration(field);
        return false;
    }

    /**
     * Edit the slug.
     *
     * @private
     * @function edit
     * @memberof Bolt.fields.slug
     *
     * @param {FieldData} field - Field data.
     */
    function edit(field) {
        var newslug = prompt(bolt.data('field.slug.message.set'), field.data.val());

        if (newslug) {
            field.group.removeClass('unlocked').addClass('locked');
            stopAutoGeneration(field);
            getUriAjax(field, newslug);
        }
    }

    /**
     * Get URI for slug from remote.
     *
     * @private
     * @function getUriAjax
     * @memberof Bolt.fields.slug
     *
     * @param {FieldData} field - Field data.
     * @param {string} text - New slug text.
     */
    function getUriAjax(field, text) {
        $.ajax({
            url: bolt.conf('paths.async') + 'makeuri',
            type: 'GET',
            data: {
                title: text,
                contenttypeslug: field.slug,
                id: field.id,
                slugfield: field.key,
                fulluri: false
            },
            success: function (uri) {
                field.data.val(uri);
                field.show.html(uri);
                field.copy.attr('data-clipboard-text', field.prefix.text() + uri);
            },
            error: function () {
                console.log('failed to get an URI');
            }
        });
    }

    /**
     * Start generating slugs from uses fields.
     *
     * @private
     * @function startAutoGeneration
     * @memberof Bolt.fields.slug
     *
     * @param {FieldData} field - Field data.
     */
    function startAutoGeneration(field) {
        $.each(field.uses, function (i, bindField) {
            $('#' + bindField).on('propertychange.bolt input.bolt change.bolt', function () {
                var usesValue = [];

                $.each(field.uses, function (i, useField) {
                    var field = $('#' + useField);

                    if (field.is('select')) {
                        field.find('option:selected').each(function(i, option) {
                            if (option.text !== '') {
                                usesValue.push(option.text);
                            }
                        });
                    } else if (field.val()) {
                        usesValue.push(field.val());
                    }
                });

                clearTimeout(timeout[field.key]);
                timeout[field.key] = setTimeout(
                    function () {
                        getUriAjax(field, usesValue.join(' '));
                    },
                    200
                );
            }).trigger('change.bolt');
        });
    }

    /**
     * Stop generating slugs from uses fields.
     *
     * @private
     * @function stopAutoGeneration
     * @memberof Bolt.fields.slug
     *
     * @param {FieldData} field - Field data.
     */
    function stopAutoGeneration(field) {
        $.each(field.uses, function (i, name) {
            $('#' + name).off('propertychange.bolt input.bolt change.bolt');
        });
        clearTimeout(timeout[field.key]);
    }

    // Apply mixin container
    bolt.fields.slug = slug;

})(Bolt || {}, jQuery, Clipboard);
<|endoftext|>


<commit_before>/**
 * Main diagram class.
 *
 * @copyright   copyright (c) 2015 by Harald Lapp
 * @author      Harald Lapp <harald@octris.org>
 */

;(function(flowdesigner) {
    var wire = flowdesigner.wire;
    var node = flowdesigner.node;

    /*
     * zoom inspired by StableZoom
     * https://github.com/mberth/PanAndZoom/blob/master/app/scripts/pan_and_zoom.coffee
     */
    function zoom(old_zoom, delta, c, p) {
        var factor = 1.05;
        var new_zoom = (delta < 0
                        ? old_zoom * factor
                        : (delta > 0
                            ? old_zoom / factor
                            : old_zoom));

        return {
            zoom: new_zoom,
            offset: p.subtract(p.subtract(c).multiply(old_zoom / new_zoom)).subtract(c)
        };
    }

    /**
     * Constructor.
     *
     * @param   mixed       canvas              Canvas selector.
     * @param   object      options             Optional options.
     */
    function diagram(canvas, options)
    {
        this.canvas = paper.setup(canvas);
        this.options = $.extend({'raster': 0}, options || {});
        this.nodes = [];
        this.scopes = {};
        this.registry = {};

        this.layers = {
            'wires': new this.canvas.Layer(),
            'nodes': new this.canvas.Layer(),
            'draw': new this.canvas.Layer()
        };

        this.wire = new wire(this);

        // disable context menu
        $('#' + canvas).bind('contextmenu', function() {
            return false;
        });

        // zoom
        $('#' + canvas).mousewheel(function(event) {
            var pos = paper.view.viewToProject(new paper.Point(event.offsetX, event.offsetY));
            var ret = zoom(paper.view.zoom, event.deltaY, paper.view.center, pos);

            paper.view.zoom = ret.zoom;
            paper.view.center = paper.view.center.add(ret.offset);

            event.preventDefault();

            paper.view.draw();
        });

        // pan
        (function() {
            var tool = new paper.Tool();
            var drag = false;
            var point = {x: 0, y: 0};

            tool.onMouseDrag = function(event) {
                if (drag) {
                    var delta = {
                        x: point.x - event.event.offsetX,
                        y: point.y - event.event.offsetY
                    };

                    point = {x: event.event.offsetX, y: event.event.offsetY};

                    paper.view.center = paper.view.center.add(new paper.Point(delta.x, delta.y));

                    event.stopPropagation();
                }
            }
            tool.onMouseUp = function(event) {
                drag = false;
            }

            $('#' + canvas).on({
                mousedown: function(event) {
                    if (event.shiftKey) {
                        tool.activate();

                        drag = true;
                        point = {x: event.offsetX, y: event.offsetY};
                    }
                }
            });
        })();
    }

    /**
     * Define a node.
     *
     * @param   string      name                Name of node to define.
     * @param   string      def                 Node definition.
     */
    diagram.prototype.defineNode = function(name, def)
    {
        var _def = $.extend({
            input: [],
            output: [],
            border_color: node.prototype.node_border_color,
            color: node.prototype.node_color,
            font_color: node.prototype.node_font_color,
            onClick: function() {},
            onDblClick: function() {}
        }, def);

        function def_node(dia, data) {
            node.call(this, dia, data);
        }

        def_node.prototype = Object.create(node.prototype);
        def_node.prototype.constructor = def_node;

        def_node.prototype.onClick = _def.onClick;
        def_node.prototype.onDblClick = _def.onDblClick;
        def_node.prototype.node_input = _def.input;
        def_node.prototype.node_output = _def.output;
        def_node.prototype.node_color = _def.color;
        def_node.prototype.node_border_color = _def.border_color;
        def_node.prototype.node_font_color = _def.font_color;

        this.registry[name] = def_node;
    }

    /**
     * Register a node node-derived class with specified name.
     *
     * @param   string      name                Name of node to register.
     * @param   string      node_subclass       Node class to register.
     */
    diagram.prototype.registerNode = function(name, node_subclass)
    {
        if (!node.prototype.isPrototypeOf(test.prototype)) {
            throw new Error('Invalid parameter specified');
        }

        this.registry[name] = node_subclass;
    }

    /**
     * Define a connector scope.
     *
     * @param   string      name                Name of scope.
     * @param   object      settings            Scope settings.
     */
    diagram.prototype.defineScope = function(name, settings)
    {
        this.scopes[name] = settings;
    }

    /**
     * Test if scope is available.
     *
     * @param   string      name                Name of scope.
     * @return  bool                            Returns true if scope is available.
     */
    diagram.prototype.hasScope = function(name)
    {
        return (name in this.scopes);
    }

    /**
     * Return scope settings.
     *
     * @param   string      name                Name of scope.
     * @return  object                          Scope settings.
     */
    diagram.prototype.getScope = function(name)
    {
        return this.scopes[name];
    }

    /**
     * Return and activate layer of specified name. Returns the canvas layer, if no layer name
     * is specified.
     *
     * @param   string      name                Name of layer to get.
     * @return  node                            Layer node.
     */
    diagram.prototype.getLayer = function(name)
    {
        var layer = (typeof name !== 'undefined'
                        ? this.layers[name]
                        : this.canvas);

        layer.activate();

        return layer;
    }

    /**
     * Return wires.
     *
     * @return  array                           Array ofwires.
     */
    diagram.prototype.exportWires = function()
    {
        return this.wire.exportWires();
    }

    /**
     * Export nodes.
     *
     * @return  array                           Array of nodes.
     */
    diagram.prototype.exportNodes = function()
    {
        return this.nodes.map(function(node) {
            return node.getData();
        });
    }

    /**
     * Add multiple nodes.
     *
     * @param   array       nodes               Array of nodes.
     */
    diagram.prototype.addNodes = function(nodes)
    {
        nodes.forEach(function(data) {
            this.addNode(data);
        }, this);
    }

    /**
     * Add a single node to diagram.
     *
     * @param   object      data                Node data.
     */
    diagram.prototype.addNode = function(data)
    {
        if (typeof this.registry[data.node] == 'undefined') {
            throw new Error('Unknown node "' + data.node + '"')
        }

        var node = new this.registry[data.node](this, data);
        node.render();

        this.nodes.push(node);
    }

    /**
     * Add multiple wires.
     *
     * @param   array       wires               Array of wires.
     */
    diagram.prototype.addWires = function(wires)
    {
        wires.forEach(function(wire) {
            this.addWire(wire);
        }, this);
    }

    /**
     * Add a single wire to diagram.
     *
     * @param   object      wire                Wire to add.
     */
    diagram.prototype.addWire = function(wire)
    {
        this.wire.addWire(wire.source, wire.target);
    }

    /**
     * Remove node of the specified ID.
     *
     * @param   string      id                  ID of node to remove.
     */
    diagram.prototype.removeNode = function(id)
    {
        this.nodes = this.nodes.filter(function(node) {
            var ret = true;

            if (node.getId() == id) {
                node.destroy();

                ret = false;
            }

            return ret;
        });
    }

    /**
     * Remove multiple nodes.
     *
     * @param   array       ids                 Array of IDs of nodes to remove.
     */
    diagram.prototype.removeNodes = function(ids)
    {
        ids.forEach(function(id) {
            this.removeNode(id);
        }, this);
    }

    /**
     * Remove all nodes from diagram.
     */
    diagram.prototype.removeAllNodes = function()
    {
        this.nodes = this.nodes.filter(function(node) {
            node.destroy();

            return false;
        });
    }

    flowdesigner.diagram = diagram;
})(flowdesigner);
<commit_msg>allow to specify can_remove setting in defineNode<commit_after>/**
 * Main diagram class.
 *
 * @copyright   copyright (c) 2015 by Harald Lapp
 * @author      Harald Lapp <harald@octris.org>
 */

;(function(flowdesigner) {
    var wire = flowdesigner.wire;
    var node = flowdesigner.node;

    /*
     * zoom inspired by StableZoom
     * https://github.com/mberth/PanAndZoom/blob/master/app/scripts/pan_and_zoom.coffee
     */
    function zoom(old_zoom, delta, c, p) {
        var factor = 1.05;
        var new_zoom = (delta < 0
                        ? old_zoom * factor
                        : (delta > 0
                            ? old_zoom / factor
                            : old_zoom));

        return {
            zoom: new_zoom,
            offset: p.subtract(p.subtract(c).multiply(old_zoom / new_zoom)).subtract(c)
        };
    }

    /**
     * Constructor.
     *
     * @param   mixed       canvas              Canvas selector.
     * @param   object      options             Optional options.
     */
    function diagram(canvas, options)
    {
        this.canvas = paper.setup(canvas);
        this.options = $.extend({'raster': 0}, options || {});
        this.nodes = [];
        this.scopes = {};
        this.registry = {};

        this.layers = {
            'wires': new this.canvas.Layer(),
            'nodes': new this.canvas.Layer(),
            'draw': new this.canvas.Layer()
        };

        this.wire = new wire(this);

        // disable context menu
        $('#' + canvas).bind('contextmenu', function() {
            return false;
        });

        // zoom
        $('#' + canvas).mousewheel(function(event) {
            var pos = paper.view.viewToProject(new paper.Point(event.offsetX, event.offsetY));
            var ret = zoom(paper.view.zoom, event.deltaY, paper.view.center, pos);

            paper.view.zoom = ret.zoom;
            paper.view.center = paper.view.center.add(ret.offset);

            event.preventDefault();

            paper.view.draw();
        });

        // pan
        (function() {
            var tool = new paper.Tool();
            var drag = false;
            var point = {x: 0, y: 0};

            tool.onMouseDrag = function(event) {
                if (drag) {
                    var delta = {
                        x: point.x - event.event.offsetX,
                        y: point.y - event.event.offsetY
                    };

                    point = {x: event.event.offsetX, y: event.event.offsetY};

                    paper.view.center = paper.view.center.add(new paper.Point(delta.x, delta.y));

                    event.stopPropagation();
                }
            }
            tool.onMouseUp = function(event) {
                drag = false;
            }

            $('#' + canvas).on({
                mousedown: function(event) {
                    if (event.shiftKey) {
                        tool.activate();

                        drag = true;
                        point = {x: event.offsetX, y: event.offsetY};
                    }
                }
            });
        })();
    }

    /**
     * Define a node.
     *
     * @param   string      name                Name of node to define.
     * @param   string      def                 Node definition.
     */
    diagram.prototype.defineNode = function(name, def)
    {
        var _def = $.extend({
            input: [],
            output: [],
            border_color: node.prototype.node_border_color,
            color: node.prototype.node_color,
            font_color: node.prototype.node_font_color,
            can_remove: true,
            onClick: function() {},
            onDblClick: function() {}
        }, def);

        function def_node(dia, data) {
            node.call(this, dia, data);
        }

        def_node.prototype = Object.create(node.prototype);
        def_node.prototype.constructor = def_node;

        def_node.prototype.onClick = _def.onClick;
        def_node.prototype.onDblClick = _def.onDblClick;
        def_node.prototype.node_input = _def.input;
        def_node.prototype.node_output = _def.output;
        def_node.prototype.node_color = _def.color;
        def_node.prototype.node_border_color = _def.border_color;
        def_node.prototype.node_font_color = _def.font_color;
        def_node.prototype.node_can_remove = _def.can_remove;

        this.registry[name] = def_node;
    }

    /**
     * Register a node node-derived class with specified name.
     *
     * @param   string      name                Name of node to register.
     * @param   string      node_subclass       Node class to register.
     */
    diagram.prototype.registerNode = function(name, node_subclass)
    {
        if (!node.prototype.isPrototypeOf(test.prototype)) {
            throw new Error('Invalid parameter specified');
        }

        this.registry[name] = node_subclass;
    }

    /**
     * Define a connector scope.
     *
     * @param   string      name                Name of scope.
     * @param   object      settings            Scope settings.
     * @param   string      parent              Optional parent scope.
     */
    diagram.prototype.defineScope = function(name, settings, parent)
    {
        this.scopes[name] = settings;
    }

    /**
     * Test if scope is available.
     *
     * @param   string      name                Name of scope.
     * @return  bool                            Returns true if scope is available.
     */
    diagram.prototype.hasScope = function(name)
    {
        return (name in this.scopes);
    }

    /**
     * Return scope settings.
     *
     * @param   string      name                Name of scope.
     * @return  object                          Scope settings.
     */
    diagram.prototype.getScope = function(name)
    {
        return this.scopes[name];
    }

    /**
     * Return and activate layer of specified name. Returns the canvas layer, if no layer name
     * is specified.
     *
     * @param   string      name                Name of layer to get.
     * @return  node                            Layer node.
     */
    diagram.prototype.getLayer = function(name)
    {
        var layer = (typeof name !== 'undefined'
                        ? this.layers[name]
                        : this.canvas);

        layer.activate();

        return layer;
    }

    /**
     * Return wires.
     *
     * @return  array                           Array ofwires.
     */
    diagram.prototype.exportWires = function()
    {
        return this.wire.exportWires();
    }

    /**
     * Export nodes.
     *
     * @return  array                           Array of nodes.
     */
    diagram.prototype.exportNodes = function()
    {
        return this.nodes.map(function(node) {
            return node.getData();
        });
    }

    /**
     * Add multiple nodes.
     *
     * @param   array       nodes               Array of nodes.
     */
    diagram.prototype.addNodes = function(nodes)
    {
        nodes.forEach(function(data) {
            this.addNode(data);
        }, this);
    }

    /**
     * Add a single node to diagram.
     *
     * @param   object      data                Node data.
     */
    diagram.prototype.addNode = function(data)
    {
        if (typeof this.registry[data.node] == 'undefined') {
            throw new Error('Unknown node "' + data.node + '"')
        }

        var node = new this.registry[data.node](this, data);
        node.render();

        this.nodes.push(node);
    }

    /**
     * Add multiple wires.
     *
     * @param   array       wires               Array of wires.
     */
    diagram.prototype.addWires = function(wires)
    {
        wires.forEach(function(wire) {
            this.addWire(wire);
        }, this);
    }

    /**
     * Add a single wire to diagram.
     *
     * @param   object      wire                Wire to add.
     */
    diagram.prototype.addWire = function(wire)
    {
        this.wire.addWire(wire.source, wire.target);
    }

    /**
     * Remove node of the specified ID.
     *
     * @param   string      id                  ID of node to remove.
     */
    diagram.prototype.removeNode = function(id)
    {
        this.nodes = this.nodes.filter(function(node) {
            var ret = true;

            if (node.getId() == id) {
                node.destroy();

                ret = false;
            }

            return ret;
        });
    }

    /**
     * Remove multiple nodes.
     *
     * @param   array       ids                 Array of IDs of nodes to remove.
     */
    diagram.prototype.removeNodes = function(ids)
    {
        ids.forEach(function(id) {
            this.removeNode(id);
        }, this);
    }

    /**
     * Remove all nodes from diagram.
     */
    diagram.prototype.removeAllNodes = function()
    {
        this.nodes = this.nodes.filter(function(node) {
            node.destroy();

            return false;
        });
    }

    flowdesigner.diagram = diagram;
})(flowdesigner);
<|endoftext|>


<commit_before>/**
 *
 * diglett.js v0.0.7
 *
 * by bubkoo@163.com
 *
 * MIT license
 *
 */
;
(function (global) {

    'use strict';

    function Template(options) {
        this.options = options;

        var openTag = this.options.openTag;
        var closeTag = this.options.closeTag;
        //
        this.rEachStart = new RegExp(openTag + '\\s*[#@]each\\s+(.*)' + closeTag, 'igm');
        this.rEachEnd = new RegExp(openTag + '\\s*\\/each\\s*' + closeTag, 'igm');
        this.rIfStart = new RegExp(openTag + '\\s*[#@]if\\s+(.*?)\\s*' + closeTag, 'igm');
        this.rIfEnd = new RegExp(openTag + '\\s*\\/if\\s*' + closeTag, 'igm');
        this.rElse = new RegExp(openTag + '\\s*[#@]else\\s*' + closeTag, 'igm');
        this.rElseIf = new RegExp(openTag + '\\s*[#@]else\\s*if\\s+(.*?)\\s*' + closeTag, 'igm');
        this.rInterpolate = new RegExp(openTag + '\\s*((?!\\/|#|@|\\/\\/|!--)[\\s\\S]+?)\\s*' + closeTag, 'igm');
        this.rComment = new RegExp(openTag + '!--[\\s\\S]*--' + closeTag, 'igm');
        this.rInline = new RegExp(openTag + '\\s*\\/\\/(.*)\\s*' + closeTag, 'igm');
        this.rInclude = new RegExp(openTag + '\\s*[#@]include\\s*(\\S*)\\s*(\\S*)\\s*' + closeTag, 'igm');

        var that = this;

        Template.prototype.method['include'] = function (tpl, data) {
            var useCache = that.options.cache,
                cached;
            if (useCache) {
                if (cached = Template.cache[tpl]) {
                    return cached.render(data);
                }
            }
            cached = that.parse(tpl);
            if (useCache) {
                Template.cache[tpl] = cached;
            }
            return cached.render(data);
        };
    }

    // cache the compiled template
    Template.cache = {};

    Template.prototype = {
        constructor: Template,

        method: {
            each: function (data, callback) {
                var i,
                    l,
                    counter = 0,
                    even = false,
                    odd = false,
                    first = false,
                    last = false,
                    isArray = Array.isArray || function (obj) {
                        return '[object Array]' === Object.prototype.toString.call(obj);
                    },
                    setFlag = function (index, len) {
                        if ((index + 1) % 2 === 0) {
                            even = true;
                            odd = false;
                        } else {
                            even = false;
                            odd = true;
                        }
                        index === 0 && (first = true);
                        index === (len - 1) && (last = true);
                    };
                if (isArray(data)) {
                    for (i = 0, l = data.length; i < l; i++) {
                        setFlag(i, l);
                        callback.call(data, data[i], i, even, odd, first, last);
                    }
                } else {
                    for (i in data) {
                        setFlag(counter, counter);
                        if (data.hasOwnProperty(i)) {
                            callback.call(data, data[i], i, even, odd, first, last);
                        }
                        counter++;
                    }
                }
            },
            throw: _throw
        },

        filter: {
            // escape html
            'html': function (content) {
                var escapeMap = {
                    '<': '<',
                    '>': '>',
                    '"': '"',
                    '\'': ''',
                    '&': '&'
                };
                return ('' + content).replace(/&(?![\w#]+;)|[<>"']/g, function (s) {
                    s = escapeMap[s];
                    return s || '&';
                });
            },

            'lowercase': function (value) {
                return ('' + value).toLowerCase();
            },

            'uppercase': function (value) {
                return ('' + value).toUpperCase();
            }
        },

        include: function () {
        },

        _unshell: function (source) {
            var that = this,
                variables = [],
                declare,
                trim = function (str) {
                    str = str.replace(/^\s+/g, '');
                    for (var i = str.length - 1; i >= 0; i--) {
                        if (/\S/.test(str.charAt(i))) {
                            str = str.substring(0, i + 1);
                            break;
                        }
                    }
                    return str;
                },
                indexOf = function (array, item) {
                    if (Array.prototype.indexOf) {
                        return Array.prototype.indexOf.call(array, item);
                    }

                    var i,
                        len;

                    for (i = 0, len = array.length; i < len; i++) {
                        if (array[i] === item) {
                            return i;
                        }
                    }

                    return -1;
                },
                addVarible = function (variable) {
                    if (variable && indexOf(variables, variable) === -1) {
                        variables.push(variable);
                    }
                },
                variableAnalyze = function (input, exp) {
                    var match = exp.match(/[A-Za-z_$][A-Za-z0-9_$]+/igm),
                        variable;
                    if (match) {
                        while (variable = match.shift()) {
                            addVarible(variable);
                        }
                    }
                    // contains operator
                    if (/[\+\-\*\/%!\?\^&~<>=,\(\)\[\]]/.test(exp)) {
                        exp = '(' + exp + ')';
                    }
                    return exp;
                },
                handleFilter = function (value, filterStr) {
                    if (filterStr) {
                        filterStr = trim(filterStr);
                    }
                    if (filterStr) {
                        var filterGroups = filterStr.split(/\s*\|\s*/g),
                            filterGroup,
                            filter,
                            buffer,
                            args,
                            arg;
                        while (filterGroup = filterGroups.shift()) {
                            filterGroup = filterGroup.replace(/(['"]{1}?)([\s\S]*?)\1/g, function (input, quote, param) {
                                return param.replace(/:/g, '\u00A4').replace(/\|/g, '\u00AA');
                            });
                            args = filterGroup.split(/\s*:\s*/g);
                            filter = args.shift();

                            buffer = value;
                            while (arg = args.shift()) {
                                buffer += ',"' + arg
                                    .replace(/\u00A4/g, ':')
                                    .replace(/\u00AA/g, '|')
                                    .replace(/'/g, "\'")
                                    .replace(/\"/g, '"') + '"';
                            }
                            value = '__filter["' + filter + '"].call(this,' + buffer + ')';
                        }
                    }
                    return value;
                };

            source = source
                // each expression
                .replace(this.rEachStart, function (input, expression) {
                    var index = expression.indexOf(' '),
                        key = '$index',
                        value = '$value',
                        data,
                        options;
                    if (index > 0) {
                        data = expression.substr(0, index);
                        options = expression.substr(index + 1);

                        // add variables
                        variableAnalyze(input, data);

                        // analyze options
                        options = trim(options);
                        if (options) {
                            options = options.replace(/as\s+([A-Za-z_$][A-Za-z0-9_$]+)(\s+[A-Za-z_$][A-Za-z0-9_$]+)?/ig,
                                function (input, v, k) {
                                    v && (v = trim(v));
                                    v && (value = v);
                                    k && (k = trim(k));
                                    k && (key = k);
                                    return '';
                                });
                        }
                        if (options) {
                            options = trim(options);
                        }
                        // analyze filters
                        if (options) {
                            if (options.charAt(0) == '|') {
                                options = options.substr(1);
                            }
                            data = handleFilter(data, options);
                        }
                    } else {
                        data = variableAnalyze(input, expression);
                    }
                    return '<% __method["each"](' + data + ', function(' + value + ', ' + key + ',$even,$odd,$first,$last){ %>';
                })
                .replace(this.rEachEnd, '<% }); %>')

                // if expression
                .replace(this.rIfStart, function (input, condition) {
                    variableAnalyze(input, condition);
                    return '<% if(' + condition + ') { %>';
                })

                // else expression
                .replace(this.rElse, function () {
                    return '<% } else { %>';
                })

                // else if expression
                .replace(this.rElseIf, function (input, condition) {
                    variableAnalyze(input, condition);
                    return '<% } else if(' + condition + ') { %>';
                })

                .replace(this.rIfEnd, '<% } %>')

                // interpolate
                .replace(this.rInterpolate, function (input, interpolate) {
                    interpolate = trim(interpolate);
                    var index = interpolate.indexOf('|'),
                        filterStr,
                        content;

                    if (index > 0) {
                        content = interpolate.substr(0, index);
                        filterStr = interpolate.substr(index + 1);
                        content = variableAnalyze(input, content);
                        content = handleFilter(content, filterStr);
                    } else {
                        content = variableAnalyze(input, interpolate);
                    }
                    return '<%=' + content + '%>';
                })

                .replace(this.rInclude, function (input, tpl, data) {
                    // get variable
                    if (tpl.match(/^(['"])#[\w:\-\.]+\1$/igm)) {
                        tpl = tpl.replace(/['"]/g, '');
                    } else {
                        addVarible(tpl);
                    }
                    addVarible(data);

                    // remove custom grammar
                    return '<%= __method["include"](' + tpl + ', ' + data + '); %>';
                })

                // clean up comments
                .replace(this.rComment, '')

                // inline
                .replace(this.rInline, function (input, text) {
                    return that.options.openTag + text + that.options.closeTag;
                });

            // pre-declare variables
            var i,
                len = variables.length;
            if (len > 0) {
                declare = 'var ';
                for (i = 0; i < len; i++) {
                    declare += variables[i] + '=__.' + variables[i] + ',';
                }
            }
            if (declare) {
                source = '<%' + declare.substr(0, declare.length - 1) + '; %>' + source;
            }

            // if debug, then wrapped with try-catch
            if (this.options.debug !== true) {
                source = '<% try { %>'
                    + source
                    + '<% } catch(e) { __method.throw("diglett render exception: " + e.message); } %>';
            }

            return source;
        },

        _toNative: function (source) {
            var uglify = this.options.uglify,
                buffer = "'use strict';"; // use strict mode

            buffer += "__ = __ || {};";
            buffer += "__filter = __filter || {};";
            buffer += "__method = __method || {};";
            buffer += "var __out='';__out+='";

            buffer += source
                .replace(/\\/g, '\\\\')
                .replace(/<%=(.+?)%>/g, "';__out+=$1;__out+='")
                .split('<%').join("';")
                .split('%>').join("__out+='");
            if (uglify === true) {
                buffer = buffer
                    .replace(/[\r\t\n]+/g, '')
                    .replace(/__out\+='\s*';/g, '')
                    .replace(/>\s+</g, '><')
                    .replace(/(__out\+=')\s+</g, '$1<')
                    .replace(/>\s+'/g, '>\'')
                    .replace(/>\s+\b/g, '> ')
                    .replace(/\b\s+</g, ' <');
            } else {
                buffer = buffer
                    .replace(/[\r\n]+/g, ' ')
                    .replace(/__out\+='';/g, '')
            }

            return buffer += "';return __out;";
        },

        parse: function (source) {

            var that = this,
                useCache = that.options.cache,
                cached;
            if (useCache) {
                if (cached = Template.cache[source]) {
                    return cached;
                }
            }

            // source is element's ID, like this #nodeId
            var regId = /^\s*#([\w:\-\.]+)\s*$/igm;
            if (source.match(regId)) {
                source.replace(regId, function (input, id) {
                    var doc = document,
                        ele = doc && doc.getElementById(id);
                    source = ele ? (ele.value || ele.innerHTML) : input;
                });
            }

            // firstly, remove the html comment
            if (that.options.uglify === true) {
                source = source.replace(/<!--.*?-->/g, '');
            }

            source = that._unshell(source);
            source = that._toNative(source);

            that._render = new Function('__, __method, __filter', source);
            that.render = function (data, options) {
                options = options || {};
                var filter = merge(options.filter, that.filter),
                    method = merge(options.method, that.method);
                return that._render.call(this, data, method, filter);
            };

            if (useCache) {
                Template.cache[source] = that;
            }

            return that;
        }
    };

    Template.registerFilter = function (filterName, fn, overwrite) {
        var filters = Template.prototype.filter;
        if (filters.hasOwnProperty(filterName)) {
            if (overwrite === true) {
                return filters[filterName] = fn;
            } else {
                return false;
            }
        }
        return filters[filterName] = fn;
    };

    Template.removeFilter = function (filterName) {
        var filters = Template.prototype.filter;
        if (filters.hasOwnProperty(filterName)) {
            return delete filters[filterName];
        }
    };

    // create a local object, to be exported or attached to the global object later
    var diglett = function (source, data) {
        // call `compile` or `render` with default options
        if (data) {
            return diglett.render.call(diglett, source, data, diglett.options);
        } else {
            return diglett.compile.call(diglett, source, diglett.options);
        }
    };

    // current version
    diglett.version = '0.0.7';

    diglett.options = {
        'openTag': '{{',
        'closeTag': '}}',
        'cache': true, // cache the compiled template
        'debug': true,
        'uglify': true // compress result
    };

    diglett.compile = function (source, options) {
        options = fixOptions(options);

        var doParse = function () {
            var engine,
                cached;
            if (options.cache !== false) {
                if (cached = Template.cache[source]) {
                    engine = cached;
                }
            }
            engine = engine || new Template(options).parse(source);

            return engine;
        };

        if (options.debug) {
            return doParse();
        } else {
            try {
                return doParse();
            }
            catch (e) {
                _throw('diglett compile exception: ' + e.message);

                return {
                    // noop
                    render: function () {
                    }
                }
            }
        }
    };

    diglett.render = function (source, data, options) {
        return this.compile(source, options).render(data, options);
    };

    diglett.registerFilter = Template.registerFilter;

    diglett.removeFilter = Template.removeFilter;

    function merge(target, source) {
        var key;
        target || (target = {});
        if (source) {
            for (key in source) {
                if (source.hasOwnProperty(key)) {
                    target[key] = source[key];
                }
            }
        }
        return target;
    }

    function fixOptions(options) {
        var ret = {};
        merge(ret, diglett.options);
        merge(ret, options);
        return ret;
    }

    function _throw(error) {
        if (global.console) {
            if (console.warn) {
                console.warn(error);
            }
            else if (console.log) {
                console.log(error);
            }
        }
        throw (error);
    }

    if (typeof define === 'function') {
        // RequireJS && SeaJS
        define(function () {
            return diglett;
        });
    } else if (typeof exports !== 'undefined') {
        if (typeof module !== 'undefined' && module.exports) {
            // NodeJS
            module.exports = diglett;
        }
    } else {
        global.diglett = diglett;
    }

})(this);<commit_msg>bugfix: {{#each ... }}<commit_after>/**
 *
 * diglett.js v0.0.7
 *
 * by bubkoo@163.com
 *
 * MIT license
 *
 */
;
(function (global) {

    'use strict';

    function Template(options) {
        this.options = options;

        var openTag = this.options.openTag;
        var closeTag = this.options.closeTag;
        //
        this.rEachStart = new RegExp(openTag + '\\s*[#@]each\\s+(.*)' + closeTag, 'igm');
        this.rEachEnd = new RegExp(openTag + '\\s*\\/each\\s*' + closeTag, 'igm');
        this.rIfStart = new RegExp(openTag + '\\s*[#@]if\\s+(.*?)\\s*' + closeTag, 'igm');
        this.rIfEnd = new RegExp(openTag + '\\s*\\/if\\s*' + closeTag, 'igm');
        this.rElse = new RegExp(openTag + '\\s*[#@]else\\s*' + closeTag, 'igm');
        this.rElseIf = new RegExp(openTag + '\\s*[#@]else\\s*if\\s+(.*?)\\s*' + closeTag, 'igm');
        this.rInterpolate = new RegExp(openTag + '\\s*((?!\\/|#|@|\\/\\/|!--)[\\s\\S]+?)\\s*' + closeTag, 'igm');
        this.rComment = new RegExp(openTag + '!--[\\s\\S]*--' + closeTag, 'igm');
        this.rInline = new RegExp(openTag + '\\s*\\/\\/(.*)\\s*' + closeTag, 'igm');
        this.rInclude = new RegExp(openTag + '\\s*[#@]include\\s*(\\S*)\\s*(\\S*)\\s*' + closeTag, 'igm');

        var that = this;

        Template.prototype.method['include'] = function (tpl, data) {
            var useCache = that.options.cache,
                cached;
            if (useCache) {
                if (cached = Template.cache[tpl]) {
                    return cached.render(data);
                }
            }
            cached = that.parse(tpl);
            if (useCache) {
                Template.cache[tpl] = cached;
            }
            return cached.render(data);
        };
    }

    // cache the compiled template
    Template.cache = {};

    Template.prototype = {
        constructor: Template,

        method: {
            each: function (data, callback) {
                var i,
                    l,
                    counter = 0,
                    even = false,
                    odd = false,
                    first = false,
                    last = false,
                    isArray = Array.isArray || function (obj) {
                        return '[object Array]' === Object.prototype.toString.call(obj);
                    },
                    getObjLength = function (obj) {
                        var c = 0;
                        for (var j in obj) {
                            if (obj.hasOwnProperty(j)) {
                                c++;
                            }
                        }
                        return c;
                    },
                    setFlag = function (index, len) {
                        if ((index + 1) % 2 === 0) {
                            even = true;
                            odd = false;
                        } else {
                            even = false;
                            odd = true;
                        }
                        index === 0 && (first = true);
                        index === (len - 1) && (last = true);
                    };
                if (isArray(data)) {
                    for (i = 0, l = data.length; i < l; i++) {
                        setFlag(i, l);
                        callback.call(data, data[i], i, even, odd, first, last);
                    }
                } else {
                    l = getObjLength(data);
                    for (i in data) {
                        setFlag(counter, l);
                        if (data.hasOwnProperty(i)) {
                            callback.call(data, data[i], i, even, odd, first, last);
                        }
                        counter++;
                    }
                }
            },
            throw: _throw
        },

        filter: {
            // escape html
            'html': function (content) {
                var escapeMap = {
                    '<': '<',
                    '>': '>',
                    '"': '"',
                    '\'': ''',
                    '&': '&'
                };
                return ('' + content).replace(/&(?![\w#]+;)|[<>"']/g, function (s) {
                    s = escapeMap[s];
                    return s || '&';
                });
            },

            'lowercase': function (value) {
                return ('' + value).toLowerCase();
            },

            'uppercase': function (value) {
                return ('' + value).toUpperCase();
            }
        },

        include: function () {
        },

        _unshell: function (source) {
            var that = this,
                variables = [],
                declare,
                trim = function (str) {
                    str = str.replace(/^\s+/g, '');
                    for (var i = str.length - 1; i >= 0; i--) {
                        if (/\S/.test(str.charAt(i))) {
                            str = str.substring(0, i + 1);
                            break;
                        }
                    }
                    return str;
                },
                indexOf = function (array, item) {
                    if (Array.prototype.indexOf) {
                        return Array.prototype.indexOf.call(array, item);
                    }

                    var i,
                        len;

                    for (i = 0, len = array.length; i < len; i++) {
                        if (array[i] === item) {
                            return i;
                        }
                    }

                    return -1;
                },
                addVarible = function (variable) {
                    if (variable && indexOf(variables, variable) === -1) {
                        variables.push(variable);
                    }
                },
                variableAnalyze = function (input, exp) {
                    var match = exp.match(/[A-Za-z_$][A-Za-z0-9_$]+/igm),
                        variable;
                    if (match) {
                        while (variable = match.shift()) {
                            addVarible(variable);
                        }
                    }
                    // contains operator
                    if (/[\+\-\*\/%!\?\^&~<>=,\(\)\[\]]/.test(exp)) {
                        exp = '(' + exp + ')';
                    }
                    return exp;
                },
                handleFilter = function (value, filterStr) {
                    if (filterStr) {
                        filterStr = trim(filterStr);
                    }
                    if (filterStr) {
                        var filterGroups = filterStr.split(/\s*\|\s*/g),
                            filterGroup,
                            filter,
                            buffer,
                            args,
                            arg;
                        while (filterGroup = filterGroups.shift()) {
                            filterGroup = filterGroup.replace(/(['"]{1}?)([\s\S]*?)\1/g, function (input, quote, param) {
                                return param.replace(/:/g, '\u00A4').replace(/\|/g, '\u00AA');
                            });
                            args = filterGroup.split(/\s*:\s*/g);
                            filter = args.shift();

                            buffer = value;
                            while (arg = args.shift()) {
                                buffer += ',"' + arg
                                    .replace(/\u00A4/g, ':')
                                    .replace(/\u00AA/g, '|')
                                    .replace(/'/g, "\'")
                                    .replace(/\"/g, '"') + '"';
                            }
                            value = '__filter["' + filter + '"].call(this,' + buffer + ')';
                        }
                    }
                    return value;
                };

            source = source
                // each expression
                .replace(this.rEachStart, function (input, expression) {
                    var index = expression.indexOf(' '),
                        key = '$index',
                        value = '$value',
                        data,
                        options;
                    if (index > 0) {
                        data = expression.substr(0, index);
                        options = expression.substr(index + 1);

                        // add variables
                        variableAnalyze(input, data);

                        // analyze options
                        options = trim(options);
                        if (options) {
                            options = options.replace(/as\s+([A-Za-z_$][A-Za-z0-9_$]+)(\s+[A-Za-z_$][A-Za-z0-9_$]+)?/ig,
                                function (input, v, k) {
                                    v && (v = trim(v));
                                    v && (value = v);
                                    k && (k = trim(k));
                                    k && (key = k);
                                    return '';
                                });
                        }
                        if (options) {
                            options = trim(options);
                        }
                        // analyze filters
                        if (options) {
                            if (options.charAt(0) == '|') {
                                options = options.substr(1);
                            }
                            data = handleFilter(data, options);
                        }
                    } else {
                        data = variableAnalyze(input, expression);
                    }
                    return '<% __method["each"](' + data + ', function(' + value + ', ' + key + ',$even,$odd,$first,$last){ %>';
                })
                .replace(this.rEachEnd, '<% }); %>')

                // if expression
                .replace(this.rIfStart, function (input, condition) {
                    variableAnalyze(input, condition);
                    return '<% if(' + condition + ') { %>';
                })

                // else expression
                .replace(this.rElse, function () {
                    return '<% } else { %>';
                })

                // else if expression
                .replace(this.rElseIf, function (input, condition) {
                    variableAnalyze(input, condition);
                    return '<% } else if(' + condition + ') { %>';
                })

                .replace(this.rIfEnd, '<% } %>')

                // interpolate
                .replace(this.rInterpolate, function (input, interpolate) {
                    interpolate = trim(interpolate);
                    var index = interpolate.indexOf('|'),
                        filterStr,
                        content;

                    if (index > 0) {
                        content = interpolate.substr(0, index);
                        filterStr = interpolate.substr(index + 1);
                        content = variableAnalyze(input, content);
                        content = handleFilter(content, filterStr);
                    } else {
                        content = variableAnalyze(input, interpolate);
                    }
                    return '<%=' + content + '%>';
                })

                .replace(this.rInclude, function (input, tpl, data) {
                    // get variable
                    if (tpl.match(/^(['"])#[\w:\-\.]+\1$/igm)) {
                        tpl = tpl.replace(/['"]/g, '');
                    } else {
                        addVarible(tpl);
                    }
                    addVarible(data);

                    // remove custom grammar
                    return '<%= __method["include"](' + tpl + ', ' + data + '); %>';
                })

                // clean up comments
                .replace(this.rComment, '')

                // inline
                .replace(this.rInline, function (input, text) {
                    return that.options.openTag + text + that.options.closeTag;
                });

            // pre-declare variables
            var i,
                len = variables.length;
            if (len > 0) {
                declare = 'var ';
                for (i = 0; i < len; i++) {
                    declare += variables[i] + '=__.' + variables[i] + ',';
                }
            }
            if (declare) {
                source = '<%' + declare.substr(0, declare.length - 1) + '; %>' + source;
            }

            // if debug, then wrapped with try-catch
            if (this.options.debug !== true) {
                source = '<% try { %>'
                    + source
                    + '<% } catch(e) { __method.throw("diglett render exception: " + e.message); } %>';
            }

            return source;
        },

        _toNative: function (source) {
            var uglify = this.options.uglify,
                buffer = "'use strict';"; // use strict mode

            buffer += "__ = __ || {};";
            buffer += "__filter = __filter || {};";
            buffer += "__method = __method || {};";
            buffer += "var __out='';__out+='";

            buffer += source
                .replace(/\\/g, '\\\\')
                .replace(/<%=(.+?)%>/g, "';__out+=$1;__out+='")
                .split('<%').join("';")
                .split('%>').join("__out+='");
            if (uglify === true) {
                buffer = buffer
                    .replace(/[\r\t\n]+/g, '')
                    .replace(/__out\+='\s*';/g, '')
                    .replace(/>\s+</g, '><')
                    .replace(/(__out\+=')\s+</g, '$1<')
                    .replace(/>\s+'/g, '>\'')
                    .replace(/>\s+\b/g, '> ')
                    .replace(/\b\s+</g, ' <');
            } else {
                buffer = buffer
                    .replace(/[\r\n]+/g, ' ')
                    .replace(/__out\+='';/g, '')
            }

            return buffer += "';return __out;";
        },

        parse: function (source) {

            var that = this,
                useCache = that.options.cache,
                cached;
            if (useCache) {
                if (cached = Template.cache[source]) {
                    return cached;
                }
            }

            // source is element's ID, like this #nodeId
            var regId = /^\s*#([\w:\-\.]+)\s*$/igm;
            if (source.match(regId)) {
                source.replace(regId, function (input, id) {
                    var doc = document,
                        ele = doc && doc.getElementById(id);
                    source = ele ? (ele.value || ele.innerHTML) : input;
                });
            }

            // firstly, remove the html comment
            if (that.options.uglify === true) {
                source = source.replace(/<!--.*?-->/g, '');
            }

            source = that._unshell(source);
            source = that._toNative(source);

            that._render = new Function('__, __method, __filter', source);
            that.render = function (data, options) {
                options = options || {};
                var filter = merge(options.filter, that.filter),
                    method = merge(options.method, that.method);
                return that._render.call(this, data, method, filter);
            };

            if (useCache) {
                Template.cache[source] = that;
            }

            return that;
        }
    };

    Template.registerFilter = function (filterName, fn, overwrite) {
        var filters = Template.prototype.filter;
        if (filters.hasOwnProperty(filterName)) {
            if (overwrite === true) {
                return filters[filterName] = fn;
            } else {
                return false;
            }
        }
        return filters[filterName] = fn;
    };

    Template.removeFilter = function (filterName) {
        var filters = Template.prototype.filter;
        if (filters.hasOwnProperty(filterName)) {
            return delete filters[filterName];
        }
    };

    // create a local object, to be exported or attached to the global object later
    var diglett = function (source, data) {
        // call `compile` or `render` with default options
        if (data) {
            return diglett.render.call(diglett, source, data, diglett.options);
        } else {
            return diglett.compile.call(diglett, source, diglett.options);
        }
    };

    // current version
    diglett.version = '0.0.7';

    diglett.options = {
        'openTag': '{{',
        'closeTag': '}}',
        'cache': true, // cache the compiled template
        'debug': true,
        'uglify': true // compress result
    };

    diglett.compile = function (source, options) {
        options = fixOptions(options);

        var doParse = function () {
            var engine,
                cached;
            if (options.cache !== false) {
                if (cached = Template.cache[source]) {
                    engine = cached;
                }
            }
            engine = engine || new Template(options).parse(source);

            return engine;
        };

        if (options.debug) {
            return doParse();
        } else {
            try {
                return doParse();
            }
            catch (e) {
                _throw('diglett compile exception: ' + e.message);

                return {
                    // noop
                    render: function () {
                    }
                }
            }
        }
    };

    diglett.render = function (source, data, options) {
        return this.compile(source, options).render(data, options);
    };

    diglett.registerFilter = Template.registerFilter;

    diglett.removeFilter = Template.removeFilter;

    function merge(target, source) {
        var key;
        target || (target = {});
        if (source) {
            for (key in source) {
                if (source.hasOwnProperty(key)) {
                    target[key] = source[key];
                }
            }
        }
        return target;
    }

    function fixOptions(options) {
        var ret = {};
        merge(ret, diglett.options);
        merge(ret, options);
        return ret;
    }

    function _throw(error) {
        if (global.console) {
            if (console.warn) {
                console.warn(error);
            }
            else if (console.log) {
                console.log(error);
            }
        }
        throw (error);
    }

    if (typeof define === 'function') {
        // RequireJS && SeaJS
        define(function () {
            return diglett;
        });
    } else if (typeof exports !== 'undefined') {
        if (typeof module !== 'undefined' && module.exports) {
            // NodeJS
            module.exports = diglett;
        }
    } else {
        global.diglett = diglett;
    }

})(this);<|endoftext|>


<commit_before>const debug = require('debug')('loki:chrome:local');
const chromeLauncher = require('lighthouse/chrome-launcher/chrome-launcher');
const CDP = require('chrome-remote-interface');
const createChromeTarget = require('./create-chrome-target');

function createChromeAppTarget({
  baseUrl = 'http://localhost:6006',
  chromeFlags = ['--headless', '--disable-gpu', '--hide-scrollbars'],
}) {
  let instance;

  async function start(options = {}) {
    const launchOptions = Object.assign(
      {
        chromeFlags,
        logLevel: 'silent',
      },
      options
    );
    debug(
      `Launching chrome with flags "${launchOptions.chromeFlags.join(' ')}"`
    );
    instance = await chromeLauncher.launch(launchOptions);
  }

  async function stop() {
    if (instance) {
      debug('Killing chrome');
      await instance.kill();
    } else {
      debug('No chrome instance to kill');
    }
  }

  async function createNewDebuggerInstance() {
    const port = instance.port;
    debug(`Launching new tab with debugger at port ${port}`);
    const target = await CDP.New({ port });
    debug(`Launched with target id ${target.id}`);
    const client = await CDP({ port, target });

    client.close = () => {
      debug('New closing tab');
      CDP.Close({ port, id: target.id });
    };

    return client;
  }

  return createChromeTarget(start, stop, createNewDebuggerInstance, baseUrl);
}

module.exports = createChromeAppTarget;
<commit_msg>Fix some chrome output when stopping app that broke listr output<commit_after>const debug = require('debug')('loki:chrome:local');
const chromeLauncher = require('lighthouse/chrome-launcher/chrome-launcher');
const CDP = require('chrome-remote-interface');
const createChromeTarget = require('./create-chrome-target');

function createChromeAppTarget({
  baseUrl = 'http://localhost:6006',
  chromeFlags = ['--headless', '--disable-gpu', '--hide-scrollbars'],
}) {
  let instance;

  async function start(options = {}) {
    const launchOptions = Object.assign(
      {
        chromeFlags,
        logLevel: 'silent',
      },
      options
    );
    debug(
      `Launching chrome with flags "${launchOptions.chromeFlags.join(' ')}"`
    );
    instance = await chromeLauncher.launch(launchOptions);
  }

  async function stop() {
    if (instance) {
      debug('Killing chrome');
      // Do this woodoo to avoid some output that borks listr
      setTimeout(async () => {
        try {
          await instance.kill();
        } catch (err) {
          debug('Failed killing chrome', err);
        }
      }, 100);
    } else {
      debug('No chrome instance to kill');
    }
  }

  async function createNewDebuggerInstance() {
    const port = instance.port;
    debug(`Launching new tab with debugger at port ${port}`);
    const target = await CDP.New({ port });
    debug(`Launched with target id ${target.id}`);
    const client = await CDP({ port, target });

    client.close = () => {
      debug('New closing tab');
      CDP.Close({ port, id: target.id });
    };

    return client;
  }

  return createChromeTarget(start, stop, createNewDebuggerInstance, baseUrl);
}

module.exports = createChromeAppTarget;
<|endoftext|>


<commit_before>import React from 'react';
import PropTypes from 'proptypes';
import graphql from 'graphql';
import Link from '../components/Link';

class TagRoute extends React.Component {
  static propTypes = {
    data: PropTypes.object,
    pathContext: PropTypes.object
  }

  render() {
    const posts = this.props.data.allMarkdownRemark.edges;
    const postLinks = posts.map(post => {
      return (

          <Link to={post.node.fields.slug}>
            {post.node.frontmatter.title}
          </Link>

      );
    });

    return (

          {this.props.data.allMarkdownRemark.totalCount} posts tagged with “{this.props.pathContext.tag}”

          {postLinks}

          <Link to="/tags/">Browse all tags</Link>

    );
  }
}

export default TagRoute;

export const pageQuery = graphql`
  query TagPage($tag: String) {
    allMarkdownRemark(
      limit: 1000
      sort: { fields: [frontmatter___date], order: DESC }
      filter: { frontmatter: { tags: { in: [$tag] }, draft: { ne: true } } }
    ) {
      totalCount
      edges {
        node {
          fields {
            slug
          }
          frontmatter {
            title
          }
        }
      }
    }
  }
`;
<commit_msg>Fix links in tags page<commit_after>import React from 'react';
import PropTypes from 'proptypes';
import graphql from 'graphql';
import Link from '../components/Link';

class TagRoute extends React.Component {
  static propTypes = {
    data: PropTypes.object,
    pathContext: PropTypes.object
  }

  render() {
    const posts = this.props.data.allMarkdownRemark.edges;
    const postLinks = posts.map(post => {
      return (

          <Link to={post.node.fields.path}>
            {post.node.frontmatter.title}
          </Link>

      );
    });

    return (

          {this.props.data.allMarkdownRemark.totalCount} posts tagged with “{this.props.pathContext.tag}”

          {postLinks}

          <Link to="/tags/">Browse all tags</Link>

    );
  }
}

export default TagRoute;

export const pageQuery = graphql`
  query TagPage($tag: String) {
    allMarkdownRemark(
      limit: 1000
      sort: { fields: [frontmatter___date], order: DESC }
      filter: { frontmatter: { tags: { in: [$tag] }, draft: { ne: true } } }
    ) {
      totalCount
      edges {
        node {
          fields {
            path
          }
          frontmatter {
            title
          }
        }
      }
    }
  }
`;
<|endoftext|>


<commit_before>(function (window, document, undefined) {
  'use strict';

  // Device profiles
  var profiles = {
    tablet: 768,
    smartphone: 375
  };

  // Default viewport width
  var baseWidth = 980;

  // Default options
  var defaults = {
    html: '',
    width: baseWidth,
    profile: ''
  };

  // Constructor
  var Dyframe = function (element, options) {
    this.element = element;
    this.wrapper = document.createElement('div');
    this.viewport = document.createElement('iframe');
    setStyles(this.wrapper, {
      position: 'relative',
      display: 'block',
      height: 0,
      padding: 0,
      overflow: 'hidden'
    });
    setStyles(this.viewport, {
      position: 'absolute',
      top: 0,
      left: 0,
      bottom: 0,
      height: '100%',
      width: '100%',
      border: 0,
      webkitTransformOrigin: '0 0',
      msTransformOrigin: '0 0',
      transformOrigin: '0 0'
    });
    this.wrapper.appendChild(this.viewport);
    this.element.appendChild(this.wrapper);
    this.render(options || {});
  };

  // Render viewport
  Dyframe.prototype.render = function (options) {
    if (typeof options === 'object') {
      this.updateOptions(options);
    }
    var innerSize = getInnerSize(this.element);
    this.width = innerSize.width;
    this.height = innerSize.height;
    this.wrapper.style.paddingBottom = this.height + 'px';
    this.scale();
    this.viewport.contentWindow.document.open();
    this.viewport.contentWindow.document.write(this.options.html);
    this.viewport.contentWindow.document.close();
  };

  // Init or override options
  Dyframe.prototype.updateOptions = function (options) {
    if (!this.options) {
      this.options = mergeObjects({}, defaults, options);
      return;
    }
    mergeObjects(this.options, options);
  };

  // Scale preview accroding to options
  Dyframe.prototype.scale = function () {
    var scale = this.width / this.getPreviewWidth();
    setStyles(this.viewport, {
      width: (100 / scale) + '%',
      height: (100 / scale) + '%',
      webkitTransform: 'scale(' + scale + ')',
      msTransform: 'scale(' + scale + ')',
      transform: 'scale(' + scale + ')'
    });
  };

  // Get preview HTML width
  Dyframe.prototype.getPreviewWidth = function () {
    if (!this.options.profile || !profiles[this.options.profile]) {
      return this.options.width;
    }
    var viewportData = this.getViewportData();
    var width = viewportData.width;
    if (!width) {
      return baseWidth;
    }
    if (width === 'device-width') {
      return profiles[this.options.profile];
    }
    return parseInt(width, 10);
  };

  // Get viewport content as object
  Dyframe.prototype.getViewportData = function () {
    var el = document.createElement('div');
    var viewportElement;
    var viewportContent;
    var viewportData = {};
    el.innerHTML = this.options.html;
    viewportElement = el.querySelector('meta[name="viewport"]');
    if (!viewportElement) {
      return viewportData;
    }
    viewportContent = viewportElement.getAttribute('content');
    if (!viewportContent) {
      return viewportData;
    }
    viewportContent.split(',').forEach(function (configSet) {
      var config = configSet.trim().split('=');
      if (!config[0] || !config[1]) {
        return;
      }
      viewportData[config[0].trim()] = config[1].trim();
    });
    return viewportData;
  };

  // Utility for merging objects
  var mergeObjects = function () {
    var merged = arguments[0];
    var i;
    var prop;
    for (i = 1; i < arguments.length; i++) {
      for (prop in arguments[i]) {
        if (arguments[i].hasOwnProperty(prop)) {
          merged[prop] = arguments[i][prop];
        }
      }
    }
    return merged;
  };

  // Utility for setting styles
  var setStyles = function (element, styles) {
    var prop;
    for (prop in styles) {
      element.style[prop] = styles[prop];
    }
  };

  // Get inner width/height of element
  var getInnerSize = function (element) {
    var style = window.getComputedStyle(element);
    var paddingTop = parseInt(style.getPropertyValue('padding-top'), 0);
    var paddingLeft = parseInt(style.getPropertyValue('padding-left'), 0);
    var paddingRight = parseInt(style.getPropertyValue('padding-right'), 0);
    var paddingBottom = parseInt(style.getPropertyValue('padding-bottom'), 0);
    var innerSize = {
      width: element.clientWidth - (paddingLeft + paddingRight),
      height: element.clientHeight - (paddingTop + paddingBottom)
    };
    return innerSize;
  };

  // Module interface
  if (typeof define === 'function' && define.amd) {
    define('dyframe', [], function () {
      return Dyframe;
    });
  }
  else if (typeof module === 'object' && module.exports) {
    module.exports = Dyframe;
  }
  else {
    window.Dyframe = Dyframe;
  }

}(window, document));
<commit_msg>Add class names to enable styling with css<commit_after>(function (window, document, undefined) {
  'use strict';

  // Device profiles
  var profiles = {
    tablet: 768,
    smartphone: 375
  };

  // Default viewport width
  var baseWidth = 980;

  // Prefix for class names
  var prefix = 'df-';

  // Default options
  var defaults = {
    html: '',
    width: baseWidth,
    profile: ''
  };

  // Constructor
  var Dyframe = function (element, options) {
    this.element = element;
    this.wrapper = document.createElement('div');
    this.viewport = document.createElement('iframe');
    addClass(this.element, prefix + 'element');
    setStyles(this.wrapper, {
      position: 'relative',
      display: 'block',
      height: 0,
      padding: 0,
      overflow: 'hidden'
    });
    setStyles(this.viewport, {
      position: 'absolute',
      top: 0,
      left: 0,
      bottom: 0,
      height: '100%',
      width: '100%',
      border: 0,
      webkitTransformOrigin: '0 0',
      msTransformOrigin: '0 0',
      transformOrigin: '0 0'
    });
    this.wrapper.appendChild(this.viewport);
    this.element.appendChild(this.wrapper);
    this.render(options || {});
  };

  // Render viewport
  Dyframe.prototype.render = function (options) {
    if (typeof options === 'object') {
      this.updateOptions(options);
    }
    this.updateClass();
    var innerSize = getInnerSize(this.element);
    this.width = innerSize.width;
    this.height = innerSize.height;
    this.wrapper.style.paddingBottom = this.height + 'px';
    this.scale();
    this.viewport.contentWindow.document.open();
    this.viewport.contentWindow.document.write(this.options.html);
    this.viewport.contentWindow.document.close();
  };

  // Init or override options
  Dyframe.prototype.updateOptions = function (options) {
    if (!this.options) {
      this.options = mergeObjects({}, defaults, options);
      return;
    }
    mergeObjects(this.options, options);
  };

  // Check if active profile is given
  Dyframe.prototype.hasActiveProfile = function () {
    return this.options.profile && profiles[this.options.profile];
  };

  // Update class name of dyframe.element
  Dyframe.prototype.updateClass = function () {
    removePrefixedClass(this.element, prefix + 'width-');
    removePrefixedClass(this.element, prefix + 'profile-');
    if (this.hasActiveProfile()) {
      addClass(this.element, prefix + 'profile-' + this.options.profile);
    }
    else {
      addClass(this.element, prefix + 'width-' + this.options.width);
    }
  };

  // Scale preview accroding to options
  Dyframe.prototype.scale = function () {
    var scale = this.width / this.getPreviewWidth();
    setStyles(this.viewport, {
      width: (100 / scale) + '%',
      height: (100 / scale) + '%',
      webkitTransform: 'scale(' + scale + ')',
      msTransform: 'scale(' + scale + ')',
      transform: 'scale(' + scale + ')'
    });
  };

  // Get preview HTML width
  Dyframe.prototype.getPreviewWidth = function () {
    if (!this.hasActiveProfile()) {
      return this.options.width;
    }
    var viewportData = this.getViewportData();
    var width = viewportData.width;
    if (!width) {
      return baseWidth;
    }
    if (width === 'device-width') {
      return profiles[this.options.profile];
    }
    return parseInt(width, 10);
  };

  // Get viewport content as object
  Dyframe.prototype.getViewportData = function () {
    var el = document.createElement('div');
    var viewportElement;
    var viewportContent;
    var viewportData = {};
    el.innerHTML = this.options.html;
    viewportElement = el.querySelector('meta[name="viewport"]');
    if (!viewportElement) {
      return viewportData;
    }
    viewportContent = viewportElement.getAttribute('content');
    if (!viewportContent) {
      return viewportData;
    }
    viewportContent.split(',').forEach(function (configSet) {
      var config = configSet.trim().split('=');
      if (!config[0] || !config[1]) {
        return;
      }
      viewportData[config[0].trim()] = config[1].trim();
    });
    return viewportData;
  };

  // Utility for merging objects
  var mergeObjects = function () {
    var merged = arguments[0];
    var i;
    var prop;
    for (i = 1; i < arguments.length; i++) {
      for (prop in arguments[i]) {
        if (arguments[i].hasOwnProperty(prop)) {
          merged[prop] = arguments[i][prop];
        }
      }
    }
    return merged;
  };

  // Utility for setting styles
  var setStyles = function (element, styles) {
    var prop;
    for (prop in styles) {
      element.style[prop] = styles[prop];
    }
  };

  // Utility for adding class
  var addClass = function (element, className) {
    if (element.classList) {
      element.classList.add(className);
    }
    else {
      element.className += ' ' + className;
    }
  };

  // Utility for removing prefixed classes (e.g. "df-profile-*")
  var removePrefixedClass = function (element, classPrefix) {
    var pattern = new RegExp('(^|\\s)' + classPrefix + '\\S+', 'g');
    element.className = element.className.replace(pattern, '');
  };

  // Get inner width/height of element
  var getInnerSize = function (element) {
    var style = window.getComputedStyle(element);
    var paddingTop = parseInt(style.getPropertyValue('padding-top'), 0);
    var paddingLeft = parseInt(style.getPropertyValue('padding-left'), 0);
    var paddingRight = parseInt(style.getPropertyValue('padding-right'), 0);
    var paddingBottom = parseInt(style.getPropertyValue('padding-bottom'), 0);
    var innerSize = {
      width: element.clientWidth - (paddingLeft + paddingRight),
      height: element.clientHeight - (paddingTop + paddingBottom)
    };
    return innerSize;
  };

  // Module interface
  if (typeof define === 'function' && define.amd) {
    define('dyframe', [], function () {
      return Dyframe;
    });
  }
  else if (typeof module === 'object' && module.exports) {
    module.exports = Dyframe;
  }
  else {
    window.Dyframe = Dyframe;
  }

}(window, document));
<|endoftext|>


<commit_before>import PropTypes from 'prop-types';
import React from 'react';

/**
 * The Topic Takeaway component
 */
const TopicTakeaway = ( page ) => {
	return (
	<div className={ `uikit-body uikit-grid` } >

{ page.heading }

{ page.firstcolumnheader }

						{ page.firstcolumncontent }

{ page.secondcolumnheader }

						{ page._body }

← { page.previousHeader }

   { page.previousText }

{ page.nextHeader }  →

{ page.nextText }

)};

TopicTakeaway.propTypes = {
	/**
	 * _body: (text)(7)
	 */
	_body: PropTypes.node.isRequired,
};

TopicTakeaway.defaultProps = {};

export default TopicTakeaway;
<commit_msg>clean up Grid and classes<commit_after>import PropTypes from 'prop-types';
import React from 'react';

/**
 * The Topic Takeaway component
 */
const TopicTakeaway = ( page ) => {
	return (
	<div className={ `uikit-body uikit-grid` } >

{ page.heading }

{ page.firstcolumnheader }

						{ page.firstcolumncontent }

{ page.secondcolumnheader }

						{ page._body }

← { page.previousHeader }

   { page.previousText }

{ page.nextHeader }  →

{ page.nextText }

)};

TopicTakeaway.propTypes = {
	/**
	 * _body: (text)(7)
	 */
	_body: PropTypes.node.isRequired,
};

TopicTakeaway.defaultProps = {};

export default TopicTakeaway;
<|endoftext|>