123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899 |
- /**
- * @fileoverview Require or prevent a new line after jsx elements and expressions.
- * @author Johnny Zabala
- * @author Joseph Stiles
- */
- 'use strict';
- const docsUrl = require('../util/docsUrl');
- // ------------------------------------------------------------------------------
- // Rule Definition
- // ------------------------------------------------------------------------------
- module.exports = {
- meta: {
- docs: {
- description: 'Require or prevent a new line after jsx elements and expressions.',
- category: 'Stylistic Issues',
- recommended: false,
- url: docsUrl('jsx-newline')
- },
- fixable: 'code',
- messages: {
- require: 'JSX element should start in a new line',
- prevent: 'JSX element should not start in a new line'
- },
- schema: [
- {
- type: 'object',
- properties: {
- prevent: {
- default: false,
- type: 'boolean'
- }
- },
- additionalProperties: false
- }
- ]
- },
- create(context) {
- const jsxElementParents = new Set();
- const sourceCode = context.getSourceCode();
- return {
- 'Program:exit'() {
- jsxElementParents.forEach((parent) => {
- parent.children.forEach((element, index, elements) => {
- if (element.type === 'JSXElement' || element.type === 'JSXExpressionContainer') {
- const firstAdjacentSibling = elements[index + 1];
- const secondAdjacentSibling = elements[index + 2];
- const hasSibling = firstAdjacentSibling
- && secondAdjacentSibling
- && (firstAdjacentSibling.type === 'Literal' || firstAdjacentSibling.type === 'JSXText');
- if (!hasSibling) return;
- // Check adjacent sibling has the proper amount of newlines
- const isWithoutNewLine = !/\n\s*\n/.test(firstAdjacentSibling.value);
- const prevent = !!(context.options[0] || {}).prevent;
- if (isWithoutNewLine === prevent) return;
- const messageId = prevent
- ? 'prevent'
- : 'require';
- const regex = prevent
- ? /(\n\n)(?!.*\1)/g
- : /(\n)(?!.*\1)/g;
- const replacement = prevent
- ? '\n'
- : '\n\n';
- context.report({
- node: secondAdjacentSibling,
- messageId,
- fix(fixer) {
- return fixer.replaceText(
- firstAdjacentSibling,
- // double or remove the last newline
- sourceCode.getText(firstAdjacentSibling)
- .replace(regex, replacement)
- );
- }
- });
- }
- });
- });
- },
- ':matches(JSXElement, JSXFragment) > :matches(JSXElement, JSXExpressionContainer)': (node) => {
- jsxElementParents.add(node.parent);
- }
- };
- }
- };
|