<commit_before>// const center = require('center-align')
const { parse } = require('node-html-parser')
require('colors')
const terminalLink = require('terminal-link')
const { AllHtmlEntities: Entities } = require('html-entities')
const Ansi = require('./ansi')

const entities = new Entities();

const quote = {
  test: text => text.startsWith('
') && (/#comment\d+_\d+/).test(text),
  replace: text => {
    const root = parse(text)
    const comment = entities.decode(root.querySelector('.quote').childNodes.filter(node => !node.rawAttributes || !node.rawAttributes.hasOwnProperty('rel')).map(node => node.rawText).join('').replace(/\n/g, ' ').replace('—', ''))
    const author = root.querySelector('a').childNodes[0].rawText
    const { href: url } = root.querySelectorAll('a').filter(a => a.rawAttributes.hasOwnProperty('rel'))[1].rawAttributes
    let u = new URL(url)
    const urls = {
      'meta.stackexchange.com': 'Meta Stack Exchange',
      'stackoverflow.com': 'Stack Overflow',
      'pt.stackoverflow.com': 'Stack Overflow em Português',
      'meta.pt.stackoverflow.com': 'Meta Stack Overflow em Português',
      'es.stackoverflow.com': 'Stack Overflow en español',
      'meta.es.stackoverflow.com': 'Meta Stack Overflow en español',
      'ru.stackoverflow.com': 'Stack Overflow на русском',
      'meta.ru.stackoverflow.com': 'Meta Stack Overflow на русском',
      'ja.stackoverflow.com': 'スタック・オーバーフロー',
      'meta.ja.stackoverflow.com': 'Meta スタック・オーバーフロー',
      'askubuntu.com': 'Ask Ubuntu',
      'meta.askubuntu.com': 'Ask Ubuntu',
      'mathoverflow.net': 'Math Overflow',
      'meta.mathoverflow.net': 'Meta Math Overflow',
      'serverfault.com': 'Server Fault',
      'meta.serverfault.com': 'Meta Server Fault',
      'superuser.com': 'Super User',
      'meta.superuser.com': 'Meta Super User'
    }
    const sites = {
      'codereview': 'Code Review',
      'codegolf': 'Code Golf',
      'anime': 'Anime & Manga',
      'apple': 'Ask Different',
      'english': 'English Language & Usage',
      'ell': 'English Language Learners',
      'gamedev': 'Game Development',
      'graphicdesign': 'Graphic Design',
      'diy': 'Home Improvement',
      'security': 'Information Security',
      'japanese': 'Japanese Language',
      'magento': 'Magento',
      'mathematica': 'Mathematica',
      'math': 'Mathematics',
      'judaism': 'Mi Yodeya',
      'movies': 'Movies & TV',
      'music': 'Music: Practice & Theory',
      'networkengineering': 'Network Engineering',
      'money': 'Personal Finance & Money',
      'photo': 'Photography',
      'physics': 'Physics',
      'puzzling': 'Puzzling',
      'quantumcomputing': 'Quantum Computing',
      'raspberrypi': 'Raspberry Pi',
      'rpg': 'Role-playing Games',
      'salesforce': 'Salesforce',
      'scifi': 'Science Fiction & Fantasy',
      'sharepoint': 'Sharepoint',
      'dsp': 'Signal Processing',
      'skeptics': 'Skeptics',
      'softwareengineering': 'Software Engineering',
      'softwarerecs': 'Software Recommendations',
      'tex': 'TeX - LaTeX',
      'workplace': 'The Workplace',
      'cstheory': 'Theoretical Computer Science',
      'travel': 'Travel',
      'unix': 'Unix & Linux',
      'ux': 'User Experience',
      'webapp': 'Web Applications',
      'webmasters': 'Webmasters',
      'wordpress': 'WordPress Development',
      'worldbuilding': 'Worldbuilding'
    }
    for (const [name, site] of Object.entries(sites)) {
      sites[`meta.${name}`] = `Meta ${site}`
    }
    const hostname = u.hostname.split('.').reverse()
      .slice(0, 2)
      .reverse()
      .join('.')
    let place = ''
    let match = Object.keys(urls).find(domain => u.hostname.startsWith(domain))
    if (match !== null) {
      place = urls[match]
    } else if (hostname === 'stackexchange.com') {
      let site = u.hostname.replace(`.${hostname}`, '')
      place = `${sites.hasOwnProperty(site) ? sites[site] : site} SE`
    } else {
      place = urls[hostname]
    }
    const [, questionName] = text.match(/questions\/\d+\/([^#]+)/)
    const spreadComment = Ansi.spreadAcrossLines(comment.trim(), 60)
    return '\n' + Ansi.box(spreadComment, terminalLink(`Comment from ${place}`.blue, url), false, true)
  }
}

const postOnebox = {
  test: text => text.startsWith('
'),
  replace: text => {
    const TITLE_LENGTH = 35
    const BODY_LENGTH = 75
    const root = parse(text)
    let votes = root.querySelector('.ob-post-votes').rawText
    const title = root.querySelector('.ob-post-title').rawText
    const { title: user } = root.querySelector('.ob-post-body img').rawAttributes
    const body = root.querySelector('.ob-post-body').text
    const tags = root.querySelectorAll('.ob-post-tags .ob-post-tag').map(tag => tag.rawText)
    const { title: site } = root.querySelector('.ob-post-siteicon').rawAttributes
    let { href: url } = root.querySelector('.ob-post-title a').attributes
    url = url.replace(/^\/\//, 'https://')
    const [, id] = url.match(/questions\/(\d+)\//)
    const fixedBody = body.replace(/\n/g, ' ')
    let thinTitle = Ansi.trimBySpaces(title, TITLE_LENGTH)
    thinTitle += Ansi.len(thinTitle) >= TITLE_LENGTH ? '...' : ''
    let thinBody = Ansi.trimBySpaces(fixedBody, BODY_LENGTH)
    thinBody = Ansi.len(thinBody) >= TITLE_LENGTH ? Ansi.spreadAcrossLines(thinBody, TITLE_LENGTH) : thinBody
    return '\n' + Ansi.box(`
${Ansi.joinLines([Ansi.box(votes, 'votes'.red, true, true), Ansi.box(thinBody, 'text'.red, false, true)])}
${Ansi.joinLines([Ansi.box(tags.map(t => t.bold).join(', '), 'tags'.green, false, true), Ansi.box(user.underline, 'user'.green, false, true), Ansi.box(terminalLink(id.toString().underline, url), 'qID'.green, true, true)])}
`, `${entities.decode(site).bold} - ${entities.decode(thinTitle).blue}`, false, true)
  }
}

const matchReplace = (regex, string, callback, two = false) => {
  let wip = string
  wip = wip.replace(regex, (...args) => {
    if (two) return callback(args[1], args[2])
    return callback(args[1])
  })
  return wip
}

const italic = {
  test: text => (/_[^_]+_/).test(text),
  replace: text => matchReplace(/_([^_]+)_/g, text, str => str.italic)
}
const bold = {
  test: text => (/\*\*[^*]+\*\*/).test(text),
  replace: text => matchReplace(/\*\*([^*]+)\*\*/g, text, str => str.bold)
}
const italicAsterisk = {
  test: text => (/\*[^*]+\*/).test(text),
  replace: text => matchReplace(/\*([^*]+)\*/g, text, str => str.italic)
}

const boldHTML = {
  test: text => (/[^<>]+<\/b>/).test(text),
  replace: text => matchReplace(/([^<>]+)<\/b>/g, text, str => str.bold)
}
const italicHTML = {
  test: text => (/[^<>]+<\/i>/).test(text),
  replace: text => matchReplace(/([^<>]+)<\/i>/g, text, str => str.italic)
}
const codeHTML = {
  test: text => (/[^<>]+<\/code>/).test(text),
  replace: text => matchReplace(/([^<>]+)<\/code>/g, text, str => str.inverse)
}
const linkHTML = {
  test: text => (/([^<>]+)<\/a>/).test(text),
  replace: text => matchReplace(/([^<>]+)<\/a>/g, text, (link, title) => terminalLink(title, link.replace(/^\/\//, 'https://')), true)
}

const tagHTML = {
  test: text => (/ matchReplace(/([^<]+)<\/span><\/a>/g, text, (link, title) => `[${terminalLink(title, link.replace(/^\/\//, 'https://')).white}]`, true)
}

let a = '\u001b]8;;https://chat.meta.stackexchange.com/transcript/message/7335865#7335865\u00076 mins ago, by Jon Ericson\u001b]8;;\u0007'

const oneboxMessage = {
  test: text => (/
 {
    const root = parse(text)
    const { href } = root.querySelector('a').rawAttributes
    const age = root.querySelector('a').rawText
    const author = root.querySelector('.user-name').rawText
    const body = root.querySelector('div.quote').rawText
    return '\n' + Ansi.box(` | ${body}`, terminalLink(`${age}, by ${author}`.blue, `https://chat.${context.domain}.com${href}`), false, false)
  }
}

const oneboxImage = {
  test: text => (/^
/).test(text),
  replace: text => {
    const root = parse(text)
    const { href } = root.querySelector('a').rawAttributes
    return '\n' + Ansi.box(terminalLink(href.green, href), 'Image'.blue, true, false)
  }
}

const all = {
  postOnebox,
  oneboxMessage,
  oneboxImage,
  quote,
  bold,
  boldHTML,
  italic,
  italicHTML,
  italicAsterisk,
  codeHTML,
  linkHTML,
  tagHTML,
}

function test(text, context) {
  let wip = text
  for (const [name, type] of Object.entries(all)) {
    const isMatch = type.test(wip)
    if (isMatch && !type.replace) {
      console.log(`Text matched ${name} type but no replacement function exists`)
    } else if (isMatch) {
      wip = type.replace(wip, context)
    }
  }
  return wip
}

function fix(text, context) {
  const replacement = test(text, context)
  // if (replacement === null) {
  //   // console.log('no parser found for text')
  //   return text
  // }
  return replacement || text
}

module.exports = fix
<commit_msg>added formatting for arrows<commit_after>// const center = require('center-align')
const { parse } = require('node-html-parser')
require('colors')
const terminalLink = require('terminal-link')
const { AllHtmlEntities: Entities } = require('html-entities')
const Ansi = require('./ansi')

const entities = new Entities();

const quote = {
  test: text => text.startsWith('
') && (/#comment\d+_\d+/).test(text),
  replace: text => {
    const root = parse(text)
    const comment = entities.decode(root.querySelector('.quote').childNodes.filter(node => !node.rawAttributes || !node.rawAttributes.hasOwnProperty('rel')).map(node => node.rawText).join('').replace(/\n/g, ' ').replace('—', ''))
    const author = root.querySelector('a').childNodes[0].rawText
    const { href: url } = root.querySelectorAll('a').filter(a => a.rawAttributes.hasOwnProperty('rel'))[1].rawAttributes
    let u = new URL(url)
    const urls = {
      'meta.stackexchange.com': 'Meta Stack Exchange',
      'stackoverflow.com': 'Stack Overflow',
      'pt.stackoverflow.com': 'Stack Overflow em Português',
      'meta.pt.stackoverflow.com': 'Meta Stack Overflow em Português',
      'es.stackoverflow.com': 'Stack Overflow en español',
      'meta.es.stackoverflow.com': 'Meta Stack Overflow en español',
      'ru.stackoverflow.com': 'Stack Overflow на русском',
      'meta.ru.stackoverflow.com': 'Meta Stack Overflow на русском',
      'ja.stackoverflow.com': 'スタック・オーバーフロー',
      'meta.ja.stackoverflow.com': 'Meta スタック・オーバーフロー',
      'askubuntu.com': 'Ask Ubuntu',
      'meta.askubuntu.com': 'Ask Ubuntu',
      'mathoverflow.net': 'Math Overflow',
      'meta.mathoverflow.net': 'Meta Math Overflow',
      'serverfault.com': 'Server Fault',
      'meta.serverfault.com': 'Meta Server Fault',
      'superuser.com': 'Super User',
      'meta.superuser.com': 'Meta Super User'
    }
    const sites = {
      'codereview': 'Code Review',
      'codegolf': 'Code Golf',
      'anime': 'Anime & Manga',
      'apple': 'Ask Different',
      'english': 'English Language & Usage',
      'ell': 'English Language Learners',
      'gamedev': 'Game Development',
      'graphicdesign': 'Graphic Design',
      'diy': 'Home Improvement',
      'security': 'Information Security',
      'japanese': 'Japanese Language',
      'magento': 'Magento',
      'mathematica': 'Mathematica',
      'math': 'Mathematics',
      'judaism': 'Mi Yodeya',
      'movies': 'Movies & TV',
      'music': 'Music: Practice & Theory',
      'networkengineering': 'Network Engineering',
      'money': 'Personal Finance & Money',
      'photo': 'Photography',
      'physics': 'Physics',
      'puzzling': 'Puzzling',
      'quantumcomputing': 'Quantum Computing',
      'raspberrypi': 'Raspberry Pi',
      'rpg': 'Role-playing Games',
      'salesforce': 'Salesforce',
      'scifi': 'Science Fiction & Fantasy',
      'sharepoint': 'Sharepoint',
      'dsp': 'Signal Processing',
      'skeptics': 'Skeptics',
      'softwareengineering': 'Software Engineering',
      'softwarerecs': 'Software Recommendations',
      'tex': 'TeX - LaTeX',
      'workplace': 'The Workplace',
      'cstheory': 'Theoretical Computer Science',
      'travel': 'Travel',
      'unix': 'Unix & Linux',
      'ux': 'User Experience',
      'webapp': 'Web Applications',
      'webmasters': 'Webmasters',
      'wordpress': 'WordPress Development',
      'worldbuilding': 'Worldbuilding'
    }
    for (const [name, site] of Object.entries(sites)) {
      sites[`meta.${name}`] = `Meta ${site}`
    }
    const hostname = u.hostname.split('.').reverse()
      .slice(0, 2)
      .reverse()
      .join('.')
    let place = ''
    let match = Object.keys(urls).find(domain => u.hostname.startsWith(domain))
    if (match !== null) {
      place = urls[match]
    } else if (hostname === 'stackexchange.com') {
      let site = u.hostname.replace(`.${hostname}`, '')
      place = `${sites.hasOwnProperty(site) ? sites[site] : site} SE`
    } else {
      place = urls[hostname]
    }
    const [, questionName] = text.match(/questions\/\d+\/([^#]+)/)
    const spreadComment = Ansi.spreadAcrossLines(comment.trim(), 60)
    return '\n' + Ansi.box(spreadComment, terminalLink(`Comment from ${place}`.blue, url), false, true)
  }
}

const postOnebox = {
  test: text => text.startsWith('
'),
  replace: text => {
    const TITLE_LENGTH = 35
    const BODY_LENGTH = 75
    const root = parse(text)
    let votes = root.querySelector('.ob-post-votes').rawText
    const title = root.querySelector('.ob-post-title').rawText
    const { title: user } = root.querySelector('.ob-post-body img').rawAttributes
    const body = root.querySelector('.ob-post-body').text
    const tags = root.querySelectorAll('.ob-post-tags .ob-post-tag').map(tag => tag.rawText)
    const { title: site } = root.querySelector('.ob-post-siteicon').rawAttributes
    let { href: url } = root.querySelector('.ob-post-title a').attributes
    url = url.replace(/^\/\//, 'https://')
    const [, id] = url.match(/questions\/(\d+)\//)
    const fixedBody = body.replace(/\n/g, ' ')
    let thinTitle = Ansi.trimBySpaces(title, TITLE_LENGTH)
    thinTitle += Ansi.len(thinTitle) >= TITLE_LENGTH ? '...' : ''
    let thinBody = Ansi.trimBySpaces(fixedBody, BODY_LENGTH)
    thinBody = Ansi.len(thinBody) >= TITLE_LENGTH ? Ansi.spreadAcrossLines(thinBody, TITLE_LENGTH) : thinBody
    return '\n' + Ansi.box(`
${Ansi.joinLines([Ansi.box(votes, 'votes'.red, true, true), Ansi.box(thinBody, 'text'.red, false, true)])}
${Ansi.joinLines([Ansi.box(tags.map(t => t.bold).join(', '), 'tags'.green, false, true), Ansi.box(user.underline, 'user'.green, false, true), Ansi.box(terminalLink(id.toString().underline, url), 'qID'.green, true, true)])}
`, `${entities.decode(site).bold} - ${entities.decode(thinTitle).blue}`, false, true)
  }
}

const matchReplace = (regex, string, callback, two = false) => {
  let wip = string
  wip = wip.replace(regex, (...args) => {
    if (two) return callback(args[1], args[2])
    return callback(args[1])
  })
  return wip
}

const italic = {
  test: text => (/_[^_]+_/).test(text),
  replace: text => matchReplace(/_([^_]+)_/g, text, str => str.italic)
}
const bold = {
  test: text => (/\*\*[^*]+\*\*/).test(text),
  replace: text => matchReplace(/\*\*([^*]+)\*\*/g, text, str => str.bold)
}
const italicAsterisk = {
  test: text => (/\*[^*]+\*/).test(text),
  replace: text => matchReplace(/\*([^*]+)\*/g, text, str => str.italic)
}

const boldHTML = {
  test: text => (/[^<>]+<\/b>/).test(text),
  replace: text => matchReplace(/([^<>]+)<\/b>/g, text, str => str.bold)
}
const italicHTML = {
  test: text => (/[^<>]+<\/i>/).test(text),
  replace: text => matchReplace(/([^<>]+)<\/i>/g, text, str => str.italic)
}
const codeHTML = {
  test: text => (/[^<>]+<\/code>/).test(text),
  replace: text => matchReplace(/([^<>]+)<\/code>/g, text, str => str.inverse)
}
const linkHTML = {
  test: text => (/([^<>]+)<\/a>/).test(text),
  replace: text => matchReplace(/([^<>]+)<\/a>/g, text, (link, title) => terminalLink(title, link.replace(/^\/\//, 'https://')), true)
}

const tagHTML = {
  test: text => (/ matchReplace(/([^<]+)<\/span><\/a>/g, text, (link, title) => `[${terminalLink(title, link.replace(/^\/\//, 'https://')).white}]`, true)
}

const arrow = {
  test: text => text.includes('→'),
  replace: text => text.replace(/→/g, '→')
}

let a = '\u001b]8;;https://chat.meta.stackexchange.com/transcript/message/7335865#7335865\u00076 mins ago, by Jon Ericson\u001b]8;;\u0007'

const oneboxMessage = {
  test: text => (/
 {
    const root = parse(text)
    const { href } = root.querySelector('a').rawAttributes
    const age = root.querySelector('a').rawText
    const author = root.querySelector('.user-name').rawText
    const body = root.querySelector('div.quote').rawText
    return '\n' + Ansi.box(` | ${body}`, terminalLink(`${age}, by ${author}`.blue, `https://chat.${context.domain}.com${href}`), false, false)
  }
}

const oneboxImage = {
  test: text => (/^
/).test(text),
  replace: text => {
    const root = parse(text)
    const { href } = root.querySelector('a').rawAttributes
    return '\n' + Ansi.box(terminalLink(href.green, href), 'Image'.blue, true, false)
  }
}

const all = {
  postOnebox,
  oneboxMessage,
  oneboxImage,
  quote,
  bold,
  boldHTML,
  italic,
  italicHTML,
  italicAsterisk,
  codeHTML,
  linkHTML,
  tagHTML,
  arrow,
}

function test(text, context) {
  let wip = text
  for (const [name, type] of Object.entries(all)) {
    const isMatch = type.test(wip)
    if (isMatch && !type.replace) {
      console.log(`Text matched ${name} type but no replacement function exists`)
    } else if (isMatch) {
      wip = type.replace(wip, context)
    }
  }
  return wip
}

function fix(text, context) {
  const replacement = test(text, context)
  // if (replacement === null) {
  //   // console.log('no parser found for text')
  //   return text
  // }
  return replacement || text
}

module.exports = fix
<|endoftext|>


<commit_before>//= require "vendor/braintree"

Spree.routes.payment_client_token_api = Spree.pathFor("api/payment_client_token")

var braintreeDropinIntegration;
var cardSelector = "#new_payment [name=card]";

var getClientToken = function(onSuccess) {
  return Spree.ajax({
    url: Spree.routes.payment_client_token_api,
    type: "POST",
    data: {
      payment_method_id: $('form input[type=radio]:checked').val()
    },
    error: function(xhr, status) {
      show_flash("error", xhr.responseJSON.message);
    },
    success: function(data) {
      onSuccess(data);
    }
  });
};

var attachDropIn = function(data) {
  braintree.setup(data.client_token, "dropin", {
    container: "braintree-dropin",
    form: "new_payment",
    onReady: function (integration) {
      braintreeDropinIntegration = integration;
    },
    onError: function(type, message) {
      show_flash("error", message);
    },
    onPaymentMethodReceived: function(obj) {
      $("#payment_method_nonce").val(obj.nonce);
      $("#new_payment").submit();
      return;
    }
  });
};

$(document).ready(function() {
  if ($(cardSelector).length) {
    $(cardSelector).on("change", function() {
      if ($(cardSelector + ":checked").val() === "new") {
        getClientToken(attachDropIn);
      } else {
        if (braintreeDropinIntegration) {
          braintreeDropinIntegration.teardown();
        }
      }
    });
  } else {
    getClientToken(attachDropIn);
  }
});
<commit_msg>Get client token from braintree only in the payment page.<commit_after>//= require "vendor/braintree"

Spree.routes.payment_client_token_api = Spree.pathFor("api/payment_client_token")

var braintreeDropinIntegration;
var paymentForm = "#new_payment";
var cardSelector = "#new_payment [name=card]";

var getClientToken = function(onSuccess) {
  return Spree.ajax({
    url: Spree.routes.payment_client_token_api,
    type: "POST",
    data: {
      payment_method_id: $('form input[type=radio]:checked').val()
    },
    error: function(xhr, status) {
      show_flash("error", xhr.responseJSON.message);
    },
    success: function(data) {
      onSuccess(data);
    }
  });
};

var attachDropIn = function(data) {
  braintree.setup(data.client_token, "dropin", {
    container: "braintree-dropin",
    form: "new_payment",
    onReady: function (integration) {
      braintreeDropinIntegration = integration;
    },
    onError: function(type, message) {
      show_flash("error", message);
    },
    onPaymentMethodReceived: function(obj) {
      $("#payment_method_nonce").val(obj.nonce);
      $("#new_payment").submit();
      return;
    }
  });
};

$(document).ready(function() {
  if ($(paymentForm).length) {
    if ($(cardSelector).length) {
      $(cardSelector).on("change", function() {
        if ($(cardSelector + ":checked").val() === "new") {
          getClientToken(attachDropIn);
        } else {
          if (braintreeDropinIntegration) {
            braintreeDropinIntegration.teardown();
          }
        }
      });
    } else {
      getClientToken(attachDropIn);
    }
  }
});
<|endoftext|>


<commit_before>"use strict";
const HTMLElementImpl = require("./HTMLElement-impl").implementation;
const notImplemented = require("../../browser/not-implemented");
const idlUtils = require("../generated/utils");
const { Canvas } = require("../../utils");

class HTMLCanvasElementImpl extends HTMLElementImpl {
  _attrModified(name, value) {
    if (this._canvas && (name === "width" || name === "height")) {
      this._canvas[name] = parseInt(value);
    }

    return super._attrModified.apply(this, arguments);
  }

  _getCanvas() {
    if (Canvas && !this._canvas) {
      this._canvas = new Canvas(this.width, this.height);
    }
    return this._canvas;
  }

  getContext(contextId) {
    const canvas = this._getCanvas();
    if (canvas) {
      if (!this._context) {
        this._context = canvas.getContext(contextId) || null;
        if (this._context) {
          // Override the native canvas reference with our wrapper. This is the
          // reason why we need to locally cache _context, since each call to
          // canvas.getContext(contextId) would replace this reference again.
          // Perhaps in the longer term, a better solution would be to create a
          // full wrapper for the Context object as well.
          this._context.canvas = idlUtils.wrapperForImpl(this);
          wrapNodeCanvasMethod(this._context, "createPattern");
          wrapNodeCanvasMethod(this._context, "drawImage");
        }
      }
      return this._context;
    }

    notImplemented(
      "HTMLCanvasElement.prototype.getContext (without installing the canvas npm package)",
      this._ownerDocument._defaultView
    );
    return null;
  }

  toDataURL() {
    const canvas = this._getCanvas();
    if (canvas) {
      return canvas.toDataURL.apply(this._canvas, arguments);
    }

    notImplemented(
      "HTMLCanvasElement.prototype.toDataURL (without installing the canvas npm package)",
      this._ownerDocument._defaultView
    );
    return null;
  }

  toBlob(callback, type, qualityArgument) {
    const window = this._ownerDocument._defaultView;
    const canvas = this._getCanvas();
    if (canvas) {
      let stream;
      switch (type) {
        case "image/jpg":
        case "image/jpeg":
          stream = canvas.createJPEGStream({
            quality: Math.min(0, Math.max(1, qualityArgument)) * 100
          });
          break;
        default:
          // TODO: Patch node-canvas to receive qualityArgument for PNG stream
          type = "image/png";
          stream = canvas.createPNGStream();
      }
      const buffers = [];
      stream.on("data", chunk => {
        buffers.push(chunk);
      });
      stream.on("end", () => {
        callback(new window.Blob(buffers, { type }));
      });
    } else {
      notImplemented(
        "HTMLCanvasElement.prototype.toBlob (without installing the canvas npm package)",
        window
      );
    }
  }

  get width() {
    const parsed = parseInt(this.getAttribute("width"));
    return isNaN(parsed) || parsed < 0 || parsed > 2147483647 ? 300 : parsed;
  }

  set width(v) {
    v = v > 2147483647 ? 300 : v;
    this.setAttribute("width", String(v));
  }

  get height() {
    const parsed = parseInt(this.getAttribute("height"));
    return isNaN(parsed) || parsed < 0 || parsed > 2147483647 ? 150 : parsed;
  }

  set height(v) {
    v = v > 2147483647 ? 150 : v;
    this.setAttribute("height", String(v));
  }
}

// We need to wrap the methods that receive an image or canvas object
// (luckily, always as the first argument), so that these objects can be
// unwrapped an the expected types passed.
function wrapNodeCanvasMethod(ctx, name) {
  const prev = ctx[name];
  ctx[name] = function (image) {
    const impl = idlUtils.implForWrapper(image);
    if (impl) {
      arguments[0] = impl._image || impl._canvas;
    }
    return prev.apply(ctx, arguments);
  };
}

module.exports = {
  implementation: HTMLCanvasElementImpl
};
<commit_msg>Fix canvas.toBlob() JPEG quality to not always be zero<commit_after>"use strict";
const HTMLElementImpl = require("./HTMLElement-impl").implementation;
const notImplemented = require("../../browser/not-implemented");
const idlUtils = require("../generated/utils");
const { Canvas } = require("../../utils");

class HTMLCanvasElementImpl extends HTMLElementImpl {
  _attrModified(name, value) {
    if (this._canvas && (name === "width" || name === "height")) {
      this._canvas[name] = parseInt(value);
    }

    return super._attrModified.apply(this, arguments);
  }

  _getCanvas() {
    if (Canvas && !this._canvas) {
      this._canvas = new Canvas(this.width, this.height);
    }
    return this._canvas;
  }

  getContext(contextId) {
    const canvas = this._getCanvas();
    if (canvas) {
      if (!this._context) {
        this._context = canvas.getContext(contextId) || null;
        if (this._context) {
          // Override the native canvas reference with our wrapper. This is the
          // reason why we need to locally cache _context, since each call to
          // canvas.getContext(contextId) would replace this reference again.
          // Perhaps in the longer term, a better solution would be to create a
          // full wrapper for the Context object as well.
          this._context.canvas = idlUtils.wrapperForImpl(this);
          wrapNodeCanvasMethod(this._context, "createPattern");
          wrapNodeCanvasMethod(this._context, "drawImage");
        }
      }
      return this._context;
    }

    notImplemented(
      "HTMLCanvasElement.prototype.getContext (without installing the canvas npm package)",
      this._ownerDocument._defaultView
    );
    return null;
  }

  toDataURL() {
    const canvas = this._getCanvas();
    if (canvas) {
      return canvas.toDataURL.apply(this._canvas, arguments);
    }

    notImplemented(
      "HTMLCanvasElement.prototype.toDataURL (without installing the canvas npm package)",
      this._ownerDocument._defaultView
    );
    return null;
  }

  toBlob(callback, type, qualityArgument) {
    const window = this._ownerDocument._defaultView;
    const canvas = this._getCanvas();
    if (canvas) {
      let stream;
      switch (type) {
        case "image/jpg":
        case "image/jpeg":
          stream = canvas.createJPEGStream({
            quality: Math.max(0, Math.min(1, qualityArgument)) * 100
          });
          break;
        default:
          // TODO: Patch node-canvas to receive qualityArgument for PNG stream
          type = "image/png";
          stream = canvas.createPNGStream();
      }
      const buffers = [];
      stream.on("data", chunk => {
        buffers.push(chunk);
      });
      stream.on("end", () => {
        callback(new window.Blob(buffers, { type }));
      });
    } else {
      notImplemented(
        "HTMLCanvasElement.prototype.toBlob (without installing the canvas npm package)",
        window
      );
    }
  }

  get width() {
    const parsed = parseInt(this.getAttribute("width"));
    return isNaN(parsed) || parsed < 0 || parsed > 2147483647 ? 300 : parsed;
  }

  set width(v) {
    v = v > 2147483647 ? 300 : v;
    this.setAttribute("width", String(v));
  }

  get height() {
    const parsed = parseInt(this.getAttribute("height"));
    return isNaN(parsed) || parsed < 0 || parsed > 2147483647 ? 150 : parsed;
  }

  set height(v) {
    v = v > 2147483647 ? 150 : v;
    this.setAttribute("height", String(v));
  }
}

// We need to wrap the methods that receive an image or canvas object
// (luckily, always as the first argument), so that these objects can be
// unwrapped an the expected types passed.
function wrapNodeCanvasMethod(ctx, name) {
  const prev = ctx[name];
  ctx[name] = function (image) {
    const impl = idlUtils.implForWrapper(image);
    if (impl) {
      arguments[0] = impl._image || impl._canvas;
    }
    return prev.apply(ctx, arguments);
  };
}

module.exports = {
  implementation: HTMLCanvasElementImpl
};
<|endoftext|>


<commit_before>/* eslint-disable relay/unused-fields */
import React, { Component } from 'react';
import { graphql, createFragmentContainer, commitMutation } from 'react-relay/compat';
import { Store } from 'react-relay/classic';
import PropTypes from 'prop-types';
import styled from 'styled-components';
import qs from 'qs';
import { withPusher, pusherShape } from '../../pusher';
import PageTitle from '../PageTitle';
import MediaDetail from './MediaDetail';
import MediaSidebar from './MediaSidebar';
import MediaAnalysis from './MediaAnalysis'; // eslint-disable-line no-unused-vars
import MediaTags from './MediaTags'; // eslint-disable-line no-unused-vars
import MediaComponentRightPanel from './MediaComponentRightPanel';
import MediaSimilarityBar from './Similarity/MediaSimilarityBar';
import MediaSimilaritiesComponent from './Similarity/MediaSimilaritiesComponent';
import CheckContext from '../../CheckContext';

import {
  units,
  brandSecondary,
  backgroundMain,
  Column,
} from '../../styles/js/shared';

const StyledThreeColumnLayout = styled.div`
  display: flex;
  flex-wrap: wrap;
  justify-content: center;

  /* Middle column */
  .media__column {
    background-color: ${backgroundMain};
  }

  /* Middle column */
  .media-suggestions__center-column {
    background-color: white;
  }

  /* Right Column */
  .media__suggestions-column {
    max-width: none;
    background-color: ${backgroundMain};
  }

  /* Right Column */
  .media__annotations-column {
    border-left: 2px solid ${brandSecondary};
    padding-top: 0;
    padding-left: 0;
    padding-right: 0;
    max-width: none;

    /* Container of tabs */
    .media__annotations-tabs {
      background-color: white;
      border-bottom: 1px solid ${brandSecondary};
      padding-top: ${units(0.5)};
    }
  }
`;

const AnalysisColumn = styled.div`
  width: 420px;
  flex-grow: 0;
  padding: 0 ${units(2)} ${units(2)} ${units(2)};
  border-right: 1px solid ${brandSecondary};
  max-height: calc(100vh - 64px);
  overflow-y: auto;
`;

class MediaComponent extends Component {
  static scrollToAnnotation() {
    if (window.location.hash !== '') {
      const id = window.location.hash.replace(/^#/, '');
      const element = document.getElementById(id);
      if (element && element.scrollIntoView !== undefined) {
        element.scrollIntoView();
      }
    }
  }

  constructor(props) {
    super(props);

    // https://www.w3.org/TR/media-frags/
    const { t: temporalInterval = '' } = qs.parse(document.location.hash.substring(1));
    const [start, end] = temporalInterval.split(',').map(s => parseFloat(s));

    const gaps = [];
    if (start) gaps.push([0, start]);
    if (end) gaps.push([end, Number.MAX_VALUE]);

    const { team_bots: teamBots } = this.props.projectMedia.team;
    const enabledBots = teamBots.edges.map(b => b.node.login);
    const showRequests = (enabledBots.indexOf('smooch') > -1 || this.props.projectMedia.requests_count > 0);

    let initialTab = 'metadata';
    if (showRequests && this.props.view !== 'similarMedia') {
      initialTab = 'requests';
    } else {
      initialTab = 'suggestedMedia';
    }

    this.state = {
      playerState: {
        start,
        end,
        gaps,
        playing: false,
      },
      showTab: initialTab,
    };

    this.playerRef = React.createRef();
  }

  componentDidMount() {
    // this.setCurrentContext();
    MediaComponent.scrollToAnnotation();
    this.subscribe();
    window.addEventListener('resize', this.updatePlayerRect);
    window.addEventListener('scroll', this.updatePlayerRect);
    this.setPlayerRect();
    if (!this.props.projectMedia.read_by_me) {
      commitMutation(Store, {
        mutation: graphql`
          mutation MediaComponentCreateProjectMediaUserMutation($input: CreateProjectMediaUserInput!) {
            createProjectMediaUser(input: $input) {
              project_media {
                id
                read_by_someone: is_read
                read_by_me: is_read(by_me: true)
              }
            }
          }
        `,
        variables: {
          input: {
            project_media_id: this.props.projectMedia.dbid,
            read: true,
          },
        },
      });
    }
  }

  shouldComponentUpdate(nextProps, nextState) {
    const oldState = JSON.parse(JSON.stringify(this.state));
    const newState = JSON.parse(JSON.stringify(nextState));
    if (oldState.playerState) {
      delete oldState.playerState;
    }
    if (newState.playerState) {
      delete newState.playerState;
    }
    return JSON.stringify(newState) !== JSON.stringify(oldState) ||
    JSON.stringify(this.props) !== JSON.stringify(nextProps);
  }

  // componentWillUpdate(nextProps) {
  //   if (this.props.projectMedia.dbid !== nextProps.media.dbid) {
  //     this.unsubscribe();
  //   }
  // }

  // componentDidUpdate(prevProps) {
  //   this.setCurrentContext();
  //   MediaComponent.scrollToAnnotation();
  //   if (this.props.projectMedia.dbid !== prevProps.media.dbid) {
  //     this.subscribe();
  //   }
  // }

  componentWillUnmount() {
    window.removeEventListener('resize', this.updatePlayerRect);
    window.removeEventListener('scroll', this.updatePlayerRect);
    // this.unsubscribe();
  }

  setCurrentContext() {
    if (/^\/[^/]+\/project\/[0-9]+\/media\/[0-9]+/.test(window.location.pathname)) {
      const projectId = window.location.pathname.match(/^\/[^/]+\/project\/([0-9]+)\/media\/[0-9]+/)[1];
      if (this.props.relay.variables.contextId !== projectId) {
        this.props.relay.setVariables({ contextId: projectId });
      }
    }
  }

  setPlayerRect = () => {
    // update player rect used to anchor video annotation drawer
    if (this.playerRef && this.playerRef.current) {
      this.setState({ playerRect: this.playerRef.current.getBoundingClientRect() });
    }
  }

  getContext() {
    return new CheckContext(this).getContextStore();
  }

  setPlayerState = payload =>
    this.setState({ playerState: { ...this.state.playerState, ...payload } });

  updatePlayerRect = () => {
    this.setPlayerRect();
  }

  subscribe() {
    const { pusher, clientSessionId, projectMedia } = this.props;
    pusher.subscribe(projectMedia.pusher_channel).bind('relationship_change', 'MediaComponent', (data, run) => {
      const relationship = JSON.parse(data.message);
      if (
        (!relationship.id || clientSessionId !== data.actor_session_id) &&
        (relationship.source_id === projectMedia.dbid ||
        relationship.target_id === projectMedia.dbid)
      ) {
        if (run) {
          this.props.relay.forceFetch();
          return true;
        }
        return {
          id: `media-${projectMedia.dbid}`,
          callback: this.props.relay.forceFetch,
        };
      }
      return false;
    });

    pusher.subscribe(projectMedia.pusher_channel).bind('media_updated', 'MediaComponent', (data, run) => {
      const annotation = JSON.parse(data.message);
      if (annotation.annotated_id === projectMedia.dbid && clientSessionId !== data.actor_session_id) {
        if (run) {
          this.props.relay.forceFetch();
          return true;
        }
        return {
          id: `media-${projectMedia.dbid}`,
          callback: this.props.relay.forceFetch,
        };
      }
      return false;
    });
  }

  unsubscribe() {
    const { pusher, projectMedia } = this.props;
    pusher.unsubscribe(projectMedia.pusher_channel);
  }

  render() {
    // if (this.props.relay.variables.contextId === null && /\/project\//.test(window.location.pathname)) {
    //   return null;
    // }
    // TODO: New Relay `relay` prop has no  `variables`, `setVariables` or `forceFetch`
    // What will be of pusher?

    const { projectMedia, view } = this.props;

    const {
      playerState: {
        start,
        end,
        gaps,
        playing,
        scrubTo,
        seekTo,
      },
    } = this.state;

    const setShowTab = value => this.setState({ showTab: value });

    const linkPrefix = window.location.pathname.match(/^\/[^/]+\/((project|list)\/[0-9]+\/)?media\/[0-9]+/);
    const isSuggestedOrSimilar = (projectMedia.is_suggested || projectMedia.is_confirmed_similar_to_another_item);

    return (
      <div>
        <PageTitle prefix={projectMedia.title} team={projectMedia.team} />
        <StyledThreeColumnLayout className="media">
          <AnalysisColumn>
            <MediaSidebar projectMedia={projectMedia} />
          </AnalysisColumn>
          { view === 'default' || view === 'similarMedia' ?
            <React.Fragment>
              <Column className="media__column">
                { (linkPrefix && !isSuggestedOrSimilar) ? <MediaSimilarityBar projectMedia={projectMedia} setShowTab={setShowTab} /> : null }
                <MediaDetail
                  hideBorder
                  hideRelated
                  media={projectMedia}
                  onPlayerReady={this.setPlayerRect}
                  onReady={this.handleMediaDetailReady}
                  playerRef={this.playerRef}
                  setPlayerState={this.setPlayerState}
                  {...{
                    playing, start, end, gaps, seekTo, scrubTo,
                  }}
                />
                { isSuggestedOrSimilar ? null : <MediaSimilaritiesComponent projectMedia={projectMedia} setShowTab={setShowTab} /> }
              </Column>
              <Column className="media__annotations-column" overflow="hidden">
                <MediaComponentRightPanel
                  projectMedia={projectMedia}
                  showTab={this.state.showTab}
                  setShowTab={setShowTab}
                />
              </Column>
            </React.Fragment> : null }
        </StyledThreeColumnLayout>
      </div>
    );
  }
}

MediaComponent.propTypes = {
  // https://github.com/yannickcr/eslint-plugin-react/issues/1389
  // eslint-disable-next-line react/no-typos
  pusher: pusherShape.isRequired,
  clientSessionId: PropTypes.string.isRequired,
};

MediaComponent.contextTypes = {
  store: PropTypes.object,
};

export default createFragmentContainer(withPusher(MediaComponent), graphql`
  fragment MediaComponent_projectMedia on ProjectMedia {
    ...MediaAnalysis_projectMedia
    ...MediaTags_projectMedia
    ...MediaSimilaritiesComponent_projectMedia
    id
    dbid
    title
    read_by_someone: is_read
    read_by_me: is_read(by_me: true)
    permissions
    pusher_channel
    project_id
    requests_count
    picture
    show_warning_cover
    creator_name
    user_id
    channel
    suggested_similar_relationships(first: 10000) {
      edges {
        node {
          id
            relationship_type
            dbid
            source_id
            target_id
        }
      }
    }
    suggested_main_item { # used by MediaClaim, MediaFactCheck
      dbid
      team {
        slug
      }
      claim_description {
        id
        dbid
        context
        description
        user {
          name
        }
        updated_at
        fact_check {
          id
          summary
          title
          url
          user {
            name
          }
          updated_at
        }
      }
    }
    confirmed_main_item {
      dbid
      team {
        slug
      }
    }
    is_confirmed_similar_to_another_item
    is_suggested
    is_secondary
    claim_description {
      id
      dbid
      description
      context
      updated_at
      user {
        name
      }
      fact_check {
        id
        title
        summary
        url
        updated_at
        user {
          name
        }
      }
    }
    media {
      url
      quote
      embed_path
      metadata
      type
      picture
    }
    last_status
    last_status_obj {
      id
      data
      updated_at
    }
    report: dynamic_annotation_report_design {
      id
      data
    }
    comments: annotations(first: 10000, annotation_type: "comment") {
      edges {
        node {
          ... on Comment {
            id
            dbid
            text
            parsed_fragment
            annotator {
              id
              name
              profile_image
            }
            comments: annotations(first: 10000, annotation_type: "comment") {
              edges {
                node {
                  ... on Comment {
                    id
                    created_at
                    text
                    annotator {
                      id
                      name
                      profile_image
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
    clips: annotations(first: 10000, annotation_type: "clip") {
      edges {
        node {
          ... on Dynamic {
            id
            data
            parsed_fragment
          }
        }
      }
    }
    tags(first: 10000) {
      edges {
        node {
          id
          dbid
          fragment
          parsed_fragment
          annotated_id
          annotated_type
          annotated_type
          tag_text_object {
            id
            text
          }
        }
      }
    }
    geolocations: annotations(first: 10000, annotation_type: "geolocation") {
      edges {
        node {
          ... on Dynamic {
            id
            parsed_fragment
            content
          }
        }
      }
    }
    team {
      id
      dbid
      slug
      name
      get_language
      get_report
      verification_statuses
      permissions
      team_bots(first: 10000) {
        edges {
          node {
            login
          }
        }
      }
      smooch_bot: team_bot_installation(bot_identifier: "smooch") {
        id
      }
    }
  }
`);
<commit_msg>Fixing integration test and tab behavior<commit_after>/* eslint-disable relay/unused-fields */
import React, { Component } from 'react';
import { graphql, createFragmentContainer, commitMutation } from 'react-relay/compat';
import { Store } from 'react-relay/classic';
import PropTypes from 'prop-types';
import styled from 'styled-components';
import qs from 'qs';
import { withPusher, pusherShape } from '../../pusher';
import PageTitle from '../PageTitle';
import MediaDetail from './MediaDetail';
import MediaSidebar from './MediaSidebar';
import MediaAnalysis from './MediaAnalysis'; // eslint-disable-line no-unused-vars
import MediaTags from './MediaTags'; // eslint-disable-line no-unused-vars
import MediaComponentRightPanel from './MediaComponentRightPanel';
import MediaSimilarityBar from './Similarity/MediaSimilarityBar';
import MediaSimilaritiesComponent from './Similarity/MediaSimilaritiesComponent';
import CheckContext from '../../CheckContext';

import {
  units,
  brandSecondary,
  backgroundMain,
  Column,
} from '../../styles/js/shared';

const StyledThreeColumnLayout = styled.div`
  display: flex;
  flex-wrap: wrap;
  justify-content: center;

  /* Middle column */
  .media__column {
    background-color: ${backgroundMain};
  }

  /* Middle column */
  .media-suggestions__center-column {
    background-color: white;
  }

  /* Right Column */
  .media__suggestions-column {
    max-width: none;
    background-color: ${backgroundMain};
  }

  /* Right Column */
  .media__annotations-column {
    border-left: 2px solid ${brandSecondary};
    padding-top: 0;
    padding-left: 0;
    padding-right: 0;
    max-width: none;

    /* Container of tabs */
    .media__annotations-tabs {
      background-color: white;
      border-bottom: 1px solid ${brandSecondary};
      padding-top: ${units(0.5)};
    }
  }
`;

const AnalysisColumn = styled.div`
  width: 420px;
  flex-grow: 0;
  padding: 0 ${units(2)} ${units(2)} ${units(2)};
  border-right: 1px solid ${brandSecondary};
  max-height: calc(100vh - 64px);
  overflow-y: auto;
`;

class MediaComponent extends Component {
  static scrollToAnnotation() {
    if (window.location.hash !== '') {
      const id = window.location.hash.replace(/^#/, '');
      const element = document.getElementById(id);
      if (element && element.scrollIntoView !== undefined) {
        element.scrollIntoView();
      }
    }
  }

  constructor(props) {
    super(props);

    // https://www.w3.org/TR/media-frags/
    const { t: temporalInterval = '' } = qs.parse(document.location.hash.substring(1));
    const [start, end] = temporalInterval.split(',').map(s => parseFloat(s));

    const gaps = [];
    if (start) gaps.push([0, start]);
    if (end) gaps.push([end, Number.MAX_VALUE]);

    const { team_bots: teamBots } = this.props.projectMedia.team;
    const enabledBots = teamBots.edges.map(b => b.node.login);
    const showRequests = (enabledBots.indexOf('smooch') > -1 || this.props.projectMedia.requests_count > 0);

    let initialTab = 'metadata';
    if (showRequests && this.props.view !== 'similarMedia') {
      initialTab = 'requests';
    } else if (this.props.view === 'similarMedia') {
      initialTab = 'suggestedMedia';
    }

    this.state = {
      playerState: {
        start,
        end,
        gaps,
        playing: false,
      },
      showTab: initialTab,
    };

    this.playerRef = React.createRef();
  }

  componentDidMount() {
    // this.setCurrentContext();
    MediaComponent.scrollToAnnotation();
    this.subscribe();
    window.addEventListener('resize', this.updatePlayerRect);
    window.addEventListener('scroll', this.updatePlayerRect);
    this.setPlayerRect();
    if (!this.props.projectMedia.read_by_me) {
      commitMutation(Store, {
        mutation: graphql`
          mutation MediaComponentCreateProjectMediaUserMutation($input: CreateProjectMediaUserInput!) {
            createProjectMediaUser(input: $input) {
              project_media {
                id
                read_by_someone: is_read
                read_by_me: is_read(by_me: true)
              }
            }
          }
        `,
        variables: {
          input: {
            project_media_id: this.props.projectMedia.dbid,
            read: true,
          },
        },
      });
    }
  }

  shouldComponentUpdate(nextProps, nextState) {
    const oldState = JSON.parse(JSON.stringify(this.state));
    const newState = JSON.parse(JSON.stringify(nextState));
    if (oldState.playerState) {
      delete oldState.playerState;
    }
    if (newState.playerState) {
      delete newState.playerState;
    }
    return JSON.stringify(newState) !== JSON.stringify(oldState) ||
    JSON.stringify(this.props) !== JSON.stringify(nextProps);
  }

  // componentWillUpdate(nextProps) {
  //   if (this.props.projectMedia.dbid !== nextProps.media.dbid) {
  //     this.unsubscribe();
  //   }
  // }

  // componentDidUpdate(prevProps) {
  //   this.setCurrentContext();
  //   MediaComponent.scrollToAnnotation();
  //   if (this.props.projectMedia.dbid !== prevProps.media.dbid) {
  //     this.subscribe();
  //   }
  // }

  componentWillUnmount() {
    window.removeEventListener('resize', this.updatePlayerRect);
    window.removeEventListener('scroll', this.updatePlayerRect);
    // this.unsubscribe();
  }

  setCurrentContext() {
    if (/^\/[^/]+\/project\/[0-9]+\/media\/[0-9]+/.test(window.location.pathname)) {
      const projectId = window.location.pathname.match(/^\/[^/]+\/project\/([0-9]+)\/media\/[0-9]+/)[1];
      if (this.props.relay.variables.contextId !== projectId) {
        this.props.relay.setVariables({ contextId: projectId });
      }
    }
  }

  setPlayerRect = () => {
    // update player rect used to anchor video annotation drawer
    if (this.playerRef && this.playerRef.current) {
      this.setState({ playerRect: this.playerRef.current.getBoundingClientRect() });
    }
  }

  getContext() {
    return new CheckContext(this).getContextStore();
  }

  setPlayerState = payload =>
    this.setState({ playerState: { ...this.state.playerState, ...payload } });

  updatePlayerRect = () => {
    this.setPlayerRect();
  }

  subscribe() {
    const { pusher, clientSessionId, projectMedia } = this.props;
    pusher.subscribe(projectMedia.pusher_channel).bind('relationship_change', 'MediaComponent', (data, run) => {
      const relationship = JSON.parse(data.message);
      if (
        (!relationship.id || clientSessionId !== data.actor_session_id) &&
        (relationship.source_id === projectMedia.dbid ||
        relationship.target_id === projectMedia.dbid)
      ) {
        if (run) {
          this.props.relay.forceFetch();
          return true;
        }
        return {
          id: `media-${projectMedia.dbid}`,
          callback: this.props.relay.forceFetch,
        };
      }
      return false;
    });

    pusher.subscribe(projectMedia.pusher_channel).bind('media_updated', 'MediaComponent', (data, run) => {
      const annotation = JSON.parse(data.message);
      if (annotation.annotated_id === projectMedia.dbid && clientSessionId !== data.actor_session_id) {
        if (run) {
          this.props.relay.forceFetch();
          return true;
        }
        return {
          id: `media-${projectMedia.dbid}`,
          callback: this.props.relay.forceFetch,
        };
      }
      return false;
    });
  }

  unsubscribe() {
    const { pusher, projectMedia } = this.props;
    pusher.unsubscribe(projectMedia.pusher_channel);
  }

  render() {
    // if (this.props.relay.variables.contextId === null && /\/project\//.test(window.location.pathname)) {
    //   return null;
    // }
    // TODO: New Relay `relay` prop has no  `variables`, `setVariables` or `forceFetch`
    // What will be of pusher?

    const { projectMedia, view } = this.props;

    const {
      playerState: {
        start,
        end,
        gaps,
        playing,
        scrubTo,
        seekTo,
      },
    } = this.state;

    const setShowTab = value => this.setState({ showTab: value });

    const linkPrefix = window.location.pathname.match(/^\/[^/]+\/((project|list)\/[0-9]+\/)?media\/[0-9]+/);
    const isSuggestedOrSimilar = (projectMedia.is_suggested || projectMedia.is_confirmed_similar_to_another_item);

    return (
      <div>
        <PageTitle prefix={projectMedia.title} team={projectMedia.team} />
        <StyledThreeColumnLayout className="media">
          <AnalysisColumn>
            <MediaSidebar projectMedia={projectMedia} />
          </AnalysisColumn>
          { view === 'default' || view === 'similarMedia' ?
            <React.Fragment>
              <Column className="media__column">
                { (linkPrefix && !isSuggestedOrSimilar) ? <MediaSimilarityBar projectMedia={projectMedia} setShowTab={setShowTab} /> : null }
                <MediaDetail
                  hideBorder
                  hideRelated
                  media={projectMedia}
                  onPlayerReady={this.setPlayerRect}
                  onReady={this.handleMediaDetailReady}
                  playerRef={this.playerRef}
                  setPlayerState={this.setPlayerState}
                  {...{
                    playing, start, end, gaps, seekTo, scrubTo,
                  }}
                />
                { isSuggestedOrSimilar ? null : <MediaSimilaritiesComponent projectMedia={projectMedia} setShowTab={setShowTab} /> }
              </Column>
              <Column className="media__annotations-column" overflow="hidden">
                <MediaComponentRightPanel
                  projectMedia={projectMedia}
                  showTab={this.state.showTab}
                  setShowTab={setShowTab}
                />
              </Column>
            </React.Fragment> : null }
        </StyledThreeColumnLayout>
      </div>
    );
  }
}

MediaComponent.propTypes = {
  // https://github.com/yannickcr/eslint-plugin-react/issues/1389
  // eslint-disable-next-line react/no-typos
  pusher: pusherShape.isRequired,
  clientSessionId: PropTypes.string.isRequired,
};

MediaComponent.contextTypes = {
  store: PropTypes.object,
};

export default createFragmentContainer(withPusher(MediaComponent), graphql`
  fragment MediaComponent_projectMedia on ProjectMedia {
    ...MediaAnalysis_projectMedia
    ...MediaTags_projectMedia
    ...MediaSimilaritiesComponent_projectMedia
    id
    dbid
    title
    read_by_someone: is_read
    read_by_me: is_read(by_me: true)
    permissions
    pusher_channel
    project_id
    requests_count
    picture
    show_warning_cover
    creator_name
    user_id
    channel
    suggested_similar_relationships(first: 10000) {
      edges {
        node {
          id
            relationship_type
            dbid
            source_id
            target_id
        }
      }
    }
    suggested_main_item { # used by MediaClaim, MediaFactCheck
      dbid
      team {
        slug
      }
      claim_description {
        id
        dbid
        context
        description
        user {
          name
        }
        updated_at
        fact_check {
          id
          summary
          title
          url
          user {
            name
          }
          updated_at
        }
      }
    }
    confirmed_main_item {
      dbid
      team {
        slug
      }
    }
    is_confirmed_similar_to_another_item
    is_suggested
    is_secondary
    claim_description {
      id
      dbid
      description
      context
      updated_at
      user {
        name
      }
      fact_check {
        id
        title
        summary
        url
        updated_at
        user {
          name
        }
      }
    }
    media {
      url
      quote
      embed_path
      metadata
      type
      picture
    }
    last_status
    last_status_obj {
      id
      data
      updated_at
    }
    report: dynamic_annotation_report_design {
      id
      data
    }
    comments: annotations(first: 10000, annotation_type: "comment") {
      edges {
        node {
          ... on Comment {
            id
            dbid
            text
            parsed_fragment
            annotator {
              id
              name
              profile_image
            }
            comments: annotations(first: 10000, annotation_type: "comment") {
              edges {
                node {
                  ... on Comment {
                    id
                    created_at
                    text
                    annotator {
                      id
                      name
                      profile_image
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
    clips: annotations(first: 10000, annotation_type: "clip") {
      edges {
        node {
          ... on Dynamic {
            id
            data
            parsed_fragment
          }
        }
      }
    }
    tags(first: 10000) {
      edges {
        node {
          id
          dbid
          fragment
          parsed_fragment
          annotated_id
          annotated_type
          annotated_type
          tag_text_object {
            id
            text
          }
        }
      }
    }
    geolocations: annotations(first: 10000, annotation_type: "geolocation") {
      edges {
        node {
          ... on Dynamic {
            id
            parsed_fragment
            content
          }
        }
      }
    }
    team {
      id
      dbid
      slug
      name
      get_language
      get_report
      verification_statuses
      permissions
      team_bots(first: 10000) {
        edges {
          node {
            login
          }
        }
      }
      smooch_bot: team_bot_installation(bot_identifier: "smooch") {
        id
      }
    }
  }
`);
<|endoftext|>


<commit_before>import React from "react-native";
import RoomItem from "../components/room-item";
import controller from "./controller";

const {
	InteractionManager
} = React;

@controller
export default class RoomItemController extends React.Component {
	constructor(props) {
		super(props);

		this.state = {
			role: "none"
		};
	}

	componentDidMount() {
		this._updateData();

		this.handle("statechange", changes => {
			const user = this.store.get("user");

			if (changes.entities && changes.entities[this.props.room.id + "_" + user]) {
				this._updateData();
			}
		});
	}

	_updateData() {
		InteractionManager.runAfterInteractions(() => {
			if (this._mounted) {
				const role = this.store.getUserRole(this.store.get("user"), this.props.room.id);

				this.setState({
					role: role === "registered" || !role ? "none" : role
				});
			}
		});
	}

	_joinCommunity() {
		this.dispatch("join", {
			to: this.props.room.id
		});
	}

	_leaveCommunity() {
		this.dispatch("part", {
			to: this.props.room.id
		});
	}

	render() {
		return (
			<RoomItem
				{...this.props}
				{...this.state}
				joinCommunity={this._joinCommunity.bind(this)}
				leaveCommunity={this._leaveCommunity.bind(this)}
			/>
		);
	}
}

RoomItemController.propTypes = {
	room: React.PropTypes.shape({
		id: React.PropTypes.string.isRequired
	})
};
<commit_msg>Send away for room when leaving room<commit_after>import React from "react-native";
import RoomItem from "../components/room-item";
import controller from "./controller";

const {
	InteractionManager
} = React;

@controller
export default class RoomItemController extends React.Component {
	constructor(props) {
		super(props);

		this.state = {
			role: "none"
		};
	}

	componentDidMount() {
		this._updateData();

		this.handle("statechange", changes => {
			const user = this.store.get("user");

			if (changes.entities && changes.entities[this.props.room.id + "_" + user]) {
				this._updateData();
			}
		});
	}

	_updateData() {
		InteractionManager.runAfterInteractions(() => {
			if (this._mounted) {
				const role = this.store.getUserRole(this.store.get("user"), this.props.room.id);

				this.setState({
					role: role === "registered" || !role ? "none" : role
				});
			}
		});
	}

	_joinCommunity() {
		this.dispatch("join", {
			to: this.props.room.id
		});
	}

	_leaveCommunity() {
		const room = this.props.room.id;

		this.dispatch("part", {
			to: room
		})
		.then(() => {
			return this.dispatch("away", {
				to: room
			});
		});
	}

	render() {
		return (
			<RoomItem
				{...this.props}
				{...this.state}
				joinCommunity={this._joinCommunity.bind(this)}
				leaveCommunity={this._leaveCommunity.bind(this)}
			/>
		);
	}
}

RoomItemController.propTypes = {
	room: React.PropTypes.shape({
		id: React.PropTypes.string.isRequired
	})
};
<|endoftext|>


<commit_before>// Edit page settings.
//
// Typically instantiated by the page settings button, however it can be instantiated
// programmatically to edit the page settings of a different page, in which case
// `options.page` must provide at least the `_id` and `type` properties.
//
// If the page settings of the current page are edited, after editing is complete the
// user is redirected to the page on save, to reflect all changes including slug edits.
//
// `options.afterSave` may be a function which takes a page object and a callback.
// The page object is the page as returned by the server after the save operation.

apos.define('apostrophe-pages-editor', {
  extend: 'apostrophe-modal',
  source: 'editor',
  verb: 'insert',
  label: 'New Page',
  construct: function(self, options) {
    self.typeChoices = apos.pages.options.typeChoices;
    self.page = options.page || apos.pages.page;
    self.verb = self.options.verb;
    self.label = self.options.label;

    // Current page type name
    self.type = self.page.type;

    // data to send to the source
    self.body = {
      type: self.type,
      verb: self.verb,
      id: self.page._id
    };

    self.beforeShow = function(callback) {
      var $type = apos.schemas.findField(self.$el, 'type');
      $type.on('change', function() {
        self.changedType($type.val());
      });
      return self.open(callback);
    };

    self.open = function(callback) {
      return self.api(
        'fetch-to-' + self.verb,
        {
          _id: self.page._id,
          type: self.type
        }, function(result) {
        if (result.status === 'notfound') {
          apos('That page does not exist.');
          return callback('error');
        } else if (result.status !== 'ok') {
          apos.notify('An error occurred. Please try again.', { type: 'error' });
          return callback('error');
        }
        self.schema = result.schema;
        return self.populate(result.data, callback);
      }, function() {
        apos.notify('An error occurred. Please try again.', { type: 'error' });
        return callback('network');
      });
    };

    self.populate = function(data, callback) {
      return apos.schemas.populate(self.$el, self.schema, data, callback);
    };
    self.beforeSave = function(callback) {
      return setImmediate(callback);
    };
    self.afterSave = function(callback) {
      return setImmediate(callback);
    };
    self.convert = function(page, callback) {
      return apos.schemas.convert(self.$el, self.schema, page, callback);
    };
    // For pages, saveContent never invokes its callback except on an error,
    // because it redirects to the new page URL. To aid you in doing something
    // before that happens, the afterSave method is provided and can be overridden
    // as you see fit.
    self.saveContent = function(callback) {
      var page = {};
      var data;
      return async.series({
        convert: function(callback) {
          return self.convert(page, callback);
        },
        beforeSave: function(callback) {
          return self.beforeSave(callback);
        },
        save: function(callback) {
          return self.api(self.verb, { currentPageId: self.page._id, page: page }, function(_data) {
            data = _data;
            if (data.status !== 'ok') {
              apos.notify('An error occurred while creating the page: ' + data.status, { type: 'error' });
              return callback(data.status);
            }
            self.savedPage = data.page;
            return callback(null);
          });
        },
        afterSave: function(callback) {
          if (self.options.afterSave) {
            return self.options.afterSave(self.savedPage, method);
          } else {
            return method();
          }
          function method() {
            return self.afterSave(callback);
          }
        },
        redirect: function(callback) {
          if (self.options.redirectIfSamePage || (self.options.redirectIfSamePage === undefined)) {
            if (self.page._id === apos.pages.page._id) {
              // The slug may have changed, etc. Reflect that
              window.location.href = data.url;
            }
          }
          return callback(null);
        }
      }, callback);
    };

    self.changedType = function(type) {
      var page = _.cloneDeep(self.page);
      return async.series({
        convert: function(callback) {
          return self.convert(page, function(err) {
            // errors are OK here because we are just switching
            // page types. We want as much data as we can get for
            // the new page type to populate with
            return callback(null);
          });
        },
        fetch: function(callback) {
          return self.api('fetch-to-' + self.verb, { _id: self.page._id, type: type }, function(result) {
            if (result.status === 'notfound') {
              apos.notify('That page does not exist.', { type: 'error' });
              return callback('error');
            } else if (result.status !== 'ok') {
              apos.notify('An error occurred. Please try again.', { type: 'error' });
              return callback('error');
            }
            self.schema = result.schema;
            return callback(null);
          }, function() {
            return callback('network');
          });
        },
        editor: function(callback) {
          return self.html('editor', { id: self.page._id, type: type, verb: self.verb }, function(html) {
            var $html = $(html);
            var $newFields = $html.find('[data-page-schema-fields]').children();
            var $wrapper = self.$el.find('[data-page-schema-fields]');
            $wrapper.html('');
            $wrapper.append($newFields);
            return callback(null);
          }, function() {
            return callback('network');
          });
        },
        refresh: function(callback) {
          // Repopulate with what we know so far from editing
          // prior to the page type change
          return self.populate(page, callback);
        }
      }, function(err) {
        if (err) {
          apos.notify('An error occurred. Please try again.', { type: 'error' });
          return;
        }
        apos.emit('enhance', self.$el.find('[data-page-schema-fields]'));
        self.type = type;
      });
    };
  }
});

// A subclass for updating rather than inserting.
// Could be more exciting later

apos.define('apostrophe-pages-editor-update', {
  extend: 'apostrophe-pages-editor',
  verb: 'update',
  label: 'Edit Page Settings'
});

apos.define('apostrophe-pages-editor-copy', {
  extend: 'apostrophe-pages-editor',
  verb: 'copy',
  label: 'Copy Page'
});
<commit_msg>* Page type changes only refreshed the schema fields on the first change — now they do it properly after every change * Page type changes use the "busy" mechanism properly to prevent race conditions<commit_after>// Edit page settings.
//
// Typically instantiated by the page settings button, however it can be instantiated
// programmatically to edit the page settings of a different page, in which case
// `options.page` must provide at least the `_id` and `type` properties.
//
// If the page settings of the current page are edited, after editing is complete the
// user is redirected to the page on save, to reflect all changes including slug edits.
//
// `options.afterSave` may be a function which takes a page object and a callback.
// The page object is the page as returned by the server after the save operation.

apos.define('apostrophe-pages-editor', {
  extend: 'apostrophe-modal',
  source: 'editor',
  verb: 'insert',
  label: 'New Page',
  construct: function(self, options) {
    self.typeChoices = apos.pages.options.typeChoices;
    self.page = options.page || apos.pages.page;
    self.verb = self.options.verb;
    self.label = self.options.label;

    // Current page type name
    self.type = self.page.type;

    // data to send to the source
    self.body = {
      type: self.type,
      verb: self.verb,
      id: self.page._id
    };

    self.beforeShow = function(callback) {
      self.addTypeChangeHandler();
      return self.open(callback);
    };

    // Add a change event handler to the type field.
    // This is installed at initial load time and also
    // when the content is re-rendered due to a page
    // type change, resulting in a new type field element.

    self.addTypeChangeHandler = function() {
      var $type = apos.schemas.findField(self.$el, 'type');
      $type.on('change', function() {
        self.changedType($type.val());
      });
    };

    self.open = function(callback) {
      return self.api(
        'fetch-to-' + self.verb,
        {
          _id: self.page._id,
          type: self.type
        }, function(result) {
        if (result.status === 'notfound') {
          apos('That page does not exist.');
          return callback('error');
        } else if (result.status !== 'ok') {
          apos.notify('An error occurred. Please try again.', { type: 'error' });
          return callback('error');
        }
        self.schema = result.schema;
        return self.populate(result.data, callback);
      }, function() {
        apos.notify('An error occurred. Please try again.', { type: 'error' });
        return callback('network');
      });
    };

    self.populate = function(data, callback) {
      return apos.schemas.populate(self.$el, self.schema, data, callback);
    };
    self.beforeSave = function(callback) {
      return setImmediate(callback);
    };
    self.afterSave = function(callback) {
      return setImmediate(callback);
    };
    self.convert = function(page, callback) {
      return apos.schemas.convert(self.$el, self.schema, page, callback);
    };
    // For pages, saveContent never invokes its callback except on an error,
    // because it redirects to the new page URL. To aid you in doing something
    // before that happens, the afterSave method is provided and can be overridden
    // as you see fit.
    self.saveContent = function(callback) {
      var page = {};
      var data;
      return async.series({
        convert: function(callback) {
          return self.convert(page, callback);
        },
        beforeSave: function(callback) {
          return self.beforeSave(callback);
        },
        save: function(callback) {
          return self.api(self.verb, { currentPageId: self.page._id, page: page }, function(_data) {
            data = _data;
            if (data.status !== 'ok') {
              apos.notify('An error occurred while creating the page: ' + data.status, { type: 'error' });
              return callback(data.status);
            }
            self.savedPage = data.page;
            return callback(null);
          });
        },
        afterSave: function(callback) {
          if (self.options.afterSave) {
            return self.options.afterSave(self.savedPage, method);
          } else {
            return method();
          }
          function method() {
            return self.afterSave(callback);
          }
        },
        redirect: function(callback) {
          if (self.options.redirectIfSamePage || (self.options.redirectIfSamePage === undefined)) {
            if (self.page._id === apos.pages.page._id) {
              // The slug may have changed, etc. Reflect that
              window.location.href = data.url;
            }
          }
          return callback(null);
        }
      }, callback);
    };

    self.changedType = function(type) {
      apos.ui.globalBusy(true);
      var page = _.cloneDeep(self.page);
      return async.series({
        convert: function(callback) {
          return self.convert(page, function(err) {
            // errors are OK here because we are just switching
            // page types. We want as much data as we can get for
            // the new page type to populate with
            return callback(null);
          });
        },
        fetch: function(callback) {
          return self.api('fetch-to-' + self.verb, { _id: self.page._id, type: type }, function(result) {
            if (result.status === 'notfound') {
              apos.notify('That page does not exist.', { type: 'error' });
              return callback('error');
            } else if (result.status !== 'ok') {
              apos.notify('An error occurred. Please try again.', { type: 'error' });
              return callback('error');
            }
            self.schema = result.schema;
            return callback(null);
          }, function() {
            return callback('network');
          });
        },
        editor: function(callback) {
          return self.html('editor', { id: self.page._id, type: type, verb: self.verb }, function(html) {
            var $html = $(html);
            var $newFields = $html.find('[data-page-schema-fields]').children();
            var $wrapper = self.$el.find('[data-page-schema-fields]');
            $wrapper.html('');
            $wrapper.append($newFields);
            return callback(null);
          }, function() {
            return callback('network');
          });
        },
        refresh: function(callback) {
          // Repopulate with what we know so far from editing
          // prior to the page type change
          return self.populate(page, callback);
        }
      }, function(err) {
        apos.ui.globalBusy(false);
        if (err) {
          apos.notify('An error occurred. Please try again.', { type: 'error' });
          return;
        }
        apos.emit('enhance', self.$el.find('[data-page-schema-fields]'));
        self.addTypeChangeHandler();
        self.type = type;
      });
    };
  }
});

// A subclass for updating rather than inserting.
// Could be more exciting later

apos.define('apostrophe-pages-editor-update', {
  extend: 'apostrophe-pages-editor',
  verb: 'update',
  label: 'Edit Page Settings'
});

apos.define('apostrophe-pages-editor-copy', {
  extend: 'apostrophe-pages-editor',
  verb: 'copy',
  label: 'Copy Page'
});
<|endoftext|>


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

'use strict';

/*
* When adding modules to the namespace, ensure that they are added in alphabetical order according to module name.
*/

// MODULES //

var setReadOnly = require( '@stdlib/utils/define-read-only-property' );

// MAIN //

/**
* Top-level namespace.
*
* @namespace ns
*/
var ns = {};

/**
* @name incrcount
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/count}
*/
setReadOnly( ns, 'incrcount', require( '@stdlib/stats/incr/count' ) );

/**
* @name incrcovariance
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/covariance}
*/
setReadOnly( ns, 'incrcovariance', require( '@stdlib/stats/incr/covariance' ) );

/**
* @name incrcovmat
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/covmat}
*/
setReadOnly( ns, 'incrcovmat', require( '@stdlib/stats/incr/covmat' ) );

/**
* @name increwmean
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/ewmean}
*/
setReadOnly( ns, 'increwmean', require( '@stdlib/stats/incr/ewmean' ) );

/**
* @name incrgmean
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/gmean}
*/
setReadOnly( ns, 'incrgmean', require( '@stdlib/stats/incr/gmean' ) );

/**
* @name incrhmean
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/hmean}
*/
setReadOnly( ns, 'incrhmean', require( '@stdlib/stats/incr/hmean' ) );

/**
* @name incrkurtosis
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/kurtosis}
*/
setReadOnly( ns, 'incrkurtosis', require( '@stdlib/stats/incr/kurtosis' ) );

/**
* @name incrmax
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/max}
*/
setReadOnly( ns, 'incrmax', require( '@stdlib/stats/incr/max' ) );

/**
* @name incrmaxabs
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/maxabs}
*/
setReadOnly( ns, 'incrmaxabs', require( '@stdlib/stats/incr/maxabs' ) );

/**
* @name incrmcovariance
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/mcovariance}
*/
setReadOnly( ns, 'incrmcovariance', require( '@stdlib/stats/incr/mcovariance' ) );

/**
* @name incrmean
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/mean}
*/
setReadOnly( ns, 'incrmean', require( '@stdlib/stats/incr/mean' ) );

/**
* @name incrmeanabs
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/meanabs}
*/
setReadOnly( ns, 'incrmeanabs', require( '@stdlib/stats/incr/meanabs' ) );

/**
* @name incrmgmean
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/mgmean}
*/
setReadOnly( ns, 'incrmgmean', require( '@stdlib/stats/incr/mgmean' ) );

/**
* @name incrmhmean
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/mhmean}
*/
setReadOnly( ns, 'incrmhmean', require( '@stdlib/stats/incr/mhmean' ) );

/**
* @name incrmidrange
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/midrange}
*/
setReadOnly( ns, 'incrmidrange', require( '@stdlib/stats/incr/midrange' ) );

/**
* @name incrmin
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/min}
*/
setReadOnly( ns, 'incrmin', require( '@stdlib/stats/incr/min' ) );

/**
* @name incrminabs
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/minabs}
*/
setReadOnly( ns, 'incrminabs', require( '@stdlib/stats/incr/minabs' ) );

/**
* @name incrmmax
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/mmax}
*/
setReadOnly( ns, 'incrmmax', require( '@stdlib/stats/incr/mmax' ) );

/**
* @name incrmmaxabs
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/mmaxabs}
*/
setReadOnly( ns, 'incrmmaxabs', require( '@stdlib/stats/incr/mmaxabs' ) );

/**
* @name incrmmean
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/mmean}
*/
setReadOnly( ns, 'incrmmean', require( '@stdlib/stats/incr/mmean' ) );

/**
* @name incrmmeanabs
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/mmeanabs}
*/
setReadOnly( ns, 'incrmmeanabs', require( '@stdlib/stats/incr/mmeanabs' ) );

/**
* @name incrmmidrange
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/mmidrange}
*/
setReadOnly( ns, 'incrmmidrange', require( '@stdlib/stats/incr/mmidrange' ) );

/**
* @name incrmmin
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/mmin}
*/
setReadOnly( ns, 'incrmmin', require( '@stdlib/stats/incr/mmin' ) );

/**
* @name incrmminabs
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/mminabs}
*/
setReadOnly( ns, 'incrmminabs', require( '@stdlib/stats/incr/mminabs' ) );

/**
* @name incrmminmax
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/mminmax}
*/
setReadOnly( ns, 'incrmminmax', require( '@stdlib/stats/incr/mminmax' ) );

/**
* @name incrmpcorr
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/mpcorr}
*/
setReadOnly( ns, 'incrmpcorr', require( '@stdlib/stats/incr/mpcorr' ) );

/**
* @name incrmpcorrdist
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/mpcorrdist}
*/
setReadOnly( ns, 'incrmpcorrdist', require( '@stdlib/stats/incr/mpcorrdist' ) );

/**
* @name incrmprod
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/mprod}
*/
setReadOnly( ns, 'incrmprod', require( '@stdlib/stats/incr/mprod' ) );

/**
* @name incrmrange
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/mrange}
*/
setReadOnly( ns, 'incrmrange', require( '@stdlib/stats/incr/mrange' ) );

/**
* @name incrmstdev
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/mstdev}
*/
setReadOnly( ns, 'incrmstdev', require( '@stdlib/stats/incr/mstdev' ) );

/**
* @name incrmsum
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/msum}
*/
setReadOnly( ns, 'incrmsum', require( '@stdlib/stats/incr/msum' ) );

/**
* @name incrmsumabs
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/msumabs}
*/
setReadOnly( ns, 'incrmsumabs', require( '@stdlib/stats/incr/msumabs' ) );

/**
* @name incrmsummary
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/msummary}
*/
setReadOnly( ns, 'incrmsummary', require( '@stdlib/stats/incr/msummary' ) );

/**
* @name incrmvariance
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/mvariance}
*/
setReadOnly( ns, 'incrmvariance', require( '@stdlib/stats/incr/mvariance' ) );

/**
* @name incrpcorr
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/pcorr}
*/
setReadOnly( ns, 'incrpcorr', require( '@stdlib/stats/incr/pcorr' ) );

/**
* @name incrpcorrdist
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/pcorrdist}
*/
setReadOnly( ns, 'incrpcorrdist', require( '@stdlib/stats/incr/pcorrdist' ) );

/**
* @name incrpcorrdistmat
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/pcorrdistmat}
*/
setReadOnly( ns, 'incrpcorrdistmat', require( '@stdlib/stats/incr/pcorrdistmat' ) );

/**
* @name incrpcorrmat
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/pcorrmat}
*/
setReadOnly( ns, 'incrpcorrmat', require( '@stdlib/stats/incr/pcorrmat' ) );

/**
* @name incrprod
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/prod}
*/
setReadOnly( ns, 'incrprod', require( '@stdlib/stats/incr/prod' ) );

/**
* @name incrrange
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/range}
*/
setReadOnly( ns, 'incrrange', require( '@stdlib/stats/incr/range' ) );

/**
* @name incrskewness
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/skewness}
*/
setReadOnly( ns, 'incrskewness', require( '@stdlib/stats/incr/skewness' ) );

/**
* @name incrstdev
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/stdev}
*/
setReadOnly( ns, 'incrstdev', require( '@stdlib/stats/incr/stdev' ) );

/**
* @name incrsum
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/sum}
*/
setReadOnly( ns, 'incrsum', require( '@stdlib/stats/incr/sum' ) );

/**
* @name incrsumabs
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/sumabs}
*/
setReadOnly( ns, 'incrsumabs', require( '@stdlib/stats/incr/sumabs' ) );

/**
* @name incrsummary
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/summary}
*/
setReadOnly( ns, 'incrsummary', require( '@stdlib/stats/incr/summary' ) );

/**
* @name incrvariance
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/variance}
*/
setReadOnly( ns, 'incrvariance', require( '@stdlib/stats/incr/variance' ) );

// EXPORTS //

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

'use strict';

/*
* When adding modules to the namespace, ensure that they are added in alphabetical order according to module name.
*/

// MODULES //

var setReadOnly = require( '@stdlib/utils/define-read-only-property' );

// MAIN //

/**
* Top-level namespace.
*
* @namespace ns
*/
var ns = {};

/**
* @name incrcount
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/count}
*/
setReadOnly( ns, 'incrcount', require( '@stdlib/stats/incr/count' ) );

/**
* @name incrcovariance
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/covariance}
*/
setReadOnly( ns, 'incrcovariance', require( '@stdlib/stats/incr/covariance' ) );

/**
* @name incrcovmat
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/covmat}
*/
setReadOnly( ns, 'incrcovmat', require( '@stdlib/stats/incr/covmat' ) );

/**
* @name increwmean
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/ewmean}
*/
setReadOnly( ns, 'increwmean', require( '@stdlib/stats/incr/ewmean' ) );

/**
* @name incrgmean
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/gmean}
*/
setReadOnly( ns, 'incrgmean', require( '@stdlib/stats/incr/gmean' ) );

/**
* @name incrhmean
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/hmean}
*/
setReadOnly( ns, 'incrhmean', require( '@stdlib/stats/incr/hmean' ) );

/**
* @name incrkurtosis
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/kurtosis}
*/
setReadOnly( ns, 'incrkurtosis', require( '@stdlib/stats/incr/kurtosis' ) );

/**
* @name incrmax
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/max}
*/
setReadOnly( ns, 'incrmax', require( '@stdlib/stats/incr/max' ) );

/**
* @name incrmaxabs
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/maxabs}
*/
setReadOnly( ns, 'incrmaxabs', require( '@stdlib/stats/incr/maxabs' ) );

/**
* @name incrmcovariance
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/mcovariance}
*/
setReadOnly( ns, 'incrmcovariance', require( '@stdlib/stats/incr/mcovariance' ) );

/**
* @name incrmean
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/mean}
*/
setReadOnly( ns, 'incrmean', require( '@stdlib/stats/incr/mean' ) );

/**
* @name incrmeanabs
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/meanabs}
*/
setReadOnly( ns, 'incrmeanabs', require( '@stdlib/stats/incr/meanabs' ) );

/**
* @name incrmgmean
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/mgmean}
*/
setReadOnly( ns, 'incrmgmean', require( '@stdlib/stats/incr/mgmean' ) );

/**
* @name incrmhmean
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/mhmean}
*/
setReadOnly( ns, 'incrmhmean', require( '@stdlib/stats/incr/mhmean' ) );

/**
* @name incrmidrange
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/midrange}
*/
setReadOnly( ns, 'incrmidrange', require( '@stdlib/stats/incr/midrange' ) );

/**
* @name incrmin
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/min}
*/
setReadOnly( ns, 'incrmin', require( '@stdlib/stats/incr/min' ) );

/**
* @name incrminabs
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/minabs}
*/
setReadOnly( ns, 'incrminabs', require( '@stdlib/stats/incr/minabs' ) );

/**
* @name incrmmax
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/mmax}
*/
setReadOnly( ns, 'incrmmax', require( '@stdlib/stats/incr/mmax' ) );

/**
* @name incrmmaxabs
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/mmaxabs}
*/
setReadOnly( ns, 'incrmmaxabs', require( '@stdlib/stats/incr/mmaxabs' ) );

/**
* @name incrmmean
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/mmean}
*/
setReadOnly( ns, 'incrmmean', require( '@stdlib/stats/incr/mmean' ) );

/**
* @name incrmmeanabs
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/mmeanabs}
*/
setReadOnly( ns, 'incrmmeanabs', require( '@stdlib/stats/incr/mmeanabs' ) );

/**
* @name incrmmidrange
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/mmidrange}
*/
setReadOnly( ns, 'incrmmidrange', require( '@stdlib/stats/incr/mmidrange' ) );

/**
* @name incrmmin
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/mmin}
*/
setReadOnly( ns, 'incrmmin', require( '@stdlib/stats/incr/mmin' ) );

/**
* @name incrmminabs
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/mminabs}
*/
setReadOnly( ns, 'incrmminabs', require( '@stdlib/stats/incr/mminabs' ) );

/**
* @name incrmminmax
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/mminmax}
*/
setReadOnly( ns, 'incrmminmax', require( '@stdlib/stats/incr/mminmax' ) );

/**
* @name incrmpcorr
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/mpcorr}
*/
setReadOnly( ns, 'incrmpcorr', require( '@stdlib/stats/incr/mpcorr' ) );

/**
* @name incrmpcorrdist
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/mpcorrdist}
*/
setReadOnly( ns, 'incrmpcorrdist', require( '@stdlib/stats/incr/mpcorrdist' ) );

/**
* @name incrmprod
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/mprod}
*/
setReadOnly( ns, 'incrmprod', require( '@stdlib/stats/incr/mprod' ) );

/**
* @name incrmrange
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/mrange}
*/
setReadOnly( ns, 'incrmrange', require( '@stdlib/stats/incr/mrange' ) );

/**
* @name incrmstdev
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/mstdev}
*/
setReadOnly( ns, 'incrmstdev', require( '@stdlib/stats/incr/mstdev' ) );

/**
* @name incrmsum
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/msum}
*/
setReadOnly( ns, 'incrmsum', require( '@stdlib/stats/incr/msum' ) );

/**
* @name incrmsumabs
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/msumabs}
*/
setReadOnly( ns, 'incrmsumabs', require( '@stdlib/stats/incr/msumabs' ) );

/**
* @name incrmsummary
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/msummary}
*/
setReadOnly( ns, 'incrmsummary', require( '@stdlib/stats/incr/msummary' ) );

/**
* @name incrmvariance
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/mvariance}
*/
setReadOnly( ns, 'incrmvariance', require( '@stdlib/stats/incr/mvariance' ) );

/**
* @name incrpcorr
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/pcorr}
*/
setReadOnly( ns, 'incrpcorr', require( '@stdlib/stats/incr/pcorr' ) );

/**
* @name incrpcorrdist
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/pcorrdist}
*/
setReadOnly( ns, 'incrpcorrdist', require( '@stdlib/stats/incr/pcorrdist' ) );

/**
* @name incrpcorrdistmat
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/pcorrdistmat}
*/
setReadOnly( ns, 'incrpcorrdistmat', require( '@stdlib/stats/incr/pcorrdistmat' ) );

/**
* @name incrpcorrmat
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/pcorrmat}
*/
setReadOnly( ns, 'incrpcorrmat', require( '@stdlib/stats/incr/pcorrmat' ) );

/**
* @name incrprod
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/prod}
*/
setReadOnly( ns, 'incrprod', require( '@stdlib/stats/incr/prod' ) );

/**
* @name incrrange
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/range}
*/
setReadOnly( ns, 'incrrange', require( '@stdlib/stats/incr/range' ) );

/**
* @name incrskewness
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/skewness}
*/
setReadOnly( ns, 'incrskewness', require( '@stdlib/stats/incr/skewness' ) );

/**
* @name incrstdev
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/stdev}
*/
setReadOnly( ns, 'incrstdev', require( '@stdlib/stats/incr/stdev' ) );

/**
* @name incrsum
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/sum}
*/
setReadOnly( ns, 'incrsum', require( '@stdlib/stats/incr/sum' ) );

/**
* @name incrsumabs
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/sumabs}
*/
setReadOnly( ns, 'incrsumabs', require( '@stdlib/stats/incr/sumabs' ) );

/**
* @name incrsummary
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/summary}
*/
setReadOnly( ns, 'incrsummary', require( '@stdlib/stats/incr/summary' ) );

/**
* @name incrsumprod
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/sumprod}
*/
setReadOnly( ns, 'incrsumprod', require( '@stdlib/stats/incr/sumprod' ) );

/**
* @name incrvariance
* @memberof ns
* @readonly
* @type {Function}
* @see {@link module:@stdlib/stats/incr/variance}
*/
setReadOnly( ns, 'incrvariance', require( '@stdlib/stats/incr/variance' ) );

// EXPORTS //

module.exports = ns;
<|endoftext|>


<commit_before>const { sh, help, cli } = require('../../lib')

function echo(...args) {
  console.log('echo', args)
}

function commands() {
  sh('echo "sync terminal"')
  console.log('output', sh('echo "sync pipe"', { stdio: 'pipe' }))
  sh('echo "async terminal"', { async: true })
  sh('echo "async terminal"', { async: true, stdio: 'pipe' }).then(output =>
    console.log('output', output)
  )
}

function described(options, p1, p2) {
  console.log(p1, p2, options)
}

const nested = {
  echo(...args) {
    console.log('nested echo', args)
  }
}

function localbin() {
  sh('hello')
}

async function asyncawait() {
  const output = await sh('echo "async and await"', {
    async: true,
    stdio: 'pipe'
  })
  console.log('output', output)
  console.log('after await')
}

function error() {
  sh('node ./scripts/error.js', { async: true })
  sh('node ./scripts/error.js')
}

function color() {
  sh('node ./scripts/color.js')
  sh('node ./scripts/color.js', { async: true })
}

help(echo, 'Simple echo task')
help(nested.echo, 'Description of nested task')
help(described, 'Task description', {
  params: ['p1', 'p2'],
  options: {
    foo: 'foo option'
  }
})

cli({
  echo,
  commands,
  described,
  nested,
  localbin,
  asyncawait,
  error,
  color
})
<commit_msg>Sandbox: remove not used task<commit_after>const { sh, help, cli } = require('../../lib')

help(echo, 'Simple echo task')

function echo(...args) {
  console.log('echo', args)
}

const nested = {
  echo(...args) {
    console.log('nested echo', args)
  },

  default (...args) {
    console.log('nested default', args)
  }
}

help(nested.echo, 'Description of nested task')

function commands() {
  sh('echo "sync terminal"')
  console.log('output', sh('echo "sync pipe"', { stdio: 'pipe' }))
  sh('echo "async terminal"', { async: true })
  sh('echo "async terminal"', { async: true, stdio: 'pipe' }).then(output =>
    console.log('output', output)
  )
}

function localbin() {
  sh('hello')
}

async function asyncawait() {
  const output = await sh('echo "async and await"', {
    async: true,
    stdio: 'pipe'
  })
  console.log('output', output)
  console.log('after await')
}

function error() {
  sh('node ./scripts/error.js', { async: true })
  sh('node ./scripts/error.js')
}

function color() {
  sh('node ./scripts/color.js')
  sh('node ./scripts/color.js', { async: true })
}

cli({
  echo,
  commands,
  nested,
  localbin,
  asyncawait,
  error,
  color
})
<|endoftext|>