-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #24 from cwyyue/feat-properties-defualt
feat: 校验properties
- Loading branch information
Showing
8 changed files
with
405 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
--- | ||
pageClass: rule-details | ||
sidebarDepth: 0 | ||
title: mpx/valid-properties | ||
description: 校验properties有效值 | ||
--- | ||
# mpx/valid-properties | ||
> 校验properties有效值 | ||
- :gear: 这条规则包含在`"plugin:mpx/mpx-essential"`。 | ||
|
||
此规则检查每个properties的值是否有效, 推荐开启ts获取更完善的类型校验。 | ||
|
||
## :book: 规则详情 | ||
|
||
保障properties的配置项有效,要求properties的配置项是只能是类型或对象。支持对`<script setup>`中的 defineProps 校验。 | ||
|
||
当配置项为对象时,只允许存在配置的键`(默认"type"、"value"、"optionalTypes"、"observer")`,强制要求配置`"type"`。不允许配置空对象,因为在微信低版本基础库会报错导致白屏;不允许其他无效键存在,例如"default"会在skyline下引起报错。 | ||
|
||
<eslint-code-block :rules="{'mpx/valid-properties': ['error']}"> | ||
|
||
```vue | ||
<script> | ||
// ✓ GOOD | ||
createComponent({ | ||
properties: { | ||
propsA: { | ||
type: String, | ||
value: "" | ||
}, | ||
propsB: Object, | ||
propsC: { | ||
type: String, | ||
optionalTypes:[Number] | ||
} | ||
} | ||
}) | ||
// ✗ BAD | ||
createComponent({ | ||
properties: { | ||
propsA: {}, | ||
propsB: '', | ||
propsC: { | ||
type: Object, | ||
default: {} | ||
}, | ||
propsD: [1,2], | ||
propsE: { | ||
value: {} | ||
} | ||
} | ||
}) | ||
</script> | ||
``` | ||
</eslint-code-block> | ||
|
||
<eslint-code-block :rules="{'mpx/valid-properties': ['error']}"> | ||
```vue | ||
<script setup> | ||
// ✓ GOOD | ||
const props = defineProps({ | ||
propsA: { | ||
type: Object, | ||
value: {} | ||
}, | ||
propsB: Array | ||
}) | ||
// ✗ BAD | ||
const badProps = defineProps({ | ||
propsA: { | ||
type: Object, | ||
default: {} | ||
}, | ||
propsB: {} | ||
}) | ||
</script> | ||
``` | ||
</eslint-code-block> | ||
|
||
## :wrench: 选项 | ||
可配置allowKeys选项,允许properties的配置对象存在这些key。默认为`"type", "value", "optionalTypes", "observer"` | ||
```json | ||
{ | ||
"mpx/valid-wx-key": ["error", { | ||
"allowKeys": ["type", "value","optionalTypes","observer"] | ||
}] | ||
} | ||
``` | ||
|
||
## :mag: 具体实现 | ||
|
||
- [规则](https://github.com/mpx-ecology/eslint-plugin-mpx/blob/master/lib/rules/valid-properties.js) | ||
- [测试](https://github.com/mpx-ecology/eslint-plugin-mpx/blob/master/tests/lib/rules/valid-properties.js) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,151 @@ | ||
/** | ||
* @author pagnkelly | ||
* @copyright 2020 pagnkelly. All rights reserved. | ||
* See LICENSE file in root directory for full license. | ||
*/ | ||
'use strict' | ||
|
||
// ------------------------------------------------------------------------------ | ||
// Requirements | ||
// ------------------------------------------------------------------------------ | ||
|
||
const utils = require('../utils') | ||
|
||
/** | ||
* @typedef {import("../utils").ComponentObjectProp} ComponentObjectProp | ||
*/ | ||
|
||
// ------------------------------------------------------------------------------ | ||
// Rule Definition | ||
// ------------------------------------------------------------------------------ | ||
// 校验properties是否符合预期 | ||
/** 默认允许的key */ | ||
const DEFAULT_KEYS = ['type', 'value', 'optionalTypes', 'observer'] | ||
/** | ||
* check prop | ||
* @param {Property} node | ||
* @returns | ||
*/ | ||
/** | ||
* | ||
* @param {Property} node | ||
* @param {RuleContext} context | ||
* @param {string[]} allowKeys | ||
* @returns | ||
*/ | ||
function validProp(node, context, allowKeys) { | ||
if (!node) return | ||
const sourceCode = context.getSourceCode() | ||
const propName = sourceCode.getText(node.key) | ||
if (!node.value) { | ||
return context.report({ | ||
node, | ||
message: "The value of '{{propName}}' cannot be empty.", | ||
data: { | ||
propName | ||
} | ||
}) | ||
} | ||
if (node.value.type === 'ObjectExpression') { | ||
if (!node.value.properties.length) { | ||
return context.report({ | ||
node: node.value, | ||
message: "The value of '{{propName}}' cannot be empty object.", | ||
data: { | ||
propName | ||
} | ||
}) | ||
} | ||
let hasType = 0 | ||
node.value.properties.forEach((item) => { | ||
if (item.type !== 'Property') return | ||
const keyName = sourceCode.getText(item.key) | ||
if (!allowKeys.includes(keyName)) { | ||
context.report({ | ||
node: item, | ||
message: "Property '{{propName}}' has invalid key '{{keyName}}'.", | ||
data: { | ||
propName, | ||
keyName | ||
} | ||
}) | ||
} else if (keyName === 'type') { | ||
hasType = 1 | ||
} | ||
}) | ||
if (!hasType) { | ||
context.report({ | ||
node: node.value, | ||
message: "Property '{{propName}}' requires 'type' key.", | ||
data: { | ||
propName | ||
} | ||
}) | ||
} | ||
} else if (node.value.type !== 'Identifier') { | ||
return context.report({ | ||
node, | ||
message: "Invalid value for '{{propName}}'.", | ||
data: { | ||
propName | ||
} | ||
}) | ||
} | ||
} | ||
module.exports = { | ||
meta: { | ||
type: 'problem', | ||
docs: { | ||
description: | ||
'enforce that a return statement is present in computed property', | ||
categories: ['mpx-essential'], | ||
url: 'https://mpx-ecology.github.io/eslint-plugin-mpx/rules/valid-properties.html' | ||
}, | ||
fixable: null, // or "code" or "whitespace" | ||
schema: [ | ||
{ | ||
type: 'object', | ||
properties: { | ||
allowKeys: { | ||
type: 'array' | ||
} | ||
} | ||
} | ||
] | ||
}, | ||
/** @param {RuleContext} context */ | ||
create(context) { | ||
const options = context.options[0] || {} | ||
const allowKeys = options.allowKeys || DEFAULT_KEYS | ||
const isScriptSetup = utils.isScriptSetup(context) | ||
|
||
// ---------------------------------------------------------------------- | ||
// Public | ||
// ---------------------------------------------------------------------- | ||
|
||
if (isScriptSetup) { | ||
return utils.defineTemplateBodyVisitor( | ||
context, | ||
{}, | ||
{ | ||
/** | ||
* @param {ObjectExpression} node | ||
*/ | ||
"CallExpression[callee.name='defineProps'] > ObjectExpression"(node) { | ||
for (const prop of utils.getComponentPropsFromDefine(node)) { | ||
prop.type === 'object' && validProp(prop.node, context, allowKeys) | ||
} | ||
} | ||
} | ||
) | ||
} else { | ||
return utils.defineMpxVisitor(context, { | ||
onMpxObjectEnter(obj) { | ||
for (const prop of utils.getComponentPropsFromOptions(obj)) { | ||
prop.type === 'object' && validProp(prop.node, context, allowKeys) | ||
} | ||
} | ||
}) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.