20

我正在尝试用 C# 编写一个函数,该函数接受一个包含打字稿代码的字符串并返回一个包含 JavaScript 代码的字符串。有这个库函数吗?

4

3 回答 3

13

您可以使用Process来调用编译器,指定--out file.js到一个临时文件夹并读取编译文件的内容。

我做了一个小应用程序来做到这一点:

用法

TypeScriptCompiler.Compile(@"C:\tmp\test.ts");

要获得JS string

string javascriptSource = File.ReadAllText(@"C:\tmp\test.js");

带有示例和评论的完整源代码:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                // compiles a TS file
                TypeScriptCompiler.Compile(@"C:\tmp\test.ts");

                // if no errors were found, read the contents of the compile file
                string javascriptSource = File.ReadAllText(@"C:\tmp\test.js");
            }
            catch (InvalidTypeScriptFileException ex)
            {
                // there was a compiler error, show the compiler output
                Console.WriteLine(ex.Message);
            }

            Console.ReadKey();
        }
    }

    public static class TypeScriptCompiler
    {
        // helper class to add parameters to the compiler
        public class Options
        {
            private static Options @default;
            public static Options Default
            {
                get
                {
                    if (@default == null)
                        @default = new Options();

                    return @default;
                }
            }

            public enum Version
            {
                ES5,
                ES3,
            }

            public bool EmitComments { get; set; }
            public bool GenerateDeclaration { get; set; }
            public bool GenerateSourceMaps { get; set; }
            public string OutPath { get; set; }
            public Version TargetVersion { get; set; }

            public Options() { }

            public Options(bool emitComments = false
                , bool generateDeclaration = false
                , bool generateSourceMaps = false
                , string outPath = null
                , Version targetVersion = Version.ES5)
            {
                EmitComments = emitComments;
                GenerateDeclaration = generateDeclaration;
                GenerateSourceMaps = generateSourceMaps;
                OutPath = outPath;
                TargetVersion = targetVersion;
            }
        }

        public static void Compile(string tsPath, Options options = null)
        {
            if (options == null)
                options = Options.Default;

            var d = new Dictionary<string,string>();

            if (options.EmitComments)
                d.Add("-c", null);

            if (options.GenerateDeclaration)
                d.Add("-d", null);

            if (options.GenerateSourceMaps)
                d.Add("--sourcemap", null);

            if (!String.IsNullOrEmpty(options.OutPath))
                d.Add("--out", options.OutPath);

            d.Add("--target", options.TargetVersion.ToString());

            // this will invoke `tsc` passing the TS path and other
            // parameters defined in Options parameter
            Process p = new Process();

            ProcessStartInfo psi = new ProcessStartInfo("tsc", tsPath + " " + String.Join(" ", d.Select(o => o.Key + " " + o.Value)));

            // run without showing console windows
            psi.CreateNoWindow = true;
            psi.UseShellExecute = false;

            // redirects the compiler error output, so we can read
            // and display errors if any
            psi.RedirectStandardError = true;

            p.StartInfo = psi;

            p.Start();

            // reads the error output
            var msg = p.StandardError.ReadToEnd();

            // make sure it finished executing before proceeding 
            p.WaitForExit();

            // if there were errors, throw an exception
            if (!String.IsNullOrEmpty(msg))
                throw new InvalidTypeScriptFileException(msg);
        }
    }

    public class InvalidTypeScriptFileException : Exception
    {
        public InvalidTypeScriptFileException() : base()
        {

        }
        public InvalidTypeScriptFileException(string message) : base(message)
        {

        }
    }
}
于 2013-07-08T18:54:57.487 回答
5

也许您可以使用 JavaScriptDotNet 之类的 JavaScript 解释从 C#运行 typescript 编译器tsc.js。

就像是:

string tscJs = File.ReadAllText("tsc.js");

using (var context = new JavascriptContext())
{
    // Some trivial typescript:
    var typescriptSource = "window.alert('hello world!');";
    context.SetParameter("typescriptSource", typescriptSource);
    context.SetParameter("result", "");

    // Build some js to execute:
    string script = tscJs + @"
result = TypeScript.compile(""typescriptSource"")";

    // Execute the js
    context.Run(script);

    // Retrieve the result (which should be the compiled JS)
    var js = context.GetParameter("result");
    Assert.AreEqual(typescriptSource, js);
}

显然,该代码需要一些认真的工作。如果这确实可行,我当然会对结果感兴趣。

您可能还想进行修改tsc,以便它可以对内存中的字符串进行操作,而不是需要文件 IO。

于 2012-12-26T21:33:33.817 回答
2

TypeScript 编译器文件在 node.js 或 Windows Script Host 上正式运行——它是用 TypeScript 本身编写的(并转译为 JavaScript)。它需要一个可以访问文件系统的脚本主机。

因此,本质上,您可以从任何语言运行 TypeScript,只要您可以将其包装在支持所需文件系统操作的脚本引擎中。

如果您想纯粹在 C# 中将 TypeScript 编译为 JavaScript,您最终将编写编译器的 C# 克隆。

于 2012-12-26T22:52:32.793 回答