prettier-eslint-cli version: 5.0.0
prettier version: 2.0.5
eslint version: 7.0.0
Relevant code/config.
import isEmpty from 'lodash.isempty';
import map from 'lodash.map';
import Link from 'next/link';
import React, { ReactNode } from 'react';
import useI18n, { I18n } from '../../hooks/useI18n';
import { I18nRoute, resolveI18nRoute } from '../../utils/app/router';
type Props = {
as?: string;
children: ReactNode;
href: string;
locale?: string; // The locale can be specified, but it'll fallback to the current locale if unspecified
params?: { [key: string]: string | number };
passHref?: boolean;
prefetch?: boolean;
replace?: boolean;
scroll?: boolean;
shallow?: boolean;
wrapChildrenAsLink?: boolean; // Helper to avoid writing redundant code
}
/**
* Wrapper around the native Next.js <Link> component. Handles localised links.
*
* Use the current active locale by default
*
* @example Recommended usage
* <I18nLink href={`/`}>Homepage</I18nLink>
*
* @example When specifying the locale to use (overrides default)
* <I18nLink href={`/`} locale={'fr-FR'}>Homepage in "fr-FR" locale</I18nLink>
*
* @example The recommended usage is equivalent to this (wrapChildrenAsLink is true, by default)
* <I18nLink href={`/`} wrapChildrenAsLink={false}><a>Homepage</a></I18nLink>
*
* @example When using children that use a <a> tag, you must set wrapChildrenAsLink to false to avoid using a link within a link
* <I18nLink
* href={`/`}
* wrapChildrenAsLink={false}
* >
* <NavLink>Homepage</NavLink>
* </I18nLink>
*
* @example When using route params (other than "locale")
* <I18nLink
* href={'/products/[id]'}
* params={{
* id: 5,
* }}
* >
* Go to product 5
* </I18nLink>
*
* @param props
*/
const I18nLink: React.FunctionComponent<Props> = (props): JSX.Element => {
const { locale: currentLocale }: I18n = useI18n();
const {
as,
children,
href,
locale = currentLocale,
params,
passHref = true,
wrapChildrenAsLink = true,
...rest // Should only contain valid next/Link props
} = props;
let {
i18nHref, // eslint-disable-line prefer-const
i18nAs,
}: I18nRoute = resolveI18nRoute({ as, href, locale });
if (!isEmpty(params)) {
// If any params are provided, replace their name by the provided value
map(params, (value: string, key: string | number) => {
i18nAs = i18nAs.replace(`[${key}]`, value);
});
}
return (
<Link
href={i18nHref}
as={i18nAs}
{...rest}
passHref={passHref}
>
{
wrapChildrenAsLink ? (
// eslint-disable-next-line jsx-a11y/anchor-is-valid
<a>{children}</a>
) : React.cloneElement(children as React.ReactElement)
}
</Link>
);
};
export default I18nLink;
Running the following:
prettier-eslint --write "$PWD/src/components/i18n/I18nLink.{js,jsx,ts,tsx}" --eslint-config-path .eslintrc.yml --trailing-comma es5 --bracket-spacing
I get a result shown in this diff

How can I force prettier-eslint-cli to:
- Keep properties in
<Link always multiline
- Have react
{} always multiline
The end result should look like this:
return (
<Link
href={i18nHref}
as={i18nAs}
{...rest}
passHref={passHref}
>
{
wrapChildrenAsLink ? (
// eslint-disable-next-line jsx-a11y/anchor-is-valid
<a>{children}</a>
) : (
React.cloneElement(children as React.ReactElement)
)
}
</Link>
);
Details
.eslintrc
---
# XXX Must read to understand how prettier/eslint work together - https://blog.theodo.com/2019/08/empower-your-dev-environment-with-eslint-prettier-and-editorconfig-with-no-conflicts/
# XXX EditorConfig provides everyone with the same editor configuration (prettier inherits from it) - All configuration related to the editor (end of line, indent style, indent size...) should be handled by EditorConfig
# XXX No "code formatting" should be done by ESLint - Everything related to code formatting should be handled by Prettier
# XXX EsLint handles our code quality only - The rest (code quality) should be handled by ESLint
env:
browser: true
commonjs: true
es6: true
node: true
extends:
- airbnb-typescript-prettier # https://github.com/toshi-toma/eslint-config-airbnb-typescript-prettier#readme
plugins:
- jest
parserOptions:
project: ./tsconfig.json
globals:
Atomics: readonly
SharedArrayBuffer: readonly
settings:
react:
version: detect
rules: # See https://eslint.org/docs/rules
# Managed by prettier
# semi
# quotes
# indent
# max-len
comma-spacing:
- error
- before: false
after: true
arrow-parens:
- error
- always
strict: 'off'
no-console: 1 # Shouldn't use "console", but "logger" instead
allowArrowFunctions: 0
no-unused-vars: 0 # Disabled, already handled by @typescript-eslint/no-unused-vars
import/prefer-default-export: 0 # When there is only a single export from a module, don't enforce a default export, but rather let developer choose what's best
no-else-return: 0 # Don't enforce, let developer choose. Sometimes we like to specifically use "return" for the sake of comprehensibility and avoid ambiguity
no-underscore-dangle: 0 # Allow _ before/after variables and functions, convention for something meant to be "private"
arrow-body-style: 0 # Don't enforce, let developer choose. Sometimes we like to specifically use "return" for ease of debugging and printing
quote-props:
- warn
- consistent-as-needed # Enforce consistency with quotes on props, either all must be quoted, or all unquoted for a given object
no-return-await: 0 # Useful before, but recent node.js enhancements make it useless on node 12+ (we use 10, but still, for consistency) - Read https://stackoverflow.com/questions/44806135/why-no-return-await-vs-const-x-await
no-extra-boolean-cast: 0 # Don't enforce, let developer choose. Using "!!!" is sometimes useful (edge cases), and has a semantic value (dev intention)
array-element-newline: # https://eslint.org/docs/rules/array-element-newline
- error
- consistent
object-curly-newline:
- warn
- ObjectExpression:
multiline: true
minProperties: 5
consistent: true
ObjectPattern:
multiline: true
minProperties: 5
consistent: true
ImportDeclaration:
multiline: true
minProperties: 8 # Doesn't play so well with webstorm, which wraps based on the number of chars in the row, not based on the number of props #sucks
consistent: true
ExportDeclaration:
multiline: true
minProperties: 5
consistent: true
react-hooks/rules-of-hooks: error
react-hooks/exhaustive-deps: warn
react/jsx-no-target-blank: warn # Not using "noreferrer" is not a security risk, but "noopener" should always be used indeed
react/prop-types: warn # Should be handled with TS instead
react/no-unescaped-entities: 0 # Causes text mismatch when enabled
jsx-a11y/anchor-is-valid: warn
linebreak-style:
- error
- unix
'@typescript-eslint/ban-ts-ignore': warn # ts-ignore are sometimes the only way to bypass a TS issue, we trust we will use them for good and not abuse them
'@typescript-eslint/no-use-before-define': warn
'@typescript-eslint/no-unused-vars':
- warn
-
vars: 'all' # We don't want unused variables (noise) - XXX Note that this will be a duplicate of "no-unused-vars" rule
args: 'none' # Sometimes it's useful to have unused arguments for later use, such as describing what args are available (DX)
ignoreRestSiblings: true # Sometimes it's useful to have unused props for later use, such as describing what props are available (DX)
overrides:
- files: ['**/*.tsx']
rules:
'react/prop-types': 'off'
prettier-eslint-cliversion: 5.0.0prettierversion: 2.0.5eslintversion: 7.0.0Relevant code/config.
Running the following:
prettier-eslint --write "$PWD/src/components/i18n/I18nLink.{js,jsx,ts,tsx}" --eslint-config-path .eslintrc.yml --trailing-comma es5 --bracket-spacingI get a result shown in this diff
How can I force prettier-eslint-cli to:
<Linkalways multiline{}always multilineThe end result should look like this:
Details
.eslintrc