"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.astro2tsx = exports.getTSXRangesAsLSPRanges = exports.safeConvertToTSX = void 0; const sync_1 = require("@astrojs/compiler/sync"); const sourcemap_codec_1 = require("@jridgewell/sourcemap-codec"); const language_core_1 = require("@volar/language-core"); const language_server_1 = require("@volar/language-server"); const vscode_html_languageservice_1 = require("vscode-html-languageservice"); const utils_js_1 = require("./utils.js"); function safeConvertToTSX(content, options) { try { const tsx = (0, sync_1.convertToTSX)(content, { filename: options.filename }); return tsx; } catch (e) { console.error(`There was an error transforming ${options.filename} to TSX. An empty file will be returned instead. Please create an issue: https://github.com/withastro/language-tools/issues\nError: ${e}.`); return { code: '', map: { file: options.filename ?? '', sources: [], sourcesContent: [], names: [], mappings: '', version: 0, }, diagnostics: [ { code: 1000, location: { file: options.filename, line: 1, column: 1, length: content.length }, severity: 1, text: `The Astro compiler encountered an unknown error while transform this file to TSX. Please create an issue with your code and the error shown in the server's logs: https://github.com/withastro/language-tools/issues`, }, ], metaRanges: { frontmatter: { start: 0, end: 0, }, body: { start: 0, end: 0, }, }, }; } } exports.safeConvertToTSX = safeConvertToTSX; function getTSXRangesAsLSPRanges(tsx) { const textDocument = vscode_html_languageservice_1.TextDocument.create('', 'typescriptreact', 0, tsx.code); return { frontmatter: language_server_1.Range.create(textDocument.positionAt(tsx.metaRanges.frontmatter.start), textDocument.positionAt(tsx.metaRanges.frontmatter.end)), body: language_server_1.Range.create(textDocument.positionAt(tsx.metaRanges.body.start), textDocument.positionAt(tsx.metaRanges.body.end)), }; } exports.getTSXRangesAsLSPRanges = getTSXRangesAsLSPRanges; function astro2tsx(input, fileName, ts, htmlDocument) { const tsx = safeConvertToTSX(input, { filename: fileName }); return { virtualFile: getVirtualFileTSX(input, tsx, fileName, ts, htmlDocument), diagnostics: tsx.diagnostics, ranges: getTSXRangesAsLSPRanges(tsx), }; } exports.astro2tsx = astro2tsx; function getVirtualFileTSX(input, tsx, fileName, ts, htmlDocument) { tsx.code = (0, utils_js_1.patchTSX)(tsx.code, fileName); const v3Mappings = (0, sourcemap_codec_1.decode)(tsx.map.mappings); const sourcedDoc = vscode_html_languageservice_1.TextDocument.create(fileName, 'astro', 0, input); const genDoc = vscode_html_languageservice_1.TextDocument.create(fileName + '.tsx', 'typescriptreact', 0, tsx.code); const mappings = []; let current; for (let genLine = 0; genLine < v3Mappings.length; genLine++) { for (const segment of v3Mappings[genLine]) { const genCharacter = segment[0]; const genOffset = genDoc.offsetAt({ line: genLine, character: genCharacter }); if (current) { let length = genOffset - current.genOffset; const sourceText = input.substring(current.sourceOffset, current.sourceOffset + length); const genText = tsx.code.substring(current.genOffset, current.genOffset + length); if (sourceText !== genText) { length = 0; for (let i = 0; i < genOffset - current.genOffset; i++) { if (sourceText[i] === genText[i]) { length = i + 1; } else { break; } } } if (length > 0) { const lastMapping = mappings.length ? mappings[mappings.length - 1] : undefined; if (lastMapping && lastMapping.generatedRange[1] === current.genOffset && lastMapping.sourceRange[1] === current.sourceOffset) { lastMapping.generatedRange[1] = current.genOffset + length; lastMapping.sourceRange[1] = current.sourceOffset + length; } else { // Disable features inside script tags. This is a bit annoying to do, I wonder if maybe leaving script tags // unmapped would be better. const node = htmlDocument.findNodeAt(current.sourceOffset); const rangeCapabilities = node.tag !== 'script' ? language_core_1.FileRangeCapabilities.full : { completion: false, definition: false, diagnostic: false, displayWithLink: false, hover: false, references: false, referencesCodeLens: false, rename: false, semanticTokens: false, }; mappings.push({ sourceRange: [current.sourceOffset, current.sourceOffset + length], generatedRange: [current.genOffset, current.genOffset + length], data: rangeCapabilities, }); } } current = undefined; } if (segment[2] !== undefined && segment[3] !== undefined) { const sourceOffset = sourcedDoc.offsetAt({ line: segment[2], character: segment[3] }); current = { genOffset, sourceOffset, }; } } } const ast = ts.createSourceFile('/a.tsx', tsx.code, ts.ScriptTarget.ESNext); if (ast.statements[0]) { mappings.push({ sourceRange: [0, input.length], generatedRange: [ast.statements[0].getStart(ast), tsx.code.length], data: {}, }); } return { fileName: fileName + '.tsx', kind: language_core_1.FileKind.TypeScriptHostFile, capabilities: { codeAction: true, documentFormatting: false, diagnostic: true, documentSymbol: true, inlayHint: true, foldingRange: true, }, codegenStacks: [], snapshot: { getText: (start, end) => tsx.code.substring(start, end), getLength: () => tsx.code.length, getChangeRange: () => undefined, }, mappings: mappings, embeddedFiles: [], }; } //# sourceMappingURL=astro2tsx.js.map