Skip to content

Commit

Permalink
feat: add missing-directive-value rule (#322)
Browse files Browse the repository at this point in the history
* wip: add new rule

* feat: add changeset file

* fix: add new check for the rule and more tests

* fix: rename the rule from missing-client-only-directive-value

---------

Co-authored-by: OM <[email protected]>
  • Loading branch information
oanaOM and OM authored Mar 24, 2024
1 parent bd11f45 commit d55a51e
Show file tree
Hide file tree
Showing 13 changed files with 153 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .changeset/slimy-pillows-change.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"eslint-plugin-astro": minor
---

feat add `astro/missing-client-only-directive-value` rule
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,7 @@ These rules relate to possible syntax or logic errors in Astro component code:

| Rule ID | Description | |
|:--------|:------------|:---|
| [astro/missing-client-only-directive-value](https://ota-meshi.github.io/eslint-plugin-astro/rules/missing-client-only-directive-value/) | the client:only directive is missing the correct component's framework value ||
| [astro/no-conflict-set-directives](https://ota-meshi.github.io/eslint-plugin-astro/rules/no-conflict-set-directives/) | disallow conflicting set directives and child contents ||
| [astro/no-deprecated-astro-canonicalurl](https://ota-meshi.github.io/eslint-plugin-astro/rules/no-deprecated-astro-canonicalurl/) | disallow using deprecated `Astro.canonicalURL` ||
| [astro/no-deprecated-astro-fetchcontent](https://ota-meshi.github.io/eslint-plugin-astro/rules/no-deprecated-astro-fetchcontent/) | disallow using deprecated `Astro.fetchContent()` | ⭐🔧 |
Expand Down
1 change: 1 addition & 0 deletions docs/rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ These rules relate to possible syntax or logic errors in Astro component code:

| Rule ID | Description | |
|:--------|:------------|:---|
| [astro/missing-client-only-directive-value](./rules/missing-client-only-directive-value.md) | the client:only directive is missing the correct component's framework value ||
| [astro/no-conflict-set-directives](./rules/no-conflict-set-directives.md) | disallow conflicting set directives and child contents ||
| [astro/no-deprecated-astro-canonicalurl](./rules/no-deprecated-astro-canonicalurl.md) | disallow using deprecated `Astro.canonicalURL` ||
| [astro/no-deprecated-astro-fetchcontent](./rules/no-deprecated-astro-fetchcontent.md) | disallow using deprecated `Astro.fetchContent()` | ⭐🔧 |
Expand Down
49 changes: 49 additions & 0 deletions docs/rules/missing-client-only-directive-value.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
---
title: "astro/missing-client-only-directive-value"
description: "the client:only directive is missing the correct component's framework value"
---

# astro/missing-client-only-directive-value

> the client:only directive is missing the correct component's framework value
- ❗ <badge text="This rule has not been released yet." vertical="middle" type="error"> **_This rule has not been released yet._** </badge>
- ⚙ This rule is included in `"plugin:astro/recommended"`.

## 📖 Rule Details

This rule reports not setting a value for the `client:only` directive.

<ESLintCodeBlock>

<!--eslint-skip-->

```astro
---
/* eslint astro/missing-client-only-directive-value: "error" */
---
{/* ✓ GOOD */}
<SomeSvelteComponent client:only="svelte" />
{/* ✗ BAD */}
<SomeSvelteComponent client:only />
```

</ESLintCodeBlock>

## 🔧 Options

Nothing.


## 📚 Further Reading

- [Astro Documentation | Template Directives Reference > client:only](https://docs.astro.build/en/reference/directives-reference/#clientonly)

## 🔍 Implementation

- [Rule source](https://github.com/ota-meshi/eslint-plugin-astro/blob/main/src/rules/missing-client-only-directive-value.ts)
- [Test source](https://github.com/ota-meshi/eslint-plugin-astro/blob/main/tests/src/rules/missing-client-only-directive-value.ts)
- [Test fixture sources](https://github.com/ota-meshi/eslint-plugin-astro/tree/main/tests/fixtures/rules/missing-client-only-directive-value)
1 change: 1 addition & 0 deletions src/configs/flat/recommended.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ export default [
{
rules: {
// eslint-plugin-astro rules
"astro/missing-client-only-directive-value": "error",
"astro/no-conflict-set-directives": "error",
"astro/no-deprecated-astro-canonicalurl": "error",
"astro/no-deprecated-astro-fetchcontent": "error",
Expand Down
1 change: 1 addition & 0 deletions src/configs/recommended.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export = {
extends: [baseExtend],
rules: {
// eslint-plugin-astro rules
"astro/missing-client-only-directive-value": "error",
"astro/no-conflict-set-directives": "error",
"astro/no-deprecated-astro-canonicalurl": "error",
"astro/no-deprecated-astro-fetchcontent": "error",
Expand Down
50 changes: 50 additions & 0 deletions src/rules/missing-client-only-directive-value.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import type { AST } from "astro-eslint-parser"
import { createRule } from "../utils"
import { getAttributeName, getStaticAttributeValue } from "../utils/ast-utils"
import { getSourceCode } from "../utils/compat"

export default createRule("missing-client-only-directive-value", {
meta: {
docs: {
description:
"the client:only directive is missing the correct component's framework value",
category: "Possible Errors",
recommended: true,
},
schema: [],
messages: {
missingValue: "`client:only` directive is missing a value",
},
type: "problem",
},
create(context) {
const sourceCode = getSourceCode(context)
if (!sourceCode.parserServices.isAstro) {
return {}
}

/** VerifyDirectiveValue */
function verifyDirectiveValue(
attr: AST.JSXAttribute | AST.AstroTemplateLiteralAttribute,
) {
const directiveName = getAttributeName(attr)
const directiveValue = getStaticAttributeValue(attr)

if (directiveName !== "client:only") return

if (directiveValue !== null) {
return
}

context.report({
node: attr.name,
messageId: "missingValue",
})
}

return {
JSXAttribute: verifyDirectiveValue,
AstroTemplateLiteralAttribute: verifyDirectiveValue,
}
},
})
2 changes: 2 additions & 0 deletions src/utils/rules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// This file has been automatically generated,
// in order to update its content execute "npm run update"
import type { RuleModule } from "../types"
import missingClientOnlyDirectiveValue from "../rules/missing-client-only-directive-value"
import noConflictSetDirectives from "../rules/no-conflict-set-directives"
import noDeprecatedAstroCanonicalurl from "../rules/no-deprecated-astro-canonicalurl"
import noDeprecatedAstroFetchcontent from "../rules/no-deprecated-astro-fetchcontent"
Expand All @@ -19,6 +20,7 @@ import validCompile from "../rules/valid-compile"
import { buildA11yRules } from "../a11y"

export const rules = [
missingClientOnlyDirectiveValue,
noConflictSetDirectives,
noDeprecatedAstroCanonicalurl,
noDeprecatedAstroFetchcontent,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<script>
</script>

<main>
<h1>Hello Svelte!</h1>
</main>
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[
{
"message": "`client:only` directive is missing a value",
"line": 5,
"column": 22
}
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
import SomeSvelteComponent from "../SomeSvelteComponent.svelte"
---

<SomeSvelteComponent client:only />
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
import SomeSvelteComponent from "../SomeSvelteComponent.svelte"
let string = "svelte"
---

<!-- prettier-ignore-start -->
<SomeSvelteComponent client:only={string} />
<SomeSvelteComponent client:idle />
<!-- prettier-ignore-end -->
16 changes: 16 additions & 0 deletions tests/src/rules/missing-client-only-directive-value.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { RuleTester } from "../../utils/eslint-compat"
import rule from "../../../src/rules/missing-client-only-directive-value"
import { loadTestCases } from "../../utils/utils"

const tester = new RuleTester({
languageOptions: {
ecmaVersion: 2020,
sourceType: "module",
},
})

tester.run(
"missing-client-only-directive-value",
rule as any,
loadTestCases("missing-client-only-directive-value"),
)

0 comments on commit d55a51e

Please sign in to comment.