mirror of
https://github.com/vuejs/babel-plugin-jsx.git
synced 2025-01-10 08:19:10 +08:00
chore: use airbnb-typescript/base eslint plugin (#420)
This commit is contained in:
parent
4cb4d7fcdf
commit
a7121f8553
@ -24,5 +24,7 @@ jobs:
|
||||
- ~/.cache/yarn
|
||||
key: v2-dependencies-{{ checksum "yarn.lock" }}
|
||||
|
||||
- run: yarn lint
|
||||
|
||||
# run tests!
|
||||
- run: yarn test
|
||||
|
17
.eslintrc.js
17
.eslintrc.js
@ -5,6 +5,7 @@ module.exports = {
|
||||
ecmaFeatures: {
|
||||
jsx: true,
|
||||
},
|
||||
project: './tsconfig.json',
|
||||
},
|
||||
env: {
|
||||
browser: true,
|
||||
@ -15,8 +16,7 @@ module.exports = {
|
||||
parser: '@typescript-eslint/parser',
|
||||
plugins: ['@typescript-eslint', 'import'],
|
||||
extends: [
|
||||
'eslint-config-airbnb-base',
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
'airbnb-typescript/base',
|
||||
],
|
||||
rules: {
|
||||
'no-nested-ternary': [0],
|
||||
@ -27,19 +27,8 @@ module.exports = {
|
||||
'import/no-extraneous-dependencies': [0],
|
||||
'consistent-return': [0],
|
||||
'no-bitwise': [0],
|
||||
'@typescript-eslint/no-use-before-define': [0],
|
||||
'prefer-destructuring': [2, { array: false }],
|
||||
'import/extensions': [0],
|
||||
'@typescript-eslint/ban-ts-comment': [0],
|
||||
'@typescript-eslint/explicit-module-boundary-types': [0],
|
||||
'@typescript-eslint/no-explicit-any': [0],
|
||||
'@typescript-eslint/no-non-null-assertion': [0],
|
||||
'max-len': [0],
|
||||
},
|
||||
settings: {
|
||||
'import/resolver': {
|
||||
node: {
|
||||
extensions: ['.js', '.jsx', '.ts', '.tsx'],
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
@ -16,9 +16,10 @@
|
||||
"jsx"
|
||||
],
|
||||
"devDependencies": {
|
||||
"@typescript-eslint/eslint-plugin": "^4.4.1",
|
||||
"eslint": "^7.7.0",
|
||||
"eslint-config-airbnb-base": "^14.1.0",
|
||||
"eslint-plugin-import": "^2.20.2",
|
||||
"eslint-config-airbnb-typescript": "^12.3.1",
|
||||
"eslint-plugin-import": "^2.22.1",
|
||||
"lerna": "^3.19.0"
|
||||
}
|
||||
}
|
||||
|
@ -1,382 +0,0 @@
|
||||
import * as t from '@babel/types';
|
||||
import { NodePath } from '@babel/traverse';
|
||||
import { addDefault } from '@babel/helper-module-imports';
|
||||
import {
|
||||
createIdentifier,
|
||||
isDirective,
|
||||
checkIsComponent,
|
||||
getTag,
|
||||
getJSXAttributeName,
|
||||
walksScope,
|
||||
transformJSXExpressionContainer,
|
||||
} from './utils';
|
||||
import parseDirectives from './parseDirectives';
|
||||
import { PatchFlags } from './patchFlags';
|
||||
import { State } from '.';
|
||||
import { transformJSXElement } from './transform-vue-jsx';
|
||||
import SlotFlags from './slotFlags';
|
||||
|
||||
const xlinkRE = /^xlink([A-Z])/;
|
||||
const onRE = /^on[^a-z]/;
|
||||
|
||||
const isOn = (key: string) => onRE.test(key);
|
||||
|
||||
export type Slots = t.Identifier | t.ObjectExpression | null;
|
||||
|
||||
const getJSXAttributeValue = (
|
||||
path: NodePath<t.JSXAttribute>,
|
||||
state: State,
|
||||
): (
|
||||
t.StringLiteral | t.Expression | null
|
||||
) => {
|
||||
const valuePath = path.get('value');
|
||||
if (valuePath.isJSXElement()) {
|
||||
return transformJSXElement(valuePath, state);
|
||||
}
|
||||
if (valuePath.isStringLiteral()) {
|
||||
return valuePath.node;
|
||||
}
|
||||
if (valuePath.isJSXExpressionContainer()) {
|
||||
return transformJSXExpressionContainer(valuePath);
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
const transformJSXSpreadAttribute = (
|
||||
nodePath: NodePath,
|
||||
path: NodePath<t.JSXSpreadAttribute>,
|
||||
mergeProps: boolean,
|
||||
args: (t.ObjectProperty | t.Expression | t.SpreadElement)[],
|
||||
) => {
|
||||
const argument = path.get('argument') as NodePath<t.ObjectExpression | t.Identifier>;
|
||||
const properties = t.isObjectExpression(argument.node) ? argument.node.properties : undefined;
|
||||
if (!properties) {
|
||||
if (argument.isIdentifier()) {
|
||||
walksScope(nodePath, (argument.node as t.Identifier).name, SlotFlags.DYNAMIC);
|
||||
}
|
||||
args.push(mergeProps ? argument.node : t.spreadElement(argument.node));
|
||||
} else if (mergeProps) {
|
||||
args.push(t.objectExpression(properties));
|
||||
} else {
|
||||
args.push(...(properties as t.ObjectProperty[]));
|
||||
}
|
||||
};
|
||||
|
||||
const mergeAsArray = (existing: t.ObjectProperty, incoming: t.ObjectProperty) => {
|
||||
if (t.isArrayExpression(existing.value)) {
|
||||
existing.value.elements.push(incoming.value as t.Expression);
|
||||
} else {
|
||||
existing.value = t.arrayExpression([
|
||||
existing.value as t.Expression,
|
||||
incoming.value as t.Expression,
|
||||
]);
|
||||
}
|
||||
};
|
||||
|
||||
const dedupeProperties = (properties: t.ObjectProperty[] = [], mergeProps?: boolean) => {
|
||||
if (!mergeProps) {
|
||||
return properties;
|
||||
}
|
||||
const knownProps = new Map<string, t.ObjectProperty>();
|
||||
const deduped: t.ObjectProperty[] = [];
|
||||
properties.forEach((prop) => {
|
||||
if (t.isStringLiteral(prop.key)) {
|
||||
const { value: name } = prop.key;
|
||||
const existing = knownProps.get(name);
|
||||
if (existing) {
|
||||
if (name === 'style' || name === 'class' || name.startsWith('on')) {
|
||||
mergeAsArray(existing, prop);
|
||||
}
|
||||
} else {
|
||||
knownProps.set(name, prop);
|
||||
deduped.push(prop);
|
||||
}
|
||||
} else {
|
||||
// v-model target with variable
|
||||
deduped.push(prop);
|
||||
}
|
||||
});
|
||||
|
||||
return deduped;
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if an attribute value is constant
|
||||
* @param node
|
||||
* @returns boolean
|
||||
*/
|
||||
const isConstant = (
|
||||
node: t.Expression | t.Identifier | t.Literal | t.SpreadElement | null,
|
||||
): boolean => {
|
||||
if (t.isIdentifier(node)) {
|
||||
return node.name === 'undefined';
|
||||
}
|
||||
if (t.isArrayExpression(node)) {
|
||||
const { elements } = node;
|
||||
return elements.every((element) => element && isConstant(element));
|
||||
}
|
||||
if (t.isObjectExpression(node)) {
|
||||
return node.properties.every((property) => isConstant((property as any).value));
|
||||
}
|
||||
if (t.isLiteral(node)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
const buildProps = (path: NodePath<t.JSXElement>, state: State) => {
|
||||
const tag = getTag(path, state);
|
||||
const isComponent = checkIsComponent(path.get('openingElement'));
|
||||
const props = path.get('openingElement').get('attributes');
|
||||
const directives: t.ArrayExpression[] = [];
|
||||
const dynamicPropNames = new Set<string>();
|
||||
|
||||
let slots: Slots = null;
|
||||
let patchFlag = 0;
|
||||
|
||||
if (props.length === 0) {
|
||||
return {
|
||||
tag,
|
||||
isComponent,
|
||||
slots,
|
||||
props: t.nullLiteral(),
|
||||
directives,
|
||||
patchFlag,
|
||||
dynamicPropNames,
|
||||
};
|
||||
}
|
||||
|
||||
let properties: t.ObjectProperty[] = [];
|
||||
|
||||
// patchFlag analysis
|
||||
let hasRef = false;
|
||||
let hasClassBinding = false;
|
||||
let hasStyleBinding = false;
|
||||
let hasHydrationEventBinding = false;
|
||||
let hasDynamicKeys = false;
|
||||
|
||||
const mergeArgs: (t.CallExpression | t.ObjectExpression | t.Identifier)[] = [];
|
||||
const { mergeProps = true } = state.opts;
|
||||
props
|
||||
.forEach((prop) => {
|
||||
if (prop.isJSXAttribute()) {
|
||||
let name = getJSXAttributeName(prop);
|
||||
|
||||
const attributeValue = getJSXAttributeValue(prop, state);
|
||||
|
||||
if (!isConstant(attributeValue) || name === 'ref') {
|
||||
if (
|
||||
!isComponent
|
||||
&& isOn(name)
|
||||
// omit the flag for click handlers becaues hydration gives click
|
||||
// dedicated fast path.
|
||||
&& name.toLowerCase() !== 'onclick'
|
||||
// omit v-model handlers
|
||||
&& name !== 'onUpdate:modelValue'
|
||||
) {
|
||||
hasHydrationEventBinding = true;
|
||||
}
|
||||
|
||||
if (name === 'ref') {
|
||||
hasRef = true;
|
||||
} else if (name === 'class' && !isComponent) {
|
||||
hasClassBinding = true;
|
||||
} else if (name === 'style' && !isComponent) {
|
||||
hasStyleBinding = true;
|
||||
} else if (
|
||||
name !== 'key'
|
||||
&& !isDirective(name)
|
||||
&& name !== 'on'
|
||||
) {
|
||||
dynamicPropNames.add(name);
|
||||
}
|
||||
}
|
||||
if (state.opts.transformOn && (name === 'on' || name === 'nativeOn')) {
|
||||
if (!state.get('transformOn')) {
|
||||
state.set('transformOn', addDefault(
|
||||
path,
|
||||
'@vue/babel-helper-vue-transform-on',
|
||||
{ nameHint: '_transformOn' },
|
||||
));
|
||||
}
|
||||
mergeArgs.push(t.callExpression(
|
||||
state.get('transformOn'),
|
||||
[attributeValue || t.booleanLiteral(true)],
|
||||
));
|
||||
return;
|
||||
}
|
||||
if (isDirective(name)) {
|
||||
const {
|
||||
directive, modifiers, values, args, directiveName,
|
||||
} = parseDirectives({
|
||||
tag,
|
||||
isComponent,
|
||||
name,
|
||||
path: prop,
|
||||
state,
|
||||
value: attributeValue,
|
||||
});
|
||||
|
||||
if (directiveName === 'slots') {
|
||||
slots = attributeValue as Slots;
|
||||
return;
|
||||
}
|
||||
if (directive) {
|
||||
directives.push(t.arrayExpression(directive));
|
||||
} else if (directiveName === 'html') {
|
||||
properties.push(t.objectProperty(
|
||||
t.stringLiteral('innerHTML'),
|
||||
values[0] as any,
|
||||
));
|
||||
dynamicPropNames.add('innerHTML');
|
||||
} else if (directiveName === 'text') {
|
||||
properties.push(t.objectProperty(
|
||||
t.stringLiteral('textContent'),
|
||||
values[0] as any,
|
||||
));
|
||||
dynamicPropNames.add('textContent');
|
||||
}
|
||||
|
||||
if (['models', 'model'].includes(directiveName)) {
|
||||
values.forEach((value, index) => {
|
||||
const propName = args[index];
|
||||
// v-model target with variable
|
||||
const isDynamic = propName && !t.isStringLiteral(propName) && !t.isNullLiteral(propName);
|
||||
|
||||
// must be v-model or v-models and is a component
|
||||
if (!directive) {
|
||||
properties.push(
|
||||
t.objectProperty(t.isNullLiteral(propName)
|
||||
? t.stringLiteral('modelValue') : propName, value as any, isDynamic),
|
||||
);
|
||||
if (!isDynamic) {
|
||||
dynamicPropNames.add((propName as t.StringLiteral)?.value || 'modelValue');
|
||||
}
|
||||
|
||||
if (modifiers[index]?.size) {
|
||||
properties.push(
|
||||
t.objectProperty(
|
||||
isDynamic
|
||||
? t.binaryExpression('+', propName, t.stringLiteral('Modifiers'))
|
||||
: t.stringLiteral(`${(propName as t.StringLiteral)?.value || 'model'}Modifiers`),
|
||||
t.objectExpression(
|
||||
[...modifiers[index]].map((modifier) => t.objectProperty(
|
||||
t.stringLiteral(modifier),
|
||||
t.booleanLiteral(true),
|
||||
)),
|
||||
),
|
||||
isDynamic,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const updateName = isDynamic
|
||||
? t.binaryExpression('+', t.stringLiteral('onUpdate'), propName)
|
||||
: t.stringLiteral(`onUpdate:${(propName as t.StringLiteral)?.value || 'modelValue'}`);
|
||||
|
||||
properties.push(
|
||||
t.objectProperty(
|
||||
updateName,
|
||||
t.arrowFunctionExpression(
|
||||
[t.identifier('$event')],
|
||||
t.assignmentExpression('=', value as any, t.identifier('$event')),
|
||||
),
|
||||
isDynamic,
|
||||
),
|
||||
);
|
||||
|
||||
if (!isDynamic) {
|
||||
dynamicPropNames.add((updateName as t.StringLiteral).value);
|
||||
} else {
|
||||
hasDynamicKeys = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
if (name.match(xlinkRE)) {
|
||||
name = name.replace(xlinkRE, (_, firstCharacter) => `xlink:${firstCharacter.toLowerCase()}`);
|
||||
}
|
||||
properties.push(t.objectProperty(
|
||||
t.stringLiteral(name),
|
||||
attributeValue || t.booleanLiteral(true),
|
||||
));
|
||||
}
|
||||
} else {
|
||||
if (properties.length && mergeProps) {
|
||||
mergeArgs.push(t.objectExpression(dedupeProperties(properties, mergeProps)));
|
||||
properties = [];
|
||||
}
|
||||
|
||||
// JSXSpreadAttribute
|
||||
hasDynamicKeys = true;
|
||||
transformJSXSpreadAttribute(
|
||||
path as NodePath,
|
||||
prop as NodePath<t.JSXSpreadAttribute>,
|
||||
mergeProps,
|
||||
mergeProps ? mergeArgs : properties,
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// patchFlag analysis
|
||||
if (hasDynamicKeys) {
|
||||
patchFlag |= PatchFlags.FULL_PROPS;
|
||||
} else {
|
||||
if (hasClassBinding) {
|
||||
patchFlag |= PatchFlags.CLASS;
|
||||
}
|
||||
if (hasStyleBinding) {
|
||||
patchFlag |= PatchFlags.STYLE;
|
||||
}
|
||||
if (dynamicPropNames.size) {
|
||||
patchFlag |= PatchFlags.PROPS;
|
||||
}
|
||||
if (hasHydrationEventBinding) {
|
||||
patchFlag |= PatchFlags.HYDRATE_EVENTS;
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
(patchFlag === 0 || patchFlag === PatchFlags.HYDRATE_EVENTS)
|
||||
&& (hasRef || directives.length > 0)
|
||||
) {
|
||||
patchFlag |= PatchFlags.NEED_PATCH;
|
||||
}
|
||||
|
||||
let propsExpression: t.Expression | t.ObjectProperty | t.Literal = t.nullLiteral();
|
||||
if (mergeArgs.length) {
|
||||
if (properties.length) {
|
||||
mergeArgs.push(t.objectExpression(dedupeProperties(properties, mergeProps)));
|
||||
}
|
||||
if (mergeArgs.length > 1) {
|
||||
propsExpression = t.callExpression(
|
||||
createIdentifier(state, 'mergeProps'),
|
||||
mergeArgs,
|
||||
);
|
||||
} else {
|
||||
// single no need for a mergeProps call
|
||||
propsExpression = mergeArgs[0];
|
||||
}
|
||||
} else if (properties.length) {
|
||||
// single no need for spread
|
||||
if (properties.length === 1 && t.isSpreadElement(properties[0])) {
|
||||
propsExpression = (properties[0] as unknown as t.SpreadElement).argument;
|
||||
} else {
|
||||
propsExpression = t.objectExpression(dedupeProperties(properties, mergeProps));
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
tag,
|
||||
props: propsExpression,
|
||||
isComponent,
|
||||
slots,
|
||||
directives,
|
||||
patchFlag,
|
||||
dynamicPropNames,
|
||||
};
|
||||
};
|
||||
|
||||
export default buildProps;
|
@ -6,30 +6,9 @@ import { addNamed, isModule, addNamespace } from '@babel/helper-module-imports';
|
||||
import { NodePath } from '@babel/traverse';
|
||||
import transformVueJSX from './transform-vue-jsx';
|
||||
import sugarFragment from './sugar-fragment';
|
||||
import type { VueJSXPluginOptions, State } from './interface';
|
||||
|
||||
export type State = {
|
||||
get: (name: string) => any;
|
||||
set: (name: string, value: any) => any;
|
||||
opts: VueJSXPluginOptions;
|
||||
file: BabelCore.BabelFile
|
||||
}
|
||||
|
||||
export interface VueJSXPluginOptions {
|
||||
/** transform `on: { click: xx }` to `onClick: xxx` */
|
||||
transformOn?: boolean;
|
||||
/** enable optimization or not. */
|
||||
optimize?: boolean;
|
||||
/** merge static and dynamic class / style attributes / onXXX handlers */
|
||||
mergeProps?: boolean;
|
||||
/** configuring custom elements */
|
||||
isCustomElement?: (tag: string) => boolean;
|
||||
/** enable object slots syntax */
|
||||
enableObjectSlots?: boolean;
|
||||
/** Replace the function used when compiling JSX expressions */
|
||||
pragma?: string;
|
||||
}
|
||||
|
||||
export type ExcludesBoolean = <T>(x: T | false | true) => x is T;
|
||||
export { VueJSXPluginOptions };
|
||||
|
||||
const hasJSX = (parentPath: NodePath<t.Program>) => {
|
||||
let fileHasJSX = false;
|
||||
|
28
packages/babel-plugin-jsx/src/interface.ts
Normal file
28
packages/babel-plugin-jsx/src/interface.ts
Normal file
@ -0,0 +1,28 @@
|
||||
import * as t from '@babel/types';
|
||||
import * as BabelCore from '@babel/core';
|
||||
|
||||
export type Slots = t.Identifier | t.ObjectExpression | null;
|
||||
|
||||
export type State = {
|
||||
get: (name: string) => any;
|
||||
set: (name: string, value: any) => any;
|
||||
opts: VueJSXPluginOptions;
|
||||
file: BabelCore.BabelFile
|
||||
};
|
||||
|
||||
export interface VueJSXPluginOptions {
|
||||
/** transform `on: { click: xx }` to `onClick: xxx` */
|
||||
transformOn?: boolean;
|
||||
/** enable optimization or not. */
|
||||
optimize?: boolean;
|
||||
/** merge static and dynamic class / style attributes / onXXX handlers */
|
||||
mergeProps?: boolean;
|
||||
/** configuring custom elements */
|
||||
isCustomElement?: (tag: string) => boolean;
|
||||
/** enable object slots syntax */
|
||||
enableObjectSlots?: boolean;
|
||||
/** Replace the function used when compiling JSX expressions */
|
||||
pragma?: string;
|
||||
}
|
||||
|
||||
export type ExcludesBoolean = <T>(x: T | false | true) => x is T;
|
@ -1,7 +1,7 @@
|
||||
import * as t from '@babel/types';
|
||||
import { NodePath } from '@babel/traverse';
|
||||
import { createIdentifier } from './utils';
|
||||
import { State } from '.';
|
||||
import type { State } from './interface';
|
||||
|
||||
export type Tag = t.Identifier | t.MemberExpression | t.StringLiteral | t.CallExpression;
|
||||
|
||||
|
@ -13,7 +13,7 @@ export const enum PatchFlags {
|
||||
NEED_PATCH = 1 << 9,
|
||||
DYNAMIC_SLOTS = 1 << 10,
|
||||
HOISTED = -1,
|
||||
BAIL = -2
|
||||
BAIL = -2,
|
||||
}
|
||||
|
||||
// dev only flag -> name mapping
|
||||
|
@ -18,7 +18,7 @@ const enum SlotFlags {
|
||||
* received. This has to be refined at runtime, when the child's vnode
|
||||
* is being created (in `normalizeChildren`)
|
||||
*/
|
||||
FORWARDED = 3
|
||||
FORWARDED = 3,
|
||||
}
|
||||
|
||||
export default SlotFlags;
|
||||
|
@ -1,6 +1,6 @@
|
||||
import * as t from '@babel/types';
|
||||
import { NodePath } from '@babel/traverse';
|
||||
import { State } from '.';
|
||||
import type { State } from './interface';
|
||||
import { createIdentifier, FRAGMENT } from './utils';
|
||||
|
||||
const transformFragment = (
|
||||
|
@ -1,5 +1,6 @@
|
||||
import * as t from '@babel/types';
|
||||
import { NodePath } from '@babel/traverse';
|
||||
import { addDefault } from '@babel/helper-module-imports';
|
||||
import {
|
||||
createIdentifier,
|
||||
transformJSXSpreadChild,
|
||||
@ -7,10 +8,295 @@ import {
|
||||
transformJSXExpressionContainer,
|
||||
walksScope,
|
||||
buildIIFE,
|
||||
isDirective,
|
||||
checkIsComponent,
|
||||
getTag,
|
||||
getJSXAttributeName,
|
||||
isOn,
|
||||
isConstant,
|
||||
dedupeProperties,
|
||||
transformJSXSpreadAttribute,
|
||||
} from './utils';
|
||||
import buildProps from './buildProps';
|
||||
import SlotFlags from './slotFlags';
|
||||
import { State, ExcludesBoolean } from '.';
|
||||
import { PatchFlags } from './patchFlags';
|
||||
import parseDirectives from './parseDirectives';
|
||||
import type { State, ExcludesBoolean, Slots } from './interface';
|
||||
|
||||
const xlinkRE = /^xlink([A-Z])/;
|
||||
|
||||
const getJSXAttributeValue = (
|
||||
path: NodePath<t.JSXAttribute>,
|
||||
state: State,
|
||||
): (
|
||||
t.StringLiteral | t.Expression | null
|
||||
) => {
|
||||
const valuePath = path.get('value');
|
||||
if (valuePath.isJSXElement()) {
|
||||
return transformJSXElement(valuePath, state);
|
||||
}
|
||||
if (valuePath.isStringLiteral()) {
|
||||
return valuePath.node;
|
||||
}
|
||||
if (valuePath.isJSXExpressionContainer()) {
|
||||
return transformJSXExpressionContainer(valuePath);
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
const buildProps = (path: NodePath<t.JSXElement>, state: State) => {
|
||||
const tag = getTag(path, state);
|
||||
const isComponent = checkIsComponent(path.get('openingElement'));
|
||||
const props = path.get('openingElement').get('attributes');
|
||||
const directives: t.ArrayExpression[] = [];
|
||||
const dynamicPropNames = new Set<string>();
|
||||
|
||||
let slots: Slots = null;
|
||||
let patchFlag = 0;
|
||||
|
||||
if (props.length === 0) {
|
||||
return {
|
||||
tag,
|
||||
isComponent,
|
||||
slots,
|
||||
props: t.nullLiteral(),
|
||||
directives,
|
||||
patchFlag,
|
||||
dynamicPropNames,
|
||||
};
|
||||
}
|
||||
|
||||
let properties: t.ObjectProperty[] = [];
|
||||
|
||||
// patchFlag analysis
|
||||
let hasRef = false;
|
||||
let hasClassBinding = false;
|
||||
let hasStyleBinding = false;
|
||||
let hasHydrationEventBinding = false;
|
||||
let hasDynamicKeys = false;
|
||||
|
||||
const mergeArgs: (t.CallExpression | t.ObjectExpression | t.Identifier)[] = [];
|
||||
const { mergeProps = true } = state.opts;
|
||||
props
|
||||
.forEach((prop) => {
|
||||
if (prop.isJSXAttribute()) {
|
||||
let name = getJSXAttributeName(prop);
|
||||
|
||||
const attributeValue = getJSXAttributeValue(prop, state);
|
||||
|
||||
if (!isConstant(attributeValue) || name === 'ref') {
|
||||
if (
|
||||
!isComponent
|
||||
&& isOn(name)
|
||||
// omit the flag for click handlers becaues hydration gives click
|
||||
// dedicated fast path.
|
||||
&& name.toLowerCase() !== 'onclick'
|
||||
// omit v-model handlers
|
||||
&& name !== 'onUpdate:modelValue'
|
||||
) {
|
||||
hasHydrationEventBinding = true;
|
||||
}
|
||||
|
||||
if (name === 'ref') {
|
||||
hasRef = true;
|
||||
} else if (name === 'class' && !isComponent) {
|
||||
hasClassBinding = true;
|
||||
} else if (name === 'style' && !isComponent) {
|
||||
hasStyleBinding = true;
|
||||
} else if (
|
||||
name !== 'key'
|
||||
&& !isDirective(name)
|
||||
&& name !== 'on'
|
||||
) {
|
||||
dynamicPropNames.add(name);
|
||||
}
|
||||
}
|
||||
if (state.opts.transformOn && (name === 'on' || name === 'nativeOn')) {
|
||||
if (!state.get('transformOn')) {
|
||||
state.set('transformOn', addDefault(
|
||||
path,
|
||||
'@vue/babel-helper-vue-transform-on',
|
||||
{ nameHint: '_transformOn' },
|
||||
));
|
||||
}
|
||||
mergeArgs.push(t.callExpression(
|
||||
state.get('transformOn'),
|
||||
[attributeValue || t.booleanLiteral(true)],
|
||||
));
|
||||
return;
|
||||
}
|
||||
if (isDirective(name)) {
|
||||
const {
|
||||
directive, modifiers, values, args, directiveName,
|
||||
} = parseDirectives({
|
||||
tag,
|
||||
isComponent,
|
||||
name,
|
||||
path: prop,
|
||||
state,
|
||||
value: attributeValue,
|
||||
});
|
||||
|
||||
if (directiveName === 'slots') {
|
||||
slots = attributeValue as Slots;
|
||||
return;
|
||||
}
|
||||
if (directive) {
|
||||
directives.push(t.arrayExpression(directive));
|
||||
} else if (directiveName === 'html') {
|
||||
properties.push(t.objectProperty(
|
||||
t.stringLiteral('innerHTML'),
|
||||
values[0] as any,
|
||||
));
|
||||
dynamicPropNames.add('innerHTML');
|
||||
} else if (directiveName === 'text') {
|
||||
properties.push(t.objectProperty(
|
||||
t.stringLiteral('textContent'),
|
||||
values[0] as any,
|
||||
));
|
||||
dynamicPropNames.add('textContent');
|
||||
}
|
||||
|
||||
if (['models', 'model'].includes(directiveName)) {
|
||||
values.forEach((value, index) => {
|
||||
const propName = args[index];
|
||||
// v-model target with variable
|
||||
const isDynamic = propName && !t.isStringLiteral(propName) && !t.isNullLiteral(propName);
|
||||
|
||||
// must be v-model or v-models and is a component
|
||||
if (!directive) {
|
||||
properties.push(
|
||||
t.objectProperty(t.isNullLiteral(propName)
|
||||
? t.stringLiteral('modelValue') : propName, value as any, isDynamic),
|
||||
);
|
||||
if (!isDynamic) {
|
||||
dynamicPropNames.add((propName as t.StringLiteral)?.value || 'modelValue');
|
||||
}
|
||||
|
||||
if (modifiers[index]?.size) {
|
||||
properties.push(
|
||||
t.objectProperty(
|
||||
isDynamic
|
||||
? t.binaryExpression('+', propName, t.stringLiteral('Modifiers'))
|
||||
: t.stringLiteral(`${(propName as t.StringLiteral)?.value || 'model'}Modifiers`),
|
||||
t.objectExpression(
|
||||
[...modifiers[index]].map((modifier) => t.objectProperty(
|
||||
t.stringLiteral(modifier),
|
||||
t.booleanLiteral(true),
|
||||
)),
|
||||
),
|
||||
isDynamic,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const updateName = isDynamic
|
||||
? t.binaryExpression('+', t.stringLiteral('onUpdate'), propName)
|
||||
: t.stringLiteral(`onUpdate:${(propName as t.StringLiteral)?.value || 'modelValue'}`);
|
||||
|
||||
properties.push(
|
||||
t.objectProperty(
|
||||
updateName,
|
||||
t.arrowFunctionExpression(
|
||||
[t.identifier('$event')],
|
||||
t.assignmentExpression('=', value as any, t.identifier('$event')),
|
||||
),
|
||||
isDynamic,
|
||||
),
|
||||
);
|
||||
|
||||
if (!isDynamic) {
|
||||
dynamicPropNames.add((updateName as t.StringLiteral).value);
|
||||
} else {
|
||||
hasDynamicKeys = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
if (name.match(xlinkRE)) {
|
||||
name = name.replace(xlinkRE, (_, firstCharacter) => `xlink:${firstCharacter.toLowerCase()}`);
|
||||
}
|
||||
properties.push(t.objectProperty(
|
||||
t.stringLiteral(name),
|
||||
attributeValue || t.booleanLiteral(true),
|
||||
));
|
||||
}
|
||||
} else {
|
||||
if (properties.length && mergeProps) {
|
||||
mergeArgs.push(t.objectExpression(dedupeProperties(properties, mergeProps)));
|
||||
properties = [];
|
||||
}
|
||||
|
||||
// JSXSpreadAttribute
|
||||
hasDynamicKeys = true;
|
||||
transformJSXSpreadAttribute(
|
||||
path as NodePath,
|
||||
prop as NodePath<t.JSXSpreadAttribute>,
|
||||
mergeProps,
|
||||
mergeProps ? mergeArgs : properties,
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// patchFlag analysis
|
||||
if (hasDynamicKeys) {
|
||||
patchFlag |= PatchFlags.FULL_PROPS;
|
||||
} else {
|
||||
if (hasClassBinding) {
|
||||
patchFlag |= PatchFlags.CLASS;
|
||||
}
|
||||
if (hasStyleBinding) {
|
||||
patchFlag |= PatchFlags.STYLE;
|
||||
}
|
||||
if (dynamicPropNames.size) {
|
||||
patchFlag |= PatchFlags.PROPS;
|
||||
}
|
||||
if (hasHydrationEventBinding) {
|
||||
patchFlag |= PatchFlags.HYDRATE_EVENTS;
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
(patchFlag === 0 || patchFlag === PatchFlags.HYDRATE_EVENTS)
|
||||
&& (hasRef || directives.length > 0)
|
||||
) {
|
||||
patchFlag |= PatchFlags.NEED_PATCH;
|
||||
}
|
||||
|
||||
let propsExpression: t.Expression | t.ObjectProperty | t.Literal = t.nullLiteral();
|
||||
if (mergeArgs.length) {
|
||||
if (properties.length) {
|
||||
mergeArgs.push(t.objectExpression(dedupeProperties(properties, mergeProps)));
|
||||
}
|
||||
if (mergeArgs.length > 1) {
|
||||
propsExpression = t.callExpression(
|
||||
createIdentifier(state, 'mergeProps'),
|
||||
mergeArgs,
|
||||
);
|
||||
} else {
|
||||
// single no need for a mergeProps call
|
||||
propsExpression = mergeArgs[0];
|
||||
}
|
||||
} else if (properties.length) {
|
||||
// single no need for spread
|
||||
if (properties.length === 1 && t.isSpreadElement(properties[0])) {
|
||||
propsExpression = (properties[0] as unknown as t.SpreadElement).argument;
|
||||
} else {
|
||||
propsExpression = t.objectExpression(dedupeProperties(properties, mergeProps));
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
tag,
|
||||
props: propsExpression,
|
||||
isComponent,
|
||||
slots,
|
||||
directives,
|
||||
patchFlag,
|
||||
dynamicPropNames,
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Get children from Array of JSX children
|
||||
@ -19,11 +305,11 @@ import { State, ExcludesBoolean } from '.';
|
||||
*/
|
||||
const getChildren = (
|
||||
paths: NodePath<
|
||||
t.JSXText
|
||||
| t.JSXExpressionContainer
|
||||
| t.JSXSpreadChild
|
||||
| t.JSXElement
|
||||
| t.JSXFragment
|
||||
t.JSXText
|
||||
| t.JSXExpressionContainer
|
||||
| t.JSXSpreadChild
|
||||
| t.JSXElement
|
||||
| t.JSXFragment
|
||||
>[],
|
||||
state: State,
|
||||
): t.Expression[] => paths
|
||||
@ -211,8 +497,6 @@ const transformJSXElement = (
|
||||
]);
|
||||
};
|
||||
|
||||
export { transformJSXElement };
|
||||
|
||||
export default ({
|
||||
JSXElement: {
|
||||
exit(path: NodePath<t.JSXElement>, state: State) {
|
||||
|
@ -2,12 +2,12 @@ import * as t from '@babel/types';
|
||||
import htmlTags from 'html-tags';
|
||||
import svgTags from 'svg-tags';
|
||||
import { NodePath } from '@babel/traverse';
|
||||
import { State } from '.';
|
||||
import type { State } from './interface';
|
||||
import SlotFlags from './slotFlags';
|
||||
|
||||
const JSX_HELPER_KEY = 'JSX_HELPER_KEY';
|
||||
const FRAGMENT = 'Fragment';
|
||||
const KEEP_ALIVE = 'KeepAlive';
|
||||
export const JSX_HELPER_KEY = 'JSX_HELPER_KEY';
|
||||
export const FRAGMENT = 'Fragment';
|
||||
export const KEEP_ALIVE = 'KeepAlive';
|
||||
|
||||
/**
|
||||
* create Identifier
|
||||
@ -16,7 +16,7 @@ const KEEP_ALIVE = 'KeepAlive';
|
||||
* @param name string
|
||||
* @returns MemberExpression
|
||||
*/
|
||||
const createIdentifier = (
|
||||
export const createIdentifier = (
|
||||
state: State, name: string,
|
||||
): t.Identifier | t.MemberExpression => state.get(name)();
|
||||
|
||||
@ -24,7 +24,7 @@ const createIdentifier = (
|
||||
* Checks if string is describing a directive
|
||||
* @param src string
|
||||
*/
|
||||
const isDirective = (src: string): boolean => src.startsWith('v-')
|
||||
export const isDirective = (src: string): boolean => src.startsWith('v-')
|
||||
|| (src.startsWith('v') && src.length >= 2 && src[1] >= 'A' && src[1] <= 'Z');
|
||||
|
||||
/**
|
||||
@ -32,7 +32,7 @@ const isDirective = (src: string): boolean => src.startsWith('v-')
|
||||
* @param tag string
|
||||
* @returns boolean
|
||||
*/
|
||||
const shouldTransformedToSlots = (tag: string) => !(tag.endsWith(FRAGMENT) || tag === KEEP_ALIVE);
|
||||
export const shouldTransformedToSlots = (tag: string) => !(tag.endsWith(FRAGMENT) || tag === KEEP_ALIVE);
|
||||
|
||||
/**
|
||||
* Check if a Node is a component
|
||||
@ -41,7 +41,7 @@ const shouldTransformedToSlots = (tag: string) => !(tag.endsWith(FRAGMENT) || ta
|
||||
* @param path JSXOpeningElement
|
||||
* @returns boolean
|
||||
*/
|
||||
const checkIsComponent = (path: NodePath<t.JSXOpeningElement>): boolean => {
|
||||
export const checkIsComponent = (path: NodePath<t.JSXOpeningElement>): boolean => {
|
||||
const namePath = path.get('name');
|
||||
|
||||
if (namePath.isJSXMemberExpression()) {
|
||||
@ -58,7 +58,7 @@ const checkIsComponent = (path: NodePath<t.JSXOpeningElement>): boolean => {
|
||||
* @param path JSXMemberExpression
|
||||
* @returns MemberExpression
|
||||
*/
|
||||
const transformJSXMemberExpression = (
|
||||
export const transformJSXMemberExpression = (
|
||||
path: NodePath<t.JSXMemberExpression>,
|
||||
): t.MemberExpression => {
|
||||
const objectPath = path.node.object;
|
||||
@ -78,7 +78,7 @@ const transformJSXMemberExpression = (
|
||||
* @param state State
|
||||
* @returns Identifier | StringLiteral | MemberExpression | CallExpression
|
||||
*/
|
||||
const getTag = (
|
||||
export const getTag = (
|
||||
path: NodePath<t.JSXElement>,
|
||||
state: State,
|
||||
): t.Identifier | t.CallExpression | t.StringLiteral | t.MemberExpression => {
|
||||
@ -104,7 +104,7 @@ const getTag = (
|
||||
throw new Error(`getTag: ${namePath.type} is not supported`);
|
||||
};
|
||||
|
||||
const getJSXAttributeName = (path: NodePath<t.JSXAttribute>): string => {
|
||||
export const getJSXAttributeName = (path: NodePath<t.JSXAttribute>): string => {
|
||||
const nameNode = path.node.name;
|
||||
if (t.isJSXIdentifier(nameNode)) {
|
||||
return nameNode.name;
|
||||
@ -118,7 +118,7 @@ const getJSXAttributeName = (path: NodePath<t.JSXAttribute>): string => {
|
||||
* @param path JSXText
|
||||
* @returns StringLiteral | null
|
||||
*/
|
||||
const transformJSXText = (path: NodePath<t.JSXText>): t.StringLiteral | null => {
|
||||
export const transformJSXText = (path: NodePath<t.JSXText>): t.StringLiteral | null => {
|
||||
const { node } = path;
|
||||
const lines = node.value.split(/\r\n|\n|\r/);
|
||||
|
||||
@ -169,10 +169,10 @@ const transformJSXText = (path: NodePath<t.JSXText>): t.StringLiteral | null =>
|
||||
* @param path JSXExpressionContainer
|
||||
* @returns Expression
|
||||
*/
|
||||
const transformJSXExpressionContainer = (
|
||||
export const transformJSXExpressionContainer = (
|
||||
path: NodePath<t.JSXExpressionContainer>,
|
||||
): (
|
||||
t.Expression
|
||||
t.Expression
|
||||
) => path.get('expression').node as t.Expression;
|
||||
|
||||
/**
|
||||
@ -180,11 +180,11 @@ const transformJSXExpressionContainer = (
|
||||
* @param path JSXSpreadChild
|
||||
* @returns SpreadElement
|
||||
*/
|
||||
const transformJSXSpreadChild = (
|
||||
export const transformJSXSpreadChild = (
|
||||
path: NodePath<t.JSXSpreadChild>,
|
||||
): t.SpreadElement => t.spreadElement(path.get('expression').node);
|
||||
|
||||
const walksScope = (path: NodePath, name: string, slotFlag: SlotFlags): void => {
|
||||
export const walksScope = (path: NodePath, name: string, slotFlag: SlotFlags): void => {
|
||||
if (path.scope.hasBinding(name) && path.parentPath) {
|
||||
if (t.isJSXElement(path.parentPath.node)) {
|
||||
path.parentPath.setData('slotFlag', slotFlag);
|
||||
@ -193,7 +193,7 @@ const walksScope = (path: NodePath, name: string, slotFlag: SlotFlags): void =>
|
||||
}
|
||||
};
|
||||
|
||||
const buildIIFE = (path: NodePath<t.JSXElement>, children: t.Expression[]) => {
|
||||
export const buildIIFE = (path: NodePath<t.JSXElement>, children: t.Expression[]) => {
|
||||
const { parentPath } = path;
|
||||
if (t.isAssignmentExpression(parentPath)) {
|
||||
const { left } = parentPath.node as t.AssignmentExpression;
|
||||
@ -221,19 +221,88 @@ const buildIIFE = (path: NodePath<t.JSXElement>, children: t.Expression[]) => {
|
||||
return children;
|
||||
};
|
||||
|
||||
export {
|
||||
createIdentifier,
|
||||
isDirective,
|
||||
checkIsComponent,
|
||||
transformJSXMemberExpression,
|
||||
getTag,
|
||||
getJSXAttributeName,
|
||||
transformJSXText,
|
||||
transformJSXSpreadChild,
|
||||
transformJSXExpressionContainer,
|
||||
shouldTransformedToSlots,
|
||||
FRAGMENT,
|
||||
walksScope,
|
||||
buildIIFE,
|
||||
JSX_HELPER_KEY,
|
||||
const onRE = /^on[^a-z]/;
|
||||
|
||||
export const isOn = (key: string) => onRE.test(key);
|
||||
|
||||
const mergeAsArray = (existing: t.ObjectProperty, incoming: t.ObjectProperty) => {
|
||||
if (t.isArrayExpression(existing.value)) {
|
||||
existing.value.elements.push(incoming.value as t.Expression);
|
||||
} else {
|
||||
existing.value = t.arrayExpression([
|
||||
existing.value as t.Expression,
|
||||
incoming.value as t.Expression,
|
||||
]);
|
||||
}
|
||||
};
|
||||
|
||||
export const dedupeProperties = (properties: t.ObjectProperty[] = [], mergeProps?: boolean) => {
|
||||
if (!mergeProps) {
|
||||
return properties;
|
||||
}
|
||||
const knownProps = new Map<string, t.ObjectProperty>();
|
||||
const deduped: t.ObjectProperty[] = [];
|
||||
properties.forEach((prop) => {
|
||||
if (t.isStringLiteral(prop.key)) {
|
||||
const { value: name } = prop.key;
|
||||
const existing = knownProps.get(name);
|
||||
if (existing) {
|
||||
if (name === 'style' || name === 'class' || name.startsWith('on')) {
|
||||
mergeAsArray(existing, prop);
|
||||
}
|
||||
} else {
|
||||
knownProps.set(name, prop);
|
||||
deduped.push(prop);
|
||||
}
|
||||
} else {
|
||||
// v-model target with variable
|
||||
deduped.push(prop);
|
||||
}
|
||||
});
|
||||
|
||||
return deduped;
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if an attribute value is constant
|
||||
* @param node
|
||||
* @returns boolean
|
||||
*/
|
||||
export const isConstant = (
|
||||
node: t.Expression | t.Identifier | t.Literal | t.SpreadElement | null,
|
||||
): boolean => {
|
||||
if (t.isIdentifier(node)) {
|
||||
return node.name === 'undefined';
|
||||
}
|
||||
if (t.isArrayExpression(node)) {
|
||||
const { elements } = node;
|
||||
return elements.every((element) => element && isConstant(element));
|
||||
}
|
||||
if (t.isObjectExpression(node)) {
|
||||
return node.properties.every((property) => isConstant((property as any).value));
|
||||
}
|
||||
if (t.isLiteral(node)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
export const transformJSXSpreadAttribute = (
|
||||
nodePath: NodePath,
|
||||
path: NodePath<t.JSXSpreadAttribute>,
|
||||
mergeProps: boolean,
|
||||
args: (t.ObjectProperty | t.Expression | t.SpreadElement)[],
|
||||
) => {
|
||||
const argument = path.get('argument') as NodePath<t.ObjectExpression | t.Identifier>;
|
||||
const properties = t.isObjectExpression(argument.node) ? argument.node.properties : undefined;
|
||||
if (!properties) {
|
||||
if (argument.isIdentifier()) {
|
||||
walksScope(nodePath, (argument.node as t.Identifier).name, SlotFlags.DYNAMIC);
|
||||
}
|
||||
args.push(mergeProps ? argument.node : t.spreadElement(argument.node));
|
||||
} else if (mergeProps) {
|
||||
args.push(t.objectExpression(properties));
|
||||
} else {
|
||||
args.push(...(properties as t.ObjectProperty[]));
|
||||
}
|
||||
};
|
||||
|
@ -4,7 +4,6 @@
|
||||
"rootDirs": ["./src"],
|
||||
"outDir": "dist",
|
||||
"downlevelIteration": true,
|
||||
"types": ["node", "jest"],
|
||||
"declaration": true
|
||||
},
|
||||
"include": ["src/**/*", "global.d.ts"],
|
||||
|
@ -12,10 +12,15 @@
|
||||
"esModuleInterop": true,
|
||||
"removeComments": false,
|
||||
"jsx": "preserve",
|
||||
"lib": ["esnext", "dom"],
|
||||
"types": ["node"]
|
||||
"lib": [
|
||||
"esnext",
|
||||
"dom"
|
||||
],
|
||||
"types": ["node", "jest"],
|
||||
},
|
||||
"include": [
|
||||
"global.d.ts"
|
||||
"global.d.ts",
|
||||
"packages/*/src",
|
||||
"packages/*/test",
|
||||
]
|
||||
}
|
||||
|
106
yarn.lock
106
yarn.lock
@ -2167,9 +2167,35 @@
|
||||
semver "^7.3.2"
|
||||
tsutils "^3.17.1"
|
||||
|
||||
"@typescript-eslint/eslint-plugin@^4.4.1":
|
||||
version "4.15.2"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.15.2.tgz#981b26b4076c62a5a55873fbef3fe98f83360c61"
|
||||
integrity sha512-uiQQeu9tWl3f1+oK0yoAv9lt/KXO24iafxgQTkIYO/kitruILGx3uH+QtIAHqxFV+yIsdnJH+alel9KuE3J15Q==
|
||||
dependencies:
|
||||
"@typescript-eslint/experimental-utils" "4.15.2"
|
||||
"@typescript-eslint/scope-manager" "4.15.2"
|
||||
debug "^4.1.1"
|
||||
functional-red-black-tree "^1.0.1"
|
||||
lodash "^4.17.15"
|
||||
regexpp "^3.0.0"
|
||||
semver "^7.3.2"
|
||||
tsutils "^3.17.1"
|
||||
|
||||
"@typescript-eslint/experimental-utils@4.15.2":
|
||||
version "4.15.2"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.15.2.tgz#5efd12355bd5b535e1831282e6cf465b9a71cf36"
|
||||
integrity sha512-Fxoshw8+R5X3/Vmqwsjc8nRO/7iTysRtDqx6rlfLZ7HbT8TZhPeQqbPjTyk2RheH3L8afumecTQnUc9EeXxohQ==
|
||||
dependencies:
|
||||
"@types/json-schema" "^7.0.3"
|
||||
"@typescript-eslint/scope-manager" "4.15.2"
|
||||
"@typescript-eslint/types" "4.15.2"
|
||||
"@typescript-eslint/typescript-estree" "4.15.2"
|
||||
eslint-scope "^5.0.0"
|
||||
eslint-utils "^2.0.0"
|
||||
|
||||
"@typescript-eslint/experimental-utils@4.17.0":
|
||||
version "4.17.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.17.0.tgz#762c44aaa1a6a3c05b6d63a8648fb89b89f84c80"
|
||||
resolved "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.17.0.tgz#762c44aaa1a6a3c05b6d63a8648fb89b89f84c80"
|
||||
integrity sha512-ZR2NIUbnIBj+LGqCFGQ9yk2EBQrpVVFOh9/Kd0Lm6gLpSAcCuLLe5lUCibKGCqyH9HPwYC0GIJce2O1i8VYmWA==
|
||||
dependencies:
|
||||
"@types/json-schema" "^7.0.3"
|
||||
@ -2189,9 +2215,27 @@
|
||||
"@typescript-eslint/typescript-estree" "4.22.0"
|
||||
debug "^4.1.1"
|
||||
|
||||
"@typescript-eslint/parser@^4.4.1":
|
||||
version "4.15.2"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.15.2.tgz#c804474321ef76a3955aec03664808f0d6e7872e"
|
||||
integrity sha512-SHeF8xbsC6z2FKXsaTb1tBCf0QZsjJ94H6Bo51Y1aVEZ4XAefaw5ZAilMoDPlGghe+qtq7XdTiDlGfVTOmvA+Q==
|
||||
dependencies:
|
||||
"@typescript-eslint/scope-manager" "4.15.2"
|
||||
"@typescript-eslint/types" "4.15.2"
|
||||
"@typescript-eslint/typescript-estree" "4.15.2"
|
||||
debug "^4.1.1"
|
||||
|
||||
"@typescript-eslint/scope-manager@4.15.2":
|
||||
version "4.15.2"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.15.2.tgz#5725bda656995960ae1d004bfd1cd70320f37f4f"
|
||||
integrity sha512-Zm0tf/MSKuX6aeJmuXexgdVyxT9/oJJhaCkijv0DvJVT3ui4zY6XYd6iwIo/8GEZGy43cd7w1rFMiCLHbRzAPQ==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "4.15.2"
|
||||
"@typescript-eslint/visitor-keys" "4.15.2"
|
||||
|
||||
"@typescript-eslint/scope-manager@4.17.0":
|
||||
version "4.17.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.17.0.tgz#f4edf94eff3b52a863180f7f89581bf963e3d37d"
|
||||
resolved "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.17.0.tgz#f4edf94eff3b52a863180f7f89581bf963e3d37d"
|
||||
integrity sha512-OJ+CeTliuW+UZ9qgULrnGpPQ1bhrZNFpfT/Bc0pzNeyZwMik7/ykJ0JHnQ7krHanFN9wcnPK89pwn84cRUmYjw==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "4.17.0"
|
||||
@ -2199,25 +2243,43 @@
|
||||
|
||||
"@typescript-eslint/scope-manager@4.22.0":
|
||||
version "4.22.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.22.0.tgz#ed411545e61161a8d702e703a4b7d96ec065b09a"
|
||||
resolved "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.22.0.tgz#ed411545e61161a8d702e703a4b7d96ec065b09a"
|
||||
integrity sha512-OcCO7LTdk6ukawUM40wo61WdeoA7NM/zaoq1/2cs13M7GyiF+T4rxuA4xM+6LeHWjWbss7hkGXjFDRcKD4O04Q==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "4.22.0"
|
||||
"@typescript-eslint/visitor-keys" "4.22.0"
|
||||
|
||||
"@typescript-eslint/types@4.15.2":
|
||||
version "4.15.2"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.15.2.tgz#04acf3a2dc8001a88985291744241e732ef22c60"
|
||||
integrity sha512-r7lW7HFkAarfUylJ2tKndyO9njwSyoy6cpfDKWPX6/ctZA+QyaYscAHXVAfJqtnY6aaTwDYrOhp+ginlbc7HfQ==
|
||||
|
||||
"@typescript-eslint/types@4.17.0":
|
||||
version "4.17.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.17.0.tgz#f57d8fc7f31b348db946498a43050083d25f40ad"
|
||||
resolved "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.17.0.tgz#f57d8fc7f31b348db946498a43050083d25f40ad"
|
||||
integrity sha512-RN5z8qYpJ+kXwnLlyzZkiJwfW2AY458Bf8WqllkondQIcN2ZxQowAToGSd9BlAUZDB5Ea8I6mqL2quGYCLT+2g==
|
||||
|
||||
"@typescript-eslint/types@4.22.0":
|
||||
version "4.22.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.22.0.tgz#0ca6fde5b68daf6dba133f30959cc0688c8dd0b6"
|
||||
resolved "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.22.0.tgz#0ca6fde5b68daf6dba133f30959cc0688c8dd0b6"
|
||||
integrity sha512-sW/BiXmmyMqDPO2kpOhSy2Py5w6KvRRsKZnV0c4+0nr4GIcedJwXAq+RHNK4lLVEZAJYFltnnk1tJSlbeS9lYA==
|
||||
|
||||
"@typescript-eslint/typescript-estree@4.15.2":
|
||||
version "4.15.2"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.15.2.tgz#c2f7a1e94f3428d229d5ecff3ead6581ee9b62fa"
|
||||
integrity sha512-cGR8C2g5SPtHTQvAymEODeqx90pJHadWsgTtx6GbnTWKqsg7yp6Eaya9nFzUd4KrKhxdYTTFBiYeTPQaz/l8bw==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "4.15.2"
|
||||
"@typescript-eslint/visitor-keys" "4.15.2"
|
||||
debug "^4.1.1"
|
||||
globby "^11.0.1"
|
||||
is-glob "^4.0.1"
|
||||
semver "^7.3.2"
|
||||
tsutils "^3.17.1"
|
||||
|
||||
"@typescript-eslint/typescript-estree@4.17.0":
|
||||
version "4.17.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.17.0.tgz#b835d152804f0972b80dbda92477f9070a72ded1"
|
||||
resolved "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.17.0.tgz#b835d152804f0972b80dbda92477f9070a72ded1"
|
||||
integrity sha512-lRhSFIZKUEPPWpWfwuZBH9trYIEJSI0vYsrxbvVvNyIUDoKWaklOAelsSkeh3E2VBSZiNe9BZ4E5tYBZbUczVQ==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "4.17.0"
|
||||
@ -2241,9 +2303,17 @@
|
||||
semver "^7.3.2"
|
||||
tsutils "^3.17.1"
|
||||
|
||||
"@typescript-eslint/visitor-keys@4.15.2":
|
||||
version "4.15.2"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.15.2.tgz#3d1c7979ce75bf6acf9691109bd0d6b5706192b9"
|
||||
integrity sha512-TME1VgSb7wTwgENN5KVj4Nqg25hP8DisXxNBojM4Nn31rYaNDIocNm5cmjOFfh42n7NVERxWrDFoETO/76ePyg==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "4.15.2"
|
||||
eslint-visitor-keys "^2.0.0"
|
||||
|
||||
"@typescript-eslint/visitor-keys@4.17.0":
|
||||
version "4.17.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.17.0.tgz#9c304cfd20287c14a31d573195a709111849b14d"
|
||||
resolved "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.17.0.tgz#9c304cfd20287c14a31d573195a709111849b14d"
|
||||
integrity sha512-WfuMN8mm5SSqXuAr9NM+fItJ0SVVphobWYkWOwQ1odsfC014Vdxk/92t4JwS1Q6fCA/ABfCKpa3AVtpUKTNKGQ==
|
||||
dependencies:
|
||||
"@typescript-eslint/types" "4.17.0"
|
||||
@ -4602,7 +4672,7 @@ escodegen@^1.14.1:
|
||||
optionalDependencies:
|
||||
source-map "~0.6.1"
|
||||
|
||||
eslint-config-airbnb-base@^14.1.0:
|
||||
eslint-config-airbnb-base@^14.2.0, eslint-config-airbnb-base@^14.2.1:
|
||||
version "14.2.1"
|
||||
resolved "https://registry.yarnpkg.com/eslint-config-airbnb-base/-/eslint-config-airbnb-base-14.2.1.tgz#8a2eb38455dc5a312550193b319cdaeef042cd1e"
|
||||
integrity sha512-GOrQyDtVEc1Xy20U7vsB2yAoB4nBlfH5HZJeatRXHleO+OS5Ot+MWij4Dpltw4/DyIkqUfqz1epfhVR5XWWQPA==
|
||||
@ -4611,6 +4681,24 @@ eslint-config-airbnb-base@^14.1.0:
|
||||
object.assign "^4.1.2"
|
||||
object.entries "^1.1.2"
|
||||
|
||||
eslint-config-airbnb-typescript@^12.3.1:
|
||||
version "12.3.1"
|
||||
resolved "https://registry.yarnpkg.com/eslint-config-airbnb-typescript/-/eslint-config-airbnb-typescript-12.3.1.tgz#83ab40d76402c208eb08516260d1d6fac8f8acbc"
|
||||
integrity sha512-ql/Pe6/hppYuRp4m3iPaHJqkBB7dgeEmGPQ6X0UNmrQOfTF+dXw29/ZjU2kQ6RDoLxaxOA+Xqv07Vbef6oVTWw==
|
||||
dependencies:
|
||||
"@typescript-eslint/parser" "^4.4.1"
|
||||
eslint-config-airbnb "^18.2.0"
|
||||
eslint-config-airbnb-base "^14.2.0"
|
||||
|
||||
eslint-config-airbnb@^18.2.0:
|
||||
version "18.2.1"
|
||||
resolved "https://registry.yarnpkg.com/eslint-config-airbnb/-/eslint-config-airbnb-18.2.1.tgz#b7fe2b42f9f8173e825b73c8014b592e449c98d9"
|
||||
integrity sha512-glZNDEZ36VdlZWoxn/bUR1r/sdFKPd1mHPbqUtkctgNG4yT2DLLtJ3D+yCV+jzZCc2V1nBVkmdknOJBZ5Hc0fg==
|
||||
dependencies:
|
||||
eslint-config-airbnb-base "^14.2.1"
|
||||
object.assign "^4.1.2"
|
||||
object.entries "^1.1.2"
|
||||
|
||||
eslint-import-resolver-node@^0.3.4:
|
||||
version "0.3.4"
|
||||
resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.4.tgz#85ffa81942c25012d8231096ddf679c03042c717"
|
||||
@ -4627,7 +4715,7 @@ eslint-module-utils@^2.6.0:
|
||||
debug "^2.6.9"
|
||||
pkg-dir "^2.0.0"
|
||||
|
||||
eslint-plugin-import@^2.20.2:
|
||||
eslint-plugin-import@^2.22.1:
|
||||
version "2.22.1"
|
||||
resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.22.1.tgz#0896c7e6a0cf44109a2d97b95903c2bb689d7702"
|
||||
integrity sha512-8K7JjINHOpH64ozkAhpT3sd+FswIZTfMZTjdx052pnWrgRCVfp8op9tbjpAk3DdUeI/Ba4C8OjdC0r90erHEOw==
|
||||
|
Loading…
Reference in New Issue
Block a user