<commit_before>const friendlyGroundUnitSvg =
  '<svg xmlns="http://www.w3.org/2000/svg" version="1.2" baseProfile="tiny" width="63.2" height="43.2" viewBox="21 46 158 108"><path d="M25,50 l150,0 0,100 -150,0 z" stroke-width="4" stroke="black" fill="rgb(128,224,255)" fill-opacity="1"></path></svg>';

module.exports = {
  // A few different SIDC formats that should all produce the same very basic test symbol
  SFG: friendlyGroundUnitSvg,
  "SFG-": friendlyGroundUnitSvg,
  "SFG-------": friendlyGroundUnitSvg,
  "SFG---------": friendlyGroundUnitSvg,
  "SFG-U-------": friendlyGroundUnitSvg,
  "SFGPU-------": friendlyGroundUnitSvg,
  10031000000000000000: friendlyGroundUnitSvg,
  // Reference figure from MIL-STD-2525C
  "sfgpewrh--mt":
    '<svg xmlns="http://www.w3.org/2000/svg" version="1.2" baseProfile="tiny" width="51.2" height="57.6" viewBox="36 36 128 144"><circle cx="100" cy="100" r="60" stroke-width="4" stroke="black" fill="rgb(128,224,255)" fill-opacity="1"></circle><path d="m 100,60 0,80 M 85,75 100,60 115,75" stroke-width="4" stroke="black" fill="none"></path><path d="m 85,110 30,0 m -30,-20 30,0 m -30,10 30,0" stroke-width="4" stroke="black" fill="none"></path><g transform="translate(0,160)" stroke-width="4" stroke="black" fill="none"><path d="M 50,1 l 100,0"></path><circle cx="55" cy="8" r="8"></circle><circle cx="70" cy="8" r="8"></circle><circle cx="130" cy="8" r="8"></circle><circle cx="145" cy="8" r="8"></circle></g></svg>',
  SFGXEWMASEMO:
    '<svg xmlns="http://www.w3.org/2000/svg" version="1.2" baseProfile="tiny" width="51.2" height="67.2" viewBox="36 36 128 168"><circle cx="100" cy="100" r="60" stroke-width="4" stroke="black" fill="rgb(128,224,255)" fill-opacity="1"></circle><path d="m 85,140 30,0 c 0,-20 -30,-20 -30,0 z m 15,-15 0,-65 m -15,80 0,-65 c 0,-20 30,-20 30,0 l 0,65" stroke-width="4" stroke="black" fill="none"></path><path d="m 85,100 30,0" stroke-width="4" stroke="black" fill="none"></path><text x="68" y="110" text-anchor="middle" font-size="25" font-family="Arial" font-weight="bold" stroke-width="4" stroke="none" fill="black">E</text><text x="132" y="110" text-anchor="middle" font-size="25" font-family="Arial" font-weight="bold" stroke-width="4" stroke="none" fill="black">R</text><g transform="translate(0,160)" stroke-width="4" stroke="black" fill="none"><path d="M 50,1 l 100,0"></path><circle cx="55" cy="8" r="8"></circle><circle cx="145" cy="8" r="8"></circle></g><path d="M40,185 l120,0 0,15 -120,0 z" stroke-width="4" stroke="black" fill="rgb(255,0,0)"></path></svg>',
  // Verifies this bug doesn't reoocur: https://github.com/spatialillusions/milsymbol/issues/118
  10000030000000000000: '<svg xmlns="http://www.w3.org/2000/svg" version="1.2" baseProfile="tiny" width="58.6" height="66.6" viewBox="26.75 26.75 146.5 166.5"><path d="M63,63 C63,20 137,20 137,63 C180,63 180,137 137,137 C137,180 63,180 63,137 C20,137 20,63 63,63 Z" stroke-width="4" stroke="black" fill="rgb(255,255,128)" fill-opacity="1"></path><path d="M63,63 C63,20 137,20 137,63 C180,63 180,137 137,137 C137,180 63,180 63,137 C20,137 20,63 63,63 Z" stroke-width="5" stroke-dasharray="4,4" stroke="rgb(239, 239, 239)" fill="none"></path><path d="M30.75,174.25 l138.5,0 0,15 -138.5,0 z" stroke-width="4" stroke="black" fill="rgb(255,255,0)"></path><text x="100" y="127" text-anchor="middle" font-size="80" font-family="Arial" font-weight="bold" fill="black">?</text></svg>'
};
<commit_msg>fixed typo<commit_after>const friendlyGroundUnitSvg =
  '<svg xmlns="http://www.w3.org/2000/svg" version="1.2" baseProfile="tiny" width="63.2" height="43.2" viewBox="21 46 158 108"><path d="M25,50 l150,0 0,100 -150,0 z" stroke-width="4" stroke="black" fill="rgb(128,224,255)" fill-opacity="1"></path></svg>';

module.exports = {
  // A few different SIDC formats that should all produce the same very basic test symbol
  SFG: friendlyGroundUnitSvg,
  "SFG-": friendlyGroundUnitSvg,
  "SFG-------": friendlyGroundUnitSvg,
  "SFG---------": friendlyGroundUnitSvg,
  "SFG-U-------": friendlyGroundUnitSvg,
  "SFGPU-------": friendlyGroundUnitSvg,
  10031000000000000000: friendlyGroundUnitSvg,
  // Reference figure from MIL-STD-2525C
  "sfgpewrh--mt":
    '<svg xmlns="http://www.w3.org/2000/svg" version="1.2" baseProfile="tiny" width="51.2" height="57.6" viewBox="36 36 128 144"><circle cx="100" cy="100" r="60" stroke-width="4" stroke="black" fill="rgb(128,224,255)" fill-opacity="1"></circle><path d="m 100,60 0,80 M 85,75 100,60 115,75" stroke-width="4" stroke="black" fill="none"></path><path d="m 85,110 30,0 m -30,-20 30,0 m -30,10 30,0" stroke-width="4" stroke="black" fill="none"></path><g transform="translate(0,160)" stroke-width="4" stroke="black" fill="none"><path d="M 50,1 l 100,0"></path><circle cx="55" cy="8" r="8"></circle><circle cx="70" cy="8" r="8"></circle><circle cx="130" cy="8" r="8"></circle><circle cx="145" cy="8" r="8"></circle></g></svg>',
  SFGXEWMASEMO:
    '<svg xmlns="http://www.w3.org/2000/svg" version="1.2" baseProfile="tiny" width="51.2" height="67.2" viewBox="36 36 128 168"><circle cx="100" cy="100" r="60" stroke-width="4" stroke="black" fill="rgb(128,224,255)" fill-opacity="1"></circle><path d="m 85,140 30,0 c 0,-20 -30,-20 -30,0 z m 15,-15 0,-65 m -15,80 0,-65 c 0,-20 30,-20 30,0 l 0,65" stroke-width="4" stroke="black" fill="none"></path><path d="m 85,100 30,0" stroke-width="4" stroke="black" fill="none"></path><text x="68" y="110" text-anchor="middle" font-size="25" font-family="Arial" font-weight="bold" stroke-width="4" stroke="none" fill="black">E</text><text x="132" y="110" text-anchor="middle" font-size="25" font-family="Arial" font-weight="bold" stroke-width="4" stroke="none" fill="black">R</text><g transform="translate(0,160)" stroke-width="4" stroke="black" fill="none"><path d="M 50,1 l 100,0"></path><circle cx="55" cy="8" r="8"></circle><circle cx="145" cy="8" r="8"></circle></g><path d="M40,185 l120,0 0,15 -120,0 z" stroke-width="4" stroke="black" fill="rgb(255,0,0)"></path></svg>',
  // Verifies this bug doesn't reoccur: https://github.com/spatialillusions/milsymbol/issues/118
  10000030000000000000: '<svg xmlns="http://www.w3.org/2000/svg" version="1.2" baseProfile="tiny" width="58.6" height="66.6" viewBox="26.75 26.75 146.5 166.5"><path d="M63,63 C63,20 137,20 137,63 C180,63 180,137 137,137 C137,180 63,180 63,137 C20,137 20,63 63,63 Z" stroke-width="4" stroke="black" fill="rgb(255,255,128)" fill-opacity="1"></path><path d="M63,63 C63,20 137,20 137,63 C180,63 180,137 137,137 C137,180 63,180 63,137 C20,137 20,63 63,63 Z" stroke-width="5" stroke-dasharray="4,4" stroke="rgb(239, 239, 239)" fill="none"></path><path d="M30.75,174.25 l138.5,0 0,15 -138.5,0 z" stroke-width="4" stroke="black" fill="rgb(255,255,0)"></path><text x="100" y="127" text-anchor="middle" font-size="80" font-family="Arial" font-weight="bold" fill="black">?</text></svg>'
};
<|endoftext|>


<commit_before>// we will re-enable the broken browsers once saucelabs will fix all the timeout issues
module.exports = {
  browsers: {
/*    slIphone5: {
      base: 'SauceLabs',
      browserName: 'iphone',
      version: '8.4'
    },
    */
    slIphone6: {
      base: 'SauceLabs',
      browserName: 'iphone',
      version: '9.3'
    },
    slIpad: {
      base: 'SauceLabs',
      browserName: 'ipad',
      version: '9.3'
    },
    slSafari7: {
      base: 'SauceLabs',
      browserName: 'safari',
      platform: 'OS X 10.9'
    },
/*    slSafari8: {
      base: 'SauceLabs',
      browserName: 'safari',
      platform: 'OS X 10.10'
    },*/
 /*   slSafari9: {
      base: 'SauceLabs',
      browserName: 'safari',
      platform: 'OS X 10.11'
    },*/
/*    slIE9: {
      base: 'SauceLabs',
      browserName: 'internet explorer',
      platform: 'Windows 7',
      version: '9'
    },*/
    slIE10: {
      base: 'SauceLabs',
      browserName: 'internet explorer',
      platform: 'Windows 8',
      version: '10'
    },
    slIE11: {
      base: 'SauceLabs',
      browserName: 'internet explorer',
      platform: 'Windows 8.1',
      version: '11'
    },
    slEdge: {
      base: 'SauceLabs',
      browserName: 'MicrosoftEdge',
      platform: 'Windows 10'
    },
    slChrome: {
      base: 'SauceLabs',
      browserName: 'chrome'
    },
    slFirefox: {
      base: 'SauceLabs',
      browserName: 'firefox'
    },
    slAndroid5: {
      base: 'SauceLabs',
      browserName: 'android',
      version: '5.1'
    },
    slAndroid6: {
      base: 'SauceLabs',
      browserName: 'android',
      version: '6.0'
    }
  }
}
<commit_msg>fixed: saucelabs tests<commit_after>// we will re-enable the broken browsers once saucelabs will fix all the timeout issues
module.exports = {
  browsers: {
/*    slIphone5: {
      base: 'SauceLabs',
      browserName: 'iphone',
      version: '8.4'
    },
    */
    slIphone6: {
      base: 'SauceLabs',
      browserName: 'iphone',
      version: '9.3'
    },
    slIpad: {
      base: 'SauceLabs',
      browserName: 'ipad',
      version: '9.3'
    },
    slSafari7: {
      base: 'SauceLabs',
      browserName: 'safari',
      platform: 'OS X 10.9'
    },
/*    slSafari8: {
      base: 'SauceLabs',
      browserName: 'safari',
      platform: 'OS X 10.10'
    },*/
 /*   slSafari9: {
      base: 'SauceLabs',
      browserName: 'safari',
      platform: 'OS X 10.11'
    },*/
/*    slIE9: {
      base: 'SauceLabs',
      browserName: 'internet explorer',
      platform: 'Windows 7',
      version: '9'
    },*/
    slIE10: {
      base: 'SauceLabs',
      browserName: 'internet explorer',
      platform: 'Windows 8',
      version: '10'
    },
    slIE11: {
      base: 'SauceLabs',
      browserName: 'internet explorer',
      platform: 'Windows 8.1',
      version: '11'
    },
    slEdge: {
      base: 'SauceLabs',
      browserName: 'MicrosoftEdge',
      platform: 'Windows 10'
    },
    slChrome: {
      base: 'SauceLabs',
      browserName: 'chrome'
    },
    slFirefox: {
      base: 'SauceLabs',
      browserName: 'firefox'
    },
    slAndroid5: {
      base: 'SauceLabs',
      browserName: 'android',
      version: '5.1'
    }
  }
}
<|endoftext|>


<commit_before>const rssConfig = require('../../config.json')
const striptags = require('striptags')
const filterFeed = require('./filters.js')
const createEmbed = require('./embed.js')
const cleanRandoms = require('./cleanup.js')
const moment = require('moment-timezone')
const getSubscriptions = require('./subscriptions.js')

module.exports = function (channel, rssList, rssIndex, data, isTestMessage) {
  const guildTimezone = require(`../../sources/${channel.guild.id}`).timezone

  //sometimes feeds get deleted mid process
  if (rssList[rssIndex] == null) {console.log("RSS Error: Unable to translate a null source."); return null;}
  if (data.guid == null) {console.log(`RSS Error: (${channel.guild.id}, ${channel.guild.name}) => Feed GUID is null.`, data); return null;}

  var originalDate = data.pubdate;
  if (guildTimezone != null && moment.tz.zone(guildTimezone) != null) var timezone = guildTimezone;
  else var timezone = rssConfig.timezone;
  // var vanityDate = moment(originalDate).format("ddd, MMMM Do YYYY, h:mm A")
  var vanityDate = moment.tz(originalDate, timezone).format("ddd, MMMM Do YYYY, h:mm A z")

  if (data.guid.startsWith("yt:video")) var dataDescrip = data['media:group']['media:description']['#'];
  else var dataDescrip = cleanRandoms(data.description);

  var dataSummary = cleanRandoms(data.summary);
  if (dataSummary.length > 800)  {
    dataSummary = dataSummary.slice(0, 800) + " [...]";
  }
  if (isTestMessage && dataSummary.length > 300) {
    dataSummary = dataSummary.slice(0, 300) + " [...]\n(Truncated shorter summary for test)";
  }

  if (dataDescrip.length > 800) {
    dataDescrip = dataDescrip.slice(0, 800) + " [...]";
  }
  if (isTestMessage && dataDescrip.length > 300) {
    if (data.summary == data.description) dataDescrip = dataDescrip.slice(0, 600) + " [...]\n(Truncated shorter description for test)";
    else dataDescrip = dataDescrip.slice(0, 300) + " [...]\n(Truncated shorter description for test)";
  }

  if (data.link != null && data.link.includes("reddit")) {
    let dataDescrip = dataDescrip.substr(0,dataDescrip.length-22)
            .replace("submitted by", "\n*Submitted by:*"); //truncate the useless end of reddit description
  }

  var subscriptions = getSubscriptions(channel, rssIndex, data, dataDescrip)

  function replaceKeywords(word){
    var a = word.replace(/{date}/g, vanityDate)
            .replace(/{title}/g, striptags(data.title))
            .replace(/{author}/g, data.author)
            .replace(/{summary}/g, dataSummary)
            .replace(/{image}/g, data.image.url)
            .replace(/{subscriptions}/g, subscriptions)

    if (data.link != null) var b = a.replace(/{link}/g, data.link);
    else var b = a.replace(/{link}/g, "");

    if (data.guid.startsWith("yt:video")) { //youtube feeds have the property media:group that other feeds do not have
      if (data['media:group']['media:description']['#'] != null) var c = b.replace(/{description}/g, data['media:group']['media:description']['#']);
      else var c = b.replace(/{description}/g, "");

      var d = c.replace(/{thumbnail}/g, data['media:group']['media:thumbnail']['@']['url']);
      return d;
    }
    else return b.replace(/{description}/g, dataDescrip);
  }

  //filter message
  var filterPropCount = 0;
  if (rssList[rssIndex].filters != null && typeof rssList[rssIndex].filters == "object") {
    for (var prop in rssList[rssIndex].filters)
      if (rssList[rssIndex].filters.hasOwnProperty(prop) && prop !== "roleSubscriptions") filterPropCount++;
  }

  var filterExists = false
  var filterFound = false
  if (filterPropCount !== 0) {
    filterExists = true;
    filterFound = filterFeed(rssList, rssIndex, data, dataDescrip);
  }

  //feed article only passes through if the filter found the specified content
  if (!isTestMessage && filterExists && !filterFound) {
    console.log(`RSS Delivery: (${channel.guild.id}, ${channel.guild.name}) => ${data.link} did not pass filters and was not sent:\n`, rssList[rssIndex].filters);
    return null;
  }

  if (rssList[rssIndex].message == null) var configMessage = replaceKeywords(rssConfig.defaultMessage);
  else var configMessage = replaceKeywords(rssList[rssIndex].message);

  //generate final msg
  var finalMessage = "";
  if (isTestMessage) {

    let footer = "\nBelow is the configured message to be sent for this feed:\n\n\n\n"
    finalMessage += `\`\`\`Markdown\n# Test Message\`\`\`\`\`\`Markdown\n\n[Title]: {title}\n${data.title}`;
    if (dataDescrip != null && dataDescrip !== "") finalMessage += `\n\n[Description]: {description}\n${dataDescrip}`
    if (data.description !== data.summary && dataSummary != null && dataSummary !== "") finalMessage += `\n\n[Summary]: {summary}\n${dataSummary} (Summary has been truncated for test)`
    if (vanityDate != null && vanityDate !== "") finalMessage += `\n\n[Published Date]: {date}\n${vanityDate}`
    if (data.author != null && data.author !== "") finalMessage += `\n\n[Author]: {author}\n${data.author}`
    if (data.link != null) finalMessage += `\n\n[Link]: {link}\n${data.link}`
    if (data.image.url !=  null && data.image.url !== "") finalMessage += `\n\n[Image URL]: {image}\n${data.image.url}`;
    if (subscriptions !== "") finalMessage += `\n\n[Subscriptions]: {subscriptions}\n${subscriptions.split(" ").length - 1} subscriber(s)`;
    if (filterExists) finalMessage += `\n\n[Passed Filters?]: ${filterFound}`;
    if (data.guid.startsWith("yt:video")) {
      finalMessage += `\n\n[Youtube Thumbnail]: {thumbnail}\n${data['media:group']['media:thumbnail']['@']['url']}\`\`\`` + footer + configMessage;
    }
    else finalMessage += "```" + footer + configMessage;

  }
  else finalMessage = configMessage;

  //account for final message length
  if (finalMessage.length >= 1900) {
    console.log(finalMessage);
    finalMessage = `The article titled **<${data.title}>** is greater than or equal to 1900 characters cannot be sent as a precaution. The link to the article is:\n\n${data.link}`;
    if (!isTestMessage) console.log(`RSS Delivery Warning: (${channel.guild.id}, ${channel.guild.name}) => Feed titled "${data.title}" cannot be sent to Discord because message length is >1900.`);
    else console.log(`RSS Test Delivery Warning: (${channel.guild.id}, ${channel.guild.name}) => Feed titled "${data.title}" cannot be sent to Discord because message length is >1900.`);

  }
  let finalMessageCombo = {
    textMsg: finalMessage
  }

  //check if embed is enabled
  var enabledEmbed;
  if (rssList[rssIndex].embedMessage == null || rssList[rssIndex].embedMessage.enabled == false || rssList[rssIndex].embedMessage == "" || rssList[rssIndex].embedMessage.enabled == "")
    enabledEmbed = false;
  else enabledEmbed = true;

  if (enabledEmbed !== true) {
     return finalMessageCombo;
  }
  else {

    if (rssList[rssIndex].embedMessage.properties != null)
      finalMessageCombo.embedMsg = createEmbed(channel, rssList, rssIndex, data, replaceKeywords)

    return finalMessageCombo;
  }
}
<commit_msg>better translation<commit_after>const rssConfig = require('../../config.json')
const striptags = require('striptags')
const filterFeed = require('./filters.js')
const createEmbed = require('./embed.js')
const cleanRandoms = require('./cleanup.js')
const moment = require('moment-timezone')
const getSubscriptions = require('./subscriptions.js')

module.exports = function (channel, rssList, rssIndex, data, isTestMessage) {
  const guildTimezone = require(`../../sources/${channel.guild.id}`).timezone
  require('fs').writeFileSync('./something.txt', data.description)
  //sometimes feeds get deleted mid process
  if (rssList[rssIndex] == null) {console.log("RSS Error: Unable to translate a null source."); return null;}
  if (data.guid == null) {console.log(`RSS Error: (${channel.guild.id}, ${channel.guild.name}) => Feed GUID is null.`, data); return null;}

  var originalDate = data.pubdate;
  if (guildTimezone != null && moment.tz.zone(guildTimezone) != null) var timezone = guildTimezone;
  else var timezone = rssConfig.timezone;
  // var vanityDate = moment(originalDate).format("ddd, MMMM Do YYYY, h:mm A")
  var vanityDate = moment.tz(originalDate, timezone).format("ddd, MMMM Do YYYY, h:mm A z")

  if (data.guid.startsWith("yt:video")) var dataDescrip = data['media:group']['media:description']['#'];
  else var dataDescrip = cleanRandoms(data.description);

  var dataSummary = cleanRandoms(data.summary);
  if (dataSummary.length > 800)  {
    dataSummary = dataSummary.slice(0, 800) + " [...]";
  }
  if (isTestMessage && dataSummary.length > 300) {
    dataSummary = dataSummary.slice(0, 300) + " [...]\n\n**(Truncated shorter summary for rsstest)**";
  }

  if (dataDescrip.length > 800) {
    dataDescrip = dataDescrip.slice(0, 800) + " [...]";
  }
  if (isTestMessage && dataDescrip.length > 300) {
    if (data.summary == data.description) dataDescrip = dataDescrip.slice(0, 600) + " [...]\n\n**(Truncated shorter description for rsstest)**";
    else dataDescrip = dataDescrip.slice(0, 300) + " [...]\n(Truncated shorter description for rsstest)";
  }

  if (data.link != null && data.link.includes("reddit")) {
    let dataDescrip = dataDescrip.substr(0,dataDescrip.length-22)
            .replace("submitted by", "\n*Submitted by:*"); //truncate the useless end of reddit description
  }

  var subscriptions = getSubscriptions(channel, rssIndex, data, dataDescrip)

  function replaceKeywords(word){
    var a = word.replace(/{date}/g, vanityDate)
            .replace(/{title}/g, striptags(data.title))
            .replace(/{author}/g, data.author)
            .replace(/{summary}/g, dataSummary)
            .replace(/{image}/g, data.image.url)
            .replace(/{subscriptions}/g, subscriptions)

    if (data.link != null) var b = a.replace(/{link}/g, data.link);
    else var b = a.replace(/{link}/g, "");

    if (data.guid.startsWith("yt:video")) { //youtube feeds have the property media:group that other feeds do not have
      if (data['media:group']['media:description']['#'] != null) var c = b.replace(/{description}/g, data['media:group']['media:description']['#']);
      else var c = b.replace(/{description}/g, "");

      var d = c.replace(/{thumbnail}/g, data['media:group']['media:thumbnail']['@']['url']);
      return d;
    }
    else return b.replace(/{description}/g, dataDescrip);
  }

  //filter message
  var filterPropCount = 0;
  if (rssList[rssIndex].filters != null && typeof rssList[rssIndex].filters == "object") {
    for (var prop in rssList[rssIndex].filters)
      if (rssList[rssIndex].filters.hasOwnProperty(prop) && prop !== "roleSubscriptions") filterPropCount++;
  }

  var filterExists = false
  var filterFound = false
  if (filterPropCount !== 0) {
    filterExists = true;
    filterFound = filterFeed(rssList, rssIndex, data, dataDescrip);
  }

  //feed article only passes through if the filter found the specified content
  if (!isTestMessage && filterExists && !filterFound) {
    console.log(`RSS Delivery: (${channel.guild.id}, ${channel.guild.name}) => ${data.link} did not pass filters and was not sent:\n`, rssList[rssIndex].filters);
    return null;
  }

  if (rssList[rssIndex].message == null) var configMessage = replaceKeywords(rssConfig.defaultMessage);
  else var configMessage = replaceKeywords(rssList[rssIndex].message);

  //generate final msg
  var finalMessage = "";
  if (isTestMessage) {

    let footer = "\nBelow is the configured message to be sent for this feed:\n\n\n\n"
    finalMessage += `\`\`\`Markdown\n# Test Message\`\`\`\`\`\`Markdown\n\n[Title]: {title}\n${data.title}`;
    if (dataDescrip != null && dataDescrip !== "") finalMessage += `\n\n[Description]: {description}\n${dataDescrip}`
    if (data.description !== data.summary && dataSummary != null && dataSummary !== "") finalMessage += `\n\n[Summary]: {summary}\n${dataSummary} (Summary has been truncated for test)`
    if (vanityDate != null && vanityDate !== "") finalMessage += `\n\n[Published Date]: {date}\n${vanityDate}`
    if (data.author != null && data.author !== "") finalMessage += `\n\n[Author]: {author}\n${data.author}`
    if (data.link != null) finalMessage += `\n\n[Link]: {link}\n${data.link}`
    if (data.image.url !=  null && data.image.url !== "") finalMessage += `\n\n[Image URL]: {image}\n${data.image.url}`;
    if (subscriptions !== "") finalMessage += `\n\n[Subscriptions]: {subscriptions}\n${subscriptions.split(" ").length - 1} subscriber(s)`;
    if (filterExists) finalMessage += `\n\n[Passed Filters?]: ${filterFound}`;
    if (data.guid.startsWith("yt:video")) {
      finalMessage += `\n\n[Youtube Thumbnail]: {thumbnail}\n${data['media:group']['media:thumbnail']['@']['url']}\`\`\`` + footer + configMessage;
    }
    else finalMessage += "```" + footer + configMessage;

  }
  else finalMessage = configMessage;

  //account for final message length
  if (finalMessage.length >= 1900) {
    console.log(finalMessage);
    finalMessage = `The article titled **<${data.title}>** is greater than or equal to 1900 characters cannot be sent as a precaution. The link to the article is:\n\n${data.link}`;
    if (!isTestMessage) console.log(`RSS Delivery Warning: (${channel.guild.id}, ${channel.guild.name}) => Feed titled "${data.title}" cannot be sent to Discord because message length is >1900.`);
    else console.log(`RSS Test Delivery Warning: (${channel.guild.id}, ${channel.guild.name}) => Feed titled "${data.title}" cannot be sent to Discord because message length is >1900.`);

  }
  let finalMessageCombo = {
    textMsg: finalMessage
  }

  //check if embed is enabled
  var enabledEmbed;
  if (rssList[rssIndex].embedMessage == null || rssList[rssIndex].embedMessage.enabled == false || rssList[rssIndex].embedMessage == "" || rssList[rssIndex].embedMessage.enabled == "")
    enabledEmbed = false;
  else enabledEmbed = true;

  if (enabledEmbed !== true) {
     return finalMessageCombo;
  }
  else {

    if (rssList[rssIndex].embedMessage.properties != null)
      finalMessageCombo.embedMsg = createEmbed(channel, rssList, rssIndex, data, replaceKeywords)

    return finalMessageCombo;
  }
}
<|endoftext|>


<commit_before>/* global describe, expect, Dinglake, Random */

(function () {
    describe('Dinglake', function () {
        describe('The constructor', function () {
            it('converts uppercase key bindings to uppercase', function () {
                var dl = new Dinglake([{ key: 'a', files: [] }]);

                expect(dl.bindings.keyup.has('A')).to.be.ok;
            });

            it('prevents multiple bindings to the same key', function (){
                var dl;
                var badConfig = [{ key: 'a', files: [] }, { key: 'a', files: [] }];
                var loadConfiguration = function () { dl = new Dinglake(badConfig); };

                expect(loadConfiguration).to.throw(Error);
                expect(dl).to.be.an('undefined');
            });

            it('handles non-alphanumeric key bindings', function () {
                var dl = new Dinglake([{ key: '%', files: [] }]);

                expect(dl.bindings.keyup.has('%')).to.be.ok;
            });

            it('creates Random.Array objects', function () {
                var dl = new Dinglake([{
                    key: 'a',
                    name: 'A',
                    files: []
                }]);

                expect(dl.bindings.keyup.get('A')).to.be.an.instanceOf(Random.Array);
            });
        });

        describe('Key bindings', function () {
            var keyup = jQuery.Event('keyup'),
                keydown = jQuery.Event('keydown');

            before(function () {

                sinon.stub(ion.sound, 'play');
                sinon.stub(ion.sound, 'stop');
            });

            beforeEach(function () {
                keydown.which = 'A'.charCodeAt(0);
                keyup.which = 'S'.charCodeAt(0);
            });

            afterEach(function () {
                ion.sound.play.reset();
                ion.sound.stop.reset();
                $(document).off('keyup').off('keydown');
            });

            after(function () {
                ion.sound.play.restore();
                ion.sound.stop.restore();
            });

            it('responds to keydown', function () {
                var dl = new Dinglake([{
                    name: 'a',
                    key: 'a',
                    event: 'keydown',
                    files: ['keydown']
                }, {
                    name: 'b',
                    key: 's',
                    event: 'keyup',
                    files: ['keyup']
                }]);

                $(document).trigger(keydown);

                assert(ion.sound.play.calledWithMatch('keydown'));
            });

            it('responds to keyup', function () {
                var dl = new Dinglake([{
                    name: 'a',
                    key: 'a',
                    event: 'keydown',
                    files: ['keydown']
                }, {
                    name: 'b',
                    key: 's',
                    event: 'keyup',
                    files: ['keyup']
                }]);
                $(document).trigger(keyup);

                assert(ion.sound.play.calledWithMatch('keyup'));
            });

            it('defaults to keyup', function () {
                var dl = new Dinglake([{
                    name: 'one',
                    key: 'A',
                    files: ['one']
                }]);

                keyup.which = keydown.which;

                $(document).trigger(keydown);
                expect(ion.sound.play.callCount).to.equal(0);

                $(document).trigger(keyup);
                expect(ion.sound.play.calledOnce).to.be.true;
            });

            it('allows different sounds to be triggered for different events on the same key', function () {
                var dl = new Dinglake([{
                    name: 'one',
                    key: 'A',
                    event: 'keyup',
                    files: ['keyup']
                }, {
                    name: 'two',
                    key: 'A',
                    event: 'keydown',
                    files: ['keydown']
                }]);

                keyup.which = keydown.which;

                $(document).trigger(keyup);
                expect(ion.sound.play.callCount).to.equal(1);
                assert(ion.sound.play.calledWith('keyup'));

                $(document).trigger(keydown);
                expect(ion.sound.play.callCount).to.equal(2);
                assert(ion.sound.play.calledWith('keydown'));
            });
        });
    });
})();
<commit_msg>Remove the Dinglake tests.<commit_after><|endoftext|>


<commit_before>'use strict';

module.exports = {
    srcDirectory: './css/src/',

    srcPath: '*.scss',

    destPath: './css/',

    sassSettings: {
        noCache: true,
        sourcemap: true,
        style: 'compact'
    },

    autoPrefixSettings: {
        browsers: ["last 2 versions", "> 1%", "ie 8", "ie 7"]
    }
};<commit_msg>- Making the autoprefixer output a bit more relevant.<commit_after>'use strict';

module.exports = {
    srcDirectory: './css/src/',

    srcPath: '*.scss',

    destPath: './css/',

    sassSettings: {
        noCache: true,
        sourcemap: true,
        style: 'compact'
    },

    autoPrefixSettings: {
        browsers: ['last 2 versions', 'ios 6.1', 'android >= 4']
    }
};<|endoftext|>


<commit_before>var Code = require('code')
var Lab = require('lab')

var copyFunc = require('../index.js')

var lab = exports.lab = Lab.script()
var describe = lab.describe
var it = lab.it
var afterEach = lab.afterEach
var beforeEach = lab.beforeEach
var expect = Code.expect
var IS_GTE_NODE_4 = process.version.split('.')[0] === 'v4'

function add (a, b) {
  return a + b
}

describe('copyFunction', function () {
  it('should copy a function', function (done) {
    var addCopy = copyFunc(add)
    expect(addCopy).to.not.equal(add)
    expect(addCopy(1, 2))
      .to.equal(add(1, 2))
      .to.equal(1 + 2)
    if (IS_GTE_NODE_4) {
      expect(addCopy.name).to.equal(add.name)
    }
    expect(addCopy.length).to.equal(add.length)
    done()
  })
  it('should copy a function and assign a customName', function (done) {
    var addCopy = copyFunc(add, 'addCopy')
    expect(addCopy).to.not.equal(add)
    expect(addCopy(1, 2))
      .to.equal(add(1, 2))
      .to.equal(1 + 2)
    if (IS_GTE_NODE_4) {
      expect(addCopy.name).to.equal('addCopy')
    }
    expect(addCopy.length).to.equal(add.length)
    done()
  })

  describe('errors', function () {
    it('should throw an error if pass a non-function', function (done) {
      expect(function () {
        copyFunc({})
      }).to.throw(Error, /fn.*function/)
      done()
    })
  })
  describe('compatibility', function () {
    var defineProperty = Object.defineProperty
    var fnWithoutLength = function () {}
    if (IS_GTE_NODE_4) {
      Object.defineProperty(fnWithoutLength, 'length', {
        value: null,
        writable: false,
        enumerable: false,
        configurable: true
      })
    }

    describe('no Object.defineProperty', function () {
      beforeEach(function (done) {
        delete Object.defineProperty
        done()
      })
      afterEach(function (done) {
        Object.defineProperty = defineProperty
        done()
      })
      if (IS_GTE_NODE_4) {
        // cannot redifine fn's length
        // to test this w/out node 4+
        it('should copy a function w/ no length', function (done) {
          var fn = fnWithoutLength
          var fnCopy = copyFunc(fn)
          assertCopy(fnCopy, fn)
          done()
        })
      }
      it('should copy a function of length 0', function (done) {
        var fn = function () { return 10 }
        var fnCopy = copyFunc(fn)
        assertCopy(fnCopy, fn)
        done()
      })
      it('should copy a function of length 1', function (done) {
        var fn = function (a) { return 10 }
        var fnCopy = copyFunc(fn)
        assertCopy(fnCopy, fn)
        done()
      })
      it('should copy a function of length 2', function (done) {
        var fn = function (a, b) { return 10 }
        var fnCopy = copyFunc(fn)
        assertCopy(fnCopy, fn)
        done()
      })
      it('should copy a function of length 3', function (done) {
        var fn = function (a, b, c) { return 10 }
        var fnCopy = copyFunc(fn)
        assertCopy(fnCopy, fn)
        done()
      })
      it('should copy a function of length 4', function (done) {
        var fn = function (a, b, c, d) { return 10 }
        var fnCopy = copyFunc(fn)
        assertCopy(fnCopy, fn)
        done()
      })
      it('should copy a function of length 5', function (done) {
        var fn = function (a, b, c, d, e) { return 10 }
        var fnCopy = copyFunc(fn)
        assertCopy(fnCopy, fn)
        done()
      })
      it('should copy a function of length 6', function (done) {
        var fn = function (a, b, c, d, e, f) { return 10 }
        var fnCopy = copyFunc(fn)
        assertCopy(fnCopy, fn)
        done()
      })
      it('should copy a function of length 7', function (done) {
        var fn = function (a, b, c, d, e, f, g) { return 10 }
        var fnCopy = copyFunc(fn)
        assertCopy(fnCopy, fn)
        done()
      })

      function assertCopy (fnCopy, fn) {
        expect(fnCopy).to.not.equal(fn)
        expect(fnCopy()).to.equal(fn())
        if (IS_GTE_NODE_4) {
          expect(fnCopy.name).to.equal(fn.name)
        }
        if (fn.length) {
          expect(fnCopy.length).to.equal(fn.length)
        }
      }
    })
  })
})
<commit_msg>100% test coverate in nod v4+<commit_after>var Code = require('code')
var Lab = require('lab')

var copyFunc = require('../index.js')

var lab = exports.lab = Lab.script()
var describe = lab.describe
var it = lab.it
var afterEach = lab.afterEach
var beforeEach = lab.beforeEach
var expect = Code.expect
var IS_GTE_NODE_4 = process.version.split('.')[0] === 'v4'

function add (a, b) {
  return a + b
}

describe('copyFunction', function () {
  it('should copy a function', function (done) {
    var addCopy = copyFunc(add)
    expect(addCopy).to.not.equal(add)
    expect(addCopy(1, 2))
      .to.equal(add(1, 2))
      .to.equal(1 + 2)
    if (IS_GTE_NODE_4) {
      expect(addCopy.name).to.equal(add.name)
    }
    expect(addCopy.length).to.equal(add.length)
    done()
  })
  it('should copy a function and assign a customName', function (done) {
    var addCopy = copyFunc(add, 'addCopy')
    expect(addCopy).to.not.equal(add)
    expect(addCopy(1, 2))
      .to.equal(add(1, 2))
      .to.equal(1 + 2)
    if (IS_GTE_NODE_4) {
      expect(addCopy.name).to.equal('addCopy')
    }
    expect(addCopy.length).to.equal(add.length)
    done()
  })

  describe('errors', function () {
    it('should throw an error if pass a non-function', function (done) {
      expect(function () {
        copyFunc({})
      }).to.throw(Error, /fn.*function/)
      done()
    })
  })
  describe('compatibility', function () {
    var getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor
    var defineProperty = Object.defineProperty
    var fnWithoutLength = function () {}
    if (IS_GTE_NODE_4) {
      Object.defineProperty(fnWithoutLength, 'length', {
        value: null,
        writable: false,
        enumerable: false,
        configurable: true
      })
    }

    describe('no Object.getOwnPropertyDescriptor', function () {
      beforeEach(function (done) {
        delete Object.getOwnPropertyDescriptor
        done()
      })
      afterEach(function (done) {
        Object.getOwnPropertyDescriptor = getOwnPropertyDescriptor
        done()
      })

      it('should use "legacy" copy', function (done) {
        var fn = function () { return 10 }
        var fnCopy = copyFunc(fn)
        // different assertions, bc lab throws errors w/out getOwnPropDesc
        expect(fnCopy !== fn).to.be.true()
        expect(fnCopy() === fn()).to.be.true()
        expect(fnCopy.length === fn.length).to.be.true()
        done()
      })
    })

    describe('no Object.defineProperty', function () {
      beforeEach(function (done) {
        delete Object.defineProperty
        done()
      })
      afterEach(function (done) {
        Object.defineProperty = defineProperty
        done()
      })
      if (IS_GTE_NODE_4) {
        // cannot redifine fn's length
        // to test this w/out node 4+
        it('should copy a function w/ no length', function (done) {
          var fn = fnWithoutLength
          var fnCopy = copyFunc(fn)
          assertCopy(fnCopy, fn)
          done()
        })
      }
      it('should copy a function of length 0', function (done) {
        var fn = function () { return 10 }
        var fnCopy = copyFunc(fn)
        assertCopy(fnCopy, fn)
        done()
      })
      it('should copy a function of length 1', function (done) {
        var fn = function (a) { return 10 }
        var fnCopy = copyFunc(fn)
        assertCopy(fnCopy, fn)
        done()
      })
      it('should copy a function of length 2', function (done) {
        var fn = function (a, b) { return 10 }
        var fnCopy = copyFunc(fn)
        assertCopy(fnCopy, fn)
        done()
      })
      it('should copy a function of length 3', function (done) {
        var fn = function (a, b, c) { return 10 }
        var fnCopy = copyFunc(fn)
        assertCopy(fnCopy, fn)
        done()
      })
      it('should copy a function of length 4', function (done) {
        var fn = function (a, b, c, d) { return 10 }
        var fnCopy = copyFunc(fn)
        assertCopy(fnCopy, fn)
        done()
      })
      it('should copy a function of length 5', function (done) {
        var fn = function (a, b, c, d, e) { return 10 }
        var fnCopy = copyFunc(fn)
        assertCopy(fnCopy, fn)
        done()
      })
      it('should copy a function of length 6', function (done) {
        var fn = function (a, b, c, d, e, f) { return 10 }
        var fnCopy = copyFunc(fn)
        assertCopy(fnCopy, fn)
        done()
      })
      it('should copy a function of length 7', function (done) {
        var fn = function (a, b, c, d, e, f, g) { return 10 }
        var fnCopy = copyFunc(fn)
        assertCopy(fnCopy, fn)
        done()
      })
    })

    function assertCopy (fnCopy, fn) {
      expect(fnCopy).to.not.equal(fn)
      expect(fnCopy()).to.equal(fn())
      expect(fnCopy.name).to.equal(fn.name)
      if (fn.length) {
        expect(fnCopy.length).to.equal(fn.length)
      }
    }
  })
})
<|endoftext|>


<commit_before>// @
// Copyright (c) 2017 Google Inc. All rights reserved.
// This code may only be used under the BSD style license found at
// http://polymer.github.io/LICENSE.txt
// Code distributed by Google as part of this project is also
// subject to an additional IP rights grant found at
// http://polymer.github.io/PATENTS.txt

import StorageProviderBase from './storage-provider-base.js';
import firebase from '../platform/firebase-web.js';
import assert from '../platform/assert-web.js';

class FirebaseKey {
  constructor(key) {
    var parts = key.split('://');
    this.protocol = parts[0];
    assert(this.protocol == 'firebase');
    if (parts[1]) {
      parts = parts[1].split('/');
      assert(parts[0].endsWith('.firebaseio.com'));
      this.databaseUrl = parts[0];
      this.projectId = this.databaseUrl.split('.')[0];
      this.apiKey = parts[1];
      this.location = parts.slice(2).join('/');
    } else {
      this.databaseUrl = undefined;
      this.projectId = undefined;
      this.apiKey = undefined;
      this.location = "";
    }
  }

  toString() {
    if (this.databaseUrl && this.apiKey)
      return `${this.protocol}://${this.databaseUrl}/${this.apiKey}`;
    return `${this.protocol}://`;
  }
}

export default class FirebaseStorage {
  constructor(arc) {
    this._arc = arc;
    this._apps = {};
    this._nextAppNameSuffix = 0;
  }

  async construct(id, type, keyFragment) {
    return this._join(id, type, keyFragment, false);
  }

  async connect(id, type, key) {
    return this._join(id, type, key, true);
  }

  async _join(id, type, key, shouldExist) {
    key = new FirebaseKey(key);
    // TODO: is it ever going to be possible to autoconstruct new firebase datastores?
    if (key.databaseUrl == undefined || key.apiKey == undefined)
      throw new Error("Can't complete partial firebase keys");

    if (this._apps[key.projectId] == undefined)
      this._apps[key.projectId] = firebase.initializeApp({
        apiKey: key.apiKey,
        databaseURL: key.databaseUrl
      }, `app${this._nextAppNameSuffix++}`);

    var reference = firebase.database(this._apps[key.projectId]).ref(key.location);
    let snapshot = await reference.once('value');
    let exists = snapshot.val() != null;
    if (shouldExist != exists)
      return null;

    return FirebaseStorageProvider.newProvider(type, this._arc, id, reference, key);
  }
}

class FirebaseStorageProvider extends StorageProviderBase {
  constructor(type, arc, id, reference, key) {
    super(type, arc, undefined, id, key.toString());
    this.firebaseKey = key;
    this.reference = reference;
  }

  static newProvider(type, arc, id, reference, key) {
    if (type.isSetView)
      return new FirebaseCollection(type, arc, id, reference, key);
    return new FirebaseVariable(type, arc, id, reference, key);
  }
}

class FirebaseVariable extends FirebaseStorageProvider {
  constructor(type, arc, id, reference, firebaseKey) {
    super(type, arc, id, reference, firebaseKey);
    this.dataSnapshot = undefined;
    this.version = 0;
    this.reference.on('value', dataSnapshot => {
      this.dataSnapshot = dataSnapshot;
      this._fire('change', {data: this.dataSnapshot.val(), version: this._version});
    });
  }

  async get() {
    return this.dataSnapshot.val();
  }

  async set(value) {
    this.version++;
    return this.reference.set(value);
  }

  async clear() {
    this.set(undefined);
  }
}

class FirebaseCollection extends FirebaseStorageProvider {
  constructor(type, arc, id, reference, firebaseKey) {
    super(type, arc, id, reference, firebaseKey);
    this.dataSnapshot = undefined;
    this.reference.on('value', dataSnapshot => {
      this.dataSnapshot = dataSnapshot;
      this._fire('change', {data: this._setToList(this.dataSnapshot.val()), version: this._version});
    });
  }

  async get(id) {
    return this.dataSnapshot.val()[id];
  }

  async store(entity) {
    return this.reference.child(entity.id).set(entity);
  }

  async toList() {
    return this._setToList(this.dataSnapshot.val());
  }

  _setToList(set) {
    var list = [];
    for (let key in set) {
      list.push(set[key]);
    }
    return list;
  }
}<commit_msg>Modify firebase integration to track versions inside datastore.<commit_after>// @
// Copyright (c) 2017 Google Inc. All rights reserved.
// This code may only be used under the BSD style license found at
// http://polymer.github.io/LICENSE.txt
// Code distributed by Google as part of this project is also
// subject to an additional IP rights grant found at
// http://polymer.github.io/PATENTS.txt

import StorageProviderBase from './storage-provider-base.js';
import firebase from '../platform/firebase-web.js';
import assert from '../platform/assert-web.js';

class FirebaseKey {
  constructor(key) {
    var parts = key.split('://');
    this.protocol = parts[0];
    assert(this.protocol == 'firebase');
    if (parts[1]) {
      parts = parts[1].split('/');
      assert(parts[0].endsWith('.firebaseio.com'));
      this.databaseUrl = parts[0];
      this.projectId = this.databaseUrl.split('.')[0];
      this.apiKey = parts[1];
      this.location = parts.slice(2).join('/');
    } else {
      this.databaseUrl = undefined;
      this.projectId = undefined;
      this.apiKey = undefined;
      this.location = "";
    }
  }

  toString() {
    if (this.databaseUrl && this.apiKey)
      return `${this.protocol}://${this.databaseUrl}/${this.apiKey}`;
    return `${this.protocol}://`;
  }
}

async function realTransaction(reference, transactionFunction) {
  let realData = undefined;
  await reference.once('value', data => {realData = data.val(); });
  return reference.transaction(data => {
    if (data == null)
      data = realData;
    return transactionFunction(data);
  }, undefined, false);
}

export default class FirebaseStorage {
  constructor(arc) {
    this._arc = arc;
    this._apps = {};
    this._nextAppNameSuffix = 0;
  }

  async construct(id, type, keyFragment) {
    return this._join(id, type, keyFragment, false);
  }

  async connect(id, type, key) {
    return this._join(id, type, key, true);
  }

  async _join(id, type, key, shouldExist) {
    key = new FirebaseKey(key);
    // TODO: is it ever going to be possible to autoconstruct new firebase datastores?
    if (key.databaseUrl == undefined || key.apiKey == undefined)
      throw new Error("Can't complete partial firebase keys");

    if (this._apps[key.projectId] == undefined)
      this._apps[key.projectId] = firebase.initializeApp({
        apiKey: key.apiKey,
        databaseURL: key.databaseUrl
      }, `app${this._nextAppNameSuffix++}`);

    var reference = firebase.database(this._apps[key.projectId]).ref(key.location);

    let result = await realTransaction(reference, data => {
      if ((data == null) == shouldExist)
        return; // abort transaction
      if (!shouldExist) {
        return {version: 0};
      }
      return data;
    });

    if (!result.committed)
      return null;

    return FirebaseStorageProvider.newProvider(type, this._arc, id, reference, key);
  }
}

class FirebaseStorageProvider extends StorageProviderBase {
  constructor(type, arc, id, reference, key) {
    super(type, arc, undefined, id, key.toString());
    this.firebaseKey = key;
    this.reference = reference;
  }

  static newProvider(type, arc, id, reference, key) {
    if (type.isSetView)
      return new FirebaseCollection(type, arc, id, reference, key);
    return new FirebaseVariable(type, arc, id, reference, key);
  }
}

class FirebaseVariable extends FirebaseStorageProvider {
  constructor(type, arc, id, reference, firebaseKey) {
    super(type, arc, id, reference, firebaseKey);
    this.dataSnapshot = undefined;
    this.reference.on('value', dataSnapshot => {
      this.dataSnapshot = dataSnapshot;
      let data = dataSnapshot.val();
      this._fire('change', {data: data.data, version: data.version});
    });
  }

  async get() {
    return this.dataSnapshot.val().data;
  }

  async set(value) {
    return realTransaction(this.reference, data => ({data: value, version: data.version + 1}));
  }

  async clear() {
    this.set(undefined);
  }
}

class FirebaseCollection extends FirebaseStorageProvider {
  constructor(type, arc, id, reference, firebaseKey) {
    super(type, arc, id, reference, firebaseKey);
    this.dataSnapshot = undefined;
    this.reference.on('value', dataSnapshot => {
      this.dataSnapshot = dataSnapshot;
      let data = dataSnapshot.val();
      this._fire('change', {data: this._setToList(data.data), version: data.version});
    });
  }

  async get(id) {
    var set = this.dataSnapshot.val().data;
    if (set)
      return set[id];
    return undefined;
  }

  async store(entity) {
    return realTransaction(this.reference, data => {
      if (!data.data)
        data.data = {};
      data.data[entity.id] = entity;
      data.version += 1;
      return data;
    });
  }

  async toList() {
    return this._setToList(this.dataSnapshot.val().data);
  }

  _setToList(set) {
    var list = [];
    if (set) {
      for (let key in set) {
        list.push(set[key]);
      }
    }
    return list;
  }
}<|endoftext|>


<commit_before>const assert = require('assert')
const http = require('http')
const multiparty = require('multiparty')
const path = require('path')
const temp = require('temp').track()
const url = require('url')
const {closeWindow} = require('./window-helpers')

const {remote} = require('electron')
const {app, BrowserWindow, crashReporter} = remote.require('electron')

const isCI = remote.getGlobal('isCi')

describe('crashReporter module', function () {
  var fixtures = path.resolve(__dirname, 'fixtures')
  var w = null
  var originalTempDirectory = null
  var tempDirectory = null

  beforeEach(function () {
    w = new BrowserWindow({
      show: false
    })
    tempDirectory = temp.mkdirSync('electronCrashReporterSpec-')
    originalTempDirectory = app.getPath('temp')
    app.setPath('temp', tempDirectory)
  })

  afterEach(function () {
    app.setPath('temp', originalTempDirectory)
    return closeWindow(w).then(function () { w = null })
  })

  if (process.mas) {
    return
  }

  it('should send minidump when renderer crashes', function (done) {
    if (isCI) return

    this.timeout(120000)

    var called = false
    var server = http.createServer(function (req, res) {
      server.close()
      var form = new multiparty.Form()
      form.parse(req, function (error, fields) {
        if (error) throw error
        if (called) return
        called = true
        assert.equal(fields['prod'], 'Electron')
        assert.equal(fields['ver'], process.versions.electron)
        assert.equal(fields['process_type'], 'renderer')
        assert.equal(fields['platform'], process.platform)
        assert.equal(fields['extra1'], 'extra1')
        assert.equal(fields['extra2'], 'extra2')
        assert.equal(fields['_productName'], 'Zombies')
        assert.equal(fields['_companyName'], 'Umbrella Corporation')
        assert.equal(fields['_version'], app.getVersion())

        const reportId = 'abc-123-def-456-abc-789-abc-123-abcd'
        res.end(reportId, () => {
          waitForCrashReport().then(() => {
            assert.equal(crashReporter.getLastCrashReport().id, reportId)
            assert.notEqual(crashReporter.getUploadedReports().length, 0)
            assert.equal(crashReporter.getUploadedReports()[0].id, reportId)
            done()
          }, done)
        })
      })
    })
    var port = remote.process.port
    server.listen(port, '127.0.0.1', function () {
      port = server.address().port
      remote.process.port = port
      const crashUrl = url.format({
        protocol: 'file',
        pathname: path.join(fixtures, 'api', 'crash.html'),
        search: '?port=' + port
      })
      if (process.platform === 'darwin') {
        crashReporter.start({
          companyName: 'Umbrella Corporation',
          submitURL: 'http://127.0.0.1:' + port
        })
      }
      w.loadURL(crashUrl)
    })
  })

  describe('.start(options)', function () {
    it('requires that the companyName and submitURL options be specified', function () {
      assert.throws(function () {
        crashReporter.start({
          companyName: 'Missing submitURL'
        })
      }, /submitURL is a required option to crashReporter\.start/)
      assert.throws(function () {
        crashReporter.start({
          submitURL: 'Missing companyName'
        })
      }, /companyName is a required option to crashReporter\.start/)
    })

    it('can be called multiple times', function () {
      assert.doesNotThrow(function () {
        crashReporter.start({
          companyName: 'Umbrella Corporation',
          submitURL: 'http://127.0.0.1/crashes'
        })

        crashReporter.start({
          companyName: 'Umbrella Corporation 2',
          submitURL: 'http://127.0.0.1/more-crashes'
        })
      })
    })
  })

  describe('.get/setUploadToServer', function () {
    it('throws an error when called from the renderer process', function () {
      assert.throws(() => require('electron').crashReporter.getUploadToServer())
    })

    it('can be read/set from the main process', function () {
      if (process.platform === 'darwin') {
        crashReporter.start({
          companyName: 'Umbrella Corporation',
          submitURL: 'http://127.0.0.1/crashes',
          autoSubmit: true
        })
        assert.equal(crashReporter.getUploadToServer(), true)
        crashReporter.setUploadToServer(false)
        assert.equal(crashReporter.getUploadToServer(), false)
      } else {
        assert.equal(crashReporter.getUploadToServer(), true)
      }
    })
  })
})

const waitForCrashReport = () => {
  return new Promise((resolve, reject) => {
    let times = 0
    const checkForReport = () => {
      if (crashReporter.getLastCrashReport() != null) {
        resolve()
      } else if (times >= 10) {
        reject(new Error('No crash report available'))
      } else {
        times++
        setTimeout(checkForReport, 100)
      }
    }
    checkForReport()
  })
}
<commit_msg>Add missing call to done<commit_after>const assert = require('assert')
const http = require('http')
const multiparty = require('multiparty')
const path = require('path')
const temp = require('temp').track()
const url = require('url')
const {closeWindow} = require('./window-helpers')

const {remote} = require('electron')
const {app, BrowserWindow, crashReporter} = remote.require('electron')

const isCI = remote.getGlobal('isCi')

describe('crashReporter module', function () {
  var fixtures = path.resolve(__dirname, 'fixtures')
  var w = null
  var originalTempDirectory = null
  var tempDirectory = null

  beforeEach(function () {
    w = new BrowserWindow({
      show: false
    })
    tempDirectory = temp.mkdirSync('electronCrashReporterSpec-')
    originalTempDirectory = app.getPath('temp')
    app.setPath('temp', tempDirectory)
  })

  afterEach(function () {
    app.setPath('temp', originalTempDirectory)
    return closeWindow(w).then(function () { w = null })
  })

  if (process.mas) {
    return
  }

  it('should send minidump when renderer crashes', function (done) {
    if (isCI) return done()

    this.timeout(120000)

    var called = false
    var server = http.createServer(function (req, res) {
      server.close()
      var form = new multiparty.Form()
      form.parse(req, function (error, fields) {
        if (error) throw error
        if (called) return
        called = true
        assert.equal(fields['prod'], 'Electron')
        assert.equal(fields['ver'], process.versions.electron)
        assert.equal(fields['process_type'], 'renderer')
        assert.equal(fields['platform'], process.platform)
        assert.equal(fields['extra1'], 'extra1')
        assert.equal(fields['extra2'], 'extra2')
        assert.equal(fields['_productName'], 'Zombies')
        assert.equal(fields['_companyName'], 'Umbrella Corporation')
        assert.equal(fields['_version'], app.getVersion())

        const reportId = 'abc-123-def-456-abc-789-abc-123-abcd'
        res.end(reportId, () => {
          waitForCrashReport().then(() => {
            assert.equal(crashReporter.getLastCrashReport().id, reportId)
            assert.notEqual(crashReporter.getUploadedReports().length, 0)
            assert.equal(crashReporter.getUploadedReports()[0].id, reportId)
            done()
          }, done)
        })
      })
    })
    var port = remote.process.port
    server.listen(port, '127.0.0.1', function () {
      port = server.address().port
      remote.process.port = port
      const crashUrl = url.format({
        protocol: 'file',
        pathname: path.join(fixtures, 'api', 'crash.html'),
        search: '?port=' + port
      })
      if (process.platform === 'darwin') {
        crashReporter.start({
          companyName: 'Umbrella Corporation',
          submitURL: 'http://127.0.0.1:' + port
        })
      }
      w.loadURL(crashUrl)
    })
  })

  describe('.start(options)', function () {
    it('requires that the companyName and submitURL options be specified', function () {
      assert.throws(function () {
        crashReporter.start({
          companyName: 'Missing submitURL'
        })
      }, /submitURL is a required option to crashReporter\.start/)
      assert.throws(function () {
        crashReporter.start({
          submitURL: 'Missing companyName'
        })
      }, /companyName is a required option to crashReporter\.start/)
    })

    it('can be called multiple times', function () {
      assert.doesNotThrow(function () {
        crashReporter.start({
          companyName: 'Umbrella Corporation',
          submitURL: 'http://127.0.0.1/crashes'
        })

        crashReporter.start({
          companyName: 'Umbrella Corporation 2',
          submitURL: 'http://127.0.0.1/more-crashes'
        })
      })
    })
  })

  describe('.get/setUploadToServer', function () {
    it('throws an error when called from the renderer process', function () {
      assert.throws(() => require('electron').crashReporter.getUploadToServer())
    })

    it('can be read/set from the main process', function () {
      if (process.platform === 'darwin') {
        crashReporter.start({
          companyName: 'Umbrella Corporation',
          submitURL: 'http://127.0.0.1/crashes',
          autoSubmit: true
        })
        assert.equal(crashReporter.getUploadToServer(), true)
        crashReporter.setUploadToServer(false)
        assert.equal(crashReporter.getUploadToServer(), false)
      } else {
        assert.equal(crashReporter.getUploadToServer(), true)
      }
    })
  })
})

const waitForCrashReport = () => {
  return new Promise((resolve, reject) => {
    let times = 0
    const checkForReport = () => {
      if (crashReporter.getLastCrashReport() != null) {
        resolve()
      } else if (times >= 10) {
        reject(new Error('No crash report available'))
      } else {
        times++
        setTimeout(checkForReport, 100)
      }
    }
    checkForReport()
  })
}
<|endoftext|>


<commit_before>/* $This file is distributed under the terms of the license in /doc/license.txt$ */

/*
 * ----------------------------------------------------------------------------
 * proxyItemsPanel
 * ----------------------------------------------------------------------------
 * Display an AJAX-enabled list of proxy-related items (either proxies or
 * profiles).
 *
 * The list may start out with a population of items. items may be added by
 * selecting them in the auto-complete box. Items may be removed by clicking
 * the "remove" link next to that item.
 *
 * A hidden field will hold the URI for each item, so when the form is submitted,
 * the controller can determine the list of items.
 * ----------------------------------------------------------------------------
 * You provide:
 *   p -- the DOM element that contains the template and the data.
 *         It also contains the autocomplete field.
 * ----------------------------------------------------------------------------
 */
function proxyItemsPanel(panel, contextInfo)  {
	var self = this;

	this.itemData = [];

	var excludedUris = contextInfo.excludedUris;
	var dataContainerElement = $("[name='proxyData']", panel).first();
	var autoCompleteField = $("input[name='proxySelectorAC']", panel).first();
	var searchStatusField = $("span[name='proxySelectorSearchStatus']", panel).first();

	var parseTemplate = function(dataContainer) {
		var templateDiv = $("div[name='template']", dataContainer)
		var templateHtml = templateDiv.html();
		templateDiv.remove();
		return templateHtml;
	};
	this.templateHtml = parseTemplate(dataContainerElement);

	this.displayItemData = function() {
		$(".proxyInfoElement", dataContainerElement).remove();

		for (i = 0; i < self.itemData.length; i++) {
			self.itemData[i].element().appendTo(dataContainerElement);
		}
	}

	var getItemData = function() {
		return self.itemData;
	}

	this.removeItem = function(info) {
		var idx = self.itemData.indexOf(info);
		if (idx != -1) {
			self.itemData.splice(idx, 1);
		}
		self.displayItemData();
	}

	this.addItemData = function(selection) {
		var imageUrl = contextInfo.defaultImageUrl;
		if (selection.imageUrl) {
			imageUrl = contextInfo.baseUrl + selection.imageUrl;
		}

		var classLabel = selection.classLabel ? selection.classLabel : "";

		var info = new itemElement(self.templateHtml, selection.uri, selection.label, classLabel,
				imageUrl, self.removeItem);
        self.itemData.unshift(info);
        self.displayItemData();
        self.getAdditionalData(self, info, selection.externalAuthId)
	}

	this.getAdditionalData = function(parent, info, externalAuthId) {
		// For the plain vanilla panel, this need not do anything. For the
		// proxy panel, this will be replaced by a function that does another
		// AJAX call to get the classLabel and imageUrl.
	}

	var parseOriginalData = function() {
		var dataDivs = $("div[name='data']", dataContainerElement)
		var data = [];
		for (i = 0; i < dataDivs.length; i++) {
			var dd = dataDivs[i];
			var uri = $("p[name='uri']", dd).text();
			var label = $("p[name='label']", dd).text();
			var classLabel = $("p[name='classLabel']", dd).text();
			var imageUrl = $("p[name='imageUrl']", dd).text();
			data.push(new itemElement(self.templateHtml, uri, label, classLabel, imageUrl, self.removeItem));
		}
		return data;
	}
	this.itemData = parseOriginalData();

	var setupAutoCompleteFields = function() {
		var parms = {
		    query: contextInfo.query,
		    model: contextInfo.model,
		    url: contextInfo.sparqlQueryUrl
		    };
		var updateStatus = new statusFieldUpdater(searchStatusField, 3).setText;
		var autocompleteInfo = new proxyAutocomplete(parms, excludedUris, getItemData, self.addItemData, updateStatus)
	    autoCompleteField.autocomplete(autocompleteInfo);
	}
	setupAutoCompleteFields();

	self.displayItemData();
}

function statusFieldUpdater(element, minLength) {
	var emptyText = element.text();
	var moreCharsText = element.attr('moreCharsText');
	var noMatchText = element.attr('noMatchText');

	this.setText = function(searchTermLength, numberOfResults) {
		if (numberOfResults > 0) {
			element.text('');
		} else if (searchTermLength == 0) {
			element.text(emptyText);
		} else if (searchTermLength < minLength) {
			element.text(moreCharsText);
		} else {
			element.text(noMatchText);
		}
	}
}

var profileQuery = ""
    + "PREFIX fn: <http://www.w3.org/2005/xpath-functions#> \n"
    + "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n"
	+ "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n"
    + "PREFIX foaf: <http://xmlns.com/foaf/0.1/> \n"
	+ "PREFIX vitro: <http://vitro.mannlib.cornell.edu/ns/vitro/0.7#> \n"
	+ "PREFIX vpublic: <http://vitro.mannlib.cornell.edu/ns/vitro/public#> \n"
	+ "PREFIX auth: <http://vitro.mannlib.cornell.edu/ns/vitro/authorization#> \n"
	+ "\n"
	+ "SELECT DISTINCT ?uri ?label ?classLabel ?imageUrl \n"
	+ "WHERE { \n"
	+ "    %typesUnion% \n"
	+ "    ?uri rdfs:label ?label ; \n"
	+ "    OPTIONAL { \n"
	+ "       ?uri vitro:mostSpecificType ?type. \n"
	+ "       ?type rdfs:label ?classLabel  \n"
	+ "       }  \n"
	+ "   OPTIONAL { \n"
	+ "       ?uri vpublic:mainImage ?imageUri. \n"
	+ "       ?imageUri vpublic:thumbnailImage ?thumbUri. \n"
	+ "       ?thumbUri vpublic:downloadLocation ?thumbstreamUri. \n"
	+ "       ?thumbstreamUri vpublic:directDownloadUrl ?imageUrl. \n"
	+ "       }  \n"
	+ "    FILTER (REGEX(str(?label), '^%term%', 'i')) \n"
	+ "} \n"
	+ "ORDER BY ASC(?label) \n"
	+ "LIMIT 25 \n";

var proxyQuery = ""
    + "PREFIX fn: <http://www.w3.org/2005/xpath-functions#> \n"
	+ "PREFIX auth: <http://vitro.mannlib.cornell.edu/ns/vitro/authorization#> \n"
	+ "\n"
	+ "SELECT DISTINCT ?uri ?label ?externalAuthId \n"
	+ "WHERE { \n"
	+ "    ?uri a auth:UserAccount ; \n"
	+ "            auth:firstName ?firstName ; \n"
	+ "            auth:lastName ?lastName . \n"
	+ "    LET ( ?label := fn:concat(?lastName, ', ', ?firstName) )"
	+ "    OPTIONAL { ?uri auth:externalAuthId ?externalAuthId } \n"
	+ "    FILTER (REGEX(?label, '^%term%', 'i')) \n"
	+ "} \n"
	+ "ORDER BY ASC(?lastName) ASC(?firstName) \n"
	+ "LIMIT 25 \n";

var moreInfoQuery = ""
	+ "PREFIX rdfs:  <http://www.w3.org/2000/01/rdf-schema#> \n"
	+ "PREFIX vitro: <http://vitro.mannlib.cornell.edu/ns/vitro/0.7#> \n"
	+ "PREFIX p.1: <http://vitro.mannlib.cornell.edu/ns/vitro/public#> \n"
	+ " \n"
	+ "SELECT ?uri ?classLabel ?imageUrl \n"
	+ "WHERE \n"
	+ "{ \n"
	+ "    ?uri <%matchingProperty%> '%externalAuthId%'. \n"
	+ " \n"
	+ "    OPTIONAL { \n"
	+ "       ?uri vitro:mostSpecificType ?type. \n"
	+ "       ?type rdfs:label ?classLabel  \n"
	+ "       }  \n"
	+ " \n"
	+ "   OPTIONAL { \n"
	+ "       ?uri p.1:mainImage ?imageUri. \n"
	+ "       ?imageUri p.1:thumbnailImage ?thumbUri. \n"
	+ "       ?thumbUri p.1:downloadLocation ?thumbstreamUri. \n"
	+ "       ?thumbstreamUri p.1:directDownloadUrl ?imageUrl. \n"
	+ "       }  \n"
	+ "} \n"
	+ "LIMIT 1 \n";

/*
 * This function will allow a proxy panel to execute another query for each proxy.
 */
var getAdditionalProxyInfo = function(parent, info, externalAuthId) {
    $.ajax({
        url: proxyContextInfo.sparqlQueryUrl,
        dataType: 'json',
        data: {
        	query: moreInfoQuery.replace("%matchingProperty%", proxyContextInfo.matchingProperty)
        	                    .replace("%externalAuthId%", externalAuthId)
        },
        complete: function(xhr, status) {
            var results = $.parseJSON(xhr.responseText);
            var parsed = sparqlUtils.parseSparqlResults(results);
            if (parsed.length > 0) {
                if ("classLabel" in parsed[0]) {
                    info.classLabel = parsed[0].classLabel;
                }
                if ("imageUrl" in parsed[0]) {
                	info.imageUrl = proxyContextInfo.baseUrl + parsed[0].imageUrl;
                }
                parent.displayItemData();
            }
        }
    });
}

/*
 * The profileTypes context string must have one or more type URIs, separated by commas.
 */
var applyProfileTypes = function(rawQuery) {
	var typeClause = '';
	var types = proxyContextInfo.profileTypes.split(',');

    for (var i = 0; i < types.length; i++) {
	    typeClause += '{ ?uri rdf:type <' + types[i].trim() + '> }';
    	if (i + 1 < types.length) {
	    	typeClause += ' UNION ';
	    } else {
		    typeClause += ' .';
    	}
	}
    return rawQuery.replace("%typesUnion%", typeClause);
}

/*
 * Execute this when the page loads.
 */
$(document).ready(function() {
	var disableFormInUnsupportedBrowsers = function() {
		var disableWrapper = $('#ie67DisableWrapper');

		// Check for unsupported browsers only if the element exists on the page
		if (disableWrapper.length) {
			if (vitro.browserUtils.isIELessThan8()) {
				disableWrapper.show();
				$('.noIE67').hide();
				return true;
			}
		}
		return false;
	};

	/* If we don't support this form in this browser, just stop here. */
	if (disableFormInUnsupportedBrowsers()) {
		return;
	}

	/*
	 * For each proxyProfilesPanel, modify the profile query to restrict it
	 * to the permitted types, then create a plain vanilla panel using the
	 * profile query against the main model.
	 */
	$("div[name='proxyProfilesPanel']").each(function(i) {
		var query = applyProfileTypes(profileQuery);
		var context = {
			excludedUris: [],
			baseUrl: proxyContextInfo.baseUrl,
			sparqlQueryUrl: proxyContextInfo.sparqlQueryUrl,
			defaultImageUrl: proxyContextInfo.defaultImageUrl,
			query: query,
			model: ''
		}
		this["proxyItemsPanel"] = new proxyItemsPanel(this, context);
	});

	/*
	 * For each proxyProxiesPanel, we start with a plain panel using the proxy
	 * query against the user accounts model. Then we augment it with a method
	 * that will fetch more info from the main model for each proxy.
	 */
	$("div[name='proxyProxiesPanel']").each(function(i) {
		var context = {
            excludedUris: [],
			baseUrl: proxyContextInfo.baseUrl,
			sparqlQueryUrl: proxyContextInfo.sparqlQueryUrl,
			defaultImageUrl: proxyContextInfo.defaultImageUrl,
			query: proxyQuery,
			model: 'userAccounts'
		}
		var pip = new proxyItemsPanel(this, context);
		pip.getAdditionalData = getAdditionalProxyInfo;
		this["proxyItemsPanel"] = pip;
	});
});
<commit_msg>NIHVIVO-2343 Use a simpler query for the profile auto-complete to try to speed the response. Is it enough?<commit_after>/* $This file is distributed under the terms of the license in /doc/license.txt$ */

/*
 * ----------------------------------------------------------------------------
 * proxyItemsPanel
 * ----------------------------------------------------------------------------
 * Display an AJAX-enabled list of proxy-related items (either proxies or
 * profiles).
 *
 * The list may start out with a population of items. items may be added by
 * selecting them in the auto-complete box. Items may be removed by clicking
 * the "remove" link next to that item.
 *
 * A hidden field will hold the URI for each item, so when the form is submitted,
 * the controller can determine the list of items.
 * ----------------------------------------------------------------------------
 * You provide:
 *   p -- the DOM element that contains the template and the data.
 *         It also contains the autocomplete field.
 * ----------------------------------------------------------------------------
 */
function proxyItemsPanel(panel, contextInfo)  {
	var self = this;

	this.itemData = [];

	var excludedUris = contextInfo.excludedUris;
	var dataContainerElement = $("[name='proxyData']", panel).first();
	var autoCompleteField = $("input[name='proxySelectorAC']", panel).first();
	var searchStatusField = $("span[name='proxySelectorSearchStatus']", panel).first();

	var parseTemplate = function(dataContainer) {
		var templateDiv = $("div[name='template']", dataContainer)
		var templateHtml = templateDiv.html();
		templateDiv.remove();
		return templateHtml;
	};
	this.templateHtml = parseTemplate(dataContainerElement);

	this.displayItemData = function() {
		$(".proxyInfoElement", dataContainerElement).remove();

		for (i = 0; i < self.itemData.length; i++) {
			self.itemData[i].element().appendTo(dataContainerElement);
		}
	}

	var getItemData = function() {
		return self.itemData;
	}

	this.removeItem = function(info) {
		var idx = self.itemData.indexOf(info);
		if (idx != -1) {
			self.itemData.splice(idx, 1);
		}
		self.displayItemData();
	}

	this.addItemData = function(selection) {
		var imageUrl = contextInfo.defaultImageUrl;
		if (selection.imageUrl) {
			imageUrl = contextInfo.baseUrl + selection.imageUrl;
		}

		var classLabel = selection.classLabel ? selection.classLabel : "";

		var info = new itemElement(self.templateHtml, selection.uri, selection.label, classLabel,
				imageUrl, self.removeItem);
        self.itemData.unshift(info);
        self.displayItemData();
        self.getAdditionalData(self, info, selection.externalAuthId)
	}

	this.getAdditionalData = function(parent, info, externalAuthId) {
		// For the plain vanilla panel, this need not do anything. For the
		// proxy panel, this will be replaced by a function that does another
		// AJAX call to get the classLabel and imageUrl.
	}

	var parseOriginalData = function() {
		var dataDivs = $("div[name='data']", dataContainerElement)
		var data = [];
		for (i = 0; i < dataDivs.length; i++) {
			var dd = dataDivs[i];
			var uri = $("p[name='uri']", dd).text();
			var label = $("p[name='label']", dd).text();
			var classLabel = $("p[name='classLabel']", dd).text();
			var imageUrl = $("p[name='imageUrl']", dd).text();
			data.push(new itemElement(self.templateHtml, uri, label, classLabel, imageUrl, self.removeItem));
		}
		return data;
	}
	this.itemData = parseOriginalData();

	var setupAutoCompleteFields = function() {
		var parms = {
		    query: contextInfo.query,
		    model: contextInfo.model,
		    url: contextInfo.sparqlQueryUrl
		    };
		var updateStatus = new statusFieldUpdater(searchStatusField, 3).setText;
		var autocompleteInfo = new proxyAutocomplete(parms, excludedUris, getItemData, self.addItemData, updateStatus)
	    autoCompleteField.autocomplete(autocompleteInfo);
	}
	setupAutoCompleteFields();

	self.displayItemData();
}

function statusFieldUpdater(element, minLength) {
	var emptyText = element.text();
	var moreCharsText = element.attr('moreCharsText');
	var noMatchText = element.attr('noMatchText');

	this.setText = function(searchTermLength, numberOfResults) {
		if (numberOfResults > 0) {
			element.text('');
		} else if (searchTermLength == 0) {
			element.text(emptyText);
		} else if (searchTermLength < minLength) {
			element.text(moreCharsText);
		} else {
			element.text(noMatchText);
		}
	}
}

var profileQuery = ""
    + "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n"
	+ "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n"
	+ "\n"
	+ "SELECT DISTINCT ?uri ?label ?classLabel ?imageUrl \n"
	+ "WHERE { \n"
	+ "    %typesUnion% \n"
	+ "    ?uri rdfs:label ?label ; \n"
	+ "    FILTER (REGEX(str(?label), '^%term%', 'i')) \n"
	+ "} \n"
	+ "ORDER BY ASC(?label) \n"
	+ "LIMIT 25 \n";

var profileMoreInfoQuery = ""
	+ "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> \n"
	+ "PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#> \n"
	+ "PREFIX vitro: <http://vitro.mannlib.cornell.edu/ns/vitro/0.7#> \n"
	+ "PREFIX vpublic: <http://vitro.mannlib.cornell.edu/ns/vitro/public#> \n"
	+ "\n"
	+ "SELECT DISTINCT ?classLabel ?imageUrl \n"
	+ "WHERE { \n"
	+ "    OPTIONAL { \n"
	+ "       <%uri%> vitro:mostSpecificType ?type. \n"
	+ "       ?type rdfs:label ?classLabel  \n"
	+ "       }  \n"
	+ "   OPTIONAL { \n"
	+ "       <%uri%> vpublic:mainImage ?imageUri. \n"
	+ "       ?imageUri vpublic:thumbnailImage ?thumbUri. \n"
	+ "       ?thumbUri vpublic:downloadLocation ?thumbstreamUri. \n"
	+ "       ?thumbstreamUri vpublic:directDownloadUrl ?imageUrl. \n"
	+ "       }  \n"
	+ "} \n"
	+ "ORDER BY ASC(?label) \n"
	+ "LIMIT 25 \n";

var proxyQuery = ""
    + "PREFIX fn: <http://www.w3.org/2005/xpath-functions#> \n"
	+ "PREFIX auth: <http://vitro.mannlib.cornell.edu/ns/vitro/authorization#> \n"
	+ "\n"
	+ "SELECT DISTINCT ?uri ?label ?externalAuthId \n"
	+ "WHERE { \n"
	+ "    ?uri a auth:UserAccount ; \n"
	+ "            auth:firstName ?firstName ; \n"
	+ "            auth:lastName ?lastName . \n"
	+ "    LET ( ?label := fn:concat(?lastName, ', ', ?firstName) )"
	+ "    OPTIONAL { ?uri auth:externalAuthId ?externalAuthId } \n"
	+ "    FILTER (REGEX(?label, '^%term%', 'i')) \n"
	+ "} \n"
	+ "ORDER BY ASC(?lastName) ASC(?firstName) \n"
	+ "LIMIT 25 \n";

var proxyMoreInfoQuery = ""
	+ "PREFIX rdfs:  <http://www.w3.org/2000/01/rdf-schema#> \n"
	+ "PREFIX vitro: <http://vitro.mannlib.cornell.edu/ns/vitro/0.7#> \n"
	+ "PREFIX p.1: <http://vitro.mannlib.cornell.edu/ns/vitro/public#> \n"
	+ " \n"
	+ "SELECT ?uri ?classLabel ?imageUrl \n"
	+ "WHERE \n"
	+ "{ \n"
	+ "    ?uri <%matchingProperty%> '%externalAuthId%'. \n"
	+ " \n"
	+ "    OPTIONAL { \n"
	+ "       ?uri vitro:mostSpecificType ?type. \n"
	+ "       ?type rdfs:label ?classLabel  \n"
	+ "       }  \n"
	+ " \n"
	+ "   OPTIONAL { \n"
	+ "       ?uri p.1:mainImage ?imageUri. \n"
	+ "       ?imageUri p.1:thumbnailImage ?thumbUri. \n"
	+ "       ?thumbUri p.1:downloadLocation ?thumbstreamUri. \n"
	+ "       ?thumbstreamUri p.1:directDownloadUrl ?imageUrl. \n"
	+ "       }  \n"
	+ "} \n"
	+ "LIMIT 1 \n";

/*
 * This function will allow a proxy panel to execute another query for each proxy.
 */
var getAdditionalProxyInfo = function(parent, info, externalAuthId) {
    $.ajax({
        url: proxyContextInfo.sparqlQueryUrl,
        dataType: 'json',
        data: {
        	query: proxyMoreInfoQuery.replace(/%matchingProperty%/g, proxyContextInfo.matchingProperty)
        	                    .replace(/%externalAuthId%/g, externalAuthId)
        },
        complete: function(xhr, status) {
            var results = $.parseJSON(xhr.responseText);
            var parsed = sparqlUtils.parseSparqlResults(results);
            if (parsed.length > 0) {
                if ("classLabel" in parsed[0]) {
                    info.classLabel = parsed[0].classLabel;
                }
                if ("imageUrl" in parsed[0]) {
                	info.imageUrl = proxyContextInfo.baseUrl + parsed[0].imageUrl;
                }
                parent.displayItemData();
            }
        }
    });
}

/*
 * The profileTypes context string must have one or more type URIs, separated by commas.
 */
var applyProfileTypes = function(rawQuery) {
	var typeClause = '';
	var types = proxyContextInfo.profileTypes.split(',');

    for (var i = 0; i < types.length; i++) {
	    typeClause += '{ ?uri rdf:type <' + types[i].trim() + '> }';
    	if (i + 1 < types.length) {
	    	typeClause += ' UNION ';
	    } else {
		    typeClause += ' .';
    	}
	}
    return rawQuery.replace(/%typesUnion%/g, typeClause);
}

/*
 * This function will allow a profile panel to execute another query for each profile.
 */
var getAdditionalProfileInfo = function(parent, info) {
    $.ajax({
        url: proxyContextInfo.sparqlQueryUrl,
        dataType: 'json',
        data: {
        	query: profileMoreInfoQuery.replace(/%uri%/g, info.uri)
        },
        complete: function(xhr, status) {
            var results = $.parseJSON(xhr.responseText);
            var parsed = sparqlUtils.parseSparqlResults(results);
            if (parsed.length > 0) {
                if ("classLabel" in parsed[0]) {
                    info.classLabel = parsed[0].classLabel;
                }
                if ("imageUrl" in parsed[0]) {
                	info.imageUrl = proxyContextInfo.baseUrl + parsed[0].imageUrl;
                }
                parent.displayItemData();
            }
        }
    });
}

/*
 * Execute this when the page loads.
 */
$(document).ready(function() {
	var disableFormInUnsupportedBrowsers = function() {
		var disableWrapper = $('#ie67DisableWrapper');

		// Check for unsupported browsers only if the element exists on the page
		if (disableWrapper.length) {
			if (vitro.browserUtils.isIELessThan8()) {
				disableWrapper.show();
				$('.noIE67').hide();
				return true;
			}
		}
		return false;
	};

	/* If we don't support this form in this browser, just stop here. */
	if (disableFormInUnsupportedBrowsers()) {
		return;
	}

	/*
	 * For each proxyProfilesPanel, modify the profile query to restrict it
	 * to the permitted types, then create a plain vanilla panel using the
	 * profile query against the main model.
	 */
	$("div[name='proxyProfilesPanel']").each(function(i) {
		var query = applyProfileTypes(profileQuery);
		var context = {
			excludedUris: [],
			baseUrl: proxyContextInfo.baseUrl,
			sparqlQueryUrl: proxyContextInfo.sparqlQueryUrl,
			defaultImageUrl: proxyContextInfo.defaultImageUrl,
			query: query,
			model: ''
		}
		var pip = new proxyItemsPanel(this, context);
		pip.getAdditionalData = getAdditionalProfileInfo;
		this["proxyItemsPanel"] = pip;
	});

	/*
	 * For each proxyProxiesPanel, we start with a plain panel using the proxy
	 * query against the user accounts model. Then we augment it with a method
	 * that will fetch more info from the main model for each proxy.
	 */
	$("div[name='proxyProxiesPanel']").each(function(i) {
		var context = {
            excludedUris: [],
			baseUrl: proxyContextInfo.baseUrl,
			sparqlQueryUrl: proxyContextInfo.sparqlQueryUrl,
			defaultImageUrl: proxyContextInfo.defaultImageUrl,
			query: proxyQuery,
			model: 'userAccounts'
		}
		var pip = new proxyItemsPanel(this, context);
		pip.getAdditionalData = getAdditionalProxyInfo;
		this["proxyItemsPanel"] = pip;
	});
});
<|endoftext|>


<commit_before>// Except as noted, this content is licensed under Creative Commons
// Attribution 3.0

/* A little code to ease navigation of these documents.
 *
 * On window load we:
 *  + Generate a table of contents (godocs_generateTOC)
 *  + Add links up to the top of the doc from each section (godocs_addTopLinks)
 */

/* We want to do some stuff on page load (after the HTML is rendered).
   So listen for that:
 */
function bindEvent(el, e, fn) {
  if (el.addEventListener){
    el.addEventListener(e, fn, false);
  } else if (el.attachEvent){
    el.attachEvent('on'+e, fn);
  }
}
bindEvent(window, 'load', godocs_onload);

function godocs_onload() {
  godocs_bindSearchEvents();
  godocs_generateTOC();
  godocs_bindExamples();
}

function godocs_bindSearchEvents() {
  var search = document.getElementById('search');
  if (!search) {
    // no search box (index disabled)
    return;
  }
  function clearInactive() {
    if (search.className == "inactive") {
      search.value = "";
      search.className = "";
    }
  }
  function restoreInactive() {
    if (search.value != "") {
      return;
    }
    if (search.type != "search") {
      search.value = search.getAttribute("placeholder");
    }
    search.className = "inactive";
  }
  restoreInactive();
  bindEvent(search, 'focus', clearInactive);
  bindEvent(search, 'blur', restoreInactive);
}

/* Generates a table of contents: looks for h2 and h3 elements and generates
 * links.  "Decorates" the element with id=="nav" with this table of contents.
 */
function godocs_generateTOC() {
  if (document.getElementById('manual-nav')) { return; }
  var navbar = document.getElementById('nav');
  if (!navbar) { return; }

  var toc_items = [];

  var i;
  var seenNav = false;
  for (i = 0; i < navbar.parentNode.childNodes.length; i++) {
    var node = navbar.parentNode.childNodes[i];
    if (!seenNav) {
      if (node.id == 'nav') {
        seenNav = true;
      }
      continue;
    }
    if ((node.tagName != 'h2') && (node.tagName != 'H2') &&
        (node.tagName != 'h3') && (node.tagName != 'H3')) {
      continue;
    }
    if (!node.id) {
      node.id = 'tmp_' + i;
    }
    var text = godocs_nodeToText(node);
    if (!text) { continue; }

    var textNode = document.createTextNode(text);

    var link = document.createElement('a');
    link.href = '#' + node.id;
    link.appendChild(textNode);

    // Then create the item itself
    var item;
    if ((node.tagName == 'h2') || (node.tagName == 'H2')) {
      item = document.createElement('dt');
    } else { // h3
      item = document.createElement('dd');
    }

    item.appendChild(link);
    toc_items.push(item);
  }

  if (toc_items.length <= 1) { return; }

  var dl1 = document.createElement('dl');
  var dl2 = document.createElement('dl');

  var split_index = (toc_items.length / 2) + 1;
  if (split_index < 8) {
    split_index = toc_items.length;
  }

  for (i = 0; i < split_index; i++) {
    dl1.appendChild(toc_items[i]);
  }
  for (/* keep using i */; i < toc_items.length; i++) {
    dl2.appendChild(toc_items[i]);
  }

  var tocTable = document.createElement('table');
  navbar.appendChild(tocTable);
  tocTable.className = 'unruled';
  var tocBody = document.createElement('tbody');
  tocTable.appendChild(tocBody);

  var tocRow = document.createElement('tr');
  tocBody.appendChild(tocRow);

  // 1st column
  var tocCell = document.createElement('td');
  tocCell.className = 'first';
  tocRow.appendChild(tocCell);
  tocCell.appendChild(dl1);

  // 2nd column
  tocCell = document.createElement('td');
  tocRow.appendChild(tocCell);
  tocCell.appendChild(dl2);
}

/* Returns the "This sweet header" from
This sweet header
.
 * Takes a node, returns a string.
 */
function godocs_nodeToText(node) {
  var TEXT_NODE = 3; // Defined in Mozilla but not MSIE :(

  var text = '';
  for (var j = 0; j != node.childNodes.length; j++) {
    var child = node.childNodes[j];
    if (child.nodeType == TEXT_NODE) {
      if (child.nodeValue != '[Top]') { //ok, that's a hack, but it works.
        text = text + child.nodeValue;
      }
    } else {
      text = text + godocs_nodeToText(child);
    }
  }
  return text;
}

function godocs_bindExamples() {
  var examples = document.getElementsByClassName("example");
  for (var i = 0; i < examples.length; i++) {
    godocs_bindExampleToggle(examples[i]);
  }
  var links = document.getElementsByClassName("exampleLink");
  for (var i = 0; i < links.length; i++) {
    godocs_bindExampleLink(links[i]);
  }
}
function godocs_bindExampleToggle(eg) {
  var heading = eg.getElementsByClassName("exampleHeading");
  for (var i = 0; i < heading.length; i++) {
    bindEvent(heading[i], "click", function() {
      if (eg.className == "example") {
        eg.className = "exampleVisible";
      } else {
        eg.className = "example";
      }
    });
  }
}
function godocs_bindExampleLink(l) {
  var prefix = "example_";
  bindEvent(l, "click", function() {
    var i = l.href.indexOf("#"+prefix);
    if (i < 0)
      return;
    var id = prefix + l.href.slice(i+1+prefix.length);
    var eg = document.getElementById(id);
    eg.className = "exampleVisible";
  });
}
<commit_msg>doc/godoc.js: fix error on IE8.         * implement simple getElementsByClassName for IE8.         * remove some lint warnings.<commit_after>// Except as noted, this content is licensed under Creative Commons
// Attribution 3.0

/* A little code to ease navigation of these documents.
 *
 * On window load we:
 *  + Generate a table of contents (godocs_generateTOC)
 *  + Add links up to the top of the doc from each section (godocs_addTopLinks)
 */

/* We want to do some stuff on page load (after the HTML is rendered).
   So listen for that:
 */
function bindEvent(el, e, fn) {
  if (el.addEventListener){
    el.addEventListener(e, fn, false);
  } else if (el.attachEvent){
    el.attachEvent('on'+e, fn);
  }
}

function godocs_bindSearchEvents() {
  var search = document.getElementById('search');
  if (!search) {
    // no search box (index disabled)
    return;
  }
  function clearInactive() {
    if (search.className == "inactive") {
      search.value = "";
      search.className = "";
    }
  }
  function restoreInactive() {
    if (search.value !== "") {
      return;
    }
    if (search.type != "search") {
      search.value = search.getAttribute("placeholder");
    }
    search.className = "inactive";
  }
  restoreInactive();
  bindEvent(search, 'focus', clearInactive);
  bindEvent(search, 'blur', restoreInactive);
}

/* Returns the "This sweet header" from
This sweet header
.
 * Takes a node, returns a string.
 */
function godocs_nodeToText(node) {
  var TEXT_NODE = 3; // Defined in Mozilla but not MSIE :(

  var text = '';
  for (var j = 0; j != node.childNodes.length; j++) {
    var child = node.childNodes[j];
    if (child.nodeType == TEXT_NODE) {
      if (child.nodeValue != '[Top]') { //ok, that's a hack, but it works.
        text = text + child.nodeValue;
      }
    } else {
      text = text + godocs_nodeToText(child);
    }
  }
  return text;
}

/* Generates a table of contents: looks for h2 and h3 elements and generates
 * links.  "Decorates" the element with id=="nav" with this table of contents.
 */
function godocs_generateTOC() {
  if (document.getElementById('manual-nav')) { return; }
  var navbar = document.getElementById('nav');
  if (!navbar) { return; }

  var toc_items = [];

  var i;
  var seenNav = false;
  for (i = 0; i < navbar.parentNode.childNodes.length; i++) {
    var node = navbar.parentNode.childNodes[i];
    if (!seenNav) {
      if (node.id == 'nav') {
        seenNav = true;
      }
      continue;
    }
    if ((node.tagName != 'h2') && (node.tagName != 'H2') &&
        (node.tagName != 'h3') && (node.tagName != 'H3')) {
      continue;
    }
    if (!node.id) {
      node.id = 'tmp_' + i;
    }
    var text = godocs_nodeToText(node);
    if (!text) { continue; }

    var textNode = document.createTextNode(text);

    var link = document.createElement('a');
    link.href = '#' + node.id;
    link.appendChild(textNode);

    // Then create the item itself
    var item;
    if ((node.tagName == 'h2') || (node.tagName == 'H2')) {
      item = document.createElement('dt');
    } else { // h3
      item = document.createElement('dd');
    }

    item.appendChild(link);
    toc_items.push(item);
  }

  if (toc_items.length <= 1) { return; }

  var dl1 = document.createElement('dl');
  var dl2 = document.createElement('dl');

  var split_index = (toc_items.length / 2) + 1;
  if (split_index < 8) {
    split_index = toc_items.length;
  }

  for (i = 0; i < split_index; i++) {
    dl1.appendChild(toc_items[i]);
  }
  for (/* keep using i */; i < toc_items.length; i++) {
    dl2.appendChild(toc_items[i]);
  }

  var tocTable = document.createElement('table');
  navbar.appendChild(tocTable);
  tocTable.className = 'unruled';
  var tocBody = document.createElement('tbody');
  tocTable.appendChild(tocBody);

  var tocRow = document.createElement('tr');
  tocBody.appendChild(tocRow);

  // 1st column
  var tocCell = document.createElement('td');
  tocCell.className = 'first';
  tocRow.appendChild(tocCell);
  tocCell.appendChild(dl1);

  // 2nd column
  tocCell = document.createElement('td');
  tocRow.appendChild(tocCell);
  tocCell.appendChild(dl2);
}

function getElementsByClassName(base, clazz) {
  if (base.getElementsByClassName) {
    return base.getElementsByClassName(clazz);
  }
  var elements = base.getElementsByTagName('*'), foundElements = [];
  for (var n in elements) {
    if (clazz == elements[n].className) {
      foundElements.push(elements[n]);
    }
  }
  return foundElements;
}

function godocs_bindExampleToggle(eg) {
  var heading = getElementsByClassName(eg, "exampleHeading");
  var callback = function() {
    if (eg.className == "example") {
      eg.className = "exampleVisible";
    } else {
      eg.className = "example";
    }
  };
  for (var i = 0; i < heading.length; i++) {
    bindEvent(heading[i], "click", callback);
  }
}
function godocs_bindExampleLink(l) {
  var prefix = "example_";
  bindEvent(l, "click", function() {
    var i = l.href.indexOf("#"+prefix);
    if (i < 0) {
      return;
    }
    var id = prefix + l.href.slice(i+1+prefix.length);
    var eg = document.getElementById(id);
    eg.className = "exampleVisible";
  });
}
function godocs_bindExamples() {
  var examples = getElementsByClassName(document, "example");
  for (var i = 0; i < examples.length; i++) {
    godocs_bindExampleToggle(examples[i]);
  }
  var links = getElementsByClassName(document, "exampleLink");
  for (i = 0; i < links.length; i++) {
    godocs_bindExampleLink(links[i]);
  }
}

function godocs_onload() {
  godocs_bindSearchEvents();
  godocs_generateTOC();
  godocs_bindExamples();
}

bindEvent(window, 'load', godocs_onload);
<|endoftext|>


<commit_before>define(['jquery', 'base/js/utils'], function ($, utils) {
    function createDisplayDiv() {
        $('#maintoolbar-container').append(
            $('<div>').attr('id', 'nbresuse-display')
                      .addClass('btn-group')
                      .addClass('pull-right')
            .append(
                $('<strong>').text('Mem: ')
            ).append(
                $('<span>').attr('id', 'nbresuse-mem')
                           .attr('title', 'Actively used Memory (updates every 5s)')
            )
        );
    }

    var displayMetrics = function() {
        $.getJSON(utils.get_body_data('baseUrl') + 'metrics', function(data) {
            // FIXME: Proper setups for MB and GB. MB should have 0 things
            // after the ., but GB should have 2.
            var display = str((data['rss'] / (1024 * 1024)).toFixed(0)) + " MB";

            if (data['limits']['mem'] !== null) {
                display += " / " + (data['limits']['mem'] / (1024 * 1024));
            }
            $('#nbresuse-mem').text(display);
        });
    }

    var load_ipython_extension = function () {
        createDisplayDiv();
        displayMetrics();
        // Update every five seconds, eh?
        setInterval(displayMetrics, 1000 * 5);
    };

    return {
        load_ipython_extension: load_ipython_extension,
    };
});
<commit_msg>Fix Python in Javascript<commit_after>define(['jquery', 'base/js/utils'], function ($, utils) {
    function createDisplayDiv() {
        $('#maintoolbar-container').append(
            $('<div>').attr('id', 'nbresuse-display')
                      .addClass('btn-group')
                      .addClass('pull-right')
            .append(
                $('<strong>').text('Mem: ')
            ).append(
                $('<span>').attr('id', 'nbresuse-mem')
                           .attr('title', 'Actively used Memory (updates every 5s)')
            )
        );
    }

    var displayMetrics = function() {
        $.getJSON(utils.get_body_data('baseUrl') + 'metrics', function(data) {
            // FIXME: Proper setups for MB and GB. MB should have 0 things
            // after the ., but GB should have 2.
            var display = Math.round(data['rss'] / (1024 * 1024)) + " MB";

            if (data['limits']['memory'] !== null) {
                display += " / " + (data['limits']['memory'] / (1024 * 1024));
            }
            $('#nbresuse-mem').text(display);
        });
    }

    var load_ipython_extension = function () {
        createDisplayDiv();
        displayMetrics();
        // Update every five seconds, eh?
        setInterval(displayMetrics, 1000 * 5);
    };

    return {
        load_ipython_extension: load_ipython_extension,
    };
});
<|endoftext|>