<commit_before>var fs = require('fs');
var path = require('path');
var through = require('through2');
var PassThrough = require('stream').PassThrough;
var asyncFilter = require('async-filter');
var tryall = require('tryall');
var mkdirp = require('mkdirp');
var twelveHoursInSeconds = 43200;

/**
 * Create a new StreamCache (or attach to an existing one)
 *
 * @constructor
 * @param {String} rootDirectory The directory in which to store cached objects.
 */
function StreamCache(rootDirectory, options) {
	this.rootCacheDirectory = rootDirectory;
	options = options || {};
	this.defaultTtl = options.defaultTtl || twelveHoursInSeconds;
	this.serveStale = options.serveStale || false;

	// TODO: Where's best to handle errors here?
	// Ensure the rootCacheDirectory is present.
	this.ready = new Promise(function(resolve, reject) {
		mkdirp(this.rootCacheDirectory, function(e) {
			if (e) {
				reject(e);
			} else {
				resolve();
			}
		});
	}.bind(this));
}

StreamCache.prototype.getMetaData = function(identifier) {
	var cachedObjectPath = this._getCachedObjectPath(identifier);
	var cache = this;

	return this._getReadFileDescriptor(identifier).then(function(fd) {
		return cache._getMetaDataUsingFileDescriptor(fd);
	});
};

StreamCache.prototype._getMetaDataUsingFileDescriptor = function(fd) {
	return new Promise(function(resolve, reject) {
		fs.fstat(fd, function(err, stat) {
			if (err) {
				reject(err);
				return;
			}

			var lastModified = (stat.mtime.getTime() / 1000)|0;
			var timeNowInSeconds = ((Date.now() / 1000)|0);

			resolve({
				age: timeNowInSeconds - lastModified,
				firstCreated: (stat.birthtime.getTime() / 1000)|0,
				lastModified: lastModified
			});
		});
	});
};

/**
 * Get a Stream from the cache, if the stream doesn't exist, create it via the
 * callback and cache it.
 *
 * @param {String} identifier                     The cache key.
 * @param {Object} options                        The options object.
 * @param {Function -> ReadStream} createCallback A function that can be used to create a new object if the cache key is empty.
 * @return {ReadStream}
 */
StreamCache.prototype.get = function(identifier, options, createCallback) {
	// Create a PassThrough stream (https://nodejs.org/api/stream.html#stream_class_stream_passthrough)
	// and attach the cache stream or the writeThrough stream to it once the
	// cached object has been looked up.

	var cache = this;
	var passThroughStream = new PassThrough();

	cache._read(identifier, options).then(function(stream) {
		if (!stream) {
			var newStream;

			try {
				newStream = createCallback();
			} catch(err) {
				passThroughStream.emit('error', err);
				throw err;
			}

			cache.writeThrough(identifier, newStream).pipe(passThroughStream);
		} else {
			stream.pipe(passThroughStream);
		}
	});

	return passThroughStream;
};

/**
 * Purge the cache based on the filter function.  The function will take a
 * single argument of the cache key.  The function can then return true, if the
 * key should remain in the cache or false if the cache key should be purged.
 *
 * @example Purge everything in the cache
 *
 * cache.purge(function() { return true; });
 *
 * @param {Function} callback The filter function to determine whether the
 *                            cache key should be purged.
 */
StreamCache.prototype.purge = function(callback) {
	var cache = this;
	return new Promise(function(resolve, reject) {
		// Read the files that exist in the cache directory
		fs.readdir(cache.rootCacheDirectory, function(err, files) {
			if (err) {
				reject(err);
			}

			// Filter based on the callback function
			var filesToPurgePromise = asyncFilter(files, function(item) {
				var callbackResult = callback(item);
				return Promise.resolve(callbackResult);
			});

			// Try and purge all of the cached objects.  `tryall` will try
			// every promise and collect erroring promises as part of it's
			// resolved value rather than throwing.
			resolve(filesToPurgePromise.then(function(filesToPurge) {
				return tryall(filesToPurge.map(function(file) {
					return new Promise(function(innerResolve, innerReject) {
						fs.unlink(cache._getCachedObjectPath(file), function(err) {
							if (err) {
								innerReject(err);
							} else {
								innerResolve(true);
							}
						});
					});
				}));
			}));
		});
	});
};

/**
 * Return a stream if the requested cache key exists, or boolean false if the
 * cache key does not exist in the cache.
 *
 * @param {String} identifier    The cache key.
 * @param {Object} options       Additional options.
 * @param {Date}   options.newer Than Only return cached objects that are newer
 *                               than this time
 *
 * @return {Promise<{(ReadStream | Boolean)}>} A promise containing the stream
 *                                             from the cache.
 */
StreamCache.prototype._read = function(identifier, options) {
	var cachedObjectPath = this._getCachedObjectPath(identifier);
	var cache = this;

	return this._getReadFileDescriptor(identifier).then(function(fd) {
		return cache._isStale(fd).then(function(isStale) {
			if (isStale) {
				return false;
			} else {
				// First argument of fs.createReadStream is ignored
				// because the 'fd' is present
				return fs.createReadStream(false, { fd: fd, autoClose: true });
			}
		});

	}).catch(function(e) {
		return false;
	});
};

StreamCache.prototype.isStale = function(identifier) {
	var cache = this;
	return this._getReadFileDescriptor(identifier).then(function(fd) {
		return cache._isStale(fd);
	});
};

StreamCache.prototype._isStale = function(fd) {
	var defaultTtl = this.defaultTtl;

	return this._getMetaDataUsingFileDescriptor(fd).then(function(metadata) {
		return metadata.age > defaultTtl;
	});
};

StreamCache.prototype._getReadFileDescriptor = function(identifier, options) {
	var cachedObjectPath = this._getCachedObjectPath(identifier);

	return new Promise(function(resolve, reject) {
		fs.open(cachedObjectPath, 'r', function(e, fd) {
			if (e) {
				reject(e);
				return;
			}

			resolve(fd);
		});
	});
};

/**
 * Write a stream's content to the cache transparently, the returned stream is
 * equivalent.
 *
 * @param   {String}    identifier The cache key to store the cached object at
 * @param  {ReadStream} stream     The stream to cache, the return value is
 *                                 equivalent to this stream.
 * @return {ReadStream} Returns a stream equivalent to the stream passed to this method.
 */
StreamCache.prototype.writeThrough = function(identifier, stream) {
	var cachedObjectPath = this._getCachedObjectPath(identifier);

	var cacheStream = this.ready.then(function() {
		return fs.createWriteStream(cachedObjectPath);
	});

	stream.on('error', function(err) {
		cacheStream.then(function(s) { s.end();
			fs.unlink(cachedObjectPath, function(e) {
			});
		});
		cachedStream.emit('error', err);
	});

	var cachedStream = stream.pipe(through(function(chunk, enc, callback) {
		this.push(chunk, enc);

		cacheStream.then(function(cache) {
			cache.write(chunk, enc);
		});

		callback();
	}, function flush(callback) {
		cacheStream.then(function(stream) {
			stream.end();
			callback();
		});
	}));

	return cachedStream;
};

StreamCache.prototype._getCachedObjectPath = function(identifier) {

	// resolving the identifier against the root filesystem directory prevents directory
	// traversal attacks
	return path.join(this.rootCacheDirectory, path.resolve('/', identifier));
};

module.exports = StreamCache;
<commit_msg>Unused variable<commit_after>var fs = require('fs');
var path = require('path');
var through = require('through2');
var PassThrough = require('stream').PassThrough;
var asyncFilter = require('async-filter');
var tryall = require('tryall');
var mkdirp = require('mkdirp');
var twelveHoursInSeconds = 43200;

/**
 * Create a new StreamCache (or attach to an existing one)
 *
 * @constructor
 * @param {String} rootDirectory The directory in which to store cached objects.
 */
function StreamCache(rootDirectory, options) {
	this.rootCacheDirectory = rootDirectory;
	options = options || {};
	this.defaultTtl = options.defaultTtl || twelveHoursInSeconds;

	// TODO: Where's best to handle errors here?
	// Ensure the rootCacheDirectory is present.
	this.ready = new Promise(function(resolve, reject) {
		mkdirp(this.rootCacheDirectory, function(e) {
			if (e) {
				reject(e);
			} else {
				resolve();
			}
		});
	}.bind(this));
}

StreamCache.prototype.getMetaData = function(identifier) {
	var cachedObjectPath = this._getCachedObjectPath(identifier);
	var cache = this;

	return this._getReadFileDescriptor(identifier).then(function(fd) {
		return cache._getMetaDataUsingFileDescriptor(fd);
	});
};

StreamCache.prototype._getMetaDataUsingFileDescriptor = function(fd) {
	return new Promise(function(resolve, reject) {
		fs.fstat(fd, function(err, stat) {
			if (err) {
				reject(err);
				return;
			}

			var lastModified = (stat.mtime.getTime() / 1000)|0;
			var timeNowInSeconds = ((Date.now() / 1000)|0);

			resolve({
				age: timeNowInSeconds - lastModified,
				firstCreated: (stat.birthtime.getTime() / 1000)|0,
				lastModified: lastModified
			});
		});
	});
};

/**
 * Get a Stream from the cache, if the stream doesn't exist, create it via the
 * callback and cache it.
 *
 * @param {String} identifier                     The cache key.
 * @param {Object} options                        The options object.
 * @param {Function -> ReadStream} createCallback A function that can be used to create a new object if the cache key is empty.
 * @return {ReadStream}
 */
StreamCache.prototype.get = function(identifier, options, createCallback) {
	// Create a PassThrough stream (https://nodejs.org/api/stream.html#stream_class_stream_passthrough)
	// and attach the cache stream or the writeThrough stream to it once the
	// cached object has been looked up.

	var cache = this;
	var passThroughStream = new PassThrough();

	cache._read(identifier, options).then(function(stream) {
		if (!stream) {
			var newStream;

			try {
				newStream = createCallback();
			} catch(err) {
				passThroughStream.emit('error', err);
				throw err;
			}

			cache.writeThrough(identifier, newStream).pipe(passThroughStream);
		} else {
			stream.pipe(passThroughStream);
		}
	});

	return passThroughStream;
};

/**
 * Purge the cache based on the filter function.  The function will take a
 * single argument of the cache key.  The function can then return true, if the
 * key should remain in the cache or false if the cache key should be purged.
 *
 * @example Purge everything in the cache
 *
 * cache.purge(function() { return true; });
 *
 * @param {Function} callback The filter function to determine whether the
 *                            cache key should be purged.
 */
StreamCache.prototype.purge = function(callback) {
	var cache = this;
	return new Promise(function(resolve, reject) {
		// Read the files that exist in the cache directory
		fs.readdir(cache.rootCacheDirectory, function(err, files) {
			if (err) {
				reject(err);
			}

			// Filter based on the callback function
			var filesToPurgePromise = asyncFilter(files, function(item) {
				var callbackResult = callback(item);
				return Promise.resolve(callbackResult);
			});

			// Try and purge all of the cached objects.  `tryall` will try
			// every promise and collect erroring promises as part of it's
			// resolved value rather than throwing.
			resolve(filesToPurgePromise.then(function(filesToPurge) {
				return tryall(filesToPurge.map(function(file) {
					return new Promise(function(innerResolve, innerReject) {
						fs.unlink(cache._getCachedObjectPath(file), function(err) {
							if (err) {
								innerReject(err);
							} else {
								innerResolve(true);
							}
						});
					});
				}));
			}));
		});
	});
};

/**
 * Return a stream if the requested cache key exists, or boolean false if the
 * cache key does not exist in the cache.
 *
 * @param {String} identifier    The cache key.
 * @param {Object} options       Additional options.
 * @param {Date}   options.newer Than Only return cached objects that are newer
 *                               than this time
 *
 * @return {Promise<{(ReadStream | Boolean)}>} A promise containing the stream
 *                                             from the cache.
 */
StreamCache.prototype._read = function(identifier, options) {
	var cachedObjectPath = this._getCachedObjectPath(identifier);
	var cache = this;

	return this._getReadFileDescriptor(identifier).then(function(fd) {
		return cache._isStale(fd).then(function(isStale) {
			if (isStale) {
				return false;
			} else {
				// First argument of fs.createReadStream is ignored
				// because the 'fd' is present
				return fs.createReadStream(false, { fd: fd, autoClose: true });
			}
		});

	}).catch(function(e) {
		return false;
	});
};

StreamCache.prototype.isStale = function(identifier) {
	var cache = this;
	return this._getReadFileDescriptor(identifier).then(function(fd) {
		return cache._isStale(fd);
	});
};

StreamCache.prototype._isStale = function(fd) {
	var defaultTtl = this.defaultTtl;

	return this._getMetaDataUsingFileDescriptor(fd).then(function(metadata) {
		return metadata.age > defaultTtl;
	});
};

StreamCache.prototype._getReadFileDescriptor = function(identifier, options) {
	var cachedObjectPath = this._getCachedObjectPath(identifier);

	return new Promise(function(resolve, reject) {
		fs.open(cachedObjectPath, 'r', function(e, fd) {
			if (e) {
				reject(e);
				return;
			}

			resolve(fd);
		});
	});
};

/**
 * Write a stream's content to the cache transparently, the returned stream is
 * equivalent.
 *
 * @param   {String}    identifier The cache key to store the cached object at
 * @param  {ReadStream} stream     The stream to cache, the return value is
 *                                 equivalent to this stream.
 * @return {ReadStream} Returns a stream equivalent to the stream passed to this method.
 */
StreamCache.prototype.writeThrough = function(identifier, stream) {
	var cachedObjectPath = this._getCachedObjectPath(identifier);

	var cacheStream = this.ready.then(function() {
		return fs.createWriteStream(cachedObjectPath);
	});

	stream.on('error', function(err) {
		cacheStream.then(function(s) { s.end();
			fs.unlink(cachedObjectPath, function(e) {
			});
		});
		cachedStream.emit('error', err);
	});

	var cachedStream = stream.pipe(through(function(chunk, enc, callback) {
		this.push(chunk, enc);

		cacheStream.then(function(cache) {
			cache.write(chunk, enc);
		});

		callback();
	}, function flush(callback) {
		cacheStream.then(function(stream) {
			stream.end();
			callback();
		});
	}));

	return cachedStream;
};

StreamCache.prototype._getCachedObjectPath = function(identifier) {

	// resolving the identifier against the root filesystem directory prevents directory
	// traversal attacks
	return path.join(this.rootCacheDirectory, path.resolve('/', identifier));
};

module.exports = StreamCache;
<|endoftext|>


<commit_before>var fs = require('fs')
var path = require('path')
var postcss = require('postcss')
var ejs = require('ejs')
var nano = require('cssnano')
var mkdirp = require('mkdirp')
var annotation = require('css-annotation')
var themeDir = require('psg-theme-default')

var mdParse = require('./lib/md_parse')
var highlight = require('./lib/css_highlight')

module.exports = postcss.plugin('postcss-style-guide', function (options) {

    if (typeof(arguments[0]) === 'object') {
        options = arguments[0]
    }

    options = options || {}
    options.theme = options.theme !== undefined ? options.theme : 'default'
    options.name = options.name !== undefined ? options.name : 'Style Guide'
    options.file = options.file !== undefined ? options.file : 'styleguide'
    options.dir = options.dir !== undefined ? options.dir : 'docs'
    options.showCode = options.showCode !== undefined ? options.showCode : true

    var themeName = 'psg-theme-' + options.theme
    var themePath
    if (options.theme === 'default') {
        themePath = themeDir
    }
    else {
        themePath = path.join('node_modules', themeName)
    }

    options.template = fs.readFileSync(themePath + '/template.ejs', 'utf-8').trim()
    options.style = fs.readFileSync(themePath + '/style.css', 'utf-8').trim()

    var maps = []
    return function (root) {
        options.processedCSS = options.processedCSS !== undefined ? options.processedCSS : root.toString().trim()

        root.walkComments(function (comment) {

            var meta = annotation.read(comment.text)

            if (meta.documents || meta.document || meta.docs || meta.doc || meta.styleguide) {
                comment.text = comment.text.replace(/(@document|@doc|@docs|@styleguide)\s*\n/, '')

                if (comment.parent.type === 'root') {
                    var rule = comment.next()
                    var tmp = []
                    while (rule !== null && (rule.type === 'rule' || rule.type === 'atrule')) {
                        tmp.push(rule.toString().trim())
                        rule = rule.next() || null
                    }

                    var tmplRule = tmp.join('\n')
                    maps.push({
                        rule: highlight(tmplRule),
                        html: mdParse(comment.text)
                    })
                }

            }
        })

        if (arguments[0] !== 'object') {
            processedCSS = root.toString().trim()
        }

        generate(maps, options)

        return root
    }
})

function generate (maps, options) {
    var codeStylePath = path.join('node_modules', 'highlight.js')
    var codeStyle = fs.readFileSync(codeStylePath + '/styles/github.css', 'utf-8').trim()

    Promise.all([
        nano.process(options.processedCSS),
        nano.process(options.style),
        nano.process(codeStyle)
    ]).then(function (result) {

        var params = {
            projectName: options.name,
            processedCSS: result.shift().css,
            tmplStyle: result.shift().css,
            codeStyle: result.shift().css,
            showCode: options.showCode,
            maps: maps
        }

        var html = ejs.render(options.template, params)
        mkdirp(options.dir, function (err) {
            if (err) {
                throw err
            }
        })
        var fileName = options.file
        if (!path.extname(options.file)) {
            fileName = fileName + '.html'
        }
        fs.writeFile(options.dir + '/' + fileName, html, function (err) {
            if (err) {
                throw err
            }
            console.log('Successfully created style guide!')
        })
    })
    .catch(function(err) {
        console.log(err);
    });
}
<commit_msg>Fix highlight.js files not found<commit_after>var fs = require('fs')
var path = require('path')
var postcss = require('postcss')
var ejs = require('ejs')
var nano = require('cssnano')
var mkdirp = require('mkdirp')
var annotation = require('css-annotation')
var themeDir = require('psg-theme-default')

var mdParse = require('./lib/md_parse')
var highlight = require('./lib/css_highlight')

module.exports = postcss.plugin('postcss-style-guide', function (options) {

    if (typeof(arguments[0]) === 'object') {
        options = arguments[0]
    }

    options = options || {}
    options.theme = options.theme !== undefined ? options.theme : 'default'
    options.name = options.name !== undefined ? options.name : 'Style Guide'
    options.file = options.file !== undefined ? options.file : 'styleguide'
    options.dir = options.dir !== undefined ? options.dir : 'docs'
    options.showCode = options.showCode !== undefined ? options.showCode : true

    var themeName = 'psg-theme-' + options.theme
    var themePath
    if (options.theme === 'default') {
        themePath = themeDir
    }
    else {
        themePath = path.join('node_modules', themeName)
    }

    options.template = fs.readFileSync(themePath + '/template.ejs', 'utf-8').trim()
    options.style = fs.readFileSync(themePath + '/style.css', 'utf-8').trim()

    var maps = []
    return function (root) {
        options.processedCSS = options.processedCSS !== undefined ? options.processedCSS : root.toString().trim()

        root.walkComments(function (comment) {

            var meta = annotation.read(comment.text)

            if (meta.documents || meta.document || meta.docs || meta.doc || meta.styleguide) {
                comment.text = comment.text.replace(/(@document|@doc|@docs|@styleguide)\s*\n/, '')

                if (comment.parent.type === 'root') {
                    var rule = comment.next()
                    var tmp = []
                    while (rule !== null && (rule.type === 'rule' || rule.type === 'atrule')) {
                        tmp.push(rule.toString().trim())
                        rule = rule.next() || null
                    }

                    var tmplRule = tmp.join('\n')
                    maps.push({
                        rule: highlight(tmplRule),
                        html: mdParse(comment.text)
                    })
                }

            }
        })

        if (arguments[0] !== 'object') {
            processedCSS = root.toString().trim()
        }

        generate(maps, options)

        return root
    }
})

function generate (maps, options) {
    var codeStylePath = path.join(__dirname, 'node_modules', 'highlight.js')
    var codeStyle = fs.readFileSync(codeStylePath + '/styles/github.css', 'utf-8').trim()

    Promise.all([
        nano.process(options.processedCSS),
        nano.process(options.style),
        nano.process(codeStyle)
    ]).then(function (result) {

        var params = {
            projectName: options.name,
            processedCSS: result.shift().css,
            tmplStyle: result.shift().css,
            codeStyle: result.shift().css,
            showCode: options.showCode,
            maps: maps
        }

        var html = ejs.render(options.template, params)
        mkdirp(options.dir, function (err) {
            if (err) {
                throw err
            }
        })
        var fileName = options.file
        if (!path.extname(options.file)) {
            fileName = fileName + '.html'
        }
        fs.writeFile(options.dir + '/' + fileName, html, function (err) {
            if (err) {
                throw err
            }
            console.log('Successfully created style guide!')
        })
    })
    .catch(function(err) {
        console.log(err);
    });
}
<|endoftext|>


<commit_before>//
// # prunk
// ## A mocking utility for node.js require
//
//     Author: Daniel Koch <daniel@suitsoft.eu>
//     Version: 1.0.0
//

// Require node's `module` module that provides
// access to all the things `require()` uses
var Module = require('module');

// ## _load
// The original `module._load` function
var _load = void 0;

// ## cache
// The cache that contains mocks and suppressed imports
var cache = [];

// ## init
// Overwrites `Module._load` with a function that either
// returns a mocked value from the cache or whatever the original
// function returns if nothing has been mocked.
var init = function() {
    _load = Module._load;

    // Overwrite the original `_load` function
    // The important argument for us is `req` because its the
    // name of whatever was required.
    Module._load = function(req, parent, isMain) {

        // Take the cache...
        var mock = cache
                        // Find the tests that match ...
                        .filter(function(mockDef) {
                            var test = mockDef.test;

                            // If we have a regex we match it against the string
                            if( test instanceof RegExp )
                                return null !== req.match( test );

                            // If we have a function we let the
                            // function decide
                            if( 'function' === typeof test )
                                return !! test(req, parent, isMain);

                            // Last case: we simply have no idea
                            // Thus, we use a strict equal
                            return test === req;
                        })
                        // ... and grab the mocked value from it
                        .map( function(mockDef) {
                            return mockDef.value;
                        });

        // If we found a mocked import we return it.
        // We only use the first mock we find. Since the `createMock()` function
        // uses `Array.prototype.unshift` we always use the mock added at last.
        if( mock.length )
            return mock[0];

        // No mock; let the load system do its work
        return _load.apply(Module, arguments);
    };
};

// ## createMock
// Creates a mock with the given test, mocking with the given
// value and use the given type.
//
// - `test`  - Something that is used to compare. Might be a string, a function or something else
// - `value` - The mock value that replaces the original import
// - `type`  - Type, either `'mock'` or `'sup'`. This is used to remove it later on.
//
var createMock = function(test, value, type) {
    // Initialize the cache if not done already
    if( ! _load )
        init.call(this);

    // Push the new item to the front
    cache.unshift({
        test: test,
        value: value,
        _type: type
    })
};

// ## remove
// Removes a mock definition from the collection.
//
// - `test`  - Something that is used to compare. Might be a string, a function or something else
// - `type`  - Type, either `'mock'` or `'sup'`.
//
var remove = function(test, type) {
    // We want to use strict equals below thus
    // we use the string representation of RegExp's
    if( test instanceof RegExp )
            test = ('' + test);

    cache = cache.filter( function(def) {
            // If the type does not match we ignore it
            if( type !== def._type )
                return true;

            // Again, convert RegExp's if found
            var cmp = (def.test instanceof RegExp) ? '' + def.test : def.test;

            return test !== cmp;
        });
};

// ## removeAll
// Removes all mocks of the given type
//
// - `type`  - Type, either `'mock'` or `'sup'`.
//
var removeAll = function(type) {
    cache = cache.filter( function(item) {
        return item._type !== type;
    });
};

// ## The prunk object
var prunk = {

    // Provide access to the cache.
    // This is done to make the testing more reliable.
    get _cache() {
        return cache;
    },

    set _cache(what) {
        cache = what;
    },

    // ### mock
    // Mocks the given import with the given value.
    // `test` can be a **function** that is used to compare
    // whatever is required and returns `true` or `false`.
    // If the return value is truthy the import will be
    // mocked with the given value.
    //
    // The function's arguments are the same as with `Module._load`.
    // Most of the time you will look at the first argument, a `string`.
    //
    //     var mockStyles = (req) => 'style.css' === req;
    //     prunk.mock( mockStyles, 'no css, dude.');
    //
    // `test` can also be a `RegExp` that is matched agains the name
    // of the import or a string. It can be anything else, too, if your
    // imports are gone totally crazy.
    //
    //     prunk.mock( 'style.css', 'no css, dude.' );
    //     prunk.mock( /\.(css|scss|sass|less)/, 'no styles, dude.');
    //
    // It returns the prunk object so that you can chain calls.
    mock: function(test, value) {
        createMock(test, value, 'mock');
        return prunk;
    },

    // ### suppress
    // Suppresses the given import. A suppressed import always
    // returns `undefined`.
    // The `test` argument is the same as used by [mock()](#section-25).
    //
    // It returns the prunk object so that you can chain calls.
    suppress: function(test) {
        createMock(test, void 0, 'sup');
        return prunk;
    },

    // ### unmock
    // Removes the mock registered for the given `test`.
    // `unmock()` uses strict equal to compare the registered
    // mocks.
    // It returns the prunk object so that you can chain calls.
    unmock: function(test) {
        remove(test, 'mock');
        return prunk;
    },

    // ### unsuppress
    // Removes the mock registered for the given `test`.
    // `unsuppress()` uses strict equal to compare the suppressed
    // imports.
    // It returns the prunk object so that you can chain calls.
    unsuppress: function(test) {
        remove(test, 'sup');
        return prunk;
    },

    // ### unmockAll
    // Removes all mocks for imports
    // It returns the prunk object so that you can chain calls.
    unmockAll: function() {
        removeAll('mock');
        return prunk;
    },

    // ### unsuppressAll
    // Removes all suppressed imports
    // It returns the prunk object so that you can chain calls.
    unsuppressAll: function() {
        removeAll('sup');
        return prunk;
    }

};

// ## Exports
module.exports = prunk;<commit_msg>Implement alias, unalias and unaliasAll<commit_after>//
// # prunk
// ## A mocking utility for node.js require
//
//     Author: Daniel Koch <daniel@suitsoft.eu>
//     Version: 1.0.0
//

// Require node's `module` module that provides
// access to all the things `require()` uses
var Module = require('module');

// ## _load
// The original `module._load` function
var _load = void 0;

// ## cache
// The cache that contains mocks and suppressed imports
var cache = [];

// ## init
// Overwrites `Module._load` with a function that either
// returns a mocked value from the cache or whatever the original
// function returns if nothing has been mocked.
var init = function() {
    _load = Module._load;

    // Overwrite the original `_load` function
    // The important argument for us is `req` because its the
    // name of whatever was required.
    Module._load = function(req, parent, isMain) {

        // Take the cache...
        var mock = cache
                        // Find the tests that match
                        .filter(function(mockDef) {
                            var test = mockDef.test;

                            // If we have a regex we match it against the string
                            if( test instanceof RegExp )
                                return null !== req.match( test );

                            // If we have a function we let the
                            // function decide
                            if( 'function' === typeof test )
                                return !! test(req, parent, isMain);

                            // If there is an alias we check if the string starts
                            // with the desired test
                            if( 'alias' === mockDef._type )
                                return req.startsWith( mockDef.test );

                            // Last case: we simply have no idea
                            // Thus, we use a strict equal
                            return test === req;
                        });

        // If we found a mocked import we return it.
        // We only use the first mock we find. Since the `createMock()` function
        // uses `Array.prototype.unshift` we always use the mock added at last.
        if( mock.length ) {
            mock = mock[0];
            value = mock.value;

            // Aliases are a bit special
            if( 'alias' !== mock._type )
                return value;

            // If the alias is a function we let that function do the
            // transformation of the path
            if( 'function' === typeof value )
                req = value(req);
            // If it is not a function we use string replacement
            else
                req = req.replace(mock.test, value);
        }

        // No mock; let the load system do its work
        return _load.call(Module, req, parent, isMain);
    };
};

// ## createMock
// Creates a mock with the given test, mocking with the given
// value and use the given type.
//
// - `test`  - Something that is used to compare. Might be a string, a function or something else
// - `value` - The mock value that replaces the original import
// - `type`  - Type, either `'mock'` or `'sup'`. This is used to remove it later on.
//
var createMock = function(test, value, type) {
    // Initialize the cache if not done already
    if( ! _load )
        init.call(this);

    // Push the new item to the front
    cache.unshift({
        test: test,
        value: value,
        _type: type
    })
};

// ## remove
// Removes a mock definition from the collection.
//
// - `test`  - Something that is used to compare. Might be a string, a function or something else
// - `type`  - Type, either `'mock'` or `'sup'`.
//
var remove = function(test, type) {
    // We want to use strict equals below thus
    // we use the string representation of RegExp's
    if( test instanceof RegExp )
            test = ('' + test);

    cache = cache.filter( function(def) {
            // If the type does not match we ignore it
            if( type !== def._type )
                return true;

            // Again, convert RegExp's if found
            var cmp = (def.test instanceof RegExp) ? '' + def.test : def.test;

            return test !== cmp;
        });
};

// ## removeAll
// Removes all mocks of the given type
//
// - `type`  - Type, either `'mock'` or `'sup'`.
//
var removeAll = function(type) {
    cache = cache.filter( function(item) {
        return item._type !== type;
    });
};

// ## The prunk object
var prunk = {

    // Provide access to the cache.
    // This is done to make the testing more reliable.
    get _cache() {
        return cache;
    },

    set _cache(what) {
        cache = what;
    },

    // ### mock
    // Mocks the given import with the given value.
    // `test` can be a **function** that is used to compare
    // whatever is required and returns `true` or `false`.
    // If the return value is truthy the import will be
    // mocked with the given value.
    //
    // The function's arguments are the same as with `Module._load`.
    // Most of the time you will look at the first argument, a `string`.
    //
    //     var mockStyles = (req) => 'style.css' === req;
    //     prunk.mock( mockStyles, 'no css, dude.');
    //
    // `test` can also be a `RegExp` that is matched agains the name
    // of the import or a string. It can be anything else, too, if your
    // imports are gone totally crazy.
    //
    //     prunk.mock( 'style.css', 'no css, dude.' );
    //     prunk.mock( /\.(css|scss|sass|less)/, 'no styles, dude.');
    //
    // It returns the prunk object so that you can chain calls.
    mock: function(test, value) {
        createMock(test, value, 'mock');
        return prunk;
    },

    // ### suppress
    // Suppresses the given import. A suppressed import always
    // returns `undefined`.
    // The `test` argument is the same as used by [mock()](#section-25).
    //
    // It returns the prunk object so that you can chain calls.
    suppress: function(test) {
        createMock(test, void 0, 'sup');
        return prunk;
    },

    // ### unmock
    // Removes the mock registered for the given `test`.
    // `unmock()` uses strict equal to compare the registered
    // mocks.
    // It returns the prunk object so that you can chain calls.
    unmock: function(test) {
        remove(test, 'mock');
        return prunk;
    },

    // ### unsuppress
    // Removes the mock registered for the given `test`.
    // `unsuppress()` uses strict equal to compare the suppressed
    // imports.
    // It returns the prunk object so that you can chain calls.
    unsuppress: function(test) {
        remove(test, 'sup');
        return prunk;
    },

    // ### unmockAll
    // Removes all mocks for imports
    // It returns the prunk object so that you can chain calls.
    unmockAll: function() {
        removeAll('mock');
        return prunk;
    },

    // ### unsuppressAll
    // Removes all suppressed imports
    // It returns the prunk object so that you can chain calls.
    unsuppressAll: function() {
        removeAll('sup');
        return prunk;
    },

    // ### alias
    // Aliases a path that begins with the given
    // string or matches the given regex.
    // This basically performs a string replacement if
    // you provide a simple string or a regex.
    // The regular expressions **must contain** at least
    // one grouping expression `(...)` so that the replacement
    // actually happens.
    // `alias` can also be a function that gets the path and
    // returns an updated one.
    // You can only provide a predicate function for `test`
    // if `alias` is also a function returning a modified path.
    // This method will throw if arguments are invalid.
    alias: function(test, alias) {

        if( 'undefined' === typeof alias )
            throw new Error('prunk.alias needs a second argument');

        if( 'function' === typeof test && 'function' !== typeof alias )
            throw new Error('prunk.alias has been passed a function as test but not as alias');

        if( test instanceof RegExp && ! test.toString().includes('(') )
            throw new Error('prunk.alias has been passed a RegExp without a grouping expression');

        createMock(test, alias, 'alias');
        return prunk;
    },

    // ### unalias
    // Removes the alias for the given test
    // It returns the prunk object so that you can chain calls.
    unalias: function(test) {
        remove(test, 'alias');
        return prunk;
    },

    // ### unaliasAll
    // Removes all aliases
    // It returns the prunk object so that you can chain calls.
    unaliasAll: function() {
        removeAll('alias');
        return prunk;
    }

};

// ## Exports
module.exports = prunk;<|endoftext|>


<commit_before>var heatmap = require("./lib/heatmap"),
    Bacon = require("baconjs").Bacon,
    fs = require("fs"),
    express = require('express'),
    app = express();

var hosts = ["hertzen.com", "html2canvas.hertzen.com"];
var from = "2012-05-01";
var to = "2013-08-20";
var cachePath = "./cache/";
var queue = [];
var port = 8080;

function order(arrA, arrB) {
    return parseInt(arrB[1], 10) - parseInt(arrA[1], 10) ;
}

function write(filename, response) {
    fs.writeFileSync(filename, JSON.stringify(response));
    console.log(filename + ' - written with', response.length, 'rows');
}

function top50(response) {
    return response.sort(order).slice(0, 50);
}

function requestOptions(host) {
    return {
        host: host,
        path: "/",
        startDate: from,
        endDate: to
    };
}

function requestOptionsWithResolution(host, resolution) {
    var opts = requestOptions(host);
    opts.resolution = resolution[0];
    return opts;
}

function each(arr) {
    return Bacon.fromArray(arr);
}

function writeResolutions(response, host) {
    write(cachePath + host + '-resolutions.json', response);
    return response;
}

function resolutionRequestsForHosts(host) {
    return Bacon.combineWith(
        requestOptionsWithResolution, host,
        Bacon.combineWith(
            writeResolutions,
            Bacon.constant(host).map(requestOptions).flatMap(heatmap.getResolutions).map(top50),
            host
        ).flatMap(each)
    );
}

function addQueue(item) {
    queue.push(item);
}

function asInt(arg) {
    return parseInt(arg, 10);
}

function writeResponse(response, item) {
    write(cachePath + item.host + '-' + item.resolution + '.json', response);
}

function formatRows(rows) {
    return rows.map(function(row) {
        var clickPosition = row[0].split("x").map(asInt);
        return [clickPosition[0], clickPosition[1], row[1], row[2]];
    });
}

function runQueue() {
    var item = queue.pop();
    if (item) {
        Bacon.combineWith(writeResponse, heatmap.request(item).map(formatRows), item).onValue(runQueue);
    } else {
        combineResolutions("hertzen.com");
    }
}

function combineResolutions(host) {
    var targetWidth = 1366;
    var center = targetWidth / 2;
    var results = [];

    JSON.parse(fs.readFileSync(cachePath + host + "-resolutions.json")).forEach(function(resolution) {
        var parts = resolution[0].split("x").map(asInt);
        var info = JSON.parse(fs.readFileSync(cachePath + host + "-" + resolution[0] + ".json"));
        results = results.concat(info.map(function(entry) {
            var positionalCenter = (parts[0]/2) - entry[0];
            return [(center - positionalCenter), entry[1], entry[2], entry[3]];
        }));
    });

    write(cachePath + host + "-all.json", results);
}

Bacon.fromArray(hosts).flatMap(resolutionRequestsForHosts).doAction(addQueue).onEnd(runQueue);

app.use('/data', express.static(__dirname + '/cache'));
app.use('/assets', express.static(__dirname + '/assets'));
app.get('/', function(req, res) {
    res.sendfile("index.html");
});
app.get('/html2canvas.html', function(req, res) {
    res.sendfile("html2canvas.html");
});
app.listen(port);
console.log("Server opened on port", port);<commit_msg>Set port configurable<commit_after>var heatmap = require("./lib/heatmap"),
    Bacon = require("baconjs").Bacon,
    fs = require("fs"),
    express = require('express'),
    app = express();

var hosts = ["hertzen.com", "html2canvas.hertzen.com"];
var from = "2012-05-01";
var to = "2013-08-20";
var cachePath = "./cache/";
var queue = [];
var port = process.env.PORT || 8080;

function order(arrA, arrB) {
    return parseInt(arrB[1], 10) - parseInt(arrA[1], 10) ;
}

function write(filename, response) {
    fs.writeFileSync(filename, JSON.stringify(response));
    console.log(filename + ' - written with', response.length, 'rows');
}

function top50(response) {
    return response.sort(order).slice(0, 50);
}

function requestOptions(host) {
    return {
        host: host,
        path: "/",
        startDate: from,
        endDate: to
    };
}

function requestOptionsWithResolution(host, resolution) {
    var opts = requestOptions(host);
    opts.resolution = resolution[0];
    return opts;
}

function each(arr) {
    return Bacon.fromArray(arr);
}

function writeResolutions(response, host) {
    write(cachePath + host + '-resolutions.json', response);
    return response;
}

function resolutionRequestsForHosts(host) {
    return Bacon.combineWith(
        requestOptionsWithResolution, host,
        Bacon.combineWith(
            writeResolutions,
            Bacon.constant(host).map(requestOptions).flatMap(heatmap.getResolutions).map(top50),
            host
        ).flatMap(each)
    );
}

function addQueue(item) {
    queue.push(item);
}

function asInt(arg) {
    return parseInt(arg, 10);
}

function writeResponse(response, item) {
    write(cachePath + item.host + '-' + item.resolution + '.json', response);
}

function formatRows(rows) {
    return rows.map(function(row) {
        var clickPosition = row[0].split("x").map(asInt);
        return [clickPosition[0], clickPosition[1], row[1], row[2]];
    });
}

function runQueue() {
    var item = queue.pop();
    if (item) {
        Bacon.combineWith(writeResponse, heatmap.request(item).map(formatRows), item).onValue(runQueue);
    } else {
        combineResolutions("hertzen.com");
    }
}

function combineResolutions(host) {
    var targetWidth = 1366;
    var center = targetWidth / 2;
    var results = [];

    JSON.parse(fs.readFileSync(cachePath + host + "-resolutions.json")).forEach(function(resolution) {
        var parts = resolution[0].split("x").map(asInt);
        var info = JSON.parse(fs.readFileSync(cachePath + host + "-" + resolution[0] + ".json"));
        results = results.concat(info.map(function(entry) {
            var positionalCenter = (parts[0]/2) - entry[0];
            return [(center - positionalCenter), entry[1], entry[2], entry[3]];
        }));
    });

    write(cachePath + host + "-all.json", results);
}

Bacon.fromArray(hosts).flatMap(resolutionRequestsForHosts).doAction(addQueue).onEnd(runQueue);

app.use('/data', express.static(__dirname + '/cache'));
app.use('/assets', express.static(__dirname + '/assets'));
app.get('/', function(req, res) {
    res.sendfile("index.html");
});
app.get('/html2canvas.html', function(req, res) {
    res.sendfile("html2canvas.html");
});
app.listen(port);
console.log("Server opened on port", port);<|endoftext|>


<commit_before>//= require bootbox
//= require ./bootbox_crud_modals
//= require ./sortable
<commit_msg>added js requirements to main js file so they dont have to be added to main app js<commit_after>//= require bootstrap/modal
//= require bootbox
//= require ./bootbox_crud_modals
//= require ./sortable
//= require models
<|endoftext|>


<commit_before>(function(window, Ember, $) {
  var RestScroll = {};

  RestScroll.ArrayProxyMixin = Ember.Mixin.create({
   loadMore: function() {
      var res = this.get('resourceName');
      var lastItem = this.get('lastObject');
      var params = {}
      params.order_by = this.get('orderBy');
      if (lastItem) {
        params.key = {};
        for(field in params.order_by) {
          var value = lastItem.get(field);
          switch(Ember.typeOf(value)) {
          case 'date':
            params.key[field] = moment(value).toISOString();
            break;
          default:
            params.key[field] = value;
            break;
          }
        }
        params.key['id'] = lastItem.get('id');
      }
      var _this = this;
      this.set('loading', true);
      this.set('error', undefined);
      // Ember.Logger.debug('APM:loadMore: resource: ', res,
      //  ' lastItem:', this.get('lastObject'),
      //  ' params:', params);
      return this.get('store').find(res, {rest_scroll: params}).then(
        function(items) {
          _this.set('loading', false);
          var content = items.get('content');
          // Ember.Logger.debug('loadMore: then: ', items, ' content:', content);
          if (content.length) {
            _this.pushObjects(content);
            _this.set('hasMore', true);
          }
          else {
            _this.set('hasMore', false);
          }
          return _this;
        },
        function(error) {
          _this.set('loading', false);
          _this.set('error', "Error: %@(%@): %@".fmt(error.status, error.statusText, error.responseText));
          _this.set('hasMore', false);
        }
      );
    },
    addOrderBy: function(field, asc) {
      // Ember.Logger.debug('APM: addOrderBy: ', field, asc);
      var orderBy = this.get('orderBy');
      orderBy[field] = asc;
      return this.refreshOrderBy(orderBy);
    },
    removeOrderBy: function(field) {
      // Ember.Logger.debug('APM: removeOrderBy: ', field);
      var orderBy = this.get('orderBy');
      delete orderBy[field];
      return this.refreshOrderBy(orderBy);
    },
    refreshOrderBy: function(orderBy) {
      this.set('orderBy', orderBy);
      Ember.propertyDidChange(this, 'orderBy');
      this.set('content', Em.A());
      return this.loadMore();
    }
  });

  RestScroll.RouteMixin = Ember.Mixin.create({
    resource: undefined,
    loadedItems: undefined,
    getItems: function() {

      var loadedItems = this.get('loadedItems');
      // Ember.Logger.debug('getItems: ', loadedItems);
      if (loadedItems)
        return loadedItems;

      loadedItems = Em.ArrayProxy.createWithMixins(
        RestScroll.ArrayProxyMixin, {
        orderBy: {},
        loading: false,
        hasMore: true,
        resourceName: this.get('resource'),
        store: this.get('store'),
        content: Em.A()});

      return loadedItems.loadMore();
    },
    actions: {
      willTransition: function(transition) {
        // Ember.Logger.debug("willTransition: ", transition);
        var controller = this.controllerFor(this.routeName);
        var loadedItems = controller.get('content');
        this.set('loadedItems', loadedItems);
        return true;
      }
    }
  });

  RestScroll.ControllerMixin = Ember.Mixin.create({
    actions: {
      getMore: function() {
        // Ember.Logger.debug("controller: getMore");
        if (this.get('content.loading')) return;
        this.get('content').loadMore();
      },
      addOrderBy: function(field, asc) {
        // Ember.Logger.debug("controller: addOrderBy: ", field, asc);
        this.get('content').addOrderBy(field, asc);
      },
      removeOrderBy: function(field) {
        // Ember.Logger.debug("controller: removeOrderBy: ", field);
        this.get('content').removeOrderBy(field);
      }
    },
  });

  RestScroll.ToggleSortView = Ember.View.extend({
    layout: Ember.Handlebars.compile(
      "{{yield}} " +
      ""),

    getAsc: function () {
      var orderBy = this.get('controller.content.orderBy');
      var fieldName = this.get('fieldName');
      var asc = orderBy[fieldName];
      // Ember.Logger.debug('getAsc: ', orderBy, fieldName, asc);
      return asc;
    },

    icon: function() {
      // Ember.Logger.debug('icon: ', this.get('fieldName'));
      var asc = this.getAsc();
      switch(asc) {
      case undefined: return "glyphicon-sort";
      case 'asc': return "glyphicon-sort-by-alphabet";
      case 'desc': return "glyphicon-sort-by-alphabet-alt";
      }
    }.property('controller.content.orderBy'),

    /*
    init: function() {
      var _this = this;
      var fieldName = this.get('fieldName');
      Ember.addObserver(this, "controller.content.orderBy", function() {
        // Ember.Logger.debug("orderBy observer:", fieldName);
        Ember.propertyDidChange(_this, "icon");
      });
    },
    */

    actions:  {
      toggleSort: function() {
        // Ember.Logger.debug("ToggleSortView: toggleSort: ", this.get('fieldName'), ' ascending:', this.get('ascending'));
        var asc = this.getAsc();
        var action = 'addOrderBy';
        switch(asc) {
        case undefined:
          asc = 'asc';
          break;
        case 'asc':
          asc = 'desc';
          break;
        case 'desc':
          action = 'removeOrderBy';
          break;
        }
        this.get('controller').send(action, this.get('fieldName'), asc);
      }
    }
  });

  Ember.Handlebars.helper('toggle-sort', RestScroll.ToggleSortView);

  RestScroll.LoadMoreView = Ember.View.extend({
    didInsertElement: function() {
      var _controller = this.get('controller');
      // Ember.Logger.debug("LoadMoreView: didInsertElement");
      this.$().bind('inview',
        function(event, isInView, visibleX, visibleY) {
          // Ember.Logger.debug("inview: ", isInView, ' hasMore:', _controller.get('content.hasMore'));
          if (isInView && _controller.get('content.hasMore')) {
            _controller.send('getMore');
          }
        });
    }
  });

  window.RestScroll = RestScroll;
})(this, Ember, jQuery);
<commit_msg>remove dead init<commit_after>(function(window, Ember, $) {
  var RestScroll = {};

  RestScroll.ArrayProxyMixin = Ember.Mixin.create({
   loadMore: function() {
      var res = this.get('resourceName');
      var lastItem = this.get('lastObject');
      var params = {}
      params.order_by = this.get('orderBy');
      if (lastItem) {
        params.key = {};
        for(field in params.order_by) {
          var value = lastItem.get(field);
          switch(Ember.typeOf(value)) {
          case 'date':
            params.key[field] = moment(value).toISOString();
            break;
          default:
            params.key[field] = value;
            break;
          }
        }
        params.key['id'] = lastItem.get('id');
      }
      var _this = this;
      this.set('loading', true);
      this.set('error', undefined);
      // Ember.Logger.debug('APM:loadMore: resource: ', res,
      //  ' lastItem:', this.get('lastObject'),
      //  ' params:', params);
      return this.get('store').find(res, {rest_scroll: params}).then(
        function(items) {
          _this.set('loading', false);
          var content = items.get('content');
          // Ember.Logger.debug('loadMore: then: ', items, ' content:', content);
          if (content.length) {
            _this.pushObjects(content);
            _this.set('hasMore', true);
          }
          else {
            _this.set('hasMore', false);
          }
          return _this;
        },
        function(error) {
          _this.set('loading', false);
          _this.set('error', "Error: %@(%@): %@".fmt(error.status, error.statusText, error.responseText));
          _this.set('hasMore', false);
        }
      );
    },
    addOrderBy: function(field, asc) {
      // Ember.Logger.debug('APM: addOrderBy: ', field, asc);
      var orderBy = this.get('orderBy');
      orderBy[field] = asc;
      return this.refreshOrderBy(orderBy);
    },
    removeOrderBy: function(field) {
      // Ember.Logger.debug('APM: removeOrderBy: ', field);
      var orderBy = this.get('orderBy');
      delete orderBy[field];
      return this.refreshOrderBy(orderBy);
    },
    refreshOrderBy: function(orderBy) {
      this.set('orderBy', orderBy);
      Ember.propertyDidChange(this, 'orderBy');
      this.set('content', Em.A());
      return this.loadMore();
    }
  });

  RestScroll.RouteMixin = Ember.Mixin.create({
    resource: undefined,
    loadedItems: undefined,
    getItems: function() {

      var loadedItems = this.get('loadedItems');
      // Ember.Logger.debug('getItems: ', loadedItems);
      if (loadedItems)
        return loadedItems;

      loadedItems = Em.ArrayProxy.createWithMixins(
        RestScroll.ArrayProxyMixin, {
        orderBy: {},
        loading: false,
        hasMore: true,
        resourceName: this.get('resource'),
        store: this.get('store'),
        content: Em.A()});

      return loadedItems.loadMore();
    },
    actions: {
      willTransition: function(transition) {
        // Ember.Logger.debug("willTransition: ", transition);
        var controller = this.controllerFor(this.routeName);
        var loadedItems = controller.get('content');
        this.set('loadedItems', loadedItems);
        return true;
      }
    }
  });

  RestScroll.ControllerMixin = Ember.Mixin.create({
    actions: {
      getMore: function() {
        // Ember.Logger.debug("controller: getMore");
        if (this.get('content.loading')) return;
        this.get('content').loadMore();
      },
      addOrderBy: function(field, asc) {
        // Ember.Logger.debug("controller: addOrderBy: ", field, asc);
        this.get('content').addOrderBy(field, asc);
      },
      removeOrderBy: function(field) {
        // Ember.Logger.debug("controller: removeOrderBy: ", field);
        this.get('content').removeOrderBy(field);
      }
    },
  });

  RestScroll.ToggleSortView = Ember.View.extend({
    layout: Ember.Handlebars.compile(
      "{{yield}} " +
      ""),

    getAsc: function () {
      var orderBy = this.get('controller.content.orderBy');
      var fieldName = this.get('fieldName');
      var asc = orderBy[fieldName];
      // Ember.Logger.debug('getAsc: ', orderBy, fieldName, asc);
      return asc;
    },

    icon: function() {
      // Ember.Logger.debug('icon: ', this.get('fieldName'));
      var asc = this.getAsc();
      switch(asc) {
      case undefined: return "glyphicon-sort";
      case 'asc': return "glyphicon-sort-by-alphabet";
      case 'desc': return "glyphicon-sort-by-alphabet-alt";
      }
    }.property('controller.content.orderBy'),

    actions:  {
      toggleSort: function() {
        // Ember.Logger.debug("ToggleSortView: toggleSort: ", this.get('fieldName'), ' ascending:', this.get('ascending'));
        var asc = this.getAsc();
        var action = 'addOrderBy';
        switch(asc) {
        case undefined:
          asc = 'asc';
          break;
        case 'asc':
          asc = 'desc';
          break;
        case 'desc':
          action = 'removeOrderBy';
          break;
        }
        this.get('controller').send(action, this.get('fieldName'), asc);
      }
    }
  });

  Ember.Handlebars.helper('toggle-sort', RestScroll.ToggleSortView);

  RestScroll.LoadMoreView = Ember.View.extend({
    didInsertElement: function() {
      var _controller = this.get('controller');
      // Ember.Logger.debug("LoadMoreView: didInsertElement");
      this.$().bind('inview',
        function(event, isInView, visibleX, visibleY) {
          // Ember.Logger.debug("inview: ", isInView, ' hasMore:', _controller.get('content.hasMore'));
          if (isInView && _controller.get('content.hasMore')) {
            _controller.send('getMore');
          }
        });
    }
  });

  window.RestScroll = RestScroll;
})(this, Ember, jQuery);
<|endoftext|>


<commit_before>/**
 * Checkout.com
 * Authorized and regulated as an electronic money institution
 * by the UK Financial Conduct Authority (FCA) under number 900816.
 *
 * PHP version 7
 *
 * @category  Magento2
 * @package   Checkout.com
 * @author    Platforms Development Team <platforms@checkout.com>
 * @copyright 2010-2019 Checkout.com
 * @license   https://opensource.org/licenses/mit-license.html MIT License
 * @link      https://docs.checkout.com/
 */

define(
    [
        'jquery',
        'CheckoutCom_Magento2/js/view/payment/config-loader',
        'Magento_Checkout/js/model/quote',
        'Magento_Checkout/js/checkout-data',
        'mage/url',
        'Magento_Checkout/js/action/redirect-on-success',
        'Magento_Checkout/js/model/full-screen-loader',
        'mage/translate',
        'mage/cookies'
    ],
    function ($, Config, Quote, CheckoutData, Url, RedirectOnSuccessAction, FullScreenLoader, __) {
        'use strict';

        const KEY_CONFIG = 'checkoutcom_configuration';
        const KEY_DATA = 'checkoutcom_data';

        return {
            /**
             * Gets a field value.
             *
             * @param  {string}  methodId The method id
             * @param  {string}  field    The field
             * @return {mixed}            The value
             */
            getValue: function (methodId, field) {
                var val = null;
                if (methodId && Config.hasOwnProperty(methodId) && Config[methodId].hasOwnProperty(field)) {
                    val = Config[methodId][field]
                } else if (Config.hasOwnProperty(KEY_CONFIG) && Config[KEY_CONFIG].hasOwnProperty(field)) {
                    val = Config[KEY_CONFIG][field];
                }

                return val;
            },

            /**
             * Load a CSS file
             *
             * @return {void}
             */
            loadCss: function (fileName, folderPath) {
                // Prepare the folder path
                folderPath = (folderPath) ? '/' + folderPath : '';

                // Get the CSS config parameters
                var useMinCss = window.checkoutConfig.payment.checkoutcom_magento2.checkoutcom_data.use_minified_css;
                var ext = (useMinCss == '1') ? '.min.css' : '.css';

                // Build the payment form CSS path
                var cssPath = window.checkoutConfig.payment.checkoutcom_magento2.checkoutcom_data.css_path;
                cssPath += folderPath + '/' + fileName + ext;

                // Append the CSS file
                $('head').append('<link rel="stylesheet" href="' + cssPath + '" type="text/css"/>');
            },

            /**
             * Load a remote JS file
             *
             * @return {void}
             */
            loadRemoteJs: function (jsUrl) {
                // Append the CSS file
                $('head').append('<script type="text/javascript" src="' + jsUrl + '"></script>');
            },

            /**
             * Get the store name.
             *
             * @return {string}  The store name.
             */
            getStoreName: function () {
                return Config[KEY_DATA].store.name;
            },

            /**
             * Get the quote value.
             *
             * @return {float}  The quote value.
             */
            getQuoteValue: function () {
                var data = this.getRestQuoteData(false);
                var amount = parseFloat(data.totals.base_grand_total);

                return amount.toFixed(2);
            },

            /**
             * Get the updated quote data from the core REST API.
             *
             * @return {object}  The quote data.
             */
            getRestQuoteData: function (isNewApi) {
                // Prepare the required parameters
                var self = this;
                var result = null;

                // Build the URL
                var restUrl = window.BASE_URL + 'rest/default/V1/';

                if (isNewApi) {
                    restUrl += 'guest-carts/'+ window.checkoutConfig.quoteItemData[0].quote_id +'/payment-information';
                } else {
                    restUrl += 'carts/mine/payment-information';
                    restUrl += '?form_key=' + window.checkoutConfig.formKey;
                }

                // Set the event to update data on any button click
                $('button[type="submit"]')
                .off('click', isNewApi, self.getRestQuoteData)
                .on('click', isNewApi, self.getRestQuoteData);

                // Send the AJAX request
                $.ajax({
                    url: restUrl,
                    type: 'GET',
                    contentType: "application/json",
                    dataType: "json",
                    async: false,
                    showLoader: true,
                    success: function (data, status, xhr) {
                        result = data;
                    },
                    error: function (request, status, error) {
                        self.log(error);
                    }
                });

                if (result == null) {
                   return self.getRestQuoteData(true);
                } else {
                    return result;
                }

            },

            /**
             * Get the quote currency.
             *
             * @return {string}  The quote currency.
             */
            getQuoteCurrency: function () {
                return Config[KEY_DATA].quote.currency;
            },

            /**
             * Checks if user has saved cards.
             *
             * @return {bool}
             */
            userHasCards: function () {
                return Config[KEY_DATA].user.hasCards;
            },

            /**
             * Get the supported cards.
             *
             * @return {array}
             */
            getSupportedCards: function () {
                return Config[KEY_DATA].cards;
            },

            /**
             * Builds the controller URL.
             *
             * @param  {string}  path  The path
             * @return {string}
             */
            getUrl: function (path) {
                return Url.build('checkout_com/' + path);
            },

            /**
             * Customer name.
             *
             * @param  {bool} return in object format.
             * @return {mixed}  The billing address.
             */
            getCustomerName: function () {
                var billingAddress = Quote.billingAddress();
                var customerName = '';
                if (billingAddress) {
                    customerName += billingAddress.firstname;
                    customerName += ' ' + billingAddress.lastname;
                }

                return customerName;
            },

            /**
             * Billing address.
             *
             * @return {object}  The billing address.
             */
            getBillingAddress: function () {
                return Quote.billingAddress();
            },

            /**
             * @returns {string}
             */
            getEmail: function () {
                var emailCookieName = this.getValue(null, 'email_cookie_name');
                return window.checkoutConfig.customerData.email
                || Quote.guestEmail
                || CheckoutData.getValidatedEmailValue()
                || $.cookie(emailCookieName);
            },

            /**
             * @returns {void}
             */
            setEmail: function () {
                var userEmail = this.getEmail();
                var emailCookieName = this.getValue(null, 'email_cookie_name');
                $.cookie(emailCookieName, userEmail);

                // If no email found, observe the core email field
                if (!userEmail) {
                    $('#customer-email').off('change').on('change', function () {
                        userEmail = Quote.guestEmail || CheckoutData.getValidatedEmailValue();
                        $.cookie(emailCookieName, userEmail);
                    });
                }
            },

            /**
             * @returns {object}
             */
            getPhone: function () {
                var billingAddress = Quote.billingAddress();

                return {
                    number: billingAddress.telephone
                };
            },

            /**
             * Handle error logging.
             */
            log: function (val) {
                if (this.getValue(null, 'debug')
                    && this.getValue(null, 'console_logging')
                ) {
                    console.log(val);
                }
            },

            /**
             * Show a message.
             */
            showMessage: function (type, message, methodId) {
                this.clearMessages(methodId);
                var messageContainer = this.getMethodContainer(methodId).find('.message');
                messageContainer.addClass('message-' + type + ' ' + type);
                messageContainer.append('<div>' + __(message) + '</div>');
                messageContainer.show();
            },

            /**
             * Clear all messages.
             */
            clearMessages: function (methodId) {
                var messageContainer = this.getMethodContainer(methodId).find('.message');
                messageContainer.hide();
                messageContainer.empty();
            },

            /**
             * Get a payment method container instance.
             */
            getMethodContainer: function (methodId) {
                return $('#' + methodId + '_container');
            },

            /**
             * Check if an URL is valid.
             */
            isUrl: function (str) {
                var pattern = /^(?:\w+:)?\/\/([^\s\.]+\.\S{2}|localhost[\:?\d]*)\S*$/;
                return pattern.test(str);
            },

            /**
             * Handle the place order button state.
             */
            allowPlaceOrder: function (buttonId, yesNo) {
                $('#' + buttonId).prop('disabled', !yesNo);
            },

            /**
             * Check if a payment option is active.
             */
            methodIsSelected: function (idSelector) {
                var id = idSelector.replace('#', '');
                var selected = CheckoutData.getSelectedPaymentMethod();
                return id == selected;
            },

            /**
             * Place a new order.
             *
             * @returns {void}
             */
            placeOrder: function (payload, methodId) {
                var self = this;

                // Start the loader
                FullScreenLoader.startLoader();

                // Send the request
                $.ajax({
                    type: 'POST',
                    url: self.getUrl('payment/placeorder'),
                    data: payload,
                    success: function (data) {
                        if (!data.success) {
                            FullScreenLoader.stopLoader();
                            self.showMessage('error', data.message, methodId);
                        } else if (data.success && data.url) {
                            // Handle 3DS redirection
                            window.location.href = data.url
                        } else {
                            // Normal redirection
                            RedirectOnSuccessAction.execute();
                        }
                    },
                    error: function (request, status, error) {
                        self.showMessage('error', error, methodId);
                        FullScreenLoader.stopLoader();
                    }
                });
            }
        };
    }
);
<commit_msg>Refactor to improve maintainability<commit_after>/**
 * Checkout.com
 * Authorized and regulated as an electronic money institution
 * by the UK Financial Conduct Authority (FCA) under number 900816.
 *
 * PHP version 7
 *
 * @category  Magento2
 * @package   Checkout.com
 * @author    Platforms Development Team <platforms@checkout.com>
 * @copyright 2010-2019 Checkout.com
 * @license   https://opensource.org/licenses/mit-license.html MIT License
 * @link      https://docs.checkout.com/
 */

define(
    [
        'jquery',
        'CheckoutCom_Magento2/js/view/payment/config-loader',
        'Magento_Checkout/js/model/quote',
        'Magento_Checkout/js/checkout-data',
        'mage/url',
        'Magento_Checkout/js/action/redirect-on-success',
        'Magento_Checkout/js/model/full-screen-loader',
        'mage/translate',
        'mage/cookies'
    ],
    function ($, Config, Quote, CheckoutData, Url, RedirectOnSuccessAction, FullScreenLoader, __) {
        'use strict';

        const KEY_CONFIG = 'checkoutcom_configuration';
        const KEY_DATA = 'checkoutcom_data';

        return {
            /**
             * Gets a field value.
             *
             * @param  {string}  methodId The method id
             * @param  {string}  field    The field
             * @return {mixed}            The value
             */
            getValue: function (methodId, field) {
                var val = null;
                if (methodId && Config.hasOwnProperty(methodId) && Config[methodId].hasOwnProperty(field)) {
                    val = Config[methodId][field]
                } else if (Config.hasOwnProperty(KEY_CONFIG) && Config[KEY_CONFIG].hasOwnProperty(field)) {
                    val = Config[KEY_CONFIG][field];
                }

                return val;
            },

            /**
             * Load a CSS file
             *
             * @return {void}
             */
            loadCss: function (fileName, folderPath) {
                // Prepare the folder path
                folderPath = (folderPath) ? '/' + folderPath : '';

                // Get the CSS config parameters
                var useMinCss = window.checkoutConfig.payment.checkoutcom_magento2.checkoutcom_data.use_minified_css;
                var ext = (useMinCss == '1') ? '.min.css' : '.css';

                // Build the payment form CSS path
                var cssPath = window.checkoutConfig.payment.checkoutcom_magento2.checkoutcom_data.css_path;
                cssPath += folderPath + '/' + fileName + ext;

                // Append the CSS file
                $('head').append('<link rel="stylesheet" href="' + cssPath + '" type="text/css"/>');
            },

            /**
             * Load a remote JS file
             *
             * @return {void}
             */
            loadRemoteJs: function (jsUrl) {
                // Append the CSS file
                $('head').append('<script type="text/javascript" src="' + jsUrl + '"></script>');
            },

            /**
             * Get the store name.
             *
             * @return {string}  The store name.
             */
            getStoreName: function () {
                return Config[KEY_DATA].store.name;
            },

            /**
             * Get the quote value.
             *
             * @return {float}  The quote value.
             */
            getQuoteValue: function () {
                var data = this.getRestQuoteData();
                var amount = parseFloat(data.totals.base_grand_total);

                return amount.toFixed(2);
            },

            // /**
            //  * Get the updated quote data from the core REST API.
            //  *
            //  * @return {object}  The quote data.
            //  */
            // getRestQuoteData: function (isNewApi) {
            //     // Prepare the required parameters
            //     var self = this;
            //     var result = null;
            //
            //     // Build the URL
            //     var restUrl = window.BASE_URL + 'rest/default/V1/';
            //
            //     if (isNewApi) {
            //         restUrl += 'guest-carts/'+ window.checkoutConfig.quoteItemData[0].quote_id +'/payment-information';
            //     } else {
            //         restUrl += 'carts/mine/payment-information';
            //         restUrl += '?form_key=' + window.checkoutConfig.formKey;
            //     }
            //
            //     // Set the event to update data on any button click
            //     $('button[type="submit"]')
            //     .off('click', isNewApi, self.getRestQuoteData)
            //     .on('click', isNewApi, self.getRestQuoteData);
            //
            //     // Send the AJAX request
            //     $.ajax({
            //         url: restUrl,
            //         type: 'GET',
            //         contentType: "application/json",
            //         dataType: "json",
            //         async: false,
            //         showLoader: true,
            //         success: function (data, status, xhr) {
            //             result = data;
            //         },
            //         error: function (request, status, error) {
            //             self.log(error);
            //         }
            //     });
            //
            //     if (result == null) {
            //        return self.getRestQuoteData(true);
            //     } else {
            //         return result;
            //     }
            // },
            /**
             * Get the updated quote data from the core REST API.
             *
             * @return {object}  The quote data.
             */
            getRestQuoteData: function () {
                // Prepare the required parameters
                var self = this;
                var result = null;

                // Build the URL
                var restUrl = window.BASE_URL + 'rest/default/V1/';
                    restUrl += 'carts/mine/payment-information';
                    restUrl += '?form_key=' + window.checkoutConfig.formKey;

                // Set the event to update data on any button click
                $('button[type="submit"]')
                .off('click', self.getRestQuoteData)
                .on('click', self.getRestQuoteData);

                for (let i = 0; i < 2; i++) {
                    // Send the AJAX request
                    $.ajax({
                        url: restUrl,
                        type: 'GET',
                        contentType: "application/json",
                        dataType: "json",
                        async: false,
                        showLoader: true,
                        success: function (data, status, xhr) {
                            result = data;
                        },
                        error: function (request, status, error) {
                            self.log(error);
                        }
                    });

                    if (result == null) {
                        //Rebuild URL if using M2 Guest API
                        restUrl = window.BASE_URL;
                        restUrl += 'guest-carts/'+ window.checkoutConfig.quoteItemData[0].quote_id +'/payment-information';
                    } else {
                        break;
                    }
                }

                    return result;
            },

            /**
             * Get the quote currency.
             *
             * @return {string}  The quote currency.
             */
            getQuoteCurrency: function () {
                return Config[KEY_DATA].quote.currency;
            },

            /**
             * Checks if user has saved cards.
             *
             * @return {bool}
             */
            userHasCards: function () {
                return Config[KEY_DATA].user.hasCards;
            },

            /**
             * Get the supported cards.
             *
             * @return {array}
             */
            getSupportedCards: function () {
                return Config[KEY_DATA].cards;
            },

            /**
             * Builds the controller URL.
             *
             * @param  {string}  path  The path
             * @return {string}
             */
            getUrl: function (path) {
                return Url.build('checkout_com/' + path);
            },

            /**
             * Customer name.
             *
             * @param  {bool} return in object format.
             * @return {mixed}  The billing address.
             */
            getCustomerName: function () {
                var billingAddress = Quote.billingAddress();
                var customerName = '';
                if (billingAddress) {
                    customerName += billingAddress.firstname;
                    customerName += ' ' + billingAddress.lastname;
                }

                return customerName;
            },

            /**
             * Billing address.
             *
             * @return {object}  The billing address.
             */
            getBillingAddress: function () {
                return Quote.billingAddress();
            },

            /**
             * @returns {string}
             */
            getEmail: function () {
                var emailCookieName = this.getValue(null, 'email_cookie_name');
                return window.checkoutConfig.customerData.email
                || Quote.guestEmail
                || CheckoutData.getValidatedEmailValue()
                || $.cookie(emailCookieName);
            },

            /**
             * @returns {void}
             */
            setEmail: function () {
                var userEmail = this.getEmail();
                var emailCookieName = this.getValue(null, 'email_cookie_name');
                $.cookie(emailCookieName, userEmail);

                // If no email found, observe the core email field
                if (!userEmail) {
                    $('#customer-email').off('change').on('change', function () {
                        userEmail = Quote.guestEmail || CheckoutData.getValidatedEmailValue();
                        $.cookie(emailCookieName, userEmail);
                    });
                }
            },

            /**
             * @returns {object}
             */
            getPhone: function () {
                var billingAddress = Quote.billingAddress();

                return {
                    number: billingAddress.telephone
                };
            },

            /**
             * Handle error logging.
             */
            log: function (val) {
                if (this.getValue(null, 'debug')
                    && this.getValue(null, 'console_logging')
                ) {
                    console.log(val);
                }
            },

            /**
             * Show a message.
             */
            showMessage: function (type, message, methodId) {
                this.clearMessages(methodId);
                var messageContainer = this.getMethodContainer(methodId).find('.message');
                messageContainer.addClass('message-' + type + ' ' + type);
                messageContainer.append('<div>' + __(message) + '</div>');
                messageContainer.show();
            },

            /**
             * Clear all messages.
             */
            clearMessages: function (methodId) {
                var messageContainer = this.getMethodContainer(methodId).find('.message');
                messageContainer.hide();
                messageContainer.empty();
            },

            /**
             * Get a payment method container instance.
             */
            getMethodContainer: function (methodId) {
                return $('#' + methodId + '_container');
            },

            /**
             * Check if an URL is valid.
             */
            isUrl: function (str) {
                var pattern = /^(?:\w+:)?\/\/([^\s\.]+\.\S{2}|localhost[\:?\d]*)\S*$/;
                return pattern.test(str);
            },

            /**
             * Handle the place order button state.
             */
            allowPlaceOrder: function (buttonId, yesNo) {
                $('#' + buttonId).prop('disabled', !yesNo);
            },

            /**
             * Check if a payment option is active.
             */
            methodIsSelected: function (idSelector) {
                var id = idSelector.replace('#', '');
                var selected = CheckoutData.getSelectedPaymentMethod();
                return id == selected;
            },

            /**
             * Place a new order.
             *
             * @returns {void}
             */
            placeOrder: function (payload, methodId) {
                var self = this;

                // Start the loader
                FullScreenLoader.startLoader();

                // Send the request
                $.ajax({
                    type: 'POST',
                    url: self.getUrl('payment/placeorder'),
                    data: payload,
                    success: function (data) {
                        if (!data.success) {
                            FullScreenLoader.stopLoader();
                            self.showMessage('error', data.message, methodId);
                        } else if (data.success && data.url) {
                            // Handle 3DS redirection
                            window.location.href = data.url
                        } else {
                            // Normal redirection
                            RedirectOnSuccessAction.execute();
                        }
                    },
                    error: function (request, status, error) {
                        self.showMessage('error', error, methodId);
                        FullScreenLoader.stopLoader();
                    }
                });
            }
        };
    }
);
<|endoftext|>


<commit_before><commit_msg>Delete popup.js<commit_after><|endoftext|>


<commit_before>// Uses local storage to add a note
function storeToLocalStorage(note){
    localStorage.setItem(note.storageKey, JSON.stringify(note));
    PinPoint.NoteController.storeNote(note);
}

// Array of notes in string format
var notes = [];

// Array of note objects to pass to controller
var noteObjects = [];

// Parses all strigified objects into JSON objects
function parseLocalStorage(){
    for (i in notes) {
        var key = notes[i]
        var retrievedObject = localStorage.getItem(key);
        noteObjects.push(JSON.parse(retrievedObject));
    }
}

// Searches the keys in LocalStorage and returns an array of matches
function searchLocalStorage(url){
    var key = url + "/";
    for (i in localStorage) {
        if (i.match(/^\w+\:\/\/www.youtube.com\/watch\?v=.+\//) == key) {
            notes.push(i);
        }
    }
    parseLocalStorage();
}

var createButton = document.getElementById("create");
var form = document.getElementById("add-note");
createButton.addEventListener('click', function(){
  createButton.style.display = "none";
  form.style.display = "inline";
  chrome.runtime.getBackgroundPage(function(eventPage) {
    eventPage.getPageDetails(PinPoint.NoteController.getTime);
    });
});

// Event listener for the create note button
var saveButton = document.getElementById("save");
saveButton.addEventListener('click', function(){
  saveButton.style.display = "none";
  note = new PinPoint.Note();
  PinPoint.NoteController.run(note);
});

window.addEventListener('load', function() {

  PinPoint.NoteController.getUrl();
  searchLocalStorage(localStorage["url"]);
  controller = new PinPoint.NoteController(noteObjects);
  controller.defineView(new PinPoint.View());
  controller.redraw();
  chrome.browserAction.setBadgeText({text: noteObjects.length.toString()});
  chrome.browserAction.setBadgeBackgroundColor({text: noteObjects.length.toString()});

});
<commit_msg>add comment and color options<commit_after>// Uses local storage to add a note
function storeToLocalStorage(note){
    localStorage.setItem(note.storageKey, JSON.stringify(note));
    PinPoint.NoteController.storeNote(note);
}

// Array of notes in string format
var notes = [];

// Array of note objects to pass to controller
var noteObjects = [];

// Parses all strigified objects into JSON objects
function parseLocalStorage(){
    for (i in notes) {
        var key = notes[i]
        var retrievedObject = localStorage.getItem(key);
        noteObjects.push(JSON.parse(retrievedObject));
    }
}

// Searches the keys in LocalStorage and returns an array of matches
function searchLocalStorage(url){
    var key = url + "/";
    for (i in localStorage) {
        if (i.match(/^\w+\:\/\/www.youtube.com\/watch\?v=.+\//) == key) {
            notes.push(i);
        }
    }
    parseLocalStorage();
}

var createButton = document.getElementById("create");
var form = document.getElementById("add-note");
createButton.addEventListener('click', function(){
  createButton.style.display = "none";
  form.style.display = "inline";
  chrome.runtime.getBackgroundPage(function(eventPage) {
    eventPage.getPageDetails(PinPoint.NoteController.getTime);
    });
});

// Event listener for the create note button
var saveButton = document.getElementById("save");
saveButton.addEventListener('click', function(){
  saveButton.style.display = "none";
  note = new PinPoint.Note();
  PinPoint.NoteController.run(note);
});

window.addEventListener('load', function() {

  PinPoint.NoteController.getUrl();
  searchLocalStorage(localStorage["url"]);
  controller = new PinPoint.NoteController(noteObjects);
  controller.defineView(new PinPoint.View());
  controller.redraw();
  chrome.browserAction.setBadgeText({text: noteObjects.length.toString()});
  //This gives us a nice light-ish purple
  chrome.browserAction.setBadgeBackgroundColor({color:[140, 5, 220, 170]});
  //COLOR OPTION 2: This gives us a nice golden orange color
  // chrome.browserAction.setBadgeBackgroundColor({color:[235, 105, 5, 220]});

});
<|endoftext|>


<commit_before>'use strict';

(function(scope) {
  if (scope.Proxy) {
    return;
  }

  /**
   * DefaultHandlers is a holder for default behavior applied on proxy objects (i.e., untrapped).
   */
  class DefaultHelpers {
    /**
     * @this {*}
     */
    get(prop) {
      return this[prop];
    }
   /**
    * @this {*}
    */
    set(prop, value) {
      this[prop] = value;
    }
  }

  /**
   * @constructor
   */
  scope.Proxy = function(target, handler) {
    if (!(target instanceof Object && handler instanceof Object)) {
      throw new TypeError('Cannot create proxy with a non-object as target or handler');
    }
    var proxy = this;

    // Fail on unsupported traps: Chrome doesn't do this, but ensure that users of the polyfill
    // are a bit more careful.
    var valid = {'get': true, 'set': true};
    for (var k in handler) {
      if (!valid[k]) {
        throw new TypeError('Proxy polyfill does not support trap \'' + k + '\'');
      }
    }

    // Override default helper behavior if traps were provided.
    var h = new DefaultHelpers();
    if (handler.get) {
      h.get = function(prop) {
        return handler.get(this, prop, proxy);
      };
    }
    if (handler.set) {
      h.set = function(prop, value) {
        handler.set(this, prop, value, proxy);
      };
    }

    Object.getOwnPropertyNames(target).forEach(function(prop) {
      // TODO(samthor): Probably can ignore some of this. Also, check target writable=false...
      var desc = Object.getOwnPropertyDescriptor(target, prop);
      delete desc.value;
      delete desc.writable;
      desc.get = h.get.bind(target, prop);
      desc.set = h.set.bind(target, prop);
      Object.defineProperty(proxy, prop, desc);
    });

    // The Proxy polyfill cannot handle adding new properties. Seal the target and proxy.
    // TODO(samthor): Chrome just silently fails when accessing now-invalid properties.
    Object.seal(target);
    Object.seal(proxy);
  };

  scope.Proxy.revocable = function(target, handler) {
    return {proxy: new scope.Proxy(target, handler), revoke: function() {
      // TODO(samthor): Note that calling revoke() cancels all operations on the Proxy object, not
      // just the ones with traps. It may be infeasible to polyfil.
      throw new Error('revoke not implemented');
    }};
  }

  scope.Proxy['revocable'] = scope.Proxy.revocable;
  scope['Proxy'] = scope.Proxy;
})(window);<commit_msg>es6 var => let<commit_after>'use strict';

(function(scope) {
  if (scope.Proxy) {
    return;
  }

  /**
   * DefaultHandlers is a holder for default behavior applied on proxy objects (i.e., untrapped).
   */
  class DefaultHelpers {
    /**
     * @this {*}
     */
    get(prop) {
      return this[prop];
    }
   /**
    * @this {*}
    */
    set(prop, value) {
      this[prop] = value;
    }
  }

  /**
   * @constructor
   */
  scope.Proxy = function(target, handler) {
    if (!(target instanceof Object && handler instanceof Object)) {
      throw new TypeError('Cannot create proxy with a non-object as target or handler');
    }
    let proxy = this;

    // Fail on unsupported traps: Chrome doesn't do this, but ensure that users of the polyfill
    // are a bit more careful.
    let valid = {'get': true, 'set': true};
    for (let k in handler) {
      if (!valid[k]) {
        throw new TypeError('Proxy polyfill does not support trap \'' + k + '\'');
      }
    }

    // Override default helper behavior if traps were provided.
    let h = new DefaultHelpers();
    if (handler.get) {
      h.get = function(prop) {
        return handler.get(this, prop, proxy);
      };
    }
    if (handler.set) {
      h.set = function(prop, value) {
        handler.set(this, prop, value, proxy);
      };
    }

    Object.getOwnPropertyNames(target).forEach(function(prop) {
      // TODO(samthor): Probably can ignore some of this. Also, check target writable=false...
      let desc = Object.getOwnPropertyDescriptor(target, prop);
      delete desc.value;
      delete desc.writable;
      desc.get = h.get.bind(target, prop);
      desc.set = h.set.bind(target, prop);
      Object.defineProperty(proxy, prop, desc);
    });

    // The Proxy polyfill cannot handle adding new properties. Seal the target and proxy.
    // TODO(samthor): Chrome just silently fails when accessing now-invalid properties.
    Object.seal(target);
    Object.seal(proxy);
  };

  scope.Proxy.revocable = function(target, handler) {
    return {proxy: new scope.Proxy(target, handler), revoke: function() {
      // TODO(samthor): Note that calling revoke() cancels all operations on the Proxy object, not
      // just the ones with traps. It may be infeasible to polyfil.
      throw new Error('revoke not implemented');
    }};
  }

  scope.Proxy['revocable'] = scope.Proxy.revocable;
  scope['Proxy'] = scope.Proxy;
})(window);<|endoftext|>


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

var Stream = require("stream");
var Otiluke = require("otiluke");
var Browserify = require("browserify");
var Minimist = require("minimist");

var args = Minimist(process.argv.slice(2));
var ports = {http:args["http-port"], ssl:args["ssl-port"]};
if ("help" in args)
  console.log("Usage: aran --entry /path/to/entry.js --http-port 8080 --ssl-port 8443")
if (!args.entry)
  throw "Argument --entry is mandatory"

var buffer = [];
var writable = new Stream.Writable();
writable._write = function (chunk, encoding, done) {
  buffer.push(chunk.toString("utf8"));
  done();
};
writable.on("finish", function () {
  buffer.push("\nrequire('trololo');");
  Otiluke("aran", buffer.join(""), ports);
});
var b = Browserify();
b.require(args.entry, {expose:"trololo"});
b.bundle().pipe(writable);

// FS.readFile(process.argv[2], {encoding:"utf8"}, function (err, master) {
//   if (err) { throw new Error(err) }
//   FS.readFile(process.argv[3], {encoding:"utf8"}, function (err, target) {
//     if (err) { throw new Error(err) }
//     var exports = {}
//     eval(master)
//     var aran = Aran(exports.sandbox, exports.hooks, exports.traps)
//     aran(target)
//   })
// })
<commit_msg>update arguments in proxy.js<commit_after>#!/usr/bin/env node

var Stream = require("stream");
var Otiluke = require("otiluke");
var Browserify = require("browserify");
var Minimist = require("minimist");

var args = Minimist(process.argv.slice(2));
if ("help" in args)
  console.log("Usage: aran --entry /path/to/entry.js --port 8080")
if (!args.entry)
  throw "Argument --entry is mandatory"

var buffer = [];
var writable = new Stream.Writable();
writable._write = function (chunk, encoding, done) {
  buffer.push(chunk.toString("utf8"));
  done();
};
writable.on("finish", function () {
  buffer.push("\nrequire('trololo');");
  Otiluke("aran", buffer.join(""), args.port);
});
var b = Browserify();
b.require(args.entry, {expose:"trololo"});
b.bundle().pipe(writable);

// FS.readFile(process.argv[2], {encoding:"utf8"}, function (err, master) {
//   if (err) { throw new Error(err) }
//   FS.readFile(process.argv[3], {encoding:"utf8"}, function (err, target) {
//     if (err) { throw new Error(err) }
//     var exports = {}
//     eval(master)
//     var aran = Aran(exports.sandbox, exports.hooks, exports.traps)
//     aran(target)
//   })
// })
<|endoftext|>