diff --git a/packages/compiler/eslint.config.mjs b/packages/compiler/eslint.config.mjs index 5997309..f1ff2be 100644 --- a/packages/compiler/eslint.config.mjs +++ b/packages/compiler/eslint.config.mjs @@ -3,6 +3,7 @@ import tempblotPreset from 'tempblot-config/eslint-preset.js' export default [ ...tempblotPreset, { + files: ['**/*.ts', '**/*.tsx', '**/*.mts', '**/*.cts'], languageOptions: { parserOptions: { projectService: true, diff --git a/packages/compiler/src/index.ts b/packages/compiler/src/index.ts index f90ec3b..d441fcc 100644 --- a/packages/compiler/src/index.ts +++ b/packages/compiler/src/index.ts @@ -5,9 +5,9 @@ import { tokenizeRoot, transformOutputTemplate, } from "tempblot-parser"; -import { transformSetup } from "./setup-transformer.js"; +import { transformSetup } from "./setup-transformer.ts"; -export { TempblotInstance, useParams } from "./instance.js"; +export { TempblotInstance, useParams } from "./instance.ts"; declare global { var tempblotParams: Record | undefined; @@ -40,7 +40,11 @@ export async function compilePath( const tempPath = path.join(sourceDir, `.tempblot_${outputVarName}.ts`); try { await fs.writeFile(tempPath, concatenatedSetupOutput); - const compiledOutput: string = (await import(tempPath))[outputVarName]; + const compiledModule = (await import(tempPath)) as Record; + const compiledOutput = compiledModule[outputVarName]; + if (typeof compiledOutput !== "string") { + throw new TypeError("Tempblot output must compile to a string"); + } return compiledOutput; } finally { await fs.unlink(tempPath); diff --git a/packages/compiler/src/instance.ts b/packages/compiler/src/instance.ts index 668ae6a..ad53385 100644 --- a/packages/compiler/src/instance.ts +++ b/packages/compiler/src/instance.ts @@ -1,3 +1,5 @@ +// An interface so we can interface merge in the future from external sources +// eslint-disable-next-line @typescript-eslint/no-empty-object-type export interface TempblotParams {} export class TempblotInstance { diff --git a/packages/compiler/tests/index.spec.ts b/packages/compiler/tests/index.spec.ts index b2be1e4..5cc4b8e 100644 --- a/packages/compiler/tests/index.spec.ts +++ b/packages/compiler/tests/index.spec.ts @@ -4,7 +4,7 @@ import { dirname } from "node:path"; import { test, expect } from "vitest"; -import { compilePath, useParams } from "../src/index.js"; +import { compilePath, useParams } from "../src/index.ts"; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); diff --git a/packages/compiler/tests/setup-transformer.spec.ts b/packages/compiler/tests/setup-transformer.spec.ts index 6bc0540..088901f 100644 --- a/packages/compiler/tests/setup-transformer.spec.ts +++ b/packages/compiler/tests/setup-transformer.spec.ts @@ -1,5 +1,5 @@ import { expect, test } from "vitest"; -import { transformSetup } from "../src/setup-transformer.js"; +import { transformSetup } from "../src/setup-transformer.ts"; const sourcePath = "/path/to/somefile.tempblot"; diff --git a/packages/config/eslint-preset.js b/packages/config/eslint-preset.js index 2dba202..29983f4 100644 --- a/packages/config/eslint-preset.js +++ b/packages/config/eslint-preset.js @@ -20,12 +20,12 @@ export const tempblotJSRules = { { patterns: [ { - regex: '\.\.?\/.*\.js', + regex: '^\.\.?\/.*\.js$', message: "importing `.js` files is not supported by Node's built-in TypeScript support. Use `.ts` instead.", }, { - regex: '^\\./(?!.*\\.(?:ts|tsx|mts|cts|js|jsx|mjs|cjs)$)', + regex: '^\\./(?!.*\\.(?:ts|tsx|mts|cts|js|jsx|mjs|cjs|json)$)', message: 'Relative imports must include the file extension. For example, use `import foo from "./foo.ts"` instead of `import foo from "./foo"`.', }, @@ -55,6 +55,10 @@ export default defineConfig( { // - `eslint-preset.js`: the preset bootstraps itself, ignoring // keeps eslint from re-evaluating it under the typed rules. - ignores: ['eslint-preset.js', '**/dist/**', '**/lib/**', '**/out/**'], + ignores: [ + 'eslint-preset.js', + '**/dist/**', + '**/out/**', + ], }, ) diff --git a/packages/language-server/eslint.config.mjs b/packages/language-server/eslint.config.mjs index 5997309..7eb16fa 100644 --- a/packages/language-server/eslint.config.mjs +++ b/packages/language-server/eslint.config.mjs @@ -3,6 +3,7 @@ import tempblotPreset from 'tempblot-config/eslint-preset.js' export default [ ...tempblotPreset, { + files: ['**/*.ts', '**/*.tsx', '**/*.mts', '**/*.cts'], languageOptions: { parserOptions: { projectService: true, @@ -17,6 +18,6 @@ export default [ }, }, { - ignores: ['eslint.config.mjs'], + ignores: ['eslint.config.mjs', 'lib/**'], }, ] diff --git a/packages/language-server/src/index.ts b/packages/language-server/src/index.ts index e6d2968..72f016f 100644 --- a/packages/language-server/src/index.ts +++ b/packages/language-server/src/index.ts @@ -23,12 +23,7 @@ const connection = createConnection(); const server = createServer(connection); connection.onInitialize(async (parameters: InitializeParams): Promise => { - const tsdk = parameters.initializationOptions?.typescript?.tsdk; - - assert.ok( - typeof tsdk === 'string', - 'Missing initialization option typescript.tsdk' - ); + const tsdk = getTsdk(parameters); const { typescript, diagnosticMessages } = loadTsdkByPath( tsdk, @@ -52,7 +47,33 @@ connection.onInitialize(async (parameters: InitializeParams): Promise { server.initialized(); - server.fileWatcher?.watchFiles(['**/*.blot']); + void server.fileWatcher?.watchFiles(['**/*.blot']); }); connection.listen(); + +function getTsdk(parameters: InitializeParams): string { + const initializationOptions: unknown = parameters.initializationOptions; + assert.ok( + initializationOptions !== null && + typeof initializationOptions === 'object' && + 'typescript' in initializationOptions, + 'Missing initialization option typescript.tsdk' + ); + + const typescriptOptions: unknown = initializationOptions.typescript; + assert.ok( + typescriptOptions !== null && + typeof typescriptOptions === 'object' && + 'tsdk' in typescriptOptions, + 'Missing initialization option typescript.tsdk' + ); + + const tsdk: unknown = typescriptOptions.tsdk; + assert.ok( + typeof tsdk === 'string', + 'Missing initialization option typescript.tsdk' + ); + + return tsdk; +} diff --git a/packages/language-service/eslint.config.mjs b/packages/language-service/eslint.config.mjs index 5997309..7eb16fa 100644 --- a/packages/language-service/eslint.config.mjs +++ b/packages/language-service/eslint.config.mjs @@ -3,6 +3,7 @@ import tempblotPreset from 'tempblot-config/eslint-preset.js' export default [ ...tempblotPreset, { + files: ['**/*.ts', '**/*.tsx', '**/*.mts', '**/*.cts'], languageOptions: { parserOptions: { projectService: true, @@ -17,6 +18,6 @@ export default [ }, }, { - ignores: ['eslint.config.mjs'], + ignores: ['eslint.config.mjs', 'lib/**'], }, ] diff --git a/packages/language-service/src/index.ts b/packages/language-service/src/index.ts index b194bae..f700129 100644 --- a/packages/language-service/src/index.ts +++ b/packages/language-service/src/index.ts @@ -1,2 +1,2 @@ -export { createTempblotLanguagePlugin, TempblotVirtualCode } from './language-plugin.js'; -export { createTempblotServicePlugin } from './service-plugin.js'; +export { createTempblotLanguagePlugin, TempblotVirtualCode } from './language-plugin.ts'; +export { createTempblotServicePlugin } from './service-plugin.ts'; diff --git a/packages/language-service/src/language-plugin.ts b/packages/language-service/src/language-plugin.ts index 3cdabca..f0713e0 100644 --- a/packages/language-service/src/language-plugin.ts +++ b/packages/language-service/src/language-plugin.ts @@ -156,7 +156,7 @@ function* getTempblotEmbeddedCodes( const expressionStart = interpStartOffset + `(`.length; tsInterpolationMappings.push({ - sourceOffsets: [output.startTagEnd! + interp.sourceStart], + sourceOffsets: [output.startTagEnd + interp.sourceStart], generatedOffsets: [expressionStart], lengths: [interp.expression.length], data: { diff --git a/packages/language-service/src/service-plugin.ts b/packages/language-service/src/service-plugin.ts index 24237ae..e461151 100644 --- a/packages/language-service/src/service-plugin.ts +++ b/packages/language-service/src/service-plugin.ts @@ -1,15 +1,24 @@ -import { Diagnostic } from '@volar/language-service'; +import type { + Diagnostic, + LanguageServiceContext, + LanguageServicePlugin, + LanguageServicePluginInstance, +} from '@volar/language-service'; import { URI } from 'vscode-uri'; -import { TempblotVirtualCode } from './language-plugin.js'; +import { TempblotVirtualCode } from './language-plugin.ts'; -export function createTempblotServicePlugin() { +type DiagnosticsDocument = Parameters< + NonNullable +>[0]; + +export function createTempblotServicePlugin(): LanguageServicePlugin { return { capabilities: { diagnosticProvider: { interFileDependencies: false, workspaceDiagnostics: false }, }, - create(context: any) { + create(context: LanguageServiceContext) { return { - provideDiagnostics(document: any) { + provideDiagnostics(document: DiagnosticsDocument) { const decoded = context.decodeEmbeddedDocumentUri(URI.parse(document.uri)); if (!decoded) { // Not a embedded document diff --git a/packages/parser/eslint.config.mjs b/packages/parser/eslint.config.mjs index 5997309..b3931d8 100644 --- a/packages/parser/eslint.config.mjs +++ b/packages/parser/eslint.config.mjs @@ -3,9 +3,12 @@ import tempblotPreset from 'tempblot-config/eslint-preset.js' export default [ ...tempblotPreset, { + files: ['**/*.ts', '**/*.tsx', '**/*.mts', '**/*.cts'], languageOptions: { parserOptions: { - projectService: true, + projectService: { + allowDefaultProject: ['tests/*.ts', 'vite.config.ts'], + }, tsconfigRootDir: import.meta.dirname, }, }, @@ -17,6 +20,6 @@ export default [ }, }, { - ignores: ['eslint.config.mjs'], + ignores: ['eslint.config.mjs', 'lib/**'], }, ] diff --git a/packages/parser/tests/output-transformer.spec.ts b/packages/parser/tests/output-transformer.spec.ts index 211776b..70a20d0 100644 --- a/packages/parser/tests/output-transformer.spec.ts +++ b/packages/parser/tests/output-transformer.spec.ts @@ -1,5 +1,5 @@ import { expect, test } from "vitest"; -import { transformOutputTemplate } from "../src/index.js"; +import { transformOutputTemplate } from "../src/index.ts"; test("transformOutputTemplate", () => { const source = 'const someStr = `
<\\>" : "\\<\\<">>
`;'; diff --git a/packages/parser/tests/root-lexer.spec.ts b/packages/parser/tests/root-lexer.spec.ts index 9a00e9d..7973b6b 100644 --- a/packages/parser/tests/root-lexer.spec.ts +++ b/packages/parser/tests/root-lexer.spec.ts @@ -1,5 +1,5 @@ import { expect, test } from "vitest"; -import { tokenizeRoot } from "../src/index.js"; +import { tokenizeRoot } from "../src/index.ts"; function withoutOffsets(value: unknown): unknown { if (Array.isArray(value)) { diff --git a/packages/parser/tests/root-parser.spec.ts b/packages/parser/tests/root-parser.spec.ts index 84e6754..290ce13 100644 --- a/packages/parser/tests/root-parser.spec.ts +++ b/packages/parser/tests/root-parser.spec.ts @@ -1,5 +1,5 @@ import { expect, test } from "vitest"; -import { parseRoot, tokenizeRoot } from "../src/index.js"; +import { parseRoot, tokenizeRoot } from "../src/index.ts"; const source = ` diff --git a/packages/prettier-plugin/eslint.config.mjs b/packages/prettier-plugin/eslint.config.mjs index 5997309..b3931d8 100644 --- a/packages/prettier-plugin/eslint.config.mjs +++ b/packages/prettier-plugin/eslint.config.mjs @@ -3,9 +3,12 @@ import tempblotPreset from 'tempblot-config/eslint-preset.js' export default [ ...tempblotPreset, { + files: ['**/*.ts', '**/*.tsx', '**/*.mts', '**/*.cts'], languageOptions: { parserOptions: { - projectService: true, + projectService: { + allowDefaultProject: ['tests/*.ts', 'vite.config.ts'], + }, tsconfigRootDir: import.meta.dirname, }, }, @@ -17,6 +20,6 @@ export default [ }, }, { - ignores: ['eslint.config.mjs'], + ignores: ['eslint.config.mjs', 'lib/**'], }, ] diff --git a/packages/prettier-plugin/tests/index.spec.ts b/packages/prettier-plugin/tests/index.spec.ts index 58a3831..506a7c8 100644 --- a/packages/prettier-plugin/tests/index.spec.ts +++ b/packages/prettier-plugin/tests/index.spec.ts @@ -6,7 +6,7 @@ import { render } from "cli-testing-library"; import * as prettier from "prettier"; import { expect, test } from "vitest"; -import plugin from "../src/index.js"; +import plugin from "../src/index.ts"; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); diff --git a/packages/typescript-plugin/eslint.config.mjs b/packages/typescript-plugin/eslint.config.mjs index 5997309..04e5a5d 100644 --- a/packages/typescript-plugin/eslint.config.mjs +++ b/packages/typescript-plugin/eslint.config.mjs @@ -3,6 +3,7 @@ import tempblotPreset from 'tempblot-config/eslint-preset.js' export default [ ...tempblotPreset, { + files: ['**/*.ts', '**/*.tsx', '**/*.mts', '**/*.cts'], languageOptions: { parserOptions: { projectService: true, @@ -16,6 +17,18 @@ export default [ '@typescript-eslint/require-await': 'off', }, }, + { + files: ['lib/**/*.cjs'], + languageOptions: { + globals: { + module: 'readonly', + require: 'readonly', + }, + }, + rules: { + '@typescript-eslint/no-require-imports': 'off', + }, + }, { ignores: ['eslint.config.mjs'], }, diff --git a/packages/vscode/eslint.config.mjs b/packages/vscode/eslint.config.mjs index 5997309..f1ff2be 100644 --- a/packages/vscode/eslint.config.mjs +++ b/packages/vscode/eslint.config.mjs @@ -3,6 +3,7 @@ import tempblotPreset from 'tempblot-config/eslint-preset.js' export default [ ...tempblotPreset, { + files: ['**/*.ts', '**/*.tsx', '**/*.mts', '**/*.cts'], languageOptions: { parserOptions: { projectService: true, diff --git a/packages/vscode/scripts/build.mjs b/packages/vscode/scripts/build.mjs index 4850e5c..8c63a59 100644 --- a/packages/vscode/scripts/build.mjs +++ b/packages/vscode/scripts/build.mjs @@ -1,7 +1,7 @@ #!/usr/bin/env node import {createRequire} from 'node:module' import process from 'node:process' -import {fileURLToPath} from 'node:url' +import {URL, fileURLToPath} from 'node:url' import {build} from 'esbuild' const require = createRequire(import.meta.url) diff --git a/packages/vscode/src/extension.ts b/packages/vscode/src/extension.ts index 0f0f48d..8bc0ce7 100644 --- a/packages/vscode/src/extension.ts +++ b/packages/vscode/src/extension.ts @@ -42,13 +42,13 @@ export async function activate(context: ExtensionContext) { ); // Start server initially if enabled - tryRestartServer(); + void tryRestartServer(); // Watch for configuration changes context.subscriptions.push( workspace.onDidChangeConfiguration((event) => { if (event.affectsConfiguration('tempblot.server.enable')) { - tryRestartServer(); + void tryRestartServer(); } }) ); diff --git a/tsconfig.base.json b/tsconfig.base.json index 7ff5a96..6f95c3a 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -11,6 +11,8 @@ "declaration": true, "strict": true, "skipLibCheck": true, + "allowImportingTsExtensions": true, + "rewriteRelativeImportExtensions": true, "noUnusedLocals": true, "noUnusedParameters": true },