Skip to content

Commit

Permalink
feat: rule no-xkcd
Browse files Browse the repository at this point in the history
  • Loading branch information
lzear committed Nov 4, 2023
1 parent df03379 commit f62f583
Show file tree
Hide file tree
Showing 3 changed files with 139 additions and 0 deletions.
48 changes: 48 additions & 0 deletions docs/rules/no-xkcd.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
---
title: yes
description: Allow all
---

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

> "Originality is the best form of rebellion." – Mike Sasso

# Disallow xkcd references (`dont/no-xkcd`)

🔧 This rule is automatically fixable by the [`--fix` CLI option](https://eslint.org/docs/latest/user-guide/command-line-interface#--fix).

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

## 📖 Rule details

`xkcd` is great and all, but references to it are overused!
Also, you're not edgy or teaching anyone anything. Everybody and their grandma is reading it, and we've all seen that
comic a billion times, especially #927 (you already know which one I'm talking about).

On exception for https://xkcd.com/2832 which is allowed because fuck cars.

## 💡 Examples

```js
// ❌ Incorrect
// lol xkcd/3241
const woof = 'woof'

// ✅ Correct
// lol it's nonsense
const woof = 'woof'
```

## 🔧 Config

```js
{ rules: { 'dont/no-xkcd': 2 } }
```

## 🧑‍💻 Demo

<CodeEditor :rule="ruleName" :text="initialText" :presetConfigs="presetConfigs" />
76 changes: 76 additions & 0 deletions rules/no-xkcd.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import type { TSESTree } from '@typescript-eslint/types'

import type { RuleContext, RuleListener } from '../utils/eslint-types/Rule.js'

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

type MESSAGE_ID = 'noxkcd'

type Options = [unknown]

export const RULE_NAME = 'no-xkcd'
type Context = RuleContext<MESSAGE_ID, Options>
const CHAR_LIMIT = 40

export default createEslintRule<Options, MESSAGE_ID>({
name: RULE_NAME,
meta: {
type: 'problem',
docs: {
description: 'disallow xkcd references',
},
fixable: 'code',
schema: [
{
type: 'object',
properties: {},
},
],
messages: {
noxkcd:
'xkcd references are overused. Please remove them. ({{ matchedTerm }}) {{ comment }}',
},
},
defaultOptions: [{}],
create: (context: Context): RuleListener => {
const noxkcdButFuckcars =
/xkcd\.com\/(?!2832$|comics\/urban_planning_opinion_progression).*/i

const checkComment = (node: TSESTree.Comment) => {
const comment = node.value
const matches = comment.match(noxkcdButFuckcars)
for (const matchedTerm of matches || []) {
let commentToDisplay = ''
let truncated = false

for (const c of comment.trim().split(/\s+/u)) {
const tmp = commentToDisplay ? `${commentToDisplay} ${c}` : c

if (tmp.length <= CHAR_LIMIT) {
commentToDisplay = tmp
} else {
truncated = true
break
}
}

context.report({
node,
messageId: 'noxkcd',
data: {
matchedTerm,
comment: `${commentToDisplay}${truncated ? '...' : ''}`,
},
})
}
}

const { sourceCode } = context
return {
Program: () => {
const comments = sourceCode.getAllComments()
for (const node of comments) checkComment(node)
},
}
},
})
15 changes: 15 additions & 0 deletions src/sample-code/no-xkcd.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import type { PresetConfig } from './presets.js'

export const ruleName = 'no-xkcd'

export const presetConfigs = [] satisfies PresetConfig[]

export const initialText = `
// https://xkcd.com/2838/
// https://xkcd.com/2832/
// https://xkcd.com/2826/
const img = '<img src="https://xkcd.com/2820/" />'
`

0 comments on commit f62f583

Please sign in to comment.