Skip to content
This repository has been archived by the owner on Jun 25, 2024. It is now read-only.

Commit

Permalink
feat: setup eslint
Browse files Browse the repository at this point in the history
/spent 5m
  • Loading branch information
nico-i committed Feb 4, 2024
1 parent 2d646ff commit 0e0b49d
Show file tree
Hide file tree
Showing 18 changed files with 401 additions and 95 deletions.
63 changes: 63 additions & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
{
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaFeatures": {
"jsx": true,
},
"ecmaVersion": "latest",
"sourceType": "module",
},
"globals": { "NodeJS": true },
"env": {
"browser": true,
"es6": true,
"node": true,
},
"plugins": ["react", "jsx-a11y", "prettier", "@typescript-eslint"],
"extends": [
"plugin:react/recommended",
"plugin:react/jsx-runtime",
"plugin:react-hooks/recommended",
"standard",
"plugin:prettier/recommended",
],
"rules": {
"prettier/prettier": "error",
"react/prop-types": "off",
"react/jsx-filename-extension": "off",
"react/jsx-props-no-spreading": "off",
"import/prefer-default-export": "off",
"import/extensions": [
"error",
"ignorePackages",
{
"ts": "never",
"tsx": "never",
"js": "never",
"jsx": "never",
},
],
"@typescript-eslint/explicit-function-return-type": "off",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-var-requires": "off",
"quotes": "off",
"@typescript-eslint/quotes": [
2,
"backtick",
{
"avoidEscape": true,
},
],
"@typescript-eslint/no-unused-vars": [2, { "argsIgnorePattern": "^_" }],
},
"settings": {
"import/resolver": {
"typescript": {
"project": ".",
},
},
"react": {
"version": "detect",
},
},
}
16 changes: 8 additions & 8 deletions commitlint.config.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,34 @@
module.exports = {
extends: ["@commitlint/config-conventional"],
extends: [`@commitlint/config-conventional`],
rules: {
"require-spent": [2, "always"],
"require-spent": [2, `always`],
},
plugins: [
{
rules: {
"require-spent": ({ raw }: { raw: string }) => {
const commitMessage = raw.trim();

const msgSplit = commitMessage.split("\n");
const msgSplit = commitMessage.split(`\n`);
if (msgSplit.length < 3)
return [
false,
`'/spent' directive must be in new line separated by another new line`,
]; // ensure that commit message has more than 1 line

if (msgSplit[1] !== "")
if (msgSplit[1] !== ``)
return [
false,
`'/spent' directive must be separated by another new line`,
]; // ensure that commit message has more than 1 line

const spentSplit = msgSplit[msgSplit.length - 1].split(" ");
const spentSplit = msgSplit[msgSplit.length - 1].split(` `);
const isCorrectCommand =
spentSplit[0] === "/spent" || spentSplit[0] === "/spend";
spentSplit[0] === `/spent` || spentSplit[0] === `/spend`;
if (spentSplit.length < 2 || !isCorrectCommand)
return [
false,
"the last line of a commit must be a '/spent' directive",
`the last line of a commit must be a '/spent' directive`,
]; // ensure that commit message ends with '/spent'

const spentTimeValue = spentSplit[spentSplit.length - 1].trim();
Expand All @@ -39,7 +39,7 @@ module.exports = {
// ensure that spent time value is valid
return [
false,
"Commit message must end with a valid spent time with the format '/spent 1h30' or '/spent 30m' or '/spent 1h'",
`Commit message must end with a valid spent time with the format '/spent 1h30' or '/spent 30m' or '/spent 1h'`,
];
}
return [true];
Expand Down
16 changes: 9 additions & 7 deletions e2e/example.spec.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
import { test, expect } from '@playwright/test';
import { test, expect } from "@playwright/test";

test('has title', async ({ page }) => {
await page.goto('https://playwright.dev/');
test(`has title`, async ({ page }) => {
await page.goto(`https://playwright.dev/`);

// Expect a title "to contain" a substring.
await expect(page).toHaveTitle(/Playwright/);
});

test('get started link', async ({ page }) => {
await page.goto('https://playwright.dev/');
test(`get started link`, async ({ page }) => {
await page.goto(`https://playwright.dev/`);

// Click the get started link.
await page.getByRole('link', { name: 'Get started' }).click();
await page.getByRole(`link`, { name: `Get started` }).click();

// Expects page to have a heading with the name of Installation.
await expect(page.getByRole('heading', { name: 'Installation' })).toBeVisible();
await expect(
page.getByRole(`heading`, { name: `Installation` }),
).toBeVisible();
});
41 changes: 21 additions & 20 deletions gatsby-config.ts
Original file line number Diff line number Diff line change
@@ -1,36 +1,37 @@
// - Requires -
require("@dotenvx/dotenvx").config();
const i18n = require("./src/helper/i18n/i18n");

// - Imports -
import type { GatsbyConfig } from "gatsby";
import path from "path";

require(`@dotenvx/dotenvx`).config();
const i18n = require(`./src/helper/i18n/i18n`);

// - Variables -
if (process.env.SITE_URL === undefined) {
console.error("SITE_URL is not defined. Issues may occur.");
console.error(`SITE_URL is not defined. Issues may occur.`);
}
const { defaultLocale, Locale } = i18n;
const locales = Object.values(Locale);
const siteMetadata = {
title: "ssg starter",
description: "A starter for static site generation with Gatsby",
twitterUsername: "@username",
title: `ssg starter`,
description: `A starter for static site generation with Gatsby`,
twitterUsername: `@username`,
siteUrl: process.env.SITE_URL,
};

// - Plugins -
const devPlugins = ["gatsby-plugin-tsconfig-paths", "gatsby-plugin-postcss"];
const devPlugins = [`gatsby-plugin-tsconfig-paths`, `gatsby-plugin-postcss`];
const i18nPlugins = [
{
resolve: `gatsby-source-filesystem`,
options: {
path: `${__dirname}/locales`,
path: path.resolve(__dirname, `locales`), // Path to the locales directory
name: `locale`,
},
},
{
// Enable i18n support
resolve: "gatsby-plugin-react-i18next", // https://www.gatsbyjs.com/plugins/gatsby-plugin-react-i18next/
resolve: `gatsby-plugin-react-i18next`, // https://www.gatsbyjs.com/plugins/gatsby-plugin-react-i18next/
options: {
languages: locales,
defaultLanguage: defaultLocale,
Expand All @@ -41,22 +42,22 @@ const i18nPlugins = [
// debug: true,
fallbackLng: defaultLocale,
supportedLngs: locales,
defaultNS: "common",
defaultNS: `common`,
interpolation: {
escapeValue: false, // not needed for react as it escapes by default
},
keySeparator: ".",
nsSeparator: ":",
keySeparator: `.`,
nsSeparator: `:`,
},
},
},
];
const seoPlugins = [
"gatsby-plugin-sitemap",
"gatsby-plugin-robots-txt",
`gatsby-plugin-sitemap`,
`gatsby-plugin-robots-txt`,
{
// Generate favicons and icons for the site
resolve: "gatsby-plugin-manifest", // https://www.gatsbyjs.com/plugins/gatsby-plugin-manifest/
resolve: `gatsby-plugin-manifest`, // https://www.gatsbyjs.com/plugins/gatsby-plugin-manifest/
options: {
// TODO: Update this to match your site
// name: "ssg starter",
Expand All @@ -65,16 +66,16 @@ const seoPlugins = [
// background_color: "#ffffff",
// theme_color: "#663399",
// display: "standalone",
icon: "assets/img/icon.png", // necessary for develop to work
icon: `assets/img/icon.png`, // necessary for develop to work
},
},
];
const analyticsPlugins = [
{
// Configures integration with Google Analytics
resolve: "gatsby-plugin-google-gtag", // https://www.gatsbyjs.com/plugins/gatsby-plugin-google-gtag/
resolve: `gatsby-plugin-google-gtag`, // https://www.gatsbyjs.com/plugins/gatsby-plugin-google-gtag/
options: {
trackingIds: ["G-XXXXXXXXXX"], // TODO: Update this with your tracking ID
trackingIds: [`G-XXXXXXXXXX`], // TODO: Update this with your tracking ID
},
},
];
Expand All @@ -83,7 +84,7 @@ const analyticsPlugins = [
const config: GatsbyConfig = {
siteMetadata,
graphqlTypegen: true, // generates types for graphql queries
pathPrefix: "/ssg-starter", // TODO: Update this to match your site
pathPrefix: `/ssg-starter`, // TODO: Update this to match your site
plugins: [...devPlugins, ...i18nPlugins, ...seoPlugins, ...analyticsPlugins],
};

Expand Down
2 changes: 1 addition & 1 deletion gatsby-node.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
exports.onPostBuild = require("./gatsby/onPostBuild");
exports.onPostBuild = require(`./gatsby/onPostBuild`);
30 changes: 15 additions & 15 deletions gatsby/onPostBuild.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
const { chromium } = require("playwright");
const path = require("path");
const fs = require("fs");
const { chromium } = require(`playwright`);
const path = require(`path`);
const fs = require(`fs`);

// TODO: Replace this with a custom template
const exampleTemplate = require("../src/templates/OG/example.js");
const exampleTemplate = require(`../src/templates/OG/example.js`);

/**
* This post build script is used to generate OG images for blog posts and other pages.
* Based off of https://github.com/PostHog/posthog.com/blob/138a67505cc806e12d3500969b96e00b741ce338/gatsby/onPostBuild.js
*/
module.exports = exports.onPostBuild = async ({ graphql }) => {
module.exports = exports.onPostBuild = async () => {
// TODO: Fetch data from your graphql endpoint
// const { data } = await graphql(`
// query {
// }
// `);

// Create the og-images directory in the output folder if it doesn't exist
const dir = path.resolve(__dirname, "../public/og-images");
const dir = path.resolve(__dirname, `../public/og-images`);
if (!fs.existsSync(dir)) fs.mkdirSync(dir);

// TODO: Fetch and save a font to the assets folder
Expand All @@ -41,7 +41,7 @@ module.exports = exports.onPostBuild = async ({ graphql }) => {
// });

const browser = await chromium.launch({
args: ["--no-sandbox", "--disable-setuid-sandbox"],
args: [`--no-sandbox`, `--disable-setuid-sandbox`],
headless: true,
});

Expand All @@ -52,14 +52,14 @@ module.exports = exports.onPostBuild = async ({ graphql }) => {
});
async function createOG({ html, slug }) {
await page.setContent(html, {
waitUntil: "domcontentloaded",
waitUntil: `domcontentloaded`,
});

await page.evaluateHandle("document.fonts.ready");
await page.evaluateHandle(`document.fonts.ready`);

await page.screenshot({
type: "jpeg",
path: `${dir}/${slug.replace(/\//g, "")}.jpeg`,
type: `jpeg`,
path: `${dir}/${slug.replace(/\//g, ``)}.jpeg`,
quality: 75,
});
}
Expand All @@ -72,11 +72,11 @@ module.exports = exports.onPostBuild = async ({ graphql }) => {

await createOG({
html: exampleTemplate({
title: "Example OG Image",
description: "This is an example blog post.",
image: "",
title: `Example OG Image`,
description: `This is an example blog post.`,
image: ``,
}),
slug: "/example",
slug: `/example`,
});

// Repeat this process for all pages that need OG images
Expand Down
13 changes: 13 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,22 @@
"@types/node-fetch": "^2.6.11",
"@types/react": "^18.2.48",
"@types/react-dom": "^18.2.18",
"@typescript-eslint/eslint-plugin": "^6.20.0",
"@typescript-eslint/parser": "^6.20.0",
"@vitest/coverage-v8": "^1.2.2",
"c8": "^9.1.0",
"eslint": "^8.56.0",
"eslint-config-prettier": "^9.1.0",
"eslint-config-standard": "^17.1.0",
"eslint-import-resolver-typescript": "^3.6.1",
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-jsx-a11y": "^6.8.0",
"eslint-plugin-n": "^16.6.2",
"eslint-plugin-prefer-arrow": "^1.2.3",
"eslint-plugin-prettier": "^5.1.3",
"eslint-plugin-promise": "^6.1.1",
"eslint-plugin-react": "^7.33.2",
"eslint-plugin-react-hooks": "^4.6.0",
"gatsby-plugin-tsconfig-paths": "^1.0.6",
"husky": "^9.0.10",
"jsdom": "^24.0.0",
Expand Down
2 changes: 1 addition & 1 deletion postcss.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ module.exports = {
tailwindcss: {},
autoprefixer: {},
},
}
};
15 changes: 7 additions & 8 deletions src/components/Link/Link.test.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import { Link, LinkProps } from "./Link";
import { RenderResult, render } from "@testing-library/react";
import React from "react";
import { beforeEach, describe, expect, it } from "vitest";
import { Link, LinkProps } from "./Link";

describe(Link.name, () => {
const dataTestId = "test";
const dataTestId = `test`;

const mockProps: LinkProps = {
to: "/test",
children: "Test",
to: `/test`,
children: `Test`,
dataTestId,
};

Expand All @@ -17,12 +16,12 @@ describe(Link.name, () => {

beforeEach(() => {
renderResult = render(<Link {...mockProps}>Test</Link>);
LinkEle = renderResult.getByText("Test");
LinkEle = renderResult.getByText(`Test`);
});

it("should render the component with the correct data-testid", () => {
it(`should render the component with the correct data-testid`, () => {
expect(LinkEle).toBeDefined();
const dataTestIdAttr = LinkEle.getAttribute("data-testid");
const dataTestIdAttr = LinkEle.getAttribute(`data-testid`);
expect(dataTestIdAttr).toBe(dataTestId);
});
});
Loading

0 comments on commit 0e0b49d

Please sign in to comment.