123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122 |
- /**
- * @fileoverview Prevent adjacent inline elements not separated by whitespace.
- * @author Sean Hayes
- */
- 'use strict';
- const docsUrl = require('../util/docsUrl');
- // ------------------------------------------------------------------------------
- // Helpers
- // ------------------------------------------------------------------------------
- // https://developer.mozilla.org/en-US/docs/Web/HTML/Inline_elements
- const inlineNames = [
- 'a',
- 'b',
- 'big',
- 'i',
- 'small',
- 'tt',
- 'abbr',
- 'acronym',
- 'cite',
- 'code',
- 'dfn',
- 'em',
- 'kbd',
- 'strong',
- 'samp',
- 'time',
- 'var',
- 'bdo',
- 'br',
- 'img',
- 'map',
- 'object',
- 'q',
- 'script',
- 'span',
- 'sub',
- 'sup',
- 'button',
- 'input',
- 'label',
- 'select',
- 'textarea'
- ];
- // Note: raw will be transformed into \u00a0.
- const whitespaceRegex = /(?:^\s|\s$)/;
- function isInline(node) {
- if (node.type === 'Literal') {
- // Regular whitespace will be removed.
- const value = node.value;
- // To properly separate inline elements, each end of the literal will need
- // whitespace.
- return !whitespaceRegex.test(value);
- }
- if (node.type === 'JSXElement' && inlineNames.indexOf(node.openingElement.name.name) > -1) {
- return true;
- }
- if (node.type === 'CallExpression' && inlineNames.indexOf(node.arguments[0].value) > -1) {
- return true;
- }
- return false;
- }
- // ------------------------------------------------------------------------------
- // Rule Definition
- // ------------------------------------------------------------------------------
- module.exports = {
- meta: {
- docs: {
- description: 'Prevent adjacent inline elements not separated by whitespace.',
- category: 'Best Practices',
- recommended: false,
- url: docsUrl('no-adjacent-inline-elements')
- },
- schema: [],
- messages: {
- inlineElement: 'Child elements which render as inline HTML elements should be separated by a space or wrapped in block level elements.'
- }
- },
- create(context) {
- function validate(node, children) {
- let currentIsInline = false;
- let previousIsInline = false;
- if (!children) {
- return;
- }
- for (let i = 0; i < children.length; i++) {
- currentIsInline = isInline(children[i]);
- if (previousIsInline && currentIsInline) {
- context.report({
- node,
- messageId: 'inlineElement'
- });
- return;
- }
- previousIsInline = currentIsInline;
- }
- }
- return {
- JSXElement(node) {
- validate(node, node.children);
- },
- CallExpression(node) {
- if (!node.callee || node.callee.type !== 'MemberExpression' || node.callee.property.name !== 'createElement') {
- return;
- }
- if (node.arguments.length < 2 || !node.arguments[2]) {
- return;
- }
- const children = node.arguments[2].elements;
- validate(node, children);
- }
- };
- }
- };
|