Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit cdcf75e

Browse files
ota-meshiFloEdelmann
andauthored
Improved rule list doc (#1860)
* Improved rule list doc * update markdownlint config * Update tools/update-docs-rules-index.js Co-authored-by: Flo Edelmann <florian-edelmann@online.de> * Update docs/.vuepress/components/rules-table.vue Co-authored-by: Flo Edelmann <florian-edelmann@online.de> * Update docs/.vuepress/components/rules-table.vue Co-authored-by: Flo Edelmann <florian-edelmann@online.de> * Update tools/update-docs-rules-index.js Co-authored-by: Flo Edelmann <florian-edelmann@online.de> * Update tools/update-docs-rules-index.js Co-authored-by: Flo Edelmann <florian-edelmann@online.de> * Update tools/lib/utils.js Co-authored-by: Flo Edelmann <florian-edelmann@online.de> * Update tools/lib/utils.js Co-authored-by: Flo Edelmann <florian-edelmann@online.de> * Update tools/update-docs-rules-index.js Co-authored-by: Flo Edelmann <florian-edelmann@online.de> * update * update markdownlint config Co-authored-by: Flo Edelmann <florian-edelmann@online.de>
1 parent c43e04f commit cdcf75e

File tree

8 files changed

+543
-435
lines changed

8 files changed

+543
-435
lines changed

‎.markdownlint.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ no-inline-html:
55
- badge
66
- eslint-code-block
77
- sup
8+
- rules-table
9+
- span
810

911
# enforce consistency
1012
code-block-style:
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
<template>
2+
<div>
3+
<div v-if="kindMarks.length > 1" class="filter-tool">
4+
Highlight:
5+
<label v-for="kindMark in kindMarks" :key="kindMark">
6+
<input type="checkbox" :value="kindMark" v-model="checkedKindMarks" />
7+
<span class="emoji">{{ kindMark }}</span>
8+
</label>
9+
</div>
10+
<div class="table-root" ref="tableRoot">
11+
<slot />
12+
</div>
13+
</div>
14+
</template>
15+
16+
<script>
17+
const emojis = ['3️⃣', '2️⃣', '⚠️']
18+
19+
export default {
20+
data() {
21+
return {
22+
kindMarks: [],
23+
checkedKindMarks: []
24+
}
25+
},
26+
mounted() {
27+
this.setup()
28+
},
29+
watch: {
30+
checkedKindMarks: {
31+
handler: 'filterTable',
32+
deep: true
33+
}
34+
},
35+
methods: {
36+
setup() {
37+
const kindMarks = new Set()
38+
const table = this.getTable()
39+
for (const row of table.rows) {
40+
row.cells[3].classList.add('emoji')
41+
const trimmed = row.cells[3].textContent.trim()
42+
if (!trimmed) {
43+
continue
44+
}
45+
const chars =
46+
trimmed.match(new RegExp(`${emojis.join('|')}|.`, 'ug')) || []
47+
for (const mark of chars) {
48+
kindMarks.add(mark)
49+
}
50+
}
51+
this.kindMarks = [...kindMarks]
52+
},
53+
getTable() {
54+
return this.$refs.tableRoot.querySelector('table')
55+
},
56+
filterTable() {
57+
const table = this.getTable()
58+
if (this.checkedKindMarks.length === 0) {
59+
table.classList.remove('highlighting')
60+
return
61+
}
62+
table.classList.add('highlighting')
63+
for (const row of table.rows) {
64+
if (row.cells[0].tagName === 'TH') {
65+
row.classList.add('highlight')
66+
continue
67+
}
68+
const rowMarks = row.cells[3].textContent
69+
const highlight = this.checkedKindMarks.every((mark) =>
70+
rowMarks.includes(mark)
71+
)
72+
row.classList.toggle('highlight', highlight)
73+
}
74+
}
75+
}
76+
}
77+
</script>
78+
79+
<style scoped>
80+
.table-root ::v-deep .highlighting tr {
81+
opacity: 0.3;
82+
}
83+
.table-root ::v-deep .highlighting .highlight {
84+
opacity: 1;
85+
}
86+
.filter-tool label {
87+
display: inline-flex;
88+
margin-right: 0.5ex;
89+
}
90+
</style>

‎docs/.vuepress/styles/index.styl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,9 @@
1818
}
1919
}
2020
}
21+
22+
.theme-container.rule-list.theme-default-content
23+
max-width: 1280px;
24+
25+
.emoji
26+
font-family: "Segoe UI Emoji", "Segoe UI Symbol", "Apple Color Emoji", "Noto Color Emoji", "Noto Emoji", sans-serif

‎docs/rules/README.md

Lines changed: 272 additions & 373 deletions
Large diffs are not rendered by default.

‎package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,6 @@
8181
"eslint-plugin-unicorn": "^40.1.0",
8282
"eslint-plugin-vue": "file:.",
8383
"espree": "^9.0.0",
84-
"lodash": "^4.17.21",
8584
"markdownlint-cli": "^0.31.1",
8685
"mocha": "^7.1.2",
8786
"nyc": "^15.1.0",

‎tools/lib/utils.js

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
module.exports = { getPresetIds, formatItems }
2+
3+
const presetCategories = {
4+
base: null,
5+
essential: 'base',
6+
'vue3-essential': 'base',
7+
'strongly-recommended': 'essential',
8+
'vue3-strongly-recommended': 'vue3-essential',
9+
recommended: 'strongly-recommended',
10+
'vue3-recommended': 'vue3-strongly-recommended'
11+
// 'use-with-caution': 'recommended',
12+
// 'vue3-use-with-caution': 'vue3-recommended'
13+
}
14+
15+
function formatItems(items, suffix) {
16+
if (items.length === 1) {
17+
return `${items[0]}${suffix ? ` ${suffix[0]}` : ''}`
18+
}
19+
if (items.length === 2) {
20+
return `${items.join(' and ')}${suffix ? ` ${suffix[1]}` : ''}`
21+
}
22+
return `all of ${items.slice(0, -1).join(', ')} and ${[...items].pop()}${
23+
suffix ? ` ${suffix[1]}` : ''
24+
}`
25+
}
26+
27+
function getPresetIds(categoryIds) {
28+
const subsetCategoryIds = []
29+
for (const categoryId of categoryIds) {
30+
for (const [subsetCategoryId, supersetCategoryId] of Object.entries(
31+
presetCategories
32+
)) {
33+
if (supersetCategoryId === categoryId) {
34+
subsetCategoryIds.push(subsetCategoryId)
35+
}
36+
}
37+
}
38+
if (subsetCategoryIds.length === 0) {
39+
return categoryIds
40+
}
41+
return [...new Set([...categoryIds, ...getPresetIds(subsetCategoryIds)])]
42+
}

‎tools/update-docs-rules-index.js

Lines changed: 130 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,18 @@
77
const fs = require('fs')
88
const path = require('path')
99
const rules = require('./lib/rules')
10-
const categories = require('./lib/categories')
10+
const { getPresetIds, formatItems } = require('./lib/utils')
11+
12+
const VUE3_EMOJI = ':three:'
13+
const VUE2_EMOJI = ':two:'
1114

1215
// -----------------------------------------------------------------------------
16+
const categorizedRules = rules.filter(
17+
(rule) =>
18+
rule.meta.docs.categories &&
19+
!rule.meta.docs.extensionRule &&
20+
!rule.meta.deprecated
21+
)
1322
const uncategorizedRules = rules.filter(
1423
(rule) =>
1524
!rule.meta.docs.categories &&
@@ -24,16 +33,23 @@ const uncategorizedExtensionRule = rules.filter(
2433
)
2534
const deprecatedRules = rules.filter((rule) => rule.meta.deprecated)
2635

27-
function toRuleRow(rule) {
36+
const TYPE_MARK = {
37+
problem: ':warning:',
38+
suggestion: ':hammer:',
39+
layout: ':lipstick:'
40+
}
41+
42+
function toRuleRow(rule, kindMarks = []) {
2843
const mark = [
2944
rule.meta.fixable ? ':wrench:' : '',
3045
rule.meta.hasSuggestions ? ':bulb:' : '',
3146
rule.meta.deprecated ? ':warning:' : ''
3247
].join('')
48+
const kindMark = [...kindMarks, TYPE_MARK[rule.meta.type]].join('')
3349
const link = `[${rule.ruleId}](./${rule.name}.md)`
3450
const description = rule.meta.docs.description || '(no description)'
3551

36-
return `| ${link} | ${description} | ${mark} |`
52+
return `| ${link} | ${description} | ${mark} |${kindMark} |`
3753
}
3854

3955
function toDeprecatedRuleRow(rule) {
@@ -46,25 +62,97 @@ function toDeprecatedRuleRow(rule) {
4662
return `| ${link} | ${replacedBy || '(no replacement)'} |`
4763
}
4864

49-
// -----------------------------------------------------------------------------
50-
let rulesTableContent = categories
51-
.map(
52-
(category) => `
53-
## ${category.title.vuepress}
54-
55-
Enforce all the rules in this category, as well as all higher priority rules, with:
65+
const categoryGroups = [
66+
{
67+
title: 'Base Rules (Enabling Correct ESLint Parsing)',
68+
description:
69+
'Rules in this category are enabled for all presets provided by eslint-plugin-vue.',
70+
categoryIdForVue3: 'base',
71+
categoryIdForVue2: 'base',
72+
useMark: false
73+
},
74+
{
75+
title: 'Priority A: Essential (Error Prevention)',
76+
categoryIdForVue3: 'vue3-essential',
77+
categoryIdForVue2: 'essential',
78+
useMark: true
79+
},
80+
{
81+
title: 'Priority B: Strongly Recommended (Improving Readability)',
82+
categoryIdForVue3: 'vue3-strongly-recommended',
83+
categoryIdForVue2: 'strongly-recommended',
84+
useMark: true
85+
},
86+
{
87+
title: 'Priority C: Recommended (Potentially Dangerous Patterns)',
88+
categoryIdForVue3: 'vue3-recommended',
89+
categoryIdForVue2: 'recommended',
90+
useMark: true
91+
}
92+
]
5693

57-
\`\`\`json
58-
{
59-
"extends": "plugin:vue/${category.categoryId}"
60-
}
61-
\`\`\`
94+
// -----------------------------------------------------------------------------
95+
let rulesTableContent = categoryGroups
96+
.map((group) => {
97+
const rules = categorizedRules.filter(
98+
(rule) =>
99+
rule.meta.docs.categories.includes(group.categoryIdForVue3) ||
100+
rule.meta.docs.categories.includes(group.categoryIdForVue2)
101+
)
102+
let content = `
103+
## ${group.title}
104+
`
62105

63-
| Rule ID | Description | |
64-
|:--------|:------------|:---|
65-
${category.rules.map(toRuleRow).join('\n')}
106+
if (group.description) {
107+
content += `
108+
${group.description}
109+
`
110+
}
111+
if (group.useMark) {
112+
const presetsForVue3 = getPresetIds([group.categoryIdForVue3]).map(
113+
(categoryId) => `\`"plugin:vue/${categoryId}"\``
114+
)
115+
const presetsForVue2 = getPresetIds([group.categoryIdForVue2]).map(
116+
(categoryId) => `\`"plugin:vue/${categoryId}"\``
117+
)
118+
content += `
119+
- ${VUE3_EMOJI} Indicates that the rule is for Vue 3 and is included in ${formatItems(
120+
presetsForVue3,
121+
['preset', 'presets']
122+
)}.
123+
- ${VUE2_EMOJI} Indicates that the rule is for Vue 2 and is included in ${formatItems(
124+
presetsForVue2,
125+
['preset', 'presets']
126+
)}.
66127
`
67-
)
128+
}
129+
130+
content += `
131+
<rules-table>
132+
133+
| Rule ID | Description | | |
134+
|:--------|:------------|:--:|:--:|
135+
${rules
136+
.map((rule) => {
137+
const mark = group.useMark
138+
? [
139+
rule.meta.docs.categories.includes(group.categoryIdForVue3)
140+
? [VUE3_EMOJI]
141+
: [],
142+
rule.meta.docs.categories.includes(group.categoryIdForVue2)
143+
? [VUE2_EMOJI]
144+
: []
145+
].flat()
146+
: []
147+
return toRuleRow(rule, mark)
148+
})
149+
.join('\n')}
150+
151+
</rules-table>
152+
`
153+
154+
return content
155+
})
68156
.join('')
69157

70158
// -----------------------------------------------------------------------------
@@ -90,9 +178,13 @@ For example:
90178
}
91179
if (uncategorizedRules.length > 0) {
92180
rulesTableContent += `
93-
| Rule ID | Description | |
94-
|:--------|:------------|:---|
95-
${uncategorizedRules.map(toRuleRow).join('\n')}
181+
<rules-table>
182+
183+
| Rule ID | Description | | |
184+
|:--------|:------------|:--:|:--:|
185+
${uncategorizedRules.map((rule) => toRuleRow(rule)).join('\n')}
186+
187+
</rules-table>
96188
`
97189
}
98190
if (uncategorizedExtensionRule.length > 0) {
@@ -101,9 +193,13 @@ if (uncategorizedExtensionRule.length > 0) {
101193
102194
The following rules extend the rules provided by ESLint itself and apply them to the expressions in the \`<template>\`.
103195
104-
| Rule ID | Description | |
105-
|:--------|:------------|:---|
106-
${uncategorizedExtensionRule.map(toRuleRow).join('\n')}
196+
<rules-table>
197+
198+
| Rule ID | Description | | |
199+
|:--------|:------------|:--:|:--:|
200+
${uncategorizedExtensionRule.map((rule) => toRuleRow(rule)).join('\n')}
201+
202+
</rules-table>
107203
`
108204
}
109205

@@ -127,6 +223,7 @@ fs.writeFileSync(
127223
readmeFilePath,
128224
`---
129225
sidebarDepth: 0
226+
pageClass: rule-list
130227
---
131228
132229
# Available rules
@@ -139,5 +236,12 @@ sidebarDepth: 0
139236
:bulb: Indicates that some problems reported by the rule are manually fixable by editor [suggestions](https://eslint.org/docs/developer-guide/working-with-rules#providing-suggestions).
140237
:::
141238
142-
${rulesTableContent}`
239+
Mark indicating rule type:
240+
241+
- <span class="emoji">:warning:</span> Possible Problems: These rules relate to possible logic errors in code.
242+
- :hammer: Suggestions: These rules suggest alternate ways of doing things.
243+
- :lipstick: Layout & Formatting: These rules care about how the code looks rather than how it executes.
244+
245+
${rulesTableContent.trim()}
246+
`
143247
)

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /