node-mirror
Version:
node.js + CodeMirror = Great IDE and Admin Tool
1,421 lines (1,272 loc) • 724 kB
JavaScript
!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.formatter=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
/**
* Returns the lines from a file with comments removed. Will report erroneous
* trailing tokens in multiline comments if an error reporter is provided.
*
* @param {JsFile} file
* @param {Errors} [errors=null] errors
* @returns {Array}
*/
exports.getLinesWithCommentsRemoved = function(file, errors) {
var lines = file.getLines().concat();
file.getComments().reverse().forEach(function(comment) {
var startLine = comment.loc.start.line;
var startCol = comment.loc.start.column;
var endLine = comment.loc.end.line;
var endCol = comment.loc.end.column;
var i = startLine - 1;
if (startLine === endLine) {
lines[i] = lines[i].substring(0, startCol) + lines[i].substring(endCol);
} else {
lines[i] = lines[i].substring(0, startCol);
for (var x = i + 1; x < endLine - 1; x++) {
lines[x] = '';
}
lines[x] = lines[x].substring(endCol + 1);
if (errors && lines[x] !== '') {
errors.add(
'Multiline comments should not have tokens on its ending line',
x + 1,
endCol
);
}
}
});
return lines;
};
},{}],2:[function(require,module,exports){
var assert = require('assert');
var path = require('path');
var minimatch = require('minimatch');
var BUILTIN_OPTIONS = {
plugins: true,
preset: true,
excludeFiles: true,
additionalRules: true,
fileExtensions: true,
maxErrors: true,
configPath: true,
esnext: true,
esprima: true,
errorFilter: true
};
/**
* JSCS Configuration.
* Browser/Rhino-compatible.
*
* @name Configuration
*/
function Configuration() {
this._presets = {};
this._rules = {};
this._configuredRules = [];
this._configuredFormattingRules = [];
this._unsupportedRuleNames = [];
this._fileExtensions = ['.js'];
this._excludedFileMasks = [];
this._excludedFileMatchers = [];
this._ruleSettings = {};
this._maxErrors = null;
this._basePath = '.';
this._overrides = {};
this._presetName = null;
this._esnextEnabled = false;
this._esprima = null;
this._errorFilter = null;
}
/**
* Load settings from a configuration.
*
* @param {Object} config
*/
Configuration.prototype.load = function(config) {
this._throwNonCamelCaseErrorIfNeeded(config);
var overrides = this._overrides;
var currentConfig = {};
copyConfiguration(config, currentConfig);
copyConfiguration(overrides, currentConfig);
var ruleSettings = this._processConfig(currentConfig);
var processedSettings = {};
Object.keys(ruleSettings).forEach(function(optionName) {
var rule = this._rules[optionName];
if (rule) {
var optionValue = ruleSettings[optionName];
if (optionValue !== null) {
rule.configure(ruleSettings[optionName]);
this._configuredRules.push(rule);
if (rule.format) {
this._configuredFormattingRules.push(rule);
}
processedSettings[optionName] = ruleSettings[optionName];
}
} else {
this._unsupportedRuleNames.push(optionName);
}
}, this);
this._ruleSettings = processedSettings;
};
/**
* Returns resulting configuration after preset is applied and options are processed.
*
* @return {Object}
*/
Configuration.prototype.getProcessedConfig = function() {
var result = {};
Object.keys(this._ruleSettings).forEach(function(key) {
result[key] = this._ruleSettings[key];
}, this);
result.excludeFiles = this._excludedFileMasks;
result.fileExtensions = this._fileExtensions;
result.maxErrors = this._maxErrors;
result.preset = this._presetName;
result.esnext = this._esnextEnabled;
result.esprima = this._esprima;
result.errorFilter = this._errorFilter;
return result;
};
/**
* Returns list of configured formatting rules.
*
* @returns {Rule[]}
*/
Configuration.prototype.getConfiguredFormattingRules = function() {
return this._configuredFormattingRules;
};
/**
* Returns list of configured rules.
*
* @returns {Rule[]}
*/
Configuration.prototype.getConfiguredRules = function() {
return this._configuredRules;
};
/**
* Returns the list of unsupported rule names.
*
* @return {String[]}
*/
Configuration.prototype.getUnsupportedRuleNames = function() {
return this._unsupportedRuleNames;
};
/**
* Returns excluded file mask list.
*
* @returns {String[]}
*/
Configuration.prototype.getExcludedFileMasks = function() {
return this._excludedFileMasks;
};
/**
* Returns `true` if specified file path is excluded.
*
* @param {String} filePath
* @returns {Boolean}
*/
Configuration.prototype.isFileExcluded = function(filePath) {
filePath = path.resolve(filePath);
return this._excludedFileMatchers.some(function(matcher) {
return matcher.match(filePath);
});
};
/**
* Returns file extension list.
*
* @returns {String[]}
*/
Configuration.prototype.getFileExtensions = function() {
return this._fileExtensions;
};
/**
* Returns maximal error count.
*
* @returns {Number|undefined}
*/
Configuration.prototype.getMaxErrors = function() {
return this._maxErrors;
};
/**
* Returns `true` if `esnext` option is enabled.
*
* @returns {Boolean}
*/
Configuration.prototype.isESNextEnabled = function() {
return this._esnextEnabled;
};
/**
* Returns `true` if `esprima` option is not null.
*
* @returns {Boolean}
*/
Configuration.prototype.hasCustomEsprima = function() {
return !!this._esprima;
};
/**
* Returns the custom esprima parser.
*
* @returns {Object|null}
*/
Configuration.prototype.getCustomEsprima = function() {
return this._esprima;
};
/**
* Returns the loaded error filter.
*
* @returns {Function|null}
*/
Configuration.prototype.getErrorFilter = function() {
return this._errorFilter;
};
/**
* Returns base path.
*
* @returns {String}
*/
Configuration.prototype.getBasePath = function() {
return this._basePath;
};
/**
* Overrides specified settings.
*
* @param {String} overrides
*/
Configuration.prototype.override = function(overrides) {
Object.keys(overrides).forEach(function(key) {
this._overrides[key] = overrides[key];
}, this);
};
/**
* Processes configuration and returns config options.
*
* @param {Object} config
* @returns {Object}
*/
Configuration.prototype._processConfig = function(config) {
var ruleSettings = {};
// Base path
if (config.configPath) {
assert(
typeof config.configPath === 'string',
'`configPath` option requires string value'
);
this._basePath = path.dirname(config.configPath);
}
// Load plugins
if (config.plugins) {
assert(Array.isArray(config.plugins), '`plugins` option requires array value');
config.plugins.forEach(this._loadPlugin, this);
}
// Apply presets
var presetName = config.preset;
if (presetName) {
this._presetName = presetName;
assert(typeof presetName === 'string', '`preset` option requires string value');
var presetData = this._presets[presetName];
assert(Boolean(presetData), 'Preset "' + presetName + '" does not exist');
var presetResult = this._processConfig(presetData);
Object.keys(presetResult).forEach(function(key) {
ruleSettings[key] = presetResult[key];
});
}
// File extensions
if (config.fileExtensions) {
assert(
typeof config.fileExtensions === 'string' || Array.isArray(config.fileExtensions),
'`fileExtensions` option requires string or array value'
);
this._fileExtensions = [].concat(config.fileExtensions).map(function(ext) {
return ext.toLowerCase();
});
}
// File excludes
if (config.excludeFiles) {
assert(Array.isArray(config.excludeFiles), '`excludeFiles` option requires array value');
this._excludedFileMasks = config.excludeFiles;
this._excludedFileMatchers = this._excludedFileMasks.map(function(fileMask) {
return new minimatch.Minimatch(path.resolve(this._basePath, fileMask), {
dot: true
});
}, this);
}
// Additional rules
if (config.additionalRules) {
assert(Array.isArray(config.additionalRules), '`additionalRules` option requires array value');
config.additionalRules.forEach(this._loadAdditionalRule, this);
}
if (config.hasOwnProperty('maxErrors')) {
var maxErrors = config.maxErrors === null ? null : Number(config.maxErrors);
assert(
maxErrors > 0 || isNaN(maxErrors) || maxErrors === null,
'`maxErrors` option requires number or null value'
);
this._maxErrors = maxErrors;
}
if (config.hasOwnProperty('esnext')) {
assert(
typeof config.esnext === 'boolean' || config.esnext === null,
'`esnext` option requires boolean or null value'
);
this._esnextEnabled = Boolean(config.esnext);
}
if (config.hasOwnProperty('esprima')) {
this._loadEsprima(config.esprima);
}
if (config.hasOwnProperty('errorFilter')) {
this._loadErrorFilter(config.errorFilter);
}
// Apply config options
Object.keys(config).forEach(function(key) {
if (!BUILTIN_OPTIONS[key]) {
ruleSettings[key] = config[key];
}
});
return ruleSettings;
};
/**
* Loads plugin data.
*
* @param {function(Configuration)} plugin
* @protected
*/
Configuration.prototype._loadPlugin = function(plugin) {
assert(typeof plugin === 'function', '`plugin` should be a function');
plugin(this);
};
/**
* Loads an error filter.
*
* @param {Function|null} errorFilter
* @protected
*/
Configuration.prototype._loadErrorFilter = function(errorFilter) {
assert(
typeof errorFilter === 'function' ||
errorFilter === null,
'`errorFilter` option requires a function or null value'
);
this._errorFilter = errorFilter;
};
/**
* Loads a custom esprima.
*
* @param {Object|null} esprima
* @protected
*/
Configuration.prototype._loadEsprima = function(esprima) {
assert(
(esprima && typeof esprima.parse === 'function') ||
esprima === null,
'`esprima` option requires a null value or an object with a parse function'
);
this._esprima = esprima;
};
/**
* Includes plugin in the configuration environment.
*
* @param {function(Configuration)|*} plugin
*/
Configuration.prototype.usePlugin = function(plugin) {
this._loadPlugin(plugin);
};
/**
* Loads additional rule.
*
* @param {Rule} additionalRule
* @protected
*/
Configuration.prototype._loadAdditionalRule = function(additionalRule) {
assert(typeof additionalRule === 'object', '`additionalRule` should be an object');
this.registerRule(additionalRule);
};
/**
* Throws error for non camel-case options.
*
* @param {Object} ruleSettings
* @protected
*/
Configuration.prototype._throwNonCamelCaseErrorIfNeeded = function(ruleSettings) {
function symbolToUpperCase(s, symbol) {
return symbol.toUpperCase();
}
function fixSettings(originalSettings) {
var result = {};
Object.keys(originalSettings).forEach(function(key) {
var camelCaseName = key.replace(/_([a-zA-Z])/g, symbolToUpperCase);
var value = originalSettings[key];
if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
value = fixSettings(value);
}
result[camelCaseName] = value;
});
return result;
}
Object.keys(ruleSettings).forEach(function(key) {
if (key.indexOf('_') !== -1) {
throw new Error(
'JSCS now accepts configuration options in camel case. Sorry for inconvenience. ' +
'On the bright side, we tried to convert your jscs config to camel case.\n' +
'----------------------------------------\n' +
JSON.stringify(fixSettings(ruleSettings), null, 4) +
'\n----------------------------------------\n'
);
}
});
};
/**
* Adds rule to the collection.
*
* @param {Rule|function} rule Rule instance or rule class.
*/
Configuration.prototype.registerRule = function(rule) {
if (typeof rule === 'function') {
var RuleClass = rule;
rule = new RuleClass();
}
var optionName = rule.getOptionName();
assert(!this._rules.hasOwnProperty(optionName), 'Rule "' + optionName + '" is already registered');
this._rules[optionName] = rule;
};
/**
* Returns list of registered rules.
*
* @returns {Rule[]}
*/
Configuration.prototype.getRegisteredRules = function() {
var rules = this._rules;
return Object.keys(rules).map(function(ruleOptionName) {
return rules[ruleOptionName];
});
};
/**
* Adds preset to the collection.
*
* @param {String} presetName
* @param {Object} presetConfig
*/
Configuration.prototype.registerPreset = function(presetName, presetConfig) {
this._presets[presetName] = presetConfig;
};
/**
* Returns registered presets object (key - preset name, value - preset content).
*
* @returns {Object}
*/
Configuration.prototype.getRegisteredPresets = function() {
return this._presets;
};
/**
* Returns `true` if preset with specified name exists.
*
* @param {String} presetName
* @return {Boolean}
*/
Configuration.prototype.hasPreset = function(presetName) {
return this._presets.hasOwnProperty(presetName);
};
/**
* Registers built-in Code Style cheking rules.
*/
Configuration.prototype.registerDefaultRules = function() {
/*
Important!
These rules are linked explicitly to keep browser-version supported.
*/
this.registerRule(require('../rules/require-curly-braces'));
this.registerRule(require('../rules/require-multiple-var-decl'));
this.registerRule(require('../rules/disallow-multiple-var-decl'));
this.registerRule(require('../rules/disallow-empty-blocks'));
this.registerRule(require('../rules/require-space-after-keywords'));
this.registerRule(require('../rules/require-space-before-keywords'));
this.registerRule(require('../rules/disallow-space-after-keywords'));
this.registerRule(require('../rules/disallow-space-before-keywords'));
this.registerRule(require('../rules/require-parentheses-around-iife'));
/* deprecated rules */
this.registerRule(require('../rules/require-left-sticked-operators'));
this.registerRule(require('../rules/disallow-left-sticked-operators'));
this.registerRule(require('../rules/require-right-sticked-operators'));
this.registerRule(require('../rules/disallow-right-sticked-operators'));
this.registerRule(require('../rules/validate-jsdoc'));
/* deprecated rules (end) */
this.registerRule(require('../rules/require-operator-before-line-break'));
this.registerRule(require('../rules/disallow-operator-before-line-break'));
this.registerRule(require('../rules/disallow-implicit-type-conversion'));
this.registerRule(require('../rules/require-camelcase-or-uppercase-identifiers'));
this.registerRule(require('../rules/disallow-keywords'));
this.registerRule(require('../rules/disallow-multiple-line-breaks'));
this.registerRule(require('../rules/disallow-multiple-line-strings'));
this.registerRule(require('../rules/validate-line-breaks'));
this.registerRule(require('../rules/validate-quote-marks'));
this.registerRule(require('../rules/validate-indentation'));
this.registerRule(require('../rules/disallow-trailing-whitespace'));
this.registerRule(require('../rules/disallow-mixed-spaces-and-tabs'));
this.registerRule(require('../rules/require-keywords-on-new-line'));
this.registerRule(require('../rules/disallow-keywords-on-new-line'));
this.registerRule(require('../rules/require-line-feed-at-file-end'));
this.registerRule(require('../rules/maximum-line-length'));
this.registerRule(require('../rules/require-yoda-conditions'));
this.registerRule(require('../rules/disallow-yoda-conditions'));
this.registerRule(require('../rules/require-spaces-inside-object-brackets'));
this.registerRule(require('../rules/require-spaces-inside-array-brackets'));
this.registerRule(require('../rules/require-spaces-inside-parentheses'));
this.registerRule(require('../rules/disallow-spaces-inside-object-brackets'));
this.registerRule(require('../rules/disallow-spaces-inside-array-brackets'));
this.registerRule(require('../rules/disallow-spaces-inside-parentheses'));
this.registerRule(require('../rules/require-blocks-on-newline'));
this.registerRule(require('../rules/require-space-after-object-keys'));
this.registerRule(require('../rules/require-space-before-object-values'));
this.registerRule(require('../rules/disallow-space-after-object-keys'));
this.registerRule(require('../rules/disallow-space-before-object-values'));
this.registerRule(require('../rules/disallow-quoted-keys-in-objects'));
this.registerRule(require('../rules/disallow-dangling-underscores'));
this.registerRule(require('../rules/require-aligned-object-values'));
this.registerRule(require('../rules/disallow-padding-newlines-in-blocks'));
this.registerRule(require('../rules/require-padding-newlines-in-blocks'));
this.registerRule(require('../rules/require-padding-newlines-in-objects'));
this.registerRule(require('../rules/disallow-padding-newlines-in-objects'));
this.registerRule(require('../rules/require-newline-before-block-statements'));
this.registerRule(require('../rules/disallow-newline-before-block-statements'));
this.registerRule(require('../rules/require-padding-newlines-before-keywords'));
this.registerRule(require('../rules/disallow-padding-newlines-before-keywords'));
this.registerRule(require('../rules/disallow-trailing-comma'));
this.registerRule(require('../rules/require-trailing-comma'));
this.registerRule(require('../rules/disallow-comma-before-line-break'));
this.registerRule(require('../rules/require-comma-before-line-break'));
this.registerRule(require('../rules/disallow-space-before-block-statements.js'));
this.registerRule(require('../rules/require-space-before-block-statements.js'));
this.registerRule(require('../rules/disallow-space-before-postfix-unary-operators.js'));
this.registerRule(require('../rules/require-space-before-postfix-unary-operators.js'));
this.registerRule(require('../rules/disallow-space-after-prefix-unary-operators.js'));
this.registerRule(require('../rules/require-space-after-prefix-unary-operators.js'));
this.registerRule(require('../rules/disallow-space-before-binary-operators'));
this.registerRule(require('../rules/require-space-before-binary-operators'));
this.registerRule(require('../rules/disallow-space-after-binary-operators'));
this.registerRule(require('../rules/require-space-after-binary-operators'));
this.registerRule(require('../rules/require-spaces-in-conditional-expression'));
this.registerRule(require('../rules/disallow-spaces-in-conditional-expression'));
this.registerRule(require('../rules/require-spaces-in-function'));
this.registerRule(require('../rules/disallow-spaces-in-function'));
this.registerRule(require('../rules/require-spaces-in-function-expression'));
this.registerRule(require('../rules/disallow-spaces-in-function-expression'));
this.registerRule(require('../rules/require-spaces-in-anonymous-function-expression'));
this.registerRule(require('../rules/disallow-spaces-in-anonymous-function-expression'));
this.registerRule(require('../rules/require-spaces-in-named-function-expression'));
this.registerRule(require('../rules/disallow-spaces-in-named-function-expression'));
this.registerRule(require('../rules/require-spaces-in-function-declaration'));
this.registerRule(require('../rules/disallow-spaces-in-function-declaration'));
this.registerRule(require('../rules/require-spaces-in-call-expression'));
this.registerRule(require('../rules/disallow-spaces-in-call-expression'));
this.registerRule(require('../rules/validate-parameter-separator'));
this.registerRule(require('../rules/require-space-between-arguments'));
this.registerRule(require('../rules/disallow-space-between-arguments'));
this.registerRule(require('../rules/require-capitalized-constructors'));
this.registerRule(require('../rules/safe-context-keyword'));
this.registerRule(require('../rules/require-dot-notation'));
this.registerRule(require('../rules/require-space-after-line-comment'));
this.registerRule(require('../rules/disallow-space-after-line-comment'));
this.registerRule(require('../rules/require-anonymous-functions'));
this.registerRule(require('../rules/disallow-anonymous-functions'));
this.registerRule(require('../rules/require-function-declarations'));
this.registerRule(require('../rules/disallow-function-declarations'));
this.registerRule(require('../rules/require-capitalized-comments'));
this.registerRule(require('../rules/disallow-capitalized-comments'));
this.registerRule(require('../rules/require-line-break-after-variable-assignment'));
this.registerRule(require('../rules/disallow-semicolons'));
this.registerRule(require('../rules/require-spaces-in-for-statement'));
this.registerRule(require('../rules/require-spaces-in-computed-memberExpression'));
this.registerRule(require('../rules/validate-object-indentation'));
};
/**
* Registers built-in Code Style cheking presets.
*/
Configuration.prototype.registerDefaultPresets = function() {
// https://github.com/airbnb/javascript
this.registerPreset('airbnb', require('../../presets/airbnb.json'));
// http://javascript.crockford.com/code.html
this.registerPreset('crockford', require('../../presets/crockford.json'));
// https://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml
this.registerPreset('google', require('../../presets/google.json'));
// http://gruntjs.com/contributing#syntax
this.registerPreset('grunt', require('../../presets/grunt.json'));
// https://contribute.jquery.org/style-guide/js/
this.registerPreset('jquery', require('../../presets/jquery.json'));
// https://github.com/mrdoob/three.js/wiki/Mr.doob's-Code-Style%E2%84%A2
this.registerPreset('mdcs', require('../../presets/mdcs.json'));
// https://www.mediawiki.org/wiki/Manual:Coding_conventions/JavaScript
this.registerPreset('wikimedia', require('../../presets/wikimedia.json'));
// https://github.com/yandex/codestyle/blob/master/js.md
this.registerPreset('yandex', require('../../presets/yandex.json'));
};
module.exports = Configuration;
function copyConfiguration(source, dest) {
Object.keys(source).forEach(function(key) {
dest[key] = source[key];
});
if (source.configPath) {
dest.configPath = source.configPath;
}
}
},{"../../presets/airbnb.json":134,"../../presets/crockford.json":135,"../../presets/google.json":136,"../../presets/grunt.json":137,"../../presets/jquery.json":138,"../../presets/mdcs.json":139,"../../presets/wikimedia.json":140,"../../presets/yandex.json":141,"../rules/disallow-anonymous-functions":5,"../rules/disallow-capitalized-comments":6,"../rules/disallow-comma-before-line-break":7,"../rules/disallow-dangling-underscores":8,"../rules/disallow-empty-blocks":9,"../rules/disallow-function-declarations":10,"../rules/disallow-implicit-type-conversion":11,"../rules/disallow-keywords":13,"../rules/disallow-keywords-on-new-line":12,"../rules/disallow-left-sticked-operators":14,"../rules/disallow-mixed-spaces-and-tabs":15,"../rules/disallow-multiple-line-breaks":16,"../rules/disallow-multiple-line-strings":17,"../rules/disallow-multiple-var-decl":18,"../rules/disallow-newline-before-block-statements":19,"../rules/disallow-operator-before-line-break":20,"../rules/disallow-padding-newlines-before-keywords":21,"../rules/disallow-padding-newlines-in-blocks":22,"../rules/disallow-padding-newlines-in-objects":23,"../rules/disallow-quoted-keys-in-objects":24,"../rules/disallow-right-sticked-operators":25,"../rules/disallow-semicolons":26,"../rules/disallow-space-after-binary-operators":27,"../rules/disallow-space-after-keywords":28,"../rules/disallow-space-after-line-comment":29,"../rules/disallow-space-after-object-keys":30,"../rules/disallow-space-after-prefix-unary-operators.js":31,"../rules/disallow-space-before-binary-operators":32,"../rules/disallow-space-before-block-statements.js":33,"../rules/disallow-space-before-keywords":34,"../rules/disallow-space-before-object-values":35,"../rules/disallow-space-before-postfix-unary-operators.js":36,"../rules/disallow-space-between-arguments":37,"../rules/disallow-spaces-in-anonymous-function-expression":38,"../rules/disallow-spaces-in-call-expression":39,"../rules/disallow-spaces-in-conditional-expression":40,"../rules/disallow-spaces-in-function":43,"../rules/disallow-spaces-in-function-declaration":41,"../rules/disallow-spaces-in-function-expression":42,"../rules/disallow-spaces-in-named-function-expression":44,"../rules/disallow-spaces-inside-array-brackets":45,"../rules/disallow-spaces-inside-object-brackets":46,"../rules/disallow-spaces-inside-parentheses":47,"../rules/disallow-trailing-comma":48,"../rules/disallow-trailing-whitespace":49,"../rules/disallow-yoda-conditions":50,"../rules/maximum-line-length":51,"../rules/require-aligned-object-values":52,"../rules/require-anonymous-functions":53,"../rules/require-blocks-on-newline":54,"../rules/require-camelcase-or-uppercase-identifiers":55,"../rules/require-capitalized-comments":56,"../rules/require-capitalized-constructors":57,"../rules/require-comma-before-line-break":58,"../rules/require-curly-braces":59,"../rules/require-dot-notation":60,"../rules/require-function-declarations":61,"../rules/require-keywords-on-new-line":62,"../rules/require-left-sticked-operators":63,"../rules/require-line-break-after-variable-assignment":64,"../rules/require-line-feed-at-file-end":65,"../rules/require-multiple-var-decl":66,"../rules/require-newline-before-block-statements":67,"../rules/require-operator-before-line-break":68,"../rules/require-padding-newlines-before-keywords":69,"../rules/require-padding-newlines-in-blocks":70,"../rules/require-padding-newlines-in-objects":71,"../rules/require-parentheses-around-iife":72,"../rules/require-right-sticked-operators":73,"../rules/require-space-after-binary-operators":74,"../rules/require-space-after-keywords":75,"../rules/require-space-after-line-comment":76,"../rules/require-space-after-object-keys":77,"../rules/require-space-after-prefix-unary-operators.js":78,"../rules/require-space-before-binary-operators":79,"../rules/require-space-before-block-statements.js":80,"../rules/require-space-before-keywords":81,"../rules/require-space-before-object-values":82,"../rules/require-space-before-postfix-unary-operators.js":83,"../rules/require-space-between-arguments":84,"../rules/require-spaces-in-anonymous-function-expression":85,"../rules/require-spaces-in-call-expression":86,"../rules/require-spaces-in-computed-memberExpression":87,"../rules/require-spaces-in-conditional-expression":88,"../rules/require-spaces-in-for-statement":89,"../rules/require-spaces-in-function":92,"../rules/require-spaces-in-function-declaration":90,"../rules/require-spaces-in-function-expression":91,"../rules/require-spaces-in-named-function-expression":93,"../rules/require-spaces-inside-array-brackets":94,"../rules/require-spaces-inside-object-brackets":95,"../rules/require-spaces-inside-parentheses":96,"../rules/require-trailing-comma":97,"../rules/require-yoda-conditions":98,"../rules/safe-context-keyword":99,"../rules/validate-indentation":100,"../rules/validate-jsdoc":101,"../rules/validate-line-breaks":102,"../rules/validate-object-indentation":103,"../rules/validate-parameter-separator":104,"../rules/validate-quote-marks":105,"assert":143,"minimatch":125,"path":146}],3:[function(require,module,exports){
var assert = require('assert');
var colors = require('colors');
var TokenAssert = require('./token-assert');
/**
* Set of errors for specified file.
*
* @name Errors
* @param {JsFile} file
* @param {Boolean} verbose
*/
var Errors = function(file, verbose) {
this._errorList = [];
this._file = file;
this._currentRule = '';
this._verbose = verbose || false;
/**
* @type {TokenAssert}
* @public
*/
this.assert = new TokenAssert(file);
this.assert.on('error', this._addError.bind(this));
};
Errors.prototype = {
/**
* Adds style error to the list
*
* @param {String} message
* @param {Number|Object} line
* @param {Number} [column] optional if line is an object
*/
add: function(message, line, column) {
if (typeof line === 'object') {
column = line.column;
line = line.line;
}
// line and column numbers should be explicit
assert(typeof line === 'number' && line > 0,
'Unable to add an error, `line` should be a number greater than 0 but ' + line + ' given');
assert(typeof column === 'number' && column >= 0,
'Unable to add an error, `column` should be a positive number but ' + column + ' given');
this._addError({
message: message,
line: line,
column: column
});
},
/**
* Adds error to error list.
*
* @param {Object} errorInfo
* @private
*/
_addError: function(errorInfo) {
if (!this._file.isEnabledRule(this._currentRule, errorInfo.line)) {
return;
}
this._errorList.push({
filename: this._file.getFilename(),
rule: this._currentRule,
message: this._verbose ? this._currentRule + ': ' + errorInfo.message : errorInfo.message,
line: errorInfo.line,
column: errorInfo.column
});
},
/**
* Returns style error list.
*
* @returns {Object[]}
*/
getErrorList: function() {
return this._errorList;
},
/**
* Returns filename of file this error list is for.
*
* @returns {String}
*/
getFilename: function() {
return this._file.getFilename();
},
/**
* Returns true if no errors are added.
*
* @returns {Boolean}
*/
isEmpty: function() {
return this._errorList.length === 0;
},
/**
* Returns amount of errors added by the rules.
*
* @returns {Number}
*/
getErrorCount: function() {
return this._errorList.length;
},
/**
* Strips error list to the specified length.
*
* @param {Number} length
*/
stripErrorList: function(length) {
this._errorList.splice(length);
},
/**
* Filters out errors based on the supplied filter function
*
* @param {Function} filter
*/
filter: function(filter) {
this._errorList = this._errorList.filter(filter);
},
/**
* Formats error for further output.
*
* @param {Object} error
* @param {Boolean} colorize
* @returns {String}
*/
explainError: function(error, colorize) {
var lineNumber = error.line - 1;
var lines = this._file.getLines();
var result = [
renderLine(lineNumber, lines[lineNumber], colorize),
renderPointer(error.column, colorize)
];
var i = lineNumber - 1;
var linesAround = 2;
while (i >= 0 && i >= (lineNumber - linesAround)) {
result.unshift(renderLine(i, lines[i], colorize));
i--;
}
i = lineNumber + 1;
while (i < lines.length && i <= (lineNumber + linesAround)) {
result.push(renderLine(i, lines[i], colorize));
i++;
}
result.unshift(formatErrorMessage(error.message, this.getFilename(), colorize));
return result.join('\n');
},
/**
* Sets the current rule so that errors are aware
* of which rule triggered them.
*
* @param {String} rule
*/
setCurrentRule: function(rule) {
this._currentRule = rule;
}
};
/**
* Formats error message header.
*
* @param {String} message
* @param {String} filename
* @param {Boolean} colorize
* @returns {String}
*/
function formatErrorMessage(message, filename, colorize) {
return (colorize ? colors.bold(message) : message) +
' at ' +
(colorize ? colors.green(filename) : filename) + ' :';
}
/**
* Simple util for prepending spaces to the string until it fits specified size.
*
* @param {String} s
* @param {Number} len
* @returns {String}
*/
function prependSpaces(s, len) {
while (s.length < len) {
s = ' ' + s;
}
return s;
}
/**
* Renders single line of code in style error formatted output.
*
* @param {Number} n line number
* @param {String} line
* @param {Boolean} colorize
* @returns {String}
*/
function renderLine(n, line, colorize) {
// Convert tabs to spaces, so errors in code lines with tabs as indention symbol
// could be correctly rendered, plus it will provide less verbose output
line = line.replace(/\t/g, ' ');
// "n + 1" to print lines in human way (counted from 1)
var lineNumber = prependSpaces((n + 1).toString(), 5) + ' |';
return ' ' + (colorize ? colors.grey(lineNumber) : lineNumber) + line;
}
/**
* Renders pointer:
* ---------------^
*
* @param {Number} column
* @param {Boolean} colorize
* @returns {String}
*/
function renderPointer(column, colorize) {
var res = (new Array(column + 9)).join('-') + '^';
return colorize ? colors.grey(res) : res;
}
module.exports = Errors;
},{"./token-assert":107,"assert":143,"colors":115}],4:[function(require,module,exports){
var treeIterator = require('./tree-iterator');
/**
* Operator list which are represented as keywords in token list.
*/
var KEYWORD_OPERATORS = {
'instanceof': true,
'in': true
};
/**
* File representation for JSCS.
*
* @name JsFile
*/
var JsFile = function(filename, source, tree) {
this._filename = filename;
this._source = source;
this._changes = [];
this._tree = tree || {tokens: []};
this._lines = source.split(/\r\n|\r|\n/);
this._tokenRangeStartIndex = null;
this._tokenRangeEndIndex = null;
var index = this._index = {};
var _this = this;
this._buildTokenIndex();
this.iterate(function(node, parentNode, parentCollection) {
var type = node.type;
node.parentNode = parentNode;
node.parentCollection = parentCollection;
(index[type] || (index[type] = [])).push(node);
// Temporary fix (i hope) for esprima tokenizer
// (https://code.google.com/p/esprima/issues/detail?id=481)
// Fixes #83, #180
switch (type) {
case 'Property':
convertKeywordToIdentifierIfRequired(node.key);
break;
case 'MemberExpression':
convertKeywordToIdentifierIfRequired(node.property);
break;
}
});
this._buildDisabledRuleIndex();
// Part of temporary esprima fix.
function convertKeywordToIdentifierIfRequired(node) {
var tokenPos = _this.getTokenPosByRangeStart(node.range[0]);
var token = _this._tree.tokens[tokenPos];
if (token.type === 'Keyword') {
token.type = 'Identifier';
}
}
};
JsFile.prototype = {
/**
* Builds an index of disabled rules by starting line for error suppression.
*/
_buildDisabledRuleIndex: function() {
this._disabledRuleIndex = [];
var comments = this.getComments() || [];
var commentRe = /(jscs\s*:\s*(en|dis)able)(.*)/;
comments.forEach(function(comment) {
var enabled;
var parsed = commentRe.exec(comment.value.trim());
if (!parsed || parsed.index !== 0) {
return;
}
enabled = parsed[2] === 'en';
this._addToDisabledRuleIndex(enabled, parsed[3], comment.loc.start.line);
}, this);
},
/**
* Returns whether a specific rule is disabled on the given line.
*
* @param {String} ruleName the rule name being tested
* @param {Number} line the line number being tested
* @returns {Boolean} true if the rule is enabled
*/
isEnabledRule: function(ruleName, line) {
var enabled = true;
this._disabledRuleIndex.some(function(region) {
// once the comment we're inspecting occurs after the location of the error,
// no longer check for whether the state is enabled or disable
if (region.line > line) {
return true;
}
if (region.rule === ruleName || region.rule === '*') {
enabled = region.enabled;
}
}, this);
return enabled;
},
/**
* Adds rules to the disabled index given a string containing rules (or '' for all).
*
* @param {Boolean} enabled whether the rule is disabled or enabled on this line
* @param {String} rulesStr the string containing specific rules to en/disable
* @param {Number} line the line the comment appears on
*/
_addToDisabledRuleIndex: function(enabled, rulesStr, line) {
rulesStr = rulesStr || '*';
rulesStr.split(',').forEach(function(rule) {
rule = rule.trim();
if (!rule) {
return;
}
this._disabledRuleIndex.push({
rule: rule,
enabled: enabled,
line: line
});
}, this);
},
/**
* Builds token index by starting pos for futher navigation.
*/
_buildTokenIndex: function() {
var tokens = this._tree.tokens;
var tokenRangeStartIndex = {};
var tokenRangeEndIndex = {};
for (var i = 0, l = tokens.length; i < l; i++) {
tokenRangeStartIndex[tokens[i].range[0]] = i;
tokenRangeEndIndex[tokens[i].range[1]] = i;
tokens[i]._tokenIndex = i;
}
this._tokenRangeStartIndex = tokenRangeStartIndex;
this._tokenRangeEndIndex = tokenRangeEndIndex;
},
/**
* Returns token position using range start from the index.
*
* @returns {Object}
*/
getTokenPosByRangeStart: function(start) {
return this._tokenRangeStartIndex[start];
},
/**
* Returns token using range start from the index.
*
* @returns {Object|undefined}
*/
getTokenByRangeStart: function(start) {
var tokenIndex = this._tokenRangeStartIndex[start];
return tokenIndex === undefined ? undefined : this._tree.tokens[tokenIndex];
},
/**
* Returns token using range end from the index.
*
* @returns {Object|undefined}
*/
getTokenByRangeEnd: function(end) {
var tokenIndex = this._tokenRangeEndIndex[end];
return tokenIndex === undefined ? undefined : this._tree.tokens[tokenIndex];
},
/**
* Returns the first token for the node from the AST.
*
* @param {Object} node
* @returns {Object}
*/
getFirstNodeToken: function(node) {
return this.getTokenByRangeStart(node.range[0]);
},
/**
* Returns the last token for the node from the AST.
*
* @param {Object} node
* @returns {Object}
*/
getLastNodeToken: function(node) {
return this.getTokenByRangeEnd(node.range[1]);
},
/**
* Returns the first token before the given.
*
* @param {Object} token
* @returns {Object|undefined}
*/
getPrevToken: function(token) {
var index = token._tokenIndex - 1;
return index >= 0 ? this._tree.tokens[index] : undefined;
},
/**
* Returns the first token after the given.
*
* @param {Object} token
* @returns {Object|undefined}
*/
getNextToken: function(token) {
var index = token._tokenIndex + 1;
return index < this._tree.tokens.length ? this._tree.tokens[index] : undefined;
},
/**
* Returns the first token before the given which matches type (and value).
*
* @param {Object} token
* @param {String} type
* @param {String} [value]
* @returns {Object|undefined}
*/
findPrevToken: function(token, type, value) {
var prevToken = this.getPrevToken(token);
while (prevToken) {
if (prevToken.type === type && (value === undefined || prevToken.value === value)) {
return prevToken;
}
prevToken = this.getPrevToken(prevToken);
}
return prevToken;
},
/**
* Returns the first token after the given which matches type (and value).
*
* @param {Object} token
* @param {String} type
* @param {String} [value]
* @returns {Object|undefined}
*/
findNextToken: function(token, type, value) {
var nextToken = this.getNextToken(token);
while (nextToken) {
if (nextToken.type === type && (value === undefined || nextToken.value === value)) {
return nextToken;
}
nextToken = this.getNextToken(nextToken);
}
return nextToken;
},
/**
* Returns the first token before the given which matches type (and value).
*
* @param {Object} token
* @param {String} value
* @returns {Object|undefined}
*/
findPrevOperatorToken: function(token, value) {
return this.findPrevToken(token, value in KEYWORD_OPERATORS ? 'Keyword' : 'Punctuator', value);
},
/**
* Returns the first token after the given which matches type (and value).
*
* @param {Object} token
* @param {String} value
* @returns {Object|undefined}
*/
findNextOperatorToken: function(token, value) {
return this.findNextToken(token, value in KEYWORD_OPERATORS ? 'Keyword' : 'Punctuator', value);
},
/**
* Iterates through the token tree using tree iterator.
* Calls passed function for every token.
*
* @param {Function} cb
* @param {Object} [tree]
*/
iterate: function(cb, tree) {
return treeIterator.iterate(tree || this._tree, cb);
},
/**
* Returns node by its range position
*
* @returns {Object}
*/
getNodeByRange: function(number) {
var result = {};
this.iterate(function(node) {
if (number > node.range[0] && number < node.range[1]) {
result = node;
}
if (number < node.range[0]) {
return false;
}
});
return result;
},
/**
* Returns nodes by type(s) from earlier built index.
*
* @param {String|String[]} type
* @returns {Object[]}
*/
getNodesByType: function(type) {
if (typeof type === 'string') {
return this._index[type] || [];
} else {
var result = [];
for (var i = 0, l = type.length; i < l; i++) {
var nodes = this._index[type[i]];
if (nodes) {
result = result.concat(nodes);
}
}
return result;
}
},
/**
* Iterates nodes by type(s) from earlier built index.
* Calls passed function for every matched node.
*
* @param {String|String[]} type
* @param {Function} cb
*/
iterateNodesByType: function(type, cb) {
return this.getNodesByType(type).forEach(cb);
},
/**
* Iterates tokens by type(s) from the token array.
* Calls passed function for every matched token.
*
* @param {String|String[]} type
* @param {Function} cb
*/
iterateTokensByType: function(type, cb) {
var types = (typeof type === 'string') ? [type] : type;
var typeIndex = {};
types.forEach(function(type) {
typeIndex[type] = true;
});
this.getTokens().forEach(function(token, index, tokens) {
if (typeIndex[token.type]) {
cb(token, index, tokens);
}
});
},
/**
* Iterates token by value from the token array.
* Calls passed function for every matched token.
*
* @param {String|String[]} name
* @param {Function} cb
*/
iterateTokenByValue: function(name, cb) {
var names = (typeof name === 'string') ? [name] : name;
var nameIndex = {};
names.forEach(function(type) {
nameIndex[type] = true;
});
this.getTokens().forEach(function(token, index, tokens) {
if (nameIndex.hasOwnProperty(token.value)) {
cb(token, index, tokens);
}
});
},
/**
* Returns string representing contents of the file.
*
* @returns {String}
*/
getSource: function() {
return this._source;
},
/**
* Returns token tree, built using esprima.
*
* @returns {Object}
*/
getTree: function() {
return this._tree;
},
/**
* Returns token list, built using esprima.
*
* @returns {Object[]}
*/
getTokens: function() {
return this._tree.tokens;
},
/**
* Returns comment token list, built using esprima.
*/
getComments: function() {
return this._tree.comments;
},
/**
* Returns source filename for this object representation.
*
* @returns {String}
*/
getFilename: function() {
return this._filename;
},
/**
* Returns array of source lines for the file.
*
* @returns {String[]}
*/
getLines: function() {
return this._lines;
},
splice: function(startIndex, removeCharCount, charsToAdd) {
this._changes.push({startIndex: startIndex, removeCharCount: removeCharCount, charsToAdd: charsToAdd});
},
applyChanges: function() {
var result = '';
var startIndex = 0;
var source = this._source;
this._changes.sort(function(a, b) {
return a.startIndex - b.startIndex;
});
this._changes.forEach(function(change) {
result = result + source.substring(startIndex, change.startIndex) + change.charsToAdd;
startIndex = change.startIndex + change.removeCharCount;
});
if (startIndex < source.length) {
result = result + source.substring(startIndex, source.length);
}
return result;
},
getPosByLineAndColumn: function(line, column) {
var pos = 0;
var source = this._source;
for (var i = 0;i < line - 1;i++) {
pos += this._lines[i].length + 1;
if (source[pos - 1] === '\r' && source[pos] === '\n') {
pos += 1;
}
}
return pos + column;
}
};
module.exports = JsFile;
},{"./tree-iterator":109}],5:[function(require,module,exports){
var assert = require('assert');
module.exports = function() {};
module.exports.prototype = {
configure: function(disallowAnonymousFunctions) {
assert(
disallowAnonymousFunctions === true,
'disallowAnonymousFunctions option requires true value or should be removed'
);
},
getOptionName: function() {
return 'disallowAnonymousFunctions';
},
check: function(file, errors) {
file.iterateNodesByType(['FunctionExpression', 'FunctionDeclaration'], function(node) {
if (node.id === null) {
errors.add('Anonymous functions needs to be named', node.loc.start);
}
});
}
};
},{"assert":143}],6:[function(require,module,exports){
var assert = require('assert');
var Lu = require('unicode-6.3.0/categories/Lu/regex');
var Ll = require('unicode-6.3.0/categories/Ll/regex');
var Lt = require('unicode-6.3.0/categories/Lt/regex');
var Lm = require('unicode-6.3.0/categories/Lm/regex');
var Lo = require('unicode-6.3.0/categories/Lo/regex');
function letterPattern(char) {
return Lu.test(char) || Ll.test(char) || Lt.test(char) || Lm.test(char) || Lo.test(char);
}
function lowerCasePattern(char) {
return Ll.test(char);
}
module.exports = function() {};
module.exports.prototype = {
configure: function(disallowCapitalizedComments) {
assert(
disallowCapitalizedComments === true,
'disallowCapitalizedComments option requ