Skip to content

Commit

Permalink
feat: rule quine
Browse files Browse the repository at this point in the history
  • Loading branch information
lzear committed Aug 3, 2024
1 parent 6510ce0 commit b5a0638
Show file tree
Hide file tree
Showing 9 changed files with 111 additions and 8 deletions.
9 changes: 7 additions & 2 deletions api/lint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ const ruleNames = Object.keys(plugin.rules) as RuleName[]
const isRuleName = (rule: string): rule is RuleName =>
ruleNames.includes(rule as RuleName)

const isExcludedRule = (rule: RuleName) => ['quine'].includes(rule)

const lintLocal = <Rule extends RuleName>(
code: string,
rule: Rule,
Expand Down Expand Up @@ -48,9 +50,12 @@ const lintServerless = async (request: VercelRequest, res: VercelResponse) => {
// if (!parsed.success) return res.status(400).send({error: 'Invalid payload'})
const { code, options, rule } = parsed

if (!isRuleName(rule)) {
if (!isRuleName(rule))
return res.status(400).send({ error: 'invalid rule name' })
}

if (isExcludedRule(rule))
return res.status(400).send({ error: 'rule not supported' })

const lintResults = lintLocal(code, rule, options)
return res.status(200).send(lintResults)
}
Expand Down
4 changes: 2 additions & 2 deletions docs/rules/align.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
title: center
title: align
description: Align text elegantly
---

Expand All @@ -11,7 +11,7 @@ import {ruleName, presetConfigs, initialText} from '../../src/sample-code/align'
> "Typography is two-dimensional architecture, based on experience and
> imagination, and guided by rules and readability." — Hermann Zapf
# Enforce elegant text alignment (`align`)
# align

💼 This rule is enabled in the following [configs](/configs/): 🌐 `all`, ✅
`recommended`.
Expand Down
1 change: 1 addition & 0 deletions docs/rules/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ description: ESLint Plugin Ninja list of rules
| [prefer-emoji](/rules/prefer-emoji) | require variables and properties to be named using emojis | 🔧 |
| [prefer-npm](/rules/prefer-npm) | require from npm instead of using JS builtins | 🔧 |
| [prefer-tab](/rules/prefer-tab) | require word separators to be tabs, not spaces | 🔧 |
| [quine](/rules/quine) | enforce quine | |
| [yes](/rules/yes) | enforce nothing | |

<!-- end auto-generated rules list -->
41 changes: 41 additions & 0 deletions docs/rules/quine.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
---
title: quine
description: Enforce quines
---

<script setup lang="ts">
import CodeEditor from '../../.vitepress/theme/components/code-editor.vue';
import {ruleName, initialText} from '../../src/sample-code/quine';
</script>

> "This sentence contains thirty-six characters."
# Enforce quines (`quine`)

💼 This rule is enabled in the 🌐 `all` [config](/configs/).

<!-- end auto-generated rule header -->

## 💡 Examples

::: code-group

<!-- prettier-ignore -->
```js [Center]
// ✅ Correct
($=_=>`($=${$})()`)()
```

<!-- prettier-ignore -->
```js [Right]
// ✅ Correct
( function quine() {console.log("( " + quine.toString() + " )()")} )()
```

:::

## 🔧 Config

```js
{ rules: { 'ninja/quine': 2 } }
```
14 changes: 11 additions & 3 deletions index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import lottery, { RULE_NAME as lotteryName } from './rules/lottery'
import noRush, { RULE_NAME as noRushName } from './rules/no-rush'
import noWoof, { RULE_NAME as noWoofName } from './rules/no-woof'
import noXkcd, { RULE_NAME as noXkcdName } from './rules/no-xkcd'
import quine, { RULE_NAME as quineName } from './rules/quine'
import align, { RULE_NAME as alignName } from './rules/align'
import noCi, { RULE_NAME as noCiName } from './rules/no-ci'
import noTs, { RULE_NAME as noTsName } from './rules/no-ts'
Expand Down Expand Up @@ -45,6 +46,7 @@ const rules = {
[preferEmojiName]: preferEmoji,
[preferNpmName]: preferNpm,
[preferTabName]: preferTab,
[quineName]: quine,
[yesName]: yes,
} as const

Expand All @@ -67,13 +69,19 @@ const recommendedRules = [
preferEmojiName,
preferNpmName,
yesName,
] as const
] as const satisfies (keyof typeof rules)[]

const all: Record<string, [0 | 1 | 2, unknown]> = {}
const recommended: Record<string, [0 | 1 | 2, unknown]> = {}

for (const n of Object.keys(rules)) all[`ninja/${n}`] = [2, {}]
for (const n of recommendedRules) recommended[`ninja/${n}`] = [2, {}]
const excludedDangerousRules = [quineName]

for (const n of Object.keys(rules) as (keyof typeof rules)[])
if (!excludedDangerousRules.includes(n)) all[`ninja/${n}`] = [2, {}]

for (const n of recommendedRules)
if (excludedDangerousRules.includes(n)) throw new Error(`Rule ${n} should not be included in recommended rules`)
else recommended[`ninja/${n}`] = [2, {}]

recommended['ninja/no-rush'] = [1, { delay: 1 }]
recommended['ninja/lottery'] = [2, { probability: 0.9 }]
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "eslint-plugin-ninja",
"description": "Optimized ESLint Rules for Elite Coders",
"version": "0.0.8",
"version": "0.0.9",
"homepage": "https://www.dont.ninja",
"repository": {
"type": "git",
Expand Down
1 change: 1 addition & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ npm i -D eslint-plugin-ninja
| [prefer-emoji](https://www.dont.ninja/rules/prefer-emoji) | require variables and properties to be named using emojis | 🔧 |
| [prefer-npm](https://www.dont.ninja/rules/prefer-npm) | require from npm instead of using JS builtins | 🔧 |
| [prefer-tab](https://www.dont.ninja/rules/prefer-tab) | require word separators to be tabs, not spaces | 🔧 |
| [quine](https://www.dont.ninja/rules/quine) | enforce quine | |
| [yes](https://www.dont.ninja/rules/yes) | enforce nothing | |

<!-- end auto-generated rules list -->
Expand Down
39 changes: 39 additions & 0 deletions rules/quine.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import type { RuleContext, RuleListener } from '../utils/eslint-types/Rule'

import { createEslintRule } from '../utils/create-eslint-rule'

type MESSAGE_ID = 'not a quine'

type Options = []

export const RULE_NAME = 'quine'
type Context = RuleContext<MESSAGE_ID, Options>

export default createEslintRule<Options, MESSAGE_ID>({
name: RULE_NAME,
meta: {
type: 'problem',
docs: {
description: 'enforce quine',
},
schema: [{ type: 'object' }],
messages: {
'not a quine': 'not a quine',
},
},
defaultOptions: [],
create: (context: Context): RuleListener => {
const sourceCode = context.getSourceCode()
const text = sourceCode?.text || ''
const processCode = (code: string) => {
// eslint-disable-next-line no-eval
const evalResult = eval(code)
if (code !== evalResult)
context.report({
messageId: 'not a quine',
loc: { column: 0, line: 1 },
})
}
return { Program: () => processCode(text) }
},
})
8 changes: 8 additions & 0 deletions src/sample-code/quine.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import type { PresetConfig } from './presets'

export const presetConfigs = [] satisfies PresetConfig[]

export const ruleName = 'quine'

// eslint-disable-next-line no-template-curly-in-string
export const initialText = '($=_=>`($=${$})()`)()'

0 comments on commit b5a0638

Please sign in to comment.