<commit_before>import {VISITOR_KEYS} from "babel-types"

export const Tag = {push:{$:"push"},top:{$:"top"},Array:{$:"Array"}}

for(const i in VISITOR_KEYS) {
  Tag[i] = {$:i}
  for (const j of VISITOR_KEYS[i])
    Tag[j] = {$:j}
}

function isNode(node) {
  if (node == null)
    return false;
  return typeof node === 'object' && typeof node.type === 'string';
}

export function* produce(node,pos) {
  function* walk(value,pos) {
    if (Array.isArray(value)) {
      yield {enter: true, leave: false, value, pos, type: Tag.Array}
      for(const i of value)
        yield* walk(i,Tag.push)
      yield {enter: false, leave: true, value, pos, type: Tag.Array}
    } else if (isNode(value)) {
      const keys = VISITOR_KEYS[value.type]
      const type = Tag[value.type]
      if (keys.length) {
        yield {enter: true, leave: false, value, pos, type}
        for(const i of keys) {
          const v = value[i]
          if (v != null)
            yield* walk(value[i],Tag[i] || i)
        }
        yield {enter: false, leave: true, value, pos, type}
      } else {
        yield {enter: true, leave: true, value, pos, type}
      }
    }
  }
  yield* walk(node,pos || Tag.top)
}

export function consume(s) {
  const stack = [{}]
  for (const i of s) {
    if (i.type == null || !Tag[i.type.$])
      continue
    if (i.enter) {
      i.value.type = i.type.$
      if (i.type === Tag.Array)
        stack.unshift([])
      else
        stack.unshift(i.value)
    }
    if (i.leave) {
      const value = stack.shift()
      if (i.pos === Tag.push) {
        stack[0].push(value)
      } else
        stack[0][i.pos.$] = value
    }
  }
  return stack[0]
}

<commit_msg>shared data field<commit_after>import {VISITOR_KEYS} from "babel-types"

export const Tag = {push:{$:"push"},top:{$:"top"},Array:{$:"Array"}}

for(const i in VISITOR_KEYS) {
  Tag[i] = {$:i}
  for (const j of VISITOR_KEYS[i])
    Tag[j] = {$:j}
}

function isNode(node) {
  if (node == null)
    return false;
  return typeof node === 'object' && typeof node.type === 'string';
}

export function* produce(node,pos) {
  function* walk(value,pos) {
    if (Array.isArray(value)) {
      const data = {}
      yield {enter: true, leave: false, value, pos, type: Tag.Array,data}
      for(const i of value)
        yield* walk(i,Tag.push)
      yield {enter: false, leave: true, value, pos, type: Tag.Array,data}
    } else if (isNode(value)) {
      const keys = VISITOR_KEYS[value.type]
      const type = Tag[value.type]
      if (keys.length) {
        const data = {}
        yield {enter: true, leave: false, value, pos, type, data}
        for(const i of keys) {
          const v = value[i]
          if (v != null)
            yield* walk(value[i],Tag[i] || i)
        }
        yield {enter: false, leave: true, value, pos, type, data}
      } else {
        yield {enter: true, leave: true, value, pos, type, data: {}}
      }
    }
  }
  yield* walk(node,pos || Tag.top)
}

export function consume(s) {
  const stack = [{}]
  for (const i of s) {
    if (i.type == null || !Tag[i.type.$])
      continue
    if (i.enter) {
      if (!i.value.type)
        i.value.type = i.type.$
      if (i.type === Tag.Array)
        stack.unshift([])
      else
        stack.unshift(i.value)
    }
    if (i.leave) {
      const value = stack.shift()
      if (i.pos === Tag.push) {
        stack[0].push(value)
      } else
        stack[0][i.pos.$] = value
    }
  }
  return stack[0]
}

<|endoftext|>


<commit_before>import hoistNonReactStatics from 'hoist-non-react-statics';
import {
  Component,
  createElement,
  PropTypes,
} from 'react';

// id counter to be used for various things that require unique identifiers
var idCounter = 0;
function nextId() {
  return idCounter++;
}

// a stateful connection id, incremented for each connection.
var connIdCounter = 0;

// map of each connection to an object containing keys:
// - ready (boolean)
// - user (user ident - two-tuple)
// - anonymous (boolean)
var connStatus = {};

// a map of each component ID to it's object
var componentIdx = {};

// for async calls to the worker, maintains the callback to execute with the result, when applicable
var callbackRegistry = {};

// holds worker reference globally. Don't initiate until first request for connection
var fqlWorker;

// worker.onmessage handler
function workerMessageHandler(e) {
  const msg = e.data;
  var cb;
  console.log("Worker received message: " + JSON.stringify(msg));

  switch (msg.event) {

    case "connReady":
      if (connStatus[msg.conn]) {
        connStatus[msg.conn].ready = true;
      }
      return;

    case "connClosed":
      cb = callbackRegistry[msg.ref];
      if (cb) {
        delete callbackRegistry[msg.ref];
        cb(msg.data);
      }
      return;

    case "connLogout":
      cb = callbackRegistry[msg.ref];
      if (cb) {
        delete callbackRegistry[msg.ref];
        cb(msg.data);
      }
      return;

    case "setState":
      const comp = componentIdx[msg.ref];
      if (comp) {
        comp.setState(msg.data);
      } else {
        console.warn("Component no longer registered: " + msg.ref);
      }
      return;

    case "remoteInvoke":
      // check for a callback
      cb = callbackRegistry[msg.ref];
      if (cb) {
        delete callbackRegistry[msg.ref];
        cb(msg.data);
      }
      return;

    case "login":
      // if login successful,  update conn's connStatus
      if (msg.data.status === 200) {
        connStatus[msg.conn].user = msg.data.body.user;
        connStatus[msg.conn].anonymous = msg.data.body.anonymous;
      }
      // if there was a callback passed to login(), execute
      cb = callbackRegistry[msg.ref];
      if (cb) {
        delete callbackRegistry[msg.ref];
        cb(msg.data);
      }
      return;

    default:
      console.warn("Unreconized event from worker: " + msg.event + ". Full message: " + JSON.stringify(msg));
  }
}

function setStateCb(conn, id, stateUpdate) {

  const comp = componentIdx[id];

  if (comp) {
    comp.setState(stateUpdate);
  } else {
    console.warn("Component no longer registered: " + compId);
  }
}

// we use a global to track connection state, get method for it
function isReady(connId) {
  return connStatus[connId].ready;
}

// we use a global to track connection state, get method for it
function isClosed(connId) {
  const connObj = connStatus[connId];
  return (connObj && Object.keys(connObj).length === 0);
}

function workerInvoke(obj) {
  if (obj.cb) {
    obj.ref = obj.ref || nextId();
    callbackRegistry[obj.ref] = obj.cb;
    delete obj.cb;
  }
  fqlWorker.postMessage(obj);
  return true;
}

// Register a query, provide the connection, component ID, query and query options
export function registerQuery(conn, compId, query, opts) {
  const invokeObj = {
    conn: conn.id,
    action: "registerQuery",
    ref: compId,
    params: [compId, query, opts]
  };
  return workerInvoke(invokeObj);
}

// Remove query from registry
export function unregisterQuery(conn, compId) {
  workerInvoke({
    conn: conn.id,
    ref: compId,
    action: "unregisterQuery",
    params: [compId]
  });
}

// Create a new connection with settings object.
// need to provide url, instance and token keys at minumumb.
export function ReactConnect(connSettings) {

  // initialize worker if not already done
  if (!fqlWorker) {
    fqlWorker = new Worker(connSettings.workerUrl || "/fqlClient.js");
    fqlWorker.onmessage = workerMessageHandler;
  }

  connIdCounter++;

  const connId = connIdCounter;

  const baseSetting = {
    id: connId,
    removeNamespace: true // by default remove namespace from results
  };

  const settings = Object.assign(baseSetting, connSettings);

  const conn = {
    id: connId,
    isReady: () => isReady(connId),
    isClosed: () => isClosed(connId),
    login: (username, password, cb) => workerInvoke({
      conn: connId,
      action: "login",
      params: [username, password],
      cb: cb
    }),
    invoke: function (action, params, cb) {
      const invokeStatment = [action, params];
      return workerInvoke({
        conn: connId,
        action: "remoteInvoke",
        params: [invokeStatment],
        cb: cb
      });
    },
    getUser: function () {
      return connStatus[connId].user;
    },
    getInstance: function () {
      return connSettings.instance;
    },
    isAuthenticated: function () {
      if (connStatus[connId].anonymous === false) {
        return true;
      } else {
        return false;
      }
    },
    reset: function (cb) {
      connStatus[connId] = {
        ready: false,
        user: null,
        anonymous: true
      };
      return workerInvoke({
        conn: connId,
        action: "reset",
        params: [],
        cb: cb
      });
    },
    logout: function (cb) {
      connStatus[connId] = {
        ready: false,
        user: null,
        anonymous: true
      };
      return workerInvoke({
        conn: connId,
        action: "logout",
        params: [],
        cb: cb
      });
    },
    close: function (cb) {
      // clear out connection state held locally
      connStatus[connId] = {};
      return workerInvoke({
        conn: connId,
        action: "close",
        params: [],
        cb: cb
      });
    }
  };

  // initialize connection status, set ready to false
  connStatus[connId] = {
    ready: false,
    // if we already passed in a token, can also pass in the user/anonymous flags for storing
    user: connSettings.user,
    anonymous: connSettings.anonymous
  };

  // initiate our connection in the web worker
  workerInvoke({
    conn: 0, // conn 0 means not connection specific
    action: "connect",
    params: [settings]
  });

  // return connection object
  return conn;
}

function getDisplayName(component) {
  return component.displayName || component.name || "Component";
}

// wraps react components that need a particular connection, making the
// connection available via the context to children
export class FlureeProvider extends Component {

  static propTypes = {
    conn: PropTypes.object.isRequired
  };

  static childContextTypes = {
    conn: PropTypes.object.isRequired
  };

  constructor(props, context) {
    super(props, context);

    if (!props.conn) {
      throw "FlureeProvider was not provided a conn prop, which should be a connection object."
    }

    this.conn = props.conn;
  };

  getChildContext() {

    return {
      conn: this.conn
    }
  };

  render() {
    return React.Children.only(this.props.children);
  };
}

// given a query and options, returns a vector of variables that
// were not provided via options. We use this to look for the variables
// in props
function getMissingVars(flurQL, opts) {

  const vars = flurQL.vars;

  if (!vars || !Array.isArray(vars)) {
    return [];
  }

  if (opts && opts.vars) {
    return vars.filter((v) => { return !opts.vars[v]; });
  } else {
    return vars;
  }
}

// Create an empty map of the top level query nodes so less
// boilerplate is required to test if a property exists in the
// wrapped component
function fillDefaultResult(query) {

  if (!query) return {};

  const graph = query.graph || query;

  if (!Array.isArray(graph)) { // invalid graph
    return;
  }

  var defaultResult = {};

  graph.map(([stream, opts]) => {
    if (opts.as) {
      defaultResult[opts.as] = null;
    } else {
      defaultResult[stream] = null;
    }
  });

  return defaultResult;
}

function wrapComponent(WrappedComponent, query, opts) {

  const flurQLDisplayName = `Fluree(${getDisplayName(WrappedComponent)})`;

  class FlurQL extends Component {
    static displayName = flurQLDisplayName;
    static WrappedComponent = WrappedComponent;
    static contextTypes = {
      conn: PropTypes.object.isRequired
    };

    constructor(props, context) {
      super(props, context);
      this.conn = context.conn;
      this.opts = Object.assign({ vars: {} }, opts);
      this.id = nextId();
      this.queryIsFunction = (typeof query === "function")
      this.query = this.queryIsFunction ? query(props, this.context) : query;
      this.missingVars = this.query ? getMissingVars(this.query, this.opts) : []; // list of vars we need to check props for
      this.state = {
        result: fillDefaultResult(this.query),
        error: null,
        warning: null,
        status: null,
        loading: true
      };

      if (!this.conn) {
        throw "Could not find a Fluree connection (conn) in the context of " + flurQLDisplayName + ".";
      }
    }

    componentWillMount() {
      // get any missing vars from props and update this.opts with them
      if (this.missingVars.length !== 0) {
        this.missingVars.map((v) => { this.opts.vars[v] = this.props[v] });
      }

      // register this component for later re-render calling, etc.
      componentIdx[this.id] = this;

      registerQuery(this.conn, this.id, this.query, this.opts);

    }

    componentWillUnmount() {

      unregisterQuery(this.conn, this.id);
      delete componentIdx[this.id];

    }

    componentWillReceiveProps(nextProps) {
      if (this.queryIsFunction) {
        const newQuery = query(nextProps, this.context);
        this.query = newQuery;
        registerQuery(this.conn, this.id, this.query, this.opts);
      } else {
        // check if any of the missing vars changed with the new props
        let didMissingVarsChange = false;

        for (let i = 0; i < this.missingVars.length; i++) {
          const varName = this.missingVars[i];
          if (this.props[varName] !== nextProps[varName]) {
            didMissingVarsChange = true;
          }
        }

        if (didMissingVarsChange === true) {
          this.missingVars.map((v) => {
            this.opts.vars[v] = nextProps[v];
            return;
          });
          registerQuery(this.conn, this.id, this.query, this.opts);
        }
      }
    }

    render() {
      const result = this.state.result;
      const data = {
        id: this.id,
        result: result,
        error: this.state.error,
        warning: this.state.warning,
        status: this.state.status,
        loading: this.state.status !== "loaded",
        get: function (keySeq, defaultVal) {
          keySeq = Array.isArray(keySeq) ? keySeq : [keySeq];
          let obj = result;
          let idx = 0;
          const length = keySeq.length;

          while (obj != null && idx < length) {
            obj = obj[keySeq[idx++]];
          }

          return (idx == length && obj !== undefined) ? obj : defaultVal;
        }
      };

      const childProps = Object.assign({}, this.props, { data: data, invoke: this.conn.invoke });

      return createElement(WrappedComponent, childProps);
    }
  }

  return hoistNonReactStatics(FlurQL, WrappedComponent, {});
}

export function flureeQL(query, opts) {
  return function (WrappedComponent) {
    return wrapComponent(WrappedComponent, query, opts);
  }
}

<commit_msg>Improved handling of null or invalid queries<commit_after>import hoistNonReactStatics from 'hoist-non-react-statics';
import {
  Component,
  createElement,
  PropTypes,
} from 'react';

// id counter to be used for various things that require unique identifiers
var idCounter = 0;
function nextId() {
  return idCounter++;
}

// a stateful connection id, incremented for each connection.
var connIdCounter = 0;

// map of each connection to an object containing keys:
// - ready (boolean)
// - user (user ident - two-tuple)
// - anonymous (boolean)
var connStatus = {};

// a map of each component ID to it's object
var componentIdx = {};

// for async calls to the worker, maintains the callback to execute with the result, when applicable
var callbackRegistry = {};

// holds worker reference globally. Don't initiate until first request for connection
var fqlWorker;

// worker.onmessage handler
function workerMessageHandler(e) {
  const msg = e.data;
  var cb;
  console.log("Worker received message: " + JSON.stringify(msg));

  switch (msg.event) {

    case "connReady":
      if (connStatus[msg.conn]) {
        connStatus[msg.conn].ready = true;
      }
      return;

    case "connClosed":
      cb = callbackRegistry[msg.ref];
      if (cb) {
        delete callbackRegistry[msg.ref];
        cb(msg.data);
      }
      return;

    case "connLogout":
      cb = callbackRegistry[msg.ref];
      if (cb) {
        delete callbackRegistry[msg.ref];
        cb(msg.data);
      }
      return;

    case "setState":
      const comp = componentIdx[msg.ref];
      if (comp) {
        comp.setState(msg.data);
      } else {
        console.warn("Component no longer registered: " + msg.ref);
      }
      return;

    case "remoteInvoke":
      // check for a callback
      cb = callbackRegistry[msg.ref];
      if (cb) {
        delete callbackRegistry[msg.ref];
        cb(msg.data);
      }
      return;

    case "login":
      // if login successful,  update conn's connStatus
      if (msg.data.status === 200) {
        connStatus[msg.conn].user = msg.data.body.user;
        connStatus[msg.conn].anonymous = msg.data.body.anonymous;
      }
      // if there was a callback passed to login(), execute
      cb = callbackRegistry[msg.ref];
      if (cb) {
        delete callbackRegistry[msg.ref];
        cb(msg.data);
      }
      return;

    default:
      console.warn("Unreconized event from worker: " + msg.event + ". Full message: " + JSON.stringify(msg));
  }
}

function setStateCb(conn, id, stateUpdate) {

  const comp = componentIdx[id];

  if (comp) {
    comp.setState(stateUpdate);
  } else {
    console.warn("Component no longer registered: " + compId);
  }
}

// we use a global to track connection state, get method for it
function isReady(connId) {
  return connStatus[connId].ready;
}

// we use a global to track connection state, get method for it
function isClosed(connId) {
  const connObj = connStatus[connId];
  return (connObj && Object.keys(connObj).length === 0);
}

function workerInvoke(obj) {
  if (obj.cb) {
    obj.ref = obj.ref || nextId();
    callbackRegistry[obj.ref] = obj.cb;
    delete obj.cb;
  }
  fqlWorker.postMessage(obj);
  return true;
}

// Register a query, provide the connection, component ID, query and query options
export function registerQuery(conn, compId, query, opts) {
  const invokeObj = {
    conn: conn.id,
    action: "registerQuery",
    ref: compId,
    params: [compId, query, opts]
  };
  return workerInvoke(invokeObj);
}

// Remove query from registry
export function unregisterQuery(conn, compId) {
  workerInvoke({
    conn: conn.id,
    ref: compId,
    action: "unregisterQuery",
    params: [compId]
  });
}

// Create a new connection with settings object.
// need to provide url, instance and token keys at minumumb.
export function ReactConnect(connSettings) {

  // initialize worker if not already done
  if (!fqlWorker) {
    fqlWorker = new Worker(connSettings.workerUrl || "/fqlClient.js");
    fqlWorker.onmessage = workerMessageHandler;
  }

  connIdCounter++;

  const connId = connIdCounter;

  const baseSetting = {
    id: connId,
    removeNamespace: true // by default remove namespace from results
  };

  const settings = Object.assign(baseSetting, connSettings);

  const conn = {
    id: connId,
    isReady: () => isReady(connId),
    isClosed: () => isClosed(connId),
    login: (username, password, cb) => workerInvoke({
      conn: connId,
      action: "login",
      params: [username, password],
      cb: cb
    }),
    invoke: function (action, params, cb) {
      const invokeStatment = [action, params];
      return workerInvoke({
        conn: connId,
        action: "remoteInvoke",
        params: [invokeStatment],
        cb: cb
      });
    },
    getUser: function () {
      return connStatus[connId].user;
    },
    getInstance: function () {
      return connSettings.instance;
    },
    isAuthenticated: function () {
      if (connStatus[connId].anonymous === false) {
        return true;
      } else {
        return false;
      }
    },
    reset: function (cb) {
      connStatus[connId] = {
        ready: false,
        user: null,
        anonymous: true
      };
      return workerInvoke({
        conn: connId,
        action: "reset",
        params: [],
        cb: cb
      });
    },
    logout: function (cb) {
      connStatus[connId] = {
        ready: false,
        user: null,
        anonymous: true
      };
      return workerInvoke({
        conn: connId,
        action: "logout",
        params: [],
        cb: cb
      });
    },
    close: function (cb) {
      // clear out connection state held locally
      connStatus[connId] = {};
      return workerInvoke({
        conn: connId,
        action: "close",
        params: [],
        cb: cb
      });
    }
  };

  // initialize connection status, set ready to false
  connStatus[connId] = {
    ready: false,
    // if we already passed in a token, can also pass in the user/anonymous flags for storing
    user: connSettings.user,
    anonymous: connSettings.anonymous
  };

  // initiate our connection in the web worker
  workerInvoke({
    conn: 0, // conn 0 means not connection specific
    action: "connect",
    params: [settings]
  });

  // return connection object
  return conn;
}

function getDisplayName(component) {
  return component.displayName || component.name || "Component";
}

// wraps react components that need a particular connection, making the
// connection available via the context to children
export class FlureeProvider extends Component {

  static propTypes = {
    conn: PropTypes.object.isRequired
  };

  static childContextTypes = {
    conn: PropTypes.object.isRequired
  };

  constructor(props, context) {
    super(props, context);

    if (!props.conn) {
      throw "FlureeProvider was not provided a conn prop, which should be a connection object."
    }

    this.conn = props.conn;
  };

  getChildContext() {

    return {
      conn: this.conn
    }
  };

  render() {
    return React.Children.only(this.props.children);
  };
}

// given a query and options, returns a vector of variables that
// were not provided via options. We use this to look for the variables
// in props
function getMissingVars(flurQL, opts) {

  const vars = flurQL.vars;

  if (!vars || !Array.isArray(vars)) {
    return [];
  }

  if (opts && opts.vars) {
    return vars.filter((v) => { return !opts.vars[v]; });
  } else {
    return vars;
  }
}

// Create an empty map of the top level query nodes so less
// boilerplate is required to test if a property exists in the
// wrapped component
function fillDefaultResult(query) {

  if (!query) return {};

  const graph = query.graph || query;

  if (!Array.isArray(graph)) { // invalid graph
    return;
  }

  var defaultResult = {};

  graph.map(([stream, opts]) => {
    if (opts.as) {
      defaultResult[opts.as] = null;
    } else {
      defaultResult[stream] = null;
    }
  });

  return defaultResult;
}

function queryIsValid(query) {
  if (query !== null && (Array.isArray(query) || typeof query === "object")) {
    const graph = Array.isArray(query) ? query : query.graph;
    if (Array.isArray(graph) && graph.length > 0) {
      return true;
    } else {
      return false;
    }
  } else {
    return false;
  }
}

function wrapComponent(WrappedComponent, query, opts) {

  const flurQLDisplayName = `Fluree(${getDisplayName(WrappedComponent)})`;

  class FlurQL extends Component {
    static displayName = flurQLDisplayName;
    static WrappedComponent = WrappedComponent;
    static contextTypes = {
      conn: PropTypes.object.isRequired
    };

    constructor(props, context) {
      super(props, context);
      this.conn = context.conn;
      this.opts = Object.assign({ vars: {} }, opts);
      this.id = nextId();
      this.queryIsFunction = (typeof query === "function")
      this.query = this.queryIsFunction ? query(props, this.context) : query;
      this.isValidQuery = this.query && queryIsValid(this.query);
      this.missingVars = this.isValidQuery ? getMissingVars(this.query, this.opts) : []; // list of vars we need to check props for
      this.state = {
        result: this.isValidQuery ? fillDefaultResult(this.query) : {},
        error: this.query && !this.isValidQuery ? { status: 400, message: "Query is not valid: " + JSON.stringify(this.query) } : null,
        warning: this.query ? null : "No query yet, waiting...",
        status: "pending",
        loading: true
      };

      if (!this.conn) {
        throw "Could not find a Fluree connection (conn) in the context of " + flurQLDisplayName + ".";
      }
    }

    componentWillMount() {
      // get any missing vars from props and update this.opts with them
      if (this.missingVars.length !== 0) {
        this.missingVars.map((v) => { this.opts.vars[v] = this.props[v] });
      }

      // register this component for later re-render calling, etc.
      componentIdx[this.id] = this;

      if (this.query && this.isValidQuery) {
        registerQuery(this.conn, this.id, this.query, this.opts);
      }
    }

    componentWillUnmount() {

      unregisterQuery(this.conn, this.id);
      delete componentIdx[this.id];

    }

    componentWillReceiveProps(nextProps) {
      if (this.queryIsFunction) {
        const newQuery = query(nextProps, this.context);
        this.query = newQuery;
        this.isValidQuery = queryIsValid(this.query);
        if (this.query && this.isValidQuery) {
          registerQuery(this.conn, this.id, this.query, this.opts);
        }
      } else {
        // check if any of the missing vars changed with the new props
        let didMissingVarsChange = false;

        for (let i = 0; i < this.missingVars.length; i++) {
          const varName = this.missingVars[i];
          if (this.props[varName] !== nextProps[varName]) {
            didMissingVarsChange = true;
          }
        }

        if (didMissingVarsChange === true) {
          this.missingVars.map((v) => {
            this.opts.vars[v] = nextProps[v];
            return;
          });
          registerQuery(this.conn, this.id, this.query, this.opts);
        }
      }
    }

    render() {
      const result = this.state.result;
      const data = {
        id: this.id,
        result: result,
        error: this.state.error,
        warning: this.state.warning,
        status: this.state.status,
        loading: this.state.status !== "loaded",
        get: function (keySeq, defaultVal) {
          keySeq = Array.isArray(keySeq) ? keySeq : [keySeq];
          let obj = result;
          let idx = 0;
          const length = keySeq.length;

          while (obj != null && idx < length) {
            obj = obj[keySeq[idx++]];
          }

          return (idx == length && obj !== undefined) ? obj : defaultVal;
        }
      };

      const childProps = Object.assign({}, this.props, { data: data, invoke: this.conn.invoke });

      return createElement(WrappedComponent, childProps);
    }
  }

  return hoistNonReactStatics(FlurQL, WrappedComponent, {});
}

export function flureeQL(query, opts) {
  return function (WrappedComponent) {
    return wrapComponent(WrappedComponent, query, opts);
  }
}

<|endoftext|>


<commit_before>var defaults = require('./defaults');
var dotHIVStyles = require('./templates/styles.dot');
var dotHIVTemplate = require('./templates/dot.dot');

var childrenTextNodes = require('./utils/children-text-nodes');

function dotHIVify(config) {
	'use strict';
	var options = {};

	// (Poor man's) merge of defaults with user-provided configuration
	for (var property in defaults) {
		if (defaults.hasOwnProperty(property)) {
			options[property] = typeof config[property] !== 'undefined' ? config[property] : defaults[property];
		}
	}

	var els = document.querySelectorAll(options['queries'].join(', ')); // jshint ignore: line
	var replacement = dotHIVTemplate(options);
	var styles = dotHIVStyles(options);

	// Construct detoggle input
	var detoggle = document.createElement('input');
	detoggle.type = 'radio';
	detoggle.name = options['prefix']; // jshint ignore: line
	detoggle.className = options['prefix'] + '-state'; // jshint ignore: line
	detoggle.id = options['prefix'] + '-state-revert'; // jshint ignore: line

	// Construct styling
	var sheet = document.createElement('style');
	sheet.type = 'text/css';

	// Construct dot template
	var documentFragment = document.createDocumentFragment();
	var container = document.createElement('div');
	container.innerHTML = replacement;
	documentFragment.appendChild(container);
	var dotTemplate = container.firstChild;

	if (sheet.styleSheet) {
		sheet.styleSheet.cssText = styles;
	} else {
		sheet.appendChild(document.createTextNode(styles));
	}

	// Inject styling and detoggle
	document.head.appendChild(sheet);
	document.body.appendChild(detoggle);

	// Replace all the things.
	for (var i = 0; i < els.length; i += 1) {
		var textNodes = childrenTextNodes(els[i]);

		for (var j = 0; j < textNodes.length; j += 1) {
			var replacementNodes = [];
			var fragments = textNodes[j].nodeValue.split(options['replaced']); // jshint ignore: line
			var previousChars = [];
			var trailingChars = [];

			for (var k = 0; k < fragments.length; k += 1) {
				var previousChar = fragments[k - 1] ? fragments[k - 1][fragments[k - 1].length - 1] : '';
				var trailingChar = fragments[k + 1] ? fragments[k + 1][0] : null;

				previousChars.push(previousChar.match(/[a-z]/i));
				trailingChars.push(trailingChar !== null);
				replacementNodes.push(document.createTextNode(fragments[k]));
			}

			for (var l = 0; l < replacementNodes.length; l += 1) {
				textNodes[j].parentNode.insertBefore(replacementNodes[l], textNodes[j]);

				if (replacementNodes[l].nodeValue && previousChars[l] && trailingChars[l]) {
					textNodes[j].parentNode.insertBefore(dotTemplate.cloneNode(true), replacementNodes[l]);
				} else if (previousChars[l]) {
					replacementNodes[l].nodeValue = '.' + replacementNodes[l].nodeValue;
				}
			}

			textNodes[j].parentNode.removeChild(textNodes[j]);
		}
	}
}

module.exports = dotHIVify;
<commit_msg>Export to global ns<commit_after>var defaults = require('./defaults');
var dotHIVStyles = require('./templates/styles.dot');
var dotHIVTemplate = require('./templates/dot.dot');

var childrenTextNodes = require('./utils/children-text-nodes');

function dotHIVify(config) {
	'use strict';
	var options = {};

	// (Poor man's) merge of defaults with user-provided configuration
	for (var property in defaults) {
		if (defaults.hasOwnProperty(property)) {
			options[property] = typeof config[property] !== 'undefined' ? config[property] : defaults[property];
		}
	}

	var els = document.querySelectorAll(options['queries'].join(', ')); // jshint ignore: line
	var replacement = dotHIVTemplate(options);
	var styles = dotHIVStyles(options);

	// Construct detoggle input
	var detoggle = document.createElement('input');
	detoggle.type = 'radio';
	detoggle.name = options['prefix']; // jshint ignore: line
	detoggle.className = options['prefix'] + '-state'; // jshint ignore: line
	detoggle.id = options['prefix'] + '-state-revert'; // jshint ignore: line

	// Construct styling
	var sheet = document.createElement('style');
	sheet.type = 'text/css';

	// Construct dot template
	var documentFragment = document.createDocumentFragment();
	var container = document.createElement('div');
	container.innerHTML = replacement;
	documentFragment.appendChild(container);
	var dotTemplate = container.firstChild;

	if (sheet.styleSheet) {
		sheet.styleSheet.cssText = styles;
	} else {
		sheet.appendChild(document.createTextNode(styles));
	}

	// Inject styling and detoggle
	document.head.appendChild(sheet);
	document.body.appendChild(detoggle);

	// Replace all the things.
	for (var i = 0; i < els.length; i += 1) {
		var textNodes = childrenTextNodes(els[i]);

		for (var j = 0; j < textNodes.length; j += 1) {
			var replacementNodes = [];
			var fragments = textNodes[j].nodeValue.split(options['replaced']); // jshint ignore: line
			var previousChars = [];
			var trailingChars = [];

			for (var k = 0; k < fragments.length; k += 1) {
				var previousChar = fragments[k - 1] ? fragments[k - 1][fragments[k - 1].length - 1] : '';
				var trailingChar = fragments[k + 1] ? fragments[k + 1][0] : null;

				previousChars.push(previousChar.match(/[a-z]/i));
				trailingChars.push(trailingChar !== null);
				replacementNodes.push(document.createTextNode(fragments[k]));
			}

			for (var l = 0; l < replacementNodes.length; l += 1) {
				textNodes[j].parentNode.insertBefore(replacementNodes[l], textNodes[j]);

				if (replacementNodes[l].nodeValue && previousChars[l] && trailingChars[l]) {
					textNodes[j].parentNode.insertBefore(dotTemplate.cloneNode(true), replacementNodes[l]);
				} else if (previousChars[l]) {
					replacementNodes[l].nodeValue = '.' + replacementNodes[l].nodeValue;
				}
			}

			textNodes[j].parentNode.removeChild(textNodes[j]);
		}
	}
}

window['dotHIVify'] = dotHIVify; // jshint ignore: line
module.exports = dotHIVify;
<|endoftext|>


<commit_before>#! /usr/bin/env node
// @flow
import program from "commander";
import prettier from "prettier";
import yaml from "js-yaml";
import fs from "fs";
import path from "path";

// Swagger data types are base on types supported by the JSON-Scheme Draft4.
const typeMapping = {
  array: "Array<*>",
  boolean: "boolean",
  integer: "number",
  number: "number",
  null: "null",
  object: "Object",
  string: "string"
};

export class FlowTypeGenerator {
  result: string;
  +withExport: boolean;
  +swagger: Object;

  constructor(swagger: Object, withExport: boolean = true) {
    if (!swagger) {
      throw new Error("Can't create FlowTypeGenerator");
    }
    this.result = "// @flow \n";
    (this: any).withExport = withExport;
    (this: any).swagger = swagger;
  }

  static isPrimitiveType(type: string) {
    return ["integer", "number", "string", "boolean"].indexOf(type) !== -1;
  }

  static definitionType(ref: string) {
    const re = /#\/definitions\/(.*)/;
    const found = ref.match(re);
    return found ? found[1] : "";
  }

  static hasNext(key: string, definitions: Object) {
    const keys = Object.keys(definitions);
    return keys.findIndex(v => v === key) < keys.length - 1;
  }

  definitions(): string {
    const { definitions } = this.swagger;
    Object.keys(definitions).forEach(k => {
      const headLine = this.withExport ? `export type ${k} = ` : `type ${k} = `;
      this.appendResult(headLine);
      this.determineTypes(k, definitions, true);
      this.appendResult("\n");
    });
    return this.result;
  }

  appendResult(text: string) {
    this.result += text;
  }

  determineTypes(key: string, properties: Object, isPrimary: boolean = false) {
    const property = properties[key];
    if ("$ref" in property) {
      this.appendResult(
        `${key}: ${FlowTypeGenerator.definitionType(property.$ref)}`
      );
      if (FlowTypeGenerator.hasNext(key, properties)) {
        this.appendResult(",");
      }
    }

    if (FlowTypeGenerator.isPrimitiveType(property.type)) {
      this.appendResult(`${key}: ${typeMapping[property.type]}`);
      if (FlowTypeGenerator.hasNext(key, properties)) {
        this.appendResult(",");
      }
    }

    if (property.type === "object") {
      if ("properties" in property) {
        if (!isPrimary) {
          this.appendResult(`${key}: `);
        }
        this.appendResult("{");
        Object.keys(property.properties).forEach(k => {
          this.determineTypes(k, property.properties);
        });
        this.appendResult("}");
        if (FlowTypeGenerator.hasNext(key, properties) && !isPrimary) {
          this.appendResult(",");
        }
      } else if (isPrimary) {
        this.appendResult(`${typeMapping[property.type]}`);
      } else {
        this.appendResult(`${key}: ${typeMapping[property.type]}`);
        if (FlowTypeGenerator.hasNext(key, properties)) {
          this.appendResult(",");
        }
      }
    }

    if (property.type === "array") {
      const type: * = "$ref" in property.items
        ? FlowTypeGenerator.definitionType(property.items.$ref)
        : property.items.type;
      const typeString = `Array<${type}>`;
      this.appendResult(`${key}: ${typeString}`);
      if (FlowTypeGenerator.hasNext(key, properties)) {
        this.appendResult(",");
      }
    }
  }
}

export const generator = (file: string) => {
  const doc: Object = path.extname(file) === ".yaml"
    ? yaml.safeLoad(fs.readFileSync(file, "utf8"))
    : JSON.parse(fs.readFileSync(file, "utf8"));
  const g = new FlowTypeGenerator(doc);
  const options = {};
  return prettier.format(g.definitions(), options);
};

export const writeToFile = (dist: string = "./flowtype.js", result: string) => {
  fs.writeFile(dist, result, err => {
    if (err) {
      throw err;
    }
  });
};

export const distFile = (p: Object) => p.distination || "./flowtype.js";

program
  .arguments("<file>")
  .option("-d --distination <distination>", "Distination path")
  .action(file => {
    try {
      const result = generator(file);
      const dist = distFile(program);
      writeToFile(dist, result);
      console.log(`Generated flow types to ${dist}`);
    } catch (e) {
      console.log(e);
    }
  })
  .parse(process.argv);
<commit_msg>Fix eslint.<commit_after>#! /usr/bin/env node
// @flow
import program from "commander";
import prettier from "prettier";
import yaml from "js-yaml";
import fs from "fs";
import path from "path";

// Swagger data types are base on types supported by the JSON-Scheme Draft4.
const typeMapping = {
  array: "Array<*>",
  boolean: "boolean",
  integer: "number",
  number: "number",
  null: "null",
  object: "Object",
  string: "string"
};

export class FlowTypeGenerator {
  result: string;
  +withExport: boolean;
  +swagger: Object;

  constructor(swagger: Object, withExport: boolean = true) {
    if (!swagger) {
      throw new Error("Can't create FlowTypeGenerator");
    }
    this.result = "// @flow \n";
    (this: any).withExport = withExport;
    (this: any).swagger = swagger;
  }

  static isPrimitiveType(type: string) {
    return ["integer", "number", "string", "boolean"].indexOf(type) !== -1;
  }

  static definitionType(ref: string) {
    const re = /#\/definitions\/(.*)/;
    const found = ref.match(re);
    return found ? found[1] : "";
  }

  static hasNext(key: string, definitions: Object) {
    const keys = Object.keys(definitions);
    return keys.findIndex(v => v === key) < keys.length - 1;
  }

  definitions(): string {
    const { definitions } = this.swagger;
    Object.keys(definitions).forEach((k) => {
      const headLine = this.withExport ? `export type ${k} = ` : `type ${k} = `;
      this.appendResult(headLine);
      this.determineTypes(k, definitions, true);
      this.appendResult("\n");
    });
    return this.result;
  }

  appendResult(text: string) {
    this.result += text;
  }

  determineTypes(key: string, properties: Object, isPrimary: boolean = false) {
    const property = properties[key];
    if ("$ref" in property) {
      this.appendResult(
        `${key}: ${FlowTypeGenerator.definitionType(property.$ref)}`
      );
      if (FlowTypeGenerator.hasNext(key, properties)) {
        this.appendResult(",");
      }
    }

    if (FlowTypeGenerator.isPrimitiveType(property.type)) {
      this.appendResult(`${key}: ${typeMapping[property.type]}`);
      if (FlowTypeGenerator.hasNext(key, properties)) {
        this.appendResult(",");
      }
    }

    if (property.type === "object") {
      if ("properties" in property) {
        if (!isPrimary) {
          this.appendResult(`${key}: `);
        }
        this.appendResult("{");
        Object.keys(property.properties).forEach((k) => {
          this.determineTypes(k, property.properties);
        });
        this.appendResult("}");
        if (FlowTypeGenerator.hasNext(key, properties) && !isPrimary) {
          this.appendResult(",");
        }
      } else if (isPrimary) {
        this.appendResult(`${typeMapping[property.type]}`);
      } else {
        this.appendResult(`${key}: ${typeMapping[property.type]}`);
        if (FlowTypeGenerator.hasNext(key, properties)) {
          this.appendResult(",");
        }
      }
    }

    if (property.type === "array") {
      const type: * = "$ref" in property.items
        ? FlowTypeGenerator.definitionType(property.items.$ref)
        : property.items.type;
      const typeString = `Array<${type}>`;
      this.appendResult(`${key}: ${typeString}`);
      if (FlowTypeGenerator.hasNext(key, properties)) {
        this.appendResult(",");
      }
    }
  }
}

export const generator = (file: string) => {
  const doc: Object = path.extname(file) === ".yaml"
    ? yaml.safeLoad(fs.readFileSync(file, "utf8"))
    : JSON.parse(fs.readFileSync(file, "utf8"));
  const g = new FlowTypeGenerator(doc);
  const options = {};
  return prettier.format(g.definitions(), options);
};

export const writeToFile = (dist: string = "./flowtype.js", result: string) => {
  fs.writeFile(dist, result, (err) => {
    if (err) {
      throw err;
    }
  });
};

export const distFile = (p: Object) => p.distination || "./flowtype.js";

program
  .arguments("<file>")
  .option("-d --distination <distination>", "Distination path")
  .action((file) => {
    try {
      const result = generator(file);
      const dist = distFile(program);
      writeToFile(dist, result);
      console.log(`Generated flow types to ${dist}`);
    } catch (e) {
      console.log(e);
    }
  })
  .parse(process.argv);
<|endoftext|>


<commit_before>import most from 'most'
import snabbdom from 'snabbdom'
import h from 'snabbdom/h'
const {
  a, abbr, address, area, article, aside, audio, b, base,
  bdi, bdo, blockquote, body, br, button, canvas, caption,
  cite, code, col, colgroup, dd, del, dfn, dir, div, dl,
  dt, em, embed, fieldset, figcaption, figure, footer, form,
  h1, h2, h3, h4, h5, h6, head, header, hgroup, hr, html,
  i, iframe, img, input, ins, kbd, keygen, label, legend,
  li, link, map, mark, menu, meta, nav, noscript, object,
  ol, optgroup, option, p, param, pre, q, rp, rt, ruby, s,
  samp, script, section, select, small, source, span, strong,
  style, sub, sup, table, tbody, td, textarea, tfoot, th,
  thead, title, tr, u, ul, video,
} = require(`hyperscript-helpers`)(h)
import matchesSelector from 'matches-selector'
import fastMap from 'fast.js/array/map'
import reduce from 'fast.js/array/reduce'
import filter from 'fast.js/array/filter'

import {getDomElement} from './utils'
import fromEvent from './fromEvent'
import parseTree from './parseTree'

const isolateSource =
  (_source, _scope) =>
    _source.select(`.cycle-scope-${_scope}`)

const isolateSink =
  (sink, scope) =>
    sink.map(
      vtree => {
        const c = `${vtree.sel} cycle-scope-${scope}`.trim()
        vtree.sel = c
        return vtree
      }
    )

const makeIsStrictlyInRootScope =
  (rootList, namespace) =>
    leaf => {
      const classIsForeign =
        c => {
          const matched = c.match(/cycle-scope-(\S+)/)
          return matched && namespace.indexOf(`.${c}`) === -1
        }

      for (let el = leaf.parentElement; el !== null; el = el.parentElement) {
        if (rootList.indexOf(el) >= 0) {
          return true
        }
        const classList = el.className.split(` `)
        if (classList.some(classIsForeign)) {
          return false
        }
      }
      return true
    }

const makeEventsSelector =
  element$ =>
    (eventName, useCapture = false) => {
      if (typeof eventName !== `string`) {
        throw new Error(`DOM drivers events() expects argument to be a ` +
          `string representing the event type to listen for.`)
      }
      return element$
        .map(elements => {
          if (!elements) {
            return most.empty()
          }
          return most.merge(
            ...fastMap(elements, el => {
              return fromEvent(eventName, el, useCapture)
            })
         )
        }).switch().multicast()
    }

// Use function not 'const = x => {}' for this.namespace below
function makeElementSelector(rootElem$) {
  return function DOMSelect(selector) {
    if (typeof selector !== `string`) {
      throw new Error(`DOM drivers select() expects first argument to be a ` +
        `string as a CSS selector`)
    }
    const namespace = this.namespace
    const scopedSelector = `${namespace.join(` `)} ${selector}`.trim()
    const element$ =
      selector.trim() === `:root` ?
        rootElem$ :
        rootElem$.map(
          x => {
            const array = Array.isArray(x) ? x : [x]
            return filter(
              reduce(
                fastMap(
                  array,
                  element => {
                    if (matchesSelector(element, scopedSelector)) {
                      return [element]
                    } else {
                      let nodeList = element.querySelectorAll(scopedSelector)
                      const nodeListArray = new Array(nodeList.length)
                      for (let j = 0; j < nodeListArray.length; j++) {
                        nodeListArray[j] = nodeList[j]
                      }
                      return nodeListArray
                    }
                  }
                ),
                (prev, curr) => prev.concat(curr),
                []
              ),
              makeIsStrictlyInRootScope(array, namespace)
            )
          }
      )
    return {
      observable: element$,
      namespace: namespace.concat(selector),
      select: makeElementSelector(element$),
      events: makeEventsSelector(element$),
      isolateSource,
      isolateSink,
    }
  }
}

const validateDOMDriverInput =
  view$ => {
    if (!view$ || typeof view$.observe !== `function`) {
      throw new Error(`The DOM driver function expects as input an ` +
        `Observable of virtual DOM elements`)
    }
  }

const makeDOMDriver =
  (container, modules = [
    require(`snabbdom/modules/class`),
    require(`snabbdom/modules/props`),
    require(`snabbdom/modules/attributes`),
    require(`snabbdom/modules/style`),
  ]) => {
    const patch = snabbdom.init(modules)
    const rootElem = getDomElement(container)

    const DOMDriver =
      view$ => {
        validateDOMDriverInput(view$)

        const rootElem$ =
          most.create(
            add =>
              view$
                .flatMap(parseTree)
                .reduce(
                  (prevView, newView) => {
                    patch(prevView, newView)
                    add(newView.elm)
                    return newView
                  }
                  , rootElem
                )
          )
        rootElem$.drain()

        return {
          namespace: [],
          select: makeElementSelector(rootElem$),
          isolateSink,
          isolateSource,
        }
      }

    return DOMDriver
  }

export {
  makeDOMDriver,
  h,
  a, abbr, address, area, article, aside, audio, b, base,
  bdi, bdo, blockquote, body, br, button, canvas, caption,
  cite, code, col, colgroup, dd, del, dfn, dir, div, dl,
  dt, em, embed, fieldset, figcaption, figure, footer, form,
  h1, h2, h3, h4, h5, h6, head, header, hgroup, hr, html,
  i, iframe, img, input, ins, kbd, keygen, label, legend,
  li, link, map, mark, menu, meta, nav, noscript, object,
  ol, optgroup, option, p, param, pre, q, rp, rt, ruby, s,
  samp, script, section, select, small, source, span, strong,
  style, sub, sup, table, tbody, td, textarea, tfoot, th,
  thead, title, tr, u, ul, video
}
<commit_msg>feat(): use new fromEvent() semantics<commit_after>import most from 'most'
import snabbdom from 'snabbdom'
import h from 'snabbdom/h'
const {
  a, abbr, address, area, article, aside, audio, b, base,
  bdi, bdo, blockquote, body, br, button, canvas, caption,
  cite, code, col, colgroup, dd, del, dfn, dir, div, dl,
  dt, em, embed, fieldset, figcaption, figure, footer, form,
  h1, h2, h3, h4, h5, h6, head, header, hgroup, hr, html,
  i, iframe, img, input, ins, kbd, keygen, label, legend,
  li, link, map, mark, menu, meta, nav, noscript, object,
  ol, optgroup, option, p, param, pre, q, rp, rt, ruby, s,
  samp, script, section, select, small, source, span, strong,
  style, sub, sup, table, tbody, td, textarea, tfoot, th,
  thead, title, tr, u, ul, video,
} = require(`hyperscript-helpers`)(h)
import matchesSelector from 'matches-selector'
import fastMap from 'fast.js/array/map'
import reduce from 'fast.js/array/reduce'
import filter from 'fast.js/array/filter'

import {getDomElement} from './utils'
import fromEvent from './fromEvent'
import parseTree from './parseTree'

const isolateSource =
  (_source, _scope) =>
    _source.select(`.cycle-scope-${_scope}`)

const isolateSink =
  (sink, scope) =>
    sink.map(
      vtree => {
        const c = `${vtree.sel} cycle-scope-${scope}`.trim()
        vtree.sel = c
        return vtree
      }
    )

const makeIsStrictlyInRootScope =
  (rootList, namespace) =>
    leaf => {
      const classIsForeign =
        c => {
          const matched = c.match(/cycle-scope-(\S+)/)
          return matched && namespace.indexOf(`.${c}`) === -1
        }

      for (let el = leaf.parentElement; el !== null; el = el.parentElement) {
        if (rootList.indexOf(el) >= 0) {
          return true
        }
        const classList = el.className.split(` `)
        if (classList.some(classIsForeign)) {
          return false
        }
      }
      return true
    }

const makeEventsSelector =
  element$ =>
    (eventName, useCapture = false) => {
      if (typeof eventName !== `string`) {
        throw new Error(`DOM drivers events() expects argument to be a ` +
          `string representing the event type to listen for.`)
      }
      return element$
        .map(elements => {
          if (!elements) {
            return most.empty()
          }
          return fromEvent(eventName, elements, useCapture)
        }).switch().multicast()
    }

// Use function not 'const = x => {}' for this.namespace below
function makeElementSelector(rootElem$) {
  return function DOMSelect(selector) {
    if (typeof selector !== `string`) {
      throw new Error(`DOM drivers select() expects first argument to be a ` +
        `string as a CSS selector`)
    }
    const namespace = this.namespace
    const scopedSelector = `${namespace.join(` `)} ${selector}`.trim()
    const element$ =
      selector.trim() === `:root` ?
        rootElem$ :
        rootElem$.map(
          x => {
            const array = Array.isArray(x) ? x : [x]
            return filter(
              reduce(
                fastMap(
                  array,
                  element => {
                    if (matchesSelector(element, scopedSelector)) {
                      return [element]
                    } else {
                      let nodeList = element.querySelectorAll(scopedSelector)
                      const nodeListArray = new Array(nodeList.length)
                      for (let j = 0; j < nodeListArray.length; j++) {
                        nodeListArray[j] = nodeList[j]
                      }
                      return nodeListArray
                    }
                  }
                ),
                (prev, curr) => prev.concat(curr),
                []
              ),
              makeIsStrictlyInRootScope(array, namespace)
            )
          }
      )
    return {
      observable: element$,
      namespace: namespace.concat(selector),
      select: makeElementSelector(element$),
      events: makeEventsSelector(element$),
      isolateSource,
      isolateSink,
    }
  }
}

const validateDOMDriverInput =
  view$ => {
    if (!view$ || typeof view$.observe !== `function`) {
      throw new Error(`The DOM driver function expects as input an ` +
        `Observable of virtual DOM elements`)
    }
  }

const makeDOMDriver =
  (container, modules = [
    require(`snabbdom/modules/class`),
    require(`snabbdom/modules/props`),
    require(`snabbdom/modules/attributes`),
    require(`snabbdom/modules/style`),
  ]) => {
    const patch = snabbdom.init(modules)
    const rootElem = getDomElement(container)

    const DOMDriver =
      view$ => {
        validateDOMDriverInput(view$)

        const rootElem$ =
          most.create(
            add =>
              view$
                .flatMap(parseTree)
                .reduce(
                  (prevView, newView) => {
                    patch(prevView, newView)
                    add(newView.elm)
                    return newView
                  }
                  , rootElem
                )
          )
        rootElem$.drain()

        return {
          namespace: [],
          select: makeElementSelector(rootElem$),
          isolateSink,
          isolateSource,
        }
      }

    return DOMDriver
  }

export {
  makeDOMDriver,
  h,
  a, abbr, address, area, article, aside, audio, b, base,
  bdi, bdo, blockquote, body, br, button, canvas, caption,
  cite, code, col, colgroup, dd, del, dfn, dir, div, dl,
  dt, em, embed, fieldset, figcaption, figure, footer, form,
  h1, h2, h3, h4, h5, h6, head, header, hgroup, hr, html,
  i, iframe, img, input, ins, kbd, keygen, label, legend,
  li, link, map, mark, menu, meta, nav, noscript, object,
  ol, optgroup, option, p, param, pre, q, rp, rt, ruby, s,
  samp, script, section, select, small, source, span, strong,
  style, sub, sup, table, tbody, td, textarea, tfoot, th,
  thead, title, tr, u, ul, video
}
<|endoftext|>


<commit_before>import querystring from 'querystring';
import request from 'request';
import cheerio from 'cheerio';
import debug from 'debug';
import queryMap from './queryMap.json';

const log = debug('alis-web-request');

export const recordTypes = queryMap.recordType;

export function sendInitialQuery(params, callback) {
  if (!params.alisEndpoint) {
    return process.nextTick(callback, new Error('alisEndpoint is not provided'));
  }
  if (!params.query) {
    return process.nextTick(callback, new Error('query is not provided'));
  }
  if (!params.queryType) {
    return process.nextTick(callback, new Error('queryType is not provided'));
  }
  if (!params.recordType) {
    return process.nextTick(callback, new Error('recordType is not provided'));
  }
  const j = request.jar();
  const alisEndpoint = `${params.alisEndpoint}`;
  const qs = querystring.stringify({
    radiodate: 'simple',
    valueINP: params.query,
    tema: queryMap.recordType[params.recordType],
    tag: queryMap.queryType[params.queryType],
  });
  const firstPageUrl = `/alis/EK/do_searh.php?${qs}`;
  const INITIAL_URL = `${alisEndpoint}${firstPageUrl}`;

  log(`sendInitialQuery: ${INITIAL_URL}`);

  request({ url: INITIAL_URL, jar: j }, (err, response, body) => {
    if (err) {
      return callback(err);
    }
    callback(null, { page: body, jar: j });
  });
}

const cacheManager = require('cache-manager');
const fsHashStore = require('cache-manager-fs-hash');

const CACHE_DIR = `${__dirname}/../.cache`;

const pageCache = cacheManager.caching({
  store: fsHashStore,
  options: {
    ttl: 60 * 60 * 24 /* 1 day in seconds */,
    maxsize: 1000 * 1000 * 1000 /* max size in bytes on disk */,
    path: `${CACHE_DIR}/pages`,
    subdirs: true,
  },
});

export function getPage(options, callback) {
  const { url, jar, initParams } = options;

  log(`getPage: ${url}`);

  const cacheKey = JSON.stringify({ url, ...initParams });

  pageCache.wrap(cacheKey, (cacheCallback) => {
    request({ url, jar }, (err, response, body) => {
      if (err) {
        return cacheCallback(err);
      }
      cacheCallback(null, body);
    });
  }, {}, callback);
}

export function getNextPageUrl($) {
  const pageLink = $('#Agt');
  const pageUrl = $(pageLink).attr('href');
  return pageUrl;
}

export function getTotal($) {
  const total = $('.listbzstat').first().text().match(/\d+(?=\sзап\.)/)[0];
  return total;
}

export function getItems($) {
  const items = $('.article').map(function (i, el) {
    return {
      id: $(el).attr('id').replace(/^H/, ''),
      title: $(el).text().trim(),
    };
  }).toArray();
  return items;
}

export function getNumberedPageUrls($) {
  // `fcheck` гэта лічба першай нумарованай старонкі, усяго іх будзе паказана дзевяць.
  //
  // `ccheck`, `crow`, `frow` не маюць дзеянне, але бяз іх з'яўляецца Notice.
  // Notice: Undefined index: ccheck in E:\ALIS\pls\alis\EK\do_other.php on line 42
  // Яны задаюцца аўтаматычна у нумар старонкі, і першы нумар рэзультату.
  //
  // `action` гэта нумар старонкі для паказа.
  const pageLinks = $('a[href^=\'do_other\']');
  const relativePageUrls = $(pageLinks).map((i, link) => $(link).attr('href').replace(/\r|\n/g, '')).toArray();
  return relativePageUrls;
}

export function parsePage(body) {
  const $ = cheerio.load(body);
  return $;
}

export function processItems(memo, q, options, callback) {
  if (!options) {
    return process.nextTick(callback, new Error('options is not provided'));
  }

  getPage(options, (err, body) => {
    if (err) return callback(err);
    const $ = parsePage(body);

    const items = getItems($);

    const nextPageUrl = getNextPageUrl($);
    const remainingQueue = q.slice(1);
    if (q.length === 1) {
      remainingQueue.push(`${nextPageUrl}`);
    }
    items.forEach((item) => {
      memo.push(item);
    });
    callback(null, memo, remainingQueue);
  });
}

export function run(fn, q, memo, options, callback) {
  if (!q) {
    return new Error('q is not provided');
  }

  if (q[0] === 'undefined') {
    return callback(null, memo);
  }
  fn(memo, q, { url: `${options.alisEndpoint}/alis/EK/${q[0]}`, ...options }, (err, nextMemo, nextQ) => {
    if (err) {
      return callback(err);
    }
    run(fn, nextQ, memo, options, callback);
  });
}

export function getRecordsByQuery(initParams, callback) {
  sendInitialQuery(initParams, (err, res) => {
    if (err) {
      return callback(err);
    }
    const options = {
      alisEndpoint: initParams.alisEndpoint,
      jar: res.jar,
      initParams,
    };
    if (res.page.match('<title>Не результативный поиск</title>')) {
      return callback(new Error('no match'));
    }
    const $ = parsePage(res.page);
    const firstNumberedPageUrls = getNumberedPageUrls($);
    const remainingQueue = firstNumberedPageUrls;
    run(processItems, remainingQueue, [], options, (runErr, memo) => {
      if (err) {
        return callback(err);
      }
      callback(null, memo);
    });
  });
}

export function collectReferences(table) {
  const references = [];
  const data = table.children().toArray();
  data.shift();
  data.forEach((el) => {
    const a = el.children[0].children[0];
    references.push({
      tag: Number(a.attribs.onclick.match(/[0-9]+/)[0]),
      value: a.children[0].data,
    });
  });
  return references;
}

export function collectFunds(table) {
  const funds = [];
  const data = table.children().toArray();
  data.shift();
  data.forEach((el) => {
    funds.push({
      name: el.children[0].children[0].children[0].data,
      count: Number(el.children[1].children[0].data),
    });
  });
  return funds;
}

export function collectFields($, table) {
  const fields = table.find('tr')
    .filter((i, tr) => {
      return $('tr:nth-child(1) th:nth-child(1)', tr).text() !== 'Название';
    }).map((i, tr) => {
      return {
        tag: $('td:nth-child(1)', tr).text(),
        value: $('td:nth-child(2)', tr).text(),
      };
    }).get();
  return fields;
}

export function collectYears(table) {
  const references = [];
  const data = table.children().toArray();
  data.shift();
  data.forEach((el) => {
    const a = el.children[0].children[0];
    references.push(Number(a.children[0].data.substr(0, 4)));
  });
  return references;
}

export function getTable($, name) {
  const nameToTitle = {
    years: 'Год(комплект)',
    references: 'Ссылки на др. биб.записи',
    fields: 'Название',
    funds: 'Фонд',
  };
  const tablesIndex = $('table').map((i, table) => {
    const $table = $(table);
    const title = $('tr:nth-child(1) th:nth-child(1)', table).text();
    return { title, $table };
  });
  const find = tablesIndex.get().find(el => el.title === nameToTitle[name]);
  if (find) return find.$table;
  return undefined;
}

export function getRecordInfo($) {
  const years = getTable($, 'years');
  const references = getTable($, 'references');
  const fields = getTable($, 'fields');
  const funds = getTable($, 'funds');
  return {
    belmarcId: $('span')[0].children[0].data.substr(4),
    years: years ? collectYears(years) : [],
    references: references ? collectReferences(references) : [],
    fields: fields ? collectFields($, fields) : [],
    funds: funds ? collectFunds(funds) : [],
  };
}

export function getRecordByID(alisEndpoint, id, callback) {
  const firstPageUrl = `/alis/EK/do_view.php?id=${id}`;
  const INITIAL_URL = `${alisEndpoint}${firstPageUrl}`;
  getPage({ url: INITIAL_URL }, (err, body) => {
    if (err) return callback(err);
    if (body.match('Undefined variable')) return callback(new Error('Record not found'));
    const $ = parsePage(body);
    const info = getRecordInfo($);
    info.id = id;
    return callback(null, info);
  });
}
<commit_msg>chore: add todo to order cache key<commit_after>import querystring from 'querystring';
import request from 'request';
import cheerio from 'cheerio';
import debug from 'debug';
import queryMap from './queryMap.json';

const log = debug('alis-web-request');

export const recordTypes = queryMap.recordType;

export function sendInitialQuery(params, callback) {
  if (!params.alisEndpoint) {
    return process.nextTick(callback, new Error('alisEndpoint is not provided'));
  }
  if (!params.query) {
    return process.nextTick(callback, new Error('query is not provided'));
  }
  if (!params.queryType) {
    return process.nextTick(callback, new Error('queryType is not provided'));
  }
  if (!params.recordType) {
    return process.nextTick(callback, new Error('recordType is not provided'));
  }
  const j = request.jar();
  const alisEndpoint = `${params.alisEndpoint}`;
  const qs = querystring.stringify({
    radiodate: 'simple',
    valueINP: params.query,
    tema: queryMap.recordType[params.recordType],
    tag: queryMap.queryType[params.queryType],
  });
  const firstPageUrl = `/alis/EK/do_searh.php?${qs}`;
  const INITIAL_URL = `${alisEndpoint}${firstPageUrl}`;

  log(`sendInitialQuery: ${INITIAL_URL}`);

  request({ url: INITIAL_URL, jar: j }, (err, response, body) => {
    if (err) {
      return callback(err);
    }
    callback(null, { page: body, jar: j });
  });
}

const cacheManager = require('cache-manager');
const fsHashStore = require('cache-manager-fs-hash');

const CACHE_DIR = `${__dirname}/../.cache`;

const pageCache = cacheManager.caching({
  store: fsHashStore,
  options: {
    ttl: 60 * 60 * 24 /* 1 day in seconds */,
    maxsize: 1000 * 1000 * 1000 /* max size in bytes on disk */,
    path: `${CACHE_DIR}/pages`,
    subdirs: true,
  },
});

export function getPage(options, callback) {
  const { url, jar, initParams } = options;

  log(`getPage: ${url}`);

  // TODO sort initParams entries to allow cache reuse on different props order
  const cacheKey = JSON.stringify({ url, ...initParams });

  pageCache.wrap(cacheKey, (cacheCallback) => {
    request({ url, jar }, (err, response, body) => {
      if (err) {
        return cacheCallback(err);
      }
      cacheCallback(null, body);
    });
  }, {}, callback);
}

export function getNextPageUrl($) {
  const pageLink = $('#Agt');
  const pageUrl = $(pageLink).attr('href');
  return pageUrl;
}

export function getTotal($) {
  const total = $('.listbzstat').first().text().match(/\d+(?=\sзап\.)/)[0];
  return total;
}

export function getItems($) {
  const items = $('.article').map(function (i, el) {
    return {
      id: $(el).attr('id').replace(/^H/, ''),
      title: $(el).text().trim(),
    };
  }).toArray();
  return items;
}

export function getNumberedPageUrls($) {
  // `fcheck` гэта лічба першай нумарованай старонкі, усяго іх будзе паказана дзевяць.
  //
  // `ccheck`, `crow`, `frow` не маюць дзеянне, але бяз іх з'яўляецца Notice.
  // Notice: Undefined index: ccheck in E:\ALIS\pls\alis\EK\do_other.php on line 42
  // Яны задаюцца аўтаматычна у нумар старонкі, і першы нумар рэзультату.
  //
  // `action` гэта нумар старонкі для паказа.
  const pageLinks = $('a[href^=\'do_other\']');
  const relativePageUrls = $(pageLinks).map((i, link) => $(link).attr('href').replace(/\r|\n/g, '')).toArray();
  return relativePageUrls;
}

export function parsePage(body) {
  const $ = cheerio.load(body);
  return $;
}

export function processItems(memo, q, options, callback) {
  if (!options) {
    return process.nextTick(callback, new Error('options is not provided'));
  }

  getPage(options, (err, body) => {
    if (err) return callback(err);
    const $ = parsePage(body);

    const items = getItems($);

    const nextPageUrl = getNextPageUrl($);
    const remainingQueue = q.slice(1);
    if (q.length === 1) {
      remainingQueue.push(`${nextPageUrl}`);
    }
    items.forEach((item) => {
      memo.push(item);
    });
    callback(null, memo, remainingQueue);
  });
}

export function run(fn, q, memo, options, callback) {
  if (!q) {
    return new Error('q is not provided');
  }

  if (q[0] === 'undefined') {
    return callback(null, memo);
  }
  fn(memo, q, { url: `${options.alisEndpoint}/alis/EK/${q[0]}`, ...options }, (err, nextMemo, nextQ) => {
    if (err) {
      return callback(err);
    }
    run(fn, nextQ, memo, options, callback);
  });
}

export function getRecordsByQuery(initParams, callback) {
  sendInitialQuery(initParams, (err, res) => {
    if (err) {
      return callback(err);
    }
    const options = {
      alisEndpoint: initParams.alisEndpoint,
      jar: res.jar,
      initParams,
    };
    if (res.page.match('<title>Не результативный поиск</title>')) {
      return callback(new Error('no match'));
    }
    const $ = parsePage(res.page);
    const firstNumberedPageUrls = getNumberedPageUrls($);
    const remainingQueue = firstNumberedPageUrls;
    run(processItems, remainingQueue, [], options, (runErr, memo) => {
      if (err) {
        return callback(err);
      }
      callback(null, memo);
    });
  });
}

export function collectReferences(table) {
  const references = [];
  const data = table.children().toArray();
  data.shift();
  data.forEach((el) => {
    const a = el.children[0].children[0];
    references.push({
      tag: Number(a.attribs.onclick.match(/[0-9]+/)[0]),
      value: a.children[0].data,
    });
  });
  return references;
}

export function collectFunds(table) {
  const funds = [];
  const data = table.children().toArray();
  data.shift();
  data.forEach((el) => {
    funds.push({
      name: el.children[0].children[0].children[0].data,
      count: Number(el.children[1].children[0].data),
    });
  });
  return funds;
}

export function collectFields($, table) {
  const fields = table.find('tr')
    .filter((i, tr) => {
      return $('tr:nth-child(1) th:nth-child(1)', tr).text() !== 'Название';
    }).map((i, tr) => {
      return {
        tag: $('td:nth-child(1)', tr).text(),
        value: $('td:nth-child(2)', tr).text(),
      };
    }).get();
  return fields;
}

export function collectYears(table) {
  const references = [];
  const data = table.children().toArray();
  data.shift();
  data.forEach((el) => {
    const a = el.children[0].children[0];
    references.push(Number(a.children[0].data.substr(0, 4)));
  });
  return references;
}

export function getTable($, name) {
  const nameToTitle = {
    years: 'Год(комплект)',
    references: 'Ссылки на др. биб.записи',
    fields: 'Название',
    funds: 'Фонд',
  };
  const tablesIndex = $('table').map((i, table) => {
    const $table = $(table);
    const title = $('tr:nth-child(1) th:nth-child(1)', table).text();
    return { title, $table };
  });
  const find = tablesIndex.get().find(el => el.title === nameToTitle[name]);
  if (find) return find.$table;
  return undefined;
}

export function getRecordInfo($) {
  const years = getTable($, 'years');
  const references = getTable($, 'references');
  const fields = getTable($, 'fields');
  const funds = getTable($, 'funds');
  return {
    belmarcId: $('span')[0].children[0].data.substr(4),
    years: years ? collectYears(years) : [],
    references: references ? collectReferences(references) : [],
    fields: fields ? collectFields($, fields) : [],
    funds: funds ? collectFunds(funds) : [],
  };
}

export function getRecordByID(alisEndpoint, id, callback) {
  const firstPageUrl = `/alis/EK/do_view.php?id=${id}`;
  const INITIAL_URL = `${alisEndpoint}${firstPageUrl}`;
  getPage({ url: INITIAL_URL }, (err, body) => {
    if (err) return callback(err);
    if (body.match('Undefined variable')) return callback(new Error('Record not found'));
    const $ = parsePage(body);
    const info = getRecordInfo($);
    info.id = id;
    return callback(null, info);
  });
}
<|endoftext|>


<commit_before>// @flow
/* global $Shape */
import { applyMiddleware, compose } from 'redux';
import type { Config } from './types';
import { createOfflineMiddleware } from './middleware';
import { enhanceReducer } from './updater';
import { applyDefaults } from './config';
import { networkStatusChanged } from './actions';

// @TODO: Take createStore as config?
const warnIfNotReduxAction = (config: $Shape<Config>, key: string) => {
  const maybeAction = config[key];

  const isNotReduxAction =
    maybeAction === null ||
    typeof maybeAction !== 'object' ||
    typeof maybeAction.type !== 'string' ||
    maybeAction.type === '';

  if (isNotReduxAction && console.warn) {
    const msg =
      `${key} must be a proper redux action, ` +
      `i.e. it must be an object and have a non-empty string type. ` +
      `Instead you provided: ${JSON.stringify(maybeAction, null, 2)}`;
    console.warn(msg);
  }
};

// eslint-disable-next-line no-unused-vars
let persistor;

export const offline = (userConfig: $Shape<Config> = {}) => (
  createStore: any
) => (reducer: any, preloadedState: any, enhancer: any = x => x) => {
  const config = applyDefaults(userConfig);

  warnIfNotReduxAction(config, 'defaultCommit');
  warnIfNotReduxAction(config, 'defaultRollback');

  // wraps userland reducer with a top-level
  // reducer that handles offline state updating
  const offlineReducer = enhanceReducer(reducer, config);

  const offlineMiddleware = applyMiddleware(createOfflineMiddleware(config));

  // create autoRehydrate enhancer if required
  const offlineEnhancer =
    config.persist && config.rehydrate && config.persistAutoRehydrate
      ? compose(offlineMiddleware, enhancer, config.persistAutoRehydrate())
      : compose(offlineMiddleware, enhancer);

  // create store
  const store = offlineEnhancer(createStore)(
    offlineReducer,
    preloadedState,
    enhancer
  );

  // launch store persistor
  if (config.persist) {
    persistor = config.persist(
      store,
      config.persistOptions,
      config.persistCallback
    );
  }

  // launch network detector
  if (config.detectNetwork) {
    config.detectNetwork(online => {
      store.dispatch(networkStatusChanged(online));
    });
  }

  return store;
};
<commit_msg>Remove double application of enhancer<commit_after>// @flow
/* global $Shape */
import { applyMiddleware, compose } from 'redux';
import type { Config } from './types';
import { createOfflineMiddleware } from './middleware';
import { enhanceReducer } from './updater';
import { applyDefaults } from './config';
import { networkStatusChanged } from './actions';

// @TODO: Take createStore as config?
const warnIfNotReduxAction = (config: $Shape<Config>, key: string) => {
  const maybeAction = config[key];

  const isNotReduxAction =
    maybeAction === null ||
    typeof maybeAction !== 'object' ||
    typeof maybeAction.type !== 'string' ||
    maybeAction.type === '';

  if (isNotReduxAction && console.warn) {
    const msg =
      `${key} must be a proper redux action, ` +
      `i.e. it must be an object and have a non-empty string type. ` +
      `Instead you provided: ${JSON.stringify(maybeAction, null, 2)}`;
    console.warn(msg);
  }
};

// eslint-disable-next-line no-unused-vars
let persistor;

export const offline = (userConfig: $Shape<Config> = {}) => (
  createStore: any
) => (reducer: any, preloadedState: any, enhancer: any = x => x) => {
  const config = applyDefaults(userConfig);

  warnIfNotReduxAction(config, 'defaultCommit');
  warnIfNotReduxAction(config, 'defaultRollback');

  // wraps userland reducer with a top-level
  // reducer that handles offline state updating
  const offlineReducer = enhanceReducer(reducer, config);

  const offlineMiddleware = applyMiddleware(createOfflineMiddleware(config));

  // create autoRehydrate enhancer if required
  const offlineEnhancer =
    config.persist && config.rehydrate && config.persistAutoRehydrate
      ? compose(offlineMiddleware, config.persistAutoRehydrate())
      : offlineMiddleware;

  // create store
  const store = offlineEnhancer(createStore)(
    offlineReducer,
    preloadedState,
    enhancer
  );

  // launch store persistor
  if (config.persist) {
    persistor = config.persist(
      store,
      config.persistOptions,
      config.persistCallback
    );
  }

  // launch network detector
  if (config.detectNetwork) {
    config.detectNetwork(online => {
      store.dispatch(networkStatusChanged(online));
    });
  }

  return store;
};
<|endoftext|>


<commit_before>'use strict'

import {Installer} from './main'
import {getDependencies} from './helpers'

if (typeof window.__steelbrain_package_deps === 'undefined') {
  window.__steelbrain_package_deps = new Set()
}

export async function install(name = null) {
  if (!name) {
    name = require('atom-package-path').guessFromCallIndex(5)
  }
  if (!name) {
    console.log(`Unable to get package name for file: ${filePath}`)
    return
  }

  const dependencies = getDependencies(name)
  if (dependencies.length) {
    await atom.packages.activatePackage('notifications')
    await new Installer(dependencies).install()
  }
}
<commit_msg>:new: Use the new installer API in main<commit_after>'use strict'

import {Installer} from './main'
import {getDependencies} from './helpers'

if (typeof window.__steelbrain_package_deps === 'undefined') {
  window.__steelbrain_package_deps = new Set()
}

export async function install(name = null) {
  if (!name) {
    name = require('atom-package-path').guessFromCallIndex(5)
  }
  if (!name) {
    console.log(`Unable to get package name for file: ${filePath}`)
    return
  }

  const dependencies = getDependencies(name)
  if (dependencies.length) {
    await atom.packages.activatePackage('notifications')
    await new Installer(name, dependencies).install()
  }
}
<|endoftext|>


<commit_before>import React from "react"
import ReactDOM from "react-dom"
import App from "./App"
import registerServiceWorker from "./registerServiceWorker"
import { MuiThemeProvider, createMuiTheme } from "material-ui/styles"
import createTypography from "material-ui/Typography"
import "typeface-arimo"
import { I18nextProvider } from "react-i18next"
import { i18n, i18next } from "./utils/i18n"

const oakland = {
  50: "#f1eee9",
  100: "#dbd4c8",
  200: "#c3b8a4",
  300: "#ab9c7f",
  400: "#b89f74",
  500: "#877148",
  600: "#7f6941",
  700: "#745e38",
  800: "#6a5430",
  900: "#574221",
  A100: "#0074b7",
  A200: "#0074b7",
  A400: "#0074b7",
  A700: "#0074b7",
  contrastDefaultColor: "light"
}

const oaklandAccent = {
  50: "#e0eef6",
  100: "#b3d5e9",
  200: "#80badb",
  300: "#4d9ecd",
  400: "#2689c2",
  500: "#0074b7",
  600: "#006cb0",
  700: "#0061a7",
  800: "#00579f",
  900: "#004490",
  A100: "#bcd6ff",
  A200: "#0074b7",
  A400: "#5699ff",
  A700: "#3c8aff",
  contrastDefaultColor: "light"
}

const theme = createMuiTheme({
  palette: {
    primary: oakland,
    secondary: oaklandAccent
  },
  typography: {
    fontFamily: "Arimo"
  }
})

const termBounds = [1494216000000, 1503720000000]

ReactDOM.render(
  <I18nextProvider i18n={i18n}>
    <MuiThemeProvider theme={theme}>
      <App
        theme={theme}
        eventsURLObj={{
          url: "http://localhost:8082/api/calendar",
          credentialsNeeded: false
        }}
        termBounds={termBounds}
        rootID="root"
      />
    </MuiThemeProvider>
  </I18nextProvider>,
  document.getElementById("root")
)
registerServiceWorker()
<commit_msg>Address @kdjohnson's issue<commit_after>import React from "react"
import ReactDOM from "react-dom"
import App from "./App"
import registerServiceWorker from "./registerServiceWorker"
import { MuiThemeProvider, createMuiTheme } from "material-ui/styles"
import createTypography from "material-ui/Typography"
import "typeface-arimo"
import { I18nextProvider } from "react-i18next"
import { i18n } from "./utils/i18n"

const oakland = {
  50: "#f1eee9",
  100: "#dbd4c8",
  200: "#c3b8a4",
  300: "#ab9c7f",
  400: "#b89f74",
  500: "#877148",
  600: "#7f6941",
  700: "#745e38",
  800: "#6a5430",
  900: "#574221",
  A100: "#0074b7",
  A200: "#0074b7",
  A400: "#0074b7",
  A700: "#0074b7",
  contrastDefaultColor: "light"
}

const oaklandAccent = {
  50: "#e0eef6",
  100: "#b3d5e9",
  200: "#80badb",
  300: "#4d9ecd",
  400: "#2689c2",
  500: "#0074b7",
  600: "#006cb0",
  700: "#0061a7",
  800: "#00579f",
  900: "#004490",
  A100: "#bcd6ff",
  A200: "#0074b7",
  A400: "#5699ff",
  A700: "#3c8aff",
  contrastDefaultColor: "light"
}

const theme = createMuiTheme({
  palette: {
    primary: oakland,
    secondary: oaklandAccent
  },
  typography: {
    fontFamily: "Arimo"
  }
})

const termBounds = [1494216000000, 1503720000000]

ReactDOM.render(
  <I18nextProvider i18n={i18n}>
    <MuiThemeProvider theme={theme}>
      <App
        theme={theme}
        eventsURLObj={{
          url: "http://localhost:8082/api/calendar",
          credentialsNeeded: false
        }}
        termBounds={termBounds}
        rootID="root"
      />
    </MuiThemeProvider>
  </I18nextProvider>,
  document.getElementById("root")
)
registerServiceWorker()
<|endoftext|>


<commit_before>import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';

class Square extends React.Component {
  constructor() {
    super();
    this.state = {
      value: null,
    };
  }
  render() {
    return (
      <button className="square" onClick={() => this.setState({value: 'X'})}>
        {this.state.value}
      </button>
    );
  }
}

class Board extends React.Component {
  renderSquare(i) {
    return <Square value={i} />;
  }

  render() {
    const status = 'Next player: X';

    return (

{status}

          {this.renderSquare(0)}
          {this.renderSquare(1)}
          {this.renderSquare(2)}

          {this.renderSquare(3)}
          {this.renderSquare(4)}
          {this.renderSquare(5)}

          {this.renderSquare(6)}
          {this.renderSquare(7)}
          {this.renderSquare(8)}

    );
  }
}

class Game extends React.Component {
  render() {
    return (

          <Board />

{/* status */}

{/* TODO */}

    );
  }
}

// ========================================

ReactDOM.render(
  <Game />,
  document.getElementById('root')
);
<commit_msg>a working game<commit_after>import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';

function Square(props) {
  return (
    <button className="square" onClick={props.onClick}>
      {props.value}
    </button>
  )
}

class Board extends React.Component {
  constructor() {
    super();
    this.state = {
      squares: Array(9).fill(null),
      xIsNext: true,
    };
  }

  handleClick(i) {
    const squares = this.state.squares.slice();
    if (calculateWinner(squares) || squares[i]) {
      return;
    }
    squares[i] = this.state.xIsNext ? 'X' : 'O';
    this.setState({
      squares: squares,
      xIsNext: !this.state.xIsNext,
    });
  }

  renderSquare(i) {
    return (
      <Square value={this.state.squares[i]}
              onClick={() => this.handleClick(i)}
      />
    );
  }

  render() {
    const winner = calculateWinner(this.state.squares);
    let status;
    if (winner) {
      status = 'Winner: ' + winner;
    } else {
      status = 'Next player: ' + (this.state.xIsNext ? 'X' : 'O');
    }

    return (

{status}

          {this.renderSquare(0)}
          {this.renderSquare(1)}
          {this.renderSquare(2)}

          {this.renderSquare(3)}
          {this.renderSquare(4)}
          {this.renderSquare(5)}

          {this.renderSquare(6)}
          {this.renderSquare(7)}
          {this.renderSquare(8)}

    );
  }
}

class Game extends React.Component {
  render() {
    return (

          <Board/>

{/* status */}

{/* TODO */}

    );
  }
}

// ========================================

ReactDOM.render(
  <Game/>,
  document.getElementById('root')
);

function calculateWinner(squares) {
  const lines = [
    [0, 1, 2],
    [3, 4, 5],
    [6, 7, 8],
    [0, 3, 6],
    [1, 4, 7],
    [2, 5, 8],
    [0, 4, 8],
    [2, 4, 6],
  ];
  for (let i = 0; i < lines.length; i++) {
    const [a, b, c] = lines[i];
    if (squares[a] && squares[a] === squares[b]
      && squares[a] === squares[c]) {
      return squares[a];
    }
  }
  return null;
}<|endoftext|>


<commit_before>import registerServiceWorker from './registerServiceWorker';
import * as Stores from 'common/stores';
import { registerKeyboardBindings } from 'common/utils';
import { openConnection, Writer } from 'common/connection';

window.addEventListener('resize', () => Stores.view.updateDimensions());
window.addEventListener('unload', () => Writer.exit()); // When closing the view
registerKeyboardBindings();
registerServiceWorker();
openConnection();<commit_msg>Only kills the server when not in debug mode<commit_after>import registerServiceWorker from './registerServiceWorker';
import * as Stores from 'common/stores';
import { General } from 'common/constants';
import { registerKeyboardBindings } from 'common/utils';
import { openConnection, Writer } from 'common/connection';

window.addEventListener('resize', () => Stores.view.updateDimensions());
!General.DEBUG && window.addEventListener('unload', () => Writer.exit()); // When closing the view
registerKeyboardBindings();
registerServiceWorker();
openConnection();<|endoftext|>


<commit_before>import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';

// Internal utility fns
function calculateWinner(squares) {
  const lines = [
    [0, 1, 2],
    [3, 4, 5],
    [6, 7, 8],
    [0, 3, 6],
    [1, 4, 7],
    [2, 5, 8],
    [0, 4, 8],
    [2, 4, 6],
  ];
  for (let i = 0; i < lines.length; i++) {
    const [a, b, c] = lines[i];
    if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) {
      return squares[a];
    }
  }
  return null;
}

function Square(props) {
  return (
    <button className="square" onClick={props.onClick}>
      {props.value}
    </button>
  );
}

class Board extends React.Component {
  constructor() {
    super();

    this.state = {
      squares: Array(9).fill(null),
      xIsNext: true
    }
  }
  renderSquare(i) {
    return <Square value={this.props.squares[i]} onClick={() => this.props.onClick(i)}/>;
  }

  render() {
    return (

          {this.renderSquare(0)}
          {this.renderSquare(1)}
          {this.renderSquare(2)}

          {this.renderSquare(3)}
          {this.renderSquare(4)}
          {this.renderSquare(5)}

          {this.renderSquare(6)}
          {this.renderSquare(7)}
          {this.renderSquare(8)}

    );
  }
}

class Game extends React.Component {
  constructor() {
    super();
    this.state = {
      history: [{
        squares: Array(9).fill(null),
      }],
      xIsNext: true,
    };
  }

  handleClick(i) {
    const history = this.state.history;
    const current = history[history.length - 1];
    const squares = current.squares.slice();
    if (calculateWinner(squares) || squares[i]) {
      return;
    }
    squares[i] = this.state.xIsNext ? 'X' : 'O';
    this.setState({
      history: history.concat([{
        squares: squares,
      }]),
      xIsNext: !this.state.xIsNext
    });
  }

  render() {
    const history = this.state.history;
    const current = history[history.length - 1];
    const winner = calculateWinner(current.squares);

    const moves = history.map((step, move) => {
      const desc = move ?
        'Move #' + move :
        'Game start';
      return (

           this.jumpTo(move)}>{desc}

      );
    });

    let status;
    if (winner) {
      status = 'Winner: ' + winner;
    } else {
      status = 'Next player: ' + (this.state.xIsNext ? 'X' : 'O');
    }

    return (

          <Board squares={current.squares} onClick={(i) => this.handleClick(i)}/>

{status}

{/* TODO */}

    );
  }
}

// ========================================

ReactDOM.render(
  <Game />,
  document.getElementById('root')
);
<commit_msg>Finished the last step in the tutorial. Now come the fun modificatons<commit_after>import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';

// Internal utility fns
function calculateWinner(squares) {
  const lines = [
    [0, 1, 2],
    [3, 4, 5],
    [6, 7, 8],
    [0, 3, 6],
    [1, 4, 7],
    [2, 5, 8],
    [0, 4, 8],
    [2, 4, 6],
  ];
  for (let i = 0; i < lines.length; i++) {
    const [a, b, c] = lines[i];
    if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) {
      return squares[a];
    }
  }
  return null;
}

function Square(props) {
  return (
    <button className="square" onClick={props.onClick}>
      {props.value}
    </button>
  );
}

class Board extends React.Component {
  constructor() {
    super();

    this.state = {
      squares: Array(9).fill(null),
      xIsNext: true
    }
  }
  renderSquare(i) {
    return <Square value={this.props.squares[i]} onClick={() => this.props.onClick(i)}/>;
  }

  render() {
    return (

          {this.renderSquare(0)}
          {this.renderSquare(1)}
          {this.renderSquare(2)}

          {this.renderSquare(3)}
          {this.renderSquare(4)}
          {this.renderSquare(5)}

          {this.renderSquare(6)}
          {this.renderSquare(7)}
          {this.renderSquare(8)}

    );
  }
}

class Game extends React.Component {
  constructor() {
    super();
    this.state = {
      history: [{
        squares: Array(9).fill(null),
      }],
      stepNumber: 0,
      xIsNext: true,
    };
  }

  handleClick(i) {
    const history = this.state.history.slice(0, this.state.stepNumber + 1);
    const current = history[history.length - 1];
    const squares = current.squares.slice();
    if (calculateWinner(squares) || squares[i]) {
      return;
    }
    squares[i] = this.state.xIsNext ? 'X' : 'O';
    this.setState({
      history: history.concat([{
        squares: squares,
      }]),
      stepNumber: history.length,
      xIsNext: !this.state.xIsNext
    });
  }

  jumpTo(step) {
    this.setState({
      stepNumber: step,
      xIsNext: (step % 2) === 0,
    });
  }

  render() {
    const history = this.state.history;
    const current = history[this.state.stepNumber];
    const winner = calculateWinner(current.squares);

    const moves = history.map((step, move) => {
      const desc = move ?
        'Move #' + move :
        'Game start';
      return (

           this.jumpTo(move)}>{desc}

      );
    });

    let status;
    if (winner) {
      status = 'Winner: ' + winner;
    } else {
      status = 'Next player: ' + (this.state.xIsNext ? 'X' : 'O');
    }

    return (

          <Board squares={current.squares} onClick={(i) => this.handleClick(i)}/>

{status}

{moves}

    );
  }
}

// ========================================

ReactDOM.render(
  <Game />,
  document.getElementById('root')
);
<|endoftext|>


<commit_before>function BrowserNotification(options) {
  // Handle old browsers - this way we can skip polyfill Promise and Object.assign
  // (No browser with Notification lacks Promise or Object.assign)
  if (!window.hasOwnProperty('Notification')) {
    console.info('This browser does not support notifications');

    // Return no-op function and mock promise
    return {
      notify: () => {},
      availablePromise: {
        then: fn => {
          fn(false);
        }
      }
    };
  }

  const defaults = {
    ignoreFocused: true,
    timeout: 0,
    cooldown: 0
  };
  const settings = Object.assign(defaults, options);

  const availablePromise = new Promise((resolve, reject) => {
    if (Notification.permission === 'granted') {
      resolve(true);
    } else if (Notification.permission !== 'denied') {
      Notification.requestPermission().then(permission => {
        if (permission === 'granted') {
          resolve(true);
        }
        resolve(false);
      });
    } else {
      resolve(false);
    }
  });

  let available = false;
  let cooldownActive = false;
  let focused = true;

  availablePromise.then(result => {
    available = result;
  });

  window.onfocus = () => {
    focused = true;
  };

  window.onblur = () => {
    focused = false;
  };

  function notify(title, notifyOptions) {
    if (!available || ignoreFocused && focused || cooldownActive) {
      return null;
    }

    const n = new Notification(title, notifyOptions);

    n.onclick = () => {
      window.focus();
      n.close();
    };

    if (settings.timeout !== 0) {
      window.setTimeout(
        () => {
          n.close();
        },
        settings.timeout
      );
    }

    if (settings.cooldown !== 0) {
      cooldownActive = true;
      window.setTimeout(
        () => {
          cooldownActive = false;
        },
        settings.cooldown
      );
    }

    return n;
  }

  return {
    notify: notify,
    availablePromise: availablePromise
  };
}

export {BrowserNotification};
<commit_msg>Fix typo breaking notify<commit_after>function BrowserNotification(options) {
  // Handle old browsers - this way we can skip polyfill Promise and Object.assign
  // (No browser with Notification lacks Promise or Object.assign)
  if (!window.hasOwnProperty('Notification')) {
    console.info('This browser does not support notifications');

    // Return no-op function and mock promise
    return {
      notify: () => {},
      availablePromise: {
        then: fn => {
          fn(false);
        }
      }
    };
  }

  const defaults = {
    ignoreFocused: true,
    timeout: 0,
    cooldown: 0
  };
  const settings = Object.assign(defaults, options);

  const availablePromise = new Promise((resolve, reject) => {
    if (Notification.permission === 'granted') {
      resolve(true);
    } else if (Notification.permission !== 'denied') {
      Notification.requestPermission().then(permission => {
        if (permission === 'granted') {
          resolve(true);
        }
        resolve(false);
      });
    } else {
      resolve(false);
    }
  });

  let available = false;
  let cooldownActive = false;
  let focused = true;

  availablePromise.then(result => {
    available = result;
  });

  window.onfocus = () => {
    focused = true;
  };

  window.onblur = () => {
    focused = false;
  };

  function notify(title, notifyOptions) {
    if (!available || settings.ignoreFocused && focused || cooldownActive) {
      return null;
    }

    const n = new Notification(title, notifyOptions);

    n.onclick = () => {
      window.focus();
      n.close();
    };

    if (settings.timeout !== 0) {
      window.setTimeout(
        () => {
          n.close();
        },
        settings.timeout
      );
    }

    if (settings.cooldown !== 0) {
      cooldownActive = true;
      window.setTimeout(
        () => {
          cooldownActive = false;
        },
        settings.cooldown
      );
    }

    return n;
  }

  return {
    notify: notify,
    availablePromise: availablePromise
  };
}

export {BrowserNotification};
<|endoftext|>