Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

chore(website): [playground] add support for extends in eslint config#6796

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
armano2 merged 4 commits intov6fromchore/playground-add-support-for-extends
Apr 2, 2023
Merged
Show file tree
Hide file tree
Changes fromall 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
1 change: 1 addition & 0 deletionspackages/website-eslint/package.json
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -31,6 +31,7 @@
"@typescript-eslint/types": "5.57.0",
"@typescript-eslint/utils": "5.57.0",
"eslint": "*",
"@eslint/js": "8.36.0",
"esbuild": "~0.17.12",
"esquery": "*",
"semver": "^7.3.7"
Expand Down
25 changes: 22 additions & 3 deletionspackages/website-eslint/src/index.js
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -5,7 +5,8 @@ This saves us having to mock unnecessary things and reduces our bundle size.
*/
// @ts-check

import { rules } from '@typescript-eslint/eslint-plugin';
import eslintJs from '@eslint/js';
import * as plugin from '@typescript-eslint/eslint-plugin';
import { analyze } from '@typescript-eslint/scope-manager';
import {
astConverter,
Expand All@@ -24,8 +25,26 @@ exports.esquery = esquery;

exports.createLinter = function () {
const linter = new Linter();
for (const name in rules) {
linter.defineRule(`@typescript-eslint/${name}`, rules[name]);
for (const name inplugin.rules) {
linter.defineRule(`@typescript-eslint/${name}`,plugin.rules[name]);
}
return linter;
};

/** @type {Record<string, unknown>} */
const configs = {};

for (const [name, value] of Object.entries(eslintJs.configs)) {
configs[`eslint:${name}`] = value;
}

for (const [name, value] of Object.entries(plugin.configs)) {
if (value.extends && Array.isArray(value.extends)) {
value.extends = value.extends.map(name =>
name.replace(/^\.\/configs\//, 'plugin:@typescript-eslint/'),
);
}
configs[`plugin:@typescript-eslint/${name}`] = value;
}

exports.configs = configs;
6 changes: 6 additions & 0 deletionspackages/website-eslint/types/eslint-js.d.ts
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
declare module '@eslint/js' {
declare const configs: Record<string, unknown>;
export = {
configs,
};
}
8 changes: 4 additions & 4 deletionspackages/website/src/components/editor/LoadedEditor.tsx
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -109,7 +109,7 @@ export const LoadedEditor: React.FC<LoadedEditorProps> = ({
}, [sandboxInstance, tsconfig, webLinter]);

useEffect(() => {
webLinter.updateRules(parseESLintRC(eslintrc).rules);
webLinter.updateEslintConfig(parseESLintRC(eslintrc));
}, [eslintrc, webLinter]);

useEffect(() => {
Expand All@@ -128,7 +128,7 @@ export const LoadedEditor: React.FC<LoadedEditorProps> = ({

const markers = parseLintResults(messages, codeActions, ruleId =>
sandboxInstance.monaco.Uri.parse(
webLinter.rulesUrl.get(ruleId) ?? '',
webLinter.rulesMap.get(ruleId)?.url ?? '',
),
);

Expand DownExpand Up@@ -185,7 +185,7 @@ export const LoadedEditor: React.FC<LoadedEditorProps> = ({
{
uri: sandboxInstance.monaco.Uri.file('eslint-schema.json').toString(), // id of the first schema
fileMatch: [tabs.eslintrc.uri.toString()], // associate with our model
schema: getEslintSchema(webLinter.ruleNames),
schema: getEslintSchema(webLinter),
},
{
uri: sandboxInstance.monaco.Uri.file('ts-schema.json').toString(), // id of the first schema
Expand DownExpand Up@@ -290,7 +290,7 @@ export const LoadedEditor: React.FC<LoadedEditorProps> = ({
tabs.eslintrc,
tabs.tsconfig,
updateMarkers,
webLinter.ruleNames,
webLinter.rulesMap,
]);

const resize = useMemo(() => {
Expand Down
61 changes: 35 additions & 26 deletionspackages/website/src/components/editor/config.ts
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,6 +2,7 @@ import type { JSONSchema4 } from '@typescript-eslint/utils/json-schema';
import type Monaco from 'monaco-editor';

import { getTypescriptOptions } from '../config/utils';
import type { WebLinter } from '../linter/WebLinter';

export function createCompilerOptions(
tsConfig: Record<string, unknown> = {},
Expand DownExpand Up@@ -34,37 +35,45 @@ export function createCompilerOptions(
return options;
}

export function getEslintSchema(
rules: { name: string; description?: string }[],
): JSONSchema4 {
const properties = rules.reduce<Record<string, JSONSchema4>>(
(rules, item) => {
rules[item.name] = {
description: item.description,
export function getEslintSchema(linter: WebLinter): JSONSchema4 {
const properties: Record<string, JSONSchema4> = {};

for (const [, item] of linter.rulesMap) {
properties[item.name] = {
description: `${item.description}\n ${item.url}`,
title: item.name.startsWith('@typescript') ? 'Rules' : 'Core rules',
default: 'off',
oneOf: [
{
type: ['string', 'number'],
enum: ['off', 'warn', 'error', 0, 1, 2],
},
{
type: 'array',
items: [
{
type: ['string', 'number'],
enum: ['off', 'warn', 'error', 0, 1, 2],
},
],
},
],
};
}

return {
type: 'object',
properties: {
extends: {
oneOf: [
{
type: ['string', 'number'],
enum: ['off', 'warn', 'error', 0, 1, 2],
},
{ type: 'string' },
{
type: 'array',
items: [
{
type: ['string', 'number'],
enum: ['off', 'warn', 'error', 0, 1, 2],
},
],
items: { type: 'string', enum: Object.keys(linter.configs) },
uniqueItems: true,
},
],
};
return rules;
},
{},
);

return {
type: 'object',
properties: {
},
rules: {
type: 'object',
properties: properties,
Expand Down
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -85,7 +85,7 @@ export const useSandboxServices = (
const webLinter = new WebLinter(system, compilerOptions, lintUtils);

onLoaded(
webLinter.ruleNames,
Array.from(webLinter.rulesMap.values()),
Array.from(
new Set([...sandboxInstance.supportedVersions, window.ts.version]),
)
Expand Down
90 changes: 49 additions & 41 deletionspackages/website/src/components/linter/WebLinter.ts
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
import { createVirtualCompilerHost } from '@site/src/components/linter/CompilerHost';
import { parseSettings } from '@site/src/components/linter/config';
import type { analyze } from '@typescript-eslint/scope-manager';
import type { ParserOptions } from '@typescript-eslint/types';
import type {
Expand All@@ -8,14 +6,11 @@ import type {
} from '@typescript-eslint/typescript-estree/use-at-your-own-risk';
import type { TSESLint, TSESTree } from '@typescript-eslint/utils';
import type esquery from 'esquery';
import type {
CompilerHost,
CompilerOptions,
SourceFile,
System,
} from 'typescript';
import type * as ts from 'typescript';

const PARSER_NAME = '@typescript-eslint/parser';
import type { EslintRC, RuleDetails } from '../types';
import { createVirtualCompilerHost } from './CompilerHost';
import { eslintConfig, PARSER_NAME, parseSettings } from './config';

export interface LintUtils {
createLinter: () => TSESLint.Linter;
Expand All@@ -24,37 +19,28 @@ export interface LintUtils {
astConverter: typeof astConverter;
getScriptKind: typeof getScriptKind;
esquery: typeof esquery;
configs: Record<string, TSESLint.Linter.Config>;
}

export class WebLinter {
private readonly host: CompilerHost;
private readonly host:ts.CompilerHost;

public storedAST?: TSESTree.Program;
public storedTsAST?: SourceFile;
public storedTsAST?:ts.SourceFile;
public storedScope?: Record<string, unknown>;

private compilerOptions: CompilerOptions;
private readonly parserOptions: ParserOptions = {
ecmaFeatures: {
jsx: true,
globalReturn: false,
},
comment: true,
ecmaVersion: 'latest',
project: ['./tsconfig.json'],
sourceType: 'module',
};
private compilerOptions: ts.CompilerOptions;
private eslintConfig = eslintConfig;

private linter: TSESLint.Linter;
private lintUtils: LintUtils;
private rules: TSESLint.Linter.RulesRecord = {};

public readonlyruleNames: { name:string; description?: string }[] = [];
public readonlyrulesUrl = new Map<string,string | undefined>();
public readonlyrulesMap = new Map<string, RuleDetails>();
public readonlyconfigs: Record<string,TSESLint.Linter.Config> = {};

constructor(
system: System,
compilerOptions: CompilerOptions,
system:ts.System,
compilerOptions:ts.CompilerOptions,
lintUtils: LintUtils,
) {
this.compilerOptions = compilerOptions;
Expand All@@ -69,23 +55,17 @@ export class WebLinter {
},
});

this.configs = lintUtils.configs;

this.linter.getRules().forEach((item, name) => {
this.ruleNames.push({
this.rulesMap.set(name,{
name: name,
description: item.meta?.docs?.description,
url: item.meta?.docs?.url,
});
this.rulesUrl.set(name, item.meta?.docs?.url);
});
}

get eslintConfig(): TSESLint.Linter.Config {
return {
parser: PARSER_NAME,
parserOptions: this.parserOptions,
rules: this.rules,
};
}

lint(code: string, filename: string): TSESLint.Linter.LintMessage[] {
return this.linter.verify(code, this.eslintConfig, {
filename: filename,
Expand All@@ -99,15 +79,17 @@ export class WebLinter {
});
}

updateRules(rules: TSESLint.Linter.RulesRecord): void {
this.rules = rules;
updateEslintConfig(config: EslintRC): void {
const resolvedConfig = this.resolveEslintConfig(config);
this.eslintConfig.rules = resolvedConfig.rules;
}

updateParserOptions(sourceType?: TSESLint.SourceType): void {
this.parserOptions.sourceType = sourceType ?? 'module';
this.eslintConfig.parserOptions ??= {};
this.eslintConfig.parserOptions.sourceType = sourceType ?? 'module';
}

updateCompilerOptions(options: CompilerOptions = {}): void {
updateCompilerOptions(options:ts.CompilerOptions = {}): void {
this.compilerOptions = options;
}

Expand DownExpand Up@@ -161,4 +143,30 @@ export class WebLinter {
visitorKeys: this.lintUtils.visitorKeys,
};
}

private resolveEslintConfig(
cfg: Partial<TSESLint.Linter.Config>,
): TSESLint.Linter.Config {
const config = {
rules: {},
overrides: [],
};
if (cfg.extends) {
const cfgExtends = Array.isArray(cfg.extends)
? cfg.extends
: [cfg.extends];
for (const extendsName of cfgExtends) {
if (typeof extendsName === 'string' && extendsName in this.configs) {
const resolved = this.resolveEslintConfig(this.configs[extendsName]);
if (resolved.rules) {
Object.assign(config.rules, resolved.rules);
}
}
}
}
if (cfg.rules) {
Object.assign(config.rules, cfg.rules);
}
return config;
}
}
17 changes: 17 additions & 0 deletionspackages/website/src/components/linter/config.ts
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
import type { ParseSettings } from '@typescript-eslint/typescript-estree/use-at-your-own-risk';
import type { TSESLint } from '@typescript-eslint/utils';

export const PARSER_NAME = '@typescript-eslint/parser';

export const parseSettings: ParseSettings = {
allowInvalidAST: false,
Expand DownExpand Up@@ -26,3 +29,17 @@ export const parseSettings: ParseSettings = {
tsconfigMatchCache: new Map(),
tsconfigRootDir: '/',
};

export const eslintConfig: TSESLint.Linter.Config = {
parser: PARSER_NAME,
parserOptions: {
ecmaFeatures: {
jsx: false,
globalReturn: false,
},
ecmaVersion: 'latest',
project: ['./tsconfig.json'],
sourceType: 'module',
},
rules: {},
};
1 change: 1 addition & 0 deletionspackages/website/src/components/types.ts
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -11,6 +11,7 @@ export type RuleEntry = TSESLint.Linter.RuleEntry;
export interface RuleDetails {
name: string;
description?: string;
url?: string;
}

export type TabType = 'code' | 'tsconfig' | 'eslintrc';
Expand Down

[8]ページ先頭

©2009-2025 Movatter.jp