<commit_before>const styles = {};

export const bodyStyle = {
  fontFamily: '"HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif',
  fontWeight: '300',
  fontSize: '24px',
};
styles.body = bodyStyle;

export const bottomNavStyle = {
  display: 'flex',
  alignItems: 'center',
  justifyContent: 'space-around',
};

export const login = {
  backgroundImage: 'url("http://68.media.tumblr.com/b4f33d654b4448794313633770cc8572/tumblr_oh34v07h9w1u9ooogo1_540.gif")',
  backgroundAttachment: 'fixed',
  backgroundPosition: 'center',
  backgroundRepeat: 'no-repeat',
  width: '100%',
  height: '100vh',
};

export const fbLogin = {
  background: 'none',
  marginBottom: '30px',
  display: 'flex',
  alignItems: 'center',
  justifyContent: 'space-around',
};

export const splashText = {
  color: 'white',
  marginTop: '150px',
  marginBottom: '100px',
  fontFamily: '"HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif',
  fontWeight: '300',
  fontSize: '90px',
  textAlign: 'center',
  textShadow: '0px 0px 3px #000',
};

export const tint = {
  content: '""',
  position: 'absolute',
  top: '0',
  left: '0',
  right: '0',
  bottom: '0',
  width: '100%',
  height: '100%',
  backgroundColor: 'rgba(0,0,0,.5)',
  margin: 'auto',
};

export const tagline = {
  textAlign: 'center',
  fontFamily: '"HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif',
  fontWeight: '300',
  fontSize: '24px',
  color: 'white',
};

// export const titleStyle = {
//   ...styles.body,
// };
// styles.title = titleStyle;

export default styles;
<commit_msg>changed margins to % for responsize design<commit_after>const styles = {};

export const bodyStyle = {
  fontFamily: '"HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif',
  fontWeight: '300',
  fontSize: '24px',
};
styles.body = bodyStyle;

export const bottomNavStyle = {
  display: 'flex',
  alignItems: 'center',
  justifyContent: 'space-around',
};

export const login = {
  backgroundImage: 'url("http://68.media.tumblr.com/b4f33d654b4448794313633770cc8572/tumblr_oh34v07h9w1u9ooogo1_540.gif")',
  backgroundAttachment: 'fixed',
  backgroundPosition: 'center center',
  backgroundSize: 'cover',
  width: '100%',
  height: '100vh',
};

export const fbLogin = {
  background: 'none',
  marginBottom: '30px',
  display: 'flex',
  alignItems: 'center',
  justifyContent: 'space-around',
};

export const splashText = {
  color: 'white',
  marginTop: '10%',
  marginBottom: '10%',
  fontFamily: '"HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif',
  fontWeight: '300',
  fontSize: '90px',
  textAlign: 'center',
  textShadow: '0px 0px 3px #000',
};

export const tint = {
  content: '""',
  position: 'absolute',
  top: '0',
  left: '0',
  right: '0',
  bottom: '0',
  width: '100%',
  height: '100%',
  backgroundColor: 'rgba(0,0,0,.5)',
  margin: 'auto',
};

export const tagline = {
  textAlign: 'center',
  fontFamily: '"HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif',
  fontWeight: '300',
  fontSize: '24px',
  color: 'white',
};

// export const titleStyle = {
//   ...styles.body,
// };
// styles.title = titleStyle;

export default styles;
<|endoftext|>


<commit_before>// Copyright (C) 2016 Allegorithmic
//
// This software may be modified and distributed under the terms
// of the MIT license.  See the LICENSE file for details.

function ExportConfig() {
  this.padding = "Infinite"
  this.dilation = 0
  this.bitDepth = 8
  this.keepAlpha = true
}

ExportConfig.prototype = {
  clone: function() {
    var conf = new ExportConfig
    conf.padding = this.padding
    conf.dilation = this.dilation
    conf.bitDepth = this.bitDepth
    conf.keepAlpha = this.keepAlpha
    return conf
  },

  usePadding : function(val) {
    this.padding = (val === true) ? "Infinite" : "Transparent"
  }
}

function PhotoshopExporter(callback) {
  this.logUserInfo =
    function logUserInfo(str) {
      if (callback) {
        callback(str)
      }
      else {
        alg.log.info(""+str+"")
      }
    }

  //Padding's struct
  this.exportConfig = new ExportConfig()
  // Weird behavior
  this.exportConfig.usePadding(alg.settings.value("padding", false))

  //Get the project name
  var projectName = alg.project.name()

  //The export path is the working directory
  this.exportPath = alg.mapexport.exportPath() + "/" + projectName + "_photoshop_export/";

  //Add the header photoshop script
  var headerScript = alg.fileIO.open(alg.plugin_root_directory + "/header.jsx", 'r');
  this.photoshopScript = headerScript.readAll();
  headerScript.close();

  //Run the script
  this.run(this);

  //Add the footer photoshop script
  var footerScript = alg.fileIO.open(alg.plugin_root_directory + "/footer.jsx", 'r');
  this.photoshopScript += footerScript.readAll();
  footerScript.close();

  try{
    var scriptFile = alg.fileIO.open(this.exportPath + "/photoshopScript.jsx", 'w');
    scriptFile.write(this.photoshopScript);
    scriptFile.close();
  } catch (error) {
    alg.log.error(error.message);
    return;
  }

  this.logUserInfo("Export done");
  if (alg.settings.value("launchPhotoshop", false)) {
    this.logUserInfo("Starting Photoshop...");
    if (Qt.platform.os == "windows") {
      alg.subprocess.startDetached(["\"" + alg.settings.value("photoshopPath", "") + "\"", "\"" + this.exportPath.split('/').join('\\') + "photoshopScript.jsx\""]);
    } else if (Qt.platform.os == "osx") {
      alg.subprocess.startDetached(["open", "-a", alg.settings.value("photoshopPath", "").split(' ').join('\ '), this.exportPath.split(' ').join('\ ') + "photoshopScript.jsx"]);
    }
  }
}

PhotoshopExporter.prototype = {

  /*
  * Main function of the script
  * Browsing of all layers into the document structure
  */
  run: function() {
    function documentNbStacks(document) {
      return document.materials
        .map(function(m) {return m.stacks.length})
        .reduce(function(a, b){ return a + b}, 0);
    }
    function elementNbLayers(element) {
      var nbLayers = 1;
      if (element.layers != undefined) {
        nbLayers = element.layers
          .map(elementNbLayers)
          .reduce(function(a, b){ return a + b}, 0);
      }
      return nbLayers + (element.hasMask? 1 : 0);
    }
    var self = this;
    function createProgressMethod(progressBar, total) {
      var progression = 1;
      return function() {
        if (progressBar === "layer") {
          var stackPath = [self.materialName, self.stackName, self.channel].filter(function(e) {return e}).join("/");
          self.logUserInfo("Exporting " + stackPath + " layers and masks: " + progression + "/" + total);
        }
        self.photoshopScript +=
          "progressBar." + progressBar + ".value = " + 100/total*(progression++) + ";\n";
      }
    }

    var doc_str = alg.mapexport.documentStructure();
    var stackProgress = createProgressMethod("stack", documentNbStacks(doc_str));

    //Browse material
    for (var materialId in doc_str.materials) {
      var material = doc_str.materials[materialId];
      this.materialName = material.name;
      //Browse stacks
      for (var stackId in material.stacks) {
        //Update the progress bar
        stackProgress();
        var stack = material.stacks[stackId];
        var totalLayers = elementNbLayers(stack);
        var progressChannel = createProgressMethod("channel", stack.channels.length);
        this.stackName = stack.name;
        //Browse channels
        for (var channelId in stack.channels) {
          //Update the progress bar
          progressChannel();
          this.channel = stack.channels[channelId];
          var channelFormat = alg.mapexport.channelFormat([this.materialName, this.stackName],this.channel)
          var bitDepth = alg.settings.value("bitDepth", -1)
          this.exportConfig.bitDepth = bitDepth == -1 ? channelFormat.bitDepth : bitDepth
          //PNG export of a channel snapshot into the path export
          var filename = this.createFilename(".png");
          var exportConfig = this.exportConfig.clone()
          exportConfig.keepAlpha = false
          alg.mapexport.save([this.materialName, this.stackName, this.channel], filename, exportConfig);

          //Create a new document into photoshop
          this.photoshopScript += this.newPSDDocumentStr(filename);
          //Browse layers roots forest
          var progressLayer = createProgressMethod("layer", totalLayers);
          for (var layerId = 0; layerId < stack.layers.length; ++layerId) {
            var layer = stack.layers[layerId];
            //Browse layer tree from root
            this.layersDFS(layer, progressLayer);
          }

          //Rasterize all layers
          this.photoshopScript += "app.activeDocument.rasterizeAllLayers(); \n";
          //Update the progress bar
          this.photoshopScript += "progressBar.layer.value = 0; \n";
          //Gamma correction for sRGB channel
          if(this.channel == "basecolor" || this.channel == "diffuse" || this.channel == "specular" || this.channel == "emissive" || this.channel == "transmissive" ) {
            this.photoshopScript += " convert_to_profile(); \n";
          }
          // Add default background in normal channel
          if(this.channel === "normal") {
            this.photoshopScript += this.newFillLayerStr("Background", {R:128, G:128, B:255});
            this.photoshopScript += "app.activeDocument.activeLayer.move(app.activeDocument, ElementPlacement.PLACEATEND); \n";
          }
          //Move the snapshot to the document head
          this.photoshopScript += "snapshot.move(app.activeDocument, ElementPlacement.PLACEATBEGINNING); \n";
          this.photoshopScript += "app.activeDocument.activeLayer = snapshot; \n";
          //Hide the snapshot
          this.photoshopScript += "snapshot.visible = false; \n";
          //Save the psd
          this.photoshopScript += " app.activeDocument.saveAs(File(\"" + this.createFilename() + "\")); \n";
        }
        //Update the progress bar
        this.photoshopScript += "progressBar.channel.value = 0; \n";
      }
    }
  },

  /*
   * Recursive function to explore a hierarchy of layers
   * Leaf has exported as photoshop layer
   * Folder has exported as photoshop groupe
   */
  layersDFS: function(layer, progressLayer) {
    //The layer is a leaf
    if (layer.layers == undefined) {
      //PNG export of the leaf into the path export
      var filename = this.createFilename("_" + layer.uid + ".png");
      alg.mapexport.save([layer.uid, this.channel], filename, this.exportConfig);
      progressLayer();
      //Create the layer into photoshop
      this.photoshopScript += this.newLayerStr(filename, layer, this.channel);
      //Add his mask if exist
      if (layer.hasMask == true) {
        this.addMask(layer, progressLayer);
      }
    }
    //The layer is a folder
    else {
      //Create the folder into photoshop
      this.photoshopScript += this.newFolderStr(layer, this.channel);
      //Add his mask if exist
      if (layer.hasMask == true) {
        this.addMask(layer, progressLayer);
      }
      //Browse layer tree from the current layer
      for (var layerId = 0; layerId < layer.layers.length; ++layerId) {
        this.layersDFS(layer.layers[layerId], progressLayer);
      }
      //Pull folder up
      this.photoshopScript += " app.activeDocument.activeLayer = folders.pop();\n";
      // Need to set folder visibility once all the layers inside have been added otherwise it will always be
      // overriden to true
      this.photoshopScript += " app.activeDocument.activeLayer.visible = " + (layer.enabled? "true" : "false") + ";";
    }
  },

  /*
   * Add the layer/folder mask if exist
   */
  addMask: function(layer, progressLayer) {
    //PNG export of the mask into the path export
    var filename = this.createFilename("_" + layer.uid + "_mask.png");
    alg.mapexport.save([layer.uid, "mask"], filename, this.exportConfig);
    progressLayer();
    //Create the mask into photoshop
    this.photoshopScript += this.newMaskStr(filename);
  },

  /**********Photoshop generation script**********/

  createFilename: function(concate) {
    concate = concate || ''
    return (this.exportPath + this.materialName + "_" +this.stackName + "_" + this.channel + concate).replace("__", "_");
  },

  /*
   * Return the string to open a new photoshop document
   */
  newPSDDocumentStr: function(filename) {
    return "\n\n//New Document \n\
   var exportFile = File(\"" + filename + "\"); \n\
   open(exportFile); \n\
   exportFile.remove();
   var folders = []; \n\
   folders.push(app.activeDocument); \n\
   var snapshot = app.activeDocument.activeLayer; \n\
   snapshot.name = \"snapshot\"; ";
  },

  /*
   * Return the string to assign a mask to a photoshop layer
   */
  newMaskStr: function(filename) {
    return " //Add mask \n\
   var maskFile = File(\"" + filename + "\"); \n\
   open_png(maskFile); \n\
   maskFile.remove(); \n\
   layerToMask();";
  },

  /*
   * Return the string to create a new photoshop folder
   */
  newFolderStr: function(folder, channel) {
    var blending = alg.mapexport.layerBlendingModes(folder.uid)[channel];
    return "\n\n //Add folder \n\
   folders.push(folders[folders.length - 1].layerSets.add()); \n\
   app.activeDocument.activeLayer.opacity = " + blending.opacity + ";\n\
   " + this.convertBlendingMode(blending.mode, 1) + "; \n\
   app.activeDocument.activeLayer.name = \"" + folder.name + "\"; ";
  },

  /*
   * Return the string to create a new photoshop layer
   */
  newLayerStr: function(filename, layer, channel) {
    var blending = alg.mapexport.layerBlendingModes(layer.uid)[channel];
    return "\n\n //Add layer \n\
   folders[folders.length - 1].artLayers.add(); \n\
   var layerFile = File(\"" + filename + "\"); \n\
   open_png(layerFile); \n\
   layerFile.remove(); \n\
   app.activeDocument.activeLayer.opacity = " + blending.opacity + ";\n\
   " + this.convertBlendingMode(blending.mode, 0) + ";\n\
   app.activeDocument.activeLayer.name = \"" + layer.name + "\";\n\
   app.activeDocument.activeLayer.visible = " + (layer.enabled? "true" : "false") + ";";
  },

  /*
   * Return the string to create a new fill layer
   */
  newFillLayerStr: function(name, color) {
    return "\n\n //Add fill layer \n\
   var layer = folders[folders.length - 1].artLayers.add(); \n\
   app.activeDocument.activeLayer.name = \"" + name + "\"; \n\
   fillSolidColour(" + color.R + "," + color.G + "," + color.B + ");\n\
   ";
  },

  /*
   * Return the string to assign a blending mode to the current photoshop layer/folder
   * Folder in Passthrough mode have to be assign to PASSTHROUGH but layer
   */
  convertBlendingMode: function(painterMode, isFolder) {
    var blendingMode = "app.activeDocument.activeLayer.blendMode = BlendMode.";
    if (painterMode == "Passthrough") {
      if (isFolder == 1) {
        blendingMode = blendingMode + "PASSTHROUGH";
      } else {
        blendingMode = blendingMode + "NORMAL";
      }
      return blendingMode;
    }
    switch(painterMode) {
    case "Normal":
    case "Replace":                      blendingMode = blendingMode + "NORMAL";
      break;
    case "Multiply":                     blendingMode = blendingMode + "MULTIPLY"; break;
    case "Divide":                       blendingMode = blendingMode + "DIVIDE"; break;
    case "Linear dodge (Add)":           blendingMode = blendingMode + "LINEARDODGE"; break;
    case "Subtract":                     blendingMode = blendingMode + "SUBTRACT"; break;
    case "Difference":                   blendingMode = blendingMode + "DIFFERENCE"; break;
    case "Exclusion":                    blendingMode = blendingMode + "EXCLUSION"; break;
    case "Overlay":                      blendingMode = blendingMode + "OVERLAY"; break;
    case "Screen":                       blendingMode = blendingMode + "SCREEN"; break;
    case "Linear burn":                  blendingMode = blendingMode + "LINEARBURN"; break;
    case "Color burn":                   blendingMode = blendingMode + "COLORBURN"; break;
    case "Color dodge":                  blendingMode = blendingMode + "COLORDODGE"; break;
    case "Soft light":                   blendingMode = blendingMode + "SOFTLIGHT"; break;
    case "Hard light":                   blendingMode = blendingMode + "HARDLIGHT"; break;
    case "Vivid light":                  blendingMode = blendingMode + "VIVIDLIGHT"; break;
    case "Pin light":                    blendingMode = blendingMode + "PINLIGHT"; break;
    case "Saturation":                   blendingMode = blendingMode + "SATURATION"; break;
    case "Color":                        blendingMode = blendingMode + "COLORBLEND"; break;
    case "Normal map combine":           blendingMode = "Overlay_Normal()"; break;
    case "Normal map detail":            blendingMode = "Overlay_Normal()"; break;
    case "Normal map inverse detail":    blendingMode = "Overlay_Normal()"; break;
    case "Disable":
    case "Inverse divide":
    case "Darken (Min)":
    case "Lighten (Max)":
    case "Inverse Subtract":
    case "Signed addition (AddSub)":
    case "Tint":
    case "Value":
    default:
      blendingMode = ""
    }
    return blendingMode;
  }

}

function importPainterDocument(callback) {
  new PhotoshopExporter(callback);
}
<commit_msg>Remove old comment<commit_after>// Copyright (C) 2016 Allegorithmic
//
// This software may be modified and distributed under the terms
// of the MIT license.  See the LICENSE file for details.

function ExportConfig() {
  this.padding = "Infinite"
  this.dilation = 0
  this.bitDepth = 8
  this.keepAlpha = true
}

ExportConfig.prototype = {
  clone: function() {
    var conf = new ExportConfig
    conf.padding = this.padding
    conf.dilation = this.dilation
    conf.bitDepth = this.bitDepth
    conf.keepAlpha = this.keepAlpha
    return conf
  },

  usePadding : function(val) {
    this.padding = (val === true) ? "Infinite" : "Transparent"
  }
}

function PhotoshopExporter(callback) {
  this.logUserInfo =
    function logUserInfo(str) {
      if (callback) {
        callback(str)
      }
      else {
        alg.log.info(""+str+"")
      }
    }

  //Padding's struct
  this.exportConfig = new ExportConfig()
  this.exportConfig.usePadding(alg.settings.value("padding", false))

  //Get the project name
  var projectName = alg.project.name()

  //The export path is the working directory
  this.exportPath = alg.mapexport.exportPath() + "/" + projectName + "_photoshop_export/";

  //Add the header photoshop script
  var headerScript = alg.fileIO.open(alg.plugin_root_directory + "/header.jsx", 'r');
  this.photoshopScript = headerScript.readAll();
  headerScript.close();

  //Run the script
  this.run(this);

  //Add the footer photoshop script
  var footerScript = alg.fileIO.open(alg.plugin_root_directory + "/footer.jsx", 'r');
  this.photoshopScript += footerScript.readAll();
  footerScript.close();

  try{
    var scriptFile = alg.fileIO.open(this.exportPath + "/photoshopScript.jsx", 'w');
    scriptFile.write(this.photoshopScript);
    scriptFile.close();
  } catch (error) {
    alg.log.error(error.message);
    return;
  }

  this.logUserInfo("Export done");
  if (alg.settings.value("launchPhotoshop", false)) {
    this.logUserInfo("Starting Photoshop...");
    if (Qt.platform.os == "windows") {
      alg.subprocess.startDetached(["\"" + alg.settings.value("photoshopPath", "") + "\"", "\"" + this.exportPath.split('/').join('\\') + "photoshopScript.jsx\""]);
    } else if (Qt.platform.os == "osx") {
      alg.subprocess.startDetached(["open", "-a", alg.settings.value("photoshopPath", "").split(' ').join('\ '), this.exportPath.split(' ').join('\ ') + "photoshopScript.jsx"]);
    }
  }
}

PhotoshopExporter.prototype = {

  /*
  * Main function of the script
  * Browsing of all layers into the document structure
  */
  run: function() {
    function documentNbStacks(document) {
      return document.materials
        .map(function(m) {return m.stacks.length})
        .reduce(function(a, b){ return a + b}, 0);
    }
    function elementNbLayers(element) {
      var nbLayers = 1;
      if (element.layers != undefined) {
        nbLayers = element.layers
          .map(elementNbLayers)
          .reduce(function(a, b){ return a + b}, 0);
      }
      return nbLayers + (element.hasMask? 1 : 0);
    }
    var self = this;
    function createProgressMethod(progressBar, total) {
      var progression = 1;
      return function() {
        if (progressBar === "layer") {
          var stackPath = [self.materialName, self.stackName, self.channel].filter(function(e) {return e}).join("/");
          self.logUserInfo("Exporting " + stackPath + " layers and masks: " + progression + "/" + total);
        }
        self.photoshopScript +=
          "progressBar." + progressBar + ".value = " + 100/total*(progression++) + ";\n";
      }
    }

    var doc_str = alg.mapexport.documentStructure();
    var stackProgress = createProgressMethod("stack", documentNbStacks(doc_str));

    //Browse material
    for (var materialId in doc_str.materials) {
      var material = doc_str.materials[materialId];
      this.materialName = material.name;
      //Browse stacks
      for (var stackId in material.stacks) {
        //Update the progress bar
        stackProgress();
        var stack = material.stacks[stackId];
        var totalLayers = elementNbLayers(stack);
        var progressChannel = createProgressMethod("channel", stack.channels.length);
        this.stackName = stack.name;
        //Browse channels
        for (var channelId in stack.channels) {
          //Update the progress bar
          progressChannel();
          this.channel = stack.channels[channelId];
          var channelFormat = alg.mapexport.channelFormat([this.materialName, this.stackName],this.channel)
          var bitDepth = alg.settings.value("bitDepth", -1)
          this.exportConfig.bitDepth = bitDepth == -1 ? channelFormat.bitDepth : bitDepth
          //PNG export of a channel snapshot into the path export
          var filename = this.createFilename(".png");
          var exportConfig = this.exportConfig.clone()
          exportConfig.keepAlpha = false
          alg.mapexport.save([this.materialName, this.stackName, this.channel], filename, exportConfig);

          //Create a new document into photoshop
          this.photoshopScript += this.newPSDDocumentStr(filename);
          //Browse layers roots forest
          var progressLayer = createProgressMethod("layer", totalLayers);
          for (var layerId = 0; layerId < stack.layers.length; ++layerId) {
            var layer = stack.layers[layerId];
            //Browse layer tree from root
            this.layersDFS(layer, progressLayer);
          }

          //Rasterize all layers
          this.photoshopScript += "app.activeDocument.rasterizeAllLayers(); \n";
          //Update the progress bar
          this.photoshopScript += "progressBar.layer.value = 0; \n";
          //Gamma correction for sRGB channel
          if(this.channel == "basecolor" || this.channel == "diffuse" || this.channel == "specular" || this.channel == "emissive" || this.channel == "transmissive" ) {
            this.photoshopScript += " convert_to_profile(); \n";
          }
          // Add default background in normal channel
          if(this.channel === "normal") {
            this.photoshopScript += this.newFillLayerStr("Background", {R:128, G:128, B:255});
            this.photoshopScript += "app.activeDocument.activeLayer.move(app.activeDocument, ElementPlacement.PLACEATEND); \n";
          }
          //Move the snapshot to the document head
          this.photoshopScript += "snapshot.move(app.activeDocument, ElementPlacement.PLACEATBEGINNING); \n";
          this.photoshopScript += "app.activeDocument.activeLayer = snapshot; \n";
          //Hide the snapshot
          this.photoshopScript += "snapshot.visible = false; \n";
          //Save the psd
          this.photoshopScript += " app.activeDocument.saveAs(File(\"" + this.createFilename() + "\")); \n";
        }
        //Update the progress bar
        this.photoshopScript += "progressBar.channel.value = 0; \n";
      }
    }
  },

  /*
   * Recursive function to explore a hierarchy of layers
   * Leaf has exported as photoshop layer
   * Folder has exported as photoshop groupe
   */
  layersDFS: function(layer, progressLayer) {
    //The layer is a leaf
    if (layer.layers == undefined) {
      //PNG export of the leaf into the path export
      var filename = this.createFilename("_" + layer.uid + ".png");
      alg.mapexport.save([layer.uid, this.channel], filename, this.exportConfig);
      progressLayer();
      //Create the layer into photoshop
      this.photoshopScript += this.newLayerStr(filename, layer, this.channel);
      //Add his mask if exist
      if (layer.hasMask == true) {
        this.addMask(layer, progressLayer);
      }
    }
    //The layer is a folder
    else {
      //Create the folder into photoshop
      this.photoshopScript += this.newFolderStr(layer, this.channel);
      //Add his mask if exist
      if (layer.hasMask == true) {
        this.addMask(layer, progressLayer);
      }
      //Browse layer tree from the current layer
      for (var layerId = 0; layerId < layer.layers.length; ++layerId) {
        this.layersDFS(layer.layers[layerId], progressLayer);
      }
      //Pull folder up
      this.photoshopScript += " app.activeDocument.activeLayer = folders.pop();\n";
      // Need to set folder visibility once all the layers inside have been added otherwise it will always be
      // overriden to true
      this.photoshopScript += " app.activeDocument.activeLayer.visible = " + (layer.enabled? "true" : "false") + ";";
    }
  },

  /*
   * Add the layer/folder mask if exist
   */
  addMask: function(layer, progressLayer) {
    //PNG export of the mask into the path export
    var filename = this.createFilename("_" + layer.uid + "_mask.png");
    alg.mapexport.save([layer.uid, "mask"], filename, this.exportConfig);
    progressLayer();
    //Create the mask into photoshop
    this.photoshopScript += this.newMaskStr(filename);
  },

  /**********Photoshop generation script**********/

  createFilename: function(concate) {
    concate = concate || ''
    return (this.exportPath + this.materialName + "_" +this.stackName + "_" + this.channel + concate).replace("__", "_");
  },

  /*
   * Return the string to open a new photoshop document
   */
  newPSDDocumentStr: function(filename) {
    return "\n\n//New Document \n\
   var exportFile = File(\"" + filename + "\"); \n\
   open(exportFile); \n\
   exportFile.remove();
   var folders = []; \n\
   folders.push(app.activeDocument); \n\
   var snapshot = app.activeDocument.activeLayer; \n\
   snapshot.name = \"snapshot\"; ";
  },

  /*
   * Return the string to assign a mask to a photoshop layer
   */
  newMaskStr: function(filename) {
    return " //Add mask \n\
   var maskFile = File(\"" + filename + "\"); \n\
   open_png(maskFile); \n\
   maskFile.remove(); \n\
   layerToMask();";
  },

  /*
   * Return the string to create a new photoshop folder
   */
  newFolderStr: function(folder, channel) {
    var blending = alg.mapexport.layerBlendingModes(folder.uid)[channel];
    return "\n\n //Add folder \n\
   folders.push(folders[folders.length - 1].layerSets.add()); \n\
   app.activeDocument.activeLayer.opacity = " + blending.opacity + ";\n\
   " + this.convertBlendingMode(blending.mode, 1) + "; \n\
   app.activeDocument.activeLayer.name = \"" + folder.name + "\"; ";
  },

  /*
   * Return the string to create a new photoshop layer
   */
  newLayerStr: function(filename, layer, channel) {
    var blending = alg.mapexport.layerBlendingModes(layer.uid)[channel];
    return "\n\n //Add layer \n\
   folders[folders.length - 1].artLayers.add(); \n\
   var layerFile = File(\"" + filename + "\"); \n\
   open_png(layerFile); \n\
   layerFile.remove(); \n\
   app.activeDocument.activeLayer.opacity = " + blending.opacity + ";\n\
   " + this.convertBlendingMode(blending.mode, 0) + ";\n\
   app.activeDocument.activeLayer.name = \"" + layer.name + "\";\n\
   app.activeDocument.activeLayer.visible = " + (layer.enabled? "true" : "false") + ";";
  },

  /*
   * Return the string to create a new fill layer
   */
  newFillLayerStr: function(name, color) {
    return "\n\n //Add fill layer \n\
   var layer = folders[folders.length - 1].artLayers.add(); \n\
   app.activeDocument.activeLayer.name = \"" + name + "\"; \n\
   fillSolidColour(" + color.R + "," + color.G + "," + color.B + ");\n\
   ";
  },

  /*
   * Return the string to assign a blending mode to the current photoshop layer/folder
   * Folder in Passthrough mode have to be assign to PASSTHROUGH but layer
   */
  convertBlendingMode: function(painterMode, isFolder) {
    var blendingMode = "app.activeDocument.activeLayer.blendMode = BlendMode.";
    if (painterMode == "Passthrough") {
      if (isFolder == 1) {
        blendingMode = blendingMode + "PASSTHROUGH";
      } else {
        blendingMode = blendingMode + "NORMAL";
      }
      return blendingMode;
    }
    switch(painterMode) {
    case "Normal":
    case "Replace":                      blendingMode = blendingMode + "NORMAL";
      break;
    case "Multiply":                     blendingMode = blendingMode + "MULTIPLY"; break;
    case "Divide":                       blendingMode = blendingMode + "DIVIDE"; break;
    case "Linear dodge (Add)":           blendingMode = blendingMode + "LINEARDODGE"; break;
    case "Subtract":                     blendingMode = blendingMode + "SUBTRACT"; break;
    case "Difference":                   blendingMode = blendingMode + "DIFFERENCE"; break;
    case "Exclusion":                    blendingMode = blendingMode + "EXCLUSION"; break;
    case "Overlay":                      blendingMode = blendingMode + "OVERLAY"; break;
    case "Screen":                       blendingMode = blendingMode + "SCREEN"; break;
    case "Linear burn":                  blendingMode = blendingMode + "LINEARBURN"; break;
    case "Color burn":                   blendingMode = blendingMode + "COLORBURN"; break;
    case "Color dodge":                  blendingMode = blendingMode + "COLORDODGE"; break;
    case "Soft light":                   blendingMode = blendingMode + "SOFTLIGHT"; break;
    case "Hard light":                   blendingMode = blendingMode + "HARDLIGHT"; break;
    case "Vivid light":                  blendingMode = blendingMode + "VIVIDLIGHT"; break;
    case "Pin light":                    blendingMode = blendingMode + "PINLIGHT"; break;
    case "Saturation":                   blendingMode = blendingMode + "SATURATION"; break;
    case "Color":                        blendingMode = blendingMode + "COLORBLEND"; break;
    case "Normal map combine":           blendingMode = "Overlay_Normal()"; break;
    case "Normal map detail":            blendingMode = "Overlay_Normal()"; break;
    case "Normal map inverse detail":    blendingMode = "Overlay_Normal()"; break;
    case "Disable":
    case "Inverse divide":
    case "Darken (Min)":
    case "Lighten (Max)":
    case "Inverse Subtract":
    case "Signed addition (AddSub)":
    case "Tint":
    case "Value":
    default:
      blendingMode = ""
    }
    return blendingMode;
  }

}

function importPainterDocument(callback) {
  new PhotoshopExporter(callback);
}
<|endoftext|>


<commit_before>'use strict';
angular.module('copayApp.directives')
  .directive('validAddress', ['$rootScope', 'bitcore', 'bitcoreCash', 'bitcoinCashJsService',
    function($rootScope, bitcore, bitcoreCash, bitcoinCashJsService) {
      return {
        require: 'ngModel',
        link: function(scope, elem, attrs, ctrl) {
          // Bitcoin address
          var URI = bitcore.URI;
          var Address = bitcore.Address

          // Bitcoin Cash address
          var URICash = bitcoreCash.URI;
          var AddressCash = bitcoreCash.Address

          var validator = function(value) {

            if (value.indexOf('bitcoincash:') >= 0 || value[0] == 'C' || value[0] == 'H' || value[0] == 'p' || value[0] == 'q') {
              if (value.indexOf('bitcoincash:') < 0) {
                value = 'bitcoincash:' + value;
              }
              value = bitcoinCashJsService.readAddress(value).legacy;
            }

            // Regular url
            if (/^https?:\/\//.test(value)) {
              ctrl.$setValidity('validAddress', true);
              return value;
            }

            // Bip21 uri
            var uri, isAddressValidLivenet, isAddressValidTestnet;
            if (/^bitcoin:/.test(value)) {
              var isUriValid = URI.isValid(value);
              if (isUriValid) {
                uri = new URI(value);
                isAddressValidLivenet = Address.isValid(uri.address.toString(), 'livenet')
                isAddressValidTestnet = Address.isValid(uri.address.toString(), 'testnet')
              }
              ctrl.$setValidity('validAddress', isUriValid && (isAddressValidLivenet || isAddressValidTestnet));
              return value;
            } else if (/^bitcoincash:/.test(value)) {
              var isUriValid = URICash.isValid(value);
              if (isUriValid) {
                uri = new URICash(value);
                isAddressValidLivenet = AddressCash.isValid(uri.address.toString(), 'livenet')
              }
              ctrl.$setValidity('validAddress', isUriValid && (isAddressValidLivenet));
              return value;
            }

            if (typeof value == 'undefined') {
              ctrl.$pristine = true;
              return;
            }

            // Regular Address: try Bitcoin and Bitcoin Cash
            var regularAddressLivenet = Address.isValid(value, 'livenet');
            var regularAddressTestnet = Address.isValid(value, 'testnet');
            var regularAddressCashLivenet = AddressCash.isValid(value, 'livenet');
            ctrl.$setValidity('validAddress', (regularAddressLivenet || regularAddressTestnet || regularAddressCashLivenet));
            return value;
          };

          ctrl.$parsers.unshift(validator);
          ctrl.$formatters.unshift(validator);
        }
      };
    }
  ])
  .directive('validAmount', ['configService',
    function(configService) {

      return {
        require: 'ngModel',
        link: function(scope, element, attrs, ctrl) {
          var val = function(value) {
            var settings = configService.getSync().wallet.settings;
            var vNum = Number((value * settings.unitToSatoshi).toFixed(0));
            if (typeof value == 'undefined' || value == 0) {
              ctrl.$pristine = true;
            }

            if (typeof vNum == "number" && vNum > 0) {
              if (vNum > Number.MAX_SAFE_INTEGER) {
                ctrl.$setValidity('validAmount', false);
              } else {
                var decimals = Number(settings.unitDecimals);
                var sep_index = ('' + value).indexOf('.');
                var str_value = ('' + value).substring(sep_index + 1);
                if (sep_index >= 0 && str_value.length > decimals) {
                  ctrl.$setValidity('validAmount', false);
                  return;
                } else {
                  ctrl.$setValidity('validAmount', true);
                }
              }
            } else {
              ctrl.$setValidity('validAmount', false);
            }
            return value;
          }
          ctrl.$parsers.unshift(val);
          ctrl.$formatters.unshift(val);
        }
      };
    }
  ])
  .directive('walletSecret', function(bitcore) {
    return {
      require: 'ngModel',
      link: function(scope, elem, attrs, ctrl) {
        var validator = function(value) {
          if (value.length > 0) {
            var m = value.match(/^[0-9A-HJ-NP-Za-km-z]{70,80}$/);
            ctrl.$setValidity('walletSecret', m ? true : false);
          }
          return value;
        };

        ctrl.$parsers.unshift(validator);
      }
    };
  })
  .directive('ngFileSelect', function() {
    return {
      link: function($scope, el) {
        el.bind('change', function(e) {
          $scope.formData.file = (e.srcElement || e.target).files[0];
          $scope.getFile();
        });
      }
    }
  })
  .directive('contact', ['addressbookService', 'lodash',
    function(addressbookService, lodash) {
      return {
        restrict: 'E',
        link: function(scope, element, attrs) {
          var addr = attrs.address;
          addressbookService.get(addr, function(err, ab) {
            if (ab) {
              var name = lodash.isObject(ab) ? ab.name : ab;
              element.append(name);
            } else {
              element.append(addr);
            }
          });
        }
      };
    }
  ])
  .directive('ignoreMouseWheel', function($rootScope, $timeout) {
    return {
      restrict: 'A',
      link: function(scope, element, attrs) {
        element.bind('mousewheel', function(event) {
          element[0].blur();
          $timeout(function() {
            element[0].focus();
          }, 1);
        });
      }
    }
  })
  .directive('validDate', function() {
    return {
      require: 'ngModel',
      link: function(scope, elem, attr, ctrl) {
        ctrl.$validators.validDate = function(modelValue, viewValue) {
          // Expected Format is DD/MM/YYYY
          if (ctrl.$isEmpty(modelValue)) {
            // consider empty models to be valid
            return true;
          }
          var now = new Date();
          if (viewValue.match(/\d{2}\/\d{2}\/\d{4}/g)) {
            var split = viewValue.split(/\//);
            return parseInt(split[0]) <= 31 &&
              parseInt(split[0]) > 0 &&
              parseInt(split[1]) <= 12 &&
              parseInt(split[1]) > 0 &&
              (parseInt(split[1])) > 0;
          }

          return false;
        };
      }
    };
  })
  .directive('validExpiration', function() {
    return {
      require: 'ngModel',
      link: function(scope, elem, attr, ctrl) {
        ctrl.$validators.validExpiration = function(modelValue, viewValue) {
          if (ctrl.$isEmpty(modelValue)) {
            // consider empty models to be valid
            return true;
          }
          var now = new Date();
          if (viewValue.match(/\d{2}\/\d{2}/g)) {
            var split = viewValue.split(/\//);
            return parseInt(split[0]) <= 12 &&
              parseInt(split[0]) > 0 &&
              (2000 + parseInt(split[1])) >= now.getFullYear();
          }

          return false;
        };
      }
    };
  })
  .directive('maskedAmount', function() {
    return {
      require: 'ngModel',
      link: function(scope, elem, attr, ngModel) {
        // Masks amounts to the format of 999999999.99

        function addSpaces(value) {
          if(typeof(value) == typeof(undefined)) {
            return value;
          }
          var parsedValue = value.toString()
            .replace(/^0+(\d)/g,'$1')
            .replace(/^(\d{6})(\d+)$/g, '$1')
            .replace(/[^\d.]/g, '')
            .replace(/\/$/, '').trim();
          return parsedValue;
        }

        function removeSpaces(value) {
          if (typeof(value) == typeof(undefined)) {
            return value;
          }

          var parsedValue = value.toString().replace(/\s/g, '');
          return parsedValue;
        }

        function parseViewValue(value) {
          var viewValue = addSpaces(value);
          ngModel.$viewValue = viewValue;
          ngModel.$render();

          // Return what we want the model value to be
          return removeSpaces(viewValue);
        }

        function formatModelValue(value) {
          var modelValue = removeSpaces(value);
          ngModel.$modelValue = modelValue;
          return addSpaces(modelValue);
        }

        ngModel.$parsers.push(parseViewValue);
        ngModel.$formatters.push(formatModelValue);
      }
    }
  })
  .directive('maskedDate', function() {
    return {
      require: 'ngModel',
      link: function(scope, elem, attr, ngModel) {
        // Masks expirations to the format of 0000 0000 0000 0000

        var originalValue = '';
        var groupValue = 2;
        var groupIndex = 0;
        var separtor = '/';
        var maxDigit = 10;

        function isGroupFullyComplete(newValue) {
          // Check if a group is fully completed, if yes, let's format that
          var countOfNumbers = 0;
          var isDiff = false;
          for (var i = 0; i < newValue.length; i++) {
            var element = newValue[i];

            if (!isDiff && i < originalValue.length && element != originalValue[i]) {
              isDiff = true;
            }

            if (element == separtor) {
              if (isDiff) return false;
              countOfNumbers = 0;
              groupIndex++;
            }
            else countOfNumbers++;

            if (isDiff && countOfNumbers%(groupValue * (groupIndex > 2 ? 2 : 1)) == 0) return true;
          }

          return false
        }

        function addSpaces(value) {
          if(typeof(value) == typeof(undefined)) {
            return value;
          }

          var parsedValue = value.toString()
            .replace(/[^\d]/g, '')
            .replace(/^(\d{2})$/g, '$1//')
            .replace(/^(\d{2})(\d?.)$/g, '$1/$2')
            .replace(/^(\d{2})\/(\d{2})$/g, '$1/$2//')
            .replace(/^(\d{2})(\d{2})(\d+)$/g, '$1/$2/$3')
            .replace(/\/$/, '');
          return parsedValue.slice(0,10);
        }
        function removeSpaces(value) {
          if (typeof(value) == typeof(undefined)) {
            return value;
          }

          var parsedValue = value.toString().replace(/\s/g, '');
          return parsedValue;
        }

        function parseViewValue(value) {
          var viewValue = value;

          // Need to remove the right part
          if (viewValue.length >= maxDigit
            || originalValue[originalValue.length - 1] != viewValue[viewValue.length - 1]   // Complete at the end
            || isGroupFullyComplete(viewValue)) { // If a new one fully grouped, lets format that by the regex
            viewValue = addSpaces(viewValue);
          }

          if (typeof viewValue !== 'undefined') {
            originalValue = viewValue;
          }

          ngModel.$viewValue = viewValue;
          ngModel.$render();

          return removeSpaces(viewValue);
        }

        function formatModelValue(value) {
          var modelValue = removeSpaces(value);
          ngModel.$modelValue = modelValue;
          return addSpaces(modelValue);
        }

        ngModel.$parsers.push(parseViewValue);
        //ngModel.$formatters.push(formatModelValue);
      }
    }
  })
  .directive('maskedCreditCard', function() {
    return {
      require: 'ngModel',
      link: function(scope, elem, attr, ngModel) {
        // Masks expirations to the format of 0000 0000 0000 0000

        function addSpaces(value) {
          if(typeof(value) == typeof(undefined)) {
            return value;
          }

          var parsedValue = value.toString()
            .replace(/[^\d]/g, '')
            .replace(/(.{4})/g, '$1 ').trim()
            .replace(/\/$/, '');
          return parsedValue.slice(0,19);
        }

        function removeSpaces(value) {
          if (typeof(value) == typeof(undefined)) {
            return value;
          }

          var parsedValue = value.toString().replace(/\s/g, '');
          return parsedValue;
        }

        var originalValue = '';
        var groupValue = 4;
        var separtor = ' ';
        var maxDigit = 19;

        function isGroupFullyComplete(newValue) {
          // Check if a group is fully completed, if yes, let's format that
          var countOfNumbers = 0;
          var isDiff = false;
          for (var i = 0; i < newValue.length; i++) {
            var element = newValue[i];

            if (!isDiff && i < originalValue.length && element != originalValue[i]) {
              isDiff = true;
            }

            if (element == separtor) {
              if (isDiff) return false;
              countOfNumbers = 0;
            }
            else countOfNumbers++;

            if (isDiff && countOfNumbers%groupValue == 0) return true;
          }

          return false
        }

        function parseViewValue(value) {

          var viewValue = value;

          // Need to remove the right part
          if (viewValue.length >= maxDigit
            || originalValue[originalValue.length - 1] != viewValue[viewValue.length - 1]   // Complete at the end
            || isGroupFullyComplete(viewValue)) { // If a new one fully grouped, lets format that by the regex
            viewValue = addSpaces(viewValue);
          }

          if (typeof viewValue !== 'undefined') {
            originalValue = viewValue;
          }

          ngModel.$viewValue = viewValue;
          ngModel.$render();

          return removeSpaces(viewValue);
        }

        ngModel.$parsers.push(parseViewValue);
      }
    }
  })
  .directive('maskedExpiration', function() {
    return {
      require: 'ngModel',
      link: function(scope, elem, attr, ngModel) {
        // Masks expirations to the format of MM/YY

        var originalValue = '';
        var groupValue = 2;
        var separtor = '/';
        var maxDigit = 5;

        function isGroupFullyComplete(newValue) {
          // Check if a group is fully completed, if yes, let's format that
          var countOfNumbers = 0;
          var isDiff = false;
          for (var i = 0; i < newValue.length; i++) {
            var element = newValue[i];

            if (!isDiff && i < originalValue.length && element != originalValue[i]) {
              isDiff = true;
            }

            if (element == separtor) {
              if (isDiff) return false;
              countOfNumbers = 0;
            }
            else countOfNumbers++;

            if (isDiff && countOfNumbers%groupValue == 0) return true;
          }

          return false
        }

        function addSpaces(value) {
          if(typeof(value) == typeof(undefined)) {
            return value;
          }

          var parsedValue = value.toString()
            .replace(/[^\d]/g, '')
            .replace(/^(\d{2})$/g, '$1//').trim()
            .replace(/^(\d{2})(\d+)$/g, '$1/$2').trim()
            .replace(/\/$/, '');
          return parsedValue.slice(0,5);
        }

        function removeSpaces(value) {
          if (typeof(value) == typeof(undefined)) {
            return value;
          }

          var parsedValue = value.toString().replace(/\s/g, '').replace(/\//g, '');
          return parsedValue;
        }

        function parseViewValue(value) {

          var viewValue = value;

          // Need to remove the right part
          if (viewValue.length >= maxDigit
            || originalValue[originalValue.length - 1] != viewValue[viewValue.length - 1]   // Complete at the end
            || isGroupFullyComplete(viewValue)) { // If a new one fully grouped, lets format that by the regex
            viewValue = addSpaces(viewValue);
          }

          if (typeof viewValue !== 'undefined') {
            originalValue = viewValue;
          }

          ngModel.$viewValue = viewValue;
          ngModel.$render();

          return removeSpaces(viewValue);
        }

        ngModel.$parsers.push(parseViewValue);
      }
    }
  });
<commit_msg>Resolved error with ngFormat on amount page.<commit_after>'use strict';
angular.module('copayApp.directives')
  .directive('validAddress', ['$rootScope', 'bitcore', 'bitcoreCash', 'bitcoinCashJsService',
    function($rootScope, bitcore, bitcoreCash, bitcoinCashJsService) {
      return {
        require: 'ngModel',
        link: function(scope, elem, attrs, ctrl) {
          // Bitcoin address
          var URI = bitcore.URI;
          var Address = bitcore.Address

          // Bitcoin Cash address
          var URICash = bitcoreCash.URI;
          var AddressCash = bitcoreCash.Address

          var validator = function(value) {

            if (value.indexOf('bitcoincash:') >= 0 || value[0] == 'C' || value[0] == 'H' || value[0] == 'p' || value[0] == 'q') {
              if (value.indexOf('bitcoincash:') < 0) {
                value = 'bitcoincash:' + value;
              }
              value = bitcoinCashJsService.readAddress(value).legacy;
            }

            // Regular url
            if (/^https?:\/\//.test(value)) {
              ctrl.$setValidity('validAddress', true);
              return value;
            }

            // Bip21 uri
            var uri, isAddressValidLivenet, isAddressValidTestnet;
            if (/^bitcoin:/.test(value)) {
              var isUriValid = URI.isValid(value);
              if (isUriValid) {
                uri = new URI(value);
                isAddressValidLivenet = Address.isValid(uri.address.toString(), 'livenet')
                isAddressValidTestnet = Address.isValid(uri.address.toString(), 'testnet')
              }
              ctrl.$setValidity('validAddress', isUriValid && (isAddressValidLivenet || isAddressValidTestnet));
              return value;
            } else if (/^bitcoincash:/.test(value)) {
              var isUriValid = URICash.isValid(value);
              if (isUriValid) {
                uri = new URICash(value);
                isAddressValidLivenet = AddressCash.isValid(uri.address.toString(), 'livenet')
              }
              ctrl.$setValidity('validAddress', isUriValid && (isAddressValidLivenet));
              return value;
            }

            if (typeof value == 'undefined') {
              ctrl.$pristine = true;
              return;
            }

            // Regular Address: try Bitcoin and Bitcoin Cash
            var regularAddressLivenet = Address.isValid(value, 'livenet');
            var regularAddressTestnet = Address.isValid(value, 'testnet');
            var regularAddressCashLivenet = AddressCash.isValid(value, 'livenet');
            ctrl.$setValidity('validAddress', (regularAddressLivenet || regularAddressTestnet || regularAddressCashLivenet));
            return value;
          };

          ctrl.$parsers.unshift(validator);
          ctrl.$formatters.unshift(validator);
        }
      };
    }
  ])
  .directive('validAmount', ['configService',
    function(configService) {

      return {
        require: 'ngModel',
        link: function(scope, element, attrs, ctrl) {
          var val = function(value) {
            var settings = configService.getSync().wallet.settings;
            var vNum = Number((value * settings.unitToSatoshi).toFixed(0));
            if (typeof value == 'undefined' || value == 0) {
              ctrl.$pristine = true;
            }

            if (typeof vNum == "number" && vNum > 0) {
              if (vNum > Number.MAX_SAFE_INTEGER) {
                ctrl.$setValidity('validAmount', false);
              } else {
                var decimals = Number(settings.unitDecimals);
                var sep_index = ('' + value).indexOf('.');
                var str_value = ('' + value).substring(sep_index + 1);
                if (sep_index >= 0 && str_value.length > decimals) {
                  ctrl.$setValidity('validAmount', false);
                  return;
                } else {
                  ctrl.$setValidity('validAmount', true);
                }
              }
            } else {
              ctrl.$setValidity('validAmount', false);
            }
            return value;
          }
          ctrl.$parsers.unshift(val);
          ctrl.$formatters.unshift(val);
        }
      };
    }
  ])
  .directive('walletSecret', function(bitcore) {
    return {
      require: 'ngModel',
      link: function(scope, elem, attrs, ctrl) {
        var validator = function(value) {
          if (value.length > 0) {
            var m = value.match(/^[0-9A-HJ-NP-Za-km-z]{70,80}$/);
            ctrl.$setValidity('walletSecret', m ? true : false);
          }
          return value;
        };

        ctrl.$parsers.unshift(validator);
      }
    };
  })
  .directive('ngFileSelect', function() {
    return {
      link: function($scope, el) {
        el.bind('change', function(e) {
          $scope.formData.file = (e.srcElement || e.target).files[0];
          $scope.getFile();
        });
      }
    }
  })
  .directive('contact', ['addressbookService', 'lodash',
    function(addressbookService, lodash) {
      return {
        restrict: 'E',
        link: function(scope, element, attrs) {
          var addr = attrs.address;
          addressbookService.get(addr, function(err, ab) {
            if (ab) {
              var name = lodash.isObject(ab) ? ab.name : ab;
              element.append(name);
            } else {
              element.append(addr);
            }
          });
        }
      };
    }
  ])
  .directive('ignoreMouseWheel', function($rootScope, $timeout) {
    return {
      restrict: 'A',
      link: function(scope, element, attrs) {
        element.bind('mousewheel', function(event) {
          element[0].blur();
          $timeout(function() {
            element[0].focus();
          }, 1);
        });
      }
    }
  })
  .directive('validDate', function() {
    return {
      require: 'ngModel',
      link: function(scope, elem, attr, ctrl) {
        ctrl.$validators.validDate = function(modelValue, viewValue) {
          // Expected Format is DD/MM/YYYY
          if (ctrl.$isEmpty(modelValue)) {
            // consider empty models to be valid
            return true;
          }
          var now = new Date();
          if (viewValue.match(/\d{2}\/\d{2}\/\d{4}/g)) {
            var split = viewValue.split(/\//);
            return parseInt(split[0]) <= 31 &&
              parseInt(split[0]) > 0 &&
              parseInt(split[1]) <= 12 &&
              parseInt(split[1]) > 0 &&
              (parseInt(split[1])) > 0;
          }

          return false;
        };
      }
    };
  })
  .directive('validExpiration', function() {
    return {
      require: 'ngModel',
      link: function(scope, elem, attr, ctrl) {
        ctrl.$validators.validExpiration = function(modelValue, viewValue) {
          if (ctrl.$isEmpty(modelValue)) {
            // consider empty models to be valid
            return true;
          }
          var now = new Date();
          if (viewValue.match(/\d{2}\/\d{2}/g)) {
            var split = viewValue.split(/\//);
            return parseInt(split[0]) <= 12 &&
              parseInt(split[0]) > 0 &&
              (2000 + parseInt(split[1])) >= now.getFullYear();
          }

          return false;
        };
      }
    };
  })
  .directive('maskedAmount', function() {
    return {
      require: 'ngModel',
      link: function(scope, elem, attr, ngModel) {
        // Masks amounts to the format of 999999999.99

        function addSpaces(value) {
          if(typeof(value) == typeof(undefined) || value === null ) {
            return 0;
          }
          var parsedValue = value.toString()
            .replace(/^0+(\d)/g,'$1')
            .replace(/^(\d{6})(\d+)$/g, '$1')
            .replace(/[^\d.]/g, '')
            .replace(/\/$/, '').trim();
          return parseInt(parsedValue);
        }

        function removeSpaces(value) {
          if(typeof(value) == typeof(undefined) || value === null ) {
            return 0;
          }

          var parsedValue = value.toString().replace(/\s/g, '');
          return parseInt(parsedValue);
        }

        function parseViewValue(value) {
          var viewValue = addSpaces(value);
          ngModel.$viewValue = viewValue;
          ngModel.$render();

          // Return what we want the model value to be
          return removeSpaces(viewValue);
        }

        function formatModelValue(value) {
          var modelValue = removeSpaces(value);
          ngModel.$modelValue = modelValue;
          return addSpaces(modelValue);
        }

        ngModel.$parsers.push(parseViewValue);
        ngModel.$formatters.push(formatModelValue);
      }
    }
  })
  .directive('maskedDate', function() {
    return {
      require: 'ngModel',
      link: function(scope, elem, attr, ngModel) {
        // Masks expirations to the format of 0000 0000 0000 0000

        var originalValue = '';
        var groupValue = 2;
        var groupIndex = 0;
        var separtor = '/';
        var maxDigit = 10;

        function isGroupFullyComplete(newValue) {
          // Check if a group is fully completed, if yes, let's format that
          var countOfNumbers = 0;
          var isDiff = false;
          for (var i = 0; i < newValue.length; i++) {
            var element = newValue[i];

            if (!isDiff && i < originalValue.length && element != originalValue[i]) {
              isDiff = true;
            }

            if (element == separtor) {
              if (isDiff) return false;
              countOfNumbers = 0;
              groupIndex++;
            }
            else countOfNumbers++;

            if (isDiff && countOfNumbers%(groupValue * (groupIndex > 2 ? 2 : 1)) == 0) return true;
          }

          return false
        }

        function addSpaces(value) {
          if(typeof(value) == typeof(undefined)) {
            return value;
          }

          var parsedValue = value.toString()
            .replace(/[^\d]/g, '')
            .replace(/^(\d{2})$/g, '$1//')
            .replace(/^(\d{2})(\d?.)$/g, '$1/$2')
            .replace(/^(\d{2})\/(\d{2})$/g, '$1/$2//')
            .replace(/^(\d{2})(\d{2})(\d+)$/g, '$1/$2/$3')
            .replace(/\/$/, '');
          return parsedValue.slice(0,10);
        }
        function removeSpaces(value) {
          if (typeof(value) == typeof(undefined)) {
            return value;
          }

          var parsedValue = value.toString().replace(/\s/g, '');
          return parsedValue;
        }

        function parseViewValue(value) {
          var viewValue = value;

          // Need to remove the right part
          if (viewValue.length >= maxDigit
            || originalValue[originalValue.length - 1] != viewValue[viewValue.length - 1]   // Complete at the end
            || isGroupFullyComplete(viewValue)) { // If a new one fully grouped, lets format that by the regex
            viewValue = addSpaces(viewValue);
          }

          if (typeof viewValue !== 'undefined') {
            originalValue = viewValue;
          }

          ngModel.$viewValue = viewValue;
          ngModel.$render();

          return removeSpaces(viewValue);
        }

        function formatModelValue(value) {
          var modelValue = removeSpaces(value);
          ngModel.$modelValue = modelValue;
          return addSpaces(modelValue);
        }

        ngModel.$parsers.push(parseViewValue);
        //ngModel.$formatters.push(formatModelValue);
      }
    }
  })
  .directive('maskedCreditCard', function() {
    return {
      require: 'ngModel',
      link: function(scope, elem, attr, ngModel) {
        // Masks expirations to the format of 0000 0000 0000 0000

        function addSpaces(value) {
          if(typeof(value) == typeof(undefined)) {
            return value;
          }

          var parsedValue = value.toString()
            .replace(/[^\d]/g, '')
            .replace(/(.{4})/g, '$1 ').trim()
            .replace(/\/$/, '');
          return parsedValue.slice(0,19);
        }

        function removeSpaces(value) {
          if (typeof(value) == typeof(undefined)) {
            return value;
          }

          var parsedValue = value.toString().replace(/\s/g, '');
          return parsedValue;
        }

        var originalValue = '';
        var groupValue = 4;
        var separtor = ' ';
        var maxDigit = 19;

        function isGroupFullyComplete(newValue) {
          // Check if a group is fully completed, if yes, let's format that
          var countOfNumbers = 0;
          var isDiff = false;
          for (var i = 0; i < newValue.length; i++) {
            var element = newValue[i];

            if (!isDiff && i < originalValue.length && element != originalValue[i]) {
              isDiff = true;
            }

            if (element == separtor) {
              if (isDiff) return false;
              countOfNumbers = 0;
            }
            else countOfNumbers++;

            if (isDiff && countOfNumbers%groupValue == 0) return true;
          }

          return false
        }

        function parseViewValue(value) {

          var viewValue = value;

          // Need to remove the right part
          if (viewValue.length >= maxDigit
            || originalValue[originalValue.length - 1] != viewValue[viewValue.length - 1]   // Complete at the end
            || isGroupFullyComplete(viewValue)) { // If a new one fully grouped, lets format that by the regex
            viewValue = addSpaces(viewValue);
          }

          if (typeof viewValue !== 'undefined') {
            originalValue = viewValue;
          }

          ngModel.$viewValue = viewValue;
          ngModel.$render();

          return removeSpaces(viewValue);
        }

        ngModel.$parsers.push(parseViewValue);
      }
    }
  })
  .directive('maskedExpiration', function() {
    return {
      require: 'ngModel',
      link: function(scope, elem, attr, ngModel) {
        // Masks expirations to the format of MM/YY

        var originalValue = '';
        var groupValue = 2;
        var separtor = '/';
        var maxDigit = 5;

        function isGroupFullyComplete(newValue) {
          // Check if a group is fully completed, if yes, let's format that
          var countOfNumbers = 0;
          var isDiff = false;
          for (var i = 0; i < newValue.length; i++) {
            var element = newValue[i];

            if (!isDiff && i < originalValue.length && element != originalValue[i]) {
              isDiff = true;
            }

            if (element == separtor) {
              if (isDiff) return false;
              countOfNumbers = 0;
            }
            else countOfNumbers++;

            if (isDiff && countOfNumbers%groupValue == 0) return true;
          }

          return false
        }

        function addSpaces(value) {
          if(typeof(value) == typeof(undefined)) {
            return value;
          }

          var parsedValue = value.toString()
            .replace(/[^\d]/g, '')
            .replace(/^(\d{2})$/g, '$1//').trim()
            .replace(/^(\d{2})(\d+)$/g, '$1/$2').trim()
            .replace(/\/$/, '');
          return parsedValue.slice(0,5);
        }

        function removeSpaces(value) {
          if (typeof(value) == typeof(undefined)) {
            return value;
          }

          var parsedValue = value.toString().replace(/\s/g, '').replace(/\//g, '');
          return parsedValue;
        }

        function parseViewValue(value) {

          var viewValue = value;

          // Need to remove the right part
          if (viewValue.length >= maxDigit
            || originalValue[originalValue.length - 1] != viewValue[viewValue.length - 1]   // Complete at the end
            || isGroupFullyComplete(viewValue)) { // If a new one fully grouped, lets format that by the regex
            viewValue = addSpaces(viewValue);
          }

          if (typeof viewValue !== 'undefined') {
            originalValue = viewValue;
          }

          ngModel.$viewValue = viewValue;
          ngModel.$render();

          return removeSpaces(viewValue);
        }

        ngModel.$parsers.push(parseViewValue);
      }
    }
  });
<|endoftext|>


<commit_before>var util = require('util');
var path = require('path');
var Q = require('q');
var chmodr = require('chmodr');
var rimraf = require('rimraf');
var mkdirp = require('mkdirp');
var which = require('which');
var LRU = require('lru-cache');
var mout = require('mout');
var Resolver = require('./Resolver');
var semver = require('../../util/semver');
var createError = require('../../util/createError');
var defaultConfig = require('../../config');
var cli = require('../../util/cli');
var Hw2Core = require("hw2-js/modules/js/src/kernel");

var hasGit;

// Check if git is installed
try {
    which.sync('git');
    hasGit = true;
} catch (ex) {
    hasGit = false;
}

// Set template dir to the empty directory so that user templates are not run
// This environment variable is not multiple config aware but it's not documented
// anyway
mkdirp.sync(defaultConfig.storage.empty);
process.env.GIT_TEMPLATE_DIR = defaultConfig.storage.empty;

function GitResolver (decEndpoint, config, logger) {
    Resolver.call(this, decEndpoint, config, logger);

    if (!hasGit) {
        throw createError('git is not installed or not in the PATH', 'ENOGIT');
    }
}

util.inherits(GitResolver, Resolver);
mout.object.mixIn(GitResolver, Resolver);

// -----------------

GitResolver.prototype._checkGitCommit = function (resolution) {
    var deferred = Q.defer();
    var that = this;
    Hw2Core(function () {
        var $ = this;
        $.Loader.load("PATH_JS_LIB:nodejs/git/index.js", function () {
            var p = path.join(that._config.cwd, that._config.directory, that._name);
            $.NodeJs.Git.getCommitHash(p, function (hash) {
                // TODO: maybe we need to update the json file too
                deferred.resolve(hash === resolution.commit);
            });
        });
    });

    return deferred.promise;
};

GitResolver.prototype._hasNew = function (canonicalDir, pkgMeta) {
    var oldResolution = pkgMeta._resolution || {};
    var that = this;

    return this._findResolution()
            .then(function (resolution) {
                return that._checkGitCommit(resolution).then(function (gitUpdated) {
                    if (gitUpdated) {
                        return true;
                    }

                    // Check if resolution types are different
                    if (oldResolution.type !== resolution.type) {
                        return true;
                    }

                    // If resolved to a version, there is new content if the tags are not equal
                    if (resolution.type === 'version' && semver.neq(resolution.tag, oldResolution.tag)) {
                        return true;
                    }

                    // As last check, we compare both commit hashes
                    return resolution.commit !== oldResolution.commit;
                });
            });
};

GitResolver.prototype._resolve = function () {
    var that = this;

    return this._findResolution()
            .then(function (resolution) {
                return that._checkGitCommit(resolution);
            })
            .then(function (gitUpdated) {
                return gitUpdated || that._checkout()
                        // Always run cleanup after checkout to ensure that .git is removed!
                        // If it's not removed, problems might arise when the "tmp" module attempts
                        // to delete the temporary folder
                        .fin(function () {
                            return that._cleanup();
                        });
            });
};

// -----------------

// Abstract functions that should be implemented by concrete git resolvers
GitResolver.prototype._checkout = function () {
    throw new Error('_checkout not implemented');
};

GitResolver.refs = function (source) {
    throw new Error('refs not implemented');
};

// -----------------

GitResolver.prototype._findResolution = function (target) {
    var err;
    var self = this.constructor;
    var that = this;

    target = target || this._target || '*';

    // Target is a commit, so it's a stale target (not a moving target)
    // There's nothing to do in this case
    if ((/^[a-f0-9]{40}$/).test(target)) {
        this._resolution = {type: 'commit', commit: target};
        return Q.resolve(this._resolution);
    }

    // Target is a range/version
    if (semver.validRange(target)) {
        return self.versions(this._source, true)
                .then(function (versions) {
                    var versionsArr,
                            version,
                            index;

                    versionsArr = versions.map(function (obj) {
                        return obj.version;
                    });

                    // If there are no tags and target is *,
                    // fallback to the latest commit on master
                    if (!versions.length && target === '*') {
                        return that._findResolution('master');
                    }

                    versionsArr = versions.map(function (obj) {
                        return obj.version;
                    });
                    // Find a satisfying version, enabling strict match so that pre-releases
                    // have lower priority over normal ones when target is *
                    index = semver.maxSatisfyingIndex(versionsArr, target, true);
                    if (index !== -1) {
                        version = versions[index];
                        return that._resolution = {type: 'version', tag: version.tag, commit: version.commit};
                    }

                    // Check if there's an exact branch/tag with this name as last resort
                    return Q.all([
                        self.branches(that._source),
                        self.tags(that._source)
                    ])
                            .spread(function (branches, tags) {
                                // Use hasOwn because a branch/tag could have a name like "hasOwnProperty"
                                if (mout.object.hasOwn(tags, target)) {
                                    return that._resolution = {type: 'tag', tag: target, commit: tags[target]};
                                }
                                if (mout.object.hasOwn(branches, target)) {
                                    return that._resolution = {type: 'branch', branch: target, commit: branches[target]};
                                }

                                throw createError('No tag found that was able to satisfy ' + target, 'ENORESTARGET', {
                                    details: !versions.length ?
                                            'No versions found in ' + that._source :
                                            'Available versions: ' + versions.map(function (version) {
                                                return version.version;
                                            }).join(', ')
                                });
                            });
                });
    }

    // Otherwise, target is either a tag or a branch
    return Q.all([
        self.branches(that._source),
        self.tags(that._source)
    ])
            .spread(function (branches, tags) {
                // Use hasOwn because a branch/tag could have a name like "hasOwnProperty"
                if (mout.object.hasOwn(tags, target)) {
                    return that._resolution = {type: 'tag', tag: target, commit: tags[target]};
                }
                if (mout.object.hasOwn(branches, target)) {
                    return that._resolution = {type: 'branch', branch: target, commit: branches[target]};
                }

                if ((/^[a-f0-9]{4,40}$/).test(target)) {
                    if (target.length < 12) {
                        that._logger.warn(
                                'short-sha',
                                'Consider using longer commit SHA to avoid conflicts'
                                );
                    }

                    that._resolution = {type: 'commit', commit: target};
                    return that._resolution;
                }

                branches = Object.keys(branches);
                tags = Object.keys(tags);

                err = createError('Tag/branch ' + target + ' does not exist', 'ENORESTARGET');
                err.details = !tags.length ?
                        'No tags found in ' + that._source :
                        'Available tags: ' + tags.join(', ');
                err.details += '\n';
                err.details += !branches.length ?
                        'No branches found in ' + that._source :
                        'Available branches: ' + branches.join(', ');

                throw err;
            });
};

GitResolver.prototype._cleanup = function () {
    // if we are not in production, we can keep .git folder
    if (!this._config.cmdOptions.production)
        return;

    var gitFolder = path.join(this._tempDir, '.git');

    // Remove the .git folder
    // Note that on windows, we need to chmod to 0777 before due to a bug in git
    // See: https://github.com/isaacs/rimraf/issues/19
    if (process.platform === 'win32') {
        return Q.nfcall(chmodr, gitFolder, 0777)
                .then(function () {
                    return Q.nfcall(rimraf, gitFolder);
                }, function (err) {
                    // If .git does not exist, chmodr returns ENOENT
                    // so, we ignore that error code
                    if (err.code !== 'ENOENT') {
                        throw err;
                    }
                });
    } else {
        return Q.nfcall(rimraf, gitFolder);
    }
};

GitResolver.prototype._savePkgMeta = function (meta) {
    var version;

    if (this._resolution.type === 'version') {
        version = semver.clean(this._resolution.tag);

        // Warn if the package meta version is different than the resolved one
        if (typeof meta.version === 'string' && semver.neq(meta.version, version)) {
            this._logger.warn('mismatch', 'Version declared in the json (' + meta.version + ') is different than the resolved one (' + version + ')', {
                resolution: this._resolution,
                pkgMeta: meta
            });
        }

        // Ensure package meta version is the same as the resolution
        meta.version = version;
    } else {
        // If resolved to a target that is not a version,
        // remove the version from the meta
        delete meta.version;
    }

    // Save version/tag/commit in the release
    // Note that we can't store branches because _release is supposed to be
    // an unique id of this ref.
    meta._release = version ||
            this._resolution.tag ||
            this._resolution.commit.substr(0, 10);

    // Save resolution to be used in hasNew later
    meta._resolution = this._resolution;

    meta._res_type = "Git";

    return Resolver.prototype._savePkgMeta.call(this, meta);
};

// ------------------------------

GitResolver.versions = function (source, extra) {
    var value = this._cache.versions.get(source);

    if (value) {
        return Q.resolve(value)
                .then(function () {
                    var versions = this._cache.versions.get(source);

                    // If no extra information was requested,
                    // resolve simply with the versions
                    if (!extra) {
                        versions = versions.map(function (version) {
                            return version.version;
                        });
                    }

                    return versions;
                }.bind(this));
    }

    value = this.tags(source)
            .then(function (tags) {
                var tag;
                var version;
                var versions = [];

                // For each tag
                for (tag in tags) {
                    version = semver.clean(tag);
                    if (version) {
                        versions.push({version: version, tag: tag, commit: tags[tag]});
                    }
                }

                // Sort them by DESC order
                versions.sort(function (a, b) {
                    return semver.rcompare(a.version, b.version);
                });

                this._cache.versions.set(source, versions);

                // Call the function again to keep it DRY
                return this.versions(source, extra);
            }.bind(this));

    // Store the promise to be reused until it resolves
    // to a specific value
    this._cache.versions.set(source, value);

    return value;
};

GitResolver.tags = function (source) {
    var value = this._cache.tags.get(source);

    if (value) {
        return Q.resolve(value);
    }

    value = this.refs(source)
            .then(function (refs) {
                var tags = {};

                // For each line in the refs, match only the tags
                refs.forEach(function (line) {
                    var match = line.match(/^([a-f0-9]{40})\s+refs\/tags\/(\S+)/);

                    if (match && !mout.string.endsWith(match[2], '^{}')) {
                        tags[match[2]] = match[1];
                    }
                });

                this._cache.tags.set(source, tags);

                return tags;
            }.bind(this));

    // Store the promise to be reused until it resolves
    // to a specific value
    this._cache.tags.set(source, value);

    return value;
};

GitResolver.branches = function (source) {
    var value = this._cache.branches.get(source);

    if (value) {
        return Q.resolve(value);
    }

    value = this.refs(source)
            .then(function (refs) {
                var branches = {};

                // For each line in the refs, extract only the heads
                // Organize them in an object where keys are branches and values
                // the commit hashes
                refs.forEach(function (line) {
                    var match = line.match(/^([a-f0-9]{40})\s+refs\/heads\/(\S+)/);

                    if (match) {
                        branches[match[2]] = match[1];
                    }
                });

                this._cache.branches.set(source, branches);

                return branches;
            }.bind(this));

    // Store the promise to be reused until it resolves
    // to a specific value
    this._cache.branches.set(source, value);

    return value;
};

GitResolver.clearRuntimeCache = function () {
    // Reset cache for branches, tags, etc
    mout.object.forOwn(GitResolver._cache, function (lru) {
        lru.reset();
    });
};

GitResolver._cache = {
    branches: new LRU({max: 50, maxAge: 5 * 60 * 1000}),
    tags: new LRU({max: 50, maxAge: 5 * 60 * 1000}),
    versions: new LRU({max: 50, maxAge: 5 * 60 * 1000}),
    refs: new LRU({max: 50, maxAge: 5 * 60 * 1000})
};

module.exports = GitResolver;
<commit_msg>fixed hw2-core require<commit_after>var util = require('util');
var path = require('path');
var Q = require('q');
var chmodr = require('chmodr');
var rimraf = require('rimraf');
var mkdirp = require('mkdirp');
var which = require('which');
var LRU = require('lru-cache');
var mout = require('mout');
var Resolver = require('./Resolver');
var semver = require('../../util/semver');
var createError = require('../../util/createError');
var defaultConfig = require('../../config');
var cli = require('../../util/cli');
var Hw2Core = require("hw2-core-js/modules/js/src/kernel");

var hasGit;

// Check if git is installed
try {
    which.sync('git');
    hasGit = true;
} catch (ex) {
    hasGit = false;
}

// Set template dir to the empty directory so that user templates are not run
// This environment variable is not multiple config aware but it's not documented
// anyway
mkdirp.sync(defaultConfig.storage.empty);
process.env.GIT_TEMPLATE_DIR = defaultConfig.storage.empty;

function GitResolver (decEndpoint, config, logger) {
    Resolver.call(this, decEndpoint, config, logger);

    if (!hasGit) {
        throw createError('git is not installed or not in the PATH', 'ENOGIT');
    }
}

util.inherits(GitResolver, Resolver);
mout.object.mixIn(GitResolver, Resolver);

// -----------------

GitResolver.prototype._checkGitCommit = function (resolution) {
    var deferred = Q.defer();
    var that = this;
    Hw2Core(function () {
        var $ = this;
        $.Loader.load("PATH_JS_LIB:nodejs/git/index.js", function () {
            var p = path.join(that._config.cwd, that._config.directory, that._name);
            $.NodeJs.Git.getCommitHash(p, function (hash) {
                // TODO: maybe we need to update the json file too
                deferred.resolve(hash === resolution.commit);
            });
        });
    });

    return deferred.promise;
};

GitResolver.prototype._hasNew = function (canonicalDir, pkgMeta) {
    var oldResolution = pkgMeta._resolution || {};
    var that = this;

    return this._findResolution()
            .then(function (resolution) {
                return that._checkGitCommit(resolution).then(function (gitUpdated) {
                    if (gitUpdated) {
                        return true;
                    }

                    // Check if resolution types are different
                    if (oldResolution.type !== resolution.type) {
                        return true;
                    }

                    // If resolved to a version, there is new content if the tags are not equal
                    if (resolution.type === 'version' && semver.neq(resolution.tag, oldResolution.tag)) {
                        return true;
                    }

                    // As last check, we compare both commit hashes
                    return resolution.commit !== oldResolution.commit;
                });
            });
};

GitResolver.prototype._resolve = function () {
    var that = this;

    return this._findResolution()
            .then(function (resolution) {
                return that._checkGitCommit(resolution);
            })
            .then(function (gitUpdated) {
                return gitUpdated || that._checkout()
                        // Always run cleanup after checkout to ensure that .git is removed!
                        // If it's not removed, problems might arise when the "tmp" module attempts
                        // to delete the temporary folder
                        .fin(function () {
                            return that._cleanup();
                        });
            });
};

// -----------------

// Abstract functions that should be implemented by concrete git resolvers
GitResolver.prototype._checkout = function () {
    throw new Error('_checkout not implemented');
};

GitResolver.refs = function (source) {
    throw new Error('refs not implemented');
};

// -----------------

GitResolver.prototype._findResolution = function (target) {
    var err;
    var self = this.constructor;
    var that = this;

    target = target || this._target || '*';

    // Target is a commit, so it's a stale target (not a moving target)
    // There's nothing to do in this case
    if ((/^[a-f0-9]{40}$/).test(target)) {
        this._resolution = {type: 'commit', commit: target};
        return Q.resolve(this._resolution);
    }

    // Target is a range/version
    if (semver.validRange(target)) {
        return self.versions(this._source, true)
                .then(function (versions) {
                    var versionsArr,
                            version,
                            index;

                    versionsArr = versions.map(function (obj) {
                        return obj.version;
                    });

                    // If there are no tags and target is *,
                    // fallback to the latest commit on master
                    if (!versions.length && target === '*') {
                        return that._findResolution('master');
                    }

                    versionsArr = versions.map(function (obj) {
                        return obj.version;
                    });
                    // Find a satisfying version, enabling strict match so that pre-releases
                    // have lower priority over normal ones when target is *
                    index = semver.maxSatisfyingIndex(versionsArr, target, true);
                    if (index !== -1) {
                        version = versions[index];
                        return that._resolution = {type: 'version', tag: version.tag, commit: version.commit};
                    }

                    // Check if there's an exact branch/tag with this name as last resort
                    return Q.all([
                        self.branches(that._source),
                        self.tags(that._source)
                    ])
                            .spread(function (branches, tags) {
                                // Use hasOwn because a branch/tag could have a name like "hasOwnProperty"
                                if (mout.object.hasOwn(tags, target)) {
                                    return that._resolution = {type: 'tag', tag: target, commit: tags[target]};
                                }
                                if (mout.object.hasOwn(branches, target)) {
                                    return that._resolution = {type: 'branch', branch: target, commit: branches[target]};
                                }

                                throw createError('No tag found that was able to satisfy ' + target, 'ENORESTARGET', {
                                    details: !versions.length ?
                                            'No versions found in ' + that._source :
                                            'Available versions: ' + versions.map(function (version) {
                                                return version.version;
                                            }).join(', ')
                                });
                            });
                });
    }

    // Otherwise, target is either a tag or a branch
    return Q.all([
        self.branches(that._source),
        self.tags(that._source)
    ])
            .spread(function (branches, tags) {
                // Use hasOwn because a branch/tag could have a name like "hasOwnProperty"
                if (mout.object.hasOwn(tags, target)) {
                    return that._resolution = {type: 'tag', tag: target, commit: tags[target]};
                }
                if (mout.object.hasOwn(branches, target)) {
                    return that._resolution = {type: 'branch', branch: target, commit: branches[target]};
                }

                if ((/^[a-f0-9]{4,40}$/).test(target)) {
                    if (target.length < 12) {
                        that._logger.warn(
                                'short-sha',
                                'Consider using longer commit SHA to avoid conflicts'
                                );
                    }

                    that._resolution = {type: 'commit', commit: target};
                    return that._resolution;
                }

                branches = Object.keys(branches);
                tags = Object.keys(tags);

                err = createError('Tag/branch ' + target + ' does not exist', 'ENORESTARGET');
                err.details = !tags.length ?
                        'No tags found in ' + that._source :
                        'Available tags: ' + tags.join(', ');
                err.details += '\n';
                err.details += !branches.length ?
                        'No branches found in ' + that._source :
                        'Available branches: ' + branches.join(', ');

                throw err;
            });
};

GitResolver.prototype._cleanup = function () {
    // if we are not in production, we can keep .git folder
    if (!this._config.cmdOptions.production)
        return;

    var gitFolder = path.join(this._tempDir, '.git');

    // Remove the .git folder
    // Note that on windows, we need to chmod to 0777 before due to a bug in git
    // See: https://github.com/isaacs/rimraf/issues/19
    if (process.platform === 'win32') {
        return Q.nfcall(chmodr, gitFolder, 0777)
                .then(function () {
                    return Q.nfcall(rimraf, gitFolder);
                }, function (err) {
                    // If .git does not exist, chmodr returns ENOENT
                    // so, we ignore that error code
                    if (err.code !== 'ENOENT') {
                        throw err;
                    }
                });
    } else {
        return Q.nfcall(rimraf, gitFolder);
    }
};

GitResolver.prototype._savePkgMeta = function (meta) {
    var version;

    if (this._resolution.type === 'version') {
        version = semver.clean(this._resolution.tag);

        // Warn if the package meta version is different than the resolved one
        if (typeof meta.version === 'string' && semver.neq(meta.version, version)) {
            this._logger.warn('mismatch', 'Version declared in the json (' + meta.version + ') is different than the resolved one (' + version + ')', {
                resolution: this._resolution,
                pkgMeta: meta
            });
        }

        // Ensure package meta version is the same as the resolution
        meta.version = version;
    } else {
        // If resolved to a target that is not a version,
        // remove the version from the meta
        delete meta.version;
    }

    // Save version/tag/commit in the release
    // Note that we can't store branches because _release is supposed to be
    // an unique id of this ref.
    meta._release = version ||
            this._resolution.tag ||
            this._resolution.commit.substr(0, 10);

    // Save resolution to be used in hasNew later
    meta._resolution = this._resolution;

    meta._res_type = "Git";

    return Resolver.prototype._savePkgMeta.call(this, meta);
};

// ------------------------------

GitResolver.versions = function (source, extra) {
    var value = this._cache.versions.get(source);

    if (value) {
        return Q.resolve(value)
                .then(function () {
                    var versions = this._cache.versions.get(source);

                    // If no extra information was requested,
                    // resolve simply with the versions
                    if (!extra) {
                        versions = versions.map(function (version) {
                            return version.version;
                        });
                    }

                    return versions;
                }.bind(this));
    }

    value = this.tags(source)
            .then(function (tags) {
                var tag;
                var version;
                var versions = [];

                // For each tag
                for (tag in tags) {
                    version = semver.clean(tag);
                    if (version) {
                        versions.push({version: version, tag: tag, commit: tags[tag]});
                    }
                }

                // Sort them by DESC order
                versions.sort(function (a, b) {
                    return semver.rcompare(a.version, b.version);
                });

                this._cache.versions.set(source, versions);

                // Call the function again to keep it DRY
                return this.versions(source, extra);
            }.bind(this));

    // Store the promise to be reused until it resolves
    // to a specific value
    this._cache.versions.set(source, value);

    return value;
};

GitResolver.tags = function (source) {
    var value = this._cache.tags.get(source);

    if (value) {
        return Q.resolve(value);
    }

    value = this.refs(source)
            .then(function (refs) {
                var tags = {};

                // For each line in the refs, match only the tags
                refs.forEach(function (line) {
                    var match = line.match(/^([a-f0-9]{40})\s+refs\/tags\/(\S+)/);

                    if (match && !mout.string.endsWith(match[2], '^{}')) {
                        tags[match[2]] = match[1];
                    }
                });

                this._cache.tags.set(source, tags);

                return tags;
            }.bind(this));

    // Store the promise to be reused until it resolves
    // to a specific value
    this._cache.tags.set(source, value);

    return value;
};

GitResolver.branches = function (source) {
    var value = this._cache.branches.get(source);

    if (value) {
        return Q.resolve(value);
    }

    value = this.refs(source)
            .then(function (refs) {
                var branches = {};

                // For each line in the refs, extract only the heads
                // Organize them in an object where keys are branches and values
                // the commit hashes
                refs.forEach(function (line) {
                    var match = line.match(/^([a-f0-9]{40})\s+refs\/heads\/(\S+)/);

                    if (match) {
                        branches[match[2]] = match[1];
                    }
                });

                this._cache.branches.set(source, branches);

                return branches;
            }.bind(this));

    // Store the promise to be reused until it resolves
    // to a specific value
    this._cache.branches.set(source, value);

    return value;
};

GitResolver.clearRuntimeCache = function () {
    // Reset cache for branches, tags, etc
    mout.object.forOwn(GitResolver._cache, function (lru) {
        lru.reset();
    });
};

GitResolver._cache = {
    branches: new LRU({max: 50, maxAge: 5 * 60 * 1000}),
    tags: new LRU({max: 50, maxAge: 5 * 60 * 1000}),
    versions: new LRU({max: 50, maxAge: 5 * 60 * 1000}),
    refs: new LRU({max: 50, maxAge: 5 * 60 * 1000})
};

module.exports = GitResolver;
<|endoftext|>


<commit_before>'use babel';
'use strict';

import database from '../characters/database';

export default class ListCharactersCommand {
	static get information() {
		return {
			label: 'characters',
			description: 'Lists all of the characters in the database.',
			usage: '!characters'
		};
	}

	static get triggers() {
		return [
			/^!characters(?:\s.*)?$/i
		];
	}

	static run(message) {
		const characters = database.findCharactersInServer(message.server.id);
		if(characters && characters.length > 0) {
			let characterList = '';
			for(const character of characters) characterList += (characterList ? '\n' : '') + character.name;
			message.client.reply(message, 'Character list (use !character <name> to view information about one):\n' + characterList);
		} else {
			message.client.reply(message, 'There are no characters in the database.');
		}
	}
}
<commit_msg>Added some quotes<commit_after>'use babel';
'use strict';

import database from '../characters/database';

export default class ListCharactersCommand {
	static get information() {
		return {
			label: 'characters',
			description: 'Lists all of the characters in the database.',
			usage: '!characters'
		};
	}

	static get triggers() {
		return [
			/^!characters(?:\s.*)?$/i
		];
	}

	static run(message) {
		const characters = database.findCharactersInServer(message.server.id);
		if(characters && characters.length > 0) {
			let characterList = '';
			for(const character of characters) characterList += (characterList ? '\n' : '') + character.name;
			message.client.reply(message, 'Character list (use "!character <name>" to view information about one):\n' + characterList);
		} else {
			message.client.reply(message, 'There are no characters in the database.');
		}
	}
}
<|endoftext|>


<commit_before>goog.require('ol.Map');
goog.require('ol.RendererHint');
goog.require('ol.View2D');
goog.require('ol.control.Select');
goog.require('ol.control.defaults');
goog.require('ol.layer.TileLayer');
goog.require('ol.layer.Vector');
goog.require('ol.parser.ogc.GML_v3');
goog.require('ol.source.MapQuestOpenAerial');
goog.require('ol.source.Vector');
goog.require('ol.style.Polygon');
goog.require('ol.style.Rule');
goog.require('ol.style.Style');

var raster = new ol.layer.TileLayer({
  source: new ol.source.MapQuestOpenAerial()
});

var vector = new ol.layer.Vector({
  source: new ol.source.Vector({
    parser: new ol.parser.ogc.GML_v3(),
    url: 'data/gml/topp-states-wfs.xml'
  }),
  style: new ol.style.Style({rules: [
    new ol.style.Rule({
      symbolizers: [
        new ol.style.Polygon({
          strokeColor: '#bada55'
        })
      ]
    })
  ]})
});

var selectControl = new ol.control.Select({layers: [vector]});

var map = new ol.Map({
  controls: ol.control.defaults({}, [selectControl]),
  layers: [raster, vector],
  renderer: ol.RendererHint.CANVAS,
  target: 'map',
  view: new ol.View2D({
    center: [-10997171.194994785, 5206335.565590534],
    zoom: 4
  })
});

selectControl.activate();
<commit_msg>Example update after recent API changes<commit_after>goog.require('ol.Map');
goog.require('ol.RendererHint');
goog.require('ol.View2D');
goog.require('ol.control.Select');
goog.require('ol.control.defaults');
goog.require('ol.layer.TileLayer');
goog.require('ol.layer.Vector');
goog.require('ol.parser.ogc.GML_v3');
goog.require('ol.source.MapQuestOpenAerial');
goog.require('ol.source.Vector');
goog.require('ol.style.Fill');
goog.require('ol.style.Stroke');
goog.require('ol.style.Style');

var raster = new ol.layer.TileLayer({
  source: new ol.source.MapQuestOpenAerial()
});

var vector = new ol.layer.Vector({
  source: new ol.source.Vector({
    parser: new ol.parser.ogc.GML_v3(),
    url: 'data/gml/topp-states-wfs.xml'
  }),
  style: new ol.style.Style({
    symbolizers: [
      new ol.style.Fill({
        color: '#ffffff',
        opacity: 0.25
      }),
      new ol.style.Stroke({
        color: '#6666ff'
      })
    ]
  })
});

var selectControl = new ol.control.Select({layers: [vector]});

var map = new ol.Map({
  controls: ol.control.defaults().extend([selectControl]),
  layers: [raster, vector],
  renderer: ol.RendererHint.CANVAS,
  target: 'map',
  view: new ol.View2D({
    center: [-10997171.194994785, 5206335.565590534],
    zoom: 4
  })
});

selectControl.activate();
<|endoftext|>