If you write code in TypeScript and you need declaration files for some popular JavaScript libraries check my repository. I wrote almost complete declaration files for linqjs, jasmine and angularjs libraries so far.
Friday, October 26, 2012
Saturday, October 6, 2012
TypeScript Interactive in Visual Studio (TypeScript REPL)
Last time I have been writing about JavaScript Interactive. After announcement of a new language called TypeScript last Monday (2012.10. 01) I have upgraded my solution to work also with TypeScript language. Everything works exactly the same as previously but instead of calling Generate method at the end of the file we need to call TypeScript’s counterpart GenerateFromTS. This method takes 3 parameters: two optional parameters already described (useClipboard , history – here TS file) and one new optional parameter jsFile. TypeScript language is compiled into JavaScript so parameter jsFile specifies the path where generated JavaScript code is stored. Let’s look at the sample usage of TypeScript Interactive:
New JS/TS Interactive implementation looks like this:
<#@ template hostspecific="true"#>
<#@ output extension=".txt"#>
<#@ assembly name="System.Windows.Forms" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System" #>
<#@ import namespace="System.Diagnostics" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Windows.Forms" #>
<#@ import namespace="System.IO" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Threading" #>
<#+
public void Generate(bool useClipboard = false, string historyFile = null, Func<string, string> convertFileContent = null)
{
var fileContent = useClipboard ? GetClipboardText() : File.ReadAllText(Host.TemplateFile);
convertFileContent = convertFileContent ?? (s => s);
GenerationEnvironment.Clear();
var tempFile = Path.GetTempFileName();
if(string.IsNullOrEmpty(historyFile))
{
File.WriteAllText(tempFile, convertFileContent(fileContent));
RunProcess("node", tempFile, WriteLine, WriteLine);
File.Delete(tempFile);
}
else
{
var historyFilePath = Host.ResolvePath(historyFile);
if(!File.Exists(historyFilePath))
{
WriteLine("Specified history file path '{0}' does not exist.", historyFilePath);
}
else
{
var historyLines = File.ReadAllLines(historyFilePath);
int? printedOutputLinesCount = ExtractOutputLinesCount(historyLines);
long i = 0, max = printedOutputLinesCount ?? 0;
var tempFileLines =
(printedOutputLinesCount == null ? new [] {"//0"} : new string[0])
.Concat(historyLines)
.Concat(fileContent.Split(new string[] {Environment.NewLine},StringSplitOptions.None))
.Concat(new [] {new string('/',100)})
.ToArray();
var content = convertFileContent(string.Join(Environment.NewLine, tempFileLines));
if(content == null)
return;
File.WriteAllText(tempFile, content);
var result = RunProcess("node", tempFile, s => { if(++i >= max) WriteLine(s); }, WriteLine );
File.Delete(tempFile);
if(result == 0) // ok
{
tempFileLines[0] = @"//" + i;
File.WriteAllLines(historyFilePath, tempFileLines);
}
}
}
}
public void GenerateFromTS(string jsFile = null, bool useClipboard = false, string historyFile = null)
{
Generate(useClipboard, historyFile,
tsContent =>
{
var tsTempFile = Path.ChangeExtension(Path.GetTempFileName(), "ts");
var jsTempFile = Path.GetTempFileName();
File.WriteAllText(tsTempFile, tsContent);
var result = RunProcess(@"tsc", string.Format("--out \"{0}\" \"{1}\" ",jsTempFile, tsTempFile), WriteLine, WriteLine);
File.Delete(tsTempFile);
if(result != 0) // !ok
return null;
var jsContent = File.ReadAllText(jsTempFile);
if(!string.IsNullOrEmpty(jsFile))
{
var jsFilePath = Host.ResolvePath(jsFile);
if(!File.Exists(jsFilePath))
WriteLine("Specified JavaScript file path '{0}' does not exist.", jsFilePath);
else
File.WriteAllText(jsFilePath, jsContent);
}
File.Delete(jsTempFile);
return jsContent;
} );
}
private static int? ExtractOutputLinesCount(string[] allLines)
{
int count;
string firstLine = null;
return (allLines != null) && ((firstLine = allLines.FirstOrDefault()) != null) && int.TryParse(firstLine.Replace(@"//",""), out count) ?
(int?)count : null;
}
private static int RunProcess(string processName, string processArguments, Action<string> onOutputDataReceived = null, Action<string> onErrorDataReceived = null)
{
onOutputDataReceived = onOutputDataReceived ?? (s => {});
onErrorDataReceived = onErrorDataReceived ?? (s => {});
var processStartInfo = new ProcessStartInfo(processName, processArguments);
processStartInfo.RedirectStandardInput = true;
processStartInfo.RedirectStandardOutput = true;
processStartInfo.RedirectStandardError = true;
processStartInfo.CreateNoWindow = true;
processStartInfo.UseShellExecute = false;
var process = Process.Start(processStartInfo);
process.OutputDataReceived += (sender, args) => onOutputDataReceived(args.Data);
process.ErrorDataReceived += (sender, args) => { if(args.Data!=null) onErrorDataReceived(args.Data); };
process.BeginOutputReadLine();
process.BeginErrorReadLine();
process.WaitForExit();
return process.ExitCode;
}
private string GetClipboardText()
{
try
{
return Clipboard.GetDataObject().GetData(DataFormats.Text) as string;
}
catch
{
return "";
}
}
#>