Skip to content

Commit 219c8b2

Browse files
authored
Add linting support (#15)
For code, add eslint, typescript-eslint, and stylistic. For styles, add stylelint and @stylistic/stylelint-plugin. Use new flat file format for eslint config. Clean up package.json Fix lint errors.
1 parent 3d1cd50 commit 219c8b2

11 files changed

Lines changed: 2557 additions & 161 deletions

File tree

package-lock.json

Lines changed: 2354 additions & 70 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
{
22
"private": true,
3+
"type": "module",
34
"workspaces": [
45
"./packages/*"
56
],

packages/astro/eslint.config.js

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import eslint from "@eslint/js";
2+
import tseslint from "typescript-eslint";
3+
import stylistic from "@stylistic/eslint-plugin";
4+
import astroParser from "astro-eslint-parser";
5+
import astro from "eslint-plugin-astro";
6+
7+
const stylisticRules = {
8+
"@stylistic/indent": ["error", "tab"],
9+
"@stylistic/eol-last": ["error", "always"],
10+
"@stylistic/no-trailing-spaces": ["error"],
11+
};
12+
13+
export default tseslint.config(
14+
eslint.configs.recommended,
15+
{
16+
files: ["src/**/*.astro"],
17+
plugins: {
18+
astro,
19+
"@stylistic": stylistic,
20+
},
21+
languageOptions: {
22+
globals: {
23+
// enable the standard global variables available in Astro components
24+
node: true,
25+
"astro/astro": true,
26+
es2020: true,
27+
},
28+
parser: astroParser,
29+
parserOptions: {
30+
parser: "@typescript-eslint/parser",
31+
extraFileExtensions: [".astro"],
32+
// the script frontmatter in Astro components uses ESM
33+
sourceType: "module",
34+
},
35+
},
36+
extends: [
37+
...tseslint.configs.recommended,
38+
],
39+
rules: {
40+
"@stylistic/indent": ["error", "tab"],
41+
"@stylistic/eol-last": ["error", "always"],
42+
"@stylistic/no-trailing-spaces": ["error"],
43+
...astro.configs.all.rules,
44+
// this sometimes errors even when the class is used in the same file
45+
"astro/no-unused-css-selector": ["off"],
46+
// this errors when the class is just set to a single string via a variable
47+
"astro/prefer-class-list-directive": ["off"],
48+
},
49+
},
50+
{
51+
files: ["src/**/*.{ts,tsx}"],
52+
extends: [
53+
...tseslint.configs.recommended,
54+
],
55+
plugins: {
56+
"@stylistic": stylistic
57+
},
58+
rules: {
59+
// Astro uses a triple slash reference in the env.d.ts file it automatically
60+
// creates, so just disable the rule to avoid trying to change that
61+
"@typescript-eslint/triple-slash-reference": ["off"],
62+
...stylisticRules,
63+
// this rule expects the tags in a .astro file to be indented at least
64+
// one level, but we want the outermost tag to start at column 0. so
65+
// only enable it in .tsx files, not .astro.
66+
"@stylistic/jsx-indent": ["error", "tab"],
67+
}
68+
},
69+
{
70+
files: ["src/**/*.{js,jsx}"],
71+
plugins: {
72+
"@stylistic": stylistic
73+
},
74+
rules: {
75+
...stylisticRules,
76+
"@stylistic/jsx-indent": ["error", "tab"],
77+
}
78+
}
79+
);

packages/astro/package.json

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,28 @@
77
"start": "astro dev",
88
"build": "astro check && astro build",
99
"preview": "astro preview",
10-
"astro": "astro"
10+
"astro": "astro",
11+
"lint:es": "eslint .",
12+
"lint:css": "stylelint \"**/*.{astro,css}\"",
13+
"lint:fix": "npm run lint:es -- --fix && npm run lint:css -- --fix",
14+
"lint": "(npm run lint:es || cd .) && npm run lint:css"
1115
},
1216
"dependencies": {
1317
"@astrojs/check": "^0.4.1",
1418
"@iconify-json/fa": "^1.1.8",
19+
"@stylistic/eslint-plugin": "^1.7.0",
20+
"@stylistic/stylelint-config": "^1.0.1",
21+
"@stylistic/stylelint-plugin": "^2.1.0",
22+
"@typescript-eslint/parser": "^7.2.0",
23+
"@iconify-json/fa": "^1.1.8",
1524
"@picocss/pico": "^2.0.6",
1625
"astro": "^4.0.6",
1726
"astro-icon": "^1.0.4",
18-
"typescript": "^5.3.3"
27+
"eslint-plugin-astro": "^0.31.4",
28+
"postcss-html": "^1.6.0",
29+
"stylelint": "^16.2.1",
30+
"stylelint-config-html": "^1.1.0",
31+
"typescript": "^5.3.3",
32+
"typescript-eslint": "^7.2.0"
1933
}
2034
}

packages/astro/src/components/FooterNav.astro

Lines changed: 53 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -3,39 +3,39 @@ import { Icon } from "astro-icon/components";
33
import NavLink from "./NavLink.astro";
44
55
const columns = [
6-
[
7-
"Resources",
8-
[
9-
[
10-
"https://docs.google.com/forms/d/e/1FAIpQLScHe7aWQ-2n3lSTU1WfcK8rhBZp8pkDGH9EcJdbQb5lqMbbzA/viewform",
11-
"propose a talk",
12-
],
13-
[
14-
"https://docs.google.com/forms/d/e/1FAIpQLSexe5qvmJ6LTiU1HcR-XAzlrgPLBudVBPK_ouHeBkFz2JVUHw/viewform",
15-
"pitch a project",
16-
],
17-
],
18-
],
19-
[
20-
"About",
21-
[
22-
["about", "about"],
23-
["about", "meet the core team"],
24-
["about", "code of conduct"],
25-
["mailto:hello@sfcivictech.org", "contact"],
26-
],
27-
],
28-
[
29-
"Elsewhere",
30-
[
31-
["https://twitter.com/sfbrigade", "twitter", true],
32-
["https://www.facebook.com/codeforsanfrancisco", "facebook", true],
33-
["https://www.linkedin.com/company/18115347/", "linkedin", true],
34-
["https://github.com/sfbrigade/", "github", true],
35-
["https://c4sf.me/slack", "slack", true],
36-
["https://www.meetup.com/sfcivictech/", "meetup", true],
37-
],
38-
],
6+
[
7+
"Resources",
8+
[
9+
[
10+
"https://docs.google.com/forms/d/e/1FAIpQLScHe7aWQ-2n3lSTU1WfcK8rhBZp8pkDGH9EcJdbQb5lqMbbzA/viewform",
11+
"propose a talk",
12+
],
13+
[
14+
"https://docs.google.com/forms/d/e/1FAIpQLSexe5qvmJ6LTiU1HcR-XAzlrgPLBudVBPK_ouHeBkFz2JVUHw/viewform",
15+
"pitch a project",
16+
],
17+
],
18+
],
19+
[
20+
"About",
21+
[
22+
["about", "about"],
23+
["about", "meet the core team"],
24+
["about", "code of conduct"],
25+
["mailto:hello@sfcivictech.org", "contact"],
26+
],
27+
],
28+
[
29+
"Elsewhere",
30+
[
31+
["https://twitter.com/sfbrigade", "twitter", true],
32+
["https://www.facebook.com/codeforsanfrancisco", "facebook", true],
33+
["https://www.linkedin.com/company/18115347/", "linkedin", true],
34+
["https://github.com/sfbrigade/", "github", true],
35+
["https://c4sf.me/slack", "slack", true],
36+
["https://www.meetup.com/sfcivictech/", "meetup", true],
37+
],
38+
],
3939
] as const;
4040
---
4141

@@ -48,10 +48,9 @@ const columns = [
4848
{links.map(([page, label, needsIcon]) => (
4949
<li class="footer-list-cat-list-item ">
5050
{needsIcon &&
51-
// adding a class attribute to the <Icon> component works just fine
52-
// but TS complains, so tell it to keep quiet
53-
// @ts-ignore
54-
<Icon name={"fa:" + label} class={"icon"} />
51+
// @ts-expect-error adding a class attribute to the <Icon> component
52+
// works just fine but TS complains, so tell it to keep quiet
53+
<Icon name={"fa:" + label} class="icon" />
5554
}
5655
<NavLink href={page}>
5756
{label}
@@ -67,30 +66,30 @@ const columns = [
6766
<style>
6867
h3 {
6968
font-size: 1.25rem;
70-
margin: 0;
71-
text-transform: uppercase;
72-
}
69+
margin: 0;
70+
text-transform: uppercase;
71+
}
7372

74-
ul {
73+
ul {
7574
--nav-element-spacing-horizontal: 0;
76-
align-items: start;
77-
display: flex;
78-
flex-direction: column;
79-
}
75+
align-items: start;
76+
display: flex;
77+
flex-direction: column;
78+
}
8079

8180
ul:first-of-type, ul:last-of-type {
8281
margin-left: initial;
8382
margin-right: initial;
8483
}
8584

86-
li {
87-
margin: 0;
88-
padding: 0;
89-
}
85+
li {
86+
margin: 0;
87+
padding: 0;
88+
}
9089

91-
.icon {
92-
display: inline-block;
93-
min-width: 1.5rem;
94-
text-align: center;
95-
}
90+
.icon {
91+
display: inline-block;
92+
min-width: 1.5rem;
93+
text-align: center;
94+
}
9695
</style>

packages/astro/src/components/NavDropdown.astro

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ const { items } = Astro.props;
3131

3232
/* set global styles on li's inside a nav, since we can't target their scoped
3333
styles from here */
34+
3435
:global(nav li) {
3536
position: relative;
3637
}

packages/astro/src/components/NavLink.astro

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@ interface Props {
44
class?: string;
55
}
66
7-
// we can destructure `class` from props, but we have to rename it so it won't
8-
// trigger syntax errors in the JS
7+
// we can destructure `class` from props, but we have to rename it so it won't
8+
// trigger syntax errors in the JS
99
const { href, class: className } = Astro.props;
1010
11-
// remove the base URL from the beginning of the current page so we can match
12-
// it against the href prop, which shouldn't include any base URL. because of
13-
// annoying differences between dev and build modes, due to this behavior
14-
// (https://github.com/withastro/astro/issues/5630), we also have to remove
15-
// any trailing slash so currentPage can match the href.
11+
// remove the base URL from the beginning of the current page so we can match
12+
// it against the href prop, which shouldn't include any base URL. because of
13+
// annoying differences between dev and build modes, due to this behavior
14+
// (https://github.com/withastro/astro/issues/5630), we also have to remove
15+
// any trailing slash so currentPage can match the href.
1616
const currentPage = Astro.url.pathname
1717
.replace(import.meta.env.BASE_URL, "")
1818
.replace(/\/$/, "");

packages/astro/src/layouts/BaseLayout.astro

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,16 @@ import HeaderNav from "../components/HeaderNav.astro";
44
import FooterNav from "../components/FooterNav.astro";
55
66
interface Props {
7-
title: string;
7+
title: string;
88
}
99
1010
const { title } = Astro.props;
1111
---
1212

1313
<Page title={title}>
14-
<HeaderNav />
15-
<main class="container">
16-
<slot />
17-
</main>
14+
<HeaderNav />
15+
<main class="container">
16+
<slot />
17+
</main>
1818
<FooterNav />
1919
</Page>

packages/astro/src/pages/about/index.astro

Lines changed: 20 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -15,24 +15,24 @@ import BaseLayout from "@/layouts/BaseLayout.astro";
1515
<li> We respect the boundaries of others </li>
1616
</ul>
1717

18-
<p> These are not just statements of belief, but principles that we collectively enact.
19-
We are dedicated to upholding them, and to ensuring that all members of our community
20-
respect them. </p>
21-
22-
<p>The full Code of Conduct is available, with more detailed information about our
23-
community principles. You’ll also find our harassment policy, along with information
24-
about who to contact if you think the policy has been violated. For other questions
25-
about the Code of Conduct, or about our collective, reach out to hello@sfcivictech.org.
18+
<p> These are not just statements of belief, but principles that we collectively enact.
19+
We are dedicated to upholding them, and to ensuring that all members of our community
20+
respect them. </p>
21+
22+
<p>The full Code of Conduct is available, with more detailed information about our
23+
community principles. You’ll also find our harassment policy, along with information
24+
about who to contact if you think the policy has been violated. For other questions
25+
about the Code of Conduct, or about our collective, reach out to hello@sfcivictech.org.
2626
</p>
2727

28-
<div class="code-of-conduct-btn">
29-
<a href="code-of-conduct" role="button">Read the full Code of Conduct</a>
30-
</div>
28+
<div class="code-of-conduct-btn">
29+
<a href="code-of-conduct" role="button">Read the full Code of Conduct</a>
30+
</div>
3131
</BaseLayout>
3232

3333
<style>
3434
h1, h2 {
35-
text-align: center
35+
text-align: center;
3636
}
3737

3838
h2 {
@@ -41,18 +41,17 @@ import BaseLayout from "@/layouts/BaseLayout.astro";
4141

4242
p, ul {
4343
line-height: 1.4em;
44-
font-size: 16px;
44+
font-size: 16px;
4545
margin-bottom: 20px;
4646

4747
li {
48-
margin-bottom: 0px
48+
margin-bottom: 0;
4949
}
5050
}
5151

52-
.code-of-conduct-btn {
53-
display: flex;
54-
align-items: center;
55-
justify-content: center;
56-
}
57-
58-
</style>
52+
.code-of-conduct-btn {
53+
display: flex;
54+
align-items: center;
55+
justify-content: center;
56+
}
57+
</style>

packages/astro/src/utils/getBlogImage.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ export async function getBlogImage(
66
filename: string = ""): Promise<ImageMetadata | null>
77
{
88
if (filename) {
9-
// this Vite import method requires that its parameter be a literal string,
10-
// not even one assembled from other literals
9+
// this Vite import method requires that its parameter be a literal string,
10+
// not even one assembled from other literals
1111
const imagePath = "/src/assets/blog/" + filename.replace(/^\/img\/uploads\//, "");
1212

1313
if (images[imagePath]) {

0 commit comments

Comments
 (0)