123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109 |
- /**
- * @fileoverview Detects raw text outside of Text component
- * @author Alex Zhukov
- */
- 'use strict';
- const { default: traverse } = require('@babel/traverse');
- const elementName = (node, scope) => {
- const identifiers = [];
- traverse(node, {
- JSXOpeningElement({ node: element }) {
- traverse(element, {
- JSXIdentifier({ node: identifier }) {
- if (identifier.parent.type === 'JSXOpeningElement'
- || identifier.parent.type === 'JSXMemberExpression') {
- identifiers.push(identifier.name);
- }
- },
- }, scope);
- },
- }, scope);
- return identifiers.join('.');
- };
- function create(context) {
- const options = context.options[0] || {};
- const report = (node) => {
- const errorValue = node.type === 'TemplateLiteral'
- ? `TemplateLiteral: ${node.expressions[0].name}`
- : node.value.trim();
- const formattedErrorValue = errorValue.length > 0
- ? `Raw text (${errorValue})`
- : 'Whitespace(s)';
- context.report({
- node,
- message: `${formattedErrorValue} cannot be used outside of a <Text> tag`,
- });
- };
- const skippedElements = options.skip ? options.skip : [];
- const allowedElements = ['Text', 'TSpan', 'StyledText', 'Animated.Text'].concat(skippedElements);
- const hasOnlyLineBreak = (value) => /^[\r\n\t\f\v]+$/.test(value.replace(/ /g, ''));
- const scope = context.getScope();
- const getValidation = (node) => !allowedElements.includes(elementName(node.parent, scope));
- return {
- Literal(node) {
- const parentType = node.parent.type;
- const onlyFor = ['JSXExpressionContainer', 'JSXElement'];
- if (typeof node.value !== 'string'
- || hasOnlyLineBreak(node.value)
- || !onlyFor.includes(parentType)
- || (node.parent.parent && node.parent.parent.type === 'JSXAttribute')
- ) return;
- const isStringLiteral = parentType === 'JSXExpressionContainer';
- if (getValidation(isStringLiteral ? node.parent : node)) {
- report(node);
- }
- },
- JSXText(node) {
- if (typeof node.value !== 'string' || hasOnlyLineBreak(node.value)) return;
- if (getValidation(node)) {
- report(node);
- }
- },
- TemplateLiteral(node) {
- if (
- node.parent.type !== 'JSXExpressionContainer'
- || (node.parent.parent && node.parent.parent.type === 'JSXAttribute')
- ) return;
- if (getValidation(node.parent)) {
- report(node);
- }
- },
- };
- }
- module.exports = {
- meta: {
- schema: [
- {
- type: 'object',
- properties: {
- skip: {
- type: 'array',
- items: {
- type: 'string',
- },
- },
- },
- additionalProperties: false,
- },
- ],
- },
- create,
- };
|