@swiftuijs/twill-linter 0.3.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["files","metadata"],"sources":["../package.json","../src/positions.twill","../src/index.twill"],"sourcesContent":["{\n \"name\": \"@swiftuijs/twill-linter\",\n \"version\": \"0.3.0\",\n \"type\": \"module\",\n \"license\": \"MIT\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/swiftuijs/twill.git\",\n \"directory\": \"packages/linter\"\n },\n \"files\": [\n \"dist\",\n \"README.md\",\n \"LICENSE\"\n ],\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.js\"\n }\n },\n \"scripts\": {\n \"build\": \"vite build && twill declarations -p tsconfig.build.json -o dist\",\n \"typecheck\": \"twill check -p tsconfig.json\",\n \"test:unit\": \"vitest run\",\n \"test:watch\": \"vitest\",\n \"test:coverage\": \"vitest run --coverage\",\n \"test:package\": \"node tests/consumer.mjs\",\n \"prepack\": \"pnpm run build\",\n \"test\": \"pnpm run test:unit\"\n },\n \"dependencies\": {\n \"@swiftuijs/twill\": \"workspace:*\",\n \"@typescript-eslint/parser\": \"^8.71.0\",\n \"@typescript-eslint/eslint-plugin\": \"^8.71.0\",\n \"@eslint/js\": \"catalog:\",\n \"typescript\": \"catalog:\"\n },\n \"devDependencies\": {\n \"vite\": \"catalog:\",\n \"@types/node\": \"catalog:\",\n \"typescript\": \"catalog:\",\n \"eslint\": \"catalog:\",\n \"vitest\": \"catalog:\",\n \"@vitest/coverage-v8\": \"catalog:\"\n },\n \"engines\": {\n \"node\": \"^20.19.0 || >=22.12.0\"\n },\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"peerDependencies\": {\n \"eslint\": \"^9.0.0 || ^10.0.0\"\n },\n \"author\": {\n \"name\": \"forth.ink\",\n \"url\": \"https://forth.ink\"\n },\n \"homepage\": \"https://twill.evecalm.com/\",\n \"bugs\": {\n \"url\": \"https://github.com/swiftuijs/twill/issues\"\n },\n \"keywords\": [\n \"twill\",\n \"eslint\",\n \"eslint-plugin\",\n \"typescript\",\n \"linter\"\n ],\n \"description\": \"ESLint flat configurations for Twill with TypeScript rules, original-source diagnostics and safe fixes.\"\n}\n","/** Source-map lines use LF; ESLint positions also count CR and Unicode separators. */\nexport class SourcePositions {\n private native = [0];\n private mapped = [0];\n\n constructor(text: string) {\n const breaks = /\\r\\n|[\\n\\r\\u2028\\u2029]/g;\n while (breaks.exec(text)) this.native.push(breaks.lastIndex);\n for (let index = 0; index < text.length; index++)\n if (text[index] === '\\n') this.mapped.push(index + 1);\n }\n\n private position(starts: number[], offset: number) {\n let low = 0;\n let high = starts.length;\n while (low + 1 < high) {\n const middle = (low + high) >>> 1;\n if (starts[middle]! <= offset) low = middle;\n else high = middle;\n }\n return { line: low, character: offset - starts[low]! };\n }\n\n getLineAndCharacterOfPosition(offset: number) {\n return this.position(this.native, offset);\n }\n\n getPositionOfLineAndCharacter(line: number, column: number) {\n return this.native[line]! + column;\n }\n\n mapPosition(offset: number) {\n const position = this.position(this.mapped, offset);\n return { line: position.line + 1, column: position.character };\n }\n\n mapOffset(line: number, column: number) {\n return this.mapped[line - 1]! + column;\n }\n}\n","import {\n transform,\n originalPosition,\n generatedPosition,\n type TransformResult,\n} from '@swiftuijs/twill';\nimport { TwillProject, virtualFilename, sourceFilename } from '@swiftuijs/twill/project';\nimport * as parser from '@typescript-eslint/parser';\nimport typescriptPlugin from '@typescript-eslint/eslint-plugin';\nimport js from '@eslint/js';\nimport ts from 'typescript';\nimport { loadConfig } from '@swiftuijs/twill/config';\nimport { dirname, resolve } from 'node:path';\nimport { statSync } from 'node:fs';\nimport type { ESLint, Linter, Rule } from 'eslint';\nimport metadata from '../package.json' with { type: 'json' };\nimport { SourcePositions } from './positions.twill';\n\ntype State = {\n source: string;\n filename: string;\n result?: TransformResult;\n error?: any;\n original: SourcePositions;\n generated?: SourcePositions;\n project?: TwillProject;\n};\nconst pending = new Map<string, State>();\nconst projects = new Map<string, { project: TwillProject; times: Map<string, number> }>();\nconst normalize = (filename: string) => filename.replaceAll('\\\\', '/');\nconst stamp = (filename: string) => {\n try {\n return statSync(filename).mtimeMs;\n } catch {\n return -1;\n }\n};\n\nfunction projectFor(filename: string) {\n const config = ts.findConfigFile(dirname(filename), ts.sys.fileExists);\n guard config else {\n throw new Error('Typed Twill linting requires a tsconfig.json.');\n }\n let cached = projects.get(config);\n if (\n cached &&\n cached.project.configFiles.some((file) => cached!.times.get(file) !== stamp(file))\n ) {\n cached.project.dispose();\n projects.delete(config);\n cached = undefined;\n }\n if (!cached) {\n cached = { project: new TwillProject(config), times: new Map() };\n for (const file of cached.project.configFiles) cached.times.set(file, stamp(file));\n if (projects.size >= 8) {\n const oldest = projects.keys().next().value!;\n projects.get(oldest)!.project.dispose();\n projects.delete(oldest);\n }\n projects.set(config, cached);\n }\n for (const file of cached.project.sourceFiles()) {\n const time = stamp(file);\n if (cached.times.has(file) && cached.times.get(file) !== time) cached.project.refresh(file);\n cached.times.set(file, time);\n }\n return cached.project;\n}\n\nfunction originalOffset(state: State, offset: number) {\n const position = state.generated!.mapPosition(offset);\n const point = originalPosition(state.result!, position.line, position.column);\n return point.line == null || point.column == null\n ? undefined\n : state.original.mapOffset(point.line, point.column);\n}\nfunction fix(state: State, value: Rule.Fix | undefined): Rule.Fix | undefined {\n if (!value) return undefined;\n const [start, end] = value.range;\n const offset = originalOffset(state, start);\n if (offset === undefined) return undefined;\n const position = state.original.mapPosition(offset);\n const generated = generatedPosition(state.result!, position.line, position.column);\n if (\n generated.line == null ||\n generated.column == null ||\n state.generated!.mapOffset(generated.line, generated.column) !== start ||\n state.source.slice(offset, offset + end - start) !== state.result!.code.slice(start, end)\n )\n return undefined;\n return { range: [offset, offset + end - start], text: value.text };\n}\n\nconst processor: Linter.Processor = {\n supportsAutofix: true,\n preprocess(source, filename) {\n filename = normalize(filename);\n const state: State = {\n source,\n filename,\n original: new SourcePositions(source),\n };\n pending.set(filename, state);\n try {\n // A project supplies the same inherited JSX settings as builds/checking.\n const config = ts.findConfigFile(dirname(filename), ts.sys.fileExists);\n state.result = transform(source, {\n ...loadConfig(config ? dirname(config) : dirname(filename)),\n filename,\n });\n state.generated = new SourcePositions(state.result.code);\n return [\n {\n text: state.result.code,\n filename: filename.endsWith('.twillx') ? 'source.tsx' : 'source.ts',\n },\n ];\n } catch (error) {\n state.error = error;\n return [];\n }\n },\n postprocess(lists, filename) {\n filename = normalize(filename);\n const state = pending.get(filename)!;\n pending.delete(filename);\n state.project?.update(filename);\n if (state.error)\n return [\n {\n ruleId: null,\n severity: 2,\n fatal: true,\n message: state.error.message,\n line: state.error.line ?? 1,\n column: (state.error.column ?? 0) + 1,\n },\n ];\n return lists.flat().flatMap((message) => {\n if (!message.line || !message.column) return [message];\n const generated = state.generated!;\n const start = generated.getPositionOfLineAndCharacter(message.line - 1, message.column - 1);\n let offset = originalOffset(state, start);\n let expressionSwitch = false;\n let expressionKeywordLength = 6;\n if (\n message.ruleId === '@typescript-eslint/switch-exhaustiveness-check' &&\n state.project &&\n (offset === undefined || state.result!.code[start] !== state.source[offset])\n ) {\n // Expression subjects use a generated once-evaluated local. Report the\n // missing union arm on the source-backed switch/match keyword instead.\n const file = state.project.service.getProgram()?.getSourceFile(virtualFilename(filename));\n const visit = (node: ts.Node) => {\n if (ts.isSwitchStatement(node) && node.expression.getStart() === start) {\n const sourceStart = originalOffset(state, node.getStart());\n if (\n sourceStart !== undefined &&\n /^(?:switch|match)\\b/.test(state.source.slice(sourceStart))\n ) {\n offset = sourceStart;\n expressionSwitch = true;\n expressionKeywordLength = state.source.startsWith('match', sourceStart) ? 5 : 6;\n }\n } else if (start >= node.getFullStart() && start < node.end) ts.forEachChild(node, visit);\n };\n if (file) visit(file);\n }\n if (\n offset === undefined ||\n (!expressionSwitch &&\n start < state.result!.code.length &&\n state.result!.code[start] !== state.source[offset])\n )\n return [];\n const position = state.original.getLineAndCharacterOfPosition(offset);\n const endOffset = expressionSwitch\n ? offset + expressionKeywordLength\n : message.endLine && message.endColumn\n ? originalOffset(\n state,\n generated.getPositionOfLineAndCharacter(message.endLine - 1, message.endColumn - 1),\n )\n : undefined;\n const end =\n endOffset === undefined\n ? undefined\n : state.original.getLineAndCharacterOfPosition(endOffset);\n return [\n {\n ...message,\n line: position.line + 1,\n column: position.character + 1,\n endLine: end && end.line + 1,\n endColumn: end && end.character + 1,\n fix: expressionSwitch ? undefined : fix(state, message.fix),\n // Native statement-case suggestions introduce blocks/value labels that\n // are invalid in a Twill switch expression. Keep the diagnostic.\n suggestions: expressionSwitch\n ? []\n : message.suggestions?.flatMap((suggestion) => {\n const mapped = fix(state, suggestion.fix);\n return mapped ? [{ ...suggestion, fix: mapped }] : [];\n }),\n },\n ];\n });\n },\n};\n\nconst virtualParser = {\n meta: { name: '@swiftuijs/twill-linter/parser', version: metadata.version },\n parseForESLint(code: string, options: any) {\n const original = normalize(options.filePath ?? '').replace(/\\/(?:\\d+_)?source\\.tsx?$/, '');\n const state = pending.get(original);\n if (!state) return parser.parseForESLint(code, options);\n const typed = options.projectService || options.project || options.programs;\n if (!typed) return parser.parseForESLint(code, options);\n const project = projectFor(original);\n project.update(original, state.source);\n state.project = project;\n return parser.parseForESLint(code, {\n ...options,\n filePath: virtualFilename(original),\n projectService: false,\n project: undefined,\n programs: [project.service.getProgram()!],\n });\n },\n};\n\nconst plugin: ESLint.Plugin & { configs: Record<string, Linter.Config[]> } = {\n meta: { name: '@swiftuijs/twill-linter', version: metadata.version },\n processors: { twill: processor },\n configs: {} as Record<string, Linter.Config[]>,\n};\nconst files = ['**/*.ts', '**/*.tsx', '**/*.mts', '**/*.cts'];\nfunction configuration(typed: boolean): Linter.Config[] {\n const recommended = typescriptPlugin.configs[\n typed ? 'flat/recommended-type-checked' : 'flat/recommended'\n ] as Linter.Config[];\n return [\n js.configs.recommended,\n { files: ['**/*.twill', '**/*.twillx'], plugins: { twill: plugin }, processor: 'twill/twill' },\n ...recommended.map((config) => ({\n ...config,\n files,\n languageOptions: {\n ...config.languageOptions,\n parser: virtualParser,\n ...(typed ? { parserOptions: { projectService: true } } : {}),\n },\n })),\n ...(typed\n ? [\n {\n files,\n rules: {\n '@typescript-eslint/switch-exhaustiveness-check': [\n 'error',\n { considerDefaultExhaustiveForUnions: false },\n ] satisfies Linter.RuleEntry,\n },\n },\n ]\n : []),\n ];\n}\nplugin.configs.recommended = configuration(false);\nplugin.configs.recommendedTypeChecked = configuration(true);\nexport const configs: Record<string, Linter.Config[]> = plugin.configs;\nexport const processors: Record<string, Linter.Processor> = { twill: processor };\nexport function disposeProjects() {\n for (const { project } of projects.values()) project.dispose();\n projects.clear();\n pending.clear();\n}\nexport default plugin;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["files","metadata"],"sources":["../package.json","../src/positions.twill","../src/index.twill"],"sourcesContent":["{\n \"name\": \"@swiftuijs/twill-linter\",\n \"version\": \"0.3.1\",\n \"type\": \"module\",\n \"license\": \"MIT\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git+https://github.com/swiftuijs/twill.git\",\n \"directory\": \"packages/linter\"\n },\n \"files\": [\n \"dist\",\n \"README.md\",\n \"LICENSE\"\n ],\n \"exports\": {\n \".\": {\n \"types\": \"./dist/index.d.ts\",\n \"import\": \"./dist/index.js\"\n }\n },\n \"scripts\": {\n \"build\": \"vite build && twill declarations -p tsconfig.build.json -o dist\",\n \"typecheck\": \"twill check -p tsconfig.json\",\n \"test:unit\": \"vitest run\",\n \"test:watch\": \"vitest\",\n \"test:coverage\": \"vitest run --coverage\",\n \"test:package\": \"node tests/consumer.mjs\",\n \"prepack\": \"pnpm run build\",\n \"test\": \"pnpm run test:unit\"\n },\n \"dependencies\": {\n \"@swiftuijs/twill\": \"workspace:*\",\n \"@typescript-eslint/parser\": \"^8.71.0\",\n \"@typescript-eslint/eslint-plugin\": \"^8.71.0\",\n \"@eslint/js\": \"catalog:\",\n \"typescript\": \"catalog:\"\n },\n \"devDependencies\": {\n \"vite\": \"catalog:\",\n \"@types/node\": \"catalog:\",\n \"typescript\": \"catalog:\",\n \"eslint\": \"catalog:\",\n \"vitest\": \"catalog:\",\n \"@vitest/coverage-v8\": \"catalog:\"\n },\n \"engines\": {\n \"node\": \"^20.19.0 || >=22.12.0\"\n },\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"peerDependencies\": {\n \"eslint\": \"^9.0.0 || ^10.0.0\"\n },\n \"author\": {\n \"name\": \"forth.ink\",\n \"url\": \"https://forth.ink\"\n },\n \"homepage\": \"https://twill.evecalm.com/\",\n \"bugs\": {\n \"url\": \"https://github.com/swiftuijs/twill/issues\"\n },\n \"keywords\": [\n \"twill\",\n \"eslint\",\n \"eslint-plugin\",\n \"typescript\",\n \"linter\"\n ],\n \"description\": \"ESLint flat configurations for Twill with TypeScript rules, original-source diagnostics and safe fixes.\"\n}\n","/** Source-map lines use LF; ESLint positions also count CR and Unicode separators. */\nexport class SourcePositions {\n private native = [0];\n private mapped = [0];\n\n constructor(text: string) {\n const breaks = /\\r\\n|[\\n\\r\\u2028\\u2029]/g;\n while (breaks.exec(text)) this.native.push(breaks.lastIndex);\n for (let index = 0; index < text.length; index++)\n if (text[index] === '\\n') this.mapped.push(index + 1);\n }\n\n private position(starts: number[], offset: number) {\n let low = 0;\n let high = starts.length;\n while (low + 1 < high) {\n const middle = (low + high) >>> 1;\n if (starts[middle]! <= offset) low = middle;\n else high = middle;\n }\n return { line: low, character: offset - starts[low]! };\n }\n\n getLineAndCharacterOfPosition(offset: number) {\n return this.position(this.native, offset);\n }\n\n getPositionOfLineAndCharacter(line: number, column: number) {\n return this.native[line]! + column;\n }\n\n mapPosition(offset: number) {\n const position = this.position(this.mapped, offset);\n return { line: position.line + 1, column: position.character };\n }\n\n mapOffset(line: number, column: number) {\n return this.mapped[line - 1]! + column;\n }\n}\n","import {\n transform,\n originalPosition,\n generatedPosition,\n type TransformResult,\n} from '@swiftuijs/twill';\nimport { TwillProject, virtualFilename, sourceFilename } from '@swiftuijs/twill/project';\nimport * as parser from '@typescript-eslint/parser';\nimport typescriptPlugin from '@typescript-eslint/eslint-plugin';\nimport js from '@eslint/js';\nimport ts from 'typescript';\nimport { loadConfig } from '@swiftuijs/twill/config';\nimport { dirname, resolve } from 'node:path';\nimport { statSync } from 'node:fs';\nimport type { ESLint, Linter, Rule } from 'eslint';\nimport metadata from '../package.json' with { type: 'json' };\nimport { SourcePositions } from './positions.twill';\n\ntype State = {\n source: string;\n filename: string;\n result?: TransformResult;\n error?: any;\n original: SourcePositions;\n generated?: SourcePositions;\n project?: TwillProject;\n};\nconst pending = new Map<string, State>();\nconst projects = new Map<string, { project: TwillProject; times: Map<string, number> }>();\nconst normalize = (filename: string) => filename.replaceAll('\\\\', '/');\nconst stamp = (filename: string) => {\n try {\n return statSync(filename).mtimeMs;\n } catch {\n return -1;\n }\n};\n\nfunction projectFor(filename: string) {\n const config = ts.findConfigFile(dirname(filename), ts.sys.fileExists);\n guard config else {\n throw new Error('Typed Twill linting requires a tsconfig.json.');\n }\n let cached = projects.get(config);\n if (\n cached &&\n cached.project.configFiles.some((file) => cached!.times.get(file) !== stamp(file))\n ) {\n cached.project.dispose();\n projects.delete(config);\n cached = undefined;\n }\n if (!cached) {\n cached = { project: new TwillProject(config), times: new Map() };\n for (const file of cached.project.configFiles) cached.times.set(file, stamp(file));\n if (projects.size >= 8) {\n const oldest = projects.keys().next().value!;\n projects.get(oldest)!.project.dispose();\n projects.delete(oldest);\n }\n projects.set(config, cached);\n }\n for (const file of cached.project.sourceFiles()) {\n const time = stamp(file);\n if (cached.times.has(file) && cached.times.get(file) !== time) cached.project.refresh(file);\n cached.times.set(file, time);\n }\n return cached.project;\n}\n\nfunction originalOffset(state: State, offset: number) {\n const position = state.generated!.mapPosition(offset);\n const point = originalPosition(state.result!, position.line, position.column);\n return point.line == null || point.column == null\n ? undefined\n : state.original.mapOffset(point.line, point.column);\n}\nfunction fix(state: State, value: Rule.Fix | undefined): Rule.Fix | undefined {\n if (!value) return undefined;\n const [start, end] = value.range;\n const offset = originalOffset(state, start);\n if (offset === undefined) return undefined;\n const position = state.original.mapPosition(offset);\n const generated = generatedPosition(state.result!, position.line, position.column);\n if (\n generated.line == null ||\n generated.column == null ||\n state.generated!.mapOffset(generated.line, generated.column) !== start ||\n state.source.slice(offset, offset + end - start) !== state.result!.code.slice(start, end)\n )\n return undefined;\n return { range: [offset, offset + end - start], text: value.text };\n}\n\nconst processor: Linter.Processor = {\n supportsAutofix: true,\n preprocess(source, filename) {\n filename = normalize(filename);\n const state: State = {\n source,\n filename,\n original: new SourcePositions(source),\n };\n pending.set(filename, state);\n try {\n // A project supplies the same inherited JSX settings as builds/checking.\n const config = ts.findConfigFile(dirname(filename), ts.sys.fileExists);\n state.result = transform(source, {\n ...loadConfig(config ? dirname(config) : dirname(filename)),\n filename,\n });\n state.generated = new SourcePositions(state.result.code);\n return [\n {\n text: state.result.code,\n filename: filename.endsWith('.twillx') ? 'source.tsx' : 'source.ts',\n },\n ];\n } catch (error) {\n state.error = error;\n return [];\n }\n },\n postprocess(lists, filename) {\n filename = normalize(filename);\n const state = pending.get(filename)!;\n pending.delete(filename);\n state.project?.update(filename);\n if (state.error)\n return [\n {\n ruleId: null,\n severity: 2,\n fatal: true,\n message: state.error.message,\n line: state.error.line ?? 1,\n column: (state.error.column ?? 0) + 1,\n },\n ];\n return lists.flat().flatMap((message) => {\n if (!message.line || !message.column) return [message];\n const generated = state.generated!;\n const start = generated.getPositionOfLineAndCharacter(message.line - 1, message.column - 1);\n let offset = originalOffset(state, start);\n let expressionSwitch = false;\n let expressionKeywordLength = 6;\n if (\n message.ruleId === '@typescript-eslint/switch-exhaustiveness-check' &&\n state.project &&\n (offset === undefined || state.result!.code[start] !== state.source[offset])\n ) {\n // Expression subjects use a generated once-evaluated local. Report the\n // missing union arm on the source-backed switch/match keyword instead.\n const file = state.project.service.getProgram()?.getSourceFile(virtualFilename(filename));\n const visit = (node: ts.Node) => {\n if (ts.isSwitchStatement(node) && node.expression.getStart() === start) {\n const sourceStart = originalOffset(state, node.getStart());\n if (\n sourceStart !== undefined &&\n /^(?:switch|match)\\b/.test(state.source.slice(sourceStart))\n ) {\n offset = sourceStart;\n expressionSwitch = true;\n expressionKeywordLength = state.source.startsWith('match', sourceStart) ? 5 : 6;\n }\n } else if (start >= node.getFullStart() && start < node.end) ts.forEachChild(node, visit);\n };\n if (file) visit(file);\n }\n if (\n offset === undefined ||\n (!expressionSwitch &&\n start < state.result!.code.length &&\n state.result!.code[start] !== state.source[offset])\n )\n return [];\n const position = state.original.getLineAndCharacterOfPosition(offset);\n const endOffset = expressionSwitch\n ? offset + expressionKeywordLength\n : message.endLine && message.endColumn\n ? originalOffset(\n state,\n generated.getPositionOfLineAndCharacter(message.endLine - 1, message.endColumn - 1),\n )\n : undefined;\n const end =\n endOffset === undefined\n ? undefined\n : state.original.getLineAndCharacterOfPosition(endOffset);\n return [\n {\n ...message,\n line: position.line + 1,\n column: position.character + 1,\n endLine: end && end.line + 1,\n endColumn: end && end.character + 1,\n fix: expressionSwitch ? undefined : fix(state, message.fix),\n // Native statement-case suggestions introduce blocks/value labels that\n // are invalid in a Twill switch expression. Keep the diagnostic.\n suggestions: expressionSwitch\n ? []\n : message.suggestions?.flatMap((suggestion) => {\n const mapped = fix(state, suggestion.fix);\n return mapped ? [{ ...suggestion, fix: mapped }] : [];\n }),\n },\n ];\n });\n },\n};\n\nconst virtualParser = {\n meta: { name: '@swiftuijs/twill-linter/parser', version: metadata.version },\n parseForESLint(code: string, options: any) {\n const original = normalize(options.filePath ?? '').replace(/\\/(?:\\d+_)?source\\.tsx?$/, '');\n const state = pending.get(original);\n if (!state) return parser.parseForESLint(code, options);\n const typed = options.projectService || options.project || options.programs;\n if (!typed) return parser.parseForESLint(code, options);\n const project = projectFor(original);\n project.update(original, state.source);\n state.project = project;\n return parser.parseForESLint(code, {\n ...options,\n filePath: virtualFilename(original),\n projectService: false,\n project: undefined,\n programs: [project.service.getProgram()!],\n });\n },\n};\n\nconst plugin: ESLint.Plugin & { configs: Record<string, Linter.Config[]> } = {\n meta: { name: '@swiftuijs/twill-linter', version: metadata.version },\n processors: { twill: processor },\n configs: {} as Record<string, Linter.Config[]>,\n};\nconst files = ['**/*.ts', '**/*.tsx', '**/*.mts', '**/*.cts'];\nfunction configuration(typed: boolean): Linter.Config[] {\n const recommended = typescriptPlugin.configs[\n typed ? 'flat/recommended-type-checked' : 'flat/recommended'\n ] as Linter.Config[];\n return [\n js.configs.recommended,\n { files: ['**/*.twill', '**/*.twillx'], plugins: { twill: plugin }, processor: 'twill/twill' },\n ...recommended.map((config) => ({\n ...config,\n files,\n languageOptions: {\n ...config.languageOptions,\n parser: virtualParser,\n ...(typed ? { parserOptions: { projectService: true } } : {}),\n },\n })),\n ...(typed\n ? [\n {\n files,\n rules: {\n '@typescript-eslint/switch-exhaustiveness-check': [\n 'error',\n { considerDefaultExhaustiveForUnions: false },\n ] satisfies Linter.RuleEntry,\n },\n },\n ]\n : []),\n ];\n}\nplugin.configs.recommended = configuration(false);\nplugin.configs.recommendedTypeChecked = configuration(true);\nexport const configs: Record<string, Linter.Config[]> = plugin.configs;\nexport const processors: Record<string, Linter.Processor> = { twill: processor };\nexport function disposeProjects() {\n for (const { project } of projects.values()) project.dispose();\n projects.clear();\n pending.clear();\n}\nexport default plugin;\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@swiftuijs/twill-linter",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"@typescript-eslint/eslint-plugin": "^8.71.0",
|
|
25
25
|
"@eslint/js": "^9.39.5",
|
|
26
26
|
"typescript": "5.9.3",
|
|
27
|
-
"@swiftuijs/twill": "0.3.
|
|
27
|
+
"@swiftuijs/twill": "0.3.1"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
30
|
"vite": "^8.3.2",
|