feat: allow string arguments on directives (#496)

* chore: update dependencies

* feat: allow string arguments on directives

resolves #325
This commit is contained in:
Kael 2021-09-22 12:27:50 +10:00 committed by GitHub
parent 65ebf6fd09
commit 1ab8483933
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 1199 additions and 1166 deletions

View File

@ -16,10 +16,10 @@
"jsx" "jsx"
], ],
"devDependencies": { "devDependencies": {
"@typescript-eslint/eslint-plugin": "^4.4.1", "@typescript-eslint/eslint-plugin": "^4.30.0",
"eslint": "^7.7.0", "eslint": "^7.32.0",
"eslint-config-airbnb-typescript": "^12.3.1", "eslint-config-airbnb-typescript": "^12.3.1",
"eslint-plugin-import": "^2.22.1", "eslint-plugin-import": "^2.24.2",
"lerna": "^3.19.0" "lerna": "^3.19.0"
} }
} }

View File

@ -12,6 +12,7 @@
}, },
"scripts": { "scripts": {
"build": "rm -rf dist && tsc", "build": "rm -rf dist && tsc",
"watch": "rm -rf dist && tsc --watch",
"lint": "eslint 'src/*.ts'", "lint": "eslint 'src/*.ts'",
"test": "yarn build && jest --coverage", "test": "yarn build && jest --coverage",
"prepublishOnly": "yarn build" "prepublishOnly": "yarn build"
@ -34,18 +35,18 @@
"svg-tags": "^1.0.0" "svg-tags": "^1.0.0"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.0.0", "@babel/core": "^7.15.5",
"@babel/preset-env": "^7.0.0", "@babel/preset-env": "^7.15.4",
"@types/jest": "^26.0.7", "@types/jest": "^26.0.24",
"@types/svg-tags": "^1.0.0", "@types/svg-tags": "^1.0.0",
"@typescript-eslint/eslint-plugin": "^4.0.1", "@typescript-eslint/eslint-plugin": "^4.30.0",
"@typescript-eslint/parser": "^4.0.1", "@typescript-eslint/parser": "^4.30.0",
"@vue/compiler-dom": "3.0.5", "@vue/compiler-dom": "3.2.8",
"@vue/test-utils": "2.0.0-beta.2", "@vue/test-utils": "2.0.0-beta.2",
"jest": "^26.0.1", "jest": "^26.0.1",
"regenerator-runtime": "^0.13.5", "regenerator-runtime": "^0.13.9",
"ts-jest": "^26.1.3", "ts-jest": "^26.1.3",
"typescript": "^4.2.3", "typescript": "^4.4.2",
"vue": "3.0.7" "vue": "3.2.8"
} }
} }

View File

@ -40,16 +40,33 @@ const parseDirectives = (params: {
isComponent: boolean isComponent: boolean
}) => { }) => {
const { const {
name, path, value, state, tag, isComponent, path, value, state, tag, isComponent,
} = params; } = params;
const args: Array<t.Expression | t.NullLiteral> = []; const args: Array<t.Expression | t.NullLiteral> = [];
const vals: t.Expression[] = []; const vals: t.Expression[] = [];
const modifiersSet: Set<string>[] = []; const modifiersSet: Set<string>[] = [];
const underscoreModifiers = name.split('_');
const directiveName: string = underscoreModifiers.shift() let directiveName;
?.replace(/^v/, '') let directiveArgument;
let directiveModifiers;
if ('namespace' in path.node.name) {
[directiveName, directiveArgument] = params.name.split(':');
directiveName = path.node.name.namespace.name;
directiveArgument = path.node.name.name.name;
directiveModifiers = directiveArgument.split('_').slice(1);
} else {
const underscoreModifiers = params.name.split('_');
directiveName = underscoreModifiers.shift() || '';
directiveModifiers = underscoreModifiers;
}
directiveName = directiveName
.replace(/^v/, '')
.replace(/^-/, '') .replace(/^-/, '')
.replace(/^\S/, (s: string) => s.toLowerCase()) || ''; .replace(/^\S/, (s: string) => s.toLowerCase());
if (directiveArgument) {
args.push(t.stringLiteral(directiveArgument));
}
const isVModels = directiveName === 'models'; const isVModels = directiveName === 'models';
const isVModel = directiveName === 'model'; const isVModel = directiveName === 'model';
@ -64,7 +81,7 @@ const parseDirectives = (params: {
const shouldResolve = !['html', 'text', 'model', 'models'].includes(directiveName) const shouldResolve = !['html', 'text', 'model', 'models'].includes(directiveName)
|| (isVModel && !isComponent); || (isVModel && !isComponent);
let modifiers = underscoreModifiers; let modifiers = directiveModifiers;
if (t.isArrayExpression(value)) { if (t.isArrayExpression(value)) {
const elementsList = isVModels ? value.elements! : [value]; const elementsList = isVModels ? value.elements! : [value];
@ -95,9 +112,9 @@ const parseDirectives = (params: {
} else if (isVModel && !shouldResolve) { } else if (isVModel && !shouldResolve) {
// work as v-model={value} // work as v-model={value}
args.push(t.nullLiteral()); args.push(t.nullLiteral());
modifiersSet.push(new Set(underscoreModifiers)); modifiersSet.push(new Set(directiveModifiers));
} else { } else {
modifiersSet.push(new Set(underscoreModifiers)); modifiersSet.push(new Set(directiveModifiers));
} }
return { return {

View File

@ -13,7 +13,7 @@ const patchFlagExpect = (
flag: number, flag: number,
dynamic: string[] | null, dynamic: string[] | null,
) => { ) => {
const { patchFlag, dynamicProps } = wrapper.vm.$.subTree; const { patchFlag, dynamicProps } = wrapper.vm.$.subTree as any;
expect(patchFlag).toBe(flag); expect(patchFlag).toBe(flag);
expect(dynamicProps).toEqual(dynamic); expect(dynamicProps).toEqual(dynamic);
@ -260,7 +260,8 @@ describe('directive', () => {
test('vHtml', () => { test('vHtml', () => {
const wrapper = shallowMount({ const wrapper = shallowMount({
setup() { setup() {
return () => <h1 v-html="<div>foo</div>"></h1>; const html = '<div>foo</div>';
return () => <h1 v-html={ html }></h1>;
}, },
}); });
expect(wrapper.html()).toBe('<h1><div>foo</div></h1>'); expect(wrapper.html()).toBe('<h1><div>foo</div></h1>');

View File

@ -230,3 +230,39 @@ test('underscore modifier should work in custom component', async () => {
await wrapper.trigger('click'); await wrapper.trigger('click');
expect(wrapper.html()).toBe('<div>6</div>'); expect(wrapper.html()).toBe('<div>6</div>');
}); });
test('Named model', async () => {
const Child = defineComponent({
emits: ['update:value'],
props: {
value: {
type: Number,
default: 0,
},
},
setup(props, { emit }) {
const handleClick = () => {
emit('update:value', 2);
};
return () => (
<div onClick={ handleClick }>{ props.value }</div>
);
},
});
const wrapper = mount({
data: () => ({
foo: 0,
}),
render() {
return <Child v-model:value={ this.foo } />;
},
});
expect(wrapper.html()).toBe('<div>0</div>');
wrapper.vm.$data.foo += 1;
await wrapper.vm.$nextTick();
expect(wrapper.html()).toBe('<div>1</div>');
await wrapper.trigger('click');
expect(wrapper.html()).toBe('<div>2</div>');
});

View File

@ -3,17 +3,17 @@
"version": "1.0.4", "version": "1.0.4",
"private": true, "private": true,
"dependencies": { "dependencies": {
"monaco-editor": "^0.20.0" "monaco-editor": "^0.27.0"
}, },
"devDependencies": { "devDependencies": {
"@babel/core": "^7.0.0", "@babel/core": "^7.15.5",
"css-loader": "^3.5.3", "css-loader": "^3.5.3",
"html-webpack-plugin": "^4.3.0", "html-webpack-plugin": "^4.5.2",
"style-loader": "^1.2.1", "style-loader": "^1.2.1",
"ts-loader": "^8.0.0", "ts-loader": "^8.3.0",
"typescript": "^4.2.3", "typescript": "^4.4.2",
"vue": "3.0.7", "vue": "3.2.8",
"webpack": "^4.43.0", "webpack": "^4.46.0",
"webpack-dev-server": "^3.11.0" "webpack-dev-server": "^3.11.2"
} }
} }

View File

@ -8,7 +8,7 @@ const devServerOptions = {
inline: true, inline: true,
open: true, open: true,
hot: true, hot: true,
overlay: true, overlay: false,
}; };
const server = new WebpackDevServer(compiler, devServerOptions); const server = new WebpackDevServer(compiler, devServerOptions);

View File

@ -16,6 +16,7 @@ module.exports = {
loader: 'ts-loader', loader: 'ts-loader',
exclude: /node_modules/, exclude: /node_modules/,
options: { options: {
transpileOnly: true,
compilerOptions: { downlevelIteration: true }, compilerOptions: { downlevelIteration: true },
}, },
}, },

View File

@ -1,6 +1,6 @@
{ {
"compilerOptions": { "compilerOptions": {
"sourceMap": false, "sourceMap": true,
"target": "es2015", "target": "es2015",
"module": "commonjs", "module": "commonjs",
"moduleResolution": "node", "moduleResolution": "node",
@ -11,6 +11,7 @@
"resolveJsonModule": true, "resolveJsonModule": true,
"esModuleInterop": true, "esModuleInterop": true,
"removeComments": false, "removeComments": false,
"jsx": "preserve",
"lib": [ "lib": [
"esnext", "esnext",
"dom" "dom"

2244
yarn.lock

File diff suppressed because it is too large Load Diff