<commit_before>//usage:
//tab_metro.setUp(bpm , the element you want to attach metronome);<=must do this
//tab_metor.play();
//you can use setBpm to change bpm, and attachTo() to attach metronome on more element
let tab_metro={
	bpm:120,
	playing:false,
	setUp:function(b=120,e=null){
		this.bpm=b;
		this.content=document.createElement('div');
		this.content.setAttribute('style',`
			width:420px;height:250px;
			background:URL('./img/tick_bg.png') #565656;
			text-align:center;
			position:relative;
			border-radius:8px`);
		this.content.innerHTML=`
${this.bpm}

bpm

			`;
		this.shouldStop = true;
		this.pos = 0;
		this.f = function() {
			if (!this.start) {
				this.start = new Date().getTime();
				this.nextAt = this.start;
			}
			this.nextAt += (60/this.bpm) * 1000;
			this.audio.currentTime = 0;
			this.audio.play();
			if(this.pos == 0)
				this.pos = 390;
			else
				this.pos = 0;
			this.content.children[3].style.transform=`translateX(${this.pos}px)`;
/*
			var drift = (new Date().getTime() - start) % 1000;
			$('
').text(drift + "ms").appendTo('#results');
*/
			if(!this.shouldStop)
			setTimeout(this.f.bind(this), this.nextAt - new Date().getTime());
		};
		//this.tick=(function(){this.content.children[3].style.transform="translateX(0px)";}).bind(this);
		//this.tock=(function(){this.content.children[3].style.transform="translateX(390px)";}).bind(this);
		this.attachTo(e);
 		this.audio = new Audio("data:audio/wav;base64,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qJrx4KOQjahZxWbcZgztj2c49nKmkId44S71j0c8eV9yDK6uPRzx5X18eDvjvQ6yKo9ZSS6l//8elePK/Lf//IInrOF/FvDoADYAGBMGb7FtErm5MXMlmPAJQVgWta7Zx2go+8xJ0UiCb8LHHdftWyLJE0QIAIsI+UbXu67dZMjmgDGCGl1H+vpF4NSDckSIkk7Vd+sxEhBQMRU8j/12UIRhzSaUdQ+rQU5kGeFxm+hb1oh6pWWmv3uvmReDl0UnvtapVaIzo1jZbf/pD6ElLqSX+rUmOQNpJFa/r+sa4e/pBlAABoAAAAA3CUgShLdGIxsY7AUABPRrgCABdDuQ5GC7DqPQCgbbJUAoRSUj+NIEig0YfyWUho1VBBBA//uQZB4ABZx5zfMakeAAAAmwAAAAF5F3P0w9GtAAACfAAAAAwLhMDmAYWMgVEG1U0FIGCBgXBXAtfMH10000EEEEEECUBYln03TTTdNBDZopopYvrTTdNa325mImNg3TTPV9q3pmY0xoO6bv3r00y+IDGid/9aaaZTGMuj9mpu9Mpio1dXrr5HERTZSmqU36A3CumzN/9Robv/Xx4v9ijkSRSNLQhAWumap82WRSBUqXStV/YcS+XVLnSS+WLDroqArFkMEsAS+eWmrUzrO0oEmE40RlMZ5+ODIkAyKAGUwZ3mVKmcamcJnMW26MRPgUw6j+LkhyHGVGYjSUUKNpuJUQoOIAyDvEyG8S5yfK6dhZc0Tx1KI/gviKL6qvvFs1+bWtaz58uUNnryq6kt5RzOCkPWlVqVX2a/EEBUdU1KrXLf40GoiiFXK///qpoiDXrOgqDR38JB0bw7SoL+ZB9o1RCkQjQ2CBYZKd/+VJxZRRZlqSkKiws0WFxUyCwsKiMy7hUVFhIaCrNQsKkTIsLivwKKigsj8XYlwt/WKi2N4d//uQRCSAAjURNIHpMZBGYiaQPSYyAAABLAAAAAAAACWAAAAApUF/Mg+0aohSIRobBAsMlO//Kk4soosy1JSFRYWaLC4qZBYWFRGZdwqKiwkNBVmoWFSJkWFxX4FFRQWR+LsS4W/rFRb/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////VEFHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU291bmRib3kuZGUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMjAwNGh0dHA6Ly93d3cuc291bmRib3kuZGUAAAAAAAAAACU=");
	},
	attachTo:function(e){
		this.displayer=e;
		e.appendChild(this.content);
	},
	setBpm:function(b){
		this.bpm=b;
		this.content.children[0].innerHTML=this.bpm;
	},
	play:function(){
		if(this.playing)return;
		this.playing=true;
		let spb=60000/this.bpm;
		this.content.children[3].style.transition=`transform ${spb}ms linear`;
		this.shouldStop = false;
		this.f();

	},
	stop:function(){
		clearInterval(this.tickInt);
		clearInterval(this.tockInt);
		this.playing=false;
		this.content.children[3].style.transform="translateX(0px)";
		this.shouldStop = true;
	}
};<commit_msg>Fixed metronome bug<commit_after>//usage:
//tab_metro.setUp(bpm , the element you want to attach metronome);<=must do this
//tab_metor.play();
//you can use setBpm to change bpm, and attachTo() to attach metronome on more element
let tab_metro={
	bpm:120,
	playing:false,
	setUp:function(b=120,e=null){
		this.bpm=b;
		this.content=document.createElement('div');
		this.content.setAttribute('style',`
			width:420px;height:250px;
			background:URL('./img/tick_bg.png') #565656;
			text-align:center;
			position:relative;
			border-radius:8px`);
		this.content.innerHTML=`
${this.bpm}

bpm

			`;
		this.shouldStop = true;
		this.pos = 0;
		this.f = function() {
			if (!this.start) {
				this.start = new Date().getTime();
				this.nextAt = this.start;
			}
			this.nextAt += (60/this.bpm) * 1000;
			this.audio.currentTime = 0;
			this.audio.play();
			if(this.pos == 0)
				this.pos = 390;
			else
				this.pos = 0;
			this.content.children[3].style.transform=`translateX(${this.pos}px)`;
/*
			var drift = (new Date().getTime() - start) % 1000;
			$('
').text(drift + "ms").appendTo('#results');
*/
			if(!this.shouldStop)
			setTimeout(this.f.bind(this), this.nextAt - new Date().getTime());
		};
		//this.tick=(function(){this.content.children[3].style.transform="translateX(0px)";}).bind(this);
		//this.tock=(function(){this.content.children[3].style.transform="translateX(390px)";}).bind(this);
		this.attachTo(e);
 		this.audio = new Audio("data:audio/wav;base64,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qJrx4KOQjahZxWbcZgztj2c49nKmkId44S71j0c8eV9yDK6uPRzx5X18eDvjvQ6yKo9ZSS6l//8elePK/Lf//IInrOF/FvDoADYAGBMGb7FtErm5MXMlmPAJQVgWta7Zx2go+8xJ0UiCb8LHHdftWyLJE0QIAIsI+UbXu67dZMjmgDGCGl1H+vpF4NSDckSIkk7Vd+sxEhBQMRU8j/12UIRhzSaUdQ+rQU5kGeFxm+hb1oh6pWWmv3uvmReDl0UnvtapVaIzo1jZbf/pD6ElLqSX+rUmOQNpJFa/r+sa4e/pBlAABoAAAAA3CUgShLdGIxsY7AUABPRrgCABdDuQ5GC7DqPQCgbbJUAoRSUj+NIEig0YfyWUho1VBBBA//uQZB4ABZx5zfMakeAAAAmwAAAAF5F3P0w9GtAAACfAAAAAwLhMDmAYWMgVEG1U0FIGCBgXBXAtfMH10000EEEEEECUBYln03TTTdNBDZopopYvrTTdNa325mImNg3TTPV9q3pmY0xoO6bv3r00y+IDGid/9aaaZTGMuj9mpu9Mpio1dXrr5HERTZSmqU36A3CumzN/9Robv/Xx4v9ijkSRSNLQhAWumap82WRSBUqXStV/YcS+XVLnSS+WLDroqArFkMEsAS+eWmrUzrO0oEmE40RlMZ5+ODIkAyKAGUwZ3mVKmcamcJnMW26MRPgUw6j+LkhyHGVGYjSUUKNpuJUQoOIAyDvEyG8S5yfK6dhZc0Tx1KI/gviKL6qvvFs1+bWtaz58uUNnryq6kt5RzOCkPWlVqVX2a/EEBUdU1KrXLf40GoiiFXK///qpoiDXrOgqDR38JB0bw7SoL+ZB9o1RCkQjQ2CBYZKd/+VJxZRRZlqSkKiws0WFxUyCwsKiMy7hUVFhIaCrNQsKkTIsLivwKKigsj8XYlwt/WKi2N4d//uQRCSAAjURNIHpMZBGYiaQPSYyAAABLAAAAAAAACWAAAAApUF/Mg+0aohSIRobBAsMlO//Kk4soosy1JSFRYWaLC4qZBYWFRGZdwqKiwkNBVmoWFSJkWFxX4FFRQWR+LsS4W/rFRb/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////VEFHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU291bmRib3kuZGUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMjAwNGh0dHA6Ly93d3cuc291bmRib3kuZGUAAAAAAAAAACU=");
	},
	attachTo:function(e){
		this.displayer=e;
		e.appendChild(this.content);
	},
	setBpm:function(b){
		this.bpm=b;
		this.content.children[0].innerHTML=this.bpm;
	},
	play:function(){
		if(this.playing)return;
		this.playing=true;
		let spb=60000/this.bpm;
		this.content.children[3].style.transition=`transform ${spb}ms linear`;
		this.shouldStop = false;
		this.f();

	},
	stop:function(){
		clearInterval(this.tickInt);
		clearInterval(this.tockInt);
		this.playing=false;
		this.start = null;
		this.content.children[3].style.transform="translateX(0px)";
		this.shouldStop = true;
	}
};<|endoftext|>


<commit_before>
var add_host_dialog = function() {
  $('#add_host_tabs').tabs('select', '#add_host_prompt');
  $('#add_host_dialog').dialog('open');
}

$(document).ready(function() {
  $('#add_host_dialog').dialog({
      autoOpen: false,
      title: "Add server",
      resizable: false
  });
  $('#add_host_dialog').keyup(function(ev) {
    if (e.keyCode == 27) {
      $('#add_host_dialog').dialog('close')
    }
  });
  $('#add_host_tabs').tabs()

  $('.add_host_close_button').button()
  $('.add_host_confirm_button').button()
  $('.add_host_submit_button').button()
  $('.add_host_back_button').button()

  $('#add_host_address').keypress(function(ev) {
      if (ev.which == 13) {
          $('.add_host_submit_button').click();
          ev.stopPropagation();
          ev.preventDefault();
          return false;
      }
      /* TODO: would also like to have enter work
           for going confirm->complete */
  });
  function submit_complete(result) {
      console.log('submit_complete: ' + result);
      $('#add_host_tabs').tabs('select', '#add_host_confirm');
      $('.add_host_confirm_button').focus();

      $('#add_host_address_label').html(result['address']);
      $('#add_host_resolve').toggleClass('success', result['resolve']);
      $('#add_host_resolve').toggleClass('failure', !result['resolve']);
      $('#add_host_ping').toggleClass('success', result['ping']);
      $('#add_host_ping').toggleClass('failure', !result['ping']);
      $('#add_host_agent').toggleClass('success', result['agent']);
      $('#add_host_agent').toggleClass('failure', !result['agent']);
  }

  function add_host_error(message) {
      $('#add_host_tabs').tabs('select', '#add_host_error');
      $('#add_host_error_message').html(message);
  }

  function submit_poll(task_id) {
      $.get('/djcelery/' + task_id + '/status/')
          .success(function(data, textStatus, jqXHR) {
              task_status = data['task']['status']
              console.log(task_status)
              if (task_status == 'SUCCESS') {
                  console.log(data);
                  submit_complete(data['task']['result']);
              } else if (task_status == 'FAILURE') {
                  console.log(event.responseText);
                  add_host_error("Internal error.");
              } else {
                  /* Incomplete, schedule re-check */
                  setTimeout(function() {submit_poll(task_id)}, 1000);
              }
              })
          .error(function(event) {
                  console.log(event.responseText);
                  add_host_error("Failed to get status for task " + task_id + ".");
              });
  }

  $('.add_host_submit_button').click(function(ev) {
      $('#add_host_tabs').tabs('select', '#add_host_loading');

      $.post('/api/test_host/', {hostname: $('#add_host_address').attr('value'), commit: false})
      .success(function(data, textStatus, jqXHR) {
          task_id = data.response.task_id
          submit_poll(task_id)
      })
      .error(function(event) {
          console.log(event.responseText);
          data = $.parseJSON(event.responseText);
          add_host_error(data['error']);
      });
      console.log('preventing default');
      ev.preventDefault();
  });

  $('.add_host_confirm_button').click(function(ev) {
          $.post('/api/add_host/', {hostname: $('#add_host_address_label').html(), commit: true})
      .success(function(data, textStatus, jqXHR) {
          $('#add_host_tabs').tabs('select', '#add_host_complete');
          $('.add_host_back_button').focus();
          $('#server_configuration').dataTable().fnClearTable();
          LoadServerConf_ServerConfig();
      })
      .error(function(event) {
          console.log(event.responseText);
          data = $.parseJSON(event.responseText);
          add_host_error(data['error'])
      });

      ev.preventDefault();
  });

  $('.add_host_close_button').click(function(ev) {
      $('#add_host_dialog').dialog('close')
      ev.preventDefault();
  });

  $('.add_host_back_button').click(function(ev) {
      $('#add_host_tabs').tabs('select', '#add_host_prompt')
            ev.preventDefault();
        });
});
<commit_msg>My esc key code was unnecessary<commit_after>
var add_host_dialog = function() {
  $('#add_host_tabs').tabs('select', '#add_host_prompt');
  $('#add_host_dialog').dialog('open');
  $('#add_host_address').focus();
}

$(document).ready(function() {
  $('#add_host_dialog').dialog({
      autoOpen: false,
      title: "Add server",
      resizable: false
  });
  $('#add_host_tabs').tabs()

  $('.add_host_close_button').button()
  $('.add_host_confirm_button').button()
  $('.add_host_submit_button').button()
  $('.add_host_back_button').button()

  $('#add_host_address').keypress(function(ev) {
      if (ev.which == 13) {
          $('.add_host_submit_button').click();
          ev.stopPropagation();
          ev.preventDefault();
          return false;
      }
  });
  function submit_complete(result) {
      console.log('submit_complete: ' + result);
      $('#add_host_tabs').tabs('select', '#add_host_confirm');
      $('.add_host_confirm_button').focus();

      $('#add_host_address_label').html(result['address']);
      $('#add_host_resolve').toggleClass('success', result['resolve']);
      $('#add_host_resolve').toggleClass('failure', !result['resolve']);
      $('#add_host_ping').toggleClass('success', result['ping']);
      $('#add_host_ping').toggleClass('failure', !result['ping']);
      $('#add_host_agent').toggleClass('success', result['agent']);
      $('#add_host_agent').toggleClass('failure', !result['agent']);
  }

  function add_host_error(message) {
      $('#add_host_tabs').tabs('select', '#add_host_error');
      $('#add_host_error_message').html(message);
  }

  function submit_poll(task_id) {
      $.get('/djcelery/' + task_id + '/status/')
          .success(function(data, textStatus, jqXHR) {
              task_status = data['task']['status']
              console.log(task_status)
              if (task_status == 'SUCCESS') {
                  console.log(data);
                  submit_complete(data['task']['result']);
              } else if (task_status == 'FAILURE') {
                  console.log(event.responseText);
                  add_host_error("Internal error.");
              } else {
                  /* Incomplete, schedule re-check */
                  setTimeout(function() {submit_poll(task_id)}, 1000);
              }
              })
          .error(function(event) {
                  console.log(event.responseText);
                  add_host_error("Failed to get status for task " + task_id + ".");
              });
  }

  $('.add_host_submit_button').click(function(ev) {
      $('#add_host_tabs').tabs('select', '#add_host_loading');

      $.post('/api/test_host/', {hostname: $('#add_host_address').attr('value'), commit: false})
      .success(function(data, textStatus, jqXHR) {
          task_id = data.response.task_id
          submit_poll(task_id)
      })
      .error(function(event) {
          console.log(event.responseText);
          data = $.parseJSON(event.responseText);
          add_host_error(data['error']);
      });
      ev.preventDefault();
  });

  $('.add_host_confirm_button').click(function(ev) {
          $.post('/api/add_host/', {hostname: $('#add_host_address_label').html(), commit: true})
      .success(function(data, textStatus, jqXHR) {
          $('#add_host_tabs').tabs('select', '#add_host_complete');
          $('.add_host_back_button').focus();
          $('#server_configuration').dataTable().fnClearTable();
          LoadServerConf_ServerConfig();
      })
      .error(function(event) {
          console.log(event.responseText);
          add_host_error(data['error'])
      });

      ev.preventDefault();
  });

  $('.add_host_close_button').click(function(ev) {
      $('#add_host_dialog').dialog('close')
      ev.preventDefault();
  });

  $('.add_host_back_button').click(function(ev) {
      $('#add_host_tabs').tabs('select', '#add_host_prompt')
      ev.preventDefault();
  });
});
<|endoftext|>


<commit_before>var path      = require('path');
var requirejs = require('requirejs');
var should    = require('should');

requirejs.config({
  nodeRequire: require,
  baseUrl: path.normalize(path.join(__dirname, '../../../src')),
});

var m4 = requirejs('./m4');

describe('m4', function() {
  var m = [
     0,  1,  2,  3,
     4,  5,  6,  7,
     8,  9, 10, 11,
    12, 13, 14, 15,
  ];

  function testM4WithoutDest(func, expected) {
    var d = func();
    d.should.eql(expected);
  }

  function testM4WithDest(func, expected) {
    var d = new Float32Array(16);
    var c = func(d);
    c.should.be.equal(d);
    c.should.be.eql(expected);
  }

  function testM4WithAndWithoutDest(func, expected) {
    expected = new Float32Array(expected);
    testM4WithoutDest(func, expected);
    testM4WithDest(func, expected);
  }

  function testV3WithoutDest(func, expected) {
    var d = func();
    d.should.eql(expected);
  }

  function testV3WithDest(func, expected) {
    var d = new Float32Array(3);
    var c = func(d);
    c.should.be.equal(d);
    c.should.be.eql(expected);
  }

  function testV3WithAndWithoutDest(func, expected) {
    expected = new Float32Array(expected);
    testV3WithoutDest(func, expected);
    testV3WithDest(func, expected);
  }

  it('should set default type', function() {
    m4.setDefaultType(Array);
    var d = m4.identity();
    d.should.be.Array();
    m4.setDefaultType(Float32Array);
    d = m4.identity();
    d.should.be.instanceOf(Float32Array);
  });

  it('should negate', function() {
    var expected = [
      -0,  -1,  -2,  -3,
      -4,  -5,  -6,  -7,
      -8,  -9, -10, -11,
     -12, -13, -14, -15,
    ];
    testM4WithAndWithoutDest(function(dst) {
      return m4.negate(m, dst);
    }, expected);
  });

  it('should copy', function() {
    var expected = m;
    testM4WithAndWithoutDest(function(dst) {
      return m4.copy(m, dst);
    }, expected);
  });

  it('should make identity', function() {
    var expected = [
      1, 0, 0, 0,
      0, 1, 0, 0,
      0, 0, 1, 0,
      0, 0, 0, 1,
    ];
    testM4WithAndWithoutDest(function(dst) {
      return m4.identity(dst);
    }, expected);
  });

  it('should transpose', function() {
    var expected = [
      0, 4, 8, 12,
      1, 5, 9, 13,
      2, 6, 10, 14,
      3, 7, 11, 15,
    ];
    testM4WithAndWithoutDest(function(dst) {
      return m4.transpose(m, dst);
    }, expected);
  });

  it('should set translation', function() {
    var expected = [
      0,  1,  2,  3,
      4,  5,  6,  7,
      8,  9, 10, 11,
     11, 22, 33, 1,
    ];
    testM4WithAndWithoutDest(function(dst) {
      return m4.setTranslation(m, [11, 22, 33], dst);
    }, expected);
  });

  it('should get translation', function() {
    var expected = [12, 13, 14];
    testV3WithAndWithoutDest(function(dst) {
      return m4.getTranslation(m, dst);
    }, expected);
  });

  it('should get axis', function() {
    var expected = [
      [0, 1, 2],
      [4, 5, 6],
      [8, 9, 10],
    ].forEach(function(expected, ndx) {
      testV3WithAndWithoutDest(function(dst) {
        return m4.getAxis(m, ndx, dst);
      }, expected);
    });
  });

  it('should compute perspective', function() {
    var fov = 2;
    var aspect = 4;
    var zNear = 10;
    var zFar = 30;
    var f = Math.tan(Math.PI * 0.5 - 0.5 * fov);
    var rangeInv = 1.0 / (zNear - zFar);
    var expected = [
      f / aspect,
      0,
      0,
      0,

      0,
      f,
      0,
      0,

      0,
      0,
      (zNear + zFar) * rangeInv,
      -1,

      0,
      0,
      zNear * zFar * rangeInv * 2,
      0,
    ];
    testM4WithAndWithoutDest(function(dst) {
      return m4.perspective(fov, aspect, zNear, zFar, dst);
    }, expected);
  });

  it('should compute ortho', function() {
    var left = 2;
    var right = 4;
    var top = 10;
    var bottom = 30;
    var near = 15;
    var far = 25;
    var expected = [
      2 / (right - left),
      0,
      0,
      0,

      0,
      2 / (top - bottom),
      0,
      0,

      0,
      0,
      -1 / (far - near),
      0,

      (right + left) / (left - right),
      (top + bottom) / (bottom - top),
      -near / (near - far),
      1,
    ];
    testM4WithAndWithoutDest(function(dst) {
      return m4.ortho(left, right, bottom, top, near, far, dst);
    }, expected);
  });

  it('should compute frustum', function() {
    var left = 2;
    var right = 4;
    var top = 10;
    var bottom = 30;
    var near = 15;
    var far = 25;

    var dx = (right - left);
    var dy = (top - bottom);
    var dz = (near - far);

    var expected = [
      2 * near / dx,
      0,
      0,
      0,
      0,
      2 * near / dy,
      0,
      0,
      (left + right) / dx,
      (top + bottom) / dy,
      far / dz,
      -1,
      0,
      0,
      near * far / dz,
      0,
    ];
    testM4WithAndWithoutDest(function(dst) {
      return m4.frustum(left, right, bottom, top, near, far, dst);
    }, expected);
  });

  it('should making scaling', function() {
    var expected = [
      2, 0, 0, 0,
      0, 3, 0, 0,
      0, 0, 4, 0,
      0, 0, 0, 1,
    ];
    testM4WithAndWithoutDest(function(dst) {
      return m4.scaling([2, 3, 4], dst);
    }, expected);
  });

  it('should scale', function() {
    var expected = [
       0,  2,  4,  6,
      12, 15, 18, 21,
      32, 36, 40, 44,
      12, 13, 14, 15,
    ];
    testM4WithAndWithoutDest(function(dst) {
      return m4.scale(m, [2, 3, 4], dst);
    }, expected);
  });

});

<commit_msg>add more tests<commit_after>var path      = require('path');
var requirejs = require('requirejs');
var should    = require('should');

requirejs.config({
  nodeRequire: require,
  baseUrl: path.normalize(path.join(__dirname, '../../../src')),
});

var m4 = requirejs('./m4');

describe('m4', function() {
  var m = [
     0,  1,  2,  3,
     4,  5,  6,  7,
     8,  9, 10, 11,
    12, 13, 14, 15,
  ];

  function testM4WithoutDest(func, expected) {
    var d = func();
    d.should.eql(expected);
  }

  function testM4WithDest(func, expected) {
    var d = new Float32Array(16);
    var c = func(d);
    c.should.be.equal(d);
    c.should.be.eql(expected);
  }

  function testM4WithAndWithoutDest(func, expected) {
    expected = new Float32Array(expected);
    testM4WithoutDest(func, expected);
    testM4WithDest(func, expected);
  }

  function testV3WithoutDest(func, expected) {
    var d = func();
    d.should.eql(expected);
  }

  function testV3WithDest(func, expected) {
    var d = new Float32Array(3);
    var c = func(d);
    c.should.be.equal(d);
    c.should.be.eql(expected);
  }

  function testV3WithAndWithoutDest(func, expected) {
    expected = new Float32Array(expected);
    testV3WithoutDest(func, expected);
    testV3WithDest(func, expected);
  }

  it('should set default type', function() {
    m4.setDefaultType(Array);
    var d = m4.identity();
    d.should.be.Array();
    m4.setDefaultType(Float32Array);
    d = m4.identity();
    d.should.be.instanceOf(Float32Array);
  });

  it('should negate', function() {
    var expected = [
      -0,  -1,  -2,  -3,
      -4,  -5,  -6,  -7,
      -8,  -9, -10, -11,
     -12, -13, -14, -15,
    ];
    testM4WithAndWithoutDest(function(dst) {
      return m4.negate(m, dst);
    }, expected);
  });

  it('should copy', function() {
    var expected = m;
    testM4WithAndWithoutDest(function(dst) {
      return m4.copy(m, dst);
    }, expected);
  });

  it('should make identity', function() {
    var expected = [
      1, 0, 0, 0,
      0, 1, 0, 0,
      0, 0, 1, 0,
      0, 0, 0, 1,
    ];
    testM4WithAndWithoutDest(function(dst) {
      return m4.identity(dst);
    }, expected);
  });

  it('should transpose', function() {
    var expected = [
      0, 4, 8, 12,
      1, 5, 9, 13,
      2, 6, 10, 14,
      3, 7, 11, 15,
    ];
    testM4WithAndWithoutDest(function(dst) {
      return m4.transpose(m, dst);
    }, expected);
  });

// TODO inverse
// TODO multiply

  it('should set translation', function() {
    var expected = [
      0,  1,  2,  3,
      4,  5,  6,  7,
      8,  9, 10, 11,
     11, 22, 33, 1,
    ];
    testM4WithAndWithoutDest(function(dst) {
      return m4.setTranslation(m, [11, 22, 33], dst);
    }, expected);
  });

  it('should get translation', function() {
    var expected = [12, 13, 14];
    testV3WithAndWithoutDest(function(dst) {
      return m4.getTranslation(m, dst);
    }, expected);
  });

  it('should get axis', function() {
    var expected = [
      [0, 1, 2],
      [4, 5, 6],
      [8, 9, 10],
    ].forEach(function(expected, ndx) {
      testV3WithAndWithoutDest(function(dst) {
        return m4.getAxis(m, ndx, dst);
      }, expected);
    });
  });

  it('should compute perspective', function() {
    var fov = 2;
    var aspect = 4;
    var zNear = 10;
    var zFar = 30;
    var f = Math.tan(Math.PI * 0.5 - 0.5 * fov);
    var rangeInv = 1.0 / (zNear - zFar);
    var expected = [
      f / aspect,
      0,
      0,
      0,

      0,
      f,
      0,
      0,

      0,
      0,
      (zNear + zFar) * rangeInv,
      -1,

      0,
      0,
      zNear * zFar * rangeInv * 2,
      0,
    ];
    testM4WithAndWithoutDest(function(dst) {
      return m4.perspective(fov, aspect, zNear, zFar, dst);
    }, expected);
  });

  it('should compute ortho', function() {
    var left = 2;
    var right = 4;
    var top = 10;
    var bottom = 30;
    var near = 15;
    var far = 25;
    var expected = [
      2 / (right - left),
      0,
      0,
      0,

      0,
      2 / (top - bottom),
      0,
      0,

      0,
      0,
      -1 / (far - near),
      0,

      (right + left) / (left - right),
      (top + bottom) / (bottom - top),
      -near / (near - far),
      1,
    ];
    testM4WithAndWithoutDest(function(dst) {
      return m4.ortho(left, right, bottom, top, near, far, dst);
    }, expected);
  });

  it('should compute frustum', function() {
    var left = 2;
    var right = 4;
    var top = 10;
    var bottom = 30;
    var near = 15;
    var far = 25;

    var dx = (right - left);
    var dy = (top - bottom);
    var dz = (near - far);

    var expected = [
      2 * near / dx,
      0,
      0,
      0,
      0,
      2 * near / dy,
      0,
      0,
      (left + right) / dx,
      (top + bottom) / dy,
      far / dz,
      -1,
      0,
      0,
      near * far / dz,
      0,
    ];
    testM4WithAndWithoutDest(function(dst) {
      return m4.frustum(left, right, bottom, top, near, far, dst);
    }, expected);
  });

// TODO lookAt

  it('should make translation matrix', function() {
    var expected = [
      1, 0, 0, 0,
      0, 1, 0, 0,
      0, 0, 1, 0,
      2, 3, 4, 1,
    ];
    testM4WithAndWithoutDest(function(dst) {
      return m4.translation([2, 3, 4], dst);
    }, expected);
  });

  it('should translate', function() {
    var expected = [
      0,  1,  2,  3,
      4,  5,  6,  7,
      8,  9, 10, 11,
     12 + 0 * 2 + 4 * 3 + 8 * 4,
     13 + 1 * 2 + 5 * 3 + 9 * 4,
     14 + 2 * 2 + 6 * 3 + 10 * 4,
     15 + 3 * 2 + 7 * 3 + 11 * 4,
    ];
    testM4WithAndWithoutDest(function(dst) {
      return m4.translate(m, [2, 3, 4], dst);
    }, expected);
  });

  it('should make x rotation matrix', function() {
    var angle = 1.23;
    var c = Math.cos(angle);
    var s = Math.sin(angle);
    var expected = [
      1, 0, 0, 0,
      0, c, s, 0,
      0,-s, c, 0,
      0, 0, 0, 1,
    ];
    testM4WithAndWithoutDest(function(dst) {
      return m4.rotationX(angle, dst);
    }, expected);
  });

// TODO rotate x

  it('should make y rotation matrix', function() {
    var angle = 1.23;
    var c = Math.cos(angle);
    var s = Math.sin(angle);
    var expected = [
      c, 0,-s, 0,
      0, 1, 0, 0,
      s, 0, c, 0,
      0, 0, 0, 1,
    ];
    testM4WithAndWithoutDest(function(dst) {
      return m4.rotationY(angle, dst);
    }, expected);
  });

// TODO rotate y

  it('should make z rotation matrix', function() {
    var angle = 1.23;
    var c = Math.cos(angle);
    var s = Math.sin(angle);
    var expected = [
      c, s, 0, 0,
     -s, c, 0, 0,
      0, 0, 1, 0,
      0, 0, 0, 1,
    ];
    testM4WithAndWithoutDest(function(dst) {
      return m4.rotationZ(angle, dst);
    }, expected);
  });

// TODO rotate z
// TODO axisRotation
// TODO axisRotate

  it('should make scaling matrix', function() {
    var expected = [
      2, 0, 0, 0,
      0, 3, 0, 0,
      0, 0, 4, 0,
      0, 0, 0, 1,
    ];
    testM4WithAndWithoutDest(function(dst) {
      return m4.scaling([2, 3, 4], dst);
    }, expected);
  });

  it('should scale', function() {
    var expected = [
       0,  2,  4,  6,
      12, 15, 18, 21,
      32, 36, 40, 44,
      12, 13, 14, 15,
    ];
    testM4WithAndWithoutDest(function(dst) {
      return m4.scale(m, [2, 3, 4], dst);
    }, expected);
  });

// TODO transformPoint
// TODO transformDirectiojn
// TODO transformNormal

});

<|endoftext|>


<commit_before>class PortfolioIndexService {
  constructor () {
    'ngInject';

    this.data = [
      // {
      //   title : 'TrailLink',
      // 	image : 'assets/images/projects/sony-wheel/sony-wheel-thumbnail.jpg',
      //   state  : 'trail-link'
      // },
      {
        title : 'Banners',
      	image : 'assets/images/projects/sapient-banners/sapient-banners-thumbnail.jpg',
        state  : 'sapient-banners'
      },
      {
        title : 'Sony Wheel',
      	image : 'assets/images/projects/sony-wheel/sony-wheel-thumbnail.jpg',
        state  : 'sony-wheel'
      },
      {
        title : 'Digital Room',
      	image : 'assets/images/projects/haygarth-digital-room/haygarth-digital-room-thumbnail.jpg',
        state  : 'haygarth-digital-room'
      },
      // {
      //   title : 'Think Differently',
      // 	image : 'assets/images/projects/think-differently/think-differently-thumbnail.jpg',
      //   state  : 'think-differently'
      // },
      {
        title : 'YSL Rock Chick',
      	image : 'assets/images/projects/ysl-rock-chick/ysl-rock-chick-thumbnail.jpg',
        state  : 'ysl-rock-chick'
      },
      // {
      //   title : 'Gulp Emails',
      // 	image : 'assets/images/projects/gulp-emails/gulp-emails-thumbnail.jpg',
      //   state  : 'gulp-emails'
      // },
      {
        title : 'Haygarth',
      	image : 'assets/images/projects/haygarth/haygarth-thumbnail.jpg',
        state  : 'haygarth'
      },
      {
        title : 'Sony Demo Bay',
      	image : 'assets/images/projects/sony-demo-bay/sony-demo-bay-thumbnail.jpg',
        state  : 'sony-demo-bay'
      },
      {
        title : 'Giles Deacon',
      	image : 'assets/images/projects/giles-deacon/giles-deacon-thumbnail.jpg',
        state  : 'giles-deacon'
      },
      // {
      //   title : 'Toni & Guy',
      // 	image : 'assets/images/projects/toni-and-guy/toni-and-guy-thumbnail.png',
      //   state  : 'toni-and-guy'
      // },
      // {
      //   title : 'Louise & Daniel',
      // 	image : 'assets/images/projects/louise-and-daniel/louise-and-daniel-thumbnail.jpg',
      //   state  : 'louise-and-daniel'
      // },
      // {
      //   title : 'Dumfries House',
      // 	image : 'assets/images/projects/dumfries-house/dumfries-house-thumbnail.jpg',
      //   state  : 'dumfries-house'
      // },
      // {
      //   title : 'Lambeth Advice Network',
      // 	image : 'assets/images/projects/lambeth/lambeth-thumbnail.jpg',
      //   state  : 'lambeth'
      // },
      {
        title : 'AMBR Media',
      	image : 'assets/images/projects/ambr/ambr-thumbnail.png',
        state  : 'ambr'
      },
      {
        title : 'Layla Moran',
      	image : 'assets/images/projects/layla/layla-thumbnail.png',
        state  : 'layla-moran'
      },
      {
        title : 'Lancastrians',
      	image : 'assets/images/projects/lancastrians/lancastrians-thumbnail.jpg',
        state  : 'lancastrians'
      },
      {
        title : 'EUFN',
      	image : 'assets/images/projects/eufn/eufn-thumbnail.png',
        state  : 'eufn'
      }
      // {
      //   title : 'Waterleaf',
      // 	image : 'assets/images/projects/waterleaf/waterleaf-thumbnail.png',
      //   state  : 'waterleaf'
      // }
    ];
  }

  getPortfolioIndexContent() {
    return this.data;
  }
}

export default PortfolioIndexService;
<commit_msg>Add Plaids project to index<commit_after>class PortfolioIndexService {
  constructor () {
    'ngInject';

    this.data = [
      {
        title : 'Pladis',
      	image : 'assets/images/projects/pladis/pladis-thumbnail.jpg',
        state  : 'pladis'
      },
      // {
      //   title : 'TrailLink',
      // 	image : 'assets/images/projects/sony-wheel/sony-wheel-thumbnail.jpg',
      //   state  : 'trail-link'
      // },
      {
        title : 'Banners',
      	image : 'assets/images/projects/sapient-banners/sapient-banners-thumbnail.jpg',
        state  : 'sapient-banners'
      },
      {
        title : 'Sony Wheel',
      	image : 'assets/images/projects/sony-wheel/sony-wheel-thumbnail.jpg',
        state  : 'sony-wheel'
      },
      {
        title : 'Digital Room',
      	image : 'assets/images/projects/haygarth-digital-room/haygarth-digital-room-thumbnail.jpg',
        state  : 'haygarth-digital-room'
      },
      // {
      //   title : 'Think Differently',
      // 	image : 'assets/images/projects/think-differently/think-differently-thumbnail.jpg',
      //   state  : 'think-differently'
      // },
      {
        title : 'YSL Rock Chick',
      	image : 'assets/images/projects/ysl-rock-chick/ysl-rock-chick-thumbnail.jpg',
        state  : 'ysl-rock-chick'
      },
      // {
      //   title : 'Gulp Emails',
      // 	image : 'assets/images/projects/gulp-emails/gulp-emails-thumbnail.jpg',
      //   state  : 'gulp-emails'
      // },
      {
        title : 'Haygarth',
      	image : 'assets/images/projects/haygarth/haygarth-thumbnail.jpg',
        state  : 'haygarth'
      },
      {
        title : 'Sony Demo Bay',
      	image : 'assets/images/projects/sony-demo-bay/sony-demo-bay-thumbnail.jpg',
        state  : 'sony-demo-bay'
      },
      {
        title : 'Giles Deacon',
      	image : 'assets/images/projects/giles-deacon/giles-deacon-thumbnail.jpg',
        state  : 'giles-deacon'
      },
      // {
      //   title : 'Toni & Guy',
      // 	image : 'assets/images/projects/toni-and-guy/toni-and-guy-thumbnail.png',
      //   state  : 'toni-and-guy'
      // },
      // {
      //   title : 'Louise & Daniel',
      // 	image : 'assets/images/projects/louise-and-daniel/louise-and-daniel-thumbnail.jpg',
      //   state  : 'louise-and-daniel'
      // },
      // {
      //   title : 'Dumfries House',
      // 	image : 'assets/images/projects/dumfries-house/dumfries-house-thumbnail.jpg',
      //   state  : 'dumfries-house'
      // },
      // {
      //   title : 'Lambeth Advice Network',
      // 	image : 'assets/images/projects/lambeth/lambeth-thumbnail.jpg',
      //   state  : 'lambeth'
      // },
      {
        title : 'AMBR Media',
      	image : 'assets/images/projects/ambr/ambr-thumbnail.png',
        state  : 'ambr'
      },
      {
        title : 'Layla Moran',
      	image : 'assets/images/projects/layla/layla-thumbnail.png',
        state  : 'layla-moran'
      },
      {
        title : 'Lancastrians',
      	image : 'assets/images/projects/lancastrians/lancastrians-thumbnail.jpg',
        state  : 'lancastrians'
      },
      {
        title : 'EUFN',
      	image : 'assets/images/projects/eufn/eufn-thumbnail.png',
        state  : 'eufn'
      }
      // {
      //   title : 'Waterleaf',
      // 	image : 'assets/images/projects/waterleaf/waterleaf-thumbnail.png',
      //   state  : 'waterleaf'
      // }
    ];
  }

  getPortfolioIndexContent() {
    return this.data;
  }
}

export default PortfolioIndexService;
<|endoftext|>


<commit_before>(function webpackUniversalModuleDefinition(root, factory) {
	if(typeof exports === 'object' && typeof module === 'object')
		module.exports = factory(require("leaflet"));
	else if(typeof define === 'function' && define.amd)
		define(["leaflet"], factory);
	else if(typeof exports === 'object')
		exports["VectorMarkers"] = factory(require("leaflet"));
	else
		root["VectorMarkers"] = factory(root["L"]);
})(this, function(__WEBPACK_EXTERNAL_MODULE_1__) {
return /******/ (function(modules) { // webpackBootstrap
/******/ 	// The module cache
/******/ 	var installedModules = {};

/******/ 	// The require function
/******/ 	function __webpack_require__(moduleId) {

/******/ 		// Check if module is in cache
/******/ 		if(installedModules[moduleId])
/******/ 			return installedModules[moduleId].exports;

/******/ 		// Create a new module (and put it into the cache)
/******/ 		var module = installedModules[moduleId] = {
/******/ 			exports: {},
/******/ 			id: moduleId,
/******/ 			loaded: false
/******/ 		};

/******/ 		// Execute the module function
/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);

/******/ 		// Flag the module as loaded
/******/ 		module.loaded = true;

/******/ 		// Return the exports of the module
/******/ 		return module.exports;
/******/ 	}

/******/ 	// expose the modules object (__webpack_modules__)
/******/ 	__webpack_require__.m = modules;

/******/ 	// expose the module cache
/******/ 	__webpack_require__.c = installedModules;

/******/ 	// __webpack_public_path__
/******/ 	__webpack_require__.p = "";

/******/ 	// Load entry module and return exports
/******/ 	return __webpack_require__(0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.Icon = exports.VectorMarkers = undefined;

	var _leaflet = __webpack_require__(1);

	var _leaflet2 = _interopRequireDefault(_leaflet);

	var _VectorMarkers2 = __webpack_require__(2);

	var _VectorMarkers3 = _interopRequireDefault(_VectorMarkers2);

	var _Icon2 = __webpack_require__(3);

	var _Icon3 = _interopRequireDefault(_Icon2);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	exports.VectorMarkers = _VectorMarkers3.default;
	exports.Icon = _Icon3.default;

	_leaflet2.default.VectorMarkers = _VectorMarkers3.default;

/***/ },
/* 1 */
/***/ function(module, exports) {

	module.exports = __WEBPACK_EXTERNAL_MODULE_1__;

/***/ },
/* 2 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	var _Icon = __webpack_require__(3);

	var _Icon2 = _interopRequireDefault(_Icon);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	exports.default = {
	  version: '1.0.0',

	  Icon: _Icon2.default,

	  icon: function icon(options) {
	    return new _Icon2.default(options);
	  }
	};

/***/ },
/* 3 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

	var _leaflet = __webpack_require__(1);

	var _leaflet2 = _interopRequireDefault(_leaflet);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

	function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

	var iconOptions = {
	  iconSize: [30, 50],
	  iconAnchor: [15, 50],
	  popupAnchor: [2, -40],
	  shadowAnchor: [39, 45],
	  shadowSize: [54, 51],
	  className: 'vector-marker',
	  prefix: 'fa',
	  spinClass: 'fa-spin',
	  extraIconClasses: '',
	  extraDivClasses: '',
	  icon: 'home',
	  markerColor: 'blue',
	  iconColor: 'white',
	  viewBox: '0 0 32 52'
	};

	var mapPin = 'M16,1 C7.7146,1 1,7.65636364 1,15.8648485 C1,24.0760606 16,51 16,51 C16,51 31,24.0760606 31,15.8648485 C31,7.65636364 24.2815,1 16,1 L16,1 Z';

	var Icon = function (_Leaflet$Icon) {
	  _inherits(Icon, _Leaflet$Icon);

	  function Icon(options) {
	    _classCallCheck(this, Icon);

	    var _this = _possibleConstructorReturn(this, Object.getPrototypeOf(Icon).call(this, options));

	    _leaflet2.default.Util.setOptions(_this, iconOptions);
	    _leaflet2.default.Util.setOptions(_this, options);
	    return _this;
	  }

	  _createClass(Icon, [{
	    key: 'createIcon',
	    value: function createIcon(oldIcon) {
	      var div = oldIcon && oldIcon.tagName === 'DIV' ? oldIcon : document.createElement('div');
	      var options = this.options;
	      var pin_path = options.map_pin || mapPin;

	      div.innerHTML = '<svg width="' + options.iconSize[0] + 'px" height="' + options.iconSize[1] + 'px" viewBox="' + options.viewBox + '" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="' + pin_path + '" fill="' + options.markerColor + '"></path></svg>';

	      if (options.icon) {
	        div.appendChild(this._createInner());
	      }

	      options.className += options.className.length > 0 ? ' ' + options.extraDivClasses : options.extraDivClasses;
	      this._setIconStyles(div, 'icon');
	      this._setIconStyles(div, 'icon-' + options.markerColor);
	      return div;
	    }
	  }, {
	    key: 'createShadow',
	    value: function createShadow() {
	      var div = document.createElement('div');
	      this._setIconStyles(div, 'shadow');
	      return div;
	    }
	  }, {
	    key: '_createInner',
	    value: function _createInner() {
	      var i = document.createElement('i');
	      var options = this.options;

	      i.classList.add(options.prefix);
	      if (options.extraClasses) {
	        i.classList.add(options.extraClasses);
	      }
	      if (options.icon.slice(0, options.prefix.length + 1) === options.prefix + '-') {
	        i.classList.add(options.icon);
	      } else {
	        i.classList.add(options.prefix + '-' + options.icon);
	      }
	      if (options.spin && typeof options.spinClass === 'string') {
	        i.classList.add(options.spinClass);
	      }
	      if (options.iconColor) {
	        if (options.iconColor === 'white' || options.iconColor === 'black') {
	          i.classList.add('icon-' + options.iconColor);
	        } else {
	          i.style.color = options.iconColor;
	        }
	      }
	      if (options.iconSize) {
	        i.style.width = options.iconSize[0] + 'px';
	      }
	      return i;
	    }
	  }, {
	    key: '_setIconStyles',
	    value: function _setIconStyles(img, name) {
	      var options = this.options;
	      var size = _leaflet2.default.point(options[name === 'shadow' ? 'shadowSize' : 'iconSize']);
	      var anchor = void 0;

	      if (name === 'shadow') {
	        anchor = _leaflet2.default.point(options.shadowAnchor || options.iconAnchor);
	      } else {
	        anchor = _leaflet2.default.point(options.iconAnchor);
	      }
	      if (!anchor && size) {
	        anchor = size.divideBy(2, true);
	      }
	      img.className = 'vector-marker-' + name + ' ' + options.className;
	      if (anchor) {
	        img.style.marginLeft = -anchor.x + 'px';
	        img.style.marginTop = -anchor.y + 'px';
	      }
	      if (size) {
	        img.style.width = size.x + 'px';
	        img.style.height = size.y + 'px';
	      }
	    }
	  }]);

	  return Icon;
	}(_leaflet2.default.Icon);

	exports.default = Icon;

/***/ }
/******/ ])
});
;<commit_msg>Leaflet.awesome-markers.<commit_after>(function webpackUniversalModuleDefinition(root, factory) {
	if(typeof exports === 'object' && typeof module === 'object')
		module.exports = factory(require("leaflet"));
	else if(typeof define === 'function' && define.amd)
		define(["leaflet"], factory);
	else if(typeof exports === 'object')
		exports["VectorMarkers"] = factory(require("leaflet"));
	else
		root["VectorMarkers"] = factory(root["L"]);
})(this, function(__WEBPACK_EXTERNAL_MODULE_1__) {
return /******/ (function(modules) { // webpackBootstrap
/******/ 	// The module cache
/******/ 	var installedModules = {};

/******/ 	// The require function
/******/ 	function __webpack_require__(moduleId) {

/******/ 		// Check if module is in cache
/******/ 		if(installedModules[moduleId])
/******/ 			return installedModules[moduleId].exports;

/******/ 		// Create a new module (and put it into the cache)
/******/ 		var module = installedModules[moduleId] = {
/******/ 			exports: {},
/******/ 			id: moduleId,
/******/ 			loaded: false
/******/ 		};

/******/ 		// Execute the module function
/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);

/******/ 		// Flag the module as loaded
/******/ 		module.loaded = true;

/******/ 		// Return the exports of the module
/******/ 		return module.exports;
/******/ 	}

/******/ 	// expose the modules object (__webpack_modules__)
/******/ 	__webpack_require__.m = modules;

/******/ 	// expose the module cache
/******/ 	__webpack_require__.c = installedModules;

/******/ 	// __webpack_public_path__
/******/ 	__webpack_require__.p = "";

/******/ 	// Load entry module and return exports
/******/ 	return __webpack_require__(0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});
	exports.Icon = exports.VectorMarkers = undefined;

	var _leaflet = __webpack_require__(1);

	var _leaflet2 = _interopRequireDefault(_leaflet);

	var _VectorMarkers2 = __webpack_require__(2);

	var _VectorMarkers3 = _interopRequireDefault(_VectorMarkers2);

	var _Icon2 = __webpack_require__(3);

	var _Icon3 = _interopRequireDefault(_Icon2);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	exports.VectorMarkers = _VectorMarkers3.default;
	exports.Icon = _Icon3.default;

	_leaflet2.default.VectorMarkers = _VectorMarkers3.default;

/***/ },
/* 1 */
/***/ function(module, exports) {

	module.exports = __WEBPACK_EXTERNAL_MODULE_1__;

/***/ },
/* 2 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	var _Icon = __webpack_require__(3);

	var _Icon2 = _interopRequireDefault(_Icon);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	exports.default = {
	  version: '1.0.0',

	  Icon: _Icon2.default,

	  icon: function icon(options) {
	    return new _Icon2.default(options);
	  }
	};

/***/ },
/* 3 */
/***/ function(module, exports, __webpack_require__) {

	'use strict';

	Object.defineProperty(exports, "__esModule", {
	  value: true
	});

	var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

	var _leaflet = __webpack_require__(1);

	var _leaflet2 = _interopRequireDefault(_leaflet);

	function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

	function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

	function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

	function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

	var iconOptions = {
	  iconSize: [30, 50],
	  iconAnchor: [15, 50],
	  popupAnchor: [10, -30], //[2, -40],
	  shadowAnchor: [39, 45],
	  shadowSize: [54, 51],
	  className: 'vector-marker',
	  prefix: 'fa',
	  spinClass: 'fa-spin',
	  extraIconClasses: '',
	  extraDivClasses: '',
	  icon: 'home',
	  markerColor: 'blue',
	  iconColor: 'white',
	  viewBox: '0 0 32 52'
	};

	var mapPin = 'M16,1 C7.7146,1 1,7.65636364 1,15.8648485 C1,24.0760606 16,51 16,51 C16,51 31,24.0760606 31,15.8648485 C31,7.65636364 24.2815,1 16,1 L16,1 Z';

	var Icon = function (_Leaflet$Icon) {
	  _inherits(Icon, _Leaflet$Icon);

	  function Icon(options) {
	    _classCallCheck(this, Icon);

	    var _this = _possibleConstructorReturn(this, Object.getPrototypeOf(Icon).call(this, options));

	    _leaflet2.default.Util.setOptions(_this, iconOptions);
	    _leaflet2.default.Util.setOptions(_this, options);
	    return _this;
	  }

	  _createClass(Icon, [{
	    key: 'createIcon',
	    value: function createIcon(oldIcon) {
	      var div = oldIcon && oldIcon.tagName === 'DIV' ? oldIcon : document.createElement('div');
	      var options = this.options;
	      var pin_path = options.map_pin || mapPin;

	      div.innerHTML = '<svg width="' + options.iconSize[0] + 'px" height="' + options.iconSize[1] + 'px" viewBox="' + options.viewBox + '" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="' + pin_path + '" fill="' + options.markerColor + '"></path></svg>';

	      if (options.icon) {
	        div.appendChild(this._createInner());
	      }

	      options.className += options.className.length > 0 ? ' ' + options.extraDivClasses : options.extraDivClasses;
	      this._setIconStyles(div, 'icon');
	      this._setIconStyles(div, 'icon-' + options.markerColor);
	      return div;
	    }
	  }, {
	    key: 'createShadow',
	    value: function createShadow() {
	      var div = document.createElement('div');
	      this._setIconStyles(div, 'shadow');
	      return div;
	    }
	  }, {
	    key: '_createInner',
	    value: function _createInner() {
	      var i = document.createElement('i');
	      var options = this.options;

	      i.classList.add(options.prefix);
	      if (options.extraClasses) {
	        i.classList.add(options.extraClasses);
	      }
	      if (options.icon.slice(0, options.prefix.length + 1) === options.prefix + '-') {
	        i.classList.add(options.icon);
	      } else {
	        i.classList.add(options.prefix + '-' + options.icon);
	      }
	      if (options.spin && typeof options.spinClass === 'string') {
	        i.classList.add(options.spinClass);
	      }
	      if (options.iconColor) {
	        if (options.iconColor === 'white' || options.iconColor === 'black') {
	          i.classList.add('icon-' + options.iconColor);
	        } else {
	          i.style.color = options.iconColor;
	        }
	      }
	      if (options.iconSize) {
	        i.style.width = options.iconSize[0] + 'px';
	      }
	      return i;
	    }
	  }, {
	    key: '_setIconStyles',
	    value: function _setIconStyles(img, name) {
	      var options = this.options;
	      var size = _leaflet2.default.point(options[name === 'shadow' ? 'shadowSize' : 'iconSize']);
	      var anchor = void 0;

	      if (name === 'shadow') {
	        anchor = _leaflet2.default.point(options.shadowAnchor || options.iconAnchor);
	      } else {
	        anchor = _leaflet2.default.point(options.iconAnchor);
	      }
	      if (!anchor && size) {
	        anchor = size.divideBy(2, true);
	      }
	      img.className = 'vector-marker-' + name + ' ' + options.className;
	      if (anchor) {
	        img.style.marginLeft = -anchor.x + 'px';
	        img.style.marginTop = -anchor.y + 'px';
	      }
	      if (size) {
	        img.style.width = size.x + 'px';
	        img.style.height = size.y + 'px';
	      }
	    }
	  }]);

	  return Icon;
	}(_leaflet2.default.Icon);

	exports.default = Icon;

/***/ }
/******/ ])
});
;<|endoftext|>


<commit_before>var example = require("washington")

var ArrayElement = require("../object-pattern").ArrayElement
var ArrayEllipsis = require("../object-pattern").ArrayEllipsis
var ArrayPattern = require("../object-pattern").ArrayPattern
var ArrayWildcard = require("../object-pattern").ArrayWildcard
var ExactProperty = require("../object-pattern").ExactProperty
var Negator = require("../object-pattern").Negator
var ObjectPattern = require("../object-pattern").ObjectPattern
var TypedValue = require("../object-pattern").TypedValue
var WildcardProperty = require("../object-pattern").WildcardProperty
var WildcardValue = require("../object-pattern").WildcardValue

var Interpreter = function (source) {
  this.pattern = this.object(source)
}

Interpreter.prototype.object = function (source) {
  var buffer = ""
  var deepness = 0
  var object = new ObjectPattern

  source.split("").forEach(function (character, index) {
    if (character === "," && deepness === 0) {
      object.properties.push(this.property(buffer))
      buffer = ""
    }

    else
      buffer += character

    if (character === "(") deepness ++
    if (character === ")") {
      deepness --
      if (deepness === 0) {
        object.properties.push(this.property(buffer))
        buffer = ""
      }
    }

    if (index + 1 === source.length)
      object.properties.push(this.property(buffer))
  }.bind(this))

  return object
}

Interpreter.prototype.property = function (source) {
  var buffer        = ""
  var deepness      = 0
  var propertyName  = source.substring(0, source.indexOf(":"))
  var propertyValue = this.value(source.substring(source.indexOf(":") + 1))

  if (propertyName === "*")
    return new WildcardProperty(propertyValue)

  else if (propertyName.substring(0, 1) === "!")
    return new Negator( propertyName.substring(1) === "*" ?
      new WildcardProperty(propertyValue) :
      new ExactProperty(
        propertyName.substring(1),
        propertyValue ) )

  else
    return new ExactProperty(propertyName, propertyValue)
}

Interpreter.prototype.value = function (source) {
  if (source === "*")
    return new WildcardValue

  if (source.substring(0, 1) === "<" &&
      source.substring(source.length - 1, source.length) === ">")
    return new TypedValue(source.substring(1, source.length - 1))

  if (source.substring(0, 1) === "(" &&
      source.substring(source.length - 1, source.length) === ")")
    return this.object(source.substring(1, source.length - 1))

  if (source.substring(0, 1) === "/")
    return this.array(source)

  return source
}

Interpreter.prototype.array = function (source) {
  var pattern = new ArrayPattern
  var termination = false
  var deepness = []
  var buffer = ""
  var list = []

  source.split("").forEach(function (character, index) {
    if (character === "/" && deepness.length === 0) {
      list.push(buffer)
      buffer = ""
    }

    else
      buffer += character

    if (character === "(")
      deepness.push({character: "("})

    if (character === "[")
      deepness.push({character: "["})

    if (character === ")") {
      if (deepness[deepness.length - 1].character === "(")
        deepness.pop()

      if (deepness.length === 0) {
        list.push(buffer)
        buffer = ""
      }
    }

    if (character === "]") {
      if (deepness.length > 0 &&
          deepness[deepness.length - 1].character === "[")
        deepness.pop()

      if (deepness.length === 0) {
        list.push(buffer)
        buffer = ""
      }
    }

    if (index + 1 === source.length)
      list.push(buffer)
  })

  list.forEach(function (chunk, index, list) {
    if (termination)
      termination = false

    else {
      if (chunk === "*")
        pattern.matchables.push(new ArrayWildcard)

      else if (chunk === "**") {
        pattern.matchables.push(new ArrayEllipsis(
          index + 1 < list.length ? list[index + 1] : undefined ))
        termination = true
      }

      else if (chunk.substring(0, 1) === "[" &&
          chunk.substring(chunk.length - 1, chunk.length) === "]")
        pattern.matchables.push(
          new ArrayElement(
            this.array(chunk.substring(1, chunk.length - 1)) ) )

      else if (chunk !== "")
        pattern.matchables.push(chunk)
    }
  }.bind(this))

  return pattern
}

example("Interpreter: '' > OP", function () {
  return new Interpreter("")
    .pattern instanceof ObjectPattern
})

example("Interpreter: 'key:value' > OP[EP]", function () {
  return new Interpreter("key:value")
    .pattern
    .properties[0] instanceof ExactProperty
})

example("Interpreter: 'key:value' > OP[EP[key]]", function () {
  return new Interpreter("key:value")
    .pattern
    .properties[0]
    .name === "key"
})

example("Interpreter: 'key:value' > OP[EP[,value]]", function () {
  return new Interpreter("key:value")
    .pattern
    .properties[0]
    .value === "value"
})

example("Interpreter: '*:value' > OP[WP]", function () {
  return new Interpreter("*:value")
    .pattern
    .properties[0] instanceof WildcardProperty
})

example("Interpreter: '*:value,other:23' > OP[WP,EP]", function () {
  var properties = new Interpreter("*:value,other:23").pattern.properties

  return  properties[0] instanceof WildcardProperty &&
          properties[1] instanceof ExactProperty
})

example("Interpreter: '!prop:value' > OP[N[EP]]", function () {
  return  new Interpreter("!prop:value")
    .pattern
    .properties[0]
    .matchable instanceof ExactProperty
})

example("Interpreter: '!prop:value' > OP[N[EP[prop]]]", function () {
  return  new Interpreter("!prop:value")
    .pattern
    .properties[0]
    .matchable
    .name === "prop"
})

example("Interpreter: '!prop:value' > OP[N[EP[,value]]]", function () {
  return  new Interpreter("!prop:value")
    .pattern
    .properties[0]
    .matchable
    .value === "value"
})

example("Interpreter: '!*:value' > OP[N[WP]]", function () {
  return  new Interpreter("!*:value")
    .pattern
    .properties[0]
    .matchable instanceof WildcardProperty
})

example("Interpreter: '!*:value' > OP[N[WP[value]]]", function () {
  return  new Interpreter("!*:value")
    .pattern
    .properties[0]
    .matchable
    .value === "value"
})

example("Interpreter: 'something:*' > OP[EP[WV]]", function () {
  return  new Interpreter("something:*")
    .pattern
    .properties[0]
    .value instanceof WildcardValue
})

example("Interpreter: 'type:<string>' > OP[EP[TV]]", function () {
  return  new Interpreter("type:<string>")
    .pattern
    .properties[0]
    .value instanceof TypedValue
})

example("Interpreter: 'type:<string>' > OP[EP[TV[string]]]", function () {
  return  new Interpreter("type:<string>")
    .pattern
    .properties[0]
    .value
    .type === "string"
})

example("Interpreter: 'prop:(object:inside)' > OP[EP[OP]]", function () {
  return  new Interpreter("prop:(object:inside)")
    .pattern
    .properties[0]
    .value instanceof ObjectPattern
})

example("Interpreter: 'prop:(object:inside)' > OP[EP[OP[EP]]]", function () {
  return  new Interpreter("prop:(object:inside)")
    .pattern
    .properties[0]
    .value
    .properties[0] instanceof ExactProperty
})

example("Interpreter: 'prop:(object:inside)' > OP[EP[OP[EP[object]]]]", function () {
  return  new Interpreter("prop:(object:inside)")
    .pattern
    .properties[0]
    .value
    .properties[0]
    .name === "object"
})

example("Interpreter: 'prop:(object:inside)' > OP[EP[OP[EP[,inside]]]]", function () {
  return  new Interpreter("prop:(object:inside)")
    .pattern
    .properties[0]
    .value
    .properties[0]
    .value === "inside"
})

example("Interpreter: 'type:/some/array' > OP[EP[AP]]", function () {
  return  new Interpreter("type:/some/array")
    .pattern
    .properties[0]
    .value instanceof ArrayPattern
})

example("Interpreter: 'type:/some/array' > OP[EP[AP[some]]]", function () {
  return  new Interpreter("type:/some/array")
    .pattern
    .properties[0]
    .value
    .matchables[0] === "some"
})

example("Interpreter: 'type:/some/array' > OP[EP[AP[/array]]]", function () {
  return  new Interpreter("type:/some/array")
    .pattern
    .properties[0]
    .value
    .matchables[1] === "array"
})

example("Interpreter: 'type:/*/array' > OP[EP[AP[AW]]]", function () {
  return  new Interpreter("type:/*/array")
    .pattern
    .properties[0]
    .value
    .matchables[0] instanceof ArrayWildcard
})

example("Interpreter: 'type:/**/array' > OP[EP[AP[AE]]]", function () {
  return  new Interpreter("type:/**/array")
    .pattern
    .properties[0]
    .value
    .matchables[0] instanceof ArrayEllipsis
})

example("Interpreter: 'type:/**/array' > OP[EP[AP[AE[array]]]]", function () {
  return  new Interpreter("type:/**/array")
    .pattern
    .properties[0]
    .value
    .matchables[0]
    .termination === "array"
})

example("Interpreter: 'type:/**' > OP[EP[AP[AE[undefined]]]]", function () {
  return  new Interpreter("type:/**")
    .pattern
    .properties[0]
    .value
    .matchables[0]
    .termination === undefined
})

example("Interpreter: 'type:/*/**/a/b' > OP[EP[AP[AW]]", function () {
  return  new Interpreter("type:/*/**/a/b")
    .pattern
    .properties[0]
    .value
    .matchables[0] instanceof ArrayWildcard
})

example("Interpreter: 'type:/*/**/a/b' > OP[EP[AP[,AE]]", function () {
  return  new Interpreter("type:/*/**/a/b")
    .pattern
    .properties[0]
    .value
    .matchables[1] instanceof ArrayEllipsis
})

example("Interpreter: 'type:/*/**/a/b' > OP[EP[AP[,AE[a]]]", function () {
  return  new Interpreter("type:/*/**/a/b")
    .pattern
    .properties[0]
    .value
    .matchables[1]
    .termination === "a"
})

example("Interpreter: 'type:/*/**/a/b' > OP[EP[AP[,,b]", function () {
  return  new Interpreter("type:/*/**/a/b")
    .pattern
    .properties[0]
    .value
    .matchables[2] === "b"
})

example("Interpreter: 'a:/[/sub/array]/b' > OP[EP[AP[AE]]]", function () {
  return  new Interpreter("a:/[/sub/array]/b")
    .pattern
    .properties[0]
    .value
    .matchables[0] instanceof ArrayElement
})

example("Interpreter: 'a:/[/sub/array]/b' > OP[EP[AP[AE[AP]]]]", function () {
  return  new Interpreter("a:/[/sub/array]/b")
    .pattern
    .properties[0]
    .value
    .matchables[0]
    .matchable instanceof ArrayPattern
})

example("Interpreter: 'a:/[/sub/array]/b' > OP[EP[AP[AE[AP[sub]]]]]", function () {
  return  new Interpreter("a:/[/sub/array]/b")
    .pattern
    .properties[0]
    .value
    .matchables[0]
    .matchable
    .matchables[0] === "sub"
})

example("Interpreter: 'a:/[/sub/array]/b' > OP[EP[AP[AE[AP[,array]]]]]", function () {
  return  new Interpreter("a:/[/sub/array]/b")
    .pattern
    .properties[0]
    .value
    .matchables[0]
    .matchable
    .matchables[1] === "array"
})

example("Interpreter: 'a:/[/sub/[/sub]/array]/b' > OP[EP[AP[AE[AP[,AE]]]]]", function () {
  return  new Interpreter("a:/[/sub/[/sub]/array]/b")
    .pattern
    .properties[0]
    .value
    .matchables[0]
    .matchable
    .matchables[1] instanceof ArrayElement
})

example("Interpreter: 'a:/(sub:object)/b' > OP[EP[AP[AE]]]")

example("Interpreter: 'a:/(sub:object)/b' > OP[EP[AP[AE[OP]]]]")

example("Interpreter: 'a:/(sub:object)/b' > OP[EP[AP[AE[OP[EP]]]]]")

example("Interpreter: 'a:/(sub:object)/b' > OP[EP[AP[AE[OP[EP[sub]]]]]]")

example("Interpreter: 'a:/(sub:object)/b' > OP[EP[AP[AE[OP[EP[,object]]]]]]")

example("Interpreter: 'a:true' > OP[EP[,true]]")

example("Interpreter: 'a:24' > OP[EP[,24]]")

example("Interpreter: 'a:\"true\"' > OP[EP[,\"true\"]]")

example("Interpreter: 'a:\"/true/(a:b)\"' > OP[EP[,\"/true/(a:b)\"]]")
<commit_msg>Support ObjectPattern inside ArrayPatterns<commit_after>var example = require("washington")

var ArrayElement = require("../object-pattern").ArrayElement
var ArrayEllipsis = require("../object-pattern").ArrayEllipsis
var ArrayPattern = require("../object-pattern").ArrayPattern
var ArrayWildcard = require("../object-pattern").ArrayWildcard
var ExactProperty = require("../object-pattern").ExactProperty
var Negator = require("../object-pattern").Negator
var ObjectPattern = require("../object-pattern").ObjectPattern
var TypedValue = require("../object-pattern").TypedValue
var WildcardProperty = require("../object-pattern").WildcardProperty
var WildcardValue = require("../object-pattern").WildcardValue

var Interpreter = function (source) {
  this.pattern = this.object(source)
}

Interpreter.prototype.object = function (source) {
  var buffer = ""
  var deepness = 0
  var object = new ObjectPattern

  source.split("").forEach(function (character, index) {
    if (character === "," && deepness === 0) {
      object.properties.push(this.property(buffer))
      buffer = ""
    }

    else
      buffer += character

    if (character === "(") deepness ++
    if (character === ")") {
      deepness --
      if (deepness === 0) {
        object.properties.push(this.property(buffer))
        buffer = ""
      }
    }

    if (index + 1 === source.length)
      object.properties.push(this.property(buffer))
  }.bind(this))

  return object
}

Interpreter.prototype.property = function (source) {
  var buffer        = ""
  var deepness      = 0
  var propertyName  = source.substring(0, source.indexOf(":"))
  var propertyValue = this.value(source.substring(source.indexOf(":") + 1))

  if (propertyName === "*")
    return new WildcardProperty(propertyValue)

  else if (propertyName.substring(0, 1) === "!")
    return new Negator( propertyName.substring(1) === "*" ?
      new WildcardProperty(propertyValue) :
      new ExactProperty(
        propertyName.substring(1),
        propertyValue ) )

  else
    return new ExactProperty(propertyName, propertyValue)
}

Interpreter.prototype.value = function (source) {
  if (source === "*")
    return new WildcardValue

  if (source.substring(0, 1) === "<" &&
      source.substring(source.length - 1, source.length) === ">")
    return new TypedValue(source.substring(1, source.length - 1))

  if (source.substring(0, 1) === "(" &&
      source.substring(source.length - 1, source.length) === ")")
    return this.object(source.substring(1, source.length - 1))

  if (source.substring(0, 1) === "/")
    return this.array(source)

  return source
}

Interpreter.prototype.array = function (source) {
  var pattern = new ArrayPattern
  var termination = false
  var deepness = []
  var buffer = ""
  var list = []

  source.split("").forEach(function (character, index) {
    if (character === "/" && deepness.length === 0) {
      list.push(buffer)
      buffer = ""
    }

    else
      buffer += character

    if (character === "(")
      deepness.push({character: "("})

    if (character === "[")
      deepness.push({character: "["})

    if (character === ")") {
      if (deepness[deepness.length - 1].character === "(")
        deepness.pop()

      if (deepness.length === 0) {
        list.push(buffer)
        buffer = ""
      }
    }

    if (character === "]") {
      if (deepness.length > 0 &&
          deepness[deepness.length - 1].character === "[")
        deepness.pop()

      if (deepness.length === 0) {
        list.push(buffer)
        buffer = ""
      }
    }

    if (index + 1 === source.length)
      list.push(buffer)
  })

  list.forEach(function (chunk, index, list) {
    if (termination)
      termination = false

    else {
      if (chunk === "*")
        pattern.matchables.push(new ArrayWildcard)

      else if (chunk === "**") {
        pattern.matchables.push(new ArrayEllipsis(
          index + 1 < list.length ? list[index + 1] : undefined ))
        termination = true
      }

      else if (chunk.substring(0, 1) === "[" &&
          chunk.substring(chunk.length - 1, chunk.length) === "]")
        pattern.matchables.push(
          new ArrayElement(
            this.array(chunk.substring(1, chunk.length - 1)) ) )

      else if (chunk.substring(0, 1) === "(" &&
          chunk.substring(chunk.length - 1, chunk.length) === ")")
        pattern.matchables.push(
          new ArrayElement(
            this.object(chunk.substring(1, chunk.length - 1)) ) )

      else if (chunk !== "")
        pattern.matchables.push(chunk)
    }
  }.bind(this))

  return pattern
}

example("Interpreter: '' > OP", function () {
  return new Interpreter("")
    .pattern instanceof ObjectPattern
})

example("Interpreter: 'key:value' > OP[EP]", function () {
  return new Interpreter("key:value")
    .pattern
    .properties[0] instanceof ExactProperty
})

example("Interpreter: 'key:value' > OP[EP[key]]", function () {
  return new Interpreter("key:value")
    .pattern
    .properties[0]
    .name === "key"
})

example("Interpreter: 'key:value' > OP[EP[,value]]", function () {
  return new Interpreter("key:value")
    .pattern
    .properties[0]
    .value === "value"
})

example("Interpreter: '*:value' > OP[WP]", function () {
  return new Interpreter("*:value")
    .pattern
    .properties[0] instanceof WildcardProperty
})

example("Interpreter: '*:value,other:23' > OP[WP,EP]", function () {
  var properties = new Interpreter("*:value,other:23").pattern.properties

  return  properties[0] instanceof WildcardProperty &&
          properties[1] instanceof ExactProperty
})

example("Interpreter: '!prop:value' > OP[N[EP]]", function () {
  return  new Interpreter("!prop:value")
    .pattern
    .properties[0]
    .matchable instanceof ExactProperty
})

example("Interpreter: '!prop:value' > OP[N[EP[prop]]]", function () {
  return  new Interpreter("!prop:value")
    .pattern
    .properties[0]
    .matchable
    .name === "prop"
})

example("Interpreter: '!prop:value' > OP[N[EP[,value]]]", function () {
  return  new Interpreter("!prop:value")
    .pattern
    .properties[0]
    .matchable
    .value === "value"
})

example("Interpreter: '!*:value' > OP[N[WP]]", function () {
  return  new Interpreter("!*:value")
    .pattern
    .properties[0]
    .matchable instanceof WildcardProperty
})

example("Interpreter: '!*:value' > OP[N[WP[value]]]", function () {
  return  new Interpreter("!*:value")
    .pattern
    .properties[0]
    .matchable
    .value === "value"
})

example("Interpreter: 'something:*' > OP[EP[WV]]", function () {
  return  new Interpreter("something:*")
    .pattern
    .properties[0]
    .value instanceof WildcardValue
})

example("Interpreter: 'type:<string>' > OP[EP[TV]]", function () {
  return  new Interpreter("type:<string>")
    .pattern
    .properties[0]
    .value instanceof TypedValue
})

example("Interpreter: 'type:<string>' > OP[EP[TV[string]]]", function () {
  return  new Interpreter("type:<string>")
    .pattern
    .properties[0]
    .value
    .type === "string"
})

example("Interpreter: 'prop:(object:inside)' > OP[EP[OP]]", function () {
  return  new Interpreter("prop:(object:inside)")
    .pattern
    .properties[0]
    .value instanceof ObjectPattern
})

example("Interpreter: 'prop:(object:inside)' > OP[EP[OP[EP]]]", function () {
  return  new Interpreter("prop:(object:inside)")
    .pattern
    .properties[0]
    .value
    .properties[0] instanceof ExactProperty
})

example("Interpreter: 'prop:(object:inside)' > OP[EP[OP[EP[object]]]]", function () {
  return  new Interpreter("prop:(object:inside)")
    .pattern
    .properties[0]
    .value
    .properties[0]
    .name === "object"
})

example("Interpreter: 'prop:(object:inside)' > OP[EP[OP[EP[,inside]]]]", function () {
  return  new Interpreter("prop:(object:inside)")
    .pattern
    .properties[0]
    .value
    .properties[0]
    .value === "inside"
})

example("Interpreter: 'type:/some/array' > OP[EP[AP]]", function () {
  return  new Interpreter("type:/some/array")
    .pattern
    .properties[0]
    .value instanceof ArrayPattern
})

example("Interpreter: 'type:/some/array' > OP[EP[AP[some]]]", function () {
  return  new Interpreter("type:/some/array")
    .pattern
    .properties[0]
    .value
    .matchables[0] === "some"
})

example("Interpreter: 'type:/some/array' > OP[EP[AP[/array]]]", function () {
  return  new Interpreter("type:/some/array")
    .pattern
    .properties[0]
    .value
    .matchables[1] === "array"
})

example("Interpreter: 'type:/*/array' > OP[EP[AP[AW]]]", function () {
  return  new Interpreter("type:/*/array")
    .pattern
    .properties[0]
    .value
    .matchables[0] instanceof ArrayWildcard
})

example("Interpreter: 'type:/**/array' > OP[EP[AP[AE]]]", function () {
  return  new Interpreter("type:/**/array")
    .pattern
    .properties[0]
    .value
    .matchables[0] instanceof ArrayEllipsis
})

example("Interpreter: 'type:/**/array' > OP[EP[AP[AE[array]]]]", function () {
  return  new Interpreter("type:/**/array")
    .pattern
    .properties[0]
    .value
    .matchables[0]
    .termination === "array"
})

example("Interpreter: 'type:/**' > OP[EP[AP[AE[undefined]]]]", function () {
  return  new Interpreter("type:/**")
    .pattern
    .properties[0]
    .value
    .matchables[0]
    .termination === undefined
})

example("Interpreter: 'type:/*/**/a/b' > OP[EP[AP[AW]]", function () {
  return  new Interpreter("type:/*/**/a/b")
    .pattern
    .properties[0]
    .value
    .matchables[0] instanceof ArrayWildcard
})

example("Interpreter: 'type:/*/**/a/b' > OP[EP[AP[,AE]]", function () {
  return  new Interpreter("type:/*/**/a/b")
    .pattern
    .properties[0]
    .value
    .matchables[1] instanceof ArrayEllipsis
})

example("Interpreter: 'type:/*/**/a/b' > OP[EP[AP[,AE[a]]]", function () {
  return  new Interpreter("type:/*/**/a/b")
    .pattern
    .properties[0]
    .value
    .matchables[1]
    .termination === "a"
})

example("Interpreter: 'type:/*/**/a/b' > OP[EP[AP[,,b]", function () {
  return  new Interpreter("type:/*/**/a/b")
    .pattern
    .properties[0]
    .value
    .matchables[2] === "b"
})

example("Interpreter: 'a:/[/sub/array]/b' > OP[EP[AP[AE]]]", function () {
  return  new Interpreter("a:/[/sub/array]/b")
    .pattern
    .properties[0]
    .value
    .matchables[0] instanceof ArrayElement
})

example("Interpreter: 'a:/[/sub/array]/b' > OP[EP[AP[AE[AP]]]]", function () {
  return  new Interpreter("a:/[/sub/array]/b")
    .pattern
    .properties[0]
    .value
    .matchables[0]
    .matchable instanceof ArrayPattern
})

example("Interpreter: 'a:/[/sub/array]/b' > OP[EP[AP[AE[AP[sub]]]]]", function () {
  return  new Interpreter("a:/[/sub/array]/b")
    .pattern
    .properties[0]
    .value
    .matchables[0]
    .matchable
    .matchables[0] === "sub"
})

example("Interpreter: 'a:/[/sub/array]/b' > OP[EP[AP[AE[AP[,array]]]]]", function () {
  return  new Interpreter("a:/[/sub/array]/b")
    .pattern
    .properties[0]
    .value
    .matchables[0]
    .matchable
    .matchables[1] === "array"
})

example("Interpreter: 'a:/[/sub/[/sub]/array]/b' > OP[EP[AP[AE[AP[,AE]]]]]", function () {
  return  new Interpreter("a:/[/sub/[/sub]/array]/b")
    .pattern
    .properties[0]
    .value
    .matchables[0]
    .matchable
    .matchables[1] instanceof ArrayElement
})

example("Interpreter: 'a:/(sub:object)/b' > OP[EP[AP[AE]]]", function () {
  return  new Interpreter("a:/(sub:object)/b")
    .pattern
    .properties[0]
    .value
    .matchables[0] instanceof ArrayElement
})

example("Interpreter: 'a:/(sub:object)/b' > OP[EP[AP[AE[OP]]]]", function () {
  return  new Interpreter("a:/(sub:object)/b")
    .pattern
    .properties[0]
    .value
    .matchables[0]
    .matchable instanceof ObjectPattern
})

example("Interpreter: 'a:/(sub:object)/b' > OP[EP[AP[AE[OP[EP]]]]]", function () {
  return  new Interpreter("a:/(sub:object)/b")
    .pattern
    .properties[0]
    .value
    .matchables[0]
    .matchable
    .properties[0] instanceof ExactProperty
})

example("Interpreter: 'a:/(sub:object)/b' > OP[EP[AP[AE[OP[EP[sub]]]]]]", function () {
  return  new Interpreter("a:/(sub:object)/b")
    .pattern
    .properties[0]
    .value
    .matchables[0]
    .matchable
    .properties[0]
    .name === "sub"
})

example("Interpreter: 'a:/(sub:object)/b' > OP[EP[AP[AE[OP[EP[,object]]]]]]", function () {
  return  new Interpreter("a:/(sub:object)/b")
    .pattern
    .properties[0]
    .value
    .matchables[0]
    .matchable
    .properties[0]
    .value === "object"
})

example("Interpreter: 'a:true' > OP[EP[,true]]")

example("Interpreter: 'a:24' > OP[EP[,24]]")

example("Interpreter: 'a:\"true\"' > OP[EP[,\"true\"]]")

example("Interpreter: 'a:\"/true/(a:b)\"' > OP[EP[,\"/true/(a:b)\"]]")
<|endoftext|>


<commit_before>define(["./Constants","./Cube"],
    function(Constants,Cube) {

  var BRIDGE_CALL = {
    nick: "setNick",
    status: "setStatus",
    posX: "setPosX",
    posY: "setPosY",
    posZ: "setPosZ",
    rotX: "setRotX",
    rotY: "setRotY",
    rotZ: "setRotZ",
    rotW: "setRotW",
    dVx: "setDVX",
    dVy: "setDVY",
    dVz: "setDVZ",
    dRx: "setDRX",
    dRY: "setDRY",
    dRz: "setDRZ"
  };

  var CONVERT = {
      posX: true,
      posY: true,
      posZ: true,
      rotX: true,
      rotY: true,
      rotZ: true,
      rotW: true
  };

  var Game = function(field) {
    this.players = {};
    this.field = field;

    this.localPlayerKey = null;

    this.extraInfo = null;
    this.showExtraInfo(true);
  };

  Game.prototype = {

      showExtraInfo: function(show) {
        var newV = this.field.isWebGLinUse() && show;

        if (this.extraInfo != newV) {
          this.forEachPlayer(function(player) {
            player.showStatus(newV);
            player.showNick(newV);
          });
          this.extraInfo = newV;
        }
      },

      setLocalPlayerKey: function(key) {
        this.localPlayerKey = key;
      },

      onItemUpdate: function(itemUpdate) {

        var key = itemUpdate.getValue("key");
        var command = itemUpdate.getValue("command");

        if (command == "DELETE") {
          this.removePlayer(key);
          return;
        }

        if (command == "ADD") {
          this.addPlayer(key);
        }

        this.updatePlayer(key,itemUpdate);
      },

      onUnsubscription: function() {
        var that = this;
        this.forEachPlayer(function(player) {
          that.removePlayer(player.getKey());
        });
      },

      forEachPlayer: function(cb) {
        for (var i in this.players) {
          cb(this.players[i]);
        }
      },

      removePlayer: function(key) {
        if (!this.players[key]) {
          return;
        }
        var player = this.players[key];
        delete(this.players[key]);
        player.clear();
      },
      addPlayer: function(key) {
        if (this.players[key]) {
          return;
        }

        this.players[key] = new Cube(key,key == this.localPlayerKey ? Constants.OWN : Constants.OTHER,this.field,this.extraInfo);
      },
      getPlayer: function(key) {
        return this.players[key];
      },
      updatePlayer: function(key,itemUpdate) {
        var player = this.players[key];
        if (!player) {
          //TODO error?
          return;
        }

        itemUpdate.forEachChangedField(function(name,pos,val) {
          var tc = BRIDGE_CALL[name];
          console.log(tc + " - " + val);
          if (val !== null && tc) {
            if (CONVERT[name]) {
              val = getMyDouble(fromBase64(val));
            }
            player[tc](val);
          }
        });
      }

  };

  return Game;
});<commit_msg>remove forgotten console.log<commit_after>define(["./Constants","./Cube"],
    function(Constants,Cube) {

  var BRIDGE_CALL = {
    nick: "setNick",
    status: "setStatus",
    posX: "setPosX",
    posY: "setPosY",
    posZ: "setPosZ",
    rotX: "setRotX",
    rotY: "setRotY",
    rotZ: "setRotZ",
    rotW: "setRotW",
    dVx: "setDVX",
    dVy: "setDVY",
    dVz: "setDVZ",
    dRx: "setDRX",
    dRY: "setDRY",
    dRz: "setDRZ"
  };

  var CONVERT = {
      posX: true,
      posY: true,
      posZ: true,
      rotX: true,
      rotY: true,
      rotZ: true,
      rotW: true
  };

  var Game = function(field) {
    this.players = {};
    this.field = field;

    this.localPlayerKey = null;

    this.extraInfo = null;
    this.showExtraInfo(true);
  };

  Game.prototype = {

      showExtraInfo: function(show) {
        var newV = this.field.isWebGLinUse() && show;

        if (this.extraInfo != newV) {
          this.forEachPlayer(function(player) {
            player.showStatus(newV);
            player.showNick(newV);
          });
          this.extraInfo = newV;
        }
      },

      setLocalPlayerKey: function(key) {
        this.localPlayerKey = key;
      },

      onItemUpdate: function(itemUpdate) {

        var key = itemUpdate.getValue("key");
        var command = itemUpdate.getValue("command");

        if (command == "DELETE") {
          this.removePlayer(key);
          return;
        }

        if (command == "ADD") {
          this.addPlayer(key);
        }

        this.updatePlayer(key,itemUpdate);
      },

      onUnsubscription: function() {
        var that = this;
        this.forEachPlayer(function(player) {
          that.removePlayer(player.getKey());
        });
      },

      forEachPlayer: function(cb) {
        for (var i in this.players) {
          cb(this.players[i]);
        }
      },

      removePlayer: function(key) {
        if (!this.players[key]) {
          return;
        }
        var player = this.players[key];
        delete(this.players[key]);
        player.clear();
      },
      addPlayer: function(key) {
        if (this.players[key]) {
          return;
        }

        this.players[key] = new Cube(key,key == this.localPlayerKey ? Constants.OWN : Constants.OTHER,this.field,this.extraInfo);
      },
      getPlayer: function(key) {
        return this.players[key];
      },
      updatePlayer: function(key,itemUpdate) {
        var player = this.players[key];
        if (!player) {
          //TODO error?
          return;
        }

        itemUpdate.forEachChangedField(function(name,pos,val) {
          var tc = BRIDGE_CALL[name];
          if (val !== null && tc) {
            if (CONVERT[name]) {
              val = getMyDouble(fromBase64(val));
            }
            player[tc](val);
          }
        });
      }

  };

  return Game;
});<|endoftext|>


<commit_before>import WAE from 'web-auto-extractor';
import browser from 'webextension-polyfill';

import sanitize from './sanitize';

// Mapping of tab id -> recipe id
const TAB_RECIPE_MAP = {};
// Mapping of tab id -> recipe that is not persisted to storage.
const EPHEMERAL_TAB_MAP = {};

// Keys that should have `common` run against them.
const KEYS_TO_CLEAN = [
    'name',
    'author',
    'time',
    'description',
    'ingredients',
    'instructionText',
    'instructionList',
];

browser.pageAction.onClicked.addListener((tab) => {
    const recipe = EPHEMERAL_TAB_MAP[tab.id];

    // We delay storing the recipe until the user actually wants it.
    saveToStorage(recipe).then(recipeId => {
        TAB_RECIPE_MAP[tab.id] = recipeId;

        browser.tabs.update({
            url: `recipe.html?recipeId=${encodeURI(recipeId)}`
        }).catch(e => {
            console.error('FAILED to inject script:', e);
        });
    });
});

// Clean up after ourselves.
browser.tabs.onRemoved.addListener((tabId) => {
    delete EPHEMERAL_TAB_MAP[tabId];
    delete TAB_RECIPE_MAP[tabId];
});

export function normalizeRecipe(tab, recipe) {
    console.log('recipe dirty', recipe);

    // Deprecated, redundant, and still used :(
    if ((recipe['@context'] || '').includes('data-vocabulary.org')) {
        recipe = {
            name: recipe.name,
            ingredients: recipe.ingredient,
            description: recipe.summary,
            recipeInstructions: recipe.instructions,
        };
    }

    const clean = {
        name: recipe.name || 'An untitled recipe',
        description: recipe.description,
        ingredients: recipe.recipeIngredient || recipe.ingredients || [],
        image: sanitize.image(recipe.image),
        author: sanitize.author(recipe.author),
        time: sanitize.time(recipe.totalTime),
        yield: sanitize.yield(recipe.recipeYield),
        url: tab.url,
        original: recipe,
    };

    // instructions isn't in the spec, but is sometimes used anyway.
    const instructions = recipe.recipeInstructions || recipe.instruction || [];

    if (typeof instructions === 'string') {
        const text = sanitize.common(instructions)
            .replace(/^preparation/i, '')
            .replace(/(\w)\.(\w)/g, (_match, w1, w2) => `${w1}.\n${w2}`);

        // Sometimes the text block is actually a list in disguise.
        if (text.startsWith('1.')) {
            clean.instructionList = text.split(/\d+\./);
        } else if (text.includes('\n')) {
            clean.instructionList = text.split(/\r?\n/);
        } else {
            clean.instructionText = text;
        }
    }

    if (Array.isArray(instructions)) {
        clean.instructionList = instructions.map((inst, idx) => {
            // Sometimes the instruction list includes a number
            // prefix, strip that out.
            return inst.replace(/^(\d+)\.?\s*/, (orig, num) => {
                return +num === idx + 1 ? '' : orig;
            });
        });
    }

    // Remove the junk from the strings.
    KEYS_TO_CLEAN.forEach(k => {
        const value = clean[k];

        if (typeof value === 'string') {
            clean[k] = sanitize.common(value);
        } else if (Array.isArray(value)) {
            // Seems relatively common to have blank items in the list
            clean[k] = value
                .map(v => sanitize.common(v))
                .filter(i => i !== '');
        }
    });

    // Try to map ingredients from text to [{quantity, ingredient, unit}]
    clean.ingredients = clean.ingredients.map(i => sanitize.ingredient(i));

    console.log('recipe cleaned:', clean);

    return clean;
}

// TODO: Clean up old recipes after a while.
function saveToStorage(recipe) {
    const cleanName = recipe.name
        .replace(/\s+/g, '-')
        .replace(/[^\w-]/g, '');

    const id = `${Date.now()}-${cleanName}`;

    console.log('Saving recipe as', id);

    return browser.storage.local.set({[id]: recipe}).then(() => id);
}

function setRecipeData(tab, data) {
    const recipe = normalizeRecipe(tab, data);

    EPHEMERAL_TAB_MAP[tab.id] = recipe;

    // Some weird bug in chrome...
    if (typeof chrome !== 'undefined') {
        chrome.pageAction.show(tab.id);
    } else {
        browser.pageAction.show(tab.id);
    }
}

browser.runtime.onMessage.addListener((msg, sender) => {
    let result;

    if (msg.kind === 'try-extract-recipe') {
        const scraper = WAE();

        try {
            const data = scraper.parse(msg.data);

            if (data.jsonld.Recipe) {
                result = data.jsonld.Recipe[0];
            } else if (data.microdata.Recipe) {
                result = data.microdata.Recipe[0];
            } else if (data.rdfa.Recipe) {
                result = data.rdfa.Recipe[0];
            }
        } catch (e) {
            console.error('Failed to parse microdata:', e);
        }

    } else if (msg.kind === 'recipe-detected') {
        result = msg.data;
    } else {
        console.error('Unknown message kind:', msg.kind);
    }

    if (result) {
        setRecipeData(sender.tab, result);
    }
});
<commit_msg>Code golf<commit_after>import WAE from 'web-auto-extractor';
import browser from 'webextension-polyfill';

import sanitize from './sanitize';

// Mapping of tab id -> recipe id
const TAB_RECIPE_MAP = {};
// Mapping of tab id -> recipe that is not persisted to storage.
const EPHEMERAL_TAB_MAP = {};

// Keys that should have `common` run against them.
const KEYS_TO_CLEAN = [
    'name',
    'author',
    'time',
    'description',
    'ingredients',
    'instructionText',
    'instructionList',
];

browser.pageAction.onClicked.addListener((tab) => {
    const recipe = EPHEMERAL_TAB_MAP[tab.id];

    // We delay storing the recipe until the user actually wants it.
    saveToStorage(recipe).then(recipeId => {
        TAB_RECIPE_MAP[tab.id] = recipeId;

        browser.tabs.update({
            url: `recipe.html?recipeId=${encodeURI(recipeId)}`
        }).catch(e => {
            console.error('FAILED to inject script:', e);
        });
    });
});

// Clean up after ourselves.
browser.tabs.onRemoved.addListener((tabId) => {
    delete EPHEMERAL_TAB_MAP[tabId];
    delete TAB_RECIPE_MAP[tabId];
});

export function normalizeRecipe(tab, recipe) {
    console.log('recipe dirty', recipe);

    // Deprecated, redundant, and still used :(
    if ((recipe['@context'] || '').includes('data-vocabulary.org')) {
        recipe = {
            name: recipe.name,
            ingredients: recipe.ingredient,
            description: recipe.summary,
            recipeInstructions: recipe.instructions,
        };
    }

    const clean = {
        name: recipe.name || 'An untitled recipe',
        description: recipe.description,
        ingredients: recipe.recipeIngredient || recipe.ingredients || [],
        image: sanitize.image(recipe.image),
        author: sanitize.author(recipe.author),
        time: sanitize.time(recipe.totalTime),
        yield: sanitize.yield(recipe.recipeYield),
        url: tab.url,
        original: recipe,
    };

    // instructions isn't in the spec, but is sometimes used anyway.
    const instructions = recipe.recipeInstructions || recipe.instruction || [];

    if (typeof instructions === 'string') {
        const text = sanitize.common(instructions)
            .replace(/^preparation/i, '')
            .replace(/(\w)\.(\w)/g, (_match, w1, w2) => `${w1}.\n${w2}`);

        // Sometimes the text block is actually a list in disguise.
        if (text.startsWith('1.')) {
            clean.instructionList = text.split(/\d+\./);
        } else if (text.includes('\n')) {
            clean.instructionList = text.split(/\r?\n/);
        } else {
            clean.instructionText = text;
        }
    }

    if (Array.isArray(instructions)) {
        clean.instructionList = instructions.map((inst, idx) => {
            // Sometimes the instruction list includes a number
            // prefix, strip that out.
            return inst.replace(/^(\d+)\.?\s*/, (orig, num) => {
                return +num === idx + 1 ? '' : orig;
            });
        });
    }

    // Remove the junk from the strings.
    KEYS_TO_CLEAN.forEach(k => {
        const value = clean[k];

        if (typeof value === 'string') {
            clean[k] = sanitize.common(value);
        } else if (Array.isArray(value)) {
            // Seems relatively common to have blank items in the list
            clean[k] = value
                .map(v => sanitize.common(v))
                .filter(i => i !== '');
        }
    });

    // Try to map ingredients from text to [{quantity, ingredient, unit}]
    clean.ingredients = clean.ingredients.map(i => sanitize.ingredient(i));

    console.log('recipe cleaned:', clean);

    return clean;
}

// TODO: Clean up old recipes after a while.
function saveToStorage(recipe) {
    const cleanName = recipe.name
        .replace(/\s+/g, '-')
        .replace(/[^\w-]/g, '');

    const id = `${Date.now()}-${cleanName}`;

    console.log('Saving recipe as', id);

    return browser.storage.local.set({[id]: recipe}).then(() => id);
}

function setRecipeData(tab, data) {
    const recipe = normalizeRecipe(tab, data);

    EPHEMERAL_TAB_MAP[tab.id] = recipe;

    // Some weird bug in chrome...
    if (typeof chrome !== 'undefined') {
        chrome.pageAction.show(tab.id);
    } else {
        browser.pageAction.show(tab.id);
    }
}

browser.runtime.onMessage.addListener((msg, sender) => {
    let result;

    if (msg.kind === 'try-extract-recipe') {
        const scraper = WAE();

        try {
            const data = scraper.parse(msg.data);
            const parsed = (data.jsonld.Recipe || data.microdata.Recipe || data.rdfa.Recipe);

            result = (parsed || [null])[0];
        } catch (e) {
            console.error('Failed to parse microdata:', e);
        }

    } else if (msg.kind === 'recipe-detected') {
        result = msg.data;
    } else {
        console.error('Unknown message kind:', msg.kind);
    }

    if (result) {
        setRecipeData(sender.tab, result);
    }
});
<|endoftext|>