Skip to content

Commit

Permalink
(chore) Decouple linting and formatting concerns (#30)
Browse files Browse the repository at this point in the history
  • Loading branch information
denniskigen authored May 7, 2024
1 parent 33a31ea commit 0afa818
Show file tree
Hide file tree
Showing 29 changed files with 816 additions and 746 deletions.
38 changes: 28 additions & 10 deletions .eslintrc
Original file line number Diff line number Diff line change
@@ -1,16 +1,34 @@
{
"env": {
"node": true
},
"extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"],
"parser": "@typescript-eslint/parser",
"plugins": [
"@typescript-eslint"
],
"plugins": ["@typescript-eslint", "react-hooks"],
"root": true,
"extends": [
"eslint:recommended",
"plugin:prettier/recommended",
"plugin:@typescript-eslint/recommended",
"ts-react-important-stuff"
],
"rules": {
"react-hooks/exhaustive-deps": "warn",
"react-hooks/rules-of-hooks": "error",
// Disabling these rules for now just to keep the diff small. I'll enable them in a future PR that fixes lint issues.
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-unused-vars": "off",
"@typescript-eslint/no-var-requires": "off",
"@typescript-eslint/ban-ts-comment": "off",
"@typescript-eslint/ban-types": "off",
// Use `import type` instead of `import` for type imports https://typescript-eslint.io/blog/consistent-type-imports-and-exports-why-and-how
"@typescript-eslint/consistent-type-imports": [
"error",
{
"fixStyle": "inline-type-imports"
}
],
"prefer-const": "off",
"no-console": ["error", { "allow": ["warn", "error"] }],
"no-unsafe-optional-chaining": "off",
"no-explicit-any": "off",
"no-extra-boolean-cast": "off",
"no-prototype-builtins": "off",
"no-useless-escape": "off",
"no-restricted-imports": [
"error",
{
Expand All @@ -36,4 +54,4 @@
}
]
}
}
}
2 changes: 1 addition & 1 deletion .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ jobs:
run: npx playwright install chromium --with-deps

- name: Build apps
run: yarn turbo run build --color --concurrency=5
run: yarn turbo build --concurrency=5

- name: Run dev server
run: bash e2e/support/github/run-e2e-docker-env.sh
Expand Down
4 changes: 2 additions & 2 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@

set -e # die on error

yarn pretty-quick --staged
yarn turbo run extract-translations
npx lint-staged
yarn turbo extract-translations
23 changes: 9 additions & 14 deletions __mocks__/react-i18next.js
Original file line number Diff line number Diff line change
@@ -1,42 +1,37 @@
/** At present, this entire mock is boilerplate. */
const React = require("react");
const reactI18next = require("react-i18next");
const React = require('react');
const reactI18next = require('react-i18next');

const hasChildren = (node) =>
node && (node.children || (node.props && node.props.children));
const hasChildren = (node) => node && (node.children || (node.props && node.props.children));

const getChildren = (node) =>
node && node.children ? node.children : node.props && node.props.children;
const getChildren = (node) => (node && node.children ? node.children : node.props && node.props.children);

const renderNodes = (reactNodes) => {
if (typeof reactNodes === "string") {
if (typeof reactNodes === 'string') {
return reactNodes;
}

return Object.keys(reactNodes).map((key, i) => {
const child = reactNodes[key];
const isElement = React.isValidElement(child);

if (typeof child === "string") {
if (typeof child === 'string') {
return child;
}
if (hasChildren(child)) {
const inner = renderNodes(getChildren(child));
return React.cloneElement(child, { ...child.props, key: i }, inner);
}
if (typeof child === "object" && !isElement) {
return Object.keys(child).reduce(
(str, childKey) => `${str}${child[childKey]}`,
""
);
if (typeof child === 'object' && !isElement) {
return Object.keys(child).reduce((str, childKey) => `${str}${child[childKey]}`, '');
}

return child;
});
};

const useMock = [(k) => k, {}];
useMock.t = (k, o) => (o && o.defaultValue) || (typeof o === "string" ? o : k);
useMock.t = (k, o) => (o && o.defaultValue) || (typeof o === 'string' ? o : k);
useMock.i18n = {};

module.exports = {
Expand Down
2 changes: 1 addition & 1 deletion e2e/pages/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export * from './home-page';
export * from './home-page';
16 changes: 8 additions & 8 deletions e2e/specs/sample-test.spec.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import test from "@playwright/test";
import { HomePage } from "../pages";
import { expect } from "@playwright/test";
import test from '@playwright/test';
import { HomePage } from '../pages';
import { expect } from '@playwright/test';

// This test is a sample E2E test. You can delete it.

test("Sample test", async ({ page}) => {
const homePage = new HomePage(page);
await homePage.goto();
await expect(homePage.page.getByRole('link', { name: 'Home' })).toBeVisible();
});
test('Sample test', async ({ page }) => {
const homePage = new HomePage(page);
await homePage.goto();
await expect(homePage.page.getByRole('link', { name: 'Home' })).toBeVisible();
});
4 changes: 2 additions & 2 deletions e2e/support/github/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
# This docker compose file is used to create a backend environment for the e2e.yml workflow.
version: "3.7"
version: '3.7'

services:
gateway:
image: openmrs/openmrs-reference-application-3-gateway:${TAG:-nightly}
ports:
- "8080:80"
- '8080:80'

frontend:
build:
Expand Down
38 changes: 19 additions & 19 deletions i18next-parser.config.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
module.exports = {
contextSeparator: "_",
contextSeparator: '_',
// Key separator used in your translation keys

createOldCatalogs: false,
// Save the \_old files

defaultNamespace: "translations",
defaultNamespace: 'translations',
// Default namespace used in your i18next config

defaultValue: "",
defaultValue: '',
// Default value to give to empty keys
// You may also specify a function accepting the locale, namespace, and key as arguments

Expand All @@ -18,43 +18,43 @@ module.exports = {
keepRemoved: false,
// Keep keys from the catalog that are no longer in code

keySeparator: ".",
keySeparator: '.',
// Key separator used in your translation keys
// If you want to use plain english keys, separators such as `.` and `:` will conflict. You might want to set `keySeparator: false` and `namespaceSeparator: false`. That way, `t('Status: Loading...')` will not think that there are a namespace and three separator dots for instance.

// see below for more details
lexers: {
hbs: ["HandlebarsLexer"],
handlebars: ["HandlebarsLexer"],
hbs: ['HandlebarsLexer'],
handlebars: ['HandlebarsLexer'],

htm: ["HTMLLexer"],
html: ["HTMLLexer"],
htm: ['HTMLLexer'],
html: ['HTMLLexer'],

mjs: ["JavascriptLexer"],
js: ["JavascriptLexer"], // if you're writing jsx inside .js files, change this to JsxLexer
ts: ["JavascriptLexer"],
jsx: ["JsxLexer"],
tsx: ["JsxLexer"],
mjs: ['JavascriptLexer'],
js: ['JavascriptLexer'], // if you're writing jsx inside .js files, change this to JsxLexer
ts: ['JavascriptLexer'],
jsx: ['JsxLexer'],
tsx: ['JsxLexer'],

default: ["JavascriptLexer"],
default: ['JavascriptLexer'],
},

lineEnding: "auto",
lineEnding: 'auto',
// Control the line ending. See options at https://github.com/ryanve/eol

locales: ["en"],
locales: ['en'],
// An array of the locales in your applications

namespaceSeparator: ":",
namespaceSeparator: ':',
// Namespace separator used in your translation keys
// If you want to use plain english keys, separators such as `.` and `:` will conflict. You might want to set `keySeparator: false` and `namespaceSeparator: false`. That way, `t('Status: Loading...')` will not think that there are a namespace and three separator dots for instance.

output: "$NAMESPACE/$LOCALE.json",
output: '$NAMESPACE/$LOCALE.json',
// Supports $LOCALE and $NAMESPACE injection
// Supports JSON (.json) and YAML (.yml) file formats
// Where to write the locale files relative to process.cwd()

pluralSeparator: "_",
pluralSeparator: '_',
// Plural separator used in your translation keys
// If you want to use plain english keys, separators such as `_` might conflict. You might want to set `pluralSeparator` to a different string that does not occur in your keys.

Expand Down
36 changes: 18 additions & 18 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -1,32 +1,32 @@
/**
* @returns {Promise<import('jest').Config>}
*/
const path = require("path");
const path = require('path');

module.exports = {
collectCoverageFrom: [
"**/src/**/*.component.tsx",
"!**/node_modules/**",
"!**/vendor/**",
"!**/src/**/*.test.*",
"!**/src/declarations.d.ts",
"!**/e2e/**",
'**/src/**/*.component.tsx',
'!**/node_modules/**',
'!**/vendor/**',
'!**/src/**/*.test.*',
'!**/src/declarations.d.ts',
'!**/e2e/**',
],
transform: {
"^.+\\.tsx?$": ["@swc/jest"],
'^.+\\.tsx?$': ['@swc/jest'],
},
transformIgnorePatterns: ["/node_modules/(?!@openmrs)"],
transformIgnorePatterns: ['/node_modules/(?!@openmrs)'],
moduleNameMapper: {
"@openmrs/esm-framework": "@openmrs/esm-framework/mock",
"@openmrs/esm-utils": "@openmrs/esm-framework/mock",
"\\.(s?css)$": "identity-obj-proxy",
"^lodash-es/(.*)$": "lodash/$1",
"^dexie$": require.resolve("dexie"),
'@openmrs/esm-framework': '@openmrs/esm-framework/mock',
'@openmrs/esm-utils': '@openmrs/esm-framework/mock',
'\\.(s?css)$': 'identity-obj-proxy',
'^lodash-es/(.*)$': 'lodash/$1',
'^dexie$': require.resolve('dexie'),
},
setupFilesAfterEnv: ["<rootDir>/src/setup-tests.ts"],
testPathIgnorePatterns: [path.resolve(__dirname, "e2e")],
testEnvironment: "jsdom",
setupFilesAfterEnv: ['<rootDir>/src/setup-tests.ts'],
testPathIgnorePatterns: [path.resolve(__dirname, 'e2e')],
testEnvironment: 'jsdom',
testEnvironmentOptions: {
url: "http://localhost/",
url: 'http://localhost/',
},
};
25 changes: 12 additions & 13 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"serve": "webpack serve --mode=development",
"build": "webpack --mode production",
"analyze": "webpack --mode=production --env analyze=true",
"lint": "TIMING=1 eslint src --ext js,jsx,ts,tsx",
"lint": "eslint src --ext js,jsx,ts,tsx --max-warnings 0",
"prettier": "prettier --write \"src/**/*.{ts,tsx}\" --list-different",
"typescript": "tsc",
"test": "jest --config jest.config.js --passWithNoTests",
Expand All @@ -21,11 +21,6 @@
"extract-translations": "i18next 'src/**/*.component.tsx' --config ./i18next-parser.config.js",
"test-e2e": "playwright test"
},
"husky": {
"hooks": {
"pre-commit": "pretty-quick --staged && yarn verify"
}
},
"browserslist": [
"extends browserslist-config-openmrs"
],
Expand Down Expand Up @@ -73,34 +68,38 @@
"@types/react-router": "^5.1.20",
"@types/react-router-dom": "^5.3.3",
"@types/webpack-env": "^1.18.1",
"@typescript-eslint/eslint-plugin": "^5.61.0",
"@typescript-eslint/parser": "^5.61.0",
"@typescript-eslint/eslint-plugin": "^7.8.0",
"@typescript-eslint/parser": "^7.8.0",
"css-loader": "^6.8.1",
"dotenv": "^16.0.3",
"eslint": "^8.44.0",
"eslint": "^8.50.0",
"eslint-config-prettier": "^8.8.0",
"eslint-config-ts-react-important-stuff": "^3.0.0",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-prettier": "^5.1.3",
"eslint-plugin-react-hooks": "^4.6.2",
"husky": "^8.0.3",
"i18next": "^23.2.8",
"i18next-parser": "^8.0.0",
"identity-obj-proxy": "^3.0.0",
"jest": "^29.7.0",
"jest-cli": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
"lint-staged": "^15.2.2",
"openmrs": "next",
"prettier": "^2.8.8",
"pretty-quick": "^3.1.3",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-i18next": "^11.18.6",
"react-router-dom": "^6.14.1",
"rxjs": "^6.6.7",
"swc-loader": "^0.2.3",
"turbo": "^1.12.4",
"turbo": "^1.13.3",
"typescript": "^4.9.5",
"webpack": "^5.88.1",
"webpack-cli": "^5.1.4"
},
"lint-staged": {
"packages/**/src/**/*.{ts,tsx}": "eslint --cache --fix --max-warnings 0",
"*.{css,scss,ts,tsx}": "prettier --write --list-different"
},
"packageManager": "[email protected]"
}
8 changes: 8 additions & 0 deletions prettier.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module.exports = {
bracketSpacing: true,
printWidth: 120,
semi: true,
singleQuote: true,
tabWidth: 2,
trailingComma: 'all',
};
4 changes: 2 additions & 2 deletions src/boxes/extensions/blue-box.component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
* https://o3-docs.vercel.app/docs/extension-system
*/

import React from "react";
import styles from "./box.scss";
import React from 'react';
import styles from './box.scss';

const BlueBox: React.FC = () => {
return <div className={styles.blue}></div>;
Expand Down
4 changes: 2 additions & 2 deletions src/boxes/extensions/brand-box.component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
* https://o3-docs.vercel.app/docs/extension-system
*/

import React from "react";
import styles from "./box.scss";
import React from 'react';
import styles from './box.scss';

const RedBox: React.FC = () => {
return <div className={styles.brand}></div>;
Expand Down
4 changes: 2 additions & 2 deletions src/boxes/extensions/red-box.component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
* https://o3-docs.vercel.app/docs/extension-system
*/

import React from "react";
import styles from "./box.scss";
import React from 'react';
import styles from './box.scss';

const RedBox: React.FC = () => {
return <div className={styles.red}></div>;
Expand Down
Loading

0 comments on commit 0afa818

Please sign in to comment.