<commit_before>
var ryver = require('ryver');
var ejs = require('ejs');
var p = require('path');
var crypto = require('crypto');

var eventEC = ryver.eventEC;

function makeHash(){
  return crypto.createHash('md5').update( (Math.random()*1000000).toString() ).digest('hex');
}

eventEC.onCollect( 'afterPreProcessFilters', function( cb ){

  var f = function( fileData, cb ){

    var hashTable = fileData.system.ejsHashTable = {};

    // This filter will only work on text files (of any kind)
    // and ONLY IF EJS IS IN THE PIPELINE!
    if( fileData.system.mimetype.split('/')[0] !== 'text'){

      ryver.log( "File ignored as mime type is not 'text'" );
      return cb( null, fileData);

    } else {

      if(  !fileData.info.filtersPipeline ||  !fileData.info.filtersPipeline.find( function( i ) { return i.name == 'template-ejs'} ) ){
        ryver.log( "File ignored as file won't be processed by EJS later" );
        return cb( null, fileData);
      }
    }

    var found = false;
    var b = fileData.contents;
    // Convert anything that is ejs into an MD5. This will prevent any kind of escaping
    fileData.contents = fileData.contents.replace( /(\<\%[^\%][\s\S]*?\%\>)/gm, function( match, type ){
      var h = makeHash();
      hashTable[ h ] = match;
      found = true;
      return h;
    });

    if( Object.keys( hashTable ).length ){
      fileData.system.hasEjs = true;
      ryver.vlog( "EJS preserving. Contents before the 'cure':", b );
      ryver.vlog( "...and after the 'cure':", fileData.contents );
      ryver.log("File had EJS tags, which were mapped away to prevent any escaping");
    }

    cb( null );
  }

  // Return the function just defined as the filter
  cb( null, { name: 'ejs-saver', executor: f } );
});

eventEC.onCollect( 'filter', function( cb ){

  var f = function( fileData, cb ){

    // This filter will only work on text files (of any kind)
    if( fileData.system.mimetype.split('/')[0] !== 'text'){
      ryver.log( "File ignored as mime type is not 'text':", fileData.system.mimetype );
      return cb( null, fileData);
    }

    // The hash table from the system
    var hashTable = fileData.system.ejsHashTable;

    // NOTE: The next 3 lines are wrong, since there could be tags even without
    // anything in the hash, since the hash table only happens to the actual contents
    //if( !Object.keys( hashTable ).length ){
    //  return cb( null, fileData);
    //}

    ryver.log( "File had EJS tags, restoring them now!" );

    ryver.vlog( "EJS restoring. Contents before the 'cure':", fileData.contents );
    // Resolve any hash contents in the file
    Object.keys( hashTable ).forEach( function( hash ){
      fileData.contents = fileData.contents.replace( hash, hashTable[ hash ] );
    })

    // TODO: Take this out
    fileData.info.inspect = require('util').inspect;

    // Work out (and pass) `filename` so that the include directive works
    var s = fileData.system;
    var filename = p.join( ryver.getSrc(), s.filePath, s.fileName + s.fileExt );

    ryver.vlog("Contents before running EJS filter, with EJS tags restored:", fileData.contents );
    fileData.contents = ejs.render( fileData.contents, fileData, { filename: filename} );
    ryver.vlog("Contents after running EJS filter:", fileData.contents );

    cb( null );
  }

  // Return the function just defined as the filter
  cb( null, { name: 'template-ejs', executor: f } );
});
<commit_msg>Set _include directory as default include directory<commit_after>
var ryver = require('ryver');
var ejs = require('ejs');
var p = require('path');
var crypto = require('crypto');

var eventEC = ryver.eventEC;

function makeHash(){
  return crypto.createHash('md5').update( (Math.random()*1000000).toString() ).digest('hex');
}

eventEC.onCollect( 'afterPreProcessFilters', function( cb ){

  var f = function( fileData, cb ){

    var hashTable = fileData.system.ejsHashTable = {};

    // This filter will only work on text files (of any kind)
    // and ONLY IF EJS IS IN THE PIPELINE!
    if( fileData.system.mimetype.split('/')[0] !== 'text'){

      ryver.log( "File ignored as mime type is not 'text'" );
      return cb( null, fileData);

    } else {

      if(  !fileData.info.filtersPipeline ||  !fileData.info.filtersPipeline.find( function( i ) { return i.name == 'template-ejs'} ) ){
        ryver.log( "File ignored as file won't be processed by EJS later" );
        return cb( null, fileData);
      }
    }

    var found = false;
    var b = fileData.contents;
    // Convert anything that is ejs into an MD5. This will prevent any kind of escaping
    fileData.contents = fileData.contents.replace( /(\<\%[^\%][\s\S]*?\%\>)/gm, function( match, type ){
      var h = makeHash();
      hashTable[ h ] = match;
      found = true;
      return h;
    });

    if( Object.keys( hashTable ).length ){
      fileData.system.hasEjs = true;
      ryver.vlog( "EJS preserving. Contents before the 'cure':", b );
      ryver.vlog( "...and after the 'cure':", fileData.contents );
      ryver.log("File had EJS tags, which were mapped away to prevent any escaping");
    }

    cb( null );
  }

  // Return the function just defined as the filter
  cb( null, { name: 'ejs-saver', executor: f } );
});

eventEC.onCollect( 'filter', function( cb ){

  var f = function( fileData, cb ){

    // This filter will only work on text files (of any kind)
    if( fileData.system.mimetype.split('/')[0] !== 'text'){
      ryver.log( "File ignored as mime type is not 'text':", fileData.system.mimetype );
      return cb( null, fileData);
    }

    // The hash table from the system
    var hashTable = fileData.system.ejsHashTable;

    // NOTE: The next 3 lines are wrong, since there could be tags even without
    // anything in the hash, since the hash table only happens to the actual contents
    //if( !Object.keys( hashTable ).length ){
    //  return cb( null, fileData);
    //}

    ryver.log( "File had EJS tags, restoring them now!" );

    ryver.vlog( "EJS restoring. Contents before the 'cure':", fileData.contents );
    // Resolve any hash contents in the file
    Object.keys( hashTable ).forEach( function( hash ){
      fileData.contents = fileData.contents.replace( hash, hashTable[ hash ] );
    })

    // TODO: Take this out
    fileData.info.inspect = require('util').inspect;

    // Work out (and pass) `filename` so that the include directive works
    var s = fileData.system;
    //var filename = p.join( ryver.getSrc(), s.filePath, s.fileName + s.fileExt );
    var filename = p.join( ryver.getSrc(), '_includes', s.fileName + s.fileExt );

    ryver.vlog("Contents before running EJS filter, with EJS tags restored:", fileData.contents );
    fileData.contents = ejs.render( fileData.contents, fileData, { filename: filename} );
    ryver.vlog("Contents after running EJS filter:", fileData.contents );

    cb( null );
  }

  // Return the function just defined as the filter
  cb( null, { name: 'template-ejs', executor: f } );
});
<|endoftext|>


<commit_before>var cache = { id: 0 };

module.exports = function(React) {
  return {
    uniqueId: function() {
      return 'rsui-' + cache.id++;
    },

    defaults: function() {
      var base = arguments[0],
          current;
      for (var i=1; i<arguments.length; i++) {
        current = arguments[i];
        for (var name in current) {
          if (base[name] === undefined) {
            base[name] = current[name];
          }
        }
      }
      return base;
    },

    omit: function(data, keys) {
      var rtn = {};
      for (var name in data) {
        if (keys.indexOf(name) === -1) {
          rtn[name] = data[name];
        }
      }
      return rtn;
    },

    mergeClassNames: function() {
      var rtn = '';
      for (var i=0; i<arguments.length; i++) {
        if (arguments[i]) {
          if (rtn.length > 0) rtn += ' ';
          rtn += arguments[i];
        }
      }
      return rtn && rtn;
    },

    eventBinder: function(value, type, context, cancelEvent) {
      return function(event) {
        if (cancelEvent) {
          event.stopPropagation();
          event.preventDefault();
        }
        if (context[type]) {
          context[type](value, event);
        }
        if (context.props[type]) {
          context.props[type](value, event);
        }
      };
    },

    result: function(value, context) {
      if (typeof value === 'function') {
        return value.call(context);
      } else {
        return value;
      }
    },

    init: function(exports, classData, options) {
      options = options || {};
      var _mixins = exports.mixins;
      if (!exports.mixins) {
        _mixins = exports.mixins || {all: []};
      }

      function _init() {
        for (var name in classData) {
          var data = classData[name],
              spec = {};
          for (var _name in data) {
            spec[_name] = data[_name];
          }
          if (options.defaults) {
            for (var fName in options.defaults) {
              if (!spec[fName]) {
                spec[fName] = options.defaults[fName];
              }
            }
          }
          data.mixins = [data.mixins, _mixins[name], _mixins.all];
          exports[name] = React.createClass(data);
        }
      }

      exports.reset = _init;
      exports.classData = classData;
      _init();
    }
  };
};
<commit_msg>add private context mixin settings<commit_after>var cache = { id: 0 };

module.exports = function(React) {
  return {
    uniqueId: function() {
      return 'rsui-' + cache.id++;
    },

    defaults: function() {
      var base = arguments[0],
          current;
      for (var i=1; i<arguments.length; i++) {
        current = arguments[i];
        for (var name in current) {
          if (base[name] === undefined) {
            base[name] = current[name];
          }
        }
      }
      return base;
    },

    omit: function(data, keys) {
      var rtn = {};
      for (var name in data) {
        if (keys.indexOf(name) === -1) {
          rtn[name] = data[name];
        }
      }
      return rtn;
    },

    mergeClassNames: function() {
      var rtn = '';
      for (var i=0; i<arguments.length; i++) {
        if (arguments[i]) {
          if (rtn.length > 0) rtn += ' ';
          rtn += arguments[i];
        }
      }
      return rtn && rtn;
    },

    eventBinder: function(value, type, context, cancelEvent) {
      return function(event) {
        if (cancelEvent) {
          event.stopPropagation();
          event.preventDefault();
        }
        if (context[type]) {
          context[type](value, event);
        }
        if (context.props[type]) {
          context.props[type](value, event);
        }
      };
    },

    result: function(value, context) {
      if (typeof value === 'function') {
        return value.call(context);
      } else {
        return value;
      }
    },

    init: function(exports, classData, options) {
      options = options || {};
      var _mixins = exports.mixins;
      if (!exports.mixins) {
        _mixins = exports.mixins || {all: []};
      }

      function _init() {
        for (var name in classData) {
          var data = classData[name],
              spec = {};
          for (var _name in data) {
            spec[_name] = data[_name];
          }
          if (options.defaults) {
            for (var fName in options.defaults) {
              if (!spec[fName]) {
                spec[fName] = options.defaults[fName];
              }
            }
          }
          options.mixins = options.mixins || {};
          spec.mixins = [spec.mixins, _mixins[name], _mixins.all, options.mixins[name], options.mixins.all];
          exports[name] = React.createClass(spec);
        }
      }

      exports.reset = _init;
      exports.classData = classData;
      _init();
    }
  };
};
<|endoftext|>


<commit_before>/*
    Rob Holme

    Common functions used across the extension commands
*/

const vscode = require('vscode');
const resultClass = require('./ExtractFieldResult.js');

//----------------------------------------------------
// Parse the delimiters for the currently opened HL7 message. If more than one message per file
// this will assume the delimiters are the same for all messages (only the first MSH segment
// is examined). The currentMessage parameter supplies the message text to parse, if not supplied
// as a parameter the active document in the editor will be used instead.
//
// @param {string} currentMessage - A string containing the message text of a HL7 message to parse the delimiters in.
//									If not supplied, the function will default to using the active document in the editor.
//
// @returns {object} - returns a object containing the HL7 delimiters used in the message
function ParseDelimiters(currentMessage) {

	// if the message content is not passed in as a string, get the text from the current document open in the editor
	if (!currentMessage) {
		const vscode = require('vscode');
		var window = vscode.window;
		var currentMessage = window.activeTextEditor.document.getText();
	}

	// default delimiter values, return these if not detected in the message header
	var field = "|";
	var component = "^";
	var subcomponent = "&";
	var escape = "\\";
	var repeat = "~";

	var hl7HeaderRegex = /^MSH(.){5}/im;
	var result = hl7HeaderRegex.exec(currentMessage);
	// if the result is null, then the default delimiter characters would apply
	if (result != null) {
		field = result[0][3];
		component = result[0][4];
		repeat = result[0][5];
		escape = result[0][6];
		subcomponent = result[0][7];
	}
	var delimiters = { FIELD: field, COMPONENT: component, REPEAT: repeat, ESCAPE: escape, SUBCOMPONENT: subcomponent };
	return delimiters;
}

//----------------------------------------------------
// Identify if the vscode document contains a valid HL7 v2.x message
// @param {object} vsCodeDocument - the vscode document object to check.
//
// @returns {boolean} - Return true if a HL7 v2.x file is detected, otherwise returns false
function IsHL7File(vsCodeDocument) {
	if (vsCodeDocument) {
		if (vsCodeDocument.languageId == "hl7") {
			return true;
		}
		var allText = vsCodeDocument.getText();
		var delimiters = ParseDelimiters(allText);
		var hl7HeaderRegex = new RegExp("(^MSH\\" + delimiters.FIELD + ")|(^FHS\\" + delimiters.FIELD + ")|(^BHS\\" + delimiters.FIELD + ")", "i");
		if (hl7HeaderRegex.test(allText)) {
			return true;
		}
		else {
			return false;
		}
	}
	else {
		return false;
	}
}

//----------------------------------------------------
// Add trailing characters to right pad a string
// @param {string} stringToPad - the original string to apply the padding to.
// @param {int} padLength - the total size to pad the string length to (including the original string).
// @param {char} padChar - the character to use for the padding. Defaults to a space if this parameter is not supplied.
//
// @returns {string} - Returns the string padded to the specified length. If the original string is longer than the requested
//						pad length, the original string is returned in full without truncation.
// TO DO: add optional true/false parameter to truncate the string if longer than pad length (default to false)
function padRight(stringToPad, padLength, padChar) {
	// default to space if the padding char not supplied
	if (padChar === undefined) {
		padChar = ' ';
	}
	// convert to string, such as when an numeric string is interpreted as an integer.
	stringToPad = stringToPad.toString();

	// if the string length is already equal to or greater than the pad length, then return the original string in it's entirety (no truncation)
	if (stringToPad.length < padLength) {
		// no string provided, so return all padding characters
		if (!stringToPad) {
			for (var i = 0; i < padLength; i++) {
				stringToPad += padChar;
			}
		}
		// else pad out the string
		else {
			var maxLength = (padLength - stringToPad.length);
			for (var i = 0; i < maxLength; i++) {
				stringToPad += padChar;
			}
		}
	}
	return stringToPad;
}

//----------------------------------------------------
// Add leading characters to left pad a string
// @param {string} stringToPad - the original string to apply the padding to.
// @param {int} padLength - the total size to pad the string length to (including the original string).
// @param {char} padChar - the character to use for the padding. Defaults to a space if this parameter is not supplied.
//
// @returns {string} - Returns the string padded to the specified length. If the original string is longer than the requested
//						pad length, the original string is returned in full without truncation.
// TO DO: add optional true/false parameter to truncate the string if longer than pad length (default to false)
function padLeft(stringToPad, padLength, padChar) {
	// default to space if the padding char not supplied
	if (padChar === undefined) {
		padChar = ' ';
	}

	// convert to string, such as when an numeric string is interpreted as an integer.
	stringToPad = stringToPad.toString();

	if (!stringToPad || stringToPad.length >= padLength) {
		return stringToPad;
	}
	var maxLength = (padLength - stringToPad.length);
	for (var i = 0; i < maxLength; i++) {
		stringToPad = padChar + stringToPad;
	}
	return stringToPad;
}

//----------------------------------------------------
//  Finds active documents by cycling them.
//  From https://github.com/atishay/vscode-allautocomplete
//
function findActiveDocsHack() {

	// Based on https://github.com/eamodio/vscode-restore-editors/blob/master/src/documentManager.ts#L57
	const vscode = require('vscode');

	return new Promise((resolve, reject) => {
		let active = vscode.window.activeTextEditor;
		let editor = active;
		const openEditors = [];
		function handleNextEditor() {
			if (editor !== undefined) {
				// If we didn't start with a valid editor, set one once we find it
				if (active === undefined) {
					active = editor;
				}
				openEditors.push(editor);
			}
			// window.onDidChangeActiveTextEditor should work here but I don't know why it doesn't
			setTimeout(() => {
				editor = vscode.window.activeTextEditor;
				if (editor !== undefined && openEditors.some(_ => _._id === editor._id))
					return resolve();
				if ((active === undefined && editor === undefined) || editor._id !== active._id)
					return handleNextEditor();
				resolve();
			}, 250);
			vscode.commands.executeCommand('workbench.action.nextEditor');
		}
		handleNextEditor();
	});

}

//----------------------------------------------------
// return a resultCollection object containing all of the field value(s) identified by the segmentName and fieldIndex parameters.
// @param {string} segmentName - The name of the segment contain the field (e.g. PID, PV1, NK1)
// @param {int} fieldIndex - The index identifying the field in the segment (1 based index).
//
// @returns {object} - returns an object containing the field value and the name of the file the value was found in.
function GetFields(segmentName, fieldIndex) {
	var results = new resultClass.resultCollection();

	// exit if the editor is not active
	var allTextDocuments = vscode.workspace.textDocuments;
	if (!allTextDocuments) {
		return results;
	}

	// for each open editor (document), search the file for a matching field
	for (i = 0; i < allTextDocuments.length; i++) {
		var currentDoc = allTextDocuments[i];
		if (IsHL7File(currentDoc)) {
			// load the message delimiters from the current file
			var allText = currentDoc.getText();
			var delimiters = ParseDelimiters(allText);
			var segmentRegex = new RegExp("^" + segmentName + "\\" + delimiters.FIELD)
			for (lineIndex = 0; lineIndex < currentDoc.lineCount; lineIndex++) {
				var currentLine = currentDoc.lineAt(lineIndex).text;
				if (segmentRegex.test(currentLine)) {
					var fields = currentLine.split(delimiters.FIELD);
					if (fieldIndex < fields.length) {
						var repeats = fields[fieldIndex].split(delimiters.REPEAT);
						for (repeatIndex = 0; repeatIndex < repeats.length; repeatIndex++) {
							var resultItem = new resultClass.result(currentDoc.fileName, repeats[repeatIndex]);
							results.AddResult(resultItem);
						}
					}
				}
			}
		}
	}
	return results;
}

//----------------------------------------------------
// Confirm if the location string provided is valid.
// This checks the syntax, it does not confirm if the location is present in the message.
// @param {string} itemLocation - A string identifying the location of the field. e.g. PID-3
//
// @returns {boolean} - returns true if the location string's syntax is valid. It does not confiem if the item is present in the message or not.
function IsItemLocationValid(itemLocation) {
	var itemLocationRegex = new RegExp("^[A-Z]{2}([A-Z]|[0-9])[-]([1-9][0-9]{0,2})$", 'i');
	// test to see if the user has provided a valid location string
	if (!itemLocationRegex.test(itemLocation)) {
		return false;
	}
	return true;
}

//----------------------------------------------------
// get the field index from a location string
// @param {string} hl7ItemlocationString - A string identifying the location of the field. e.g. PID-3
//
// @returns {int} - returns the field index contained in the HL7 location string parameter.
function GetFieldIndex(hl7ItemlocationString) {
	var split1 = hl7ItemlocationString.split("-");
	if (split1.length > 1) {
		return split1[1].split(".")[0];
	}
	else {
		return;
	}
}

//----------------------------------------------------
// extract the segment name from the hl7 item location string
// @param {string} hl7ItemlocationString - A string identifying the location of the field. e.g. PID-3
//
// @returns {string} - returns the segment name contained in the HL7 location string parameter.
function GetSegmentNameFromLocationString(hl7ItemlocationString) {
	return hl7ItemlocationString.substring(0, 3);
}

//----------------------------------------------------
// Return an array of HL7 location strings that match the fieldDescription parameter.
// The array is indexed with the 3 letter segment name, the value is the field index.
// @param {string} fieldDescription - a string containing a description, or partial description of the field. e.g. "Patient Name"
// @param {object} hl7Schema - An object containing the HL7 schema corresponding to the version of the HL7 message
//
// @return {object} - a hashtable containing HL7 location strings for every field matching the description supplied by the fieldDescription parameter. Includes partial matches.
function FindLocationFromDescription(fieldDescription, hl7Schema) {
	var locationHashtable = {};
	var itemLocationRegex = new RegExp("^[A-Z]{2}([A-Z]|[0-9])[-]([0-9]{1,3})$", 'i');
	var currentDoc = vscode.window.activeTextEditor.document;
	// regex to match the description of the segment provided
	var nameRegEx = new RegExp(fieldDescription, "i");

	// Test to see if the user has provided a valid location string, otherwise assume a description has been provided instead
	if (itemLocationRegex.test(fieldDescription)) {
		// identify the segment name and field index from the location string
		var segmentName = GetSegmentNameFromLocationString(fieldDescription).toUpperCase();
		var fieldIndex = parseInt(GetFieldIndex(fieldDescription), 10);
		// the first field of MSH segments is the field delimiter, adjust index accordingly for MSH fields
		if (segmentName == "MSH") {
			fieldIndex--;
		}
		locationHashtable[segmentName] = [fieldIndex];
	}
	// else assume the user has provided a field description to search for instead of a location.
	else {
		// find matching field names for any segment present in the message
		var segmentHash = GetAllSegmentNames(currentDoc);
		for (var key in segmentHash) {
			var segmentDef = hl7Schema[key];
			// ignore segments not present in the hl7 scheme (i.e. custom Z segments)
			if (!(segmentDef === undefined)) {
				fieldIndexArray = [];
				for (var i = 0; i < segmentDef.fields.length; i++) {
					if (nameRegEx.test(segmentDef.fields[i].desc)) {
						// the first field of MSH segments is the field delimiter, adjust index accordingly for MSH fields
						if (key == "MSH") {
							fieldIndexArray.push(i);
						}
						else {
							fieldIndexArray.push(i + 1);
						}
					}
				}
				if (fieldIndexArray.length > 0) {
					locationHashtable[key] = fieldIndexArray;
				}
			}
		}
	}
	return locationHashtable;
}

//----------------------------------------------------
// return the unique names of all segments in the message. Return as a associative array indexed by segment name. key values are not consequential.
// @param {object} document - a vscode document object containing a HL7 message
//
// @returns {object} - returns a hashtable containing all unique segment names (as keys).
function GetAllSegmentNames(document) {
	// load the message delimiters from the current file
	var allText = document.getText();
	var delimiters = ParseDelimiters(allText);

	var segmentHashtable = {};
	var segmentRegex = new RegExp("^[A-Z]{2}([A-Z]|[0-9])\\" + delimiters.FIELD, "i")
	for (var i = 0; i < document.lineCount; i++) {
		var currentSegment = document.lineAt(i).text;
		if (segmentRegex.test(currentSegment)) {
			var segmentName = currentSegment.split(delimiters.FIELD)[0];
			if (segmentHashtable[segmentName.toUpperCase()] === undefined) {
				segmentHashtable[segmentName.toUpperCase()] = 1;
			}
		}
	}
	return segmentHashtable;
}

exports.findActiveDocsHack = findActiveDocsHack;
exports.ParseDelimiters = ParseDelimiters;
exports.IsHL7File = IsHL7File;
exports.padRight = padRight;
exports.padLeft = padLeft;
exports.GetFields = GetFields;
exports.IsItemLocationValid = IsItemLocationValid;
exports.GetFieldIndex = GetFieldIndex;
exports.GetSegmentNameFromLocationString = GetSegmentNameFromLocationString;
exports.FindLocationFromDescription = FindLocationFromDescription;
<commit_msg>Added IsSegmentValid() fucntion<commit_after>/*
    Rob Holme

    Common functions used across the extension commands
*/

const vscode = require('vscode');
const resultClass = require('./ExtractFieldResult.js');

//----------------------------------------------------
// Parse the delimiters for the currently opened HL7 message. If more than one message per file
// this will assume the delimiters are the same for all messages (only the first MSH segment
// is examined). The currentMessage parameter supplies the message text to parse, if not supplied
// as a parameter the active document in the editor will be used instead.
//
// @param {string} currentMessage - A string containing the message text of a HL7 message to parse the delimiters in.
//									If not supplied, the function will default to using the active document in the editor.
//
// @returns {object} - returns a object containing the HL7 delimiters used in the message
function ParseDelimiters(currentMessage) {

	// if the message content is not passed in as a string, get the text from the current document open in the editor
	if (!currentMessage) {
		const vscode = require('vscode');
		var window = vscode.window;
		var currentMessage = window.activeTextEditor.document.getText();
	}

	// default delimiter values, return these if not detected in the message header
	var field = "|";
	var component = "^";
	var subcomponent = "&";
	var escape = "\\";
	var repeat = "~";

	var hl7HeaderRegex = /^MSH(.){5}/im;
	var result = hl7HeaderRegex.exec(currentMessage);
	// if the result is null, then the default delimiter characters would apply
	if (result != null) {
		field = result[0][3];
		component = result[0][4];
		repeat = result[0][5];
		escape = result[0][6];
		subcomponent = result[0][7];
	}
	var delimiters = { FIELD: field, COMPONENT: component, REPEAT: repeat, ESCAPE: escape, SUBCOMPONENT: subcomponent };
	return delimiters;
}

//----------------------------------------------------
// Identify if the vscode document contains a valid HL7 v2.x message
// @param {object} vsCodeDocument - the vscode document object to check.
//
// @returns {boolean} - Return true if a HL7 v2.x file is detected, otherwise returns false
function IsHL7File(vsCodeDocument) {
	if (vsCodeDocument) {
		if (vsCodeDocument.languageId == "hl7") {
			return true;
		}
		var allText = vsCodeDocument.getText();
		var delimiters = ParseDelimiters(allText);
		var hl7HeaderRegex = new RegExp("(^MSH\\" + delimiters.FIELD + ")|(^FHS\\" + delimiters.FIELD + ")|(^BHS\\" + delimiters.FIELD + ")", "i");
		if (hl7HeaderRegex.test(allText)) {
			return true;
		}
		else {
			return false;
		}
	}
	else {
		return false;
	}
}

//----------------------------------------------------
// Add trailing characters to right pad a string
// @param {string} stringToPad - the original string to apply the padding to.
// @param {int} padLength - the total size to pad the string length to (including the original string).
// @param {char} padChar - the character to use for the padding. Defaults to a space if this parameter is not supplied.
//
// @returns {string} - Returns the string padded to the specified length. If the original string is longer than the requested
//						pad length, the original string is returned in full without truncation.
// TO DO: add optional true/false parameter to truncate the string if longer than pad length (default to false)
function padRight(stringToPad, padLength, padChar) {
	// default to space if the padding char not supplied
	if (padChar === undefined) {
		padChar = ' ';
	}
	// convert to string, such as when an numeric string is interpreted as an integer.
	stringToPad = stringToPad.toString();

	// if the string length is already equal to or greater than the pad length, then return the original string in it's entirety (no truncation)
	if (stringToPad.length < padLength) {
		// no string provided, so return all padding characters
		if (!stringToPad) {
			for (var i = 0; i < padLength; i++) {
				stringToPad += padChar;
			}
		}
		// else pad out the string
		else {
			var maxLength = (padLength - stringToPad.length);
			for (var i = 0; i < maxLength; i++) {
				stringToPad += padChar;
			}
		}
	}
	return stringToPad;
}

//----------------------------------------------------
// Add leading characters to left pad a string
// @param {string} stringToPad - the original string to apply the padding to.
// @param {int} padLength - the total size to pad the string length to (including the original string).
// @param {char} padChar - the character to use for the padding. Defaults to a space if this parameter is not supplied.
//
// @returns {string} - Returns the string padded to the specified length. If the original string is longer than the requested
//						pad length, the original string is returned in full without truncation.
// TO DO: add optional true/false parameter to truncate the string if longer than pad length (default to false)
function padLeft(stringToPad, padLength, padChar) {
	// default to space if the padding char not supplied
	if (padChar === undefined) {
		padChar = ' ';
	}

	// convert to string, such as when an numeric string is interpreted as an integer.
	stringToPad = stringToPad.toString();

	if (!stringToPad || stringToPad.length >= padLength) {
		return stringToPad;
	}
	var maxLength = (padLength - stringToPad.length);
	for (var i = 0; i < maxLength; i++) {
		stringToPad = padChar + stringToPad;
	}
	return stringToPad;
}

//----------------------------------------------------
//  Finds active documents by cycling them.
//  From https://github.com/atishay/vscode-allautocomplete
//
function findActiveDocsHack() {

	// Based on https://github.com/eamodio/vscode-restore-editors/blob/master/src/documentManager.ts#L57
	const vscode = require('vscode');

	return new Promise((resolve, reject) => {
		let active = vscode.window.activeTextEditor;
		let editor = active;
		const openEditors = [];
		function handleNextEditor() {
			if (editor !== undefined) {
				// If we didn't start with a valid editor, set one once we find it
				if (active === undefined) {
					active = editor;
				}
				openEditors.push(editor);
			}
			// window.onDidChangeActiveTextEditor should work here but I don't know why it doesn't
			setTimeout(() => {
				editor = vscode.window.activeTextEditor;
				if (editor !== undefined && openEditors.some(_ => _._id === editor._id))
					return resolve();
				if ((active === undefined && editor === undefined) || editor._id !== active._id)
					return handleNextEditor();
				resolve();
			}, 250);
			vscode.commands.executeCommand('workbench.action.nextEditor');
		}
		handleNextEditor();
	});

}

//----------------------------------------------------
// return a resultCollection object containing all of the field value(s) identified by the segmentName and fieldIndex parameters.
// @param {string} segmentName - The name of the segment contain the field (e.g. PID, PV1, NK1)
// @param {int} fieldIndex - The index identifying the field in the segment (1 based index).
//
// @returns {object} - returns an object containing the field value and the name of the file the value was found in.
function GetFields(segmentName, fieldIndex) {
	var results = new resultClass.resultCollection();

	// exit if the editor is not active
	var allTextDocuments = vscode.workspace.textDocuments;
	if (!allTextDocuments) {
		return results;
	}

	// for each open editor (document), search the file for a matching field
	for (i = 0; i < allTextDocuments.length; i++) {
		var currentDoc = allTextDocuments[i];
		if (IsHL7File(currentDoc)) {
			// load the message delimiters from the current file
			var allText = currentDoc.getText();
			var delimiters = ParseDelimiters(allText);
			var segmentRegex = new RegExp("^" + segmentName + "\\" + delimiters.FIELD)
			for (lineIndex = 0; lineIndex < currentDoc.lineCount; lineIndex++) {
				var currentLine = currentDoc.lineAt(lineIndex).text;
				if (segmentRegex.test(currentLine)) {
					var fields = currentLine.split(delimiters.FIELD);
					if (fieldIndex < fields.length) {
						var repeats = fields[fieldIndex].split(delimiters.REPEAT);
						for (repeatIndex = 0; repeatIndex < repeats.length; repeatIndex++) {
							var resultItem = new resultClass.result(currentDoc.fileName, repeats[repeatIndex]);
							results.AddResult(resultItem);
						}
					}
				}
			}
		}
	}
	return results;
}

//----------------------------------------------------
// Confirm if the location string provided is valid.
// This checks the syntax, it does not confirm if the location is present in the message.
// @param {string} itemLocation - A string identifying the location of the field. e.g. PID-3
//
// @returns {boolean} - returns true if the location string's syntax is valid. It does not confiem if the item is present in the message or not.
function IsItemLocationValid(itemLocation) {
	var itemLocationRegex = new RegExp("^[A-Z]{2}([A-Z]|[0-9])[-]([1-9][0-9]{0,2})$", 'i');
	// test to see if the user has provided a valid location string
	if (!itemLocationRegex.test(itemLocation)) {
		return false;
	}
	return true;
}

//----------------------------------------------------
// Confirms if a segment starts with the expected pattern. Does not confirm if the segment is in the schema
// @param {string} segment - a string containing a HL7 segment
//
// @returns {bool} - returns true if the start of the line contains a segment name and field delimiter
function IsSegmentValid(Segment, FieldDelimeter) {
	// Looking for [A-Z][A-Z]([A-Z]|[0-9]) for standard segments, and [z]([a-z]|[0-9]){2} for Z segments. (Some may use Z01 for custom segments, but standard segments should always starts with 2 letter, then  3rd letter or digit).
	var validSegmentRegEx = new RegExp("^([a-z]{2}([a-z]|([0-9]))|([z]([a-z]|[0-9]){2}))\\" + FieldDelimeter, "i");
	return validSegmentRegEx.test(Segment);
}

//----------------------------------------------------
// get the field index from a location string
// @param {string} hl7ItemlocationString - A string identifying the location of the field. e.g. PID-3
//
// @returns {int} - returns the field index contained in the HL7 location string parameter.
function GetFieldIndex(hl7ItemlocationString) {
	var split1 = hl7ItemlocationString.split("-");
	if (split1.length > 1) {
		return split1[1].split(".")[0];
	}
	else {
		return;
	}
}

//----------------------------------------------------
// extract the segment name from the hl7 item location string
// @param {string} hl7ItemlocationString - A string identifying the location of the field. e.g. PID-3
//
// @returns {string} - returns the segment name contained in the HL7 location string parameter.
function GetSegmentNameFromLocationString(hl7ItemlocationString) {
	return hl7ItemlocationString.substring(0, 3);
}

//----------------------------------------------------
// Return an array of HL7 location strings that match the fieldDescription parameter.
// The array is indexed with the 3 letter segment name, the value is the field index.
// @param {string} fieldDescription - a string containing a description, or partial description of the field. e.g. "Patient Name"
// @param {object} hl7Schema - An object containing the HL7 schema corresponding to the version of the HL7 message
//
// @return {object} - a hashtable containing HL7 location strings for every field matching the description supplied by the fieldDescription parameter. Includes partial matches.
function FindLocationFromDescription(fieldDescription, hl7Schema) {
	var locationHashtable = {};
	var itemLocationRegex = new RegExp("^[A-Z]{2}([A-Z]|[0-9])[-]([0-9]{1,3})$", 'i');
	var currentDoc = vscode.window.activeTextEditor.document;
	// regex to match the description of the segment provided
	var nameRegEx = new RegExp(fieldDescription, "i");

	// Test to see if the user has provided a valid location string, otherwise assume a description has been provided instead
	if (itemLocationRegex.test(fieldDescription)) {
		// identify the segment name and field index from the location string
		var segmentName = GetSegmentNameFromLocationString(fieldDescription).toUpperCase();
		var fieldIndex = parseInt(GetFieldIndex(fieldDescription), 10);
		// the first field of MSH segments is the field delimiter, adjust index accordingly for MSH fields
		if (segmentName == "MSH") {
			fieldIndex--;
		}
		locationHashtable[segmentName] = [fieldIndex];
	}
	// else assume the user has provided a field description to search for instead of a location.
	else {
		// find matching field names for any segment present in the message
		var segmentHash = GetAllSegmentNames(currentDoc);
		for (var key in segmentHash) {
			var segmentDef = hl7Schema[key];
			// ignore segments not present in the hl7 scheme (i.e. custom Z segments)
			if (!(segmentDef === undefined)) {
				fieldIndexArray = [];
				for (var i = 0; i < segmentDef.fields.length; i++) {
					if (nameRegEx.test(segmentDef.fields[i].desc)) {
						// the first field of MSH segments is the field delimiter, adjust index accordingly for MSH fields
						if (key == "MSH") {
							fieldIndexArray.push(i);
						}
						else {
							fieldIndexArray.push(i + 1);
						}
					}
				}
				if (fieldIndexArray.length > 0) {
					locationHashtable[key] = fieldIndexArray;
				}
			}
		}
	}
	return locationHashtable;
}

//----------------------------------------------------
// return the unique names of all segments in the message. Return as a associative array indexed by segment name. key values are not consequential.
// @param {object} document - a vscode document object containing a HL7 message
//
// @returns {object} - returns a hashtable containing all unique segment names (as keys).
function GetAllSegmentNames(document) {
	// load the message delimiters from the current file
	var allText = document.getText();
	var delimiters = ParseDelimiters(allText);

	var segmentHashtable = {};
	var segmentRegex = new RegExp("^[A-Z]{2}([A-Z]|[0-9])\\" + delimiters.FIELD, "i")
	for (var i = 0; i < document.lineCount; i++) {
		var currentSegment = document.lineAt(i).text;
		if (segmentRegex.test(currentSegment)) {
			var segmentName = currentSegment.split(delimiters.FIELD)[0];
			if (segmentHashtable[segmentName.toUpperCase()] === undefined) {
				segmentHashtable[segmentName.toUpperCase()] = 1;
			}
		}
	}
	return segmentHashtable;
}

exports.findActiveDocsHack = findActiveDocsHack;
exports.ParseDelimiters = ParseDelimiters;
exports.IsHL7File = IsHL7File;
exports.padRight = padRight;
exports.padLeft = padLeft;
exports.GetFields = GetFields;
exports.IsItemLocationValid = IsItemLocationValid;
exports.IsSegmentValid = IsSegmentValid;
exports.GetFieldIndex = GetFieldIndex;
exports.GetSegmentNameFromLocationString = GetSegmentNameFromLocationString;
exports.FindLocationFromDescription = FindLocationFromDescription;
<|endoftext|>


<commit_before>const Markdown=require('markdown-it')({
  html:true
});
const JSDOM=require('jsdom').JSDOM;
const ejs=require('ejs');
const iconv=require('iconv-lite');

//Tools for calling imagemagick convert
const util = require('util');
const spawn = require('child_process').spawn;

//MathJAX init
const mathjax = require('mathjax-full/js/mathjax.js').mathjax;
const TeX = require('mathjax-full/js/input/tex.js').TeX;
const SVG = require('mathjax-full/js/output/svg.js').SVG;
const liteAdaptor = require('mathjax-full/js/adaptors/liteAdaptor.js').liteAdaptor;
const RegisterHTMLHandler = require('mathjax-full/js/handlers/html.js').RegisterHTMLHandler;
const adaptor = liteAdaptor({
  fontSize:16
});
RegisterHTMLHandler(adaptor);

const tex = new TeX({packages:require('mathjax-full/js/input/tex/AllPackages.js').AllPackages});
const svg = new SVG({fontCache:'none', internalSpeechTitles:false});

function processTexHanzi(content){
  let regex=/\\text{[^}]+}/g, text=[], counter=10000;
  while(counter--){
    let match=regex.exec(content);
    if(!match){
      break;
    }
    content.slice(match.index);
    text.push(match[0]);
  }
  if(counter<=0){
    console.error('Dead loop!!!');
  }
  for(let item of text){
    let itemNew=item.replace(/([\u1100-\u11F9\u3000-\u303F\u3041-\u3094\u3099-\u309E\u30A1-\u30FE\u3131-\u318E\u3190-\u319F\u3200-\u321C\u3220-\u3243\u3260-\u32B0\u32C0-\u3376\u337B-\u33DD\u33E0-\u33FE\u4E00-\u9FA5\uAC00-\uD7A3\uE000-\uE757\uF900-\uFA2D\uFE30-\uFE44\uFE49-\uFE52\uFE54-\uFE6B\uFF01-\uFF5E\uFFE0-\uFFE6])/g,'$1 ');
    content=content.replace(item,itemNew);
  }
  return content;
}
function svg2gif(svgData){
  return new Promise((resolve,reject)=>{
    let rsvgConvert=spawn('rsvg-convert',['-b','#ffffff','-f','png']),
      convert=spawn('convert',['-','+dither','+antialias','-colors','16','GIF:-']),
      result=Buffer.alloc(0,0,'binary');
    rsvgConvert.stderr.on('data',(data)=>{
      console.error('rsvg:',data.toString());
    });
    convert.stderr.on('data',(data)=>{
      console.error('convert:',data.toString());
    });
    rsvgConvert.stdout.pipe(convert.stdin);
    convert.stdout.on('data',(data)=>{
      result=Buffer.concat([result,data]);
    });
    convert.on('close',()=>{
      resolve(result);
    });
    rsvgConvert.stdin.write(svgData);
    rsvgConvert.stdin.end();
  });
}
function applyFont(document,text,fontTable={}){
  let _apply=(text,charType)=>{
    let node;
    if(fontTable[charType]){
      node=document.createElement('font');
      node.setAttribute('face', fontTable[charType]);
      node.appendChild(document.createTextNode(textProc));
    }else{
      node=document.createTextNode(textProc);
    }
    return node;
  }

  let textProc='', lastCharType=null, result=document.createDocumentFragment();
  for(let i=0; i<text.length; i++){
    let ch=text[i], charCode=text.charCodeAt(i), charType=null;
    if(charCode>=0x20 && charCode <= 0x7f){
      charType='ascii';
    }else if(charCode>0x7f){
      charType='cjk';
    }else{
      charType=null;
    }

    if(charType==lastCharType){
      textProc+=ch;
      continue;
    }else if(!textProc.length){
      textProc+=ch;
      lastCharType=charType;
      continue;
    }

    result.appendChild(_apply(textProc, lastCharType));

    textProc=ch;
    lastCharType=charType;
  }
  if(textProc){
    result.appendChild(_apply(textProc, lastCharType));
  }
  return result;
}
function processTitle(title,params={}){
  var dom=new JSDOM();
  var document=dom.window.document;
  document.body.appendChild(applyFont(document,title,params.font));
  return document.body.innerHTML;
}
function processSVG(document,svg){
  for(let textNode of svg.querySelectorAll('text')){
    let ch=textNode.childNodes[0].nodeValue;
    let glyph=global.fontManager.getGlyph(ch,0,'HZKPSST.GBK');
    if(!glyph || !glyph.toSVG()){
      continue;
    }
    let path=document.createElement('path'), fontSize=880;
    for(let attr of textNode.attributes){
      switch(attr.nodeName){
        case 'font-size':
          fontSize=parseInt(attr.value);
        break;
        case 'font-family':
        break;
        default:
          path.setAttribute(attr.nodeName,attr.nodeValue);
        break;
      }
    }
    let scale=fontSize/glyph.BASE_HEIGHT;
    path.setAttribute(
      'transform',
      (path.getAttribute('transform')||'')
        .replace(/matrix\([^\)]*\)/g,`matrix(${scale} 0 0 ${-scale} 0 ${600+(fontSize-600)/2})`)
    );
    path.setAttribute('d',glyph.toSVG());
    textNode.parentNode.replaceChild(path,textNode);
  }
}
async function processHTML(content,params={}){
  //Replace equations with corresponding images
  var dom=new JSDOM(content);
  var document=dom.window.document;
  var containers=document.querySelectorAll('mjx-container');

  let svgList=[];
  for(let item of containers){
    //Get svg data
    let svg=item.querySelector('svg');
    let width=parseFloat(svg.getAttribute('width'));
    let height=parseFloat(svg.getAttribute('height'));
    let scale=params.scale || 16;
    svg.setAttribute('width',`${width*scale}px`);
    svg.setAttribute('height',`${height*scale}px`);

    //Convert Chinese characters to its correcct glyph
    processSVG(document,svg);
    let svgContent='<?xml version="1.0" encoding="UTF-8" standalone="no"?>\n'+item.innerHTML;

    //Replace svg with image tag
    let img=document.createElement('img');
    let imgPath=`${params.imagePrefix||''}e${svgList.length}.gif`;
    img.setAttribute('src',imgPath);
    img.setAttribute('valign','middle');
    img.setAttribute('align','center');
    item.parentNode.replaceChild(img,item);

    //Prepare data for conversion
    svgList.push({
      path:imgPath,
      data:svgContent
    });
  }

  let imgList=[];
  for(let item of svgList){
    imgList.push({
      ...item,
      data:await svg2gif(item.data)
    });
  }
  /*
  let resp=await Promise.all(svgList.map(item=>svg2gif(item.data)));
  let len=resp.length, imgList=[];
  for(let i=0; i<len; i++){
    imgList.push({
      ...svgList[i],
      data:resp[i]
    });
  }
  */

  //Walk through the whole dom
  let tagNameBlacklist={
    'CODE':true,
    'PRE':true,
    'IMG':true,
    'BR':true
  };
  let _procDom=(nodeList)=>{
    let nodeListCopy=[];
    for(let item of nodeList){
      nodeListCopy.push(item);
    }
    for(let node of nodeListCopy){
      if(tagNameBlacklist[node.tagName]){
        continue;
      }

      //Process child nodes
      if(1==node.nodeType){
        _procDom(node.childNodes);
        continue;
      }

      //Replace child node with font applied
      if(3==node.nodeType){
        node.parentNode.replaceChild(applyFont(document, node.nodeValue, params.font),node);
      }
    }
  }
  _procDom(document.body.childNodes);

  //Add template
  let html=document.body.innerHTML;
  if(params.template){
    html=await new Promise((resolve,reject)=>{
      ejs.renderFile(params.template,{
        encoding:params.targetEncoding,
        title:params.title,
        titleProcessed:processTitle(params.title,params),
        content:html
      },(e,data)=>(e?reject(e):resolve(data)));
    });
  }
  return {
    html:params.targetEncoding ? iconv.encode(html,params.targetEncoding) : html,
    image:imgList
  };
}
module.exports=async function(content,params={}){
  var contentHTML=processTexHanzi(Markdown.render(content));
  var html = mathjax.document(contentHTML, {InputJax: tex, OutputJax: svg});
  html.render();
  return await processHTML(adaptor.outerHTML(adaptor.root(html.document)),{
    ...params
  });
}

<commit_msg>Updated<commit_after>const Markdown=require('markdown-it')({
  html:true
});
const JSDOM=require('jsdom').JSDOM;
const ejs=require('ejs');
const iconv=require('iconv-lite');

//Tools for calling imagemagick convert
const util = require('util');
const spawn = require('child_process').spawn;

//MathJAX init
const mathjax = require('mathjax-full/js/mathjax.js').mathjax;
const TeX = require('mathjax-full/js/input/tex.js').TeX;
const SVG = require('mathjax-full/js/output/svg.js').SVG;
const liteAdaptor = require('mathjax-full/js/adaptors/liteAdaptor.js').liteAdaptor;
const RegisterHTMLHandler = require('mathjax-full/js/handlers/html.js').RegisterHTMLHandler;
const adaptor = liteAdaptor({
  fontSize:16
});
RegisterHTMLHandler(adaptor);

const tex = new TeX({packages:require('mathjax-full/js/input/tex/AllPackages.js').AllPackages});
const svg = new SVG({fontCache:'none', internalSpeechTitles:false});

function processTexHanzi(content){
  let regex=/\\text{[^}]+}/g, text=[], counter=10000;
  while(counter--){
    let match=regex.exec(content);
    if(!match){
      break;
    }
    content.slice(match.index);
    text.push(match[0]);
  }
  if(counter<=0){
    console.error('Dead loop!!!');
  }
  for(let item of text){
    let itemNew=item.replace(/([\u1100-\u11F9\u3000-\u303F\u3041-\u3094\u3099-\u309E\u30A1-\u30FE\u3131-\u318E\u3190-\u319F\u3200-\u321C\u3220-\u3243\u3260-\u32B0\u32C0-\u3376\u337B-\u33DD\u33E0-\u33FE\u4E00-\u9FA5\uAC00-\uD7A3\uE000-\uE757\uF900-\uFA2D\uFE30-\uFE44\uFE49-\uFE52\uFE54-\uFE6B\uFF01-\uFF5E\uFFE0-\uFFE6])/g,'$1 ');
    content=content.replace(item,itemNew);
  }
  return content;
}
function svg2gif(svgData){
  return new Promise((resolve,reject)=>{
    let rsvgConvert=spawn('rsvg-convert',['-b','#ffffff','-f','png']),
      convert=spawn('convert',['-','+dither','+antialias','-colors','16','GIF:-']),
      result=Buffer.alloc(0,0,'binary');
    rsvgConvert.stderr.on('data',(data)=>{
      console.error('rsvg:',data.toString());
    });
    convert.stderr.on('data',(data)=>{
      console.error('convert:',data.toString());
    });
    rsvgConvert.stdout.pipe(convert.stdin);
    convert.stdout.on('data',(data)=>{
      result=Buffer.concat([result,data]);
    });
    convert.on('close',()=>{
      resolve(result);
    });
    rsvgConvert.stdin.write(svgData);
    rsvgConvert.stdin.end();
  });
}
function applyFont(document,text,fontTable={}){
  let _apply=(text,charType)=>{
    let node;
    if(fontTable[charType]){
      node=document.createElement('font');
      node.setAttribute('face', fontTable[charType]);
      node.appendChild(document.createTextNode(textProc));
    }else{
      node=document.createTextNode(textProc);
    }
    return node;
  }

  let textProc='', lastCharType=null, result=document.createDocumentFragment();
  for(let i=0; i<text.length; i++){
    let ch=text[i], charCode=text.charCodeAt(i), charType=null;
    if(charCode>=0x20 && charCode <= 0x7f){
      charType='ascii';
    }else if(charCode>0x7f){
      charType='cjk';
    }else{
      charType=null;
    }

    if(charType==lastCharType){
      textProc+=ch;
      continue;
    }else if(!textProc.length){
      textProc+=ch;
      lastCharType=charType;
      continue;
    }

    result.appendChild(_apply(textProc, lastCharType));

    textProc=ch;
    lastCharType=charType;
  }
  if(textProc){
    result.appendChild(_apply(textProc, lastCharType));
  }
  return result;
}
function processTitle(title,params={}){
  var dom=new JSDOM();
  var document=dom.window.document;
  document.body.appendChild(applyFont(document,title,params.font));
  return document.body.innerHTML;
}
function processSVG(document,svg){
  for(let textNode of svg.querySelectorAll('text')){
    let ch=textNode.childNodes[0].nodeValue;
    let glyph=global.fontManager.getGlyph(ch,0,'HZKPSST.GBK');
    if(!glyph || !glyph.toSVG()){
      continue;
    }
    let path=document.createElement('path'), fontSize=880;
    for(let attr of textNode.attributes){
      switch(attr.nodeName){
        case 'font-size':
          fontSize=parseInt(attr.value);
        break;
        case 'font-family':
        break;
        default:
          path.setAttribute(attr.nodeName,attr.nodeValue);
        break;
      }
    }
    let scale=fontSize/glyph.constructor.BASE_HEIGHT;
    path.setAttribute(
      'transform',
      (path.getAttribute('transform')||'')
        .replace(/matrix\([^\)]*\)/g,`matrix(${scale} 0 0 ${-scale} 0 ${600+(fontSize-600)/2})`)
    );
    path.setAttribute('d',glyph.toSVG());
    textNode.parentNode.replaceChild(path,textNode);
  }
}
async function processHTML(content,params={}){
  //Replace equations with corresponding images
  var dom=new JSDOM(content);
  var document=dom.window.document;
  var containers=document.querySelectorAll('mjx-container');

  let svgList=[];
  for(let item of containers){
    //Get svg data
    let svg=item.querySelector('svg');
    let width=parseFloat(svg.getAttribute('width'));
    let height=parseFloat(svg.getAttribute('height'));
    let scale=params.scale || 16;
    svg.setAttribute('width',`${width*scale}px`);
    svg.setAttribute('height',`${height*scale}px`);

    //Convert Chinese characters to its correcct glyph
    processSVG(document,svg);
    let svgContent='<?xml version="1.0" encoding="UTF-8" standalone="no"?>\n'+item.innerHTML;

    //Replace svg with image tag
    let img=document.createElement('img');
    let imgPath=`${params.imagePrefix||''}e${svgList.length}.gif`;
    img.setAttribute('src',imgPath);
    img.setAttribute('valign','middle');
    img.setAttribute('align','center');
    item.parentNode.replaceChild(img,item);

    //Prepare data for conversion
    svgList.push({
      path:imgPath,
      data:svgContent
    });
  }

  let imgList=[];
  for(let item of svgList){
    imgList.push({
      ...item,
      data:await svg2gif(item.data)
    });
  }
  /*
  let resp=await Promise.all(svgList.map(item=>svg2gif(item.data)));
  let len=resp.length, imgList=[];
  for(let i=0; i<len; i++){
    imgList.push({
      ...svgList[i],
      data:resp[i]
    });
  }
  */

  //Walk through the whole dom
  let tagNameBlacklist={
    'CODE':true,
    'PRE':true,
    'IMG':true,
    'BR':true
  };
  let _procDom=(nodeList)=>{
    let nodeListCopy=[];
    for(let item of nodeList){
      nodeListCopy.push(item);
    }
    for(let node of nodeListCopy){
      if(tagNameBlacklist[node.tagName]){
        continue;
      }

      //Process child nodes
      if(1==node.nodeType){
        _procDom(node.childNodes);
        continue;
      }

      //Replace child node with font applied
      if(3==node.nodeType){
        node.parentNode.replaceChild(applyFont(document, node.nodeValue, params.font),node);
      }
    }
  }
  _procDom(document.body.childNodes);

  //Add template
  let html=document.body.innerHTML;
  if(params.template){
    html=await new Promise((resolve,reject)=>{
      ejs.renderFile(params.template,{
        encoding:params.targetEncoding,
        title:params.title,
        titleProcessed:processTitle(params.title,params),
        content:html
      },(e,data)=>(e?reject(e):resolve(data)));
    });
  }
  return {
    html:params.targetEncoding ? iconv.encode(html,params.targetEncoding) : html,
    image:imgList
  };
}
module.exports=async function(content,params={}){
  var contentHTML=processTexHanzi(Markdown.render(content));
  var html = mathjax.document(contentHTML, {InputJax: tex, OutputJax: svg});
  html.render();
  return await processHTML(adaptor.outerHTML(adaptor.root(html.document)),{
    ...params
  });
}

<|endoftext|>


<commit_before>(function() {

  const path = require('path');
  const nconf = require('nconf');
  const jetpack = require('fs-jetpack');

  const fileName = 'config.json';
  const rootDir = path.join(__dirname, '..');
  const dataDir = path.join(rootDir, 'data');
  const homeDir = process.env.HOME
    || process.env.HOMEPATH
    || process.env.USERPROFILE;
  const confDir = path.join(homeDir, '.nxtpm');
  // Const rootConf = path.join(rootDir, fileName);
  const homeConf = path.join(confDir, fileName);
  const servFile = path.join(dataDir, 'servers_nxt_testnet.json');

  nconf.env();
  //Nconf.file({ file: rootConf });
  nconf.file({ file: homeConf });
  nconf.defaults({
    env: 'development',
    channel: 'nxtpm',
    filename: 'nxtpm.json',
    package: {
      requiredFields: {
        name: {
          type: 'string',
        },
        description: {
          type: 'string',
        },
        version: {
          type: 'string',
        },
        channel: {
          type: 'string',
        },
        resources: {
          type: 'object',
        },
      },
    },
    nxt: {
      aliasFee: 200000000,
      dataFee: 100000000,
      deadline: 1440,
      numSources: 3,
      ignoreJSONKeys: ['requestProcessingTime'],
      serverList: jetpack.read(servFile, 'json'),
    },
  });

  module.exports = nconf;

})();
<commit_msg>use testnet in development<commit_after>(function() {

  const path = require('path');
  const nconf = require('nconf');
  const jetpack = require('fs-jetpack');
  const log = require('./log');

  const fileName = 'config.json';
  const rootDir = path.join(__dirname, '..');
  const dataDir = path.join(rootDir, 'data');
  const homeDir = process.env.HOME
    || process.env.HOMEPATH
    || process.env.USERPROFILE;
  const confDir = path.join(homeDir, '.nxtpm');
  const homeConf = path.join(confDir, fileName);

  let servFile;
  if(process.env.NODE_ENV === 'development') {
    log.info('Development mode; Using Nxt testnet');
    servFile = path.join(dataDir, 'servers_nxt_testnet.json');
  } else {
    servFile = path.join(dataDir, 'servers_nxt.json');
  }

  nconf.env();
  nconf.file({ file: homeConf });
  nconf.defaults({
    env: 'development',
    channel: 'nxtpm',
    filename: 'nxtpm.json',
    package: {
      requiredFields: {
        name: {
          type: 'string',
        },
        description: {
          type: 'string',
        },
        version: {
          type: 'string',
        },
        channel: {
          type: 'string',
        },
        resources: {
          type: 'object',
        },
      },
    },
    nxt: {
      aliasFee: 200000000,
      dataFee: 100000000,
      deadline: 1440,
      numSources: 3,
      ignoreJSONKeys: ['requestProcessingTime'],
      serverList: jetpack.read(servFile, 'json'),
    },
  });

  module.exports = nconf;

})();
<|endoftext|>


<commit_before>#! /usr/bin/env node

import RecompressJpegs from './recompress-jpegs';
import ImageMinifier from './image-minifier';

console.log('Running JPEG recompression...\n');
new RecompressJpegs().run('_site/**/*.jpg');

console.log('\n--------------------------------------------------\n');

console.log('Running image minifier...\n');
new ImageMinifier().run('_site/images');
<commit_msg>Add package version to output<commit_after>#! /usr/bin/env node

import RecompressJpegs from './recompress-jpegs';
import ImageMinifier from './image-minifier';

console.log(`ritter-jekyll ${require('../package.json').version}`);

console.log('\n--------------------------------------------------\n');

console.log('Running JPEG recompression...\n');
new RecompressJpegs().run('_site/**/*.jpg');

console.log('\n--------------------------------------------------\n');

console.log('Running image minifier...\n');
new ImageMinifier().run('_site/images');
<|endoftext|>


<commit_before>var config
  , path = require('path')
  , fs = require('fs')
  , utils = require('utilities');

config = new (function () {

  this.readConfig = function (options) {
    var opts = options || {}
      , ret = {}
      , baseConfig
      , env
      , dir = process.cwd()
      , dirList = fs.readdirSync(path.join(dir, 'config'))
      , fileName
      , fileExt
      , fileBaseName
      , useCoffee
      , appBaseConfig
      , appEnvConfig;

    baseConfig = utils.mixin({}, require('./base_config'), true);
    env = opts.environment || baseConfig.environment;

    // Base config for workers-count should be 1 in dev-mode
    // Cycle based on filesystem changes, not keep-alive
    // Process-rotation not possible in this mode
    if (env == 'development') {
      baseConfig.workers = 1;
      baseConfig.rotateWorkers = false;
    }

    // App configs
    for (var i = 0; i < dirList.length; i++) {
      fileName = dirList[i];
      fileExt = path.extname(fileName);
      fileBaseName = path.basename(fileName, fileExt);
      // Require the environment configuration and the base configuration file
      if (fileBaseName === env || fileBaseName === 'environment') {
        if (fileExt === '.coffee') {
          // fileName is a CoffeeScript file so try to require it
          useCoffee = useCoffee || utils.file.requireLocal('coffee-script');
        }
        appBaseConfig = require(dir + '/config/environment');
        appEnvConfig = require(dir + '/config/' + baseConfig.environment);
      }
    }

    // Start with a blank slate, mix everything in
    utils.mixin(ret, baseConfig, true);
    utils.mixin(ret, appBaseConfig, true);
    utils.mixin(ret, appEnvConfig, true);
    utils.mixin(ret, opts, true);

    // Obvious, don't rotate with only one worker
    if (ret.workers < 2) {
      ret.rotateWorkers = false;
    }

    return ret;
  };

})();

module.exports = config;
<commit_msg>Load correct environment<commit_after>var config
  , path = require('path')
  , fs = require('fs')
  , utils = require('utilities');

config = new (function () {

  this.readConfig = function (options) {
    var opts = options || {}
      , ret = {}
      , baseConfig
      , env
      , dir = process.cwd()
      , dirList = fs.readdirSync(path.join(dir, 'config'))
      , fileName
      , fileExt
      , fileBaseName
      , useCoffee
      , appBaseConfig
      , appEnvConfig;

    baseConfig = utils.mixin({}, require('./base_config'), true);
    env = opts.environment || baseConfig.environment;

    // Base config for workers-count should be 1 in dev-mode
    // Cycle based on filesystem changes, not keep-alive
    // Process-rotation not possible in this mode
    if (env == 'development') {
      baseConfig.workers = 1;
      baseConfig.rotateWorkers = false;
    }

    // App configs
    for (var i = 0; i < dirList.length; i++) {
      fileName = dirList[i];
      fileExt = path.extname(fileName);
      fileBaseName = path.basename(fileName, fileExt);
      // Require the environment configuration and the base configuration file
      if (fileBaseName === env || fileBaseName === 'environment') {
        if (fileExt === '.coffee') {
          // fileName is a CoffeeScript file so try to require it
          useCoffee = useCoffee || utils.file.requireLocal('coffee-script');
        }
        appBaseConfig = require(dir + '/config/environment');
        appEnvConfig = require(dir + '/config/' + env);
      }
    }

    // Start with a blank slate, mix everything in
    utils.mixin(ret, baseConfig, true);
    utils.mixin(ret, appBaseConfig, true);
    utils.mixin(ret, appEnvConfig, true);
    utils.mixin(ret, opts, true);

    // Obvious, don't rotate with only one worker
    if (ret.workers < 2) {
      ret.rotateWorkers = false;
    }

    return ret;
  };

})();

module.exports = config;
<|endoftext|>


<commit_before>var luckyWord = [
    {
        "img": "https://4.bp.blogspot.com/-s9aoQUpjSic/VwUUwMJQT2I/AAAAAAAAB9U/_OB1osuzSpYlzJSyFgRjJEwjGVhaLE5_g/s320/IMG_0222.png",
        "text": "It%39s%20New%20Me!"
    },
    {
        "img": "https://2.bp.blogspot.com/-agnHXR8ghtQ/VwUUwHull9I/AAAAAAAAB9Y/zSc7yTHOSPYeg48WtI8DZJ6RWyGMBQ8BQ/s320/IMG_0223.png",
        "text": "そうなんですの?"
    },
    {
        "img": "https://3.bp.blogspot.com/-ZQQQ_x1v_3g/VwUUwCa7ijI/AAAAAAAAB9Q/6tzGbRyHdxkW2nHq9vrAinQ73l6DIa4Ww/s320/IMG_0224.png",
        "text": "がっぷりやってやるぞ"
    },
    {
        "img": "https://2.bp.blogspot.com/-jparoIZl8g0/VwUUw3nBKWI/AAAAAAAAB9c/c5H8_ylTdi4Xt6ilf2KJjKyDZsKjDCxmA/s320/IMG_0225.png",
        "text": "さてがんばるべっ"
    },
    {
        "img": "https://3.bp.blogspot.com/-ly8xkOSy3oM/VwUUw4VV_VI/AAAAAAAAB9g/cOkLs61hTEkOqqxYHq5I2ifYp14sw1WTw/s320/IMG_0226.png",
        "text": "このとんま!"
    },
    {
        "img": "https://1.bp.blogspot.com/-wBFAQ_OlX-k/VwUUxPHeUyI/AAAAAAAAB9k/pnRera6F6YovIBGcJH7Ue396IhCSH_sag/s320/IMG_0227.png",
        "text": "ごくつぶて"
    },
    {
        "img": "https://4.bp.blogspot.com/-hWKVm9qS46w/VwUUxWRYKII/AAAAAAAAB9o/V_6IwuBEk-sB8g1oVsqeAUjCoOpJYEYmQ/s320/IMG_0228.png",
        "text": "なにそのすっとんきょうな顔は!?"
    },
    {
        "img": "https://2.bp.blogspot.com/-r5KwT0szJQw/VwUUxuQyUcI/AAAAAAAAB9s/85c69N-x3UYdRUmp1LsE37Wzofx3U0GmA/s320/IMG_0229.png",
        "text": "今日すごいラッキー"
    },
    {
        "img": "https://3.bp.blogspot.com/-bq0cazudybA/VwUUxyIe1HI/AAAAAAAAB9w/54dbjkUi1AULLktbU1C-ESdjLaTubfxFA/s320/IMG_0230.png",
        "text": "はてしがないね〜"
    },
    {
        "img": "https://2.bp.blogspot.com/-lyeP4VCQsso/VwUUyEKj90I/AAAAAAAAB90/a6tT6Seer10wfpoJlImss1ek_V1ln8NBg/s320/IMG_0231.png",
        "text": "とてつもなく"
    },
    {
        "img": "https://1.bp.blogspot.com/-EZxmoYtp98g/VwUUyeHOoJI/AAAAAAAAB94/rdiOIoK1FYIR5nEa9yZX2A6BHxDiunb_Q/s320/IMG_0232.png",
        "text": "いい日だなぁ〜"
    },
    {
        "img": "https://1.bp.blogspot.com/-MDCaZtPosd0/VwUUym8dd7I/AAAAAAAAB98/3wSQsGZDUFA5c6nUvus2I1NhKs1SsZNZQ/s320/IMG_0233.png",
        "text": "生きている限り望みはある"
    },
    {
        "img": "https://2.bp.blogspot.com/-hSANzQHZVIs/VwUUywdrdXI/AAAAAAAAB-A/RDg1IhYWFzMxRM6wzbUvg6SHsDKoK6fcA/s320/IMG_0234.png",
        "text": "地球は丸いからね"
    },
    {
        "img": "https://4.bp.blogspot.com/-dT4zlpHtuk8/VwUUzKmNLKI/AAAAAAAAB-M/DWvwVcdztiI53nBTlwKgYKzO6VRZINWJA/s320/IMG_0235.png",
        "text": "今日はいちだんときれいだね"
    },
    {
        "img": "https://4.bp.blogspot.com/-nYOPrMXckGg/VwUUzU0SoOI/AAAAAAAAB-E/xKc17BBjF7Ywy2NdKIRiW6RLvdOppzYpg/s320/IMG_0236.png",
        "text": "がっびーん"
    },
    {
        "img": "https://2.bp.blogspot.com/-3trKbKmnO24/VwUUznrEJcI/AAAAAAAAB-I/7OJKQVB5ss8MS50byJa6J9CVb0HWhzb4g/s320/IMG_0237.png",
        "text": "逆ではないけどね..."
    },
    {
        "img": "https://1.bp.blogspot.com/-ieS7mbGtcvw/VwUU0L3eRVI/AAAAAAAAB-Q/6uKnCaxO1ZMm2bFqZk-NxHwQuyYR3nm0A/s320/IMG_0238.png",
        "text": "どんっどんっどんたこすっ"
    },
    {
        "img": "https://3.bp.blogspot.com/-JR-D3Z0ibhE/VwUU0bgJ_JI/AAAAAAAAB-U/mDPRwJwCnxYY9fNOUyyqyzkQnkrKYsT6w/s320/IMG_0239.png",
        "text": "もんもんもんまるとる!"
    },
//    {
//        "img": "https://3.bp.blogspot.com/-T8wFElxITMs/VwUU0rZ7XVI/AAAAAAAAB-Y/ygVHdt_-kyMa7FIXZ7b-uca6c5IqGeXPg/s320/IMG_0240.png",
//        "text": "Have A Funny Day :)"
//    },
    {
        "img": "https://1.bp.blogspot.com/-V8VjdyR9rsU/VwUU0mwfC3I/AAAAAAAAB-c/cquMF2Q0MxkjV9EivLS0oB8YsVuGD7Wnw/s320/IMG_0241.png",
        "text": "おたんこなすー"
    },
    {
        "img": "https://3.bp.blogspot.com/-Du5kLNalKLQ/VwUU1EMAmSI/AAAAAAAAB-k/Ykme8r1KEJ07nUYMSEoYSkmi4rw-lcytA/s320/IMG_0242.png",
        "text": "やなこった!"
    },
    {
        "img": "https://4.bp.blogspot.com/-XK7T4O9CsfY/VwUU1JsLSmI/AAAAAAAAB-g/kC49eK-liYM7ht4VdmJLE2UNsGnG3hXEA/s320/IMG_0243.png",
        "text": "ばいなら"
    },
    {
        "img": "https://4.bp.blogspot.com/-Vp4S79_K9M0/VwUU1T9LKDI/AAAAAAAAB-o/66Uu2BVGgI4l8zr38jIsshXpH1rQnDT9Q/s320/IMG_0244.png",
        "text": "どっひゃー"
    },
    {
        "img": "https://3.bp.blogspot.com/-YsQuaj-Dkn0/VwUU162L5gI/AAAAAAAAB-s/qPr3YhNsK-8J8vSUPhECu5gkLHTt1EAaw/s320/IMG_0245.png",
        "text": "運も実力のうち"
    },
    {
        "img": "https://2.bp.blogspot.com/-IDbqkzzZmZE/VwUU1zYpJ-I/AAAAAAAAB-w/CRhG-HCqQdg_cTwJAwZl1UsvvLC8-YvXw/s320/IMG_0246.png",
        "text": "このスットコドッコイ!"
    }
];

var luckyIcon = [
    "https://2.bp.blogspot.com/-fK0VZbQ_glM/VwUUMQqU69I/AAAAAAAAB8I/u56itzMBTFQnKSxaw8rea1iFTj5JS9E6w/s320/IMG_0202.png",
    "https://3.bp.blogspot.com/-Zs4sYLFz-kc/VwUUMjV3eTI/AAAAAAAAB8M/hGo6oT25jy4cYit_S8aigyWmI1Pfzp66Q/s320/IMG_0203.png",
    "https://2.bp.blogspot.com/-s3AoXBMF1w4/VwUUMbzj8WI/AAAAAAAAB8E/Bt9W2bDCoO4R9yLpUieMrkSD6lR5I-LfA/s320/IMG_0204.png",
    "https://2.bp.blogspot.com/-p7qNn6mlLXw/VwUUNM74nlI/AAAAAAAAB8Q/IAadiFSKqCU35OfPqA-NWmgwg5kF4mwzg/s320/IMG_0205.png",
    "https://1.bp.blogspot.com/-yNO_lDFDBDo/VwUUNwKuZKI/AAAAAAAAB8c/7PyS0PdExcYejIsDFhRWSZ8y1ATgMBjDw/s320/IMG_0206.png",
    "https://1.bp.blogspot.com/-9qAKgMu_zXQ/VwUUNk5zHPI/AAAAAAAAB8U/OVAFLIL5qkUo34e3I6X-EAr7XdnTYuU1g/s320/IMG_0207.png",
    "https://2.bp.blogspot.com/-puRDv8cjnHs/VwUUNiH0jHI/AAAAAAAAB8Y/F4SsuRYIY6kVUUPB6f-PCkQWm5qwm_76Q/s320/IMG_0208.png",
    "https://4.bp.blogspot.com/-XAnYP9NNgwM/VwUUOfzRk4I/AAAAAAAAB8g/x923a1MRh_sPufQFMaPcx-FXHQSGvVcqg/s320/IMG_0209.png",
    "https://2.bp.blogspot.com/-yaqewPFk6jk/VwUUOa-FIQI/AAAAAAAAB8k/Wb8jfwhhRG0p8X-g82a6nrZAxGcePrBNA/s320/IMG_0210.png",
    "https://2.bp.blogspot.com/-HDWxhTsKR7U/VwUUOqaC0LI/AAAAAAAAB8o/EwPvqZPNKKM75mkyh0Qf76GInyPLOaI-A/s320/IMG_0211.png",
    "https://3.bp.blogspot.com/-2HW6GB8ZLzs/VwUUO5sYgpI/AAAAAAAAB8s/7uesT58PeDwjnjd0OzyI0h8i2EqbNeuTA/s320/IMG_0212.png",
    "https://3.bp.blogspot.com/-Fh6QEwnJ8Jk/VwUUPCH7n-I/AAAAAAAAB8w/G3gK7gmvnWoBm5gdkwvjdPNP0Tco2TBYg/s320/IMG_0213.png",
    "https://4.bp.blogspot.com/-5SOAQjQe-2I/VwUUPU21SzI/AAAAAAAAB80/E3QoqH1vlBUgaR4xco1rmvGvvG66dWLeQ/s320/IMG_0214.png",
    "https://2.bp.blogspot.com/-S50RC9Beew8/VwUUPpj9IcI/AAAAAAAAB84/GkQGVnMfKbsBC5UD-j11Ezhjbry8JT7jw/s320/IMG_0215.png",
    "https://1.bp.blogspot.com/-X7CILi2d_10/VwUUPwvpw0I/AAAAAAAAB88/o2Xjehk2BRQyzl-LuPNRvoQk60H33qUhg/s320/IMG_0216.png",
    "https://3.bp.blogspot.com/-8NmYH1SRfpY/VwUUQFH7fVI/AAAAAAAAB9A/FsnpFtEmCqwlSpX-hzOHpL9pw_SLeECZA/s320/IMG_0217.png",
    "https://4.bp.blogspot.com/-U7kXYHM_VFA/VwUURP_nnoI/AAAAAAAAB9M/MRTuCPqZ9a8NYZgjxWD0KZOZgAoR5z6cQ/s320/IMG_0218.png",
    "https://2.bp.blogspot.com/-BDc06ZxdxLo/VwUUQcDivKI/AAAAAAAAB9E/TSr-QCBWpxwZOqKH1rSKTuFQMOTo7Ey6Q/s320/IMG_0219.png",
    "https://2.bp.blogspot.com/-Xmthb3oo6Us/VwUUQ0el6fI/AAAAAAAAB9I/Z9Dz65vlSB8Bwcuet71FM0KacfNNbRkzA/s320/IMG_0220.png"
];
<commit_msg>Change Lucky Word text.<commit_after>var luckyWord = [
    {
        "img": "https://4.bp.blogspot.com/-s9aoQUpjSic/VwUUwMJQT2I/AAAAAAAAB9U/_OB1osuzSpYlzJSyFgRjJEwjGVhaLE5_g/s320/IMG_0222.png",
        "text": "イッツニューミー!"
    },
    {
        "img": "https://2.bp.blogspot.com/-agnHXR8ghtQ/VwUUwHull9I/AAAAAAAAB9Y/zSc7yTHOSPYeg48WtI8DZJ6RWyGMBQ8BQ/s320/IMG_0223.png",
        "text": "そうなんですの?"
    },
    {
        "img": "https://3.bp.blogspot.com/-ZQQQ_x1v_3g/VwUUwCa7ijI/AAAAAAAAB9Q/6tzGbRyHdxkW2nHq9vrAinQ73l6DIa4Ww/s320/IMG_0224.png",
        "text": "がっぷりやってやるぞ"
    },
    {
        "img": "https://2.bp.blogspot.com/-jparoIZl8g0/VwUUw3nBKWI/AAAAAAAAB9c/c5H8_ylTdi4Xt6ilf2KJjKyDZsKjDCxmA/s320/IMG_0225.png",
        "text": "さてがんばるべっ"
    },
    {
        "img": "https://3.bp.blogspot.com/-ly8xkOSy3oM/VwUUw4VV_VI/AAAAAAAAB9g/cOkLs61hTEkOqqxYHq5I2ifYp14sw1WTw/s320/IMG_0226.png",
        "text": "このとんま!"
    },
    {
        "img": "https://1.bp.blogspot.com/-wBFAQ_OlX-k/VwUUxPHeUyI/AAAAAAAAB9k/pnRera6F6YovIBGcJH7Ue396IhCSH_sag/s320/IMG_0227.png",
        "text": "ごくつぶて"
    },
    {
        "img": "https://4.bp.blogspot.com/-hWKVm9qS46w/VwUUxWRYKII/AAAAAAAAB9o/V_6IwuBEk-sB8g1oVsqeAUjCoOpJYEYmQ/s320/IMG_0228.png",
        "text": "なにそのすっとんきょうな顔は!?"
    },
    {
        "img": "https://2.bp.blogspot.com/-r5KwT0szJQw/VwUUxuQyUcI/AAAAAAAAB9s/85c69N-x3UYdRUmp1LsE37Wzofx3U0GmA/s320/IMG_0229.png",
        "text": "今日すごいラッキー"
    },
    {
        "img": "https://3.bp.blogspot.com/-bq0cazudybA/VwUUxyIe1HI/AAAAAAAAB9w/54dbjkUi1AULLktbU1C-ESdjLaTubfxFA/s320/IMG_0230.png",
        "text": "はてしがないね〜"
    },
    {
        "img": "https://2.bp.blogspot.com/-lyeP4VCQsso/VwUUyEKj90I/AAAAAAAAB90/a6tT6Seer10wfpoJlImss1ek_V1ln8NBg/s320/IMG_0231.png",
        "text": "とてつもなく"
    },
    {
        "img": "https://1.bp.blogspot.com/-EZxmoYtp98g/VwUUyeHOoJI/AAAAAAAAB94/rdiOIoK1FYIR5nEa9yZX2A6BHxDiunb_Q/s320/IMG_0232.png",
        "text": "いい日だなぁ〜"
    },
    {
        "img": "https://1.bp.blogspot.com/-MDCaZtPosd0/VwUUym8dd7I/AAAAAAAAB98/3wSQsGZDUFA5c6nUvus2I1NhKs1SsZNZQ/s320/IMG_0233.png",
        "text": "生きている限り望みはある"
    },
    {
        "img": "https://2.bp.blogspot.com/-hSANzQHZVIs/VwUUywdrdXI/AAAAAAAAB-A/RDg1IhYWFzMxRM6wzbUvg6SHsDKoK6fcA/s320/IMG_0234.png",
        "text": "地球は丸いからね"
    },
    {
        "img": "https://4.bp.blogspot.com/-dT4zlpHtuk8/VwUUzKmNLKI/AAAAAAAAB-M/DWvwVcdztiI53nBTlwKgYKzO6VRZINWJA/s320/IMG_0235.png",
        "text": "今日はいちだんときれいだね"
    },
    {
        "img": "https://4.bp.blogspot.com/-nYOPrMXckGg/VwUUzU0SoOI/AAAAAAAAB-E/xKc17BBjF7Ywy2NdKIRiW6RLvdOppzYpg/s320/IMG_0236.png",
        "text": "がっびーん"
    },
    {
        "img": "https://2.bp.blogspot.com/-3trKbKmnO24/VwUUznrEJcI/AAAAAAAAB-I/7OJKQVB5ss8MS50byJa6J9CVb0HWhzb4g/s320/IMG_0237.png",
        "text": "逆ではないけどね..."
    },
    {
        "img": "https://1.bp.blogspot.com/-ieS7mbGtcvw/VwUU0L3eRVI/AAAAAAAAB-Q/6uKnCaxO1ZMm2bFqZk-NxHwQuyYR3nm0A/s320/IMG_0238.png",
        "text": "どんっどんっどんたこすっ"
    },
    {
        "img": "https://3.bp.blogspot.com/-JR-D3Z0ibhE/VwUU0bgJ_JI/AAAAAAAAB-U/mDPRwJwCnxYY9fNOUyyqyzkQnkrKYsT6w/s320/IMG_0239.png",
        "text": "もんもんもんまるとる!"
    },
//    {
//        "img": "https://3.bp.blogspot.com/-T8wFElxITMs/VwUU0rZ7XVI/AAAAAAAAB-Y/ygVHdt_-kyMa7FIXZ7b-uca6c5IqGeXPg/s320/IMG_0240.png",
//        "text": "Have A Funny Day :)"
//    },
    {
        "img": "https://1.bp.blogspot.com/-V8VjdyR9rsU/VwUU0mwfC3I/AAAAAAAAB-c/cquMF2Q0MxkjV9EivLS0oB8YsVuGD7Wnw/s320/IMG_0241.png",
        "text": "おたんこなすー"
    },
    {
        "img": "https://3.bp.blogspot.com/-Du5kLNalKLQ/VwUU1EMAmSI/AAAAAAAAB-k/Ykme8r1KEJ07nUYMSEoYSkmi4rw-lcytA/s320/IMG_0242.png",
        "text": "やなこった!"
    },
    {
        "img": "https://4.bp.blogspot.com/-XK7T4O9CsfY/VwUU1JsLSmI/AAAAAAAAB-g/kC49eK-liYM7ht4VdmJLE2UNsGnG3hXEA/s320/IMG_0243.png",
        "text": "ばいなら"
    },
    {
        "img": "https://4.bp.blogspot.com/-Vp4S79_K9M0/VwUU1T9LKDI/AAAAAAAAB-o/66Uu2BVGgI4l8zr38jIsshXpH1rQnDT9Q/s320/IMG_0244.png",
        "text": "どっひゃー"
    },
    {
        "img": "https://3.bp.blogspot.com/-YsQuaj-Dkn0/VwUU162L5gI/AAAAAAAAB-s/qPr3YhNsK-8J8vSUPhECu5gkLHTt1EAaw/s320/IMG_0245.png",
        "text": "運も実力のうち"
    },
    {
        "img": "https://2.bp.blogspot.com/-IDbqkzzZmZE/VwUU1zYpJ-I/AAAAAAAAB-w/CRhG-HCqQdg_cTwJAwZl1UsvvLC8-YvXw/s320/IMG_0246.png",
        "text": "このスットコドッコイ!"
    }
];

var luckyIcon = [
    "https://2.bp.blogspot.com/-fK0VZbQ_glM/VwUUMQqU69I/AAAAAAAAB8I/u56itzMBTFQnKSxaw8rea1iFTj5JS9E6w/s320/IMG_0202.png",
    "https://3.bp.blogspot.com/-Zs4sYLFz-kc/VwUUMjV3eTI/AAAAAAAAB8M/hGo6oT25jy4cYit_S8aigyWmI1Pfzp66Q/s320/IMG_0203.png",
    "https://2.bp.blogspot.com/-s3AoXBMF1w4/VwUUMbzj8WI/AAAAAAAAB8E/Bt9W2bDCoO4R9yLpUieMrkSD6lR5I-LfA/s320/IMG_0204.png",
    "https://2.bp.blogspot.com/-p7qNn6mlLXw/VwUUNM74nlI/AAAAAAAAB8Q/IAadiFSKqCU35OfPqA-NWmgwg5kF4mwzg/s320/IMG_0205.png",
    "https://1.bp.blogspot.com/-yNO_lDFDBDo/VwUUNwKuZKI/AAAAAAAAB8c/7PyS0PdExcYejIsDFhRWSZ8y1ATgMBjDw/s320/IMG_0206.png",
    "https://1.bp.blogspot.com/-9qAKgMu_zXQ/VwUUNk5zHPI/AAAAAAAAB8U/OVAFLIL5qkUo34e3I6X-EAr7XdnTYuU1g/s320/IMG_0207.png",
    "https://2.bp.blogspot.com/-puRDv8cjnHs/VwUUNiH0jHI/AAAAAAAAB8Y/F4SsuRYIY6kVUUPB6f-PCkQWm5qwm_76Q/s320/IMG_0208.png",
    "https://4.bp.blogspot.com/-XAnYP9NNgwM/VwUUOfzRk4I/AAAAAAAAB8g/x923a1MRh_sPufQFMaPcx-FXHQSGvVcqg/s320/IMG_0209.png",
    "https://2.bp.blogspot.com/-yaqewPFk6jk/VwUUOa-FIQI/AAAAAAAAB8k/Wb8jfwhhRG0p8X-g82a6nrZAxGcePrBNA/s320/IMG_0210.png",
    "https://2.bp.blogspot.com/-HDWxhTsKR7U/VwUUOqaC0LI/AAAAAAAAB8o/EwPvqZPNKKM75mkyh0Qf76GInyPLOaI-A/s320/IMG_0211.png",
    "https://3.bp.blogspot.com/-2HW6GB8ZLzs/VwUUO5sYgpI/AAAAAAAAB8s/7uesT58PeDwjnjd0OzyI0h8i2EqbNeuTA/s320/IMG_0212.png",
    "https://3.bp.blogspot.com/-Fh6QEwnJ8Jk/VwUUPCH7n-I/AAAAAAAAB8w/G3gK7gmvnWoBm5gdkwvjdPNP0Tco2TBYg/s320/IMG_0213.png",
    "https://4.bp.blogspot.com/-5SOAQjQe-2I/VwUUPU21SzI/AAAAAAAAB80/E3QoqH1vlBUgaR4xco1rmvGvvG66dWLeQ/s320/IMG_0214.png",
    "https://2.bp.blogspot.com/-S50RC9Beew8/VwUUPpj9IcI/AAAAAAAAB84/GkQGVnMfKbsBC5UD-j11Ezhjbry8JT7jw/s320/IMG_0215.png",
    "https://1.bp.blogspot.com/-X7CILi2d_10/VwUUPwvpw0I/AAAAAAAAB88/o2Xjehk2BRQyzl-LuPNRvoQk60H33qUhg/s320/IMG_0216.png",
    "https://3.bp.blogspot.com/-8NmYH1SRfpY/VwUUQFH7fVI/AAAAAAAAB9A/FsnpFtEmCqwlSpX-hzOHpL9pw_SLeECZA/s320/IMG_0217.png",
    "https://4.bp.blogspot.com/-U7kXYHM_VFA/VwUURP_nnoI/AAAAAAAAB9M/MRTuCPqZ9a8NYZgjxWD0KZOZgAoR5z6cQ/s320/IMG_0218.png",
    "https://2.bp.blogspot.com/-BDc06ZxdxLo/VwUUQcDivKI/AAAAAAAAB9E/TSr-QCBWpxwZOqKH1rSKTuFQMOTo7Ey6Q/s320/IMG_0219.png",
    "https://2.bp.blogspot.com/-Xmthb3oo6Us/VwUUQ0el6fI/AAAAAAAAB9I/Z9Dz65vlSB8Bwcuet71FM0KacfNNbRkzA/s320/IMG_0220.png"
];
<|endoftext|>


<commit_before>"use strict";

var program = require('commander')
  , fs = require('fs');

var defaultValues = {
  cli: false,
  dir: './',
  filter: [
    {type: 'exclude', pattern: '.{git,svn}/'},
    {type: 'include', pattern: '*/'},
    {type: 'include', pattern: '*.{html,shtml,tmpl,xml,css,js,json,jpeg,jpg,gif,png,ico,cgi,php,py,pl,pm,rb}'},
    {type: 'exclude', pattern: '*'}
  ],
  static: false,
  port: 35729,
  preferLocal: false,
  proxy: '',
  verbose: false,
  liveCSS: true,
  liveImg: true
};

program
  .version(JSON.parse(fs.readFileSync(__dirname + '/../package.json', 'utf8')).version)
  .usage('[options] [dir]')
  .option('--exclude <pattern>', 'exclude file matching pattern')
  .option('--include <pattern>', 'don\'t exclude file matching pattern')
  .option('-p, --port <port>', 'change wait port', parseInt)
  .option('-l, --prefer-local', 'return a local file if it exists (proxy mode only)')
  .option('-s, --static', 'enable static server mode')
  .option('-v, --verbose', 'enable verbose log')
  .option('-y, --proxy <url>', 'enable proxy server mode')
  .option('-C, --no-liveCSS', 'disable liveCSS')
  .option('-I, --no-liveImg', 'disable liveImg');

program.on('include', function(val) {
  program.filter.splice(program.filter.length - defaultValues.filter.length, 0,
    {type: 'include', pattern: val});
});
program.on('exclude', function(val) {
  program.filter.splice(program.filter.length - defaultValues.filter.length, 0,
    {type: 'exclude', pattern: val});
});

function copyValues(dst, src) {
  for (var key in defaultValues) {
    dst[key] = src[key];
  }
  return dst;
}

var validate = exports.validate = function(conf) {
  for (var key in conf) {
    if (!(key in defaultValues)) {
      throw "Invalid key: " + key;
    }
    if (typeof defaultValues[key] !== typeof conf[key]) {
      throw "Invalid type: " + key + " should be " + typeof defaultValues[key];
    }
    if (typeof conf[key] === 'number' && isNaN(conf[key])) {
      throw "Invalid value: " + key + " should be a number";
    }

    if (conf.static && conf.proxy !== '') {
      throw 'The "static" option cannot be specified together with "proxy" option';
    }
    if (conf.preferLocal && conf.proxy === '') {
      throw 'The "prefer-local" option must be specified with "proxy" option';
    }
  }
  return conf;
};

var parseArgv = exports.parseArgv = function(argv) {
  // set default value
  copyValues(program, defaultValues);

  // HACK: avoid commander.js's bug
  // (https://github.com/visionmedia/commander.js/pull/121)
  // program.parse() doesn't fail when unknown option and args are given.
  // So we call program.parseOptions() instead of program.parse().
  program._name = 'livereloadx';
  var parsed = program.parseOptions(program.normalize(argv.slice(2)));
  program.args = parsed.args;

  // handle unknown options
  if (parsed.unknown.length > 0) {
    program.parseArgs([], parsed.unknown);
  }

  // handle <dir>
  if (program.args.length === 1) {
    program.dir = program.args[0];
  } else if (program.args.length === 0) {
    program.dir = '.';
  } else if (program.args.length > 1) {
    throw "Too much arguments";
  }

  // delete include and exclude
  delete program.include;
  delete program.exclude;

  // copy program to Object
  return validate(copyValues({}, program));
};

var setDefaultValue = exports.setDefaultValue = function(conf) {
  for (var key in defaultValues) {
    if (!(key in conf)) {
      conf[key] = defaultValues[key];
    }
  }
  return validate(conf);
};

var dump = exports.dump = function(log, conf) {
  log('Config:');
  log('  - mode:   %s', conf.static ? 'static' : conf.proxy !== '' ? 'proxy' : 'default');
  if (conf.proxy) {
    log('    url:  %s', conf.proxy);
    log('    prefer local: %s', conf.preferLocal ? 'ON' : 'OFF');
  }
  log('  - port:   %d', conf.port);
  log('  - filter:');
  conf.filter.forEach(function(filter, i) {
    log('    %d: %s "%s"', i + 1, filter.type, filter.pattern);
  });
};<commit_msg>Fix port option for commander 2.2.0<commit_after>"use strict";

var program = require('commander')
  , fs = require('fs');

var defaultValues = {
  cli: false,
  dir: './',
  filter: [
    {type: 'exclude', pattern: '.{git,svn}/'},
    {type: 'include', pattern: '*/'},
    {type: 'include', pattern: '*.{html,shtml,tmpl,xml,css,js,json,jpeg,jpg,gif,png,ico,cgi,php,py,pl,pm,rb}'},
    {type: 'exclude', pattern: '*'}
  ],
  static: false,
  port: 35729,
  preferLocal: false,
  proxy: '',
  verbose: false,
  liveCSS: true,
  liveImg: true
};

program
  .version(JSON.parse(fs.readFileSync(__dirname + '/../package.json', 'utf8')).version)
  .usage('[options] [dir]')
  .option('--exclude <pattern>', 'exclude file matching pattern')
  .option('--include <pattern>', 'don\'t exclude file matching pattern')
  .option('-p, --port <port>', 'change wait port', function(val){ return parseInt(val) })
  .option('-l, --prefer-local', 'return a local file if it exists (proxy mode only)')
  .option('-s, --static', 'enable static server mode')
  .option('-v, --verbose', 'enable verbose log')
  .option('-y, --proxy <url>', 'enable proxy server mode')
  .option('-C, --no-liveCSS', 'disable liveCSS')
  .option('-I, --no-liveImg', 'disable liveImg');

program.on('include', function(val) {
  program.filter.splice(program.filter.length - defaultValues.filter.length, 0,
    {type: 'include', pattern: val});
});
program.on('exclude', function(val) {
  program.filter.splice(program.filter.length - defaultValues.filter.length, 0,
    {type: 'exclude', pattern: val});
});

function copyValues(dst, src) {
  for (var key in defaultValues) {
    dst[key] = src[key];
  }
  return dst;
}

var validate = exports.validate = function(conf) {
  for (var key in conf) {
    if (!(key in defaultValues)) {
      throw "Invalid key: " + key;
    }
    if (typeof defaultValues[key] !== typeof conf[key]) {
      throw "Invalid type: " + key + " should be " + typeof defaultValues[key];
    }
    if (typeof conf[key] === 'number' && isNaN(conf[key])) {
      throw "Invalid value: " + key + " should be a number";
    }

    if (conf.static && conf.proxy !== '') {
      throw 'The "static" option cannot be specified together with "proxy" option';
    }
    if (conf.preferLocal && conf.proxy === '') {
      throw 'The "prefer-local" option must be specified with "proxy" option';
    }
  }
  return conf;
};

var parseArgv = exports.parseArgv = function(argv) {
  // set default value
  copyValues(program, defaultValues);

  // HACK: avoid commander.js's bug
  // (https://github.com/visionmedia/commander.js/pull/121)
  // program.parse() doesn't fail when unknown option and args are given.
  // So we call program.parseOptions() instead of program.parse().
  program._name = 'livereloadx';
  var parsed = program.parseOptions(program.normalize(argv.slice(2)));
  program.args = parsed.args;

  // handle unknown options
  if (parsed.unknown.length > 0) {
    program.parseArgs([], parsed.unknown);
  }

  // handle <dir>
  if (program.args.length === 1) {
    program.dir = program.args[0];
  } else if (program.args.length === 0) {
    program.dir = '.';
  } else if (program.args.length > 1) {
    throw "Too much arguments";
  }

  // delete include and exclude
  delete program.include;
  delete program.exclude;

  // copy program to Object
  return validate(copyValues({}, program));
};

var setDefaultValue = exports.setDefaultValue = function(conf) {
  for (var key in defaultValues) {
    if (!(key in conf)) {
      conf[key] = defaultValues[key];
    }
  }
  return validate(conf);
};

var dump = exports.dump = function(log, conf) {
  log('Config:');
  log('  - mode:   %s', conf.static ? 'static' : conf.proxy !== '' ? 'proxy' : 'default');
  if (conf.proxy) {
    log('    url:  %s', conf.proxy);
    log('    prefer local: %s', conf.preferLocal ? 'ON' : 'OFF');
  }
  log('  - port:   %d', conf.port);
  log('  - filter:');
  conf.filter.forEach(function(filter, i) {
    log('    %d: %s "%s"', i + 1, filter.type, filter.pattern);
  });
};<|endoftext|>


<commit_before>module.exports = {

  // basic command to call the bot
  appCmd:   ':rss',

  // rss polling timer in seconds
  timer:    60,

};
<commit_msg>1min > 30min<commit_after>module.exports = {

  // basic command to call the bot
  appCmd:   ':rss',

  // rss polling timer in seconds
  timer:    1800,

};
<|endoftext|>


<commit_before>var _ = require('lodash');
var path = require('path');
var format = require('util').format;
// var untildify = require('untildify');
var Model = require('ampersand-model');
var debug = require('debug')('mj:config');

var Config = Model.extend({
  props: {
    plaform: {
      type: 'string',
      values: [
        'windows',
        'osx',
        'linux'
      ]
    },
    /**
     * Which nodejs distribution are we using?
     */
    nodejs_distro: {
      type: 'string',
      default: 'io.js',
      values: [
        'io.js',
        'node'
      ]
    },
    /**
     * Which nodejs version are we using?
     */
    nodejs_version: {
      type: 'string',
      default: '2.3.4'
    },
    /**
     * Which npm version are we using?
     */
    npm_version: {
      type: 'string',
      default: '3.3.8'
    },
    /**
     * Which version of nodist do we use to
     * manage node.js on windows?
     */
    nodist_version: {
      type: 'string',
      default: '0.6.0'
    },
    /**
     * Which version of nvm do we use to
     * manage node.js on linux and osx?
     */
    nvm_version: {
      type: 'string',
      default: '0.29.0'
    },
    /**
     * Which npm version are we using?
     */
    electron_version: {
      type: 'string',
      default: '0.30.8'
    }
  /**
   * @todo (imlucas): Grab logic from `mongodb-js/runner/config.js`
   * so `mj` can change `this.directory` on the fly to take advantage
   * of directory caching on evergreen and travis.
   */
  // is_installed_globally: {
  //   type: 'boolean',
  //   default: true
  // }
  },
  derived: {
    /**
     * Where does mj put things?
     */
    directory: {
      deps: ['platform'],
      fn: function() {
        return process.cwd();
      // if (this.platform === 'windows') {
      //   return path.join('C:', '.mj');
      // }
      // return untildify('~/.mj');
      }
    },
    /**
     * values: ia32 (32bit) or x64 (64bit)
     */
    arch: {
      deps: ['platform'],
      fn: function() {
        if (this.platform === 'windows') {
          return 'ia32';
        }
        return 'x64';
      }
    },
    /**
     * Which tool do we use to install and manage
     * node.js? On windows: nodist. Linux and osx: nvm.
     */
    nodejs_manager: {
      deps: ['platform'],
      fn: function() {
        if (this.platform === 'windows') {
          return 'nodist';
        }
        return 'nvm';
      }
    },
    /**
     * What is the root directory nodist uses to manage node.js?
     *
     * @todo (imlucas): `env.set('NODIST_PREFIX', config.nodist_prefix)`
     */
    nodist_prefix: {
      deps: ['nodist_version', 'directory'],
      fn: function() {
        return path.join(this.directory, format('nodist-%s', this.nodist_version));
      }
    },
    /**
     * What is the URL to download the prebuilt version of nodist?
     */
    nodist_url: {
      deps: ['nodist_version'],
      fn: function() {
        return format('https://github.com/marcelklehr/nodist/archive/v%s.zip',
          this.nodist_version);
      }
    },
    /**
     * What is the arg we pass to `nodist use`?
     * @example
     *   nodist use iojsv2.3.4
     */
    nodist_use: {
      deps: ['nodejs_distro', 'nodejs_version'],
      fn: function() {
        return format('%sv%s',
          this.nodejs_distro.replace('.', ''),
          this.nodejs_version);
      }
    },
    /**
     * What is the directory `npm install -g <package>` places
     * executable scripts into?
     *
     * @todo (imlucas): `env.set('NODIST_PREFIX', config.nodist_prefix)`
     */
    bin_directory: {
      deps: [
        'directory',
        'platform',
        'nodist_prefix',
        'nvm_prefix'
      ],
      fn: function() {
        if (this.platform === 'windows') {
          return path.join(this.nodist_prefix, 'bin');
        }
        return path.join(this.directory, 'nvm', 'versions',
          this.nodejs_distro, this.nodejs_version, 'bin');
      }
    },
    /**
     * What is the arg we pass to `nvm use`?
     * @example
     *   nodist use iojs-v2.3.4
     */
    nvm_use: {
      deps: ['nodejs_distro', 'nodejs_version'],
      fn: function() {
        return format('%s-v%s',
          this.nodejs_distro.replace('.', ''),
          this.nodejs_version);
      }
    },
    /**
     * What is the URL to download the nvm installer script?
     */
    nvm_url: {
      deps: ['nvm_version'],
      fn: function() {
        return format('https://raw.githubusercontent.com/creationix/nvm/v%s/install.sh',
          this.nvm_version);
      }
    }
  },
  serialize: function() {
    return Model.prototype.serialize.call(this, {
      derived: true
    });
  },
  initialize: function(attrs) {
    attrs = _.defaults(attrs || {}, {
      platform: process.platform
    });

    debug('normalizing platform', attrs.platform);

    var platform = attrs.platform
      .toLowerCase()
      .replace(/ /g, '');

    if (_.contains(['win32', 'windows'], platform)) {
      platform = 'windows';
    } else if (_.contains(['darwin', 'osx'], platform)) {
      platform = 'osx';
    } else if (_.contains(['linux', 'ubuntu'], platform)) {
      platform = 'linux';
    } else {
      throw new TypeError('Dont know how to parse for platform `'
        + platform + '`');
    }
    if (platform === 'windows') {
      this.set({
        platform: platform
      });
    } else {
      this.platform = platform;
    }
    attrs.platform = platform;
    debug('platform is `%s`', this.platform);
  }
});

var config = new Config({});
debug('initialized', JSON.stringify(config, null, 2));

module.exports = config;
module.exports.Config = Config;
<commit_msg>:checkered_flag: debugging<commit_after>var _ = require('lodash');
var path = require('path');
var format = require('util').format;
// var untildify = require('untildify');
var Model = require('ampersand-model');
var debug = require('debug')('mj:config');

var Config = Model.extend({
  props: {
    plaform: {
      type: 'string',
      values: [
        'windows',
        'osx',
        'linux'
      ]
    },
    /**
     * Which nodejs distribution are we using?
     */
    nodejs_distro: {
      type: 'string',
      default: 'io.js',
      values: [
        'io.js',
        'node'
      ]
    },
    /**
     * Which nodejs version are we using?
     */
    nodejs_version: {
      type: 'string',
      default: '2.3.4'
    },
    /**
     * Which npm version are we using?
     */
    npm_version: {
      type: 'string',
      default: '3.3.8'
    },
    /**
     * Which version of nodist do we use to
     * manage node.js on windows?
     */
    nodist_version: {
      type: 'string',
      default: '0.6.0'
    },
    /**
     * Which version of nvm do we use to
     * manage node.js on linux and osx?
     */
    nvm_version: {
      type: 'string',
      default: '0.29.0'
    },
    /**
     * Which npm version are we using?
     */
    electron_version: {
      type: 'string',
      default: '0.30.8'
    }
  /**
   * @todo (imlucas): Grab logic from `mongodb-js/runner/config.js`
   * so `mj` can change `this.directory` on the fly to take advantage
   * of directory caching on evergreen and travis.
   */
  // is_installed_globally: {
  //   type: 'boolean',
  //   default: true
  // }
  },
  derived: {
    /**
     * Where does mj put things?
     */
    directory: {
      deps: ['platform'],
      fn: function() {
        return process.cwd();
      // if (this.platform === 'windows') {
      //   return path.join('C:', '.mj');
      // }
      // return untildify('~/.mj');
      }
    },
    /**
     * values: ia32 (32bit) or x64 (64bit)
     */
    arch: {
      deps: ['platform'],
      fn: function() {
        if (this.platform === 'windows') {
          return 'ia32';
        }
        return 'x64';
      }
    },
    /**
     * Which tool do we use to install and manage
     * node.js? On windows: nodist. Linux and osx: nvm.
     */
    nodejs_manager: {
      deps: ['platform'],
      fn: function() {
        if (this.platform === 'windows') {
          return 'nodist';
        }
        return 'nvm';
      }
    },
    /**
     * What is the root directory nodist uses to manage node.js?
     *
     * @todo (imlucas): `env.set('NODIST_PREFIX', config.nodist_prefix)`
     */
    nodist_prefix: {
      deps: ['nodist_version', 'directory'],
      fn: function() {
        return path.join(this.directory, format('nodist-%s', this.nodist_version));
      }
    },
    /**
     * What is the URL to download the prebuilt version of nodist?
     */
    nodist_url: {
      deps: ['nodist_version'],
      fn: function() {
        return format('https://github.com/marcelklehr/nodist/archive/v%s.zip',
          this.nodist_version);
      }
    },
    /**
     * What is the arg we pass to `nodist use`?
     * @example
     *   nodist use iojsv2.3.4
     */
    nodist_use: {
      deps: ['nodejs_distro', 'nodejs_version'],
      fn: function() {
        return format('%sv%s',
          this.nodejs_distro.replace('.', ''),
          this.nodejs_version);
      }
    },
    /**
     * What is the directory `npm install -g <package>` places
     * executable scripts into?
     *
     * @todo (imlucas): `env.set('NODIST_PREFIX', config.nodist_prefix)`
     */
    bin_directory: {
      deps: [
        'directory',
        'platform',
        'nodist_prefix',
        'nvm_prefix'
      ],
      fn: function() {
        if (this.platform === 'windows') {
          return path.join(this.nodist_prefix, 'bin');
        }
        return path.join(this.directory, 'nvm', 'versions',
          this.nodejs_distro, this.nodejs_version, 'bin');
      }
    },
    /**
     * What is the arg we pass to `nvm use`?
     * @example
     *   nodist use iojs-v2.3.4
     */
    nvm_use: {
      deps: ['nodejs_distro', 'nodejs_version'],
      fn: function() {
        return format('%s-v%s',
          this.nodejs_distro.replace('.', ''),
          this.nodejs_version);
      }
    },
    /**
     * What is the URL to download the nvm installer script?
     */
    nvm_url: {
      deps: ['nvm_version'],
      fn: function() {
        return format('https://raw.githubusercontent.com/creationix/nvm/v%s/install.sh',
          this.nvm_version);
      }
    }
  },
  serialize: function() {
    return Model.prototype.serialize.call(this, {
      derived: true
    });
  },
  initialize: function(attrs) {
    attrs = _.defaults(attrs || {}, {
      platform: process.platform
    });

    debug('normalizing platform', attrs.platform);

    var platform = attrs.platform
      .toLowerCase()
      .replace(/ /g, '');

    if (_.contains(['win32', 'windows'], platform)) {
      platform = 'windows';
    } else if (_.contains(['darwin', 'osx'], platform)) {
      platform = 'osx';
    } else if (_.contains(['linux', 'ubuntu'], platform)) {
      platform = 'linux';
    } else {
      throw new TypeError('Dont know how to parse for platform `'
        + platform + '`');
    }
    if (platform === 'windows') {
      this.set({
        platform: platform
      });
      this.platform = platform;
    } else {
      this.platform = platform;
    }
    attrs.platform = platform;
    debug('platform is `%s`', this.platform);
  }
});

var config = new Config({});
debug('initialized', JSON.stringify(config, null, 2));

module.exports = config;
module.exports.Config = Config;
<|endoftext|>