<commit_before>/* eslint no-console: 0 */
'use strict';
let app = require('app'),
  BrowserWindow = require('browser-window'),
  ipc = require('electron').ipcMain,
  Menu = require('menu'),
  WebSocketServer = require('ws').Server,
  wss = new WebSocketServer({ 'port': 1234 }),
  EddystoneBeacon = require('eddystone-beacon'),
  mainWindow = null,
  mdns = require('mdns'),
  mdnsAd = null,
  modeBLE = null,
  modeMDNS = null,
  activeModes = '';

// Quit when all windows are closed.
app.on('window-all-closed', () => {
  app.quit();
});

function setBleUrl(url, ws) {
  return new Promise((resolve, reject) => {
    try {
      EddystoneBeacon.advertiseUrl(url);
      activeModes += 'Bluetooth';
      mainWindow.webContents.send('status', [`${url} ${activeModes}`, 'Broadcasting', true]);
      console.log(`ble broadcasting: ${url}`);
      if (ws) {
        ws.send(`ble broadcasting: ${url}`);
      }
      resolve();
    } catch (e) {
      console.log(`error: ${e}`);
      mainWindow.webContents.send('status', [e.message, 'Error', false]);
      if (ws) {
        ws.send(`error: ${e}`);
      }
      reject();
    }
  });
}

function setMdnsUrl(url, ws) {
  return new Promise((resolve, reject) => {
    try {
      let urlParts = url.split('/'),
        protocol = urlParts[0].replace(':', ''),
        port = protocol === 'https' ? 443 : 80,
        host = urlParts[2],
        path = urlParts.filter((part, i) => {
          return i > 2 ? part : false;
        }).join('/');
      mdnsAd = new mdns.Advertisement(mdns.tcp(protocol), port, {
        'name': url,
        'txtRecord': {
          'path': path
        },
        'host': host,
        'domain': 'local',
        'ip': host
      });
      mdnsAd.start();
      activeModes += 'mDNS';
      mainWindow.webContents.send('status', [`${url} ${activeModes}`, 'Broadcasting', true]);
      console.log(`mdns broadcasting: ${url}`);
      if (ws) {
        ws.send(`mdns broadcasting: ${url}`);
      }
      resolve();
    } catch (e) {
      console.log(`error: ${e}`);
      mainWindow.webContents.send('status', [e.message, 'Error', false]);
      if (ws) {
        ws.send(`error: ${e}`);
      }
      reject();
    }
  });
}

function stopMdns() {
  if (mdnsAd) {
    mdnsAd.stop();
  }
}

function setUrl(url, ws) {
  activeModes = '';
  stopMdns();
  if (modeBLE.checked || modeMDNS.checked) {
    if (modeBLE.checked) {
      setBleUrl(url, ws).then(() => {
        if (modeMDNS.checked) {
          setMdnsUrl(url, ws);
        }
      });
    }
    if (!modeBLE.checked && modeMDNS.checked) {
      setMdnsUrl(url, ws);
    }
  } else {
    mainWindow.webContents.send('status', ['Choose at least one broadcasting mode', 'Error', false]);
  }
}

function toggleMode(item) {
  if (item.checked) {
    mainWindow.webContents.send('mode', [item.id, true]);
  } else {
    mainWindow.webContents.send('mode', [item.id, false]);
  }
}

app.on('ready', () => {
  const menuTemplate = [
    {
      'label': 'Eddystone',
      'submenu': [
        {
          'label': 'Broadcast URL',
          'accelerator': 'Command+B',
          'click': () => {
            mainWindow.webContents.send('enter-url', 'go');
          }
        },
        {
          'label': 'Stop broadcasting',
          'accelerator': 'Command+S',
          'click': () => {
            EddystoneBeacon.stop();
            stopMdns();
            mainWindow.webContents.send('status', ['Use bookmarklet or ⌘ + B to enter', 'Waiting', true]);
          }
        },
        {
          'label': 'Quit',
          'accelerator': 'Command+Q',
          'click': () => { app.quit(); }
        }
      ]
    },
    {
      'label': 'Edit',
      'submenu': [
        { 'label': 'Paste', 'accelerator': 'CmdOrCtrl+V', 'selector': 'paste:' }
      ]
    },
    {
      'label': 'Broadcasting modes',
      'submenu': [
        {
          'label': 'Bluetooth',
          'type': 'checkbox',
          'id': 'mode-ble',
          'checked': true,
          'click': item => {
            toggleMode(item);
          }
        },
        {
          'label': 'mDNS',
          'type': 'checkbox',
          'id': 'mode-mdns',
          'checked': false,
          'click': item => {
            toggleMode(item);
          }
        }
      ]
    }
  ];

  let menu = Menu.buildFromTemplate(menuTemplate);
  Menu.setApplicationMenu(menu);
  modeBLE = menu.items[2].submenu.items[0];
  modeMDNS = menu.items[2].submenu.items[1];

  mainWindow = new BrowserWindow({'width': 600, 'height': 400, 'resizable': false});
  mainWindow.loadURL(`file://${__dirname}/index.html`);
  mainWindow.on('closed', () => {
    mainWindow = null;
  });

  mainWindow.webContents.on('did-finish-load', () => {
    mainWindow.webContents.send('status', ['Use bookmarklet or ⌘ + B to enter', 'Waiting', true]);
  });

  wss.on('connection', ws => {
    ws.on('message', url => {
      console.log(`received: ${url}`);
      ws.send(`received: ${url}`);
      setUrl(url, ws);
    });
  });

  ipc.on('set-url', (event, arg) => {
    setUrl(arg);
  });

  ipc.on('set-mode', (event, arg) => {
    switch (arg) {
    case 'mode-ble':
      modeBLE.checked ? modeBLE.checked = false : modeBLE.checked = true;
      toggleMode(modeBLE);
      break;
    case 'mode-mdns':
      modeMDNS.checked ? modeMDNS.checked = false : modeMDNS.checked = true;
      toggleMode(modeMDNS);
      break;
    default:
      break;
    }
  });
});
<commit_msg>remove note about bookmarklet and add reveal.js<commit_after>/* eslint no-console: 0 */
'use strict';
let app = require('app'),
  BrowserWindow = require('browser-window'),
  ipc = require('electron').ipcMain,
  Menu = require('menu'),
  WebSocketServer = require('ws').Server,
  wss = new WebSocketServer({ 'port': 1234 }),
  EddystoneBeacon = require('eddystone-beacon'),
  mainWindow = null,
  mdns = require('mdns'),
  mdnsAd = null,
  modeBLE = null,
  modeMDNS = null,
  activeModes = '';

// Quit when all windows are closed.
app.on('window-all-closed', () => {
  app.quit();
});

function setBleUrl(url, ws) {
  return new Promise((resolve, reject) => {
    try {
      EddystoneBeacon.advertiseUrl(url);
      activeModes += 'Bluetooth';
      mainWindow.webContents.send('status', [`${url} ${activeModes}`, 'Broadcasting', true]);
      console.log(`ble broadcasting: ${url}`);
      if (ws) {
        ws.send(`ble broadcasting: ${url}`);
      }
      resolve();
    } catch (e) {
      console.log(`error: ${e}`);
      mainWindow.webContents.send('status', [e.message, 'Error', false]);
      if (ws) {
        ws.send(`error: ${e}`);
      }
      reject();
    }
  });
}

function setMdnsUrl(url, ws) {
  return new Promise((resolve, reject) => {
    try {
      let urlParts = url.split('/'),
        protocol = urlParts[0].replace(':', ''),
        port = protocol === 'https' ? 443 : 80,
        host = urlParts[2],
        path = urlParts.filter((part, i) => {
          return i > 2 ? part : false;
        }).join('/');
      mdnsAd = new mdns.Advertisement(mdns.tcp(protocol), port, {
        'name': url,
        'txtRecord': {
          'path': path
        },
        'host': host,
        'domain': 'local',
        'ip': host
      });
      mdnsAd.start();
      activeModes += 'mDNS';
      mainWindow.webContents.send('status', [`${url} ${activeModes}`, 'Broadcasting', true]);
      console.log(`mdns broadcasting: ${url}`);
      if (ws) {
        ws.send(`mdns broadcasting: ${url}`);
      }
      resolve();
    } catch (e) {
      console.log(`error: ${e}`);
      mainWindow.webContents.send('status', [e.message, 'Error', false]);
      if (ws) {
        ws.send(`error: ${e}`);
      }
      reject();
    }
  });
}

function stopMdns() {
  if (mdnsAd) {
    mdnsAd.stop();
  }
}

function setUrl(url, ws) {
  activeModes = '';
  stopMdns();
  if (modeBLE.checked || modeMDNS.checked) {
    if (modeBLE.checked) {
      setBleUrl(url, ws).then(() => {
        if (modeMDNS.checked) {
          setMdnsUrl(url, ws);
        }
      });
    }
    if (!modeBLE.checked && modeMDNS.checked) {
      setMdnsUrl(url, ws);
    }
  } else {
    mainWindow.webContents.send('status', ['Choose at least one broadcasting mode', 'Error', false]);
  }
}

function toggleMode(item) {
  if (item.checked) {
    mainWindow.webContents.send('mode', [item.id, true]);
  } else {
    mainWindow.webContents.send('mode', [item.id, false]);
  }
}

app.on('ready', () => {
  const menuTemplate = [
    {
      'label': 'Eddystone',
      'submenu': [
        {
          'label': 'Broadcast URL',
          'accelerator': 'Command+B',
          'click': () => {
            mainWindow.webContents.send('enter-url', 'go');
          }
        },
        {
          'label': 'Stop broadcasting',
          'accelerator': 'Command+S',
          'click': () => {
            EddystoneBeacon.stop();
            stopMdns();
            mainWindow.webContents.send('status', ['Use reveal.js presentation plugin or ⌘ + B to enter', 'Waiting', true]);
          }
        },
        {
          'label': 'Quit',
          'accelerator': 'Command+Q',
          'click': () => { app.quit(); }
        }
      ]
    },
    {
      'label': 'Edit',
      'submenu': [
        { 'label': 'Paste', 'accelerator': 'CmdOrCtrl+V', 'selector': 'paste:' }
      ]
    },
    {
      'label': 'Broadcasting modes',
      'submenu': [
        {
          'label': 'Bluetooth',
          'type': 'checkbox',
          'id': 'mode-ble',
          'checked': true,
          'click': item => {
            toggleMode(item);
          }
        },
        {
          'label': 'mDNS',
          'type': 'checkbox',
          'id': 'mode-mdns',
          'checked': false,
          'click': item => {
            toggleMode(item);
          }
        }
      ]
    }
  ];

  let menu = Menu.buildFromTemplate(menuTemplate);
  Menu.setApplicationMenu(menu);
  modeBLE = menu.items[2].submenu.items[0];
  modeMDNS = menu.items[2].submenu.items[1];

  mainWindow = new BrowserWindow({'width': 600, 'height': 400, 'resizable': false});
  mainWindow.loadURL(`file://${__dirname}/index.html`);
  mainWindow.on('closed', () => {
    mainWindow = null;
  });

  mainWindow.webContents.on('did-finish-load', () => {
    mainWindow.webContents.send('status', ['Use reveal.js presentation plugin or ⌘ + B to enter', 'Waiting', true]);
  });

  wss.on('connection', ws => {
    ws.on('message', url => {
      console.log(`received: ${url}`);
      ws.send(`received: ${url}`);
      setUrl(url, ws);
    });
  });

  ipc.on('set-url', (event, arg) => {
    setUrl(arg);
  });

  ipc.on('set-mode', (event, arg) => {
    switch (arg) {
    case 'mode-ble':
      modeBLE.checked ? modeBLE.checked = false : modeBLE.checked = true;
      toggleMode(modeBLE);
      break;
    case 'mode-mdns':
      modeMDNS.checked ? modeMDNS.checked = false : modeMDNS.checked = true;
      toggleMode(modeMDNS);
      break;
    default:
      break;
    }
  });
});
<|endoftext|>


<commit_before>define([
    "/jquery.js"
    ], function() {
    var self;

    function init(config) {
        self = this;
        getAppsNames(function(data) {
            buildTable(data);
        });
    }

    return init;
});

function getAppsNames(callback) {
    $.get("@/dev_applications/applications", function(data) {
        callback(data);
    });
}

function buildTable(apps) {
    var appsTable = $("#appsTable");

    // Redeploy button
    var redeployButton = $("<button class='btn btn-primary'>");
    var redeployIcon = $("");
    redeployButton.append(redeployIcon);
    redeployButton.append(" Redeploy");

    // Start button
    var startButton = $("<button class='btn btn-success'>");
    var startIcon = $("");
    startButton.append(startIcon);
    startButton.append(" Start");

    // Edit button
    var editButton = $("<button class='btn btn-warning'>");
    var editIcon = $("");
    editButton.append(editIcon);
    editButton.append(" Edit");

    // Delete button
    var deleteButton = $("<button class='btn btn-danger'>");
    var deleteIcon = $("");
    deleteButton.append(deleteIcon);
    deleteButton.append(" Delete");

    // HTML Table
    var htmlTable = $("
");
    var thead = $("
");
    var tr = $("
");

    var th1 = $("");
    th1.html("Application Name");

    var th2 = $("");
    th2.html("Operations");

    tr.append(th1);
    tr.append(th2);

    thead.append(tr);

    var tbody = $("
");

    for(var i in apps) {
        var row = $("
");

        var col1 = $("");
        col1.html(i + ". " + apps[i].name);

        var col2 = $("");
        col2.append(redeployButton);
        col2.append(startButton);
        col2.append(editButton);
        col2.append(deleteButton);

        row.append(col1);
        row.append(col2);

        tbody.append(row);
    }

    htmlTable.append(tbody);
    appsTable.append(htmlTable);
}
<commit_msg>Changed the jQuery get function into a mono module function.<commit_after>define([
    "/jquery.js"
    ], function() {
    var self;

    function init(config) {
        self = this;
        getAppsNames(function(data) {
            buildTable(data);
        });
    }

    return init;
});

function getAppsNames(callback) {
    self.link("applications", function(data) {
        callback(data);
    });
}

function buildTable(apps) {
    var appsTable = $("#appsTable");

    // Redeploy button
    var redeployButton = $("<button class='btn btn-primary'>");
    var redeployIcon = $("");
    redeployButton.append(redeployIcon);
    redeployButton.append(" Redeploy");

    // Start button
    var startButton = $("<button class='btn btn-success'>");
    var startIcon = $("");
    startButton.append(startIcon);
    startButton.append(" Start");

    // Edit button
    var editButton = $("<button class='btn btn-warning'>");
    var editIcon = $("");
    editButton.append(editIcon);
    editButton.append(" Edit");

    // Delete button
    var deleteButton = $("<button class='btn btn-danger'>");
    var deleteIcon = $("");
    deleteButton.append(deleteIcon);
    deleteButton.append(" Delete");

    // HTML Table
    var htmlTable = $("
");
    var thead = $("
");
    var tr = $("
");

    var th1 = $("");
    th1.html("Application Name");

    var th2 = $("");
    th2.html("Operations");

    tr.append(th1);
    tr.append(th2);

    thead.append(tr);

    var tbody = $("
");

    for(var i in apps) {
        var row = $("
");

        var col1 = $("");
        col1.html(i + ". " + apps[i].name);

        var col2 = $("");
        col2.append(redeployButton);
        col2.append(startButton);
        col2.append(editButton);
        col2.append(deleteButton);

        row.append(col1);
        row.append(col2);

        tbody.append(row);
    }

    htmlTable.append(tbody);
    appsTable.append(htmlTable);
}
<|endoftext|>


<commit_before>const path = require('path');
const CSSSplitWebpackPlugin = require('css-split-webpack-plugin').default;

const isDev = process.env.NODE_ENV === 'development';
const usePreact = process.env.REACT_ENV === 'preact';

module.exports = {
  port: 8001,
  source: {
    components: './components',
    docs: './docs',
    changelog: [
      'CHANGELOG.zh-CN.md',
      'CHANGELOG.en-US.md',
    ],
  },
  theme: './site/theme',
  htmlTemplate: './site/theme/static/template.html',
  themeConfig: {
    categoryOrder: {
      设计原则: 2,
      Principles: 2,
    },
    typeOrder: {
      General: 0,
      Layout: 1,
      Navigation: 2,
      'Data Entry': 3,
      'Data Display': 4,
      Feedback: 5,
      Localization: 6,
      Other: 7,
    },
    docVersions: {
      '0.9.x': 'http://09x.ant.design',
      '0.10.x': 'http://010x.ant.design',
      '0.11.x': 'http://011x.ant.design',
      '0.12.x': 'http://012x.ant.design',
      '1.x': 'http://1x.ant.design',
    },
  },
  filePathMapper(filePath) {
    if (filePath === '/index.html') {
      return ['/index.html', '/index-cn.html'];
    }
    if (filePath.endsWith('/index.html')) {
      return [filePath, filePath.replace(/\/index\.html$/, '-cn/index.html')];
    }
    if (filePath !== '/404.html' && filePath !== '/index-cn.html') {
      return [filePath, filePath.replace(/\.html$/, '-cn.html')];
    }
    return filePath;
  },
  doraConfig: {
    verbose: true,
    plugins: ['dora-plugin-upload'],
  },
  webpackConfig(config) {
    config.resolve.alias = {
      'antd/lib': path.join(process.cwd(), 'components'),
      antd: path.join(process.cwd(), 'index'),
      site: path.join(process.cwd(), 'site'),
      'react-router': 'react-router/umd/ReactRouter',
    };

    config.externals = {
      'react-router-dom': 'ReactRouterDOM',
    };

    if (usePreact) {
      config.resolve.alias = Object.assign({}, config.resolve.alias, {
        react: 'preact-compat',
        'react-dom': 'preact-compat',
        'create-react-class': 'preact-compat/lib/create-react-class',
        'react-router': 'react-router',
      });
    } else {
      config.externals = Object.assign({}, config.externals, {
        react: 'React',
        'react-dom': 'ReactDOM',
      });
    }

    config.babel.plugins.push([
      require.resolve('babel-plugin-transform-runtime'),
      {
        polyfill: false,
        regenerator: true,
      },
    ]);

    config.plugins.push(new CSSSplitWebpackPlugin({ size: 4000 }));

    return config;
  },

  htmlTemplateExtraData: {
    isDev,
    usePreact,
  },
};
<commit_msg>site: fix tnpm run deploy<commit_after>const path = require('path');
const CSSSplitWebpackPlugin = require('css-split-webpack-plugin').default;

const isDev = process.env.NODE_ENV === 'development';
const usePreact = process.env.REACT_ENV === 'preact';

module.exports = {
  port: 8001,
  source: {
    components: './components',
    docs: './docs',
    changelog: [
      'CHANGELOG.zh-CN.md',
      'CHANGELOG.en-US.md',
    ],
  },
  theme: './site/theme',
  htmlTemplate: './site/theme/static/template.html',
  themeConfig: {
    categoryOrder: {
      设计原则: 2,
      Principles: 2,
    },
    typeOrder: {
      General: 0,
      Layout: 1,
      Navigation: 2,
      'Data Entry': 3,
      'Data Display': 4,
      Feedback: 5,
      Localization: 6,
      Other: 7,
    },
    docVersions: {
      '0.9.x': 'http://09x.ant.design',
      '0.10.x': 'http://010x.ant.design',
      '0.11.x': 'http://011x.ant.design',
      '0.12.x': 'http://012x.ant.design',
      '1.x': 'http://1x.ant.design',
    },
  },
  filePathMapper(filePath) {
    if (filePath === '/index.html') {
      return ['/index.html', '/index-cn.html'];
    }
    if (filePath.endsWith('/index.html')) {
      return [filePath, filePath.replace(/\/index\.html$/, '-cn/index.html')];
    }
    if (filePath !== '/404.html' && filePath !== '/index-cn.html') {
      return [filePath, filePath.replace(/\.html$/, '-cn.html')];
    }
    return filePath;
  },
  doraConfig: {
    verbose: true,
    plugins: ['dora-plugin-upload'],
  },
  webpackConfig(config) {
    config.resolve.alias = {
      'antd/lib': path.join(process.cwd(), 'components'),
      antd: path.join(process.cwd(), 'index'),
      site: path.join(process.cwd(), 'site'),
      'react-router': 'react-router/umd/ReactRouter',
    };

    config.externals = {
      'react-router-dom': 'ReactRouterDOM',
    };

    if (usePreact) {
      config.resolve.alias = Object.assign({}, config.resolve.alias, {
        react: 'preact-compat',
        'react-dom': 'preact-compat',
        'create-react-class': 'preact-compat/lib/create-react-class',
        'react-router': 'react-router',
      });
    } else if (isDev) {
      config.externals = Object.assign({}, config.externals, {
        react: 'React',
        'react-dom': 'ReactDOM',
      });
    }

    config.babel.plugins.push([
      require.resolve('babel-plugin-transform-runtime'),
      {
        polyfill: false,
        regenerator: true,
      },
    ]);

    config.plugins.push(new CSSSplitWebpackPlugin({ size: 4000 }));

    return config;
  },

  htmlTemplateExtraData: {
    isDev,
    usePreact,
  },
};
<|endoftext|>


<commit_before>/**
# Object Registry

Bindinator is built around the idea of registering objects under unique names
and binding events and element properties to paths based on those names.

b8r's registry is an observable object that b8r uses to keep track of objects.
Once an object is registered, its properties will automatically be bound
to events and DOM properties by path.

    set('root', object_value); // registers the object with the name
    set('root.path.to.value', new_value); // sets the value

You can set the registry's properties by path. Root level properties must
themselves be objects.

    get('root.path.to.value'); // gets the value

You can get a property by path.

Two convenience methods are provided for working with JSON data:

    getJSON('path.to.value' [, element]);
    setJSON('path.to.value', json_string);

Note that unlike set, setJSON does not accept an optional element argument.

    call('root.path.to.method', ...args); // returns value as appropriate

You can call a method by path.

    touch(path [, source_element]);

Triggers all observers as though the value at path has changed. Useful
if you change a property independently of the registry.

    async_touch(path);

Triggers all observers asynchronousely (on requestAnimationFrame).

    isValidPath(path);

`isValidPath` returns true if the path looks OK, false otherwise.

~~~~
Test(() => b8r.isValidPath('foo')).shouldBe(true);
Test(() => b8r.isValidPath('foo.bar')).shouldBe(true);
Test(() => b8r.isValidPath('.')).shouldBe(true);
Test(() => b8r.isValidPath('airtime-rooms[1234]')).shouldBe(true);
Test(() => b8r.isValidPath('airtime-rooms[id=1234]')).shouldBe(true);
Test(() => b8r.isValidPath('airtime-rooms[id=1234].')).shouldBe(true);
Test(() => b8r.isValidPath('airtime-rooms[id=1234')).shouldBe(false);
Test(() => b8r.isValidPath('airtime-rooms[id]')).shouldBe(false);
Test(() => b8r.isValidPath('airtime-rooms[id=1234]]')).shouldBe(false);
Test(() => b8r.isValidPath('airtime-rooms]')).shouldBe(false);
~~~~

*/
/* jshint latedef:false */
/* global module, require, console */
'use strict';

const {getByPath, setByPath, deleteByPath} = require('./b8r.byPath.js');
const {forEachKey} = require('./b8r.iterators.js');
const {getDataPath, getComponentInstancePath} = require('./b8r.bindings.js');
const {logStart, logEnd} = require('./b8r.perf.js');
const registry = {};
let listeners = [];  // { path_string_or_test, callback }

const valid_path = /^(\.|[^.\[\]])+(\.[^.\[\]]+|\[\d+\]|\[[^=\[\]]+\=[^\[\]]+\])*(\.)?$/;

const isValidPath = path => valid_path.test(path);

class Listener {
  constructor(test, callback) {
    if (typeof test === 'string') {
      this.test = t =>
          t.length >= test.length && test === t.substr(0, test.length);
    } else if (test instanceof RegExp) {
      this.test = test.test.bind(test);
    } else if (test instanceof Function) {
      this.test = test;
    } else {
      throw 'expect listener test to be a string, RegExp, or test function';
  }
    if (typeof callback === 'string') {
      this.callback = (...args) => {
        if (get(callback)) {
          call(callback, ...args);
        } else {
          unobserve(this);
        }
      };
    } else if (typeof callback === 'function') {
      this.callback = callback;
    } else {
      throw 'expect callback to be a path or function';
    }
    listeners.push(this);
  }
}

const resolvePath = (path, element) => {
  if (path[0] === '.') {
    if (!element) {
      throw 'cannot evaluate relative path without element';
    }
    path = getDataPath(element) + path;
  } else if (path.substr(0, 6) === '_data_') {
    if (!element) {
      throw 'cannot evaluate _data_ path without element';
    }
    path = getDataPath(element) + path.substr(6);
  } else if (path.substr() === '_component_') {
    if (!element) {
      throw 'cannot evaluate _component_ path without element';
    }
    path = getComponentInstancePath(element) + path;
  }
  return path;
};

const get = (path, element) => {
  path = resolvePath(path, element);
  return getByPath(registry, path);
};

const getJSON = (path, element) => JSON.stringify(get(path, element));

const touch = (path, source_element) => {
  logStart('touch', path);
  listeners.filter(listener => listener.test(path))
      .forEach(listener => listener.callback(path, source_element));
  logEnd('touch', path);
};

const _async_touch_dirty_list = [];
let _async_touch_id = null;

const _async_touch = () => {
  _async_touch_dirty_list.forEach(touch);
  _async_touch_dirty_list.splice(0);
};

const async_touch = path => {
  if (_async_touch_dirty_list.indexOf(path) === -1) {
    _async_touch_dirty_list.push(path);
  }
  if (!_async_touch_id) {
    _async_touch_id = requestAnimationFrame(_async_touch);
  }
};

const set = (path, value, source_element) => {
  const path_parts = path.split(/\.|\[/);
  const model = path_parts[0];
  const existing = getByPath(registry, path);
  if (path_parts.length > 1 && !registry[model]) {
    console.error(`cannot set ${path} to ${value}, ${model} does not exist`);
  } else if (path_parts.length === 1 && typeof value !== 'object') {
    throw 'cannot set ${path}; you can only register objects at root-level';
  } else if (value === existing) {
    // nothing to see here, move along
  } else if (value && value.constructor) {
    if (path_parts.length === 1 && ! registry[path]) {
      register(path, value);
    } else {
      // we only drill down into vanilla objects
      // not arrays or instances of custom classes
      if (value.constructor === Object && existing && existing.constructor === Object) {
        forEachKey(value, (val, key) => set(`${path}.${key}`, val));
      } else {
        setByPath(registry, path, value);
      }
      touch(path, source_element);
    }
  } else {
    setByPath(registry, path, value);
    touch(path, source_element);
  }
  return value;
};

const _register = (name, obj) => {
  registry[name] = obj;
}

const register = (name, obj, block_updates) => {
  if (name.match(/^_[^_]*_$/)) {
    throw 'cannot register object as ' + name +
      ', all names starting and ending with a single \'_\' are reserved.';
  }

  _register(name, obj, block_updates);

  if (!block_updates) {
    touch(name);
    require.lazy('./b8r.events.js').then(({play_saved_messages}) => play_saved_messages(name));
  }
};

const setJSON = (path, value) => set(path, JSON.parse(value));

const push = (path, value) => {
  const list = get(path) || set(path, []);
  if(Array.isArray(list)) {
    list.push(value);
    async_touch(path);
  }
};

const call = (path, ...args) => {
  const method = get(path);
  if (method instanceof Function) {
    return method(...args);
  } else {
    console.error(`cannot call ${path}; not a method`);
  }
};

/**
    observe('root.path.to', callback); // returns a Listener instance

You can observe a path (string). The callback will fire whenever any path
matching or starting
with the string changes. The callback will be passed the exact path that
changed.

    observe(/root.path.[^\.]+.value/, callback);

Instead of a constant path, you can pass a RegExp which will fire the callback
when a path
matching the test changes. The callback will be passed the exact path that
changed.

    observe(path => path.split('.').length === 1, callback);

Finally you can observe a path test function.

    const listener = observe(test, callback);

The `callback` can be a function or a path. If a path, the listener will
automatically be removed if the path is no longer registered (so, for example,
you can hook up a component method as a listener and it will be
'garbage collected' with the compoent.

You can remove a listener (if you kept the reference handy).

    unobserve(listener);

You can remove a listener by test, but it will remove _all_ listeners which use
that test.

~~~~
b8r.register('listener_test1', {
  flag_changed: () => {
    console.log('flag changed');
    b8r.set('listener_test2.counter', b8r.get('listener_test2.counter') + 1);
  }
});
b8r.register('listener_test2', {counter: 0, flag: false});
b8r.observe('listener_test2.flag', 'listener_test1.flag_changed');
b8r.set('listener_test2.flag', true);
Test(() => b8r.get('listener_test2.counter'), 'observer counted flag set to true').shouldBe(1);
b8r.set('listener_test2.flag', false);
Test(() => b8r.get('listener_test2.counter'), 'observer counted flag set to false').shouldBe(2);
b8r.set('listener_test2.flag', false);
Test(() => b8r.get('listener_test2.counter'), 'observer ignored flag set to false').shouldBe(2);
b8r.set('listener_test2.flag', true);
Test(() => b8r.get('listener_test2.counter'), 'observer counted flag set to true').shouldBe(3);
b8r.remove('listener_test1');
b8r.set('listener_test2.flag', false);
Test(() => b8r.get('listener_test2.counter'), 'observer automatically removed').shouldBe(3);
~~~~
*/

const observe = (test, callback) => {
  return new Listener(test, callback);
};

const unobserve = test => {
  let index;
  let found = false;
  if (test instanceof Listener) {
    index = listeners.indexOf(test);
    if (index > -1) {
      listeners.splice(index, 1);
    } else {
      console.error('unobserve failed, listener not found');
    }
  } else {
    for (let i = listeners.length - 1; i >= 0; i--) {
      if (listeners[i].test === test) {
        listeners.splice(i, 1);
        found = true;
      }
    }
  }
  return found;
};

/**
    registered('root-name'); // => true | false

You can get a list of root level objects:

    models();

You can obtain a value using a path.
*/

const models = () => Object.keys(registry);

const registered = path => !!registry[path.split('.')[0]];

/**
    remove('root');
    remove('path.to.property')

Will remove the specified property from the registry (including root-level objects). If the object
does not exist, has no effect. So:

~~~~
const {register, remove, get} = b8r;
register('foo', {bar: 17, baz: {lurman: true}});
Test(() => {remove('foo.bar'); return get('foo.bar');}).shouldBe(null);
Test(() => {remove('foo.boris.yeltsin'); return get('foo.boris')}).shouldBe(null);
Test(() => {remove('foo.baz.lurman'); return Object.keys(get('foo.baz')).length}).shouldBe(0);
~~~~
*/
const remove = path => deleteByPath(registry, path);

module.exports = {
  get,
  getJSON,
  set,
  setJSON,
  push,
  call,
  touch,
  async_touch,
  observe,
  unobserve,
  models,
  _register,
  register,
  registered,
  remove,
  resolvePath,
  isValidPath,
};
<commit_msg>fix — forEachKey doesn't work for set since set returns the value and forEachKey breaks on explicit false return<commit_after>/**
# Object Registry

Bindinator is built around the idea of registering objects under unique names
and binding events and element properties to paths based on those names.

b8r's registry is an observable object that b8r uses to keep track of objects.
Once an object is registered, its properties will automatically be bound
to events and DOM properties by path.

    set('root', object_value); // registers the object with the name
    set('root.path.to.value', new_value); // sets the value

You can set the registry's properties by path. Root level properties must
themselves be objects.

    get('root.path.to.value'); // gets the value

You can get a property by path.

Two convenience methods are provided for working with JSON data:

    getJSON('path.to.value' [, element]);
    setJSON('path.to.value', json_string);

Note that unlike set, setJSON does not accept an optional element argument.

    call('root.path.to.method', ...args); // returns value as appropriate

You can call a method by path.

    touch(path [, source_element]);

Triggers all observers as though the value at path has changed. Useful
if you change a property independently of the registry.

    async_touch(path);

Triggers all observers asynchronousely (on requestAnimationFrame).

    isValidPath(path);

`isValidPath` returns true if the path looks OK, false otherwise.

~~~~
Test(() => b8r.isValidPath('foo')).shouldBe(true);
Test(() => b8r.isValidPath('foo.bar')).shouldBe(true);
Test(() => b8r.isValidPath('.')).shouldBe(true);
Test(() => b8r.isValidPath('airtime-rooms[1234]')).shouldBe(true);
Test(() => b8r.isValidPath('airtime-rooms[id=1234]')).shouldBe(true);
Test(() => b8r.isValidPath('airtime-rooms[id=1234].')).shouldBe(true);
Test(() => b8r.isValidPath('airtime-rooms[id=1234')).shouldBe(false);
Test(() => b8r.isValidPath('airtime-rooms[id]')).shouldBe(false);
Test(() => b8r.isValidPath('airtime-rooms[id=1234]]')).shouldBe(false);
Test(() => b8r.isValidPath('airtime-rooms]')).shouldBe(false);
~~~~

*/
/* jshint latedef:false */
/* global module, require, console */
'use strict';

const {getByPath, setByPath, deleteByPath} = require('./b8r.byPath.js');
const {getDataPath, getComponentInstancePath} = require('./b8r.bindings.js');
const {logStart, logEnd} = require('./b8r.perf.js');
const registry = {};
let listeners = [];  // { path_string_or_test, callback }

const valid_path = /^(\.|[^.\[\]])+(\.[^.\[\]]+|\[\d+\]|\[[^=\[\]]+\=[^\[\]]+\])*(\.)?$/;

const isValidPath = path => valid_path.test(path);

class Listener {
  constructor(test, callback) {
    if (typeof test === 'string') {
      this.test = t =>
          t.length >= test.length && test === t.substr(0, test.length);
    } else if (test instanceof RegExp) {
      this.test = test.test.bind(test);
    } else if (test instanceof Function) {
      this.test = test;
    } else {
      throw 'expect listener test to be a string, RegExp, or test function';
  }
    if (typeof callback === 'string') {
      this.callback = (...args) => {
        if (get(callback)) {
          call(callback, ...args);
        } else {
          unobserve(this);
        }
      };
    } else if (typeof callback === 'function') {
      this.callback = callback;
    } else {
      throw 'expect callback to be a path or function';
    }
    listeners.push(this);
  }
}

const resolvePath = (path, element) => {
  if (path[0] === '.') {
    if (!element) {
      throw 'cannot evaluate relative path without element';
    }
    path = getDataPath(element) + path;
  } else if (path.substr(0, 6) === '_data_') {
    if (!element) {
      throw 'cannot evaluate _data_ path without element';
    }
    path = getDataPath(element) + path.substr(6);
  } else if (path.substr() === '_component_') {
    if (!element) {
      throw 'cannot evaluate _component_ path without element';
    }
    path = getComponentInstancePath(element) + path;
  }
  return path;
};

const get = (path, element) => {
  path = resolvePath(path, element);
  return getByPath(registry, path);
};

const getJSON = (path, element) => JSON.stringify(get(path, element));

const touch = (path, source_element) => {
  logStart('touch', path);
  listeners.filter(listener => listener.test(path))
      .forEach(listener => listener.callback(path, source_element));
  logEnd('touch', path);
};

const _async_touch_dirty_list = [];
let _async_touch_id = null;

const _async_touch = () => {
  _async_touch_dirty_list.forEach(touch);
  _async_touch_dirty_list.splice(0);
};

const async_touch = path => {
  if (_async_touch_dirty_list.indexOf(path) === -1) {
    _async_touch_dirty_list.push(path);
  }
  if (!_async_touch_id) {
    _async_touch_id = requestAnimationFrame(_async_touch);
  }
};

const set = (path, value, source_element) => {
  const path_parts = path.split(/\.|\[/);
  const model = path_parts[0];
  const existing = getByPath(registry, path);
  if (path_parts.length > 1 && !registry[model]) {
    console.error(`cannot set ${path} to ${value}, ${model} does not exist`);
  } else if (path_parts.length === 1 && typeof value !== 'object') {
    throw 'cannot set ${path}; you can only register objects at root-level';
  } else if (value === existing) {
    // nothing to see here, move along
  } else if (value && value.constructor) {
    if (path_parts.length === 1 && ! registry[path]) {
      register(path, value);
    } else {
      // we only drill down into vanilla objects
      // not arrays or instances of custom classes
      if (value.constructor === Object && existing && existing.constructor === Object) {
        // using for vs. forEachKey because set will abort loop if setting something to false
        for (let i = 0, keys = Object.keys(value); i < keys.length; i++) {
          set(`${path}.${keys[i]}`, value[keys[i]]);
        }
      } else {
        setByPath(registry, path, value);
      }
      touch(path, source_element);
    }
  } else {
    setByPath(registry, path, value);
    touch(path, source_element);
  }
  return value; // convenient for things push (see below) but maybe an anti-feature?!
};

const _register = (name, obj) => {
  registry[name] = obj;
};

const register = (name, obj, block_updates) => {
  if (name.match(/^_[^_]*_$/)) {
    throw 'cannot register object as ' + name +
      ', all names starting and ending with a single \'_\' are reserved.';
  }

  _register(name, obj, block_updates);

  if (!block_updates) {
    touch(name);
    require.lazy('./b8r.events.js').then(({play_saved_messages}) => play_saved_messages(name));
  }
};

const setJSON = (path, value) => set(path, JSON.parse(value));

const push = (path, value) => {
  const list = get(path) || set(path, []);
  if(Array.isArray(list)) {
    list.push(value);
    async_touch(path);
  }
};

const call = (path, ...args) => {
  const method = get(path);
  if (method instanceof Function) {
    return method(...args);
  } else {
    console.error(`cannot call ${path}; not a method`);
  }
};

/**
    observe('root.path.to', callback); // returns a Listener instance

You can observe a path (string). The callback will fire whenever any path
matching or starting
with the string changes. The callback will be passed the exact path that
changed.

    observe(/root.path.[^\.]+.value/, callback);

Instead of a constant path, you can pass a RegExp which will fire the callback
when a path
matching the test changes. The callback will be passed the exact path that
changed.

    observe(path => path.split('.').length === 1, callback);

Finally you can observe a path test function.

    const listener = observe(test, callback);

The `callback` can be a function or a path. If a path, the listener will
automatically be removed if the path is no longer registered (so, for example,
you can hook up a component method as a listener and it will be
'garbage collected' with the compoent.

You can remove a listener (if you kept the reference handy).

    unobserve(listener);

You can remove a listener by test, but it will remove _all_ listeners which use
that test.

~~~~
b8r.register('listener_test1', {
  flag_changed: () => {
    console.log('flag changed');
    b8r.set('listener_test2.counter', b8r.get('listener_test2.counter') + 1);
  }
});
b8r.register('listener_test2', {counter: 0, flag: false});
b8r.observe('listener_test2.flag', 'listener_test1.flag_changed');
b8r.set('listener_test2.flag', true);
Test(() => b8r.get('listener_test2.counter'), 'observer counted flag set to true').shouldBe(1);
b8r.set('listener_test2.flag', false);
Test(() => b8r.get('listener_test2.counter'), 'observer counted flag set to false').shouldBe(2);
b8r.set('listener_test2.flag', false);
Test(() => b8r.get('listener_test2.counter'), 'observer ignored flag set to false').shouldBe(2);
b8r.set('listener_test2.flag', true);
Test(() => b8r.get('listener_test2.counter'), 'observer counted flag set to true').shouldBe(3);
b8r.remove('listener_test1');
b8r.set('listener_test2.flag', false);
Test(() => b8r.get('listener_test2.counter'), 'observer automatically removed').shouldBe(3);
~~~~
*/

const observe = (test, callback) => {
  return new Listener(test, callback);
};

const unobserve = test => {
  let index;
  let found = false;
  if (test instanceof Listener) {
    index = listeners.indexOf(test);
    if (index > -1) {
      listeners.splice(index, 1);
    } else {
      console.error('unobserve failed, listener not found');
    }
  } else {
    for (let i = listeners.length - 1; i >= 0; i--) {
      if (listeners[i].test === test) {
        listeners.splice(i, 1);
        found = true;
      }
    }
  }
  return found;
};

/**
    registered('root-name'); // => true | false

You can get a list of root level objects:

    models();

You can obtain a value using a path.
*/

const models = () => Object.keys(registry);

const registered = path => !!registry[path.split('.')[0]];

/**
    remove('root');
    remove('path.to.property')

Will remove the specified property from the registry (including root-level objects). If the object
does not exist, has no effect. So:

~~~~
const {register, remove, get} = b8r;
register('foo', {bar: 17, baz: {lurman: true}});
Test(() => {remove('foo.bar'); return get('foo.bar');}).shouldBe(null);
Test(() => {remove('foo.boris.yeltsin'); return get('foo.boris')}).shouldBe(null);
Test(() => {remove('foo.baz.lurman'); return Object.keys(get('foo.baz')).length}).shouldBe(0);
~~~~
*/
const remove = path => deleteByPath(registry, path);

module.exports = {
  get,
  getJSON,
  set,
  setJSON,
  push,
  call,
  touch,
  async_touch,
  observe,
  unobserve,
  models,
  _register,
  register,
  registered,
  remove,
  resolvePath,
  isValidPath,
};
<|endoftext|>


<commit_before>/**
 * Created by johndoe on 12.08.2015.
 */
/**
 * Links:
 * http://stackoverflow.com/questions/20499225/i-need-a-nodejs-scheduler-that-allows-for-tasks-at-different-intervals
 * Cron seems nice but also check out Agenda:
 * https://github.com/rschmukler/agenda
 */
var cron = require('cron');
var Scanner  = require('./app/business/scan');

/**
 * Runs the scanner job every day of the month at 00:15 local time.
 * If captchas encountered, unfinished categories/products will be scanned in
 * subsequent attempts, after 30mins, 2 hours and 4 hours and a half.
 * TODO extend to add support for notifications to users
 */
var cronJob = cron.job("15 00 * * *", function(){
    var NR_OF_ATTEMPTS = 3;
    function attempt(docs, indexObj) {
        setTimeout(function () {
            console.info('[SCANNER-JOB] attempt ' + indexObj.index + ' to finish scan: ' + new Date().toString());
            Scanner.scanEverything(docs, function (failed, notFound) {
                if (failed.length > 0 && indexObj.index++ <= NR_OF_ATTEMPTS)
                    attempt(failed, indexObj);
            });
        }, (indexObj.index ^ 2) * 30 * 60 * 1000);
    }
    console.info('[SCANNER-JOB] started scan everything at: ' + new Date().toString());
    Scanner.scanEverything(function (failed, notFound) {
        var indexObj = { index : 1 };
        failed.forEach(function (doc, index) {
            console.log("Remainder " + index  +": " + doc.name);
        });
        notFound.forEach(function (doc, index) {
            console.log("Not found " + index  +": " + doc.name);
        });
        if (failed.length > 0)
            attempt(failed, indexObj);
    });
});
cronJob.start();<commit_msg>fix scan scheduler<commit_after>/**
 * Created by johndoe on 12.08.2015.
 */
/**
 * Links:
 * http://stackoverflow.com/questions/20499225/i-need-a-nodejs-scheduler-that-allows-for-tasks-at-different-intervals
 * Cron seems nice but also check out Agenda:
 * https://github.com/rschmukler/agenda
 */
var cron = require('cron');
var Scanner  = require('./app/business/scan');

/**
 * Runs the scanner job every day of the month at 00:15 local time.
 * If captchas encountered, unfinished categories/products will be scanned in
 * subsequent attempts, after 30mins, 2 hours and 4 hours and a half.
 * TODO extend to add support for notifications to users
 */
var cronJob = cron.job("15 00 * * *", function(){
    var NR_OF_ATTEMPTS = 3;
    function attempt(docs, indexObj) {
        setTimeout(function () {
            console.info('[SCANNER-JOB] attempt ' + indexObj.index + ' to finish scan: ' + new Date().toString());
            Scanner.scanEverything(function (failed, notFound) {
                if (failed.length > 0 && indexObj.index++ <= NR_OF_ATTEMPTS)
                    attempt(failed, indexObj);
            });
        }, Math.pow(indexObj.index, 2) * 30 * 60 * 1000);
    }
    console.info('[SCANNER-JOB] started scan everything at: ' + new Date().toString());
    Scanner.scanEverything(function (failed, notFound) {
        var indexObj = { index : 1 };
        failed.forEach(function (doc, index) {
            console.log("Remainder " + index  +": " + doc.name);
        });
        notFound.forEach(function (doc, index) {
            console.log("Not found " + index  +": " + doc.name);
        });
        if (failed.length > 0)
            attempt(failed, indexObj);
    });
});
cronJob.start();<|endoftext|>


<commit_before>var path = require('path'),
	fs = require('fs'),
	_ = require('../../../lib/alloy/underscore')._,
	uglifyjs = require('uglify-js'),
	logger = require('../../../logger'),
	U = require('../../../utils');

var EXCLUDE = ['backbone', 'CFG', 'underscore'];
var BUILTINS_PATH = path.join(__dirname, '..', '..', '..', 'builtins');
var loaded = [];

function appendExtension(file, extension) {
	extension = '.' + extension;
	file = U.trim(file);

	var len = extension.length;
	if (file.substring(file.length - extension.length) !== extension) {
		return file + extension;
	} else {
		return file;
	}
}

function loadBuiltin(source, name, dest) {
	if (!path.existsSync(source)) {
		return;
	}

	logger.debug('  - [' + name + '] --> "' + dest + '"');
	U.copyFileSync(source, dest);
	loaded = _.union(loaded, [name]);
}

function loadMomentLanguages(config) {
	// retrieve the languages of the project
	var i18nPath = path.join(config.dir.project, 'i18n');
	if (fs.existsSync(i18nPath)) {
		var languages = _.filter(fs.readdirSync(i18nPath), function(file) {
			return fs.statSync(path.join(i18nPath, file)).isDirectory();
		});

		// filter the momentjs translation files that match one of these languages
		var availableI18nPath = path.join(BUILTINS_PATH, 'moment', 'lang');
		var fileNames = _.filter(fs.readdirSync(availableI18nPath), function(file) {
			return _.indexOf(languages, file.substr(0, 2)) !== -1;
		});

		// import these files
		_.each(fileNames, function(file) {
			var source = path.join(BUILTINS_PATH, 'moment', 'lang', file);
			var dest = path.join(config.dir.resources, 'alloy', 'moment', 'lang', file);
			loadBuiltin(source, file, dest);
		});
	}
}

exports.process = function(ast, config) {
	var rx = /^(alloy)\/(.+)$/;
	var match;

	ast.walk(new uglifyjs.TreeWalker(function(node) {
		if (node instanceof uglifyjs.AST_Call) {
			var theString = node.args[0];
			if (node.expression.name === 'require' &&            // Is this a require call?
				theString && _.isString(theString.value) &&      // Is the 1st param a literal string?
				(match = theString.value.match(rx)) !== null &&  // Is it an alloy module?
				!_.contains(EXCLUDE, match[2]) &&                // Make sure it's not excluded.
				!_.contains(loaded, match[2])                    // Make sure we didn't find it already
			) {
				// Make sure it hasn't already been copied to Resources
				var name = appendExtension(match[2], 'js');
				if (fs.existsSync(path.join(config.dir.resources, match[1], name))) {
					return;
				}

				// make sure the builtin exists
				var source = path.join(BUILTINS_PATH, name);
				var dest = path.join(config.dir.resources, 'alloy', name);
				loadBuiltin(source, name, dest);

				if ('moment.js' === name) {
					// if momentjs is required in the project, also load the
					// localizations which may be used
					loadMomentLanguages(config);
				}
			}
		}
	}));
	return ast;
};
<commit_msg>fix builtins detect<commit_after>var path = require('path'),
	fs = require('fs'),
	_ = require('../../../lib/alloy/underscore')._,
	uglifyjs = require('uglify-js'),
	logger = require('../../../logger'),
	U = require('../../../utils');

var EXCLUDE = ['backbone', 'CFG', 'underscore'];
var BUILTINS_PATH = path.join(__dirname, '..', '..', '..', 'builtins');
var loaded = [];

function appendExtension(file, extension) {
	extension = '.' + extension;
	file = U.trim(file);

	var len = extension.length;
	if (file.substring(file.length - extension.length) !== extension) {
		return file + extension;
	} else {
		return file;
	}
}

function loadBuiltin(source, name, dest) {
	if (!path.existsSync(source)) {
		return;
	}

	logger.debug('  - [' + name + '] --> "' + dest + '"');
	U.copyFileSync(source, dest);
	loaded = _.union(loaded, [name]);
}

function loadMomentLanguages(config) {
	// retrieve the languages of the project
	var i18nPath = path.join(config.dir.project, 'i18n');
	if (fs.existsSync(i18nPath)) {
		var languages = _.filter(fs.readdirSync(i18nPath), function(file) {
			return fs.statSync(path.join(i18nPath, file)).isDirectory();
		});

		// filter the momentjs translation files that match one of these languages
		var availableI18nPath = path.join(BUILTINS_PATH, 'moment', 'lang');
		var fileNames = _.filter(fs.readdirSync(availableI18nPath), function(file) {
			return _.indexOf(languages, file.substr(0, 2)) !== -1;
		});

		// import these files
		_.each(fileNames, function(file) {
			var source = path.join(BUILTINS_PATH, 'moment', 'lang', file);
			var dest = path.join(config.dir.resources, 'alloy', 'moment', 'lang', file);
			loadBuiltin(source, file, dest);
		});
	}
}

exports.process = function(ast, config) {
	var rx = /^(\/?alloy)\/(.+)$/;
	var match;

	ast.walk(new uglifyjs.TreeWalker(function(node) {
		if (node instanceof uglifyjs.AST_Call) {
			var theString = node.args[0];
			if (node.expression.name === 'require' &&            // Is this a require call?
				theString && _.isString(theString.value) &&      // Is the 1st param a literal string?
				(match = theString.value.match(rx)) !== null &&  // Is it an alloy module?
				!_.contains(EXCLUDE, match[2]) &&                // Make sure it's not excluded.
				!_.contains(loaded, match[2])                    // Make sure we didn't find it already
			) {
				// Make sure it hasn't already been copied to Resources
				var name = appendExtension(match[2], 'js');
				if (fs.existsSync(path.join(config.dir.resources, match[1], name))) {
					return;
				}

				// make sure the builtin exists
				var source = path.join(BUILTINS_PATH, name);
				var dest = path.join(config.dir.resources, 'alloy', name);
				loadBuiltin(source, name, dest);

				if ('moment.js' === name) {
					// if momentjs is required in the project, also load the
					// localizations which may be used
					loadMomentLanguages(config);
				}
			}
		}
	}));
	return ast;
};
<|endoftext|>


<commit_before>

var exampleDeck = {deck:[
	{q:"hello" ,a:"hola" },
	{q: "bye",a:"adios"},
	{q: "dog",a: "perro"},
	{q: "cat",a: "gato"},
	{q: "food",a: "comida"},
	]}

function CardDeck(carddeck_object){
	this.solvedDeck = false
	this.remainingCards = carddeck_object.deck
	this.previousCorrect = false
	this.currentCard = this.remainingCards[0]
	this.advanceToNextCard = function(){
		this.remainingCards = this.remainingCards.slice(1)
		this.currentCard = this.remainingCards[0]
		if (this.remainingCards.length === 0){
			this.solvedDeck = true
		}
	}
	this.shuffleCards = function(){
		this.remainingCards = shuffle(this.remainingCards)
		this.currentCard = this.remainingCards[0]
	}
	// this.parseInput = function(){}

}

<commit_msg>work in progress<commit_after><|endoftext|>


<commit_before>#!/usr/bin/env ./rhino

importPackage(java.io);
importPackage(java.lang);
importPackage(com.itextpdf.text);
importPackage(com.itextpdf.text.pdf);

var pi = 4 * Math.atan(1);

function mm2pt(mm) {
    return 72.0 * (mm / 25.4);
}

function pt2mm(pt) {
    return 25.4 * (pt / 72.0);
}

function deg2rad(deg) {
    return deg * pi / 180;
}

var modules = [];

function registerModule(modinfo) {
    var err = System.err;
    var command = modinfo['command'];
    modules[command] = modinfo;
}

load("cat.js");
load("colorinfo.js");
load("collect.js");
load("cut.js");
load("dup-pages.js");
load("info.js");
load("merge.js");
load("rotate.js");
load("rotateScale.js");
load("2up.js");

function usage() {
    var err = System.err;

    err.print("Usage:  jspdftk action [args]\n");
    err.print("  action [args]\n");
    quit(1);
}

function jspdftk(args) {
    var err = System.err;

    if (args.length < 1) {
	usage();
    }

    var installdir = "./";
    var prog = args[0];

    if (prog in modules) {
	args.shift();
	(modules[prog]['entry'])(args);
    } else if (prog == null) {
	usage();
    } else {
	err.print("Unknown command " + prog + "\n");
    }
}

jspdftk(arguments);
<commit_msg>reorder loading of modules in alphabetical order<commit_after>#!/usr/bin/env ./rhino

importPackage(java.io);
importPackage(java.lang);
importPackage(com.itextpdf.text);
importPackage(com.itextpdf.text.pdf);

var pi = 4 * Math.atan(1);

function mm2pt(mm) {
    return 72.0 * (mm / 25.4);
}

function pt2mm(pt) {
    return 25.4 * (pt / 72.0);
}

function deg2rad(deg) {
    return deg * pi / 180;
}

var modules = [];

function registerModule(modinfo) {
    var err = System.err;
    var command = modinfo['command'];
    modules[command] = modinfo;
}

load("2up.js");
load("cat.js");
load("colorinfo.js");
load("collect.js");
load("cut.js");
load("dup-pages.js");
load("info.js");
load("merge.js");
load("rotate.js");
load("rotateScale.js");

function usage() {
    var err = System.err;

    err.print("Usage:  jspdftk action [args]\n");
    err.print("  action [args]\n");
    quit(1);
}

function jspdftk(args) {
    var err = System.err;

    if (args.length < 1) {
	usage();
    }

    var installdir = "./";
    var prog = args[0];

    if (prog in modules) {
	args.shift();
	(modules[prog]['entry'])(args);
    } else if (prog == null) {
	usage();
    } else {
	err.print("Unknown command " + prog + "\n");
    }
}

jspdftk(arguments);
<|endoftext|>


<commit_before>/*
Copyright (c) 2008-2016 Pivotal Labs

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

@flow
*/

/* eslint-disable */

type Tester = (a: any, b: any) => boolean | typeof undefined;

// Extracted out of jasmine 2.5.2
function equals(a: any, b: any, customTesters?: Array<Tester>): boolean {
  customTesters = customTesters || [];
  return eq(a, b, [], [], customTesters);
}

function isAsymmetric(obj) {
  return obj && isA('Function', obj.asymmetricMatch);
}

function asymmetricMatch(a, b) {
  var asymmetricA = isAsymmetric(a), asymmetricB = isAsymmetric(b);

  if (asymmetricA && asymmetricB) {
    return undefined;
  }

  if (asymmetricA) {
    return a.asymmetricMatch(b);
  }

  if (asymmetricB) {
    return b.asymmetricMatch(a);
  }
}

// Equality function lovingly adapted from isEqual in
//   [Underscore](http://underscorejs.org)
function eq(a, b, aStack, bStack, customTesters): boolean {
  var result = true;

  var asymmetricResult = asymmetricMatch(a, b);
  if (asymmetricResult !== void 0) {
    return asymmetricResult;
  }

  for (var i = 0; i < customTesters.length; i++) {
    var customTesterResult = customTesters[i](a, b);
    if (customTesterResult !== void 0) {
      return customTesterResult;
    }
  }

  if (a instanceof Error && b instanceof Error) {
    return a.message == b.message;
  }

  // Identical objects are equal. `0 === -0`, but they aren't identical.
  // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal).
  if (a === b) {
    return a !== 0 || 1 / a == 1 / b;
  }
  // A strict comparison is necessary because `null == undefined`.
  if (a === null || b === null) {
    return a === b;
  }
  var className = Object.prototype.toString.call(a);
  if (className != Object.prototype.toString.call(b)) {
    return false;
  }
  switch (className) {
    // Strings, numbers, dates, and booleans are compared by value.
    case '[object String]':
      // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
      // equivalent to `new String("5")`.
      return a == String(b);
    case '[object Number]':
      // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for
      // other numeric values.
      return a != +a ? b != +b : a === 0 ? 1 / a == 1 / b : a == +b;
    case '[object Date]':
    case '[object Boolean]':
      // Coerce dates and booleans to numeric primitive values. Dates are compared by their
      // millisecond representations. Note that invalid dates with millisecond representations
      // of `NaN` are not equivalent.
      return +a == +b;
    // RegExps are compared by their source patterns and flags.
    case '[object RegExp]':
      return (
        a.source == b.source &&
        a.global == b.global &&
        a.multiline == b.multiline &&
        a.ignoreCase == b.ignoreCase
      );
  }
  if (typeof a != 'object' || typeof b != 'object') {
    return false;
  }

  var aIsDomNode = isDomNode(a);
  var bIsDomNode = isDomNode(b);
  if (aIsDomNode && bIsDomNode) {
    // At first try to use DOM3 method isEqualNode
    if (a.isEqualNode) {
      return a.isEqualNode(b);
    }
    // IE8 doesn't support isEqualNode, try to use outerHTML && innerText
    var aIsElement = a instanceof Element;
    var bIsElement = b instanceof Element;
    if (aIsElement && bIsElement) {
      return a.outerHTML == b.outerHTML;
    }
    if (aIsElement || bIsElement) {
      return false;
    }
    return a.innerText == b.innerText && a.textContent == b.textContent;
  }
  if (aIsDomNode || bIsDomNode) {
    return false;
  }

  // Assume equality for cyclic structures. The algorithm for detecting cyclic
  // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
  var length = aStack.length;
  while (length--) {
    // Linear search. Performance is inversely proportional to the number of
    // unique nested structures.
    if (aStack[length] == a) {
      return bStack[length] == b;
    }
  }
  // Add the first object to the stack of traversed objects.
  aStack.push(a);
  bStack.push(b);
  var size = 0;
  // Recursively compare objects and arrays.
  // Compare array lengths to determine if a deep comparison is necessary.
  if (className == '[object Array]') {
    size = a.length;
    if (size !== b.length) {
      return false;
    }

    while (size--) {
      result = eq(a[size], b[size], aStack, bStack, customTesters);
      if (!result) {
        return false;
      }
    }
  } else {
    // Objects with different constructors are not equivalent, but `Object`s
    // or `Array`s from different frames are.
    // CUSTOM JEST CHANGE:
    // TODO(cpojer): fix all tests and this and re-enable this check
    /*
    var aCtor = a.constructor, bCtor = b.constructor;
    if (aCtor !== bCtor && !(isFunction(aCtor) && aCtor instanceof aCtor &&
           isFunction(bCtor) && bCtor instanceof bCtor)) {
      return false;
    }
    */
  }

  // Deep compare objects.
  var aKeys = keys(a, className == '[object Array]'), key;
  size = aKeys.length;

  // Ensure that both objects contain the same number of properties before comparing deep equality.
  if (keys(b, className == '[object Array]').length !== size) {
    return false;
  }

  while (size--) {
    key = aKeys[size];

    // Deep compare each member
    result = has(b, key) && eq(a[key], b[key], aStack, bStack, customTesters);

    if (!result) {
      return false;
    }
  }
  // Remove the first object from the stack of traversed objects.
  aStack.pop();
  bStack.pop();

  return result;
}

function keys(obj, isArray) {
  // CUSTOM JEST CHANGE: don't consider undefined keys.
  var allKeys = (function(o) {
    var keys = [];
    for (var key in o) {
      if (has(o, key)) {
        keys.push(key);
      }
    }
    return keys;
  })(obj);

  if (!isArray) {
    return allKeys;
  }

  var extraKeys = [];
  if (allKeys.length === 0) {
    return allKeys;
  }

  for (var x = 0; x < allKeys.length; x++) {
    if (!allKeys[x].match(/^[0-9]+$/)) {
      extraKeys.push(allKeys[x]);
    }
  }

  return extraKeys;
}

function has(obj, key) {
  // CUSTOM JEST CHANGE:
  // TODO(cpojer): remove the `obj[key] !== undefined` check.
  return (
    Object.prototype.hasOwnProperty.call(obj, key) && obj[key] !== undefined
  );
}

function isA(typeName: string, value: any) {
  return Object.prototype.toString.apply(value) === '[object ' + typeName + ']';
}

function isDomNode(obj) {
  return obj.nodeType > 0;
}

function fnNameFor(func: Function) {
  if (func.name) {
    return func.name;
  }

  const matches = func.toString().match(/^\s*function\s*(\w*)\s*\(/);
  return matches ? matches[1] : '<anonymous>';
}

function isUndefined(obj: any)  {
  return obj === void 0;
}

function getPrototype(obj) {
  if (Object.getPrototypeOf) {
    return Object.getPrototypeOf(obj);
  }

  if (obj.constructor.prototype == obj) {
    return null;
  }

  return obj.constructor.prototype;
}

function hasProperty(obj: Object | null, property: string) {
  if (!obj) {
    return false;
  }

  if (Object.prototype.hasOwnProperty.call(obj, property)) {
    return true;
  }

  return hasProperty(getPrototype(obj), property);
}

module.exports = {
  equals,
  fnNameFor,
  hasProperty,
  isA,
  isUndefined,
};
<commit_msg>Replace "void 0" with "undefined"<commit_after>/*
Copyright (c) 2008-2016 Pivotal Labs

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

@flow
*/

/* eslint-disable */

type Tester = (a: any, b: any) => boolean | typeof undefined;

// Extracted out of jasmine 2.5.2
function equals(a: any, b: any, customTesters?: Array<Tester>): boolean {
  customTesters = customTesters || [];
  return eq(a, b, [], [], customTesters);
}

function isAsymmetric(obj) {
  return obj && isA('Function', obj.asymmetricMatch);
}

function asymmetricMatch(a, b) {
  var asymmetricA = isAsymmetric(a), asymmetricB = isAsymmetric(b);

  if (asymmetricA && asymmetricB) {
    return undefined;
  }

  if (asymmetricA) {
    return a.asymmetricMatch(b);
  }

  if (asymmetricB) {
    return b.asymmetricMatch(a);
  }
}

// Equality function lovingly adapted from isEqual in
//   [Underscore](http://underscorejs.org)
function eq(a, b, aStack, bStack, customTesters): boolean {
  var result = true;

  var asymmetricResult = asymmetricMatch(a, b);
  if (asymmetricResult !== undefined) {
    return asymmetricResult;
  }

  for (var i = 0; i < customTesters.length; i++) {
    var customTesterResult = customTesters[i](a, b);
    if (customTesterResult !== undefined) {
      return customTesterResult;
    }
  }

  if (a instanceof Error && b instanceof Error) {
    return a.message == b.message;
  }

  // Identical objects are equal. `0 === -0`, but they aren't identical.
  // See the [Harmony `egal` proposal](http://wiki.ecmascript.org/doku.php?id=harmony:egal).
  if (a === b) {
    return a !== 0 || 1 / a == 1 / b;
  }
  // A strict comparison is necessary because `null == undefined`.
  if (a === null || b === null) {
    return a === b;
  }
  var className = Object.prototype.toString.call(a);
  if (className != Object.prototype.toString.call(b)) {
    return false;
  }
  switch (className) {
    // Strings, numbers, dates, and booleans are compared by value.
    case '[object String]':
      // Primitives and their corresponding object wrappers are equivalent; thus, `"5"` is
      // equivalent to `new String("5")`.
      return a == String(b);
    case '[object Number]':
      // `NaN`s are equivalent, but non-reflexive. An `egal` comparison is performed for
      // other numeric values.
      return a != +a ? b != +b : a === 0 ? 1 / a == 1 / b : a == +b;
    case '[object Date]':
    case '[object Boolean]':
      // Coerce dates and booleans to numeric primitive values. Dates are compared by their
      // millisecond representations. Note that invalid dates with millisecond representations
      // of `NaN` are not equivalent.
      return +a == +b;
    // RegExps are compared by their source patterns and flags.
    case '[object RegExp]':
      return (
        a.source == b.source &&
        a.global == b.global &&
        a.multiline == b.multiline &&
        a.ignoreCase == b.ignoreCase
      );
  }
  if (typeof a != 'object' || typeof b != 'object') {
    return false;
  }

  var aIsDomNode = isDomNode(a);
  var bIsDomNode = isDomNode(b);
  if (aIsDomNode && bIsDomNode) {
    // At first try to use DOM3 method isEqualNode
    if (a.isEqualNode) {
      return a.isEqualNode(b);
    }
    // IE8 doesn't support isEqualNode, try to use outerHTML && innerText
    var aIsElement = a instanceof Element;
    var bIsElement = b instanceof Element;
    if (aIsElement && bIsElement) {
      return a.outerHTML == b.outerHTML;
    }
    if (aIsElement || bIsElement) {
      return false;
    }
    return a.innerText == b.innerText && a.textContent == b.textContent;
  }
  if (aIsDomNode || bIsDomNode) {
    return false;
  }

  // Assume equality for cyclic structures. The algorithm for detecting cyclic
  // structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
  var length = aStack.length;
  while (length--) {
    // Linear search. Performance is inversely proportional to the number of
    // unique nested structures.
    if (aStack[length] == a) {
      return bStack[length] == b;
    }
  }
  // Add the first object to the stack of traversed objects.
  aStack.push(a);
  bStack.push(b);
  var size = 0;
  // Recursively compare objects and arrays.
  // Compare array lengths to determine if a deep comparison is necessary.
  if (className == '[object Array]') {
    size = a.length;
    if (size !== b.length) {
      return false;
    }

    while (size--) {
      result = eq(a[size], b[size], aStack, bStack, customTesters);
      if (!result) {
        return false;
      }
    }
  } else {
    // Objects with different constructors are not equivalent, but `Object`s
    // or `Array`s from different frames are.
    // CUSTOM JEST CHANGE:
    // TODO(cpojer): fix all tests and this and re-enable this check
    /*
    var aCtor = a.constructor, bCtor = b.constructor;
    if (aCtor !== bCtor && !(isFunction(aCtor) && aCtor instanceof aCtor &&
           isFunction(bCtor) && bCtor instanceof bCtor)) {
      return false;
    }
    */
  }

  // Deep compare objects.
  var aKeys = keys(a, className == '[object Array]'), key;
  size = aKeys.length;

  // Ensure that both objects contain the same number of properties before comparing deep equality.
  if (keys(b, className == '[object Array]').length !== size) {
    return false;
  }

  while (size--) {
    key = aKeys[size];

    // Deep compare each member
    result = has(b, key) && eq(a[key], b[key], aStack, bStack, customTesters);

    if (!result) {
      return false;
    }
  }
  // Remove the first object from the stack of traversed objects.
  aStack.pop();
  bStack.pop();

  return result;
}

function keys(obj, isArray) {
  // CUSTOM JEST CHANGE: don't consider undefined keys.
  var allKeys = (function(o) {
    var keys = [];
    for (var key in o) {
      if (has(o, key)) {
        keys.push(key);
      }
    }
    return keys;
  })(obj);

  if (!isArray) {
    return allKeys;
  }

  var extraKeys = [];
  if (allKeys.length === 0) {
    return allKeys;
  }

  for (var x = 0; x < allKeys.length; x++) {
    if (!allKeys[x].match(/^[0-9]+$/)) {
      extraKeys.push(allKeys[x]);
    }
  }

  return extraKeys;
}

function has(obj, key) {
  // CUSTOM JEST CHANGE:
  // TODO(cpojer): remove the `obj[key] !== undefined` check.
  return (
    Object.prototype.hasOwnProperty.call(obj, key) && obj[key] !== undefined
  );
}

function isA(typeName: string, value: any) {
  return Object.prototype.toString.apply(value) === '[object ' + typeName + ']';
}

function isDomNode(obj) {
  return obj.nodeType > 0;
}

function fnNameFor(func: Function) {
  if (func.name) {
    return func.name;
  }

  const matches = func.toString().match(/^\s*function\s*(\w*)\s*\(/);
  return matches ? matches[1] : '<anonymous>';
}

function isUndefined(obj: any)  {
  return obj === void 0;
}

function getPrototype(obj) {
  if (Object.getPrototypeOf) {
    return Object.getPrototypeOf(obj);
  }

  if (obj.constructor.prototype == obj) {
    return null;
  }

  return obj.constructor.prototype;
}

function hasProperty(obj: Object | null, property: string) {
  if (!obj) {
    return false;
  }

  if (Object.prototype.hasOwnProperty.call(obj, property)) {
    return true;
  }

  return hasProperty(getPrototype(obj), property);
}

module.exports = {
  equals,
  fnNameFor,
  hasProperty,
  isA,
  isUndefined,
};
<|endoftext|>


<commit_before>import React from 'react';

export default () => (

            <svg style={styles.home} viewBox="0 0 64 72"><g><path d="M60.034 33.795l-26-23.984a2.997 2.997 0 0 0-4.068 0l-26 23.984a3 3 0 0 0 4.068 4.41l2.265-2.09 6.809 24.683A3 3 0 0 0 20 63h24a3 3 0 0 0 2.892-2.202l6.809-24.683 2.265 2.09a2.988 2.988 0 0 0 2.033.795 3 3 0 0 0 2.035-5.205zM32 53a3 3 0 1 1 0-6 3 3 0 0 1 0 6zm0-11a6.999 6.999 0 1 1 0-13.998A7 7 0 1 1 32 42z"></path></g></svg>

Home

React
 @reactjs3h

Have you tried our 15.4 release candidate? Give it a shot and let us know if you have any issues before we ship it!

);

var styles = {
    home: {
        display: 'inline-block',
        fill: '#1da1f2',
        width: '10%',
        marginLeft: '5%',
        verticalAlign: 'text-bottom'
    },
    h1: {
        fontSize: '120%',
        marginLeft: '5%',
        display: 'inline'
    },
    nav: {
        padding: '10px 0',
        boxShadow: '0 0 4px #657786'
    },
    ul: {
        padding: 0,
        margin: 0,
        listStyle: 'none',
        height: '351px',
        overflow: 'auto'
    },
    img: {
        width: '20%',
        display: 'block',
        float: 'left'
    },
    li: {
        padding: '3%',
        borderBottom: '1px solid #ccd6dd'
    },
    div: {
        marginLeft: '23%'
    },
    h2: {
        display: 'inline',
        fontSize: '100%',
        marginLeft: '3%'
    },
    span: {
        color: '#657786'
    },
    time: {
        color: '#657786',
        float: 'right'
    }
}<commit_msg>Renamed style keys<commit_after>import React from 'react';

export default () => (

            <svg style={styles.home} viewBox="0 0 64 72"><g><path d="M60.034 33.795l-26-23.984a2.997 2.997 0 0 0-4.068 0l-26 23.984a3 3 0 0 0 4.068 4.41l2.265-2.09 6.809 24.683A3 3 0 0 0 20 63h24a3 3 0 0 0 2.892-2.202l6.809-24.683 2.265 2.09a2.988 2.988 0 0 0 2.033.795 3 3 0 0 0 2.035-5.205zM32 53a3 3 0 1 1 0-6 3 3 0 0 1 0 6zm0-11a6.999 6.999 0 1 1 0-13.998A7 7 0 1 1 32 42z"></path></g></svg>

Home

React

                @reactjs3h

Have you tried our 15.4 release candidate? Give it a shot and let us know if you have any issues before we ship it!

);

var styles = {
    home: {
        display: 'inline-block',
        fill: '#1da1f2',
        width: '10%',
        marginLeft: '5%',
        verticalAlign: 'text-bottom'
    },
    heading: {
        fontSize: '120%',
        marginLeft: '5%',
        display: 'inline'
    },
    nav: {
        padding: '10px 0',
        boxShadow: '0 0 4px #657786'
    },
    tweets: {
        padding: 0,
        margin: 0,
        listStyle: 'none',
        height: '351px',
        overflow: 'auto'
    },
    logo: {
        width: '20%',
        display: 'block',
        float: 'left'
    },
    tweet: {
        padding: '3%',
        borderBottom: '1px solid #ccd6dd'
    },
    text: {
        marginLeft: '23%'
    },
    name: {
        display: 'inline',
        fontSize: '100%',
        marginLeft: '3%',
        marginRight: '2%'
    },
    username: {
        color: '#657786'
    },
    time: {
        color: '#657786',
        float: 'right'
    }
}<|endoftext|>


<commit_before>'use strict';

var React                 = require('react-native');
var Icon                  = require('react-native-vector-icons/Ionicons');
var BackgroundGeolocation = require('react-native-background-geolocation');
var SettingsService       = require('./SettingsService');

var mapRef = 'mapRef';

// Map annotations stack.  pretty ugly business here.
// TODO MapboxGL doesn't handle annotations very well when we switch views (to Settings, for example), its annotations get all messed up.
// This needs work.
var annotations = [];

var {
  AsyncStorage,
  StyleSheet,
  MapView,
  AppStateIOS,
  Text,
  TextInput,
  View,
  SwitchIOS,
  Navigator,
  NavButton,
  TouchableHighlight
} = React;

var Map = React.createClass({

  getInitialState() {
    var me = this;

    AsyncStorage.getItem("state")
    .then((values) => {
      if (values !== null){
        values = JSON.parse(values);
        values.isStationary = true;
        me.setState(values);
        if (values.isEnabled) {
          me.onToggleEnabled(values.isEnabled);
        }
      }
    })
    .catch((error) => console.error("- error: ", error.message))
    .done();

    AppStateIOS.addEventListener('change', this.onAppStateChange);

    this.bgGeo = BackgroundGeolocation;

    // Fetch bg-geo settings.
    SettingsService.getValues(function(values) {

      // Configure Background Geolocation.
      me.bgGeo.configure(values);

      me.bgGeo.getState(function(state) {
        console.log('------------ state: ', state);
      });

      // Listen to location events coming out.
      me.bgGeo.on('location', me.onBackgroundGeolocation);

      // Listen to motionchange events.
      me.bgGeo.on('motionchange', function(location) {
        console.log('- motionchanged: ', JSON.stringify(location));
        me.setState({
          isStationary: !location.is_moving,
          paceButtonStyle: (location.is_moving) ? styles.redButton : styles.greenButton
        });
      });

      // This fires after plugin successfully synced to server.
      me.bgGeo.on('sync', function(rs) {
        console.log('- sync complete: ', JSON.stringify(rs));
      })
    });

    return {
      zoom: 11,
      odometer: 0,
      isEnabled: false,
      isStationary: true,
      paceButtonStyle: styles.greenButton,
      navigateButton: 'navigate'
    };
  },
  onAppStateChange(state) {
    if (state === 'active') {
      var me = this;
      me.bgGeo.getCurrentPosition(function(location) {
        //me.setCenterCoordinateAnimated(mapRef, location.coords.latitude, location.coords.longitude);
        console.log('- received current position: ', location);
      })
    }
  },
  onClickSettings() {
    this.props.navigator.push({
      id: 'settings',
      sceneConfig: Navigator.SceneConfigs.FloatFromBottom,
    });
  },
  onToggleEnabled(enabled) {
    var me = this;

    if (!enabled && !this.state.isStationary) {
      this.onToggleStationary();
    }
    this.setState({
      isEnabled: enabled,
      odometer: 0
    }, function() {
      AsyncStorage.setItem("state", JSON.stringify(me.state));
    });

    this.bgGeo.resetOdometer(function() {
      console.log('- resetOdometer success');
    });

    annotations = [];
    if (enabled) {
      this.bgGeo.start(function() {
        // Successfully started.  Now fetch current position.
        me.bgGeo.getCurrentPosition(function(location) {
          //me.setCenterCoordinateZoomLevelAnimated(mapRef, location.coords.latitude, location.coords.longitude, 14);
        });
      });
    } else {
      this.bgGeo.stop();
    }
  },
  onToggleStationary() {
    var me = this;
    var value = !this.state.isStationary;

    this.setState({
      isStationary: value,
      paceButtonStyle: (value) ? styles.greenButton : styles.redButton
    });

    this.bgGeo.changePace(!value);
  },
  onUpdatePosition() {
    var me = this;
    this.setState({
      navigateButton: 'load-d'
    });
    me.bgGeo.getCurrentPosition(function(location) {
      //me.setCenterCoordinateAnimated(mapRef, location.coords.latitude, location.coords.longitude);
      me.setState({
        navigateButton: 'navigate'
      });
    });
  },
  onBackgroundGeolocation(location) {
    console.log('- [js] bgGeo location: ', JSON.stringify(location));
    var me    = this,
        now   = ((location.timestamp) ? new Date(location.timestamp) : new Date()),
        label = [now.getHours(), now.getMinutes(), now.getSeconds()].join(':');

    me.bgGeo.getOdometer(function(distance) {
      me.setState({
        odometer: (distance/1000).toFixed(1)
      });
    });

    // Push onto our annotations stack
    annotations.push({
      latitude: location.coords.latitude,
      longitude: location.coords.longitude,
      title: label,
      annotationImage: {
        url: 'https://dl.dropboxusercontent.com/u/2319755/react-native-background-geolocation-demo/green-dot.png',
        height: 20,
        width: 20
      }
    });

    // Send annotations-stack to MapBoxGL.  Unfortunately, it has to destroy all existing then re-add...
    // TODO this needs to work better.  We need existing annotations to persist.  And we need polylines too.
    //me.addAnnotations(mapRef, annotations);
  },
  onRegionChange(location) {
    //this.setState({ currentZoom: location.zoom });
  },
  onRegionWillChange(location) {
    //console.log(location);
  },
  onUpdateUserLocation(location) {
    //console.log('[js]MapBox location: ', location);
  },
  onOpenAnnotation(annotation) {
    //console.log(annotation);
  },
  onRightAnnotationTapped(e) {
    //console.log(e);
  },
  render: function() {

    return (
      <View style={styles.container}>
        <View style={styles.map}><Text>Map Goes Here</Text></View>
        <View style={styles.toolbar}>
          <TouchableHighlight style={[styles.locationButton, styles.iconButton]} underlayColor={"transparent"} onPress={this.onUpdatePosition}>
            <Icon name={this.state.navigateButton} size={24} color="#4f8ef7" />
          </TouchableHighlight>
          <Text>{this.state.odometer}km</Text>

          <SwitchIOS style={styles.enabledButton} value={this.state.isEnabled} onValueChange={this.onToggleEnabled}></SwitchIOS>

          <TouchableHighlight style={[this.state.paceButtonStyle, styles.stationaryButton, styles.iconButton]} underlayColor={"transparent"} onPress={this.onToggleStationary}>
            <Icon name={this.state.isStationary ? 'play' : 'pause'} size={24} />
          </TouchableHighlight>

        </View>
      </View>
    );
  }
});

var styles = StyleSheet.create({
  container: {
    flex: 1,
    marginTop: 10,
    backgroundColor: 'transparent',
  },
  map: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  toolbar: {
    //top: 50,
    height: 50,
    padding: 5,
    justifyContent: 'center',
    alignItems: 'center'
  },
  settingsButton: {
    position: 'absolute',
    left: 10,
    top: 15
  },
  buttonText: {
    color: 'blue',
    fontSize: 16
  },
  locationButton: {
    position: 'absolute',
    left: 0,
    top: 0
  },
  spinner: {
    position: 'absolute',
    top: 10,
    left: 40
  },
  iconButton: {
    width: 50,
    height: 50,
    justifyContent: 'center',
    alignItems: 'center'
  },
  enabledButton: {
    position: 'absolute',
    top: 10,
    right: 60
  },
  stationaryButton: {
    position: 'absolute',
    top: 0,
    right: 0
  },
  paceButton: {

  },
  redButton: {
    backgroundColor: '#ff1300'
  },
  greenButton: {
    backgroundColor: '#4cd964'
  },
  text: {
    padding: 2
  }
});

module.exports = Map;
<commit_msg>DEbug location-error issue.  getGeofences issue<commit_after>'use strict';

var React                 = require('react-native');
var Icon                  = require('react-native-vector-icons/Ionicons');
var BackgroundGeolocation = require('react-native-background-geolocation');
var SettingsService       = require('./SettingsService');

var mapRef = 'mapRef';

var {
  AsyncStorage,
  StyleSheet,
  MapView,
  AppStateIOS,
  Text,
  TextInput,
  View,
  SwitchIOS,
  Navigator,
  NavButton,
  TouchableHighlight
} = React;

var Map = React.createClass({

  getInitialState() {
    var me = this;

    AsyncStorage.getItem("state")
    .then((values) => {
      if (values !== null){
        values = JSON.parse(values);
        values.isStationary = true;
        me.setState(values);
        if (values.isEnabled) {
          me.onToggleEnabled(values.isEnabled);
        }
      }
    })
    .catch((error) => console.error("- error: ", error.message))
    .done();

    AppStateIOS.addEventListener('change', this.onAppStateChange);

    this.bgGeo = BackgroundGeolocation;

    // Fetch bg-geo settings.
    SettingsService.getValues(function(values) {

      // Configure Background Geolocation.
      me.bgGeo.configure(values);

      me.bgGeo.getState(function(state) {
        console.log('BackgroundGeolocation state: ', state);
      });

      // Listen to location events coming out.
      me.bgGeo.on('location', me.onBackgroundGeolocation);

      // Listen to motionchange events.
      me.bgGeo.on('motionchange', function(location) {
        console.log('- motionchanged: ', JSON.stringify(location));
        me.setState({
          isStationary: !location.is_moving,
          paceButtonStyle: (location.is_moving) ? styles.redButton : styles.greenButton
        });
      });

      // This fires after plugin successfully synced to server.
      me.bgGeo.on('sync', function(rs) {
        console.log('- sync complete: ', JSON.stringify(rs));
      });

      me.bgGeo.on('error', function(error) {
        alert(error.type + ' error: ' + error.code);
        console.log('- ERROR: ', error.type, error.code);
      });
    });

    return {
      zoom: 11,
      odometer: 0,
      isEnabled: false,
      isStationary: true,
      paceButtonStyle: styles.greenButton,
      navigateButton: 'navigate'
    };
  },
  onAppStateChange(state) {
    if (state === 'active') {
      var me = this;
      me.bgGeo.getCurrentPosition({timeout: 1000}, function(location) {
        console.log('- received current position: ', location);
      }, function(error) {
        alert('Location error: ' + error);
      });
    }
  },
  onClickSettings() {
    this.props.navigator.push({
      id: 'settings',
      sceneConfig: Navigator.SceneConfigs.FloatFromBottom,
    });
  },
  onToggleEnabled(enabled) {
    var me = this;

    if (!enabled && !this.state.isStationary) {
      this.onToggleStationary();
    }
    this.setState({
      isEnabled: enabled,
      odometer: 0
    }, function() {
      AsyncStorage.setItem("state", JSON.stringify(me.state));
    });

    this.bgGeo.resetOdometer(function() {
      console.log('- resetOdometer success');
    });

    if (enabled) {
      this.bgGeo.start(function() {
        // Successfully started.  Now fetch current position.
        me.bgGeo.getCurrentPosition({timeout: 1000}, function(location) {
          console.log('[js] received current position: ', location);
        }, function(error) {
          alert('Location error: ' + error);
        });
      });
    } else {
      this.bgGeo.stop();
    }
  },
  onToggleStationary() {
    var me = this;
    var value = !this.state.isStationary;

    this.setState({
      isStationary: value,
      paceButtonStyle: (value) ? styles.greenButton : styles.redButton
    });

    this.bgGeo.changePace(!value);
  },
  onUpdatePosition() {
    var me = this;
    this.setState({
      navigateButton: 'load-d'
    });

    me.bgGeo.getCurrentPosition({timeout: 1000}, function(location) {
      me.bgGeo.getGeofences(function(rs) {
        console.log('- current geofences: ', rs);
      });
      me.setState({
        navigateButton: 'navigate'
      });
    }, function(error) {
      alert('Location error: ' + error);
      me.setState({
        navigateButton: 'navigate'
      });
    });
  },
  onBackgroundGeolocation(location) {
    console.log('- [js] bgGeo location: ', JSON.stringify(location));
    var me    = this,
        now   = ((location.timestamp) ? new Date(location.timestamp) : new Date()),
        label = [now.getHours(), now.getMinutes(), now.getSeconds()].join(':');

    me.bgGeo.getOdometer(function(distance) {
      me.setState({
        odometer: (distance/1000).toFixed(1)
      });
    });
  },
  onRegionChange(location) {
    //this.setState({ currentZoom: location.zoom });
  },
  onRegionWillChange(location) {
    //console.log(location);
  },
  onUpdateUserLocation(location) {
    //console.log('[js]MapBox location: ', location);
  },
  onOpenAnnotation(annotation) {
    //console.log(annotation);
  },
  onRightAnnotationTapped(e) {
    //console.log(e);
  },
  render: function() {

    return (
      <View style={styles.container}>
        <View style={styles.map}><Text>Map Goes Here</Text></View>
        <View style={styles.toolbar}>
          <TouchableHighlight style={[styles.locationButton, styles.iconButton]} underlayColor={"transparent"} onPress={this.onUpdatePosition}>
            <Icon name={this.state.navigateButton} size={24} color="#4f8ef7" />
          </TouchableHighlight>
          <Text>{this.state.odometer}km</Text>

          <SwitchIOS style={styles.enabledButton} value={this.state.isEnabled} onValueChange={this.onToggleEnabled}></SwitchIOS>

          <TouchableHighlight style={[this.state.paceButtonStyle, styles.stationaryButton, styles.iconButton]} underlayColor={"transparent"} onPress={this.onToggleStationary}>
            <Icon name={this.state.isStationary ? 'play' : 'pause'} size={24} />
          </TouchableHighlight>

        </View>
      </View>
    );
  }
});

var styles = StyleSheet.create({
  container: {
    flex: 1,
    marginTop: 10,
    backgroundColor: 'transparent',
  },
  map: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  toolbar: {
    //top: 50,
    height: 50,
    padding: 5,
    justifyContent: 'center',
    alignItems: 'center'
  },
  settingsButton: {
    position: 'absolute',
    left: 10,
    top: 15
  },
  buttonText: {
    color: 'blue',
    fontSize: 16
  },
  locationButton: {
    position: 'absolute',
    left: 0,
    top: 0
  },
  spinner: {
    position: 'absolute',
    top: 10,
    left: 40
  },
  iconButton: {
    width: 50,
    height: 50,
    justifyContent: 'center',
    alignItems: 'center'
  },
  enabledButton: {
    position: 'absolute',
    top: 10,
    right: 60
  },
  stationaryButton: {
    position: 'absolute',
    top: 0,
    right: 0
  },
  paceButton: {

  },
  redButton: {
    backgroundColor: '#ff1300'
  },
  greenButton: {
    backgroundColor: '#4cd964'
  },
  text: {
    padding: 2
  }
});

module.exports = Map;
<|endoftext|>


<commit_before>Date.prototype.getWeek = function() {
    var onejan = new Date(this.getFullYear(),0,1);
    return Math.ceil((((this - onejan) / 86400000) + onejan.getDay()+1)/7);
};
var jsonToPostParameters = function (json) {
    return Object.keys(json).map(function(k) {
        return encodeURIComponent(k) + '=' + encodeURIComponent(json[k]);
    }).join('&');
};
function getFileNameExtension(filename) {
    var parts = filename.split('.');
    return parts[parts.length - 1];
}
function getFileType(filename) {
    var ext = getFileNameExtension(filename);
    switch (ext.toLowerCase()) {
      case 'jpg':
      case 'jpeg':
      case 'gif':
      case 'bmp':
      case 'png':
        return 'image';
      case 'm4v':
      case 'avi':
      case 'mpg':
      case 'mp4':
        return 'video';
      case 'pdf':
        return 'pdf';
      case 'txt':
        return 'text';
      case 'tex':
        return 'latex';
    }
    return 'other';
}
function clone(obj) {
    // Handle the 3 simple types, and null or undefined
    if (null == obj || "object" != typeof obj) return obj;

    // Handle Date
    if (obj instanceof Date) {
        var copy = new Date();
        copy.setTime(obj.getTime());
        return copy;
    }

    // Handle Array
    if (obj instanceof Array) {
        var copy = [];
        for (var i = 0, len = obj.length; i < len; i++) {
            copy[i] = clone(obj[i]);
        }
        return copy;
    }

    // Handle Object
    if (obj instanceof Object) {
        var copy = {};
        for (var attr in obj) {
            if (obj.hasOwnProperty(attr)) copy[attr] = clone(obj[attr]);
        }
        return copy;
    }

    throw new Error("Unable to copy obj! Its type isn't supported.");
}
function get_radom_color () {
  return (function(m,s,c){return (c ? arguments.callee(m,s,c-1) : '#') +
  s[m.floor(m.random() * s.length)];})(Math,'0123456789ABCDEF',5);
}
function findPosX(obj) {
    var curleft = 0;
    if (obj.offsetParent) {
        while (1) {
            curleft+=obj.offsetLeft;
            if (!obj.offsetParent) {
                break;
            }
            obj=obj.offsetParent;
        }
    } else if (obj.x) {
        curleft+=obj.x;
    }
    return curleft;
};

function findPosY(obj) {
    var curtop = 0;
    if (obj.offsetParent) {
        while (1) {
            curtop+=obj.offsetTop;
            if (!obj.offsetParent) {
                break;
            }
            obj=obj.offsetParent;
        }
    } else if (obj.y) {
        curtop+=obj.y;
    }
    return curtop;
};

var convertToViewportPoint  = function (x, y, dimension) {
    var transform = [
      dimension.scale,
      0,
      0,
      -dimension.scale,
      0,
      dimension.height
    ];

    var xt = x * transform[0] + y * transform[2] + transform[4];
    var yt = x * transform[1] + y * transform[3] + transform[5];
    return [xt, yt];
};<commit_msg>Add utility functions<commit_after>/**
* Get the week number of a date
*/
Date.prototype.getWeek = function() {
    var onejan = new Date(this.getFullYear(),0,1);
    return Math.ceil((((this - onejan) / 86400000) + onejan.getDay()+1)/7);
};
/**
* Transform json to HTTP POST parameters
*/
var jsonToPostParameters = function (json) {
    return Object.keys(json).map(function(k) {
        return encodeURIComponent(k) + '=' + encodeURIComponent(json[k]);
    }).join('&');
};
/*
* Get the file name without the extension
*/
function getFileNameExtension(filename) {
    var parts = filename.split('.');
    return parts[parts.length - 1];
}
/**
* Get the file type of the file based on the extension
*/
function getFileType(filename) {
    var ext = getFileNameExtension(filename);
    switch (ext.toLowerCase()) {
      case 'jpg':
      case 'jpeg':
      case 'gif':
      case 'bmp':
      case 'png':
        return 'image';
      case 'm4v':
      case 'avi':
      case 'mpg':
      case 'mp4':
        return 'video';
      case 'pdf':
        return 'pdf';
      case 'txt':
        return 'text';
      case 'tex':
        return 'latex';
    }
    return 'text';
}
/**
* Clone an object
*/
function clone(obj) {
    // Handle the 3 simple types, and null or undefined
    if (null == obj || "object" != typeof obj) return obj;

    // Handle Date
    if (obj instanceof Date) {
        var copy = new Date();
        copy.setTime(obj.getTime());
        return copy;
    }

    // Handle Array
    if (obj instanceof Array) {
        var copy = [];
        for (var i = 0, len = obj.length; i < len; i++) {
            copy[i] = clone(obj[i]);
        }
        return copy;
    }

    // Handle Object
    if (obj instanceof Object) {
        var copy = {};
        for (var attr in obj) {
            if (obj.hasOwnProperty(attr)) copy[attr] = clone(obj[attr]);
        }
        return copy;
    }

    throw new Error("Unable to copy obj! Its type isn't supported.");
}
/**
* Get absolute position of an element in the dom
*/
function findPosX(obj) {
    var curleft = 0;
    if (obj.offsetParent) {
        while (1) {
            curleft+=obj.offsetLeft;
            if (!obj.offsetParent) {
                break;
            }
            obj=obj.offsetParent;
        }
    } else if (obj.x) {
        curleft+=obj.x;
    }
    return curleft;
};
/**
* Get absolute position of an element in the dom
*/
function findPosY(obj) {
    var curtop = 0;
    if (obj.offsetParent) {
        while (1) {
            curtop+=obj.offsetTop;
            if (!obj.offsetParent) {
                break;
            }
            obj=obj.offsetParent;
        }
    } else if (obj.y) {
        curtop+=obj.y;
    }
    return curtop;
};
/*
* Convert pdf viewport to pixel
*/
var convertToViewportPoint  = function (x, y, dimension) {
    var transform = [
      dimension.scale,
      0,
      0,
      -dimension.scale,
      0,
      dimension.height
    ];

    var xt = x * transform[0] + y * transform[2] + transform[4];
    var yt = x * transform[1] + y * transform[3] + transform[5];
    return [xt, yt];
};

/**
* Create a random hex color
*/
function getRadomColor () {
  return (function(m,s,c){return (c ? arguments.callee(m,s,c-1) : '#') +
  s[m.floor(m.random() * s.length)];})(Math,'0123456789ABCDEF',5);
}

/**
* Define Object.keys if not available
*/
if(Object.keys == null) {
  Object.keys = function (obj) {
    var r = [];
    for (var k in obj) {
        if (!obj.hasOwnProperty(k))
            continue;
        r.push(k);
    }
    return r;
  }
}<|endoftext|>


<commit_before>import createLWTheme from './createThemeDefaults.js';
import grey from '@material-ui/core/colors/grey';
import deepOrange from '@material-ui/core/colors/deepOrange';

const sansSerifStack = [
  'Calibri',
  '"Gill Sans"',
  '"Gill Sans MT"',
  "Myriad Pro",
  'Myriad',
  '"DejaVu Sans Condensed"',
  '"Liberation Sans"',
  '"Nimbus Sans L"',
  'Tahoma',
  'Geneva',
  '"Helvetica Neue"',
  'Helvetica',
  'Arial',
  'sans-serif'
].join(',')

const serifStack = [
  'warnock-pro',
  'Palatino',
  '"Palatino Linotype"',
  '"Palatino LT STD"',
  '"Book Antiqua"',
  'Georgia',
  'serif'
].join(',')

const palette = {
  primary: {
    main: '#5f9b65',
  },
  secondary: {
    main: '#5f9b65',
  },
  lwTertiary: {
    main: "#77947b"
  },
  error: {
    main: deepOrange[900]
  },
  background: {
    default: '#fff'
  }
}

const theme = createLWTheme({
  palette: palette,
  typography: {
    fontFamily: sansSerifStack,
    postStyle: {
      fontFamily: serifStack,
      linkUnderlinePosition: "72%",
    },
    headerStyle: {
      fontFamily: serifStack,
      linkUnderlinePosition: "72%",
    },
    body2: {
      fontSize: "1.16rem"
    },
    commentStyle: {
      fontFamily: sansSerifStack
    },
    headline: {
      fontFamily: serifStack,
    },
    subheading: {
      fontFamily: serifStack,
    },
    title: {
      fontFamily: serifStack,
      fontWeight: 500,
    }
  },
  overrides: {
    MuiAppBar: {
      colorDefault: {
        backgroundColor: grey[50],
      }
    },
    PostsVote: {
      voteScores: {
        margin: "25% 15% 15% 15%"
      }
    },
    MuiTooltip: {
      tooltip: {
        fontSize: "1rem",
        padding: ".7rem",
      }
    },
    MuiDialogContent: {
      root: {
        fontFamily: sansSerifStack,
        fontSize: "1.16rem",
        lineHeight: "1.5em"
      }
    },
    MuiMenuItem: {
      root: {
        fontFamily: sansSerifStack,
        color: grey[800],
        fontSize: "1.1rem",
        lineHeight: "1em"
      }
    },
    MuiListItem: {
      root: {
        paddingTop: 8,
        paddingBottom: 8
      }
    }
  }
});

export default theme
<commit_msg>shade 3<commit_after>import createLWTheme from './createThemeDefaults.js';
import grey from '@material-ui/core/colors/grey';
import deepOrange from '@material-ui/core/colors/deepOrange';

const sansSerifStack = [
  'Calibri',
  '"Gill Sans"',
  '"Gill Sans MT"',
  "Myriad Pro",
  'Myriad',
  '"DejaVu Sans Condensed"',
  '"Liberation Sans"',
  '"Nimbus Sans L"',
  'Tahoma',
  'Geneva',
  '"Helvetica Neue"',
  'Helvetica',
  'Arial',
  'sans-serif'
].join(',')

const serifStack = [
  'warnock-pro',
  'Palatino',
  '"Palatino Linotype"',
  '"Palatino LT STD"',
  '"Book Antiqua"',
  'Georgia',
  'serif'
].join(',')

const palette = {
  primary: {
    main: '#5f9b65',
  },
  secondary: {
    main: '#5f9b65',
  },
  lwTertiary: {
    main: "#69886e"
  },
  error: {
    main: deepOrange[900]
  },
  background: {
    default: '#fff'
  }
}

const theme = createLWTheme({
  palette: palette,
  typography: {
    fontFamily: sansSerifStack,
    postStyle: {
      fontFamily: serifStack,
      linkUnderlinePosition: "72%",
    },
    headerStyle: {
      fontFamily: serifStack,
      linkUnderlinePosition: "72%",
    },
    body2: {
      fontSize: "1.16rem"
    },
    commentStyle: {
      fontFamily: sansSerifStack
    },
    headline: {
      fontFamily: serifStack,
    },
    subheading: {
      fontFamily: serifStack,
    },
    title: {
      fontFamily: serifStack,
      fontWeight: 500,
    }
  },
  overrides: {
    MuiAppBar: {
      colorDefault: {
        backgroundColor: grey[50],
      }
    },
    PostsVote: {
      voteScores: {
        margin: "25% 15% 15% 15%"
      }
    },
    MuiTooltip: {
      tooltip: {
        fontSize: "1rem",
        padding: ".7rem",
      }
    },
    MuiDialogContent: {
      root: {
        fontFamily: sansSerifStack,
        fontSize: "1.16rem",
        lineHeight: "1.5em"
      }
    },
    MuiMenuItem: {
      root: {
        fontFamily: sansSerifStack,
        color: grey[800],
        fontSize: "1.1rem",
        lineHeight: "1em"
      }
    },
    MuiListItem: {
      root: {
        paddingTop: 8,
        paddingBottom: 8
      }
    }
  }
});

export default theme
<|endoftext|>