├── .prettierignore ├── .czrc ├── tests ├── lib │ ├── rules │ │ ├── fixtures │ │ │ ├── use-env-prefix │ │ │ │ ├── invalid │ │ │ │ │ ├── 01 │ │ │ │ │ │ ├── .env │ │ │ │ │ │ └── code.vue │ │ │ │ │ └── 02 │ │ │ │ │ │ ├── .env │ │ │ │ │ │ └── client.js │ │ │ │ └── valid │ │ │ │ │ ├── 01 │ │ │ │ │ ├── .env │ │ │ │ │ └── code.vue │ │ │ │ │ ├── 02 │ │ │ │ │ ├── .env │ │ │ │ │ └── client.js │ │ │ │ │ └── 03 │ │ │ │ │ └── client.js │ │ │ └── format-query-block │ │ │ │ ├── valid │ │ │ │ ├── 03 │ │ │ │ │ └── code.vue │ │ │ │ ├── 01 │ │ │ │ │ └── code.vue │ │ │ │ └── 02 │ │ │ │ │ └── code.vue │ │ │ │ └── invalid │ │ │ │ ├── 03 │ │ │ │ ├── output.vue │ │ │ │ └── code.vue │ │ │ │ ├── 04 │ │ │ │ ├── code.vue │ │ │ │ └── output.vue │ │ │ │ ├── 01 │ │ │ │ ├── output.vue │ │ │ │ └── code.vue │ │ │ │ └── 02 │ │ │ │ ├── output.vue │ │ │ │ └── code.vue │ │ ├── require-g-image-src.spec.ts │ │ ├── require-g-link-to.spec.ts │ │ ├── format-query-block.spec.ts │ │ └── use-env-prefix.spec.ts │ └── utils │ │ ├── fixtures │ │ ├── get-code-wrap-indent-info │ │ │ ├── use-prettierrc │ │ │ │ ├── set-other-option │ │ │ │ │ ├── .prettierrc │ │ │ │ │ └── file.vue │ │ │ │ ├── set-tab-width │ │ │ │ │ ├── file.vue │ │ │ │ │ └── .prettierrc │ │ │ │ └── set-use-tabs │ │ │ │ │ ├── file.vue │ │ │ │ │ └── .prettierrc │ │ │ ├── not-use-prettierrc │ │ │ │ └── file.vue │ │ │ └── override-prettier-option │ │ │ │ ├── use-prettierrc │ │ │ │ ├── file.vue │ │ │ │ └── .prettierrc │ │ │ │ └── not-use-prettierrc │ │ │ │ └── file.vue │ │ └── get-prettier-option │ │ │ ├── use-prettierrc │ │ │ ├── file.vue │ │ │ └── .prettierrc │ │ │ └── not-use-prettierrc │ │ │ └── file.vue │ │ ├── path.spec.ts │ │ ├── env.spec.ts │ │ ├── get-prettier-option.spec.ts │ │ └── get-code-wrap-indent-info.spec.ts └── util │ ├── index.ts │ ├── rule-tester.ts │ └── load-fixture-creator.ts ├── .hygen.js ├── .eslintignore ├── lib ├── configs.ts ├── utils │ ├── types │ │ ├── index.ts │ │ ├── Node.ts │ │ ├── Parser.ts │ │ ├── Prettier.ts │ │ └── Rule.ts │ ├── path.ts │ ├── create-rule.ts │ ├── parser-services.ts │ ├── attribute.ts │ ├── index.ts │ ├── env.ts │ ├── get-prettier-option.ts │ ├── directive.ts │ ├── rule-creator.ts │ └── get-code-wrap-indent-info.ts ├── index.ts ├── configs │ ├── base.ts │ └── recommended.ts ├── rules.ts └── rules │ ├── require-g-image-src.ts │ ├── require-g-link-to.ts │ ├── use-env-prefix.ts │ └── format-query-block.ts ├── docs ├── .vuepress │ ├── public │ │ ├── favicon.png │ │ └── eslint-plugin-gridsome.svg │ └── config.js ├── README.md ├── developer-guide │ └── README.md ├── introduction │ └── README.md ├── rules │ ├── require-g-image-src.md │ ├── README.md │ ├── require-g-link-to.md │ ├── use-env-prefix.md │ └── format-query-block.md └── user-guide │ └── README.md ├── assets └── logo │ ├── eslint-plugin-gridsome.png │ └── eslint-plugin-gridsome.svg ├── tools ├── util │ ├── index.ts │ ├── format-markdown.ts │ ├── types.ts │ ├── const.ts │ ├── format-typescript.ts │ ├── get-rules-meta-data.ts │ ├── create-rules-list.ts │ └── create-rules-docs.ts ├── update.ts ├── update-rules-docs.ts └── update-rules-list.ts ├── .github ├── ISSUE_TEMPLATE │ ├── Others.md │ ├── Improve_Rule.md │ ├── bug_report.md │ └── Rule_proposal.md ├── PULL_REQUEST_TEMPLATE.md └── workflows │ ├── test.yml │ ├── release.yml │ └── check-update.yml ├── tsconfig.build.json ├── _hygen └── generate │ ├── log │ ├── eslint.ejs.t │ ├── test.ejs.t │ └── log.ejs.t │ ├── development │ ├── eslint.ejs.t │ └── test.ejs.t │ └── rule │ ├── prompt.js │ ├── doc.ejs.t │ ├── test.ejs.t │ └── rule.ejs.t ├── .dependabot └── config.yml ├── .eslintrc.js ├── LICENSE ├── .all-contributorsrc ├── CONTRIBUTING.md ├── .gitignore ├── README.md ├── package.json ├── tsconfig.json └── CHANGELOG.md /.prettierignore: -------------------------------------------------------------------------------- 1 | tools/update-readme/_* -------------------------------------------------------------------------------- /.czrc: -------------------------------------------------------------------------------- 1 | { 2 | "path": "cz-conventional-changelog" 3 | } 4 | -------------------------------------------------------------------------------- /tests/lib/rules/fixtures/use-env-prefix/invalid/01/.env: -------------------------------------------------------------------------------- 1 | API_URL=http://foobar -------------------------------------------------------------------------------- /tests/lib/rules/fixtures/use-env-prefix/valid/01/.env: -------------------------------------------------------------------------------- 1 | API_URL=http://foobar -------------------------------------------------------------------------------- /.hygen.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | templates: `${__dirname}/_hygen`, 3 | }; 4 | -------------------------------------------------------------------------------- /tests/lib/rules/fixtures/use-env-prefix/invalid/02/.env: -------------------------------------------------------------------------------- 1 | DB_USER=user 2 | DB_PASS=password -------------------------------------------------------------------------------- /tests/lib/rules/fixtures/use-env-prefix/valid/02/.env: -------------------------------------------------------------------------------- 1 | DB_USER=user 2 | DB_PASS=password -------------------------------------------------------------------------------- /tests/util/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./rule-tester"; 2 | export * from "./load-fixture-creator"; 3 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules/**/* 2 | log/**/* 3 | tools/update-readme/_readme/* 4 | fixtures 5 | lib/**/*.js -------------------------------------------------------------------------------- /lib/configs.ts: -------------------------------------------------------------------------------- 1 | import recommended from "./configs/recommended"; 2 | 3 | export const configs = { 4 | recommended, 5 | }; 6 | -------------------------------------------------------------------------------- /docs/.vuepress/public/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gridsome/eslint-plugin-gridsome/HEAD/docs/.vuepress/public/favicon.png -------------------------------------------------------------------------------- /tests/lib/utils/fixtures/get-code-wrap-indent-info/use-prettierrc/set-other-option/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "arrowParens": "avoid" 3 | } -------------------------------------------------------------------------------- /tests/lib/utils/fixtures/get-prettier-option/use-prettierrc/file.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/lib/utils/fixtures/get-prettier-option/not-use-prettierrc/file.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /assets/logo/eslint-plugin-gridsome.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gridsome/eslint-plugin-gridsome/HEAD/assets/logo/eslint-plugin-gridsome.png -------------------------------------------------------------------------------- /lib/utils/types/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./Node"; 2 | export * from "./Rule"; 3 | export * from "./Parser"; 4 | export * from "./Prettier"; 5 | -------------------------------------------------------------------------------- /tests/lib/utils/fixtures/get-code-wrap-indent-info/not-use-prettierrc/file.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /lib/index.ts: -------------------------------------------------------------------------------- 1 | import { rules } from "./rules"; 2 | import { configs } from "./configs"; 3 | 4 | export = { 5 | rules, 6 | configs, 7 | }; 8 | -------------------------------------------------------------------------------- /tests/lib/utils/fixtures/get-code-wrap-indent-info/use-prettierrc/set-tab-width/file.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/lib/utils/fixtures/get-code-wrap-indent-info/use-prettierrc/set-use-tabs/file.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/lib/utils/fixtures/get-prettier-option/use-prettierrc/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "arrowParens": "avoid", 3 | "htmlWhitespaceSensitivity": "css" 4 | } -------------------------------------------------------------------------------- /tests/lib/utils/fixtures/get-code-wrap-indent-info/use-prettierrc/set-other-option/file.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/lib/utils/fixtures/get-code-wrap-indent-info/use-prettierrc/set-tab-width/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "tabWidth": 4, 3 | "vueIndentScriptAndStyle": true 4 | } -------------------------------------------------------------------------------- /lib/utils/path.ts: -------------------------------------------------------------------------------- 1 | export const getPathFromProjectRoot = (filename: string, cwd: string) => 2 | filename.split("/").splice(cwd.split("/").length).join("/"); 3 | -------------------------------------------------------------------------------- /tests/lib/utils/fixtures/get-code-wrap-indent-info/override-prettier-option/use-prettierrc/file.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/lib/utils/fixtures/get-code-wrap-indent-info/override-prettier-option/not-use-prettierrc/file.vue: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/lib/utils/fixtures/get-code-wrap-indent-info/override-prettier-option/use-prettierrc/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "tabWidth": 20, 3 | "vueIndentScriptAndStyle": true 4 | } -------------------------------------------------------------------------------- /tools/util/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./const"; 2 | export * from "./get-rules-meta-data"; 3 | export * from "./create-rules-docs"; 4 | export * from "./create-rules-list"; 5 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/Others.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Others 3 | about: Others 4 | --- 5 | 6 | 9 | -------------------------------------------------------------------------------- /tests/lib/utils/fixtures/get-code-wrap-indent-info/use-prettierrc/set-use-tabs/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "tabWidth": 200, 3 | "useTabs": true, 4 | "vueIndentScriptAndStyle": true 5 | } -------------------------------------------------------------------------------- /tools/util/format-markdown.ts: -------------------------------------------------------------------------------- 1 | import prettier from "prettier"; 2 | 3 | export const formatMarkdown = (content: string) => 4 | prettier.format(content, { parser: "markdown" }); 5 | -------------------------------------------------------------------------------- /tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "exclude": ["tests/**/*", "tools/**/*"], 4 | "compilerOptions": { 5 | "removeComments": true 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /tests/lib/rules/fixtures/format-query-block/valid/03/code.vue: -------------------------------------------------------------------------------- 1 | 2 | query Example { 3 | example: examplePage(path: "/docs/example") { 4 | content 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /lib/utils/types/Node.ts: -------------------------------------------------------------------------------- 1 | export const NodeNames = { 2 | template: "template", 3 | script: "script", 4 | style: "style", 5 | 6 | "page-query": "page-query", 7 | "static-query": "static-query", 8 | } as const; 9 | -------------------------------------------------------------------------------- /tests/lib/rules/fixtures/format-query-block/invalid/03/output.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | query Example { 4 | example: examplePage(path: "/docs/example") { 5 | content 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /lib/configs/base.ts: -------------------------------------------------------------------------------- 1 | export = { 2 | parser: "vue-eslint-parser", 3 | parserOptions: { 4 | sourceType: "module", 5 | ecmaFeatures: { 6 | jsx: true, 7 | }, 8 | }, 9 | plugins: ["gridsome"], 10 | }; 11 | -------------------------------------------------------------------------------- /tests/lib/rules/fixtures/use-env-prefix/invalid/01/code.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /tools/util/types.ts: -------------------------------------------------------------------------------- 1 | import { ESLintUtils } from "@typescript-eslint/experimental-utils"; 2 | 3 | export type Rule = ReturnType>; 4 | 5 | export type RuleMetaData = { name: string; meta: Rule["meta"] }; 6 | -------------------------------------------------------------------------------- /tests/lib/rules/fixtures/format-query-block/invalid/03/code.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | query Example { 4 | example: examplePage (path: "/docs/example") { 5 | content 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /tests/lib/rules/fixtures/format-query-block/invalid/04/code.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | query Example { 4 | example: examplePage (path: "/docs/example") { 5 | content 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /tests/lib/rules/fixtures/use-env-prefix/valid/01/code.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /tests/lib/rules/fixtures/format-query-block/invalid/04/output.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | query Example { 4 | example: examplePage(path: "/docs/example") { 5 | content 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /tools/util/const.ts: -------------------------------------------------------------------------------- 1 | import path from "path"; 2 | 3 | export const NAME_SPACE = "gridsome"; 4 | export const DIR_ROOT = path.join(__dirname, "../../"); 5 | export const DIR_LIB = path.join(DIR_ROOT, "lib"); 6 | export const DIR_DOCS = path.join(DIR_ROOT, "docs"); 7 | -------------------------------------------------------------------------------- /tests/lib/rules/fixtures/format-query-block/valid/01/code.vue: -------------------------------------------------------------------------------- 1 | 2 | query Blog { 3 | allWordPressPost(limit: 5) { 4 | edges { 5 | node { 6 | id 7 | title 8 | } 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /lib/utils/create-rule.ts: -------------------------------------------------------------------------------- 1 | import { RuleCreator } from "./rule-creator"; 2 | 3 | // eslint-disable-next-line new-cap 4 | export const createRule = RuleCreator( 5 | (name) => 6 | `https://github.com/gridsome/eslint-plugin-gridsome/blob/master/docs/rules/${name}.md` 7 | ); 8 | -------------------------------------------------------------------------------- /tests/lib/rules/fixtures/format-query-block/invalid/01/output.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | query Blog { 4 | allWordPressPost(limit: 5) { 5 | edges { 6 | node { 7 | id 8 | title 9 | } 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /tests/lib/rules/fixtures/use-env-prefix/valid/03/client.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: [ 3 | { 4 | use: "@gridsome/source-plugin", 5 | options: { 6 | username: "user", 7 | password: "password", 8 | }, 9 | }, 10 | ], 11 | }; 12 | -------------------------------------------------------------------------------- /tools/util/format-typescript.ts: -------------------------------------------------------------------------------- 1 | import eslint from "eslint"; 2 | 3 | export const formatTypescript = async (content: string) => { 4 | const linter = new eslint.ESLint({ fix: true }); 5 | const results = await linter.lintText(content); 6 | 7 | return results[0].output; 8 | }; 9 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | home: true 3 | heroImage: /eslint-plugin-gridsome.svg 4 | heroText: ESLint plugin Gridsome 5 | tagline: ESLint plugin for Gridsome 6 | actionText: Get Started → 7 | actionLink: /introduction/ 8 | footer: MIT Licensed | Copyright © 2018-present Gridsome 9 | --- 10 | -------------------------------------------------------------------------------- /tests/lib/rules/fixtures/format-query-block/invalid/02/output.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | query Blog { 4 | allWordPressPost(limit: 5) { 5 | edges { 6 | node { 7 | id 8 | 9 | title 10 | } 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /tools/update.ts: -------------------------------------------------------------------------------- 1 | import { updateRulesDocs } from "./update-rules-docs"; 2 | import { updateRulesList } from "./update-rules-list"; 3 | 4 | // eslint-disable-next-line @mysticatea/ts/no-floating-promises 5 | (async () => { 6 | await updateRulesDocs(); 7 | await updateRulesList(); 8 | })(); 9 | -------------------------------------------------------------------------------- /tests/lib/rules/fixtures/format-query-block/invalid/01/code.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | query Blog { 4 | allWordPressPost(limit: 5){ 5 | edges{ 6 | node { 7 | id 8 | title 9 | } 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /tests/lib/rules/fixtures/use-env-prefix/invalid/02/client.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: [ 3 | { 4 | use: '@gridsome/source-plugin', 5 | options: { 6 | username: process.env.DB_USER, 7 | password: process.env.DB_PASS 8 | } 9 | } 10 | ] 11 | } -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Check 4 | 5 | - [ ] Pass the rule's test. : `npm run test` 6 | - [ ] Fill the rule's docs. 7 | - [ ] Create files by Hygen. : `npm run gen:rule` 8 | 9 | 10 | 11 | # What 12 | 13 | # Related issue 14 | -------------------------------------------------------------------------------- /lib/configs/recommended.ts: -------------------------------------------------------------------------------- 1 | export = { 2 | extends: require.resolve("./base"), 3 | rules: { 4 | "gridsome/format-query-block": "warn", 5 | "gridsome/require-g-image-src": "error", 6 | "gridsome/require-g-link-to": "warn", 7 | "gridsome/use-env-prefix": "warn", 8 | }, 9 | }; 10 | -------------------------------------------------------------------------------- /tests/lib/rules/fixtures/use-env-prefix/valid/02/client.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: [ 3 | { 4 | use: '@gridsome/source-plugin', 5 | options: { 6 | username: process.env.GRIDSOME_DB_USER, 7 | password: process.env.GRIDSOME_DB_PASS 8 | } 9 | } 10 | ] 11 | } -------------------------------------------------------------------------------- /tests/lib/rules/fixtures/format-query-block/invalid/02/code.vue: -------------------------------------------------------------------------------- 1 | 2 | 3 | query Blog { 4 | allWordPressPost(limit: 5) { 5 | edges { 6 | node { 7 | id 8 | 9 | 10 | title 11 | } 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /_hygen/generate/log/eslint.ejs.t: -------------------------------------------------------------------------------- 1 | --- 2 | to: log/.eslintrc.js 3 | --- 4 | module.exports = { 5 | root: true, 6 | env: { 7 | node: true, 8 | es6: true 9 | }, 10 | parser: "vue-eslint-parser", 11 | parserOptions: { 12 | "sourceType": "module", 13 | }, 14 | rules: { 15 | log: 2 16 | } 17 | }; 18 | -------------------------------------------------------------------------------- /docs/developer-guide/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Developer Guide 3 | --- 4 | 5 | # Developer Guide 6 | 7 | Are you interested in developing this plugin? 8 | **Great!!** 9 | We are always welcome to your help!! 10 | 11 | Please check [CONTRIBUTING.md](https://github.com/gridsome/eslint-plugin-gridsome/blob/master/CONTRIBUTING.md) 12 | -------------------------------------------------------------------------------- /.dependabot/config.yml: -------------------------------------------------------------------------------- 1 | version: 1 2 | 3 | update_configs: 4 | - package_manager: 'javascript' 5 | directory: '/' 6 | update_schedule: 'weekly' 7 | target_branch: 'master' 8 | default_reviewers: 9 | - 'tyankatsu0105' 10 | default_assignees: 11 | - 'tyankatsu0105' 12 | default_labels: 13 | - '🤖dependencies' -------------------------------------------------------------------------------- /_hygen/generate/development/eslint.ejs.t: -------------------------------------------------------------------------------- 1 | --- 2 | to: development/.eslintrc.js 3 | --- 4 | module.exports = { 5 | root: true, 6 | env: { 7 | node: true, 8 | es6: true 9 | }, 10 | parser: "vue-eslint-parser", 11 | rules: { 12 | "format-query-block": 2, 13 | "require-g-image-src": 2, 14 | "require-g-link-to": 2 15 | } 16 | }; -------------------------------------------------------------------------------- /_hygen/generate/rule/prompt.js: -------------------------------------------------------------------------------- 1 | module.exports = [ 2 | { 3 | type: "input", 4 | name: "name", 5 | message: "New rule's name is ..." 6 | }, 7 | { 8 | type: "input", 9 | name: "author", 10 | message: "This rule's author is ..." 11 | }, 12 | { 13 | type: "input", 14 | name: "description", 15 | message: "This rule's brief description is ..." 16 | } 17 | ]; 18 | -------------------------------------------------------------------------------- /_hygen/generate/development/test.ejs.t: -------------------------------------------------------------------------------- 1 | --- 2 | to: development/test.vue 3 | --- 4 | 11 | 12 | 13 | query Blog { 14 | allWordPressPost(limit: 5) { 15 | edges { 16 | node { 17 | id 18 | title 19 | } 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /tools/update-rules-docs.ts: -------------------------------------------------------------------------------- 1 | import fs from "fs"; 2 | import path from "path"; 3 | 4 | import { getRulesMetaData, createRuleDocs, DIR_DOCS } from "./util"; 5 | 6 | const rulesDocsPath = path.join(DIR_DOCS, "rules", "README.md"); 7 | 8 | export const updateRulesDocs = async () => { 9 | const { rulesMetaData } = await getRulesMetaData(); 10 | 11 | const { doc } = createRuleDocs(rulesMetaData); 12 | 13 | fs.writeFileSync(rulesDocsPath, doc); 14 | }; 15 | -------------------------------------------------------------------------------- /tools/update-rules-list.ts: -------------------------------------------------------------------------------- 1 | import fs from "fs"; 2 | 3 | import { getRulesMetaData, createRulesList, DIR_LIB } from "./util"; 4 | 5 | const rulesListPath = `${DIR_LIB}/rules.ts`; 6 | 7 | export const updateRulesList = async () => { 8 | const { rulesMetaData } = await getRulesMetaData(); 9 | const { list } = await createRulesList(rulesMetaData); 10 | 11 | if (list !== undefined) { 12 | fs.writeFileSync(rulesListPath, list); 13 | } 14 | }; 15 | -------------------------------------------------------------------------------- /lib/utils/parser-services.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @see https://github.com/mysticatea/vue-eslint-parser/blob/master/src/parser-services.ts 3 | */ 4 | 5 | import { TemplateBodyVisitor, ScriptVisitor } from "./types"; 6 | 7 | export const defineTemplateBodyVisitor = ( 8 | context: any, 9 | templateBodyVisitor?: TemplateBodyVisitor, 10 | scriptVisitor?: ScriptVisitor 11 | ) => 12 | context.parserServices.defineTemplateBodyVisitor( 13 | templateBodyVisitor, 14 | scriptVisitor 15 | ); 16 | -------------------------------------------------------------------------------- /lib/utils/types/Parser.ts: -------------------------------------------------------------------------------- 1 | import { AST } from "vue-eslint-parser"; 2 | import { TSESLint, TSESTree } from "@typescript-eslint/experimental-utils"; 3 | 4 | export type VueEslintParserNodeTypes = AST.Node["type"]; 5 | 6 | export type TemplateBodyVisitor = { 7 | [key in VueEslintParserNodeTypes]?: TSESLint.RuleFunction< 8 | AST.Node & TSESTree.BaseNode 9 | >; 10 | } & { [nodeSelector: string]: TSESLint.RuleFunction | undefined }; 11 | 12 | export type ScriptVisitor = { [key: string]: (...args: any) => void }; 13 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/Improve_Rule.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Improve Rule 3 | about: Suggest an idea for a exist rule 4 | --- 5 | 6 | **Please write rule name what you want to improve:** 7 | 8 | 9 | 10 | **How are the rules improved?:** 11 | 12 | **Provide 2-3 code examples that this rule should warn about:** 13 | 14 | ```vue 15 | 16 | ``` 17 | 18 | **Additional context** 19 | 20 | 21 | -------------------------------------------------------------------------------- /_hygen/generate/rule/doc.ejs.t: -------------------------------------------------------------------------------- 1 | --- 2 | to: docs/rules/<%= name %>.md 3 | --- 4 | --- 5 | title: <%= name %> 6 | sidebarDepth: 0 7 | description: <%= description %> 8 | --- 9 | ## Rule's description is here (gridsome/<%= name %>) 10 | 11 | ## :book: Rule Details 12 | 13 | :-1: Examples of **incorrect** code for this rule: 14 | 15 | ```html 16 | Bad example 17 | ``` 18 | 19 | :+1: Examples of **correct** code for this rule: 20 | 21 | ```html 22 | Good example 23 | ``` 24 | 25 | ## :wrench: Options 26 | 27 | If this rule has option, write here. 28 | -------------------------------------------------------------------------------- /lib/rules.ts: -------------------------------------------------------------------------------- 1 | // This file has been automatically generated, in order to update it's content execute "npm run update" 2 | import formatQueryBlock from "./rules/format-query-block"; 3 | import requireGImageSrc from "./rules/require-g-image-src"; 4 | import requireGLinkTo from "./rules/require-g-link-to"; 5 | import useEnvPrefix from "./rules/use-env-prefix"; 6 | 7 | export const rules = { 8 | "format-query-block": formatQueryBlock, 9 | "require-g-image-src": requireGImageSrc, 10 | "require-g-link-to": requireGLinkTo, 11 | "use-env-prefix": useEnvPrefix, 12 | }; 13 | -------------------------------------------------------------------------------- /tests/lib/utils/path.spec.ts: -------------------------------------------------------------------------------- 1 | import { getPathFromProjectRoot } from "../../../lib/utils/path"; 2 | 3 | import { expect } from "chai"; 4 | 5 | describe("path", () => { 6 | describe("getPathFromProjectRoot", () => { 7 | it("when call getPathFromProjectRoot with context.getFilename() and process.cwd(), return path from project root", () => { 8 | const filename = "/User/path/to/project/src/index.js"; 9 | const cwd = "/User/path/to/project"; 10 | 11 | const result = getPathFromProjectRoot(filename, cwd); 12 | 13 | expect(result).to.deep.equal("src/index.js"); 14 | }); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /_hygen/generate/rule/test.ejs.t: -------------------------------------------------------------------------------- 1 | --- 2 | to: tests/lib/rules/<%= name %>.spec.ts 3 | --- 4 | import { RuleTester } from "../../util"; 5 | 6 | import rule from "../../../lib/rules/<%= name %>"; 7 | 8 | const tester = new RuleTester({ 9 | parser: "vue-eslint-parser", 10 | parserOptions: { 11 | ecmaVersion: 2017, 12 | }, 13 | }); 14 | 15 | tester.run("<%= name %>", rule, { 16 | valid: [ 17 | ``, 18 | ], 19 | invalid: [ 20 | { 21 | code: ``, 22 | errors: [ 23 | { 24 | messageId: "<%= h.changeCase.camel(name) %>", 25 | }, 26 | ], 27 | }, 28 | ], 29 | }); 30 | -------------------------------------------------------------------------------- /tests/util/rule-tester.ts: -------------------------------------------------------------------------------- 1 | import { TSESLint } from "@typescript-eslint/experimental-utils"; 2 | 3 | type Parser = "vue-eslint-parser"; 4 | 5 | type RuleTesterConfig = Omit & { 6 | parser: Parser; 7 | }; 8 | 9 | export class RuleTester extends TSESLint.RuleTester { 10 | constructor(protected config: RuleTesterConfig) { 11 | super({ 12 | ...config, 13 | // @see https://eslint.org/docs/user-guide/migrating-to-6.0.0#ruletester-now-requires-an-absolute-path-on-parser-option 14 | parser: require.resolve(config.parser), 15 | }); 16 | } 17 | } 18 | /* eslint-enable */ 19 | -------------------------------------------------------------------------------- /tests/lib/rules/fixtures/format-query-block/valid/02/code.vue: -------------------------------------------------------------------------------- 1 | 2 | fragment RankingParts on TourRanking { 3 | id 4 | rankings: data { 5 | rank 6 | nickname 7 | score 8 | badge: pin_badge_image_url 9 | ranking_started_at 10 | ranking_finished_at 11 | } 12 | } 13 | 14 | query($id: ID, $prevId: ID, $nextId: ID) { 15 | ranking: tourRanking(id: $id) { 16 | ...RankingParts 17 | } 18 | 19 | next: tourRanking(id: $prevId) { 20 | ...RankingParts 21 | } 22 | 23 | prev: tourRanking(id: $nextId) { 24 | ...RankingParts 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /lib/utils/attribute.ts: -------------------------------------------------------------------------------- 1 | import { AST } from "vue-eslint-parser"; 2 | 3 | /** 4 | * Get the attribute which has the given name. 5 | */ 6 | export const getAttribute = ( 7 | node: AST.VElement, 8 | name: string, 9 | value?: string 10 | ) => 11 | node.startTag.attributes.find( 12 | (a) => 13 | !a.directive && 14 | a.key.name === name && 15 | (value === undefined || (a.value != null && a.value.value === value)) 16 | ); 17 | 18 | /** 19 | * Check whether the given start tag has specific directive. 20 | */ 21 | export const hasAttribute = ( 22 | node: AST.VElement, 23 | name: string, 24 | value?: string 25 | ) => Boolean(getAttribute(node, name, value)); 26 | -------------------------------------------------------------------------------- /_hygen/generate/log/test.ejs.t: -------------------------------------------------------------------------------- 1 | --- 2 | to: log/tests/log.vue 3 | --- 4 | 10 | 19 | 20 | 21 | query Blog { 22 | allWordPressPost (limit: 5) { 23 | edges { 24 | node { 25 | id 26 | 27 | title 28 | } 29 | } 30 | } 31 | } 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /tools/util/get-rules-meta-data.ts: -------------------------------------------------------------------------------- 1 | import fs from "fs"; 2 | 3 | import { DIR_LIB } from "./const"; 4 | import { Rule, RuleMetaData } from "./types"; 5 | 6 | const getRuleName = (rulePath: string) => { 7 | const ruleName = rulePath.slice(0, -3); 8 | 9 | return ruleName; 10 | }; 11 | 12 | export const getRulesMetaData = async () => { 13 | const rulePaths = fs.readdirSync(`${DIR_LIB}/rules`); 14 | const rulesMetaData: RuleMetaData[] = []; 15 | 16 | for (const rulePath of rulePaths) { 17 | const name = getRuleName(rulePath); 18 | 19 | const rule: Promise = await import(`${DIR_LIB}/rules/${rulePath}`); 20 | rulesMetaData.push({ 21 | name, 22 | meta: (await rule).meta, 23 | }); 24 | } 25 | 26 | return { rulesMetaData }; 27 | }; 28 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | /** @type import('eslint').Linter.BaseConfig */ 2 | module.exports = { 3 | parserOptions: { 4 | ecmaVersion: 2017, 5 | sourceType: "module", 6 | }, 7 | parser: "@typescript-eslint/parser", 8 | env: { 9 | node: true, 10 | }, 11 | 12 | extends: [ 13 | "eslint:recommended", 14 | "plugin:@typescript-eslint/recommended", 15 | "prettier", 16 | ], 17 | plugins: ["prettier"], 18 | rules: { 19 | "prettier/prettier": "error", 20 | "func-style": ["error", "expression"], 21 | "@typescript-eslint/explicit-module-boundary-types": "off", 22 | "@typescript-eslint/ban-types": "off", 23 | "@typescript-eslint/no-explicit-any": "off", 24 | "no-irregular-whitespace": ["error", { 25 | "skipRegExps": true 26 | }] 27 | }, 28 | }; 29 | -------------------------------------------------------------------------------- /docs/introduction/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Introduction 3 | --- 4 | 5 | # Introduction 6 | 7 | Official ESLint plugin for Gridsome. 8 | This plugin helps you to check the `