Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: make lint rule docs better looking #1277

Merged
merged 15 commits into from
Dec 20, 2024
1 change: 1 addition & 0 deletions _config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ site.ignore(
(path) => path.match(/\/reference_gen.*.ts/) !== null,
(path) => path.includes("/reference_gen/node_modules"),
(path) => path.includes("/reference_gen/node_descriptions"),
(path) => path.includes("/lint/rules/"),
// "deploy",
// "runtime",
// "subhosting",
Expand Down
1 change: 1 addition & 0 deletions _includes/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ export default function Layout(props: Lume.Data) {
<script src="/darkmode.client.js"></script>
<script type="module" src="/darkmode-toggle.client.js"></script>
<script type="module" src="/sidebar.client.js"></script>
<script type="module" src="/lint_rules.client.js"></script>
<script type="module" src="/copy.client.js"></script>
<script type="module" src="/tabs.client.js"></script>
<script type="module" src="/feedback.client.js"></script>
Expand Down
81 changes: 81 additions & 0 deletions _includes/lintRule.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
export const layout = "doc.tsx";

const generateConfigFileForTag = (tag: string) => {
return `{
"lint": {
"tags": ["${tag}"]
}
}`;
};

const generateConfigFileForTags = (tags: string[]) => {
return `{
"lint": {
"tags": ["${tags[0]}"] // ...or ${
tags.slice(1).map((tag) => `"${tag}"`).join(", ")
}
}
}`;
};

const generateCliForTag = (tag: string) => {
return `deno lint --tags=${tag}`;
};

const generateCliForTags = (tags: string[]) => {
return tags.map((tag) => `deno lint --tags=${tag}`).join("\n# or ...\n");
};

function LintRuleTags(props: { tags: string[] }) {
const tags = props.tags;
if (tags.length === 0) {
return null;
}

return (
<div class="rounded-md p-4 bg-background-secondary text-sm mb-8 flex flex-col gap-1">
{tags.length === 1
? (
<>
<div class="mb-4">
<b>NOTE:</b> this rule is part of the <code>{tags[0]}</code>{" "}
rule set.
</div>
<div>
Enable full set in <code>deno.json</code>:
</div>
<pre>{generateConfigFileForTag(tags[0])}</pre>
<div>Enable full set using the Deno CLI:</div>
<pre class="!mb-0">{generateCliForTag(tags[0])}</pre>
</>
)
: (
<>
<div class="mb-4">
<span class="flex flex-wrap items-center gap-2">
<b>NOTE:</b> this rule is included the following rule sets:
{tags.map((tag) => <code>{tag}</code>)}
</span>
</div>
<div>
Enable full set in <code>deno.json</code>:
</div>
<pre>{generateConfigFileForTags(tags)}</pre>
<div>Enable full set using the Deno CLI:</div>
<pre class="!mb-0">{generateCliForTags(tags)}</pre>
</>
)}
</div>
);
}

export default function LintRule(props: Lume.Data, _helpers: Lume.Helpers) {
const tags = props.data.tags;

return (
<>
<LintRuleTags tags={tags} />
{props.children}
</>
);
}
13 changes: 0 additions & 13 deletions _includes/lint_rule.tsx

This file was deleted.

1 change: 1 addition & 0 deletions deno.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"@std/assert": "jsr:@std/assert@^1.0.6",
"@std/dotenv": "jsr:@std/dotenv@^0.225.2",
"@std/fs": "jsr:@std/fs@^0.229.3",
"@std/front-matter": "jsr:@std/[email protected]",
"@std/html": "jsr:@std/html@^1.0.3",
"@std/media-types": "jsr:@std/media-types@^1.0.3",
"@std/path": "jsr:@std/path@^1.0.8",
Expand Down
1 change: 1 addition & 0 deletions deno.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 11 additions & 9 deletions lint/_data.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Sidebar, SidebarLink } from "../types.ts";
import { extractYaml } from "@std/front-matter";
import { walk } from "jsr:@std/fs";
import { basename } from "jsr:@std/path";
import { extractYaml } from "jsr:@std/[email protected]";
import { Sidebar, SidebarLink } from "../types.ts";

async function generateSidebarItems() {
const sidebarItems = [];
Expand All @@ -21,15 +21,14 @@ async function generateSidebarItems() {
frontMatterData.body = mdContent;
}
const tags = frontMatterData.attrs.tags ?? [];
// TODO(bartlomieju): handle descriptions properly
// const description = frontMatterData.body.split(".")[0];
const content = frontMatterData.body;

sidebarItems.push(
{
href: `/lint/rules/${lintRuleName}`,
href: `/lint/rules/${lintRuleName}/`,
label: lintRuleName,
tags,
// description,
content,
} satisfies SidebarLink,
);
}
Expand All @@ -41,11 +40,14 @@ async function generateSidebarItems() {

export const lintRulePages = await generateSidebarItems();

export const sectionTitle = "Lint rules";

export const sectionHref = "/lint/";

export const sidebar = [
{
title: "Lint rules",
title: "List of rules",
href: sectionHref,
items: lintRulePages,
},
] satisfies Sidebar;

export const sectionTitle = "Lint rules";
19 changes: 0 additions & 19 deletions lint/index.md

This file was deleted.

108 changes: 108 additions & 0 deletions lint/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
type LintIconType = "jsr" | "react" | "jsx" | "recommended" | "fresh";

export const title = "List of rules";
export const toc = [];

const getReadableIconName = (iconType: LintIconType) => {
if (["jsx", "jsr"].includes(iconType)) {
return iconType.toUpperCase();
}
return iconType.charAt(0).toUpperCase() + iconType.slice(1);
};

export const getLintIcon = (
type: LintIconType,
) => {
const svgFileName = type === "recommended" ? "checkmark" : type;
return (
<img
src={`/img/${svgFileName}.svg`}
class="size-6 !bg-transparent"
alt={getReadableIconName(type)}
title={getReadableIconName(type)}
/>
);
};

export default function LintRulesIndex(
data: Lume.Data,
helpers: Lume.Helpers,
) {
const TYPES = [
"recommended",
"fresh",
"jsx",
"react",
"jsr",
] as LintIconType[];
return (
<div>
<div class="flex flex-col gap-4 mb-8">
<input
type="text"
id="lint-rule-search"
placeholder="Search lint rules"
className="
w-full
lg:flex
rounded-md
items-center
text-sm
leading-6
py-1.5 pl-2 pr-3
border
text-slate-600
bg-slate-100
dark:bg-background-secondary
dark:text-slate-200
dark:highlight-white/5
dark:hover:bg-slate-700
dark:border-foreground-tertiary
hover:bg-slate-200
duration-150 ease-in-out"
/>

<ul
class="flex flex-wrap gap-2 mb-8 !list-none !pl-0"
aria-labelledby="lint-rules-key"
>
{TYPES.map((iconType) => (
<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">
{getLintIcon(iconType)}&ensp;{getReadableIconName(iconType)}
</li>
))}
</ul>
</div>

<ul class="flex flex-col gap-4 !list-none !pl-0">
{data.lintRulePages.map((lintRule, idx: number) => (
<li
class="border-t md:border md:rounded-md pt-8 pb-4 md:p-4 lint-rule-box"
id={lintRule.label}
>
<div class="flex flex-row justify-start items-center gap-4 mb-2">
<a href={lintRule.href} class="block font-mono">
{lintRule.label}
</a>{" "}
{lintRule.tags.map((tag: LintIconType) => (
<div class="bg-background-secondary/30 border border-background-secondary rounded-md p-1">
{getLintIcon(tag)}
</div>
))}
</div>
<div
class="text-sm [&>*]:last:mb-0"
dangerouslySetInnerHTML={{
__html: helpers.md(
lintRule.content.split(/\n\n/)[0] +
` <a href="${lintRule.href}">Details<span class="sr-only"> about ${lintRule.label}</span></a>`,
),
}}
>
</div>
</li>
))}
</ul>
</div>
);
}
39 changes: 39 additions & 0 deletions lint/lint_rule.page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { extractYaml } from "@std/front-matter";
import { walkSync } from "@std/fs/walk";
import { basename } from "@std/path";
export { sectionHref, sidebar } from "./_data.ts";

export const sectionTitle = "Lint rules";

export const layout = "lintRule.tsx";

export const toc = [];

export default function* (_data: Lume.Data, helpers: Lume.Helpers) {
const files = walkSync("lint/rules/", { exts: [".md"] });

for (const file of files) {
const content = Deno.readTextFileSync(file.path);
let fmData = {
body: "",
attrs: {},
};

try {
fmData = extractYaml(content);
} catch {
fmData.body = content;
}

const ruleName = basename(file.path).slice(0, -3);

yield {
url: `/lint/rules/${ruleName}/`,
title: ruleName,
content: helpers.md(fmData.body),
data: {
tags: fmData.attrs.tags,
},
};
}
}
1 change: 0 additions & 1 deletion lint/rules/_data.ts

This file was deleted.

2 changes: 1 addition & 1 deletion lint/rules/ban-unknown-rule-code.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
tags: [recommended]
---

Warns the usage of unknown rule codes in ignore directives
Warns the usage of unknown rule codes in ignore directives.

We sometimes have to suppress and ignore lint errors for some reasons. We can do
so using [ignore directives](https://lint.deno.land/ignoring-rules) with rule
Expand Down
2 changes: 1 addition & 1 deletion lint/rules/ban-unused-ignore.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
tags: [recommended]
---

Warns unused ignore directives
Warns unused ignore directives.

We sometimes have to suppress and ignore lint errors for some reasons and we can
do so using [ignore directives](https://lint.deno.land/ignoring-rules).
Expand Down
2 changes: 1 addition & 1 deletion lint/rules/camelcase.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
tags: []
---

Enforces the use of camelCase in variable names
Enforces the use of camelCase in variable names.

Consistency in a code base is key for readability and maintainability. This rule
enforces variable declarations and object property names which you create to be
Expand Down
2 changes: 1 addition & 1 deletion lint/rules/explicit-module-boundary-types.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
tags: []
---

Requires all module exports to have fully typed declarations
Requires all module exports to have fully typed declarations.

Having fully typed function arguments and return values clearly defines the
inputs and outputs of a module (known as the module boundary). This will make it
Expand Down
2 changes: 1 addition & 1 deletion lint/rules/for-direction.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
tags: [recommended]
---

Requires `for` loop control variables to increment in the correct direction
Requires `for` loop control variables to increment in the correct direction.

Incrementing `for` loop control variables in the wrong direction leads to
infinite loops. This can occur through incorrect initialization, bad
Expand Down
2 changes: 1 addition & 1 deletion lint/rules/fresh-handler-export.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
tags: [fresh]
---

Checks correct naming for named fresh middleware export
Checks correct naming for named fresh middleware export.

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