<commit_before>var core = (function() {

	var public = module.parent.iosuite,
		private = {};

	private._return = 'success';

	private._response;

	private._requestFile = '';
	private._cacheFile = '';
	private._cacheFileFull = '';
	private._library = require('./library');

	public.init = function( file, parameters, response ) {

		private._response = response;

		if( file.indexOf('assets/') >= 0 ) {
			/*
			 * Request is for an image / script / style
			 */
			private._return = private._readAsset( file );
		} else {
			private._return = private._readFile( file );
		}

		return private._return;

	};

	private._readAsset = function( file ) {
		private._requestFile = './' + file.substr(0, file.lastIndexOf('.'));
		private._requestFileExt = '.' + file.split('.').pop();

		var asset;
		try {
			var textExtensions = '|.html|.htm|.css|.js|.txt|';
			if( textExtensions.indexOf( '|' + private._requestFileExt + '|' ) >= 0 ) {
				asset = private._library.format( public.module.fs.readFileSync( private._requestFile + private._requestFileExt, 'utf-8' ), {site_url: public.setting('server','url'), environment: public.setting('application','environment')} );
			} else {
				asset = public.module.fs.readFileSync( private._requestFile + private._requestFileExt );
			}

			var contentType = public.module.mime.lookup( private._requestFile + private._requestFileExt ),
				headers = {};

			headers['Content-Type'] = contentType;
			headers["Access-Control-Allow-Headers"] = 'Origin, X-Requested-With, Content-Type, Accept';
			headers["Access-Control-Allow-Origin"] = ( public.setting('application','environment') == 'production' ) ? 'https://system.netsuite.com' : 'https://system.sandbox.netsuite.com';

			private._response.writeHead( 200, headers );
			private._response.end( asset, 'binary' );

		} catch(e) {
			if( e.code !== 'ENOENT' ) {
				private._response.writeHead( 404, { 'Content-Type': 'text/html', 'charset': 'utf-8' } );
				private._response.end( private._library.handleError( e, private._response ) );
			} else {
				private._writeResponse( 404, 'File does not exist', { 'Content-Type': 'text/plain', 'charset': 'utf-8' });
			}
		}

	};

	private._readFile = function( file ) {

		var cacheHash = public.module.crypto.createHash('md5'),
			filePieces = file.split('/'),
			requestFolder = './';

		if( file.indexOf('.') >= 0 ) {
			private._requestFile = requestFolder + file.substr(0, file.lastIndexOf('.'));
			private._requestFileExt = '.' + file.split('.').pop();
		} else {
			private._requestFile = requestFolder + public.setting('application','directory') + '/' + file;
			private._requestFileExt = '.js';
		}

		console.log( private._requestFile );

		/*
		 * Generate MD5 hash cache name
		 */
		cacheHash.update( private._requestFile );
		private._cacheFile = cacheHash.digest('hex');
		private._cacheFileFull = './' + public.setting('application','directory') + '/cache/' + private._cacheFile + private._requestFileExt;

		switch( public.setting('application','environment') ) {
			case 'development':
				/*
				 * If the app is in development, create a cache file and send
				 */
				console.log( private._requestFile + private._requestFileExt );
				public.module.fs.readFile( private._requestFile + private._requestFileExt, 'utf8', private._createCacheFile );
				break;
			case 'production':
			case 'staging':
				/*
				 * If the app is in any other environment, read the cache if it exists otherwise create the file
				 * Note: The cache files shouldn't be saved to the repo, they will be created at first use
				 */
				public.module.fs.readFile( private._cacheFileFull, 'utf8', private._outputCacheFile );
				break;
		}

	};

	private._outputCacheFile = function( error, data ) {

		if( error === null ) {
			private._writeResponse( 200, data, { 'Content-Type': 'text/plain', 'charset': 'utf-8' });
		} else {
			public.module.fs.readFile( private._requestFile + private._requestFileExt, 'utf8', private._createCacheFile );
		}

	}

	private._createCacheFile = function( err, data ) {

		if( err == null ) {

			var lines, count,
				matches = data.match(/{{(.*)}}/g),
				tag = '',
				md5sum, newFile;

			for( var match in matches ) {

				var tag = matches[ match ].replace('{{','').replace('}}','').split(':'),
					call = '_setup' + tag[0].charAt(0).toUpperCase() + tag[0].slice(1);

				if( typeof private[ call ] == 'function' ) {
					data = private[ call ]( data, matches[ match ], tag[1] );
				}

			}

			data = data.replace(/[^'":]\/\/.*/g, function(match){
				return '/*' + match.replace('//','') + '*/';
			});

			newFile = public.setting('application','root') + public.setting('application','directory') + '/cache/' + private._cacheFile + private._requestFileExt;

			public.module.fs.writeFileSync( newFile, data );

			/*
			 * Run the file through the jshinter and show errors if needed
			 */
			if( public.setting('application','environment') == 'development' ) {
				//console.log( 'jshint --show-non-errors --reporter=' + public.setting('general','server_directory') + 'server/jshint_reporter.js ' + newFile );
				public.module.child_process.exec( 'jshint --show-non-errors --reporter=' + public.setting('application','root') + '/server/jshint_reporter.js' + newFile, function(error, stdout, stderr) {
					if( stdout.toString() == '' ) {
						console.log( error );
						//private._writeResponse( 200, stderr.toString(), { 'Content-Type': 'text/plain', 'charset': 'utf-8' });
						public.module.fs.readFile( private._cacheFileFull, 'utf8', private._outputCacheFile );
					} else {
						private._writeResponse( 200, stdout, { 'Content-Type': 'text/plain', 'charset': 'utf-8' });
					}

				});
			}

		} else {
			var fourohfour = './server/404.js';
			public.module.fs.readFile( fourohfour, 'utf8', function( error, data ){
				if( error === null ) {
					private._writeResponse( 200, data, { 'Content-Type': 'text/plain', 'charset': 'utf-8' });
				} else {
					private._writeResponse( 404, error.toString() );
				}
			} );

		}

	};

	private._writeResponse = function( code, output, headers ) {

		if( headers == null ) {
			private._response.writeHead( code );
		} else {
			private._response.writeHead( code, headers );
		}
		private._response.write( output );
		private._response.end();
	}

	/*
	 * Convert template call to NetSuite getBody
	 */
	private._setupTemplate = function( data, match, file ) {

		var templateUrl = public.setting('server','url') + public.setting('application','assets') + '/templates/' + file + '.html',
			templateScript = 'nlapiRequestURL("' + templateUrl + '").getBody()';

		return data.replace( match, templateScript );

	};

	private._setupStyle = function( data, match, file ) {

		var styleUrl = public.setting('server','url') + public.setting('application','assets') + '/styles/' + file + '.css',
			styleHref = 'nlapiRequestURL("' + styleUrl + '").getBody()';

		return data.replace( match, styleHref );

	};

	private._setupClient = function( data, match, file ) {

		var scriptUrl = public.setting('server','url') + '/scripts/' + file + '.js',
			scriptSrc = 'nlapiRequestURL("' + scriptUrl + '").getBody()';

		return data.replace( match, scriptSrc );

	};

	private._setupLibrary = function( data, match, file ) {

		var scriptUrl = './' + public.setting('application','directory') + '/libraries/' + file + '.js',
			library = private._stripBackreference( public.module.fs.readFileSync(scriptUrl, 'utf8') ),
			library = ( file != 'global' ) ? private._library.format( library, {site_url: public.setting('server','url'), environment: public.setting('application','environment')} ) : library;

		return private._replaceBackreference( data.replace( match, library ) );
	};

	private._stripBackreference = function( text ) {
		var pattern = new RegExp(/(\$)((?! )(.))/g);

		return text.replace( pattern, '|{$1+$2}|' );
	};

	private._replaceBackreference = function( text ) {
		var pattern = new RegExp(/(\|{)(\$)(\+)(.)(}\|)/g);

		return text.replace( pattern, '$2$4' );
	};

	return public;
})();

module.exports = core;<commit_msg>Regex cleanup<commit_after>var core = (function() {

	var public = module.parent.iosuite,
		private = {};

	private._return = 'success';

	private._response;

	private._requestFile = '';
	private._cacheFile = '';
	private._cacheFileFull = '';
	private._library = require('./library');

	public.init = function( file, parameters, response ) {

		private._response = response;

		if( file.indexOf('assets/') >= 0 ) {
			/*
			 * Request is for an image / script / style
			 */
			private._return = private._readAsset( file );
		} else {
			private._return = private._readFile( file );
		}

		return private._return;

	};

	private._readAsset = function( file ) {
		private._requestFile = './' + file.substr(0, file.lastIndexOf('.'));
		private._requestFileExt = '.' + file.split('.').pop();

		var asset;
		try {
			var textExtensions = '|.html|.htm|.css|.js|.txt|';
			if( textExtensions.indexOf( '|' + private._requestFileExt + '|' ) >= 0 ) {
				asset = private._library.format( public.module.fs.readFileSync( private._requestFile + private._requestFileExt, 'utf-8' ), {site_url: public.setting('server','url'), environment: public.setting('application','environment')} );
			} else {
				asset = public.module.fs.readFileSync( private._requestFile + private._requestFileExt );
			}

			var contentType = public.module.mime.lookup( private._requestFile + private._requestFileExt ),
				headers = {};

			headers['Content-Type'] = contentType;
			headers["Access-Control-Allow-Headers"] = 'Origin, X-Requested-With, Content-Type, Accept';
			headers["Access-Control-Allow-Origin"] = ( public.setting('application','environment') == 'production' ) ? 'https://system.netsuite.com' : 'https://system.sandbox.netsuite.com';

			private._response.writeHead( 200, headers );
			private._response.end( asset, 'binary' );

		} catch(e) {
			if( e.code !== 'ENOENT' ) {
				private._response.writeHead( 404, { 'Content-Type': 'text/html', 'charset': 'utf-8' } );
				private._response.end( private._library.handleError( e, private._response ) );
			} else {
				private._writeResponse( 404, 'File does not exist', { 'Content-Type': 'text/plain', 'charset': 'utf-8' });
			}
		}

	};

	private._readFile = function( file ) {

		var cacheHash = public.module.crypto.createHash('md5'),
			filePieces = file.split('/'),
			requestFolder = './';

		if( file.indexOf('.') >= 0 ) {
			private._requestFile = requestFolder + file.substr(0, file.lastIndexOf('.'));
			private._requestFileExt = '.' + file.split('.').pop();
		} else {
			private._requestFile = requestFolder + public.setting('application','directory') + '/' + file;
			private._requestFileExt = '.js';
		}

		console.log( private._requestFile );

		/*
		 * Generate MD5 hash cache name
		 */
		cacheHash.update( private._requestFile );
		private._cacheFile = cacheHash.digest('hex');
		private._cacheFileFull = './' + public.setting('application','directory') + '/cache/' + private._cacheFile + private._requestFileExt;

		switch( public.setting('application','environment') ) {
			case 'development':
				/*
				 * If the app is in development, create a cache file and send
				 */
				console.log( private._requestFile + private._requestFileExt );
				public.module.fs.readFile( private._requestFile + private._requestFileExt, 'utf8', private._createCacheFile );
				break;
			case 'production':
			case 'staging':
				/*
				 * If the app is in any other environment, read the cache if it exists otherwise create the file
				 * Note: The cache files shouldn't be saved to the repo, they will be created at first use
				 */
				public.module.fs.readFile( private._cacheFileFull, 'utf8', private._outputCacheFile );
				break;
		}

	};

	private._outputCacheFile = function( error, data ) {

		if( error === null ) {
			private._writeResponse( 200, data, { 'Content-Type': 'text/plain', 'charset': 'utf-8' });
		} else {
			public.module.fs.readFile( private._requestFile + private._requestFileExt, 'utf8', private._createCacheFile );
		}

	}

	private._createCacheFile = function( err, data ) {

		if( err == null ) {

			var lines, count,
				regex = new RegExp( '({{)((?:[a-zA-Z0-9_:])*?)(}})', 'ig' ),
				md5sum, newFile;

			data = data.replace( regex, function(match, open, tag){
				var tag = tag.split(':'),
					call = '_setup' + tag[0].charAt(0).toUpperCase() + tag[0].slice(1);

				if( typeof private[ call ] == 'function' ) {
					return private[ call ]( tag[1] );
				} else {
					return match;
				}
			});

			data = data.replace(/[^'":]\/\/.*/g, function(match){
				return '/*' + match.replace('//','') + '*/';
			});

			newFile = public.setting('application','root') + public.setting('application','directory') + '/cache/' + private._cacheFile + private._requestFileExt;

			public.module.fs.writeFileSync( newFile, data );

			/*
			 * Run the file through the jshinter and show errors if needed
			 */
			if( public.setting('application','environment') == 'development' ) {
				//console.log( 'jshint --show-non-errors --reporter=' + public.setting('general','server_directory') + 'server/jshint_reporter.js ' + newFile );
				public.module.child_process.exec( 'jshint --show-non-errors --reporter=' + public.setting('application','root') + '/server/jshint_reporter.js' + newFile, function(error, stdout, stderr) {
					if( stdout.toString() == '' ) {
						console.log( error );
						//private._writeResponse( 200, stderr.toString(), { 'Content-Type': 'text/plain', 'charset': 'utf-8' });
						public.module.fs.readFile( private._cacheFileFull, 'utf8', private._outputCacheFile );
					} else {
						private._writeResponse( 200, stdout, { 'Content-Type': 'text/plain', 'charset': 'utf-8' });
					}

				});
			} else {

				/*
				 *  For non-development environments, display the cache file
				 */
				public.module.fs.readFile( private._cacheFileFull, 'utf8', private._outputCacheFile );
			}

		} else {
			var fourohfour = './server/404.js';
			public.module.fs.readFile( fourohfour, 'utf8', function( error, data ){
				if( error === null ) {
					private._writeResponse( 200, data, { 'Content-Type': 'text/plain', 'charset': 'utf-8' });
				} else {
					private._writeResponse( 404, error.toString() );
				}
			} );

		}

	};

	private._writeResponse = function( code, output, headers ) {

		if( headers == null ) {
			private._response.writeHead( code );
		} else {
			private._response.writeHead( code, headers );
		}
		private._response.write( output );
		private._response.end();
	}

	/*
	 * Convert template call to NetSuite getBody
	 */
	private._setupTemplate = function( file ) {

		var templateUrl = public.setting('server','url') + public.setting('application','assets') + '/templates/' + file + '.html',
			templateScript = 'nlapiRequestURL("' + templateUrl + '").getBody()';

		return templateScript;

	};

	private._setupStyle = function( file ) {

		var styleUrl = public.setting('server','url') + public.setting('application','assets') + '/styles/' + file + '.css',
			styleHref = 'nlapiRequestURL("' + styleUrl + '").getBody()';

		return styleHref;

	};

	private._setupClient = function( file ) {

		var scriptUrl = public.setting('server','url') + '/scripts/' + file + '.js',
			scriptSrc = 'nlapiRequestURL("' + scriptUrl + '").getBody()';

		return scriptSrc;

	};

	private._setupLibrary = function( file ) {

		var scriptUrl = './' + public.setting('application','directory') + '/libraries/' + file + '.js',
			library = private._stripBackreference( public.module.fs.readFileSync(scriptUrl, 'utf8') ),
			library = ( file != 'global' ) ? private._library.format( library, {site_url: public.setting('server','url'), environment: public.setting('application','environment')} ) : library;

		return private._replaceBackreference( library );
	};

	private._stripBackreference = function( text ) {
		var pattern = new RegExp(/(\$)((?! )(.))/g);

		return text.replace( pattern, '|{$1+$2}|' );
	};

	private._replaceBackreference = function( text ) {
		var pattern = new RegExp(/(\|{)(\$)(\+)(.)(}\|)/g);

		return text.replace( pattern, '$2$4' );
	};

	return public;
})();

module.exports = core;<|endoftext|>


<commit_before>var HarmonyHubDiscover = require('harmonyhubjs-discover')
var harmonyClient = require('harmonyhubjs-client')

module.exports = function (RED) {
  function HarmonyServerNode (n) {
    RED.nodes.createNode(this, n)
    var node = this

    node.ip = n.ip
    createClient(node)
  }
  RED.nodes.registerType('harmony-server', HarmonyServerNode)

  function createClient (node) {
    var harmony = node.harmony
    var ip = node.ip
    if (harmony && typeof harmony.end !== 'undefined') {
      try {
        harmony.end()
      } catch (e) { }
    }
    harmonyClient(ip).then(function (harmony) {
      node.harmony = harmony
      !(function keepAlive () {
        harmony.request('getCurrentActivity').timeout(50000).then(function (response) {
          setTimeout(keepAlive, 50000)
        }).catch(function (e) {
          console.log('Disconnected from Harmony Hub: ' + e)
          createClient(node)
        })
      }()) // jshint ignore:line
    }).catch(function (err) {
      console.log('error: ' + err)
      if (err) throw err
    })
  }

  RED.httpAdmin.get('/harmony/server', function (req, res, next) {
    var discover = new HarmonyHubDiscover(61991)

    discover.on('online', function (hub) {
      res.end(JSON.stringify(hub.ip))
      discover.stop()
    })

    discover.start()
  })

  RED.httpAdmin.get('/harmony/activities', function (req, res, next) {
    if (!req.query.ip) {
      res.status(400).send('Missing argument IP')
    } else {
      harmonyClient(req.query.ip)
                .then(function (harmony) {
                  harmony.getActivities()
                        .then(function (acts) {
                          harmony.end()
                          res.status(200).send(JSON.stringify(acts))
                        }).fail(function (err) {
                          harmony.end()
                          res.status(500).send('Request failed.')
                          if (err) throw err
                        })
                }).fail(function (err) {
                  res.status(500).send('Request failed.')
                  if (err) throw err
                })
    }
  })

  RED.httpAdmin.get('/harmony/commands', function (req, res, next) {
    if (!req.query.ip || !req.query.activity) {
      res.status(400).send('Missing argument.')
    } else {
      harmonyClient(req.query.ip)
                .then(function (harmony) {
                  harmony.getActivities()
                        .then(function (acts) {
                          acts.some(function (act) {
                            if (act.id === req.query.activity) {
                              harmony.end()
                              res.status(200).send(JSON.stringify(act.controlGroup))
                            }
                          })
                        }).fail(function (err) {
                          harmony.end()
                          res.status(500).send('Request failed.')
                          if (err) throw err
                        })
                }).fail(function (err) {
                  res.status(500).send('Request failed.')
                  if (err) throw err
                })
    }
  })
}
<commit_msg>end harmony connection on node close / deploy<commit_after>var HarmonyHubDiscover = require('harmonyhubjs-discover')
var harmonyClient = require('harmonyhubjs-client')

module.exports = function (RED) {
  function HarmonyServerNode (n) {
    RED.nodes.createNode(this, n)
    var node = this

    node.ip = n.ip
    createClient(node)

    this.on('close', function () {
      if (node.harmony && typeof node.harmony.end !== 'undefined') {
        try {
          node.harmony.end()
        } catch (e) { }
      }
    })
  }
  RED.nodes.registerType('harmony-server', HarmonyServerNode)

  function createClient (node) {
    var harmony = node.harmony
    var ip = node.ip
    if (harmony && typeof harmony.end !== 'undefined') {
      try {
        harmony.end()
      } catch (e) { }
    }
    harmonyClient(ip).then(function (harmony) {
      node.harmony = harmony
      !(function keepAlive () {
        harmony.request('getCurrentActivity').timeout(50000).then(function (response) {
          setTimeout(keepAlive, 50000)
        }).catch(function (e) {
          console.log('Disconnected from Harmony Hub: ' + e)
          createClient(node)
        })
      }()) // jshint ignore:line
    }).catch(function (err) {
      console.log('error: ' + err)
      if (err) throw err
    })
  }

  RED.httpAdmin.get('/harmony/server', function (req, res, next) {
    var discover = new HarmonyHubDiscover(61991)

    discover.on('online', function (hub) {
      res.end(JSON.stringify(hub.ip))
      discover.stop()
    })

    discover.start()
  })

  RED.httpAdmin.get('/harmony/activities', function (req, res, next) {
    if (!req.query.ip) {
      res.status(400).send('Missing argument IP')
    } else {
      harmonyClient(req.query.ip)
                .then(function (harmony) {
                  harmony.getActivities()
                        .then(function (acts) {
                          harmony.end()
                          res.status(200).send(JSON.stringify(acts))
                        }).fail(function (err) {
                          harmony.end()
                          res.status(500).send('Request failed.')
                          if (err) throw err
                        })
                }).fail(function (err) {
                  res.status(500).send('Request failed.')
                  if (err) throw err
                })
    }
  })

  RED.httpAdmin.get('/harmony/commands', function (req, res, next) {
    if (!req.query.ip || !req.query.activity) {
      res.status(400).send('Missing argument.')
    } else {
      harmonyClient(req.query.ip)
                .then(function (harmony) {
                  harmony.getActivities()
                        .then(function (acts) {
                          acts.some(function (act) {
                            if (act.id === req.query.activity) {
                              harmony.end()
                              res.status(200).send(JSON.stringify(act.controlGroup))
                            }
                          })
                        }).fail(function (err) {
                          harmony.end()
                          res.status(500).send('Request failed.')
                          if (err) throw err
                        })
                }).fail(function (err) {
                  res.status(500).send('Request failed.')
                  if (err) throw err
                })
    }
  })
}
<|endoftext|>


<commit_before>/* Plug application system.
 * Copyright © 2011 Jan Keromnes, Thaddee Tyl. All rights reserved.
 * The following code is covered by the GPLv2 license. */

var fs = require('./fs'),
    driver = require('./driver'),
    nodepath = require('path');

// We need Camp's socket.io object here. We get it at initialization.
var camp;

exports.main = function (server) { camp = server; };

// The plug system.

exports.resolve = function (query, path, endres, ask) {

  // Get the file/folder corresponding to the query
  ///console.log('PLUG:PLUG: what is %s?', path[1]);
  fs.file (path[1], function (err, file) {

    function end(err, plug, data) {
      if (err) console.error(err);
      if (!plug || plug === 'none') {
        path[0] = path[1];
        endres(data || {});
      } else {
        if (nodepath.extname(plug).length === 0) plug += '.html';
        fs.file(plug, function(err, file) {
          // TODO template with file.content instead of giving plug path
          path[0] = (err ? path[1] : plug);
          endres(data || {});
        });
      }
    }

    // If there was an error, abort!
    if (err) {
      ask.res.statusCode = 404;
      end(err, '404.html', {error: err.message});
      return;
    }

    // TODO If file requires a password and nothing matches, abort!

    // PLUG MECHANISM

    var data = {}, delayed = false;

    // Environment variable lookup mechanism
    data.lookup = function(key) {
      // from most specific (url?key=value) to most generic (inherited metadata)
      if (query[key]) return query[key];
      if (file.meta[key]) return file.meta[key];
      return null;
    };

    // File info
    data.file = file;
    data.file.mime = fs.type.nameFromType[file.meta.type];
    data.files = [];
    data.title = nodepath.basename(file.path) || 'The File Tree';

    // Navigation crumbs
    data.nav = [];
    var crumbs = path[1].split('/').filter(function(e) {
      return e.length > 0;
    });
    var subpath = '/';
    data.nav.push({name: '/', path: subpath});
    for ( var i = 0; i < crumbs.length; i++ ) {
      crumbs[i] += (i < crumbs.length - 1 || file.isOfType('dir') ? '/' : '');
      subpath += crumbs[i];
      data.nav.push({name: crumbs[i], path: subpath});
    }

    // Find a plug to use
    var plug = data.lookup('plug');

    if (plug === 'none') {
      end(); // no plug
      return;
    }

    if (file.isOfType('dir')) {

      // Delay callback, wait for subfiles
      delayed = true;

      // FIXME check for default "dir" plug instead
      plug = plug || 'gateway.html';

      // Handle missing final '/'
      // FIXME consider redirecting user to path[1] + '/' instead
      if ( path[1][path[1].length-1] !== '/' ) {
        path[1] += '/';
      }

      // Get subfiles
      file.files (function (err, files) {
        if (err)  console.error(err);
        for (var i = 0; i < files.length; i++) {
          var filepath = driver.normalize(files[i].path + (files[i].isOfType('dir') ? '/' : ''));
          data.files.push({name: nodepath.basename(filepath), path: filepath});
        }
        ///console.log('server:root: data sent from dir is', data);
        end(err, plug, data);
      });

    } else if (file.isOfType('text/plain')) {

      // Delay callback, wait for file content
      delayed = true;

      // TODO check for default "text/plain" plug instead
      plug = plug || 'pencil.html';

      file.ot(camp.io, function(err) { end(err, plug, data); });

    } else if (file.isOfType('binary')) {

      // TODO check for default "binary" plug instead
      plug = plug || 'none';
    }

    if (!delayed) {
      //console.error('WAS NOT DELAYED');
      end(err, plug, data);
      return;
    }
  });
};

<commit_msg>fix bypass template engine when no plug<commit_after>/* Plug application system.
 * Copyright © 2011 Jan Keromnes, Thaddee Tyl. All rights reserved.
 * The following code is covered by the GPLv2 license. */

var fs = require('./fs'),
    driver = require('./driver'),
    nodepath = require('path');

// We need Camp's socket.io object here. We get it at initialization.
var camp;

exports.main = function (server) { camp = server; };

// The plug system.

exports.resolve = function (query, path, endres, ask) {

  // Get the file/folder corresponding to the query
  ///console.log('PLUG:PLUG: what is %s?', path[1]);
  fs.file (path[1], function (err, file) {

    function sendraw() {
      path[0] = path[1];
      endres(); // bypass template engine
    }

    function end(err, plug, data) {
      if (err) console.error(err);
      if (!plug || plug === 'none') sendraw();
      else {
        if (nodepath.extname(plug).length === 0) plug += '.html';
        fs.file(plug, function(err, file) {
          // TODO template with file.content instead of giving plug path
          if (err) sendraw();
          else {
            path[0] = plug;
            endres(data || {});
          }
        });
      }
    }

    // If there was an error, abort!
    if (err) {
      ask.res.statusCode = 404;
      end(err, '404.html', {error: err.message});
      return;
    }

    // TODO If file requires a password and nothing matches, abort!

    // PLUG MECHANISM

    var data = {}, delayed = false;

    // Environment variable lookup mechanism
    data.lookup = function(key) {
      // from most specific (url?key=value) to most generic (inherited metadata)
      if (query[key]) return query[key];
      if (file.meta[key]) return file.meta[key];
      return null;
    };

    // File info
    data.file = file;
    data.file.mime = fs.type.nameFromType[file.meta.type];
    data.files = [];
    data.title = nodepath.basename(file.path) || 'The File Tree';

    // Navigation crumbs
    data.nav = [];
    var crumbs = path[1].split('/').filter(function(e) {
      return e.length > 0;
    });
    var subpath = '/';
    data.nav.push({name: '/', path: subpath});
    for ( var i = 0; i < crumbs.length; i++ ) {
      crumbs[i] += (i < crumbs.length - 1 || file.isOfType('dir') ? '/' : '');
      subpath += crumbs[i];
      data.nav.push({name: crumbs[i], path: subpath});
    }

    // Find a plug to use
    var plug = data.lookup('plug');

    if (plug === 'none') {
      end(); // no plug
      return;
    }

    if (file.isOfType('dir')) {

      // Delay callback, wait for subfiles
      delayed = true;

      // FIXME check for default "dir" plug instead
      plug = plug || 'gateway.html';

      // Handle missing final '/'
      // FIXME consider redirecting user to path[1] + '/' instead
      if ( path[1][path[1].length-1] !== '/' ) {
        path[1] += '/';
      }

      // Get subfiles
      file.files (function (err, files) {
        if (err)  console.error(err);
        for (var i = 0; i < files.length; i++) {
          var filepath = driver.normalize(files[i].path + (files[i].isOfType('dir') ? '/' : ''));
          data.files.push({name: nodepath.basename(filepath), path: filepath});
        }
        ///console.log('server:root: data sent from dir is', data);
        end(err, plug, data);
      });

    } else if (file.isOfType('text/plain')) {

      // Delay callback, wait for file content
      delayed = true;

      // TODO check for default "text/plain" plug instead
      plug = plug || 'pencil.html';

      file.ot(camp.io, function(err) { end(err, plug, data); });

    } else if (file.isOfType('binary')) {

      // TODO check for default "binary" plug instead
      plug = plug || 'none';
    }

    if (!delayed) {
      end(err, plug, data);
      return;
    }
  });
};

<|endoftext|>


<commit_before>import { basename } from 'path'

import hljs from 'highlight.js'
import * as R from 'ramda'

import AsyncResult from 'utils/AsyncResult'

import { PreviewData } from '../types'
import * as utils from './utils'

const MAX_BYTES = 10 * 1024

const LANGS = {
  accesslog: /\.log$/,
  bash: /\.(ba|z)?sh$/,
  clojure: /\.clj$/,
  coffeescript: /\.(coffee|cson|iced)$/,
  coq: /\.v$/,
  cpp: /\.((c(c|\+\+|pp|xx)?)|(h(\+\+|pp|xx)?))$/,
  cs: /\.cs$/,
  css: /\.css$/,
  diff: /\.(diff|patch)$/,
  dockerfile: /^dockerfile$/,
  erlang: /\.erl$/,
  go: /\.go$/,
  haskell: /\.hs$/,
  ini: /\.(ini|toml)$/,
  java: /\.(java|jsp)$/,
  javascript: /\.m?jsx?$/,
  json: /\.jsonl?$/,
  lisp: /\.lisp$/,
  makefile: /^(gnu)?makefile$/,
  matlab: /\.m$/,
  ocaml: /\.mli?$/,
  perl: /\.pl$/,
  php: /\.php[3-7]?$/,
  plaintext: /((^license)|(^readme)|(^\.\w*(ignore|rc|config))|(\.txt)|(\.(c|t)sv)|(\.(big)?bed)|(\.fa)|(\.fsa)|(\.fasta)|(\.(san)?fastq)|(\.fq)|(\.sam)|(\.gff(2|3)?)|(\.gtf)|(\.index)|(\.readme))$/,
  python: /\.(py|gyp)$/,
  r: /\.r$/,
  ruby: /\.rb$/,
  rust: /\.rs$/,
  scala: /\.scala$/,
  scheme: /\.s(s|ls|cm)$/,
  sql: /\.sql$/,
  typescript: /\.tsx?$/,
  xml: /\.(xml|x?html|rss|atom|xjb|xsd|xsl|plist)$/,
  yaml: /\.ya?ml$/,
}

const langPairs = Object.entries(LANGS)

const findLang = R.pipe(basename, R.toLower, utils.stripCompression, (name) =>
  langPairs.find(([, re]) => re.test(name)),
)

export const detect = R.pipe(findLang, Boolean)

const getLang = R.pipe(findLang, ([lang] = []) => lang)

const hl = (lang) => (contents) => hljs.highlight(lang, contents).value

const fetcher = utils.previewFetcher(
  'txt',
  ({ info: { data, note, warnings } }, { handle, forceLang }) => {
    const head = data.head.join('\n')
    const tail = data.tail.join('\n')
    const lang = forceLang || getLang(handle.key)
    const highlighted = R.map(hl(lang), { head, tail })
    return AsyncResult.Ok(
      PreviewData.Text({ head, tail, lang, highlighted, note, warnings }),
    )
  },
)

export const load = (handle, callback, extra) =>
  fetcher(handle, callback, { query: { max_bytes: MAX_BYTES }, ...extra })
<commit_msg>Support .cef preview (#1609)<commit_after>import { basename } from 'path'

import hljs from 'highlight.js'
import * as R from 'ramda'

import AsyncResult from 'utils/AsyncResult'

import { PreviewData } from '../types'
import * as utils from './utils'

const MAX_BYTES = 10 * 1024

const LANGS = {
  accesslog: /\.log$/,
  bash: /\.(ba|z)?sh$/,
  clojure: /\.clj$/,
  coffeescript: /\.(coffee|cson|iced)$/,
  coq: /\.v$/,
  cpp: /\.((c(c|\+\+|pp|xx)?)|(h(\+\+|pp|xx)?))$/,
  cs: /\.cs$/,
  css: /\.css$/,
  diff: /\.(diff|patch)$/,
  dockerfile: /^dockerfile$/,
  erlang: /\.erl$/,
  go: /\.go$/,
  haskell: /\.hs$/,
  ini: /\.(ini|toml)$/,
  java: /\.(java|jsp)$/,
  javascript: /\.m?jsx?$/,
  json: /\.jsonl?$/,
  lisp: /\.lisp$/,
  makefile: /^(gnu)?makefile$/,
  matlab: /\.m$/,
  ocaml: /\.mli?$/,
  perl: /\.pl$/,
  php: /\.php[3-7]?$/,
  plaintext: /((^license)|(^readme)|(^\.\w*(ignore|rc|config))|(\.txt)|(\.(c|t)sv)|(\.(big)?bed)|(\.cef)|(\.fa)|(\.fsa)|(\.fasta)|(\.(san)?fastq)|(\.fq)|(\.sam)|(\.gff(2|3)?)|(\.gtf)|(\.index)|(\.readme))$/,
  python: /\.(py|gyp)$/,
  r: /\.r$/,
  ruby: /\.rb$/,
  rust: /\.rs$/,
  scala: /\.scala$/,
  scheme: /\.s(s|ls|cm)$/,
  sql: /\.sql$/,
  typescript: /\.tsx?$/,
  xml: /\.(xml|x?html|rss|atom|xjb|xsd|xsl|plist)$/,
  yaml: /\.ya?ml$/,
}

const langPairs = Object.entries(LANGS)

const findLang = R.pipe(basename, R.toLower, utils.stripCompression, (name) =>
  langPairs.find(([, re]) => re.test(name)),
)

export const detect = R.pipe(findLang, Boolean)

const getLang = R.pipe(findLang, ([lang] = []) => lang)

const hl = (lang) => (contents) => hljs.highlight(lang, contents).value

const fetcher = utils.previewFetcher(
  'txt',
  ({ info: { data, note, warnings } }, { handle, forceLang }) => {
    const head = data.head.join('\n')
    const tail = data.tail.join('\n')
    const lang = forceLang || getLang(handle.key)
    const highlighted = R.map(hl(lang), { head, tail })
    return AsyncResult.Ok(
      PreviewData.Text({ head, tail, lang, highlighted, note, warnings }),
    )
  },
)

export const load = (handle, callback, extra) =>
  fetcher(handle, callback, { query: { max_bytes: MAX_BYTES }, ...extra })
<|endoftext|>


<commit_before>cheerio = require('cheerio');
request = require('request');
MangaModel = require('../../db/MangaModel');

var api = global.api
api.mal.manga = {

	id: function(req, res, next) {
		res.type('application/json');

		var id = req.params.id;

		Manga.findById(id, function(err, manga) {
			if (err) {
				return next(err);
			}

			res.send(manga);
		});
	}
}

var Manga = (function() {

	function Manga() {}

	/**
	 * Attempts to find and retrieve a manga from the MAL DB.
	 * This method will usually return almost instantly but sometimes
	 * a cache hit will be incurred and the manga will be fetched from the MAL
	 * DB all over again.
	 * @param  {[Number]}   id - The ID of the manga to fetch
	 * @param  {Function} callback - The callback to be executed with the manga model.
	 */
	Manga.findById = function(id, callback) {

		var that = this;

		// Attempt to find it in our DB and return it if we can immediately
		MangaModel.findOne({
			mal_id: id
		}, function(err, manga) {

			if (manga == null) {
				// download and return
				that._downloadManga(id, function(mangaObject) {

					// Persist to the DB if we need to
					/* Insert the record iff it's not an invalid request */
					if (mangaObject['name'] != "Invalid Request") {
						var mangaModel = new MangaModel(mangaObject);
						mangaModel.save();
					}

					callback(null, mangaObject);
				});
			} else {
				callback(null, manga);
			}

		});

	};

	/**
	 * Fetches a manga from the MAL DB and executes a callback
	 * containing the data. This call is expensive to make and speed
	 * is dependent on the remote server. It is possible to get garbage back.
	 * @param  {[Number]}   id - The ID of the manga to download
	 * @param  {Function} callback - The callback to be executed
	 */
	Manga._downloadManga = function(id, callback) {

		var that = this;
		request({
			url: 'http://myanimelist.net/manga/' + id,
			headers: {
				'User-Agent': 'api-team-692e8861471e4de2fd84f6d91d1175c0'
			},
			timeout: 3000
		}, function(err, response, body) {
			if (err) {
				return callback(err);
			}

			var mangaObject = that._tryParse(body);
			mangaObject['mal_id'] = id;

			callback(mangaObject);
		});
	};

	/**
	 * Attempts to parse the HTML from the given MAL page and return valid JSON.
	 * @param  {[type]} html - A valid HTML markup
	 */
	Manga._tryParse = function(html) {

		var $ = cheerio.load(html);
		var manga = {};

		manga.name = $('h1').first().contents().filter(function() {
			return this.type !== 'tag';
		}).text();

		// Set the expirty to 7 days; this is how often we evict anime entries from our cache
		var now = new Date();
		manga.expiry = now.setDate(now.getDate() + 7);

		manga.poster = $('.borderClass img').attr('src');

		// Get the summary of the show
		manga.synopsis = $("h2:contains('Synopsis')").parent().text().substring(8);
		// We can grab some stats here
		var type = "Type:";
		manga.type = $(".dark_text:contains('Type:')").parent().text().substring(type.length + 1);

		var status = "Status:";
		var textStatus = $(".dark_text:contains('Status:')").parent().text().substring(status.length + 1);
		manga.status = textStatus;

		manga.genres = [];
		var genres = "Genres:";
		var englishGenres = $(".dark_text:contains('Genres:')").parent().text().substring(genres.length + 4).split(",");
		for (var genre in englishGenres)
			manga.genres.push(englishGenres[genre].trim());

		manga.malstats = {};

		var rating = "Rating:";
		manga.malstats.rating = $(".dark_text:contains('Rating:')").parent().text().substring(rating.length + 4);

		var rank = "Ranked:";
		manga.malstats.rank = $(".dark_text:contains('Ranked:')").parent().first().contents().filter(function() {
			return this.type !== 'tag';
		}).text().trim().substring(1);

		manga.malstats.score = $(".dark_text:contains('Score:')").parent().first().contents().filter(function() {
			return this.type !== 'tag';
		}).text().trim();

		return manga;

	};

	return Manga;

})();

module.exports = Manga;<commit_msg>Fixed minor spelling issues<commit_after>cheerio = require('cheerio');
request = require('request');
MangaModel = require('../../db/MangaModel');

var api = global.api
api.mal.manga = {
	id: function(req, res, next) {
		res.type('application/json');

		var id = req.params.id;

		Manga.byId(id, function(err, manga) {
			if (err) {
				return next(err);
			}

			res.send(manga);
		});
	}
}

var Manga = (function() {

	function Manga() {}

	/**
	 * Attempts to find and retrieve a manga from the MAL DB.
	 * This method will usually return almost instantly but sometimes
	 * a cache hit will be incurred and the manga will be fetched from the MAL
	 * DB all over again.
	 * @param  {[Number]}   id - The ID of the manga to fetch
	 * @param  {Function} callback - The callback to be executed with the manga model.
	 */
	Manga.byId = function(id, callback) {

		var that = this;

		// Attempt to find it in our DB and return it if we can immediately
		MangaModel.findOne({
			mal_id: id
		}, function(err, manga) {
			if (manga == null) {
				// download and return
				that._downloadManga(id, function(mangaObject) {

					// Persist to the DB if we need to
					/* Insert the record iff it's not an invalid request */
					if (mangaObject['name'] != "Invalid Request") {
						var mangaModel = new MangaModel(mangaObject);
						mangaModel.save();
					}

					callback(null, mangaObject);
				});
			} else {
				callback(null, manga);
			}

		});

	};

	/**
	 * Fetches a manga from the MAL DB and executes a callback
	 * containing the data. This call is expensive to make and speed
	 * is dependent on the remote server. It is possible to get garbage back.
	 * @param  {[Number]}   id - The ID of the manga to download
	 * @param  {Function} callback - The callback to be executed
	 */
	Manga._downloadManga = function(id, callback) {

		var that = this;
		request({
			url: 'http://myanimelist.net/manga/' + id,
			headers: {
				'User-Agent': 'api-team-692e8861471e4de2fd84f6d91d1175c0'
			},
			timeout: 3000
		}, function(err, response, body) {
			if (err) {
				return callback(err);
			}

			var mangaObject = that._tryParse(body);
			mangaObject['mal_id'] = id;

			callback(mangaObject);
		});
	};

	/**
	 * Attempts to parse the HTML from the given MAL page and return valid JSON.
	 * @param  {[type]} html - A valid HTML markup
	 */
	Manga._tryParse = function(html) {

		var $ = cheerio.load(html);
		var manga = {};

		manga.name = $('h1').first().contents().filter(function() {
			return this.type !== 'tag';
		}).text();

		// Set the expiry to 7 days; this is how often we evict anime entries from our cache
		var now = new Date();
		manga.expiry = now.setDate(now.getDate() + 7);

		manga.poster = $('.borderClass img').attr('src');

		// Get the summary of the show
		manga.synopsis = $("h2:contains('Synopsis')").parent().text().substring(8);
		// We can grab some stats here
		var type = "Type:";
		manga.type = $(".dark_text:contains('Type:')").parent().text().substring(type.length + 1);

		var status = "Status:";
		var textStatus = $(".dark_text:contains('Status:')").parent().text().substring(status.length + 1);
		manga.status = textStatus;

		manga.genres = [];
		var genres = "Genres:";
		var englishGenres = $(".dark_text:contains('Genres:')").parent().text().substring(genres.length + 4).split(",");
		for (var genre in englishGenres)
			manga.genres.push(englishGenres[genre].trim());

		manga.malstats = {};

		var rating = "Rating:";
		manga.malstats.rating = $(".dark_text:contains('Rating:')").parent().text().substring(rating.length + 4);

		var rank = "Ranked:";
		manga.malstats.rank = $(".dark_text:contains('Ranked:')").parent().first().contents().filter(function() {
			return this.type !== 'tag';
		}).text().trim().substring(1);

		manga.malstats.score = $(".dark_text:contains('Score:')").parent().first().contents().filter(function() {
			return this.type !== 'tag';
		}).text().trim();

		return manga;

	};

	return Manga;

})();

module.exports = Manga;<|endoftext|>


<commit_before>// Plug application system.
// Copyright © 2011-2015 Thaddee Tyl, Jan Keromnes. All rights reserved.
// The following code is covered by the AGPLv3 license.

var fs = require('./fs');
var stream = require('stream');
var nodepath = require('path');
var driver = require('./driver');
var lookup = require('./lookup');
var pwdCheck = require('./pwd-check');
var publicFile = require('./public-file');

// We need Camp's socket.io object here. We get it at initialization.
var camp;

exports.main = function (server) { camp = server; };

// The plug system.

exports.resolve = function (query, path, endres, ask) {

  // Get the file/folder corresponding to the query.
  fs.open(ask.path, function openQueryFile(err, file) {
    // If there was an error, abort!
    if (err) {
      ask.res.statusCode = 404;
      end(err, '404.html', {error: err.message});
      return;
    }

    var filePath = file.path;
    var content = file.content;
    function sendraw(data) {
      console.log('send', filePath);
      // Set HTTP header Content-Type.
      if (file.meta.type !== undefined) {
        ask.res.setHeader('Content-Type', file.meta.type);
      }
      if (data && data.content) {
        ask.res.end(data.content);
      } else {
        // Bypass the template engine.
        endres(null, { template: streamFromData(content) });
      }
    }

    function end(err, plug, data) {
      if (err) {
        console.error(err);
        endres(null, { template: '/404.html' });
        return;
      }
      if (!plug || plug === 'none') {
        sendraw(data); return;
      } else {
        if (nodepath.extname(plug).length === 0) { plug += '.html'; }
        fs.file(plug, function(err, file) {
          if (err) { sendraw(); return; }
          console.log('plug', file.path, '<', filePath);
          endres(data || {}, { template: file.path });
        });
      }
    }

    // TODO If file requires a password and nothing matches, abort!
    pwdCheck(file, ask.password, 'readkey', function checkedPwd(err) {
      if (err != null) {
        ask.res.statusCode = 401;
        ask.res.setHeader('WWW-Authenticate', 'Basic')
        end(err, '404.html', {error: err.message});
        return;
      }

      // Set HTTP header Last-Modified.
      if (file.meta['Last-Modified']) {
        ask.res.setHeader('Last-Modified',
            (new Date(file.meta['Last-Modified'])).toGMTString());
      }

      // PLUG MECHANISM

      var data = {};

      // Environment variable lookup mechanism.
      data.lookup = lookup(file, query);

      // File info.
      data.file = publicFile(file);
      data.files = [];
      data.title = nodepath.basename(filePath) || 'The File Tree';
      data.extname = nodepath.extname(filePath).slice(1);

      // Navigation crumbs
      data.nav = [];
      var crumbs = filePath.split('/').filter(function(e) {
        return e.length > 0;
      });
      var subpath = '/';
      data.nav.push({name: '/', path: subpath});
      for (var i = 0; i < crumbs.length; i++) {
        crumbs[i] += (i < crumbs.length - 1 || file.isOfType('dir') ? '/' : '');
        subpath += crumbs[i];
        data.nav.push({name: crumbs[i], path: subpath});
      }

      findPlug(file, data, end);
    });
  });
};

// Find the correct plug.
//
// 1. Look for the non-inherited `plug` metadata.
// 2. Look for the inherited `plugs.<file type>` metadata.
function findPlug(file, data, end) {
  var plug = data.lookup('plug');

  if (file.isOfType('dir')) {

    // Get subfiles.
    file.files (function (err, files) {
      if (err)  console.error(err);
      for (var i = 0; i < files.length; i++) {
        var filepath = driver.normalize(
          files[i].path + (files[i].isOfType('dir') ? '/' : ''));
        data.files.push({name: nodepath.basename(filepath),
                         path: filepath,
                         time: files[i].meta['Last-Modified'],
                         type: files[i].meta.type});
      }
      ///console.log('server:root: data sent from dir is', data);

      if (plug === 'none') {
        // We must send a newline-separated list of subfile names.
        var nameFromFile = function(f) {
          return nodepath.basename(f.path) +
            // Add a trailing slash for directories
            (f.isOfType('dir')? '/': '');
        };
        var subfileNames = files.map(nameFromFile).join('\n');
        end(err, null, {content: subfileNames});
      } else if (plug == null) {
        data.lookup('plugs.dir', function(plug) {
          end(err, plug || 'gateway.html', data);
        });
      } else {
        end(err, plug, data);
      }
    });

  } else if (plug === 'none') {
    end(); // no plug
    return;

  } else if (file.isOfType('text')) {

    file.ot(camp.io, function(err) {
      if (plug == null) {
        data.lookup('plugs.text', function(plug) {
          end(err, plug || 'pencil.html', data);
        });
      } else {
        end(err, plug, data);
      }
    });

  } else if (file.isOfType('binary')) {

    if (plug == null) {
      data.lookup('plugs.binary', function(plug) {
        end(null, plug || 'none', data);
      });
    } else {
      end(null, plug, data);
    }
  }
}

function objCopy(o) {
  var newObject = Object.create(null);
  for (var p in o) {
    try {
      newObject[p] = JSON.parse(JSON.stringify((o[p])));
    } catch(e) {}
  }
  return newObject;
}

function streamFromData(data) {
  var newStream = new stream.Readable();
  newStream._read = function() { newStream.push(data); newStream.push(null); };
  return newStream;
}
<commit_msg>Read plugs from /app/<commit_after>// Plug application system.
// Copyright © 2011-2016 Thaddee Tyl, Jan Keromnes. All rights reserved.
// The following code is covered by the AGPLv3 license.

var fs = require('./fs');
var stream = require('stream');
var nodepath = require('path');
var driver = require('./driver');
var lookup = require('./lookup');
var pwdCheck = require('./pwd-check');
var publicFile = require('./public-file');

// We need Camp's socket.io object here. We get it at initialization.
var camp;

exports.main = function (server) { camp = server; };

// The plug system.

exports.resolve = function (query, path, endres, ask) {

  // Get the file/folder corresponding to the query.
  fs.open(ask.path, function openQueryFile(err, file) {
    // If there was an error, abort!
    if (err) {
      ask.res.statusCode = 404;
      end(err, '404.html', {error: err.message});
      return;
    }

    var filePath = file.path;
    var content = file.content;
    function sendraw(data) {
      console.log('send', filePath);
      // Set HTTP header Content-Type.
      if (file.meta.type !== undefined) {
        ask.res.setHeader('Content-Type', file.meta.type);
      }
      if (data && data.content) {
        ask.res.end(data.content);
      } else {
        // Bypass the template engine.
        endres(null, { template: streamFromData(content) });
      }
    }

    function end(err, plug, data) {
      if (err) {
        console.error(err);
        endres(null, { template: '/404.html' });
        return;
      }
      if (!plug || plug === 'none') {
        sendraw(data); return;
      } else {
        console.log(plug);
        if (plug.slice(-5) !== '.html') {
          plug = nodepath.join('/app', plug, 'page.html');
        }
        fs.file(plug, function(err, file) {
          if (err) { sendraw(); return; }
          console.log('plug', file.path, '<', filePath);
          endres(data || {}, { template: file.path });
        });
      }
    }

    // TODO If file requires a password and nothing matches, abort!
    pwdCheck(file, ask.password, 'readkey', function checkedPwd(err) {
      if (err != null) {
        ask.res.statusCode = 401;
        ask.res.setHeader('WWW-Authenticate', 'Basic')
        end(err, '404.html', {error: err.message});
        return;
      }

      // Set HTTP header Last-Modified.
      if (file.meta['Last-Modified']) {
        ask.res.setHeader('Last-Modified',
            (new Date(file.meta['Last-Modified'])).toGMTString());
      }

      // PLUG MECHANISM

      var data = {};

      // Environment variable lookup mechanism.
      data.lookup = lookup(file, query);

      // File info.
      data.file = publicFile(file);
      data.files = [];
      data.title = nodepath.basename(filePath) || 'The File Tree';
      data.extname = nodepath.extname(filePath).slice(1);

      // Navigation crumbs
      data.nav = [];
      var crumbs = filePath.split('/').filter(function(e) {
        return e.length > 0;
      });
      var subpath = '/';
      data.nav.push({name: '/', path: subpath});
      for (var i = 0; i < crumbs.length; i++) {
        crumbs[i] += (i < crumbs.length - 1 || file.isOfType('dir') ? '/' : '');
        subpath += crumbs[i];
        data.nav.push({name: crumbs[i], path: subpath});
      }

      findPlug(file, data, end);
    });
  });
};

// Find the correct plug.
//
// 1. Look for the non-inherited `plug` metadata.
// 2. Look for the inherited `plugs.<file type>` metadata.
function findPlug(file, data, end) {
  var plug = data.lookup('plug');

  if (file.isOfType('dir')) {

    // Get subfiles.
    file.files (function (err, files) {
      if (err)  console.error(err);
      for (var i = 0; i < files.length; i++) {
        var filepath = driver.normalize(
          files[i].path + (files[i].isOfType('dir') ? '/' : ''));
        data.files.push({name: nodepath.basename(filepath),
                         path: filepath,
                         time: files[i].meta['Last-Modified'],
                         type: files[i].meta.type});
      }
      ///console.log('server:root: data sent from dir is', data);

      if (plug === 'none') {
        // We must send a newline-separated list of subfile names.
        var nameFromFile = function(f) {
          return nodepath.basename(f.path) +
            // Add a trailing slash for directories
            (f.isOfType('dir')? '/': '');
        };
        var subfileNames = files.map(nameFromFile).join('\n');
        end(err, null, {content: subfileNames});
      } else if (plug == null) {
        data.lookup('plugs.dir', function(plug) {
          end(err, plug || 'gateway.html', data);
        });
      } else {
        end(err, plug, data);
      }
    });

  } else if (plug === 'none') {
    end(); // no plug
    return;

  } else if (file.isOfType('text')) {

    file.ot(camp.io, function(err) {
      if (plug == null) {
        data.lookup('plugs.text', function(plug) {
          end(err, plug || 'pencil.html', data);
        });
      } else {
        end(err, plug, data);
      }
    });

  } else if (file.isOfType('binary')) {

    if (plug == null) {
      data.lookup('plugs.binary', function(plug) {
        end(null, plug || 'none', data);
      });
    } else {
      end(null, plug, data);
    }
  }
}

function objCopy(o) {
  var newObject = Object.create(null);
  for (var p in o) {
    try {
      newObject[p] = JSON.parse(JSON.stringify((o[p])));
    } catch(e) {}
  }
  return newObject;
}

function streamFromData(data) {
  var newStream = new stream.Readable();
  newStream._read = function() { newStream.push(data); newStream.push(null); };
  return newStream;
}
<|endoftext|>


<commit_before>/*
* Functions to create the mini modal maps
*/

// initialize map
function CDADModalMap(mapid, lat, lon, zoom, surveyid, type, numid) {

	//console.log(mapid);

    //where detroit is 42.377410, -83.093719
    this.map = new L.Map(mapid, {
		minZoom: 8,
		maxZoom: 16,
		attributionControl: false,
	});

	// add CartoDB tiles
	this.CartoDBLayer = L.tileLayer('http://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png');

	// add cartoDB tiles to start
	this.map.addLayer(this.CartoDBLayer);

	// create empty container for locations
	this.LOCATION = null;

	// create and empty container for detroit city boundary
	this.DETLAYER = null;
	this.CDOBCLAYER = null;

	if (type == 'locationAndSA') {
		// add location
		CDADModalMap.add_LOCATION(this, numid);

		// add SA
		CDADModalMap.add_SA(this, surveyid, numid);

	} else if (type == 'SA') {
		// add SA
		CDADModalMap.add_SA(this, surveyid, numid);

	} else if (type == 'location') {
		// add location
		CDADModalMap.add_LOCATION(this, numid);

		// set center and zoom
		this.map.setView([lat,lon], zoom);

		bounds[numid] = this.map.getBounds();

	} else {
		this.DETLAYER_style = L.geoJson(null, {
		    style: CDADModalMap.getStyleColorFor_DETLAYER,
		}).addTo(this.map);

		this.DETLAYER = omnivore.topojson(detlayer, null, this.DETLAYER_style)
			.on('ready', function() {
				console.log(this.getBounds());
				//bounds[numid] = .getBounds();
				//this.map.fitBounds(bounds[numid]);
		    });

		// set center and zoom
		//this.map.setView([lat,lon], zoom);

		//var southWest = L.latLng(42.257746, -83.295593);
		//var northEast = L.latLng(42.489061, -82.853394);
		//bounds[numid] = L.latLngBounds(southWest, northEast);
		//console.log(this.map.getZoom());

		//bounds[numid] = this.map.getBounds();

	}

}

CDADModalMap.add_LOCATION = function(sel, numid) {
	// define layer styles and oneachfeature popup styling
	sel.LOCATION = L.geoJson(locations, {
		pointToLayer: CDADModalMap.getStyleFor_LOCATION,
		filter: function(feature, layer) {
			if (feature.properties.counterId == numid) {
				return true;
			} else {
				return false;
			}
	    }
	});

	sel.map.addLayer(sel.LOCATION);
}

CDADModalMap.add_SA = function(sel, surveyid, numid) {
	$.ajax({
		type: "GET",
		url: "/getjsonformap/"+ surveyid +"/",
		success: function(data){
			// load the draw tools
			if (data) {
				var geojson = JSON.parse(data);

				sel.CDOBCLAYER = L.geoJson(geojson, {
			        style: CDADModalMap.getStyleColorFor_CDOBCLAYER,
			    });
			    sel.map.addLayer(sel.CDOBCLAYER);

			    // fit map to bounds of layer
				bounds[numid] = sel.CDOBCLAYER.getBounds();
				sel.map.fitBounds(bounds[numid]);

			}
        }
	});
}

CDADModalMap.getStyleFor_LOCATION = function(feature, latlng){
	var locationIcon = L.icon({
	    iconUrl: feature.properties.iconUrl,
	    iconSize: [24, 32],
		iconAnchor: [12, 30],
	});

	return L.marker(latlng, {icon: locationIcon});

}

CDADModalMap.getStyleColorFor_CDOBCLAYER = function (feature){
    return {
        weight: 2,
        opacity: 0.75,
        color: '#e8c51d',
        fillOpacity: 0.5,
        fill: '#e8c51d'
    }
}

CDADModalMap.getStyleColorFor_DETLAYER = function (feature){
    return {
        weight: 2,
        opacity: 1,
        color: '#252525',
        fillOpacity: 0
    }
}

<commit_msg>might work?<commit_after>/*
* Functions to create the mini modal maps
*/

// initialize map
function CDADModalMap(mapid, lat, lon, zoom, surveyid, type, numid) {

	//console.log(mapid);

    //where detroit is 42.377410, -83.093719
    this.map = new L.Map(mapid, {
		minZoom: 8,
		maxZoom: 16,
		attributionControl: false,
	});

	// add CartoDB tiles
	this.CartoDBLayer = L.tileLayer('http://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}.png');

	// add cartoDB tiles to start
	this.map.addLayer(this.CartoDBLayer);

	// create empty container for locations
	this.LOCATION = null;

	// create and empty container for detroit city boundary
	this.DETLAYER = null;
	this.CDOBCLAYER = null;

	if (type == 'locationAndSA') {
		// add location
		CDADModalMap.add_LOCATION(this, numid);

		// add SA
		CDADModalMap.add_SA(this, surveyid, numid);

	} else if (type == 'SA') {
		// add SA
		CDADModalMap.add_SA(this, surveyid, numid);

	} else if (type == 'location') {
		// add location
		CDADModalMap.add_LOCATION(this, numid);

		// set center and zoom
		this.map.setView([lat,lon], zoom);

		bounds[numid] = this.map.getBounds();

	} else {
		var sel = this;
		this.DETLAYER_style = L.geoJson(null, {
		    style: CDADModalMap.getStyleColorFor_DETLAYER,
		}).addTo(this.map);

		this.DETLAYER = omnivore.topojson(detlayer, null, this.DETLAYER_style)
			.on('ready', function() {
				bounds[numid] = this.getBounds();
				sel.map.fitBounds(bounds[numid]);
		    });

		// set center and zoom
		//this.map.setView([lat,lon], zoom);

		//var southWest = L.latLng(42.257746, -83.295593);
		//var northEast = L.latLng(42.489061, -82.853394);
		//bounds[numid] = L.latLngBounds(southWest, northEast);
		//console.log(this.map.getZoom());

		//bounds[numid] = this.map.getBounds();

	}

}

CDADModalMap.add_LOCATION = function(sel, numid) {
	// define layer styles and oneachfeature popup styling
	sel.LOCATION = L.geoJson(locations, {
		pointToLayer: CDADModalMap.getStyleFor_LOCATION,
		filter: function(feature, layer) {
			if (feature.properties.counterId == numid) {
				return true;
			} else {
				return false;
			}
	    }
	});

	sel.map.addLayer(sel.LOCATION);
}

CDADModalMap.add_SA = function(sel, surveyid, numid) {
	$.ajax({
		type: "GET",
		url: "/getjsonformap/"+ surveyid +"/",
		success: function(data){
			// load the draw tools
			if (data) {
				var geojson = JSON.parse(data);

				sel.CDOBCLAYER = L.geoJson(geojson, {
			        style: CDADModalMap.getStyleColorFor_CDOBCLAYER,
			    });
			    sel.map.addLayer(sel.CDOBCLAYER);

			    // fit map to bounds of layer
				bounds[numid] = sel.CDOBCLAYER.getBounds();
				sel.map.fitBounds(bounds[numid]);

			}
        }
	});
}

CDADModalMap.getStyleFor_LOCATION = function(feature, latlng){
	var locationIcon = L.icon({
	    iconUrl: feature.properties.iconUrl,
	    iconSize: [24, 32],
		iconAnchor: [12, 30],
	});

	return L.marker(latlng, {icon: locationIcon});

}

CDADModalMap.getStyleColorFor_CDOBCLAYER = function (feature){
    return {
        weight: 2,
        opacity: 0.75,
        color: '#e8c51d',
        fillOpacity: 0.5,
        fill: '#e8c51d'
    }
}

CDADModalMap.getStyleColorFor_DETLAYER = function (feature){
    return {
        weight: 2,
        opacity: 1,
        color: '#252525',
        fillOpacity: 0
    }
}

<|endoftext|>


<commit_before>"use strict";
/*
 * 不枝雀
 * 2017-4-5 22:38:04
 */
var cluster = require("cluster");
var message = require("../process/message");
if (cluster.isMaster && process.env.IN_DEBUG_MODE != "1") {
    var watch = require("../process/watch");
    var counter = 0;
    var killing;
    var quitting = [];
    var workers = [];
    var cpus = require('os').cpus();
    var count = require("../process/count");
    var counts = count() || {};
    global.counts = counts;
    var end = function () {
        quitting = quitting.concat(workers);
        workers = [];
        killing = true;
        exit();
    };
    var exit = function () {
        quitting.splice(0).forEach(function (worker) {
            worker.send("quit");
            var timeout = setTimeout(function () {
                worker.kill();
            }, 12000);
            worker.on("disconnect", function () {
                clearTimeout(timeout);
            });
        });
    };
    var broadcast = function (value) {
        var index = value.indexOf(":");
        var key = value.slice(0, index);
        var data = value.slice(index + 1);
        quitting.concat(workers).forEach(function (worker) {
            worker.send([key, data].join(":"));
        });
    };
    var run = function () {
        quitting = quitting.concat(workers);
        var workking = 0;
        workers = cpus.map(function () {
            counter++;
            var worker = cluster.fork();
            worker.on("listening", function () {
                console.info(`process ${worker.id} start at ${Date()}`);
                workking++;
                if (workking === cpus.length) {
                    exit();
                }
            });
            worker.on("exit", function () {
                if (worker.exitedAfterDisconnect !== true) {
                    for (var cx = workers.length - 1; cx >= 0; cx--) {
                        workers[cx] === worker && workers.splice(cx, 1);
                    }
                }
                counter--;
                console.info(`process ${worker.id} ended at ${Date()}`);
                if (!counter && killing) {
                    count(counts);
                    // console.info("按 ctrl + c 退出!");
                    process.exit();
                }
            });
            worker.on("message", message);
            return worker;
        });
    };
    watch("./", run);
    message.quit = end;
    message.broadcast = broadcast;
    process.on("SIGINT", end);
    process.on("SIGTERM", end);
    run();
} else {
    process.on("SIGINT", function () { });
    process.on("SIGTERM", function () { });

    //子线程们
    process.on("message", function (msg, then) {
        if (!(then instanceof Function)) {
            then = function () { };
        }
        switch (msg) {
            case "quit":
                server.close();
                then();
                process.exit();
                break;
            default:
                var index = msg.indexOf(":");
                if (index > 0) {
                    var key = msg.slice(0, index),
                        value = msg.slice(index + 1);

                } else {
                    var key = msg,
                        value = void 0;
                }
                var data = value ? JSON.parse(value) : void 0;
                if (key in message) message[key](data);
        }
    });
    // 仅做开发使用的简易服务器
    var http = require("http");
    var https = require("https");
    // build mime
    var doGet = require("./doGet");
    var doPost = require("./doPost");
    var doCross = require("./doCross");
    var doFile = require("./doFile");
    var requestListener = function (req, res) {
        var origin = req.headers.origin;
        origin && res.setHeader("Access-Control-Allow-Origin", origin);
        if (/^\/@/i.test(req.url)) {
            return doFile(req, res);
        }
        if (/^\/%7b/i.test(req.url)) {
            return doCross(req, res);
        }
        if (/^https?:\/\/[^\/]*\/%7b/i.test(req.headers.referer)) {
            return doCross(req, res, req.headers.referer);
        }
        if (req.headers.range) {
            return doFile(req, res);
        }
        var match = req.url.match(/ccon\/(.*?)\.([\da-f]+)\.png$/);
        if (match) {
            var name = match[1];
            var color = parseInt(match[2], 16);
            return res.end(doPost.ccon(name, color));
        }
        if (req.method === "GET") {
            if (SSL_ENABLED && req.socket.localPort === 80) {
                // 现代浏览器不会给http网站标记为不安全，并且火狐等浏览器对网站进行云检查以判断是否安全
                // 没有必要自动转向https，所以请让以下代码胎死腹中
                // if (req.headers["upgrade-insecure-requests"] && req.headers.host) {
                //     res.writeHead(302, { "Location": "https://" + req.headers.host + req.url });
                //     return res.end();
                // }
                // res.setHeader("Content-Security-Policy", "upgrade-insecure-requests");
            }
            return doGet(req, res);
        } else {
            return doPost(req, res);
        }
    };
    // create server
    var server = http.createServer(requestListener);
    server.on("error", function () {
        // console.info("server is already running!");
    });
    server.on("listening", function () {
        // console.info("server start success!");
    });
    server.setTimeout(0);
    server.listen(+process.env.HTTP_PORT || 80);
    var SSL_PFX_PATH = process.env["PATH.SSL_PFX"], SSL_ENABLED = false;
    if (SSL_PFX_PATH) {
        var fs = require("fs");
        if (fs.existsSync(SSL_PFX_PATH)) {
            https.createServer({
                pfx: fs.readFileSync(SSL_PFX_PATH),
                passphrase: process.env["PASSWORD.SSL_PFX"]
            }, requestListener).on("listening", function () {
                SSL_ENABLED = +process.env.IN_TEST_MODE === 1;
            }).on("error", function () {
                SSL_ENABLED = false;
            }).listen(+process.env.HTTPS_PORT || 443).setTimeout(0);
        }
    }
    process.title = `服务器地址：${require("../process/getLocalIP")()} 端口：${+process.env.HTTP_PORT || 80}`;

    cluster.isWorker && message.count("boot");
}<commit_msg>子进程的异常退出不再影响主进程<commit_after>"use strict";
/*
 * 不枝雀
 * 2017-4-5 22:38:04
 */
var cluster = require("cluster");
var message = require("../process/message");
if (cluster.isMaster && process.env.IN_DEBUG_MODE != "1") {
    var watch = require("../process/watch");
    var counter = 0;
    var killing;
    var quitting = [];
    var workers = [];
    var cpus = require('os').cpus();
    var count = require("../process/count");
    var counts = count() || {};
    global.counts = counts;
    var end = function () {
        quitting = quitting.concat(workers);
        workers = [];
        killing = true;
        exit();
    };
    var exit = function () {
        quitting.splice(0).forEach(function (worker) {
            worker.send("quit");
            var timeout = setTimeout(function () {
                worker.kill();
            }, 12000);
            worker.on("disconnect", function () {
                clearTimeout(timeout);
            });
        });
    };
    var broadcast = function (value) {
        var index = value.indexOf(":");
        var key = value.slice(0, index);
        var data = value.slice(index + 1);
        quitting.concat(workers).forEach(function (worker) {
            worker.send([key, data].join(":"));
        });
    };
    var run = function () {
        quitting = quitting.concat(workers);
        var workking = 0;
        workers = cpus.map(function () {
            counter++;
            var worker = cluster.fork();
            worker.on("listening", function () {
                console.info(`process ${worker.id} start at ${Date()}`);
                workking++;
                if (workking === cpus.length) {
                    exit();
                }
            });
            worker.on("exit", function () {
                if (worker.exitedAfterDisconnect !== true) {
                    for (var cx = workers.length - 1; cx >= 0; cx--) {
                        workers[cx] === worker && workers.splice(cx, 1);
                    }
                }
                counter--;
                console.info(`process ${worker.id} ended at ${Date()}`);
                if (!counter && killing) {
                    count(counts);
                    // console.info("按 ctrl + c 退出!");
                    process.exit();
                }
            });
            worker.on("message", message);
            return worker;
        });
    };
    watch("./", run);
    message.quit = end;
    message.broadcast = broadcast;
    process.on("SIGINT", end);
    process.on("SIGTERM", end);
    run();
} else {
    process.on("SIGINT", function () { });
    process.on("SIGTERM", function () { });
    process.on("uncaughtException", process.exit);
    process.on("unhandledRejection", process.exit);

    //子线程们
    process.on("message", function (msg, then) {
        if (!(then instanceof Function)) {
            then = function () { };
        }
        switch (msg) {
            case "quit":
                server.close();
                then();
                process.exit();
                break;
            default:
                var index = msg.indexOf(":");
                if (index > 0) {
                    var key = msg.slice(0, index),
                        value = msg.slice(index + 1);

                } else {
                    var key = msg,
                        value = void 0;
                }
                var data = value ? JSON.parse(value) : void 0;
                if (key in message) message[key](data);
        }
    });
    // 仅做开发使用的简易服务器
    var http = require("http");
    var https = require("https");
    // build mime
    var doGet = require("./doGet");
    var doPost = require("./doPost");
    var doCross = require("./doCross");
    var doFile = require("./doFile");
    var requestListener = function (req, res) {
        var origin = req.headers.origin;
        origin && res.setHeader("Access-Control-Allow-Origin", origin);
        if (/^\/@/i.test(req.url)) {
            return doFile(req, res);
        }
        if (/^\/%7b/i.test(req.url)) {
            return doCross(req, res);
        }
        if (/^https?:\/\/[^\/]*\/%7b/i.test(req.headers.referer)) {
            return doCross(req, res, req.headers.referer);
        }
        if (req.headers.range) {
            return doFile(req, res);
        }
        var match = req.url.match(/ccon\/(.*?)\.([\da-f]+)\.png$/);
        if (match) {
            var name = match[1];
            var color = parseInt(match[2], 16);
            return res.end(doPost.ccon(name, color));
        }
        if (req.method === "GET") {
            if (SSL_ENABLED && req.socket.localPort === 80) {
                // 现代浏览器不会给http网站标记为不安全，并且火狐等浏览器对网站进行云检查以判断是否安全
                // 没有必要自动转向https，所以请让以下代码胎死腹中
                // if (req.headers["upgrade-insecure-requests"] && req.headers.host) {
                //     res.writeHead(302, { "Location": "https://" + req.headers.host + req.url });
                //     return res.end();
                // }
                // res.setHeader("Content-Security-Policy", "upgrade-insecure-requests");
            }
            return doGet(req, res);
        } else {
            return doPost(req, res);
        }
    };
    // create server
    var server = http.createServer(requestListener);
    server.on("error", function () {
        // console.info("server is already running!");
    });
    server.on("listening", function () {
        // console.info("server start success!");
    });
    server.setTimeout(0);
    server.listen(+process.env.HTTP_PORT || 80);
    var SSL_PFX_PATH = process.env["PATH.SSL_PFX"], SSL_ENABLED = false;
    if (SSL_PFX_PATH) {
        var fs = require("fs");
        if (fs.existsSync(SSL_PFX_PATH)) {
            https.createServer({
                pfx: fs.readFileSync(SSL_PFX_PATH),
                passphrase: process.env["PASSWORD.SSL_PFX"]
            }, requestListener).on("listening", function () {
                SSL_ENABLED = +process.env.IN_TEST_MODE === 1;
            }).on("error", function () {
                SSL_ENABLED = false;
            }).listen(+process.env.HTTPS_PORT || 443).setTimeout(0);
        }
    }
    process.title = `服务器地址：${require("../process/getLocalIP")()} 端口：${+process.env.HTTP_PORT || 80}`;

    cluster.isWorker && message.count("boot");
}<|endoftext|>


<commit_before>import * as _ from "underscore";
import { SourceNode } from "source-map";
import { hash } from "./utils";

function header(data, h) {
	if (_.isArray(data.headers) && !_.contains(data.headers, h)) {
		data.headers.push(h);
	}
}

function query(data, q) {
	let s = JSON.stringify(q);
	let v = ("q" + hash(s)).replace("-", "_");
	header(data, `var ${v} = ${s};\n`);
	return `ctx.query(${v})`;
}

export class ASTNode {
	constructor(location) {
		this._location = location;
	}

	_sn(file, chunk) {
		let loc = this._location, line, column;

		if (loc) {
			line = loc.start.line;
			column = loc.start.column;
		}

		return new SourceNode(line, column, file, chunk);
	}

	start(data) {
		this._writer = {
			chunks: [],
			data: data
		};

		return this;
	}

	indent() {
		var d = this._writer.data;
		if (typeof d.indent !== "number") d.indent = 0;
		d.indent++;
		return this;
	}

	outdent() {
		var d = this._writer.data;
		if (typeof d.indent !== "number") d.indent = 0;
		if (d.indent > 0) d.indent--;
		return this;
	}

	write(chunk) {
		let tabs = "";
		let tabchar = this._writer.data.tabchar;
		let indent = this._writer.data.indent || 0;
		if (tabchar == null) tabchar = "  ";

		for (let i = 0; i < indent; i++) tabs += tabchar;
		this.push([].concat(tabs, chunk, "\n"));

		return this;
	}

	push(chunk) {
		this._writer.chunks.push(chunk);
		return this;
	}

	end(chunk) {
		if (chunk) this.write(chunk);
		var w = this._writer;
		delete this._writer;
		return this._sn(w.data.originalFilename, w.chunks);
	}

	compile(data) {
		// throw new Error("Not implemented.");
		return this._sn(data.originalFilename);
	}

	compileString(data) {
		// throw new Error("Not implemented.");
		return this._sn(data.originalFilename);
	}

	compileArguments(data) {
		// throw new Error("Not implemented.");
		return this._sn(data.originalFilename);
	}
}

export class Root extends ASTNode {
	constructor(location, children) {
		super(location);
		this._children = children;
	}

	compile(data) {
		var oheads = data.headers;
		data.headers = [];

		this.start(data);
		header(data, "var Views = {};\n");
		this.push(_.invoke(this._children, "compile", data));

		if (data.exports === "common") {
			this.write("module.exports = Views;");
		} else {
			this.write("return Views;");
		}

		let output = this.end();
		if (data.headers.length) output.prepend("\n").prepend(data.headers);
		data.headers = oheads;

		return output;
	}
}

export class View extends ASTNode {
	constructor(location, name, exts, attrs, partials, scripts, children) {
		super(location);
		this._name = name;
		this._extends = exts;
		this._attributes = attrs;
		this._partials = partials;
		this._scripts = scripts;
		this._children = children;
	}

	compile(data) {
		this.start(data);
		var safename = JSON.stringify(this._name);

		this.write(`Views[${safename}] = Temple.register(${safename}, {`);
		this.indent();

		if (this._scripts.length || this._attributes.length) {
			this.write("initialize: function() {").indent();
			this.write("this.super.apply(this, arguments);");
			if (this._attributes.length) {
				this.write(`this.on("render:before", function(ctx) {`).indent();
				this.push(_.invoke(this._attributes, "compile", data));
				this.outdent().write(`});`);
			}
			this.push(_.invoke(this._scripts, "compile", data));
			this.outdent().write("},");
		}

		if (this._partials.length) {
			this.write("partials: {").indent();
			var p = _.invoke(this._partials, "compile", data);
			this.push(this._sn(data.originalFilename, p).join(",\n"));
			this.outdent().write("},");
		}

		if (this._extends) {
			this.write(`extends: ${JSON.stringify(this._extends)},`);
		}

		this.write("render: function(ctx) {").indent();
		// this.push(_.invoke(this._attributes, "compile", _.defaults({ element: "this.el" }, data)));
		this.push(_.invoke(this._children, "compile", data));
		this.outdent().write("}");

		this.outdent().write("});\n");

		return this.end();
	}
}

export class Text extends ASTNode {
	constructor(location, value) {
		super(location);
		this._value = value;
	}

	compile(data) {
		this.start(data);
		this.write(`Temple.idom.text(${JSON.stringify(this._value)});`);
		return this.end();
	}

	compileString(data) {
		return this._sn(data.originalFilename, JSON.stringify(this._value));
	}
}

export class HTMLComment extends ASTNode {
	constructor(location, value) {
		super(location);
		this._value = value;
	}
}

export class Script extends ASTNode {
	constructor(location, value) {
		super(location);
		this._value = value;
	}

	compile(data) {
		return this._sn(data.originalFilename, this._value);
	}
}

export class Element extends ASTNode {
	constructor(location, name, attrs, children) {
		super(location);
		this._name = name;
		this._attributes = attrs;
		this._children = children;
	}

	compile(data) {
		this.start(data);

		let self = this;
		let tagName = JSON.stringify(this._name);
		let hasc = this._children.length;
		let hasa = this._attributes.length;

		function writeElement(inner) {
			if (hasc || hasa) {
				self.write(`Temple.idom.elementOpen(${tagName});`);//${key ? "," + JSON.stringify(key) : ""}
				inner.call(self);
				self.write(`Temple.idom.elementClose(${tagName});`);
			} else {
				self.write(`Temple.idom.elementVoid(${tagName});`);
			}
		}

		if (this._name.indexOf("-") > -1) {
			this.write(`(function(){`).indent();

			if (hasc) {
				this.write("function body(ctx) {").indent();
				this.push(_.invoke(this._children, "compile", data));
				this.outdent().write("}");
			}

			if (hasa) {
				this.write("function attributes(ctx) {").indent();
				this.push(_.invoke(this._attributes, "compile", data));
				this.outdent().write("}");
			}

			this.write(`var self = this;`);
			this.write(`var view = this.createComponent(${tagName}, ctx);`);
			this.write(`if (view) {`).indent();
			if (hasc) this.write(`view.setPartial("@body", body);`);
			if (hasa) this.write(`view.on("render:before", attributes);`);
			this.write(`view.mount();`);
			this.write(`this.comp.onInvalidate(this.removeComponent.bind(this, view));`);
			this.outdent().write(`} else {`).indent();
			writeElement(function() {
				if (hasa) this.write(`attributes(ctx);`);
				if (hasc) this.write(`body(ctx);`);
			});
			this.outdent().write(`}`);

			this.outdent().write(`}).call(this);`);
		} else {
			writeElement(function() {
				if (hasa) this.push(_.invoke(this._attributes, "compile", data));
				if (hasc) this.push(_.invoke(this._children, "compile", data));
			});
		}

		return this.end();
	}
}

export class Attribute extends ASTNode {
	constructor(location, key, value, children, args) {
		super(location);
		this._key = key;
		this._value = value;
		this._children = children;
		this._arguments = args;
	}

	compile(data) {
		this.start(data);

		this.write(`this.renderDecorator(this, ${JSON.stringify(this._key)}, {`).indent();
		this.write(`mixin: { context: ctx },`);

		let str = _.invoke(this._children, "compileString", data);
		this.write([
			`string: function() { return `,
			this._sn(data.originalFilename, str).join(" + "),
			`; },`
		]);

		let args = _.invoke(this._arguments, "compileArguments", data);
		this.write([
			`"arguments": function() { return [ `,
			this._sn(data.originalFilename, args).join(", "),
			` ]; }`
		]);

		this.outdent().write(`});`);

		return this.end();
	}
}

export class Literal extends ASTNode {
	constructor(location, value) {
		super(location);
		this._value = value;
	}

	compileArguments(data) {
		return this._sn(data.originalFilename, JSON.stringify(this._value));
	}
}

export class Section extends ASTNode {
	constructor(location, inverted, query, children) {
		super(location);
		this._inverted = inverted;
		this._query = query;
		this._children = children;
	}

	compile(data) {
		this.start(data);

		let self = this;

		function renderSection(v, i) {
			if (i) self.write(`var indexctx = new Temple.Context({ "@index": ${i} }, prevctx, { transparent: true });`);
			self.write(`var ctx = new Temple.Context(${v}, ${i ? "indexctx" : "prevctx"});`);
			self.push(_.invoke(self._children, "compile", data));
		}

		this.write("(function(){").indent();
		this.write("var prevctx = ctx;");
		this.write(`var val = ${query(data, this._query)};`);
		this.write(`var proxy = Temple.proxies.getByTarget(val, [ "empty", "section" ]);`);
		let isEmpty = `Boolean(Temple.proxies.run(proxy, "empty", val))`;

		if (this._inverted) {
			this.write(`if (${isEmpty}) {`).indent();
			this.write("(function(){").indent();
			renderSection("val");
			this.outdent().write("}).call(this);");
			this.outdent().write("}");
		} else {
			this.write(`if (!${isEmpty}) {`).indent();
			this.write(`Temple.proxies.run(proxy, "section", val, (function(data, index) {`).indent();
			renderSection("data", "index");
			this.outdent().write(`}).bind(this));`);
			this.outdent().write(`}`);
		}

		this.outdent().write("}).call(this);");

		return this.end();
	}
}

export class Interpolator extends ASTNode {
	constructor(location, escaped, query) {
		super(location);
		this._escaped = escaped;
		this._query = query;
	}

	query(data) { return query(data, this._query); }

	compile(data) {
		this.start(data);
		var src, q = this.query(data);
		if (this._escaped) src = `Temple.idom.html(${q});`;
		else src = `Temple.idom.text(utils.toString(${q}));`;
		return this.end(src);
	}

	compileString(data) {
		return this._sn(data.originalFilename, `Temple.utils.toString(${this.query(data)})`);
	}

	compileArguments(data) {
		return this._sn(data.originalFilename, this.query(data));
	}
}

export class MustacheComment extends ASTNode {
	constructor(location, value) {
		super(location);
		this._value = value;
	}

	compile(data) {
		var output = this._sn(data.originalFilename);
		this._value.split("\n").forEach(function(l) {
			output.add(["// ", l, "\n"]);
		});
		return output;
	}
}

export class PartialQuery extends ASTNode {
	constructor(location, local, value) {
		super(location);
		this._local = local;
		this._value = value;
	}

	compile(data) {
		this.start(data);

		if (this._value === "@super") {
			this.write(`this.super(ctx);`);
		} else {
			this.write(`this.renderPartial(${JSON.stringify(this._value)}, ctx, {`).indent();
			this.write(`local: ${JSON.stringify(this._local)}`);
			this.outdent().write(`});`);
		}

		return this.end();
	}
}

export class Partial extends ASTNode {
	constructor(location, name, children) {
		super(location);
		this._name = name;
		this._children = children;
	}

	compile(data) {
		this.start(data);

		this.write(`${JSON.stringify(this._name)}: function(ctx) {`).indent();
		this.write(_.invoke(this._children, "compile", data));
		this.outdent().write("}");

		return this.end();
	}
}
<commit_msg>added section support to attributes<commit_after>import * as _ from "underscore";
import { SourceNode } from "source-map";
import { hash } from "./utils";

function header(data, h) {
	if (_.isArray(data.headers) && !_.contains(data.headers, h)) {
		data.headers.push(h);
	}
}

function query(data, q) {
	let s = JSON.stringify(q);
	let v = ("q" + hash(s)).replace("-", "_");
	header(data, `var ${v} = ${s};\n`);
	return `ctx.query(${v})`;
}

export class ASTNode {
	constructor(location) {
		this._location = location;
	}

	_sn(file, chunk) {
		let loc = this._location, line, column;

		if (loc) {
			line = loc.start.line;
			column = loc.start.column;
		}

		return new SourceNode(line, column, file, chunk);
	}

	start(data) {
		this._writer = {
			chunks: [],
			data: data
		};

		return this;
	}

	indent() {
		var d = this._writer.data;
		if (typeof d.indent !== "number") d.indent = 0;
		d.indent++;
		return this;
	}

	outdent() {
		var d = this._writer.data;
		if (typeof d.indent !== "number") d.indent = 0;
		if (d.indent > 0) d.indent--;
		return this;
	}

	tabs() {
		let tabs = "";
		let tabchar = this._writer.data.tabchar;
		let indent = this._writer.data.indent || 0;
		if (tabchar == null) tabchar = "  ";
		for (let i = 0; i < indent; i++) tabs += tabchar;
		return tabs;
	}

	write(chunk) {
		this.push([].concat(this.tabs(), chunk, "\n"));
		return this;
	}

	push(chunk) {
		this._writer.chunks.push(chunk);
		return this;
	}

	end(chunk) {
		if (chunk) this.write(chunk);
		var w = this._writer;
		delete this._writer;
		return this._sn(w.data.originalFilename, w.chunks);
	}

	compile(data) {
		// throw new Error("Not implemented.");
		return this._sn(data.originalFilename);
	}

	compileString(data) {
		// throw new Error("Not implemented.");
		return this._sn(data.originalFilename);
	}

	compileArguments(data) {
		// throw new Error("Not implemented.");
		return this._sn(data.originalFilename);
	}
}

export class Root extends ASTNode {
	constructor(location, children) {
		super(location);
		this._children = children;
	}

	compile(data) {
		var oheads = data.headers;
		data.headers = [];

		this.start(data);
		header(data, "var Views = {};\n");
		this.push(_.invoke(this._children, "compile", data));

		if (data.exports === "common") {
			this.write("module.exports = Views;");
		} else {
			this.write("return Views;");
		}

		let output = this.end();
		if (data.headers.length) output.prepend("\n").prepend(data.headers);
		data.headers = oheads;

		return output;
	}
}

export class View extends ASTNode {
	constructor(location, name, exts, attrs, partials, scripts, children) {
		super(location);
		this._name = name;
		this._extends = exts;
		this._attributes = attrs;
		this._partials = partials;
		this._scripts = scripts;
		this._children = children;
	}

	compile(data) {
		this.start(data);
		var safename = JSON.stringify(this._name);

		this.write(`Views[${safename}] = Temple.register(${safename}, {`);
		this.indent();

		if (this._scripts.length || this._attributes.length) {
			this.write("initialize: function() {").indent();
			this.write("this.super.apply(this, arguments);");
			if (this._attributes.length) {
				this.write(`this.on("render:before", function(ctx) {`).indent();
				this.push(_.invoke(this._attributes, "compile", data));
				this.outdent().write(`});`);
			}
			this.push(_.invoke(this._scripts, "compile", data));
			this.outdent().write("},");
		}

		if (this._partials.length) {
			this.write("partials: {").indent();
			var p = _.invoke(this._partials, "compile", data);
			this.push(this._sn(data.originalFilename, p).join(",\n"));
			this.outdent().write("},");
		}

		if (this._extends) {
			this.write(`extends: ${JSON.stringify(this._extends)},`);
		}

		this.write("render: function(ctx) {").indent();
		this.push(_.invoke(this._children, "compile", data));
		this.outdent().write("}");

		this.outdent().write("});\n");

		return this.end();
	}
}

export class Text extends ASTNode {
	constructor(location, value) {
		super(location);
		this._value = value;
	}

	compile(data) {
		this.start(data);
		this.write(`Temple.idom.text(${JSON.stringify(this._value)});`);
		return this.end();
	}

	compileString(data) {
		return this._sn(data.originalFilename, JSON.stringify(this._value));
	}
}

export class HTMLComment extends ASTNode {
	constructor(location, value) {
		super(location);
		this._value = value;
	}
}

export class Script extends ASTNode {
	constructor(location, value) {
		super(location);
		this._value = value;
	}

	compile(data) {
		return this._sn(data.originalFilename, this._value);
	}
}

export class Element extends ASTNode {
	constructor(location, name, attrs, children) {
		super(location);
		this._name = name;
		this._attributes = attrs;
		this._children = children;
	}

	compile(data) {
		this.start(data);

		let self = this;
		let tagName = JSON.stringify(this._name);
		let hasc = this._children.length;
		let hasa = this._attributes.length;

		function writeElement(inner) {
			if (hasc || hasa) {
				self.write(`Temple.idom.elementOpen(${tagName});`);//${key ? "," + JSON.stringify(key) : ""}
				inner.call(self);
				self.write(`Temple.idom.elementClose(${tagName});`);
			} else {
				self.write(`Temple.idom.elementVoid(${tagName});`);
			}
		}

		if (this._name.indexOf("-") > -1) {
			this.write(`(function(){`).indent();

			if (hasc) {
				this.write("function body(ctx) {").indent();
				this.push(_.invoke(this._children, "compile", data));
				this.outdent().write("}");
			}

			if (hasa) {
				this.write("function attributes(ctx) {").indent();
				this.push(_.invoke(this._attributes, "compile", data));
				this.outdent().write("}");
			}

			this.write(`var self = this;`);
			this.write(`var view = this.createComponent(${tagName}, ctx);`);
			this.write(`if (view) {`).indent();
			if (hasc) this.write(`view.setPartial("@body", body);`);
			if (hasa) this.write(`view.on("render:before", attributes);`);
			this.write(`view.mount();`);
			this.write(`this.comp.onInvalidate(this.removeComponent.bind(this, view));`);
			this.outdent().write(`} else {`).indent();
			writeElement(function() {
				if (hasa) this.write(`attributes(ctx);`);
				if (hasc) this.write(`body(ctx);`);
			});
			this.outdent().write(`}`);

			this.outdent().write(`}).call(this);`);
		} else {
			writeElement(function() {
				if (hasa) this.push(_.invoke(this._attributes, "compile", data));
				if (hasc) this.push(_.invoke(this._children, "compile", data));
			});
		}

		return this.end();
	}
}

export class Attribute extends ASTNode {
	constructor(location, key, value, children, args) {
		super(location);
		this._key = key;
		this._value = value;
		this._children = children;
		this._arguments = args;
	}

	compile(data) {
		this.start(data);

		this.write(`this.renderDecorator(this, ${JSON.stringify(this._key)}, {`).indent();
		this.write(`mixin: { context: ctx },`);

		let str = _.invoke(this._children, "compileString", data);
		this.write([
			`string: function() { return `,
			this._sn(data.originalFilename, str).join(" + "),
			`; },`
		]);

		let args = _.invoke(this._arguments, "compileArguments", data);
		this.write([
			`"arguments": function() { return [ `,
			this._sn(data.originalFilename, args).join(", "),
			` ]; }`
		]);

		this.outdent().write(`});`);

		return this.end();
	}
}

export class Literal extends ASTNode {
	constructor(location, value) {
		super(location);
		this._value = value;
	}

	compileArguments(data) {
		return this._sn(data.originalFilename, JSON.stringify(this._value));
	}
}

export class Section extends ASTNode {
	constructor(location, inverted, query, children) {
		super(location);
		this._inverted = inverted;
		this._query = query;
		this._children = children;
	}

	compile(data) {
		this.start(data);

		this.write("(function(){").indent();

		this.compileSection(data, function() {
			this.push(_.invoke(this._children, "compile", data));
		});

		this.outdent().write("}).call(this);");

		return this.end();
	}

	compileString(data) {
		this.start(data);

		this.push("(function() {\n").indent();
		this.write(`var result = "";`);

		this.compileSection(data, function() {
			let children = _.invoke(this._children, "compileString", data);
			this.write([ "result += ", this._sn(data.originalFilename, children).join(" + "), ";" ]);
		});

		this.write("return result;");
		this.outdent().push(this.tabs() + "}).call(this)");

		return this.end();
	}

	compileSection(data, handle) {
		let self = this;

		function renderSection(v, i) {
			if (i) self.write(`var indexctx = new Temple.Context({ "@index": ${i} }, prevctx, { transparent: true });`);
			self.write(`var ctx = new Temple.Context(${v}, ${i ? "indexctx" : "prevctx"});`);
			handle.call(self);
		}

		this.write("var prevctx = ctx;");
		this.write(`var val = ${query(data, this._query)};`);
		this.write(`var proxy = Temple.proxies.getByTarget(val, [ "empty", "section" ]);`);
		let isEmpty = `Boolean(Temple.proxies.run(proxy, "empty", val))`;

		if (this._inverted) {
			this.write(`if (${isEmpty}) {`).indent();
			this.write("(function(){").indent();
			renderSection("val");
			this.outdent().write("}).call(this);");
			this.outdent().write("}");
		} else {
			this.write(`if (!${isEmpty}) {`).indent();
			this.write(`Temple.proxies.run(proxy, "section", val, (function(data, index) {`).indent();
			renderSection("data", "index");
			this.outdent().write(`}).bind(this));`);
			this.outdent().write(`}`);
		}
	}
}

export class Interpolator extends ASTNode {
	constructor(location, escaped, query) {
		super(location);
		this._escaped = escaped;
		this._query = query;
	}

	query(data) { return query(data, this._query); }

	compile(data) {
		this.start(data);
		var src, q = this.query(data);
		if (this._escaped) src = `Temple.idom.html(${q});`;
		else src = `Temple.idom.text(utils.toString(${q}));`;
		return this.end(src);
	}

	compileString(data) {
		return this._sn(data.originalFilename, `Temple.utils.toString(${this.query(data)})`);
	}

	compileArguments(data) {
		return this._sn(data.originalFilename, this.query(data));
	}
}

export class MustacheComment extends ASTNode {
	constructor(location, value) {
		super(location);
		this._value = value;
	}

	compile(data) {
		var output = this._sn(data.originalFilename);
		this._value.split("\n").forEach(function(l) {
			output.add(["// ", l, "\n"]);
		});
		return output;
	}
}

export class PartialQuery extends ASTNode {
	constructor(location, local, value) {
		super(location);
		this._local = local;
		this._value = value;
	}

	compile(data) {
		this.start(data);

		if (this._value === "@super") {
			this.write(`this.super(ctx);`);
		} else {
			this.write(`this.renderPartial(${JSON.stringify(this._value)}, ctx, {`).indent();
			this.write(`local: ${JSON.stringify(this._local)}`);
			this.outdent().write(`});`);
		}

		return this.end();
	}
}

export class Partial extends ASTNode {
	constructor(location, name, children) {
		super(location);
		this._name = name;
		this._children = children;
	}

	compile(data) {
		this.start(data);

		this.write(`${JSON.stringify(this._name)}: function(ctx) {`).indent();
		this.write(_.invoke(this._children, "compile", data));
		this.outdent().write("}");

		return this.end();
	}
}
<|endoftext|>


<commit_before>var env = process.env;
var clone = engine.clone;

// save caches
var caches = {};

module.exports = factory;

function factory (name, checkRole) {

    // return existing cache
    if (caches[name]) {
        return caches[name];
    }

    // clone cache class
    var cache = clone(Cache);

    // create data container
    cache._data = {};

    // check role access
    cache._roleCheck = checkRole;

    // save cache
    caches[name] = cache;

    return cache;
}

// FileCache
var Cache = {

    // remove one or all item(s)
    rm: function (key, role) {

        // remove one item
        if (key) {

            // return if key does not exists
            if (this._data[key] === undefined) {
                return;
            }

            // check role access
            if (this._roleCheck && !checkRoleAccess(this._data[key], role)) {
                return 0;
            }

            return delete this._data[key];
        }

        // remove all items
        this._data = {};
    },

    // return one or all item(s)
    get: function (key, role) {

        // return one item
        if (key) {

            // return if key does not exists
            if (this._data[key] === undefined) {
                return;
            }

            // check role access
            if (this._roleCheck && !checkRoleAccess(this._data[key], role)) {
                return 0;
            }

            return this._data[key];
        }

        // return all items
        return this._data;
    },

    // set an item
    set: function (key, data) {

        if (key) {
            this._data[key] = data;
        }
    }
};

function checkRoleAccess (item, role) {

    if (item._roles['*'] || (item._roles && item._roles[role])) {
        return true;
    }
}
<commit_msg>added documentation, clean up<commit_after>// cache data
var caches = {};

/**
 * The object cache factory.
 *
 * @public
 * @param {string} The unique file cache name.
 * @param {boolean} Check role or not.
 */
module.exports = function factory (name, checkRole) {

    // return existing cache
    if (caches[name]) {
        return caches[name];
    }

    // clone cache class
    var cache = engine.clone(Cache);

    // create data container
    cache._data = {};

    // check role access
    cache._roleCheck = checkRole;

    // save cache
    caches[name] = cache;

    return cache;
};

/**
 * The object cache class.
 *
 * @class Cache
 */
var Cache = {

    /**
     * Remove an object, or with no argument empty the cache.
     *
     * @public
     * @param {string} The file path.
     */
    rm: function (key, role) {

        // remove one item
        if (key) {

            // return if key does not exists
            if (this._data[key] === undefined) {
                return;
            }

            // check role access
            if (this._roleCheck && !checkRoleAccess(this._data[key], role)) {
                return 0;
            }

            return delete this._data[key];
        }

        // remove all items
        this._data = {};
    },

    /**
     * Get an object, or get all objects in the cache.
     *
     * @public
     * @param {string} The file path.
     */
    get: function (key, role) {

        // return one item
        if (key) {

            // return if key does not exists
            if (this._data[key] === undefined) {
                return;
            }

            // check role access
            if (this._roleCheck && !checkRoleAccess(this._data[key], role)) {
                return 0;
            }

            return this._data[key];
        }

        // return all items
        return this._data;
    },

     /**
     * Save an object in the cache.
     *
     * @public
     * @param {string} The object name.
     * @param {object} The data object.
     */
    set: function (key, data) {

        if (key) {
            this._data[key] = data;
        }
    }
};

/**
 * Check the role access for a cache item.
 *
 * @private
 * @param {object} The cached item.
 * @param {string} The role name.
 */
function checkRoleAccess (item, role) {

    if (item._roles['*'] || (item._roles && item._roles[role])) {
        return true;
    }
}
<|endoftext|>