1349 lines
156 KiB
JavaScript
1349 lines
156 KiB
JavaScript
|
|
'use strict';var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {return typeof obj;} : function (obj) {return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;};var _slicedToArray = function () {function sliceIterator(arr, i) {var _arr = [];var _n = true;var _d = false;var _e = undefined;try {for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {_arr.push(_s.value);if (i && _arr.length === i) break;}} catch (err) {_d = true;_e = err;} finally {try {if (!_n && _i["return"]) _i["return"]();} finally {if (_d) throw _e;}}return _arr;}return function (arr, i) {if (Array.isArray(arr)) {return arr;} else if (Symbol.iterator in Object(arr)) {return sliceIterator(arr, i);} else {throw new TypeError("Invalid attempt to destructure non-iterable instance");}};}();
|
||
|
|
|
||
|
|
var _minimatch = require('minimatch');var _minimatch2 = _interopRequireDefault(_minimatch);
|
||
|
|
var _arrayIncludes = require('array-includes');var _arrayIncludes2 = _interopRequireDefault(_arrayIncludes);
|
||
|
|
var _object = require('object.groupby');var _object2 = _interopRequireDefault(_object);
|
||
|
|
var _contextCompat = require('eslint-module-utils/contextCompat');
|
||
|
|
var _stringPrototype = require('string.prototype.trimend');var _stringPrototype2 = _interopRequireDefault(_stringPrototype);
|
||
|
|
|
||
|
|
var _importType = require('../core/importType');var _importType2 = _interopRequireDefault(_importType);
|
||
|
|
var _staticRequire = require('../core/staticRequire');var _staticRequire2 = _interopRequireDefault(_staticRequire);
|
||
|
|
var _docsUrl = require('../docsUrl');var _docsUrl2 = _interopRequireDefault(_docsUrl);function _interopRequireDefault(obj) {return obj && obj.__esModule ? obj : { 'default': obj };}
|
||
|
|
|
||
|
|
var categories = {
|
||
|
|
named: 'named',
|
||
|
|
'import': 'import',
|
||
|
|
exports: 'exports' };
|
||
|
|
|
||
|
|
|
||
|
|
var defaultGroups = ['builtin', 'external', 'parent', 'sibling', 'index'];
|
||
|
|
|
||
|
|
// REPORTING AND FIXING
|
||
|
|
|
||
|
|
function reverse(array) {
|
||
|
|
return array.map(function (v) {return Object.assign({}, v, { rank: -v.rank });}).reverse();
|
||
|
|
}
|
||
|
|
|
||
|
|
function getTokensOrCommentsAfter(sourceCode, node, count) {
|
||
|
|
var currentNodeOrToken = node;
|
||
|
|
var result = [];
|
||
|
|
for (var i = 0; i < count; i++) {
|
||
|
|
currentNodeOrToken = sourceCode.getTokenOrCommentAfter(currentNodeOrToken);
|
||
|
|
if (currentNodeOrToken == null) {
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
result.push(currentNodeOrToken);
|
||
|
|
}
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
function getTokensOrCommentsBefore(sourceCode, node, count) {
|
||
|
|
var currentNodeOrToken = node;
|
||
|
|
var result = [];
|
||
|
|
for (var i = 0; i < count; i++) {
|
||
|
|
currentNodeOrToken = sourceCode.getTokenOrCommentBefore(currentNodeOrToken);
|
||
|
|
if (currentNodeOrToken == null) {
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
result.push(currentNodeOrToken);
|
||
|
|
}
|
||
|
|
return result.reverse();
|
||
|
|
}
|
||
|
|
|
||
|
|
function takeTokensAfterWhile(sourceCode, node, condition) {
|
||
|
|
var tokens = getTokensOrCommentsAfter(sourceCode, node, 100);
|
||
|
|
var result = [];
|
||
|
|
for (var i = 0; i < tokens.length; i++) {
|
||
|
|
if (condition(tokens[i])) {
|
||
|
|
result.push(tokens[i]);
|
||
|
|
} else {
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
function takeTokensBeforeWhile(sourceCode, node, condition) {
|
||
|
|
var tokens = getTokensOrCommentsBefore(sourceCode, node, 100);
|
||
|
|
var result = [];
|
||
|
|
for (var i = tokens.length - 1; i >= 0; i--) {
|
||
|
|
if (condition(tokens[i])) {
|
||
|
|
result.push(tokens[i]);
|
||
|
|
} else {
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return result.reverse();
|
||
|
|
}
|
||
|
|
|
||
|
|
function findOutOfOrder(imported) {
|
||
|
|
if (imported.length === 0) {
|
||
|
|
return [];
|
||
|
|
}
|
||
|
|
var maxSeenRankNode = imported[0];
|
||
|
|
return imported.filter(function (importedModule) {
|
||
|
|
var res = importedModule.rank < maxSeenRankNode.rank;
|
||
|
|
if (maxSeenRankNode.rank < importedModule.rank) {
|
||
|
|
maxSeenRankNode = importedModule;
|
||
|
|
}
|
||
|
|
return res;
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
function findRootNode(node) {
|
||
|
|
var parent = node;
|
||
|
|
while (parent.parent != null && parent.parent.body == null) {
|
||
|
|
parent = parent.parent;
|
||
|
|
}
|
||
|
|
return parent;
|
||
|
|
}
|
||
|
|
|
||
|
|
function commentOnSameLineAs(node) {
|
||
|
|
return function (token) {return (token.type === 'Block' || token.type === 'Line') &&
|
||
|
|
token.loc.start.line === token.loc.end.line &&
|
||
|
|
token.loc.end.line === node.loc.end.line;};
|
||
|
|
}
|
||
|
|
|
||
|
|
function findEndOfLineWithComments(sourceCode, node) {
|
||
|
|
var tokensToEndOfLine = takeTokensAfterWhile(sourceCode, node, commentOnSameLineAs(node));
|
||
|
|
var endOfTokens = tokensToEndOfLine.length > 0 ?
|
||
|
|
tokensToEndOfLine[tokensToEndOfLine.length - 1].range[1] :
|
||
|
|
node.range[1];
|
||
|
|
var result = endOfTokens;
|
||
|
|
for (var i = endOfTokens; i < sourceCode.text.length; i++) {
|
||
|
|
if (sourceCode.text[i] === '\n') {
|
||
|
|
result = i + 1;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
if (sourceCode.text[i] !== ' ' && sourceCode.text[i] !== '\t' && sourceCode.text[i] !== '\r') {
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
result = i + 1;
|
||
|
|
}
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
function findStartOfLineWithComments(sourceCode, node) {
|
||
|
|
var tokensToEndOfLine = takeTokensBeforeWhile(sourceCode, node, commentOnSameLineAs(node));
|
||
|
|
var startOfTokens = tokensToEndOfLine.length > 0 ? tokensToEndOfLine[0].range[0] : node.range[0];
|
||
|
|
var result = startOfTokens;
|
||
|
|
for (var i = startOfTokens - 1; i > 0; i--) {
|
||
|
|
if (sourceCode.text[i] !== ' ' && sourceCode.text[i] !== '\t') {
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
result = i;
|
||
|
|
}
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
function findSpecifierStart(sourceCode, node) {
|
||
|
|
var token = void 0;
|
||
|
|
|
||
|
|
do {
|
||
|
|
token = sourceCode.getTokenBefore(node);
|
||
|
|
} while (token.value !== ',' && token.value !== '{');
|
||
|
|
|
||
|
|
return token.range[1];
|
||
|
|
}
|
||
|
|
|
||
|
|
function findSpecifierEnd(sourceCode, node) {
|
||
|
|
var token = void 0;
|
||
|
|
|
||
|
|
do {
|
||
|
|
token = sourceCode.getTokenAfter(node);
|
||
|
|
} while (token.value !== ',' && token.value !== '}');
|
||
|
|
|
||
|
|
return token.range[0];
|
||
|
|
}
|
||
|
|
|
||
|
|
function isRequireExpression(expr) {
|
||
|
|
return expr != null &&
|
||
|
|
expr.type === 'CallExpression' &&
|
||
|
|
expr.callee != null &&
|
||
|
|
expr.callee.name === 'require' &&
|
||
|
|
expr.arguments != null &&
|
||
|
|
expr.arguments.length === 1 &&
|
||
|
|
expr.arguments[0].type === 'Literal';
|
||
|
|
}
|
||
|
|
|
||
|
|
function isSupportedRequireModule(node) {
|
||
|
|
if (node.type !== 'VariableDeclaration') {
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
if (node.declarations.length !== 1) {
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
var decl = node.declarations[0];
|
||
|
|
var isPlainRequire = decl.id && (
|
||
|
|
decl.id.type === 'Identifier' || decl.id.type === 'ObjectPattern') &&
|
||
|
|
isRequireExpression(decl.init);
|
||
|
|
var isRequireWithMemberExpression = decl.id && (
|
||
|
|
decl.id.type === 'Identifier' || decl.id.type === 'ObjectPattern') &&
|
||
|
|
decl.init != null &&
|
||
|
|
decl.init.type === 'CallExpression' &&
|
||
|
|
decl.init.callee != null &&
|
||
|
|
decl.init.callee.type === 'MemberExpression' &&
|
||
|
|
isRequireExpression(decl.init.callee.object);
|
||
|
|
return isPlainRequire || isRequireWithMemberExpression;
|
||
|
|
}
|
||
|
|
|
||
|
|
function isPlainImportModule(node) {
|
||
|
|
return node.type === 'ImportDeclaration' && node.specifiers != null && node.specifiers.length > 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
function isPlainImportEquals(node) {
|
||
|
|
return node.type === 'TSImportEqualsDeclaration' && node.moduleReference.expression;
|
||
|
|
}
|
||
|
|
|
||
|
|
function isCJSExports(context, node) {
|
||
|
|
if (
|
||
|
|
node.type === 'MemberExpression' &&
|
||
|
|
node.object.type === 'Identifier' &&
|
||
|
|
node.property.type === 'Identifier' &&
|
||
|
|
node.object.name === 'module' &&
|
||
|
|
node.property.name === 'exports')
|
||
|
|
{
|
||
|
|
return (0, _contextCompat.getScope)(context, node).variables.findIndex(function (variable) {return variable.name === 'module';}) === -1;
|
||
|
|
}
|
||
|
|
if (
|
||
|
|
node.type === 'Identifier' &&
|
||
|
|
node.name === 'exports')
|
||
|
|
{
|
||
|
|
return (0, _contextCompat.getScope)(context, node).variables.findIndex(function (variable) {return variable.name === 'exports';}) === -1;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
function getNamedCJSExports(context, node) {
|
||
|
|
if (node.type !== 'MemberExpression') {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
var result = [];
|
||
|
|
var root = node;
|
||
|
|
var parent = null;
|
||
|
|
while (root.type === 'MemberExpression') {
|
||
|
|
if (root.property.type !== 'Identifier') {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
result.unshift(root.property.name);
|
||
|
|
parent = root;
|
||
|
|
root = root.object;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (isCJSExports(context, root)) {
|
||
|
|
return result;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (isCJSExports(context, parent)) {
|
||
|
|
return result.slice(1);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
function canCrossNodeWhileReorder(node) {
|
||
|
|
return isSupportedRequireModule(node) || isPlainImportModule(node) || isPlainImportEquals(node);
|
||
|
|
}
|
||
|
|
|
||
|
|
function canReorderItems(firstNode, secondNode) {
|
||
|
|
var parent = firstNode.parent;var _sort =
|
||
|
|
[
|
||
|
|
parent.body.indexOf(firstNode),
|
||
|
|
parent.body.indexOf(secondNode)].
|
||
|
|
sort(),_sort2 = _slicedToArray(_sort, 2),firstIndex = _sort2[0],secondIndex = _sort2[1];
|
||
|
|
var nodesBetween = parent.body.slice(firstIndex, secondIndex + 1);var _iteratorNormalCompletion = true;var _didIteratorError = false;var _iteratorError = undefined;try {
|
||
|
|
for (var _iterator = nodesBetween[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {var nodeBetween = _step.value;
|
||
|
|
if (!canCrossNodeWhileReorder(nodeBetween)) {
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}} catch (err) {_didIteratorError = true;_iteratorError = err;} finally {try {if (!_iteratorNormalCompletion && _iterator['return']) {_iterator['return']();}} finally {if (_didIteratorError) {throw _iteratorError;}}}
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
function makeImportDescription(node) {
|
||
|
|
if (node.type === 'export') {
|
||
|
|
if (node.node.exportKind === 'type') {
|
||
|
|
return 'type export';
|
||
|
|
}
|
||
|
|
return 'export';
|
||
|
|
}
|
||
|
|
if (node.node.importKind === 'type') {
|
||
|
|
return 'type import';
|
||
|
|
}
|
||
|
|
if (node.node.importKind === 'typeof') {
|
||
|
|
return 'typeof import';
|
||
|
|
}
|
||
|
|
return 'import';
|
||
|
|
}
|
||
|
|
|
||
|
|
function fixOutOfOrder(context, firstNode, secondNode, order, category) {
|
||
|
|
var isNamed = category === categories.named;
|
||
|
|
var isExports = category === categories.exports;
|
||
|
|
var sourceCode = (0, _contextCompat.getSourceCode)(context);var _ref =
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
isNamed ? {
|
||
|
|
firstRoot: firstNode.node,
|
||
|
|
secondRoot: secondNode.node } :
|
||
|
|
{
|
||
|
|
firstRoot: findRootNode(firstNode.node),
|
||
|
|
secondRoot: findRootNode(secondNode.node) },firstRoot = _ref.firstRoot,secondRoot = _ref.secondRoot;var _ref2 =
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
isNamed ? {
|
||
|
|
firstRootStart: findSpecifierStart(sourceCode, firstRoot),
|
||
|
|
firstRootEnd: findSpecifierEnd(sourceCode, firstRoot),
|
||
|
|
secondRootStart: findSpecifierStart(sourceCode, secondRoot),
|
||
|
|
secondRootEnd: findSpecifierEnd(sourceCode, secondRoot) } :
|
||
|
|
{
|
||
|
|
firstRootStart: findStartOfLineWithComments(sourceCode, firstRoot),
|
||
|
|
firstRootEnd: findEndOfLineWithComments(sourceCode, firstRoot),
|
||
|
|
secondRootStart: findStartOfLineWithComments(sourceCode, secondRoot),
|
||
|
|
secondRootEnd: findEndOfLineWithComments(sourceCode, secondRoot) },firstRootStart = _ref2.firstRootStart,firstRootEnd = _ref2.firstRootEnd,secondRootStart = _ref2.secondRootStart,secondRootEnd = _ref2.secondRootEnd;
|
||
|
|
|
||
|
|
|
||
|
|
if (firstNode.displayName === secondNode.displayName) {
|
||
|
|
if (firstNode.alias) {
|
||
|
|
firstNode.displayName = String(firstNode.displayName) + ' as ' + String(firstNode.alias);
|
||
|
|
}
|
||
|
|
if (secondNode.alias) {
|
||
|
|
secondNode.displayName = String(secondNode.displayName) + ' as ' + String(secondNode.alias);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
var firstImport = String(makeImportDescription(firstNode)) + ' of `' + String(firstNode.displayName) + '`';
|
||
|
|
var secondImport = '`' + String(secondNode.displayName) + '` ' + String(makeImportDescription(secondNode));
|
||
|
|
var message = secondImport + ' should occur ' + String(order) + ' ' + firstImport;
|
||
|
|
|
||
|
|
if (isNamed) {
|
||
|
|
var firstCode = sourceCode.text.slice(firstRootStart, firstRoot.range[1]);
|
||
|
|
var firstTrivia = sourceCode.text.slice(firstRoot.range[1], firstRootEnd);
|
||
|
|
var secondCode = sourceCode.text.slice(secondRootStart, secondRoot.range[1]);
|
||
|
|
var secondTrivia = sourceCode.text.slice(secondRoot.range[1], secondRootEnd);
|
||
|
|
|
||
|
|
if (order === 'before') {
|
||
|
|
var trimmedTrivia = (0, _stringPrototype2['default'])(secondTrivia);
|
||
|
|
var gapCode = sourceCode.text.slice(firstRootEnd, secondRootStart - 1);
|
||
|
|
var whitespaces = secondTrivia.slice(trimmedTrivia.length);
|
||
|
|
context.report({
|
||
|
|
node: secondNode.node,
|
||
|
|
message: message,
|
||
|
|
fix: function () {function fix(fixer) {return fixer.replaceTextRange(
|
||
|
|
[firstRootStart, secondRootEnd], String(
|
||
|
|
secondCode) + ',' + String(trimmedTrivia) + String(firstCode) + String(firstTrivia) + String(gapCode) + String(whitespaces));}return fix;}() });
|
||
|
|
|
||
|
|
|
||
|
|
} else if (order === 'after') {
|
||
|
|
var _trimmedTrivia = (0, _stringPrototype2['default'])(firstTrivia);
|
||
|
|
var _gapCode = sourceCode.text.slice(secondRootEnd + 1, firstRootStart);
|
||
|
|
var _whitespaces = firstTrivia.slice(_trimmedTrivia.length);
|
||
|
|
context.report({
|
||
|
|
node: secondNode.node,
|
||
|
|
message: message,
|
||
|
|
fix: function () {function fix(fixes) {return fixes.replaceTextRange(
|
||
|
|
[secondRootStart, firstRootEnd], '' + String(
|
||
|
|
_gapCode) + String(firstCode) + ',' + String(_trimmedTrivia) + String(secondCode) + String(_whitespaces));}return fix;}() });
|
||
|
|
|
||
|
|
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
var canFix = isExports || canReorderItems(firstRoot, secondRoot);
|
||
|
|
var newCode = sourceCode.text.substring(secondRootStart, secondRootEnd);
|
||
|
|
|
||
|
|
if (newCode[newCode.length - 1] !== '\n') {
|
||
|
|
newCode = String(newCode) + '\n';
|
||
|
|
}
|
||
|
|
|
||
|
|
if (order === 'before') {
|
||
|
|
context.report({
|
||
|
|
node: secondNode.node,
|
||
|
|
message: message,
|
||
|
|
fix: canFix && function (fixer) {return fixer.replaceTextRange(
|
||
|
|
[firstRootStart, secondRootEnd],
|
||
|
|
newCode + sourceCode.text.substring(firstRootStart, secondRootStart));} });
|
||
|
|
|
||
|
|
|
||
|
|
} else if (order === 'after') {
|
||
|
|
context.report({
|
||
|
|
node: secondNode.node,
|
||
|
|
message: message,
|
||
|
|
fix: canFix && function (fixer) {return fixer.replaceTextRange(
|
||
|
|
[secondRootStart, firstRootEnd],
|
||
|
|
sourceCode.text.substring(secondRootEnd, firstRootEnd) + newCode);} });
|
||
|
|
|
||
|
|
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
function reportOutOfOrder(context, imported, outOfOrder, order, category) {
|
||
|
|
outOfOrder.forEach(function (imp) {
|
||
|
|
var found = imported.find(function () {function hasHigherRank(importedItem) {
|
||
|
|
return importedItem.rank > imp.rank;
|
||
|
|
}return hasHigherRank;}());
|
||
|
|
fixOutOfOrder(context, found, imp, order, category);
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
function makeOutOfOrderReport(context, imported, category) {
|
||
|
|
var outOfOrder = findOutOfOrder(imported);
|
||
|
|
if (!outOfOrder.length) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
// There are things to report. Try to minimize the number of reported errors.
|
||
|
|
var reversedImported = reverse(imported);
|
||
|
|
var reversedOrder = findOutOfOrder(reversedImported);
|
||
|
|
if (reversedOrder.length < outOfOrder.length) {
|
||
|
|
reportOutOfOrder(context, reversedImported, reversedOrder, 'after', category);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
reportOutOfOrder(context, imported, outOfOrder, 'before', category);
|
||
|
|
}
|
||
|
|
|
||
|
|
var compareString = function compareString(a, b) {
|
||
|
|
if (a < b) {
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
if (a > b) {
|
||
|
|
return 1;
|
||
|
|
}
|
||
|
|
return 0;
|
||
|
|
};
|
||
|
|
|
||
|
|
/** Some parsers (languages without types) don't provide ImportKind */
|
||
|
|
var DEFAULT_IMPORT_KIND = 'value';
|
||
|
|
var getNormalizedValue = function getNormalizedValue(node, toLowerCase) {
|
||
|
|
var value = node.value;
|
||
|
|
return toLowerCase ? String(value).toLowerCase() : value;
|
||
|
|
};
|
||
|
|
|
||
|
|
function getSorter(alphabetizeOptions) {
|
||
|
|
var multiplier = alphabetizeOptions.order === 'asc' ? 1 : -1;
|
||
|
|
var orderImportKind = alphabetizeOptions.orderImportKind;
|
||
|
|
var multiplierImportKind = orderImportKind !== 'ignore' && (
|
||
|
|
alphabetizeOptions.orderImportKind === 'asc' ? 1 : -1);
|
||
|
|
|
||
|
|
return function () {function importsSorter(nodeA, nodeB) {
|
||
|
|
var importA = getNormalizedValue(nodeA, alphabetizeOptions.caseInsensitive);
|
||
|
|
var importB = getNormalizedValue(nodeB, alphabetizeOptions.caseInsensitive);
|
||
|
|
var result = 0;
|
||
|
|
|
||
|
|
if (!(0, _arrayIncludes2['default'])(importA, '/') && !(0, _arrayIncludes2['default'])(importB, '/')) {
|
||
|
|
result = compareString(importA, importB);
|
||
|
|
} else {
|
||
|
|
var A = importA.split('/');
|
||
|
|
var B = importB.split('/');
|
||
|
|
var a = A.length;
|
||
|
|
var b = B.length;
|
||
|
|
|
||
|
|
for (var i = 0; i < Math.min(a, b); i++) {
|
||
|
|
// Skip comparing the first path segment, if they are relative segments for both imports
|
||
|
|
if (i === 0 && (A[i] === '.' || A[i] === '..') && (B[i] === '.' || B[i] === '..')) {
|
||
|
|
// If one is sibling and the other parent import, no need to compare at all, since the paths belong in different groups
|
||
|
|
if (A[i] !== B[i]) {break;}
|
||
|
|
continue;
|
||
|
|
}
|
||
|
|
result = compareString(A[i], B[i]);
|
||
|
|
if (result) {break;}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!result && a !== b) {
|
||
|
|
result = a < b ? -1 : 1;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
result = result * multiplier;
|
||
|
|
|
||
|
|
// In case the paths are equal (result === 0), sort them by importKind
|
||
|
|
if (!result && multiplierImportKind) {
|
||
|
|
result = multiplierImportKind * compareString(
|
||
|
|
nodeA.node.importKind || DEFAULT_IMPORT_KIND,
|
||
|
|
nodeB.node.importKind || DEFAULT_IMPORT_KIND);
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
return result;
|
||
|
|
}return importsSorter;}();
|
||
|
|
}
|
||
|
|
|
||
|
|
function mutateRanksToAlphabetize(imported, alphabetizeOptions) {
|
||
|
|
var groupedByRanks = (0, _object2['default'])(imported, function (item) {return item.rank;});
|
||
|
|
|
||
|
|
var sorterFn = getSorter(alphabetizeOptions);
|
||
|
|
|
||
|
|
// sort group keys so that they can be iterated on in order
|
||
|
|
var groupRanks = Object.keys(groupedByRanks).sort(function (a, b) {
|
||
|
|
return a - b;
|
||
|
|
});
|
||
|
|
|
||
|
|
// sort imports locally within their group
|
||
|
|
groupRanks.forEach(function (groupRank) {
|
||
|
|
groupedByRanks[groupRank].sort(sorterFn);
|
||
|
|
});
|
||
|
|
|
||
|
|
// assign globally unique rank to each import
|
||
|
|
var newRank = 0;
|
||
|
|
var alphabetizedRanks = groupRanks.reduce(function (acc, groupRank) {
|
||
|
|
groupedByRanks[groupRank].forEach(function (importedItem) {
|
||
|
|
acc[String(importedItem.value) + '|' + String(importedItem.node.importKind)] = parseInt(groupRank, 10) + newRank;
|
||
|
|
newRank += 1;
|
||
|
|
});
|
||
|
|
return acc;
|
||
|
|
}, {});
|
||
|
|
|
||
|
|
// mutate the original group-rank with alphabetized-rank
|
||
|
|
imported.forEach(function (importedItem) {
|
||
|
|
importedItem.rank = alphabetizedRanks[String(importedItem.value) + '|' + String(importedItem.node.importKind)];
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
// DETECTING
|
||
|
|
|
||
|
|
function computePathRank(ranks, pathGroups, path, maxPosition) {
|
||
|
|
for (var i = 0, l = pathGroups.length; i < l; i++) {var _pathGroups$i =
|
||
|
|
pathGroups[i],pattern = _pathGroups$i.pattern,patternOptions = _pathGroups$i.patternOptions,group = _pathGroups$i.group,_pathGroups$i$positio = _pathGroups$i.position,position = _pathGroups$i$positio === undefined ? 1 : _pathGroups$i$positio;
|
||
|
|
if ((0, _minimatch2['default'])(path, pattern, patternOptions || { nocomment: true })) {
|
||
|
|
return ranks[group] + position / maxPosition;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
function computeRank(context, ranks, importEntry, excludedImportTypes, isSortingTypesGroup) {
|
||
|
|
var impType = void 0;
|
||
|
|
var rank = void 0;
|
||
|
|
|
||
|
|
var isTypeGroupInGroups = ranks.omittedTypes.indexOf('type') === -1;
|
||
|
|
var isTypeOnlyImport = importEntry.node.importKind === 'type';
|
||
|
|
var isExcludedFromPathRank = isTypeOnlyImport && isTypeGroupInGroups && excludedImportTypes.has('type');
|
||
|
|
|
||
|
|
if (importEntry.type === 'import:object') {
|
||
|
|
impType = 'object';
|
||
|
|
} else if (isTypeOnlyImport && isTypeGroupInGroups && !isSortingTypesGroup) {
|
||
|
|
impType = 'type';
|
||
|
|
} else {
|
||
|
|
impType = (0, _importType2['default'])(importEntry.value, context);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!excludedImportTypes.has(impType) && !isExcludedFromPathRank) {
|
||
|
|
rank = computePathRank(ranks.groups, ranks.pathGroups, importEntry.value, ranks.maxPosition);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (typeof rank === 'undefined') {
|
||
|
|
rank = ranks.groups[impType];
|
||
|
|
|
||
|
|
if (typeof rank === 'undefined') {
|
||
|
|
return -1;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (isTypeOnlyImport && isSortingTypesGroup) {
|
||
|
|
rank = ranks.groups.type + rank / 10;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (importEntry.type !== 'import' && !importEntry.type.startsWith('import:')) {
|
||
|
|
rank += 100;
|
||
|
|
}
|
||
|
|
|
||
|
|
return rank;
|
||
|
|
}
|
||
|
|
|
||
|
|
function registerNode(context, importEntry, ranks, imported, excludedImportTypes, isSortingTypesGroup) {
|
||
|
|
var rank = computeRank(context, ranks, importEntry, excludedImportTypes, isSortingTypesGroup);
|
||
|
|
if (rank !== -1) {
|
||
|
|
var importNode = importEntry.node;
|
||
|
|
|
||
|
|
if (importEntry.type === 'require' && importNode.parent.parent.type === 'VariableDeclaration') {
|
||
|
|
importNode = importNode.parent.parent;
|
||
|
|
}
|
||
|
|
|
||
|
|
imported.push(Object.assign({},
|
||
|
|
importEntry, {
|
||
|
|
rank: rank,
|
||
|
|
isMultiline: importNode.loc.end.line !== importNode.loc.start.line }));
|
||
|
|
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
function getRequireBlock(node) {
|
||
|
|
var n = node;
|
||
|
|
// Handle cases like `const baz = require('foo').bar.baz`
|
||
|
|
// and `const foo = require('foo')()`
|
||
|
|
while (
|
||
|
|
n.parent.type === 'MemberExpression' && n.parent.object === n ||
|
||
|
|
n.parent.type === 'CallExpression' && n.parent.callee === n)
|
||
|
|
{
|
||
|
|
n = n.parent;
|
||
|
|
}
|
||
|
|
if (
|
||
|
|
n.parent.type === 'VariableDeclarator' &&
|
||
|
|
n.parent.parent.type === 'VariableDeclaration' &&
|
||
|
|
n.parent.parent.parent.type === 'Program')
|
||
|
|
{
|
||
|
|
return n.parent.parent.parent;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
var types = ['builtin', 'external', 'internal', 'unknown', 'parent', 'sibling', 'index', 'object', 'type'];
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Creates an object with type-rank pairs.
|
||
|
|
*
|
||
|
|
* Example: { index: 0, sibling: 1, parent: 1, external: 1, builtin: 2, internal: 2 }
|
||
|
|
*/
|
||
|
|
function convertGroupsToRanks(groups) {
|
||
|
|
var rankObject = groups.reduce(function (res, group, index) {
|
||
|
|
[].concat(group).forEach(function (groupItem) {
|
||
|
|
res[groupItem] = index * 2;
|
||
|
|
});
|
||
|
|
return res;
|
||
|
|
}, {});
|
||
|
|
|
||
|
|
var omittedTypes = types.filter(function (type) {
|
||
|
|
return typeof rankObject[type] === 'undefined';
|
||
|
|
});
|
||
|
|
|
||
|
|
var ranks = omittedTypes.reduce(function (res, type) {
|
||
|
|
res[type] = groups.length * 2;
|
||
|
|
return res;
|
||
|
|
}, rankObject);
|
||
|
|
|
||
|
|
return { groups: ranks, omittedTypes: omittedTypes };
|
||
|
|
}
|
||
|
|
|
||
|
|
function convertPathGroupsForRanks(pathGroups) {
|
||
|
|
var after = {};
|
||
|
|
var before = {};
|
||
|
|
|
||
|
|
var transformed = pathGroups.map(function (pathGroup, index) {var
|
||
|
|
group = pathGroup.group,positionString = pathGroup.position;
|
||
|
|
var position = 0;
|
||
|
|
if (positionString === 'after') {
|
||
|
|
if (!after[group]) {
|
||
|
|
after[group] = 1;
|
||
|
|
}
|
||
|
|
position = after[group]++;
|
||
|
|
} else if (positionString === 'before') {
|
||
|
|
if (!before[group]) {
|
||
|
|
before[group] = [];
|
||
|
|
}
|
||
|
|
before[group].push(index);
|
||
|
|
}
|
||
|
|
|
||
|
|
return Object.assign({}, pathGroup, { position: position });
|
||
|
|
});
|
||
|
|
|
||
|
|
var maxPosition = 1;
|
||
|
|
|
||
|
|
Object.keys(before).forEach(function (group) {
|
||
|
|
var groupLength = before[group].length;
|
||
|
|
before[group].forEach(function (groupIndex, index) {
|
||
|
|
transformed[groupIndex].position = -1 * (groupLength - index);
|
||
|
|
});
|
||
|
|
maxPosition = Math.max(maxPosition, groupLength);
|
||
|
|
});
|
||
|
|
|
||
|
|
Object.keys(after).forEach(function (key) {
|
||
|
|
var groupNextPosition = after[key];
|
||
|
|
maxPosition = Math.max(maxPosition, groupNextPosition - 1);
|
||
|
|
});
|
||
|
|
|
||
|
|
return {
|
||
|
|
pathGroups: transformed,
|
||
|
|
maxPosition: maxPosition > 10 ? Math.pow(10, Math.ceil(Math.log10(maxPosition))) : 10 };
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
function fixNewLineAfterImport(context, previousImport) {
|
||
|
|
var prevRoot = findRootNode(previousImport.node);
|
||
|
|
var tokensToEndOfLine = takeTokensAfterWhile(
|
||
|
|
(0, _contextCompat.getSourceCode)(context),
|
||
|
|
prevRoot,
|
||
|
|
commentOnSameLineAs(prevRoot));
|
||
|
|
|
||
|
|
|
||
|
|
var endOfLine = prevRoot.range[1];
|
||
|
|
if (tokensToEndOfLine.length > 0) {
|
||
|
|
endOfLine = tokensToEndOfLine[tokensToEndOfLine.length - 1].range[1];
|
||
|
|
}
|
||
|
|
return function (fixer) {return fixer.insertTextAfterRange([prevRoot.range[0], endOfLine], '\n');};
|
||
|
|
}
|
||
|
|
|
||
|
|
function removeNewLineAfterImport(context, currentImport, previousImport) {
|
||
|
|
var sourceCode = (0, _contextCompat.getSourceCode)(context);
|
||
|
|
var prevRoot = findRootNode(previousImport.node);
|
||
|
|
var currRoot = findRootNode(currentImport.node);
|
||
|
|
var rangeToRemove = [
|
||
|
|
findEndOfLineWithComments(sourceCode, prevRoot),
|
||
|
|
findStartOfLineWithComments(sourceCode, currRoot)];
|
||
|
|
|
||
|
|
if (/^\s*$/.test(sourceCode.text.substring(rangeToRemove[0], rangeToRemove[1]))) {
|
||
|
|
return function (fixer) {return fixer.removeRange(rangeToRemove);};
|
||
|
|
}
|
||
|
|
return undefined;
|
||
|
|
}
|
||
|
|
|
||
|
|
function makeNewlinesBetweenReport(context, imported, newlinesBetweenImports_, newlinesBetweenTypeOnlyImports_, distinctGroup, isSortingTypesGroup, isConsolidatingSpaceBetweenImports) {
|
||
|
|
var getNumberOfEmptyLinesBetween = function getNumberOfEmptyLinesBetween(currentImport, previousImport) {
|
||
|
|
var linesBetweenImports = (0, _contextCompat.getSourceCode)(context).lines.slice(
|
||
|
|
previousImport.node.loc.end.line,
|
||
|
|
currentImport.node.loc.start.line - 1);
|
||
|
|
|
||
|
|
|
||
|
|
return linesBetweenImports.filter(function (line) {return !line.trim().length;}).length;
|
||
|
|
};
|
||
|
|
var getIsStartOfDistinctGroup = function getIsStartOfDistinctGroup(currentImport, previousImport) {return currentImport.rank - 1 >= previousImport.rank;};
|
||
|
|
var previousImport = imported[0];
|
||
|
|
|
||
|
|
imported.slice(1).forEach(function (currentImport) {
|
||
|
|
var emptyLinesBetween = getNumberOfEmptyLinesBetween(
|
||
|
|
currentImport,
|
||
|
|
previousImport);
|
||
|
|
|
||
|
|
|
||
|
|
var isStartOfDistinctGroup = getIsStartOfDistinctGroup(
|
||
|
|
currentImport,
|
||
|
|
previousImport);
|
||
|
|
|
||
|
|
|
||
|
|
var isTypeOnlyImport = currentImport.node.importKind === 'type';
|
||
|
|
var isPreviousImportTypeOnlyImport = previousImport.node.importKind === 'type';
|
||
|
|
|
||
|
|
var isNormalImportNextToTypeOnlyImportAndRelevant = isTypeOnlyImport !== isPreviousImportTypeOnlyImport && isSortingTypesGroup;
|
||
|
|
|
||
|
|
var isTypeOnlyImportAndRelevant = isTypeOnlyImport && isSortingTypesGroup;
|
||
|
|
|
||
|
|
// In the special case where newlinesBetweenImports and consolidateIslands
|
||
|
|
// want the opposite thing, consolidateIslands wins
|
||
|
|
var newlinesBetweenImports = isSortingTypesGroup &&
|
||
|
|
isConsolidatingSpaceBetweenImports && (
|
||
|
|
previousImport.isMultiline || currentImport.isMultiline) &&
|
||
|
|
newlinesBetweenImports_ === 'never' ?
|
||
|
|
'always-and-inside-groups' :
|
||
|
|
newlinesBetweenImports_;
|
||
|
|
|
||
|
|
// In the special case where newlinesBetweenTypeOnlyImports and
|
||
|
|
// consolidateIslands want the opposite thing, consolidateIslands wins
|
||
|
|
var newlinesBetweenTypeOnlyImports = isSortingTypesGroup &&
|
||
|
|
isConsolidatingSpaceBetweenImports && (
|
||
|
|
isNormalImportNextToTypeOnlyImportAndRelevant ||
|
||
|
|
previousImport.isMultiline ||
|
||
|
|
currentImport.isMultiline) &&
|
||
|
|
newlinesBetweenTypeOnlyImports_ === 'never' ?
|
||
|
|
'always-and-inside-groups' :
|
||
|
|
newlinesBetweenTypeOnlyImports_;
|
||
|
|
|
||
|
|
var isNotIgnored = isTypeOnlyImportAndRelevant &&
|
||
|
|
newlinesBetweenTypeOnlyImports !== 'ignore' ||
|
||
|
|
!isTypeOnlyImportAndRelevant && newlinesBetweenImports !== 'ignore';
|
||
|
|
|
||
|
|
if (isNotIgnored) {
|
||
|
|
var shouldAssertNewlineBetweenGroups = (isTypeOnlyImportAndRelevant || isNormalImportNextToTypeOnlyImportAndRelevant) && (
|
||
|
|
newlinesBetweenTypeOnlyImports === 'always' ||
|
||
|
|
newlinesBetweenTypeOnlyImports === 'always-and-inside-groups') ||
|
||
|
|
!isTypeOnlyImportAndRelevant && !isNormalImportNextToTypeOnlyImportAndRelevant && (
|
||
|
|
newlinesBetweenImports === 'always' ||
|
||
|
|
newlinesBetweenImports === 'always-and-inside-groups');
|
||
|
|
|
||
|
|
var shouldAssertNoNewlineWithinGroup = (isTypeOnlyImportAndRelevant || isNormalImportNextToTypeOnlyImportAndRelevant) &&
|
||
|
|
newlinesBetweenTypeOnlyImports !== 'always-and-inside-groups' ||
|
||
|
|
!isTypeOnlyImportAndRelevant && !isNormalImportNextToTypeOnlyImportAndRelevant &&
|
||
|
|
newlinesBetweenImports !== 'always-and-inside-groups';
|
||
|
|
|
||
|
|
var shouldAssertNoNewlineBetweenGroup = !isSortingTypesGroup ||
|
||
|
|
!isNormalImportNextToTypeOnlyImportAndRelevant ||
|
||
|
|
newlinesBetweenTypeOnlyImports === 'never';
|
||
|
|
|
||
|
|
var isTheNewlineBetweenImportsInTheSameGroup = distinctGroup && currentImport.rank === previousImport.rank ||
|
||
|
|
!distinctGroup && !isStartOfDistinctGroup;
|
||
|
|
|
||
|
|
// Let's try to cut down on linting errors sent to the user
|
||
|
|
var alreadyReported = false;
|
||
|
|
|
||
|
|
if (shouldAssertNewlineBetweenGroups) {
|
||
|
|
if (currentImport.rank !== previousImport.rank && emptyLinesBetween === 0) {
|
||
|
|
if (distinctGroup || isStartOfDistinctGroup) {
|
||
|
|
alreadyReported = true;
|
||
|
|
context.report({
|
||
|
|
node: previousImport.node,
|
||
|
|
message: 'There should be at least one empty line between import groups',
|
||
|
|
fix: fixNewLineAfterImport(context, previousImport) });
|
||
|
|
|
||
|
|
}
|
||
|
|
} else if (emptyLinesBetween > 0 && shouldAssertNoNewlineWithinGroup) {
|
||
|
|
if (isTheNewlineBetweenImportsInTheSameGroup) {
|
||
|
|
alreadyReported = true;
|
||
|
|
context.report({
|
||
|
|
node: previousImport.node,
|
||
|
|
message: 'There should be no empty line within import group',
|
||
|
|
fix: removeNewLineAfterImport(context, currentImport, previousImport) });
|
||
|
|
|
||
|
|
}
|
||
|
|
}
|
||
|
|
} else if (emptyLinesBetween > 0 && shouldAssertNoNewlineBetweenGroup) {
|
||
|
|
alreadyReported = true;
|
||
|
|
context.report({
|
||
|
|
node: previousImport.node,
|
||
|
|
message: 'There should be no empty line between import groups',
|
||
|
|
fix: removeNewLineAfterImport(context, currentImport, previousImport) });
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!alreadyReported && isConsolidatingSpaceBetweenImports) {
|
||
|
|
if (emptyLinesBetween === 0 && currentImport.isMultiline) {
|
||
|
|
context.report({
|
||
|
|
node: previousImport.node,
|
||
|
|
message: 'There should be at least one empty line between this import and the multi-line import that follows it',
|
||
|
|
fix: fixNewLineAfterImport(context, previousImport) });
|
||
|
|
|
||
|
|
} else if (emptyLinesBetween === 0 && previousImport.isMultiline) {
|
||
|
|
context.report({
|
||
|
|
node: previousImport.node,
|
||
|
|
message: 'There should be at least one empty line between this multi-line import and the import that follows it',
|
||
|
|
fix: fixNewLineAfterImport(context, previousImport) });
|
||
|
|
|
||
|
|
} else if (
|
||
|
|
emptyLinesBetween > 0 &&
|
||
|
|
!previousImport.isMultiline &&
|
||
|
|
!currentImport.isMultiline &&
|
||
|
|
isTheNewlineBetweenImportsInTheSameGroup)
|
||
|
|
{
|
||
|
|
context.report({
|
||
|
|
node: previousImport.node,
|
||
|
|
message:
|
||
|
|
'There should be no empty lines between this single-line import and the single-line import that follows it',
|
||
|
|
fix: removeNewLineAfterImport(context, currentImport, previousImport) });
|
||
|
|
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
previousImport = currentImport;
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
function getAlphabetizeConfig(options) {
|
||
|
|
var alphabetize = options.alphabetize || {};
|
||
|
|
var order = alphabetize.order || 'ignore';
|
||
|
|
var orderImportKind = alphabetize.orderImportKind || 'ignore';
|
||
|
|
var caseInsensitive = alphabetize.caseInsensitive || false;
|
||
|
|
|
||
|
|
return { order: order, orderImportKind: orderImportKind, caseInsensitive: caseInsensitive };
|
||
|
|
}
|
||
|
|
|
||
|
|
// TODO, semver-major: Change the default of "distinctGroup" from true to false
|
||
|
|
var defaultDistinctGroup = true;
|
||
|
|
|
||
|
|
module.exports = {
|
||
|
|
meta: {
|
||
|
|
type: 'suggestion',
|
||
|
|
docs: {
|
||
|
|
category: 'Style guide',
|
||
|
|
description: 'Enforce a convention in module import order.',
|
||
|
|
url: (0, _docsUrl2['default'])('order') },
|
||
|
|
|
||
|
|
|
||
|
|
fixable: 'code',
|
||
|
|
schema: [
|
||
|
|
{
|
||
|
|
type: 'object',
|
||
|
|
properties: {
|
||
|
|
groups: {
|
||
|
|
type: 'array',
|
||
|
|
uniqueItems: true,
|
||
|
|
items: {
|
||
|
|
oneOf: [
|
||
|
|
{ 'enum': types },
|
||
|
|
{
|
||
|
|
type: 'array',
|
||
|
|
uniqueItems: true,
|
||
|
|
items: { 'enum': types } }] } },
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
pathGroupsExcludedImportTypes: {
|
||
|
|
type: 'array' },
|
||
|
|
|
||
|
|
distinctGroup: {
|
||
|
|
type: 'boolean',
|
||
|
|
'default': defaultDistinctGroup },
|
||
|
|
|
||
|
|
pathGroups: {
|
||
|
|
type: 'array',
|
||
|
|
items: {
|
||
|
|
type: 'object',
|
||
|
|
properties: {
|
||
|
|
pattern: {
|
||
|
|
type: 'string' },
|
||
|
|
|
||
|
|
patternOptions: {
|
||
|
|
type: 'object' },
|
||
|
|
|
||
|
|
group: {
|
||
|
|
type: 'string',
|
||
|
|
'enum': types },
|
||
|
|
|
||
|
|
position: {
|
||
|
|
type: 'string',
|
||
|
|
'enum': ['after', 'before'] } },
|
||
|
|
|
||
|
|
|
||
|
|
additionalProperties: false,
|
||
|
|
required: ['pattern', 'group'] } },
|
||
|
|
|
||
|
|
|
||
|
|
'newlines-between': {
|
||
|
|
'enum': [
|
||
|
|
'ignore',
|
||
|
|
'always',
|
||
|
|
'always-and-inside-groups',
|
||
|
|
'never'] },
|
||
|
|
|
||
|
|
|
||
|
|
'newlines-between-types': {
|
||
|
|
'enum': [
|
||
|
|
'ignore',
|
||
|
|
'always',
|
||
|
|
'always-and-inside-groups',
|
||
|
|
'never'] },
|
||
|
|
|
||
|
|
|
||
|
|
consolidateIslands: {
|
||
|
|
'enum': [
|
||
|
|
'inside-groups',
|
||
|
|
'never'] },
|
||
|
|
|
||
|
|
|
||
|
|
sortTypesGroup: {
|
||
|
|
type: 'boolean',
|
||
|
|
'default': false },
|
||
|
|
|
||
|
|
named: {
|
||
|
|
'default': false,
|
||
|
|
oneOf: [{
|
||
|
|
type: 'boolean' },
|
||
|
|
{
|
||
|
|
type: 'object',
|
||
|
|
properties: {
|
||
|
|
enabled: { type: 'boolean' },
|
||
|
|
'import': { type: 'boolean' },
|
||
|
|
'export': { type: 'boolean' },
|
||
|
|
require: { type: 'boolean' },
|
||
|
|
cjsExports: { type: 'boolean' },
|
||
|
|
types: {
|
||
|
|
type: 'string',
|
||
|
|
'enum': [
|
||
|
|
'mixed',
|
||
|
|
'types-first',
|
||
|
|
'types-last'] } },
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
additionalProperties: false }] },
|
||
|
|
|
||
|
|
|
||
|
|
alphabetize: {
|
||
|
|
type: 'object',
|
||
|
|
properties: {
|
||
|
|
caseInsensitive: {
|
||
|
|
type: 'boolean',
|
||
|
|
'default': false },
|
||
|
|
|
||
|
|
order: {
|
||
|
|
'enum': ['ignore', 'asc', 'desc'],
|
||
|
|
'default': 'ignore' },
|
||
|
|
|
||
|
|
orderImportKind: {
|
||
|
|
'enum': ['ignore', 'asc', 'desc'],
|
||
|
|
'default': 'ignore' } },
|
||
|
|
|
||
|
|
|
||
|
|
additionalProperties: false },
|
||
|
|
|
||
|
|
warnOnUnassignedImports: {
|
||
|
|
type: 'boolean',
|
||
|
|
'default': false } },
|
||
|
|
|
||
|
|
|
||
|
|
additionalProperties: false,
|
||
|
|
dependencies: {
|
||
|
|
sortTypesGroup: {
|
||
|
|
oneOf: [
|
||
|
|
{
|
||
|
|
// When sortTypesGroup is true, groups must NOT be an array that does not contain 'type'
|
||
|
|
properties: {
|
||
|
|
sortTypesGroup: { 'enum': [true] },
|
||
|
|
groups: {
|
||
|
|
not: {
|
||
|
|
type: 'array',
|
||
|
|
uniqueItems: true,
|
||
|
|
items: {
|
||
|
|
oneOf: [
|
||
|
|
{ 'enum': types.filter(function (t) {return t !== 'type';}) },
|
||
|
|
{
|
||
|
|
type: 'array',
|
||
|
|
uniqueItems: true,
|
||
|
|
items: { 'enum': types.filter(function (t) {return t !== 'type';}) } }] } } } },
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
required: ['groups'] },
|
||
|
|
|
||
|
|
{
|
||
|
|
properties: {
|
||
|
|
sortTypesGroup: { 'enum': [false] } } }] },
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
'newlines-between-types': {
|
||
|
|
properties: {
|
||
|
|
sortTypesGroup: { 'enum': [true] } },
|
||
|
|
|
||
|
|
required: ['sortTypesGroup'] },
|
||
|
|
|
||
|
|
consolidateIslands: {
|
||
|
|
oneOf: [
|
||
|
|
{
|
||
|
|
properties: {
|
||
|
|
consolidateIslands: { 'enum': ['inside-groups'] } },
|
||
|
|
|
||
|
|
anyOf: [
|
||
|
|
{
|
||
|
|
properties: {
|
||
|
|
'newlines-between': { 'enum': ['always-and-inside-groups'] } },
|
||
|
|
|
||
|
|
required: ['newlines-between'] },
|
||
|
|
|
||
|
|
{
|
||
|
|
properties: {
|
||
|
|
'newlines-between-types': { 'enum': ['always-and-inside-groups'] } },
|
||
|
|
|
||
|
|
required: ['newlines-between-types'] }] },
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
{
|
||
|
|
properties: {
|
||
|
|
consolidateIslands: { 'enum': ['never'] } } }] } } }] },
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
create: function () {function create(context) {
|
||
|
|
var options = context.options[0] || {};
|
||
|
|
var newlinesBetweenImports = options['newlines-between'] || 'ignore';
|
||
|
|
var newlinesBetweenTypeOnlyImports = options['newlines-between-types'] || newlinesBetweenImports;
|
||
|
|
var pathGroupsExcludedImportTypes = new Set(options.pathGroupsExcludedImportTypes || ['builtin', 'external', 'object']);
|
||
|
|
var sortTypesGroup = options.sortTypesGroup;
|
||
|
|
var consolidateIslands = options.consolidateIslands || 'never';
|
||
|
|
|
||
|
|
var named = Object.assign({
|
||
|
|
types: 'mixed' },
|
||
|
|
_typeof(options.named) === 'object' ? Object.assign({},
|
||
|
|
options.named, {
|
||
|
|
'import': 'import' in options.named ? options.named['import'] : options.named.enabled,
|
||
|
|
'export': 'export' in options.named ? options.named['export'] : options.named.enabled,
|
||
|
|
require: 'require' in options.named ? options.named.require : options.named.enabled,
|
||
|
|
cjsExports: 'cjsExports' in options.named ? options.named.cjsExports : options.named.enabled }) :
|
||
|
|
{
|
||
|
|
'import': options.named,
|
||
|
|
'export': options.named,
|
||
|
|
require: options.named,
|
||
|
|
cjsExports: options.named });
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
var namedGroups = named.types === 'mixed' ? [] : named.types === 'types-last' ? ['value'] : ['type'];
|
||
|
|
var alphabetize = getAlphabetizeConfig(options);
|
||
|
|
var distinctGroup = options.distinctGroup == null ? defaultDistinctGroup : !!options.distinctGroup;
|
||
|
|
var ranks = void 0;
|
||
|
|
|
||
|
|
try {var _convertPathGroupsFor =
|
||
|
|
convertPathGroupsForRanks(options.pathGroups || []),pathGroups = _convertPathGroupsFor.pathGroups,maxPosition = _convertPathGroupsFor.maxPosition;var _convertGroupsToRanks =
|
||
|
|
convertGroupsToRanks(options.groups || defaultGroups),groups = _convertGroupsToRanks.groups,omittedTypes = _convertGroupsToRanks.omittedTypes;
|
||
|
|
ranks = {
|
||
|
|
groups: groups,
|
||
|
|
omittedTypes: omittedTypes,
|
||
|
|
pathGroups: pathGroups,
|
||
|
|
maxPosition: maxPosition };
|
||
|
|
|
||
|
|
} catch (error) {
|
||
|
|
// Malformed configuration
|
||
|
|
return {
|
||
|
|
Program: function () {function Program(node) {
|
||
|
|
context.report(node, error.message);
|
||
|
|
}return Program;}() };
|
||
|
|
|
||
|
|
}
|
||
|
|
var importMap = new Map();
|
||
|
|
var exportMap = new Map();
|
||
|
|
|
||
|
|
var isTypeGroupInGroups = ranks.omittedTypes.indexOf('type') === -1;
|
||
|
|
var isSortingTypesGroup = isTypeGroupInGroups && sortTypesGroup;
|
||
|
|
|
||
|
|
function getBlockImports(node) {
|
||
|
|
if (!importMap.has(node)) {
|
||
|
|
importMap.set(node, []);
|
||
|
|
}
|
||
|
|
return importMap.get(node);
|
||
|
|
}
|
||
|
|
|
||
|
|
function getBlockExports(node) {
|
||
|
|
if (!exportMap.has(node)) {
|
||
|
|
exportMap.set(node, []);
|
||
|
|
}
|
||
|
|
return exportMap.get(node);
|
||
|
|
}
|
||
|
|
|
||
|
|
function makeNamedOrderReport(context, namedImports) {
|
||
|
|
if (namedImports.length > 1) {
|
||
|
|
var imports = namedImports.map(
|
||
|
|
function (namedImport) {
|
||
|
|
var kind = namedImport.kind || 'value';
|
||
|
|
var rank = namedGroups.findIndex(function (entry) {return [].concat(entry).indexOf(kind) > -1;});
|
||
|
|
|
||
|
|
return Object.assign({
|
||
|
|
displayName: namedImport.value,
|
||
|
|
rank: rank === -1 ? namedGroups.length : rank },
|
||
|
|
namedImport, {
|
||
|
|
value: String(namedImport.value) + ':' + String(namedImport.alias || '') });
|
||
|
|
|
||
|
|
});
|
||
|
|
|
||
|
|
if (alphabetize.order !== 'ignore') {
|
||
|
|
mutateRanksToAlphabetize(imports, alphabetize);
|
||
|
|
}
|
||
|
|
|
||
|
|
makeOutOfOrderReport(context, imports, categories.named);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return Object.assign({
|
||
|
|
ImportDeclaration: function () {function ImportDeclaration(node) {
|
||
|
|
// Ignoring unassigned imports unless warnOnUnassignedImports is set
|
||
|
|
if (node.specifiers.length || options.warnOnUnassignedImports) {
|
||
|
|
var name = node.source.value;
|
||
|
|
registerNode(
|
||
|
|
context,
|
||
|
|
{
|
||
|
|
node: node,
|
||
|
|
value: name,
|
||
|
|
displayName: name,
|
||
|
|
type: 'import' },
|
||
|
|
|
||
|
|
ranks,
|
||
|
|
getBlockImports(node.parent),
|
||
|
|
pathGroupsExcludedImportTypes,
|
||
|
|
isSortingTypesGroup);
|
||
|
|
|
||
|
|
|
||
|
|
if (named['import']) {
|
||
|
|
makeNamedOrderReport(
|
||
|
|
context,
|
||
|
|
node.specifiers.filter(
|
||
|
|
function (specifier) {return specifier.type === 'ImportSpecifier';}).map(
|
||
|
|
function (specifier) {return Object.assign({
|
||
|
|
node: specifier,
|
||
|
|
value: specifier.imported.name,
|
||
|
|
type: 'import',
|
||
|
|
kind: specifier.importKind },
|
||
|
|
specifier.local.range[0] !== specifier.imported.range[0] && {
|
||
|
|
alias: specifier.local.name });}));
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}return ImportDeclaration;}(),
|
||
|
|
TSImportEqualsDeclaration: function () {function TSImportEqualsDeclaration(node) {
|
||
|
|
// skip "export import"s
|
||
|
|
if (node.isExport) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
var displayName = void 0;
|
||
|
|
var value = void 0;
|
||
|
|
var type = void 0;
|
||
|
|
if (node.moduleReference.type === 'TSExternalModuleReference') {
|
||
|
|
value = node.moduleReference.expression.value;
|
||
|
|
displayName = value;
|
||
|
|
type = 'import';
|
||
|
|
} else {
|
||
|
|
value = '';
|
||
|
|
displayName = (0, _contextCompat.getSourceCode)(context).getText(node.moduleReference);
|
||
|
|
type = 'import:object';
|
||
|
|
}
|
||
|
|
|
||
|
|
registerNode(
|
||
|
|
context,
|
||
|
|
{
|
||
|
|
node: node,
|
||
|
|
value: value,
|
||
|
|
displayName: displayName,
|
||
|
|
type: type },
|
||
|
|
|
||
|
|
ranks,
|
||
|
|
getBlockImports(node.parent),
|
||
|
|
pathGroupsExcludedImportTypes,
|
||
|
|
isSortingTypesGroup);
|
||
|
|
|
||
|
|
}return TSImportEqualsDeclaration;}(),
|
||
|
|
CallExpression: function () {function CallExpression(node) {
|
||
|
|
if (!(0, _staticRequire2['default'])(node)) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
var block = getRequireBlock(node);
|
||
|
|
if (!block) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
var name = node.arguments[0].value;
|
||
|
|
registerNode(
|
||
|
|
context,
|
||
|
|
{
|
||
|
|
node: node,
|
||
|
|
value: name,
|
||
|
|
displayName: name,
|
||
|
|
type: 'require' },
|
||
|
|
|
||
|
|
ranks,
|
||
|
|
getBlockImports(block),
|
||
|
|
pathGroupsExcludedImportTypes,
|
||
|
|
isSortingTypesGroup);
|
||
|
|
|
||
|
|
}return CallExpression;}() },
|
||
|
|
named.require && {
|
||
|
|
VariableDeclarator: function () {function VariableDeclarator(node) {
|
||
|
|
if (node.id.type === 'ObjectPattern' && isRequireExpression(node.init)) {
|
||
|
|
for (var i = 0; i < node.id.properties.length; i++) {
|
||
|
|
if (
|
||
|
|
node.id.properties[i].key.type !== 'Identifier' ||
|
||
|
|
node.id.properties[i].value.type !== 'Identifier')
|
||
|
|
{
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
makeNamedOrderReport(
|
||
|
|
context,
|
||
|
|
node.id.properties.map(function (prop) {return Object.assign({
|
||
|
|
node: prop,
|
||
|
|
value: prop.key.name,
|
||
|
|
type: 'require' },
|
||
|
|
prop.key.range[0] !== prop.value.range[0] && {
|
||
|
|
alias: prop.value.name });}));
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
}
|
||
|
|
}return VariableDeclarator;}() },
|
||
|
|
|
||
|
|
named['export'] && {
|
||
|
|
ExportNamedDeclaration: function () {function ExportNamedDeclaration(node) {
|
||
|
|
makeNamedOrderReport(
|
||
|
|
context,
|
||
|
|
node.specifiers.map(function (specifier) {return Object.assign({
|
||
|
|
node: specifier,
|
||
|
|
value: specifier.local.name,
|
||
|
|
type: 'export',
|
||
|
|
kind: specifier.exportKind },
|
||
|
|
specifier.local.range[0] !== specifier.exported.range[0] && {
|
||
|
|
alias: specifier.exported.name });}));
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
}return ExportNamedDeclaration;}() },
|
||
|
|
|
||
|
|
named.cjsExports && {
|
||
|
|
AssignmentExpression: function () {function AssignmentExpression(node) {
|
||
|
|
if (node.parent.type === 'ExpressionStatement') {
|
||
|
|
if (isCJSExports(context, node.left)) {
|
||
|
|
if (node.right.type === 'ObjectExpression') {
|
||
|
|
for (var i = 0; i < node.right.properties.length; i++) {
|
||
|
|
if (
|
||
|
|
!node.right.properties[i].key ||
|
||
|
|
node.right.properties[i].key.type !== 'Identifier' ||
|
||
|
|
!node.right.properties[i].value ||
|
||
|
|
node.right.properties[i].value.type !== 'Identifier')
|
||
|
|
{
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
makeNamedOrderReport(
|
||
|
|
context,
|
||
|
|
node.right.properties.map(function (prop) {return Object.assign({
|
||
|
|
node: prop,
|
||
|
|
value: prop.key.name,
|
||
|
|
type: 'export' },
|
||
|
|
prop.key.range[0] !== prop.value.range[0] && {
|
||
|
|
alias: prop.value.name });}));
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
}
|
||
|
|
} else {
|
||
|
|
var nameParts = getNamedCJSExports(context, node.left);
|
||
|
|
if (nameParts && nameParts.length > 0) {
|
||
|
|
var name = nameParts.join('.');
|
||
|
|
getBlockExports(node.parent.parent).push({
|
||
|
|
node: node,
|
||
|
|
value: name,
|
||
|
|
displayName: name,
|
||
|
|
type: 'export',
|
||
|
|
rank: 0 });
|
||
|
|
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}return AssignmentExpression;}() }, {
|
||
|
|
|
||
|
|
'Program:exit': function () {function ProgramExit() {
|
||
|
|
importMap.forEach(function (imported) {
|
||
|
|
if (newlinesBetweenImports !== 'ignore' || newlinesBetweenTypeOnlyImports !== 'ignore') {
|
||
|
|
makeNewlinesBetweenReport(
|
||
|
|
context,
|
||
|
|
imported,
|
||
|
|
newlinesBetweenImports,
|
||
|
|
newlinesBetweenTypeOnlyImports,
|
||
|
|
distinctGroup,
|
||
|
|
isSortingTypesGroup,
|
||
|
|
consolidateIslands === 'inside-groups' && (
|
||
|
|
newlinesBetweenImports === 'always-and-inside-groups' ||
|
||
|
|
newlinesBetweenTypeOnlyImports === 'always-and-inside-groups'));
|
||
|
|
|
||
|
|
}
|
||
|
|
|
||
|
|
if (alphabetize.order !== 'ignore') {
|
||
|
|
mutateRanksToAlphabetize(imported, alphabetize);
|
||
|
|
}
|
||
|
|
|
||
|
|
makeOutOfOrderReport(context, imported, categories['import']);
|
||
|
|
});
|
||
|
|
|
||
|
|
exportMap.forEach(function (exported) {
|
||
|
|
if (alphabetize.order !== 'ignore') {
|
||
|
|
mutateRanksToAlphabetize(exported, alphabetize);
|
||
|
|
makeOutOfOrderReport(context, exported, categories.exports);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
|
||
|
|
importMap.clear();
|
||
|
|
exportMap.clear();
|
||
|
|
}return ProgramExit;}() });
|
||
|
|
|
||
|
|
}return create;}() };
|
||
|
|
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9ydWxlcy9vcmRlci5qcyJdLCJuYW1lcyI6WyJjYXRlZ29yaWVzIiwibmFtZWQiLCJleHBvcnRzIiwiZGVmYXVsdEdyb3VwcyIsInJldmVyc2UiLCJhcnJheSIsIm1hcCIsInYiLCJyYW5rIiwiZ2V0VG9rZW5zT3JDb21tZW50c0FmdGVyIiwic291cmNlQ29kZSIsIm5vZGUiLCJjb3VudCIsImN1cnJlbnROb2RlT3JUb2tlbiIsInJlc3VsdCIsImkiLCJnZXRUb2tlbk9yQ29tbWVudEFmdGVyIiwicHVzaCIsImdldFRva2Vuc09yQ29tbWVudHNCZWZvcmUiLCJnZXRUb2tlbk9yQ29tbWVudEJlZm9yZSIsInRha2VUb2tlbnNBZnRlcldoaWxlIiwiY29uZGl0aW9uIiwidG9rZW5zIiwibGVuZ3RoIiwidGFrZVRva2Vuc0JlZm9yZVdoaWxlIiwiZmluZE91dE9mT3JkZXIiLCJpbXBvcnRlZCIsIm1heFNlZW5SYW5rTm9kZSIsImZpbHRlciIsImltcG9ydGVkTW9kdWxlIiwicmVzIiwiZmluZFJvb3ROb2RlIiwicGFyZW50IiwiYm9keSIsImNvbW1lbnRPblNhbWVMaW5lQXMiLCJ0b2tlbiIsInR5cGUiLCJsb2MiLCJzdGFydCIsImxpbmUiLCJlbmQiLCJmaW5kRW5kT2ZMaW5lV2l0aENvbW1lbnRzIiwidG9rZW5zVG9FbmRPZkxpbmUiLCJlbmRPZlRva2VucyIsInJhbmdlIiwidGV4dCIsImZpbmRTdGFydE9mTGluZVdpdGhDb21tZW50cyIsInN0YXJ0T2ZUb2tlbnMiLCJmaW5kU3BlY2lmaWVyU3RhcnQiLCJnZXRUb2tlbkJlZm9yZSIsInZhbHVlIiwiZmluZFNwZWNpZmllckVuZCIsImdldFRva2VuQWZ0ZXIiLCJpc1JlcXVpcmVFeHByZXNzaW9uIiwiZXhwciIsImNhbGxlZSIsIm5hbWUiLCJhcmd1bWVudHMiLCJpc1N1cHBvcnRlZFJlcXVpcmVNb2R1bGUiLCJkZWNsYXJhdGlvbnMiLCJkZWNsIiwiaXNQbGFpblJlcXVpcmUiLCJpZCIsImluaXQiLCJpc1JlcXVpcmVXaXRoTWVtYmVyRXhwcmVzc2lvbiIsIm9iamVjdCIsImlzUGxhaW5JbXBvcnRNb2R1bGUiLCJzcGVjaWZpZXJzIiwiaXNQbGFpbkltcG9ydEVxdWFscyIsIm1vZHVsZVJlZmVyZW5jZSIsImV4cHJlc3Npb24iLCJpc0NKU0V4cG9ydHMiLCJjb250ZXh0IiwicHJvcGVydHkiLCJ2YXJpYWJsZXMiLCJmaW5kSW5kZXgiLCJ2YXJpYWJsZSIsImdldE5hbWVkQ0pTRXhwb3J0cyIsInJvb3QiLCJ1bnNoaWZ0Iiwic2xpY2UiLCJjYW5Dcm9zc05vZGVXaGlsZVJlb3JkZXIiLCJjYW5SZW9yZGVySXRlbXMiLCJmaXJzdE5vZGUiLCJzZWNvbmROb2RlIiwiaW5kZXhPZiIsInNvcnQiLCJmaXJzdEluZGV4Iiwic2Vjb25kSW5kZXgiLCJub2Rlc0JldHdlZW4iLCJub2RlQmV0d2VlbiIsIm1ha2VJbXBvcnREZXNjcmlwdGlvbiIsImV4cG9ydEtpbmQiLCJpbXBvcnRLaW5kIiwiZml4T3V0T2ZPcmRlciIsIm9yZGVyIiwiY2F0ZWdvcnkiLCJpc05hbWVkIiwiaXNFeHBvcnRzIiwiZmlyc3RSb290Iiwic2Vjb25kUm9vdCIsImZpcnN0Um9vdFN0YXJ0IiwiZmlyc3RSb290RW5kIiwic2Vjb25kUm9vdFN0YXJ0Iiwic2Vjb25kUm9vdEVuZCIsImRpc3BsYXlOYW1lIiwiYWxpYXMiLCJmaXJzdEltcG9ydCIsInNlY29uZEltcG9ydCIsIm1lc3NhZ2UiLCJmaXJzdENvZGUiLCJmaXJzdFRyaXZpYSIsInNlY29uZENvZGUiLCJzZWNvbmRUcml2aWEiLCJ0cmltbWVkVHJpdmlhIiwiZ2FwQ29kZSIsIndoaXRlc3BhY2VzIiwicmVwb3J0IiwiZml4IiwiZml4ZXIiLCJyZXBsYWNlVGV4dFJhbmdlIiwiZml4ZXMiLCJjYW5GaXgiLCJuZXdDb2RlIiwic3Vic3RyaW5nIiwicmVwb3J0T3V0T2ZPcmRlciIsIm91dE9mT3JkZXIiLCJmb3JFYWNoIiwiaW1wIiwiZm91bmQiLCJmaW5kIiwiaGFzSGlnaGVyUmFuayIsImltcG9ydGVkSXRlbSIsIm1ha2VPdXRPZk9yZGVyUmVwb3J0IiwicmV2ZXJzZWRJbXBvcnRlZCIsInJldmVyc2VkT3JkZXIiLCJjb21wYXJlU3RyaW5nIiwiYSIsImIiLCJERUZBVUxUX0lNUE9SVF9LSU5EIiwiZ2V0Tm9ybWFsaXplZFZhbHVlIiwidG9Mb3dlckNhc2UiLCJTdHJpbmciLCJnZXRTb3J0ZXIiLCJhbHBoYWJldGl6ZU9wdGlvbnMiLCJtdWx0aXBsaWVyIiwib3JkZXJJbXBvcnRLaW5kIiwibXVsdGlwbGllckltcG9ydEtpbmQiLCJpbXBvcnRzU29ydGVyIiwibm9kZUEiLCJub2RlQiIsImltcG9ydEEiLCJjYXNlSW5zZW5zaXRpdmUiLCJpbXBvcnRCIiwiQSIsInNwbGl0IiwiQiIsIk1hdGgiLCJtaW4iLCJtdXRhdGVSYW5rc1RvQWxwaGFiZXRpemUiLCJncm91cGVkQnlSYW5rcyIsIml0ZW0iLCJzb3J0ZXJGbiIsImdyb3VwUmFua3MiLCJPYmplY3QiLCJrZXlzIiwiZ3JvdXBSYW5rIiwibmV3UmFuayIsImFscGhhYmV0aXplZFJhbmtzIiwicmVkdWNlIiwiYWNjIiwicGFyc2VJbnQiLCJjb21wdXRlUGF0aFJhbmsiLCJyYW5rcyIsInBhdGhHcm91cHMiLCJwYXRoIiwibWF4UG9zaXRpb24iLCJsIiwicGF0dGVybiIsInBhdHRlcm5PcHRpb25zIiwiZ3JvdXAiLCJwb3NpdGlvbiIsIm5vY29tbWVudCIsImNvbXB1dGVSYW5rIiwiaW1wb3J0RW50cnkiLCJleGNsdWRlZEltcG9ydFR5cGVzIiwiaXNTb3J0aW5nVHlwZXNHcm91cCIsImltcFR5cGUiLCJpc1R5cGVHcm91cEluR3JvdXBzIiwib21pdHRlZFR5cGVzIiwiaXNUeXBlT25seUltcG9ydCIsImlzRXhjbHVkZWRGcm9tUGF0aFJhbmsiLCJoYXMiLCJncm91cHMiLCJzdGFydHNXaXRoIiwicmVnaXN0ZXJOb2RlIiwiaW1wb3J0Tm9kZSIsImlzTXVsdGlsaW5lIiwiZ2V0UmVxdWlyZUJsb2NrIiwibiIsInR5cGVzIiwiY29udmVydEdyb3Vwc1RvUmFua3MiLCJyYW5rT2JqZWN0IiwiaW5kZXgiLCJjb25jYXQiLCJncm91cEl0ZW0iLCJjb252ZXJ0UGF0aEdyb3Vwc0ZvclJhbmtzIiwiYWZ0ZXIiLCJiZWZvcmUiLCJ0cmFuc2Zvcm1lZCIsInBhdGhHcm91cCIsInBvc2l0aW9uU3RyaW5nIiwiZ3JvdXBMZW5ndGgiLCJncm91cEluZGV4IiwibWF4Iiwia2V5IiwiZ3JvdXBOZXh0UG9zaXRpb24iLCJwb3ciLCJjZWlsIiwibG9nMTAiLCJmaXhOZXdMaW5lQWZ0ZXJJbXBvcnQiLCJwcmV2aW91c0ltcG9ydCIsInByZXZSb290IiwiZW5kT2ZMaW5lIiwiaW5zZXJ0VGV4dEFmdGVyUmFuZ2UiLCJ
|