Skip to content

Commit 83ef793

Browse files
crowlKatsbartlomiejujosh-collinsworth
authored
refactor: make lint rule docs better looking (#1277)
Co-authored-by: Bartek Iwańczuk <[email protected]> Co-authored-by: Josh Collinsworth <[email protected]>
1 parent dc42d0a commit 83ef793

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

75 files changed

+367
-109
lines changed

_config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,7 @@ site.ignore(
172172
(path) => path.match(/\/reference_gen.*.ts/) !== null,
173173
(path) => path.includes("/reference_gen/node_modules"),
174174
(path) => path.includes("/reference_gen/node_descriptions"),
175+
(path) => path.includes("/lint/rules/"),
175176
// "deploy",
176177
// "runtime",
177178
// "subhosting",

_includes/layout.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ export default function Layout(props: Lume.Data) {
6767
<script src="/darkmode.client.js"></script>
6868
<script type="module" src="/darkmode-toggle.client.js"></script>
6969
<script type="module" src="/sidebar.client.js"></script>
70+
<script type="module" src="/lint_rules.client.js"></script>
7071
<script type="module" src="/copy.client.js"></script>
7172
<script type="module" src="/tabs.client.js"></script>
7273
<script type="module" src="/feedback.client.js"></script>

_includes/lintRule.tsx

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
export const layout = "doc.tsx";
2+
3+
const generateConfigFileForTag = (tag: string) => {
4+
return `{
5+
"lint": {
6+
"tags": ["${tag}"]
7+
}
8+
}`;
9+
};
10+
11+
const generateConfigFileForTags = (tags: string[]) => {
12+
return `{
13+
"lint": {
14+
"tags": ["${tags[0]}"] // ...or ${
15+
tags.slice(1).map((tag) => `"${tag}"`).join(", ")
16+
}
17+
}
18+
}`;
19+
};
20+
21+
const generateCliForTag = (tag: string) => {
22+
return `deno lint --tags=${tag}`;
23+
};
24+
25+
const generateCliForTags = (tags: string[]) => {
26+
return tags.map((tag) => `deno lint --tags=${tag}`).join("\n# or ...\n");
27+
};
28+
29+
function LintRuleTags(props: { tags: string[] }) {
30+
const tags = props.tags;
31+
if (tags.length === 0) {
32+
return null;
33+
}
34+
35+
return (
36+
<div class="rounded-md p-4 bg-background-secondary text-sm mb-8 flex flex-col gap-1">
37+
{tags.length === 1
38+
? (
39+
<>
40+
<div class="mb-4">
41+
<b>NOTE:</b> this rule is part of the <code>{tags[0]}</code>{" "}
42+
rule set.
43+
</div>
44+
<div>
45+
Enable full set in <code>deno.json</code>:
46+
</div>
47+
<pre>{generateConfigFileForTag(tags[0])}</pre>
48+
<div>Enable full set using the Deno CLI:</div>
49+
<pre class="!mb-0">{generateCliForTag(tags[0])}</pre>
50+
</>
51+
)
52+
: (
53+
<>
54+
<div class="mb-4">
55+
<span class="flex flex-wrap items-center gap-2">
56+
<b>NOTE:</b> this rule is included the following rule sets:
57+
{tags.map((tag) => <code>{tag}</code>)}
58+
</span>
59+
</div>
60+
<div>
61+
Enable full set in <code>deno.json</code>:
62+
</div>
63+
<pre>{generateConfigFileForTags(tags)}</pre>
64+
<div>Enable full set using the Deno CLI:</div>
65+
<pre class="!mb-0">{generateCliForTags(tags)}</pre>
66+
</>
67+
)}
68+
</div>
69+
);
70+
}
71+
72+
export default function LintRule(props: Lume.Data, _helpers: Lume.Helpers) {
73+
const tags = props.data.tags;
74+
75+
return (
76+
<>
77+
<LintRuleTags tags={tags} />
78+
{props.children}
79+
</>
80+
);
81+
}

_includes/lint_rule.tsx

Lines changed: 0 additions & 13 deletions
This file was deleted.

deno.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
"@std/assert": "jsr:@std/assert@^1.0.6",
44
"@std/dotenv": "jsr:@std/dotenv@^0.225.2",
55
"@std/fs": "jsr:@std/fs@^0.229.3",
6+
"@std/front-matter": "jsr:@std/[email protected]",
67
"@std/html": "jsr:@std/html@^1.0.3",
78
"@std/media-types": "jsr:@std/media-types@^1.0.3",
89
"@std/path": "jsr:@std/path@^1.0.8",

deno.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lint/_data.ts

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import { Sidebar, SidebarLink } from "../types.ts";
1+
import { extractYaml } from "@std/front-matter";
22
import { walk } from "jsr:@std/fs";
33
import { basename } from "jsr:@std/path";
4-
import { extractYaml } from "jsr:@std/[email protected]";
4+
import { Sidebar, SidebarLink } from "../types.ts";
55

66
async function generateSidebarItems() {
77
const sidebarItems = [];
@@ -21,15 +21,14 @@ async function generateSidebarItems() {
2121
frontMatterData.body = mdContent;
2222
}
2323
const tags = frontMatterData.attrs.tags ?? [];
24-
// TODO(bartlomieju): handle descriptions properly
25-
// const description = frontMatterData.body.split(".")[0];
24+
const content = frontMatterData.body;
2625

2726
sidebarItems.push(
2827
{
29-
href: `/lint/rules/${lintRuleName}`,
28+
href: `/lint/rules/${lintRuleName}/`,
3029
label: lintRuleName,
3130
tags,
32-
// description,
31+
content,
3332
} satisfies SidebarLink,
3433
);
3534
}
@@ -41,11 +40,14 @@ async function generateSidebarItems() {
4140

4241
export const lintRulePages = await generateSidebarItems();
4342

43+
export const sectionTitle = "Lint rules";
44+
45+
export const sectionHref = "/lint/";
46+
4447
export const sidebar = [
4548
{
46-
title: "Lint rules",
49+
title: "List of rules",
50+
href: sectionHref,
4751
items: lintRulePages,
4852
},
4953
] satisfies Sidebar;
50-
51-
export const sectionTitle = "Lint rules";

lint/index.md

Lines changed: 0 additions & 19 deletions
This file was deleted.

lint/index.tsx

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
type LintIconType = "jsr" | "react" | "jsx" | "recommended" | "fresh";
2+
3+
export const title = "List of rules";
4+
export const toc = [];
5+
6+
const getReadableIconName = (iconType: LintIconType) => {
7+
if (["jsx", "jsr"].includes(iconType)) {
8+
return iconType.toUpperCase();
9+
}
10+
return iconType.charAt(0).toUpperCase() + iconType.slice(1);
11+
};
12+
13+
export const getLintIcon = (
14+
type: LintIconType,
15+
) => {
16+
const svgFileName = type === "recommended" ? "checkmark" : type;
17+
return (
18+
<img
19+
src={`/img/${svgFileName}.svg`}
20+
class="size-6 !bg-transparent"
21+
alt={getReadableIconName(type)}
22+
title={getReadableIconName(type)}
23+
/>
24+
);
25+
};
26+
27+
export default function LintRulesIndex(
28+
data: Lume.Data,
29+
helpers: Lume.Helpers,
30+
) {
31+
const TYPES = [
32+
"recommended",
33+
"fresh",
34+
"jsx",
35+
"react",
36+
"jsr",
37+
] as LintIconType[];
38+
return (
39+
<div>
40+
<div class="flex flex-col gap-4 mb-8">
41+
<input
42+
type="text"
43+
id="lint-rule-search"
44+
placeholder="Search lint rules"
45+
className="
46+
w-full
47+
lg:flex
48+
rounded-md
49+
items-center
50+
text-sm
51+
leading-6
52+
py-1.5 pl-2 pr-3
53+
border
54+
text-slate-600
55+
bg-slate-100
56+
dark:bg-background-secondary
57+
dark:text-slate-200
58+
dark:highlight-white/5
59+
dark:hover:bg-slate-700
60+
dark:border-foreground-tertiary
61+
hover:bg-slate-200
62+
duration-150 ease-in-out"
63+
/>
64+
65+
<ul
66+
class="flex flex-wrap gap-2 mb-8 !list-none !pl-0"
67+
aria-labelledby="lint-rules-key"
68+
>
69+
{TYPES.map((iconType) => (
70+
<li class="p-1.5 px-3 rounded-md bg-background-secondary/30 border border-background-secondary w-max max-w-full !m-0 whitespace-pre-wrap">
71+
{getLintIcon(iconType)}&ensp;{getReadableIconName(iconType)}
72+
</li>
73+
))}
74+
</ul>
75+
</div>
76+
77+
<ul class="flex flex-col gap-4 !list-none !pl-0">
78+
{data.lintRulePages.map((lintRule, idx: number) => (
79+
<li
80+
class="border-t md:border md:rounded-md pt-8 pb-4 md:p-4 lint-rule-box"
81+
id={lintRule.label}
82+
>
83+
<div class="flex flex-row justify-start items-center gap-4 mb-2">
84+
<a href={lintRule.href} class="block font-mono">
85+
{lintRule.label}
86+
</a>{" "}
87+
{lintRule.tags.map((tag: LintIconType) => (
88+
<div class="bg-background-secondary/30 border border-background-secondary rounded-md p-1">
89+
{getLintIcon(tag)}
90+
</div>
91+
))}
92+
</div>
93+
<div
94+
class="text-sm [&>*]:last:mb-0"
95+
dangerouslySetInnerHTML={{
96+
__html: helpers.md(
97+
lintRule.content.split(/\n\n/)[0] +
98+
` <a href="${lintRule.href}">Details<span class="sr-only"> about ${lintRule.label}</span></a>`,
99+
),
100+
}}
101+
>
102+
</div>
103+
</li>
104+
))}
105+
</ul>
106+
</div>
107+
);
108+
}

lint/lint_rule.page.tsx

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import { extractYaml } from "@std/front-matter";
2+
import { walkSync } from "@std/fs/walk";
3+
import { basename } from "@std/path";
4+
export { sectionHref, sidebar } from "./_data.ts";
5+
6+
export const sectionTitle = "Lint rules";
7+
8+
export const layout = "lintRule.tsx";
9+
10+
export const toc = [];
11+
12+
export default function* (_data: Lume.Data, helpers: Lume.Helpers) {
13+
const files = walkSync("lint/rules/", { exts: [".md"] });
14+
15+
for (const file of files) {
16+
const content = Deno.readTextFileSync(file.path);
17+
let fmData = {
18+
body: "",
19+
attrs: {},
20+
};
21+
22+
try {
23+
fmData = extractYaml(content);
24+
} catch {
25+
fmData.body = content;
26+
}
27+
28+
const ruleName = basename(file.path).slice(0, -3);
29+
30+
yield {
31+
url: `/lint/rules/${ruleName}/`,
32+
title: ruleName,
33+
content: helpers.md(fmData.body),
34+
data: {
35+
tags: fmData.attrs.tags,
36+
},
37+
};
38+
}
39+
}

lint/rules/_data.ts

Lines changed: 0 additions & 1 deletion
This file was deleted.

lint/rules/ban-unknown-rule-code.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
tags: [recommended]
33
---
44

5-
Warns the usage of unknown rule codes in ignore directives
5+
Warns the usage of unknown rule codes in ignore directives.
66

77
We sometimes have to suppress and ignore lint errors for some reasons. We can do
88
so using [ignore directives](https://lint.deno.land/ignoring-rules) with rule

lint/rules/ban-unused-ignore.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
tags: [recommended]
33
---
44

5-
Warns unused ignore directives
5+
Warns unused ignore directives.
66

77
We sometimes have to suppress and ignore lint errors for some reasons and we can
88
do so using [ignore directives](https://lint.deno.land/ignoring-rules).

lint/rules/camelcase.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
tags: []
33
---
44

5-
Enforces the use of camelCase in variable names
5+
Enforces the use of camelCase in variable names.
66

77
Consistency in a code base is key for readability and maintainability. This rule
88
enforces variable declarations and object property names which you create to be

lint/rules/explicit-module-boundary-types.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
tags: []
33
---
44

5-
Requires all module exports to have fully typed declarations
5+
Requires all module exports to have fully typed declarations.
66

77
Having fully typed function arguments and return values clearly defines the
88
inputs and outputs of a module (known as the module boundary). This will make it

lint/rules/for-direction.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
tags: [recommended]
33
---
44

5-
Requires `for` loop control variables to increment in the correct direction
5+
Requires `for` loop control variables to increment in the correct direction.
66

77
Incrementing `for` loop control variables in the wrong direction leads to
88
infinite loops. This can occur through incorrect initialization, bad

lint/rules/fresh-handler-export.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
tags: [fresh]
33
---
44

5-
Checks correct naming for named fresh middleware export
5+
Checks correct naming for named fresh middleware export.
66

77
Files inside the `routes/` folder can export middlewares that run before any
88
rendering happens. They are expected to be available as a named export called

0 commit comments

Comments
 (0)