File: /var/www/design.system/node_modules/eslint-plugin-storybook/dist/rules/prefer-pascal-case.js
"use strict";
/**
* @fileoverview Prefer pascal case
* @author Yann Braga
*/
const utils_1 = require("@typescript-eslint/utils");
const csf_1 = require("@storybook/csf");
const utils_2 = require("../utils");
const ast_1 = require("../utils/ast");
const constants_1 = require("../utils/constants");
const create_storybook_rule_1 = require("../utils/create-storybook-rule");
module.exports = (0, create_storybook_rule_1.createStorybookRule)({
name: 'prefer-pascal-case',
defaultOptions: [],
meta: {
type: 'suggestion',
fixable: 'code',
hasSuggestions: true,
severity: 'warn',
docs: {
description: 'Stories should use PascalCase',
categories: [constants_1.CategoryId.RECOMMENDED],
},
messages: {
convertToPascalCase: 'Use pascal case',
usePascalCase: 'The story should use PascalCase notation: {{name}}',
},
schema: [],
},
create(context) {
// variables should be defined here
//----------------------------------------------------------------------
// Helpers
//----------------------------------------------------------------------
const isPascalCase = (str) => /^[A-Z]+([a-z0-9]?)+/.test(str);
const toPascalCase = (str) => {
return str
.replace(new RegExp(/[-_]+/, 'g'), ' ')
.replace(new RegExp(/[^\w\s]/, 'g'), '')
.replace(new RegExp(/\s+(.)(\w+)/, 'g'), (_, $2, $3) => `${$2.toUpperCase() + $3.toLowerCase()}`)
.replace(new RegExp(/\s/, 'g'), '')
.replace(new RegExp(/\w/), (s) => s.toUpperCase());
};
const getModuleScope = () => {
var _a, _b;
const { sourceCode } = context;
// Compatibility implementation for eslint v8.x and v9.x or later
// see https://eslint.org/blog/2023/09/preparing-custom-rules-eslint-v9/#context.getscope()
// @ts-expect-error keep it for compatibility with eslint v8.x
if (sourceCode.getScope) {
// for eslint v9.x or later
return (_b = (_a = sourceCode.scopeManager) === null || _a === void 0 ? void 0 : _a.scopes) === null || _b === void 0 ? void 0 : _b.find((scope) => scope.type === 'module');
}
else {
// for eslint v8.x
return context
.getScope()
.childScopes.find((scope) => scope.type === 'module');
}
};
const checkAndReportError = (id, nonStoryExportsConfig = {}) => {
const { name } = id;
if (!(0, csf_1.isExportStory)(name, nonStoryExportsConfig) || name === '__namedExportsOrder') {
return null;
}
if (!name.startsWith('_') && !isPascalCase(name)) {
context.report({
node: id,
messageId: 'usePascalCase',
data: {
name,
},
suggest: [
{
messageId: 'convertToPascalCase',
*fix(fixer) {
var _a;
const fullText = context.getSourceCode().text;
const fullName = fullText.slice(id.range[0], id.range[1]);
const suffix = fullName.substring(name.length);
const pascal = toPascalCase(name);
yield fixer.replaceTextRange(id.range, pascal + suffix);
const scope = getModuleScope();
if (scope) {
const variable = utils_1.ASTUtils.findVariable(scope, name);
const referenceCount = ((_a = variable === null || variable === void 0 ? void 0 : variable.references) === null || _a === void 0 ? void 0 : _a.length) || 0;
for (let i = 0; i < referenceCount; i++) {
const ref = variable === null || variable === void 0 ? void 0 : variable.references[i];
if (ref && !ref.init) {
yield fixer.replaceTextRange(ref.identifier.range, pascal);
}
}
}
},
},
],
});
}
};
//----------------------------------------------------------------------
// Public
//----------------------------------------------------------------------
let meta;
let nonStoryExportsConfig;
const namedExports = [];
let hasStoriesOfImport = false;
return {
ImportSpecifier(node) {
if (node.imported.name === 'storiesOf') {
hasStoriesOfImport = true;
}
},
ExportDefaultDeclaration: function (node) {
meta = (0, utils_2.getMetaObjectExpression)(node, context);
if (meta) {
try {
nonStoryExportsConfig = {
excludeStories: (0, utils_2.getDescriptor)(meta, 'excludeStories'),
includeStories: (0, utils_2.getDescriptor)(meta, 'includeStories'),
};
// eslint-disable-next-line @typescript-eslint/no-unused-vars
}
catch (err) {
//
}
}
},
ExportNamedDeclaration: function (node) {
// if there are specifiers, node.declaration should be null
if (!node.declaration)
return;
const decl = node.declaration;
if ((0, ast_1.isVariableDeclaration)(decl)) {
const declaration = decl.declarations[0];
if (declaration == null)
return;
const { id } = declaration;
if ((0, ast_1.isIdentifier)(id)) {
namedExports.push(id);
}
}
},
'Program:exit': function () {
if (namedExports.length && !hasStoriesOfImport) {
namedExports.forEach((n) => checkAndReportError(n, nonStoryExportsConfig));
}
},
};
},
});