refactor: with TypeScript (#24)

* refactor: add ts support (#19)

Co-authored-by: 逆寒 <869732751@qq.com>
This commit is contained in:
Amour1688 2020-07-09 20:51:47 +08:00 committed by GitHub
parent 3d49271878
commit bc4ef2c028
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 430 additions and 285 deletions

2
global.d.ts vendored Normal file
View File

@ -0,0 +1,2 @@
declare module '@babel/helper-module-imports';
declare module '@babel/plugin-syntax-jsx';

View File

@ -5,6 +5,7 @@
], ],
"scripts": { "scripts": {
"publish": "lerna publish", "publish": "lerna publish",
"test": "lerna run test",
"dev": "node scripts/dev.js", "dev": "node scripts/dev.js",
"site": "node scripts/site.js" "site": "node scripts/site.js"
}, },

2
packages/babel-plugin-jsx/global.d.ts vendored Normal file
View File

@ -0,0 +1,2 @@
declare module '@babel/helper-module-imports';
declare module '@babel/plugin-syntax-jsx';

View File

@ -12,9 +12,9 @@
}, },
"scripts": { "scripts": {
"dev": "npm run build && webpack-dev-server", "dev": "npm run build && webpack-dev-server",
"build": "rollup -c", "build": "tsc",
"lint": "eslint --ext .js src", "lint": "eslint --ext .js src",
"test": "jest --coverage" "test": "npm run build && jest --coverage"
}, },
"bugs": { "bugs": {
"url": "https://github.com/vueComponent/jsx/issues" "url": "https://github.com/vueComponent/jsx/issues"
@ -27,13 +27,14 @@
"@ant-design-vue/babel-helper-vue-transform-on": "^1.0.0", "@ant-design-vue/babel-helper-vue-transform-on": "^1.0.0",
"@babel/helper-module-imports": "^7.0.0", "@babel/helper-module-imports": "^7.0.0",
"@babel/plugin-syntax-jsx": "^7.0.0", "@babel/plugin-syntax-jsx": "^7.0.0",
"@babel/types": "^7.0.0",
"camelcase": "^6.0.0", "camelcase": "^6.0.0",
"html-tags": "^3.1.0", "html-tags": "^3.1.0",
"svg-tags": "^1.0.0" "svg-tags": "^1.0.0"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.9.6", "@babel/core": "^7.0.0",
"@babel/preset-env": "^7.9.6", "@babel/preset-env": "^7.0.0",
"@rollup/plugin-babel": "^5.0.3", "@rollup/plugin-babel": "^5.0.3",
"@vue/compiler-dom": "3.0.0-beta.20", "@vue/compiler-dom": "3.0.0-beta.20",
"@vue/test-utils": "^2.0.0-alpha.8", "@vue/test-utils": "^2.0.0-alpha.8",
@ -43,6 +44,7 @@
"regenerator-runtime": "^0.13.5", "regenerator-runtime": "^0.13.5",
"rollup": "^2.13.1", "rollup": "^2.13.1",
"vue": "3.0.0-beta.20", "vue": "3.0.0-beta.20",
"typescript": "^3.9.6",
"webpack": "^4.43.0", "webpack": "^4.43.0",
"webpack-cli": "^3.3.11", "webpack-cli": "^3.3.11",
"webpack-dev-server": "^3.10.3" "webpack-dev-server": "^3.10.3"

View File

@ -1,22 +1,12 @@
import babel from '@rollup/plugin-babel'; // import babel from '@rollup/plugin-babel';
import commonjs from '@rollup/plugin-commonjs';
import typescript from '@rollup/plugin-typescript';
export default { export default {
input: 'src/index.js', input: 'src/index.ts',
plugins: [ plugins: [
babel({ commonjs(),
presets: [ typescript(),
[
'@babel/preset-env',
{
targets: {
node: 8,
},
modules: false,
},
],
],
configFile: false,
}),
], ],
output: [ output: [
{ {

View File

@ -1,12 +0,0 @@
import syntaxJsx from '@babel/plugin-syntax-jsx';
import tranformVueJSX from './transform-vue-jsx';
import sugarFragment from './sugar-fragment';
export default ({ types: t }) => ({
name: 'babel-plugin-jsx',
inherits: syntaxJsx,
visitor: {
...tranformVueJSX(t),
...sugarFragment(t),
},
});

View File

@ -0,0 +1,25 @@
import syntaxJsx from '@babel/plugin-syntax-jsx';
import tranformVueJSX from './transform-vue-jsx';
import sugarFragment from './sugar-fragment';
export type State = {
get: (name: string) => any;
set: (name: string, value: any) => any;
opts: Opts;
}
interface Opts {
transformOn?: boolean;
compatibleProps?: boolean;
}
export type ExcludesFalse = <T>(x: T | false) => x is T;
export default () => ({
name: 'babel-plugin-jsx',
inherits: syntaxJsx,
visitor: {
...tranformVueJSX(),
...sugarFragment(),
},
});

View File

@ -0,0 +1,33 @@
// https://github.com/vuejs/vue-next/blob/master/packages/shared/src/patchFlags.ts
export const enum PatchFlags {
TEXT = 1,
CLASS = 1 << 1,
STYLE = 1 << 2,
PROPS = 1 << 3,
FULL_PROPS = 1 << 4,
HYDRATE_EVENTS = 1 << 5,
STABLE_FRAGMENT = 1 << 6,
KEYED_FRAGMENT = 1 << 7,
UNKEYED_FRAGMENT = 1 << 8,
NEED_PATCH = 1 << 9,
DYNAMIC_SLOTS = 1 << 10,
HOISTED = -1,
BAIL = -2
}
// dev only flag -> name mapping
export const PatchFlagNames = {
[PatchFlags.TEXT]: `TEXT`,
[PatchFlags.CLASS]: `CLASS`,
[PatchFlags.STYLE]: `STYLE`,
[PatchFlags.PROPS]: `PROPS`,
[PatchFlags.FULL_PROPS]: `FULL_PROPS`,
[PatchFlags.HYDRATE_EVENTS]: `HYDRATE_EVENTS`,
[PatchFlags.STABLE_FRAGMENT]: `STABLE_FRAGMENT`,
[PatchFlags.KEYED_FRAGMENT]: `KEYED_FRAGMENT`,
[PatchFlags.UNKEYED_FRAGMENT]: `UNKEYED_FRAGMENT`,
[PatchFlags.DYNAMIC_SLOTS]: `DYNAMIC_SLOTS`,
[PatchFlags.NEED_PATCH]: `NEED_PATCH`,
[PatchFlags.HOISTED]: `HOISTED`,
[PatchFlags.BAIL]: `BAIL`
}

View File

@ -1,6 +1,9 @@
import * as t from '@babel/types'
import { addNamespace } from '@babel/helper-module-imports'; import { addNamespace } from '@babel/helper-module-imports';
import { NodePath } from '@babel/traverse';
import { State } from './';
const transformFragment = (t, path, Fragment) => { const transformFragment = (path: NodePath<t.JSXElement>, Fragment: t.JSXMemberExpression) => {
const children = path.get('children') || []; const children = path.get('children') || [];
return t.jsxElement( return t.jsxElement(
t.jsxOpeningElement(Fragment, []), t.jsxOpeningElement(Fragment, []),
@ -10,15 +13,15 @@ const transformFragment = (t, path, Fragment) => {
); );
}; };
export default (t) => ({ export default () => ({
JSXFragment: { JSXFragment: {
enter(path, state) { enter(path: NodePath<t.JSXElement>, state: State) {
if (!state.get('vue')) { if (!state.get('vue')) {
state.set('vue', addNamespace(path, 'vue')); state.set('vue', addNamespace(path, 'vue'));
} }
path.replaceWith( path.replaceWith(
transformFragment( transformFragment(
t, path, path,
t.jsxMemberExpression( t.jsxMemberExpression(
t.jsxIdentifier(state.get('vue').name), t.jsxIdentifier(state.get('vue').name),
t.jsxIdentifier('Fragment'), t.jsxIdentifier('Fragment'),

View File

@ -1,39 +1,49 @@
import * as t from '@babel/types';
import { NodePath } from '@babel/traverse';
import { addDefault, addNamespace } from '@babel/helper-module-imports'; import { addDefault, addNamespace } from '@babel/helper-module-imports';
import { import {
createIdentifier, createIdentifier,
PatchFlags,
PatchFlagNames,
isDirective, isDirective,
checkIsComponent, checkIsComponent,
transformJSXSpreadChild,
getTag, getTag,
getJSXAttributeName, getJSXAttributeName,
transformJSXText, transformJSXText,
transformJSXExpressionContainer, transformJSXExpressionContainer,
transformJSXSpreadChild,
parseDirectives, parseDirectives,
isFragment, isFragment,
} from './utils'; } from './utils';
import { PatchFlags, PatchFlagNames } from './patchFlags';
import { State, ExcludesFalse } from './';
const xlinkRE = /^xlink([A-Z])/; const xlinkRE = /^xlink([A-Z])/;
const onRE = /^on[^a-z]/; const onRE = /^on[^a-z]/;
const isOn = (key) => onRE.test(key); const isOn = (key: string) => onRE.test(key);
const transformJSXSpreadAttribute = (t, path, mergeArgs) => { const transformJSXSpreadAttribute = (
const argument = path.get('argument').node; path: NodePath<t.JSXSpreadAttribute>,
const { properties } = argument; mergeArgs: (t.ObjectProperty | t.Expression)[]
) => {
const argument = path.get('argument') as NodePath<t.ObjectExpression>;
const { properties } = argument.node;
if (!properties) { if (!properties) {
// argument is an Identifier // argument is an Identifier
mergeArgs.push(argument); mergeArgs.push(argument.node);
} else { } else {
mergeArgs.push(t.objectExpression(properties)); mergeArgs.push(t.objectExpression(properties));
} }
}; };
const getJSXAttributeValue = (t, path, state) => { const getJSXAttributeValue = (
path: NodePath<t.JSXAttribute>,
state: State
): (
t.StringLiteral | t.Expression | null
) => {
const valuePath = path.get('value'); const valuePath = path.get('value');
if (valuePath.isJSXElement()) { if (valuePath.isJSXElement()) {
return transformJSXElement(t, valuePath, state); return transformJSXElement(valuePath, state);
} }
if (valuePath.isStringLiteral()) { if (valuePath.isStringLiteral()) {
return valuePath.node; return valuePath.node;
@ -47,46 +57,48 @@ const getJSXAttributeValue = (t, path, state) => {
/** /**
* Check if an attribute value is constant * Check if an attribute value is constant
* @param t
* @param path * @param path
* @returns boolean * @returns boolean
*/ */
const isConstant = (t, path) => { const isConstant = (
if (t.isIdentifier(path)) { node: t.Expression | t.Identifier | t.Literal | t.SpreadElement | null
return path.name === 'undefined'; ): boolean => {
if (t.isIdentifier(node)) {
return node.name === 'undefined';
} }
if (t.isArrayExpression(path)) { if (t.isArrayExpression(node)) {
return path.elements.every((element) => isConstant(t, element)); const elements = node.elements;
return elements.every((element) => element && isConstant(element));
} }
if (t.isObjectExpression(path)) { if (t.isObjectExpression(node)) {
return path.properties.every((property) => isConstant(t, property.value)); return node.properties.every((property) => isConstant((property as any).value));
} }
if (t.isLiteral(path)) { if (t.isLiteral(node)) {
return true; return true;
} }
return false; return false;
}; };
const mergeAsArray = (t, existing, incoming) => { const mergeAsArray = (existing: t.ObjectProperty, incoming: t.ObjectProperty) => {
if (t.isArrayExpression(existing.value)) { if (t.isArrayExpression(existing.value)) {
existing.value.elements.push(incoming.value); existing.value.elements.push(incoming.value as t.Expression);
} else { } else {
existing.value = t.arrayExpression([ existing.value = t.arrayExpression([
existing.value, existing.value as t.Expression,
incoming.value, incoming.value as t.Expression,
]); ]);
} }
}; };
const dedupeProperties = (t, properties = []) => { const dedupeProperties = (properties: t.ObjectProperty[] = []) => {
const knownProps = new Map(); const knownProps = new Map<string, t.ObjectProperty>();
const deduped = []; const deduped: t.ObjectProperty[] = [];
properties.forEach((prop) => { properties.forEach((prop) => {
const { key: { value: name } = {} } = prop; const { value: name } = prop.key as t.StringLiteral;
const existing = knownProps.get(name); const existing = knownProps.get(name);
if (existing) { if (existing) {
if (name === 'style' || name === 'class' || name.startsWith('on')) { if (name === 'style' || name === 'class' || name.startsWith('on')) {
mergeAsArray(t, existing, prop); mergeAsArray(existing, prop);
} }
} else { } else {
knownProps.set(name, prop); knownProps.set(name, prop);
@ -97,19 +109,17 @@ const dedupeProperties = (t, properties = []) => {
return deduped; return deduped;
}; };
const buildProps = (t, path, state, hasContainer) => { const buildProps = (path: NodePath<t.JSXElement>, state: State) => {
const tag = getTag(t, path); const tag = getTag(path, state);
const isComponent = checkIsComponent(t, path.get('openingElement')); const isComponent = checkIsComponent(path.get('openingElement'));
const props = path.get('openingElement').get('attributes'); const props = path.get('openingElement').get('attributes');
const directives = []; const directives: t.ArrayExpression[] = [];
const dynamicPropNames = new Set(); const dynamicPropNames = new Set();
let patchFlag = 0; let patchFlag = 0;
if (isFragment(t, path.get('openingElement.name'))) { if (isFragment(path.get('openingElement').get('name'))) {
patchFlag |= PatchFlags.STABLE_FRAGMENT; patchFlag |= PatchFlags.STABLE_FRAGMENT;
} else if (hasContainer) {
patchFlag |= PatchFlags.BAIL;
} }
if (props.length === 0) { if (props.length === 0) {
@ -122,7 +132,7 @@ const buildProps = (t, path, state, hasContainer) => {
}; };
} }
const properties = []; const properties: t.ObjectProperty[] = [];
// patchFlag analysis // patchFlag analysis
let hasRef = false; let hasRef = false;
@ -131,16 +141,15 @@ const buildProps = (t, path, state, hasContainer) => {
let hasHydrationEventBinding = false; let hasHydrationEventBinding = false;
let hasDynamicKeys = false; let hasDynamicKeys = false;
const mergeArgs = []; const mergeArgs: (t.CallExpression | t.ObjectProperty | t.Identifier)[] = [];
props props
.forEach((prop) => { .forEach((prop) => {
if (prop.isJSXAttribute()) { if (prop.isJSXAttribute()) {
let name = getJSXAttributeName(t, prop); let name = getJSXAttributeName(prop);
const attributeValue = getJSXAttributeValue(t, prop); const attributeValue = getJSXAttributeValue(prop, state);
if (!isConstant(t, attributeValue) || name === 'ref') { if (!isConstant(attributeValue) || name === 'ref') {
if ( if (
!isComponent !isComponent
&& isOn(name) && isOn(name)
@ -182,16 +191,14 @@ const buildProps = (t, path, state, hasContainer) => {
return; return;
} }
if (isDirective(name)) { if (isDirective(name)) {
const { directive, modifiers, directiveName } = parseDirectives( const { directive, modifiers, directiveName } = parseDirectives({
t, { tag,
tag, isComponent,
isComponent, name,
name, path: prop,
path: prop, state,
state, value: attributeValue,
value: attributeValue, });
},
);
if (directive) { if (directive) {
directives.push(t.arrayExpression(directive)); directives.push(t.arrayExpression(directive));
@ -199,6 +206,7 @@ const buildProps = (t, path, state, hasContainer) => {
// must be v-model and is a component // must be v-model and is a component
properties.push(t.objectProperty( properties.push(t.objectProperty(
t.stringLiteral('modelValue'), t.stringLiteral('modelValue'),
// @ts-ignore
attributeValue, attributeValue,
)); ));
@ -219,11 +227,12 @@ const buildProps = (t, path, state, hasContainer) => {
} }
} }
if (directiveName === 'model') { if (directiveName === 'model' && attributeValue) {
properties.push(t.objectProperty( properties.push(t.objectProperty(
t.stringLiteral('onUpdate:modelValue'), t.stringLiteral('onUpdate:modelValue'),
t.arrowFunctionExpression( t.arrowFunctionExpression(
[t.identifier('$event')], [t.identifier('$event')],
// @ts-ignore
t.assignmentExpression('=', attributeValue, t.identifier('$event')), t.assignmentExpression('=', attributeValue, t.identifier('$event')),
), ),
)); ));
@ -240,8 +249,9 @@ const buildProps = (t, path, state, hasContainer) => {
attributeValue || t.booleanLiteral(true), attributeValue || t.booleanLiteral(true),
)); ));
} else { } else {
// JSXSpreadAttribute
hasDynamicKeys = true; hasDynamicKeys = true;
transformJSXSpreadAttribute(t, prop, mergeArgs); transformJSXSpreadAttribute(prop as NodePath<t.JSXSpreadAttribute>, mergeArgs);
} }
}); });
@ -270,15 +280,15 @@ const buildProps = (t, path, state, hasContainer) => {
patchFlag |= PatchFlags.NEED_PATCH; patchFlag |= PatchFlags.NEED_PATCH;
} }
let propsExpression = t.nullLiteral(); let propsExpression: t.Expression | t.ObjectProperty | t.Literal = t.nullLiteral();
if (mergeArgs.length) { if (mergeArgs.length) {
if (properties.length) { if (properties.length) {
mergeArgs.push(...dedupeProperties(t, properties)); mergeArgs.push(...dedupeProperties(properties));
} }
if (mergeArgs.length > 1) { if (mergeArgs.length > 1) {
const exps = []; const exps: (t.CallExpression | t.Identifier)[] = [];
const objectProperties = []; const objectProperties: t.ObjectProperty[] = [];
mergeArgs.forEach((arg) => { mergeArgs.forEach((arg) => {
if (t.isIdentifier(arg) || t.isExpression(arg)) { if (t.isIdentifier(arg) || t.isExpression(arg)) {
exps.push(arg); exps.push(arg);
@ -287,20 +297,18 @@ const buildProps = (t, path, state, hasContainer) => {
} }
}); });
propsExpression = t.callExpression( propsExpression = t.callExpression(
createIdentifier(t, state, 'mergeProps'), createIdentifier(state, 'mergeProps'),
[ [
...exps, ...exps,
objectProperties.length !!objectProperties.length && t.objectExpression(objectProperties),
&& t.objectExpression(objectProperties), ].filter(Boolean as any as ExcludesFalse),
].filter(Boolean),
); );
} else { } else {
// single no need for a mergeProps call // single no need for a mergeProps call
// eslint-disable-next-line prefer-destructuring
propsExpression = mergeArgs[0]; propsExpression = mergeArgs[0];
} }
} else if (properties.length) { } else if (properties.length) {
propsExpression = t.objectExpression(dedupeProperties(t, properties)); propsExpression = t.objectExpression(dedupeProperties(properties));
} }
return { return {
@ -314,50 +322,59 @@ const buildProps = (t, path, state, hasContainer) => {
/** /**
* Get children from Array of JSX children * Get children from Array of JSX children
* @param t * @param paths Array<JSXText | JSXExpressionContainer | JSXElement | JSXFragment>
* @param paths Array<JSXText | JSXExpressionContainer | JSXSpreadChild | JSXElement>
* @returns Array<Expression | SpreadElement> * @returns Array<Expression | SpreadElement>
*/ */
const getChildren = (t, paths, state) => { const getChildren = (
let hasContainer = false; paths: NodePath<
return { t.JSXText
children: paths | t.JSXExpressionContainer
.map((path) => { | t.JSXSpreadChild
if (path.isJSXText()) { | t.JSXElement
return transformJSXText(t, path); | t.JSXFragment
>[],
state: State
): t.Expression[] =>
paths
.map((path) => {
if (path.isJSXText()) {
const transformedText = transformJSXText(path);
if (transformedText) {
return t.callExpression(createIdentifier(state, 'createTextVNode'), [transformedText]);
} }
if (path.isJSXExpressionContainer()) { return transformedText;
hasContainer = true; }
return transformJSXExpressionContainer(path); if (path.isJSXExpressionContainer()) {
} return transformJSXExpressionContainer(path);
if (path.isJSXSpreadChild()) { }
return transformJSXSpreadChild(t, path); if (t.isJSXSpreadChild(path)) {
} return transformJSXSpreadChild(path as NodePath<t.JSXSpreadChild>);
if (path.isCallExpression()) { }
return path.node; if (path.isCallExpression()) {
} return path.node;
if (path.isJSXElement()) { }
return transformJSXElement(t, path, state); if (path.isJSXElement()) {
} return transformJSXElement(path, state);
throw new Error(`getChildren: ${path.type} is not supported`); }
}).filter((value) => ( throw new Error(`getChildren: ${path.type} is not supported`);
value !== undefined }).filter(((value: any) => (
value !== undefined
&& value !== null && value !== null
&& !t.isJSXEmptyExpression(value) && !t.isJSXEmptyExpression(value)
)), )) as any);
hasContainer,
};
};
const transformJSXElement = (t, path, state) => { const transformJSXElement = (
const { children, hasContainer } = getChildren(t, path.get('children'), state); path: NodePath<t.JSXElement>,
state: State
): t.CallExpression => {
const children = getChildren(path.get('children'), state);
const { const {
tag, tag,
props, props,
directives, directives,
patchFlag, patchFlag,
dynamicPropNames, dynamicPropNames,
} = buildProps(t, path, state, hasContainer); } = buildProps(path, state);
const flagNames = Object.keys(PatchFlagNames) const flagNames = Object.keys(PatchFlagNames)
.map(Number) .map(Number)
@ -365,10 +382,6 @@ const transformJSXElement = (t, path, state) => {
.map((n) => PatchFlagNames[n]) .map((n) => PatchFlagNames[n])
.join(', '); .join(', ');
const isComponent = checkIsComponent(t, path.get('openingElement'));
const child = children.length === 1 && t.isStringLiteral(children[0])
? children[0] : t.arrayExpression(children);
const { compatibleProps } = state.opts; const { compatibleProps } = state.opts;
if (compatibleProps && !state.get('compatibleProps')) { if (compatibleProps && !state.get('compatibleProps')) {
state.set('compatibleProps', addDefault( state.set('compatibleProps', addDefault(
@ -376,53 +389,35 @@ const transformJSXElement = (t, path, state) => {
)); ));
} }
const createVNode = t.callExpression(createIdentifier(t, state, 'createVNode'), [ // @ts-ignore
const createVNode = t.callExpression(createIdentifier(state, 'createVNode'), [
tag, tag,
// @ts-ignore
compatibleProps ? t.callExpression(state.get('compatibleProps'), [props]) : props, compatibleProps ? t.callExpression(state.get('compatibleProps'), [props]) : props,
children[0] !!children.length ? t.arrayExpression(children) : t.nullLiteral(),
? ( !!patchFlag && t.addComment(t.numericLiteral(patchFlag), 'trailing', ` ${flagNames} `, false),
isComponent !!dynamicPropNames.size
? t.objectExpression([ && t.arrayExpression([...dynamicPropNames.keys()].map((name) => t.stringLiteral(name as string))),
t.objectProperty( ].filter(Boolean as any as ExcludesFalse));
t.identifier('default'),
t.callExpression(createIdentifier(t, state, 'withCtx'), [
t.arrowFunctionExpression(
[],
t.isStringLiteral(child)
? t.callExpression(
createIdentifier(t, state, 'createTextVNode'),
[child],
)
: child,
),
]),
),
])
: child
) : t.nullLiteral(),
patchFlag && t.addComment(t.numericLiteral(patchFlag), 'trailing', ` ${flagNames} `, false),
dynamicPropNames.size
&& t.arrayExpression([...dynamicPropNames.keys()].map((name) => t.stringLiteral(name))),
].filter(Boolean));
if (!directives.length) { if (!directives.length) {
return createVNode; return createVNode;
} }
return t.callExpression(createIdentifier(t, state, 'withDirectives'), [ return t.callExpression(createIdentifier(state, 'withDirectives'), [
createVNode, createVNode,
t.arrayExpression(directives), t.arrayExpression(directives),
]); ]);
}; };
export default (t) => ({ export default () => ({
JSXElement: { JSXElement: {
exit(path, state) { exit(path: NodePath<t.JSXElement>, state: State) {
if (!state.get('vue')) { if (!state.get('vue')) {
state.set('vue', addNamespace(path, 'vue')); state.set('vue', addNamespace(path, 'vue'));
} }
path.replaceWith( path.replaceWith(
transformJSXElement(t, path, state), transformJSXElement(path, state),
); );
}, },
}, },

View File

@ -1,119 +1,97 @@
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 { State, ExcludesFalse } from './';
const PatchFlags = { /**
TEXT: 1, * create Identifier
CLASS: 1 << 1, * @param state
STYLE: 1 << 2, * @param id string
PROPS: 1 << 3, * @returns MemberExpression
FULL_PROPS: 1 << 4, */
HYDRATE_EVENTS: 1 << 5, const createIdentifier = (
STABLE_FRAGMENT: 1 << 6, state: State, id: string
KEYED_FRAGMENT: 1 << 7, ): t.MemberExpression => t.memberExpression(state.get('vue'), t.identifier(id));
UNKEYED_FRAGMENT: 1 << 8,
NEED_PATCH: 1 << 9,
DYNAMIC_SLOTS: 1 << 10,
HOISTED: -1,
BAIL: -2,
};
// dev only flag -> name mapping
const PatchFlagNames = {
[PatchFlags.TEXT]: 'TEXT',
[PatchFlags.CLASS]: 'CLASS',
[PatchFlags.STYLE]: 'STYLE',
[PatchFlags.PROPS]: 'PROPS',
[PatchFlags.FULL_PROPS]: 'FULL_PROPS',
[PatchFlags.HYDRATE_EVENTS]: 'HYDRATE_EVENTS',
[PatchFlags.STABLE_FRAGMENT]: 'STABLE_FRAGMENT',
[PatchFlags.KEYED_FRAGMENT]: 'KEYED_FRAGMENT',
[PatchFlags.UNKEYED_FRAGMENT]: 'UNKEYED_FRAGMENT',
[PatchFlags.NEED_PATCH]: 'NEED_PATCH',
[PatchFlags.DYNAMIC_SLOTS]: 'DYNAMIC_SLOTS',
[PatchFlags.HOISTED]: 'HOISTED',
[PatchFlags.BAIL]: 'BAIL',
};
const createIdentifier = (t, state, id) => t.memberExpression(state.get('vue'), t.identifier(id));
/** /**
* Checks if string is describing a directive * Checks if string is describing a directive
* @param src string * @param src string
*/ */
const isDirective = (src) => src.startsWith('v-') 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');
/** /**
* Check if a JSXOpeningElement is fragment * Check if a Node is fragment
* @param {*} t * @param {*} path JSXIdentifier | JSXMemberExpression | JSXNamespacedName
* @param {*} path
* @returns boolean * @returns boolean
*/ */
const isFragment = (t, path) => t.isJSXMemberExpression(path) const isFragment = (path: NodePath<t.JSXIdentifier | t.JSXMemberExpression | t.JSXNamespacedName>) =>
&& path.node.property.name === 'Fragment'; t.isJSXMemberExpression(path)
&& (path.node as t.JSXMemberExpression).property.name === 'Fragment';
/** /**
* Check if a JSXOpeningElement is a component * Check if a Node is a component
* *
* @param t * @param t
* @param path JSXOpeningElement * @param path JSXOpeningElement
* @returns boolean * @returns boolean
*/ */
const checkIsComponent = (t, path) => { const checkIsComponent = (path: NodePath<t.JSXOpeningElement>): boolean => {
const namePath = path.get('name'); const namePath = path.get('name');
if (t.isJSXMemberExpression(namePath)) { if (t.isJSXMemberExpression(namePath)) {
return !isFragment(t, namePath); // For withCtx return !isFragment(namePath); // For withCtx
} }
const tag = namePath.get('name').node; const tag = (namePath as NodePath<t.JSXIdentifier>).get('name');
return !htmlTags.includes(tag) && !svgTags.includes(tag); return !htmlTags.includes(tag) && !svgTags.includes(tag);
}; };
/** /**
* Transform JSXMemberExpression to MemberExpression * Transform JSXMemberExpression to MemberExpression
* @param t
* @param path JSXMemberExpression * @param path JSXMemberExpression
* @returns MemberExpression * @returns MemberExpression
*/ */
const transformJSXMemberExpression = (t, path) => { const transformJSXMemberExpression = (path: NodePath<t.JSXMemberExpression>): t.MemberExpression => {
const objectPath = path.get('object'); const objectPath = path.node.object;
const propertyPath = path.get('property'); const propertyPath = path.node.property;
const transformedObject = t.isJSXMemberExpression(objectPath)
const transformedObject = objectPath.isJSXMemberExpression() ? transformJSXMemberExpression(path.get('object') as NodePath<t.JSXMemberExpression>)
? transformJSXMemberExpression(t, objectPath) : t.isJSXIdentifier(objectPath)
: objectPath.isJSXIdentifier() ? t.identifier(objectPath.name)
? t.identifier(objectPath.node.name)
: t.nullLiteral(); : t.nullLiteral();
const transformedProperty = t.identifier(propertyPath.get('name').node); const transformedProperty = t.identifier(propertyPath.name);
return t.memberExpression(transformedObject, transformedProperty); return t.memberExpression(transformedObject, transformedProperty);
}; };
/** /**
* Get tag (first attribute for h) from JSXOpeningElement * Get tag (first attribute for h) from JSXOpeningElement
* @param t * @param path JSXElement
* @param path JSXOpeningElement * @param state State
* @returns Identifier | StringLiteral | MemberExpression * @returns Identifier | StringLiteral | MemberExpression
*/ */
const getTag = (t, path) => { const getTag = (path: NodePath<t.JSXElement>, state: State) => {
const namePath = path.get('openingElement').get('name'); const namePath = path.get('openingElement').get('name');
if (namePath.isJSXIdentifier()) { if (namePath.isJSXIdentifier()) {
const { name } = namePath.node; const { name } = namePath.node;
if (path.scope.hasBinding(name) && !htmlTags.includes(name) && !svgTags.includes(name)) { if (!htmlTags.includes(name) && !svgTags.includes(name)) {
return t.identifier(name); return path.scope.hasBinding(name)
? t.identifier(name)
: t.callExpression(createIdentifier(state, 'resolveComponent'), [t.stringLiteral(name)]);
} }
return t.stringLiteral(name); return t.stringLiteral(name);
} }
if (namePath.isJSXMemberExpression()) { if (namePath.isJSXMemberExpression()) {
return transformJSXMemberExpression(t, namePath); return transformJSXMemberExpression(namePath);
} }
throw new Error(`getTag: ${namePath.type} is not supported`); throw new Error(`getTag: ${namePath.type} is not supported`);
}; };
const getJSXAttributeName = (t, path) => { 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;
@ -124,11 +102,10 @@ const getJSXAttributeName = (t, path) => {
/** /**
* Transform JSXText to StringLiteral * Transform JSXText to StringLiteral
* @param t
* @param path JSXText * @param path JSXText
* @returns StringLiteral * @returns StringLiteral | null
*/ */
const transformJSXText = (t, path) => { 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/);
@ -179,64 +156,69 @@ const transformJSXText = (t, path) => {
* @param path JSXExpressionContainer * @param path JSXExpressionContainer
* @returns Expression * @returns Expression
*/ */
const transformJSXExpressionContainer = (path) => path.get('expression').node; const transformJSXExpressionContainer = (
path: NodePath<t.JSXExpressionContainer>
): (t.Expression) => path.get('expression').node as t.Expression;
/** /**
* Transform JSXSpreadChild * Transform JSXSpreadChild
* @param t
* @param path JSXSpreadChild * @param path JSXSpreadChild
* @returns SpreadElement * @returns SpreadElement
*/ */
const transformJSXSpreadChild = (t, path) => t.spreadElement(path.get('expression').node); const transformJSXSpreadChild = (
path: NodePath<t.JSXSpreadChild>
): t.SpreadElement => t.spreadElement(path.get('expression').node);
/** /**
* Get JSX element type * Get JSX element type
* *
* @param t
* @param path Path<JSXOpeningElement> * @param path Path<JSXOpeningElement>
*/ */
const getType = (t, path) => { const getType = (path: NodePath<t.JSXOpeningElement>) => {
const typePath = path const typePath = path
.get('attributes') .get('attributes')
.find( .find((attribute) => {
(attributePath) => t.isJSXAttribute(attributePath) if (!t.isJSXAttribute(attribute)) {
&& t.isJSXIdentifier(attributePath.get('name')) return false;
&& attributePath.get('name.name').node === 'type' }
&& t.isStringLiteral(attributePath.get('value')), return t.isJSXIdentifier(attribute.get('name'))
&& (attribute.get('name') as NodePath<t.JSXIdentifier>).get('name') === 'type'
&& t.isStringLiteral(attribute.get('value'))
},
); );
return typePath ? typePath.get('value.value').node : ''; return typePath ? typePath.get('value.value') : '';
}; };
const resolveDirective = (t, path, state, tag, directiveName) => { const resolveDirective = (path: NodePath<t.JSXAttribute>, state: State, tag: any, directiveName: string) => {
if (directiveName === 'show') { if (directiveName === 'show') {
return createIdentifier(t, state, 'vShow'); return createIdentifier(state, 'vShow');
} if (directiveName === 'model') { } if (directiveName === 'model') {
let modelToUse; let modelToUse;
const type = getType(t, path.parentPath); const type = getType(path.parentPath as NodePath<t.JSXOpeningElement>);
switch (tag.value) { switch (tag.value) {
case 'select': case 'select':
modelToUse = createIdentifier(t, state, 'vModelSelect'); modelToUse = createIdentifier(state, 'vModelSelect');
break; break;
case 'textarea': case 'textarea':
modelToUse = createIdentifier(t, state, 'vModelText'); modelToUse = createIdentifier(state, 'vModelText');
break; break;
default: default:
switch (type) { switch (type) {
case 'checkbox': case 'checkbox':
modelToUse = createIdentifier(t, state, 'vModelCheckbox'); modelToUse = createIdentifier(state, 'vModelCheckbox');
break; break;
case 'radio': case 'radio':
modelToUse = createIdentifier(t, state, 'vModelRadio'); modelToUse = createIdentifier(state, 'vModelRadio');
break; break;
default: default:
modelToUse = createIdentifier(t, state, 'vModelText'); modelToUse = createIdentifier(state, 'vModelText');
} }
} }
return modelToUse; return modelToUse;
} }
return t.callExpression( return t.callExpression(
createIdentifier(t, state, 'resolveDirective'), [ createIdentifier(state, 'resolveDirective'), [
t.stringLiteral(directiveName), t.stringLiteral(directiveName),
], ],
); );
@ -245,18 +227,25 @@ const resolveDirective = (t, path, state, tag, directiveName) => {
/** /**
* Parse directives metadata * Parse directives metadata
* *
* @param t
* @param path JSXAttribute * @param path JSXAttribute
* @returns null | Object<{ modifiers: Set<string>, valuePath: Path<Expression>}> * @returns null | Object<{ modifiers: Set<string>, valuePath: Path<Expression>}>
*/ */
const parseDirectives = (t, { const parseDirectives = (args: {
name, path, value, state, tag, isComponent, name: string,
path: NodePath<t.JSXAttribute>,
value: t.StringLiteral | t.Expression | null,
state: State,
tag: t.Identifier | t.MemberExpression | t.StringLiteral | t.CallExpression,
isComponent: boolean
}) => { }) => {
const modifiers = name.split('_'); const {
const directiveName = modifiers.shift() name, path, value, state, tag, isComponent,
.replace(/^v/, '') } = args
const modifiers: string[] = name.split('_');
const directiveName: string = modifiers.shift()
?.replace(/^v/, '')
.replace(/^-/, '') .replace(/^-/, '')
.replace(/^\S/, (s) => s.toLowerCase()); .replace(/^\S/, (s: string) => s.toLowerCase()) || '';
if (directiveName === 'model' && !t.isJSXExpressionContainer(path.get('value'))) { if (directiveName === 'model' && !t.isJSXExpressionContainer(path.get('value'))) {
throw new Error('You have to use JSX Expression inside your v-model'); throw new Error('You have to use JSX Expression inside your v-model');
@ -270,10 +259,10 @@ const parseDirectives = (t, {
directiveName, directiveName,
modifiers: modifiersSet, modifiers: modifiersSet,
directive: hasDirective ? [ directive: hasDirective ? [
resolveDirective(t, path, state, tag, directiveName), resolveDirective(path, state, tag, directiveName),
value, value,
modifiersSet.size && t.unaryExpression('void', t.numericLiteral(0), true), !!modifiersSet.size && t.unaryExpression('void', t.numericLiteral(0), true),
modifiersSet.size && t.objectExpression( !!modifiersSet.size && t.objectExpression(
[...modifiersSet].map( [...modifiersSet].map(
(modifier) => t.objectProperty( (modifier) => t.objectProperty(
t.identifier(modifier), t.identifier(modifier),
@ -281,7 +270,7 @@ const parseDirectives = (t, {
), ),
), ),
), ),
].filter(Boolean) : undefined, ].filter(Boolean as any as ExcludesFalse) : undefined,
}; };
}; };
@ -295,8 +284,6 @@ export {
transformJSXText, transformJSXText,
transformJSXSpreadChild, transformJSXSpreadChild,
transformJSXExpressionContainer, transformJSXExpressionContainer,
PatchFlags,
PatchFlagNames,
parseDirectives, parseDirectives,
isFragment, isFragment,
}; };

View File

@ -3,6 +3,7 @@ import { shallowMount, mount } from '@vue/test-utils';
const patchFlagExpect = (wrapper, flag, dynamic) => { const patchFlagExpect = (wrapper, flag, dynamic) => {
const { patchFlag, dynamicProps } = wrapper.vm.$.subTree; const { patchFlag, dynamicProps } = wrapper.vm.$.subTree;
expect(patchFlag).toBe(flag); expect(patchFlag).toBe(flag);
expect(dynamicProps).toEqual(dynamic); expect(dynamicProps).toEqual(dynamic);
}; };

View File

@ -0,0 +1,13 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"rootDirs": ["./src"],
"outDir": "dist",
"downlevelIteration": true
},
"include": [
"src/**/*",
"global.d.ts"
],
"exclude": ["node_modules"]
}

View File

@ -8,12 +8,13 @@
"devDependencies": { "devDependencies": {
"@ant-design-vue/babel-plugin-jsx": "^1.0.0-alpha.6", "@ant-design-vue/babel-plugin-jsx": "^1.0.0-alpha.6",
"@babel/core": "^7.0.0", "@babel/core": "^7.0.0",
"babel-loader": "^8.1.0",
"css-loader": "^3.5.3", "css-loader": "^3.5.3",
"file-loader": "^6.0.0", "file-loader": "^6.0.0",
"html-webpack-plugin": "^4.3.0", "html-webpack-plugin": "^4.3.0",
"monaco-editor-webpack-plugin": "^1.9.0", "monaco-editor-webpack-plugin": "^1.9.0",
"style-loader": "^1.2.1", "style-loader": "^1.2.1",
"ts-loader": "^8.0.0",
"typescript": "^3.9.6",
"url-loader": "^4.1.0", "url-loader": "^4.1.0",
"vue": "3.0.0-beta.20", "vue": "3.0.0-beta.20",
"webpack": "^4.43.0", "webpack": "^4.43.0",

View File

@ -12,13 +12,15 @@ createApp(
() => h('h1', null, 'Vue JSX Explorer'), () => h('h1', null, 'Vue JSX Explorer'),
).mount('#header'); ).mount('#header');
// @ts-ignore
if (module.hot) { if (module.hot) {
// @ts-ignore
module.hot.accept('../../babel-plugin-jsx/src', () => { module.hot.accept('../../babel-plugin-jsx/src', () => {
compile(); compile();
}); });
} }
const sharedEditorOptions = { const sharedEditorOptions: monaco.editor.IStandaloneEditorConstructionOptions = {
theme: 'vs-dark', theme: 'vs-dark',
fontSize: 14, fontSize: 14,
wordWrap: 'on', wordWrap: 'on',
@ -39,14 +41,14 @@ monaco.languages.typescript.typescriptDefaults.setCompilerOptions({
typeRoots: ['node_modules/@types'], typeRoots: ['node_modules/@types'],
}); });
const editor = monaco.editor.create(document.getElementById('source'), { const editor = monaco.editor.create(document.getElementById('source')!, {
value: decodeURIComponent(window.location.hash.slice(1)) || localStorage.getItem('state') || 'const App = () => <div>Hello World</div>', value: decodeURIComponent(window.location.hash.slice(1)) || localStorage.getItem('state') || 'const App = () => <div>Hello World</div>',
language: 'javascript', language: 'javascript',
tabSize: 2, tabSize: 2,
...sharedEditorOptions, ...sharedEditorOptions,
}); });
const output = monaco.editor.create(document.getElementById('output'), { const output = monaco.editor.create(document.getElementById('output')!, {
value: '', value: '',
language: 'javascript', language: 'javascript',
readOnly: true, readOnly: true,
@ -63,12 +65,13 @@ const compile = () => {
babelrc: false, babelrc: false,
plugins: [[babelPluginJSx, { transformOn: true }]], plugins: [[babelPluginJSx, { transformOn: true }]],
ast: true, ast: true,
}, (err, result) => { }, (err, result = {}) => {
const res = result!;
if (!err) { if (!err) {
console.log('AST', result.ast); console.log('AST', res.ast!);
output.setValue(result.code); output.setValue(res.code!);
} else { } else {
output.setValue(err.message); output.setValue(err.message!);
} }
}); });
}; };
@ -84,15 +87,18 @@ compile();
// update compile output when input changes // update compile output when input changes
editor.onDidChangeModelContent(debounce(compile)); editor.onDidChangeModelContent(debounce(compile));
function debounce(fn, delay = 300) { function debounce<T extends (...args: any[]) => any>(
let prevTimer = null; fn: T,
return ((...args) => { delay: number = 300
): T {
let prevTimer: number | null = null
return ((...args: any[]) => {
if (prevTimer) { if (prevTimer) {
clearTimeout(prevTimer); clearTimeout(prevTimer)
} }
prevTimer = window.setTimeout(() => { prevTimer = window.setTimeout(() => {
fn(...args); fn(...args)
prevTimer = null; prevTimer = null
}, delay); }, delay)
}); }) as any
} }

View File

@ -4,25 +4,28 @@ const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = { module.exports = {
mode: 'development', mode: 'development',
devtool: 'cheap-module-eval-source-map', devtool: false,
context: path.join(__dirname, '../packages/jsx-explorer'), context: path.join(__dirname, '../packages/jsx-explorer'),
entry: './src/index.js', entry: './src/index.ts',
output: { output: {
publicPath: './', publicPath: './',
}, },
module: { module: {
rules: [ rules: [
{ {
test: /\.jsx?$/, test: /\.tsx?$/,
loader: 'babel-loader', loader: 'ts-loader',
exclude: /node_modules/, exclude: /node_modules/,
options: {
compilerOptions: { downlevelIteration: true },
},
}, },
{ {
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader', loader: 'url-loader',
options: { options: {
limit: 10000, limit: 10000,
name: 'dist/fonts/[name].[hash:7].[ext]', name: 'fonts/[name].[hash:7].[ext]',
}, },
}, },
{ {
@ -40,6 +43,9 @@ module.exports = {
filename: 'index.html', filename: 'index.html',
}), }),
], ],
resolve: {
extensions: ['.ts', '.js'],
},
node: { node: {
fs: 'empty', fs: 'empty',
}, },

21
tsconfig.json Normal file
View File

@ -0,0 +1,21 @@
{
"compilerOptions": {
"sourceMap": false,
"target": "es5",
"module": "commonjs",
"moduleResolution": "node",
"allowJs": false,
"strict": true,
"noUnusedLocals": true,
"experimentalDecorators": true,
"resolveJsonModule": true,
"esModuleInterop": true,
"removeComments": false,
"jsx": "preserve",
"lib": ["esnext", "dom"],
"types": ["node"],
},
"include": [
"global.d.ts"
]
}

View File

@ -224,6 +224,11 @@
resolved "https://r.cnpmjs.org/@babel/helper-validator-identifier/download/@babel/helper-validator-identifier-7.10.1.tgz#5770b0c1a826c4f53f5ede5e153163e0318e94b5" resolved "https://r.cnpmjs.org/@babel/helper-validator-identifier/download/@babel/helper-validator-identifier-7.10.1.tgz#5770b0c1a826c4f53f5ede5e153163e0318e94b5"
integrity sha1-V3CwwagmxPU/Xt5eFTFj4DGOlLU= integrity sha1-V3CwwagmxPU/Xt5eFTFj4DGOlLU=
"@babel/helper-validator-identifier@^7.10.4":
version "7.10.4"
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz#a78c7a7251e01f616512d31b10adcf52ada5e0d2"
integrity sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==
"@babel/helper-wrap-function@^7.10.1": "@babel/helper-wrap-function@^7.10.1":
version "7.10.1" version "7.10.1"
resolved "https://r.cnpmjs.org/@babel/helper-wrap-function/download/@babel/helper-wrap-function-7.10.1.tgz#956d1310d6696257a7afd47e4c42dfda5dfcedc9" resolved "https://r.cnpmjs.org/@babel/helper-wrap-function/download/@babel/helper-wrap-function-7.10.1.tgz#956d1310d6696257a7afd47e4c42dfda5dfcedc9"
@ -817,6 +822,15 @@
lodash "^4.17.13" lodash "^4.17.13"
to-fast-properties "^2.0.0" to-fast-properties "^2.0.0"
"@babel/types@^7.10.4":
version "7.10.4"
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.10.4.tgz#369517188352e18219981efd156bfdb199fff1ee"
integrity sha512-UTCFOxC3FsFHb7lkRMVvgLzaRVamXuAs2Tz4wajva4WxtVY82eZeaUBtC2Zt95FU9TiznuC0Zk35tsim8jeVpg==
dependencies:
"@babel/helper-validator-identifier" "^7.10.4"
lodash "^4.17.13"
to-fast-properties "^2.0.0"
"@bcoe/v8-coverage@^0.2.3": "@bcoe/v8-coverage@^0.2.3":
version "0.2.3" version "0.2.3"
resolved "https://r.cnpmjs.org/@bcoe/v8-coverage/download/@bcoe/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" resolved "https://r.cnpmjs.org/@bcoe/v8-coverage/download/@bcoe/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
@ -1901,7 +1915,28 @@
"@babel/helper-module-imports" "^7.7.4" "@babel/helper-module-imports" "^7.7.4"
"@rollup/pluginutils" "^3.0.8" "@rollup/pluginutils" "^3.0.8"
"@rollup/pluginutils@^3.0.8": "@rollup/plugin-commonjs@^13.0.0":
version "13.0.0"
resolved "https://r.cnpmjs.org/@rollup/plugin-commonjs/download/@rollup/plugin-commonjs-13.0.0.tgz#8a1d684ba6848afe8b9e3d85649d4b2f6f7217ec"
integrity sha1-ih1oS6aEiv6Lnj2FZJ1LL29yF+w=
dependencies:
"@rollup/pluginutils" "^3.0.8"
commondir "^1.0.1"
estree-walker "^1.0.1"
glob "^7.1.2"
is-reference "^1.1.2"
magic-string "^0.25.2"
resolve "^1.11.0"
"@rollup/plugin-typescript@^3.0.0":
version "3.1.1"
resolved "https://r.cnpmjs.org/@rollup/plugin-typescript/download/@rollup/plugin-typescript-3.1.1.tgz#a39175a552ed82a3e424862e6bb403bf9da451ee"
integrity sha1-o5F1pVLtgqPkJIYua7QDv52kUe4=
dependencies:
"@rollup/pluginutils" "^3.0.1"
resolve "^1.14.1"
"@rollup/pluginutils@^3.0.1", "@rollup/pluginutils@^3.0.8":
version "3.1.0" version "3.1.0"
resolved "https://r.cnpmjs.org/@rollup/pluginutils/download/@rollup/pluginutils-3.1.0.tgz#706b4524ee6dc8b103b3c995533e5ad680c02b9b" resolved "https://r.cnpmjs.org/@rollup/pluginutils/download/@rollup/pluginutils-3.1.0.tgz#706b4524ee6dc8b103b3c995533e5ad680c02b9b"
integrity sha1-cGtFJO5tyLEDs8mVUz5a1oDAK5s= integrity sha1-cGtFJO5tyLEDs8mVUz5a1oDAK5s=
@ -1967,6 +2002,11 @@
resolved "https://r.cnpmjs.org/@types/color-name/download/@types/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0" resolved "https://r.cnpmjs.org/@types/color-name/download/@types/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0"
integrity sha1-HBJhu+qhCoBVu8XYq4S3sq/IRqA= integrity sha1-HBJhu+qhCoBVu8XYq4S3sq/IRqA=
"@types/estree@*":
version "0.0.45"
resolved "https://r.cnpmjs.org/@types/estree/download/@types/estree-0.0.45.tgz#e9387572998e5ecdac221950dab3e8c3b16af884"
integrity sha1-6Th1cpmOXs2sIhlQ2rPow7Fq+IQ=
"@types/estree@0.0.39": "@types/estree@0.0.39":
version "0.0.39" version "0.0.39"
resolved "https://r.cnpmjs.org/@types/estree/download/@types/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f" resolved "https://r.cnpmjs.org/@types/estree/download/@types/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f"
@ -2057,6 +2097,11 @@
resolved "https://r.cnpmjs.org/@types/stack-utils/download/@types/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e" resolved "https://r.cnpmjs.org/@types/stack-utils/download/@types/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e"
integrity sha1-CoUdO9lkmPolwzq3J47TvWXwbD4= integrity sha1-CoUdO9lkmPolwzq3J47TvWXwbD4=
"@types/svg-tags@^1.0.0":
version "1.0.0"
resolved "https://registry.yarnpkg.com/@types/svg-tags/-/svg-tags-1.0.0.tgz#2ba2a2e8d72827ae41cbec453d52f939c2049b63"
integrity sha512-PlLI3u2hocS4nbzd9WUzQn/EyFl+NifbssU9QV40XzWOpwf5R7cDod2dmTUKYN7awE9jMrhy9FCO904ZYwaBDw==
"@types/tapable@*", "@types/tapable@^1.0.5": "@types/tapable@*", "@types/tapable@^1.0.5":
version "1.0.6" version "1.0.6"
resolved "https://r.cnpmjs.org/@types/tapable/download/@types/tapable-1.0.6.tgz#a9ca4b70a18b270ccb2bc0aaafefd1d486b7ea74" resolved "https://r.cnpmjs.org/@types/tapable/download/@types/tapable-1.0.6.tgz#a9ca4b70a18b270ccb2bc0aaafefd1d486b7ea74"
@ -6049,6 +6094,13 @@ is-potential-custom-element-name@^1.0.0:
resolved "https://r.cnpmjs.org/is-potential-custom-element-name/download/is-potential-custom-element-name-1.0.0.tgz#0c52e54bcca391bb2c494b21e8626d7336c6e397" resolved "https://r.cnpmjs.org/is-potential-custom-element-name/download/is-potential-custom-element-name-1.0.0.tgz#0c52e54bcca391bb2c494b21e8626d7336c6e397"
integrity sha1-DFLlS8yjkbssSUsh6GJtczbG45c= integrity sha1-DFLlS8yjkbssSUsh6GJtczbG45c=
is-reference@^1.1.2:
version "1.2.1"
resolved "https://r.cnpmjs.org/is-reference/download/is-reference-1.2.1.tgz#8b2dac0b371f4bc994fdeaba9eb542d03002d0b7"
integrity sha1-iy2sCzcfS8mU/eq6nrVC0DAC0Lc=
dependencies:
"@types/estree" "*"
is-regex@^1.0.4, is-regex@^1.1.0: is-regex@^1.0.4, is-regex@^1.1.0:
version "1.1.0" version "1.1.0"
resolved "https://r.cnpmjs.org/is-regex/download/is-regex-1.1.0.tgz#ece38e389e490df0dc21caea2bd596f987f767ff" resolved "https://r.cnpmjs.org/is-regex/download/is-regex-1.1.0.tgz#ece38e389e490df0dc21caea2bd596f987f767ff"
@ -6959,6 +7011,13 @@ macos-release@^2.2.0:
resolved "https://r.cnpmjs.org/macos-release/download/macos-release-2.3.0.tgz#eb1930b036c0800adebccd5f17bc4c12de8bb71f" resolved "https://r.cnpmjs.org/macos-release/download/macos-release-2.3.0.tgz#eb1930b036c0800adebccd5f17bc4c12de8bb71f"
integrity sha1-6xkwsDbAgArevM1fF7xMEt6Ltx8= integrity sha1-6xkwsDbAgArevM1fF7xMEt6Ltx8=
magic-string@^0.25.2:
version "0.25.7"
resolved "https://r.cnpmjs.org/magic-string/download/magic-string-0.25.7.tgz#3f497d6fd34c669c6798dcb821f2ef31f5445051"
integrity sha1-P0l9b9NMZpxnmNy4IfLvMfVEUFE=
dependencies:
sourcemap-codec "^1.4.4"
make-dir@^1.0.0: make-dir@^1.0.0:
version "1.3.0" version "1.3.0"
resolved "https://r.cnpmjs.org/make-dir/download/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c" resolved "https://r.cnpmjs.org/make-dir/download/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c"
@ -8947,7 +9006,7 @@ resolve-url@^0.2.1:
resolved "https://r.cnpmjs.org/resolve-url/download/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" resolved "https://r.cnpmjs.org/resolve-url/download/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a"
integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=
resolve@^1.10.0, resolve@^1.13.1, resolve@^1.17.0, resolve@^1.3.2: resolve@^1.10.0, resolve@^1.11.0, resolve@^1.13.1, resolve@^1.14.1, resolve@^1.17.0, resolve@^1.3.2:
version "1.17.0" version "1.17.0"
resolved "https://r.cnpmjs.org/resolve/download/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" resolved "https://r.cnpmjs.org/resolve/download/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444"
integrity sha1-sllBtUloIxzC0bt2p5y38sC/hEQ= integrity sha1-sllBtUloIxzC0bt2p5y38sC/hEQ=
@ -9419,6 +9478,11 @@ source-map@^0.7.3:
resolved "https://r.cnpmjs.org/source-map/download/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" resolved "https://r.cnpmjs.org/source-map/download/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383"
integrity sha1-UwL4FpAxc1ImVECS5kmB91F1A4M= integrity sha1-UwL4FpAxc1ImVECS5kmB91F1A4M=
sourcemap-codec@^1.4.4:
version "1.4.8"
resolved "https://r.cnpmjs.org/sourcemap-codec/download/sourcemap-codec-1.4.8.tgz#ea804bd94857402e6992d05a38ef1ae35a9ab4c4"
integrity sha1-6oBL2UhXQC5pktBaOO8a41qatMQ=
spdx-correct@^3.0.0: spdx-correct@^3.0.0:
version "3.1.1" version "3.1.1"
resolved "https://r.cnpmjs.org/spdx-correct/download/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9" resolved "https://r.cnpmjs.org/spdx-correct/download/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9"
@ -10127,6 +10191,11 @@ typedarray@^0.0.6:
resolved "https://r.cnpmjs.org/typedarray/download/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" resolved "https://r.cnpmjs.org/typedarray/download/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
typescript@^3.9.6:
version "3.9.6"
resolved "https://r.cnpmjs.org/typescript/download/typescript-3.9.6.tgz#8f3e0198a34c3ae17091b35571d3afd31999365a"
integrity sha1-jz4BmKNMOuFwkbNVcdOv0xmZNlo=
uglify-js@^3.1.4: uglify-js@^3.1.4:
version "3.9.4" version "3.9.4"
resolved "https://r.cnpmjs.org/uglify-js/download/uglify-js-3.9.4.tgz#867402377e043c1fc7b102253a22b64e5862401b" resolved "https://r.cnpmjs.org/uglify-js/download/uglify-js-3.9.4.tgz#867402377e043c1fc7b102253a22b64e5862401b"