Skip to content

Commit

Permalink
Add composition-vue2 style in vue/component-api-style (#1703)
Browse files Browse the repository at this point in the history
* Add `composition-vue2` api style

* Improve error message

* Also allow `renderTracked` and `renderTriggered`
  • Loading branch information
FloEdelmann committed Nov 12, 2021
1 parent c033ac6 commit e928e4c
Show file tree
Hide file tree
Showing 3 changed files with 336 additions and 57 deletions.
7 changes: 4 additions & 3 deletions docs/rules/component-api-style.md
Expand Up @@ -73,14 +73,15 @@ export default {
```json
{
"vue/component-api-style": ["error",
["script-setup", "composition"] // "script-setup", "composition", or "options"
["script-setup", "composition"] // "script-setup", "composition", "composition-vue2", or "options"
]
}
```

- Array options ... Defines the API styles you want to allow. Default is `["script-setup", "composition"]`. You can use the following values.
- `"script-setup"` ... If set, allows `<script setup>`.
- `"composition"` ... If set, allows Composition API (not `<script setup>`).
- `"script-setup"` ... If set, allows [`<script setup>`](https://v3.vuejs.org/api/sfc-script-setup.html).
- `"composition"` ... If set, allows [Composition API](https://v3.vuejs.org/api/composition-api.html) (not `<script setup>`).
- `"composition-vue2"` ... If set, allows [Composition API for Vue 2](https://github.com/vuejs/composition-api) (not `<script setup>`). In particular, it allows `render`, `renderTracked` and `renderTriggered` alongside `setup`.
- `"options"` ... If set, allows Options API.

### `["options"]`
Expand Down
91 changes: 67 additions & 24 deletions lib/rules/component-api-style.js
Expand Up @@ -7,22 +7,29 @@
const utils = require('../utils')

/**
* @typedef { 'script-setup' | 'composition' | 'options' } PreferOption
* @typedef { 'script-setup' | 'composition' | 'composition-vue2' | 'options' } PreferOption
*
* @typedef {PreferOption[]} UserPreferOption
*
* @typedef {object} NormalizeOptions
* @property {object} allowsSFC
* @property {boolean} [allowsSFC.scriptSetup]
* @property {boolean} [allowsSFC.composition]
* @property {boolean} [allowsSFC.compositionVue2]
* @property {boolean} [allowsSFC.options]
* @property {object} allowsOther
* @property {boolean} [allowsOther.composition]
* @property {boolean} [allowsOther.compositionVue2]
* @property {boolean} [allowsOther.options]
*/

/** @type {PreferOption[]} */
const STYLE_OPTIONS = ['script-setup', 'composition', 'options']
const STYLE_OPTIONS = [
'script-setup',
'composition',
'composition-vue2',
'options'
]

/**
* Normalize options.
Expand All @@ -41,14 +48,22 @@ function parseOptions(options) {
} else if (prefer === 'composition') {
opts.allowsSFC.composition = true
opts.allowsOther.composition = true
} else if (prefer === 'composition-vue2') {
opts.allowsSFC.compositionVue2 = true
opts.allowsOther.compositionVue2 = true
} else if (prefer === 'options') {
opts.allowsSFC.options = true
opts.allowsOther.options = true
}
}

if (!opts.allowsOther.composition && !opts.allowsOther.options) {
if (
!opts.allowsOther.composition &&
!opts.allowsOther.compositionVue2 &&
!opts.allowsOther.options
) {
opts.allowsOther.composition = true
opts.allowsOther.compositionVue2 = true
opts.allowsOther.options = true
}

Expand Down Expand Up @@ -87,6 +102,13 @@ const OPTIONS_API_OPTIONS = new Set([
])
const COMPOSITION_API_OPTIONS = new Set(['setup'])

const COMPOSITION_API_VUE2_OPTIONS = new Set([
'setup',
'render', // https://github.com/vuejs/composition-api#template-refs
'renderTracked', // https://github.com/vuejs/composition-api#missing-apis
'renderTriggered' // https://github.com/vuejs/composition-api#missing-apis
])

const LIFECYCLE_HOOK_OPTIONS = new Set([
'beforeCreate',
'created',
Expand All @@ -113,6 +135,7 @@ const LIFECYCLE_HOOK_OPTIONS = new Set([
* @param {object} allowsOpt
* @param {boolean} [allowsOpt.scriptSetup]
* @param {boolean} [allowsOpt.composition]
* @param {boolean} [allowsOpt.compositionVue2]
* @param {boolean} [allowsOpt.options]
*/
function buildAllowedPhrase(allowsOpt) {
Expand All @@ -123,6 +146,9 @@ function buildAllowedPhrase(allowsOpt) {
if (allowsOpt.composition) {
phrases.push('Composition API')
}
if (allowsOpt.compositionVue2) {
phrases.push('Composition API (Vue 2)')
}
if (allowsOpt.options) {
phrases.push('Options API')
}
Expand All @@ -135,10 +161,16 @@ function buildAllowedPhrase(allowsOpt) {
* @param {object} allowsOpt
* @param {boolean} [allowsOpt.scriptSetup]
* @param {boolean} [allowsOpt.composition]
* @param {boolean} [allowsOpt.compositionVue2]
* @param {boolean} [allowsOpt.options]
*/
function isPreferScriptSetup(allowsOpt) {
if (!allowsOpt.scriptSetup || allowsOpt.composition || allowsOpt.options) {
if (
!allowsOpt.scriptSetup ||
allowsOpt.composition ||
allowsOpt.compositionVue2 ||
allowsOpt.options
) {
return false
}
return true
Expand Down Expand Up @@ -179,7 +211,7 @@ module.exports = {
disallowScriptSetup:
'`<script setup>` is not allowed in your project. Use {{allowedApis}} instead.',
disallowComponentOption:
'{{disallowedApi}} is not allowed in your project. {{optionPhrase}} is the API of {{disallowedApi}}. Use {{allowedApis}} instead.',
'{{disallowedApi}} is not allowed in your project. {{optionPhrase}} is part of the {{disallowedApi}}. Use {{allowedApis}} instead.',
disallowComponentOptionPreferScriptSetup:
'{{disallowedApi}} is not allowed in your project. Use `<script setup>` instead.'
}
Expand Down Expand Up @@ -211,21 +243,29 @@ module.exports = {
const allows = utils.isSFCObject(context, node)
? options.allowsSFC
: options.allowsOther
if (allows.composition && allows.options) {
if (
(allows.composition || allows.compositionVue2) &&
allows.options
) {
return
}
const disallows = [
const apis = [
{
allow: allows.composition,
options: COMPOSITION_API_OPTIONS,
api: 'Composition API'
apiName: 'Composition API'
},
{
allow: allows.options,
options: OPTIONS_API_OPTIONS,
api: 'Options API'
apiName: 'Options API'
},
{
allow: allows.compositionVue2,
options: COMPOSITION_API_VUE2_OPTIONS,
apiName: 'Composition API (Vue 2)'
}
].filter(({ allow }) => !allow)
]
for (const prop of node.properties) {
if (prop.type !== 'Property') {
continue
Expand All @@ -234,20 +274,23 @@ module.exports = {
if (!name) {
continue
}
for (const { options, api } of disallows) {
if (options.has(name)) {
context.report({
node: prop.key,
messageId: isPreferScriptSetup(allows)
? 'disallowComponentOptionPreferScriptSetup'
: 'disallowComponentOption',
data: {
disallowedApi: api,
optionPhrase: buildOptionPhrase(name),
allowedApis: buildAllowedPhrase(allows)
}
})
}
const propAllowed = apis.some(
(api) => api.allow && api.options.has(name)
)
if (!propAllowed) {
context.report({
node: prop.key,
messageId: isPreferScriptSetup(allows)
? 'disallowComponentOptionPreferScriptSetup'
: 'disallowComponentOption',
data: {
disallowedApi: apis.filter(
(api) => !api.allow && api.options.has(name)
)[0].apiName,
optionPhrase: buildOptionPhrase(name),
allowedApis: buildAllowedPhrase(allows)
}
})
}
}
}
Expand Down

0 comments on commit e928e4c

Please sign in to comment.