web 3d图形渲染器
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

685 lines
77 KiB

  1. 'use strict';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");}};}();
  2. var _minimatch = require('minimatch');var _minimatch2 = _interopRequireDefault(_minimatch);
  3. var _importType = require('../core/importType');var _importType2 = _interopRequireDefault(_importType);
  4. var _staticRequire = require('../core/staticRequire');var _staticRequire2 = _interopRequireDefault(_staticRequire);
  5. var _docsUrl = require('../docsUrl');var _docsUrl2 = _interopRequireDefault(_docsUrl);function _interopRequireDefault(obj) {return obj && obj.__esModule ? obj : { default: obj };}
  6. const defaultGroups = ['builtin', 'external', 'parent', 'sibling', 'index'];
  7. // REPORTING AND FIXING
  8. function reverse(array) {
  9. return array.map(function (v) {
  10. return Object.assign({}, v, { rank: -v.rank });
  11. }).reverse();
  12. }
  13. function getTokensOrCommentsAfter(sourceCode, node, count) {
  14. let currentNodeOrToken = node;
  15. const result = [];
  16. for (let i = 0; i < count; i++) {
  17. currentNodeOrToken = sourceCode.getTokenOrCommentAfter(currentNodeOrToken);
  18. if (currentNodeOrToken == null) {
  19. break;
  20. }
  21. result.push(currentNodeOrToken);
  22. }
  23. return result;
  24. }
  25. function getTokensOrCommentsBefore(sourceCode, node, count) {
  26. let currentNodeOrToken = node;
  27. const result = [];
  28. for (let i = 0; i < count; i++) {
  29. currentNodeOrToken = sourceCode.getTokenOrCommentBefore(currentNodeOrToken);
  30. if (currentNodeOrToken == null) {
  31. break;
  32. }
  33. result.push(currentNodeOrToken);
  34. }
  35. return result.reverse();
  36. }
  37. function takeTokensAfterWhile(sourceCode, node, condition) {
  38. const tokens = getTokensOrCommentsAfter(sourceCode, node, 100);
  39. const result = [];
  40. for (let i = 0; i < tokens.length; i++) {
  41. if (condition(tokens[i])) {
  42. result.push(tokens[i]);
  43. } else
  44. {
  45. break;
  46. }
  47. }
  48. return result;
  49. }
  50. function takeTokensBeforeWhile(sourceCode, node, condition) {
  51. const tokens = getTokensOrCommentsBefore(sourceCode, node, 100);
  52. const result = [];
  53. for (let i = tokens.length - 1; i >= 0; i--) {
  54. if (condition(tokens[i])) {
  55. result.push(tokens[i]);
  56. } else
  57. {
  58. break;
  59. }
  60. }
  61. return result.reverse();
  62. }
  63. function findOutOfOrder(imported) {
  64. if (imported.length === 0) {
  65. return [];
  66. }
  67. let maxSeenRankNode = imported[0];
  68. return imported.filter(function (importedModule) {
  69. const res = importedModule.rank < maxSeenRankNode.rank;
  70. if (maxSeenRankNode.rank < importedModule.rank) {
  71. maxSeenRankNode = importedModule;
  72. }
  73. return res;
  74. });
  75. }
  76. function findRootNode(node) {
  77. let parent = node;
  78. while (parent.parent != null && parent.parent.body == null) {
  79. parent = parent.parent;
  80. }
  81. return parent;
  82. }
  83. function findEndOfLineWithComments(sourceCode, node) {
  84. const tokensToEndOfLine = takeTokensAfterWhile(sourceCode, node, commentOnSameLineAs(node));
  85. let endOfTokens = tokensToEndOfLine.length > 0 ?
  86. tokensToEndOfLine[tokensToEndOfLine.length - 1].range[1] :
  87. node.range[1];
  88. let result = endOfTokens;
  89. for (let i = endOfTokens; i < sourceCode.text.length; i++) {
  90. if (sourceCode.text[i] === '\n') {
  91. result = i + 1;
  92. break;
  93. }
  94. if (sourceCode.text[i] !== ' ' && sourceCode.text[i] !== '\t' && sourceCode.text[i] !== '\r') {
  95. break;
  96. }
  97. result = i + 1;
  98. }
  99. return result;
  100. }
  101. function commentOnSameLineAs(node) {
  102. return token => (token.type === 'Block' || token.type === 'Line') &&
  103. token.loc.start.line === token.loc.end.line &&
  104. token.loc.end.line === node.loc.end.line;
  105. }
  106. function findStartOfLineWithComments(sourceCode, node) {
  107. const tokensToEndOfLine = takeTokensBeforeWhile(sourceCode, node, commentOnSameLineAs(node));
  108. let startOfTokens = tokensToEndOfLine.length > 0 ? tokensToEndOfLine[0].range[0] : node.range[0];
  109. let result = startOfTokens;
  110. for (let i = startOfTokens - 1; i > 0; i--) {
  111. if (sourceCode.text[i] !== ' ' && sourceCode.text[i] !== '\t') {
  112. break;
  113. }
  114. result = i;
  115. }
  116. return result;
  117. }
  118. function isPlainRequireModule(node) {
  119. if (node.type !== 'VariableDeclaration') {
  120. return false;
  121. }
  122. if (node.declarations.length !== 1) {
  123. return false;
  124. }
  125. const decl = node.declarations[0];
  126. const result = decl.id && (
  127. decl.id.type === 'Identifier' || decl.id.type === 'ObjectPattern') &&
  128. decl.init != null &&
  129. decl.init.type === 'CallExpression' &&
  130. decl.init.callee != null &&
  131. decl.init.callee.name === 'require' &&
  132. decl.init.arguments != null &&
  133. decl.init.arguments.length === 1 &&
  134. decl.init.arguments[0].type === 'Literal';
  135. return result;
  136. }
  137. function isPlainImportModule(node) {
  138. return node.type === 'ImportDeclaration' && node.specifiers != null && node.specifiers.length > 0;
  139. }
  140. function isPlainImportEquals(node) {
  141. return node.type === 'TSImportEqualsDeclaration' && node.moduleReference.expression;
  142. }
  143. function canCrossNodeWhileReorder(node) {
  144. return isPlainRequireModule(node) || isPlainImportModule(node) || isPlainImportEquals(node);
  145. }
  146. function canReorderItems(firstNode, secondNode) {
  147. const parent = firstNode.parent;var _sort =
  148. [
  149. parent.body.indexOf(firstNode),
  150. parent.body.indexOf(secondNode)].
  151. sort(),_sort2 = _slicedToArray(_sort, 2);const firstIndex = _sort2[0],secondIndex = _sort2[1];
  152. const nodesBetween = parent.body.slice(firstIndex, secondIndex + 1);
  153. for (var nodeBetween of nodesBetween) {
  154. if (!canCrossNodeWhileReorder(nodeBetween)) {
  155. return false;
  156. }
  157. }
  158. return true;
  159. }
  160. function fixOutOfOrder(context, firstNode, secondNode, order) {
  161. const sourceCode = context.getSourceCode();
  162. const firstRoot = findRootNode(firstNode.node);
  163. const firstRootStart = findStartOfLineWithComments(sourceCode, firstRoot);
  164. const firstRootEnd = findEndOfLineWithComments(sourceCode, firstRoot);
  165. const secondRoot = findRootNode(secondNode.node);
  166. const secondRootStart = findStartOfLineWithComments(sourceCode, secondRoot);
  167. const secondRootEnd = findEndOfLineWithComments(sourceCode, secondRoot);
  168. const canFix = canReorderItems(firstRoot, secondRoot);
  169. let newCode = sourceCode.text.substring(secondRootStart, secondRootEnd);
  170. if (newCode[newCode.length - 1] !== '\n') {
  171. newCode = newCode + '\n';
  172. }
  173. const message = `\`${secondNode.displayName}\` import should occur ${order} import of \`${firstNode.displayName}\``;
  174. if (order === 'before') {
  175. context.report({
  176. node: secondNode.node,
  177. message: message,
  178. fix: canFix && (fixer =>
  179. fixer.replaceTextRange(
  180. [firstRootStart, secondRootEnd],
  181. newCode + sourceCode.text.substring(firstRootStart, secondRootStart))) });
  182. } else if (order === 'after') {
  183. context.report({
  184. node: secondNode.node,
  185. message: message,
  186. fix: canFix && (fixer =>
  187. fixer.replaceTextRange(
  188. [secondRootStart, firstRootEnd],
  189. sourceCode.text.substring(secondRootEnd, firstRootEnd) + newCode)) });
  190. }
  191. }
  192. function reportOutOfOrder(context, imported, outOfOrder, order) {
  193. outOfOrder.forEach(function (imp) {
  194. const found = imported.find(function hasHigherRank(importedItem) {
  195. return importedItem.rank > imp.rank;
  196. });
  197. fixOutOfOrder(context, found, imp, order);
  198. });
  199. }
  200. function makeOutOfOrderReport(context, imported) {
  201. const outOfOrder = findOutOfOrder(imported);
  202. if (!outOfOrder.length) {
  203. return;
  204. }
  205. // There are things to report. Try to minimize the number of reported errors.
  206. const reversedImported = reverse(imported);
  207. const reversedOrder = findOutOfOrder(reversedImported);
  208. if (reversedOrder.length < outOfOrder.length) {
  209. reportOutOfOrder(context, reversedImported, reversedOrder, 'after');
  210. return;
  211. }
  212. reportOutOfOrder(context, imported, outOfOrder, 'before');
  213. }
  214. function getSorter(ascending) {
  215. const multiplier = ascending ? 1 : -1;
  216. return function importsSorter(importA, importB) {
  217. let result;
  218. if (importA < importB) {
  219. result = -1;
  220. } else if (importA > importB) {
  221. result = 1;
  222. } else {
  223. result = 0;
  224. }
  225. return result * multiplier;
  226. };
  227. }
  228. function mutateRanksToAlphabetize(imported, alphabetizeOptions) {
  229. const groupedByRanks = imported.reduce(function (acc, importedItem) {
  230. if (!Array.isArray(acc[importedItem.rank])) {
  231. acc[importedItem.rank] = [];
  232. }
  233. acc[importedItem.rank].push(importedItem.value);
  234. return acc;
  235. }, {});
  236. const groupRanks = Object.keys(groupedByRanks);
  237. const sorterFn = getSorter(alphabetizeOptions.order === 'asc');
  238. const comparator = alphabetizeOptions.caseInsensitive ? (a, b) => sorterFn(String(a).toLowerCase(), String(b).toLowerCase()) : (a, b) => sorterFn(a, b);
  239. // sort imports locally within their group
  240. groupRanks.forEach(function (groupRank) {
  241. groupedByRanks[groupRank].sort(comparator);
  242. });
  243. // assign globally unique rank to each import
  244. let newRank = 0;
  245. const alphabetizedRanks = groupRanks.sort().reduce(function (acc, groupRank) {
  246. groupedByRanks[groupRank].forEach(function (importedItemName) {
  247. acc[importedItemName] = parseInt(groupRank, 10) + newRank;
  248. newRank += 1;
  249. });
  250. return acc;
  251. }, {});
  252. // mutate the original group-rank with alphabetized-rank
  253. imported.forEach(function (importedItem) {
  254. importedItem.rank = alphabetizedRanks[importedItem.value];
  255. });
  256. }
  257. // DETECTING
  258. function computePathRank(ranks, pathGroups, path, maxPosition) {
  259. for (let i = 0, l = pathGroups.length; i < l; i++) {var _pathGroups$i =
  260. pathGroups[i];const pattern = _pathGroups$i.pattern,patternOptions = _pathGroups$i.patternOptions,group = _pathGroups$i.group;var _pathGroups$i$positio = _pathGroups$i.position;const position = _pathGroups$i$positio === undefined ? 1 : _pathGroups$i$positio;
  261. if ((0, _minimatch2.default)(path, pattern, patternOptions || { nocomment: true })) {
  262. return ranks[group] + position / maxPosition;
  263. }
  264. }
  265. }
  266. function computeRank(context, ranks, importEntry, excludedImportTypes) {
  267. let impType;
  268. let rank;
  269. if (importEntry.type === 'import:object') {
  270. impType = 'object';
  271. } else {
  272. impType = (0, _importType2.default)(importEntry.value, context);
  273. }
  274. if (!excludedImportTypes.has(impType)) {
  275. rank = computePathRank(ranks.groups, ranks.pathGroups, importEntry.value, ranks.maxPosition);
  276. }
  277. if (typeof rank === 'undefined') {
  278. rank = ranks.groups[impType];
  279. }
  280. if (importEntry.type !== 'import' && !importEntry.type.startsWith('import:')) {
  281. rank += 100;
  282. }
  283. return rank;
  284. }
  285. function registerNode(context, importEntry, ranks, imported, excludedImportTypes) {
  286. const rank = computeRank(context, ranks, importEntry, excludedImportTypes);
  287. if (rank !== -1) {
  288. imported.push(Object.assign({}, importEntry, { rank }));
  289. }
  290. }
  291. function isInVariableDeclarator(node) {
  292. return node && (
  293. node.type === 'VariableDeclarator' || isInVariableDeclarator(node.parent));
  294. }
  295. const types = ['builtin', 'external', 'internal', 'unknown', 'parent', 'sibling', 'index', 'object'];
  296. // Creates an object with type-rank pairs.
  297. // Example: { index: 0, sibling: 1, parent: 1, external: 1, builtin: 2, internal: 2 }
  298. // Will throw an error if it contains a type that does not exist, or has a duplicate
  299. function convertGroupsToRanks(groups) {
  300. const rankObject = groups.reduce(function (res, group, index) {
  301. if (typeof group === 'string') {
  302. group = [group];
  303. }
  304. group.forEach(function (groupItem) {
  305. if (types.indexOf(groupItem) === -1) {
  306. throw new Error('Incorrect configuration of the rule: Unknown type `' +
  307. JSON.stringify(groupItem) + '`');
  308. }
  309. if (res[groupItem] !== undefined) {
  310. throw new Error('Incorrect configuration of the rule: `' + groupItem + '` is duplicated');
  311. }
  312. res[groupItem] = index;
  313. });
  314. return res;
  315. }, {});
  316. const omittedTypes = types.filter(function (type) {
  317. return rankObject[type] === undefined;
  318. });
  319. return omittedTypes.reduce(function (res, type) {
  320. res[type] = groups.length;
  321. return res;
  322. }, rankObject);
  323. }
  324. function convertPathGroupsForRanks(pathGroups) {
  325. const after = {};
  326. const before = {};
  327. const transformed = pathGroups.map((pathGroup, index) => {const
  328. group = pathGroup.group,positionString = pathGroup.position;
  329. let position = 0;
  330. if (positionString === 'after') {
  331. if (!after[group]) {
  332. after[group] = 1;
  333. }
  334. position = after[group]++;
  335. } else if (positionString === 'before') {
  336. if (!before[group]) {
  337. before[group] = [];
  338. }
  339. before[group].push(index);
  340. }
  341. return Object.assign({}, pathGroup, { position });
  342. });
  343. let maxPosition = 1;
  344. Object.keys(before).forEach(group => {
  345. const groupLength = before[group].length;
  346. before[group].forEach((groupIndex, index) => {
  347. transformed[groupIndex].position = -1 * (groupLength - index);
  348. });
  349. maxPosition = Math.max(maxPosition, groupLength);
  350. });
  351. Object.keys(after).forEach(key => {
  352. const groupNextPosition = after[key];
  353. maxPosition = Math.max(maxPosition, groupNextPosition - 1);
  354. });
  355. return {
  356. pathGroups: transformed,
  357. maxPosition: maxPosition > 10 ? Math.pow(10, Math.ceil(Math.log10(maxPosition))) : 10 };
  358. }
  359. function fixNewLineAfterImport(context, previousImport) {
  360. const prevRoot = findRootNode(previousImport.node);
  361. const tokensToEndOfLine = takeTokensAfterWhile(
  362. context.getSourceCode(), prevRoot, commentOnSameLineAs(prevRoot));
  363. let endOfLine = prevRoot.range[1];
  364. if (tokensToEndOfLine.length > 0) {
  365. endOfLine = tokensToEndOfLine[tokensToEndOfLine.length - 1].range[1];
  366. }
  367. return fixer => fixer.insertTextAfterRange([prevRoot.range[0], endOfLine], '\n');
  368. }
  369. function removeNewLineAfterImport(context, currentImport, previousImport) {
  370. const sourceCode = context.getSourceCode();
  371. const prevRoot = findRootNode(previousImport.node);
  372. const currRoot = findRootNode(currentImport.node);
  373. const rangeToRemove = [
  374. findEndOfLineWithComments(sourceCode, prevRoot),
  375. findStartOfLineWithComments(sourceCode, currRoot)];
  376. if (/^\s*$/.test(sourceCode.text.substring(rangeToRemove[0], rangeToRemove[1]))) {
  377. return fixer => fixer.removeRange(rangeToRemove);
  378. }
  379. return undefined;
  380. }
  381. function makeNewlinesBetweenReport(context, imported, newlinesBetweenImports) {
  382. const getNumberOfEmptyLinesBetween = (currentImport, previousImport) => {
  383. const linesBetweenImports = context.getSourceCode().lines.slice(
  384. previousImport.node.loc.end.line,
  385. currentImport.node.loc.start.line - 1);
  386. return linesBetweenImports.filter(line => !line.trim().length).length;
  387. };
  388. let previousImport = imported[0];
  389. imported.slice(1).forEach(function (currentImport) {
  390. const emptyLinesBetween = getNumberOfEmptyLinesBetween(currentImport, previousImport);
  391. if (newlinesBetweenImports === 'always' ||
  392. newlinesBetweenImports === 'always-and-inside-groups') {
  393. if (currentImport.rank !== previousImport.rank && emptyLinesBetween === 0) {
  394. context.report({
  395. node: previousImport.node,
  396. message: 'There should be at least one empty line between import groups',
  397. fix: fixNewLineAfterImport(context, previousImport) });
  398. } else if (currentImport.rank === previousImport.rank &&
  399. emptyLinesBetween > 0 &&
  400. newlinesBetweenImports !== 'always-and-inside-groups') {
  401. context.report({
  402. node: previousImport.node,
  403. message: 'There should be no empty line within import group',
  404. fix: removeNewLineAfterImport(context, currentImport, previousImport) });
  405. }
  406. } else if (emptyLinesBetween > 0) {
  407. context.report({
  408. node: previousImport.node,
  409. message: 'There should be no empty line between import groups',
  410. fix: removeNewLineAfterImport(context, currentImport, previousImport) });
  411. }
  412. previousImport = currentImport;
  413. });
  414. }
  415. function getAlphabetizeConfig(options) {
  416. const alphabetize = options.alphabetize || {};
  417. const order = alphabetize.order || 'ignore';
  418. const caseInsensitive = alphabetize.caseInsensitive || false;
  419. return { order, caseInsensitive };
  420. }
  421. module.exports = {
  422. meta: {
  423. type: 'suggestion',
  424. docs: {
  425. url: (0, _docsUrl2.default)('order') },
  426. fixable: 'code',
  427. schema: [
  428. {
  429. type: 'object',
  430. properties: {
  431. groups: {
  432. type: 'array' },
  433. pathGroupsExcludedImportTypes: {
  434. type: 'array' },
  435. pathGroups: {
  436. type: 'array',
  437. items: {
  438. type: 'object',
  439. properties: {
  440. pattern: {
  441. type: 'string' },
  442. patternOptions: {
  443. type: 'object' },
  444. group: {
  445. type: 'string',
  446. enum: types },
  447. position: {
  448. type: 'string',
  449. enum: ['after', 'before'] } },
  450. required: ['pattern', 'group'] } },
  451. 'newlines-between': {
  452. enum: [
  453. 'ignore',
  454. 'always',
  455. 'always-and-inside-groups',
  456. 'never'] },
  457. alphabetize: {
  458. type: 'object',
  459. properties: {
  460. caseInsensitive: {
  461. type: 'boolean',
  462. default: false },
  463. order: {
  464. enum: ['ignore', 'asc', 'desc'],
  465. default: 'ignore' } },
  466. additionalProperties: false } },
  467. additionalProperties: false }] },
  468. create: function importOrderRule(context) {
  469. const options = context.options[0] || {};
  470. const newlinesBetweenImports = options['newlines-between'] || 'ignore';
  471. const pathGroupsExcludedImportTypes = new Set(options['pathGroupsExcludedImportTypes'] || ['builtin', 'external', 'object']);
  472. const alphabetize = getAlphabetizeConfig(options);
  473. let ranks;
  474. try {var _convertPathGroupsFor =
  475. convertPathGroupsForRanks(options.pathGroups || []);const pathGroups = _convertPathGroupsFor.pathGroups,maxPosition = _convertPathGroupsFor.maxPosition;
  476. ranks = {
  477. groups: convertGroupsToRanks(options.groups || defaultGroups),
  478. pathGroups,
  479. maxPosition };
  480. } catch (error) {
  481. // Malformed configuration
  482. return {
  483. Program: function (node) {
  484. context.report(node, error.message);
  485. } };
  486. }
  487. let imported = [];
  488. let level = 0;
  489. function incrementLevel() {
  490. level++;
  491. }
  492. function decrementLevel() {
  493. level--;
  494. }
  495. return {
  496. ImportDeclaration: function handleImports(node) {
  497. if (node.specifiers.length) {// Ignoring unassigned imports
  498. const name = node.source.value;
  499. registerNode(
  500. context,
  501. {
  502. node,
  503. value: name,
  504. displayName: name,
  505. type: 'import' },
  506. ranks,
  507. imported,
  508. pathGroupsExcludedImportTypes);
  509. }
  510. },
  511. TSImportEqualsDeclaration: function handleImports(node) {
  512. let displayName;
  513. let value;
  514. let type;
  515. // skip "export import"s
  516. if (node.isExport) {
  517. return;
  518. }
  519. if (node.moduleReference.type === 'TSExternalModuleReference') {
  520. value = node.moduleReference.expression.value;
  521. displayName = value;
  522. type = 'import';
  523. } else {
  524. value = '';
  525. displayName = context.getSourceCode().getText(node.moduleReference);
  526. type = 'import:object';
  527. }
  528. registerNode(
  529. context,
  530. {
  531. node,
  532. value,
  533. displayName,
  534. type },
  535. ranks,
  536. imported,
  537. pathGroupsExcludedImportTypes);
  538. },
  539. CallExpression: function handleRequires(node) {
  540. if (level !== 0 || !(0, _staticRequire2.default)(node) || !isInVariableDeclarator(node.parent)) {
  541. return;
  542. }
  543. const name = node.arguments[0].value;
  544. registerNode(
  545. context,
  546. {
  547. node,
  548. value: name,
  549. displayName: name,
  550. type: 'require' },
  551. ranks,
  552. imported,
  553. pathGroupsExcludedImportTypes);
  554. },
  555. 'Program:exit': function reportAndReset() {
  556. if (newlinesBetweenImports !== 'ignore') {
  557. makeNewlinesBetweenReport(context, imported, newlinesBetweenImports);
  558. }
  559. if (alphabetize.order !== 'ignore') {
  560. mutateRanksToAlphabetize(imported, alphabetize);
  561. }
  562. makeOutOfOrderReport(context, imported);
  563. imported = [];
  564. },
  565. FunctionDeclaration: incrementLevel,
  566. FunctionExpression: incrementLevel,
  567. ArrowFunctionExpression: incrementLevel,
  568. BlockStatement: incrementLevel,
  569. ObjectExpression: incrementLevel,
  570. 'FunctionDeclaration:exit': decrementLevel,
  571. 'FunctionExpression:exit': decrementLevel,
  572. 'ArrowFunctionExpression:exit': decrementLevel,
  573. 'BlockStatement:exit': decrementLevel,
  574. 'ObjectExpression:exit': decrementLevel };
  575. } };
  576. //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9ydWxlcy9vcmRlci5qcyJdLCJuYW1lcyI6WyJkZWZhdWx0R3JvdXBzIiwicmV2ZXJzZSIsImFycmF5IiwibWFwIiwidiIsIk9iamVjdCIsImFzc2lnbiIsInJhbmsiLCJnZXRUb2tlbnNPckNvbW1lbnRzQWZ0ZXIiLCJzb3VyY2VDb2RlIiwibm9kZSIsImNvdW50IiwiY3VycmVudE5vZGVPclRva2VuIiwicmVzdWx0IiwiaSIsImdldFRva2VuT3JDb21tZW50QWZ0ZXIiLCJwdXNoIiwiZ2V0VG9rZW5zT3JDb21tZW50c0JlZm9yZSIsImdldFRva2VuT3JDb21tZW50QmVmb3JlIiwidGFrZVRva2Vuc0FmdGVyV2hpbGUiLCJjb25kaXRpb24iLCJ0b2tlbnMiLCJsZW5ndGgiLCJ0YWtlVG9rZW5zQmVmb3JlV2hpbGUiLCJmaW5kT3V0T2ZPcmRlciIsImltcG9ydGVkIiwibWF4U2VlblJhbmtOb2RlIiwiZmlsdGVyIiwiaW1wb3J0ZWRNb2R1bGUiLCJyZXMiLCJmaW5kUm9vdE5vZGUiLCJwYXJlbnQiLCJib2R5IiwiZmluZEVuZE9mTGluZVdpdGhDb21tZW50cyIsInRva2Vuc1RvRW5kT2ZMaW5lIiwiY29tbWVudE9uU2FtZUxpbmVBcyIsImVuZE9mVG9rZW5zIiwicmFuZ2UiLCJ0ZXh0IiwidG9rZW4iLCJ0eXBlIiwibG9jIiwic3RhcnQiLCJsaW5lIiwiZW5kIiwiZmluZFN0YXJ0T2ZMaW5lV2l0aENvbW1lbnRzIiwic3RhcnRPZlRva2VucyIsImlzUGxhaW5SZXF1aXJlTW9kdWxlIiwiZGVjbGFyYXRpb25zIiwiZGVjbCIsImlkIiwiaW5pdCIsImNhbGxlZSIsIm5hbWUiLCJhcmd1bWVudHMiLCJpc1BsYWluSW1wb3J0TW9kdWxlIiwic3BlY2lmaWVycyIsImlzUGxhaW5JbXBvcnRFcXVhbHMiLCJtb2R1bGVSZWZlcmVuY2UiLCJleHByZXNzaW9uIiwiY2FuQ3Jvc3NOb2RlV2hpbGVSZW9yZGVyIiwiY2FuUmVvcmRlckl0ZW1zIiwiZmlyc3ROb2RlIiwic2Vjb25kTm9kZSIsImluZGV4T2YiLCJzb3J0IiwiZmlyc3RJbmRleCIsInNlY29uZEluZGV4Iiwibm9kZXNCZXR3ZWVuIiwic2xpY2UiLCJub2RlQmV0d2VlbiIsImZpeE91dE9mT3JkZXIiLCJjb250ZXh0Iiwib3JkZXIiLCJnZXRTb3VyY2VDb2RlIiwiZmlyc3RSb290IiwiZmlyc3RSb290U3RhcnQiLCJmaXJzdFJvb3RFbmQiLCJzZWNvbmRSb290Iiwic2Vjb25kUm9vdFN0YXJ0Iiwic2Vjb25kUm9vdEVuZCIsImNhbkZpeCIsIm5ld0NvZGUiLCJzdWJzdHJpbmciLCJtZXNzYWdlIiwiZGlzcGxheU5hbWUiLCJyZXBvcnQiLCJmaXgiLCJmaXhlciIsInJlcGxhY2VUZXh0UmFuZ2UiLCJyZXBvcnRPdXRPZk9yZGVyIiwib3V0T2ZPcmRlciIsImZvckVhY2giLCJpbXAiLCJmb3VuZCIsImZpbmQiLCJoYXNIaWdoZXJSYW5rIiwiaW1wb3J0ZWRJdGVtIiwibWFrZU91dE9mT3JkZXJSZXBvcnQiLCJyZXZlcnNlZEltcG9ydGVkIiwicmV2ZXJzZWRPcmRlciIsImdldFNvcnRlciIsImFzY2VuZGluZyIsIm11bHRpcGxpZXIiLCJpbXBvcnRzU29ydGVyIiwiaW1wb3J0QSIsImltcG9ydEIiLCJtdXRhdGVSYW5rc1RvQWxwaGFiZXRpemUiLCJhbHBoYWJldGl6ZU9wdGlvbnMiLCJncm91cGVkQnlSYW5rcyIsInJlZHVjZSIsImFjYyIsIkFycmF5IiwiaXNBcnJheSIsInZhbHVlIiwiZ3JvdXBSYW5rcyIsImtleXMiLCJzb3J0ZXJGbiIsImNvbXBhcmF0b3IiLCJjYXNlSW5zZW5zaXRpdmUiLCJhIiwiYiIsIlN0cmluZyIsInRvTG93ZXJDYXNlIiwiZ3JvdXBSYW5rIiwibmV3UmFuayIsImFscGhhYmV0aXplZFJhbmtzIiwiaW1wb3J0ZWRJdGVtTmFtZSIsInBhcnNlSW50IiwiY29tcHV0ZVBhdGhSYW5rIiwicmFua3MiLCJwYXRoR3JvdXBzIiwicGF0aCIsIm1heFBvc2l0aW9uIiwibCIsInBhdHRlcm4iLCJwYXR0ZXJuT3B0aW9ucyIsImdyb3VwIiwicG9zaXRpb24iLCJub2NvbW1lbnQiLCJjb21wdXRlUmFuayIsImltcG9ydEVudHJ5IiwiZXhjbHVkZWRJbXBvcnRUeXBlcyIsImltcFR5cGUiLCJoYXMiLCJncm91cHMiLCJzdGFydHNXaXRoIiwicmVnaXN0ZXJOb2RlIiwiaXNJblZhcmlhYmxlRGVjbGFyYXRvciIsInR5cGVzIiwiY29udmVydEdyb3Vwc1RvUmFua3MiLCJyYW5rT2JqZWN0IiwiaW5kZXgiLCJncm91cEl0ZW0iLCJFcnJvciIsIkpTT04iLCJzdHJpbmdpZnkiLCJ1bmRlZmluZWQiLCJvbWl0dGVkVHlwZXMiLCJjb252ZXJ0UGF0aEdyb3Vwc0ZvclJhbmtzIiwiYWZ0ZXIiLCJiZWZvcmUiLCJ0cmFuc2Zvcm1lZCIsInBhdGhHcm91cCIsInBvc2l0aW9uU3RyaW5nIiwiZ3JvdXBMZW5ndGgiLCJncm91cEluZGV4IiwiTWF0aCIsIm1heCIsImtleSIsImdyb3VwTmV4dFBvc2l0aW9uIiwicG93IiwiY2VpbCIsImxvZzEwIiwiZml4TmV3TGluZUFmdGVySW1wb3J0IiwicHJldmlvdXNJbXBvcnQiLCJwcmV2Um9vdCIsImVuZE9mTGluZSIsImluc2VydFRleHRBZnRlclJhbmdlIiwicmVtb3ZlTmV3TGluZUFmdGVySW1wb3J0IiwiY3VycmVudEltcG9ydCIsImN1cnJSb290IiwicmFuZ2VUb1JlbW92ZSIsInRlc3QiLCJyZW1vdmVSYW5nZSIsIm1ha2VOZXdsaW5lc0JldHdlZW5SZXBvcnQiLCJuZXdsaW5lc0JldHdlZW5JbXBvcnRzIiwiZ2V0TnVtYmVyT2ZFbXB0eUxpbmVzQmV0d2VlbiIsImxpbmVzQmV0d2VlbkltcG9ydHMiLCJsaW5lcyIsInRyaW0iLCJlbXB0eUxpbmVzQmV0d2VlbiIsImdldEFscGhhYmV0aXplQ29uZmlnIiwib3B0aW9ucyIsImFscGhhYmV0aXplIiwibW9kdWxlIiwiZXhwb3J0cyIsIm1ldGEiLCJkb2NzIiwidXJsIiwiZml4YWJsZSIsInNjaGVtYSIsInByb3BlcnRpZXMiLCJwYXRoR3JvdXBzRXhjbHVkZWRJbXBvcnRUeXBlcyIsIml0ZW1zIiwiZW51bSIsInJlcXVpcmVkIiwiZGVmYXVsdCIsImFkZGl0aW9uYWxQcm9wZXJ0aWVzIiwiY3JlYXRlIiwiaW1wb3J0T3JkZXJSdWxlIiwiU2V0IiwiZXJyb3IiLCJQcm9ncmFtIiwibGV2ZWwiLCJpbmNyZW1lbnRMZXZlbCIsImRlY3JlbWVudExldmVsIiwiSW1wb3J0RGVjbGFyYXRpb24iLCJoYW5kbGVJbXBvcnRzIiwic291cmNlIiwiVFNJbXBvcnRFcXVhbHNEZWNsYXJhdGlvbiIsImlzRXhwb3J0IiwiZ2V0VGV4dCIsIkNhbGxFeHByZXNzaW9uIiwiaGFuZGxlUmVxdWl