mirror of
https://github.com/vuejs/babel-plugin-jsx.git
synced 2025-01-10 16:29:12 +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
|
- ~/.cache/yarn
|
||||||
key: v2-dependencies-{{ checksum "yarn.lock" }}
|
key: v2-dependencies-{{ checksum "yarn.lock" }}
|
||||||
|
|
||||||
|
- run: yarn lint
|
||||||
|
|
||||||
# run tests!
|
# run tests!
|
||||||
- run: yarn test
|
- run: yarn test
|
||||||
|
17
.eslintrc.js
17
.eslintrc.js
@ -5,6 +5,7 @@ module.exports = {
|
|||||||
ecmaFeatures: {
|
ecmaFeatures: {
|
||||||
jsx: true,
|
jsx: true,
|
||||||
},
|
},
|
||||||
|
project: './tsconfig.json',
|
||||||
},
|
},
|
||||||
env: {
|
env: {
|
||||||
browser: true,
|
browser: true,
|
||||||
@ -15,8 +16,7 @@ module.exports = {
|
|||||||
parser: '@typescript-eslint/parser',
|
parser: '@typescript-eslint/parser',
|
||||||
plugins: ['@typescript-eslint', 'import'],
|
plugins: ['@typescript-eslint', 'import'],
|
||||||
extends: [
|
extends: [
|
||||||
'eslint-config-airbnb-base',
|
'airbnb-typescript/base',
|
||||||
'plugin:@typescript-eslint/recommended',
|
|
||||||
],
|
],
|
||||||
rules: {
|
rules: {
|
||||||
'no-nested-ternary': [0],
|
'no-nested-ternary': [0],
|
||||||
@ -27,19 +27,8 @@ module.exports = {
|
|||||||
'import/no-extraneous-dependencies': [0],
|
'import/no-extraneous-dependencies': [0],
|
||||||
'consistent-return': [0],
|
'consistent-return': [0],
|
||||||
'no-bitwise': [0],
|
'no-bitwise': [0],
|
||||||
|
'@typescript-eslint/no-use-before-define': [0],
|
||||||
'prefer-destructuring': [2, { array: false }],
|
'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],
|
'max-len': [0],
|
||||||
},
|
},
|
||||||
settings: {
|
|
||||||
'import/resolver': {
|
|
||||||
node: {
|
|
||||||
extensions: ['.js', '.jsx', '.ts', '.tsx'],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
@ -16,9 +16,10 @@
|
|||||||
"jsx"
|
"jsx"
|
||||||
],
|
],
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@typescript-eslint/eslint-plugin": "^4.4.1",
|
||||||
"eslint": "^7.7.0",
|
"eslint": "^7.7.0",
|
||||||
"eslint-config-airbnb-base": "^14.1.0",
|
"eslint-config-airbnb-typescript": "^12.3.1",
|
||||||
"eslint-plugin-import": "^2.20.2",
|
"eslint-plugin-import": "^2.22.1",
|
||||||
"lerna": "^3.19.0"
|
"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 { NodePath } from '@babel/traverse';
|
||||||
import transformVueJSX from './transform-vue-jsx';
|
import transformVueJSX from './transform-vue-jsx';
|
||||||
import sugarFragment from './sugar-fragment';
|
import sugarFragment from './sugar-fragment';
|
||||||
|
import type { VueJSXPluginOptions, State } from './interface';
|
||||||
|
|
||||||
export type State = {
|
export { VueJSXPluginOptions };
|
||||||
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;
|
|
||||||
|
|
||||||
const hasJSX = (parentPath: NodePath<t.Program>) => {
|
const hasJSX = (parentPath: NodePath<t.Program>) => {
|
||||||
let fileHasJSX = false;
|
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 * as t from '@babel/types';
|
||||||
import { NodePath } from '@babel/traverse';
|
import { NodePath } from '@babel/traverse';
|
||||||
import { createIdentifier } from './utils';
|
import { createIdentifier } from './utils';
|
||||||
import { State } from '.';
|
import type { State } from './interface';
|
||||||
|
|
||||||
export type Tag = t.Identifier | t.MemberExpression | t.StringLiteral | t.CallExpression;
|
export type Tag = t.Identifier | t.MemberExpression | t.StringLiteral | t.CallExpression;
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ export const enum PatchFlags {
|
|||||||
NEED_PATCH = 1 << 9,
|
NEED_PATCH = 1 << 9,
|
||||||
DYNAMIC_SLOTS = 1 << 10,
|
DYNAMIC_SLOTS = 1 << 10,
|
||||||
HOISTED = -1,
|
HOISTED = -1,
|
||||||
BAIL = -2
|
BAIL = -2,
|
||||||
}
|
}
|
||||||
|
|
||||||
// dev only flag -> name mapping
|
// 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
|
* received. This has to be refined at runtime, when the child's vnode
|
||||||
* is being created (in `normalizeChildren`)
|
* is being created (in `normalizeChildren`)
|
||||||
*/
|
*/
|
||||||
FORWARDED = 3
|
FORWARDED = 3,
|
||||||
}
|
}
|
||||||
|
|
||||||
export default SlotFlags;
|
export default SlotFlags;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import * as t from '@babel/types';
|
import * as t from '@babel/types';
|
||||||
import { NodePath } from '@babel/traverse';
|
import { NodePath } from '@babel/traverse';
|
||||||
import { State } from '.';
|
import type { State } from './interface';
|
||||||
import { createIdentifier, FRAGMENT } from './utils';
|
import { createIdentifier, FRAGMENT } from './utils';
|
||||||
|
|
||||||
const transformFragment = (
|
const transformFragment = (
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import * as t from '@babel/types';
|
import * as t from '@babel/types';
|
||||||
import { NodePath } from '@babel/traverse';
|
import { NodePath } from '@babel/traverse';
|
||||||
|
import { addDefault } from '@babel/helper-module-imports';
|
||||||
import {
|
import {
|
||||||
createIdentifier,
|
createIdentifier,
|
||||||
transformJSXSpreadChild,
|
transformJSXSpreadChild,
|
||||||
@ -7,10 +8,295 @@ import {
|
|||||||
transformJSXExpressionContainer,
|
transformJSXExpressionContainer,
|
||||||
walksScope,
|
walksScope,
|
||||||
buildIIFE,
|
buildIIFE,
|
||||||
|
isDirective,
|
||||||
|
checkIsComponent,
|
||||||
|
getTag,
|
||||||
|
getJSXAttributeName,
|
||||||
|
isOn,
|
||||||
|
isConstant,
|
||||||
|
dedupeProperties,
|
||||||
|
transformJSXSpreadAttribute,
|
||||||
} from './utils';
|
} from './utils';
|
||||||
import buildProps from './buildProps';
|
|
||||||
import SlotFlags from './slotFlags';
|
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
|
* Get children from Array of JSX children
|
||||||
@ -211,8 +497,6 @@ const transformJSXElement = (
|
|||||||
]);
|
]);
|
||||||
};
|
};
|
||||||
|
|
||||||
export { transformJSXElement };
|
|
||||||
|
|
||||||
export default ({
|
export default ({
|
||||||
JSXElement: {
|
JSXElement: {
|
||||||
exit(path: NodePath<t.JSXElement>, state: State) {
|
exit(path: NodePath<t.JSXElement>, state: State) {
|
||||||
|
@ -2,12 +2,12 @@ import * as t from '@babel/types';
|
|||||||
import htmlTags from 'html-tags';
|
import htmlTags from 'html-tags';
|
||||||
import svgTags from 'svg-tags';
|
import svgTags from 'svg-tags';
|
||||||
import { NodePath } from '@babel/traverse';
|
import { NodePath } from '@babel/traverse';
|
||||||
import { State } from '.';
|
import type { State } from './interface';
|
||||||
import SlotFlags from './slotFlags';
|
import SlotFlags from './slotFlags';
|
||||||
|
|
||||||
const JSX_HELPER_KEY = 'JSX_HELPER_KEY';
|
export const JSX_HELPER_KEY = 'JSX_HELPER_KEY';
|
||||||
const FRAGMENT = 'Fragment';
|
export const FRAGMENT = 'Fragment';
|
||||||
const KEEP_ALIVE = 'KeepAlive';
|
export const KEEP_ALIVE = 'KeepAlive';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* create Identifier
|
* create Identifier
|
||||||
@ -16,7 +16,7 @@ const KEEP_ALIVE = 'KeepAlive';
|
|||||||
* @param name string
|
* @param name string
|
||||||
* @returns MemberExpression
|
* @returns MemberExpression
|
||||||
*/
|
*/
|
||||||
const createIdentifier = (
|
export const createIdentifier = (
|
||||||
state: State, name: string,
|
state: State, name: string,
|
||||||
): t.Identifier | t.MemberExpression => state.get(name)();
|
): t.Identifier | t.MemberExpression => state.get(name)();
|
||||||
|
|
||||||
@ -24,7 +24,7 @@ const createIdentifier = (
|
|||||||
* Checks if string is describing a directive
|
* Checks if string is describing a directive
|
||||||
* @param src string
|
* @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');
|
|| (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
|
* @param tag string
|
||||||
* @returns boolean
|
* @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
|
* Check if a Node is a component
|
||||||
@ -41,7 +41,7 @@ const shouldTransformedToSlots = (tag: string) => !(tag.endsWith(FRAGMENT) || ta
|
|||||||
* @param path JSXOpeningElement
|
* @param path JSXOpeningElement
|
||||||
* @returns boolean
|
* @returns boolean
|
||||||
*/
|
*/
|
||||||
const checkIsComponent = (path: NodePath<t.JSXOpeningElement>): boolean => {
|
export const checkIsComponent = (path: NodePath<t.JSXOpeningElement>): boolean => {
|
||||||
const namePath = path.get('name');
|
const namePath = path.get('name');
|
||||||
|
|
||||||
if (namePath.isJSXMemberExpression()) {
|
if (namePath.isJSXMemberExpression()) {
|
||||||
@ -58,7 +58,7 @@ const checkIsComponent = (path: NodePath<t.JSXOpeningElement>): boolean => {
|
|||||||
* @param path JSXMemberExpression
|
* @param path JSXMemberExpression
|
||||||
* @returns MemberExpression
|
* @returns MemberExpression
|
||||||
*/
|
*/
|
||||||
const transformJSXMemberExpression = (
|
export const transformJSXMemberExpression = (
|
||||||
path: NodePath<t.JSXMemberExpression>,
|
path: NodePath<t.JSXMemberExpression>,
|
||||||
): t.MemberExpression => {
|
): t.MemberExpression => {
|
||||||
const objectPath = path.node.object;
|
const objectPath = path.node.object;
|
||||||
@ -78,7 +78,7 @@ const transformJSXMemberExpression = (
|
|||||||
* @param state State
|
* @param state State
|
||||||
* @returns Identifier | StringLiteral | MemberExpression | CallExpression
|
* @returns Identifier | StringLiteral | MemberExpression | CallExpression
|
||||||
*/
|
*/
|
||||||
const getTag = (
|
export const getTag = (
|
||||||
path: NodePath<t.JSXElement>,
|
path: NodePath<t.JSXElement>,
|
||||||
state: State,
|
state: State,
|
||||||
): t.Identifier | t.CallExpression | t.StringLiteral | t.MemberExpression => {
|
): t.Identifier | t.CallExpression | t.StringLiteral | t.MemberExpression => {
|
||||||
@ -104,7 +104,7 @@ const getTag = (
|
|||||||
throw new Error(`getTag: ${namePath.type} is not supported`);
|
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;
|
const nameNode = path.node.name;
|
||||||
if (t.isJSXIdentifier(nameNode)) {
|
if (t.isJSXIdentifier(nameNode)) {
|
||||||
return nameNode.name;
|
return nameNode.name;
|
||||||
@ -118,7 +118,7 @@ const getJSXAttributeName = (path: NodePath<t.JSXAttribute>): string => {
|
|||||||
* @param path JSXText
|
* @param path JSXText
|
||||||
* @returns StringLiteral | null
|
* @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 { node } = path;
|
||||||
const lines = node.value.split(/\r\n|\n|\r/);
|
const lines = node.value.split(/\r\n|\n|\r/);
|
||||||
|
|
||||||
@ -169,7 +169,7 @@ const transformJSXText = (path: NodePath<t.JSXText>): t.StringLiteral | null =>
|
|||||||
* @param path JSXExpressionContainer
|
* @param path JSXExpressionContainer
|
||||||
* @returns Expression
|
* @returns Expression
|
||||||
*/
|
*/
|
||||||
const transformJSXExpressionContainer = (
|
export const transformJSXExpressionContainer = (
|
||||||
path: NodePath<t.JSXExpressionContainer>,
|
path: NodePath<t.JSXExpressionContainer>,
|
||||||
): (
|
): (
|
||||||
t.Expression
|
t.Expression
|
||||||
@ -180,11 +180,11 @@ const transformJSXExpressionContainer = (
|
|||||||
* @param path JSXSpreadChild
|
* @param path JSXSpreadChild
|
||||||
* @returns SpreadElement
|
* @returns SpreadElement
|
||||||
*/
|
*/
|
||||||
const transformJSXSpreadChild = (
|
export const transformJSXSpreadChild = (
|
||||||
path: NodePath<t.JSXSpreadChild>,
|
path: NodePath<t.JSXSpreadChild>,
|
||||||
): t.SpreadElement => t.spreadElement(path.get('expression').node);
|
): 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 (path.scope.hasBinding(name) && path.parentPath) {
|
||||||
if (t.isJSXElement(path.parentPath.node)) {
|
if (t.isJSXElement(path.parentPath.node)) {
|
||||||
path.parentPath.setData('slotFlag', slotFlag);
|
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;
|
const { parentPath } = path;
|
||||||
if (t.isAssignmentExpression(parentPath)) {
|
if (t.isAssignmentExpression(parentPath)) {
|
||||||
const { left } = parentPath.node as t.AssignmentExpression;
|
const { left } = parentPath.node as t.AssignmentExpression;
|
||||||
@ -221,19 +221,88 @@ const buildIIFE = (path: NodePath<t.JSXElement>, children: t.Expression[]) => {
|
|||||||
return children;
|
return children;
|
||||||
};
|
};
|
||||||
|
|
||||||
export {
|
const onRE = /^on[^a-z]/;
|
||||||
createIdentifier,
|
|
||||||
isDirective,
|
export const isOn = (key: string) => onRE.test(key);
|
||||||
checkIsComponent,
|
|
||||||
transformJSXMemberExpression,
|
const mergeAsArray = (existing: t.ObjectProperty, incoming: t.ObjectProperty) => {
|
||||||
getTag,
|
if (t.isArrayExpression(existing.value)) {
|
||||||
getJSXAttributeName,
|
existing.value.elements.push(incoming.value as t.Expression);
|
||||||
transformJSXText,
|
} else {
|
||||||
transformJSXSpreadChild,
|
existing.value = t.arrayExpression([
|
||||||
transformJSXExpressionContainer,
|
existing.value as t.Expression,
|
||||||
shouldTransformedToSlots,
|
incoming.value as t.Expression,
|
||||||
FRAGMENT,
|
]);
|
||||||
walksScope,
|
}
|
||||||
buildIIFE,
|
};
|
||||||
JSX_HELPER_KEY,
|
|
||||||
|
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"],
|
"rootDirs": ["./src"],
|
||||||
"outDir": "dist",
|
"outDir": "dist",
|
||||||
"downlevelIteration": true,
|
"downlevelIteration": true,
|
||||||
"types": ["node", "jest"],
|
|
||||||
"declaration": true
|
"declaration": true
|
||||||
},
|
},
|
||||||
"include": ["src/**/*", "global.d.ts"],
|
"include": ["src/**/*", "global.d.ts"],
|
||||||
|
@ -12,10 +12,15 @@
|
|||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
"removeComments": false,
|
"removeComments": false,
|
||||||
"jsx": "preserve",
|
"jsx": "preserve",
|
||||||
"lib": ["esnext", "dom"],
|
"lib": [
|
||||||
"types": ["node"]
|
"esnext",
|
||||||
|
"dom"
|
||||||
|
],
|
||||||
|
"types": ["node", "jest"],
|
||||||
},
|
},
|
||||||
"include": [
|
"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"
|
semver "^7.3.2"
|
||||||
tsutils "^3.17.1"
|
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":
|
"@typescript-eslint/experimental-utils@4.17.0":
|
||||||
version "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==
|
integrity sha512-ZR2NIUbnIBj+LGqCFGQ9yk2EBQrpVVFOh9/Kd0Lm6gLpSAcCuLLe5lUCibKGCqyH9HPwYC0GIJce2O1i8VYmWA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/json-schema" "^7.0.3"
|
"@types/json-schema" "^7.0.3"
|
||||||
@ -2189,9 +2215,27 @@
|
|||||||
"@typescript-eslint/typescript-estree" "4.22.0"
|
"@typescript-eslint/typescript-estree" "4.22.0"
|
||||||
debug "^4.1.1"
|
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":
|
"@typescript-eslint/scope-manager@4.17.0":
|
||||||
version "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==
|
integrity sha512-OJ+CeTliuW+UZ9qgULrnGpPQ1bhrZNFpfT/Bc0pzNeyZwMik7/ykJ0JHnQ7krHanFN9wcnPK89pwn84cRUmYjw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@typescript-eslint/types" "4.17.0"
|
"@typescript-eslint/types" "4.17.0"
|
||||||
@ -2199,25 +2243,43 @@
|
|||||||
|
|
||||||
"@typescript-eslint/scope-manager@4.22.0":
|
"@typescript-eslint/scope-manager@4.22.0":
|
||||||
version "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==
|
integrity sha512-OcCO7LTdk6ukawUM40wo61WdeoA7NM/zaoq1/2cs13M7GyiF+T4rxuA4xM+6LeHWjWbss7hkGXjFDRcKD4O04Q==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@typescript-eslint/types" "4.22.0"
|
"@typescript-eslint/types" "4.22.0"
|
||||||
"@typescript-eslint/visitor-keys" "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":
|
"@typescript-eslint/types@4.17.0":
|
||||||
version "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==
|
integrity sha512-RN5z8qYpJ+kXwnLlyzZkiJwfW2AY458Bf8WqllkondQIcN2ZxQowAToGSd9BlAUZDB5Ea8I6mqL2quGYCLT+2g==
|
||||||
|
|
||||||
"@typescript-eslint/types@4.22.0":
|
"@typescript-eslint/types@4.22.0":
|
||||||
version "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==
|
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":
|
"@typescript-eslint/typescript-estree@4.17.0":
|
||||||
version "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==
|
integrity sha512-lRhSFIZKUEPPWpWfwuZBH9trYIEJSI0vYsrxbvVvNyIUDoKWaklOAelsSkeh3E2VBSZiNe9BZ4E5tYBZbUczVQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@typescript-eslint/types" "4.17.0"
|
"@typescript-eslint/types" "4.17.0"
|
||||||
@ -2241,9 +2303,17 @@
|
|||||||
semver "^7.3.2"
|
semver "^7.3.2"
|
||||||
tsutils "^3.17.1"
|
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":
|
"@typescript-eslint/visitor-keys@4.17.0":
|
||||||
version "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==
|
integrity sha512-WfuMN8mm5SSqXuAr9NM+fItJ0SVVphobWYkWOwQ1odsfC014Vdxk/92t4JwS1Q6fCA/ABfCKpa3AVtpUKTNKGQ==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@typescript-eslint/types" "4.17.0"
|
"@typescript-eslint/types" "4.17.0"
|
||||||
@ -4602,7 +4672,7 @@ escodegen@^1.14.1:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
source-map "~0.6.1"
|
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"
|
version "14.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/eslint-config-airbnb-base/-/eslint-config-airbnb-base-14.2.1.tgz#8a2eb38455dc5a312550193b319cdaeef042cd1e"
|
resolved "https://registry.yarnpkg.com/eslint-config-airbnb-base/-/eslint-config-airbnb-base-14.2.1.tgz#8a2eb38455dc5a312550193b319cdaeef042cd1e"
|
||||||
integrity sha512-GOrQyDtVEc1Xy20U7vsB2yAoB4nBlfH5HZJeatRXHleO+OS5Ot+MWij4Dpltw4/DyIkqUfqz1epfhVR5XWWQPA==
|
integrity sha512-GOrQyDtVEc1Xy20U7vsB2yAoB4nBlfH5HZJeatRXHleO+OS5Ot+MWij4Dpltw4/DyIkqUfqz1epfhVR5XWWQPA==
|
||||||
@ -4611,6 +4681,24 @@ eslint-config-airbnb-base@^14.1.0:
|
|||||||
object.assign "^4.1.2"
|
object.assign "^4.1.2"
|
||||||
object.entries "^1.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:
|
eslint-import-resolver-node@^0.3.4:
|
||||||
version "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"
|
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"
|
debug "^2.6.9"
|
||||||
pkg-dir "^2.0.0"
|
pkg-dir "^2.0.0"
|
||||||
|
|
||||||
eslint-plugin-import@^2.20.2:
|
eslint-plugin-import@^2.22.1:
|
||||||
version "2.22.1"
|
version "2.22.1"
|
||||||
resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.22.1.tgz#0896c7e6a0cf44109a2d97b95903c2bb689d7702"
|
resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.22.1.tgz#0896c7e6a0cf44109a2d97b95903c2bb689d7702"
|
||||||
integrity sha512-8K7JjINHOpH64ozkAhpT3sd+FswIZTfMZTjdx052pnWrgRCVfp8op9tbjpAk3DdUeI/Ba4C8OjdC0r90erHEOw==
|
integrity sha512-8K7JjINHOpH64ozkAhpT3sd+FswIZTfMZTjdx052pnWrgRCVfp8op9tbjpAk3DdUeI/Ba4C8OjdC0r90erHEOw==
|
||||||
|
Loading…
Reference in New Issue
Block a user