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

import { RenderingCancelledException } from "pdfjs-lib";

const CLEANUP_TIMEOUT = 30000;

const RenderingStates = {
  INITIAL: 0,
  RUNNING: 1,
  PAUSED: 2,
  FINISHED: 3,
};

/**
 * Controls rendering of the views for pages and thumbnails.
 */
class PDFRenderingQueue {
  constructor() {
    this.pdfViewer = null;
    this.pdfThumbnailViewer = null;
    this.onIdle = null;
    this.highestPriorityPage = null;
    /** @type {number} */
    this.idleTimeout = null;
    this.printing = false;
    this.isThumbnailViewEnabled = false;
  }

  /**
   * @param {PDFViewer} pdfViewer
   */
  setViewer(pdfViewer) {
    this.pdfViewer = pdfViewer;
  }

  /**
   * @param {PDFThumbnailViewer} pdfThumbnailViewer
   */
  setThumbnailViewer(pdfThumbnailViewer) {
    this.pdfThumbnailViewer = pdfThumbnailViewer;
  }

  /**
   * @param {IRenderableView} view
   * @returns {boolean}
   */
  isHighestPriority(view) {
    return this.highestPriorityPage === view.renderingId;
  }

  /**
   * @returns {boolean}
   */
  hasViewer() {
    return !!this.pdfViewer;
  }

  /**
   * @param {Object} currentlyVisiblePages
   */
  renderHighestPriority(currentlyVisiblePages) {
    if (this.idleTimeout) {
      clearTimeout(this.idleTimeout);
      this.idleTimeout = null;
    }

    // Pages have a higher priority than thumbnails, so check them first.
    if (this.pdfViewer.forceRendering(currentlyVisiblePages)) {
      return;
    }
    // No pages needed rendering, so check thumbnails.
    if (this.pdfThumbnailViewer && this.isThumbnailViewEnabled) {
      if (this.pdfThumbnailViewer.forceRendering()) {
        return;
      }
    }

    if (this.printing) {
      // If printing is currently ongoing do not reschedule cleanup.
      return;
    }

    if (this.onIdle) {
      this.idleTimeout = setTimeout(this.onIdle.bind(this), CLEANUP_TIMEOUT);
    }
  }

  /**
   * @param {Object} visible
   * @param {Array} views
   * @param {boolean} scrolledDown
   * @param {boolean} [preRenderExtra]
   */
  getHighestPriority(visible, views, scrolledDown, preRenderExtra = false) {
    /**
     * The state has changed. Figure out which page has the highest priority to
     * render next (if any).
     *
     * Priority:
     * 1. visible pages
     * 2. if last scrolled down, the page after the visible pages, or
     *    if last scrolled up, the page before the visible pages
     */
    const visibleViews = visible.views;

    const numVisible = visibleViews.length;
    if (numVisible === 0) {
      return null;
    }
    for (let i = 0; i < numVisible; ++i) {
      const view = visibleViews[i].view;
      if (!this.isViewFinished(view)) {
        return view;
      }
    }

    // All the visible views have rendered; try to render next/previous page.
    // (IDs start at 1, so no need to add 1 when `scrolledDown === true`.)
    let preRenderIndex = scrolledDown ? visible.last.id : visible.first.id - 2;
    let preRenderView = views[preRenderIndex];

    if (preRenderView && !this.isViewFinished(preRenderView)) {
      return preRenderView;
    }
    if (preRenderExtra) {
      preRenderIndex += scrolledDown ? 1 : -1;
      preRenderView = views[preRenderIndex];

      if (preRenderView && !this.isViewFinished(preRenderView)) {
        return preRenderView;
      }
    }
    // Everything that needs to be rendered has been.
    return null;
  }

  /**
   * @param {IRenderableView} view
   * @returns {boolean}
   */
  isViewFinished(view) {
    return view.renderingState === RenderingStates.FINISHED;
  }

  /**
   * Render a page or thumbnail view. This calls the appropriate function
   * based on the views state. If the view is already rendered it will return
   * `false`.
   *
   * @param {IRenderableView} view
   */
  renderView(view) {
    switch (view.renderingState) {
      case RenderingStates.FINISHED:
        return false;
      case RenderingStates.PAUSED:
        this.highestPriorityPage = view.renderingId;
        view.resume();
        break;
      case RenderingStates.RUNNING:
        this.highestPriorityPage = view.renderingId;
        break;
      case RenderingStates.INITIAL:
        this.highestPriorityPage = view.renderingId;
        view
          .draw()
          .finally(() => {
            this.renderHighestPriority();
          })
          .catch(reason => {
            if (reason instanceof RenderingCancelledException) {
              return;
            }
            console.error(`renderView: "${reason}"`);
          });
        break;
    }
    return true;
  }
}

export { PDFRenderingQueue, RenderingStates };
<commit_msg>Ensure that pre-rendering works correctly with spreadModes at higher zoom levels<commit_after>/* Copyright 2012 Mozilla Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import { RenderingCancelledException } from "pdfjs-lib";

const CLEANUP_TIMEOUT = 30000;

const RenderingStates = {
  INITIAL: 0,
  RUNNING: 1,
  PAUSED: 2,
  FINISHED: 3,
};

/**
 * Controls rendering of the views for pages and thumbnails.
 */
class PDFRenderingQueue {
  constructor() {
    this.pdfViewer = null;
    this.pdfThumbnailViewer = null;
    this.onIdle = null;
    this.highestPriorityPage = null;
    /** @type {number} */
    this.idleTimeout = null;
    this.printing = false;
    this.isThumbnailViewEnabled = false;
  }

  /**
   * @param {PDFViewer} pdfViewer
   */
  setViewer(pdfViewer) {
    this.pdfViewer = pdfViewer;
  }

  /**
   * @param {PDFThumbnailViewer} pdfThumbnailViewer
   */
  setThumbnailViewer(pdfThumbnailViewer) {
    this.pdfThumbnailViewer = pdfThumbnailViewer;
  }

  /**
   * @param {IRenderableView} view
   * @returns {boolean}
   */
  isHighestPriority(view) {
    return this.highestPriorityPage === view.renderingId;
  }

  /**
   * @returns {boolean}
   */
  hasViewer() {
    return !!this.pdfViewer;
  }

  /**
   * @param {Object} currentlyVisiblePages
   */
  renderHighestPriority(currentlyVisiblePages) {
    if (this.idleTimeout) {
      clearTimeout(this.idleTimeout);
      this.idleTimeout = null;
    }

    // Pages have a higher priority than thumbnails, so check them first.
    if (this.pdfViewer.forceRendering(currentlyVisiblePages)) {
      return;
    }
    // No pages needed rendering, so check thumbnails.
    if (this.pdfThumbnailViewer && this.isThumbnailViewEnabled) {
      if (this.pdfThumbnailViewer.forceRendering()) {
        return;
      }
    }

    if (this.printing) {
      // If printing is currently ongoing do not reschedule cleanup.
      return;
    }

    if (this.onIdle) {
      this.idleTimeout = setTimeout(this.onIdle.bind(this), CLEANUP_TIMEOUT);
    }
  }

  /**
   * @param {Object} visible
   * @param {Array} views
   * @param {boolean} scrolledDown
   * @param {boolean} [preRenderExtra]
   */
  getHighestPriority(visible, views, scrolledDown, preRenderExtra = false) {
    /**
     * The state has changed. Figure out which page has the highest priority to
     * render next (if any).
     *
     * Priority:
     * 1. visible pages
     * 2. if last scrolled down, the page after the visible pages, or
     *    if last scrolled up, the page before the visible pages
     */
    const visibleViews = visible.views;

    const numVisible = visibleViews.length;
    if (numVisible === 0) {
      return null;
    }
    for (let i = 0; i < numVisible; ++i) {
      const view = visibleViews[i].view;
      if (!this.isViewFinished(view)) {
        return view;
      }
    }
    const firstId = visible.first.id,
      lastId = visible.last.id;

    // All the visible views have rendered; try to handle any "holes" in the
    // page layout (can happen e.g. with spreadModes at higher zoom levels).
    if (lastId - firstId > 1) {
      for (let i = 0, ii = lastId - firstId; i <= ii; i++) {
        const holeId = scrolledDown ? firstId + i : lastId - i,
          holeView = views[holeId - 1];
        if (!this.isViewFinished(holeView)) {
          return holeView;
        }
      }
    }

    // All the visible views have rendered; try to render next/previous page.
    // (IDs start at 1, so no need to add 1 when `scrolledDown === true`.)
    let preRenderIndex = scrolledDown ? lastId : firstId - 2;
    let preRenderView = views[preRenderIndex];

    if (preRenderView && !this.isViewFinished(preRenderView)) {
      return preRenderView;
    }
    if (preRenderExtra) {
      preRenderIndex += scrolledDown ? 1 : -1;
      preRenderView = views[preRenderIndex];

      if (preRenderView && !this.isViewFinished(preRenderView)) {
        return preRenderView;
      }
    }
    // Everything that needs to be rendered has been.
    return null;
  }

  /**
   * @param {IRenderableView} view
   * @returns {boolean}
   */
  isViewFinished(view) {
    return view.renderingState === RenderingStates.FINISHED;
  }

  /**
   * Render a page or thumbnail view. This calls the appropriate function
   * based on the views state. If the view is already rendered it will return
   * `false`.
   *
   * @param {IRenderableView} view
   */
  renderView(view) {
    switch (view.renderingState) {
      case RenderingStates.FINISHED:
        return false;
      case RenderingStates.PAUSED:
        this.highestPriorityPage = view.renderingId;
        view.resume();
        break;
      case RenderingStates.RUNNING:
        this.highestPriorityPage = view.renderingId;
        break;
      case RenderingStates.INITIAL:
        this.highestPriorityPage = view.renderingId;
        view
          .draw()
          .finally(() => {
            this.renderHighestPriority();
          })
          .catch(reason => {
            if (reason instanceof RenderingCancelledException) {
              return;
            }
            console.error(`renderView: "${reason}"`);
          });
        break;
    }
    return true;
  }
}

export { PDFRenderingQueue, RenderingStates };
<|endoftext|>


<commit_before>module.exports = function (app) {

	return {

		// ALLOW TESLA LOGGING TO BE TURNED OFF IN CONFIG
		log: function(what) {
			if ( app.config.logging.console === true ) console.log(what);
		},

		emptyObject: function(obj) {
		  return !Object.keys(obj).length;
		},

		countObject: function(obj) {
			var count = 0;
			for( key in obj ) {
			  if(obj(key)) {
			    count++;
			  }
			}

			return count;
		}

	}

};<commit_msg>add error handler<commit_after>module.exports = function (app) {

	return {

		// ALLOW TESLA LOGGING TO BE TURNED OFF IN CONFIG
		log: function(what) {
			if ( app.config.logging.console === true ) console.log(what);
		},

		emptyObject: function(obj) {
		  return !Object.keys(obj).length;
		},

		countObject: function(obj) {
			var count = 0;
			for( key in obj ) {
			  if(obj(key)) {
			    count++;
			  }
			}

			return count;
		},

		throw: function(num) {

			var code = {
				400 : '400 Bad Request',
				401 : '401 Unauthorized',
				403 : '403 Forbidden',
				404 : '404 Not Found',
				405 : '405 Method Not Allowed',
				500 : '500 Internal Server Error',
			}

			var err = new Error( code[num] );
			    err.code = num;
			    err.message = code[num];
			    err.status = num;

			return err;

		}

	}

};<|endoftext|>


<commit_before>/**
 * Created by kribh03 on 17-Jun-16.
 */
<commit_msg>Delete tableDirective.js<commit_after><|endoftext|>


<commit_before>
module.exports = owner

owner.usage = "npm owner add <username> <pkg>"
            + "\nnpm owner rm <username> <pkg>"
            + "\nnpm owner ls <pkg>"

owner.completion = function(args, index, cb) {
  var remotePkgs = require("./utils/completion/remote-packages")
    , getCompletions = require("./utils/completion/get-completions")
    , subcmdList = ["add", "ls", "rm"]
    , subcmd = args[0] || ""
    , users = require("./utils/completion/users")

  if (subcmdList.indexOf(subcmd) !== -1) {
    if (subcmd === "ls") {
      remotePkgs(args.slice(1), index - 1, false, false, false, cb)
    } else if (subcmd === "add" || subcmd === "rm") {
      if (index === 4) {
        remotePkgs(args.slice(2), index - 2, false, false, false, cb)
      } else {
        users(args.slice(1), index - 1, cb)
      }
    }
  } else cb(null, getCompletions(subcmd, subcmdList))
}

var registry = require("./utils/npm-registry-client")
  , get = registry.request.GET
  , put = registry.request.PUT
  , log = require("./utils/log")
  , output
  , npm = require("../npm")

function owner (args, cb) {
  var action = args.shift()
  switch (action) {
    case "ls": case "list": return ls(args[0], cb)
    case "add": return add(args[0], args[1], cb)
    case "rm": case "remove": return rm(args[0], args[1], cb)
    default: return unknown(action, cb)
  }
}

function ls (pkg, cb) {
  if (!pkg) return cb(owner.usage)
  get(pkg, function (er, data) {
    var msg = ""
    if (er) return log.er(cb, "Couldn't get owner data for "+pkg)(er)
    var owners = data.maintainers
    if (!owners || !owners.length) msg = "admin party!"
    else msg = owners.map(function (o) { return o.name +" <"+o.email+">" }).join("\n")
    output = output || require("./utils/output")
    output.write(msg, function (er) { cb(er, owners) })
  })
}

function add (user, pkg, cb) {
  log.verbose(user+" to "+pkg, "owner add")
  mutate(pkg, user, function (u, owners) {
    if (!owners) owners = []
    for (var i = 0, l = owners.length; i < l; i ++) {
      var o = owners[i]
      if (o.name === u.name) {
        log( "Already a package owner: "+o.name+" <"+o.email+">"
           , "owner add"
           )
        return false
      }
    }
    owners.push(u)
    return owners
  }, cb)
}
function rm (user, pkg, cb) {
  log.verbose(user+" from "+pkg, "owner rm")
  mutate(pkg, user, function (u, owners) {
    var found = false
      , m = owners.filter(function (o) {
          var match = (o.name === u.name || o.email === u.email)
          found = found || match
          return !match
        })
    if (!found) {
      log("Not a package owner: "+u.name+" <"+u.email+">", "owner rm")
      return false
    }
    if (!m.length) return new Error(
      "Cannot remove all owners of a package.  Add someone else first.")
    return m
  }, cb)
}
function mutate (pkg, user, mutation, cb) {
  get("/-/user/org.couchdb.user:"+user, function (er, u) {
    if (er) return log.er(cb, "Error getting user data for "+user)(er)
    if (!u || u.error) return cb(new Error(
      "Couldn't get user data for "+user+": "+JSON.stringify(u)))
    get("/"+pkg, function (er, data) {
      if (er) return log.er(cb, "Couldn't get package data for "+pkg)(er)
      var m = mutation({ "name" : u.name, "email" : u.email }, data.maintainers)
      if (!m) return cb() // handled
      if (m instanceof Error) return cb(m) // error
      data = { _id : data._id
             , _rev : data._rev
             , maintainers : m
             }
      put("/"+pkg+"/-rev/"+data._rev, data, function (er, data) {
        if (er) return log.er(cb, "Failed to update package metadata")(er)
        if (data.error) return cb(new Error(
          "Failed to update pacakge metadata: "+JSON.stringify(data)))
        cb(null, data)
      })
    })
  })
}

function unknown (action, cb) {
  cb("Usage: \n"+owner.usage)
}
<commit_msg>completion for owner command<commit_after>
module.exports = owner

owner.usage = "npm owner add <username> <pkg>"
            + "\nnpm owner rm <username> <pkg>"
            + "\nnpm owner ls <pkg>"

owner.completion = function (opts, cb) {
  var argv = opts.conf.argv.remain
  if (argv.length > 4) return cb()
  if (argv.length <= 2) {
    var subs = ["add", "rm"]
    if (opts.partialWord === "l") subs.push("ls")
    else subs.push("ls", "list")
    return cb(null, subs)
  }
  var un = encodeURIComponent(npm.config.get("username"))
  switch (argv[2]) {
    case "ls":
      if (argv.length > 3) return cb()
      else return registry.get("/-/short", cb)

    case "rm":
      if (argv.length > 3) {
        var theUser = encodeURIComponent(argv[3])
          , uri = "/-/by-user/"+theUser+"|"+un
        console.error(uri)
        return registry.get(uri, function (er, d) {
          if (er) return cb(er)
          // return the intersection
          return cb(null, d[theUser].filter(function (p) {
            // kludge for server adminery.
            return un === "isaacs" || d[un].indexOf(p) === -1
          }))
        })
      }
      // else fallthrough
    case "add":
      if (argv.length > 3) {
        var theUser = encodeURIComponent(argv[3])
          , uri = "/-/by-user/"+theUser+"|"+un
        console.error(uri)
        return registry.get(uri, function (er, d) {
          console.error(uri, er || d)
          // return mine that they're not already on.
          if (er) return cb(er)
          var mine = d[un] || []
            , theirs = d[theUser] || []
          return cb(null, mine.filter(function (p) {
            return theirs.indexOf(p) === -1
          }))
        })
      }
      // just list all users who aren't me.
      return registry.get("/-/users", function (er, list) {
        if (er) return cb()
        return cb(null, Object.keys(list).filter(function (n) {
          return n !== un
        }))
      })

    default:
      return cb()
  }
}

var registry = require("./utils/npm-registry-client")
  , get = registry.request.GET
  , put = registry.request.PUT
  , log = require("./utils/log")
  , output
  , npm = require("../npm")

function owner (args, cb) {
  var action = args.shift()
  switch (action) {
    case "ls": case "list": return ls(args[0], cb)
    case "add": return add(args[0], args[1], cb)
    case "rm": case "remove": return rm(args[0], args[1], cb)
    default: return unknown(action, cb)
  }
}

function ls (pkg, cb) {
  if (!pkg) return cb(owner.usage)
  get(pkg, function (er, data) {
    var msg = ""
    if (er) return log.er(cb, "Couldn't get owner data for "+pkg)(er)
    var owners = data.maintainers
    if (!owners || !owners.length) msg = "admin party!"
    else msg = owners.map(function (o) { return o.name +" <"+o.email+">" }).join("\n")
    output = output || require("./utils/output")
    output.write(msg, function (er) { cb(er, owners) })
  })
}

function add (user, pkg, cb) {
  log.verbose(user+" to "+pkg, "owner add")
  mutate(pkg, user, function (u, owners) {
    if (!owners) owners = []
    for (var i = 0, l = owners.length; i < l; i ++) {
      var o = owners[i]
      if (o.name === u.name) {
        log( "Already a package owner: "+o.name+" <"+o.email+">"
           , "owner add"
           )
        return false
      }
    }
    owners.push(u)
    return owners
  }, cb)
}
function rm (user, pkg, cb) {
  log.verbose(user+" from "+pkg, "owner rm")
  mutate(pkg, user, function (u, owners) {
    var found = false
      , m = owners.filter(function (o) {
          var match = (o.name === u.name || o.email === u.email)
          found = found || match
          return !match
        })
    if (!found) {
      log("Not a package owner: "+u.name+" <"+u.email+">", "owner rm")
      return false
    }
    if (!m.length) return new Error(
      "Cannot remove all owners of a package.  Add someone else first.")
    return m
  }, cb)
}
function mutate (pkg, user, mutation, cb) {
  get("/-/user/org.couchdb.user:"+user, function (er, u) {
    if (er) return log.er(cb, "Error getting user data for "+user)(er)
    if (!u || u.error) return cb(new Error(
      "Couldn't get user data for "+user+": "+JSON.stringify(u)))
    get("/"+pkg, function (er, data) {
      if (er) return log.er(cb, "Couldn't get package data for "+pkg)(er)
      var m = mutation({ "name" : u.name, "email" : u.email }, data.maintainers)
      if (!m) return cb() // handled
      if (m instanceof Error) return cb(m) // error
      data = { _id : data._id
             , _rev : data._rev
             , maintainers : m
             }
      put("/"+pkg+"/-rev/"+data._rev, data, function (er, data) {
        if (er) return log.er(cb, "Failed to update package metadata")(er)
        if (data.error) return cb(new Error(
          "Failed to update pacakge metadata: "+JSON.stringify(data)))
        cb(null, data)
      })
    })
  })
}

function unknown (action, cb) {
  cb("Usage: \n"+owner.usage)
}
<|endoftext|>


<commit_before>/*******************************************************************************
 * Copyright (c) 2014, Institute for Pervasive Computing, ETH Zurich.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the Institute nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * This file is part of the Copper (Cu) CoAP user-agent.
 ******************************************************************************/
/**
 * \file
 *         Content-type rendering functions
 *
 * \author  Matthias Kovatsch <kovatsch@inf.ethz.ch>\author
 */

// Rendering functions
////////////////////////////////////////////////////////////////////////////////

CopperChrome.renderText = function(message) {
	CopperChrome.updateLabel('packet_payload', Copper.bytes2str(message.getPayload()), false);
	document.getElementById('tabs_payload').selectedIndex = 0;
};

CopperChrome.renderImage = function(message) {

	if (!message.getBlockMore()) {
		// only render binary when transfer is complete (binary is heavy)
		CopperChrome.renderBinary(message);
	}

	// view corresponding render element
	document.getElementById('rendered_div').style.display = 'none';
	document.getElementById('rendered_img').style.display = 'block';

	// causes flickering, but partially added data does not draw anyway
	document.getElementById('rendered_img').src = 'data:'+Copper.getContentTypeName(message.getContentType())+';base64,'+btoa( Copper.bytes2data(message.getPayload()) );
	document.getElementById('tabs_payload').selectedIndex = 1;
};

CopperChrome.renderBinary = function(message) {

	var pl = message.getPayload();

	// TODO: loop is too heavy for large payloads, alternatives?
	for (var i in pl) {

		CopperChrome.updateLabel('packet_payload', Copper.leadingZero(pl[i].toString(16).toUpperCase()), true);

		if (i % 16 == 15) {
			CopperChrome.updateLabel('packet_payload', ' | ', true);
			for (var j=i-15; j<=i; ++j) {
				if (pl[j] < 32) {
					CopperChrome.updateLabel('packet_payload', '·', true);
				} else {
					CopperChrome.updateLabel('packet_payload', String.fromCharCode(pl[j] & 0xFF), true);
				}
			}
			CopperChrome.updateLabel('packet_payload', '\n', true);
		} else if (i % 2 == 1) {
			CopperChrome.updateLabel('packet_payload', ' ', true);
		}
	}

	// incomplete lines
	if ((parseInt(i)+1) % 16 != 0) {
		// complete line with spaces
		for (var j=0; j<39-((parseInt(i)+1)%16)*2 - ((parseInt(i)+1)%16)/2; ++j) {
			CopperChrome.updateLabel('packet_payload', ' ', true);
		}

		CopperChrome.updateLabel('packet_payload', ' | ', true);
		for (var j=i-(i%16); j<=i; ++j) {
			if (pl[j] < 32) {
				CopperChrome.updateLabel('packet_payload', '·', true);
			} else {
				CopperChrome.updateLabel('packet_payload', String.fromCharCode(pl[j] & 0xFF), true);
			}
		}
	}

	document.getElementById('tabs_payload').selectedIndex = 0;
};

CopperChrome.renderLinkFormat = function(message) {

	// Print raw Link Format in case parsing fails
	CopperChrome.renderText(message);

	// The box for output at the top-level
	document.getElementById('rendered_img').style.display = 'none';
    var view = document.getElementById('rendered_div');
    view.style.display = 'block';

    while (view.hasChildNodes()) {
    	view.removeChild(view.firstChild);
    }
    view.setAttribute("class", "link-content");

	var parsedObj = CopperChrome.parseLinkFormat( Copper.bytes2str(message.getPayload()) );

	view.appendChild( CopperChrome.renderLinkFormatUtils.getXulLinks(parsedObj) );

	document.getElementById('tabs_payload').selectedIndex = 1;
};

CopperChrome.renderLinkFormatUtils = {

	htmlns: "http://www.w3.org/1999/xhtml",

	getXulLinks: function(value) {
		if (typeof value != 'object') {
			return null;
		}

		var xulObj = document.createElementNS(this.htmlns, "ul");
		for (var uri in value) {
			this.addXulLink(xulObj, value[uri], uri);
		}

		return xulObj;
	},

	addXulLink: function(xulObj, attribs, key) {

		var xulChild = document.createElementNS(this.htmlns, "li");

		var label = document.createElement("label");
		label.setAttribute("class", "uri");
		label.setAttribute("value", key);
		xulChild.appendChild(label);
		xulChild.appendChild( this.getXulObject(attribs) );

		xulObj.appendChild(xulChild);
	},

	getXulObject: function(value) {

		if (typeof value != 'object') {
			return null;
		}

		var xulObj = document.createElementNS(this.htmlns, "ul");

		if (Array.isArray(value)) {
			xulObj.setAttribute("class", "array");
			for (var i = 0; i < value.length; i ++) {
				this.addXulChild(xulObj, value[i]);
			}
		} else {
			// object
			xulObj.setAttribute("class", "object");
			for (var prop in value) {
				this.addXulChild(xulObj, value[prop], prop);
			}
		}

		return xulObj;
	},

	addXulChild: function(xulObj, value, key) {

		var xulChild = document.createElementNS(this.htmlns, "li");

		// If the value has a label (object properties will have labels)
		if (key != null) {
			var label = document.createElement("label");
			label.setAttribute("class", "label");
			label.setAttribute("value", key + ":");
			xulChild.appendChild(label);
		}

		if (typeof value == 'object' && value != null) {
			xulChild.appendChild( this.getXulObject(value) );
		} else {
			xulChild.appendChild( this.getXulValue(value) );
		}

		xulObj.appendChild(xulChild);
	},

	getXulValue: function(value) {
		var xulObj = document.createElement("description");
		switch (typeof value) {
			case 'object':
				if (!value) {
					xulObj.setAttribute("value", 'null');
					xulObj.setAttribute("class", "null");
					return xulObj;
				}
				return null;

			case 'string':
				xulObj.appendChild( document.createTextNode(String(value)) );
				xulObj.setAttribute("class", "string");
				return xulObj;

			case 'number':
				xulObj.setAttribute("value", isFinite(value) ? String(value) : 'null');
				if (Math.floor(value) == value) {
					xulObj.setAttribute("class", "int");
				} else {
					xulObj.setAttribute("class", "float");
				}
				return xulObj;

			case 'boolean':
				xulObj.setAttribute("value", String(value));
				xulObj.setAttribute("class", "bool");
				return xulObj;

			case 'null':
				xulObj.setAttribute("value", String(value));
				xulObj.setAttribute("class", "null");
				return xulObj;

			default:
				return null;
		}
	}
};

CopperChrome.renderJSON = function(message) {

	// Print raw JSON in case parsing fails
	CopperChrome.renderText(message);

	// The box for output at the top-level
	document.getElementById('rendered_img').style.display = 'none';
    var view = document.getElementById('rendered_div');
    view.style.display = 'block';

    while (view.hasChildNodes()) {
    	view.removeChild(view.firstChild);
    }
    view.setAttribute("class", "json-content");

    var pl = Copper.bytes2str(message.getPayload()).replace(/'/g, '"');

	try {
		// Parse the JSON
		var parsedObj = JSON.parse(pl);
		// Turn the Javascript object into XUL objects
		if (typeof parsedObj == 'object') {
			view.appendChild( CopperChrome.renderJSONutils.getXulObject(parsedObj) );
			document.getElementById('tabs_payload').selectedIndex = 1;
		} else {
			alert('ERROR: Renderers.renderJSON [Top level element is not a JSON object]');
		}
	} catch (ex) {
		dump('ERROR: Renderers.renderJSON ['+ex+']');
	}

};

CopperChrome.renderJSONutils = {

	htmlns: "http://www.w3.org/1999/xhtml",

	getXulObject: function(value) {
		if (typeof value != 'object') {
			return null;
		}

		var xulObj = document.createElementNS(this.htmlns, "ul");

		if (Array.isArray(value)) {
			xulObj.setAttribute("class", "array");

			if (value.length>0) {
				var label = document.createElement("label");
				label.setAttribute("value", "(length " + value.length + ")");
				label.setAttribute("style", "color: gray;");
				xulObj.appendChild(label);

				for (var i = 0; i < value.length; i ++) {
					this.addXulChild(xulObj, value[i]);
				}
			} else {
				var label = document.createElement("label");
				label.setAttribute("value", "    ");
				xulObj.appendChild(label);
			}

		} else {
			// object
			xulObj.setAttribute("class", "object");
			for (var prop in value) {
				this.addXulChild(xulObj, value[prop], prop);
			}
		}

		return xulObj;
	},

	addXulChild: function(xulObj, value, key) {

		var xulChild = document.createElementNS(this.htmlns, "li");

		// If the value has a label (object properties will have labels)
		if (key != null) {
			var label = document.createElement("label");
			label.setAttribute("class", "label");
			label.setAttribute("value", key + ":");
			xulChild.appendChild(label);
		}

		if (typeof value == 'object' && value != null) {
			xulChild.appendChild( this.getXulObject(value) );
		} else {
			xulChild.appendChild( this.getXulValue(value) );
		}

		xulObj.appendChild(xulChild);
	},

	getXulValue: function(value) {
		var xulObj = document.createElement("description");
		switch (typeof value) {
			case 'object':
				if (!value) {
					xulObj.setAttribute("value", 'null');
					xulObj.setAttribute("class", "null");
					return xulObj;
				}
				return null;

			case 'string':
				xulObj.appendChild( document.createTextNode(String(value)) );
				xulObj.setAttribute("class", "string");
				return xulObj;

			case 'number':
				xulObj.setAttribute("value", isFinite(value) ? String(value) : 'null');
				if (Math.floor(value) == value) {
					xulObj.setAttribute("class", "int");
				} else {
					xulObj.setAttribute("class", "float");
				}
				return xulObj;

			case 'boolean':
				xulObj.setAttribute("value", String(value));
				xulObj.setAttribute("class", "bool");
				return xulObj;

			case 'null':
				xulObj.setAttribute("value", String(value));
				xulObj.setAttribute("class", "null");
				return xulObj;

			default:
				return null;
		}
	}
};

CopperChrome.renderEXI = function(message) {
	CopperChrome.updateLabel('packet_payload', Copper.bytes2data(message.getPayload()), message.getBlockNumber()>0);
	document.getElementById('tabs_payload').selectedIndex = 0;
};
<commit_msg>Added color code rendering.<commit_after>/*******************************************************************************
 * Copyright (c) 2014, Institute for Pervasive Computing, ETH Zurich.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the Institute nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * This file is part of the Copper (Cu) CoAP user-agent.
 ******************************************************************************/
/**
 * \file
 *         Content-type rendering functions
 *
 * \author  Matthias Kovatsch <kovatsch@inf.ethz.ch>\author
 */

// Rendering functions
////////////////////////////////////////////////////////////////////////////////

CopperChrome.renderText = function(message) {
	CopperChrome.updateLabel('packet_payload', Copper.bytes2str(message.getPayload()), false);
	let str = Copper.bytes2str(message.getPayload());
	if (str.match(/^#[0-9a-f]{3,6}$/i) || str.match(/´rgb\(\s*[0-9]+\s*,\s*[0-9]+\s*,\s*[0-9]+\s*\)$/i)) {

		// view corresponding render element
		document.getElementById('rendered_img').style.display = 'none';
		document.getElementById('rendered_div').style.display = 'block';

		document.getElementById('tab_rendered').style.backgroundColor = str.toLowerCase();
		document.getElementById('tabs_payload').selectedIndex = 1;
	} else {
		document.getElementById('tab_rendered').style.backgroundColor = '';
		document.getElementById('tabs_payload').selectedIndex = 0;
	}
};

CopperChrome.renderImage = function(message) {

	if (!message.getBlockMore()) {
		// only render binary when transfer is complete (binary is heavy)
		CopperChrome.renderBinary(message);
	}

	// view corresponding render element
	document.getElementById('rendered_div').style.display = 'none';
	document.getElementById('rendered_img').style.display = 'block';

	// causes flickering, but partially added data does not draw anyway
	document.getElementById('rendered_img').src = 'data:'+Copper.getContentTypeName(message.getContentType())+';base64,'+btoa( Copper.bytes2data(message.getPayload()) );
	document.getElementById('tab_rendered').style.backgroundColor = '';
	document.getElementById('tabs_payload').selectedIndex = 1;
};

CopperChrome.renderBinary = function(message) {

	var pl = message.getPayload();

	// TODO: loop is too heavy for large payloads, alternatives?
	for (var i in pl) {

		CopperChrome.updateLabel('packet_payload', Copper.leadingZero(pl[i].toString(16).toUpperCase()), true);

		if (i % 16 == 15) {
			CopperChrome.updateLabel('packet_payload', ' | ', true);
			for (var j=i-15; j<=i; ++j) {
				if (pl[j] < 32) {
					CopperChrome.updateLabel('packet_payload', '·', true);
				} else {
					CopperChrome.updateLabel('packet_payload', String.fromCharCode(pl[j] & 0xFF), true);
				}
			}
			CopperChrome.updateLabel('packet_payload', '\n', true);
		} else if (i % 2 == 1) {
			CopperChrome.updateLabel('packet_payload', ' ', true);
		}
	}

	// incomplete lines
	if ((parseInt(i)+1) % 16 != 0) {
		// complete line with spaces
		for (var j=0; j<39-((parseInt(i)+1)%16)*2 - ((parseInt(i)+1)%16)/2; ++j) {
			CopperChrome.updateLabel('packet_payload', ' ', true);
		}

		CopperChrome.updateLabel('packet_payload', ' | ', true);
		for (var j=i-(i%16); j<=i; ++j) {
			if (pl[j] < 32) {
				CopperChrome.updateLabel('packet_payload', '·', true);
			} else {
				CopperChrome.updateLabel('packet_payload', String.fromCharCode(pl[j] & 0xFF), true);
			}
		}
	}

	document.getElementById('tabs_payload').selectedIndex = 0;
};

CopperChrome.renderLinkFormat = function(message) {

	// Print raw Link Format in case parsing fails
	CopperChrome.renderText(message);

	// The box for output at the top-level
	document.getElementById('rendered_img').style.display = 'none';
    var view = document.getElementById('rendered_div');
    view.style.display = 'block';

    while (view.hasChildNodes()) {
    	view.removeChild(view.firstChild);
    }
    view.setAttribute("class", "link-content");

	var parsedObj = CopperChrome.parseLinkFormat( Copper.bytes2str(message.getPayload()) );

	view.appendChild( CopperChrome.renderLinkFormatUtils.getXulLinks(parsedObj) );

	document.getElementById('tab_rendered').style.backgroundColor = '';
	document.getElementById('tabs_payload').selectedIndex = 1;
};

CopperChrome.renderLinkFormatUtils = {

	htmlns: "http://www.w3.org/1999/xhtml",

	getXulLinks: function(value) {
		if (typeof value != 'object') {
			return null;
		}

		var xulObj = document.createElementNS(this.htmlns, "ul");
		for (var uri in value) {
			this.addXulLink(xulObj, value[uri], uri);
		}

		return xulObj;
	},

	addXulLink: function(xulObj, attribs, key) {

		var xulChild = document.createElementNS(this.htmlns, "li");

		var label = document.createElement("label");
		label.setAttribute("class", "uri");
		label.setAttribute("value", key);
		xulChild.appendChild(label);
		xulChild.appendChild( this.getXulObject(attribs) );

		xulObj.appendChild(xulChild);
	},

	getXulObject: function(value) {

		if (typeof value != 'object') {
			return null;
		}

		var xulObj = document.createElementNS(this.htmlns, "ul");

		if (Array.isArray(value)) {
			xulObj.setAttribute("class", "array");
			for (var i = 0; i < value.length; i ++) {
				this.addXulChild(xulObj, value[i]);
			}
		} else {
			// object
			xulObj.setAttribute("class", "object");
			for (var prop in value) {
				this.addXulChild(xulObj, value[prop], prop);
			}
		}

		return xulObj;
	},

	addXulChild: function(xulObj, value, key) {

		var xulChild = document.createElementNS(this.htmlns, "li");

		// If the value has a label (object properties will have labels)
		if (key != null) {
			var label = document.createElement("label");
			label.setAttribute("class", "label");
			label.setAttribute("value", key + ":");
			xulChild.appendChild(label);
		}

		if (typeof value == 'object' && value != null) {
			xulChild.appendChild( this.getXulObject(value) );
		} else {
			xulChild.appendChild( this.getXulValue(value) );
		}

		xulObj.appendChild(xulChild);
	},

	getXulValue: function(value) {
		var xulObj = document.createElement("description");
		switch (typeof value) {
			case 'object':
				if (!value) {
					xulObj.setAttribute("value", 'null');
					xulObj.setAttribute("class", "null");
					return xulObj;
				}
				return null;

			case 'string':
				xulObj.appendChild( document.createTextNode(String(value)) );
				xulObj.setAttribute("class", "string");
				return xulObj;

			case 'number':
				xulObj.setAttribute("value", isFinite(value) ? String(value) : 'null');
				if (Math.floor(value) == value) {
					xulObj.setAttribute("class", "int");
				} else {
					xulObj.setAttribute("class", "float");
				}
				return xulObj;

			case 'boolean':
				xulObj.setAttribute("value", String(value));
				xulObj.setAttribute("class", "bool");
				return xulObj;

			case 'null':
				xulObj.setAttribute("value", String(value));
				xulObj.setAttribute("class", "null");
				return xulObj;

			default:
				return null;
		}
	}
};

CopperChrome.renderJSON = function(message) {

	// Print raw JSON in case parsing fails
	CopperChrome.renderText(message);

	// The box for output at the top-level
	document.getElementById('rendered_img').style.display = 'none';
    var view = document.getElementById('rendered_div');
    view.style.display = 'block';

    while (view.hasChildNodes()) {
    	view.removeChild(view.firstChild);
    }
    view.setAttribute("class", "json-content");

    var pl = Copper.bytes2str(message.getPayload()).replace(/'/g, '"');

	try {
		// Parse the JSON
		var parsedObj = JSON.parse(pl);
		// Turn the Javascript object into XUL objects
		if (typeof parsedObj == 'object') {
			view.appendChild( CopperChrome.renderJSONutils.getXulObject(parsedObj) );
			document.getElementById('tab_rendered').style.backgroundColor = '';
			document.getElementById('tabs_payload').selectedIndex = 1;
		} else {
			alert('ERROR: Renderers.renderJSON [Top level element is not a JSON object]');
		}
	} catch (ex) {
		dump('ERROR: Renderers.renderJSON ['+ex+']');
	}

};

CopperChrome.renderJSONutils = {

	htmlns: "http://www.w3.org/1999/xhtml",

	getXulObject: function(value) {
		if (typeof value != 'object') {
			return null;
		}

		var xulObj = document.createElementNS(this.htmlns, "ul");

		if (Array.isArray(value)) {
			xulObj.setAttribute("class", "array");

			if (value.length>0) {
				var label = document.createElement("label");
				label.setAttribute("value", "(length " + value.length + ")");
				label.setAttribute("style", "color: gray;");
				xulObj.appendChild(label);

				for (var i = 0; i < value.length; i ++) {
					this.addXulChild(xulObj, value[i]);
				}
			} else {
				var label = document.createElement("label");
				label.setAttribute("value", "    ");
				xulObj.appendChild(label);
			}

		} else {
			// object
			xulObj.setAttribute("class", "object");
			for (var prop in value) {
				this.addXulChild(xulObj, value[prop], prop);
			}
		}

		return xulObj;
	},

	addXulChild: function(xulObj, value, key) {

		var xulChild = document.createElementNS(this.htmlns, "li");

		// If the value has a label (object properties will have labels)
		if (key != null) {
			var label = document.createElement("label");
			label.setAttribute("class", "label");
			label.setAttribute("value", key + ":");
			xulChild.appendChild(label);
		}

		if (typeof value == 'object' && value != null) {
			xulChild.appendChild( this.getXulObject(value) );
		} else {
			xulChild.appendChild( this.getXulValue(value) );
		}

		xulObj.appendChild(xulChild);
	},

	getXulValue: function(value) {
		var xulObj = document.createElement("description");
		switch (typeof value) {
			case 'object':
				if (!value) {
					xulObj.setAttribute("value", 'null');
					xulObj.setAttribute("class", "null");
					return xulObj;
				}
				return null;

			case 'string':
				xulObj.appendChild( document.createTextNode(String(value)) );
				xulObj.setAttribute("class", "string");
				return xulObj;

			case 'number':
				xulObj.setAttribute("value", isFinite(value) ? String(value) : 'null');
				if (Math.floor(value) == value) {
					xulObj.setAttribute("class", "int");
				} else {
					xulObj.setAttribute("class", "float");
				}
				return xulObj;

			case 'boolean':
				xulObj.setAttribute("value", String(value));
				xulObj.setAttribute("class", "bool");
				return xulObj;

			case 'null':
				xulObj.setAttribute("value", String(value));
				xulObj.setAttribute("class", "null");
				return xulObj;

			default:
				return null;
		}
	}
};

CopperChrome.renderEXI = function(message) {
	CopperChrome.updateLabel('packet_payload', Copper.bytes2data(message.getPayload()), message.getBlockNumber()>0);
	document.getElementById('tabs_payload').selectedIndex = 0;
};
<|endoftext|>


<commit_before>const Core = require('./core');

function getTypeFromId (string) {

    // type = blank node    | _:[..]
    if (string.indexOf('_:') === 0) {
        return 'blank_node'; // 5
    }

    string = string.split('/').slice(3);

    // type = instance      | /[I]/
    if (string.length === 1) {
        return 'instance'; // 0
    }

    if (string[1] === 'listener') {

        // type = listener      | /[I]/on/[L]/
        if (string.length === 3) {
            return 'listener'; // 1
        }

        // type = handler args  | /[I]/on/[L]/[Hp]/args/
        if (string[4] === 'args') {
            return 'handler_args'; // 3
        }

        // type = data handler  | /[I]/on/[L]/[Hp]/data/
        // type = stream handler| /[I]/on/[L]/[Hp]/stream/
        // type = event emit    | /[I]/on/[L]/[Hp]/emit/
        if (string.length === 4) {
            return 'handler'; // 2
        }
    }

    // type = init args     | /[I]/args/
    if (string[1] === 'args') {
        return 'init_args'; // 4
    }
}

module.exports = (loader, subject, predicate, object) => {

    let subject_type = getTypeFromId(subject);
    if (!subject_type) {
        return new Error('Flow.rules: Invalid Subject type. ' + subject);
    }

    switch (predicate) {

// R_M0: P=module + S=instance
// A_M0: Load module and emit module ready on instance
        case 'http://schema.jillix.net/vocab/module':
            if (subject_type !== 'instance') {
                return new Error('Flow.rules: Invalid module subject. ' + subject);
            }

            Core.module(loader, subject, predicate, object);
            return;

// R_I0: P=instance + S=dataHandler|streamHandler|eventEmit
// A_I0: Load instance (with module) emit ready event on sequence
        case 'http://schema.jillix.net/vocab/instance':
            Core.instance(loader, subject, predicate, object);
            return;

// R_L0: P=listener + S=instance
// A_L0: Create sequence add to instance
        case 'http://schema.jillix.net/vocab/listener':
            Core.listener(loader, subject, predicate, object);
            return;

// R_H0: P=handler, S:listener
// A_H0: Add handler as first sequence
// R_H1: P=handler, S:handler
// A_H1: Add handler as next sequence
        case 'http://schema.jillix.net/vocab/dataHandler':
        case 'http://schema.jillix.net/vocab/steramHandler':
        case 'http://schema.jillix.net/vocab/eventEmit':
            //console.log('Handler:', subject, object);
            if (subject_type === 'listener') {
                Core.sequence(loader, subject, predicate, object);
                return;
            }

            if (subject_type === 'handler') {
                Core.handler(loader, subject, predicate, object);
                return;
            }

            return new Error('Flow.rules: Invalid handler subject. ' + subject);

// R_E0: P=emit + S=instance
// A_E0: Emit flow event scope.flow(event);
        case 'http://schema.jillix.net/vocab/eventEmit':
            Core.event(loader, subject, predicate, object);
            return;

// R_F0: P=method + S=dataHandler|streamHandler
// A_F0: Get method reference add it to sequence
        case 'http://schema.jillix.net/vocab/method':
            Core.method(loader, subject, predicate, object);
            return;

// R_A0: P=argument + S=instance
// A_A0: Build first level of arguments object on instance
// R_A1: P=argument + S=handler
// A_A1: Build first level of arguments object on handler
        case 'http://schema.jillix.net/vocab/arguments':
            if (subject_type === 'instance') {
                Core.object(loader, subject, predicate, object);
                return;
            }

            if (subject_type === 'handler') {
                Core.object(loader, subject, predicate, object);
                return;
            }

            return new Error('Flow.rules: Invalid arguments subject. ' + subject);

// R_A2: P=[ANY] S=blank node
// A_A2: Add "object" to "subject", with property "predicate"
// Build one level objects and create deep object on stream end
        default:
            //if (subject)
            Core.object(loader, subject, predicate, object);
            return;
    }
};

<commit_msg>load instance rule<commit_after>const Core = require('./core');

function getTypeFromId (string) {

    // type = blank node    | _:[..]
    if (string.indexOf('_:') === 0) {
        return 'blank_node'; // 5
    }

    string = string.split('/').slice(3);

    // type = instance      | /[I]/
    if (string.length === 1) {
        return 'instance'; // 0
    }

    if (string[1] === 'listener') {

        // type = listener      | /[I]/listener/[L]/
        if (string.length === 3) {
            return 'listener'; // 1
        }

        // type = handler args  | /[I]/on/[L]/[Hp]/args/
        if (string[4] === 'args') {
            return 'handler_args'; // 3
        }

        // type = data handler  | /[I]/on/[L]/[Hp]/data/
        // type = stream handler| /[I]/on/[L]/[Hp]/stream/
        // type = event emit    | /[I]/on/[L]/[Hp]/emit/
        if (string.length === 4) {
            console.log(string.length, string);
            return 'handler'; // 2
        }
    }

    // type = init args     | /[I]/args/
    if (string[1] === 'args') {
        return 'init_args'; // 4
    }
}

module.exports = (loader, subject, predicate, object) => {

    let subject_type = getTypeFromId(subject);
    if (!subject_type) {
        return new Error('Flow.rules: Invalid Subject type. ' + subject);
    }

    switch (predicate) {

// R_M0: P=module + S=instance
// A_M0: Load module and emit module ready on instance
        case 'http://schema.jillix.net/vocab/module':
            if (subject_type !== 'instance') {
                return new Error('Flow.rules: Invalid module subject. ' + subject);
            }

            Core.module(loader, subject, predicate, object);
            return;

// R_I0: P=instance + S=dataHandler|streamHandler|eventEmit
// A_I0: Load instance (with module) emit ready event on sequence
        case 'http://schema.jillix.net/vocab/instance':
            switch (subject_type) {
                case 'handler':
                    Core.instance(loader, subject, predicate, object);
                    return;
                default:
                    return new Error('Flow.rules: Invalid module subject. ' + subject);
            }
            return;

// R_L0: P=listener + S=instance
// A_L0: Create sequence add to instance
        case 'http://schema.jillix.net/vocab/listener':
            Core.listener(loader, subject, predicate, object);
            return;

// R_H0: P=handler, S:listener
// A_H0: Add handler as first sequence
// R_H1: P=handler, S:handler
// A_H1: Add handler as next sequence
        case 'http://schema.jillix.net/vocab/dataHandler':
        case 'http://schema.jillix.net/vocab/streamHandler':
        case 'http://schema.jillix.net/vocab/eventEmit':
            //console.log('Handler:', subject, object);
            if (subject_type === 'listener') {
                Core.sequence(loader, subject, predicate, object);
                return;
            }

            if (subject_type === 'handler') {
                Core.handler(loader, subject, predicate, object);
                return;
            }

            return new Error('Flow.rules: Invalid handler subject. ' + subject);

// R_E0: P=emit + S=instance
// A_E0: Emit flow event scope.flow(event);
        case 'http://schema.jillix.net/vocab/eventEmit':
            Core.event(loader, subject, predicate, object);
            return;

// R_F0: P=method + S=dataHandler|streamHandler
// A_F0: Get method reference add it to sequence
        case 'http://schema.jillix.net/vocab/method':
            Core.method(loader, subject, predicate, object);
            return;

// R_A0: P=argument + S=instance
// A_A0: Build first level of arguments object on instance
// R_A1: P=argument + S=handler
// A_A1: Build first level of arguments object on handler
        case 'http://schema.jillix.net/vocab/arguments':
            if (subject_type === 'instance') {
                Core.object(loader, subject, predicate, object);
                return;
            }

            if (subject_type === 'handler') {
                Core.object(loader, subject, predicate, object);
                return;
            }

            return new Error('Flow.rules: Invalid arguments subject. ' + subject);

// R_A2: P=[ANY] S=blank node
// A_A2: Add "object" to "subject", with property "predicate"
// Build one level objects and create deep object on stream end
        default:
            //if (subject)
            Core.object(loader, subject, predicate, object);
            return;
    }
};
<|endoftext|>


<commit_before>'use strict';

var m = require('mithril');
var parseDomain = require('parse-domain');
var app = 'com.dannyvankooten.browserpass';
var activeTab;
var searching = false;
var logins = null;
var domain, urlDuringSearch;

m.mount(document.getElementById('mount'), { "view": view });

chrome.browserAction.setIcon({ path: 'icon-lock.svg' });
chrome.tabs.onActivated.addListener(init);
chrome.tabs.query({ currentWindow: true, active: true }, function (tabs) {
  init(tabs[0]);
});

function view() {
  var results = '';

  if( searching ) {
    results = m('div.loader');
  } else if( logins !== null ) {
    if( typeof(logins) === "undefined" ) {
      results = m('div.status-text', "Error talking to Browserpass host");
    } else if( logins.length === 0 ) {
      results = m('div.status-text',  m.trust(`No passwords found for <strong>${domain}</strong>.`));
    } else if( logins.length > 0 ) {
        results = logins.map(function(l) {
          var faviconUrl = getFaviconUrl(domain);
          return m('button.login', {
            "onclick": getLoginData.bind(l),
            "style": `background-image: url('${faviconUrl}')`
          },
          l)
        });
    }
  }

  return [
    // search form
    m('div.search', [
      m('form', {
        "onsubmit": submitSearchForm
      }, [
        m('input', {
          "type": "text",
          "name": "s",
          "placeholder": "Search password..",
          "autocomplete": "off",
          "autofocus": "on"
        }),
        m('input', {
          "type": "submit",
          "value": "Search",
          "style": "display: none;"
        })
      ])
    ]),

    // results
    m('div.results', results)
  ];
}

function submitSearchForm(e) {
  e.preventDefault();

  // don't search without input.
  if( ! this.s.value.length ) {
      return;
  }

  searchPassword(this.s.value);
}

function init(tab) {
  // do nothing if called from a non-tab context
  if( ! tab || ! tab.url ) {
    return;
  }

  activeTab = tab;
  var parsedDomain = parseDomain(tab.url, {
    customTlds:/localhost/,
  });

  if( parsedDomain ) {
    var searchDomain = [parsedDomain.domain, parsedDomain.tld]
      .filter(function (x) { return x; })
      .join('.');

    if( searchDomain ) {
      searchPassword(searchDomain);
    }
  }
}

function searchPassword(_domain) {
  searching = true;
  logins = null;
  domain = _domain;
  urlDuringSearch = activeTab.url;
  m.redraw();

  chrome.runtime.sendNativeMessage(app, { "action": "search", "domain": _domain }, function(response) {
    if( chrome.runtime.lastError ) {
      console.log(chrome.runtime.lastError);
    }

    searching = false;
    logins = response;
    m.redraw();
  });
}

function getFaviconUrl(domain){

  // use current favicon when searching for current tab
  if(activeTab && activeTab.favIconUrl && activeTab.favIconUrl.indexOf(domain) > -1) {
    return activeTab.favIconUrl;
  }

  return 'icon-key.png';
}

function getLoginData() {
  searching = true;
  logins = null;
  m.redraw();

  chrome.runtime.sendNativeMessage(app, { "action": "get", "entry": this }, function(response) {
    if( chrome.runtime.lastError) {
      console.log(chrome.runtime.lastError);
    }

    searching = false;
    fillLoginForm(response);
  });
}

// fill login form & submit
function fillLoginForm(login) {
  // do not send login data to page if URL changed during search.
  if( activeTab.url != urlDuringSearch ) {
    return false;
  }

  var code = `
  (function(d) {
    function queryAllVisible(parent, selector) {
      var result = [];
      var elems = parent.querySelectorAll(selector);
      for (var i=0; i < elems.length; i++) {
        // Elem or its parent has a style 'display: none',
        // or it is just too narrow to be a real field (a trap for spammers?).
        if (elems[i].offsetWidth < 50 || elems[i].offsetHeight < 10) { continue; }

        var style = window.getComputedStyle(elems[i]);
        // Elem takes space on the screen, but it or its parent is hidden with a visibility style.
        if (style.visibility == 'hidden') { continue; }

        // This element is visible, will use it.
        result.push(elems[i]);
      }
      return result;
    }

    function queryFirstVisible(parent, selector) {
      var elems = queryAllVisible(parent, selector);
      return (elems.length > 0) ? elems[0] : undefined;
    }

    function form() {
      var passwordField = queryFirstVisible(d, 'input[type=password]');
      return (passwordField && passwordField.form) ? passwordField.form : undefined;
    }

    function field(selector) {
      return queryFirstVisible(form(), selector) || document.createElement('input');
    }

    function update(el, value) {
      if( ! value.length ) {
        return false;
      }

      el.setAttribute('value', value);
      el.value = value;

      var eventNames = [ 'click', 'focus', 'keyup', 'keydown', 'change', 'blur' ];
      eventNames.forEach(function(eventName) {
        el.dispatchEvent(new Event(eventName, {"bubbles":true}));
      });
      return true;
    }

    if (typeof form() === 'undefined') {
      return;
    }

    update(field('input[type=password]'), ${JSON.stringify(login.p)});
    update(field('input[type=email], input[type=text]'), ${JSON.stringify(login.u)});

    var password_inputs = queryAllVisible(document, 'input[type=password]');
    if (password_inputs.length > 1) {
      password_inputs[1].select();
    } else {
      field('[type=submit]').click();
    }
  })(document);
  `;
  chrome.tabs.executeScript({ code: code, allFrames: true });
  window.close();
}
<commit_msg>Check for 2nd password field only in the same form, closes #65, thanks @irgendwie<commit_after>'use strict';

var m = require('mithril');
var parseDomain = require('parse-domain');
var app = 'com.dannyvankooten.browserpass';
var activeTab;
var searching = false;
var logins = null;
var domain, urlDuringSearch;

m.mount(document.getElementById('mount'), { "view": view });

chrome.browserAction.setIcon({ path: 'icon-lock.svg' });
chrome.tabs.onActivated.addListener(init);
chrome.tabs.query({ currentWindow: true, active: true }, function (tabs) {
  init(tabs[0]);
});

function view() {
  var results = '';

  if( searching ) {
    results = m('div.loader');
  } else if( logins !== null ) {
    if( typeof(logins) === "undefined" ) {
      results = m('div.status-text', "Error talking to Browserpass host");
    } else if( logins.length === 0 ) {
      results = m('div.status-text',  m.trust(`No passwords found for <strong>${domain}</strong>.`));
    } else if( logins.length > 0 ) {
        results = logins.map(function(l) {
          var faviconUrl = getFaviconUrl(domain);
          return m('button.login', {
            "onclick": getLoginData.bind(l),
            "style": `background-image: url('${faviconUrl}')`
          },
          l)
        });
    }
  }

  return [
    // search form
    m('div.search', [
      m('form', {
        "onsubmit": submitSearchForm
      }, [
        m('input', {
          "type": "text",
          "name": "s",
          "placeholder": "Search password..",
          "autocomplete": "off",
          "autofocus": "on"
        }),
        m('input', {
          "type": "submit",
          "value": "Search",
          "style": "display: none;"
        })
      ])
    ]),

    // results
    m('div.results', results)
  ];
}

function submitSearchForm(e) {
  e.preventDefault();

  // don't search without input.
  if( ! this.s.value.length ) {
      return;
  }

  searchPassword(this.s.value);
}

function init(tab) {
  // do nothing if called from a non-tab context
  if( ! tab || ! tab.url ) {
    return;
  }

  activeTab = tab;
  var parsedDomain = parseDomain(tab.url, {
    customTlds:/localhost/,
  });

  if( parsedDomain ) {
    var searchDomain = [parsedDomain.domain, parsedDomain.tld]
      .filter(function (x) { return x; })
      .join('.');

    if( searchDomain ) {
      searchPassword(searchDomain);
    }
  }
}

function searchPassword(_domain) {
  searching = true;
  logins = null;
  domain = _domain;
  urlDuringSearch = activeTab.url;
  m.redraw();

  chrome.runtime.sendNativeMessage(app, { "action": "search", "domain": _domain }, function(response) {
    if( chrome.runtime.lastError ) {
      console.log(chrome.runtime.lastError);
    }

    searching = false;
    logins = response;
    m.redraw();
  });
}

function getFaviconUrl(domain){

  // use current favicon when searching for current tab
  if(activeTab && activeTab.favIconUrl && activeTab.favIconUrl.indexOf(domain) > -1) {
    return activeTab.favIconUrl;
  }

  return 'icon-key.png';
}

function getLoginData() {
  searching = true;
  logins = null;
  m.redraw();

  chrome.runtime.sendNativeMessage(app, { "action": "get", "entry": this }, function(response) {
    if( chrome.runtime.lastError) {
      console.log(chrome.runtime.lastError);
    }

    searching = false;
    fillLoginForm(response);
  });
}

// fill login form & submit
function fillLoginForm(login) {
  // do not send login data to page if URL changed during search.
  if( activeTab.url != urlDuringSearch ) {
    return false;
  }

  var code = `
  (function(d) {
    function queryAllVisible(parent, selector) {
      var result = [];
      var elems = parent.querySelectorAll(selector);
      for (var i=0; i < elems.length; i++) {
        // Elem or its parent has a style 'display: none',
        // or it is just too narrow to be a real field (a trap for spammers?).
        if (elems[i].offsetWidth < 50 || elems[i].offsetHeight < 10) { continue; }

        var style = window.getComputedStyle(elems[i]);
        // Elem takes space on the screen, but it or its parent is hidden with a visibility style.
        if (style.visibility == 'hidden') { continue; }

        // This element is visible, will use it.
        result.push(elems[i]);
      }
      return result;
    }

    function queryFirstVisible(parent, selector) {
      var elems = queryAllVisible(parent, selector);
      return (elems.length > 0) ? elems[0] : undefined;
    }

    function form() {
      var passwordField = queryFirstVisible(d, 'input[type=password]');
      return (passwordField && passwordField.form) ? passwordField.form : undefined;
    }

    function field(selector) {
      return queryFirstVisible(form(), selector) || document.createElement('input');
    }

    function update(el, value) {
      if( ! value.length ) {
        return false;
      }

      el.setAttribute('value', value);
      el.value = value;

      var eventNames = [ 'click', 'focus', 'keyup', 'keydown', 'change', 'blur' ];
      eventNames.forEach(function(eventName) {
        el.dispatchEvent(new Event(eventName, {"bubbles":true}));
      });
      return true;
    }

    if (typeof form() === 'undefined') {
      return;
    }

    update(field('input[type=password]'), ${JSON.stringify(login.p)});
    update(field('input[type=email], input[type=text]'), ${JSON.stringify(login.u)});

    var password_inputs = queryAllVisible(form(), 'input[type=password]');
    if (password_inputs.length > 1) {
      password_inputs[1].select();
    } else {
      field('[type=submit]').click();
    }
  })(document);
  `;
  chrome.tabs.executeScript({ code: code, allFrames: true });
  window.close();
}
<|endoftext|>


<commit_before>	//-*depricated in favor of addListeners
	tmlib.prototype.addListener = function(argElement, argEvent, argFunction, argBubble){
		var fncBubble = (argBubble)?argBubble : false;
		if(argElement.attachEvent)
			argElement.attachEvent("on"+argEvent, argFunction);
		else
			argElement.addEventListener(argEvent, argFunction, fncBubble);
	}
	tmlib.prototype.addListeners = function(argElements, argEvent, argFunction, argBubble){
		var fncBubble = (argBubble)?argBubble : false;
		if(!__.lib.isArray(argElements))
			argElements = new Array(argElements);
		for(var i = 0; i < argElements.length; ++i){
			var forElement = argElements[i];
			if(forElement.attachEvent)
				forElement.attachEvent("on"+argEvent, argFunction);
			else
				forElement.addEventListener(argEvent, argFunction, fncBubble);
		}
	}
	//-@based from http://andrewpeace.com/javascript-is-array.html
	__.lib.isArray = function(argObject){
		if(
			(typeof argObject == 'object' && argObject instanceof Array) //-normal array
			|| ((typeof argObject == "function" || typeof argObject == "object") && typeof argObject.length == 'number' && typeof argObject.item == "function") //-nodelist
		){
			return true;
		}else{
			return false;
		}
	}
	__.lib.isNumeric = function(argValue){
		return !isNaN(argValue - 0);
	}
	//-@based from http://phpjs.org/functions/array_search:335
	__.lib.arraySearch = function(argNeedle, argHaystack, argStrict){
		for(var key in argHaystack){
			if((!argStrict && argHaystack[key] == argNeedle) || (argStrict && argHastack[key] === argNeedle)){
				return key;
			}
		}
		return false;
	}

	tmlib.prototype.getElementsByClassName = function(args){
		var fncClassName = (args.className)?args.className:null; if(!fncClassName) return;
		var fncElement = (args.element)?args.element:document;
		var fncTagName = (args.tagName)?args.tagName:null;

		var fncReturn = [], fncElementsToSearch = [];
		var fncRegex = new RegExp('\\b'+fncClassName+'\\b');

		if(fncTagName){
			fncElementsToSearch = fncElement.getElementsByTagName(fncTagName);
		}
		else if(fncElement.all)
			fncElementsToSearch = fncElement.all;
		else
			fncElementsToSearch = fncElement.getElementsByTagName('*');

		for(var i=0; i < fncElementsToSearch.length; ++i){
			if(fncRegex.test(fncElementsToSearch[i].className))
				fncReturn.push(fncElementsToSearch[i]);
		}

		return fncReturn;
	}
	tmlib.prototype.addClass = function(argElement, argClass){
		if(new RegExp('\\b'+argClass+'\\b').test(argElement.className))
			return 0;
		else{
			argElement.className+=argElement.className?' '+argClass:argClass;
			return 1;
		}
	}
	tmlib.prototype.removeClass = function(argElement, argClass){
		  var fncReplace = argElement.className.match(' '+argClass)?' '+argClass:argClass;
		  argElement.className=argElement.className.replace(fncReplace,'');
	}
	tmlib.prototype.hasClass = function(argElement, argClass){
		if(new RegExp('\\b'+argClass+'\\b').test(argElement.className))
			return 1;
		else
			return 0;
	}
	tmlib.prototype.getClasses = function(argElement){
		return argElement.className.split(/\s+/);
	}
	//-@ http://javascript.about.com/library/bldom12.htm
	__.lib.insertBefore = function(argElmInsert, argElmBefore){
		return argElmBefore.parentNode.insertBefore(argElmInsert, argElmBefore);
	}

	//-@ http://stackoverflow.com/questions/868407/hide-an-elements-next-sibling-with-javascript
	__.lib.getNextSibling = function(argElement){
		var elmReturn = argElement;
		do{
			elmReturn = elmReturn.nextSibling;
		}while(elmReturn && elmReturn.noteType != 1);

		if(elmReturn == argElement)
				elmReturn = false;
		return elmReturn;
	}

	tmlib.prototype.isIE = function(){
		if(this.isievar)
			return this.isie;
		else{
			this.initUA();
			if(this.browser.indexOf("Internet Explorer", 0) == -1) return 0;
			else return 1;
		}
	}
	tmlib.prototype.isIE6 = function(){
		if(this.isIE){
			if(!this.ieversion) // http://www.javascriptkit.com/javatutors/navigator.shtml
				if(/MSIE (\d+\.\d+);/.test(navigator.userAgent))
					this.ieversion = new Number(RegExp.$1) // capture x.x portion and store as a number
			if(this.ieversion == 6)
				return 1;
			else return 0;
		}
		else
			return 0;
	}
	tmlib.prototype.initUA = function(){
		if(!this.browser) this.browser = navigator.appName;
		if(!this.verion) this.version = parseFloat(navigator.appVersion);
	}
	tmlib.prototype.isIphone = function(){
		var isIphone = (navigator.userAgent.toLowerCase().indexOf('iphone')!=-1);
		if (isIphone)
			return true;
		else
			return false;
	}
	__.lib.vardump = function(variable, maxDeep){
		//<-http://my.opera.com/SpShut/blog/2009/12/18/best-javascript-var-dump
		var deep = 0;
		var maxDeep = maxDeep || 0;

		function fetch(object, parent){
			var buffer = '';
			deep++;

			for (var i in object) {
			if (parent) {
				objectPath = parent + '.' + i;
			} else {
				objectPath = i;
			}

			buffer += objectPath + ' (' + typeof object[i] + ')';

			if (typeof object[i] == 'object') {
				buffer += "\n";
				if (deep < maxDeep) {
					buffer += fetch(object[i], objectPath);
				}
				} else if (typeof object[i] == 'function') {
					buffer += "\n";
				} else if (typeof object[i] == 'string') {
					buffer += ': "' + object[i] + "\"\n";
				} else {
					buffer += ': ' + object[i] + "\n";
				}
			}

			deep--;
			return buffer;
		}

		if (typeof variable == 'object') {
			return fetch(variable);
		}

		return '(' + typeof variable + '): ' + variable + "\n";
	}
	tmlib.prototype.isInteger = function(argument){
		return argument.toString().match(/^-?[0-9]+$/);
	}

/*
return instance name of object from within instance
-* only use for testing purposes
*/
	__.lib.getInstanceName = function(argObject){
/*
		this.checkMembers = function(argContainer, argObject){
			var fncReturn = "";
			if(typeof argObject != undefined){
				for(var key in argContainer){
					if(argContainer[key] === argObject)
						fncReturn = key;
					if(fncReturn == ""){
						fncReturn = this.checkMembers.call(this, argContainer[key], argObject);
						if(fncReturn != "")
							fncReturn = key+"."+fncReturn;
					}
					if(fncReturn != "")
						break;
				}
			}
			return fncReturn;
		}
		var fncReturn = "[not found]";
		if(__ === argObject)
			fncReturn = "window";
		else{
			fncReturn = this.checkMembers.call(this, __, argObject);
			if(fncReturn != "")
				fncReturn = "__."+fncReturn;
		}

		return fncReturn;
*/

		for(var key in window){
			if(window[key] === argObject)
				return key;
		}
		for(var key in __){
			if(__[key] === argObject)
				return "__."+key;
			for(var subkey in __[key]){
				if(__[key][subkey] === argObject)
					return "__."+key+"."+subkey;
				for(var subsubkey in __[key][subkey]){
					if(__[key][subkey][subsubkey] === argObject)
						return "__."+key+"."+subkey+"."+subsubkey;
				}
			}
		}
	}

/*--dispatchEvent
fire an event on an element
--*/
	tmlib.prototype.dispatchEvent = function(argElement, argEvent){
		if(document.createEvent){
			var event = document.createEvent("MouseEvents");
			event.initEvent(argEvent, true, true);
			argElement.dispatchEvent(event);
		}else if(document.createEventObject){
			argElement.fireEvent("on"+argEvent);
		}

	}

/*--clearForm
supports the add placeholder support function
--*/
	tmlib.prototype.clearForm = function(argElmForm){
		if(!argElmForm) return false;
		argElmForm.reset();
		if(!__.supportsInputPlaceholder()){
//		else{
			// inputs
			var elmsInputs = argElmForm.getElementsByTagName("input");
			var elmsInputsLength = elmsInputs.length;
			for(var i = 0; i < elmsInputsLength; ++i){
				var fncThis = elmsInputs[i];
/*
				var fncThisType = fncThis.getAttribute("type");
				if(fncThis.value != "" && fncThisType != "submit" && fncThisType != "button"){
					fncThis.value = "";
*/
					__.dispatchEvent(fncThis, "blur");
//				}
			}
			// textareas
			var elmsTextareas = argElmForm.getElementsByTagName("textarea");
			var elmsTextareasLength = elmsTextareas.length;
			for(var i = 0; i < elmsTextareasLength; ++i){
				var fncThis = elmsTextareas[i];
/*
				if(fncThis.value != ""){
					fncThis.value = "";
*/
					__.dispatchEvent(fncThis, "blur");
//				}
			}
		}
	}

/*--string functions
--*/
	tmlib.prototype.nl2br = function(argString, argIsXML){
		var fncIsXML = (typeof argIsXML !== undefined)?argIsXML:false;
		var regex = /(\r\n|[\r\n])/g;
		if(fncIsXML)
			return argString.replace(regex, "
")
		else
			return argString.replace(regex, "
")
	}
	tmlib.prototype.br2nl = function(argString){
		var regex = /(
|
)/g;
		return argString.replace(regex, "\n");
	}
	tmlib.prototype.brRemove = function(argString){
		var regex = /(
|
)/g;
		return argString.replace(regex, "");
	}
	//-@based from http://beardscratchers.com/journal/using-javascript-to-get-the-hostname-of-a-url
	__.lib.urlParse = function(argURL){
		var regexExternal = /^(.*):\/\/([^\/]+)(.*)/i;
		var regexEmail = /^mailto:(.*)@(.*)/i;
		var regexTel = /^(tel|fax):(.*)/i;

		var resultExternal = argURL.match(regexExternal);
		if(resultExternal != null)
			return {type: "external", protocol: resultExternal[1], host: resultExternal[2], file: resultExternal[3]};
		var resultEmail = argURL.match(regexEmail);
		if(resultEmail != null)
			return {type: "mailto", username: resultEmail[1], host: resultEmail[2]};
		var resultTel = argURL.match(regexTel);
		if(resultTel != null)
			return {type: resultTel[1], n: resultTel[2]};

		return {type: "internal", href: argURL};
	}
	//-@ based from http://snippets.dzone.com/posts/show/5629
	__.lib.urlFriendlify = function(argString, argType){
		//var regexURLCharactersValidAll = /[^a-z0-9\-\._~:\/\?#\[\]@!\$&'\(\)\*\+,;=]+/g;
		return argString.replace(/^\s+|\s+$/g, "") //--trim spaces
			.replace(/[\s]+/g, "-") //--replace spaces with -
			.replace(/[-]+/g, "-") //--combine consecutive hyphens
			.toLowerCase() //--lowercase
			.replace(/[^a-z0-9\-\._~:\[\]@!\$'\(\)\_\*]+/g, "") //--remove all but these characters

		;
	}
	__.lib.escapeHash = function(hash){
		return hash.replace(/\//g, "\\/");
	}
	__.lib.unescapeHash = function(hash){
		return hash.replace(/\\\//g, "\/");
	}

/*--timezone functions
--*/
	tmlib.prototype.setTimezoneLocalCookie = function(){
		if(!this.lib.cookies.get("timezone"))
			this.lib.cookies.set({name:"timezone", value:this.dateGetLocalOffset()});
	}
	tmlib.prototype.dateGetLocalOffset = function() {
		var fncOffset = -1 * this.dateSetStdTimezoneOffset() / 60;
		if(this.dateIsDST()) fncOffset += 1;
		return fncOffset;
	}

	tmlib.prototype.dateSetStdTimezoneOffset = function() {
		var jan = new Date((new Date).getFullYear(), 0, 1);
		var jul = new Date((new Date).getFullYear(), 6, 1);
		return Math.max(jan.getTimezoneOffset(), jul.getTimezoneOffset());
	}

	tmlib.prototype.dateIsDST = function() {
		return (new Date).getTimezoneOffset() < this.dateSetStdTimezoneOffset();
	}

<commit_msg>cb/lib: 'd' in varDump capitalized<commit_after>	//-*depricated in favor of addListeners
	tmlib.prototype.addListener = function(argElement, argEvent, argFunction, argBubble){
		var fncBubble = (argBubble)?argBubble : false;
		if(argElement.attachEvent)
			argElement.attachEvent("on"+argEvent, argFunction);
		else
			argElement.addEventListener(argEvent, argFunction, fncBubble);
	}
	tmlib.prototype.addListeners = function(argElements, argEvent, argFunction, argBubble){
		var fncBubble = (argBubble)?argBubble : false;
		if(!__.lib.isArray(argElements))
			argElements = new Array(argElements);
		for(var i = 0; i < argElements.length; ++i){
			var forElement = argElements[i];
			if(forElement.attachEvent)
				forElement.attachEvent("on"+argEvent, argFunction);
			else
				forElement.addEventListener(argEvent, argFunction, fncBubble);
		}
	}
	//-@based from http://andrewpeace.com/javascript-is-array.html
	__.lib.isArray = function(argObject){
		if(
			(typeof argObject == 'object' && argObject instanceof Array) //-normal array
			|| ((typeof argObject == "function" || typeof argObject == "object") && typeof argObject.length == 'number' && typeof argObject.item == "function") //-nodelist
		){
			return true;
		}else{
			return false;
		}
	}
	__.lib.isNumeric = function(argValue){
		return !isNaN(argValue - 0);
	}
	//-@based from http://phpjs.org/functions/array_search:335
	__.lib.arraySearch = function(argNeedle, argHaystack, argStrict){
		for(var key in argHaystack){
			if((!argStrict && argHaystack[key] == argNeedle) || (argStrict && argHastack[key] === argNeedle)){
				return key;
			}
		}
		return false;
	}

	tmlib.prototype.getElementsByClassName = function(args){
		var fncClassName = (args.className)?args.className:null; if(!fncClassName) return;
		var fncElement = (args.element)?args.element:document;
		var fncTagName = (args.tagName)?args.tagName:null;

		var fncReturn = [], fncElementsToSearch = [];
		var fncRegex = new RegExp('\\b'+fncClassName+'\\b');

		if(fncTagName){
			fncElementsToSearch = fncElement.getElementsByTagName(fncTagName);
		}
		else if(fncElement.all)
			fncElementsToSearch = fncElement.all;
		else
			fncElementsToSearch = fncElement.getElementsByTagName('*');

		for(var i=0; i < fncElementsToSearch.length; ++i){
			if(fncRegex.test(fncElementsToSearch[i].className))
				fncReturn.push(fncElementsToSearch[i]);
		}

		return fncReturn;
	}
	tmlib.prototype.addClass = function(argElement, argClass){
		if(new RegExp('\\b'+argClass+'\\b').test(argElement.className))
			return 0;
		else{
			argElement.className+=argElement.className?' '+argClass:argClass;
			return 1;
		}
	}
	tmlib.prototype.removeClass = function(argElement, argClass){
		  var fncReplace = argElement.className.match(' '+argClass)?' '+argClass:argClass;
		  argElement.className=argElement.className.replace(fncReplace,'');
	}
	tmlib.prototype.hasClass = function(argElement, argClass){
		if(new RegExp('\\b'+argClass+'\\b').test(argElement.className))
			return 1;
		else
			return 0;
	}
	tmlib.prototype.getClasses = function(argElement){
		return argElement.className.split(/\s+/);
	}
	//-@ http://javascript.about.com/library/bldom12.htm
	__.lib.insertBefore = function(argElmInsert, argElmBefore){
		return argElmBefore.parentNode.insertBefore(argElmInsert, argElmBefore);
	}

	//-@ http://stackoverflow.com/questions/868407/hide-an-elements-next-sibling-with-javascript
	__.lib.getNextSibling = function(argElement){
		var elmReturn = argElement;
		do{
			elmReturn = elmReturn.nextSibling;
		}while(elmReturn && elmReturn.noteType != 1);

		if(elmReturn == argElement)
				elmReturn = false;
		return elmReturn;
	}

	tmlib.prototype.isIE = function(){
		if(this.isievar)
			return this.isie;
		else{
			this.initUA();
			if(this.browser.indexOf("Internet Explorer", 0) == -1) return 0;
			else return 1;
		}
	}
	tmlib.prototype.isIE6 = function(){
		if(this.isIE){
			if(!this.ieversion) // http://www.javascriptkit.com/javatutors/navigator.shtml
				if(/MSIE (\d+\.\d+);/.test(navigator.userAgent))
					this.ieversion = new Number(RegExp.$1) // capture x.x portion and store as a number
			if(this.ieversion == 6)
				return 1;
			else return 0;
		}
		else
			return 0;
	}
	tmlib.prototype.initUA = function(){
		if(!this.browser) this.browser = navigator.appName;
		if(!this.verion) this.version = parseFloat(navigator.appVersion);
	}
	tmlib.prototype.isIphone = function(){
		var isIphone = (navigator.userAgent.toLowerCase().indexOf('iphone')!=-1);
		if (isIphone)
			return true;
		else
			return false;
	}
	__.lib.varDump = function(variable, maxDeep){
		//<-http://my.opera.com/SpShut/blog/2009/12/18/best-javascript-var-dump
		var deep = 0;
		var maxDeep = maxDeep || 0;

		function fetch(object, parent){
			var buffer = '';
			deep++;

			for (var i in object) {
			if (parent) {
				objectPath = parent + '.' + i;
			} else {
				objectPath = i;
			}

			buffer += objectPath + ' (' + typeof object[i] + ')';

			if (typeof object[i] == 'object') {
				buffer += "\n";
				if (deep < maxDeep) {
					buffer += fetch(object[i], objectPath);
				}
				} else if (typeof object[i] == 'function') {
					buffer += "\n";
				} else if (typeof object[i] == 'string') {
					buffer += ': "' + object[i] + "\"\n";
				} else {
					buffer += ': ' + object[i] + "\n";
				}
			}

			deep--;
			return buffer;
		}

		if (typeof variable == 'object') {
			return fetch(variable);
		}

		return '(' + typeof variable + '): ' + variable + "\n";
	}
	tmlib.prototype.isInteger = function(argument){
		return argument.toString().match(/^-?[0-9]+$/);
	}

/*
return instance name of object from within instance
-* only use for testing purposes
*/
	__.lib.getInstanceName = function(argObject){
/*
		this.checkMembers = function(argContainer, argObject){
			var fncReturn = "";
			if(typeof argObject != undefined){
				for(var key in argContainer){
					if(argContainer[key] === argObject)
						fncReturn = key;
					if(fncReturn == ""){
						fncReturn = this.checkMembers.call(this, argContainer[key], argObject);
						if(fncReturn != "")
							fncReturn = key+"."+fncReturn;
					}
					if(fncReturn != "")
						break;
				}
			}
			return fncReturn;
		}
		var fncReturn = "[not found]";
		if(__ === argObject)
			fncReturn = "window";
		else{
			fncReturn = this.checkMembers.call(this, __, argObject);
			if(fncReturn != "")
				fncReturn = "__."+fncReturn;
		}

		return fncReturn;
*/

		for(var key in window){
			if(window[key] === argObject)
				return key;
		}
		for(var key in __){
			if(__[key] === argObject)
				return "__."+key;
			for(var subkey in __[key]){
				if(__[key][subkey] === argObject)
					return "__."+key+"."+subkey;
				for(var subsubkey in __[key][subkey]){
					if(__[key][subkey][subsubkey] === argObject)
						return "__."+key+"."+subkey+"."+subsubkey;
				}
			}
		}
	}

/*--dispatchEvent
fire an event on an element
--*/
	tmlib.prototype.dispatchEvent = function(argElement, argEvent){
		if(document.createEvent){
			var event = document.createEvent("MouseEvents");
			event.initEvent(argEvent, true, true);
			argElement.dispatchEvent(event);
		}else if(document.createEventObject){
			argElement.fireEvent("on"+argEvent);
		}

	}

/*--clearForm
supports the add placeholder support function
--*/
	tmlib.prototype.clearForm = function(argElmForm){
		if(!argElmForm) return false;
		argElmForm.reset();
		if(!__.supportsInputPlaceholder()){
//		else{
			// inputs
			var elmsInputs = argElmForm.getElementsByTagName("input");
			var elmsInputsLength = elmsInputs.length;
			for(var i = 0; i < elmsInputsLength; ++i){
				var fncThis = elmsInputs[i];
/*
				var fncThisType = fncThis.getAttribute("type");
				if(fncThis.value != "" && fncThisType != "submit" && fncThisType != "button"){
					fncThis.value = "";
*/
					__.dispatchEvent(fncThis, "blur");
//				}
			}
			// textareas
			var elmsTextareas = argElmForm.getElementsByTagName("textarea");
			var elmsTextareasLength = elmsTextareas.length;
			for(var i = 0; i < elmsTextareasLength; ++i){
				var fncThis = elmsTextareas[i];
/*
				if(fncThis.value != ""){
					fncThis.value = "";
*/
					__.dispatchEvent(fncThis, "blur");
//				}
			}
		}
	}

/*--string functions
--*/
	tmlib.prototype.nl2br = function(argString, argIsXML){
		var fncIsXML = (typeof argIsXML !== undefined)?argIsXML:false;
		var regex = /(\r\n|[\r\n])/g;
		if(fncIsXML)
			return argString.replace(regex, "
")
		else
			return argString.replace(regex, "
")
	}
	tmlib.prototype.br2nl = function(argString){
		var regex = /(
|
)/g;
		return argString.replace(regex, "\n");
	}
	tmlib.prototype.brRemove = function(argString){
		var regex = /(
|
)/g;
		return argString.replace(regex, "");
	}
	//-@based from http://beardscratchers.com/journal/using-javascript-to-get-the-hostname-of-a-url
	__.lib.urlParse = function(argURL){
		var regexExternal = /^(.*):\/\/([^\/]+)(.*)/i;
		var regexEmail = /^mailto:(.*)@(.*)/i;
		var regexTel = /^(tel|fax):(.*)/i;

		var resultExternal = argURL.match(regexExternal);
		if(resultExternal != null)
			return {type: "external", protocol: resultExternal[1], host: resultExternal[2], file: resultExternal[3]};
		var resultEmail = argURL.match(regexEmail);
		if(resultEmail != null)
			return {type: "mailto", username: resultEmail[1], host: resultEmail[2]};
		var resultTel = argURL.match(regexTel);
		if(resultTel != null)
			return {type: resultTel[1], n: resultTel[2]};

		return {type: "internal", href: argURL};
	}
	//-@ based from http://snippets.dzone.com/posts/show/5629
	__.lib.urlFriendlify = function(argString, argType){
		//var regexURLCharactersValidAll = /[^a-z0-9\-\._~:\/\?#\[\]@!\$&'\(\)\*\+,;=]+/g;
		return argString.replace(/^\s+|\s+$/g, "") //--trim spaces
			.replace(/[\s]+/g, "-") //--replace spaces with -
			.replace(/[-]+/g, "-") //--combine consecutive hyphens
			.toLowerCase() //--lowercase
			.replace(/[^a-z0-9\-\._~:\[\]@!\$'\(\)\_\*]+/g, "") //--remove all but these characters

		;
	}
	__.lib.escapeHash = function(hash){
		return hash.replace(/\//g, "\\/");
	}
	__.lib.unescapeHash = function(hash){
		return hash.replace(/\\\//g, "\/");
	}

/*--timezone functions
--*/
	tmlib.prototype.setTimezoneLocalCookie = function(){
		if(!this.lib.cookies.get("timezone"))
			this.lib.cookies.set({name:"timezone", value:this.dateGetLocalOffset()});
	}
	tmlib.prototype.dateGetLocalOffset = function() {
		var fncOffset = -1 * this.dateSetStdTimezoneOffset() / 60;
		if(this.dateIsDST()) fncOffset += 1;
		return fncOffset;
	}

	tmlib.prototype.dateSetStdTimezoneOffset = function() {
		var jan = new Date((new Date).getFullYear(), 0, 1);
		var jul = new Date((new Date).getFullYear(), 6, 1);
		return Math.max(jan.getTimezoneOffset(), jul.getTimezoneOffset());
	}

	tmlib.prototype.dateIsDST = function() {
		return (new Date).getTimezoneOffset() < this.dateSetStdTimezoneOffset();
	}

<|endoftext|>


<commit_before>// Token class

'use strict';

/**
 * class Token
 **/

/**
 * new Token(type, tag, nesting)
 *
 * Create new token and fill passed properties.
 **/
function Token(type, tag, nesting) {
  /**
   * Token#type -> String
   *
   * Type of the token (string, e.g. "paragraph_open")
   **/
  this.type     = type;

  /**
   * Token#tag -> String
   *
   * html tag name, e.g. "p"
   **/
  this.tag      = tag;

  /**
   * Token#attrs -> Array
   *
   * Html attributes. Format: `[ [ name1, value1 ], [ name2, value2 ] ]`
   **/
  this.attrs    = null;

  /**
   * Token#map -> Array
   *
   * Source map info. Format: `[ line_begin, line_end ]`
   **/
  this.map      = null;

  /**
   * Token#nesting -> Number
   *
   * Level change (number in {-1, 0, 1} set), where:
   *
   * -  `1` means the tag is opening
   * -  `0` means the tag is self-closing
   * - `-1` means the tag is closing
   **/
  this.nesting  = nesting;

  /**
   * Token#level -> Number
   *
   * nesting level, the same as `state.level`
   **/
  this.level    = 0;

  /**
   * Token#children -> Array
   *
   * An array of child nodes (inline and img tokens)
   **/
  this.children = null;

  /**
   * Token#content -> String
   *
   * In a case of self-closing tag (code, html, fence, etc.),
   * it has contents of this tag.
   **/
  this.content  = '';

  /**
   * Token#markup -> String
   *
   * '*' or '_' for emphasis, fence string for fence, etc.
   **/
  this.markup   = '';

  /**
   * Token#info -> String
   *
   * fence infostring
   **/
  this.info     = '';

  /**
   * Token#block -> Boolean
   *
   * True for block-level tokens, false for inline tokens.
   * Used in renderer to calculate line breaks
   **/
  this.block    = false;

  /**
   * Token#hidden -> Boolean
   *
   * If it's true, ignore this element when rendering. Used for tight lists
   * to hide paragraphs.
   **/
  this.hidden   = false;
}

/**
 * Token.attrIndex(name) -> Number
 *
 * Search attribute index by name.
 **/
Token.prototype.attrIndex = function attrIndex(name) {
  var attrs, i, len;

  if (!this.attrs) { return -1; }

  attrs = this.attrs;

  for (i = 0, len = attrs.length; i < len; i++) {
    if (attrs[i][0] === name) { return i; }
  }
  return -1;
};

/**
 * Token.attrPush(attrData)
 *
 * Add `[ name, value ]` attribute to list. Init attrs if necessary
 **/
Token.prototype.attrPush = function attrPush(attrData) {
  if (this.attrs) {
    this.attrs.push(attrData);
  } else {
    this.attrs = [ attrData ];
  }
};

module.exports = Token;
<commit_msg>Add token.meta for use in plugins<commit_after>// Token class

'use strict';

/**
 * class Token
 **/

/**
 * new Token(type, tag, nesting)
 *
 * Create new token and fill passed properties.
 **/
function Token(type, tag, nesting) {
  /**
   * Token#type -> String
   *
   * Type of the token (string, e.g. "paragraph_open")
   **/
  this.type     = type;

  /**
   * Token#tag -> String
   *
   * html tag name, e.g. "p"
   **/
  this.tag      = tag;

  /**
   * Token#attrs -> Array
   *
   * Html attributes. Format: `[ [ name1, value1 ], [ name2, value2 ] ]`
   **/
  this.attrs    = null;

  /**
   * Token#map -> Array
   *
   * Source map info. Format: `[ line_begin, line_end ]`
   **/
  this.map      = null;

  /**
   * Token#nesting -> Number
   *
   * Level change (number in {-1, 0, 1} set), where:
   *
   * -  `1` means the tag is opening
   * -  `0` means the tag is self-closing
   * - `-1` means the tag is closing
   **/
  this.nesting  = nesting;

  /**
   * Token#level -> Number
   *
   * nesting level, the same as `state.level`
   **/
  this.level    = 0;

  /**
   * Token#children -> Array
   *
   * An array of child nodes (inline and img tokens)
   **/
  this.children = null;

  /**
   * Token#content -> String
   *
   * In a case of self-closing tag (code, html, fence, etc.),
   * it has contents of this tag.
   **/
  this.content  = '';

  /**
   * Token#markup -> String
   *
   * '*' or '_' for emphasis, fence string for fence, etc.
   **/
  this.markup   = '';

  /**
   * Token#info -> String
   *
   * fence infostring
   **/
  this.info     = '';

  /**
   * Token#meta -> Object
   *
   * A place for plugins to store an arbitrary data
   */
  this.meta     = null;

  /**
   * Token#block -> Boolean
   *
   * True for block-level tokens, false for inline tokens.
   * Used in renderer to calculate line breaks
   **/
  this.block    = false;

  /**
   * Token#hidden -> Boolean
   *
   * If it's true, ignore this element when rendering. Used for tight lists
   * to hide paragraphs.
   **/
  this.hidden   = false;
}

/**
 * Token.attrIndex(name) -> Number
 *
 * Search attribute index by name.
 **/
Token.prototype.attrIndex = function attrIndex(name) {
  var attrs, i, len;

  if (!this.attrs) { return -1; }

  attrs = this.attrs;

  for (i = 0, len = attrs.length; i < len; i++) {
    if (attrs[i][0] === name) { return i; }
  }
  return -1;
};

/**
 * Token.attrPush(attrData)
 *
 * Add `[ name, value ]` attribute to list. Init attrs if necessary
 **/
Token.prototype.attrPush = function attrPush(attrData) {
  if (this.attrs) {
    this.attrs.push(attrData);
  } else {
    this.attrs = [ attrData ];
  }
};

module.exports = Token;
<|endoftext|>