Handle libs on web

This commit is contained in:
nknguyenhc
2025-03-22 00:47:25 +08:00
parent f2ea517495
commit c8c2281cba
5 changed files with 28 additions and 19 deletions

View File

@@ -95,7 +95,12 @@ export async function startClient(context: ExtensionContext, newLanguageClient:
const languageParticipants = getLanguageParticipants(); const languageParticipants = getLanguageParticipants();
context.subscriptions.push(languageParticipants); context.subscriptions.push(languageParticipants);
let client: Disposable | undefined = await startClientWithParticipants(languageParticipants, newLanguageClient, outputChannel, runtime); const extensionUri = {
scheme: context.extensionUri.scheme,
path: context.extensionUri.path,
};
let client: Disposable | undefined = await startClientWithParticipants(languageParticipants, newLanguageClient, outputChannel, runtime, extensionUri);
const promptForLinkedEditingKey = 'html.promptForLinkedEditing'; const promptForLinkedEditingKey = 'html.promptForLinkedEditing';
if (extensions.getExtension('formulahendry.auto-rename-tag') !== undefined && (context.globalState.get(promptForLinkedEditingKey) !== false)) { if (extensions.getExtension('formulahendry.auto-rename-tag') !== undefined && (context.globalState.get(promptForLinkedEditingKey) !== false)) {
@@ -128,7 +133,7 @@ export async function startClient(context: ExtensionContext, newLanguageClient:
const oldClient = client; const oldClient = client;
client = undefined; client = undefined;
await oldClient.dispose(); await oldClient.dispose();
client = await startClientWithParticipants(languageParticipants, newLanguageClient, outputChannel, runtime); client = await startClientWithParticipants(languageParticipants, newLanguageClient, outputChannel, runtime, extensionUri);
} }
}, 2000); }, 2000);
}); });
@@ -142,7 +147,7 @@ export async function startClient(context: ExtensionContext, newLanguageClient:
}; };
} }
async function startClientWithParticipants(languageParticipants: LanguageParticipants, newLanguageClient: LanguageClientConstructor, outputChannel: OutputChannel, runtime: Runtime): Promise<AsyncDisposable> { async function startClientWithParticipants(languageParticipants: LanguageParticipants, newLanguageClient: LanguageClientConstructor, outputChannel: OutputChannel, runtime: Runtime, extensionUri: { scheme: string; path: string }): Promise<AsyncDisposable> {
const toDispose: Disposable[] = []; const toDispose: Disposable[] = [];
@@ -158,6 +163,7 @@ async function startClientWithParticipants(languageParticipants: LanguagePartici
configurationSection: ['html', 'css', 'javascript', 'js/ts'], // the settings to synchronize configurationSection: ['html', 'css', 'javascript', 'js/ts'], // the settings to synchronize
}, },
initializationOptions: { initializationOptions: {
extensionUri: extensionUri,
embeddedLanguages, embeddedLanguages,
handledSchemas: ['file'], handledSchemas: ['file'],
provideFormatter: false, // tell the server to not provide formatting capability and ignore the `html.format.enable` setting. provideFormatter: false, // tell the server to not provide formatting capability and ignore the `html.format.enable` setting.

View File

@@ -152,7 +152,9 @@ export function startServer(connection: Connection, runtime: RuntimeEnvironment)
get folders() { return workspaceFolders; } get folders() { return workspaceFolders; }
}; };
languageModes = getLanguageModes(initializationOptions?.embeddedLanguages || { css: true, javascript: true }, workspace, params.capabilities, fileSystemProvider); const extensionUri = initializationOptions?.extensionUri;
languageModes = getLanguageModes(initializationOptions?.embeddedLanguages || { css: true, javascript: true }, workspace, params.capabilities, fileSystemProvider, extensionUri);
const dataPaths: string[] = initializationOptions?.dataPaths || []; const dataPaths: string[] = initializationOptions?.dataPaths || [];
fetchHTMLDataProviders(dataPaths, customDataRequestService).then(dataProviders => { fetchHTMLDataProviders(dataPaths, customDataRequestService).then(dataProviders => {

View File

@@ -5,7 +5,6 @@
import { join, basename, dirname } from 'path'; import { join, basename, dirname } from 'path';
import { readFileSync } from 'fs'; import { readFileSync } from 'fs';
import { TextDocument } from './languageModes';
const contents: { [name: string]: string } = {}; const contents: { [name: string]: string } = {};
@@ -32,10 +31,3 @@ export function loadLibrary(name: string) {
} }
return content; return content;
} }
export function getLibUriAndDocument(libName: string): [string, TextDocument] {
const filepath = join(TYPESCRIPT_LIB_SOURCE, libName);
const fileUri = `file:///${filepath}`;
const content = loadLibrary(libName);
return [fileUri, TextDocument.create(fileUri, 'typescript', 1, content)];
}

View File

@@ -8,14 +8,15 @@ import {
SymbolInformation, SymbolKind, CompletionItem, Location, SignatureHelp, SignatureInformation, ParameterInformation, SymbolInformation, SymbolKind, CompletionItem, Location, SignatureHelp, SignatureInformation, ParameterInformation,
Definition, TextEdit, TextDocument, Diagnostic, DiagnosticSeverity, Range, CompletionItemKind, Hover, Definition, TextEdit, TextDocument, Diagnostic, DiagnosticSeverity, Range, CompletionItemKind, Hover,
DocumentHighlight, DocumentHighlightKind, CompletionList, Position, FormattingOptions, FoldingRange, FoldingRangeKind, SelectionRange, DocumentHighlight, DocumentHighlightKind, CompletionList, Position, FormattingOptions, FoldingRange, FoldingRangeKind, SelectionRange,
LanguageMode, Settings, SemanticTokenData, Workspace, DocumentContext, CompletionItemData, isCompletionItemData LanguageMode, Settings, SemanticTokenData, Workspace, DocumentContext, CompletionItemData, isCompletionItemData, Uri
} from './languageModes'; } from './languageModes';
import { getWordAtText, isWhitespaceOnly, repeat } from '../utils/strings'; import { getWordAtText, isWhitespaceOnly, repeat } from '../utils/strings';
import { HTMLDocumentRegions } from './embeddedSupport'; import { HTMLDocumentRegions } from './embeddedSupport';
import * as ts from 'typescript'; import * as ts from 'typescript';
import { getSemanticTokens, getSemanticTokenLegend } from './javascriptSemanticTokens'; import { getSemanticTokens, getSemanticTokenLegend } from './javascriptSemanticTokens';
import { getLibUriAndDocument } from './javascriptLibs'; import { loadLibrary } from './javascriptLibs';
import path from 'path';
const JS_WORD_REGEX = /(-?\d*\.\d\w*)|([^\`\~\!\@\#\%\^\&\*\(\)\-\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\?\s]+)/g; const JS_WORD_REGEX = /(-?\d*\.\d\w*)|([^\`\~\!\@\#\%\^\&\*\(\)\-\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\?\s]+)/g;
@@ -99,7 +100,7 @@ const ignoredErrors = [
2792, /* Cannot_find_module_0_Did_you_mean_to_set_the_moduleResolution_option_to_node_or_to_add_aliases_to_the_paths_option */ 2792, /* Cannot_find_module_0_Did_you_mean_to_set_the_moduleResolution_option_to_node_or_to_add_aliases_to_the_paths_option */
]; ];
export function getJavaScriptMode(documentRegions: LanguageModelCache<HTMLDocumentRegions>, languageId: 'javascript' | 'typescript', workspace: Workspace): LanguageMode { export function getJavaScriptMode(documentRegions: LanguageModelCache<HTMLDocumentRegions>, languageId: 'javascript' | 'typescript', workspace: Workspace, extensionUri: Uri): LanguageMode {
const jsDocuments = getLanguageModelCache<TextDocument>(10, 60, document => documentRegions.get(document).getEmbeddedDocument(languageId)); const jsDocuments = getLanguageModelCache<TextDocument>(10, 60, document => documentRegions.get(document).getEmbeddedDocument(languageId));
const host = getLanguageServiceHost(languageId === 'javascript' ? ts.ScriptKind.JS : ts.ScriptKind.TS); const host = getLanguageServiceHost(languageId === 'javascript' ? ts.ScriptKind.JS : ts.ScriptKind.TS);
@@ -310,7 +311,10 @@ export function getJavaScriptMode(documentRegions: LanguageModelCache<HTMLDocume
range: convertRange(jsDocument, d.textSpan) range: convertRange(jsDocument, d.textSpan)
}; };
} else { } else {
const [libUri, libDocument] = getLibUriAndDocument(d.fileName); const filePath = path.posix.join(extensionUri.path, '../node_modules/typescript/lib', d.fileName);
const libUri = `${extensionUri.scheme}://${filePath}`;
const content = loadLibrary(d.fileName);
const libDocument = TextDocument.create(libUri, 'typescript', 1, content);
return { return {
uri: libUri, uri: libUri,
range: convertRange(libDocument, d.textSpan) range: convertRange(libDocument, d.textSpan)

View File

@@ -108,7 +108,12 @@ export interface LanguageModeRange extends Range {
attributeValue?: boolean; attributeValue?: boolean;
} }
export function getLanguageModes(supportedLanguages: { [languageId: string]: boolean }, workspace: Workspace, clientCapabilities: ClientCapabilities, requestService: FileSystemProvider): LanguageModes { export interface Uri {
scheme: string;
path: string;
}
export function getLanguageModes(supportedLanguages: { [languageId: string]: boolean }, workspace: Workspace, clientCapabilities: ClientCapabilities, requestService: FileSystemProvider, extensionUri: Uri): LanguageModes {
const htmlLanguageService = getHTMLLanguageService({ clientCapabilities, fileSystemProvider: requestService }); const htmlLanguageService = getHTMLLanguageService({ clientCapabilities, fileSystemProvider: requestService });
const cssLanguageService = getCSSLanguageService({ clientCapabilities, fileSystemProvider: requestService }); const cssLanguageService = getCSSLanguageService({ clientCapabilities, fileSystemProvider: requestService });
@@ -123,8 +128,8 @@ export function getLanguageModes(supportedLanguages: { [languageId: string]: boo
modes['css'] = getCSSMode(cssLanguageService, documentRegions, workspace); modes['css'] = getCSSMode(cssLanguageService, documentRegions, workspace);
} }
if (supportedLanguages['javascript']) { if (supportedLanguages['javascript']) {
modes['javascript'] = getJavaScriptMode(documentRegions, 'javascript', workspace); modes['javascript'] = getJavaScriptMode(documentRegions, 'javascript', workspace, extensionUri);
modes['typescript'] = getJavaScriptMode(documentRegions, 'typescript', workspace); modes['typescript'] = getJavaScriptMode(documentRegions, 'typescript', workspace, extensionUri);
} }
return { return {
async updateDataProviders(dataProviders: IHTMLDataProvider[]): Promise<void> { async updateDataProviders(dataProviders: IHTMLDataProvider[]): Promise<void> {