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

feat: implement typescript configs V1.0 #9

Merged
merged 5 commits into from
Aug 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 71 additions & 0 deletions package-lock.json

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

6 changes: 3 additions & 3 deletions src/eslint/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<p align="center"><h1 align="center">
Eslint Config
</h1>
<p align="center">
<h1 align="center">Eslint Config</h1>
</p>

<div align="center">OpenAlly Node.js Eslint configuration (Work for both JavaScript and TypeScript projects).</div>

Expand Down
5 changes: 4 additions & 1 deletion src/eslint/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@
"name": "@openally/config.eslint",
"version": "1.0.0",
"description": "OpenAlly ESLint configuration for Node.js and TypeScript",
"type": "module",
"main": "./dist/index.js",
"scripts": {
"build": "tsc",
"prepublishOnly": "npm run build",
"test-only": "tsx --test ./test/test.ts",
"test": "c8 --all --src ./src -r html npm run test-only",
"lint": "cross-env eslint src/**/*.ts",
"sync": "npx tsx ./tools/sync.ts"
"sync": "npx tsx ./scripts/sync.ts"
},
"files": [
"dist"
Expand All @@ -29,6 +30,8 @@
"typescript-eslint": "^8.1.0"
},
"devDependencies": {
"@myunisoft/httpie": "^5.0.0",
"@types/jsdom": "^21.1.7",
"@typescript-eslint/types": "^8.1.0",
"jsdom": "^24.1.1"
}
Expand Down
86 changes: 86 additions & 0 deletions src/eslint/scripts/sync.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
// Import Third-party Dependencies
import { request } from "@myunisoft/httpie";
import { JSDOM } from "jsdom";

// Import Internal Dependencies
import { rulesWithTS } from "../src/rules/index.js";

// CONSTANTS
const kEslintRulesReferenceUrl = "https://eslint.org/docs/latest/rules/";
const kStylisticRulesUrl = "https://eslint.style/rules";
const kLocalRules = new Set(Object.keys(rulesWithTS));

const [eslintResult, stylisticResult] = await Promise.all([
request<string>("GET", kEslintRulesReferenceUrl),
request<string>("GET", kStylisticRulesUrl)
]);
const eslintDom = new JSDOM(eslintResult.data);
const stylisticDom = new JSDOM(stylisticResult.data);
const rules = new Set([
...parseESLintRulesReferences(eslintDom),
...parseStylisticRules(stylisticDom)
]);

for (const rule of rules) {
if (kLocalRules.has(rule.ruleName) && rule.isDeprecated) {
console.error(
`Rule "${rule.ruleName}" is deprecated! (https://eslint.org/docs/latest/rules/${rule.ruleName})`
);
}
else if (kLocalRules.has(rule.ruleName) && rule.isRemoved) {
console.error(
`Rule "${rule.ruleName}" is removed! (https://eslint.org/docs/latest/rules/${rule.ruleName})`
);
}
else if (
!kLocalRules.has(rule.ruleName) &&
!kLocalRules.has(`@stylistic/${rule.ruleName}`) &&
!rule.isDeprecated &&
!rule.isRemoved
) {
const label = kEslintRulesReferenceUrl + rule.ruleName;
console.error(
`Rule "${rule.ruleName}" is not present in the local ESLint configuration!(${label})`
);
}
}
console.log("Done!");

function parseESLintRulesReferences(
dom: JSDOM
) {
return [
...dom.window.document.querySelectorAll("article.rule")
].map((rule) => {
return {
ruleName: parseRuleName(rule.textContent),
isDeprecated: rule.classList.contains("rule--deprecated"),
isRemoved: rule.classList.contains("rule--removed")
};
});
}

function parseStylisticRules(
dom: JSDOM
) {
return [
...dom.window.document.querySelectorAll("td a code")
].map((rule) => {
return {
ruleName: parseRuleName(rule.textContent),
isDeprecated: false,
isRemoved: false
};
});
}

function parseRuleName(textContent: string | null) {
if (typeof textContent === "string") {
return textContent
.replace(/\n/g, " ")
.trimStart()
.split(" ")[0];
}

return "";
}
64 changes: 25 additions & 39 deletions src/eslint/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,52 +1,36 @@
// Import Third-party Dependencies
import stylisticPlugin from "@stylistic/eslint-plugin";
import globals from "globals";
import tsEslint, { ConfigWithExtends } from "typescript-eslint";
import tsEslint, { type ConfigWithExtends } from "typescript-eslint";
import * as tsParser from "@typescript-eslint/parser";
import { SourceType } from "@typescript-eslint/types";
import type { SourceType } from "@typescript-eslint/types";

// Import Internal Dependencies
import bestPractices from "./rules/best-practices.js";
import ecmascript6 from "./rules/ecmascript6.js";
import eslintv9 from "./rules/eslintv9.js";
import possibleErrors from "./rules/possible-errors.js";
import styles from "./rules/styles.js";
import variables from "./rules/variables.js";
import stylistic from "./rules/stylistic.js";
import typescript from "./rules/typescript.js";
import { rules, rulesWithTS } from "./rules/index.js";

const kLanguageOptions = {
sourceType: "script",
globals: {
...globals.node
}
};
const kTypescriptLanguageOptions = {
...kLanguageOptions,
sourceType: "module" as SourceType,
parser: tsParser
};
const kRules: Record<string, any> = {
...bestPractices,
...possibleErrors,
...styles,
...ecmascript6,
...eslintv9,
...variables,
...stylistic
};

const kBaseTypeScriptConfigs: ConfigWithExtends[] = [
{
plugins: {
// @ts-ignore
"@stylistic": stylisticPlugin
},
rules: {
...kRules,
...typescript as any,
...rulesWithTS,
"no-undef": "off",
"no-redeclare": "off"
},
languageOptions: kTypescriptLanguageOptions,
languageOptions: {
...kLanguageOptions,
sourceType: "module" as SourceType,
parser: tsParser
},
files: ["**/*.ts"]
},
{
Expand All @@ -57,18 +41,20 @@ const kBaseTypeScriptConfigs: ConfigWithExtends[] = [
}
];

export const ESLintConfig = [{
plugins: {
"@stylistic": stylisticPlugin
},
rules: kRules,
languageOptions: kLanguageOptions
}];

export function typescriptConfig(config?: ConfigWithExtends) {
if (config) {
return tsEslint.config(...kBaseTypeScriptConfigs, config);
export const ESLintConfig = [
{
plugins: {
"@stylistic": stylisticPlugin
},
rules,
languageOptions: kLanguageOptions
}
];

return tsEslint.config(...kBaseTypeScriptConfigs);
export function typescriptConfig(
config?: ConfigWithExtends
) {
return config ?
tsEslint.config(...kBaseTypeScriptConfigs, config) :
tsEslint.config(...kBaseTypeScriptConfigs);
}
3 changes: 1 addition & 2 deletions src/eslint/src/rules/best-practices.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const rules = {
export default {
// See: https://eslint.org/docs/rules/accessor-pairs
"accessor-pairs": "off",

Expand Down Expand Up @@ -215,4 +215,3 @@ const rules = {
// See: https://eslint.org/docs/rules/yoda
yoda: "error"
};
export default rules;
4 changes: 1 addition & 3 deletions src/eslint/src/rules/ecmascript6.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const rules = {
export default {
// See: https://eslint.org/docs/rules/arrow-body-style
"arrow-body-style": ["error", "as-needed", { requireReturnForObjectLiteral: true }],

Expand Down Expand Up @@ -89,5 +89,3 @@ const rules = {
// See: https://eslint.style/rules/js/ryield-star-spacing
"@stylistic/yield-star-spacing": ["error", { before: false, after: true }]
};

export default rules;
3 changes: 1 addition & 2 deletions src/eslint/src/rules/eslintv9.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const rules = {
export default {
"no-constant-binary-expression": "error",
"no-constructor-return": "off",
"no-dupe-else-if": "error",
Expand Down Expand Up @@ -28,4 +28,3 @@ const rules = {
"prefer-regex-literals": "off",
strict: "off"
};
export default rules;
Loading