<commit_before>import { once } from '@ember/runloop';
import { get, set, computed, observer, setProperties } from '@ember/object';
import Mixin from '@ember/object/mixin';
import C from 'ui/utils/constants';
import { inject as service } from "@ember/service";
import Semver from 'npm:semver';

const NONE       = 'none',
      LOADING    = 'loading',
      CURRENT    = 'current',
      AVAILABLE  = 'available',
      REQUIRED   = 'required',
      INPROGRESS = 'inprogress',
      UPGRADED   = 'upgraded',
      NOTFOUND   = 'notfound',
      ERROR      = 'error';

const INPROGRESS_STATES = [
  'upgrading',
  'canceled-upgrade',
  'canceling-rollback',
  'canceling-upgrade',
  'finishing-upgrade',
  'rolling-back',
];

export default Mixin.create({
  model               : null,
  upgradeOnly         : true,

  intl                : service(),
  catalog             : service(),
  router: service(),

  upgradeInfo         : null,
  upgradeStatus       : null,
  latestVersion       : null,

  init() {
    this._super(...arguments);
    this.updateStatus();
  },

  color: computed('upgradeStatus', function() {
    switch ( get(this, 'upgradeStatus') ) {
      case NONE:
        return 'none';
      case CURRENT:
      case LOADING:
        return 'bg-default';
      case NOTFOUND:
      case ERROR:
      case INPROGRESS:
        return 'bg-disabled';
      case REQUIRED:
        return 'bg-error';
      case AVAILABLE:
      case UPGRADED:
        return 'bg-warning';
    }
  }),

  currentVersion: computed('model.externalIdInfo.{version}','model.externalId', function() {
    let text = get(this, 'intl').findTranslationByKey('upgradeBtn.version.current');
    let version = get(this, 'model.externalIdInfo.version');
    if (typeof version === 'string' || typeof version === 'number') {
      return `${text}: ${get(this, 'upgradeInfo.version')}`;
    } else {
      return null;
    }
  }),

  externalIdChanged: observer('model.{externalId,state}', function() {
    once(() => {
      this.updateStatus();
    });
  }),

  doUpgrade() {
    let status = get(this, 'upgradeStatus');

    if ( [REQUIRED,AVAILABLE,CURRENT].indexOf(status) >= 0 ) {
      let templateId = get(this, 'model.externalIdInfo.templateId');
      let versionId  = get(this, 'latestVersion');
      let catalogId  = get(this, 'model.externalIdInfo.catalog');

      get(this, 'router').transitionTo('catalog-tab.launch', templateId, {queryParams: {
        upgrade: versionId,
        catalog: catalogId,
        namespaceId: get(this, 'model.targetNamespace'),
        appId: get(this, 'model.id'),
      }});

    } else if ( status === UPGRADED ) {

      get(this, 'model').send('finishUpgrade');
    }
  },

  updateStatus() {
    let state           = get(this, 'model.state');
    let info            = get(this, 'model.externalIdInfo');
    let catalogTemplate = get(this, 'model.catalogTemplate');
    let upgradeVersions = {};
    let allVersions     = {};

    if ( state === 'upgraded' ) {
      set(this, 'upgradeStatus', UPGRADED);
      return;
    }

    if ( INPROGRESS_STATES.indexOf(state) >= 0 ) {
      set(this, 'upgradeStatus', INPROGRESS);
      return;
    }

    if ( info && C.EXTERNAL_ID.UPGRADEABLE.indexOf(info.kind) >= 0 ) {
      set(this, 'upgradeStatus', LOADING);
    } else {
      set(this, 'upgradeStatus', NONE);
    }

    if ( catalogTemplate ) {
      upgradeVersions = parseUpgradeVersions(
        get(catalogTemplate, 'versionLinks'),
        get(info, 'version'),
        get(this, 'model')
      );
      get(catalogTemplate, 'versionLinks');
    }

    if (Object.keys(upgradeVersions).length >= 1) {
      setProperties(this, {
        upgradeStatus: AVAILABLE,
        latestVersion: Object.keys(upgradeVersions)[Object.keys(upgradeVersions).length-1],
      });
    } else {
      setProperties(this, {
        upgradeStatus: CURRENT,
        latestVersion: get(info, 'version'),
      });
    }

    // console.log('upgradeVersions', upgradeVersions);

    function parseUpgradeVersions(allVersions, currentVersion) {
      let keys = Object.keys(allVersions);
      let upgrades = {};

      keys.forEach( k => {
        let gt = Semver.gt(k, currentVersion);
        if (gt) {
          upgrades[k] = allVersions[k];
        }
        // console.log(k, currentVersion, gt);
      });

      return upgrades;
    }

    setProperties(this, {
      allVersions: allVersions,
      upgradeVersions: upgradeVersions
    });
    return;
  },

});
<commit_msg>Fix catalog issue<commit_after>import { once } from '@ember/runloop';
import { get, set, computed, observer, setProperties } from '@ember/object';
import Mixin from '@ember/object/mixin';
import C from 'ui/utils/constants';
import { inject as service } from "@ember/service";
import Semver from 'npm:semver';

const NONE       = 'none',
      LOADING    = 'loading',
      CURRENT    = 'current',
      AVAILABLE  = 'available',
      REQUIRED   = 'required',
      INPROGRESS = 'inprogress',
      UPGRADED   = 'upgraded',
      NOTFOUND   = 'notfound',
      ERROR      = 'error';

const INPROGRESS_STATES = [
  'upgrading',
  'canceled-upgrade',
  'canceling-rollback',
  'canceling-upgrade',
  'finishing-upgrade',
  'rolling-back',
];

export default Mixin.create({
  model               : null,
  upgradeOnly         : true,

  intl                : service(),
  catalog             : service(),
  router              : service(),
  growl               : service(),

  upgradeInfo         : null,
  upgradeStatus       : null,
  latestVersion       : null,

  init() {
    this._super(...arguments);
    this.updateStatus();
  },

  color: computed('upgradeStatus', function() {
    switch ( get(this, 'upgradeStatus') ) {
      case NONE:
        return 'none';
      case CURRENT:
      case LOADING:
        return 'bg-default';
      case NOTFOUND:
      case ERROR:
      case INPROGRESS:
        return 'bg-disabled';
      case REQUIRED:
        return 'bg-error';
      case AVAILABLE:
      case UPGRADED:
        return 'bg-warning';
    }
  }),

  currentVersion: computed('model.externalIdInfo.{version}','model.externalId', function() {
    let text = get(this, 'intl').findTranslationByKey('upgradeBtn.version.current');
    let version = get(this, 'model.externalIdInfo.version');
    if (typeof version === 'string' || typeof version === 'number') {
      return `${text}: ${get(this, 'upgradeInfo.version')}`;
    } else {
      return null;
    }
  }),

  externalIdChanged: observer('model.{externalId,state}', function() {
    once(() => {
      this.updateStatus();
    });
  }),

  doUpgrade() {
    let status = get(this, 'upgradeStatus');

    if ( [REQUIRED,AVAILABLE,CURRENT].indexOf(status) >= 0 ) {
      let templateId = get(this, 'model.externalIdInfo.templateId');
      let versionId  = get(this, 'latestVersion');
      let catalogId  = get(this, 'model.externalIdInfo.catalog');

      get(this, 'router').transitionTo('catalog-tab.launch', templateId, {queryParams: {
        upgrade: versionId,
        catalog: catalogId,
        namespaceId: get(this, 'model.targetNamespace'),
        appId: get(this, 'model.id'),
      }});

    } else if ( status === UPGRADED ) {

      get(this, 'model').send('finishUpgrade');
    }
  },

  updateStatus() {
    let state           = get(this, 'model.state');
    let info            = get(this, 'model.externalIdInfo');
    let catalogTemplate = get(this, 'model.catalogTemplate');
    let upgradeVersions = {};
    let allVersions     = {};

    if ( state === 'upgraded' ) {
      set(this, 'upgradeStatus', UPGRADED);
      return;
    }

    if ( INPROGRESS_STATES.indexOf(state) >= 0 ) {
      set(this, 'upgradeStatus', INPROGRESS);
      return;
    }

    if ( info && C.EXTERNAL_ID.UPGRADEABLE.indexOf(info.kind) >= 0 ) {
      set(this, 'upgradeStatus', LOADING);
    } else {
      set(this, 'upgradeStatus', NONE);
    }

    if ( catalogTemplate ) {
      upgradeVersions = parseUpgradeVersions(
        get(catalogTemplate, 'versionLinks'),
        get(info, 'version'),
        get(catalogTemplate, 'name'),
        get(this,'growl')
      );
      get(catalogTemplate, 'versionLinks');
    }

    if (Object.keys(upgradeVersions).length >= 1) {
      setProperties(this, {
        upgradeStatus: AVAILABLE,
        latestVersion: Object.keys(upgradeVersions)[Object.keys(upgradeVersions).length-1],
      });
    } else {
      setProperties(this, {
        upgradeStatus: CURRENT,
        latestVersion: get(info, 'version'),
      });
    }

    // console.log('upgradeVersions', upgradeVersions);

    function parseUpgradeVersions(allVersions, currentVersion, templateName, growl) {
      let keys = Object.keys(allVersions);
      let upgrades = {};

      keys.forEach( k => {
        try {
          let gt = Semver.gt(k, currentVersion);
          if (gt) {
            upgrades[k] = allVersions[k];
          }
        } catch (err) {
          growl.fromError(`Invalid catalog app version in ${templateName}`, err);
        }
      });

      return upgrades;
    }

    setProperties(this, {
      allVersions: allVersions,
      upgradeVersions: upgradeVersions
    });
    return;
  },

});
<|endoftext|>


<commit_before>var sg = sg || {};

sg.Scene = function(context, heightmap) {
  this.context = context;
  this.gl = this.context.gl;

  this.camera = new sg.cameras.Rotating(this.context, vec3.fromValues(0, -30, 0), 55);
  this.terrain = new sg.objects.Terrain(this.context, heightmap);
  this.train = new sg.objects.Train(this.context);
  this.track = new sg.objects.Track(this.context);

  this.gl.enable(this.gl.DEPTH_TEST);
};

sg.Scene.prototype.draw = function() {
  this.context.setGLViewport();
  this.gl.clearColor(0.7, 0.7, 1.0, 1.0);
  this.gl.clear(this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT);

  this.context.shaders.basic.use();
  this.context.shaders.basic.setProjectionMatrix(this.camera.getProjection());
  this.context.shaders.basic.setViewMatrix(this.camera.getView());

  var modelMatrix = mat4.create();
  this.terrain.draw(modelMatrix);

  var trackMatrix = mat4.clone(modelMatrix);
  mat4.translate(trackMatrix, trackMatrix, vec3.fromValues(0, 0, -12));
  this.track.draw(trackMatrix);

  // var trainMatrix = mat4.clone(modelMatrix);
  // mat4.translate(trainMatrix, trainMatrix, vec3.fromValues(0, 0, -9));
  // mat4.rotateZ(trainMatrix, trainMatrix, Math.PI / 2);
  // mat4.scale(trainMatrix, trainMatrix, vec3.fromValues(0.2, 0.2, 0.2));
  // this.train.draw(trainMatrix);
};

sg.Scene.prototype.tick = function(delta) {
  this.camera.tick(delta);
};

sg.Scene.prototype.onMouseMovement = function(event) {
  this.camera.onMouseInput(event.movementX, event.movementY);
};

<commit_msg>Add proper train position<commit_after>var sg = sg || {};

sg.Scene = function(context, heightmap) {
  this.context = context;
  this.gl = this.context.gl;

  this.camera = new sg.cameras.Rotating(this.context, vec3.fromValues(0, 0, 0), 55);
  this.terrain = new sg.objects.Terrain(this.context, heightmap);
  this.train = new sg.objects.Train(this.context);
  this.track = new sg.objects.Track(this.context);

  this.gl.enable(this.gl.DEPTH_TEST);
};

sg.Scene.prototype.draw = function() {
  this.context.setGLViewport();
  this.gl.clearColor(0.7, 0.7, 1.0, 1.0);
  this.gl.clear(this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT);

  this.context.shaders.basic.use();
  this.context.shaders.basic.setProjectionMatrix(this.camera.getProjection());
  this.context.shaders.basic.setViewMatrix(this.camera.getView());

  var modelMatrix = mat4.create();
  this.terrain.draw(modelMatrix);

  var trackMatrix = mat4.clone(modelMatrix);
  mat4.translate(trackMatrix, trackMatrix, vec3.fromValues(0, 0, -12));
  this.track.draw(trackMatrix);

  var trainMatrix = mat4.clone(modelMatrix);
  var trainPosition = this.track.path.evaluate(0);
  vec3.subtract(trainPosition, trainPosition, vec3.fromValues(0, 0, 9.4));
  mat4.translate(trainMatrix, trainMatrix, trainPosition);
  mat4.rotateZ(trainMatrix, trainMatrix, Math.PI / 2);
  mat4.scale(trainMatrix, trainMatrix, vec3.fromValues(0.2, 0.2, 0.2));
  this.train.draw(trainMatrix);
};

sg.Scene.prototype.tick = function(delta) {
  this.camera.tick(delta);
};

sg.Scene.prototype.onMouseMovement = function(event) {
  this.camera.onMouseInput(event.movementX, event.movementY);
};

<|endoftext|>


<commit_before>/* eslint no-use-before-define: "off" */
/* eslint import/no-named-as-default: "off" */
import h from './snabbdom/h';
import customComponents from './custom-components';
import { isObject, eventNameToColonCase } from '../../shared/utils';

const SELF_CLOSING = 'area base br col command embed hr img input keygen link menuitem meta param source track wbr'.split(
  ' ',
);
const PROPS_ATTRS = 'hidden checked disabled readonly selected autofocus autoplay required multiple value indeterminate routeProps'.split(
  ' ',
);
const BOOLEAN_PROPS = 'hidden checked disabled readonly selected autofocus autoplay required multiple readOnly indeterminate'.split(
  ' ',
);

const getTagName = (treeNode) => {
  return typeof treeNode.type === 'function'
    ? treeNode.type.name || 'CustomComponent'
    : treeNode.type;
};

const toCamelCase = (name) => {
  return name
    .split('-')
    .map((word, index) => {
      if (index === 0) return word.toLowerCase();
      return word[0].toUpperCase() + word.substr(1);
    })
    .join('');
};
const propsFromAttrs = (...args) => {
  const context = {};
  args.forEach((obj = {}) => {
    Object.keys(obj).forEach((key) => {
      context[toCamelCase(key)] = obj[key];
    });
  });

  return context;
};

const createCustomComponent = ({ f7, treeNode, vnode, data }) => {
  const component =
    typeof treeNode.type === 'function' ? treeNode.type : customComponents[treeNode.type];
  f7.component
    .create(component, propsFromAttrs(data.attrs || {}, data.props || {}), {
      el: vnode.elm,
      children: treeNode.children,
    })
    .then((c) => {
      if (vnode.data && vnode.data.on && c && c.$el) {
        Object.keys(vnode.data.on).forEach((eventName) => {
          c.$el.on(eventName, vnode.data.on[eventName]);
        });
      }
      // eslint-disable-next-line
      vnode.elm.__component__ = c;
    });
};
const updateCustomComponent = (vnode) => {
  // eslint-disable-next-line
  const component = vnode && vnode.elm && vnode.elm.__component__;
  if (!component) return;
  const newProps = propsFromAttrs(vnode.data.attrs || {}, vnode.data.props || {});
  component.children = vnode.data.treeNode.children;
  Object.assign(component.props, newProps);
  component.update();
};
const destroyCustomComponent = (vnode) => {
  // eslint-disable-next-line
  const component = vnode && vnode.elm && vnode.elm.__component__;

  if (component) {
    const { el, $el } = component;
    if (vnode.data && vnode.data.on && $el) {
      Object.keys(vnode.data.on).forEach((eventName) => {
        $el.off(eventName, vnode.data.on[eventName]);
      });
    }
    if (component.destroy) component.destroy();
    if (el && el.parentNode) el.parentNode.removeChild(el);
    delete vnode.elm.__component__; // eslint-disable-line
  }
};

const isCustomComponent = (treeNodeType) => {
  return (
    typeof treeNodeType === 'function' ||
    (treeNodeType && treeNodeType.indexOf('-') > 0 && customComponents[treeNodeType])
  );
};

function getHooks(treeNode, data, f7, initial, isRoot) {
  const hooks = {};
  const insert = [];
  const destroy = [];
  const update = [];
  const postpatch = [];
  let isFakeElement = false;
  const tagName = getTagName(treeNode);
  if (data && data.attrs && data.attrs.component) {
    // eslint-disable-next-line
    tagName = data.attrs.component;
    delete data.attrs.component;
    isFakeElement = true;
  }

  const isCustom = isCustomComponent(treeNode.type);

  if (isCustom) {
    insert.push((vnode) => {
      if (vnode.sel !== tagName && !isFakeElement) return;
      createCustomComponent({ f7, treeNode, vnode, data });
    });
    destroy.push((vnode) => {
      destroyCustomComponent(vnode);
    });
    update.push((oldVnode, vnode) => {
      updateCustomComponent(vnode);
    });
  }

  if (!isCustom) {
    if (!data || !data.attrs || !data.attrs.class) return hooks;

    const classNames = data.attrs.class;
    classNames.split(' ').forEach((className) => {
      if (!initial) {
        insert.push(...f7.getVnodeHooks('insert', className));
      }
      destroy.push(...f7.getVnodeHooks('destroy', className));
      update.push(...f7.getVnodeHooks('update', className));
      postpatch.push(...f7.getVnodeHooks('postpatch', className));
    });
  }

  if (isRoot && !initial) {
    postpatch.push((oldVnode, vnode) => {
      const vn = vnode || oldVnode;
      if (!vn) return;
      if (vn.data && vn.data.component) {
        vn.data.component.hook('onUpdated');
      }
    });
  }
  if (
    insert.length === 0 &&
    destroy.length === 0 &&
    update.length === 0 &&
    postpatch.length === 0
  ) {
    return hooks;
  }

  if (insert.length) {
    hooks.insert = (vnode) => {
      insert.forEach((f) => f(vnode));
    };
  }
  if (destroy.length) {
    hooks.destroy = (vnode) => {
      destroy.forEach((f) => f(vnode));
    };
  }
  if (update.length) {
    hooks.update = (oldVnode, vnode) => {
      update.forEach((f) => f(oldVnode, vnode));
    };
  }
  if (postpatch.length) {
    hooks.postpatch = (oldVnode, vnode) => {
      postpatch.forEach((f) => f(oldVnode, vnode));
    };
  }

  return hooks;
}
const getEventHandler = (eventHandler, { stop, prevent, once } = {}) => {
  let fired = false;

  function handler(...args) {
    const e = args[0];
    if (once && fired) return;
    if (stop) e.stopPropagation();
    if (prevent) e.preventDefault();
    fired = true;

    eventHandler(...args);
  }

  return handler;
};

const getData = (treeNode, component, f7, initial, isRoot) => {
  const data = { component, treeNode };
  const tagName = getTagName(treeNode);
  Object.keys(treeNode.props).forEach((attrName) => {
    const attrValue = treeNode.props[attrName];
    if (typeof attrValue === 'undefined') return;
    if (PROPS_ATTRS.indexOf(attrName) >= 0) {
      // Props
      if (!data.props) data.props = {};
      if (attrName === 'readonly') {
        // eslint-disable-next-line
        attrName = 'readOnly';
      }
      if (attrName === 'routeProps') {
        // eslint-disable-next-line
        attrName = 'f7RouteProps';
      }
      if (tagName === 'option' && attrName === 'value') {
        if (!data.attrs) data.attrs = {};
        data.attrs.value = attrValue;
      }
      if (BOOLEAN_PROPS.indexOf(attrName) >= 0) {
        // eslint-disable-next-line
        data.props[attrName] = attrValue === false ? false : true;
      } else {
        data.props[attrName] = attrValue;
      }
    } else if (attrName === 'key') {
      // Key
      data.key = attrValue;
    } else if (
      attrName.indexOf('@') === 0 ||
      (attrName.indexOf('on') === 0 && attrName.length > 2)
    ) {
      // Events
      if (!data.on) data.on = {};
      let eventName =
        attrName.indexOf('@') === 0 ? attrName.substr(1) : eventNameToColonCase(attrName.substr(2));
      let stop = false;
      let prevent = false;
      let once = false;
      if (eventName.indexOf('.') >= 0) {
        eventName.split('.').forEach((eventNamePart, eventNameIndex) => {
          if (eventNameIndex === 0) eventName = eventNamePart;
          else {
            if (eventNamePart === 'stop') stop = true;
            if (eventNamePart === 'prevent') prevent = true;
            if (eventNamePart === 'once') once = true;
          }
        });
      }
      data.on[eventName] = getEventHandler(attrValue, { stop, prevent, once });
    } else if (attrName === 'style') {
      // Style
      if (typeof attrValue !== 'string') {
        data.style = attrValue;
      } else {
        if (!data.attrs) data.attrs = {};
        data.attrs.style = attrValue;
      }
    } else {
      // Rest of attribures
      if (!data.attrs) data.attrs = {};
      data.attrs[attrName] = attrValue;

      // ID -> Key
      if (attrName === 'id' && !data.key && !isRoot) {
        data.key = attrValue;
      }
    }
  });

  const hooks = getHooks(treeNode, data, f7, initial, isRoot);

  hooks.prepatch = (oldVnode, vnode) => {
    if (!oldVnode || !vnode) return;
    if (oldVnode && oldVnode.data && oldVnode.data.props) {
      Object.keys(oldVnode.data.props).forEach((key) => {
        if (BOOLEAN_PROPS.indexOf(key) < 0) return;
        if (!vnode.data) vnode.data = {};
        if (!vnode.data.props) vnode.data.props = {};
        if (oldVnode.data.props[key] === true && !(key in vnode.data.props)) {
          vnode.data.props[key] = false;
        }
      });
    }
  };

  data.hook = hooks;

  return data;
};

const getChildren = (treeNode, component, f7, initial) => {
  if (treeNode && treeNode.type && SELF_CLOSING.indexOf(treeNode.type) >= 0) {
    return [];
  }
  const children = [];
  const nodes = treeNode.children;
  for (let i = 0; i < nodes.length; i += 1) {
    const childNode = nodes[i];
    const child = treeNodeToVNode(childNode, component, f7, initial, false);
    if (Array.isArray(child)) {
      children.push(...child);
    } else if (child) {
      children.push(child);
    }
  }
  return children;
};

const getSlots = (treeNode, component, f7, initial) => {
  const slotName = treeNode.props.name || 'default';
  const slotNodes = (component.children || []).filter((childTreeNode) => {
    let childSlotName = 'default';
    if (childTreeNode.props) {
      childSlotName = childTreeNode.props.slot || 'default';
    }
    return childSlotName === slotName;
  });
  if (slotNodes.length === 0) {
    return getChildren(treeNode, component, f7, initial);
  }
  return slotNodes.map((subTreeNode) => treeNodeToVNode(subTreeNode, component, f7, initial));
};

const isTreeNode = (treeNode) => {
  return isObject(treeNode) && 'props' in treeNode && 'type' in treeNode && 'children' in treeNode;
};

const treeNodeToVNode = (treeNode, component, f7, initial, isRoot) => {
  if (!isTreeNode(treeNode)) {
    return String(treeNode);
  }
  if (treeNode.type === 'slot') {
    return getSlots(treeNode, component, f7, initial);
  }
  const data = getData(treeNode, component, f7, initial, isRoot);
  const children = isCustomComponent(treeNode.type)
    ? []
    : getChildren(treeNode, component, f7, initial);

  return h(getTagName(treeNode), data, children);
};

export default function vdom(tree = {}, component, initial) {
  return treeNodeToVNode(tree, component, component.f7, initial, true);
}
<commit_msg>(fix): Router - support innerHTML in components<commit_after>/* eslint no-use-before-define: "off" */
/* eslint import/no-named-as-default: "off" */
import h from './snabbdom/h';
import customComponents from './custom-components';
import { isObject, eventNameToColonCase } from '../../shared/utils';

const SELF_CLOSING = 'area base br col command embed hr img input keygen link menuitem meta param source track wbr'.split(
  ' ',
);
const PROPS_ATTRS = 'hidden checked disabled readonly selected autofocus autoplay required multiple value indeterminate routeProps innerHTML'.split(
  ' ',
);
const BOOLEAN_PROPS = 'hidden checked disabled readonly selected autofocus autoplay required multiple readOnly indeterminate'.split(
  ' ',
);

const getTagName = (treeNode) => {
  return typeof treeNode.type === 'function'
    ? treeNode.type.name || 'CustomComponent'
    : treeNode.type;
};

const toCamelCase = (name) => {
  return name
    .split('-')
    .map((word, index) => {
      if (index === 0) return word.toLowerCase();
      return word[0].toUpperCase() + word.substr(1);
    })
    .join('');
};
const propsFromAttrs = (...args) => {
  const context = {};
  args.forEach((obj = {}) => {
    Object.keys(obj).forEach((key) => {
      context[toCamelCase(key)] = obj[key];
    });
  });

  return context;
};

const createCustomComponent = ({ f7, treeNode, vnode, data }) => {
  const component =
    typeof treeNode.type === 'function' ? treeNode.type : customComponents[treeNode.type];
  f7.component
    .create(component, propsFromAttrs(data.attrs || {}, data.props || {}), {
      el: vnode.elm,
      children: treeNode.children,
    })
    .then((c) => {
      if (vnode.data && vnode.data.on && c && c.$el) {
        Object.keys(vnode.data.on).forEach((eventName) => {
          c.$el.on(eventName, vnode.data.on[eventName]);
        });
      }
      // eslint-disable-next-line
      vnode.elm.__component__ = c;
    });
};
const updateCustomComponent = (vnode) => {
  // eslint-disable-next-line
  const component = vnode && vnode.elm && vnode.elm.__component__;
  if (!component) return;
  const newProps = propsFromAttrs(vnode.data.attrs || {}, vnode.data.props || {});
  component.children = vnode.data.treeNode.children;
  Object.assign(component.props, newProps);
  component.update();
};
const destroyCustomComponent = (vnode) => {
  // eslint-disable-next-line
  const component = vnode && vnode.elm && vnode.elm.__component__;

  if (component) {
    const { el, $el } = component;
    if (vnode.data && vnode.data.on && $el) {
      Object.keys(vnode.data.on).forEach((eventName) => {
        $el.off(eventName, vnode.data.on[eventName]);
      });
    }
    if (component.destroy) component.destroy();
    if (el && el.parentNode) el.parentNode.removeChild(el);
    delete vnode.elm.__component__; // eslint-disable-line
  }
};

const isCustomComponent = (treeNodeType) => {
  return (
    typeof treeNodeType === 'function' ||
    (treeNodeType && treeNodeType.indexOf('-') > 0 && customComponents[treeNodeType])
  );
};

function getHooks(treeNode, data, f7, initial, isRoot) {
  const hooks = {};
  const insert = [];
  const destroy = [];
  const update = [];
  const postpatch = [];
  let isFakeElement = false;
  const tagName = getTagName(treeNode);
  if (data && data.attrs && data.attrs.component) {
    // eslint-disable-next-line
    tagName = data.attrs.component;
    delete data.attrs.component;
    isFakeElement = true;
  }

  const isCustom = isCustomComponent(treeNode.type);

  if (isCustom) {
    insert.push((vnode) => {
      if (vnode.sel !== tagName && !isFakeElement) return;
      createCustomComponent({ f7, treeNode, vnode, data });
    });
    destroy.push((vnode) => {
      destroyCustomComponent(vnode);
    });
    update.push((oldVnode, vnode) => {
      updateCustomComponent(vnode);
    });
  }

  if (!isCustom) {
    if (!data || !data.attrs || !data.attrs.class) return hooks;

    const classNames = data.attrs.class;
    classNames.split(' ').forEach((className) => {
      if (!initial) {
        insert.push(...f7.getVnodeHooks('insert', className));
      }
      destroy.push(...f7.getVnodeHooks('destroy', className));
      update.push(...f7.getVnodeHooks('update', className));
      postpatch.push(...f7.getVnodeHooks('postpatch', className));
    });
  }

  if (isRoot && !initial) {
    postpatch.push((oldVnode, vnode) => {
      const vn = vnode || oldVnode;
      if (!vn) return;
      if (vn.data && vn.data.component) {
        vn.data.component.hook('onUpdated');
      }
    });
  }
  if (
    insert.length === 0 &&
    destroy.length === 0 &&
    update.length === 0 &&
    postpatch.length === 0
  ) {
    return hooks;
  }

  if (insert.length) {
    hooks.insert = (vnode) => {
      insert.forEach((f) => f(vnode));
    };
  }
  if (destroy.length) {
    hooks.destroy = (vnode) => {
      destroy.forEach((f) => f(vnode));
    };
  }
  if (update.length) {
    hooks.update = (oldVnode, vnode) => {
      update.forEach((f) => f(oldVnode, vnode));
    };
  }
  if (postpatch.length) {
    hooks.postpatch = (oldVnode, vnode) => {
      postpatch.forEach((f) => f(oldVnode, vnode));
    };
  }

  return hooks;
}
const getEventHandler = (eventHandler, { stop, prevent, once } = {}) => {
  let fired = false;

  function handler(...args) {
    const e = args[0];
    if (once && fired) return;
    if (stop) e.stopPropagation();
    if (prevent) e.preventDefault();
    fired = true;

    eventHandler(...args);
  }

  return handler;
};

const getData = (treeNode, component, f7, initial, isRoot) => {
  const data = { component, treeNode };
  const tagName = getTagName(treeNode);
  Object.keys(treeNode.props).forEach((attrName) => {
    const attrValue = treeNode.props[attrName];
    if (typeof attrValue === 'undefined') return;
    if (PROPS_ATTRS.indexOf(attrName) >= 0) {
      // Props
      if (!data.props) data.props = {};
      if (attrName === 'readonly') {
        // eslint-disable-next-line
        attrName = 'readOnly';
      }
      if (attrName === 'routeProps') {
        // eslint-disable-next-line
        attrName = 'f7RouteProps';
      }
      if (tagName === 'option' && attrName === 'value') {
        if (!data.attrs) data.attrs = {};
        data.attrs.value = attrValue;
      }
      if (BOOLEAN_PROPS.indexOf(attrName) >= 0) {
        // eslint-disable-next-line
        data.props[attrName] = attrValue === false ? false : true;
      } else {
        data.props[attrName] = attrValue;
      }
    } else if (attrName === 'key') {
      // Key
      data.key = attrValue;
    } else if (
      attrName.indexOf('@') === 0 ||
      (attrName.indexOf('on') === 0 && attrName.length > 2)
    ) {
      // Events
      if (!data.on) data.on = {};
      let eventName =
        attrName.indexOf('@') === 0 ? attrName.substr(1) : eventNameToColonCase(attrName.substr(2));
      let stop = false;
      let prevent = false;
      let once = false;
      if (eventName.indexOf('.') >= 0) {
        eventName.split('.').forEach((eventNamePart, eventNameIndex) => {
          if (eventNameIndex === 0) eventName = eventNamePart;
          else {
            if (eventNamePart === 'stop') stop = true;
            if (eventNamePart === 'prevent') prevent = true;
            if (eventNamePart === 'once') once = true;
          }
        });
      }
      data.on[eventName] = getEventHandler(attrValue, { stop, prevent, once });
    } else if (attrName === 'style') {
      // Style
      if (typeof attrValue !== 'string') {
        data.style = attrValue;
      } else {
        if (!data.attrs) data.attrs = {};
        data.attrs.style = attrValue;
      }
    } else {
      // Rest of attribures
      if (!data.attrs) data.attrs = {};
      data.attrs[attrName] = attrValue;

      // ID -> Key
      if (attrName === 'id' && !data.key && !isRoot) {
        data.key = attrValue;
      }
    }
  });

  const hooks = getHooks(treeNode, data, f7, initial, isRoot);

  hooks.prepatch = (oldVnode, vnode) => {
    if (!oldVnode || !vnode) return;
    if (oldVnode && oldVnode.data && oldVnode.data.props) {
      Object.keys(oldVnode.data.props).forEach((key) => {
        if (BOOLEAN_PROPS.indexOf(key) < 0) return;
        if (!vnode.data) vnode.data = {};
        if (!vnode.data.props) vnode.data.props = {};
        if (oldVnode.data.props[key] === true && !(key in vnode.data.props)) {
          vnode.data.props[key] = false;
        }
      });
    }
  };

  data.hook = hooks;

  return data;
};

const getChildren = (treeNode, component, f7, initial) => {
  if (treeNode && treeNode.type && SELF_CLOSING.indexOf(treeNode.type) >= 0) {
    return [];
  }
  const children = [];
  const nodes = treeNode.children;
  for (let i = 0; i < nodes.length; i += 1) {
    const childNode = nodes[i];
    const child = treeNodeToVNode(childNode, component, f7, initial, false);
    if (Array.isArray(child)) {
      children.push(...child);
    } else if (child) {
      children.push(child);
    }
  }
  return children;
};

const getSlots = (treeNode, component, f7, initial) => {
  const slotName = treeNode.props.name || 'default';
  const slotNodes = (component.children || []).filter((childTreeNode) => {
    let childSlotName = 'default';
    if (childTreeNode.props) {
      childSlotName = childTreeNode.props.slot || 'default';
    }
    return childSlotName === slotName;
  });
  if (slotNodes.length === 0) {
    return getChildren(treeNode, component, f7, initial);
  }
  return slotNodes.map((subTreeNode) => treeNodeToVNode(subTreeNode, component, f7, initial));
};

const isTreeNode = (treeNode) => {
  return isObject(treeNode) && 'props' in treeNode && 'type' in treeNode && 'children' in treeNode;
};

const treeNodeToVNode = (treeNode, component, f7, initial, isRoot) => {
  if (!isTreeNode(treeNode)) {
    return String(treeNode);
  }
  if (treeNode.type === 'slot') {
    return getSlots(treeNode, component, f7, initial);
  }
  const data = getData(treeNode, component, f7, initial, isRoot);
  const children = isCustomComponent(treeNode.type)
    ? []
    : getChildren(treeNode, component, f7, initial);

  return h(getTagName(treeNode), data, children);
};

export default function vdom(tree = {}, component, initial) {
  return treeNodeToVNode(tree, component, component.f7, initial, true);
}
<|endoftext|>


<commit_before>---
layout: null
---

var APP_PREFIX = 'alexdiliberto-cache-';
var VERSION = 'v26';
var CACHE_NAME = APP_PREFIX + VERSION;
var urlsToCache = [];

// Cache posts
// Limits the number of posts that gets cached to 3
// Reads a piece of front-matter in each post that directs the second loop to the folder where the assets are held
// {% for post in site.posts limit:3 %}
//   urlsToCache.push("{{ post.url }}");
//   {% for asset in post.assets %}
//     {% for file in site.static_files %}
//       {% if file.path contains asset %}
//         urlsToCache.push("{{ file.path }}");
//       {% endif %}
//     {% endfor %}
//   {% endfor %}
// {% endfor %}

{% for post in site.posts limit:3 %}
  urlsToCache.push("{{ post.url }}");
{% endfor %}

// Cache pages
{% for page in site.html_pages %}
  {% unless page.url contains '/talks' %}
    {% unless page.url contains '/node_modules' %}
      urlsToCache.push("{{ page.url }}");
    {% endunless %}
  {% endunless %}
{% endfor %}

// Cache assets
{% for file in site.static_files %}
  {% unless file.path contains '/talks' %}
    {% unless file.path contains '/node_modules' %}
      {% if file.path contains '/img' or file.extname == '.js' or file.extname == '.png' %}
        urlsToCache.push("{{ file.path }}")
      {% endif %}
    {% endunless %}
  {% endunless %}
{% endfor %}

//console.log('urlsToCache', urlsToCache);

self.addEventListener('install', function(event) {
  event.waitUntil(
    caches.open(CACHE_NAME).then(function(cache) {
      return cache.addAll(urlsToCache);
    })
  );
});

self.addEventListener('fetch', function(event) {
  event.respondWith(
    caches.open(CACHE_NAME).then(function(cache) {
      return cache.match(event.request).then(function(response) {
        return response || fetch(event.request).then(function(response) {
          if (event.request.url.indexOf('chrome-extension') !== -1) {
            return response;
          }
          cache.put(event.request, response.clone());
          return response;
        });
      });
    }).catch(function() {
      return caches.match('/offline/');
    })
  );
});

self.addEventListener('activate', function(event) {
  var cacheWhitelist = [CACHE_NAME];

  event.waitUntil(
    caches.keys().then(function(cacheNames) {
      return Promise.all(
        cacheNames.map(function(cacheName) {
          if (cacheWhitelist.indexOf(cacheName) === -1) {
            return caches.delete(cacheName);
          }
        })
      );
    })
  );
});
<commit_msg>Add `self.skipWaiting()` at beginning of sw install event<commit_after>---
layout: null
---

var APP_PREFIX = 'alexdiliberto-cache-';
var VERSION = 'v26';
var CACHE_NAME = APP_PREFIX + VERSION;
var urlsToCache = [];

// Cache posts
// Limits the number of posts that gets cached to 3
// Reads a piece of front-matter in each post that directs the second loop to the folder where the assets are held
// {% for post in site.posts limit:3 %}
//   urlsToCache.push("{{ post.url }}");
//   {% for asset in post.assets %}
//     {% for file in site.static_files %}
//       {% if file.path contains asset %}
//         urlsToCache.push("{{ file.path }}");
//       {% endif %}
//     {% endfor %}
//   {% endfor %}
// {% endfor %}

{% for post in site.posts limit:3 %}
  urlsToCache.push("{{ post.url }}");
{% endfor %}

// Cache pages
{% for page in site.html_pages %}
  {% unless page.url contains '/talks' %}
    {% unless page.url contains '/node_modules' %}
      urlsToCache.push("{{ page.url }}");
    {% endunless %}
  {% endunless %}
{% endfor %}

// Cache assets
{% for file in site.static_files %}
  {% unless file.path contains '/talks' %}
    {% unless file.path contains '/node_modules' %}
      {% if file.path contains '/img' or file.extname == '.js' or file.extname == '.png' %}
        urlsToCache.push("{{ file.path }}")
      {% endif %}
    {% endunless %}
  {% endunless %}
{% endfor %}

//console.log('urlsToCache', urlsToCache);

self.addEventListener('install', function(event) {
  self.skipWaiting();

  event.waitUntil(
    caches.open(CACHE_NAME).then(function(cache) {
      return cache.addAll(urlsToCache);
    })
  );
});

self.addEventListener('fetch', function(event) {
  event.respondWith(
    caches.open(CACHE_NAME).then(function(cache) {
      return cache.match(event.request).then(function(response) {
        return response || fetch(event.request).then(function(response) {
          if (event.request.url.indexOf('chrome-extension') !== -1) {
            return response;
          }
          cache.put(event.request, response.clone());
          return response;
        });
      });
    }).catch(function() {
      return caches.match('/offline/');
    })
  );
});

self.addEventListener('activate', function(event) {
  var cacheWhitelist = [CACHE_NAME];

  event.waitUntil(
    caches.keys().then(function(cacheNames) {
      return Promise.all(
        cacheNames.map(function(cacheName) {
          if (cacheWhitelist.indexOf(cacheName) === -1) {
            return caches.delete(cacheName);
          }
        })
      );
    })
  );
});
<|endoftext|>


<commit_before>/**
 * @author Gilles Coomans <gilles.coomans@gmail.com>
 * @licence MIT
 * Minimalistic, workable, understandable html5 history shim.
 * IE8+, FF3+, Safari, Chrome, ...
 *
 *
 * Remarque : for IE8, please use it in conjonction with https://github.com/WebReflection/ie8
 * (Events listener shim for IE8)
 *
 * TODO :
 * 	test in IE8
 * 	work on creatEvent shim
 *
 * 	write test
 *
 * manage basepath
 *
 * manage title
 *   ==> as all browser ignore it :
 *   	=> need to manage it through store even for native.
 *   	=> should use hid in data object to retreieve it on popstate
 *
 * manage internal/external flag
 */
(function() {
	'use strict';
	if (!window.history) // too old !!! ;)
		return;

	// ___________________________________________________________ UTILS
	var _uaMatch = function(ua) {
		ua = ua.toLowerCase();
		var match = /(chrome)[ \/]([\w.]+)/.exec(ua) ||
			/(webkit)[ \/]([\w.]+)/.exec(ua) ||
			/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) ||
			/(msie) ([\w.]+)/.exec(ua) ||
			ua.indexOf('compatible') < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || [];
		return {
			browser: match[1] || '',
			version: match[2] || '0'
		};
	};

	var userAgent = function() {
		var browser = {},
			matched = _uaMatch(navigator.userAgent);
		if (matched.browser) {
			browser[matched.browser] = true;
			browser.version = matched.version;
		}
		if (browser.chrome)
			browser.webkit = true;
		else if (browser.webkit)
			browser.safari = true;
		return browser;
	};

	var parseUri = function(str) {
		var o = parseUri.options,
			m = o.parser[o.strictMode ? "strict" : "loose"].exec(str),
			uri = {},
			i = 14;
		while (i--)
			uri[o.key[i]] = m[i] || "";
		uri[o.q.name] = {};
		uri[o.key[12]].replace(o.q.parser, function($0, $1, $2) {
			if ($1) uri[o.q.name][$1] = $2;
		});
		return uri;
	};

	parseUri.options = {
		strictMode: true,
		key: ["href", "protocol", "host", "userInfo", "user", "password", "hostname", "port", "relative", "pathname", "directory", "file", "search", "hash"],
		q: {
			name: "query",
			parser: /(?:^|&)([^&=]*)=?([^&]*)/g
		},
		parser: {
			strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,
			loose: /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/
		}
	};

	var parseURL = function(url) {
		var obj = parseUri(url);
		obj.path = obj.pathname + (obj.search?"?":"") + obj.search;
		return obj;
	};

	// http://stackoverflow.com/questions/9077101/iphone-localstorage-quota-exceeded-err-issue/12976988#12976988
	var sessionStorageSupported = function() {
		try {
			sessionStorage.setItem("test", "test");
			sessionStorage.removeItem("test");
			return true;
		} catch (e) {
			return false;
		}
	};

	// TODO : for the moment hid == Date.now().valueOf(). Could be more sophisticated.
	var produceID = function(){
		return +new Date;
	}

	//______________________________________________________________________ History Shim

	var skipHashChange,
		skipInitPop = false,
		fromGo = false,
		agent = userAgent();

	window.history.parseURL = parseURL;
	window.history.config = {
		hashChangeAlone: true,
		setStateEvent:true,
		//setHashEvent:true,
		storageKey: "min-history",
		basePath: "/",
		hid: true
	};

	// some version of safari (and co) have no "state" property in history. force it.
	window.history.forceState = !("state" in window.history);
	if (window.history.forceState)
		window.history.state = null;

	// safari fire pop state on page load. skip it for consistency.
	if (agent.safari && location.relative !== window.history.config.basePath)
		skipInitPop = true;

	// produce href with hid in search part
	var getHrefWithHid = function(id, location) {
		var search = "?"+ (location.search || "") + "&hid=" + id;
		return (location.pathname || '/')
			+ search
			+ (location.hash ? ("#" + location.hash) : "");
	};

	// remove hid from location parts. store hid in location.
	var cleanHidFromLocation = function(location) {
		if (!location.search)
			return;
		location.search = location.search.replace(/&hid=([^&]+)/gi, function(c, v) {
			location.hid = v;
			return "";
		});
		location.path = location.pathname + (location.search ? ("?" + location.search) : "");
		location.relative = location.path + (location.hash ? ("#" + location.hash) : "");
	};

	var fireStateEvent = function(type, state, action) {
		// TODO : manage IE8 document.createEventObject
		var evt = document.createEvent("CustomEvent");
		evt.initEvent(type, true, true);
		evt.state = state || null;
		if(action)
			evt.action = action;
		return window.dispatchEvent(evt);
	};

	window.history.store = {
		states: null,
		index: -1,
		init: function() {
			if (!(window.history.sessionStorageSupported = sessionStorageSupported()))
				console.warn("You are using custom history API and Session Storage is not supported. You'll loose history when leaving page.");

			if (window.history.sessionStorageSupported)
				this.states = JSON.parse(sessionStorage.getItem(window.history.config.storageKey)) || [];
			else
				this.states = [];
			if (!Array.isArray(this.states))
				this.states = [];
		},
		current:function(){
			return this.states[this.index];
		},
		push: function(data, title, url) {
			var state = { data: data, title: title, url: url };
			if(window.history.config.hid)
			{
				state.data = state.data || {};
				state.data.hid = produceID();
			}
			this.index++;
			if (this.index < this.states.length)
				this.states = this.states.slice(0, this.index);
			this.states.push(state);
			return state;
		},
		replace: function(data, title, url) {
			var old = this.states[this.index],
				state = { data: data, title: title, url: url };
			if(window.history.config.hid)
			{
				state.data = state.data || {};
				state.data.hid = (old && old.data && old.data.hid) ? old.data.hid : produceID();
			}
			return this.states[this.index] = state;
		},
		go: function(increment) {
			var i = this.index + increment,
				state = this.states[i];
			if (!state)
				return null;
			this.index = i;
			return state;
		},
		find: function(id) {
			for (var i = 0, len = this.states.length, state; i < len && (state = this.states[i]); ++i)
				if (state.data && state.data.hid == id)
					return state;
			return null;
		},
		save: function() {
			if (window.history.sessionStorageSupported)
				sessionStorage.setItem(window.history.config.storageKey, JSON.stringify(this.states));
		}
	};
	var setState;
	if (!window.history.pushState) // EMULATED
	{
		window.history.emulated = true;
		setState = function(type, data, title, url)
		{
			if(title)
				document.title = title;
			this.location = parseURL(url);
			var href = this.location.relative;
			if (this.config.hid)
			{
				this.state = data = this.store[type](data, title, url).data;	// 'push' or 'replace' in store
				href = getHrefWithHid(data.hid, this.location); // launch hashchange
			}
			else
				this.state = data || null;
			if(this.config.setStateEvent)
				fireStateEvent("setstate", this.state, type);
			skipHashChange = true;
			window.location.hash = "!" + href; // launch hashchange
		}
		var originalGo = window.history.go;
		window.history.go = function(arg) {
			if(this.config.hid)
			{
				var state = this.store.go(arg);
				if (!state)
					return null;
				this.state = state.data;
			}
			else
				this.state = null;
			fromGo = true;
			originalGo.call(this, arg);
		};
		window.history.back = function(arg) {
			this.go(-1);
		};
		window.history.forward = function(arg) {
			this.go(1);
		};
	}
	else // NATIVE
	{
		var originalPushState = window.history.pushState,
			originalReplaceState = window.history.replaceState;
		setState = function(type, data, title, url){
			var original = originalReplaceState;
			if(type == 'push')
				original = originalPushState;
			if(title)
				document.title = title;
			this.location = parseURL(url);
			if(this.config.hid)
				data = this.store[type](data, title, url).data; // push or replace in store
			if(this.forceState)
				this.state = data || null;

			var r = original.call(this, data, title, url);
			if(this.config.setStateEvent)
				fireStateEvent('setstate', this.state, type);
			return r;
		}
	}

	window.history.pushState = function(data, title, url) {
		return setState.call(this, 'push', data, title, url);
	};
	window.history.replaceState = function(data, title, url) {
		return setState.call(this, 'replace', data, title, url);
	};

	// Native Only
	var popState = function(e) {
		// console.log("history popState : ", e);
		var stateData = e.state;
		if (window.history.forceState)
			window.history.state = stateData || null;

		if (skipInitPop) {	// safari popstate at init skipped.
			skipInitPop = false;
			e.stopImmediatePropagation();
			return false;
		}
		skipHashChange = false;
		var tmp = window.history.location,	// old
			current = window.history.location = parseURL(location.href), // new
			state;

		if(window.history.config.hid && stateData && stateData.hid)	// try to get state from hid
			state = window.history.store.find(stateData.hid);

		if(state)
		{
			// check url equality.
			if(current.relative !== state.url)
				throw new Error("bad state from native popstate (url dont match) "+current.relative+" - "+state.url);
			if(state.title) // force title
				document.title = state.title;
		}
		if (!tmp || tmp.path !== current.path) // relative has change : apply pop state
		{
			if (tmp && tmp.hash !== current.hash)
				skipHashChange = true;
			return true;
		}
		else // path doesn't change. check hash
		if (tmp.hash !== current.hash && window.history.config.hashChangeAlone)
		{
			e.stopImmediatePropagation();
			return false; // skip popstate if config.hashChangeAlone
		}
		return true; // nothing change : refresh
	};

	var hashChange = function(e) {
		if (skipHashChange) // skip after pushState/replaceState (emulated)  OR  after "path change" from popstate (native),
		{
			skipHashChange = false;
			e.stopImmediatePropagation();
			return false;
		}
		//______________________________________________________ POP STATE EMULATION
		if (window.history.emulated) // do popstate behaviour
		{
			var state,
				data = null,
				tmp = window.history.location, // swap currentLocation
				current = window.history.location = parseURL(location.hash.substring(2));
			if (!fromGo && window.history.config.hid) // could be from back/next button or manual hash change in address bar.
			{
				cleanHidFromLocation(current); // try to extract hid
				if (current.hid)
					state = window.history.store.find(current.hid);
				if(state)
					data = state.data || null;
				window.history.state = data;
			}
			if(state && state.title)	// force title
				document.title = state.title;

			if (!tmp || tmp.path !== current.path) { // path == pathname + ? + search
				// path has change : dispatch popstate and skip hashchange
				e.stopImmediatePropagation();
				fireStateEvent("popstate", data);
				return false;
			}
			// path doesn't change.
			// check hash change : if !hashChangeAlone : dispatch popstate
			if (tmp.hash !== current.hash && !window.history.config.hashChangeAlone)
				fireStateEvent("popstate", data);
		}
		return true; // propagate hashchange
	};

	window.history.init = function(opt) {
		for (var i in opt)
			this.config[i] = opt[i];
		this.location = parseURL(window.location.href);
		window.addEventListener("hashchange", hashChange);
		if (!this.emulated)
			window.addEventListener("popstate", popState);
		if(this.config.hid)
		{
			this.store.init();
			window.addEventListener("unload", function() {
				window.history.store.save();
			});
		}
	};
})();<commit_msg>debug !fromGo and hid in emulated<commit_after>/**
 * @author Gilles Coomans <gilles.coomans@gmail.com>
 * @licence MIT
 * Minimalistic, workable, understandable html5 history shim.
 * IE8+, FF3+, Safari, Chrome, ...
 *
 *
 * Remarque : for IE8, please use it in conjonction with https://github.com/WebReflection/ie8
 * (Events listener shim for IE8)
 *
 * TODO :
 * 	test in IE8
 * 	work on creatEvent shim
 *
 * 	write test
 *
 * manage basepath
 *
 * manage title
 *   ==> as all browser ignore it :
 *   	=> need to manage it through store even for native.
 *   	=> should use hid in data object to retreieve it on popstate
 *
 * manage internal/external flag
 */
(function() {
	'use strict';
	if (!window.history) // too old !!! ;)
		return;

	// ___________________________________________________________ UTILS
	var _uaMatch = function(ua) {
		ua = ua.toLowerCase();
		var match = /(chrome)[ \/]([\w.]+)/.exec(ua) ||
			/(webkit)[ \/]([\w.]+)/.exec(ua) ||
			/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) ||
			/(msie) ([\w.]+)/.exec(ua) ||
			ua.indexOf('compatible') < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || [];
		return {
			browser: match[1] || '',
			version: match[2] || '0'
		};
	};

	var userAgent = function() {
		var browser = {},
			matched = _uaMatch(navigator.userAgent);
		if (matched.browser) {
			browser[matched.browser] = true;
			browser.version = matched.version;
		}
		if (browser.chrome)
			browser.webkit = true;
		else if (browser.webkit)
			browser.safari = true;
		return browser;
	};

	var parseUri = function(str) {
		var o = parseUri.options,
			m = o.parser[o.strictMode ? "strict" : "loose"].exec(str),
			uri = {},
			i = 14;
		while (i--)
			uri[o.key[i]] = m[i] || "";
		uri[o.q.name] = {};
		uri[o.key[12]].replace(o.q.parser, function($0, $1, $2) {
			if ($1) uri[o.q.name][$1] = $2;
		});
		return uri;
	};

	parseUri.options = {
		strictMode: true,
		key: ["href", "protocol", "host", "userInfo", "user", "password", "hostname", "port", "relative", "pathname", "directory", "file", "search", "hash"],
		q: {
			name: "query",
			parser: /(?:^|&)([^&=]*)=?([^&]*)/g
		},
		parser: {
			strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,
			loose: /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/
		}
	};

	var parseURL = function(url) {
		var obj = parseUri(url);
		obj.path = obj.pathname + (obj.search?"?":"") + obj.search;
		return obj;
	};

	// http://stackoverflow.com/questions/9077101/iphone-localstorage-quota-exceeded-err-issue/12976988#12976988
	var sessionStorageSupported = function() {
		try {
			sessionStorage.setItem("test", "test");
			sessionStorage.removeItem("test");
			return true;
		} catch (e) {
			return false;
		}
	};

	// TODO : for the moment hid == Date.now().valueOf(). Could be more sophisticated.
	var produceID = function(){
		return +new Date;
	}

	//______________________________________________________________________ History Shim

	var skipHashChange,
		skipInitPop = false,
		fromGo = false,
		agent = userAgent();

	window.history.parseURL = parseURL;
	window.history.config = {
		hashChangeAlone: true,
		setStateEvent:true,
		//setHashEvent:true,
		storageKey: "min-history",
		basePath: "/",
		hid: true
	};

	// some version of safari (and co) have no "state" property in history. force it.
	window.history.forceState = !("state" in window.history);
	if (window.history.forceState)
		window.history.state = null;

	// safari fire pop state on page load. skip it for consistency.
	if (agent.safari && location.relative !== window.history.config.basePath)
		skipInitPop = true;

	// produce href with hid in search part
	var getHrefWithHid = function(id, location) {
		var search = "?"+ (location.search || "") + "&hid=" + id;
		return (location.pathname || '/')
			+ search
			+ (location.hash ? ("#" + location.hash) : "");
	};

	// remove hid from location parts. store hid in location.
	var cleanHidFromLocation = function(location) {
		if (!location.search)
			return;
		location.search = location.search.replace(/&hid=([^&]+)/gi, function(c, v) {
			location.hid = v;
			return "";
		});
		location.path = location.pathname + (location.search ? ("?" + location.search) : "");
		location.relative = location.path + (location.hash ? ("#" + location.hash) : "");
	};

	var fireStateEvent = function(type, state, action) {
		// TODO : manage IE8 document.createEventObject
		var evt = document.createEvent("CustomEvent");
		evt.initEvent(type, true, true);
		evt.state = state || null;
		if(action)
			evt.action = action;
		return window.dispatchEvent(evt);
	};

	window.history.store = {
		states: null,
		index: -1,
		init: function() {
			if (!(window.history.sessionStorageSupported = sessionStorageSupported()))
				console.warn("You are using custom history API and Session Storage is not supported. You'll loose history when leaving page.");

			if (window.history.sessionStorageSupported)
				this.states = JSON.parse(sessionStorage.getItem(window.history.config.storageKey)) || [];
			else
				this.states = [];
			if (!Array.isArray(this.states))
				this.states = [];
		},
		current:function(){
			return this.states[this.index];
		},
		push: function(data, title, url) {
			var state = { data: data, title: title, url: url };
			if(window.history.config.hid)
			{
				state.data = state.data || {};
				state.data.hid = produceID();
			}
			this.index++;
			if (this.index < this.states.length)
				this.states = this.states.slice(0, this.index);
			this.states.push(state);
			return state;
		},
		replace: function(data, title, url) {
			var old = this.states[this.index],
				state = { data: data, title: title, url: url };
			if(window.history.config.hid)
			{
				state.data = state.data || {};
				state.data.hid = (old && old.data && old.data.hid) ? old.data.hid : produceID();
			}
			return this.states[this.index] = state;
		},
		go: function(increment) {
			var i = this.index + increment,
				state = this.states[i];
			if (!state)
				return null;
			this.index = i;
			return state;
		},
		find: function(id) {
			for (var i = 0, len = this.states.length, state; i < len && (state = this.states[i]); ++i)
				if (state.data && state.data.hid == id)
					return state;
			return null;
		},
		save: function() {
			if (window.history.sessionStorageSupported)
				sessionStorage.setItem(window.history.config.storageKey, JSON.stringify(this.states));
		}
	};
	var setState;
	if (!window.history.pushState) // EMULATED
	{
		window.history.emulated = true;
		setState = function(type, data, title, url)
		{
			if(title)
				document.title = title;
			this.location = parseURL(url);
			var href = this.location.relative;
			if (this.config.hid)
			{
				this.state = data = this.store[type](data, title, url).data;	// 'push' or 'replace' in store
				href = getHrefWithHid(data.hid, this.location); // launch hashchange
			}
			else
				this.state = data || null;
			if(this.config.setStateEvent)
				fireStateEvent("setstate", this.state, type);
			skipHashChange = true;
			window.location.hash = "!" + href; // launch hashchange
		}
		var originalGo = window.history.go;
		window.history.go = function(arg) {
			if(this.config.hid)
			{
				var state = this.store.go(arg);
				if (!state)
					return null;
				this.state = state.data;
			}
			else
				this.state = null;
			fromGo = true;
			originalGo.call(this, arg);
		};
		window.history.back = function(arg) {
			this.go(-1);
		};
		window.history.forward = function(arg) {
			this.go(1);
		};
	}
	else // NATIVE
	{
		var originalPushState = window.history.pushState,
			originalReplaceState = window.history.replaceState;
		setState = function(type, data, title, url){
			var original = originalReplaceState;
			if(type == 'push')
				original = originalPushState;
			if(title)
				document.title = title;
			this.location = parseURL(url);
			if(this.config.hid)
				data = this.store[type](data, title, url).data; // push or replace in store
			if(this.forceState)
				this.state = data || null;

			var r = original.call(this, data, title, url);
			if(this.config.setStateEvent)
				fireStateEvent('setstate', this.state, type);
			return r;
		}
	}

	window.history.pushState = function(data, title, url) {
		return setState.call(this, 'push', data, title, url);
	};
	window.history.replaceState = function(data, title, url) {
		return setState.call(this, 'replace', data, title, url);
	};

	// Native Only
	var popState = function(e) {
		// console.log("history popState : ", e);
		var stateData = e.state;
		if (window.history.forceState)
			window.history.state = stateData || null;

		if (skipInitPop) {	// safari popstate at init skipped.
			skipInitPop = false;
			e.stopImmediatePropagation();
			return false;
		}
		skipHashChange = false;
		var tmp = window.history.location,	// old
			current = window.history.location = parseURL(location.href), // new
			state;

		if(window.history.config.hid && stateData && stateData.hid)	// try to get state from hid
			state = window.history.store.find(stateData.hid);

		if(state)
		{
			// check url equality.
			if(current.relative !== state.url)
				throw new Error("bad state from native popstate (url dont match) "+current.relative+" - "+state.url);
			if(state.title) // force title
				document.title = state.title;
		}
		if (!tmp || tmp.path !== current.path) // relative has change : apply pop state
		{
			if (tmp && tmp.hash !== current.hash)
				skipHashChange = true;
			return true;
		}
		else // path doesn't change. check hash
		if (tmp.hash !== current.hash && window.history.config.hashChangeAlone)
		{
			e.stopImmediatePropagation();
			return false; // skip popstate if config.hashChangeAlone
		}
		return true; // nothing change : refresh
	};

	var hashChange = function(e) {
		if (skipHashChange) // skip after pushState/replaceState (emulated)  OR  after "path change" from popstate (native),
		{
			skipHashChange = false;
			e.stopImmediatePropagation();
			return false;
		}
		//______________________________________________________ POP STATE EMULATION
		if (window.history.emulated) // do popstate behaviour
		{
			var state,
				data = null,
				tmp = window.history.location, // swap currentLocation
				current = window.history.location = parseURL(location.hash.substring(2));
			if (window.history.config.hid) // could be from back/next button or manual hash change in address bar.
			{
				cleanHidFromLocation(current); // try to extract hid
				if(!fromGo)
				{
					if (current.hid)
						state = window.history.store.find(current.hid);
					if(state)
						data = state.data || null;
					window.history.state = data;
				}
			}
			if(state && state.title)	// force title
				document.title = state.title;

			if (!tmp || tmp.path !== current.path) { // path == pathname + ? + search
				// path has change : dispatch popstate and skip hashchange
				e.stopImmediatePropagation();
				fireStateEvent("popstate", data);
				return false;
			}
			// path doesn't change.
			// check hash change : if !hashChangeAlone : dispatch popstate
			if (tmp.hash !== current.hash && !window.history.config.hashChangeAlone)
				fireStateEvent("popstate", data);
		}
		return true; // propagate hashchange
	};

	window.history.init = function(opt) {
		for (var i in opt)
			this.config[i] = opt[i];
		this.location = parseURL(window.location.href);
		window.addEventListener("hashchange", hashChange);
		if (!this.emulated)
			window.addEventListener("popstate", popState);
		if(this.config.hid)
		{
			this.store.init();
			window.addEventListener("unload", function() {
				window.history.store.save();
			});
		}
	};
})();<|endoftext|>


<commit_before>#!/usr/bin/env node
/**
 * Created by jcabresos on 4/29/2014.
 */

var domer = require('./src/domer');
var program = require('commander');
var path = require('path');
program
    .version('0.0.12');

program
    .usage("[watch] [source] [target]")
    .description('Domer, HTML to TypeScript Utility')
    .option("-s, --source [source]", "Defines the file pattern of html files. Default is *.html", path.join(process.cwd(), "*.html"))
    .option("-e, --encoding [target]", "Defines the encoding type of the source files. Default is utf8.", "utf8")
    .option("-m, --mode [mode]", "Defines how dompiler treat DOM ids [strip, resolve, retain]", "strip")
    .parse(process.argv);

var source = program.source;

var domerResource = new domer.DomerResource(source, program.encoding);

console.log("Source is: " + source);
console.log("Encoding is: " + program.encoding);

var options;

switch(program.mode) {
    case "resolve":
        options = domer.Mode.RESOLVE_IDS;
        console.log("setting mode to resolve ids");
        break;

    case "retain":
        options = domer.Mode.RETAIN_IDS;
        console.log("setting mode to retain ids");
        break;

    default:
        options = domer.Mode.STRIP_IDS;
        console.log("setting mode to strip ids");
        break;
}

try {
    new domer.Domer(domerResource, options).build();
}
catch(e) {
    console.error(e);
}

<commit_msg>refactor<commit_after>#!/usr/bin/env node

var domer = require('./src/domer');
var program = require('commander');
var path = require('path');
program
    .version('0.0.12');

program
    .usage("[watch] [source] [target]")
    .description('Domer, HTML to TypeScript Utility')
    .option("-s, --source [source]", "Defines the file pattern of html files. Default is *.html", path.join(process.cwd(), "*.html"))
    .option("-e, --encoding [target]", "Defines the encoding type of the source files. Default is utf8.", "utf8")
    .option("-m, --mode [mode]", "Defines how dompiler treat DOM ids [strip, resolve, retain]", "strip")
    .parse(process.argv);

var source = program.source;

var domerResource = new domer.DomerResource(source, program.encoding);

console.log("Source is: " + source);
console.log("Encoding is: " + program.encoding);

var options;

switch(program.mode) {
    case "resolve":
        options = domer.Mode.RESOLVE_IDS;
        console.log("setting mode to resolve ids");
        break;

    case "retain":
        options = domer.Mode.RETAIN_IDS;
        console.log("setting mode to retain ids");
        break;

    default:
        options = domer.Mode.STRIP_IDS;
        console.log("setting mode to strip ids");
        break;
}

try {
    new domer.Domer(domerResource, options).build();
}
catch(e) {
    console.error(e);
}

<|endoftext|>


<commit_before>export default {
  decimal: ",",
  thousands: ",",
  grouping: [3],
  currency: ["", "円"],
  date: "%Y/%m/%d",
  time: "%H:%M:%S",
  days: ["日曜日", "月曜日", "火曜日", "水曜日", "木曜日", "金曜日", "土曜日"],
  shortDays: ["日", "月", "火", "水", "木", "金", "土"],
  months: ["睦月", "如月", "弥生", "卯月", "皐月", "水無月", "文月", "葉月", "長月", "神無月", "霜月", "師走"],
  shortMonths: ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"]
};<commit_msg>Corrected decimal value.<commit_after>export default {
  decimal: ".",
  thousands: ",",
  grouping: [3],
  currency: ["", "円"],
  date: "%Y/%m/%d",
  time: "%H:%M:%S",
  days: ["日曜日", "月曜日", "火曜日", "水曜日", "木曜日", "金曜日", "土曜日"],
  shortDays: ["日", "月", "火", "水", "木", "金", "土"],
  months: ["睦月", "如月", "弥生", "卯月", "皐月", "水無月", "文月", "葉月", "長月", "神無月", "霜月", "師走"],
  shortMonths: ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"]
};<|endoftext|>


<commit_before>'use strict';
var Observable = require('../utils').Observable,
    metrics = require('../metrics'),
    metricPrefix = 'timer.user.',
    bcrypt = require('bcrypt-nodejs'),
    crypto = require('crypto');

module.exports = Observable.extend({
  constructor: function UserModel(store) {
    Observable.call(this);
    this.store = store;
  },
  applySettings: function (fn) {
    return function (err, user) {
      if (user) {
        if (user.settings === null) {
          user.settings = {};
        } else if (user && user.settings && typeof user.settings === 'string') {
          try {
            user.settings = JSON.parse(user.settings) || {};
          } catch (e) {
            user.settings = {};
          }
        }
      }
      fn(err, user);
    };
  },
  load: function (id, fn) {
    this.store.getUser(id, this.applySettings(fn));
  },
  getOne: function (queryKey, params, fn) {
    this.store.getOne(queryKey, params, this.applySettings(fn));
  },
  loadByApiKey: function (apiKey, fn) {
    this.store.getUserByApiKey(apiKey, this.applySettings(fn));
  },
  loadByEmail: function (email, fn) {
    this.store.getUserByEmail(email, this.applySettings(fn));
  },
  create: function (data, fn) {
    var store = this.store;

    this.hash(data.key, function (err, hash) {
      if (err) {
        return fn(err);
      }
      data.key = hash;
      store.setUser(data, this.applySettings(fn));
    }.bind(this));
  },
  updateEmail: function (id, email, fn) {
    this.store.updateUserEmail(id, email, fn);
  },
  getBinCount: function (id, fn) {
    this.store.getUserBinCount(id, fn);
  },
  updateGithubData: function (id, ghId, token, fn) {
    this.store.updateUserGithubData(id, ghId, token, fn);
  },
  setProAccount: function(id, val, fn){
    this.store.setProAccount(id, val, fn);
  },
  updateKey: function (id, key, fn, upgrade) {
    var store = this.store;
    this.hash(key, function (err, hash) {
      if (err) {
        return fn(err);
      }

      // We're upgrading an old account.
      if (upgrade === true) {
        store.upgradeUserKey(id, hash, fn);
      } else {
        store.updateUserKey(id, hash, fn);
      }
    });
  },
  // Upgrades the user from a JSBin 2 account.
  upgradeKey: function (id, key, fn) {
    this.updateKey(id, key, fn, true);
  },
  updateSettings: function (id, settings, fn) {
    this.store.updateUserSettings(id, settings, fn);
  },
  // FIXME !! This logic should be moved into bin model!!!!
  getLatestBin: function (id, n, username, fn) {
    var timer = metrics.createTimer(metricPrefix + 'getLatestBin');
    var original = fn;
    fn = function () {
      timer.stop();
      original.apply(this, [].slice.call(arguments));
    };
    n = Math.abs(parseInt(n)) || 0;
    this.store.getLatestBinForUser(id, n, function(err, bin) {
      if (bin === null) {
        return fn(404);
      }

      this.store.getBinMetadata(bin, function(err, metadata) {
        if (err) {
          return fn(err);
        }

        bin.metadata = metadata;

        if (this.isVisible(bin, username)) {
          fn(null, bin);
        } else {
          fn(401);
        }

      }.bind(this));

    }.bind(this));

  },
  // FIXME !! Duplicate logic between this and bin handler
  isVisible: function (bin, username) {
    if (!username) {
      username = '';
    }

    if (typeof username !== 'string') {
      throw new Error('isVisible requires name to be string');
    }

    // This will only occur if it isn't a real bin, it has been created
    // on from default files and does not exist in any database. By this
    // logic the bin must be public, it has no owner and no record.
    if (!bin || !bin.metadata) {
      return true;
    }
    // this should only let users see the latest
    // "active", and visible bin to that user
    if (bin && bin.active === 'y') {
      if (bin.metadata.visibility === 'public') {
        return true;
      }
      if (username && bin.metadata.name === username) {
        return true;
      }
    }

    return false;
  },
  getBins: function (id, fn) {
    var timer = metrics.createTimer(metricPrefix + 'getBins');
    var original = fn;
    fn = function () {
      timer.stop();
      original.apply(this, [].slice.call(arguments));
    };
    this.store.getBinsByUser(id, fn);
  },
  isOwnerOf: function (username, bin, fn) {
    var params = {
      name: username,
      url: bin.url,
      revision: bin.revision
    };
    this.store.isOwnerOf(params, fn);
  },
  setBinOwner: function (id, bin, fn) {
    var params = {
      name: id,
      url: bin.url,
      revision: bin.revision,
      summary: bin.summary,
      html: !!bin.html,
      css: !!bin.css,
      javascript: !!bin.javascript,
      visibility: bin.visibility
    };
    var timer = metrics.createTimer(metricPrefix + 'setBinOwner');
    var original = fn;
    fn = function () {
      timer.stop();
      original.apply(this, [].slice.call(arguments));
    };
    this.store.setBinOwner(params, fn);
  },
  touchLogin: function (id, fn) {
    var timer = metrics.createTimer(metricPrefix + 'touchLogin');
    var original = fn;
    fn = function () {
      timer.stop();
      original.apply(this, [].slice.call(arguments));
    };
    this.store.touchLogin(id, fn);
  },
  touchOwners: function (id, bin, fn) {
    var params = {
      name: id,
      url: bin.url,
      revision: bin.revision
    };
    var timer = metrics.createTimer(metricPrefix + 'touchOwners');
    var original = fn;
    fn = function () {
      timer.stop();
      original.apply(this, [].slice.call(arguments));
    };
    this.store.touchOwners(params, fn);
  },
  updateOwners: function (id, bin, fn) {
    var params = {
      name: id,
      url: bin.url,
      revision: bin.revision,
      summary: bin.summary,
      panel: bin.panel,
      panel_open: bin.panel_open // jshint ignore:line
    };
    var timer = metrics.createTimer(metricPrefix + 'updateOwners'); //
    var original = fn;
    fn = function () {
      timer.stop();
      original.apply(this, [].slice.call(arguments));
    };
    this.store.updateOwners(params, fn);
  },
  saveBookmark: function (user, bin, type, fn) {
    var params = {
      name: user.name,
      url: bin.url,
      revision: bin.revision,
      type: type
    };
    this.store.saveBookmark(params, fn);
  },
  getBookmark: function (user, type, fn) {
    var params = {
      name: user.name,
      type: type
    };
    this.store.getBookmark(params, fn);
  },
  valid: function (key, encrypted, fn) {
    return bcrypt.compare(key, encrypted, fn);
  },
  hash: function (key, fn) {
    bcrypt.genSalt(null, function (err, salt) {
      if (err) {
        return fn(err);
      }
      bcrypt.hash(key, salt, null, fn);
    });
  },
  validOldKey: function (key, encrypted, fn) {
    fn(null, encrypted === crypto.createHash('sha1').update(key).digest('hex'));
  },
  updateOwnershipData: function (username, params, fn) {
    this.store.updateOwnershipData([username], params, fn);
  },
});
<commit_msg>Add method for dropbox so we dont have to use db<commit_after>'use strict';
var Observable = require('../utils').Observable,
    metrics = require('../metrics'),
    metricPrefix = 'timer.user.',
    bcrypt = require('bcrypt-nodejs'),
    crypto = require('crypto');

module.exports = Observable.extend({
  constructor: function UserModel(store) {
    Observable.call(this);
    this.store = store;
  },
  applySettings: function (fn) {
    return function (err, user) {
      if (user) {
        if (user.settings === null) {
          user.settings = {};
        } else if (user && user.settings && typeof user.settings === 'string') {
          try {
            user.settings = JSON.parse(user.settings) || {};
          } catch (e) {
            user.settings = {};
          }
        }
      }
      fn(err, user);
    };
  },
  load: function (id, fn) {
    this.store.getUser(id, this.applySettings(fn));
  },
  getOne: function (queryKey, params, fn) {
    this.store.getOne(queryKey, params, this.applySettings(fn));
  },
  loadByApiKey: function (apiKey, fn) {
    this.store.getUserByApiKey(apiKey, this.applySettings(fn));
  },
  loadByEmail: function (email, fn) {
    this.store.getUserByEmail(email, this.applySettings(fn));
  },
  create: function (data, fn) {
    var store = this.store;

    this.hash(data.key, function (err, hash) {
      if (err) {
        return fn(err);
      }
      data.key = hash;
      store.setUser(data, this.applySettings(fn));
    }.bind(this));
  },
  updateEmail: function (id, email, fn) {
    this.store.updateUserEmail(id, email, fn);
  },
  getBinCount: function (id, fn) {
    this.store.getUserBinCount(id, fn);
  },
  updateGithubData: function (id, ghId, token, fn) {
    this.store.updateUserGithubData(id, ghId, token, fn);
  },
  updateDropboxData: function (id, token, fn) {
    this.store.updateUserDropboxData(id, token, fn);
  },
  setProAccount: function(id, val, fn){
    this.store.setProAccount(id, val, fn);
  },
  updateKey: function (id, key, fn, upgrade) {
    var store = this.store;
    this.hash(key, function (err, hash) {
      if (err) {
        return fn(err);
      }

      // We're upgrading an old account.
      if (upgrade === true) {
        store.upgradeUserKey(id, hash, fn);
      } else {
        store.updateUserKey(id, hash, fn);
      }
    });
  },
  // Upgrades the user from a JSBin 2 account.
  upgradeKey: function (id, key, fn) {
    this.updateKey(id, key, fn, true);
  },
  updateSettings: function (id, settings, fn) {
    this.store.updateUserSettings(id, settings, fn);
  },
  // FIXME !! This logic should be moved into bin model!!!!
  getLatestBin: function (id, n, username, fn) {
    var timer = metrics.createTimer(metricPrefix + 'getLatestBin');
    var original = fn;
    fn = function () {
      timer.stop();
      original.apply(this, [].slice.call(arguments));
    };
    n = Math.abs(parseInt(n)) || 0;
    this.store.getLatestBinForUser(id, n, function(err, bin) {
      if (bin === null) {
        return fn(404);
      }

      this.store.getBinMetadata(bin, function(err, metadata) {
        if (err) {
          return fn(err);
        }

        bin.metadata = metadata;

        if (this.isVisible(bin, username)) {
          fn(null, bin);
        } else {
          fn(401);
        }

      }.bind(this));

    }.bind(this));

  },
  // FIXME !! Duplicate logic between this and bin handler
  isVisible: function (bin, username) {
    if (!username) {
      username = '';
    }

    if (typeof username !== 'string') {
      throw new Error('isVisible requires name to be string');
    }

    // This will only occur if it isn't a real bin, it has been created
    // on from default files and does not exist in any database. By this
    // logic the bin must be public, it has no owner and no record.
    if (!bin || !bin.metadata) {
      return true;
    }
    // this should only let users see the latest
    // "active", and visible bin to that user
    if (bin && bin.active === 'y') {
      if (bin.metadata.visibility === 'public') {
        return true;
      }
      if (username && bin.metadata.name === username) {
        return true;
      }
    }

    return false;
  },
  getBins: function (id, fn) {
    var timer = metrics.createTimer(metricPrefix + 'getBins');
    var original = fn;
    fn = function () {
      timer.stop();
      original.apply(this, [].slice.call(arguments));
    };
    this.store.getBinsByUser(id, fn);
  },
  isOwnerOf: function (username, bin, fn) {
    var params = {
      name: username,
      url: bin.url,
      revision: bin.revision
    };
    this.store.isOwnerOf(params, fn);
  },
  setBinOwner: function (id, bin, fn) {
    var params = {
      name: id,
      url: bin.url,
      revision: bin.revision,
      summary: bin.summary,
      html: !!bin.html,
      css: !!bin.css,
      javascript: !!bin.javascript,
      visibility: bin.visibility
    };
    var timer = metrics.createTimer(metricPrefix + 'setBinOwner');
    var original = fn;
    fn = function () {
      timer.stop();
      original.apply(this, [].slice.call(arguments));
    };
    this.store.setBinOwner(params, fn);
  },
  touchLogin: function (id, fn) {
    var timer = metrics.createTimer(metricPrefix + 'touchLogin');
    var original = fn;
    fn = function () {
      timer.stop();
      original.apply(this, [].slice.call(arguments));
    };
    this.store.touchLogin(id, fn);
  },
  touchOwners: function (id, bin, fn) {
    var params = {
      name: id,
      url: bin.url,
      revision: bin.revision
    };
    var timer = metrics.createTimer(metricPrefix + 'touchOwners');
    var original = fn;
    fn = function () {
      timer.stop();
      original.apply(this, [].slice.call(arguments));
    };
    this.store.touchOwners(params, fn);
  },
  updateOwners: function (id, bin, fn) {
    var params = {
      name: id,
      url: bin.url,
      revision: bin.revision,
      summary: bin.summary,
      panel: bin.panel,
      panel_open: bin.panel_open // jshint ignore:line
    };
    var timer = metrics.createTimer(metricPrefix + 'updateOwners'); //
    var original = fn;
    fn = function () {
      timer.stop();
      original.apply(this, [].slice.call(arguments));
    };
    this.store.updateOwners(params, fn);
  },
  saveBookmark: function (user, bin, type, fn) {
    var params = {
      name: user.name,
      url: bin.url,
      revision: bin.revision,
      type: type
    };
    this.store.saveBookmark(params, fn);
  },
  getBookmark: function (user, type, fn) {
    var params = {
      name: user.name,
      type: type
    };
    this.store.getBookmark(params, fn);
  },
  valid: function (key, encrypted, fn) {
    return bcrypt.compare(key, encrypted, fn);
  },
  hash: function (key, fn) {
    bcrypt.genSalt(null, function (err, salt) {
      if (err) {
        return fn(err);
      }
      bcrypt.hash(key, salt, null, fn);
    });
  },
  validOldKey: function (key, encrypted, fn) {
    fn(null, encrypted === crypto.createHash('sha1').update(key).digest('hex'));
  },
  updateOwnershipData: function (username, params, fn) {
    this.store.updateOwnershipData([username], params, fn);
  },
});
<|endoftext|>


<commit_before>/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/
var Template = require("../Template");

function WebWorkerMainTemplatePlugin() {
}
module.exports = WebWorkerMainTemplatePlugin;

WebWorkerMainTemplatePlugin.prototype.apply = function(mainTemplate) {
	mainTemplate.plugin("local-vars", function(source, chunk) {
		if(chunk.chunks.length > 0) {
			return this.asString([
				source,
				"",
				"// object to store loaded chunks",
				"// \"1\" means \"already loaded\"",
				"var installedChunks = {",
				this.indent(
					chunk.ids.map(function(id) {
						return id + ":1";
					}).join(",\n")
				),
				"};"
			]);
		}
		return source;
	});
	mainTemplate.plugin("require-ensure", function(_, chunk, hash) {
		var filename = this.outputOptions.filename || "bundle.js";
		var chunkFilename = this.outputOptions.chunkFilename || "[id]." + filename;
		return this.asString([
			"// \"1\" is the signal for \"already loaded\"",
			"if(!installedChunks[chunkId]) {",
			this.indent([
				"importScripts(" +
					this.applyPluginsWaterfall("asset-path", JSON.stringify(chunkFilename), {
						hash: "\" + " + this.renderCurrentHashCode(hash) + " + \"",
						hashWithLength: function(length) {
							return "\" + " + this.renderCurrentHashCode(hash, length) + " + \"";
						}.bind(this),
						chunk: {
							id: "\" + chunkId + \""
						}
					}) + ");"
			]),
			"}",
			"callback.call(null, " + this.requireFn + ");"
		]);
	});
	mainTemplate.plugin("bootstrap", function(source, chunk, hash) {
		if(chunk.chunks.length > 0) {
			var chunkCallbackName = this.outputOptions.chunkCallbackName || Template.toIdentifier("webpackChunk" + (this.outputOptions.library || ""));
			return this.asString([
				source,
				"this[" + JSON.stringify(chunkCallbackName) + "] = function webpackChunkCallback(chunkIds, moreModules) {",
				this.indent([
					"for(var moduleId in moreModules) {",
					this.indent(this.renderAddModule(hash, chunk, "moduleId", "moreModules[moduleId]")),
					"}",
					"while(chunkIds.length)",
					this.indent("installedChunks[chunkIds.pop()] = 1;")
				]),
				"};"
			]);
		}
		return source;
	});
	mainTemplate.plugin("hash", function(hash) {
		hash.update("webworker");
		hash.update("3");
		hash.update(this.outputOptions.publicPath + "");
		hash.update(this.outputOptions.filename + "");
		hash.update(this.outputOptions.chunkFilename + "");
		hash.update(this.outputOptions.chunkCallbackName + "");
		hash.update(this.outputOptions.library + "");
	});
};
<commit_msg>fixed WebWorker template<commit_after>/*
	MIT License http://www.opensource.org/licenses/mit-license.php
	Author Tobias Koppers @sokra
*/
var Template = require("../Template");

function WebWorkerMainTemplatePlugin() {
}
module.exports = WebWorkerMainTemplatePlugin;

WebWorkerMainTemplatePlugin.prototype.apply = function(mainTemplate) {
	mainTemplate.plugin("local-vars", function(source, chunk) {
		if(chunk.chunks.length > 0) {
			return this.asString([
				source,
				"",
				"// object to store loaded chunks",
				"// \"1\" means \"already loaded\"",
				"var installedChunks = {",
				this.indent(
					chunk.ids.map(function(id) {
						return id + ": 1";
					}).join(",\n")
				),
				"};"
			]);
		}
		return source;
	});
	mainTemplate.plugin("require-ensure", function(_, chunk, hash) {
		var filename = this.outputOptions.filename || "bundle.js";
		var chunkFilename = this.outputOptions.chunkFilename || "[id]." + filename;
		return this.asString([
			"// \"1\" is the signal for \"already loaded\"",
			"if(!installedChunks[chunkId]) {",
			this.indent([
				"importScripts(" +
					this.applyPluginsWaterfall("asset-path", JSON.stringify(chunkFilename), {
						hash: "\" + " + this.renderCurrentHashCode(hash) + " + \"",
						hashWithLength: function(length) {
							return "\" + " + this.renderCurrentHashCode(hash, length) + " + \"";
						}.bind(this),
						chunk: {
							id: "\" + chunkId + \""
						}
					}) + ");"
			]),
			"}",
			"return Promise.resolve();"
		]);
	});
	mainTemplate.plugin("bootstrap", function(source, chunk, hash) {
		if(chunk.chunks.length > 0) {
			var chunkCallbackName = this.outputOptions.chunkCallbackName || Template.toIdentifier("webpackChunk" + (this.outputOptions.library || ""));
			return this.asString([
				source,
				"this[" + JSON.stringify(chunkCallbackName) + "] = function webpackChunkCallback(chunkIds, moreModules) {",
				this.indent([
					"for(var moduleId in moreModules) {",
					this.indent(this.renderAddModule(hash, chunk, "moduleId", "moreModules[moduleId]")),
					"}",
					"while(chunkIds.length)",
					this.indent("installedChunks[chunkIds.pop()] = 1;")
				]),
				"};"
			]);
		}
		return source;
	});
	mainTemplate.plugin("hash", function(hash) {
		hash.update("webworker");
		hash.update("3");
		hash.update(this.outputOptions.publicPath + "");
		hash.update(this.outputOptions.filename + "");
		hash.update(this.outputOptions.chunkFilename + "");
		hash.update(this.outputOptions.chunkCallbackName + "");
		hash.update(this.outputOptions.library + "");
	});
};
<|endoftext|>


<commit_before>$(document).ready(function() {
  $('#organisms').change(function() {
    var orgId = $(this).val();

    $.get('/neat/organism/', {organism_id: orgId}, function(data) {
      var org = jQuery.parseJSON(data);

      $('#fitness').html(org.fitness);
      $('#rank').html(org.rank);

      var network = jQuery.parseJSON(org.network);
      var table = '

Inode	Onode	Weight	Enabled		';

      $('#input').html(network.input);
      $('#hidden').html(network.hidden);
      $('#output').html(network.output);

      $.each(network.genes, function() {
        table += '
';
        table += '' + this['inode'] + '	';
        table += '' + this['onode'] + '	';
        table += '' + this['weight'] + '	';
        table += '' + this['enabled'] + '	';
        table += '
';
      });

      table += '
';

      $('#genes').html(table);
    });
  });

  $('#species').change(function() {
    var specId = $(this).val();

    $.get('/neat/species/', {species_id: specId}, function(data) {
      var spec = jQuery.parseJSON(data);
      var updateAction = $('#spec_form').attr('action');
      var oldId = /.*\/(species-\d+)$/.exec(updateAction)[1];

      $('#spec_form').attr('action', updateAction.replace(oldId, 'species-'.concat(specId)));

      $('#organisms').html(spec.org_count)
      $('#avg_fitness').html(spec.avg_fitness)
      $('#max_fitness').html(spec.max_fitness)
      $('#offspring').html(spec.offspring)
      $('#age_since_imp').html(spec.age_since_imp)
    });
  });

  $('#generations').change(function() {
    var genId = $(this).val();

    $.get('/neat/generation/', {generation_id: genId}, function(data) {
      var gen = jQuery.parseJSON(data);
      var updateAction = $('#gen_form').attr('action');
      var oldId = /.*\/(generation-\d+)$/.exec(updateAction)[1];

      $('#gen_form').attr('action', updateAction.replace(oldId, 'generation-'.concat(genId)));

      if (gen.winner) {
        $('#status').html('A winner was found!');
      } else {
        $('#status').html('A winner was not found!');
      }
    });
  });

  $('#experiments').change(function() {
    var expId = $(this).val();

    $.get('/neat/experiment/', {experiment_id: expId}, function(data) {
      var conf;

      conf = jQuery.parseJSON(data);

      $('#exp_form').attr('action', '/neat/experiment-'.concat(expId))

      $('#name').val(conf.name);
      $('#runs').val(conf.runs);
      $('#pop_size').val(conf.pop_size);
      $('#generations').val(conf.generations);
      $('#input').val(conf.num_input);
      $('#output').val(conf.num_output);
      $('#mut_power').val(conf.mutate_power);
      $('#coef_matching').val(conf.coef_matching);
      $('#coef_disjoint').val(conf.ceof_disjoint);
      $('#compat_threshold').val(conf.compat_threshold);
      $('#mut_neuron').val(conf.mutate_neuron_prob);
      $('#mut_gene').val(conf.mutate_gene_prob);
      $('#mut_only').val(conf.mutate_only_prob);
      $('#mate_only').val(conf.mate_only_prob);
      $('#survival').val(conf.survival_rate);
      $('#stagnation').val(conf.stagnation_threshold);
      $('#data').html(conf.data);
      $('#fitness').html(conf.fitness_func);

      $('#test').html(data)
    });
  });
});
<commit_msg>Adds exception handling for failed json parsing<commit_after>$(document).ready(function() {
  $('#organisms').change(function() {
    var orgId = $(this).val();

    $.get('/neat/organism/', {organism_id: orgId}, function(data) {
      var org = jQuery.parseJSON(data);

      $('#fitness').html(org.fitness);
      $('#rank').html(org.rank);

      try {
        var network = jQuery.parseJSON(org.network);
        var table = '

Inode	Onode	Weight	Enabled		';

        $('#input').html(network.input);
        $('#hidden').html(network.hidden);
        $('#output').html(network.output);

        $.each(network.genes, function() {
          table += '
';
          table += '' + this['inode'] + '	';
          table += '' + this['onode'] + '	';
          table += '' + this['weight'] + '	';
          table += '' + this['enabled'] + '	';
          table += '
';
        });

        table += '
';

        $('#genes').html(table);
      }
      catch (err) {
        $('#genes').html(err.message);
      }
    });
  });

  $('#species').change(function() {
    var specId = $(this).val();

    $.get('/neat/species/', {species_id: specId}, function(data) {
      var spec = jQuery.parseJSON(data);
      var updateAction = $('#spec_form').attr('action');
      var oldId = /.*\/(species-\d+)$/.exec(updateAction)[1];

      $('#spec_form').attr('action', updateAction.replace(oldId, 'species-'.concat(specId)));

      $('#organisms').html(spec.org_count)
      $('#avg_fitness').html(spec.avg_fitness)
      $('#max_fitness').html(spec.max_fitness)
      $('#offspring').html(spec.offspring)
      $('#age_since_imp').html(spec.age_since_imp)
    });
  });

  $('#generations').change(function() {
    var genId = $(this).val();

    $.get('/neat/generation/', {generation_id: genId}, function(data) {
      var gen = jQuery.parseJSON(data);
      var updateAction = $('#gen_form').attr('action');
      var oldId = /.*\/(generation-\d+)$/.exec(updateAction)[1];

      $('#gen_form').attr('action', updateAction.replace(oldId, 'generation-'.concat(genId)));

      if (gen.winner) {
        $('#status').html('A winner was found!');
      } else {
        $('#status').html('A winner was not found!');
      }
    });
  });

  $('#experiments').change(function() {
    var expId = $(this).val();

    $.get('/neat/experiment/', {experiment_id: expId}, function(data) {
      var conf;

      conf = jQuery.parseJSON(data);

      $('#exp_form').attr('action', '/neat/experiment-'.concat(expId))

      $('#name').val(conf.name);
      $('#runs').val(conf.runs);
      $('#pop_size').val(conf.pop_size);
      $('#generations').val(conf.generations);
      $('#input').val(conf.num_input);
      $('#output').val(conf.num_output);
      $('#mut_power').val(conf.mutate_power);
      $('#coef_matching').val(conf.coef_matching);
      $('#coef_disjoint').val(conf.ceof_disjoint);
      $('#compat_threshold').val(conf.compat_threshold);
      $('#mut_neuron').val(conf.mutate_neuron_prob);
      $('#mut_gene').val(conf.mutate_gene_prob);
      $('#mut_only').val(conf.mutate_only_prob);
      $('#mate_only').val(conf.mate_only_prob);
      $('#survival').val(conf.survival_rate);
      $('#stagnation').val(conf.stagnation_threshold);
      $('#data').html(conf.data);
      $('#fitness').html(conf.fitness_func);

      $('#test').html(data)
    });
  });
});
<|endoftext|>


<commit_before>import Ember from 'ember';

const {
  computed,
  inject,
  isEmpty,
  isPresent,
  merge,
  on,
  Service
} = Ember;

export default Service.extend({
  activeState: computed(() => Ember.Object.create()),
  statePoints: computed(() => Ember.A()),
  store: inject.service(),

  initializeState: on('init', async function() {
    const autosave = await this.get('autosave');

    if (isPresent(autosave)) {
      this.loadRecord(autosave);
    }
  }),

  autosave: computed({
    get: async function() {
      let autosave = await this.get('store').queryRecord('ember-theater-local-save', {
        name: 'autosave'
      });

      if (isEmpty(autosave)) {
        autosave = await this.createRecord('autosave');
      }

      return autosave;
    }
  }).readOnly(),

  saves: computed({
    get: async function() {
      return await this.get('store').findAll('ember-theater-local-save');
    }
  }).readOnly(),

  resetAutosave: async function() {
    const autosave = await this.get('autosave');

    this.get('statePoints').clear();
    this.set('activeState', Ember.Object.create());

    this.updateRecord(autosave);
  },

  // RECORD MANAGEMENT //
  createRecord: async function(name) {
    const statePoints = Ember.$.extend([], this.get('statePoints'));
    const record = this.get('store').createRecord('ember-theater-local-save', {
      name,
      statePoints
    });

    return await record.save();
  },

  deleteRecord: async function(record) {
    return await record.destroyRecord();
  },

  loadRecord(record) {
    const { activeState, statePoints } = record.getProperties('activeState', 'statePoints');

    this.setProperties({ activeState, statePoints });
  },

  updateRecord: async function(record) {
    const statePoints = Ember.$.extend([], this.get('statePoints'));

    record.set('statePoints', statePoints);

    return await record.save();
  },

  // STATE MANAGEMENT //
  appendActiveState(optionalValues) {
    const activeState = this.get('activeState');
    const mergedState = merge(optionalValues, activeState);

    this.get('statePoints').pushObject(mergedState);
  },

  deleteStateValue(key) {
    return this.setStateValue(key, undefined);
  },

  getStateValue(key) {
    return this.get(`activeState.${key}`);
  },

  setStateValue(key, value) {
    return this.set(`activeState.${key}`, value);
  }
});
<commit_msg>fix autosave<commit_after>import Ember from 'ember';

const {
  computed,
  inject,
  isEmpty,
  isPresent,
  merge,
  on,
  Service
} = Ember;

export default Service.extend({
  activeState: computed(() => Ember.Object.create()),
  statePoints: computed(() => Ember.A()),
  store: inject.service(),

  initializeState: on('init', async function() {
    const autosave = await this.get('autosave');

    if (isPresent(autosave)) {
      this.loadRecord(autosave);
    }
  }),

  autosave: computed({
    get: async function() {
      let autosave = await this.get('store').queryRecord('ember-theater-local-save', {
        name: 'autosave'
      });

      if (isEmpty(autosave)) {
        autosave = await this.createRecord('autosave');
      }

      return autosave;
    }
  }).readOnly(),

  saves: computed({
    get: async function() {
      return await this.get('store').findAll('ember-theater-local-save');
    }
  }).readOnly(),

  resetAutosave: async function() {
    const autosave = await this.get('autosave');

    this.get('statePoints').clear();
    this.set('activeState', Ember.Object.create());

    this.updateRecord(autosave);
  },

  // RECORD MANAGEMENT //
  createRecord: async function(name) {
    const statePoints = Ember.$.extend([], this.get('statePoints'));
    const record = this.get('store').createRecord('ember-theater-local-save', {
      name,
      statePoints
    });

    return await record.save();
  },

  deleteRecord: async function(record) {
    return await record.destroyRecord();
  },

  loadRecord(record) {
    const { activeState, statePoints } = record.getProperties('activeState', 'statePoints');

    this.setProperties({ activeState, statePoints });
  },

  updateRecord: async function(record) {
    const statePoints = Ember.$.extend([], this.get('statePoints'));

    record.set('statePoints', statePoints);

    return await record.save();
  },

  // STATE MANAGEMENT //
  appendActiveState(optionalValues) {
    const activeState = Ember.$.extend({}, this.get('activeState'));
    const mergedState = merge(activeState, optionalValues);

    this.get('statePoints').pushObject(mergedState);
  },

  deleteStateValue(key) {
    return this.setStateValue(key, undefined);
  },

  getStateValue(key) {
    return this.get(`activeState.${key}`);
  },

  setStateValue(key, value) {
    return this.set(`activeState.${key}`, value);
  }
});
<|endoftext|>