Skip to content

Commit

Permalink
Add linting support (#15)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
fwextensions authored Apr 7, 2024
1 parent 3d1cd50 commit 219c8b2
Show file tree
Hide file tree
Showing 11 changed files with 2,557 additions and 161 deletions.
2,424 changes: 2,354 additions & 70 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"private": true,
"type": "module",
"workspaces": [
"./packages/*"
],
Expand Down
79 changes: 79 additions & 0 deletions packages/astro/eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import eslint from "@eslint/js";
import tseslint from "typescript-eslint";
import stylistic from "@stylistic/eslint-plugin";
import astroParser from "astro-eslint-parser";
import astro from "eslint-plugin-astro";

const stylisticRules = {
"@stylistic/indent": ["error", "tab"],
"@stylistic/eol-last": ["error", "always"],
"@stylistic/no-trailing-spaces": ["error"],
};

export default tseslint.config(
eslint.configs.recommended,
{
files: ["src/**/*.astro"],
plugins: {
astro,
"@stylistic": stylistic,
},
languageOptions: {
globals: {
// enable the standard global variables available in Astro components
node: true,
"astro/astro": true,
es2020: true,
},
parser: astroParser,
parserOptions: {
parser: "@typescript-eslint/parser",
extraFileExtensions: [".astro"],
// the script frontmatter in Astro components uses ESM
sourceType: "module",
},
},
extends: [
...tseslint.configs.recommended,
],
rules: {
"@stylistic/indent": ["error", "tab"],
"@stylistic/eol-last": ["error", "always"],
"@stylistic/no-trailing-spaces": ["error"],
...astro.configs.all.rules,
// this sometimes errors even when the class is used in the same file
"astro/no-unused-css-selector": ["off"],
// this errors when the class is just set to a single string via a variable
"astro/prefer-class-list-directive": ["off"],
},
},
{
files: ["src/**/*.{ts,tsx}"],
extends: [
...tseslint.configs.recommended,
],
plugins: {
"@stylistic": stylistic
},
rules: {
// Astro uses a triple slash reference in the env.d.ts file it automatically
// creates, so just disable the rule to avoid trying to change that
"@typescript-eslint/triple-slash-reference": ["off"],
...stylisticRules,
// this rule expects the tags in a .astro file to be indented at least
// one level, but we want the outermost tag to start at column 0. so
// only enable it in .tsx files, not .astro.
"@stylistic/jsx-indent": ["error", "tab"],
}
},
{
files: ["src/**/*.{js,jsx}"],
plugins: {
"@stylistic": stylistic
},
rules: {
...stylisticRules,
"@stylistic/jsx-indent": ["error", "tab"],
}
}
);
18 changes: 16 additions & 2 deletions packages/astro/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,28 @@
"start": "astro dev",
"build": "astro check && astro build",
"preview": "astro preview",
"astro": "astro"
"astro": "astro",
"lint:es": "eslint .",
"lint:css": "stylelint \"**/*.{astro,css}\"",
"lint:fix": "npm run lint:es -- --fix && npm run lint:css -- --fix",
"lint": "(npm run lint:es || cd .) && npm run lint:css"
},
"dependencies": {
"@astrojs/check": "^0.4.1",
"@iconify-json/fa": "^1.1.8",
"@stylistic/eslint-plugin": "^1.7.0",
"@stylistic/stylelint-config": "^1.0.1",
"@stylistic/stylelint-plugin": "^2.1.0",
"@typescript-eslint/parser": "^7.2.0",
"@iconify-json/fa": "^1.1.8",
"@picocss/pico": "^2.0.6",
"astro": "^4.0.6",
"astro-icon": "^1.0.4",
"typescript": "^5.3.3"
"eslint-plugin-astro": "^0.31.4",
"postcss-html": "^1.6.0",
"stylelint": "^16.2.1",
"stylelint-config-html": "^1.1.0",
"typescript": "^5.3.3",
"typescript-eslint": "^7.2.0"
}
}
107 changes: 53 additions & 54 deletions packages/astro/src/components/FooterNav.astro
Original file line number Diff line number Diff line change
Expand Up @@ -3,39 +3,39 @@ import { Icon } from "astro-icon/components";
import NavLink from "./NavLink.astro";
const columns = [
[
"Resources",
[
[
"https://docs.google.com/forms/d/e/1FAIpQLScHe7aWQ-2n3lSTU1WfcK8rhBZp8pkDGH9EcJdbQb5lqMbbzA/viewform",
"propose a talk",
],
[
"https://docs.google.com/forms/d/e/1FAIpQLSexe5qvmJ6LTiU1HcR-XAzlrgPLBudVBPK_ouHeBkFz2JVUHw/viewform",
"pitch a project",
],
],
],
[
"About",
[
["about", "about"],
["about", "meet the core team"],
["about", "code of conduct"],
["mailto:[email protected]", "contact"],
],
],
[
"Elsewhere",
[
["https://twitter.com/sfbrigade", "twitter", true],
["https://www.facebook.com/codeforsanfrancisco", "facebook", true],
["https://www.linkedin.com/company/18115347/", "linkedin", true],
["https://github.com/sfbrigade/", "github", true],
["https://c4sf.me/slack", "slack", true],
["https://www.meetup.com/sfcivictech/", "meetup", true],
],
],
[
"Resources",
[
[
"https://docs.google.com/forms/d/e/1FAIpQLScHe7aWQ-2n3lSTU1WfcK8rhBZp8pkDGH9EcJdbQb5lqMbbzA/viewform",
"propose a talk",
],
[
"https://docs.google.com/forms/d/e/1FAIpQLSexe5qvmJ6LTiU1HcR-XAzlrgPLBudVBPK_ouHeBkFz2JVUHw/viewform",
"pitch a project",
],
],
],
[
"About",
[
["about", "about"],
["about", "meet the core team"],
["about", "code of conduct"],
["mailto:[email protected]", "contact"],
],
],
[
"Elsewhere",
[
["https://twitter.com/sfbrigade", "twitter", true],
["https://www.facebook.com/codeforsanfrancisco", "facebook", true],
["https://www.linkedin.com/company/18115347/", "linkedin", true],
["https://github.com/sfbrigade/", "github", true],
["https://c4sf.me/slack", "slack", true],
["https://www.meetup.com/sfcivictech/", "meetup", true],
],
],
] as const;
---

Expand All @@ -48,10 +48,9 @@ const columns = [
{links.map(([page, label, needsIcon]) => (
<li class="footer-list-cat-list-item ">
{needsIcon &&
// adding a class attribute to the <Icon> component works just fine
// but TS complains, so tell it to keep quiet
// @ts-ignore
<Icon name={"fa:" + label} class={"icon"} />
// @ts-expect-error adding a class attribute to the <Icon> component
// works just fine but TS complains, so tell it to keep quiet
<Icon name={"fa:" + label} class="icon" />
}
<NavLink href={page}>
{label}
Expand All @@ -67,30 +66,30 @@ const columns = [
<style>
h3 {
font-size: 1.25rem;
margin: 0;
text-transform: uppercase;
}
margin: 0;
text-transform: uppercase;
}

ul {
ul {
--nav-element-spacing-horizontal: 0;
align-items: start;
display: flex;
flex-direction: column;
}
align-items: start;
display: flex;
flex-direction: column;
}

ul:first-of-type, ul:last-of-type {
margin-left: initial;
margin-right: initial;
}

li {
margin: 0;
padding: 0;
}
li {
margin: 0;
padding: 0;
}

.icon {
display: inline-block;
min-width: 1.5rem;
text-align: center;
}
.icon {
display: inline-block;
min-width: 1.5rem;
text-align: center;
}
</style>
1 change: 1 addition & 0 deletions packages/astro/src/components/NavDropdown.astro
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ const { items } = Astro.props;

/* set global styles on li's inside a nav, since we can't target their scoped
styles from here */

:global(nav li) {
position: relative;
}
Expand Down
14 changes: 7 additions & 7 deletions packages/astro/src/components/NavLink.astro
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ interface Props {
class?: string;
}
// we can destructure `class` from props, but we have to rename it so it won't
// trigger syntax errors in the JS
// we can destructure `class` from props, but we have to rename it so it won't
// trigger syntax errors in the JS
const { href, class: className } = Astro.props;
// remove the base URL from the beginning of the current page so we can match
// it against the href prop, which shouldn't include any base URL. because of
// annoying differences between dev and build modes, due to this behavior
// (https://github.com/withastro/astro/issues/5630), we also have to remove
// any trailing slash so currentPage can match the href.
// remove the base URL from the beginning of the current page so we can match
// it against the href prop, which shouldn't include any base URL. because of
// annoying differences between dev and build modes, due to this behavior
// (https://github.com/withastro/astro/issues/5630), we also have to remove
// any trailing slash so currentPage can match the href.
const currentPage = Astro.url.pathname
.replace(import.meta.env.BASE_URL, "")
.replace(/\/$/, "");
Expand Down
10 changes: 5 additions & 5 deletions packages/astro/src/layouts/BaseLayout.astro
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@ import HeaderNav from "../components/HeaderNav.astro";
import FooterNav from "../components/FooterNav.astro";
interface Props {
title: string;
title: string;
}
const { title } = Astro.props;
---

<Page title={title}>
<HeaderNav />
<main class="container">
<slot />
</main>
<HeaderNav />
<main class="container">
<slot />
</main>
<FooterNav />
</Page>
41 changes: 20 additions & 21 deletions packages/astro/src/pages/about/index.astro
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,24 @@ import BaseLayout from "@/layouts/BaseLayout.astro";
<li> We respect the boundaries of others </li>
</ul>

<p> These are not just statements of belief, but principles that we collectively enact.
We are dedicated to upholding them, and to ensuring that all members of our community
respect them. </p>

<p>The full Code of Conduct is available, with more detailed information about our
community principles. You’ll also find our harassment policy, along with information
about who to contact if you think the policy has been violated. For other questions
about the Code of Conduct, or about our collective, reach out to [email protected].
<p> These are not just statements of belief, but principles that we collectively enact.
We are dedicated to upholding them, and to ensuring that all members of our community
respect them. </p>

<p>The full Code of Conduct is available, with more detailed information about our
community principles. You’ll also find our harassment policy, along with information
about who to contact if you think the policy has been violated. For other questions
about the Code of Conduct, or about our collective, reach out to [email protected].
</p>

<div class="code-of-conduct-btn">
<a href="code-of-conduct" role="button">Read the full Code of Conduct</a>
</div>
<div class="code-of-conduct-btn">
<a href="code-of-conduct" role="button">Read the full Code of Conduct</a>
</div>
</BaseLayout>

<style>
h1, h2 {
text-align: center
text-align: center;
}

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

p, ul {
line-height: 1.4em;
font-size: 16px;
font-size: 16px;
margin-bottom: 20px;

li {
margin-bottom: 0px
margin-bottom: 0;
}
}

.code-of-conduct-btn {
display: flex;
align-items: center;
justify-content: center;
}

</style>
.code-of-conduct-btn {
display: flex;
align-items: center;
justify-content: center;
}
</style>
4 changes: 2 additions & 2 deletions packages/astro/src/utils/getBlogImage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ export async function getBlogImage(
filename: string = ""): Promise<ImageMetadata | null>
{
if (filename) {
// this Vite import method requires that its parameter be a literal string,
// not even one assembled from other literals
// this Vite import method requires that its parameter be a literal string,
// not even one assembled from other literals
const imagePath = "/src/assets/blog/" + filename.replace(/^\/img\/uploads\//, "");

if (images[imagePath]) {
Expand Down
Loading

0 comments on commit 219c8b2

Please sign in to comment.