<commit_before>var urllib = require('url');

var Boom = require('boom');
var Hapi = require('hapi');
var Joi = require('joi');

var cheerio = require('cheerio');
var Prom = require('es6-promise').Promise;
var request = require('request');

var settings = require('../settings');

var MANIFEST_KEYS_WITH_URLS = ['src', 'start_url'];
var NODE_ENV = process.env.NODE_ENVIRONMENT || 'development';

var _processDocument = function (response) {

  var $ = cheerio.load(response.body);
  var manifests = $('[rel=manifest]');

  if (!manifests.length) {
    return Prom.reject(new Error('Could not find `link[rel=manifest]` tag'));
  }

  var manifestUrl = manifests.eq(0).attr('href');
  var manifestUrlAbsolute = urllib.resolve(response.request.href, manifestUrl);

  return fetchManifest(manifestUrlAbsolute);
};

var _processManifest = function (response) {

  return new Prom(function (resolve, reject) {

    var recursiveTransformer = function (key, value) {
      // Resolve any relative URLs (the base URL being the manifest path).
      if (response.request && response.request.href &&
          typeof value === 'string' &&
          MANIFEST_KEYS_WITH_URLS.indexOf(key) !== -1 &&
          value.substr(0, 5) !== 'data:') {

        return urllib.resolve(response.request.href, value);
      }

      // Otherwise, leave the value untouched.
      return value;
    };

    var data = {};

    try {
      data = JSON.parse(response.body, recursiveTransformer);
    } catch (e) {
      return reject(new Error('String could not be parsed as JSON: ' +
                              e.message));
    }

    resolve(data);
  });
};

var _fetch = function (data) {

  return new Prom(function (resolve, reject) {

    request.get(data, function (err, response) {
      if (err) {
        reject(err);
      } else {
        resolve(response);
      }
    });
  });
};

var fetchManifest = module.exports.fetchManifest = function (data) {

  if (typeof data === 'string' &&
      (data.substr(0, 5) === 'http:' || data.substr(0, 6) === 'https:')) {

    return _fetch(data).then(function (response) {
      if (response.statusCode !== 200) {
        return Prom.reject(new Error('Unexpected response code: ' +
                                     response.statusCode));
      }

      var contentType = response.headers['content-type'];

      if (contentType.indexOf('text/html') !== -1) {
        return _processDocument(response);

      } else if (contentType.indexOf('/json') !== -1) {
        return _processManifest(response);

      } else {
        return Prom.reject(new Error('Unexpected response Content-Type: ' +
                                     contentType));

      }
    });
  }

  return _processManifest({body: data});
};

var createServer = module.exports.createServer = function (opts) {

  opts = opts || {};

  if (!opts.server) {
    opts.server = new Hapi.Server();

    opts.server.connection({
      host: settings.HOST,
      port: settings.PORT,
      routes: {
        cors: settings.CORS,
        validate: {
          options: {
            abortEarly: false
          }
        }
      }
    });

    // Do not start the server when this script is required by another script.
    opts.server.start(function () {
      console.log('[%s] Listening on %s', NODE_ENV, opts.server.info.uri);
    });
  }

  var fetchHandler = {
    validate: {
      query: {
        url: Joi.string().regex(/^https?:\/\//i).required()
                .example('http://example.com/')
      }
    },
    handler: function (request, reply) {
      fetchManifest(request.query.url)
      .then(reply)
      .catch(function (err) {
        reply(Boom.badRequest(err.message));
      });
    }
  };

  opts.server.route({
    method: 'GET', path: '/manifest', config: fetchHandler
  });

  return opts.server;
};
<commit_msg>fix content-type check for application/manifest+json<commit_after>var urllib = require('url');

var Boom = require('boom');
var Hapi = require('hapi');
var Joi = require('joi');

var cheerio = require('cheerio');
var Prom = require('es6-promise').Promise;
var request = require('request');

var settings = require('../settings');

var MANIFEST_KEYS_WITH_URLS = ['src', 'start_url'];
var NODE_ENV = process.env.NODE_ENVIRONMENT || 'development';

var _processDocument = function (response) {

  var $ = cheerio.load(response.body);
  var manifests = $('[rel=manifest]');

  if (!manifests.length) {
    return Prom.reject(new Error('Could not find `link[rel=manifest]` tag'));
  }

  var manifestUrl = manifests.eq(0).attr('href');
  var manifestUrlAbsolute = urllib.resolve(response.request.href, manifestUrl);

  return fetchManifest(manifestUrlAbsolute);
};

var _processManifest = function (response) {

  return new Prom(function (resolve, reject) {

    var recursiveTransformer = function (key, value) {
      // Resolve any relative URLs (the base URL being the manifest path).
      if (response.request && response.request.href &&
          typeof value === 'string' &&
          MANIFEST_KEYS_WITH_URLS.indexOf(key) !== -1 &&
          value.substr(0, 5) !== 'data:') {

        return urllib.resolve(response.request.href, value);
      }

      // Otherwise, leave the value untouched.
      return value;
    };

    var data = {};

    try {
      data = JSON.parse(response.body, recursiveTransformer);
    } catch (e) {
      return reject(new Error('String could not be parsed as JSON: ' +
                              e.message));
    }

    resolve(data);
  });
};

var _fetch = function (data) {

  return new Prom(function (resolve, reject) {

    request.get(data, function (err, response) {
      if (err) {
        reject(err);
      } else {
        resolve(response);
      }
    });
  });
};

var fetchManifest = module.exports.fetchManifest = function (data) {

  if (typeof data === 'string' &&
      (data.substr(0, 5) === 'http:' || data.substr(0, 6) === 'https:')) {

    return _fetch(data).then(function (response) {
      if (response.statusCode !== 200) {
        return Prom.reject(new Error('Unexpected response code: ' +
                                     response.statusCode));
      }

      var contentType = response.headers['content-type'];

      if (contentType.indexOf('text/html') !== -1) {
        return _processDocument(response);

      } else if (contentType.indexOf('/json') !== -1 ||
                 contentType.indexOf('+json') !== -1) {
        return _processManifest(response);

      } else {
        return Prom.reject(
          new Error('Unexpected response Content-Type: ' + contentType)
        );

      }
    });
  }

  return _processManifest({body: data});
};

var createServer = module.exports.createServer = function (opts) {

  opts = opts || {};

  if (!opts.server) {
    opts.server = new Hapi.Server();

    opts.server.connection({
      host: settings.HOST,
      port: settings.PORT,
      routes: {
        cors: settings.CORS,
        validate: {
          options: {
            abortEarly: false
          }
        }
      }
    });

    // Do not start the server when this script is required by another script.
    opts.server.start(function () {
      console.log('[%s] Listening on %s', NODE_ENV, opts.server.info.uri);
    });
  }

  var fetchHandler = {
    validate: {
      query: {
        url: Joi.string().regex(/^https?:\/\//i).required()
                .example('http://example.com/')
      }
    },
    handler: function (request, reply) {
      fetchManifest(request.query.url)
      .then(reply)
      .catch(function (err) {
        reply(Boom.badRequest(err.message));
      });
    }
  };

  opts.server.route({
    method: 'GET', path: '/manifest', config: fetchHandler
  });

  return opts.server;
};
<|endoftext|>


<commit_before>'use strict';

//--------------------------------------------------------------------------
// Requirements
//--------------------------------------------------------------------------
var FFlipRequestObject = require('./request-object');

//--------------------------------------------------------------------------
// Private
//--------------------------------------------------------------------------

//--------------------------------------------------------------------------
// Public
//--------------------------------------------------------------------------

module.exports = FFlipExpressIntegration;
function FFlipExpressIntegration(fflip, options) {

	options = options || {};
	this.options = {
		cookieName: options.cookieName || 'fflip',
		cookieOptions: options.cookieOptions,
		manualRoutePath: options.manualRoutePath || '/fflip/:name/:action',
	};

	/**
	 * Express middleware. Attaches helper functions to the request object
	 * and wrap the res.render to automatically include features in the
	 * template.
	 *
	 * @param {Request} req
	 * @param {Response} res
	 * @param {Function} next
	 * @return {void}
	 */
	this.middleware = function fflipExpress(req, res, next) {

		// Attach the fflip object to the request
		req.fflip = new FFlipRequestObject(fflip, req.cookies[this.options.cookieName]);

		// Wrap res.render() to set options.features automatically
		res._render = res.render;
		res.render = function(view, options, callback) {
			options = options || {};
			options.Features = req.fflip.features;
			options.FeaturesJSON = JSON.stringify(req.fflip.features);
			res._render(view, options, callback);
		};

		// Carry On!
		next();
	}.bind(this);

	/**
	 * Attach routes for manual feature flipping.
	 *
	 * @param {Request} req
	 * @param {Response} res
	 * @param {Function} next
	 * @return {void}
	 */
	this.manualRoute = function(req, res, next) {
		var name = req.params.name;
		var action = req.params.action;
		var actionName = '';

		// Check if feature exists.
		if(fflip.features[name] === undefined) {
			var notFoundError = new Error('FFlip: Feature ' + name + ' not found');
			notFoundError.fflip = true;
			notFoundError.statusCode = 404;
			return next(notFoundError);
		}

		// Check if cookies are enabled.
		if(!req.cookies) {
			var noCookiesError = new Error('FFlip: Cookies are not enabled.');
			noCookiesError.fflip = true;
			noCookiesError.statusCode = 500;
			return next(noCookiesError);
		}

		// Apply the new action.
		var flags = req.cookies[this.options.cookieName] || {};
		switch(action) {
			// enable
			case '1':
				flags[name] = true;
				actionName = 'enabled';
				break;
			// disable
			case '0':
				flags[name] = false;
				actionName = 'disabled';
				break;
			// remove
			case '-1':
				delete flags[name];
				actionName = 'removed';
				break;
			// other: propogate error
			default:
				var err = new Error('FFlip: Bad Input. Action (' + action + ') must be 1 (enable), 0 (disable), or -1 (remove)');
				err.fflip = true;
				err.statusCode = 400;
				return next(err);
		}

		// set new fflip cookie with new data
		res.cookie(this.options.cookieName, flags, this.options.cookieOptions);
		res.json(200, {
			feature: name,
			action: action,
			status: 200,
			message: 'fflip: Feature ' + name + ' is now ' + actionName
		});
	}.bind(this);
}

/**
 * Attach all FFlip functionality to an express app. Includes helpers & routes.
 *
 * @param {Object} app An Express Application
 * @return {void}
 */
FFlipExpressIntegration.prototype.connectAll = function(app) {
	// Express Middleware
	app.use(this.middleware);
	// Manual Flipping Route (default route: '/fflip/:name/:action')
	app.get(this.options.manualRoutePath, this.manualRoute);
};
<commit_msg>Replace deprecated usage of res.json<commit_after>'use strict';

//--------------------------------------------------------------------------
// Requirements
//--------------------------------------------------------------------------
var FFlipRequestObject = require('./request-object');

//--------------------------------------------------------------------------
// Private
//--------------------------------------------------------------------------

//--------------------------------------------------------------------------
// Public
//--------------------------------------------------------------------------

module.exports = FFlipExpressIntegration;
function FFlipExpressIntegration(fflip, options) {

	options = options || {};
	this.options = {
		cookieName: options.cookieName || 'fflip',
		cookieOptions: options.cookieOptions,
		manualRoutePath: options.manualRoutePath || '/fflip/:name/:action',
	};

	/**
	 * Express middleware. Attaches helper functions to the request object
	 * and wrap the res.render to automatically include features in the
	 * template.
	 *
	 * @param {Request} req
	 * @param {Response} res
	 * @param {Function} next
	 * @return {void}
	 */
	this.middleware = function fflipExpress(req, res, next) {

		// Attach the fflip object to the request
		req.fflip = new FFlipRequestObject(fflip, req.cookies[this.options.cookieName]);

		// Wrap res.render() to set options.features automatically
		res._render = res.render;
		res.render = function(view, options, callback) {
			options = options || {};
			options.Features = req.fflip.features;
			options.FeaturesJSON = JSON.stringify(req.fflip.features);
			res._render(view, options, callback);
		};

		// Carry On!
		next();
	}.bind(this);

	/**
	 * Attach routes for manual feature flipping.
	 *
	 * @param {Request} req
	 * @param {Response} res
	 * @param {Function} next
	 * @return {void}
	 */
	this.manualRoute = function(req, res, next) {
		var name = req.params.name;
		var action = req.params.action;
		var actionName = '';

		// Check if feature exists.
		if(fflip.features[name] === undefined) {
			var notFoundError = new Error('FFlip: Feature ' + name + ' not found');
			notFoundError.fflip = true;
			notFoundError.statusCode = 404;
			return next(notFoundError);
		}

		// Check if cookies are enabled.
		if(!req.cookies) {
			var noCookiesError = new Error('FFlip: Cookies are not enabled.');
			noCookiesError.fflip = true;
			noCookiesError.statusCode = 500;
			return next(noCookiesError);
		}

		// Apply the new action.
		var flags = req.cookies[this.options.cookieName] || {};
		switch(action) {
			// enable
			case '1':
				flags[name] = true;
				actionName = 'enabled';
				break;
			// disable
			case '0':
				flags[name] = false;
				actionName = 'disabled';
				break;
			// remove
			case '-1':
				delete flags[name];
				actionName = 'removed';
				break;
			// other: propogate error
			default:
				var err = new Error('FFlip: Bad Input. Action (' + action + ') must be 1 (enable), 0 (disable), or -1 (remove)');
				err.fflip = true;
				err.statusCode = 400;
				return next(err);
		}

		// set new fflip cookie with new data
		res.cookie(this.options.cookieName, flags, this.options.cookieOptions);
		res.status(200).json({
			feature: name,
			action: action,
			status: 200,
			message: 'fflip: Feature ' + name + ' is now ' + actionName
		});
	}.bind(this);
}

/**
 * Attach all FFlip functionality to an express app. Includes helpers & routes.
 *
 * @param {Object} app An Express Application
 * @return {void}
 */
FFlipExpressIntegration.prototype.connectAll = function(app) {
	// Express Middleware
	app.use(this.middleware);
	// Manual Flipping Route (default route: '/fflip/:name/:action')
	app.get(this.options.manualRoutePath, this.manualRoute);
};
<|endoftext|>


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

/**
 * Regular expression used to extract argument names from string represention
 * of a function.
 */
var FUNCTION_REGEX = /^function\s*(?:.*?)\(\s*(.*)\s*\)/;

var NamedArgs = {};

/**
 * Returns a dictionary of arguments keyed by function argument name. Toolkit
 * functions to simulate the "named args" feature of other popular languages
 * using plain old JavaScript.
 *
 * @param {!Function} fn The function declaration.
 * @param {!Array<*>} originalArgs The original arguments passed to the function
 *   call.
 */
NamedArgs.extractFromFunction = function(fn, originalArgs) {
  if (originalArgs.length == 1 && typeof originalArgs[0] === 'object') {
    return originalArgs[0];
  }
  var regexMatch = fn.toString().match(FUNCTION_REGEX);
  if (!regexMatch || regexMatch.length < 2) {
    throw new Error('Unsupported function declaration:\n' + fn.toString());
  }
  var argNames= regexMatch[1].split(',');
  var dict = {};
  for (var i in argNames) {
    var argName = argNames[i].trim();
    dict[argName] = i < originalArgs.length ? originalArgs[i] : undefined;
  }
  return dict;
};

exports.NamedArgs = NamedArgs;
<commit_msg>Add missing space<commit_after>/**
 * @license
 * Copyright 2019 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * Regular expression used to extract argument names from string represention
 * of a function.
 */
var FUNCTION_REGEX = /^function\s*(?:.*?)\(\s*(.*)\s*\)/;

var NamedArgs = {};

/**
 * Returns a dictionary of arguments keyed by function argument name. Toolkit
 * functions to simulate the "named args" feature of other popular languages
 * using plain old JavaScript.
 *
 * @param {!Function} fn The function declaration.
 * @param {!Array<*>} originalArgs The original arguments passed to the function
 *   call.
 */
NamedArgs.extractFromFunction = function(fn, originalArgs) {
  if (originalArgs.length == 1 && typeof originalArgs[0] === 'object') {
    return originalArgs[0];
  }
  var regexMatch = fn.toString().match(FUNCTION_REGEX);
  if (!regexMatch || regexMatch.length < 2) {
    throw new Error('Unsupported function declaration:\n' + fn.toString());
  }
  var argNames = regexMatch[1].split(',');

  var dict = {};
  for (var i in argNames) {
    var argName = argNames[i].trim();
    dict[argName] = i < originalArgs.length ? originalArgs[i] : undefined;
  }
  return dict;
};

exports.NamedArgs = NamedArgs;
<|endoftext|>


<commit_before>'use strict';
var debug = require('debug')('fileprocessor');
var File = require('./file');
var _ = require('lodash');

var _defaultPatterns = {
	'html': [
      /*jshint regexp:false */
			[/<ng-include[^\>]+src=['"]+([^"']+)["']+/gm,
       'Update the HTML with the new angular include filenames'
			],
       [/<div[^\>]+ng-include=['"]+([^"']+)["']+/gm,
       'Update the HTML with the new angular include filenames inside div'
       ],
    [/<select[^\>]+ng-include=['"]+([^"']+)["']+/gm,
      'Update the HTML with the new angular include filenames inside select'
    ],
      [ /<script.+src=['"]([^"']+)["']/gm,
      'Update the HTML to reference our concat/min/revved script files'
    ],
    [
      /<link[^\>]+href=['"]([^"']+)["']/gm,
      'Update the HTML with the new css filenames'
    ],
    [
      /<img[^\>]*[^\>\S]+src=['"]([^"']+)["']/gm,
      'Update the HTML with the new img filenames'
    ],
    [
      /<video[^\>]+src=['"]([^"']+)["']/gm,
      'Update the HTML with the new video filenames'
    ],
    [
      /<video[^\>]+poster=['"]([^"']+)["']/gm,
      'Update the HTML with the new poster filenames'
    ],
    [
      /<source[^\>]+src=['"]([^"']+)["']/gm,
      'Update the HTML with the new source filenames'
    ],
    [
      /data-main\s*=['"]([^"']+)['"]/gm,
      'Update the HTML with data-main tags',
      function (m) {
        return m.match(/\.js$/) ? m : m + '.js';
      },
      function (m) {
        return m.replace('.js', '');
      }
    ],
    [
      /data-(?!main).[^=]+=['"]([^'"]+)['"]/gm,
      'Update the HTML with data-* tags'
    ],
    [
      /url\(\s*['"]?([^"'\)]+)["']?\s*\)/gm,
      'Update the HTML with background imgs, case there is some inline style'
    ],
    [
      /<a[^\>]+href=['"]([^"']+)["']/gm,
      'Update the HTML with anchors images'
    ],
    [
      /<input[^\>]+src=['"]([^"']+)["']/gm,
      'Update the HTML with reference in input'
    ],
    [
      /<meta[^\>]+content=['"]([^"']+)["']/gm,
      'Update the HTML with the new img filenames in meta tags'
    ]
   ],

	  'css': [
      /*jshint regexp:false */
      [ /(?:src=|url\(\s*)['"]?([^'"\)]+)['"]?\s*\)?/gm,
      'Update the CSS to reference our revved images'
      ]
    ],
		'js': [
			/*jshint regexp:false */
			[
			/templateUrl\:\s*['"]?([^'"\)#?]+)(?:[#?](?:[^'"\)]*))?['"]?\s*/gm,
			'Update the JS with the new angular include filenames'
			]
		]
  };

var FileProcessor = module.exports = function (patterns, finder, logcb) {
  if (!patterns) {
    throw new Error('No pattern given');
  }

  if (_.isString(patterns)) {
    if (!_.contains(_.keys(_defaultPatterns), patterns)) {
      throw new Error('Unsupported pattern: ' + patterns);
    }
    this.patterns = _defaultPatterns[patterns];
  } else {
    // FIXME: check the pattern format
    this.patterns = patterns;
  }

  this.log = logcb || function () {};

  if (!finder) {
    throw new Error('Missing parameter: finder');
  }
  this.finder = finder;
};

//
// Replace blocks by their target
//
FileProcessor.prototype.replaceBlocks = function replaceBlocks(file) {
  var result = file.content;
  var linefeed = /\r\n/g.test(result) ? '\r\n' : '\n';
  file.blocks.forEach(function (block) {
    var blockLine = block.raw.join(linefeed);
    result = result.replace(blockLine, this.replaceWith(block));
  }, this);
  return result;
};

FileProcessor.prototype.replaceWith = function replaceWith(block) {
  var result;
  var dest = block.dest;
  var conditionalStart = block.conditionalStart ? block.conditionalStart + '\n' + block.indent : '';
  var conditionalEnd = block.conditionalEnd ? '\n' + block.indent + block.conditionalEnd : '';
  if (typeof block.src === 'undefined' || block.src === null || block.src.length === 0) {
    // there are no css or js files in the block, remove it completely
    result = '';
  } else if (block.type === 'css') {
    var media = block.media ? ' media="' + block.media + '"' : '';
    result = block.indent + conditionalStart + '<link rel="stylesheet" href="' + dest + '"' + media + '/>' + conditionalEnd;
  } else if (block.defer) {
    result = block.indent + conditionalStart + '<script defer src="' + dest + '"><\/script>' + conditionalEnd;
  } else if (block.async) {
    result = block.indent + conditionalStart + '<script async src="' + dest + '"><\/script>' + conditionalEnd;
  } else if (block.type === 'js') {
    result = block.indent + conditionalStart + '<script src="' + dest + '"><\/script>' + conditionalEnd;
  } else {
    result = '';
  }
  return result;
};

//
// Replace reference to scripts, css, images, ... in +lines+ with their revved version
// If +lines+ is not furnished, use instead the cached version (i.e. stored at constructor time)
//
FileProcessor.prototype.replaceWithRevved = function replaceWithRevved(lines, assetSearchPath) {
  // Replace script sources
  var self = this;
  var content = lines;
  var regexps = this.patterns;
  var identity = function (m) {
    return m;
  };

  // Replace reference to script with the actual name of the revved script
  regexps.forEach(function (rxl) {
    var filterIn = rxl[2] || identity;
    var filterOut = rxl[3] || identity;

    self.log(rxl[1]);
    content = content.replace(rxl[0], function (match, src) {
      // Consider reference from site root
      var srcFile = filterIn(src);

      debug('Let\'s replace ' + src);

      debug('Looking for revved version of ' + srcFile + ' in ', assetSearchPath);

      var file = self.finder.find(srcFile, assetSearchPath);

      debug('Found file \'%s\'', file);

      var res = match.replace(src, filterOut(file));
      if (srcFile !== file) {
        self.log(match + ' changed to ' + res);
      }
      return res;
    });
  });

  return content;
};

FileProcessor.prototype.process = function (filename, assetSearchPath) {
  debug('processing file %s', filename, assetSearchPath);

  if (_.isString(filename)) {
    this.file = new File(filename);
  } else {
    // filename is an object and should conform to lib/file.js API
    this.file = filename;
  }

  if (assetSearchPath && assetSearchPath.length !== 0) {
    this.file.searchPath = assetSearchPath;
  }

  var content = this.replaceWithRevved(this.replaceBlocks(this.file), this.file.searchPath);

  return content;
};
<commit_msg>add td support<commit_after>'use strict';
var debug = require('debug')('fileprocessor');
var File = require('./file');
var _ = require('lodash');

var _defaultPatterns = {
	'html': [
      /*jshint regexp:false */
			[/<ng-include[^\>]+src=['"]+([^"']+)["']+/gm,
       'Update the HTML with the new angular include filenames'
			],
       [/<div[^\>]+ng-include=['"]+([^"']+)["']+/gm,
       'Update the HTML with the new angular include filenames inside div'
       ],
    [/<select[^\>]+ng-include=['"]+([^"']+)["']+/gm,
      'Update the HTML with the new angular include filenames inside select'
    ],
    [/<td[^\>]+ng-include=['"]+([^"']+)["']+/gm,
      'Update the HTML with the new angular include filenames inside td'
    ],
      [ /<script.+src=['"]([^"']+)["']/gm,
      'Update the HTML to reference our concat/min/revved script files'
    ],
    [
      /<link[^\>]+href=['"]([^"']+)["']/gm,
      'Update the HTML with the new css filenames'
    ],
    [
      /<img[^\>]*[^\>\S]+src=['"]([^"']+)["']/gm,
      'Update the HTML with the new img filenames'
    ],
    [
      /<video[^\>]+src=['"]([^"']+)["']/gm,
      'Update the HTML with the new video filenames'
    ],
    [
      /<video[^\>]+poster=['"]([^"']+)["']/gm,
      'Update the HTML with the new poster filenames'
    ],
    [
      /<source[^\>]+src=['"]([^"']+)["']/gm,
      'Update the HTML with the new source filenames'
    ],
    [
      /data-main\s*=['"]([^"']+)['"]/gm,
      'Update the HTML with data-main tags',
      function (m) {
        return m.match(/\.js$/) ? m : m + '.js';
      },
      function (m) {
        return m.replace('.js', '');
      }
    ],
    [
      /data-(?!main).[^=]+=['"]([^'"]+)['"]/gm,
      'Update the HTML with data-* tags'
    ],
    [
      /url\(\s*['"]?([^"'\)]+)["']?\s*\)/gm,
      'Update the HTML with background imgs, case there is some inline style'
    ],
    [
      /<a[^\>]+href=['"]([^"']+)["']/gm,
      'Update the HTML with anchors images'
    ],
    [
      /<input[^\>]+src=['"]([^"']+)["']/gm,
      'Update the HTML with reference in input'
    ],
    [
      /<meta[^\>]+content=['"]([^"']+)["']/gm,
      'Update the HTML with the new img filenames in meta tags'
    ]
   ],

	  'css': [
      /*jshint regexp:false */
      [ /(?:src=|url\(\s*)['"]?([^'"\)]+)['"]?\s*\)?/gm,
      'Update the CSS to reference our revved images'
      ]
    ],
		'js': [
			/*jshint regexp:false */
			[
			/templateUrl\:\s*['"]?([^'"\)#?]+)(?:[#?](?:[^'"\)]*))?['"]?\s*/gm,
			'Update the JS with the new angular include filenames'
			]
		]
  };

var FileProcessor = module.exports = function (patterns, finder, logcb) {
  if (!patterns) {
    throw new Error('No pattern given');
  }

  if (_.isString(patterns)) {
    if (!_.contains(_.keys(_defaultPatterns), patterns)) {
      throw new Error('Unsupported pattern: ' + patterns);
    }
    this.patterns = _defaultPatterns[patterns];
  } else {
    // FIXME: check the pattern format
    this.patterns = patterns;
  }

  this.log = logcb || function () {};

  if (!finder) {
    throw new Error('Missing parameter: finder');
  }
  this.finder = finder;
};

//
// Replace blocks by their target
//
FileProcessor.prototype.replaceBlocks = function replaceBlocks(file) {
  var result = file.content;
  var linefeed = /\r\n/g.test(result) ? '\r\n' : '\n';
  file.blocks.forEach(function (block) {
    var blockLine = block.raw.join(linefeed);
    result = result.replace(blockLine, this.replaceWith(block));
  }, this);
  return result;
};

FileProcessor.prototype.replaceWith = function replaceWith(block) {
  var result;
  var dest = block.dest;
  var conditionalStart = block.conditionalStart ? block.conditionalStart + '\n' + block.indent : '';
  var conditionalEnd = block.conditionalEnd ? '\n' + block.indent + block.conditionalEnd : '';
  if (typeof block.src === 'undefined' || block.src === null || block.src.length === 0) {
    // there are no css or js files in the block, remove it completely
    result = '';
  } else if (block.type === 'css') {
    var media = block.media ? ' media="' + block.media + '"' : '';
    result = block.indent + conditionalStart + '<link rel="stylesheet" href="' + dest + '"' + media + '/>' + conditionalEnd;
  } else if (block.defer) {
    result = block.indent + conditionalStart + '<script defer src="' + dest + '"><\/script>' + conditionalEnd;
  } else if (block.async) {
    result = block.indent + conditionalStart + '<script async src="' + dest + '"><\/script>' + conditionalEnd;
  } else if (block.type === 'js') {
    result = block.indent + conditionalStart + '<script src="' + dest + '"><\/script>' + conditionalEnd;
  } else {
    result = '';
  }
  return result;
};

//
// Replace reference to scripts, css, images, ... in +lines+ with their revved version
// If +lines+ is not furnished, use instead the cached version (i.e. stored at constructor time)
//
FileProcessor.prototype.replaceWithRevved = function replaceWithRevved(lines, assetSearchPath) {
  // Replace script sources
  var self = this;
  var content = lines;
  var regexps = this.patterns;
  var identity = function (m) {
    return m;
  };

  // Replace reference to script with the actual name of the revved script
  regexps.forEach(function (rxl) {
    var filterIn = rxl[2] || identity;
    var filterOut = rxl[3] || identity;

    self.log(rxl[1]);
    content = content.replace(rxl[0], function (match, src) {
      // Consider reference from site root
      var srcFile = filterIn(src);

      debug('Let\'s replace ' + src);

      debug('Looking for revved version of ' + srcFile + ' in ', assetSearchPath);

      var file = self.finder.find(srcFile, assetSearchPath);

      debug('Found file \'%s\'', file);

      var res = match.replace(src, filterOut(file));
      if (srcFile !== file) {
        self.log(match + ' changed to ' + res);
      }
      return res;
    });
  });

  return content;
};

FileProcessor.prototype.process = function (filename, assetSearchPath) {
  debug('processing file %s', filename, assetSearchPath);

  if (_.isString(filename)) {
    this.file = new File(filename);
  } else {
    // filename is an object and should conform to lib/file.js API
    this.file = filename;
  }

  if (assetSearchPath && assetSearchPath.length !== 0) {
    this.file.searchPath = assetSearchPath;
  }

  var content = this.replaceWithRevved(this.replaceBlocks(this.file), this.file.searchPath);

  return content;
};
<|endoftext|>


<commit_before>'use strict';
var debug = require('debug')('fileprocessor');
var File = require('./file');
var _ = require('lodash');

var _defaultPatterns = {
	'html': [
      /*jshint regexp:false */
      [ /<script.+src=['"]([^"']+)["']/gm,
      'Update the HTML to reference our concat/min/revved script files'
      ],
      [ /<link[^\>]+href=['"]([^"']+)["']/gm,
      'Update the HTML with the new css filenames'
      ],
      [ /<img[^\>]+src=['"]([^"']+)["']/gm,
      'Update the HTML with the new img filenames'
      ],
      [ /data-main\s*=['"]([^"']+)['"]/gm,
      'Update the HTML with data-main tags',
      function (m) { return m.match(/\.js$/) ? m : m + '.js'; },
      function (m) { return m.replace('.js', ''); }
      ],
      [ /data-(?!main).[^=]+=['"]([^'"]+)['"]/gm,
      'Update the HTML with data-* tags'
      ],
      [ /url\(\s*['"]([^"']+)["']\s*\)/gm,
      'Update the HTML with background imgs, case there is some inline style'
      ],
      [ /<a[^\>]+href=['"]([^"']+)["']/gm,
      'Update the HTML with anchors images'
      ],
      [/<input[^\>]+src=['"]([^"']+)["']/gm,
      'Update the HTML with reference in input'
      ]
    ],
	  'css': [
      /*jshint regexp:false */
      [ /(?:src=|url\(\s*)['"]?([^'"\)(\?|#)]+)['"]?\s*\)?/gm,
      'Update the CSS to reference our revved images'
      ]
    ]
  };

var FileProcessor = module.exports = function(patterns, finder, logcb) {
	if (!patterns) {
		throw new Error('No pattern given');
	}

	if (typeof patterns  === 'string' || patterns instanceof String) {
		if (!_.contains(_.keys(_defaultPatterns), patterns)) {
			throw new Error('Unsupported pattern: ' + patterns);
		}
		this.patterns = _defaultPatterns[patterns];
	}else {
		// FIXME: check the pattern format
		this.patterns = patterns;
	}

	this.log = logcb || function(){};

	if (!finder) {
		throw new Error('Missing parameter: finder');
	}
	this.finder = finder;
};

//
// Replace blocks by their target
//
FileProcessor.prototype.replaceBlocks = function replaceBlocks(file) {
  var result = file.content;
  var linefeed = /\r\n/g.test(result) ? '\r\n' : '\n';
  file.blocks.forEach(function (block) {
    var blockLine = block.raw.join(linefeed);
    result = result.replace(blockLine, this.replaceWith(block));
  }, this);
  return result;
};

FileProcessor.prototype.replaceWith = function replaceWith(block) {
  var result;
  var dest = block.dest;
  var conditionalStart = block.conditionalStart ? block.conditionalStart + '\n' + block.indent : '';
  var conditionalEnd = block.conditionalEnd ? '\n' + block.indent + block.conditionalEnd : '';
  if (typeof block.src === 'undefined' || block.src === null || block.src.length === 0) {
    // there are no css or js files in the block, remove it completely
    result = '';
  } else if (block.type === 'css') {
    var media = block.media ? ' media="' + block.media + '"' : '';
    result = block.indent + conditionalStart + '<link rel="stylesheet" href="' + dest + '"' + media + '/>' + conditionalEnd;
  } else if (block.defer) {
    result = block.indent + conditionalStart + '<script defer src="' + dest + '"><\/script>' + conditionalEnd;
  } else if (block.async) {
    result = block.indent + conditionalStart + '<script async src="' + dest + '"><\/script>' + conditionalEnd;
  } else if (block.type === 'js') {
    result = block.indent + conditionalStart + '<script src="' + dest + '"><\/script>' + conditionalEnd;
  } /*else {
    result = '';
  }*/
  return result;
};

//
// Replace reference to scripts, css, images, .. in +lines+ with their revved version
// If +lines+ is not furnished used instead the cached version (i.e. stored at constructor time)
//
FileProcessor.prototype.replaceWithRevved = function replaceWithRevved(lines, assetSearchPath) {
    // Replace script sources
    var self = this;
    var content = lines;
    var regexps = this.patterns;
    var identity = function (m) { return m; };

    // Replace reference to script with the actual name of the revved script
    regexps.forEach(function (rxl) {
      var filterIn = rxl[2] || identity;
      var filterOut = rxl[3] || identity;

      self.log(rxl[1]);
      content = content.replace(rxl[0], function (match, src) {
        // Consider reference from site root
        var srcfile = filterIn(src);

        debug('Let\'s replace ' + src);

        debug('Looking for revved version of ' + srcfile + ' in ', assetSearchPath);

        var file = self.finder.find(srcfile, assetSearchPath);

        debug('Found file \'%s\'', file);

        var res = match.replace(src, filterOut(file));
        if (srcfile !== file) {
          self.log(match + ' changed to ' + res);
        }
        return res;
      });
    });

    return content;
  };

FileProcessor.prototype.process = function(filename, assetSearchPath) {
  debug('processing file %s', filename, assetSearchPath);

  if (typeof filename  === 'string' || filename instanceof String) {
    this.file = new File(filename);
  } else {
    // filename is an object and should conform to lib/file.js API
    this.file = filename;
  }

  if (assetSearchPath && assetSearchPath.length !== 0) {
    this.file.searchPath = assetSearchPath;
  }

	var content = this.replaceWithRevved(this.replaceBlocks(this.file), this.file.searchPath);

	return content;
};
<commit_msg>fileprocessor.js: re-indent.<commit_after>'use strict';
var debug = require('debug')('fileprocessor');
var File = require('./file');
var _ = require('lodash');

var _defaultPatterns = {
  'html': [
    /*jshint regexp:false */
    [ /<script.+src=['"]([^"']+)["']/gm,
    'Update the HTML to reference our concat/min/revved script files'
    ],
    [ /<link[^\>]+href=['"]([^"']+)["']/gm,
    'Update the HTML with the new css filenames'
    ],
    [ /<img[^\>]+src=['"]([^"']+)["']/gm,
    'Update the HTML with the new img filenames'
    ],
    [ /data-main\s*=['"]([^"']+)['"]/gm,
    'Update the HTML with data-main tags',
    function (m) { return m.match(/\.js$/) ? m : m + '.js'; },
    function (m) { return m.replace('.js', ''); }
    ],
    [ /data-(?!main).[^=]+=['"]([^'"]+)['"]/gm,
    'Update the HTML with data-* tags'
    ],
    [ /url\(\s*['"]([^"']+)["']\s*\)/gm,
    'Update the HTML with background imgs, case there is some inline style'
    ],
    [ /<a[^\>]+href=['"]([^"']+)["']/gm,
    'Update the HTML with anchors images'
    ],
    [/<input[^\>]+src=['"]([^"']+)["']/gm,
    'Update the HTML with reference in input'
    ]
  ],
  'css': [
    /*jshint regexp:false */
    [ /(?:src=|url\(\s*)['"]?([^'"\)(\?|#)]+)['"]?\s*\)?/gm,
    'Update the CSS to reference our revved images'
    ]
  ]
};

var FileProcessor = module.exports = function(patterns, finder, logcb) {
  if (!patterns) {
    throw new Error('No pattern given');
  }

  if (typeof patterns  === 'string' || patterns instanceof String) {
    if (!_.contains(_.keys(_defaultPatterns), patterns)) {
      throw new Error('Unsupported pattern: ' + patterns);
    }
    this.patterns = _defaultPatterns[patterns];
  }else {
    // FIXME: check the pattern format
    this.patterns = patterns;
  }

  this.log = logcb || function(){};

  if (!finder) {
    throw new Error('Missing parameter: finder');
  }
  this.finder = finder;
};

//
// Replace blocks by their target
//
FileProcessor.prototype.replaceBlocks = function replaceBlocks(file) {
  var result = file.content;
  var linefeed = /\r\n/g.test(result) ? '\r\n' : '\n';
  file.blocks.forEach(function (block) {
    var blockLine = block.raw.join(linefeed);
    result = result.replace(blockLine, this.replaceWith(block));
  }, this);
  return result;
};

FileProcessor.prototype.replaceWith = function replaceWith(block) {
  var result;
  var dest = block.dest;
  var conditionalStart = block.conditionalStart ? block.conditionalStart + '\n' + block.indent : '';
  var conditionalEnd = block.conditionalEnd ? '\n' + block.indent + block.conditionalEnd : '';
  if (typeof block.src === 'undefined' || block.src === null || block.src.length === 0) {
    // there are no css or js files in the block, remove it completely
    result = '';
  } else if (block.type === 'css') {
    var media = block.media ? ' media="' + block.media + '"' : '';
    result = block.indent + conditionalStart + '<link rel="stylesheet" href="' + dest + '"' + media + '/>' + conditionalEnd;
  } else if (block.defer) {
    result = block.indent + conditionalStart + '<script defer src="' + dest + '"><\/script>' + conditionalEnd;
  } else if (block.async) {
    result = block.indent + conditionalStart + '<script async src="' + dest + '"><\/script>' + conditionalEnd;
  } else if (block.type === 'js') {
    result = block.indent + conditionalStart + '<script src="' + dest + '"><\/script>' + conditionalEnd;
  } /*else {
    result = '';
  }*/
  return result;
};

//
// Replace reference to scripts, css, images, .. in +lines+ with their revved version
// If +lines+ is not furnished used instead the cached version (i.e. stored at constructor time)
//
FileProcessor.prototype.replaceWithRevved = function replaceWithRevved(lines, assetSearchPath) {
    // Replace script sources
    var self = this;
    var content = lines;
    var regexps = this.patterns;
    var identity = function (m) { return m; };

    // Replace reference to script with the actual name of the revved script
    regexps.forEach(function (rxl) {
      var filterIn = rxl[2] || identity;
      var filterOut = rxl[3] || identity;

      self.log(rxl[1]);
      content = content.replace(rxl[0], function (match, src) {
        // Consider reference from site root
        var srcfile = filterIn(src);

        debug('Let\'s replace ' + src);

        debug('Looking for revved version of ' + srcfile + ' in ', assetSearchPath);

        var file = self.finder.find(srcfile, assetSearchPath);

        debug('Found file \'%s\'', file);

        var res = match.replace(src, filterOut(file));
        if (srcfile !== file) {
          self.log(match + ' changed to ' + res);
        }
        return res;
      });
    });

    return content;
  };

FileProcessor.prototype.process = function(filename, assetSearchPath) {
  debug('processing file %s', filename, assetSearchPath);

  if (typeof filename  === 'string' || filename instanceof String) {
    this.file = new File(filename);
  } else {
    // filename is an object and should conform to lib/file.js API
    this.file = filename;
  }

  if (assetSearchPath && assetSearchPath.length !== 0) {
    this.file.searchPath = assetSearchPath;
  }

  var content = this.replaceWithRevved(this.replaceBlocks(this.file), this.file.searchPath);

  return content;
};
<|endoftext|>


<commit_before>// fs.writeFile that's safe for simultaneous calls for same file.
// In such event write that is ongoing is exited and new one is initialized

'use strict';

var isCallable = require('es5-ext/lib/Object/is-callable')
  , deferred   = require('deferred')
  , fs         = require('fs')
  , resolve    = require('path').resolve

  , next, writeAll, cache = {}, _writeFile, writeFile;

next = function (path, err) {
	var data = cache[path];
	if (err) {
		delete cache[path];
		data.def.resolve(err);
		return;
	}
	if (data.data) {
		data = data.data;
		delete cache[path].data;
		_writeFile(path, data.data, data.encoding);
	} else {
		delete cache[path];
		data.def.resolve();
	}
};

writeAll = function (path, fd, buffer, offset, length) {
	fs.write(fd, buffer, offset, length, offset, function (writeErr, written) {
		if (writeErr) {
			fs.close(fd, function() {
				next(path, writeErr);
			});
		} else {
			if ((written === length) || cache[path].data) {
				fs.close(fd, function (err) {
					next(path, err);
				});
			} else {
				writeAll(path, fd, buffer, offset + written, length - written);
			}
		}
	});
};

_writeFile = function (path, data, encoding) {
	if (!encoding) {
		encoding = 'utf8';
	}
	fs.open(path, 'w', 438 /*=0666*/, function (openErr, fd) {
		if (openErr) {
			next(path, openErr);
		} else  if (!cache[path].data) {
			var buffer = Buffer.isBuffer(data) ? data : new Buffer(String(data),
				encoding);
			writeAll(path, fd, buffer, 0, buffer.length);
		} else {
			fs.close(fd, function (err) {
				next(path, err);
			});
		}
	});
};

writeFile = function (path, data, encoding) {
	var def;
	if (cache[path]) {
		cache[path].data = { data: data, encoding: encoding };
		def = cache[path].def;
	} else {
		def = deferred();
		cache[path] = { def: def };
		_writeFile(path, data, encoding, def.resolve);
	}

	return def.promise;
};
writeFile.returnsPromise = true;

module.exports = exports = function (path, data) {
	var encoding, cb;

	path = resolve(String(path));
	encoding = arguments[2];
	cb = arguments[3];
	if ((cb == null) && isCallable(encoding)) {
		cb = encoding;
		encoding = null;
	}

	return writeFile(path, data, encoding).cb(cb);
};
exports.returnsPromise = true;
exports.writeFile = writeFile;
<commit_msg>fs.writeFile now backed by descriptorLimiter<commit_after>// fs.writeFile that's safe for simultaneous calls for same file.
// In such event write that is ongoing is exited and new one is initialized

'use strict';

var partial     = require('es5-ext/lib/Function/prototype/partial')
  , isCallable  = require('es5-ext/lib/Object/is-callable')
  , deferred    = require('deferred')
  , fs          = require('fs')
  , resolve     = require('path').resolve
  , descLimiter = require('./_descriptor-limiter')

  , next, writeAll, cache = {}, _writeFile, writeFile;

next = function (path, err) {
	var data = cache[path];
	if (err) {
		delete cache[path];
		data.def.resolve(err);
		return;
	}
	if (data.data) {
		data = data.data;
		delete cache[path].data;
		_writeFile(path, data.data, data.encoding);
	} else {
		delete cache[path];
		data.def.resolve();
	}
};

writeAll = function (path, fd, buffer, offset, length) {
	fs.write(fd, buffer, offset, length, offset, function (writeErr, written) {
		if (writeErr) {
			fs.close(fd, function() {
				descLimiter.close();
				next(path, writeErr);
			});
		} else {
			if ((written === length) || cache[path].data) {
				fs.close(fd, function (err) {
					descLimiter.close();
					next(path, err);
				});
			} else {
				writeAll(path, fd, buffer, offset + written, length - written);
			}
		}
	});
};

_writeFile = function (path, data, encoding) {
	descLimiter(function () {
		if (cache[path].data) {
			next(path);
			return;
		}
		if (!encoding) {
			encoding = 'utf8';
		}
		descLimiter.open();
		fs.open(path, 'w', 438 /*=0666*/, function (openErr, fd) {
			if (openErr) {
				descLimiter.close();
				next(path, openErr);
			} else  if (!cache[path].data) {
				var buffer = Buffer.isBuffer(data) ? data : new Buffer(String(data),
					encoding);
				writeAll(path, fd, buffer, 0, buffer.length);
			} else {
				fs.close(fd, function (err) {
					descLimiter.close();
					next(path, err);
				});
			}
		});
	});
};

writeFile = function (path, data, encoding) {
	var def;
	if (cache[path]) {
		cache[path].data = { data: data, encoding: encoding };
		def = cache[path].def;
	} else {
		def = deferred();
		cache[path] = { def: def };
		_writeFile(path, data, encoding, def.resolve);
	}

	return def.promise;
};
writeFile.returnsPromise = true;

module.exports = exports = function (path, data) {
	var encoding, cb;

	path = resolve(String(path));
	encoding = arguments[2];
	cb = arguments[3];
	if ((cb == null) && isCallable(encoding)) {
		cb = encoding;
		encoding = null;
	}

	return writeFile(path, data, encoding).cb(cb);
};
exports.returnsPromise = true;
exports.writeFile = writeFile;
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2012 Mathieu Turcotte
 * Licensed under the MIT license.
 */

var events = require('events'),
    util = require('util');

var Backoff = require('./backoff'),
    FibonacciBackoffStrategy = require('./strategy/fibonacci');

/**
 * Returns true if the specified value is a function
 * @param val Variable to test.
 * @return Whether variable is a function.
 */
function isFunction(val) {
    return typeof val == 'function';
}

/**
 * Manages the calling of a function in a backoff loop.
 * @param fn Function to wrap in a backoff handler.
 * @param args Array of function's arguments.
 * @param callback Function's callback.
 * @constructor
 */
function FunctionCall(fn, args, callback) {
    events.EventEmitter.call(this);

    if (!isFunction(fn)) {
        throw new Error('fn should be a function.' +
                        'Actual: ' + typeof fn);
    }

    if (!isFunction(callback)) {
        throw new Error('callback should be a function.' +
                        'Actual: ' + typeof fn);
    }

    this.function_ = fn;
    this.arguments_ = args;
    this.callback_ = callback;
    this.results_ = [];

    this.backoff_ = null;
    this.strategy_ = null;

    this.called_ = false;
    this.aborted_ = false;
}
util.inherits(FunctionCall, events.EventEmitter);

/**
 * Creates a backoff instance from the provided strategy; defaults to a
 * Fibonacci backoff strategy if none is provided.
 * @param strategy Optional strategy to use when instantiating the backoff.
 * @return A backoff instance.
 * @private
 */
FunctionCall.backoffFactory_ = function(strategy) {
    return new Backoff(strategy || new FibonacciBackoffStrategy());
};

/**
 * Default number of backoffs.
 * @private
 */
FunctionCall.prototype.failAfter_ = 5;

/**
 * Sets the backoff strategy.
 * @param strategy The backoff strategy to use.
 */
FunctionCall.prototype.setStrategy = function(strategy) {
    if (this.called_) {
        throw new Error('Call in progress.');
    }
    this.strategy_ = strategy;
};

/**
 * Returns all intermediary results returned by the wrapped function since
 * the initial call.
 * @return An array of intermediary results.
 */
FunctionCall.prototype.getResults = function() {
    return this.results_.concat();
};

/**
 * Sets the backoff limit.
 * @param maxNumberOfRetry The maximum number of backoffs.
 */
FunctionCall.prototype.failAfter = function(maxNumberOfRetry) {
    if (this.called_) {
        throw new Error('Call in progress.');
    }
    this.failAfter_ = maxNumberOfRetry;
};

/**
 * Aborts the current call.
 */
FunctionCall.prototype.abort = function() {
    this.aborted_ = true;
    if (this.called_) {
        this.backoff_.reset();
    }
};

/**
 * Initiates the call to the wrapped function.
 * @param backoffFactory Optional factory method used to create the backoff
 *     instance.
 */
FunctionCall.prototype.call = function(backoffFactory) {
    if (this.aborted_) {
        return;
    }

    if (this.called_) {
        throw new Error('Call in progress.');
    }

    backoffFactory = backoffFactory || FunctionCall.backoffFactory_;

    this.backoff_ = backoffFactory(this.strategy_);
    this.backoff_.on('ready', this.doCall_.bind(this));
    this.backoff_.on('fail', this.doCallback_.bind(this));
    this.backoff_.on('backoff', this.handleBackoff_.bind(this));
    this.backoff_.failAfter(this.failAfter_);

    this.called_ = true;
    this.doCall_();
};

/**
 * Calls the wrapped function.
 * @private
 */
FunctionCall.prototype.doCall_ = function() {
    var eventArgs = ['call'].concat(this.arguments_);
    events.EventEmitter.prototype.emit.apply(this, eventArgs);
    var callback = this.handleFunctionCallback_.bind(this);
    this.function_.apply(null, this.arguments_.concat(callback));
};

/**
 * Calls the wrapped function's callback with the last result returned by the
 * wrapped function.
 * @private
 */
FunctionCall.prototype.doCallback_ = function() {
    var args = this.results_[this.results_.length - 1];
    this.callback_.apply(null, args);
};

/**
 * Handles wrapped function's completion. This method acts as a replacement
 * for the original callback function.
 * @private
 */
FunctionCall.prototype.handleFunctionCallback_ = function() {
    if (this.aborted_) {
        return;
    }

    var args = Array.prototype.slice.call(arguments);
    this.results_.push(args); // Save callback arguments.
    events.EventEmitter.prototype.emit.apply(this, ['callback'].concat(args));

    if (args[0]) {
        this.backoff_.backoff();
    } else {
        this.doCallback_();
    }
};

FunctionCall.prototype.handleBackoff_ = function(number, delay) {
    this.emit('backoff', number, delay);
};

module.exports = FunctionCall;
<commit_msg>Add missing comment.<commit_after>/*
 * Copyright (c) 2012 Mathieu Turcotte
 * Licensed under the MIT license.
 */

var events = require('events'),
    util = require('util');

var Backoff = require('./backoff'),
    FibonacciBackoffStrategy = require('./strategy/fibonacci');

/**
 * Returns true if the specified value is a function
 * @param val Variable to test.
 * @return Whether variable is a function.
 */
function isFunction(val) {
    return typeof val == 'function';
}

/**
 * Manages the calling of a function in a backoff loop.
 * @param fn Function to wrap in a backoff handler.
 * @param args Array of function's arguments.
 * @param callback Function's callback.
 * @constructor
 */
function FunctionCall(fn, args, callback) {
    events.EventEmitter.call(this);

    if (!isFunction(fn)) {
        throw new Error('fn should be a function.' +
                        'Actual: ' + typeof fn);
    }

    if (!isFunction(callback)) {
        throw new Error('callback should be a function.' +
                        'Actual: ' + typeof fn);
    }

    this.function_ = fn;
    this.arguments_ = args;
    this.callback_ = callback;
    this.results_ = [];

    this.backoff_ = null;
    this.strategy_ = null;

    this.called_ = false;
    this.aborted_ = false;
}
util.inherits(FunctionCall, events.EventEmitter);

/**
 * Creates a backoff instance from the provided strategy; defaults to a
 * Fibonacci backoff strategy if none is provided.
 * @param strategy Optional strategy to use when instantiating the backoff.
 * @return A backoff instance.
 * @private
 */
FunctionCall.backoffFactory_ = function(strategy) {
    return new Backoff(strategy || new FibonacciBackoffStrategy());
};

/**
 * Default number of backoffs.
 * @private
 */
FunctionCall.prototype.failAfter_ = 5;

/**
 * Sets the backoff strategy.
 * @param strategy The backoff strategy to use.
 */
FunctionCall.prototype.setStrategy = function(strategy) {
    if (this.called_) {
        throw new Error('Call in progress.');
    }
    this.strategy_ = strategy;
};

/**
 * Returns all intermediary results returned by the wrapped function since
 * the initial call.
 * @return An array of intermediary results.
 */
FunctionCall.prototype.getResults = function() {
    return this.results_.concat();
};

/**
 * Sets the backoff limit.
 * @param maxNumberOfRetry The maximum number of backoffs.
 */
FunctionCall.prototype.failAfter = function(maxNumberOfRetry) {
    if (this.called_) {
        throw new Error('Call in progress.');
    }
    this.failAfter_ = maxNumberOfRetry;
};

/**
 * Aborts the current call.
 */
FunctionCall.prototype.abort = function() {
    this.aborted_ = true;
    if (this.called_) {
        this.backoff_.reset();
    }
};

/**
 * Initiates the call to the wrapped function.
 * @param backoffFactory Optional factory method used to create the backoff
 *     instance.
 */
FunctionCall.prototype.call = function(backoffFactory) {
    if (this.aborted_) {
        return;
    }

    if (this.called_) {
        throw new Error('Call in progress.');
    }

    backoffFactory = backoffFactory || FunctionCall.backoffFactory_;

    this.backoff_ = backoffFactory(this.strategy_);
    this.backoff_.on('ready', this.doCall_.bind(this));
    this.backoff_.on('fail', this.doCallback_.bind(this));
    this.backoff_.on('backoff', this.handleBackoff_.bind(this));
    this.backoff_.failAfter(this.failAfter_);

    this.called_ = true;
    this.doCall_();
};

/**
 * Calls the wrapped function.
 * @private
 */
FunctionCall.prototype.doCall_ = function() {
    var eventArgs = ['call'].concat(this.arguments_);
    events.EventEmitter.prototype.emit.apply(this, eventArgs);
    var callback = this.handleFunctionCallback_.bind(this);
    this.function_.apply(null, this.arguments_.concat(callback));
};

/**
 * Calls the wrapped function's callback with the last result returned by the
 * wrapped function.
 * @private
 */
FunctionCall.prototype.doCallback_ = function() {
    var args = this.results_[this.results_.length - 1];
    this.callback_.apply(null, args);
};

/**
 * Handles wrapped function's completion. This method acts as a replacement
 * for the original callback function.
 * @private
 */
FunctionCall.prototype.handleFunctionCallback_ = function() {
    if (this.aborted_) {
        return;
    }

    var args = Array.prototype.slice.call(arguments);
    this.results_.push(args); // Save callback arguments.
    events.EventEmitter.prototype.emit.apply(this, ['callback'].concat(args));

    if (args[0]) {
        this.backoff_.backoff();
    } else {
        this.doCallback_();
    }
};

/**
 * Handles backoff event.
 * @param number Backoff number.
 * @param delay Backoff delay.
 * @private
 */
FunctionCall.prototype.handleBackoff_ = function(number, delay) {
    this.emit('backoff', number, delay);
};

module.exports = FunctionCall;
<|endoftext|>


<commit_before>'use strict'

const resolvePath = require('path').resolve
const isFile = require('fs').existsSync

module.exports = opts => {
  const path = resolvePath(`./data/${opts.langCode}/questions.js`)
  const file = isFile(path) ? require(path) : false
  if (!file) {
    return { error: `${path} not found` }
  } else if (opts.page > Math.round(file.length / opts.limit)) {
    return { error: 'Reached page limit' }
  }

  let res = {
    totalQuestions: file.length - 1,
    limit: opts.limit,
    totalPages: Math.round(file.length / opts.limit),
    percentDone: Math.round(opts.page / ((file.length - 1) / opts.limit) * 100),
    page: opts.page,
    langCode: opts.langCode,
    from: (opts.page - 1) * opts.limit + 1,
    to: (opts.page - 1) * opts.limit + 1 + opts.limit
  }
  res.nextLink = res.page === res.totalPages ? false : `${opts.url}/?page=${opts.page + 1}&lang=${opts.langCode}`
  const reqQuestions = file.slice(res.from, res.to)
  res.data = reqQuestions.map(q => { return { id: file.indexOf(q), text: q } })
  return res
}
<commit_msg>Adds id<commit_after>'use strict'

const resolvePath = require('path').resolve
const isFile = require('fs').existsSync

module.exports = opts => {
  const path = resolvePath(`./data/${opts.langCode}/questions.js`)
  const file = isFile(path) ? require(path) : false
  if (!file) {
    return { error: `${path} not found` }
  } else if (opts.page > Math.round(file.length / opts.limit)) {
    return { error: 'Reached page limit' }
  }

  let res = {
    totalQuestions: file.length - 1,
    limit: opts.limit,
    totalPages: Math.round(file.length / opts.limit),
    percentDone: Math.round(opts.page / ((file.length - 1) / opts.limit) * 100),
    page: opts.page,
    langCode: opts.langCode,
    from: (opts.page - 1) * opts.limit + 1,
    to: (opts.page - 1) * opts.limit + 1 + opts.limit
  }
  res.next = res.page === res.totalPages ? false : `${opts.url}/?page=${opts.page + 1}&lang=${opts.langCode}`
  const reqQuestions = file.slice(res.from, res.to)
  res.data = reqQuestions.map(q => { return { id: `Q${file.indexOf(q)}`, num: file.indexOf(q), text: q } })
  return res
}
<|endoftext|>


<commit_before>module.exports = handler

const Busboy = require('busboy')
const debug = require('debug')('solid:post')
const path = require('path')
const header = require('../header')
const patch = require('./patch')
const error = require('../http-error')
const { extensions } = require('mime-types')
const getContentType = require('../utils').getContentType

async function handler (req, res, next) {
  const ldp = req.app.locals.ldp
  const contentType = getContentType(req.headers)
  debug('content-type is ', contentType)
  // Handle SPARQL(-update?) query
  if (contentType === 'application/sparql' ||
      contentType === 'application/sparql-update') {
    debug('switching to sparql query')
    return patch(req, res, next)
  }

  // Handle container path
  let containerPath = req.path
  if (containerPath[containerPath.length - 1] !== '/') {
    containerPath += '/'
  }

  // Check if container exists
  let stats
  try {
    const ret = await ldp.exists(req.hostname, containerPath, false)
    if (ret) {
      stats = ret.stream
    }
  } catch (err) {
    return next(error(err, 'Container not valid'))
  }

  // Check if container is a directory
  if (stats && !stats.isDirectory()) {
    debug('Path is not a container, 405!')
    return next(error(405, 'Requested resource is not a container'))
  }

  // Dispatch to the right handler
  if (req.is('multipart/form-data')) {
    multi()
  } else {
    one()
  }

  function multi () {
    debug('receving multiple files')

    const busboy = new Busboy({ headers: req.headers })
    busboy.on('file', async function (fieldname, file, filename, encoding, mimetype) {
      debug('One file received via multipart: ' + filename)
      const filePath = ldp.resourceMapper._rootPath + path.join(containerPath, filename)
      const { url: putUrl } = await ldp.resourceMapper.mapFileToUrl({ path: filePath, hostname: req.hostname })
      try {
        await ldp.put(putUrl, file, mimetype)
      } catch (err) {
        busboy.emit('error', err)
      }
    })
    busboy.on('error', function (err) {
      debug('Error receiving the file: ' + err.message)
      next(error(500, 'Error receiving the file'))
    })

    // Handled by backpressure of streams!
    busboy.on('finish', function () {
      debug('Done storing files')
      res.sendStatus(200)
      next()
    })
    req.pipe(busboy)
  }

  function one () {
    debug('Receving one file')
    const { slug, link, 'content-type': contentType } = req.headers
    const links = header.parseMetadataFromHeader(link)
    const mimeType = contentType ? contentType.replace(/\s*;.*/, '') : ''
    const extension = mimeType in extensions ? `.${extensions[mimeType][0]}` : ''

    ldp.post(req.hostname, containerPath, req,
      { slug, extension, container: links.isBasicContainer }).then(
      resourcePath => {
        debug('File stored in ' + resourcePath)
        header.addLinks(res, links)
        res.set('Location', resourcePath)
        res.sendStatus(201)
        next()
      },
      err => next(err))
  }
}
<commit_msg>Reverting changes in handlers/post.js<commit_after>module.exports = handler

const Busboy = require('busboy')
const debug = require('debug')('solid:post')
const path = require('path')
const header = require('../header')
const patch = require('./patch')
const error = require('../http-error')
const { extensions } = require('mime-types')
const getContentType = require('../utils').getContentType

async function handler (req, res, next) {
  const ldp = req.app.locals.ldp
  const contentType = getContentType(req.headers)
  debug('content-type is ', contentType)
  // Handle SPARQL(-update?) query
  if (contentType === 'application/sparql' ||
      contentType === 'application/sparql-update') {
    debug('switching to sparql query')
    return patch(req, res, next)
  }

  // Handle container path
  let containerPath = req.path
  if (containerPath[containerPath.length - 1] !== '/') {
    containerPath += '/'
  }

  // Check if container exists
  let stats
  try {
    const ret = await ldp.exists(req.hostname, containerPath, false)
    if (ret) {
      stats = ret.stream
    }
  } catch (err) {
    return next(error(err, 'Container not valid'))
  }

  // Check if container is a directory
  if (stats && !stats.isDirectory()) {
    debug('Path is not a container, 405!')
    return next(error(405, 'Requested resource is not a container'))
  }

  // Dispatch to the right handler
  if (req.is('multipart/form-data')) {
    multi()
  } else {
    one()
  }

  function multi () {
    debug('receving multiple files')

    const busboy = new Busboy({ headers: req.headers })
    busboy.on('file', async function (fieldname, file, filename, encoding, mimetype) {
      debug('One file received via multipart: ' + filename)
      const { url: putUrl } = await ldp.resourceMapper.mapFileToUrl(
        { path: ldp.resourceMapper._rootPath + path.join(containerPath, filename), hostname: req.hostname })
      try {
        await ldp.put(putUrl, file, mimetype)
      } catch (err) {
        busboy.emit('error', err)
      }
    })
    busboy.on('error', function (err) {
      debug('Error receiving the file: ' + err.message)
      next(error(500, 'Error receiving the file'))
    })

    // Handled by backpressure of streams!
    busboy.on('finish', function () {
      debug('Done storing files')
      res.sendStatus(200)
      next()
    })
    req.pipe(busboy)
  }

  function one () {
    debug('Receving one file')
    const { slug, link, 'content-type': contentType } = req.headers
    const links = header.parseMetadataFromHeader(link)
    const mimeType = contentType ? contentType.replace(/\s*;.*/, '') : ''
    const extension = mimeType in extensions ? `.${extensions[mimeType][0]}` : ''

    ldp.post(req.hostname, containerPath, req,
      { slug, extension, container: links.isBasicContainer }).then(
      resourcePath => {
        debug('File stored in ' + resourcePath)
        header.addLinks(res, links)
        res.set('Location', resourcePath)
        res.sendStatus(201)
        next()
      },
      err => next(err))
  }
}
<|endoftext|>


<commit_before>var fs = require('fs'),
  parse = require('./parse'),
  path = require('path'),
  yaml = require('js-yaml');

function isVersionLess(a, b) {
  a = a.split('.').map(Number);
  b = b.split('.').map(Number);

  for (var i = 0; i < 4; i++) {
    if (a[i] != b[i]) {
      return a[i] < b[i];
    }
  }

  return false;
}

function addPlatform(value, platform, version) {
  if (!value.platforms) {
    value.platforms = {};
  }

  if (value.platforms[platform]) {
    if (isVersionLess(version, value.platforms[platform])) {
      value.platforms[platform] = version;
    }
  } else {
    value.platforms[platform] = version;
  }
}

function convertPlatformsToAvailability(value) {
  value.availability = {};

  Object.keys(value.platforms).forEach(function(platform) {
    var version = value.platforms[platform];

    if (!value.availability[version]) {
      value.availability[version] = [];
    }

    value.availability[version].push(platform);
  });

  delete value.platforms;
}

function getPlatform(reportPath, platformNames) {
  var platform = path.basename(reportPath).match(/Language\.(.+)\.txt$/)[1];

  if (!platformNames[platform]) {
    throw new Error('Unknown platform: ' + platform);
  }

  return platformNames[platform];
}

function parseLanguageReports(languageReports, platformNames) {
  var combinedReport = {
    types: {},
    properties: {}
  };

  fs.readdirSync(languageReports).forEach(function(version) {
    var versionPath = path.join(languageReports, version);

    fs.readdirSync(versionPath).forEach(function(reportFile) {
      var reportPath = path.join(versionPath, reportFile);
      var platform = getPlatform(reportPath, platformNames);

      console.error(version + ' - ' + platform);

      var report = parse(fs.readFileSync(reportPath));

      Object.keys(report.types).forEach(function(key) {
        if (!combinedReport.types[key]) {
          combinedReport.types[key] = report.types[key];
        }

        addPlatform(combinedReport.types[key], platform, version);
      });

      Object.keys(report.properties).forEach(function(key) {
        if (!combinedReport.properties[key]) {
          combinedReport.properties[key] = report.properties[key];
        }

        addPlatform(combinedReport.properties[key], platform, version);
      });
    });
  });

  Object.keys(combinedReport.types).forEach(function(key) {
    convertPlatformsToAvailability(combinedReport.types[key]);
  });

  Object.keys(combinedReport.properties).forEach(function(key) {
    convertPlatformsToAvailability(combinedReport.properties[key]);
  });

  return combinedReport;
}

function getPlatformNames() {
  var platformToTargets =
    yaml.safeLoad(fs.readFileSync(path.join(__dirname, 'platforms.yml')));

  var targetToPlatform = {};

  Object.keys(platformToTargets).forEach(function(name) {
    platformToTargets[name].forEach(function(target) {
      targetToPlatform[target] = name;
    })
  });

  return targetToPlatform;
}

function main() {
  if (process.argv.length !== 3) {
    console.error('usage: parse-language-reports <folder>');
    return process.exit(1);
  }

  var language = parseLanguageReports(process.argv[2], getPlatformNames());
  console.log(JSON.stringify(language));
}

if (require.main === module) {
  main();
}

module.exports = parseLanguageReports;
<commit_msg>Sort the platforms<commit_after>var fs = require('fs'),
  parse = require('./parse'),
  path = require('path'),
  yaml = require('js-yaml');

function isVersionLess(a, b) {
  a = a.split('.').map(Number);
  b = b.split('.').map(Number);

  for (var i = 0; i < 4; i++) {
    if (a[i] != b[i]) {
      return a[i] < b[i];
    }
  }

  return false;
}

function addPlatform(value, platform, version) {
  if (!value.platforms) {
    value.platforms = {};
  }

  if (value.platforms[platform]) {
    if (isVersionLess(version, value.platforms[platform])) {
      value.platforms[platform] = version;
    }
  } else {
    value.platforms[platform] = version;
  }
}

function convertPlatformsToAvailability(value) {
  value.availability = {};

  Object.keys(value.platforms).forEach(function(platform) {
    var version = value.platforms[platform];

    if (!value.availability[version]) {
      value.availability[version] = [];
    }

    value.availability[version].push(platform);
  });

  Object.keys(value.availability).forEach(function(version) {
    value.availability[version].sort();
  });

  delete value.platforms;
}

function getPlatform(reportPath, platformNames) {
  var platform = path.basename(reportPath).match(/Language\.(.+)\.txt$/)[1];

  if (!platformNames[platform]) {
    throw new Error('Unknown platform: ' + platform);
  }

  return platformNames[platform];
}

function parseLanguageReports(languageReports, platformNames) {
  var combinedReport = {
    types: {},
    properties: {}
  };

  fs.readdirSync(languageReports).forEach(function(version) {
    var versionPath = path.join(languageReports, version);

    fs.readdirSync(versionPath).forEach(function(reportFile) {
      var reportPath = path.join(versionPath, reportFile);
      var platform = getPlatform(reportPath, platformNames);

      console.error(version + ' - ' + platform);

      var report = parse(fs.readFileSync(reportPath));

      Object.keys(report.types).forEach(function(key) {
        if (!combinedReport.types[key]) {
          combinedReport.types[key] = report.types[key];
        }

        addPlatform(combinedReport.types[key], platform, version);
      });

      Object.keys(report.properties).forEach(function(key) {
        if (!combinedReport.properties[key]) {
          combinedReport.properties[key] = report.properties[key];
        }

        addPlatform(combinedReport.properties[key], platform, version);
      });
    });
  });

  Object.keys(combinedReport.types).forEach(function(key) {
    convertPlatformsToAvailability(combinedReport.types[key]);
  });

  Object.keys(combinedReport.properties).forEach(function(key) {
    convertPlatformsToAvailability(combinedReport.properties[key]);
  });

  return combinedReport;
}

function getPlatformNames() {
  var platformToTargets =
    yaml.safeLoad(fs.readFileSync(path.join(__dirname, 'platforms.yml')));

  var targetToPlatform = {};

  Object.keys(platformToTargets).forEach(function(name) {
    platformToTargets[name].forEach(function(target) {
      targetToPlatform[target] = name;
    })
  });

  return targetToPlatform;
}

function main() {
  if (process.argv.length !== 3) {
    console.error('usage: parse-language-reports <folder>');
    return process.exit(1);
  }

  var language = parseLanguageReports(process.argv[2], getPlatformNames());
  console.log(JSON.stringify(language));
}

if (require.main === module) {
  main();
}

module.exports = parseLanguageReports;
<|endoftext|>


<commit_before>"use strict";

/**
 * @param mailHeader {String} The content of a mail header
 * @return {Object} A correctly parsed mail with name and address keys
 */
module.exports.decomposeMails = function decomposeMails(mailHeader) {
  var pairs = mailHeader.match(/[^,]*?\s<[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}>/gi) || [];
  var parsedMails = pairs.map(function cleanPair(pair) {
    pair = pair.trim().replace(/\\t/, '');
    return {
      name: pair.split('<')[0].trim().replace(/"/g, ""),
      address: pair.split('<')[1].split('>')[0]
    };
  });
  var singles = mailHeader.match(/[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\s*,?/gi) || [];
  parsedMails = parsedMails.concat(singles.map(function cleanMail(mail) {
    return {
      address: mail.replace(/,/, "").trim()
    };
  }));

  for(var i = 0; i < parsedMails.length; i += 1) {
    for(var j = i + 1; j < parsedMails.length; j += 1) {
      if((parsedMails[i].name && parsedMails[i].name === parsedMails[j].name) ||
        (parsedMails[i].address && parsedMails[i].address === parsedMails[j].address)) {
        parsedMails[i].name = parsedMails[i].name || parsedMails[j].name;
        parsedMails[i].address = parsedMails[i].address || parsedMails[j].address;

        parsedMails.splice(j, 1);
      }
    }
  }

  return parsedMails;
};

<commit_msg>Remove email in name<commit_after>"use strict";

/**
 * @param mailHeader {String} The content of a mail header
 * @return {Object} A correctly parsed mail with name and address keys
 */
module.exports.decomposeMails = function decomposeMails(mailHeader) {
  var pairs = mailHeader.match(/[^,]*?\s<[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}>/gi) || [];
  var parsedMails = pairs.map(function cleanPair(pair) {
    pair = pair.trim().replace(/\\t/, '');
    var mail = {
      name: pair.split('<')[0].trim().replace(/"/g, ""),
      address: pair.split('<')[1].split('>')[0]
    };

    if(mail.name === mail.address) {
      delete mail.name;
    }

    return mail;
  });
  var singles = mailHeader.match(/[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\s*,?/gi) || [];
  parsedMails = parsedMails.concat(singles.map(function cleanMail(mail) {
    return {
      address: mail.replace(/,/, "").trim()
    };
  }));

  for(var i = 0; i < parsedMails.length; i += 1) {
    for(var j = i + 1; j < parsedMails.length; j += 1) {
      if((parsedMails[i].name && parsedMails[i].name === parsedMails[j].name) ||
        (parsedMails[i].address && parsedMails[i].address === parsedMails[j].address)) {

        ['name', 'address'].forEach(function(property) {
          parsedMails[i][property] = parsedMails[i][property] || parsedMails[j][property];

          if(!parsedMails[i][property]) {
            delete parsedMails[i][property];
          }
        });

        parsedMails.splice(j, 1);
        j -= 1;
      }
    }
  }

  return parsedMails;
};

<|endoftext|>


<commit_before>(function(){

	// predefine all supported html tags
	tag$.defineTag('fragment', 'htmlelement', function(tag){

		tag.createNode = function (){
			return Imba.document().createDocumentFragment();
		};
	});

	tag$.defineTag('a', function(tag){
		tag.prototype.href = function(v){ return this.getAttribute('href'); }
		tag.prototype.setHref = function(v){ this.setAttribute('href',v); return this; };
	});

	tag$.defineTag('abbr');
	tag$.defineTag('address');
	tag$.defineTag('area');
	tag$.defineTag('article');
	tag$.defineTag('aside');
	tag$.defineTag('audio');
	tag$.defineTag('b');
	tag$.defineTag('base');
	tag$.defineTag('bdi');
	tag$.defineTag('bdo');
	tag$.defineTag('big');
	tag$.defineTag('blockquote');
	tag$.defineTag('body');
	tag$.defineTag('br');

	tag$.defineTag('button', function(tag){
		tag.prototype.autofocus = function(v){ return this.getAttribute('autofocus'); }
		tag.prototype.setAutofocus = function(v){ this.setAttribute('autofocus',v); return this; };
		tag.prototype.type = function(v){ return this.getAttribute('type'); }
		tag.prototype.setType = function(v){ this.setAttribute('type',v); return this; };
		tag.prototype.disabled = function(v){ return this.getAttribute('disabled'); }
		tag.prototype.setDisabled = function(v){ this.setAttribute('disabled',v); return this; };
	});

	tag$.defineTag('canvas', function(tag){
		tag.prototype.setWidth = function (val){
			if (this.width() != val) { this.dom().width = val };
			return this;
		};

		tag.prototype.setHeight = function (val){
			if (this.height() != val) { this.dom().height = val };
			return this;
		};

		tag.prototype.width = function (){
			return this.dom().width;
		};

		tag.prototype.height = function (){
			return this.dom().height;
		};

		tag.prototype.context = function (type){
			if(type === undefined) type = '2d';
			return this.dom().getContext(type);
		};
	});

	tag$.defineTag('caption');
	tag$.defineTag('cite');
	tag$.defineTag('code');
	tag$.defineTag('col');
	tag$.defineTag('colgroup');
	tag$.defineTag('data');
	tag$.defineTag('datalist');
	tag$.defineTag('dd');
	tag$.defineTag('del');
	tag$.defineTag('details');
	tag$.defineTag('dfn');
	tag$.defineTag('div');
	tag$.defineTag('dl');
	tag$.defineTag('dt');
	tag$.defineTag('em');
	tag$.defineTag('embed');
	tag$.defineTag('fieldset');
	tag$.defineTag('figcaption');
	tag$.defineTag('figure');
	tag$.defineTag('footer');

	tag$.defineTag('form', function(tag){
		tag.prototype.method = function(v){ return this.getAttribute('method'); }
		tag.prototype.setMethod = function(v){ this.setAttribute('method',v); return this; };
		tag.prototype.action = function(v){ return this.getAttribute('action'); }
		tag.prototype.setAction = function(v){ this.setAttribute('action',v); return this; };
	});

	tag$.defineTag('h1');
	tag$.defineTag('h2');
	tag$.defineTag('h3');
	tag$.defineTag('h4');
	tag$.defineTag('h5');
	tag$.defineTag('h6');
	tag$.defineTag('head');
	tag$.defineTag('header');
	tag$.defineTag('hr');
	tag$.defineTag('html');
	tag$.defineTag('i');

	tag$.defineTag('iframe', function(tag){
		tag.prototype.src = function(v){ return this.getAttribute('src'); }
		tag.prototype.setSrc = function(v){ this.setAttribute('src',v); return this; };
	});

	tag$.defineTag('img', function(tag){
		tag.prototype.src = function(v){ return this.getAttribute('src'); }
		tag.prototype.setSrc = function(v){ this.setAttribute('src',v); return this; };
	});

	tag$.defineTag('input', function(tag){
		// can use attr instead
		tag.prototype.name = function(v){ return this.getAttribute('name'); }
		tag.prototype.setName = function(v){ this.setAttribute('name',v); return this; };
		tag.prototype.type = function(v){ return this.getAttribute('type'); }
		tag.prototype.setType = function(v){ this.setAttribute('type',v); return this; };
		tag.prototype.required = function(v){ return this.getAttribute('required'); }
		tag.prototype.setRequired = function(v){ this.setAttribute('required',v); return this; };
		tag.prototype.disabled = function(v){ return this.getAttribute('disabled'); }
		tag.prototype.setDisabled = function(v){ this.setAttribute('disabled',v); return this; };
		tag.prototype.autofocus = function(v){ return this.getAttribute('autofocus'); }
		tag.prototype.setAutofocus = function(v){ this.setAttribute('autofocus',v); return this; };

		tag.prototype.value = function (){
			return this.dom().value;
		};

		tag.prototype.setValue = function (v){
			if (v != this.dom().value) { this.dom().value = v };
			return this;
		};

		tag.prototype.setPlaceholder = function (v){
			if (v != this.dom().placeholder) { this.dom().placeholder = v };
			return this;
		};

		tag.prototype.placeholder = function (){
			return this.dom().placeholder;
		};

		tag.prototype.checked = function (){
			return this.dom().checked;
		};

		tag.prototype.setChecked = function (bool){
			if (bool != this.dom().checked) { this.dom().checked = bool };
			return this;
		};
	});

	tag$.defineTag('ins');
	tag$.defineTag('kbd');
	tag$.defineTag('keygen');
	tag$.defineTag('label');
	tag$.defineTag('legend');
	tag$.defineTag('li');

	tag$.defineTag('link', function(tag){
		tag.prototype.rel = function(v){ return this.getAttribute('rel'); }
		tag.prototype.setRel = function(v){ this.setAttribute('rel',v); return this; };
		tag.prototype.type = function(v){ return this.getAttribute('type'); }
		tag.prototype.setType = function(v){ this.setAttribute('type',v); return this; };
		tag.prototype.href = function(v){ return this.getAttribute('href'); }
		tag.prototype.setHref = function(v){ this.setAttribute('href',v); return this; };
		tag.prototype.media = function(v){ return this.getAttribute('media'); }
		tag.prototype.setMedia = function(v){ this.setAttribute('media',v); return this; };
	});

	tag$.defineTag('main');
	tag$.defineTag('map');
	tag$.defineTag('mark');
	tag$.defineTag('menu');
	tag$.defineTag('menuitem');

	tag$.defineTag('meta', function(tag){
		tag.prototype.name = function(v){ return this.getAttribute('name'); }
		tag.prototype.setName = function(v){ this.setAttribute('name',v); return this; };
		tag.prototype.content = function(v){ return this.getAttribute('content'); }
		tag.prototype.setContent = function(v){ this.setAttribute('content',v); return this; };
		tag.prototype.charset = function(v){ return this.getAttribute('charset'); }
		tag.prototype.setCharset = function(v){ this.setAttribute('charset',v); return this; };
	});

	tag$.defineTag('meter');
	tag$.defineTag('nav');
	tag$.defineTag('noscript');
	tag$.defineTag('object');
	tag$.defineTag('ol');
	tag$.defineTag('optgroup');

	tag$.defineTag('option', function(tag){
		tag.prototype.value = function(v){ return this.getAttribute('value'); }
		tag.prototype.setValue = function(v){ this.setAttribute('value',v); return this; };
	});

	tag$.defineTag('output');
	tag$.defineTag('p');
	tag$.defineTag('param');
	tag$.defineTag('pre');
	tag$.defineTag('progress');
	tag$.defineTag('q');
	tag$.defineTag('rp');
	tag$.defineTag('rt');
	tag$.defineTag('ruby');
	tag$.defineTag('s');
	tag$.defineTag('samp');

	tag$.defineTag('script', function(tag){
		tag.prototype.src = function(v){ return this.getAttribute('src'); }
		tag.prototype.setSrc = function(v){ this.setAttribute('src',v); return this; };
		tag.prototype.type = function(v){ return this.getAttribute('type'); }
		tag.prototype.setType = function(v){ this.setAttribute('type',v); return this; };
		tag.prototype.async = function(v){ return this.getAttribute('async'); }
		tag.prototype.setAsync = function(v){ this.setAttribute('async',v); return this; };
		tag.prototype.defer = function(v){ return this.getAttribute('defer'); }
		tag.prototype.setDefer = function(v){ this.setAttribute('defer',v); return this; };
	});

	tag$.defineTag('section');

	tag$.defineTag('select', function(tag){
		tag.prototype.name = function(v){ return this.getAttribute('name'); }
		tag.prototype.setName = function(v){ this.setAttribute('name',v); return this; };
		tag.prototype.multiple = function(v){ return this.getAttribute('multiple'); }
		tag.prototype.setMultiple = function(v){ this.setAttribute('multiple',v); return this; };
		tag.prototype.required = function(v){ return this.getAttribute('required'); }
		tag.prototype.setRequired = function(v){ this.setAttribute('required',v); return this; };
		tag.prototype.disabled = function(v){ return this.getAttribute('disabled'); }
		tag.prototype.setDisabled = function(v){ this.setAttribute('disabled',v); return this; };

		tag.prototype.value = function (){
			return this.dom().value;
		};

		tag.prototype.setValue = function (v){
			if (v != this.dom().value) { this.dom().value = v };
			return this;
		};
	});

	tag$.defineTag('small');
	tag$.defineTag('source');
	tag$.defineTag('span');
	tag$.defineTag('strong');
	tag$.defineTag('style');
	tag$.defineTag('sub');
	tag$.defineTag('summary');
	tag$.defineTag('sup');
	tag$.defineTag('table');
	tag$.defineTag('tbody');
	tag$.defineTag('td');

	tag$.defineTag('textarea', function(tag){
		tag.prototype.name = function(v){ return this.getAttribute('name'); }
		tag.prototype.setName = function(v){ this.setAttribute('name',v); return this; };
		tag.prototype.disabled = function(v){ return this.getAttribute('disabled'); }
		tag.prototype.setDisabled = function(v){ this.setAttribute('disabled',v); return this; };
		tag.prototype.required = function(v){ return this.getAttribute('required'); }
		tag.prototype.setRequired = function(v){ this.setAttribute('required',v); return this; };
		tag.prototype.rows = function(v){ return this.getAttribute('rows'); }
		tag.prototype.setRows = function(v){ this.setAttribute('rows',v); return this; };
		tag.prototype.cols = function(v){ return this.getAttribute('cols'); }
		tag.prototype.setCols = function(v){ this.setAttribute('cols',v); return this; };
		tag.prototype.autofocus = function(v){ return this.getAttribute('autofocus'); }
		tag.prototype.setAutofocus = function(v){ this.setAttribute('autofocus',v); return this; };

		tag.prototype.value = function (){
			return this.dom().value;
		};

		tag.prototype.setValue = function (v){
			if (v != this.dom().value) { this.dom().value = v };
			return this;
		};

		tag.prototype.setPlaceholder = function (v){
			if (v != this.dom().placeholder) { this.dom().placeholder = v };
			return this;
		};

		tag.prototype.placeholder = function (){
			return this.dom().placeholder;
		};
	});

	tag$.defineTag('tfoot');
	tag$.defineTag('th');
	tag$.defineTag('thead');
	tag$.defineTag('time');
	tag$.defineTag('title');
	tag$.defineTag('tr');
	tag$.defineTag('track');
	tag$.defineTag('u');
	tag$.defineTag('ul');
	tag$.defineTag('video');
	return tag$.defineTag('wbr');

})()<commit_msg>recompile dom.html.js<commit_after>(function(){

	// predefine all supported html tags
	tag$.defineTag('fragment', 'htmlelement', function(tag){

		tag.createNode = function (){
			return Imba.document().createDocumentFragment();
		};
	});

	tag$.defineTag('a', function(tag){
		tag.prototype.href = function(v){ return this.getAttribute('href'); }
		tag.prototype.setHref = function(v){ this.setAttribute('href',v); return this; };
	});

	tag$.defineTag('abbr');
	tag$.defineTag('address');
	tag$.defineTag('area');
	tag$.defineTag('article');
	tag$.defineTag('aside');
	tag$.defineTag('audio');
	tag$.defineTag('b');
	tag$.defineTag('base');
	tag$.defineTag('bdi');
	tag$.defineTag('bdo');
	tag$.defineTag('big');
	tag$.defineTag('blockquote');
	tag$.defineTag('body');
	tag$.defineTag('br');

	tag$.defineTag('button', function(tag){
		tag.prototype.autofocus = function(v){ return this.getAttribute('autofocus'); }
		tag.prototype.setAutofocus = function(v){ this.setAttribute('autofocus',v); return this; };
		tag.prototype.type = function(v){ return this.getAttribute('type'); }
		tag.prototype.setType = function(v){ this.setAttribute('type',v); return this; };
		tag.prototype.disabled = function(v){ return this.getAttribute('disabled'); }
		tag.prototype.setDisabled = function(v){ this.setAttribute('disabled',v); return this; };
	});

	tag$.defineTag('canvas', function(tag){
		tag.prototype.setWidth = function (val){
			if (this.width() != val) { this.dom().width = val };
			return this;
		};

		tag.prototype.setHeight = function (val){
			if (this.height() != val) { this.dom().height = val };
			return this;
		};

		tag.prototype.width = function (){
			return this.dom().width;
		};

		tag.prototype.height = function (){
			return this.dom().height;
		};

		tag.prototype.context = function (type){
			if(type === undefined) type = '2d';
			return this.dom().getContext(type);
		};
	});

	tag$.defineTag('caption');
	tag$.defineTag('cite');
	tag$.defineTag('code');
	tag$.defineTag('col');
	tag$.defineTag('colgroup');
	tag$.defineTag('data');
	tag$.defineTag('datalist');
	tag$.defineTag('dd');
	tag$.defineTag('del');
	tag$.defineTag('details');
	tag$.defineTag('dfn');
	tag$.defineTag('div');
	tag$.defineTag('dl');
	tag$.defineTag('dt');
	tag$.defineTag('em');
	tag$.defineTag('embed');
	tag$.defineTag('fieldset');
	tag$.defineTag('figcaption');
	tag$.defineTag('figure');
	tag$.defineTag('footer');

	tag$.defineTag('form', function(tag){
		tag.prototype.method = function(v){ return this.getAttribute('method'); }
		tag.prototype.setMethod = function(v){ this.setAttribute('method',v); return this; };
		tag.prototype.action = function(v){ return this.getAttribute('action'); }
		tag.prototype.setAction = function(v){ this.setAttribute('action',v); return this; };
	});

	tag$.defineTag('h1');
	tag$.defineTag('h2');
	tag$.defineTag('h3');
	tag$.defineTag('h4');
	tag$.defineTag('h5');
	tag$.defineTag('h6');
	tag$.defineTag('head');
	tag$.defineTag('header');
	tag$.defineTag('hr');
	tag$.defineTag('html');
	tag$.defineTag('i');

	tag$.defineTag('iframe', function(tag){
		tag.prototype.src = function(v){ return this.getAttribute('src'); }
		tag.prototype.setSrc = function(v){ this.setAttribute('src',v); return this; };
	});

	tag$.defineTag('img', function(tag){
		tag.prototype.src = function(v){ return this.getAttribute('src'); }
		tag.prototype.setSrc = function(v){ this.setAttribute('src',v); return this; };
	});

	tag$.defineTag('input', function(tag){
		// can use attr instead
		tag.prototype.name = function(v){ return this.getAttribute('name'); }
		tag.prototype.setName = function(v){ this.setAttribute('name',v); return this; };
		tag.prototype.type = function(v){ return this.getAttribute('type'); }
		tag.prototype.setType = function(v){ this.setAttribute('type',v); return this; };
		tag.prototype.required = function(v){ return this.getAttribute('required'); }
		tag.prototype.setRequired = function(v){ this.setAttribute('required',v); return this; };
		tag.prototype.disabled = function(v){ return this.getAttribute('disabled'); }
		tag.prototype.setDisabled = function(v){ this.setAttribute('disabled',v); return this; };
		tag.prototype.autofocus = function(v){ return this.getAttribute('autofocus'); }
		tag.prototype.setAutofocus = function(v){ this.setAttribute('autofocus',v); return this; };

		tag.prototype.value = function (){
			return this.dom().value;
		};

		tag.prototype.setValue = function (v){
			if (v != this.dom().value) { this.dom().value = v };
			return this;
		};

		tag.prototype.setPlaceholder = function (v){
			if (v != this.dom().placeholder) { this.dom().placeholder = v };
			return this;
		};

		tag.prototype.placeholder = function (){
			return this.dom().placeholder;
		};

		tag.prototype.checked = function (){
			return this.dom().checked;
		};

		tag.prototype.setChecked = function (bool){
			if (bool != this.dom().checked) { this.dom().checked = bool };
			return this;
		};
	});

	tag$.defineTag('ins');
	tag$.defineTag('kbd');
	tag$.defineTag('keygen');
	tag$.defineTag('label');
	tag$.defineTag('legend');
	tag$.defineTag('li');

	tag$.defineTag('link', function(tag){
		tag.prototype.rel = function(v){ return this.getAttribute('rel'); }
		tag.prototype.setRel = function(v){ this.setAttribute('rel',v); return this; };
		tag.prototype.type = function(v){ return this.getAttribute('type'); }
		tag.prototype.setType = function(v){ this.setAttribute('type',v); return this; };
		tag.prototype.href = function(v){ return this.getAttribute('href'); }
		tag.prototype.setHref = function(v){ this.setAttribute('href',v); return this; };
		tag.prototype.media = function(v){ return this.getAttribute('media'); }
		tag.prototype.setMedia = function(v){ this.setAttribute('media',v); return this; };
	});

	tag$.defineTag('main');
	tag$.defineTag('map');
	tag$.defineTag('mark');
	tag$.defineTag('menu');
	tag$.defineTag('menuitem');

	tag$.defineTag('meta', function(tag){
		tag.prototype.name = function(v){ return this.getAttribute('name'); }
		tag.prototype.setName = function(v){ this.setAttribute('name',v); return this; };
		tag.prototype.content = function(v){ return this.getAttribute('content'); }
		tag.prototype.setContent = function(v){ this.setAttribute('content',v); return this; };
		tag.prototype.charset = function(v){ return this.getAttribute('charset'); }
		tag.prototype.setCharset = function(v){ this.setAttribute('charset',v); return this; };
	});

	tag$.defineTag('meter');
	tag$.defineTag('nav');
	tag$.defineTag('noscript');
	tag$.defineTag('object');
	tag$.defineTag('ol');
	tag$.defineTag('optgroup');

	tag$.defineTag('option', function(tag){
		tag.prototype.value = function(v){ return this.getAttribute('value'); }
		tag.prototype.setValue = function(v){ this.setAttribute('value',v); return this; };

		tag.prototype.selected = function (){
			return this.dom().selected;
		};

		tag.prototype.setSelected = function (bool){
			if (bool != this.dom().selected) { this.dom().selected = bool };
			return this;
		};
	});

	tag$.defineTag('output');
	tag$.defineTag('p');
	tag$.defineTag('param');
	tag$.defineTag('pre');
	tag$.defineTag('progress');
	tag$.defineTag('q');
	tag$.defineTag('rp');
	tag$.defineTag('rt');
	tag$.defineTag('ruby');
	tag$.defineTag('s');
	tag$.defineTag('samp');

	tag$.defineTag('script', function(tag){
		tag.prototype.src = function(v){ return this.getAttribute('src'); }
		tag.prototype.setSrc = function(v){ this.setAttribute('src',v); return this; };
		tag.prototype.type = function(v){ return this.getAttribute('type'); }
		tag.prototype.setType = function(v){ this.setAttribute('type',v); return this; };
		tag.prototype.async = function(v){ return this.getAttribute('async'); }
		tag.prototype.setAsync = function(v){ this.setAttribute('async',v); return this; };
		tag.prototype.defer = function(v){ return this.getAttribute('defer'); }
		tag.prototype.setDefer = function(v){ this.setAttribute('defer',v); return this; };
	});

	tag$.defineTag('section');

	tag$.defineTag('select', function(tag){
		tag.prototype.name = function(v){ return this.getAttribute('name'); }
		tag.prototype.setName = function(v){ this.setAttribute('name',v); return this; };
		tag.prototype.multiple = function(v){ return this.getAttribute('multiple'); }
		tag.prototype.setMultiple = function(v){ this.setAttribute('multiple',v); return this; };
		tag.prototype.required = function(v){ return this.getAttribute('required'); }
		tag.prototype.setRequired = function(v){ this.setAttribute('required',v); return this; };
		tag.prototype.disabled = function(v){ return this.getAttribute('disabled'); }
		tag.prototype.setDisabled = function(v){ this.setAttribute('disabled',v); return this; };

		tag.prototype.value = function (){
			return this.dom().value;
		};

		tag.prototype.setValue = function (v){
			if (v != this.dom().value) { this.dom().value = v };
			return this;
		};
	});

	tag$.defineTag('small');
	tag$.defineTag('source');
	tag$.defineTag('span');
	tag$.defineTag('strong');
	tag$.defineTag('style');
	tag$.defineTag('sub');
	tag$.defineTag('summary');
	tag$.defineTag('sup');
	tag$.defineTag('table');
	tag$.defineTag('tbody');
	tag$.defineTag('td');

	tag$.defineTag('textarea', function(tag){
		tag.prototype.name = function(v){ return this.getAttribute('name'); }
		tag.prototype.setName = function(v){ this.setAttribute('name',v); return this; };
		tag.prototype.disabled = function(v){ return this.getAttribute('disabled'); }
		tag.prototype.setDisabled = function(v){ this.setAttribute('disabled',v); return this; };
		tag.prototype.required = function(v){ return this.getAttribute('required'); }
		tag.prototype.setRequired = function(v){ this.setAttribute('required',v); return this; };
		tag.prototype.rows = function(v){ return this.getAttribute('rows'); }
		tag.prototype.setRows = function(v){ this.setAttribute('rows',v); return this; };
		tag.prototype.cols = function(v){ return this.getAttribute('cols'); }
		tag.prototype.setCols = function(v){ this.setAttribute('cols',v); return this; };
		tag.prototype.autofocus = function(v){ return this.getAttribute('autofocus'); }
		tag.prototype.setAutofocus = function(v){ this.setAttribute('autofocus',v); return this; };

		tag.prototype.value = function (){
			return this.dom().value;
		};

		tag.prototype.setValue = function (v){
			if (v != this.dom().value) { this.dom().value = v };
			return this;
		};

		tag.prototype.setPlaceholder = function (v){
			if (v != this.dom().placeholder) { this.dom().placeholder = v };
			return this;
		};

		tag.prototype.placeholder = function (){
			return this.dom().placeholder;
		};
	});

	tag$.defineTag('tfoot');
	tag$.defineTag('th');
	tag$.defineTag('thead');
	tag$.defineTag('time');
	tag$.defineTag('title');
	tag$.defineTag('tr');
	tag$.defineTag('track');
	tag$.defineTag('u');
	tag$.defineTag('ul');
	tag$.defineTag('video');
	return tag$.defineTag('wbr');

})()<|endoftext|>