-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
3,283 additions
and
0 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
{ | ||
"root": true, | ||
"parser": "@typescript-eslint/parser", | ||
"plugins": [ | ||
"@typescript-eslint" | ||
], | ||
"extends": [ | ||
"eslint:recommended", | ||
"plugin:@typescript-eslint/recommended" | ||
], | ||
"rules": { | ||
"indent": [ | ||
"error", | ||
2 | ||
], | ||
"no-trailing-spaces": "error", | ||
"semi": "error", | ||
"keyword-spacing": "error", | ||
"padding-line-between-statements": [ | ||
"error", | ||
{ | ||
"blankLine": "always", | ||
"prev": [ | ||
"const", | ||
"let", | ||
"var", | ||
"if" | ||
], | ||
"next": "*" | ||
}, | ||
{ | ||
"blankLine": "any", | ||
"prev": [ | ||
"const", | ||
"let", | ||
"var" | ||
], | ||
"next": [ | ||
"const", | ||
"let", | ||
"var" | ||
] | ||
}, | ||
{ | ||
"blankLine": "always", | ||
"prev": "*", | ||
"next": "return" | ||
} | ||
] | ||
}, | ||
} |
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,34 @@ | ||
# This workflow will run tests using node and then publish a package to GitHub Packages when a release is created | ||
# For more information see: https://help.github.com/actions/language-and-framework-guides/publishing-nodejs-packages | ||
|
||
name: eslint-plugin-vue-required-attributes | ||
|
||
on: | ||
release: | ||
types: [created] | ||
|
||
jobs: | ||
tests: | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v3 | ||
- uses: actions/setup-node@v3 | ||
with: | ||
node-version: 16 | ||
- run: yarn install | ||
- run: yarn test | ||
|
||
publish-npm: | ||
needs: tests | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v3 | ||
- uses: actions/setup-node@v3 | ||
with: | ||
node-version: 16 | ||
registry-url: https://registry.npmjs.org/ | ||
- run: yarn install | ||
- run: yarn build | ||
- run: npm publish | ||
env: | ||
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} |
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,2 @@ | ||
build | ||
node_modules |
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 |
---|---|---|
@@ -1,2 +1,111 @@ | ||
# eslint-plugin-vue-required-attributes | ||
|
||
Inspired by [eslint-plugin-idiomatic-jsx](https://github.com/danrigsby/eslint-plugin-idiomatic-jsx) & `require-attributes` rule. | ||
|
||
Require specified `attributes` on specified `components` from being used. | ||
|
||
This is useful for things such as: | ||
|
||
- Requiring a `id` attribute on things used by automated tests | ||
- Requiring attributes needed for SEO or a11y concerns | ||
|
||
## Installation | ||
|
||
You'll first need to install ESLint: | ||
|
||
```sh | ||
# npm | ||
npm install eslint --save-dev | ||
|
||
# yarn | ||
yarn add eslint --dev | ||
``` | ||
|
||
Next, install `eslint-plugin-vue-required-attributes`: | ||
|
||
```sh | ||
# npm | ||
npm install eslint-plugin-vue-required-attributes --save-dev | ||
|
||
# yarn | ||
yarn add eslint-plugin-vue-required-attributes --dev | ||
``` | ||
|
||
## Configuration | ||
|
||
Add `vue-required-attributes` to the plugins section of your `.eslintrc` configuration file. _You can omit the `eslint-plugin-` prefix_ | ||
|
||
```javascript | ||
{ | ||
"plugins": [ | ||
"vue-required-attributes" | ||
] | ||
} | ||
``` | ||
|
||
Configure the rules you want to use under the rules section. | ||
|
||
```javascript | ||
{ | ||
"rules": { | ||
"vue-required-attributes/require-attributes": [ 1, { | ||
// options | ||
} ] | ||
} | ||
} | ||
``` | ||
|
||
## Usage | ||
|
||
This rule takes one object argument of type object that defines an associative array of `attributes` that that should be required on the defined array of `components`. | ||
|
||
```json | ||
{ | ||
"rules": { | ||
"vue-required-attributes/require-attributes": [ | ||
1, | ||
{ | ||
"id": ["a", "button", "input"] | ||
} | ||
] | ||
} | ||
} | ||
``` | ||
|
||
### Succeed | ||
|
||
```jsx | ||
<a id='my-id'></a> <!-- Good: id is provided--> | ||
<input id='my-id' /> <!-- Good: id is provided--> | ||
``` | ||
|
||
### Fail | ||
|
||
```jsx | ||
<a></a> <!-- Bad: id is missing--> | ||
<button></button> <!-- Bad: id is missing--> | ||
``` | ||
|
||
### Custom output message | ||
|
||
You may also pass in a 3rd option to change the default message that is output on error. | ||
|
||
This can be handy if you want to explain "why" this rule is being used in your project or organization. This option is a `function` that takes in the `nodeType` and `attribute` name and returns a `string`. | ||
|
||
```ts | ||
{ | ||
"rules": { | ||
"vue-required-attributes/require-attributes": [ | ||
1, | ||
{ | ||
id: ['a', 'button'], | ||
}, | ||
(componentName: string, missedAttribute: string) => `"${componentName}" missing "${missedAttribute} attribute."` | ||
] | ||
} | ||
} | ||
``` | ||
|
||
## ✏️ Code conduction | ||
|
||
This project uses [Gitmoji](https://gitmoji.carloscuesta.me) for commit messages |
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,6 @@ | ||
/** @type {import('ts-jest').JestConfigWithTsJest} */ | ||
module.exports = { | ||
preset: 'ts-jest', | ||
testEnvironment: 'node', | ||
verbose: false, | ||
}; |
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,37 @@ | ||
{ | ||
"name": "eslint-plugin-vue-required-attributes", | ||
"version": "1.0.0", | ||
"author": "ynhhoJ", | ||
"description": "Require specified attributes on specified components from being used!", | ||
"license": "MIT", | ||
"main": "./build/index.js", | ||
"files": [ | ||
"build" | ||
], | ||
"repository": { | ||
"type": "git", | ||
"url": "git+ssh://[email protected]:ynhhoJ/eslint-plugin-vue-required-attributes.git" | ||
}, | ||
"scripts": { | ||
"build": "tsc --build", | ||
"test": "jest" | ||
}, | ||
"devDependencies": { | ||
"@types/eslint": "^8.4.10", | ||
"@types/jest": "^29.4.0", | ||
"@types/node": "^18.11.18", | ||
"@typescript-eslint/eslint-plugin": "^5.49.0", | ||
"@typescript-eslint/parser": "^5.49.0", | ||
"eslint": "^8.32.0", | ||
"jest": "^29.4.1", | ||
"ts-jest": "^29.0.5", | ||
"typescript": "^4.9.4", | ||
"vue-eslint-parser": "^9.1.0" | ||
}, | ||
"keywords": [ | ||
"eslint", | ||
"vue", | ||
"attributes", | ||
"required" | ||
] | ||
} |
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,7 @@ | ||
import requireAttributes from './rules/require-attributes'; | ||
|
||
export = { | ||
rules: { | ||
"require-attributes": requireAttributes, | ||
}, | ||
}; |
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,64 @@ | ||
import { Rule } from "eslint"; | ||
import { AST } from "vue-eslint-parser"; | ||
|
||
const defaultMessage = (tagName: string, missedAttribute: string) => { | ||
return `"${tagName}" component must have "${missedAttribute}" attribute.`; | ||
}; | ||
|
||
const rule: Rule.RuleModule = { | ||
meta: { | ||
type: 'suggestion', | ||
docs: { | ||
description: 'Requires specified attribute to be used in component.', | ||
recommended: true, | ||
}, | ||
}, | ||
|
||
create: (context) => { | ||
return context.parserServices.defineTemplateBodyVisitor({ | ||
VElement(node: AST.VElement) { | ||
const options = context.options[0] || {}; | ||
const optionsObjectKeys = Object.keys(options); | ||
|
||
if (!optionsObjectKeys.length) { | ||
return; | ||
} | ||
|
||
const optionsSecond = context.options[1] || defaultMessage; | ||
const elementName = node.rawName; | ||
|
||
Object.keys(options).forEach((key) => { | ||
const includesKey = options[key].includes(elementName); | ||
|
||
if (!includesKey) { | ||
return; | ||
} | ||
|
||
const elementAttributes = node.startTag.attributes; | ||
const attributesName = elementAttributes.map((item) => { | ||
const itemKey = item.key; | ||
|
||
if (itemKey.type === 'VDirectiveKey' && "argument" in itemKey) { | ||
const itemArgument = itemKey.argument as AST.VIdentifier; | ||
|
||
return itemArgument.rawName; | ||
} | ||
|
||
return item.key.name; | ||
}); | ||
|
||
if (attributesName.includes(key)) { | ||
return; | ||
} | ||
|
||
context.report({ | ||
message: optionsSecond(elementName, key), | ||
loc: node.loc, | ||
}); | ||
}); | ||
} | ||
}); | ||
}, | ||
}; | ||
|
||
export = rule; |
Oops, something went wrong.