Skip to content

Commit

Permalink
[Refactor] hoist functions to module level
Browse files Browse the repository at this point in the history
  • Loading branch information
ljharb committed Jul 30, 2024
1 parent e3927a3 commit 8dc0215
Show file tree
Hide file tree
Showing 4 changed files with 148 additions and 147 deletions.
24 changes: 12 additions & 12 deletions lib/rules/boolean-prop-naming.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,18 @@ const eslintUtil = require('../util/eslint');
const getSourceCode = eslintUtil.getSourceCode;
const getText = eslintUtil.getText;

/**
* Checks if prop is nested
* @param {Object} prop Property object, single prop type declaration
* @returns {boolean}
*/
function nestedPropTypes(prop) {
return (
prop.type === 'Property'
&& prop.value.type === 'CallExpression'
);
}

// ------------------------------------------------------------------------------
// Rule Definition
// ------------------------------------------------------------------------------
Expand Down Expand Up @@ -162,18 +174,6 @@ module.exports = {
);
}

/**
* Checks if prop is nested
* @param {Object} prop Property object, single prop type declaration
* @returns {boolean}
*/
function nestedPropTypes(prop) {
return (
prop.type === 'Property'
&& prop.value.type === 'CallExpression'
);
}

/**
* Runs recursive check on all proptypes
* @param {Array} proptypes A list of Property object (for each proptype defined)
Expand Down
203 changes: 102 additions & 101 deletions lib/rules/jsx-curly-brace-presence.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,108 @@ const OPTION_VALUES = [
];
const DEFAULT_CONFIG = { props: OPTION_NEVER, children: OPTION_NEVER, propElementValues: OPTION_IGNORE };

const HTML_ENTITY_REGEX = () => /&[A-Za-z\d#]+;/g;

function containsLineTerminators(rawStringValue) {
return /[\n\r\u2028\u2029]/.test(rawStringValue);
}

function containsBackslash(rawStringValue) {
return arrayIncludes(rawStringValue, '\\');
}

function containsHTMLEntity(rawStringValue) {
return HTML_ENTITY_REGEX().test(rawStringValue);
}

function containsOnlyHtmlEntities(rawStringValue) {
return rawStringValue.replace(HTML_ENTITY_REGEX(), '').trim() === '';
}

function containsDisallowedJSXTextChars(rawStringValue) {
return /[{<>}]/.test(rawStringValue);
}

function containsQuoteCharacters(value) {
return /['"]/.test(value);
}

function containsMultilineComment(value) {
return /\/\*/.test(value);
}

function escapeDoubleQuotes(rawStringValue) {
return rawStringValue.replace(/\\"/g, '"').replace(/"/g, '\\"');
}

function escapeBackslashes(rawStringValue) {
return rawStringValue.replace(/\\/g, '\\\\');
}

function needToEscapeCharacterForJSX(raw, node) {
return (
containsBackslash(raw)
|| containsHTMLEntity(raw)
|| (node.parent.type !== 'JSXAttribute' && containsDisallowedJSXTextChars(raw))
);
}

function containsWhitespaceExpression(child) {
if (child.type === 'JSXExpressionContainer') {
const value = child.expression.value;
return value ? jsxUtil.isWhiteSpaces(value) : false;
}
return false;
}

function isLineBreak(text) {
return containsLineTerminators(text) && text.trim() === '';
}

function wrapNonHTMLEntities(text) {
const HTML_ENTITY = '<HTML_ENTITY>';
const withCurlyBraces = text.split(HTML_ENTITY_REGEX()).map((word) => (
word === '' ? '' : `{${JSON.stringify(word)}}`
)).join(HTML_ENTITY);

const htmlEntities = text.match(HTML_ENTITY_REGEX());
return htmlEntities.reduce((acc, htmlEntity) => (
acc.replace(HTML_ENTITY, htmlEntity)
), withCurlyBraces);
}

function wrapWithCurlyBraces(rawText) {
if (!containsLineTerminators(rawText)) {
return `{${JSON.stringify(rawText)}}`;
}

return rawText.split('\n').map((line) => {
if (line.trim() === '') {
return line;
}
const firstCharIndex = line.search(/[^\s]/);
const leftWhitespace = line.slice(0, firstCharIndex);
const text = line.slice(firstCharIndex);

if (containsHTMLEntity(line)) {
return `${leftWhitespace}${wrapNonHTMLEntities(text)}`;
}
return `${leftWhitespace}{${JSON.stringify(text)}}`;
}).join('\n');
}

function isWhiteSpaceLiteral(node) {
return node.type && node.type === 'Literal' && node.value && jsxUtil.isWhiteSpaces(node.value);
}

function isStringWithTrailingWhiteSpaces(value) {
return /^\s|\s$/.test(value);
}

function isLiteralWithTrailingWhiteSpaces(node) {
return node.type && node.type === 'Literal' && node.value && isStringWithTrailingWhiteSpaces(node.value);
}

// ------------------------------------------------------------------------------
// Rule Definition
// ------------------------------------------------------------------------------
Expand Down Expand Up @@ -74,100 +176,11 @@ module.exports = {
},

create(context) {
const HTML_ENTITY_REGEX = () => /&[A-Za-z\d#]+;/g;
const ruleOptions = context.options[0];
const userConfig = typeof ruleOptions === 'string'
? { props: ruleOptions, children: ruleOptions, propElementValues: OPTION_IGNORE }
: Object.assign({}, DEFAULT_CONFIG, ruleOptions);

function containsLineTerminators(rawStringValue) {
return /[\n\r\u2028\u2029]/.test(rawStringValue);
}

function containsBackslash(rawStringValue) {
return arrayIncludes(rawStringValue, '\\');
}

function containsHTMLEntity(rawStringValue) {
return HTML_ENTITY_REGEX().test(rawStringValue);
}

function containsOnlyHtmlEntities(rawStringValue) {
return rawStringValue.replace(HTML_ENTITY_REGEX(), '').trim() === '';
}

function containsDisallowedJSXTextChars(rawStringValue) {
return /[{<>}]/.test(rawStringValue);
}

function containsQuoteCharacters(value) {
return /['"]/.test(value);
}

function containsMultilineComment(value) {
return /\/\*/.test(value);
}

function escapeDoubleQuotes(rawStringValue) {
return rawStringValue.replace(/\\"/g, '"').replace(/"/g, '\\"');
}

function escapeBackslashes(rawStringValue) {
return rawStringValue.replace(/\\/g, '\\\\');
}

function needToEscapeCharacterForJSX(raw, node) {
return (
containsBackslash(raw)
|| containsHTMLEntity(raw)
|| (node.parent.type !== 'JSXAttribute' && containsDisallowedJSXTextChars(raw))
);
}

function containsWhitespaceExpression(child) {
if (child.type === 'JSXExpressionContainer') {
const value = child.expression.value;
return value ? jsxUtil.isWhiteSpaces(value) : false;
}
return false;
}

function isLineBreak(text) {
return containsLineTerminators(text) && text.trim() === '';
}

function wrapNonHTMLEntities(text) {
const HTML_ENTITY = '<HTML_ENTITY>';
const withCurlyBraces = text.split(HTML_ENTITY_REGEX()).map((word) => (
word === '' ? '' : `{${JSON.stringify(word)}}`
)).join(HTML_ENTITY);

const htmlEntities = text.match(HTML_ENTITY_REGEX());
return htmlEntities.reduce((acc, htmlEntity) => (
acc.replace(HTML_ENTITY, htmlEntity)
), withCurlyBraces);
}

function wrapWithCurlyBraces(rawText) {
if (!containsLineTerminators(rawText)) {
return `{${JSON.stringify(rawText)}}`;
}

return rawText.split('\n').map((line) => {
if (line.trim() === '') {
return line;
}
const firstCharIndex = line.search(/[^\s]/);
const leftWhitespace = line.slice(0, firstCharIndex);
const text = line.slice(firstCharIndex);

if (containsHTMLEntity(line)) {
return `${leftWhitespace}${wrapNonHTMLEntities(text)}`;
}
return `${leftWhitespace}{${JSON.stringify(text)}}`;
}).join('\n');
}

/**
* Report and fix an unnecessary curly brace violation on a node
* @param {ASTNode} JSXExpressionNode - The AST node with an unnecessary JSX expression
Expand Down Expand Up @@ -233,18 +246,6 @@ module.exports = {
});
}

function isWhiteSpaceLiteral(node) {
return node.type && node.type === 'Literal' && node.value && jsxUtil.isWhiteSpaces(node.value);
}

function isStringWithTrailingWhiteSpaces(value) {
return /^\s|\s$/.test(value);
}

function isLiteralWithTrailingWhiteSpaces(node) {
return node.type && node.type === 'Literal' && node.value && isStringWithTrailingWhiteSpaces(node.value);
}

// Bail out if there is any character that needs to be escaped in JSX
// because escaping decreases readability and the original code may be more
// readable anyway or intentional for other specific reasons
Expand Down
18 changes: 9 additions & 9 deletions lib/rules/no-unused-prop-types.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,15 @@ const Components = require('../util/Components');
const docsUrl = require('../util/docsUrl');
const report = require('../util/report');

/**
* Checks if the component must be validated
* @param {Object} component The component to process
* @returns {boolean} True if the component must be validated, false if not.
*/
function mustBeValidated(component) {
return !!component && !component.ignoreUnusedPropTypesValidation;
}

// ------------------------------------------------------------------------------
// Rule Definition
// ------------------------------------------------------------------------------
Expand Down Expand Up @@ -71,15 +80,6 @@ module.exports = {
return configuration.ignore.indexOf(name) !== -1;
}

/**
* Checks if the component must be validated
* @param {Object} component The component to process
* @returns {boolean} True if the component must be validated, false if not.
*/
function mustBeValidated(component) {
return !!component && !component.ignoreUnusedPropTypesValidation;
}

/**
* Checks if a prop is used
* @param {ASTNode} node The AST node being checked.
Expand Down
50 changes: 25 additions & 25 deletions lib/rules/self-closing-comp.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,35 @@ const docsUrl = require('../util/docsUrl');
const jsxUtil = require('../util/jsx');
const report = require('../util/report');

const optionDefaults = { component: true, html: true };

function isComponent(node) {
return (
node.name
&& (node.name.type === 'JSXIdentifier' || node.name.type === 'JSXMemberExpression')
&& !jsxUtil.isDOMComponent(node)
);
}

function childrenIsEmpty(node) {
return node.parent.children.length === 0;
}

function childrenIsMultilineSpaces(node) {
const childrens = node.parent.children;

return (
childrens.length === 1
&& (childrens[0].type === 'Literal' || childrens[0].type === 'JSXText')
&& childrens[0].value.indexOf('\n') !== -1
&& childrens[0].value.replace(/(?!\xA0)\s/g, '') === ''
);
}

// ------------------------------------------------------------------------------
// Rule Definition
// ------------------------------------------------------------------------------

const optionDefaults = { component: true, html: true };

const messages = {
notSelfClosing: 'Empty components are self-closing',
};
Expand Down Expand Up @@ -49,29 +72,6 @@ module.exports = {
},

create(context) {
function isComponent(node) {
return (
node.name
&& (node.name.type === 'JSXIdentifier' || node.name.type === 'JSXMemberExpression')
&& !jsxUtil.isDOMComponent(node)
);
}

function childrenIsEmpty(node) {
return node.parent.children.length === 0;
}

function childrenIsMultilineSpaces(node) {
const childrens = node.parent.children;

return (
childrens.length === 1
&& (childrens[0].type === 'Literal' || childrens[0].type === 'JSXText')
&& childrens[0].value.indexOf('\n') !== -1
&& childrens[0].value.replace(/(?!\xA0)\s/g, '') === ''
);
}

function isShouldBeSelfClosed(node) {
const configuration = Object.assign({}, optionDefaults, context.options[0]);
return (
Expand Down

0 comments on commit 8dc0215

Please sign in to comment.