<commit_before>/**
 * DefineJS v0.2.2
 * Copyright (c) 2014 Mehran Hatami and other define.js contributors.
 * Available via the MIT license.
 * license found at http://github.com/fixjs/define.js/raw/master/LICENSE
 */

(function (global, undefined) {
  // FIX ME! IE9 can give issues in strict mode!
  'use strict';

  //polyfills
  if (!Array.isArray) {
    Array.isArray = function (arg) {
      return Object.prototype.toString.call(arg) === '[object Array]';
    };
  }

  function defineModuleDefinition() {
    var
      doc = global.document,
      currentScript = document.currentScript,
      isArray = Array.isArray,
      emptyArray = [],
      // Mehran!! You need a couple of pre-defined options to avoid
      // the script from throwing in a couple of browsers
      options = {

          // paths:  *-- Define default path or set to 'null
      },
      files = {},
      baseFileInfo,
      baseUrl = '',
      baseGlobal = '',
      waitingList = {},
      urlCache = {},
      definedModules = {},
      modules = {},
      installed = {},
      //So far we we only capture the failure, we need to define a scenario for failed items
      failedList = {};

    function isObject(obj) {
      // http://jsperf.com/isobject4
    return value !== null && typeof value === 'object';
    }

    function isPromiseAlike(object) {
      return isObject(object) && typeof object.then === 'function';
    }

// Mehran! Slow performance!! Steal ECMA7 shim from hAzzleJS,
// and use it instead of indexOf, and reduce 'substring' usage.'
// Nasty looking code !! :)

    function getFileInfo(url) {
      var info = files[url],
        ind;
      if (!isObject(info)) {
        info = {};

        ind = url.indexOf('#');
        if (-1 < ind) {
          info.hash = url.substring(ind); // This code are similar to line #70. Cache and re-use !!
          url = url.substring(0, ind);  // This code are similar to line #71. Cache and re-use !!
        }

        ind = url.indexOf('?');
        if (-1 < ind) {
          info.search = url.substring(ind);
          url = url.substring(0, ind);
        }

        info.fileName = url.substring(url.lastIndexOf('/') + 1);
        ind = info.fileName.lastIndexOf('.');
        if (-1 < ind) {
          info.ext = info.fileName.substring(ind);
          info.fileName = info.fileName.substring(0, ind);
        }
        info.filePath = url.substring(0, url.lastIndexOf('/') + 1);
        files[url] = info;
      }
      return info;
    }

    function getUrl(modulePath) {
      var moduleInfo = getFileInfo(modulePath),
        moduleName = moduleInfo.fileName,
        url,
        urlArgs,
        path,
        pathUrl;

      if (typeof urlCache[moduleName] === 'string') {
        return urlCache[moduleName];
      }

      urlArgs = (typeof options.urlArgs === 'string') ?
        ('?' + options.urlArgs) :
        (typeof options.urlArgs === 'function') ? ('?' + options.urlArgs()) : '';

      if (options.baseUrl) {
        url = options.baseUrl;
      } else {
        url = baseUrl;
      }

      if (isObject(options.paths)) {
        for (path in options.paths) {
          if (options.paths.hasOwnProperty(path)) {
            pathUrl = options.paths[path];

            if (typeof pathUrl === 'string' &&
              modulePath.indexOf(path + '/') === 0) {
              modulePath = modulePath.replace(path, pathUrl);
              break;
            }

          }
        }
      }

    // Mehran! Is substring best alternative? Tried e.g. mehran[0] or charAt() ???

      if (url.substring(url.length - 1) !== '/' &&
        modulePath.substring(0, 1) !== '/') {
        url += '/';
      }

      url += modulePath + '.js' + urlArgs;

      urlCache[moduleName] = url;

      return url;
    }

    // Phantomjs does not provide the "currentScript" property in global document object
    if (currentScript !== undefined) {
      baseFileInfo = getFileInfo(currentScript.src);
      baseUrl = currentScript.getAttribute('base') || baseFileInfo.filePath;
      baseGlobal = currentScript.getAttribute('global');
    }

    // FIX ME! Need evalution. Loading JS files likes this need to
    // be re-written. Main reason of memory leaks and no way here to
    // remove the added listeneres after script are loaded

    function getScript(url, callback) {

      var el = doc.createElement('script'),
      func = function (e) {
        //dependency is loaded successfully
        if (typeof callback === 'function') {
          callback('success');
        }
      };

    /* Mehran! You should add a remover for this one too, and make sure it get triggerd
     * only once
     * Also consider this things:
     *
     * - Events currentTarget (e.g. var node = evt.currentTarget || evt.srcElement; )
     * - onreadystatechange
     *
     */

      el.addEventListener('error', function (e) {
        //missing dependency
        console.error('The script ' + e.target.src + ' is not accessible.');
        if (typeof callback === 'function') {
          callback('error');
        }
      });

      // Load the scripts

      el.addEventListener('load', func, /*no bubbles*/ false);

     // HTML5 spec, not supported in IE9 and older
     // If you use hAzzleJS here or DOM Level 4 specs no worries
     // about this things

     doc.head.appendChild(el);

     el.src = getUrl(url);

     // Remove the listeners once here.

     // MEHRAN !! You should favor detachEvent because of #IE9 issue, or do a check and do both
     // Make sure it's not Opera then, else it will throw!

      el.removeEventListener('load', func, false);
    }

    function executeFN(fn, args) {
      var fnData;
      if (!isArray(args)) {
        args = emptyArray;
      }

      try {
        fnData = fn.apply(undefined, args);
      } catch (ignore) {}

      return fnData;
    }

    function installModule(moduleName, status) {
      var callbacks, fn,
        i = 0, len;

      if (status === 'success') {
        if (!installed[moduleName]) {
          installed[moduleName] = true;
        }
      } else {
        failedList[moduleName] = true;
      }

      callbacks = waitingList[moduleName];

      if (isArray(callbacks)) {
        len = callbacks.length;

        for (; i < len; i += 1) {
          fn = callbacks[i];
      // try / catch slow, need a workaround
          try {
            fn(status);
          } catch (ignored) {}
        }
        waitingList[moduleName] = [];
      }
    }

    function loadModule(modulePath, callback) {
      var isFirstLoadDemand = false,
        moduleInfo = getFileInfo(modulePath),
        moduleName = moduleInfo.fileName;

      if (installed[moduleName]) {
        callback(modules[moduleName]);
      } else {
        if (!isArray(waitingList[moduleName])) {
          waitingList[moduleName] = [];
          isFirstLoadDemand = true;
        }

        waitingList[moduleName].push(callback);

        if (isFirstLoadDemand) {
          getScript(modulePath, function (status) {
            if (definedModules[moduleName] === true) {
              //Do not need to do anything so far
            } else {
              //This code block allows using this library for regular javascript files
              //with no "define" or "require"
              installModule(moduleName, status);
            }
          });
        }
      }
    }

    function loadModules(array, callback) {
      var i = 0,
        len = array.length,
        loaded = [];

      function pCallback(status) {
        loaded.push(status);
        if (loaded.length === len && typeof callback === 'function') {
          callback(loaded);
        }
      }

      for (; i < len; i += 1) {
        loadModule(array[i], pCallback);
      }
    }
   // TODO! Maybe add 'window.Promise' as default, with option for 3Party Promise lib
   // When we are talking about performance
    function setUpModule(moduleName, moduleDefinition, args) {
      var moduleData = executeFN(moduleDefinition, args),
        setUp,
        //we could have checked it out with (moduleData instanceof Promise)
        //But this way we are actually being nice to nonnative promise libraries
        isPromise = isPromiseAlike(moduleData);

      setUp = (function (moduleData, moduleName, isPromise) {
        return function setUp(value) {
          if (isPromise) {
            modules[moduleName] = value;
          } else {
            modules[moduleName] = moduleData;
          }

          installModule(moduleName, 'success');

        };
      }(moduleData, moduleName, isPromise));

      if (isPromise) {
        moduleData.then(setUp);
      } else {
        setUp();
        // setTimeout(setUp, 0);
      }
    }

    function fxdefine(moduleName, array, moduleDefinition) {
      //define(moduleDefinition)
      if (typeof moduleName === 'function') {
        moduleDefinition = moduleName;
        moduleName = undefined;
        array = emptyArray;
      }
      //define(array, moduleDefinition)
      else if (isArray(moduleName)) {
        moduleDefinition = array;
        array = moduleName;
        moduleName = undefined;
      }
      /*
       * Note: (Not a good practice)
       * You can explicitly name modules yourself, but it makes the modules less portable
       * if you move the file to another directory you will need to change the name.
       */
      else if (typeof moduleName === 'string') {
        //define(moduleName, moduleDefinition)
        if (typeof array === 'function') {
          moduleDefinition = array;
          array = emptyArray;
        }
      }

      if (typeof moduleDefinition !== 'function') {
        console.error('Invalid input parameter to define a module');
        return;
      }

      var moduleUrl = document.currentScript.src,
        moduleInfo = getFileInfo(document.currentScript.src);

      if (moduleName === undefined) {
        moduleInfo = getFileInfo(moduleUrl);
        moduleName = moduleInfo.fileName;
      }

      definedModules[moduleName] = true;

      if (isArray(array) && array.length) {
        loadModules(array, function () {
          var args = [],
            i = 0,
            len = array.length;
          for (; i < len; i += 1) {
            args.push(modules[getFileInfo(array[i]).fileName]);
          }
          setUpModule(moduleName, moduleDefinition, args);
        });
      } else {
        setUpModule(moduleName, moduleDefinition);
      }
    }

    function fxrequire(array, fn) {
      if (typeof fn !== 'function') {
        console.error('Invalid input parameter to require a module');
        return;
      }

      if (isArray(array) && array.length) {
        loadModules(array, function () {
          var args = [],
            i = 0,
            len = array.length;
          for (; i < len; i += 1) {
            args.push(modules[getFileInfo(array[i]).fileName]);
          }
          executeFN(fn, args);
        });
      } else {
        executeFN(fn);
      }
    }

    function promiseUse(array) {
      return new Promise(function (fulfill) {
        //this function accepts two params: fulfill, reject

        fxrequire(array, fulfill);

        //FIXME: think of a useful pattern for promised module rejection
        // Alternative solution: Use native browser promises if supported. See my earlier comment

        console.log('Great to see that you are using this function on DefineJS (https://www.npmjs.org/package/definejs)');
        console.log('This function provides a way of requiring your defined modules using a Promise based coding style.');
        console.log('Actually as you might have noticed we are actively extending this module loader, and that\'s why we need your feedback on this.');
        console.log('You could join the chat room on Gitter (https://gitter.im/fixjs/define.js) and provide us with your great ideas and feedbacks.');

        /*
         * OPEN DISCUSSION:
         * module rejection could offer a cool pattern when developing new modules
         * but we first need to have the community's feedback on this
         */
      });
    }

    function fxconfig(cnfOptions) {
      if (!isObject(cnfOptions)) {
        return;
      }
     // Native ( in / for ) loop are faster then Object.keys solution (14%)
      var keys = Object.keys(cnfOptions),
        len = keys.length,
        i = 0;

      while (i < len) {
        options[keys[i]] = cnfOptions[keys[i]];
        i++;
      }
    }

    fxdefine.amd = {};

    function fixDefine(g) {
      g.require = fxrequire;
      g.define = fxdefine;
      g.config = fxconfig;
      g.options = options;

      //Nonstandards
      g.use = promiseUse;

    }

    if (baseGlobal && isObject(global[baseGlobal])) {
      fixDefine(global[baseGlobal]);
      fixDefine._exposed = true;
    }

    return fixDefine;
  }

  if (typeof exports === 'object') {
    module.exports = defineModuleDefinition();
  } else if (typeof define === 'function' && define.amd) {
    define([], defineModuleDefinition);
  } else {
    var moduleFN = defineModuleDefinition();
    if (!moduleFN._exposed) {
      global.fixDefine = moduleFN;
    }
  }
}(this));
<commit_msg>better performance and smaller code size<commit_after>/**
 * DefineJS v0.2.2
 * Copyright (c) 2014 Mehran Hatami and other define.js contributors.
 * Available via the MIT license.
 * license found at http://github.com/fixjs/define.js/raw/master/LICENSE
 */

(function (global, undefined) {
  // FIX ME! IE9 can give issues in strict mode!
  'use strict';

  //polyfills
  if (!Array.isArray) {
    Array.isArray = function (arg) {
      return Object.prototype.toString.call(arg) === '[object Array]';
    };
  }

  function defineModuleDefinition() {
    var
      doc = global.document,
      currentScript = document.currentScript,
      isArray = Array.isArray,
      emptyArray = [],
      // Mehran!! You need a couple of pre-defined options to avoid
      // the script from throwing in a couple of browsers
      options = {

          // paths:  *-- Define default path or set to 'null
      },
      files = {},
      baseFileInfo,
      baseUrl = '',
      baseGlobal = '',
      waitingList = {},
      urlCache = {},
      definedModules = {},
      modules = {},
      installed = {},
      //So far we we only capture the failure, we need to define a scenario for failed items
      failedList = {};

    function isObject(obj) {
      // http://jsperf.com/isobject4
    return value !== null && typeof value === 'object';
    }

    function isFunction(value) {
        return typeof value === 'function';
    }

    function isPromiseLike(object) {
         return obj && isFunction(obj.then);
   }

// Mehran! Slow performance!! Steal ECMA7 shim from hAzzleJS,
// and use it instead of indexOf, and reduce 'substring' usage.'
// Nasty looking code !! :)

    function getFileInfo(url) {
      var info = files[url],
        ind;
      if (!isObject(info)) {
        info = {};

        ind = url.indexOf('#');
        if (-1 < ind) {
          info.hash = url.substring(ind); // This code are similar to line #70. Cache and re-use !!
          url = url.substring(0, ind);  // This code are similar to line #71. Cache and re-use !!
        }

        ind = url.indexOf('?');
        if (-1 < ind) {
          info.search = url.substring(ind);
          url = url.substring(0, ind);
        }

        info.fileName = url.substring(url.lastIndexOf('/') + 1);
        ind = info.fileName.lastIndexOf('.');
        if (-1 < ind) {
          info.ext = info.fileName.substring(ind);
          info.fileName = info.fileName.substring(0, ind);
        }
        info.filePath = url.substring(0, url.lastIndexOf('/') + 1);
        files[url] = info;
      }
      return info;
    }

    function getUrl(modulePath) {
      var moduleInfo = getFileInfo(modulePath),
        moduleName = moduleInfo.fileName,
        url,
        urlArgs,
        path,
        pathUrl;

      if (typeof urlCache[moduleName] === 'string') {
        return urlCache[moduleName];
      }

      urlArgs = (typeof options.urlArgs === 'string') ?
        ('?' + options.urlArgs) :
        (isFunction(options.urlArgs)) ? ('?' + options.urlArgs()) : '';

      if (options.baseUrl) {
        url = options.baseUrl;
      } else {
        url = baseUrl;
      }

      if (isObject(options.paths)) {
        for (path in options.paths) {
          if (options.paths.hasOwnProperty(path)) {
            pathUrl = options.paths[path];

            if (typeof pathUrl === 'string' &&
              modulePath.indexOf(path + '/') === 0) {
              modulePath = modulePath.replace(path, pathUrl);
              break;
            }

          }
        }
      }

    // Mehran! Is substring best alternative? Tried e.g. mehran[0] or charAt() ???

      if (url.substring(url.length - 1) !== '/' &&
        modulePath.substring(0, 1) !== '/') {
        url += '/';
      }

      url += modulePath + '.js' + urlArgs;

      urlCache[moduleName] = url;

      return url;
    }

    // Phantomjs does not provide the "currentScript" property in global document object
    if (currentScript !== undefined) {
      baseFileInfo = getFileInfo(currentScript.src);
      baseUrl = currentScript.getAttribute('base') || baseFileInfo.filePath;
      baseGlobal = currentScript.getAttribute('global');
    }

    // FIX ME! Need evalution. Loading JS files likes this need to
    // be re-written. Main reason of memory leaks and no way here to
    // remove the added listeneres after script are loaded

    function getScript(url, callback) {

      var el = doc.createElement('script'),
      func = function (e) {
        //dependency is loaded successfully
        if (isFunction(typeof callback)) {
          callback('success');
        }
      };

    /* Mehran! You should add a remover for this one too, and make sure it get triggerd
     * only once
     * Also consider this things:
     *
     * - Events currentTarget (e.g. var node = evt.currentTarget || evt.srcElement; )
     * - onreadystatechange
     *
     */

      el.addEventListener('error', function (e) {
        //missing dependency
        console.error('The script ' + e.target.src + ' is not accessible.');
        if (isFunction(callback)) {
          callback('error');
        }
      });

      // Load the scripts

      el.addEventListener('load', func, /*no bubbles*/ false);

     // HTML5 spec, not supported in IE9 and older
     // If you use hAzzleJS here or DOM Level 4 specs no worries
     // about this things

     doc.head.appendChild(el);

     el.src = getUrl(url);

     // Remove the listeners once here.

     // MEHRAN !! You should favor detachEvent because of #IE9 issue, or do a check and do both
     // Make sure it's not Opera then, else it will throw!

      el.removeEventListener('load', func, false);
    }

    function executeFN(fn, args) {
      var fnData;
      if (!isArray(args)) {
        args = emptyArray;
      }

      try {
        fnData = fn.apply(undefined, args);
      } catch (ignore) {}

      return fnData;
    }

    function installModule(moduleName, status) {
      var callbacks, fn,
        i = 0, len;

      if (status === 'success') {
        if (!installed[moduleName]) {
          installed[moduleName] = true;
        }
      } else {
        failedList[moduleName] = true;
      }

      callbacks = waitingList[moduleName];

      if (isArray(callbacks)) {
        len = callbacks.length;

        for (; i < len; i += 1) {
          fn = callbacks[i];
      // try / catch slow, need a workaround
          try {
            fn(status);
          } catch (ignored) {}
        }
        waitingList[moduleName] = [];
      }
    }

    function loadModule(modulePath, callback) {
      var isFirstLoadDemand = false,
        moduleInfo = getFileInfo(modulePath),
        moduleName = moduleInfo.fileName;

      if (installed[moduleName]) {
        callback(modules[moduleName]);
      } else {
        if (!isArray(waitingList[moduleName])) {
          waitingList[moduleName] = [];
          isFirstLoadDemand = true;
        }

        waitingList[moduleName].push(callback);

        if (isFirstLoadDemand) {
          getScript(modulePath, function (status) {
            if (definedModules[moduleName] === true) {
              //Do not need to do anything so far
            } else {
              //This code block allows using this library for regular javascript files
              //with no "define" or "require"
              installModule(moduleName, status);
            }
          });
        }
      }
    }

    function loadModules(array, callback) {
      var i = 0,
        len = array.length,
        loaded = [];

      function pCallback(status) {
        loaded.push(status);
        if (loaded.length === len && isFunction(callback)) {
          callback(loaded);
        }
      }

      for (; i < len; i += 1) {
        loadModule(array[i], pCallback);
      }
    }
   // TODO! Maybe add 'window.Promise' as default, with option for 3Party Promise lib
   // When we are talking about performance
    function setUpModule(moduleName, moduleDefinition, args) {
      var moduleData = executeFN(moduleDefinition, args),
        setUp,
        //we could have checked it out with (moduleData instanceof Promise)
        //But this way we are actually being nice to nonnative promise libraries
        isPromise = isPromiseLike(moduleData);

      setUp = (function (moduleData, moduleName, isPromise) {
        return function setUp(value) {
          if (isPromise) {
            modules[moduleName] = value;
          } else {
            modules[moduleName] = moduleData;
          }

          installModule(moduleName, 'success');

        };
      }(moduleData, moduleName, isPromise));

      if (isPromise) {
        moduleData.then(setUp);
      } else {
        setUp();
        // setTimeout(setUp, 0);
      }
    }

    function fxdefine(moduleName, array, moduleDefinition) {
      //define(moduleDefinition)
      if (isFunction(moduleName)) {
        moduleDefinition = moduleName;
        moduleName = undefined;
        array = emptyArray;
      }
      //define(array, moduleDefinition)
      else if (isArray(moduleName)) {
        moduleDefinition = array;
        array = moduleName;
        moduleName = undefined;
      }
      /*
       * Note: (Not a good practice)
       * You can explicitly name modules yourself, but it makes the modules less portable
       * if you move the file to another directory you will need to change the name.
       */
      else if (typeof moduleName === 'string') {
        //define(moduleName, moduleDefinition)
        if (isFunction(array)) {
          moduleDefinition = array;
          array = emptyArray;
        }
      }

      if (!isFunction(moduleDefinition)) {
        console.error('Invalid input parameter to define a module');
        return;
      }

      var moduleUrl = document.currentScript.src,
        moduleInfo = getFileInfo(document.currentScript.src);

      if (moduleName === undefined) {
        moduleInfo = getFileInfo(moduleUrl);
        moduleName = moduleInfo.fileName;
      }

      definedModules[moduleName] = true;

      if (isArray(array) && array.length) {
        loadModules(array, function () {
          var args = [],
            i = 0,
            len = array.length;
          for (; i < len; i += 1) {
            args.push(modules[getFileInfo(array[i]).fileName]);
          }
          setUpModule(moduleName, moduleDefinition, args);
        });
      } else {
        setUpModule(moduleName, moduleDefinition);
      }
    }

    function fxrequire(array, fn) {
      if (!isFunction(fn)) {
        console.error('Invalid input parameter to require a module');
        return;
      }

      if (isArray(array) && array.length) {
        loadModules(array, function () {
          var args = [],
            i = 0,
            len = array.length;
          for (; i < len; i += 1) {
            args.push(modules[getFileInfo(array[i]).fileName]);
          }
          executeFN(fn, args);
        });
      } else {
        executeFN(fn);
      }
    }

    function promiseUse(array) {
      return new Promise(function (fulfill) {
        //this function accepts two params: fulfill, reject

        fxrequire(array, fulfill);

        //FIXME: think of a useful pattern for promised module rejection
        // Alternative solution: Use native browser promises if supported. See my earlier comment

        console.log('Great to see that you are using this function on DefineJS (https://www.npmjs.org/package/definejs)');
        console.log('This function provides a way of requiring your defined modules using a Promise based coding style.');
        console.log('Actually as you might have noticed we are actively extending this module loader, and that\'s why we need your feedback on this.');
        console.log('You could join the chat room on Gitter (https://gitter.im/fixjs/define.js) and provide us with your great ideas and feedbacks.');

        /*
         * OPEN DISCUSSION:
         * module rejection could offer a cool pattern when developing new modules
         * but we first need to have the community's feedback on this
         */
      });
    }

    function fxconfig(cnfOptions) {
      if (!isObject(cnfOptions)) {
        return;
      }
     // Native ( in / for ) loop are faster then Object.keys solution (14%)
      var keys = Object.keys(cnfOptions),
        len = keys.length,
        i = 0;

      while (i < len) {
        options[keys[i]] = cnfOptions[keys[i]];
        i++;
      }
    }

    fxdefine.amd = {};

    function fixDefine(g) {
      g.require = fxrequire;
      g.define = fxdefine;
      g.config = fxconfig;
      g.options = options;

      //Nonstandards
      g.use = promiseUse;

    }

    if (baseGlobal && isObject(global[baseGlobal])) {
      fixDefine(global[baseGlobal]);
      fixDefine._exposed = true;
    }

    return fixDefine;
  }

  if (typeof exports === 'object') {
    module.exports = defineModuleDefinition();
  } else if (isFunction(define) && define.amd) {
    define([], defineModuleDefinition);
  } else {
    var moduleFN = defineModuleDefinition();
    if (!moduleFN._exposed) {
      global.fixDefine = moduleFN;
    }
  }
}(this));
<|endoftext|>


<commit_before>/*
    Copyright 2009,2010 Emilis Dambauskas

    This file is part of PolicyFeed module.

    PolicyFeed is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    PolicyFeed is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with PolicyFeed.  If not, see <http://www.gnu.org/licenses/>.
*/

var DomElement = com.gargoylesoftware.htmlunit.html.DomElement;

var fs = require("fs");
var htmlunit = require("htmlunit");
var UrlQueue = require("PolicyFeed/UrlQueue");
var UrlList = require("PolicyFeed/UrlList");
var BrowserController = require("PolicyFeed/BrowserController");
var JsonStorage = require("ctl/JsonStorage");
var Sequence = require("ctl/SimpleSequence");

var filters = {
    "default": require("PolicyFeed/filters/default"),
    abiword: require("PolicyFeed/filters/abiword"),
};

exports.parsers = {};

/**
 *
 */
exports.getParserList = function(parser_dir, parser_prefix) {
    var list = {};

    var parser_names = fs.list(parser_dir);
    for each (var name in parser_names) {
        if (name[0] != ".") {
            // remove ".js" extension:
            name = name.substr(0, name.length - 3);
            list[name] = require(parser_prefix + name);
            if (list[name].disabled)
                delete list[name];
        }
    }

    return list;
}

/**
 *
 */
exports.getDomains = function() {
    var domains = {};

    for each (var parser in this.parsers) {
        if (parser.domains) {
            for (var domain in parser.domains) {
                domains[domain] = { delay: parser.domains[domain] };
            }
        } else {
            if (parser.feed_url instanceof Array) {
                for each (var url in parser.feed_url) {
                    domains[UrlQueue.getDomainFromUrl(url)] = {};
                }
            } else {
                domains[UrlQueue.getDomainFromUrl(parser.feed_url)] = {};
            }
        }
    }

    return domains;
}

/**
 *
 */
exports.init = function(options) {
    options = options || {};
    var {parser_dir, parser_prefix} = options;

    this.parsers = this.getParserList(parser_dir, parser_prefix);

    for (var name in this.parsers) {
        this.parsers[name].name = name;
        this.parsers[name].Crawler = this;
    }

    UrlQueue.init({ domainList: this.getDomains() });

    BrowserController.init(this, UrlQueue);
    BrowserController.start();
}

/**
 *
 */
exports.checkUpdates = function() {
    for (var name in this.parsers) {
        var urls = this.parsers[name].feed_url;
        if (!(urls instanceof Array))
            urls = [urls];

        for each (var url in urls) {
            if (!UrlQueue.isUrlScheduled(url)) {
                UrlQueue.scheduleUrl({
                    url: url,
                    parser: name,
                    method: "checkFeed"
                    }, 0);
            }
        }
    }
}

/**
 *
 */
exports.processUrl = function(url, page) {
    switch (url.method) {
        case "checkFeed":
            return this.checkFeed(url.parser, url, page);
        break;
        case "parsePage":
            return this.parsePage(url.parser, url, page);
        break;
        default:
            return this.parsers[url.parser][url.method](url, page);
    }
}

/**
 *
 */
exports.checkFeed = function(parser_name, url, page) {

    var urls = this.parsers[parser_name].extractFeedItems(page);

    // Remove existing urls:
    urls = urls.filter(function (item) {
        if (UrlList.exists(item.url))
            return false;
        else
            return true;
        });

    // Save url to originals, add to UrlList and UrlQueue:
    urls.map(function (item) {
        // create originals:
        var id = "/originals/" + item.published.substr(0, 10).replace(/-/g, "/") + "/";
        id += Sequence.next();

        print("adding page:", id, item.published, item.url, item.title);

        JsonStorage.write(id, item);
        UrlList.addUrl(item.url, id);

        UrlQueue.addUrl({
            url: item.url,
            parser: parser_name,
            method: "parsePage",
            original_id: id
            });
    });

    // schedule next check:
    UrlQueue.scheduleUrl(url, new Date(new Date().getTime() + 5*60*1000));
}

/**
 *
 */
exports.parsePage = function(parser_name, url, page) {
    var parser = this.parsers[parser_name];

    if (parser.parsePage) {
        return parser.parsePage(url, page);
    } else {
        var original = this.saveOriginal(parser_name, url, page);
        var doc = parser.extractPageData(original, page);

        // run default filters on doc html:
        if (doc.html instanceof DomElement) {
            doc.text = doc.html.asText();
            doc.html = filters["default"].filterXml(doc.html).asXml();
        }
        doc.html = filters["default"].filter(doc.html);
        if (doc.converted_by == "abiword")
            doc.html = filters["abiword"].filter(doc.html)

        JsonStorage.write(doc._id, doc);
    }
}

/**
 *
 */
exports.reindexDoc = function(doc_id) {
    var doc = JsonStorage.read(doc_id);

    var url = { url: doc.url, parser: doc.parser };
    url.method = "parsePage";
    url.original_id = doc._id.replace("docs", "originals");

    return UrlQueue.addUrl(url);
}

/**
 *
 */
exports.reindexUrl = function(url) {
    return this.reindexDoc( UrlList.getDocId(url) );
}

/**
 *
 */
exports.saveOriginal = function(parser_name, url, page) {
    var original = JsonStorage.read(url.original_id);

    var response = page.getWebResponse();
    original.content_type = response.getContentType();

    // DOC files, etc.:
    if (page instanceof com.gargoylesoftware.htmlunit.UnexpectedPage) {
        original.original_file = this.saveOriginalFile(original._id, url.url, response);
        if (original.content_type == "application/msword") {
            var fields = this.getFieldsFromDoc(original.original_file);
            for (var key in fields)
                original[key] = fields[key];
        } else {
            throw Error("PolicyFeed/Crawler.saveOriginal: Unsupported page type.", url.original_id + " | " + url.url);
        }
    } else if (page instanceof com.gargoylesoftware.htmlunit.SgmlPage) {
        // Sgml page is parent class for HtmlPage, XmlPage and XhtmlPage.
        htmlunit.setPageCharset(page, "UTF-8");
        original.html = page.asXml();
    }
    else
        throw Error("PolicyFeed/Crawler.saveOriginal: Unsupported page type.", url.original_id + " | " + url.url);

    // save original:
    JsonStorage.write(original._id, original);

    return original;
}

/**
 *
 */
exports.saveOriginalFile = function(original_id, url, response) {
    var dir_name = require("config").UPLOADS_DIR + original_id.replace("/originals/", "/");
    var file_name = dir_name + "/"
        + url.split("/").pop().replace(/[^-._a-z0-9]/gi, "-");

    if (!fs.exists(dir_name))
        fs.makeTree(dir_name);

    var stream = new (require("io").Stream)(response.getContentAsStream());
    fs.write(file_name, stream.read());

    return file_name;
}

/**
 *
 */
exports.getFieldsFromDoc = function(file_name) {
    var fields = {};

    var html_file_name = fs.directory(file_name) + "/converted.html";

    // Convert file to HTML and read the result if possible:
    var proc = java.lang.Runtime.getRuntime().exec(["abiword", "--to", html_file_name, file_name]);
    proc.waitFor();

    // Set html field:
    fields.html = fs.read(html_file_name);
    fields.converted_by = "abiword";

    // Remove converted HTML to save disk space:
    //fs.remove(html_file_name);
    loadObject("Events").create("PolicyFeed/Crawler.setFieldsFromDoc-debug", ["html_file_name", html_file_name]);

    return fields;
}

<commit_msg>Now converting Abiword documents in the same thread browser window.<commit_after>/*
    Copyright 2009,2010 Emilis Dambauskas

    This file is part of PolicyFeed module.

    PolicyFeed is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    PolicyFeed is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with PolicyFeed.  If not, see <http://www.gnu.org/licenses/>.
*/

var DomElement = com.gargoylesoftware.htmlunit.html.DomElement;

var fs = require("fs");
var htmlunit = require("htmlunit");
var UrlQueue = require("PolicyFeed/UrlQueue");
var UrlList = require("PolicyFeed/UrlList");
var BrowserController = require("PolicyFeed/BrowserController");
var JsonStorage = require("ctl/JsonStorage");
var Sequence = require("ctl/SimpleSequence");

var filters = {
    "default": require("PolicyFeed/filters/default"),
    abiword: require("PolicyFeed/filters/abiword"),
};

exports.parsers = {};

/**
 *
 */
exports.getParserList = function(parser_dir, parser_prefix) {
    var list = {};

    var parser_names = fs.list(parser_dir);
    for each (var name in parser_names) {
        if (name[0] != ".") {
            // remove ".js" extension:
            name = name.substr(0, name.length - 3);
            list[name] = require(parser_prefix + name);
            if (list[name].disabled)
                delete list[name];
        }
    }

    return list;
}

/**
 *
 */
exports.getDomains = function() {
    var domains = {};

    for each (var parser in this.parsers) {
        if (parser.domains) {
            for (var domain in parser.domains) {
                domains[domain] = { delay: parser.domains[domain] };
            }
        } else {
            if (parser.feed_url instanceof Array) {
                for each (var url in parser.feed_url) {
                    domains[UrlQueue.getDomainFromUrl(url)] = {};
                }
            } else {
                domains[UrlQueue.getDomainFromUrl(parser.feed_url)] = {};
            }
        }
    }

    return domains;
}

/**
 *
 */
exports.init = function(options) {
    options = options || {};
    var {parser_dir, parser_prefix} = options;

    this.parsers = this.getParserList(parser_dir, parser_prefix);

    for (var name in this.parsers) {
        this.parsers[name].name = name;
        this.parsers[name].Crawler = this;
    }

    UrlQueue.init({ domainList: this.getDomains() });

    BrowserController.init(this, UrlQueue);
    BrowserController.start();
}

/**
 *
 */
exports.checkUpdates = function() {
    for (var name in this.parsers) {
        var urls = this.parsers[name].feed_url;
        if (!(urls instanceof Array))
            urls = [urls];

        for each (var url in urls) {
            if (!UrlQueue.isUrlScheduled(url)) {
                UrlQueue.scheduleUrl({
                    url: url,
                    parser: name,
                    method: "checkFeed"
                    }, 0);
            }
        }
    }
}

/**
 *
 */
exports.processUrl = function(url, page) {
    switch (url.method) {
        case "checkFeed":
            return this.checkFeed(url.parser, url, page);
        break;
        case "parsePage":
            return this.parsePage(url.parser, url, page);
        break;
        default:
            return this.parsers[url.parser][url.method](url, page);
    }
}

/**
 *
 */
exports.checkFeed = function(parser_name, url, page) {

    var urls = this.parsers[parser_name].extractFeedItems(page);

    // Remove existing urls:
    urls = urls.filter(function (item) {
        if (UrlList.exists(item.url))
            return false;
        else
            return true;
        });

    // Save url to originals, add to UrlList and UrlQueue:
    urls.map(function (item) {
        // create originals:
        var id = "/originals/" + item.published.substr(0, 10).replace(/-/g, "/") + "/";
        id += Sequence.next();

        print("adding page:", id, item.published, item.url, item.title);

        JsonStorage.write(id, item);
        UrlList.addUrl(item.url, id);

        UrlQueue.addUrl({
            url: item.url,
            parser: parser_name,
            method: "parsePage",
            original_id: id
            });
    });

    // schedule next check:
    UrlQueue.scheduleUrl(url, new Date(new Date().getTime() + 5*60*1000));
}

/**
 *
 */
exports.parsePage = function(parser_name, url, page) {
    var parser = this.parsers[parser_name];

    if (parser.parsePage) {
        return parser.parsePage(url, page);
    } else {
        var original = this.saveOriginal(parser_name, url, page);
        var doc = parser.extractPageData(original, page);

        // run default filters on doc html:
        if (doc.html instanceof DomElement) {
            doc.text = doc.html.asText();
            doc.html = filters["default"].filterXml(doc.html).asXml();
        }

        doc.html = filters["default"].filter(doc.html);

        // run abiword filters:
        if (doc.converted_by == "abiword") {
            var window_name = page.getEnclosingWindow().name;
            doc.html = filters["abiword"].filter(
                htmlunit.getPageFromHtml(doc.html, url.url, window_name, "UTF-8")
                );
        }

        JsonStorage.write(doc._id, doc);
    }
}

/**
 *
 */
exports.reindexDoc = function(doc_id) {
    var doc = JsonStorage.read(doc_id);

    var url = { url: doc.url, parser: doc.parser };
    url.method = "parsePage";
    url.original_id = doc._id.replace("docs", "originals");

    return UrlQueue.addUrl(url);
}

/**
 *
 */
exports.reindexUrl = function(url) {
    return this.reindexDoc( UrlList.getDocId(url) );
}

/**
 *
 */
exports.saveOriginal = function(parser_name, url, page) {
    var original = JsonStorage.read(url.original_id);

    var response = page.getWebResponse();
    original.content_type = response.getContentType();

    // DOC files, etc.:
    if (page instanceof com.gargoylesoftware.htmlunit.UnexpectedPage) {
        original.original_file = this.saveOriginalFile(original._id, url.url, response);
        if (original.content_type == "application/msword") {
            var fields = this.getFieldsFromDoc(original.original_file);
            for (var key in fields)
                original[key] = fields[key];
        } else {
            throw Error("PolicyFeed/Crawler.saveOriginal: Unsupported page type.", url.original_id + " | " + url.url);
        }
    } else if (page instanceof com.gargoylesoftware.htmlunit.SgmlPage) {
        // Sgml page is parent class for HtmlPage, XmlPage and XhtmlPage.
        htmlunit.setPageCharset(page, "UTF-8");
        original.html = page.asXml();
    }
    else
        throw Error("PolicyFeed/Crawler.saveOriginal: Unsupported page type.", url.original_id + " | " + url.url);

    // save original:
    JsonStorage.write(original._id, original);

    return original;
}

/**
 *
 */
exports.saveOriginalFile = function(original_id, url, response) {
    var dir_name = require("config").UPLOADS_DIR + original_id.replace("/originals/", "/");
    var file_name = dir_name + "/"
        + url.split("/").pop().replace(/[^-._a-z0-9]/gi, "-");

    if (!fs.exists(dir_name))
        fs.makeTree(dir_name);

    var stream = new (require("io").Stream)(response.getContentAsStream());
    fs.write(file_name, stream.read());

    return file_name;
}

/**
 *
 */
exports.getFieldsFromDoc = function(file_name) {
    var fields = {};

    var html_file_name = fs.directory(file_name) + "/converted.html";

    // Convert file to HTML and read the result if possible:
    var proc = java.lang.Runtime.getRuntime().exec(["abiword", "--to", html_file_name, file_name]);
    proc.waitFor();

    // Set html field:
    fields.html = fs.read(html_file_name);
    fields.converted_by = "abiword";

    // Remove converted HTML to save disk space:
    //fs.remove(html_file_name);
    loadObject("Events").create("PolicyFeed/Crawler.getFieldsFromDoc-debug", ["html_file_name", html_file_name]);

    return fields;
}

<|endoftext|>


<commit_before><commit_msg>Changed gear symbol so it'll show for iOS users<commit_after><|endoftext|>


<commit_before>function click_clear_button() {
  $(".form-control").val("").focus();
}

$(document).ready(function() {
  $(document).on('click', '.star', function(e) {
    var id = $(this).attr('honyomi-id');
    var page_no = $(this).attr('honyomi-page-no');
    var title = $(this).attr('honyomi-title');

    if (!$(this).hasClass('favorited')) {
      // NEW
      $(this).addClass('favorited');

      var num = parseInt($(".boomark-number").text());
      $(".boomark-number").text(num + 1);

      // ajax
      $.post(
        '/command',
        {
          kind:      'favorite',
          id:        id,
          page_no:   page_no,
          favorited: true
        },
        function(data) {
          // Return a result of POST
        }
      );

    } else {
      // EDIT
      $('#modal-bookmark-label').html(
        "" +
        title + " (P" + page_no + ")"
      );

      $(".modal-body textarea").val($(this).attr('honyomi-comment'));

      $('#modal-bookmark-edit').modal();
    }

    e.preventDefault();
  });

  var updateMemo = function () {
    var id = $(".modal-bookmark-data").attr('honyomi-id');
    var page_no = $(".modal-bookmark-data").attr('honyomi-page-no');
    var comment = $(".modal-body textarea").val();

    $("#star-" + id + "-" + page_no).attr("honyomi-comment", comment);

    $.post(
      '/command',
      {
        kind:      'favorite-update',
        id:        id,
        page_no:   page_no,
        comment:   comment
      },
      function(data) {
        var comment = $("#" + page_no + " .comment");

        if (comment.size() == 0) {
          $('
' + data + '
').insertBefore("#" + page_no + " .main");
        } else {
          comment.html(data);
        }
      }
    );
  }

  $("#modal-bookmark-edit .btn-primary").click(function (e) {
    updateMemo();
  });

  $(".modal-body textarea").keydown(function (e) {
    if (e.ctrlKey && e.keyCode == 13) {
      $('#modal-bookmark-edit').modal('hide');
      updateMemo();
    }
  });

  $("#modal-bookmark-edit .btn-danger").click(function (e) {
    var id = $(".modal-bookmark-data").attr('honyomi-id');
    var page_no = $(".modal-bookmark-data").attr('honyomi-page-no');

    if (confirm("Delete this bookmark?")) {
      $("#star-" + id + "-" + page_no).removeClass('favorited');
      $("#" + page_no + " .comment").remove();

      var num = parseInt($(".boomark-number").text());
      $(".boomark-number").text(num - 1);

      $.post(
        '/command',
        {
          kind:      'favorite',
          id:        id,
          page_no:   page_no,
          favorited: false
        }
      );
    }
  });

  $(".edit-link").click(function (e) {
    $(".title").addClass('hide');
    $(".title-form").removeClass('hide');
    $("#title-form-title").val($("#book-title").text());
    $("#title-form-author").val($("#book-author").text());
    $("#title-form-url").val($("#book-url").text());
  });

  var hideTitleForm = function() {
    $(".title").removeClass('hide');
    $(".title-form").addClass('hide');
  }

  $("#title-form-save").click(function (e) {
    var id = $("#book-title").attr('honyomi-book-id');
    var title = $("#title-form-title").val();
    var author = $("#title-form-author").val();
    var url = $("#title-form-url").val();

    $("#book-title").text(title);
    $("#book-author").text(author);
    $("#book-url").attr('href', url);
    $("#book-url").text(url);

    $.post(
      '/command',
      {
        kind:      'title-form-save',
        id:        id,
        title:     title,
        author:    author,
        url:       url
      },
      function(data) {
        // Return a result of POST
      }
    );

    hideTitleForm();
  });

  $("#title-form-cancel").click(function (e) {
    hideTitleForm();
  });

  $(function() {
    document.addEventListener("dragover", function(e) {
      e.preventDefault();
    }, true);

    $('.droparea').on('drop', function(e) {
      e.preventDefault();
      e.stopPropagation();

      var files = e.originalEvent.dataTransfer.files;

      var fd = new FormData();

      for (var i = 0; i < files.length; i++) {
        fd.append("files[]", files[i]);
      }

      $.ajax({
        url: "/upload",
        type: "POST",
        data: fd,
        processData: false,
        contentType: false,
        success: function(msg) {
          document.location = "/";
        }
      });

      return false;
    });
  });

});<commit_msg>Add confirming<commit_after>function click_clear_button() {
  $(".form-control").val("").focus();
}

$(document).ready(function() {
  $(document).on('click', '.star', function(e) {
    var id = $(this).attr('honyomi-id');
    var page_no = $(this).attr('honyomi-page-no');
    var title = $(this).attr('honyomi-title');

    if (!$(this).hasClass('favorited')) {
      // NEW
      $(this).addClass('favorited');

      var num = parseInt($(".boomark-number").text());
      $(".boomark-number").text(num + 1);

      // ajax
      $.post(
        '/command',
        {
          kind:      'favorite',
          id:        id,
          page_no:   page_no,
          favorited: true
        },
        function(data) {
          // Return a result of POST
        }
      );

    } else {
      // EDIT
      $('#modal-bookmark-label').html(
        "" +
        title + " (P" + page_no + ")"
      );

      $(".modal-body textarea").val($(this).attr('honyomi-comment'));

      $('#modal-bookmark-edit').modal();
    }

    e.preventDefault();
  });

  var updateMemo = function () {
    var id = $(".modal-bookmark-data").attr('honyomi-id');
    var page_no = $(".modal-bookmark-data").attr('honyomi-page-no');
    var comment = $(".modal-body textarea").val();

    $("#star-" + id + "-" + page_no).attr("honyomi-comment", comment);

    $.post(
      '/command',
      {
        kind:      'favorite-update',
        id:        id,
        page_no:   page_no,
        comment:   comment
      },
      function(data) {
        var comment = $("#" + page_no + " .comment");

        if (comment.size() == 0) {
          $('
' + data + '
').insertBefore("#" + page_no + " .main");
        } else {
          comment.html(data);
        }
      }
    );
  }

  $("#modal-bookmark-edit .btn-primary").click(function (e) {
    updateMemo();
  });

  $(".modal-body textarea").keydown(function (e) {
    if (e.ctrlKey && e.keyCode == 13) {
      $('#modal-bookmark-edit').modal('hide');
      updateMemo();
    }
  });

  $("#modal-bookmark-edit .btn-danger").click(function (e) {
    var id = $(".modal-bookmark-data").attr('honyomi-id');
    var page_no = $(".modal-bookmark-data").attr('honyomi-page-no');

    if (confirm("Delete this bookmark?")) {
      $("#star-" + id + "-" + page_no).removeClass('favorited');
      $("#" + page_no + " .comment").remove();

      var num = parseInt($(".boomark-number").text());
      $(".boomark-number").text(num - 1);

      $.post(
        '/command',
        {
          kind:      'favorite',
          id:        id,
          page_no:   page_no,
          favorited: false
        }
      );
    }
  });

  $(".edit-link").click(function (e) {
    $(".title").addClass('hide');
    $(".title-form").removeClass('hide');
    $("#title-form-title").val($("#book-title").text());
    $("#title-form-author").val($("#book-author").text());
    $("#title-form-url").val($("#book-url").text());
  });

  var hideTitleForm = function() {
    $(".title").removeClass('hide');
    $(".title-form").addClass('hide');
  }

  $("#title-form-save").click(function (e) {
    var id = $("#book-title").attr('honyomi-book-id');
    var title = $("#title-form-title").val();
    var author = $("#title-form-author").val();
    var url = $("#title-form-url").val();

    $("#book-title").text(title);
    $("#book-author").text(author);
    $("#book-url").attr('href', url);
    $("#book-url").text(url);

    $.post(
      '/command',
      {
        kind:      'title-form-save',
        id:        id,
        title:     title,
        author:    author,
        url:       url
      },
      function(data) {
        // Return a result of POST
      }
    );

    hideTitleForm();
  });

  $("#title-form-cancel").click(function (e) {
    hideTitleForm();
  });

  $(function() {
    document.addEventListener("dragover", function(e) {
      e.preventDefault();
    }, true);

    $('.droparea').on('drop', function(e) {
      e.preventDefault();
      e.stopPropagation();

      var files = e.originalEvent.dataTransfer.files;

      var fd = new FormData();

      for (var i = 0; i < files.length; i++) {
        fd.append("files[]", files[i]);
      }

      if (confirm("Upload?")) {
        $.ajax({
          url: "/upload",
          type: "POST",
          data: fd,
          processData: false,
          contentType: false,
          success: function(msg) {
          document.location = "/";
        }
        });
      }

      return false;
    });
  });

});<|endoftext|>


<commit_before>// install   :   cordova plugins add https://github.com/vstirbu/InstagramPlugin.git
// link      :   https://github.com/vstirbu/InstagramPlugin

/* globals Instagram: true */
angular.module('ngCordova.plugins.instagram', [])

.factory('$cordovaInstagram', ['$q', function ($q) {

  return {
    share: function (options) {
      var q = $q.defer();

      if (!window.Instagram) {
        console.error('Tried to call Instagram.share but the Instagram plugin isn\'t installed!');
        q.resolve(null);
        return q.promise;
      }

      Instagram.share(options.image, options.caption, function (err) {
        if(err) {
          q.reject(err);
        } else {
          q.resolve(true);
        }
      });
      return q.promise;
    },
    isInstalled: function () {
      var q = $q.defer();

      if (!window.Instagram) {
        console.error('Tried to call Instagram.isInstalled but the Instagram plugin isn\'t installed!');
        q.resolve(null);
        return q.promise;
      }

      Instagram.isInstalled(function (err, installed) {
        if (err) {
          q.reject(err);
        } else {
          q.resolve(installed || true);
        }
      });
      return q.promise;
    }
  };
}]);
<commit_msg>Prevent Instagram.isInstalled from always returning true<commit_after>// install   :   cordova plugins add https://github.com/vstirbu/InstagramPlugin.git
// link      :   https://github.com/vstirbu/InstagramPlugin

/* globals Instagram: true */
angular.module('ngCordova.plugins.instagram', [])

.factory('$cordovaInstagram', ['$q', function ($q) {

  return {
    share: function (options) {
      var q = $q.defer();

      if (!window.Instagram) {
        console.error('Tried to call Instagram.share but the Instagram plugin isn\'t installed!');
        q.resolve(null);
        return q.promise;
      }

      Instagram.share(options.image, options.caption, function (err) {
        if(err) {
          q.reject(err);
        } else {
          q.resolve(true);
        }
      });
      return q.promise;
    },
    isInstalled: function () {
      var q = $q.defer();

      if (!window.Instagram) {
        console.error('Tried to call Instagram.isInstalled but the Instagram plugin isn\'t installed!');
        q.resolve(null);
        return q.promise;
      }

      Instagram.isInstalled(function (err, installed) {
        if (err) {
          q.reject(err);
        } else {
          q.resolve(installed);
        }
      });
      return q.promise;
    }
  };
}]);
<|endoftext|>


<commit_before>/* Port of strftime(). Compatibility notes:
 *
 * %c - formatted string is slightly different
 * %D - not implemented (use "%m/%d/%y" or "%d/%m/%y")
 * %e - space is not added
 * %E - not implemented
 * %h - not implemented (use "%b")
 * %k - space is not added
 * %n - not implemented (use "\n")
 * %O - not implemented
 * %r - not implemented (use "%I:%M:%S %p")
 * %R - not implemented (use "%H:%M")
 * %t - not implemented (use "\t")
 * %T - not implemented (use "%H:%M:%S")
 * %U - not implemented
 * %W - not implemented
 * %+ - not implemented
 * %% - not implemented (use "%")
 *
 * strftime() reference:
 * http://man7.org/linux/man-pages/man3/strftime.3.html
 *
 * Day of year (%j) code based on Joe Orost's answer:
 * http://stackoverflow.com/questions/8619879/javascript-calculate-the-day-of-the-year-1-366
 *
 * Week number (%V) code based on Taco van den Broek's prototype:
 * http://techblog.procurios.nl/k/news/view/33796/14863/calculate-iso-8601-week-and-year-in-javascript.html
 */
function strftime(sFormat, date) {
  if (!(date instanceof Date)) date = new Date();
  var nDay = date.getDay(),
    nDate = date.getDate(),
    nMonth = date.getMonth(),
    nYear = date.getFullYear(),
    nHour = date.getHours(),
    aDays = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
    aMonths = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
    aDayCount = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334],
    isLeapYear = function() {
      return (nYear%4===0 && nYear%100!==0) || nYear%400===0;
    },
    getThursday = function() {
      var target = new Date(date);
      target.setDate(nDate - ((nDay+6)%7) + 3);
      return target;
    },
    zeroPad = function(nNum, nPad) {
      return ('' + (Math.pow(10, nPad) + nNum)).slice(1);
    };
  return sFormat.replace(/%[a-z]/gi, function(sMatch) {
    return {
      '%a': aDays[nDay].slice(0,3),
      '%A': aDays[nDay],
      '%b': aMonths[nMonth].slice(0,3),
      '%B': aMonths[nMonth],
      '%c': date.toUTCString(),
      '%C': Math.floor(nYear/100),
      '%d': zeroPad(nDate, 2),
      '%e': nDate,
      '%F': date.toISOString().slice(0,10),
      '%G': getThursday().getFullYear(),
      '%g': ('' + getThursday().getFullYear()).slice(2),
      '%H': zeroPad(nHour, 2),
      '%I': zeroPad((nHour+11)%12 + 1, 2),
      '%j': zeroPad(aDayCount[nMonth] + nDate + ((nMonth>1 && isLeapYear()) ? 1 : 0), 3),
      '%k': '' + nHour,
      '%l': (nHour+11)%12 + 1,
      '%m': zeroPad(nMonth + 1, 2),
      '%M': zeroPad(date.getMinutes(), 2),
      '%p': (nHour<12) ? 'AM' : 'PM',
      '%P': (nHour<12) ? 'am' : 'pm',
      '%s': Math.round(date.getTime()/1000),
      '%S': zeroPad(date.getSeconds(), 2),
      '%u': nDay || 7,
      '%V': (function() {
              var target = getThursday(),
                n1stThu = target.valueOf();
              target.setMonth(0, 1);
              var nJan1 = target.getDay();
              if (nJan1!==4) target.setMonth(0, 1 + ((4-nJan1)+7)%7);
              return zeroPad(1 + Math.ceil((n1stThu-target)/604800000), 2);
            })(),
      '%w': '' + nDay,
      '%x': date.toLocaleDateString(),
      '%X': date.toLocaleTimeString(),
      '%y': ('' + nYear).slice(2),
      '%Y': nYear,
      '%z': date.toTimeString().replace(/.+GMT([+-]\d+).+/, '$1'),
      '%Z': date.toTimeString().replace(/.+\((.+?)\)$/, '$1')
    }[sMatch] || sMatch;
  });
}
<commit_msg>Update header comment<commit_after>/* Port of strftime() by T. H. Doan (https://thdoan.github.io/strftime/)
 *
 * Compatibility notes:
 *
 * %c - formatted string is slightly different
 * %D - not implemented (use "%m/%d/%y" or "%d/%m/%y")
 * %e - space is not added
 * %E - not implemented
 * %h - not implemented (use "%b")
 * %k - space is not added
 * %n - not implemented (use "\n")
 * %O - not implemented
 * %r - not implemented (use "%I:%M:%S %p")
 * %R - not implemented (use "%H:%M")
 * %t - not implemented (use "\t")
 * %T - not implemented (use "%H:%M:%S")
 * %U - not implemented
 * %W - not implemented
 * %+ - not implemented
 * %% - not implemented (use "%")
 *
 * strftime() reference:
 * http://man7.org/linux/man-pages/man3/strftime.3.html
 *
 * Day of year (%j) code based on Joe Orost's answer:
 * http://stackoverflow.com/questions/8619879/javascript-calculate-the-day-of-the-year-1-366
 *
 * Week number (%V) code based on Taco van den Broek's prototype:
 * http://techblog.procurios.nl/k/news/view/33796/14863/calculate-iso-8601-week-and-year-in-javascript.html
 */
function strftime(sFormat, date) {
  if (!(date instanceof Date)) date = new Date();
  var nDay = date.getDay(),
    nDate = date.getDate(),
    nMonth = date.getMonth(),
    nYear = date.getFullYear(),
    nHour = date.getHours(),
    aDays = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
    aMonths = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
    aDayCount = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334],
    isLeapYear = function() {
      return (nYear%4===0 && nYear%100!==0) || nYear%400===0;
    },
    getThursday = function() {
      var target = new Date(date);
      target.setDate(nDate - ((nDay+6)%7) + 3);
      return target;
    },
    zeroPad = function(nNum, nPad) {
      return ('' + (Math.pow(10, nPad) + nNum)).slice(1);
    };
  return sFormat.replace(/%[a-z]/gi, function(sMatch) {
    return {
      '%a': aDays[nDay].slice(0,3),
      '%A': aDays[nDay],
      '%b': aMonths[nMonth].slice(0,3),
      '%B': aMonths[nMonth],
      '%c': date.toUTCString(),
      '%C': Math.floor(nYear/100),
      '%d': zeroPad(nDate, 2),
      '%e': nDate,
      '%F': date.toISOString().slice(0,10),
      '%G': getThursday().getFullYear(),
      '%g': ('' + getThursday().getFullYear()).slice(2),
      '%H': zeroPad(nHour, 2),
      '%I': zeroPad((nHour+11)%12 + 1, 2),
      '%j': zeroPad(aDayCount[nMonth] + nDate + ((nMonth>1 && isLeapYear()) ? 1 : 0), 3),
      '%k': '' + nHour,
      '%l': (nHour+11)%12 + 1,
      '%m': zeroPad(nMonth + 1, 2),
      '%M': zeroPad(date.getMinutes(), 2),
      '%p': (nHour<12) ? 'AM' : 'PM',
      '%P': (nHour<12) ? 'am' : 'pm',
      '%s': Math.round(date.getTime()/1000),
      '%S': zeroPad(date.getSeconds(), 2),
      '%u': nDay || 7,
      '%V': (function() {
              var target = getThursday(),
                n1stThu = target.valueOf();
              target.setMonth(0, 1);
              var nJan1 = target.getDay();
              if (nJan1!==4) target.setMonth(0, 1 + ((4-nJan1)+7)%7);
              return zeroPad(1 + Math.ceil((n1stThu-target)/604800000), 2);
            })(),
      '%w': '' + nDay,
      '%x': date.toLocaleDateString(),
      '%X': date.toLocaleTimeString(),
      '%y': ('' + nYear).slice(2),
      '%Y': nYear,
      '%z': date.toTimeString().replace(/.+GMT([+-]\d+).+/, '$1'),
      '%Z': date.toTimeString().replace(/.+\((.+?)\)$/, '$1')
    }[sMatch] || sMatch;
  });
}
<|endoftext|>


<commit_before>// Note: You must restart bin/webpack-dev-server for changes to take effect

/* eslint global-require: 0 */
/* eslint import/no-dynamic-require: 0 */

const webpack = require('webpack')
const { basename, dirname, join, relative, resolve } = require('path')
const { sync } = require('glob')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const ManifestPlugin = require('webpack-manifest-plugin')
const extname = require('path-complete-extname')
const { env, settings, output, loadersDir, resolvedModules } = require('./configuration.js')

const extensionGlob = `**/*{${settings.extensions.join(',')}}*`
const entryPath = join(settings.source_path, settings.source_entry_path)
const packPaths = sync(join(entryPath, extensionGlob))

module.exports = {
  entry: packPaths.reduce(
    (map, entry) => {
      const localMap = map
      const namespace = relative(join(entryPath), dirname(entry))
      localMap[join(namespace, basename(entry, extname(entry)))] = resolve(entry)
      return localMap
    }, {}
  ),

  output: {
    filename: '[name].js',
    path: output.path,
    publicPath: output.publicPath
  },

  module: {
    rules: sync(join(loadersDir, '*.js')).map(loader => require(loader))
  },

  plugins: [
    new webpack.EnvironmentPlugin(JSON.parse(JSON.stringify(env))),
    new ExtractTextPlugin(env.NODE_ENV === 'production' ? '[name]-[hash].css' : '[name].css'),
    new ManifestPlugin({
      publicPath: output.publicPath,
      writeToFileEmit: true
    })
  ],

  resolve: {
    extensions: settings.extensions,
    modules: resolvedModules
  },

  resolveLoader: {
    modules: ['node_modules']
  }
}
<commit_msg>Use `contenthash` instead of `hash` for CSS<commit_after>// Note: You must restart bin/webpack-dev-server for changes to take effect

/* eslint global-require: 0 */
/* eslint import/no-dynamic-require: 0 */

const webpack = require('webpack')
const { basename, dirname, join, relative, resolve } = require('path')
const { sync } = require('glob')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const ManifestPlugin = require('webpack-manifest-plugin')
const extname = require('path-complete-extname')
const { env, settings, output, loadersDir, resolvedModules } = require('./configuration.js')

const extensionGlob = `**/*{${settings.extensions.join(',')}}*`
const entryPath = join(settings.source_path, settings.source_entry_path)
const packPaths = sync(join(entryPath, extensionGlob))

module.exports = {
  entry: packPaths.reduce(
    (map, entry) => {
      const localMap = map
      const namespace = relative(join(entryPath), dirname(entry))
      localMap[join(namespace, basename(entry, extname(entry)))] = resolve(entry)
      return localMap
    }, {}
  ),

  output: {
    filename: '[name].js',
    path: output.path,
    publicPath: output.publicPath
  },

  module: {
    rules: sync(join(loadersDir, '*.js')).map(loader => require(loader))
  },

  plugins: [
    new webpack.EnvironmentPlugin(JSON.parse(JSON.stringify(env))),
    new ExtractTextPlugin(env.NODE_ENV === 'production' ? '[name]-[contenthash].css' : '[name].css'),
    new ManifestPlugin({
      publicPath: output.publicPath,
      writeToFileEmit: true
    })
  ],

  resolve: {
    extensions: settings.extensions,
    modules: resolvedModules
  },

  resolveLoader: {
    modules: ['node_modules']
  }
}
<|endoftext|>


<commit_before>'use strict';

process.env['PATH'] = process.env['PATH'] + ':' + process.env['LAMBDA_TASK_ROOT']

const spawnSync = require('child_process').spawnSync;

/**
     Defines a handler function called "index.handler" to Lambda.

     This function takes an `event` object as input, and invokes the
     `swiftcommand` executable.

     If the executable completes without error, the handler
     callback-returns an object of the form

     {
     input: event
     output: stdout
     }

     If the executable errors, the handler returns an error (?).

     In all cases, the executable's stdout is logged to the console as
     a log message, and its stderr is logged as error messages.

*/
exports.handler = (event, context, callback) => {

    const options = {
        cwd: 'native/',
        env: {
            LD_LIBRARY_PATH: 'LinuxLibraries'
        },
        input:JSON.stringify(event)
    };

    var command = '';

    if (event.command)
    {
        command = event.command;
    } else {
        command = './Lambda';
    }

    const childObject = spawnSync(command, [], options)

    var error = childObject.error;
    var stdout = childObject.stdout.toString('utf8');
    var stderr = childObject.stderr.toString('utf8');

    // Log process stdout and stderr
    console.log(stdout);
    console.error(stderr);

    if (error) {
        callback(error, null);
    } else {
        try {
            // Executable's raw stdout is the Lambda output
            var response = JSON.parse(stdout);
            callback(null, response);
        } catch(e) {
            callback(e, null);
        }
    }
};
<commit_msg>Update formatting<commit_after>'use strict';

process.env['PATH'] = process.env['PATH'] + ':' + process.env['LAMBDA_TASK_ROOT']

const spawnSync = require('child_process').spawnSync;

/**
     Defines a handler function called "index.handler" to Lambda.

     This function takes an `event` object as input, and invokes the
     `swiftcommand` executable.

     If the executable completes without error, the handler
     callback-returns an object of the form

     {
     input: event
     output: stdout
     }

     If the executable errors, the handler returns an error (?).

     In all cases, the executable's stdout is logged to the console as
     a log message, and its stderr is logged as error messages.

*/
exports.handler = (event, context, callback) => {
    const options = {
        cwd: 'native/',
        env: {
            LD_LIBRARY_PATH: 'LinuxLibraries'
        },
        input:JSON.stringify(event)
    };

    var command = '';

    if (event.command) {
        command = event.command;
    } else {
        command = './Lambda';
    }

    const childObject = spawnSync(command, [], options)

    var error = childObject.error;
    var stdout = childObject.stdout.toString('utf8');
    var stderr = childObject.stderr.toString('utf8');

    // Log process stdout and stderr
    console.log(stdout);
    console.error(stderr);

    if (error) {
        callback(error, null);
    } else {
        try {
            // Executable's raw stdout is the Lambda output
            var response = JSON.parse(stdout);
            callback(null, response);
        } catch(e) {
            callback(e, null);
        }
    }
};
<|endoftext|>


<commit_before>import React from 'react';
import _ from 'lodash';
import moment from 'moment';
import { Link } from 'react-router';
import steemembed from 'steemembed';
import BodyShort from './body-short';
import Mentions from './mentions';
import RepliesShort from './replies-short';
import Flag from './flag';
import PostActionButtons from './PostActionButtons';

const colorCode = { green: 'rgba(39, 208, 169, 0.4)', red: 'rgba(249, 43, 97, 0.2)' };
const classCode = { green: 'grid-row-green', red: 'grid-row-red' };

export default class PostFeedItem extends React.Component {
  constructor(props) {
    super(props);
  }

  render() {
    const post = this.props.entry;
    const steemit = `/${post.parent_permlink}/@${post.author}/${post.permlink}`;
    let color = '';
    color = (post.net_votes > 0) ? 'green' : color;
    color = (post.net_votes < 0) ? 'red' : color;
    const bar = Math.abs(40 / 1000 * post.net_votes);
    const style = (color) ? { height: '4px', boxShadow: `inset ${bar}em 0 0 ${colorCode[color]}` } : {};
    let className = 'grid-row';
    className += (color) ? ` ${classCode[color]}` : '';
    try { var jsonMetadata = JSON.parse(post.json_metadata); }
    catch (e) { var jsonMetadata = {}; }
    let image = _.has(jsonMetadata, 'image[0]') ? jsonMetadata.image[0] : '';
    image = (image) ? `https://img1.steemit.com/600x400/${image}` : '';
    const embeds = steemembed.getAll(post.body);

    return (

              <Link to={`/@${post.author}`} activeClassName="active">

                <img src={`https://img.busy6.com/@${post.author}`} width="24" height="24" />
               @{post.author}
              </Link>
              {!_.isEmpty(post.parent_author) &&
               replied
                <Link to={`/@${post.parent_author}`}>
                @{post.parent_author}
              </Link>'s
                <Link to={`/${post.category}/@${post.parent_author}/${post.parent_permlink}`}>post.</Link>
            }

{moment(post.created).fromNow()}
               this.props.toggleBookmark(post.id)}>

                  {_.has(this.props.bookmarks, post.id) ? 'bookmark' : 'bookmark_border'}

        {image && !_.has(embeds, '[0].embed') &&
<Link to={steemit}></Link>
}
        {_.has(embeds, '[0].embed') &&

}

            <Flag title={post.title} body={post.body} />
            <Link to={steemit}>{post.title}</Link>

          <Mentions jsonMetadata={jsonMetadata} />

<BodyShort body={post.body} />

          <PostActionButtons post={post} />

        {this.props.replies !== 'false' && post.children > 0 && <RepliesShort parent={post.author} parentPermlink={post.permlink} />}

    );
  }
}
<commit_msg>Move space<commit_after>import React from 'react';
import _ from 'lodash';
import moment from 'moment';
import { Link } from 'react-router';
import steemembed from 'steemembed';
import BodyShort from './body-short';
import Mentions from './mentions';
import RepliesShort from './replies-short';
import Flag from './flag';
import PostActionButtons from './PostActionButtons';

const colorCode = { green: 'rgba(39, 208, 169, 0.4)', red: 'rgba(249, 43, 97, 0.2)' };
const classCode = { green: 'grid-row-green', red: 'grid-row-red' };

export default class PostFeedItem extends React.Component {
  constructor(props) {
    super(props);
  }

  render() {
    const post = this.props.entry;
    const steemit = `/${post.parent_permlink}/@${post.author}/${post.permlink}`;
    let color = '';
    color = (post.net_votes > 0) ? 'green' : color;
    color = (post.net_votes < 0) ? 'red' : color;
    const bar = Math.abs(40 / 1000 * post.net_votes);
    const style = (color) ? { height: '4px', boxShadow: `inset ${bar}em 0 0 ${colorCode[color]}` } : {};
    let className = 'grid-row';
    className += (color) ? ` ${classCode[color]}` : '';
    try { var jsonMetadata = JSON.parse(post.json_metadata); }
    catch (e) { var jsonMetadata = {}; }
    let image = _.has(jsonMetadata, 'image[0]') ? jsonMetadata.image[0] : '';
    image = (image) ? `https://img1.steemit.com/600x400/${image}` : '';
    const embeds = steemembed.getAll(post.body);

    return (

              <Link to={`/@${post.author}`} activeClassName="active">

                <img src={`https://img.busy6.com/@${post.author}`} width="24" height="24" />
               @{post.author}
              </Link>
              {!_.isEmpty(post.parent_author) &&
               replied
                <Link to={`/@${post.parent_author}`}>
                  @{post.parent_author}
                </Link>'s
                 <Link to={`/${post.category}/@${post.parent_author}/${post.parent_permlink}`}>post.</Link>
              }

{moment(post.created).fromNow()}
               this.props.toggleBookmark(post.id)}>

                  {_.has(this.props.bookmarks, post.id) ? 'bookmark' : 'bookmark_border'}

        {image && !_.has(embeds, '[0].embed') &&
<Link to={steemit}></Link>
}
        {_.has(embeds, '[0].embed') &&

}

            <Flag title={post.title} body={post.body} />
            <Link to={steemit}>{post.title}</Link>

          <Mentions jsonMetadata={jsonMetadata} />

<BodyShort body={post.body} />

          <PostActionButtons post={post} />

        {this.props.replies !== 'false' && post.children > 0 && <RepliesShort parent={post.author} parentPermlink={post.permlink} />}

    );
  }
}
<|endoftext|>


<commit_before><commit_msg>Remove requestAnimationFrame check<commit_after><|endoftext|>


<commit_before>/**
 * Set the image options or select an image to insert.
 *
 * @author Arjan Scherpenisse <arjan@scherpenisse.net>
 * @author Moxiecode
 * @copyright 2010-2012 Arjan Scherpenisse <arjan@scherpenisse.net>
 * @copyright Copyright 2004-2008, Moxiecode Systems AB, All rights reserved.
 */

(function() {
     window.tinyMCEzMedia =
     {
         toHTML: function(id, opts) {
             var cls = "z-tinymce-media ";
             cls += "z-tinymce-media-align-" + (opts.align || 'block');

             var html = '';
             return html;
         }

     };
	tinymce.create('tinymce.plugins.ZotonicMediaPlugin', {

        init : function(ed, url) {
                var self = this;

                // Register commands
                ed.addCommand('mceZotonicMedia', function() {
                        var n = ed.selection.getNode();

                        if (n && self._domIsZMedia(n))
                        {
                            // Open properties dialog
                            self.propertiesDialog(n);
                        }
                        else {
                            // Open "insert" dialog
                            window.z_choose_zmedia = function(id) {
                                if (!id) return;
                                var html = window.tinyMCEzMedia.toHTML(id, {align: "block", size: "middle", crop: '', link: ''});
                                ed.execCommand('mceInsertContent', false, html, {});
                            };
                            z_event('zmedia', {language: window.zEditLanguage(), is_zmedia: 1});
                        }
                    });

                ed.onLoadContent.add(function(ed, o) {
                    ed.setContent(self._zMarkersToMediaHtml(o.content));

                    ed.onPostProcess.add(function(ed, o) {
                        o.content = self._MediaHtmlToMarkers(o.content);
                        });

                    });

                ed.onSetContent.add(function(ed, o) {
                    });

                // Register buttons
                ed.addButton('zmedia', {
                    title : 'Insert a Zotonic media item.',
                            cmd : 'mceZotonicMedia',
                            'class': 'mce_image'
                            });
            },

            propertiesDialog: function(node) {
                var id = this._zMediaIdFromDOM(node);
                var opts = this._zMediaOptsFromDOM(node);

                z_dialog_open({
                            title: 'Media properties',
                            text:
                             '<form id="zmedia-props-form">'
                            +'<fieldset>'
                            +'
'
                            +'

'
                            +'
'
                            +'<input type="radio" name="align" ' + (opts.align=='block'?'checked="checked"':'') + ' value="block" id="a-block"> Between text'
                            +'<input type="radio" name="align" ' + (opts.align=='left'?'checked="checked"':'') + 'value="left" id="a-left"> Aligned left'
                            +'<input type="radio" name="align" ' + (opts.align=='right'?'checked="checked"':'') + 'value="right" id="a-right"> Aligned right'
                            +'
'
                            +'
'
                            +'<input type="radio" name="size" ' + (opts.size=='small'?'checked="checked"':'') + ' value="small" id="a-small"> Small'
                            +'<input type="radio" name="size" ' + (opts.size=='middle' || opts.size == undefined?'checked="checked"':'') + 'value="middle" id="a-middle"> Middle'
                            +'<input type="radio" name="size" ' + (opts.size=='large'?'checked="checked"':'') + 'value="large" id="a-large"> Large'
                            +'
'
                            +'
'
                            +'<input type="checkbox" name="crop" ' + (opts.crop=='crop'?'checked="checked"':'') + ' value="crop" id="a-crop"> Crop image'
                            +'<input type="checkbox" name="link" ' + (opts.link=='link'?'checked="checked"':'') + ' value="crop" id="a-link"> Make link'
                            +'
'
                            +'
'

                            +'
'
                            +'<button class="btn" id="zmedia-props-cancel">Cancel</button>'
                            +'<button class="btn btn-primary" type="submit">Save Properties</button>'
                            +'
'
                            +'</fieldset>'
                            +'</form>'
                        });

                $('#zmedia-props-form').submit(function() {
                    var new_opts = {
                        'align': $('#zmedia-props-form input[name="align"]:checked').val(),
                        'size': $('#zmedia-props-form input[name="size"]:checked').val(),
                        'crop': $('#zmedia-props-form input[name="crop"]:checked').val() ? "crop" : "",
                        'link': $('#zmedia-props-form input[name="link"]:checked').val() ? "link" : ""
                    };
                    var el = $(window.tinyMCEzMedia.toHTML(id, new_opts));
                    node.className = el.attr("class");
                    $(node)
                        .attr("data-zmedia-opts", el.attr("data-zmedia-opts"))
                        .attr("data-zmedia-id", el.attr("data-zmedia-id"));

                    z_dialog_close();
                    return false;
                });
                $('#zmedia-props-cancel').click(function() {
                    z_dialog_close();
                    return false;
                });
            },

            getInfo : function() {
                return {
                longname : 'Zotonic Media Plugin',
                        author : 'Arjan Scherpenisse',
                        authorurl : 'http://www.zotonic.com',
                        infourl : 'http://www.zotonic.com',
                        version : tinymce.majorVersion + "." + tinymce.minorVersion
                        };
            },

            // Private methods //

            _domIsZMedia: function(el) {
                return this._zMediaIdFromDOM(el) !== null;
            },

            _zMediaIdFromDOM: function(el) {
                return el.getAttribute('data-zmedia-id');
            },

            _zMediaOptsFromDOM: function(el) {
                return eval("(" + el.getAttribute("data-zmedia-opts") + ")");
            },

            _zMediaClass: function() {
                return "z-tinymce-media";
            },

            _MediaHtmlToMarkers: function (html) {
                var re = new RegExp('', 'g');
                var m;
                while ( (m = re.exec(html)) )
                {
                    var img = m[0];
                    var idmatch = (new RegExp('data-zmedia-id="([0-9]+)', 'g')).exec(img);
                    if (!idmatch) return html;
                    var id = idmatch[1];
                    var optsmatch = (new RegExp('data-zmedia-opts="(\\{.*?\\})"', 'g')).exec(img);
                    if (!optsmatch) return html;
                    var opts = eval("(" + optsmatch[1].replace(/"/g, '"') + ")");
                    var newtag = this._zMediaMarker(id, opts);

                    html = html.substr(0, re.lastIndex - img.length) + newtag + html.substr(re.lastIndex);
                    re.lastIndex = re.lastIndex - img.length + newtag.length;
                }
                return html;
            },

            _zMediaMarker: function(id, opts) {
                return "";
            },

            _zMarkersToMediaHtml: function (html) {
                var re = new RegExp('', 'g');
                var m;
                while ( (m = re.exec(html)) )
                {
                    var id = m[1];
                    var opts = eval("(" + m[2] + ")");
                    var part = window.tinyMCEzMedia.toHTML(id, opts);
                    html = html.substr(0, re.lastIndex - m[0].length) + part + html.substr(re.lastIndex);
                    re.lastIndex = re.lastIndex - m[0].length + part.length;
                }
                return html;
            }

        }

        );

	// Register plugin
	tinymce.PluginManager.add('zmedia', tinymce.plugins.ZotonicMediaPlugin);
 })();
<commit_msg>mod_base: Fix embedding of images in TinyMCE<commit_after>/**
 * Set the image options or select an image to insert.
 *
 * @author Arjan Scherpenisse <arjan@scherpenisse.net>
 * @author Moxiecode
 * @copyright 2010-2012 Arjan Scherpenisse <arjan@scherpenisse.net>
 * @copyright Copyright 2004-2008, Moxiecode Systems AB, All rights reserved.
 */

(function() {
     window.tinyMCEzMedia =
     {
         toHTML: function(id, opts) {
             var cls = "z-tinymce-media ";
             cls += "z-tinymce-media-align-" + (opts.align || 'block');

             var html = '';
             return html;
         }

     };
	tinymce.create('tinymce.plugins.ZotonicMediaPlugin', {

        init : function(ed, url) {
                var self = this;

                // Register commands
                ed.addCommand('mceZotonicMedia', function() {
                        var n = ed.selection.getNode();

                        if (n && self._domIsZMedia(n))
                        {
                            // Open properties dialog
                            self.propertiesDialog(n);
                        }
                        else {
                            // Open "insert" dialog
                            window.z_choose_zmedia = function(id) {
                                if (!id) return;
                                var html = window.tinyMCEzMedia.toHTML(id, {align: "block", size: "middle", crop: '', link: ''});
                                ed.execCommand('mceInsertContent', false, html, {});
                            };
                            z_event('zmedia', {language: window.zEditLanguage(), is_zmedia: 1});
                        }
                    });

                ed.onPostProcess.add(function(ed, o) {
                    o.content = self._MediaHtmlToMarkers(o.content);
                });

                ed.onLoadContent.add(function(ed, o) {
                    ed.setContent(self._zMarkersToMediaHtml(o.content));
                });

                ed.onBeforeSetContent.add(function(ed, o) {
                    o.content = self._zMarkersToMediaHtml(o.content);
                });

                // Register buttons
                ed.addButton('zmedia', {
                    title : 'Insert a Zotonic media item.',
                            cmd : 'mceZotonicMedia',
                            'class': 'mce_image'
                            });
            },

            propertiesDialog: function(node) {
                var id = this._zMediaIdFromDOM(node);
                var opts = this._zMediaOptsFromDOM(node);

                z_dialog_open({
                            title: 'Media properties',
                            text:
                             '<form id="zmedia-props-form">'
                            +'<fieldset>'
                            +'
'
                            +'

'
                            +'
'
                            +'<input type="radio" name="align" ' + (opts.align=='block'?'checked="checked"':'') + ' value="block" id="a-block"> Between text'
                            +'<input type="radio" name="align" ' + (opts.align=='left'?'checked="checked"':'') + 'value="left" id="a-left"> Aligned left'
                            +'<input type="radio" name="align" ' + (opts.align=='right'?'checked="checked"':'') + 'value="right" id="a-right"> Aligned right'
                            +'
'
                            +'
'
                            +'<input type="radio" name="size" ' + (opts.size=='small'?'checked="checked"':'') + ' value="small" id="a-small"> Small'
                            +'<input type="radio" name="size" ' + (opts.size=='middle' || opts.size == undefined?'checked="checked"':'') + 'value="middle" id="a-middle"> Middle'
                            +'<input type="radio" name="size" ' + (opts.size=='large'?'checked="checked"':'') + 'value="large" id="a-large"> Large'
                            +'
'
                            +'
'
                            +'<input type="checkbox" name="crop" ' + (opts.crop=='crop'?'checked="checked"':'') + ' value="crop" id="a-crop"> Crop image'
                            +'<input type="checkbox" name="link" ' + (opts.link=='link'?'checked="checked"':'') + ' value="crop" id="a-link"> Make link'
                            +'
'
                            +'
'

                            +'
'
                            +'<button class="btn" id="zmedia-props-cancel">Cancel</button>'
                            +'<button class="btn btn-primary" type="submit">Save Properties</button>'
                            +'
'
                            +'</fieldset>'
                            +'</form>'
                        });

                $('#zmedia-props-form').submit(function() {
                    var new_opts = {
                        'align': $('#zmedia-props-form input[name="align"]:checked').val(),
                        'size': $('#zmedia-props-form input[name="size"]:checked').val(),
                        'crop': $('#zmedia-props-form input[name="crop"]:checked').val() ? "crop" : "",
                        'link': $('#zmedia-props-form input[name="link"]:checked').val() ? "link" : ""
                    };
                    var el = $(window.tinyMCEzMedia.toHTML(id, new_opts));
                    node.className = el.attr("class");
                    $(node)
                        .attr("data-zmedia-opts", el.attr("data-zmedia-opts"))
                        .attr("data-zmedia-id", el.attr("data-zmedia-id"));

                    z_dialog_close();
                    return false;
                });
                $('#zmedia-props-cancel').click(function() {
                    z_dialog_close();
                    return false;
                });
            },

            getInfo : function() {
                return {
                longname : 'Zotonic Media Plugin',
                        author : 'Arjan Scherpenisse',
                        authorurl : 'http://www.zotonic.com',
                        infourl : 'http://www.zotonic.com',
                        version : tinymce.majorVersion + "." + tinymce.minorVersion
                        };
            },

            // Private methods //

            _domIsZMedia: function(el) {
                return this._zMediaIdFromDOM(el) !== null;
            },

            _zMediaIdFromDOM: function(el) {
                return el.getAttribute('data-zmedia-id');
            },

            _zMediaOptsFromDOM: function(el) {
                return eval("(" + el.getAttribute("data-zmedia-opts") + ")");
            },

            _zMediaClass: function() {
                return "z-tinymce-media";
            },

            _MediaHtmlToMarkers: function (html) {
                var re = new RegExp('', 'g');
                var m;
                while ( (m = re.exec(html)) )
                {
                    var img = m[0];
                    var idmatch = (new RegExp('data-zmedia-id="([0-9]+)', 'g')).exec(img);
                    if (!idmatch) return html;
                    var id = idmatch[1];
                    var optsmatch = (new RegExp('data-zmedia-opts="(\\{.*?\\})"', 'g')).exec(img);
                    if (!optsmatch) return html;
                    var opts = eval("(" + optsmatch[1].replace(/"/g, '"') + ")");
                    var newtag = this._zMediaMarker(id, opts);

                    html = html.substr(0, re.lastIndex - img.length) + newtag + html.substr(re.lastIndex);
                    re.lastIndex = re.lastIndex - img.length + newtag.length;
                }
                return html;
            },

            _zMediaMarker: function(id, opts) {
                return "";
            },

            _zMarkersToMediaHtml: function (html) {
                var re = new RegExp('', 'g');
                var m;
                while ( (m = re.exec(html)) )
                {
                    var id = m[1];
                    var opts = eval("(" + m[2] + ")");
                    var part = window.tinyMCEzMedia.toHTML(id, opts);
                    html = html.substr(0, re.lastIndex - m[0].length) + part + html.substr(re.lastIndex);
                    re.lastIndex = re.lastIndex - m[0].length + part.length;
                }
                return html;
            }

        }

        );

	// Register plugin
	tinymce.PluginManager.add('zmedia', tinymce.plugins.ZotonicMediaPlugin);
 })();
<|endoftext|>