如何从摩纳哥编辑器中获取转译后的代码?

How can I get the transpiled code from the monaco editor?

如何从 monaco 编辑器中获取转换后的 TypeScript 代码?另外,是否可以访问 TypeScript 语言服务?我试过这个:

monaco.languages.typescript.getTypeScriptWorker();

但是它 returns Promise<any> 我不知道该怎么办!

经过大量研究,TypeScript LanguageService 接口似乎通过工作代理对象部分公开。这可能是因为服务在另一个线程中并且消息被推送到它,因此需要使用承诺。

为了让事情更简单,我检查了返回对象的公开函数并创建了这个定义;希望对某人有所帮助:

namespace ts {
    export interface IMonacoTypeScriptServiceProxy {
        _getModel(uri: string): Promise<{ _eol: string, _lineStarts: any, _Lines: string[], length: number, _uri: Uri, _versionId: number }>;
        findRenameLocations(uri: string, position: number, findInStrings: boolean, findInComments: boolean, providePrefixAndSuffixTextForRename?: boolean): Promise<readonly RenameLocation[] | undefined>;
        getCodeFixesAtPosition(uri: string, start: number, end: number, errorCodes: readonly number[], formatOptions: FormatCodeSettings, preferences: UserPreferences): Promise<readonly CodeFixAction[]>;
        getCompilationSettings(): Promise<CompilerOptions>;
        getCompilerOptionsDiagnostics(): Promise<Diagnostic[]>;
        getCompletionEntryDetails(uri: string, position: number, name: string, formatOptions: FormatCodeOptions | FormatCodeSettings | undefined, source: string | undefined, preferences: UserPreferences | undefined): Promise<CompletionEntryDetails | undefined>;
        getCompletionsAtPosition(uri: string, position: number, options: GetCompletionsAtPositionOptions | undefined): Promise<WithMetadata<CompletionInfo> | undefined>;
        getCurrentDirectory(): Promise<string>;
        getDefaultLibFileName(options: CompilerOptions): Promise<string>;
        getDefinitionAtPosition(uri: string, position: number): Promise<ReadonlyArray<DefinitionInfo> | undefined>;
        getEmitOutput(uri: string, emitOnlyDtsFiles?: boolean): Promise<EmitOutput>;
        getFormattingEditsAfterKeystroke(uri: string, position: number, key: string, options: FormatCodeOptions | FormatCodeSettings): Promise<TextChange[]>;
        getFormattingEditsForDocument(uri: string, options: FormatCodeOptions | FormatCodeSettings): Promise<TextChange[]>;
        getFormattingEditsForRange(uri: string, start: number, end: number, options: FormatCodeOptions | FormatCodeSettings): Promise<TextChange[]>;
        getNavigationBarItems(uri: string): Promise<NavigationBarItem[]>;
        getOccurrencesAtPosition(uri: string, position: number): Promise<ReadonlyArray<ReferenceEntry> | undefined>;
        getQuickInfoAtPosition(uri: string, position: number): Promise<QuickInfo | undefined>;
        getReferencesAtPosition(uri: string, position: number): Promise<ReferenceEntry[] | undefined>;
        getRenameInfo(uri: string, position: number, options?: RenameInfoOptions): Promise<RenameInfo>;
        getScriptFileNames(): Promise<string[]>;
        getScriptKind(uri: string): Promise<ScriptKind>;
        getScriptSnapshot(uri: string): Promise<IScriptSnapshot | undefined>;
        getScriptVersion(uri: string): Promise<string>;
        getSemanticDiagnostics(uri: string): Promise<Diagnostic[]>;
        getSignatureHelpItems(uri: string, position: number, options: SignatureHelpItemsOptions | undefined): Promise<SignatureHelpItems | undefined>;
        getSuggestionDiagnostics(uri: string): Promise<DiagnosticWithLocation[]>;
        getSyntacticDiagnostics(uri: string): Promise<DiagnosticWithLocation[]>;
        isDefaultLibFileName(uri: string): Promise<boolean>;
    }
}

它是这样使用的:

var editor = monaco.editor.create(...etc...);
var tsProxy: ts.IMonacoTypeScriptServiceProxy;

monaco.languages.typescript.getTypeScriptWorker()
            .then(function(worker: (v: monaco.Uri) => Promise<ts.IMonacoTypeScriptServiceProxy>) {
                worker(editor.getModel().uri)
                      .then(function(proxy) {
                            tsProxy = proxy;
                      });
            });

现在调用代理函数getEmitOutput(uri: string, emitOnlyDtsFiles?: boolean)uri 是文件名,它是一个 monaco.Uri 转换为字符串(model 在摩纳哥术语中是编辑器中的单个文件),因此:

tsProxy.getEmitOutput(editor.getModel().uri.toString())
                                    .then((r) => { console.log(r.outputFiles[0].text); });

Returns 转译后的 JavaScript,以及所有其他文件(如果可用)!别客气。 :)

现在版本 0.20.0 发生了变化。 getTypeScriptWorkergetJavaScriptWorker return 方法现在是有效类型:

    export const getTypeScriptWorker: () => Promise<(...uris: Uri[]) => Promise<TypeScriptWorker>>;
    export const getJavaScriptWorker: () => Promise<(...uris: Uri[]) => Promise<TypeScriptWorker>>;

promise 参数也发生了变化。

通过此更改,不再需要维护自己的工作程序(代理)类型。

目前的讨论集中在获取 JS/TS worker 代理上,但是对于关于如何获取转译代码的原始问题,有一个更简单的解决方案:

    import ts from "typescript";

    this.worker.postMessage({ code: ts.transpile(context.code) });

这就是我将 TS 代码从编辑器发送到 Web Worker 以进行隔离执行的方式。