<commit_before>"use strict";

var Config = {
  supportsHistory : !!(window.history && history.pushState),
  inMaintenanceMode : false,

  treeName: 'mozilla-central',
  hgBaseURL: "https://hg.mozilla.org/",
  hgURL: "https://hg.mozilla.org/mozilla-central/",
  hgRevURL: "https://hg.mozilla.org/mozilla-central/rev/",
  hgPushlogURL: "https://hg.mozilla.org/mozilla-central/pushloghtml?changeset=",
  showBugURL: "https://bugzilla.mozilla.org/show_bug.cgi?id=",

  // Here be dragons
  versionRE: /^mozilla\d+$/i,
  csetInputRE: /^(tip|[\da-f]{12,40})$/i,
  csetIDRE: /\b([\da-f]{12,40})\b/ig,
  leaveOpenRE: /(?:leave|keep)(?:-|\s+)open/i,
  bugNumRE: /\b(\d{4,7})\b/g,
  strictBugNumRE: /^(\d{4,7})$/,
  mergeRE: /\bmerg(ed?|ing)\b/i,
  backoutRE: /back(ing|ed)?\s*out/i,
  revertRE: /revert(ing)?/i,
  partialRevertRE: /(?:from|in)(?:\s+(?:rev(?:ision)?|c(?:hange)?set))?\s+([\da-f]{12,40})/i,
  partialTestRE: /test\s+for/i,
  revertRangeRE: /revert(?:ing)?\s+(?:\S+\s+)?to(?:\s+(?:rev(?:ision)?|c(?:hange)set))?\s+([\da-f]{12,40})/i,
  csetRangeRE: /\b([\da-f]{12,40})\s*(?:to|:|-|through)\s*([\da-f]{12,40})/i,
  hgRevRE: /https?:\/\/hg.mozilla.org\/mozilla-central\/rev\//ig,
  hgRevFullRE: /https?:\/\/hg.mozilla.org\/mozilla-central\/rev\/[\da-f]{12}/ig,
  hgPushlogRE: /https?:\/\/hg.mozilla.org\/mozilla-central\/pushloghtml\?changeset=/ig,
  emailRE: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i,   // I'm not looking for RFC 822 compliance here!

  // The many ways bug numbers are specified
  bugRE1: /b(?:ug)?=(\d{4,7})\b/i,                       // e.g. b=XXXXXX
  bugRE2: /^fix(?:es)?\s*(?:for\s*)?(\d{4,7})\b/i,                         // Fix is sometimes used as a synonym for bug
  bugRE3: /to\s+fix\s+bug\s+(\d{4,7})/i,
  bugRE4: /\((\d{4,7}), r=/i,                          // e.g. JS-team style (XXXXXX, r=foo)
  bugRE5: /but\s*(\d{4,7})/i,                          // The typo but XXXXXX happens quite often
  bugRE6: /\bb(?:u?g(?:zilla)?)?:?\s*#?(\d{4,7})\b/i,  // The catchall
  bugRE7: /^(\d{4,7})\b/i,                              // e.g. XXXXXX,

  repoMergeRE: "\\s+(&|and|with|<->|<>|-?->|(in|on)?to)\\s+",

  mcSynonyms: ["mozilla-central", "central", "m-c", "mc", "mozilla central"],

  rewriteTrees: {
    "thunderbird-trunk": "comm-central",
    "thunderbird-aurora": "comm-aurora",
    "thunderbird-beta": "comm-beta",
    "thunderbird-esr45": "comm-esr45",
    "thunderbird-esr38": "comm-esr38",
    "thunderbird-esr31": "comm-esr31",
  },

  treeInfo: {
    "mozilla-central": {
      repo: "mozilla-central",
      trackedTree: true,
      unconditionalFlag: false,
      synonyms: ["mozilla-central", "central", "m-c", "mc", "mozilla central"]
    },
    "b2g-inbound": {
      repo: "integration/b2g-inbound",
      trackedTree: false,
      unconditionalFlag: false,
      synonyms: ["b2g-inbound", "b-i", "bi"]
    },
    "mozilla-inbound": {
      repo: "integration/mozilla-inbound",
      trackedTree: false,
      unconditionalFlag: false,
      synonyms: ["mozilla-inbound", "inbound", "m-i", "mi"]
    },
    "mozilla-aurora": {
      repo: "releases/mozilla-aurora",
      trackedTree: true,
      unconditionalFlag: false,
      synonyms: ["releases/mozilla-aurora", "mozilla-aurora"]
    },
    "mozilla-beta": {
      repo: "releases/mozilla-beta",
      trackedTree: true,
      unconditionalFlag: false,
      synonyms: ["releases/mozilla-beta", "mozilla-beta"]
    },
    "mozilla-release": {
      repo: "releases/mozilla-release",
      trackedTree: true,
      unconditionalFlag: false,
      synonyms: ["releases/mozilla-release", "mozilla-release"]
    },
    "mozilla-esr31": {
      repo: "releases/mozilla-esr31",
      trackedTree: true,
      unconditionalFlag: false,
      synonyms: ["esr31", "releases/mozilla-esr31", "mozilla-esr31"]
    },
    "mozilla-esr38": {
      repo: "releases/mozilla-esr38",
      trackedTree: true,
      unconditionalFlag: false,
      synonyms: ["esr38", "releases/mozilla-esr38", "mozilla-esr38"]
    },
    "mozilla-esr45": {
      repo: "releases/mozilla-esr45",
      trackedTree: true,
      unconditionalFlag: false,
      synonyms: ["esr45", "releases/mozilla-esr45", "mozilla-esr45"]
    },
    "mozilla-b2g44_v2_5": {
      repo: "releases/mozilla-b2g44_v2_5",
      unconditionalFlag: true,
      trackedTree: true,
      synonyms: ["mozilla-b2g44_v2_5", "v2.5"]
    },
    "mozilla-b2g37_v2_2r": {
      repo: "releases/mozilla-b2g37_v2_2r",
      unconditionalFlag: true,
      trackedTree: true,
      synonyms: ["mozilla-b2g37_v2_2r", "v2.2r"]
    },
    "mozilla-b2g37_v2_2": {
      repo: "releases/mozilla-b2g37_v2_2",
      unconditionalFlag: true,
      trackedTree: true,
      synonyms: ["b2g37", "mozilla-b2g37", "mozilla-b2g37_v2_2", "v2.2"]
    },
    "jetpack": {
      repo: "projects/addon-sdk",
      trackedTree: false,
      unconditionalFlag: false,
      synonyms: ["projects/addon-sdk", "addon-sdk"]
    },
    "fx-team": {
      repo: "integration/fx-team",
      trackedTree: false,
      unconditionalFlag: false,
      synonyms: ["fx-team"]
    },
    "ux": {
      unconditionalFlag: false,
      repo: "projects/ux",
      synonyms: ["ux", "projects/ux"]
    },
    "alder": {
      repo: "projects/alder",
      unconditionalFlag: false,
      trackedTree: false,
      synonyms: ["alder", "projects/alder"]
    },
    "ash": {
      repo: "projects/ash",
      unconditionalFlag: false,
      trackedTree: false,
      synonyms: ["ash", "projects/ash"]
    },
    "cedar": {
      repo: "projects/cedar",
      unconditionalFlag: false,
      trackedTree: false,
      synonyms: ["projects/cedar", "cedar"]
    },
    "cypress": {
      repo: "projects/cypress",
      unconditionalFlag: false,
      trackedTree: false,
      synonyms: ["projects/cypress", "cypress"]
    },
    "date": {
      repo: "projects/date",
      unconditionalFlag: false,
      trackedTree: false,
      synonyms: ["projects/date", "date"]
    },
    "elm": {
      repo: "projects/elm",
      unconditionalFlag: false,
      trackedTree: false,
      synonyms: ["projects/elm", "elm"]
    },
    "fig": {
      repo: "projects/fig",
      unconditionalFlag: false,
      trackedTree: false,
      synonyms: ["projects/fig", "fig"]
    },
    "gum": {
      repo: "projects/gum",
      unconditionalFlag: false,
      trackedTree: false,
      synonyms: ["projects/gum", "gum"]
    },
    "holly": {
      repo: "projects/holly",
      unconditionalFlag: false,
      trackedTree: false,
      synonyms: ["projects/holly", "holly"]
    },
    "jamun": {
      repo: "projects/jamun",
      unconditionalFlag: false,
      trackedTree: false,
      synonyms: ["projects/jamun", "jamun"]
    },
    "larch": {
      repo: "projects/larch",
      unconditionalFlag: false,
      trackedTree: false,
      synonyms: ["projects/larch", "larch"]
    },
    "maple": {
      repo: "projects/maple",
      unconditionalFlag: false,
      trackedTree: false,
      synonyms: ["projects/maple", "maple"]
    },
    "oak": {
      repo: "projects/oak",
      unconditionalFlag: false,
      trackedTree: false,
      synonyms: ["projects/oak", "oak"]
    },
    "pine": {
      repo: "projects/pine",
      unconditionalFlag: false,
      trackedTree: false,
      synonyms: ["projects/pine", "pine"]
    },
    "comm-central": {
      repo: "comm-central",
      unconditionalFlag: false,
      trackedTree: true,
      synonyms: ["comm-central", "c-c"]
    },
    "comm-aurora": {
      repo: "releases/comm-aurora",
      unconditionalFlag: false,
      trackedTree: true,
      synonyms: ["releases/comm-aurora", "comm-aurora"]
    },
    "comm-beta": {
      repo: "releases/comm-beta",
      unconditionalFlag: false,
      trackedTree: true,
      synonyms: ["releases/comm-beta", "comm-beta"]
    },
    "comm-esr31": {
      repo: "releases/comm-esr31",
      unconditionalFlag: false,
      trackedTree: true,
      synonyms: ["releases/comm-esr31", "comm-esr31"]
    },
    "comm-esr38": {
      repo: "releases/comm-esr38",
      unconditionalFlag: false,
      trackedTree: true,
      synonyms: ["releases/comm-esr38", "comm-esr38"]
    },
    "comm-esr45": {
      repo: "releases/comm-esr45",
      unconditionalFlag: false,
      trackedTree: true,
      synonyms: ["releases/comm-esr45", "comm-esr45"]
    }
  }
};

Config.bugNumberREs = [Config.bugRE1, Config.bugRE2, Config.bugRE3,
                       Config.bugRE4, Config.bugRE5, Config.bugRE6, Config.bugRE7];

(function () {
  var base = Config.hgBaseURL;
  for (var treeName in Config.treeInfo) {
    var repo = Config.treeInfo[treeName].repo;
    Config.treeInfo[treeName]['hgURL'] = base + repo + '/';
    Config.treeInfo[treeName]['hgRevURL'] = base + repo + '/rev/';
    Config.treeInfo[treeName]['hgPushlogURL'] = base + repo + '/pushloghtml?changeset=';
    Config.treeInfo[treeName]['hgRevRE'] = new RegExp('https?:\/\/hg.mozilla.org\/' + repo + '\/rev\/', 'ig');
    Config.treeInfo[treeName]['hgRevFullRE'] = new RegExp('https?:\/\/hg.mozilla.org\/' + repo + '\/rev\/[\\da-f]{12}', 'ig');
    Config.treeInfo[treeName]['hgPushlogRE'] = new RegExp('https?:\/\/hg.mozilla.org\/' + repo + '\/pushloghtml\\?changeset=', 'ig');
  }
})();

// Detect input type="email" support
$(document).ready(function() {
  Config.needsValidation = $('#username').prop('type') != 'email';
});
<commit_msg>Bug 1332293 - Update Bugherder's known trees (#47)<commit_after>"use strict";

var Config = {
  supportsHistory : !!(window.history && history.pushState),
  inMaintenanceMode : false,

  treeName: 'mozilla-central',
  hgBaseURL: "https://hg.mozilla.org/",
  hgURL: "https://hg.mozilla.org/mozilla-central/",
  hgRevURL: "https://hg.mozilla.org/mozilla-central/rev/",
  hgPushlogURL: "https://hg.mozilla.org/mozilla-central/pushloghtml?changeset=",
  showBugURL: "https://bugzilla.mozilla.org/show_bug.cgi?id=",

  // Here be dragons
  versionRE: /^mozilla\d+$/i,
  csetInputRE: /^(tip|[\da-f]{12,40})$/i,
  csetIDRE: /\b([\da-f]{12,40})\b/ig,
  leaveOpenRE: /(?:leave|keep)(?:-|\s+)open/i,
  bugNumRE: /\b(\d{4,7})\b/g,
  strictBugNumRE: /^(\d{4,7})$/,
  mergeRE: /\bmerg(ed?|ing)\b/i,
  backoutRE: /back(ing|ed)?\s*out/i,
  revertRE: /revert(ing)?/i,
  partialRevertRE: /(?:from|in)(?:\s+(?:rev(?:ision)?|c(?:hange)?set))?\s+([\da-f]{12,40})/i,
  partialTestRE: /test\s+for/i,
  revertRangeRE: /revert(?:ing)?\s+(?:\S+\s+)?to(?:\s+(?:rev(?:ision)?|c(?:hange)set))?\s+([\da-f]{12,40})/i,
  csetRangeRE: /\b([\da-f]{12,40})\s*(?:to|:|-|through)\s*([\da-f]{12,40})/i,
  hgRevRE: /https?:\/\/hg.mozilla.org\/mozilla-central\/rev\//ig,
  hgRevFullRE: /https?:\/\/hg.mozilla.org\/mozilla-central\/rev\/[\da-f]{12}/ig,
  hgPushlogRE: /https?:\/\/hg.mozilla.org\/mozilla-central\/pushloghtml\?changeset=/ig,
  emailRE: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i,   // I'm not looking for RFC 822 compliance here!

  // The many ways bug numbers are specified
  bugRE1: /b(?:ug)?=(\d{4,7})\b/i,                       // e.g. b=XXXXXX
  bugRE2: /^fix(?:es)?\s*(?:for\s*)?(\d{4,7})\b/i,                         // Fix is sometimes used as a synonym for bug
  bugRE3: /to\s+fix\s+bug\s+(\d{4,7})/i,
  bugRE4: /\((\d{4,7}), r=/i,                          // e.g. JS-team style (XXXXXX, r=foo)
  bugRE5: /but\s*(\d{4,7})/i,                          // The typo but XXXXXX happens quite often
  bugRE6: /\bb(?:u?g(?:zilla)?)?:?\s*#?(\d{4,7})\b/i,  // The catchall
  bugRE7: /^(\d{4,7})\b/i,                              // e.g. XXXXXX,

  repoMergeRE: "\\s+(&|and|with|<->|<>|-?->|(in|on)?to)\\s+",

  mcSynonyms: ["mozilla-central", "central", "m-c", "mc", "mozilla central"],

  rewriteTrees: {
    "thunderbird-trunk": "comm-central",
    "thunderbird-aurora": "comm-aurora",
    "thunderbird-beta": "comm-beta",
    "thunderbird-esr52": "comm-esr52",
    "thunderbird-esr45": "comm-esr45",
  },

  treeInfo: {
    "mozilla-central": {
      repo: "mozilla-central",
      trackedTree: true,
      unconditionalFlag: false,
      synonyms: ["mozilla-central", "central", "m-c", "mc", "mozilla central"]
    },
    "mozilla-inbound": {
      repo: "integration/mozilla-inbound",
      trackedTree: false,
      unconditionalFlag: false,
      synonyms: ["mozilla-inbound", "inbound", "m-i", "mi"]
    },
    "autoland": {
      repo: "integration/autoland",
      trackedTree: false,
      unconditionalFlag: false,
      synonyms: ["autoland"]
    },
    "mozilla-aurora": {
      repo: "releases/mozilla-aurora",
      trackedTree: true,
      unconditionalFlag: false,
      synonyms: ["releases/mozilla-aurora", "mozilla-aurora"]
    },
    "mozilla-beta": {
      repo: "releases/mozilla-beta",
      trackedTree: true,
      unconditionalFlag: false,
      synonyms: ["releases/mozilla-beta", "mozilla-beta"]
    },
    "mozilla-release": {
      repo: "releases/mozilla-release",
      trackedTree: true,
      unconditionalFlag: false,
      synonyms: ["releases/mozilla-release", "mozilla-release"]
    },
    "mozilla-esr52": {
      repo: "releases/mozilla-esr52",
      trackedTree: true,
      unconditionalFlag: false,
      synonyms: ["esr52", "releases/mozilla-esr52", "mozilla-esr52"]
    },
    "mozilla-esr45": {
      repo: "releases/mozilla-esr45",
      trackedTree: true,
      unconditionalFlag: false,
      synonyms: ["esr45", "releases/mozilla-esr45", "mozilla-esr45"]
    },
    "ux": {
      unconditionalFlag: false,
      repo: "projects/ux",
      synonyms: ["ux", "projects/ux"]
    },
    "alder": {
      repo: "projects/alder",
      unconditionalFlag: false,
      trackedTree: false,
      synonyms: ["alder", "projects/alder"]
    },
    "ash": {
      repo: "projects/ash",
      unconditionalFlag: false,
      trackedTree: false,
      synonyms: ["ash", "projects/ash"]
    },
    "cedar": {
      repo: "projects/cedar",
      unconditionalFlag: false,
      trackedTree: false,
      synonyms: ["projects/cedar", "cedar"]
    },
    "cypress": {
      repo: "projects/cypress",
      unconditionalFlag: false,
      trackedTree: false,
      synonyms: ["projects/cypress", "cypress"]
    },
    "date": {
      repo: "projects/date",
      unconditionalFlag: false,
      trackedTree: false,
      synonyms: ["projects/date", "date"]
    },
    "elm": {
      repo: "projects/elm",
      unconditionalFlag: false,
      trackedTree: false,
      synonyms: ["projects/elm", "elm"]
    },
    "fig": {
      repo: "projects/fig",
      unconditionalFlag: false,
      trackedTree: false,
      synonyms: ["projects/fig", "fig"]
    },
    "gum": {
      repo: "projects/gum",
      unconditionalFlag: false,
      trackedTree: false,
      synonyms: ["projects/gum", "gum"]
    },
    "holly": {
      repo: "projects/holly",
      unconditionalFlag: false,
      trackedTree: false,
      synonyms: ["projects/holly", "holly"]
    },
    "jamun": {
      repo: "projects/jamun",
      unconditionalFlag: false,
      trackedTree: false,
      synonyms: ["projects/jamun", "jamun"]
    },
    "larch": {
      repo: "projects/larch",
      unconditionalFlag: false,
      trackedTree: false,
      synonyms: ["projects/larch", "larch"]
    },
    "maple": {
      repo: "projects/maple",
      unconditionalFlag: false,
      trackedTree: false,
      synonyms: ["projects/maple", "maple"]
    },
    "oak": {
      repo: "projects/oak",
      unconditionalFlag: false,
      trackedTree: false,
      synonyms: ["projects/oak", "oak"]
    },
    "pine": {
      repo: "projects/pine",
      unconditionalFlag: false,
      trackedTree: false,
      synonyms: ["projects/pine", "pine"]
    },
    "comm-central": {
      repo: "comm-central",
      unconditionalFlag: false,
      trackedTree: true,
      synonyms: ["comm-central", "c-c"]
    },
    "comm-aurora": {
      repo: "releases/comm-aurora",
      unconditionalFlag: false,
      trackedTree: true,
      synonyms: ["releases/comm-aurora", "comm-aurora"]
    },
    "comm-beta": {
      repo: "releases/comm-beta",
      unconditionalFlag: false,
      trackedTree: true,
      synonyms: ["releases/comm-beta", "comm-beta"]
    },
    "comm-esr52": {
      repo: "releases/comm-esr52",
      unconditionalFlag: false,
      trackedTree: true,
      synonyms: ["releases/comm-esr52", "comm-esr52"]
    },
    "comm-esr45": {
      repo: "releases/comm-esr45",
      unconditionalFlag: false,
      trackedTree: true,
      synonyms: ["releases/comm-esr45", "comm-esr45"]
    }
  }
};

Config.bugNumberREs = [Config.bugRE1, Config.bugRE2, Config.bugRE3,
                       Config.bugRE4, Config.bugRE5, Config.bugRE6, Config.bugRE7];

(function () {
  var base = Config.hgBaseURL;
  for (var treeName in Config.treeInfo) {
    var repo = Config.treeInfo[treeName].repo;
    Config.treeInfo[treeName]['hgURL'] = base + repo + '/';
    Config.treeInfo[treeName]['hgRevURL'] = base + repo + '/rev/';
    Config.treeInfo[treeName]['hgPushlogURL'] = base + repo + '/pushloghtml?changeset=';
    Config.treeInfo[treeName]['hgRevRE'] = new RegExp('https?:\/\/hg.mozilla.org\/' + repo + '\/rev\/', 'ig');
    Config.treeInfo[treeName]['hgRevFullRE'] = new RegExp('https?:\/\/hg.mozilla.org\/' + repo + '\/rev\/[\\da-f]{12}', 'ig');
    Config.treeInfo[treeName]['hgPushlogRE'] = new RegExp('https?:\/\/hg.mozilla.org\/' + repo + '\/pushloghtml\\?changeset=', 'ig');
  }
})();

// Detect input type="email" support
$(document).ready(function() {
  Config.needsValidation = $('#username').prop('type') != 'email';
});
<|endoftext|>


<commit_before>//
// Copyright (c) 2016-2017 DrSmugleaf
//

"use strict"
const constants = require("../../util/constants")
const commando = require("discord.js-commando")
const parse = require("parse-color")
const winston = require("winston")

module.exports = class Color extends commando.Command {
  constructor(client) {
    super(client, {
      name: "color",
      aliases: ["color", "colour"],
      group: "user",
      memberName: "color",
      description: "Change your name color in this server.",
      examples: ["color red", "color #FF0000"],
      guildOnly: true,
      throttling: {
        usages: 2,
        duration: 3
      },
      args: [
        {
          key: "color",
          prompt: "What color do you want?",
          type: "string",
          default: "",
          validate: (color) => {
            color = color.toLowerCase().replace(/ |-|'|\/|/g, "")
            return Boolean(constants.colors.hasOwnProperty(color) ||
              parse(color).hex || color === "")
          }
        }
      ]
    })

    this.roleName = (userid) => `color-${userid}`
  }

  parseColor(color) {
    if(constants.colors.hasOwnProperty(color)) return constants.colors[color]
    return parse(color).hex
  }

  addColor(msg, color) {
    const existingRole = msg.member.roles.find("name", this.roleName(msg.member.id))

    if(existingRole) {
      existingRole.edit({ color: color }).then(() => {
        return msg.reply(constants.responses.COLOR.ADDED[msg.language](msg.argString))
      }).catch(winston.error)
    }

    msg.guild.createRole({
      name: this.roleName(msg.member.id),
      color: color,
      permissions: []
    }).then(role => {
      msg.member.addRole(role.id)
      return msg.reply(constants.responses.COLOR.ADDED[msg.language](msg.argString))
    }).catch(winston.error)
  }

  removeColor(msg) {
    const role = msg.member.roles.find("name", this.roleName(msg.member.id))

    if(role) {
      role.delete().then(() => {
        return msg.reply(constants.responses.COLOR.REMOVED[msg.language])
      })
    } else {
      return msg.reply(constants.responses.COLOR.MISSING[msg.language])
    }
  }

  async run(msg, args) {
    if(!msg.channel.permissionsFor(msg.client.user).hasPermission("MANAGE_ROLES_OR_PERMISSIONS")) {
      return msg.reply(constants.responses.COLOR.NO_PERMISSION[msg.language])
    }
    const color = args.color ? this.parseColor(args.color.toLowerCase().replace(/ |-|'|\/|/g, "")) : null

    if(!color) {
      return this.removeColor(msg, color)
    } else {
      return this.addColor(msg, color)
    }
  }
}
<commit_msg>Added removing unused color roles on startup<commit_after>//
// Copyright (c) 2016-2017 DrSmugleaf
//

"use strict"
const constants = require("../../util/constants")
const commando = require("discord.js-commando")
const parse = require("parse-color")
const winston = require("winston")

module.exports = class Color extends commando.Command {
  constructor(client) {
    super(client, {
      name: "color",
      aliases: ["color", "colour"],
      group: "user",
      memberName: "color",
      description: "Change your name color in this server.",
      examples: ["color red", "color #FF0000"],
      guildOnly: true,
      throttling: {
        usages: 2,
        duration: 3
      },
      args: [
        {
          key: "color",
          prompt: "What color do you want?",
          type: "string",
          default: "",
          validate: (color) => {
            color = color.toLowerCase().replace(/ |-|'|\/|/g, "")
            return Boolean(constants.colors.hasOwnProperty(color) ||
              parse(color).hex || color === "")
          }
        }
      ]
    })

    this.roleName = (userid) => `color-${userid}`

    this.client.once("dbReady", () => {
      this.client.guilds.forEach((guild) => {
        if(!guild.member(guild.client.user).hasPermission("MANAGE_ROLES_OR_PERMISSIONS")) return
        const roles = guild.roles.filter((role) => {
          return role.name.includes("color-") && role.members.size < 1
        })
        Promise.all(roles.deleteAll()).catch(() => { return })
      })
    })
  }

  parseColor(color) {
    if(constants.colors.hasOwnProperty(color)) return constants.colors[color]
    return parse(color).hex
  }

  addColor(msg, color) {
    const existingRole = msg.member.roles.find("name", this.roleName(msg.member.id))

    if(existingRole) {
      existingRole.edit({ color: color }).then(() => {
        return msg.reply(constants.responses.COLOR.ADDED[msg.language](msg.argString))
      }).catch(winston.error)
    }

    msg.guild.createRole({
      name: this.roleName(msg.member.id),
      color: color,
      permissions: []
    }).then(role => {
      msg.member.addRole(role.id)
      return msg.reply(constants.responses.COLOR.ADDED[msg.language](msg.argString))
    }).catch(winston.error)
  }

  removeColor(msg) {
    const role = msg.member.roles.find("name", this.roleName(msg.member.id))

    if(role) {
      role.delete().then(() => {
        return msg.reply(constants.responses.COLOR.REMOVED[msg.language])
      })
    } else {
      return msg.reply(constants.responses.COLOR.MISSING[msg.language])
    }
  }

  async run(msg, args) {
    if(!msg.channel.permissionsFor(msg.client.user).hasPermission("MANAGE_ROLES_OR_PERMISSIONS")) {
      return msg.reply(constants.responses.COLOR.NO_PERMISSION[msg.language])
    }
    const color = args.color ? this.parseColor(args.color.toLowerCase().replace(/ |-|'|\/|/g, "")) : null

    if(!color) {
      return this.removeColor(msg, color)
    } else {
      return this.addColor(msg, color)
    }
  }
}
<|endoftext|>


<commit_before>/**
 * @copyright  Copyright(c) 2011 Ajax.org B.V. <info AT ajax.org>
 * @author Fabian Jakobs <fabian AT ajax DOT org>
 * @author Mike de Boer <mike AT ajax DOT org>
 * @license http://github.com/ajaxorg/node-sftp/blob/master/LICENSE MIT License
 */

"use strict";

var child_process = require("child_process");
var fs = require("fs");
var tmp = require("tmp");
var debug = require("debug")("ssh");

exports.buildArgs = function(prvkeyFile, host) {
    var args = [
        "-o", "PasswordAuthentication=no",
        "-o", "IdentityFile=" + prvkeyFile,
        "-o", "UserKnownHostsFile=/dev/null",
        "-o", "StrictHostKeyChecking=no",
        "-o", "IdentitiesOnly=yes",
        "-F", "/dev/null", // use empty config file to not depend on local settings
        // force pseudo terminal to make sure that the remote process is killed
        // when the local ssh process is killed
        "-t", "-t",
        "-o", "BatchMode=yes",
        "-o", "ConnectTimeout=10" // default timeout is 2 minutes, which is quite long
    ];

    if (host) {
        host = host.split(":");
        args.push("-p", host[1] || 22);
        args.push(host[0]);
    }

    return args;
};

exports.spawnWithKeyFile = function(prvkeyFile, host, command, args) {
    var sshArgs = exports.buildArgs(prvkeyFile, host);

    args = sshArgs.concat(command ? [command] : []).concat(args || []);
    debug("executing: ssh " + args.join(" "));

    return child_process.spawn("ssh", args);
};

exports.writeKeyFile = function(prvkey, callback) {
    tmp.tmpName(function(err, filename) {
        if (err) return callback(err);

        fs.writeFile(filename, prvkey, function(err) {
            if (err) return callback(err);

            fs.chmod(filename, "0600", function(err) {
                callback(err, filename);
            });
        });
    });
};

exports.writeKeyFiles = function(prvkey, pubkey, callback) {
    tmp.tmpName(function(err, filename) {
        if (err) return callback(err);

        fs.writeFile(filename, prvkey, function(err) {
            if (err) return callback(err);

            fs.chmod(filename, "0600", function(err) {
                if (err) return callback(err);

                fs.writeFile(filename + ".pub", pubkey, function(err) {
                    if (err) return callback(err);

                    fs.chmod(filename + ".pub", "0600", function(err) {
                        callback(err, filename);
                    });
                });
            });
        });
    });
};

exports.spawn = function(prvkey, host, command, args, callback) {
    exports.writeKeyFile(prvkey, function(err, filename) {
        if (err) return callback(err);

        var child = exports.spawnWithKeyFile(filename, host, command, args);

        child.on("exit", function(code) {
            fs.unlink(filename, function() {});
        });

        callback(null, child);
    });
};

exports.exec = function(prvkey, host, command, args, callback) {
    exports.spawn(prvkey, host, command, args, function(err, child) {
        if (err)
            return callback(err);

        var out = err = "";

        child.stdout.on("data", function (data) {
            out += data;
        });

        child.stderr.on("data", function (data) {
            err += data;
        });

        child.on("exit", function(code) {
            callback(code, out, err);
        });
    });
};

exports.generateKeyPair = function(email, callback) {
    tmp.tmpName(function(err, filename) {
        if (err) return callback(err);

        var phrase = "";

        var command = "ssh-keygen -t rsa " +
            "-f \"" + filename + "\" " +
            "-P \"" + phrase   + "\" " +
            "-C \"" + email  + "\" ";

        child_process.exec(command, function (err, stdout, stderr) {
            if (err) return callback(err);

            fs.readFile(filename + ".pub", function (err, pubkey) {
                if (err) return callback(err);

                fs.readFile(filename, function (err, prvkey) {
                    if (err) return callback(err);

                    fs.unlink(filename + ".pub", function() {
                        fs.unlink(filename, function() {
                            callback(null, pubkey.toString(), prvkey.toString());
                        });
                    });
                });
            });
        });
    });
};

exports.validateSSHKey = function(prvkey, host, callback) {
    exports.exec(prvkey, host, "", [], function(err, stdout, stderr) {
        debug("out >> " + stdout);
        debug("err >> " + stderr);
        debug(err);
        callback(null, !stderr.match(/Permission denied \(.*publickey/));
    });
};
<commit_msg>Revert "Use open for repos"<commit_after>/**
 * @copyright  Copyright(c) 2011 Ajax.org B.V. <info AT ajax.org>
 * @author Fabian Jakobs <fabian AT ajax DOT org>
 * @author Mike de Boer <mike AT ajax DOT org>
 * @license http://github.com/ajaxorg/node-sftp/blob/master/LICENSE MIT License
 */

"use strict";

var child_process = require("child_process");
var fs = require("fs");
var tmp = require("tmp");
var debug = require("debug")("ssh");

exports.buildArgs = function(prvkeyFile, host) {
    var args = [
        "-o", "PasswordAuthentication=no",
        "-o", "IdentityFile=" + prvkeyFile,
        "-o", "UserKnownHostsFile=/dev/null",
        "-o", "StrictHostKeyChecking=no",
        "-F", "/dev/null", // use empty config file to not depend on local settings
        // force pseudo terminal to make sure that the remote process is killed
        // when the local ssh process is killed
        "-t", "-t",
        "-o", "BatchMode=yes",
        "-o", "ConnectTimeout=10" // default timeout is 2 minutes, which is quite long
    ];

    if (host) {
        host = host.split(":");
        args.push("-p", host[1] || 22);
        args.push(host[0]);
    }

    return args;
};

exports.spawnWithKeyFile = function(prvkeyFile, host, command, args) {
    var sshArgs = exports.buildArgs(prvkeyFile, host);

    args = sshArgs.concat(command ? [command] : []).concat(args || []);
    debug("executing: ssh " + args.join(" "));

    return child_process.spawn("ssh", args);
};

exports.writeKeyFile = function(prvkey, callback) {
    tmp.tmpName(function(err, filename) {
        if (err) return callback(err);

        fs.writeFile(filename, prvkey, function(err) {
            if (err) return callback(err);

            fs.chmod(filename, "0600", function(err) {
                callback(err, filename);
            });
        });
    });
};

exports.writeKeyFiles = function(prvkey, pubkey, callback) {
    tmp.tmpName(function(err, filename) {
        if (err) return callback(err);

        fs.writeFile(filename, prvkey, function(err) {
            if (err) return callback(err);

            fs.chmod(filename, "0600", function(err) {
                if (err) return callback(err);

                fs.writeFile(filename + ".pub", pubkey, function(err) {
                    if (err) return callback(err);

                    fs.chmod(filename + ".pub", "0600", function(err) {
                        callback(err, filename);
                    });
                });
            });
        });
    });
};

exports.spawn = function(prvkey, host, command, args, callback) {
    exports.writeKeyFile(prvkey, function(err, filename) {
        if (err) return callback(err);

        var child = exports.spawnWithKeyFile(filename, host, command, args);

        child.on("exit", function(code) {
            fs.unlink(filename, function() {});
        });

        callback(null, child);
    });
};

exports.exec = function(prvkey, host, command, args, callback) {
    exports.spawn(prvkey, host, command, args, function(err, child) {
        if (err)
            return callback(err);

        var out = err = "";

        child.stdout.on("data", function (data) {
            out += data;
        });

        child.stderr.on("data", function (data) {
            err += data;
        });

        child.on("exit", function(code) {
            callback(code, out, err);
        });
    });
};

exports.generateKeyPair = function(email, callback) {
    tmp.tmpName(function(err, filename) {
        if (err) return callback(err);

        var phrase = "";

        var command = "ssh-keygen -t rsa " +
            "-f \"" + filename + "\" " +
            "-P \"" + phrase   + "\" " +
            "-C \"" + email  + "\" ";

        child_process.exec(command, function (err, stdout, stderr) {
            if (err) return callback(err);

            fs.readFile(filename + ".pub", function (err, pubkey) {
                if (err) return callback(err);

                fs.readFile(filename, function (err, prvkey) {
                    if (err) return callback(err);

                    fs.unlink(filename + ".pub", function() {
                        fs.unlink(filename, function() {
                            callback(null, pubkey.toString(), prvkey.toString());
                        });
                    });
                });
            });
        });
    });
};

exports.validateSSHKey = function(prvkey, host, callback) {
    exports.exec(prvkey, host, "", [], function(err, stdout, stderr) {
        // console.log("out >> " + stdout);
        // console.log("err >> " + stderr);
        // console.log(err);
        callback(null, !stderr.match(/Permission denied \(.*publickey/));
    });
};
<|endoftext|>


<commit_before>steal("./mustache_core.js", "steal-qunit", function(){

	var mustacheCore = can.view.mustacheCore;
	QUnit.module("can/view/stache/mustache_core");

	test("expressionData with sub-expressions", function(){
		var exprData = mustacheCore.expressionData("{{helperA (helperB 1 valueA propA=valueB propC=2) 'def' nested.prop outerPropA=(helperC 2 valueB)}}");

		var oneExpr = new mustacheCore.Expression(1),
			twoExpr = new mustacheCore.Expression(2),
			def = new mustacheCore.Expression('def'),

			valueA = new mustacheCore.ScopeExpression("valueA"),
			valueB = new mustacheCore.ScopeExpression("valueB"),
			nested = new mustacheCore.ScopeExpression("nested.prop"),

			helperA = new mustacheCore.ScopeExpression("helperA"),
			helperB = new mustacheCore.ScopeExpression("helperB"),
			helperC = new mustacheCore.ScopeExpression("helperC");

		var callHelperB = new mustacheCore.MethodExpression(
			helperB,
			[oneExpr, valueA],
			{
				propA: valueB,
				propC: twoExpr
			}
		);
		var callHelperC = new mustacheCore.MethodExpression(
			helperC,
			[twoExpr, valueB],
			{}
		);

		var callHelperA = new mustacheCore.MethodExpression(
			helperA,
			[callHelperB, def, nested],
			{
				outerPropA: callHelperC
			}
		);

		deepEqual( exprData, callHelperA);

	});

	test("numeric expressions", function(){
		var exprData = mustacheCore.expressionData("{{3}}");

		var result = new mustacheCore.MethodExpression(
			new mustacheCore.ScopeExpression("3"),
			[],
			{}
		);
		deepEqual( exprData, result);

	});

	test("MethodExpression.value non-observable values", function(){
		// {{fullName 'marshall' 'thompson'}}

		var scope = new can.view.Scope({
			fullName: function(first, last){
				return first+" "+last;
			}
		});

		var callFullName = new mustacheCore.MethodExpression(
			new mustacheCore.ScopeExpression("fullName"),
			[new mustacheCore.Expression('marshall'), new mustacheCore.Expression('thompson')],
			{}
		);

		var result = callFullName.value(scope, new can.view.Scope({}),  {});

		equal(result, "marshall thompson");
	});

	test("MethodExpression.value observable values", function(){
		// {{fullName first 'thompson'}}

		var scope = new can.view.Scope({
			fullName: function(first, last){
				return first()+" "+last;
			},
			first: can.compute("marshall")
		});

		var callFullName = new mustacheCore.MethodExpression(
			new mustacheCore.ScopeExpression("fullName"),
			[new mustacheCore.ScopeExpression("first"), new mustacheCore.Expression('thompson')],
			{}
		);

		var result = callFullName.value(scope, new can.view.Scope({}), {asCompute: true});

		equal(result(), "marshall thompson");
	});

	test("methods can return values (#1887)", function(){
		var MyMap = can.Map.extend({
			getSomething: function(arg){
				return this.attr("foo") + arg()
			}
		});

		var scope =
			new can.view.Scope(new MyMap({foo: 2, bar: 3}))
				.add({});

		var callGetSomething = new mustacheCore.MethodExpression(
			new mustacheCore.ScopeExpression("getSomething"),
			[new mustacheCore.ScopeExpression("bar")],
			{}
		);

		var result = callGetSomething.value(scope, new can.view.Scope({}), {asCompute: true});

		equal(result(), 5);
	});

});
<commit_msg>jshinting<commit_after>steal("./mustache_core.js", "steal-qunit", function(){

	var mustacheCore = can.view.mustacheCore;
	QUnit.module("can/view/stache/mustache_core");

	test("expressionData with sub-expressions", function(){
		var exprData = mustacheCore.expressionData("{{helperA (helperB 1 valueA propA=valueB propC=2) 'def' nested.prop outerPropA=(helperC 2 valueB)}}");

		var oneExpr = new mustacheCore.Expression(1),
			twoExpr = new mustacheCore.Expression(2),
			def = new mustacheCore.Expression('def'),

			valueA = new mustacheCore.ScopeExpression("valueA"),
			valueB = new mustacheCore.ScopeExpression("valueB"),
			nested = new mustacheCore.ScopeExpression("nested.prop"),

			helperA = new mustacheCore.ScopeExpression("helperA"),
			helperB = new mustacheCore.ScopeExpression("helperB"),
			helperC = new mustacheCore.ScopeExpression("helperC");

		var callHelperB = new mustacheCore.MethodExpression(
			helperB,
			[oneExpr, valueA],
			{
				propA: valueB,
				propC: twoExpr
			}
		);
		var callHelperC = new mustacheCore.MethodExpression(
			helperC,
			[twoExpr, valueB],
			{}
		);

		var callHelperA = new mustacheCore.MethodExpression(
			helperA,
			[callHelperB, def, nested],
			{
				outerPropA: callHelperC
			}
		);

		deepEqual( exprData, callHelperA);

	});

	test("numeric expressions", function(){
		var exprData = mustacheCore.expressionData("{{3}}");

		var result = new mustacheCore.MethodExpression(
			new mustacheCore.ScopeExpression("3"),
			[],
			{}
		);
		deepEqual( exprData, result);

	});

	test("MethodExpression.value non-observable values", function(){
		// {{fullName 'marshall' 'thompson'}}

		var scope = new can.view.Scope({
			fullName: function(first, last){
				return first+" "+last;
			}
		});

		var callFullName = new mustacheCore.MethodExpression(
			new mustacheCore.ScopeExpression("fullName"),
			[new mustacheCore.Expression('marshall'), new mustacheCore.Expression('thompson')],
			{}
		);

		var result = callFullName.value(scope, new can.view.Scope({}),  {});

		equal(result, "marshall thompson");
	});

	test("MethodExpression.value observable values", function(){
		// {{fullName first 'thompson'}}

		var scope = new can.view.Scope({
			fullName: function(first, last){
				return first()+" "+last;
			},
			first: can.compute("marshall")
		});

		var callFullName = new mustacheCore.MethodExpression(
			new mustacheCore.ScopeExpression("fullName"),
			[new mustacheCore.ScopeExpression("first"), new mustacheCore.Expression('thompson')],
			{}
		);

		var result = callFullName.value(scope, new can.view.Scope({}), {asCompute: true});

		equal(result(), "marshall thompson");
	});

	test("methods can return values (#1887)", function(){
		var MyMap = can.Map.extend({
			getSomething: function(arg){
				return this.attr("foo") + arg();
			}
		});

		var scope =
			new can.view.Scope(new MyMap({foo: 2, bar: 3}))
				.add({});

		var callGetSomething = new mustacheCore.MethodExpression(
			new mustacheCore.ScopeExpression("getSomething"),
			[new mustacheCore.ScopeExpression("bar")],
			{}
		);

		var result = callGetSomething.value(scope, new can.view.Scope({}), {asCompute: true});

		equal(result(), 5);
	});

});
<|endoftext|>


<commit_before>goog.provide('ol.control.ScaleLine');
goog.provide('ol.control.ScaleLineProperty');
goog.provide('ol.control.ScaleLineUnits');

goog.require('goog.asserts');
goog.require('goog.dom');
goog.require('goog.dom.TagName');
goog.require('goog.events');
goog.require('goog.math');
goog.require('goog.style');
goog.require('ol.Object');
goog.require('ol.TransformFunction');
goog.require('ol.control.Control');
goog.require('ol.css');
goog.require('ol.proj');
goog.require('ol.proj.METERS_PER_UNIT');
goog.require('ol.proj.Units');
goog.require('ol.sphere.NORMAL');

/**
 * @enum {string}
 */
ol.control.ScaleLineProperty = {
  UNITS: 'units'
};

/**
 * Units for the scale line. Supported values are `'degrees'`, `'imperial'`,
 * `'nautical'`, `'metric'`, `'us'`.
 * @enum {string}
 * @api stable
 */
ol.control.ScaleLineUnits = {
  DEGREES: 'degrees',
  IMPERIAL: 'imperial',
  NAUTICAL: 'nautical',
  METRIC: 'metric',
  US: 'us'
};

/**
 * @classdesc
 * A control displaying rough x-axis distances, calculated for the center of the
 * viewport.
 * No scale line will be shown when the x-axis distance cannot be calculated in
 * the view projection (e.g. at or beyond the poles in EPSG:4326).
 * By default the scale line will show in the bottom left portion of the map,
 * but this can be changed by using the css selector `.ol-scale-line`.
 *
 * @constructor
 * @extends {ol.control.Control}
 * @param {olx.control.ScaleLineOptions=} opt_options Scale line options.
 * @api stable
 */
ol.control.ScaleLine = function(opt_options) {

  var options = goog.isDef(opt_options) ? opt_options : {};

  var className = goog.isDef(options.className) ?
      options.className : 'ol-scale-line';

  /**
   * @private
   * @type {Element}
   */
  this.innerElement_ = goog.dom.createDom(goog.dom.TagName.DIV,
      className + '-inner');

  /**
   * @private
   * @type {Element}
   */
  this.element_ = goog.dom.createDom(goog.dom.TagName.DIV,
      className + ' ' + ol.css.CLASS_UNSELECTABLE, this.innerElement_);

  /**
   * @private
   * @type {?olx.ViewState}
   */
  this.viewState_ = null;

  /**
   * @private
   * @type {number}
   */
  this.minWidth_ = goog.isDef(options.minWidth) ? options.minWidth : 64;

  /**
   * @private
   * @type {boolean}
   */
  this.renderedVisible_ = false;

  /**
   * @private
   * @type {number|undefined}
   */
  this.renderedWidth_ = undefined;

  /**
   * @private
   * @type {string}
   */
  this.renderedHTML_ = '';

  /**
   * @private
   * @type {?ol.TransformFunction}
   */
  this.toEPSG4326_ = null;

  var render = goog.isDef(options.render) ?
      options.render : ol.control.ScaleLine.render;

  goog.base(this, {
    element: this.element_,
    render: render,
    target: options.target
  });

  goog.events.listen(
      this, ol.Object.getChangeEventType(ol.control.ScaleLineProperty.UNITS),
      this.handleUnitsChanged_, false, this);

  this.setUnits(/** @type {ol.control.ScaleLineUnits} */ (options.units) ||
      ol.control.ScaleLineUnits.METRIC);

};
goog.inherits(ol.control.ScaleLine, ol.control.Control);

/**
 * @const
 * @type {Array.<number>}
 */
ol.control.ScaleLine.LEADING_DIGITS = [1, 2, 5];

/**
 * @return {ol.control.ScaleLineUnits|undefined} The units to use in the scale
 *     line.
 * @observable
 * @api stable
 */
ol.control.ScaleLine.prototype.getUnits = function() {
  return /** @type {ol.control.ScaleLineUnits|undefined} */ (
      this.get(ol.control.ScaleLineProperty.UNITS));
};

/**
 * @param {ol.MapEvent} mapEvent Map event.
 * @this {ol.control.ScaleLine}
 * @api
 */
ol.control.ScaleLine.render = function(mapEvent) {
  var frameState = mapEvent.frameState;
  if (goog.isNull(frameState)) {
    this.viewState_ = null;
  } else {
    this.viewState_ = frameState.viewState;
  }
  this.updateElement_();
};

/**
 * @private
 */
ol.control.ScaleLine.prototype.handleUnitsChanged_ = function() {
  this.updateElement_();
};

/**
 * @param {ol.control.ScaleLineUnits} units The units to use in the scale line.
 * @observable
 * @api stable
 */
ol.control.ScaleLine.prototype.setUnits = function(units) {
  this.set(ol.control.ScaleLineProperty.UNITS, units);
};

/**
 * @private
 */
ol.control.ScaleLine.prototype.updateElement_ = function() {
  var viewState = this.viewState_;

  if (goog.isNull(viewState)) {
    if (this.renderedVisible_) {
      goog.style.setElementShown(this.element_, false);
      this.renderedVisible_ = false;
    }
    return;
  }

  var center = viewState.center;
  var projection = viewState.projection;
  var pointResolution =
      projection.getPointResolution(viewState.resolution, center);
  var projectionUnits = projection.getUnits();

  var cosLatitude;
  var units = this.getUnits();
  if (projectionUnits == ol.proj.Units.DEGREES &&
      (units == ol.control.ScaleLineUnits.METRIC ||
       units == ol.control.ScaleLineUnits.IMPERIAL ||
       units == ol.control.ScaleLineUnits.US ||
       units == ol.control.ScaleLineUnits.NAUTICAL)) {

    // Convert pointResolution from degrees to meters
    this.toEPSG4326_ = null;
    cosLatitude = Math.cos(goog.math.toRadians(center[1]));
    pointResolution *= Math.PI * cosLatitude * ol.sphere.NORMAL.radius / 180;
    projectionUnits = ol.proj.Units.METERS;

  } else if (projectionUnits != ol.proj.Units.DEGREES &&
      units == ol.control.ScaleLineUnits.DEGREES) {

    // Convert pointResolution from other units to degrees
    if (goog.isNull(this.toEPSG4326_)) {
      this.toEPSG4326_ = ol.proj.getTransformFromProjections(
          projection, ol.proj.get('EPSG:4326'));
    }
    cosLatitude = Math.cos(goog.math.toRadians(this.toEPSG4326_(center)[1]));
    var radius = ol.sphere.NORMAL.radius;
    goog.asserts.assert(goog.isDef(ol.proj.METERS_PER_UNIT[projectionUnits]),
        'Meters per unit should be defined for the projection unit');
    radius /= ol.proj.METERS_PER_UNIT[projectionUnits];
    pointResolution *= 180 / (Math.PI * cosLatitude * radius);
    projectionUnits = ol.proj.Units.DEGREES;

  } else {
    this.toEPSG4326_ = null;
  }

  goog.asserts.assert(
      ((units == ol.control.ScaleLineUnits.METRIC ||
        units == ol.control.ScaleLineUnits.IMPERIAL ||
        units == ol.control.ScaleLineUnits.US ||
        units == ol.control.ScaleLineUnits.NAUTICAL) &&
       projectionUnits == ol.proj.Units.METERS) ||
      (units == ol.control.ScaleLineUnits.DEGREES &&
       projectionUnits == ol.proj.Units.DEGREES),
      'Scale line units and projection units should match');

  var nominalCount = this.minWidth_ * pointResolution;
  var suffix = '';
  if (units == ol.control.ScaleLineUnits.DEGREES) {
    if (nominalCount < 1 / 60) {
      suffix = '\u2033'; // seconds
      pointResolution *= 3600;
    } else if (nominalCount < 1) {
      suffix = '\u2032'; // minutes
      pointResolution *= 60;
    } else {
      suffix = '\u00b0'; // degrees
    }
  } else if (units == ol.control.ScaleLineUnits.IMPERIAL) {
    if (nominalCount < 0.9144) {
      suffix = 'in';
      pointResolution /= 0.0254;
    } else if (nominalCount < 1609.344) {
      suffix = 'ft';
      pointResolution /= 0.3048;
    } else {
      suffix = 'mi';
      pointResolution /= 1609.344;
    }
  } else if (units == ol.control.ScaleLineUnits.NAUTICAL) {
    pointResolution /= 1852;
    suffix = 'nm';
  } else if (units == ol.control.ScaleLineUnits.METRIC) {
    if (nominalCount < 1) {
      suffix = 'mm';
      pointResolution *= 1000;
    } else if (nominalCount < 1000) {
      suffix = 'm';
    } else {
      suffix = 'km';
      pointResolution /= 1000;
    }
  } else if (units == ol.control.ScaleLineUnits.US) {
    if (nominalCount < 0.9144) {
      suffix = 'in';
      pointResolution *= 39.37;
    } else if (nominalCount < 1609.344) {
      suffix = 'ft';
      pointResolution /= 0.30480061;
    } else {
      suffix = 'mi';
      pointResolution /= 1609.3472;
    }
  } else {
    goog.asserts.fail('Scale line element cannot be updated');
  }

  var i = 3 * Math.floor(
      Math.log(this.minWidth_ * pointResolution) / Math.log(10));
  var count, width;
  while (true) {
    count = ol.control.ScaleLine.LEADING_DIGITS[i % 3] *
        Math.pow(10, Math.floor(i / 3));
    width = Math.round(count / pointResolution);
    if (isNaN(width)) {
      goog.style.setElementShown(this.element_, false);
      this.renderedVisible_ = false;
      return;
    } else if (width >= this.minWidth_) {
      break;
    }
    ++i;
  }

  var html = count + ' ' + suffix;
  if (this.renderedHTML_ != html) {
    this.innerElement_.innerHTML = html;
    this.renderedHTML_ = html;
  }

  if (this.renderedWidth_ != width) {
    this.innerElement_.style.width = width + 'px';
    this.renderedWidth_ = width;
  }

  if (!this.renderedVisible_) {
    goog.style.setElementShown(this.element_, true);
    this.renderedVisible_ = true;
  }

};
<commit_msg>Add basic docs for scalelinecontrol<commit_after>goog.provide('ol.control.ScaleLine');
goog.provide('ol.control.ScaleLineProperty');
goog.provide('ol.control.ScaleLineUnits');

goog.require('goog.asserts');
goog.require('goog.dom');
goog.require('goog.dom.TagName');
goog.require('goog.events');
goog.require('goog.math');
goog.require('goog.style');
goog.require('ol.Object');
goog.require('ol.TransformFunction');
goog.require('ol.control.Control');
goog.require('ol.css');
goog.require('ol.proj');
goog.require('ol.proj.METERS_PER_UNIT');
goog.require('ol.proj.Units');
goog.require('ol.sphere.NORMAL');

/**
 * @enum {string}
 */
ol.control.ScaleLineProperty = {
  UNITS: 'units'
};

/**
 * Units for the scale line. Supported values are `'degrees'`, `'imperial'`,
 * `'nautical'`, `'metric'`, `'us'`.
 * @enum {string}
 * @api stable
 */
ol.control.ScaleLineUnits = {
  DEGREES: 'degrees',
  IMPERIAL: 'imperial',
  NAUTICAL: 'nautical',
  METRIC: 'metric',
  US: 'us'
};

/**
 * @classdesc
 * A control displaying rough x-axis distances, calculated for the center of the
 * viewport.
 * No scale line will be shown when the x-axis distance cannot be calculated in
 * the view projection (e.g. at or beyond the poles in EPSG:4326).
 * By default the scale line will show in the bottom left portion of the map,
 * but this can be changed by using the css selector `.ol-scale-line`.
 *
 * @constructor
 * @extends {ol.control.Control}
 * @param {olx.control.ScaleLineOptions=} opt_options Scale line options.
 * @api stable
 */
ol.control.ScaleLine = function(opt_options) {

  var options = goog.isDef(opt_options) ? opt_options : {};

  var className = goog.isDef(options.className) ?
      options.className : 'ol-scale-line';

  /**
   * @private
   * @type {Element}
   */
  this.innerElement_ = goog.dom.createDom(goog.dom.TagName.DIV,
      className + '-inner');

  /**
   * @private
   * @type {Element}
   */
  this.element_ = goog.dom.createDom(goog.dom.TagName.DIV,
      className + ' ' + ol.css.CLASS_UNSELECTABLE, this.innerElement_);

  /**
   * @private
   * @type {?olx.ViewState}
   */
  this.viewState_ = null;

  /**
   * @private
   * @type {number}
   */
  this.minWidth_ = goog.isDef(options.minWidth) ? options.minWidth : 64;

  /**
   * @private
   * @type {boolean}
   */
  this.renderedVisible_ = false;

  /**
   * @private
   * @type {number|undefined}
   */
  this.renderedWidth_ = undefined;

  /**
   * @private
   * @type {string}
   */
  this.renderedHTML_ = '';

  /**
   * @private
   * @type {?ol.TransformFunction}
   */
  this.toEPSG4326_ = null;

  var render = goog.isDef(options.render) ?
      options.render : ol.control.ScaleLine.render;

  goog.base(this, {
    element: this.element_,
    render: render,
    target: options.target
  });

  goog.events.listen(
      this, ol.Object.getChangeEventType(ol.control.ScaleLineProperty.UNITS),
      this.handleUnitsChanged_, false, this);

  this.setUnits(/** @type {ol.control.ScaleLineUnits} */ (options.units) ||
      ol.control.ScaleLineUnits.METRIC);

};
goog.inherits(ol.control.ScaleLine, ol.control.Control);

/**
 * @const
 * @type {Array.<number>}
 */
ol.control.ScaleLine.LEADING_DIGITS = [1, 2, 5];

/**
 * Return the units to use in the scale line.
 * @return {ol.control.ScaleLineUnits|undefined} The units to use in the scale
 *     line.
 * @observable
 * @api stable
 */
ol.control.ScaleLine.prototype.getUnits = function() {
  return /** @type {ol.control.ScaleLineUnits|undefined} */ (
      this.get(ol.control.ScaleLineProperty.UNITS));
};

/**
 * Update the scale line element.
 * @param {ol.MapEvent} mapEvent Map event.
 * @this {ol.control.ScaleLine}
 * @api
 */
ol.control.ScaleLine.render = function(mapEvent) {
  var frameState = mapEvent.frameState;
  if (goog.isNull(frameState)) {
    this.viewState_ = null;
  } else {
    this.viewState_ = frameState.viewState;
  }
  this.updateElement_();
};

/**
 * @private
 */
ol.control.ScaleLine.prototype.handleUnitsChanged_ = function() {
  this.updateElement_();
};

/**
 * Set the units to use in the scale line.
 * @param {ol.control.ScaleLineUnits} units The units to use in the scale line.
 * @observable
 * @api stable
 */
ol.control.ScaleLine.prototype.setUnits = function(units) {
  this.set(ol.control.ScaleLineProperty.UNITS, units);
};

/**
 * @private
 */
ol.control.ScaleLine.prototype.updateElement_ = function() {
  var viewState = this.viewState_;

  if (goog.isNull(viewState)) {
    if (this.renderedVisible_) {
      goog.style.setElementShown(this.element_, false);
      this.renderedVisible_ = false;
    }
    return;
  }

  var center = viewState.center;
  var projection = viewState.projection;
  var pointResolution =
      projection.getPointResolution(viewState.resolution, center);
  var projectionUnits = projection.getUnits();

  var cosLatitude;
  var units = this.getUnits();
  if (projectionUnits == ol.proj.Units.DEGREES &&
      (units == ol.control.ScaleLineUnits.METRIC ||
       units == ol.control.ScaleLineUnits.IMPERIAL ||
       units == ol.control.ScaleLineUnits.US ||
       units == ol.control.ScaleLineUnits.NAUTICAL)) {

    // Convert pointResolution from degrees to meters
    this.toEPSG4326_ = null;
    cosLatitude = Math.cos(goog.math.toRadians(center[1]));
    pointResolution *= Math.PI * cosLatitude * ol.sphere.NORMAL.radius / 180;
    projectionUnits = ol.proj.Units.METERS;

  } else if (projectionUnits != ol.proj.Units.DEGREES &&
      units == ol.control.ScaleLineUnits.DEGREES) {

    // Convert pointResolution from other units to degrees
    if (goog.isNull(this.toEPSG4326_)) {
      this.toEPSG4326_ = ol.proj.getTransformFromProjections(
          projection, ol.proj.get('EPSG:4326'));
    }
    cosLatitude = Math.cos(goog.math.toRadians(this.toEPSG4326_(center)[1]));
    var radius = ol.sphere.NORMAL.radius;
    goog.asserts.assert(goog.isDef(ol.proj.METERS_PER_UNIT[projectionUnits]),
        'Meters per unit should be defined for the projection unit');
    radius /= ol.proj.METERS_PER_UNIT[projectionUnits];
    pointResolution *= 180 / (Math.PI * cosLatitude * radius);
    projectionUnits = ol.proj.Units.DEGREES;

  } else {
    this.toEPSG4326_ = null;
  }

  goog.asserts.assert(
      ((units == ol.control.ScaleLineUnits.METRIC ||
        units == ol.control.ScaleLineUnits.IMPERIAL ||
        units == ol.control.ScaleLineUnits.US ||
        units == ol.control.ScaleLineUnits.NAUTICAL) &&
       projectionUnits == ol.proj.Units.METERS) ||
      (units == ol.control.ScaleLineUnits.DEGREES &&
       projectionUnits == ol.proj.Units.DEGREES),
      'Scale line units and projection units should match');

  var nominalCount = this.minWidth_ * pointResolution;
  var suffix = '';
  if (units == ol.control.ScaleLineUnits.DEGREES) {
    if (nominalCount < 1 / 60) {
      suffix = '\u2033'; // seconds
      pointResolution *= 3600;
    } else if (nominalCount < 1) {
      suffix = '\u2032'; // minutes
      pointResolution *= 60;
    } else {
      suffix = '\u00b0'; // degrees
    }
  } else if (units == ol.control.ScaleLineUnits.IMPERIAL) {
    if (nominalCount < 0.9144) {
      suffix = 'in';
      pointResolution /= 0.0254;
    } else if (nominalCount < 1609.344) {
      suffix = 'ft';
      pointResolution /= 0.3048;
    } else {
      suffix = 'mi';
      pointResolution /= 1609.344;
    }
  } else if (units == ol.control.ScaleLineUnits.NAUTICAL) {
    pointResolution /= 1852;
    suffix = 'nm';
  } else if (units == ol.control.ScaleLineUnits.METRIC) {
    if (nominalCount < 1) {
      suffix = 'mm';
      pointResolution *= 1000;
    } else if (nominalCount < 1000) {
      suffix = 'm';
    } else {
      suffix = 'km';
      pointResolution /= 1000;
    }
  } else if (units == ol.control.ScaleLineUnits.US) {
    if (nominalCount < 0.9144) {
      suffix = 'in';
      pointResolution *= 39.37;
    } else if (nominalCount < 1609.344) {
      suffix = 'ft';
      pointResolution /= 0.30480061;
    } else {
      suffix = 'mi';
      pointResolution /= 1609.3472;
    }
  } else {
    goog.asserts.fail('Scale line element cannot be updated');
  }

  var i = 3 * Math.floor(
      Math.log(this.minWidth_ * pointResolution) / Math.log(10));
  var count, width;
  while (true) {
    count = ol.control.ScaleLine.LEADING_DIGITS[i % 3] *
        Math.pow(10, Math.floor(i / 3));
    width = Math.round(count / pointResolution);
    if (isNaN(width)) {
      goog.style.setElementShown(this.element_, false);
      this.renderedVisible_ = false;
      return;
    } else if (width >= this.minWidth_) {
      break;
    }
    ++i;
  }

  var html = count + ' ' + suffix;
  if (this.renderedHTML_ != html) {
    this.innerElement_.innerHTML = html;
    this.renderedHTML_ = html;
  }

  if (this.renderedWidth_ != width) {
    this.innerElement_.style.width = width + 'px';
    this.renderedWidth_ = width;
  }

  if (!this.renderedVisible_) {
    goog.style.setElementShown(this.element_, true);
    this.renderedVisible_ = true;
  }

};
<|endoftext|>


<commit_before>/*jslint vars: true, plusplus: true, devel: true, nomen: true, regexp: true, indent: 4, maxerr: 50 */
/*global define, brackets, appshell */
define(function (require, exports, module) {
    "use strict";

    var BaseServer  = brackets.getModule("LiveDevelopment/Servers/BaseServer").BaseServer;

    var Content = require("nohost/src/content");
    var Handlers = require("nohost/src/handlers");

    var Filer = appshell.MakeDrive;
    var Path = Filer.Path;

    function NoHostServer(config) {
        config = config || {};
        BaseServer.call(this, config);
    }

    NoHostServer.prototype = Object.create(BaseServer.prototype);
    NoHostServer.prototype.constructor = NoHostServer;

    // TODO: I *think* I want to return these unmodified...
    NoHostServer.prototype.pathToUrl = function(path) {
        return path;
    };
    NoHostServer.prototype.urlToPath = function(url) {
        return url;
    };

    NoHostServer.prototype.start = function() {
        this.fs = Filer.fs();
    };

    NoHostServer.prototype.stop = function() {
        this.fs = null;
    };

    /**
     * Serve the contents of path, invoking the appropriate content handler.
     */
    NoHostServer.prototype.serve = function(path, callback) {
        var fs = this.fs;

        fs.stat(path, function(err, stats) {
            if(err) {
                return callback(err);
            }

            // If this is a dir, error
            if(stats.isDirectory()) {
                return callback(new Error('expected file path'));
            }

            // This is a file, pick the right content handler based on extension
            var ext = Path.extname(path);

            if(Content.isHTML(ext)) {
                Handlers.handleHTML(path, fs, callback);
            } else {
                Handlers.handleFile(path, fs, callback);
            }
        });
    };

    exports.NoHostServer = NoHostServer;
});
<commit_msg>Rework server.serve() into servePath() and serveHTML()<commit_after>/*jslint vars: true, plusplus: true, devel: true, nomen: true, regexp: true, indent: 4, maxerr: 50 */
/*global define, brackets, appshell */
define(function (require, exports, module) {
    "use strict";

    var BaseServer  = brackets.getModule("LiveDevelopment/Servers/BaseServer").BaseServer;

    var Content = require("nohost/src/content");
    var Handlers = require("nohost/src/handlers");
    var Rewriter = require("nohost/src/rewriter");

    var Filer = appshell.MakeDrive;
    var Path = Filer.Path;

    function NoHostServer(config) {
        config = config || {};
        BaseServer.call(this, config);
    }

    NoHostServer.prototype = Object.create(BaseServer.prototype);
    NoHostServer.prototype.constructor = NoHostServer;

    // TODO: I *think* I want to return these unmodified...
    NoHostServer.prototype.pathToUrl = function(path) {
        return path;
    };
    NoHostServer.prototype.urlToPath = function(url) {
        return url;
    };

    NoHostServer.prototype.start = function() {
        this.fs = Filer.fs();
    };

    NoHostServer.prototype.stop = function() {
        this.fs = null;
    };

    /**
     * Serve the contents of a path into the filesystem,
     * invoking the appropriate content handler, and rewriting any resources
     * in the local filesystem to Blob URLs.
     */
    NoHostServer.prototype.servePath = function(path, callback) {
        var fs = this.fs;

        fs.stat(path, function(err, stats) {
            if(err) {
                return callback(err);
            }

            // If this is a dir, error
            if(stats.isDirectory()) {
                return callback(new Error('expected file path'));
            }

            // This is a file, pick the right content handler based on extension
            var ext = Path.extname(path);

            if(Content.isHTML(ext)) {
                Handlers.handleHTML(path, fs, callback);
            } else {
                Handlers.handleFile(path, fs, callback);
            }
        });
    };

    /**
     * Serve an existing HTML fragment/file (i.e., one that has already been read
     * for a given path) from the local filesystem, rewriting any resources
     * in the local filesystem to Blob URLs. The original path of the file is needed
     * in order to locate other resources with paths relative to this file.
     */
    NoHostServer.prototype.serveHTML = function(html, path, callback) {
        var fs = this.fs;

        Rewriter.rewriteHTML(html, path, fs, function(err, rewrittenHTML) {
            if(err) {
                Log.error('unable to rewrite HTML for `' + path + '`');
                // TODO: best way to deal with error here? 500?
                return handle404(path, callback);
            }

            callback(null, rewrittenHTML);
        });
    };

    exports.NoHostServer = NoHostServer;
});
<|endoftext|>


<commit_before>test("cuttyle-drill tests", function() {
  var job = {
  	"name": "test_job",
  	"units": "inch",
  	"bit_diameter": 0.25,
  	"feed_rate": 10,
  	"plunge_rate": 5,
  	"z_step_size": 0.1,
  	"cuts": [{
  		"type": "drill",
  		"points": [[0, 0], [2, 3]],
  		"depth": -0.125
  	}]
  };

  var expected = [
	"G90",
	"G20",
	"",
	"; begin cut: drill",
	"G90",
	"G1 Z0.25 F20",
	"G0 X0 Y0 F10",
	"G1 Z-0.1 F5",
	"G1 Z0",
	"G1 Z-0.125 F5",
	"G1 Z0",
	"G1 Z0.25 F20",
	"G0 X2 Y3 F10",
	"G1 Z-0.1 F5",
	"G1 Z0",
	"G1 Z-0.125 F5",
	"G1 Z0",
	"G1 Z0.25 F20",
	"; end cut: drill"];

  var results = window.opencut.toGCode(job);
  ok(results.warnings.length == 0, "no warnings");
  ok(results.errors.length == 0, "no errors");
  deepEqual(results.gcode, expected, "correct gcode");
});
<commit_msg>spelling correction.<commit_after>test("cuttype-drill tests", function() {
  var job = {
  	"name": "test_job",
  	"units": "inch",
  	"bit_diameter": 0.25,
  	"feed_rate": 10,
  	"plunge_rate": 5,
  	"z_step_size": 0.1,
  	"cuts": [{
  		"type": "drill",
  		"points": [[0, 0], [2, 3]],
  		"depth": -0.125
  	}]
  };

  var expected = [
	"G90",
	"G20",
	"",
	"; begin cut: drill",
	"G90",
	"G1 Z0.25 F20",
	"G0 X0 Y0 F10",
	"G1 Z-0.1 F5",
	"G1 Z0",
	"G1 Z-0.125 F5",
	"G1 Z0",
	"G1 Z0.25 F20",
	"G0 X2 Y3 F10",
	"G1 Z-0.1 F5",
	"G1 Z0",
	"G1 Z-0.125 F5",
	"G1 Z0",
	"G1 Z0.25 F20",
	"; end cut: drill"];

  var results = window.opencut.toGCode(job);
  ok(results.warnings.length == 0, "no warnings");
  ok(results.errors.length == 0, "no errors");
  deepEqual(results.gcode, expected, "correct gcode");
});
<|endoftext|>


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

// Parse SRT subtitles into HTML.

// Done for fun. Understand , ,  and  type
// of tags.

import parseTimestamp from "./parseTimestamp.js";

/**
 * @param {string}
 * @returns {Array.<Object>}
 */
export default function parseSRTStringToHTML(srtStr) {
  // Even if srt only authorize CRLF, we will also take LF or CR as line
  // terminators for resilience
  const lines = srtStr.split(/\r\n|\n|\r/);

  const cueBlocks = [];

  for (let i = 0; i < lines.length; i++) {
    if (lines[i]) {
      const startingI = i;
      i++;

      while (lines[i]) {
        i++;
      }
      cueBlocks.push(lines.slice(startingI, i));
    }
  }

  const cues = [];
  for (let i = 0; i < cueBlocks.length; i++) {
    const cue = parseCue(cueBlocks[i]);
    if (cue) {
      cues.push(cue);
    }
  }
  return cues;
}

/**
 * @param {Array.<string>} cueLines
 * @returns {Object}
 */
function parseCue(cueLines) {
  const [startString, endString] = cueLines[1].split(" --> ");
  const payloadLines = cueLines.slice(2, cueLines.length);
  if (!startString | !endString | !payloadLines.length) {
    return null;
  }

  const start = parseTimestamp(startString);
  const end = parseTimestamp(endString);

  const pEl = document.createElement("div");
  pEl.className = "rxp-texttrack-p";
  pEl.style.fontSize = "28px";
  pEl.style.position = "absolute";
  pEl.style.bottom = "5%";
  pEl.style.width = "100%";
  pEl.style.textAlign = "center";
  pEl.style.textShadow = "-1px -1px 2px #000," +
    "1px -1px 2px #000," +
    "-1px 1px 2px #000," +
    "1px 1px 2px #000";

  for (let i = 0; i < payloadLines.length; i++) {
    if (i) {
      pEl.appendChild(document.createElement("br"));
    }
    const span = generateSpansFromSRTText(payloadLines[i]);
    pEl.appendChild(span);
  }

  return {
    start,
    end,
    element: pEl,
  };
}

/**
 * Take a single srt line and convert it into a span with the right style while
 * avoiding XSS.
 * What we do is set a whitelist of authorized tags, and recreate the
 * corresponding tag from scratch.
 * Supported tags:
 *   - : make content bold
 *   - : make content italic
 *   - : draw underline on content
 *   - : add color x to the content
 * @param {string} text
 * @returns {HTMLElement}
 */
function generateSpansFromSRTText(text) {
  const secureDiv = document.createElement("div");
  secureDiv.innerHTML = text;

  const _loop = function (node) {
    const childNodes = node.childNodes;
    const span = document.createElement("span");
    span.className = "rxp-texttrack-span";

    for (let i = 0; i < childNodes.length; i++) {
      const currentNode = childNodes[i];
      if (currentNode.nodeName === "#text") {
        span.innerHTML += currentNode.textContent;
      } else if (currentNode.nodeName === "B") {
        const spanChild = _loop(currentNode);
        spanChild.style.fontWeight = "bold";
        span.appendChild(spanChild);
      } else if (currentNode.nodeName === "I" ) {
        const spanChild = _loop(currentNode);
        spanChild.style.fontStyle = "italic";
        span.appendChild(spanChild);
      } else if (currentNode.nodeName === "U" ) {
        const spanChild = _loop(currentNode);
        spanChild.style.textDecoration = "underline";
        span.appendChild(spanChild);
      } else if (currentNode.nodeName === "FONT" && currentNode.color) {
        const spanChild = _loop(currentNode);
        spanChild.style.color = currentNode.color;
        span.appendChild(spanChild);
      } else {
        const spanChild = _loop(currentNode);
        span.appendChild(spanChild);
      }
    }
    return span;
  };

  return _loop(secureDiv);
}
<commit_msg>languages/srt: set default color to white for srt tracks<commit_after>/**
 * Copyright 2015 CANAL+ Group
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// Parse SRT subtitles into HTML.

// Done for fun. Understand , ,  and  type
// of tags.

import parseTimestamp from "./parseTimestamp.js";

/**
 * @param {string}
 * @returns {Array.<Object>}
 */
export default function parseSRTStringToHTML(srtStr) {
  // Even if srt only authorize CRLF, we will also take LF or CR as line
  // terminators for resilience
  const lines = srtStr.split(/\r\n|\n|\r/);

  const cueBlocks = [];

  for (let i = 0; i < lines.length; i++) {
    if (lines[i]) {
      const startingI = i;
      i++;

      while (lines[i]) {
        i++;
      }
      cueBlocks.push(lines.slice(startingI, i));
    }
  }

  const cues = [];
  for (let i = 0; i < cueBlocks.length; i++) {
    const cue = parseCue(cueBlocks[i]);
    if (cue) {
      cues.push(cue);
    }
  }
  return cues;
}

/**
 * @param {Array.<string>} cueLines
 * @returns {Object}
 */
function parseCue(cueLines) {
  const [startString, endString] = cueLines[1].split(" --> ");
  const payloadLines = cueLines.slice(2, cueLines.length);
  if (!startString | !endString | !payloadLines.length) {
    return null;
  }

  const start = parseTimestamp(startString);
  const end = parseTimestamp(endString);

  const pEl = document.createElement("div");
  pEl.className = "rxp-texttrack-p";
  pEl.style.fontSize = "28px";
  pEl.style.position = "absolute";
  pEl.style.bottom = "5%";
  pEl.style.width = "100%";
  pEl.style.textAlign = "center";
  pEl.style.color = "#fff";
  pEl.style.textShadow = "-1px -1px 2px #000," +
    "1px -1px 2px #000," +
    "-1px 1px 2px #000," +
    "1px 1px 2px #000";

  for (let i = 0; i < payloadLines.length; i++) {
    if (i) {
      pEl.appendChild(document.createElement("br"));
    }
    const span = generateSpansFromSRTText(payloadLines[i]);
    pEl.appendChild(span);
  }

  return {
    start,
    end,
    element: pEl,
  };
}

/**
 * Take a single srt line and convert it into a span with the right style while
 * avoiding XSS.
 * What we do is set a whitelist of authorized tags, and recreate the
 * corresponding tag from scratch.
 * Supported tags:
 *   - : make content bold
 *   - : make content italic
 *   - : draw underline on content
 *   - : add color x to the content
 * @param {string} text
 * @returns {HTMLElement}
 */
function generateSpansFromSRTText(text) {
  const secureDiv = document.createElement("div");
  secureDiv.innerHTML = text;

  const _loop = function (node) {
    const childNodes = node.childNodes;
    const span = document.createElement("span");
    span.className = "rxp-texttrack-span";

    for (let i = 0; i < childNodes.length; i++) {
      const currentNode = childNodes[i];
      if (currentNode.nodeName === "#text") {
        span.innerHTML += currentNode.textContent;
      } else if (currentNode.nodeName === "B") {
        const spanChild = _loop(currentNode);
        spanChild.style.fontWeight = "bold";
        span.appendChild(spanChild);
      } else if (currentNode.nodeName === "I" ) {
        const spanChild = _loop(currentNode);
        spanChild.style.fontStyle = "italic";
        span.appendChild(spanChild);
      } else if (currentNode.nodeName === "U" ) {
        const spanChild = _loop(currentNode);
        spanChild.style.textDecoration = "underline";
        span.appendChild(spanChild);
      } else if (currentNode.nodeName === "FONT" && currentNode.color) {
        const spanChild = _loop(currentNode);
        spanChild.style.color = currentNode.color;
        span.appendChild(spanChild);
      } else {
        const spanChild = _loop(currentNode);
        span.appendChild(spanChild);
      }
    }
    return span;
  };

  return _loop(secureDiv);
}
<|endoftext|>


<commit_before>import React, { PropTypes } from 'react';

import RJSForm from 'react-jsonschema-form/lib/index';

import { Action } from 'react-talend-components';

import BooleanField from './fields/BooleanField';
import ObjectField from './fields/ObjectField';
import StringField from './fields/StringField';
import ArrayField from './fields/ArrayField';
import FieldTemplate from './templates/FieldTemplate';
import ToggleWidget from './widgets/ToggleWidget';
import TabsWidget from './widgets/TabsWidget';
import KeyValueWidget from './widgets/KeyValueWidget';
import MultiSelectTagWidget from './widgets/MultiSelectTagWidget/MultiSelectTagWidget';
import DatalistWidget from './widgets/DatalistWidget';
import EnumerationWidget from './widgets/EnumerationWidget/EnumerationWidget';
import ColumnsWidget from './widgets/ColumnsWidget';
import ListViewWidget from './widgets/ListViewWidget/ListViewWidget';

/**
 * @type {string} After trigger name for field value has changed
 */
const TRIGGER_AFTER = 'after';

const customWidgets = {
	toggle: ToggleWidget,
	tabs: TabsWidget,
	keyValue: KeyValueWidget,
	multiSelectTag: MultiSelectTagWidget,
	datalist: DatalistWidget,
	enumeration: EnumerationWidget,
	columns: ColumnsWidget,
	listview: ListViewWidget,
};

export function renderActionIcon(icon) {
	if (icon) {
		return ;
	}
	return null;
}

export function renderActions(actions, handleActionClick) {
	if (actions) {
		return actions.map((action, index) => (
			<Action
				key={index}
				bsStyle={action.style}
				label={action.title}
				{...Object.assign(action, { onClick: handleActionClick(action.onClick) })}
			>
				{renderActionIcon(action.icon)}
				{action.label}
			</Action>),
		);
	}
	return (<Action
		bsStyle="primary"
		onClick={() => {}}
		type="submit"
		label="Submit"
	/>);
}

class Form extends React.Component {
	constructor(props) {
		super(props);
		this.handleChange = this.handleChange.bind(this);
		this.handleSchemaChange = this.handleSchemaChange.bind(this);
		this.handleSchemaSubmit = this.handleSchemaSubmit.bind(this);
		this.handleActionClick = this.handleActionClick.bind(this);
	}

	handleSchemaSubmit(changes) {
		if (this.props.onSubmit) {
			this.props.onSubmit(changes);
		}
	}

	/**
	 * Handle changes only if modified field has "ui:trigger" option
	 * use onTrigger property to take advantage of this feature
	 * @param changes New formData
	 * @param id Form id is provided
	 * @param name Name of the modified field
	 * @param value New value of the field
	 * @param options Options from uiSchema for this field
	 */
	handleSchemaChange(changes, id, name, value, options) {
		const triggers = options && options.trigger;
		if (triggers && triggers.indexOf(TRIGGER_AFTER) !== -1) {
			if (this.props.onTrigger) {
				this.props.onTrigger(changes, id, name, value);
			}
		}
	}

	handleActionClick(onClick) {
		if (onClick) {
			return (event, data) => onClick(event, { ...data, ...this.form.state });
		}
		return () => {};
	}

	/**
	 * Handle changes of form @see https://github.com/mozilla-services/react-jsonschema-form
	 */
	handleChange(...args) {
		if (this.props.onChange) {
			this.props.onChange(...args);
		}
	}

	render() {
		const schema = this.props.data && this.props.data.jsonSchema;
		if (!schema) {
			throw Error('You must provide data with valid JSON Schema');
		}

		const widgets = {
			...customWidgets,
			...this.props.widgets,
		};

		const formData = this.props.data && this.props.data.properties;

		const customFields = {
			ArrayField,
			BooleanField,
			ObjectField,
			StringField,
		};

		const customFormContext = {
			handleSchemaChange: this.handleSchemaChange,
			handleAction: this.props.handleAction,
			...this.props.formContext,
		};
		return (
			<RJSForm
				{...this.props}
				schema={schema}
				uiSchema={this.props.data && this.props.data.uiSchema}
				formData={formData}
				formContext={customFormContext}
				fields={customFields}
				FieldTemplate={FieldTemplate}
				widgets={widgets}
				onChange={this.handleChange}
				onSubmit={this.handleSchemaSubmit}
				ref={(c) => {
					this.form = c;
				}}
			>

					{renderActions(this.props.actions, this.handleActionClick)}

			</RJSForm>
		);
	}
}

export const DataPropTypes = PropTypes.shape({
	jsonSchema: PropTypes.object.isRequired,
	uiSchema: PropTypes.object,
	properties: PropTypes.oneOfType([
		PropTypes.object,
		PropTypes.string,
	]),
});

export const ActionsPropTypes = PropTypes.arrayOf(PropTypes.shape({
	style: PropTypes.string,
	type: PropTypes.oneOf(['submit', 'reset', 'button']),
	onClick: PropTypes.func,
	label: PropTypes.string,
	icon: PropTypes.string,
	title: PropTypes.string,
}));

Form.propTypes = {
	data: DataPropTypes.isRequired,
	onChange: PropTypes.func,
	onTrigger: PropTypes.func,
	onSubmit: PropTypes.func,
	actions: ActionsPropTypes,
	buttonBlockClass: PropTypes.string,
	handleAction: PropTypes.func,
	widgets: PropTypes.object,
	formContext: PropTypes.func,
};

Form.defaultProps = {
	buttonBlockClass: 'form-actions',
};

Form.displayName = 'TalendForm';

export default Form;
<commit_msg>fix(forms): avoid undefined ref (#514)<commit_after>import React, { PropTypes } from 'react';

import RJSForm from 'react-jsonschema-form/lib/index';

import { Action } from 'react-talend-components';

import BooleanField from './fields/BooleanField';
import ObjectField from './fields/ObjectField';
import StringField from './fields/StringField';
import ArrayField from './fields/ArrayField';
import FieldTemplate from './templates/FieldTemplate';
import ToggleWidget from './widgets/ToggleWidget';
import TabsWidget from './widgets/TabsWidget';
import KeyValueWidget from './widgets/KeyValueWidget';
import MultiSelectTagWidget from './widgets/MultiSelectTagWidget/MultiSelectTagWidget';
import DatalistWidget from './widgets/DatalistWidget';
import EnumerationWidget from './widgets/EnumerationWidget/EnumerationWidget';
import ColumnsWidget from './widgets/ColumnsWidget';
import ListViewWidget from './widgets/ListViewWidget/ListViewWidget';

/**
 * @type {string} After trigger name for field value has changed
 */
const TRIGGER_AFTER = 'after';

const customWidgets = {
	toggle: ToggleWidget,
	tabs: TabsWidget,
	keyValue: KeyValueWidget,
	multiSelectTag: MultiSelectTagWidget,
	datalist: DatalistWidget,
	enumeration: EnumerationWidget,
	columns: ColumnsWidget,
	listview: ListViewWidget,
};

export function renderActionIcon(icon) {
	if (icon) {
		return ;
	}
	return null;
}

export function renderActions(actions, handleActionClick) {
	if (actions) {
		return actions.map((action, index) => (
			<Action
				key={index}
				bsStyle={action.style}
				label={action.title}
				{...Object.assign(action, { onClick: handleActionClick(action.onClick) })}
			>
				{renderActionIcon(action.icon)}
				{action.label}
			</Action>),
		);
	}
	return (<Action
		bsStyle="primary"
		onClick={() => {}}
		type="submit"
		label="Submit"
	/>);
}

class Form extends React.Component {
	constructor(props) {
		super(props);
		this.handleChange = this.handleChange.bind(this);
		this.handleSchemaChange = this.handleSchemaChange.bind(this);
		this.handleSchemaSubmit = this.handleSchemaSubmit.bind(this);
		this.handleActionClick = this.handleActionClick.bind(this);
	}

	handleSchemaSubmit(changes) {
		if (this.props.onSubmit) {
			this.props.onSubmit(changes);
		}
	}

	/**
	 * Handle changes only if modified field has "ui:trigger" option
	 * use onTrigger property to take advantage of this feature
	 * @param changes New formData
	 * @param id Form id is provided
	 * @param name Name of the modified field
	 * @param value New value of the field
	 * @param options Options from uiSchema for this field
	 */
	handleSchemaChange(changes, id, name, value, options) {
		const triggers = options && options.trigger;
		if (triggers && triggers.indexOf(TRIGGER_AFTER) !== -1) {
			if (this.props.onTrigger) {
				this.props.onTrigger(changes, id, name, value);
			}
		}
	}

	handleActionClick(onClick) {
		if (onClick) {
			return (event, data) => onClick(event, { ...data, ...(this.form && this.form.state) });
		}
		return () => {};
	}

	/**
	 * Handle changes of form @see https://github.com/mozilla-services/react-jsonschema-form
	 */
	handleChange(...args) {
		if (this.props.onChange) {
			this.props.onChange(...args);
		}
	}

	render() {
		const schema = this.props.data && this.props.data.jsonSchema;
		if (!schema) {
			throw Error('You must provide data with valid JSON Schema');
		}

		const widgets = {
			...customWidgets,
			...this.props.widgets,
		};

		const formData = this.props.data && this.props.data.properties;

		const customFields = {
			ArrayField,
			BooleanField,
			ObjectField,
			StringField,
		};

		const customFormContext = {
			handleSchemaChange: this.handleSchemaChange,
			handleAction: this.props.handleAction,
			...this.props.formContext,
		};
		return (
			<RJSForm
				{...this.props}
				schema={schema}
				uiSchema={this.props.data && this.props.data.uiSchema}
				formData={formData}
				formContext={customFormContext}
				fields={customFields}
				FieldTemplate={FieldTemplate}
				widgets={widgets}
				onChange={this.handleChange}
				onSubmit={this.handleSchemaSubmit}
				ref={(c) => {
					this.form = c;
				}}
			>

					{renderActions(this.props.actions, this.handleActionClick)}

			</RJSForm>
		);
	}
}

export const DataPropTypes = PropTypes.shape({
	jsonSchema: PropTypes.object.isRequired,
	uiSchema: PropTypes.object,
	properties: PropTypes.oneOfType([
		PropTypes.object,
		PropTypes.string,
	]),
});

export const ActionsPropTypes = PropTypes.arrayOf(PropTypes.shape({
	style: PropTypes.string,
	type: PropTypes.oneOf(['submit', 'reset', 'button']),
	onClick: PropTypes.func,
	label: PropTypes.string,
	icon: PropTypes.string,
	title: PropTypes.string,
}));

Form.propTypes = {
	data: DataPropTypes.isRequired,
	onChange: PropTypes.func,
	onTrigger: PropTypes.func,
	onSubmit: PropTypes.func,
	actions: ActionsPropTypes,
	buttonBlockClass: PropTypes.string,
	handleAction: PropTypes.func,
	widgets: PropTypes.object,
	formContext: PropTypes.func,
};

Form.defaultProps = {
	buttonBlockClass: 'form-actions',
};

Form.displayName = 'TalendForm';

export default Form;
<|endoftext|>