164 lines
7.3 KiB
Plaintext
164 lines
7.3 KiB
Plaintext
|
"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
|